blob: ad619c9b4603ad1951225ba5629cd0219076e4e2 [file] [log] [blame]
bellard6af0bf92005-07-02 14:58:51 +00001/*
2 * MIPS emulation micro-operations for qemu.
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard6af0bf92005-07-02 14:58:51 +00004 * Copyright (c) 2004-2005 Jocelyn Mayer
bellard6ea83fe2006-06-14 12:56:19 +00005 * Copyright (c) 2006 Marius Groeger (FPU operations)
ths93b12cc2007-05-20 01:36:29 +00006 * Copyright (c) 2007 Thiemo Seufer (64-bit FPU support)
bellard6af0bf92005-07-02 14:58:51 +00007 *
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"
ths05f778c2007-10-27 13:05:54 +000025#include "host-utils.h"
bellard6af0bf92005-07-02 14:58:51 +000026
bellard1b351e52005-07-02 15:39:04 +000027#ifndef CALL_FROM_TB0
ths5a5012e2007-05-07 13:55:33 +000028#define CALL_FROM_TB0(func) func()
bellard1b351e52005-07-02 15:39:04 +000029#endif
30#ifndef CALL_FROM_TB1
ths5a5012e2007-05-07 13:55:33 +000031#define CALL_FROM_TB1(func, arg0) func(arg0)
bellard1b351e52005-07-02 15:39:04 +000032#endif
33#ifndef CALL_FROM_TB1_CONST16
ths5a5012e2007-05-07 13:55:33 +000034#define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0)
bellard1b351e52005-07-02 15:39:04 +000035#endif
36#ifndef CALL_FROM_TB2
ths5a5012e2007-05-07 13:55:33 +000037#define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1)
bellard1b351e52005-07-02 15:39:04 +000038#endif
39#ifndef CALL_FROM_TB2_CONST16
40#define CALL_FROM_TB2_CONST16(func, arg0, arg1) \
ths5a5012e2007-05-07 13:55:33 +000041 CALL_FROM_TB2(func, arg0, arg1)
bellard1b351e52005-07-02 15:39:04 +000042#endif
43#ifndef CALL_FROM_TB3
ths5a5012e2007-05-07 13:55:33 +000044#define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2)
bellard1b351e52005-07-02 15:39:04 +000045#endif
46#ifndef CALL_FROM_TB4
47#define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
ths5a5012e2007-05-07 13:55:33 +000048 func(arg0, arg1, arg2, arg3)
bellard1b351e52005-07-02 15:39:04 +000049#endif
50
bellard6af0bf92005-07-02 14:58:51 +000051#define REG 1
52#include "op_template.c"
53#undef REG
54#define REG 2
55#include "op_template.c"
56#undef REG
57#define REG 3
58#include "op_template.c"
59#undef REG
60#define REG 4
61#include "op_template.c"
62#undef REG
63#define REG 5
64#include "op_template.c"
65#undef REG
66#define REG 6
67#include "op_template.c"
68#undef REG
69#define REG 7
70#include "op_template.c"
71#undef REG
72#define REG 8
73#include "op_template.c"
74#undef REG
75#define REG 9
76#include "op_template.c"
77#undef REG
78#define REG 10
79#include "op_template.c"
80#undef REG
81#define REG 11
82#include "op_template.c"
83#undef REG
84#define REG 12
85#include "op_template.c"
86#undef REG
87#define REG 13
88#include "op_template.c"
89#undef REG
90#define REG 14
91#include "op_template.c"
92#undef REG
93#define REG 15
94#include "op_template.c"
95#undef REG
96#define REG 16
97#include "op_template.c"
98#undef REG
99#define REG 17
100#include "op_template.c"
101#undef REG
102#define REG 18
103#include "op_template.c"
104#undef REG
105#define REG 19
106#include "op_template.c"
107#undef REG
108#define REG 20
109#include "op_template.c"
110#undef REG
111#define REG 21
112#include "op_template.c"
113#undef REG
114#define REG 22
115#include "op_template.c"
116#undef REG
117#define REG 23
118#include "op_template.c"
119#undef REG
120#define REG 24
121#include "op_template.c"
122#undef REG
123#define REG 25
124#include "op_template.c"
125#undef REG
126#define REG 26
127#include "op_template.c"
128#undef REG
129#define REG 27
130#include "op_template.c"
131#undef REG
132#define REG 28
133#include "op_template.c"
134#undef REG
135#define REG 29
136#include "op_template.c"
137#undef REG
138#define REG 30
139#include "op_template.c"
140#undef REG
141#define REG 31
142#include "op_template.c"
143#undef REG
144
thsc570fd12006-12-21 01:19:56 +0000145#define TN
bellard6af0bf92005-07-02 14:58:51 +0000146#include "op_template.c"
147#undef TN
148
ths5a5012e2007-05-07 13:55:33 +0000149#define FREG 0
bellard6ea83fe2006-06-14 12:56:19 +0000150#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000151#undef FREG
152#define FREG 1
bellard6ea83fe2006-06-14 12:56:19 +0000153#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000154#undef FREG
155#define FREG 2
bellard6ea83fe2006-06-14 12:56:19 +0000156#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000157#undef FREG
158#define FREG 3
bellard6ea83fe2006-06-14 12:56:19 +0000159#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000160#undef FREG
161#define FREG 4
bellard6ea83fe2006-06-14 12:56:19 +0000162#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000163#undef FREG
164#define FREG 5
bellard6ea83fe2006-06-14 12:56:19 +0000165#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000166#undef FREG
167#define FREG 6
bellard6ea83fe2006-06-14 12:56:19 +0000168#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000169#undef FREG
170#define FREG 7
bellard6ea83fe2006-06-14 12:56:19 +0000171#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000172#undef FREG
173#define FREG 8
bellard6ea83fe2006-06-14 12:56:19 +0000174#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000175#undef FREG
176#define FREG 9
bellard6ea83fe2006-06-14 12:56:19 +0000177#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000178#undef FREG
179#define FREG 10
bellard6ea83fe2006-06-14 12:56:19 +0000180#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000181#undef FREG
182#define FREG 11
bellard6ea83fe2006-06-14 12:56:19 +0000183#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000184#undef FREG
185#define FREG 12
bellard6ea83fe2006-06-14 12:56:19 +0000186#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000187#undef FREG
188#define FREG 13
bellard6ea83fe2006-06-14 12:56:19 +0000189#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000190#undef FREG
191#define FREG 14
bellard6ea83fe2006-06-14 12:56:19 +0000192#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000193#undef FREG
194#define FREG 15
bellard6ea83fe2006-06-14 12:56:19 +0000195#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000196#undef FREG
197#define FREG 16
bellard6ea83fe2006-06-14 12:56:19 +0000198#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000199#undef FREG
200#define FREG 17
bellard6ea83fe2006-06-14 12:56:19 +0000201#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000202#undef FREG
203#define FREG 18
bellard6ea83fe2006-06-14 12:56:19 +0000204#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000205#undef FREG
206#define FREG 19
bellard6ea83fe2006-06-14 12:56:19 +0000207#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000208#undef FREG
209#define FREG 20
bellard6ea83fe2006-06-14 12:56:19 +0000210#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000211#undef FREG
212#define FREG 21
bellard6ea83fe2006-06-14 12:56:19 +0000213#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000214#undef FREG
215#define FREG 22
bellard6ea83fe2006-06-14 12:56:19 +0000216#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000217#undef FREG
218#define FREG 23
bellard6ea83fe2006-06-14 12:56:19 +0000219#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000220#undef FREG
221#define FREG 24
bellard6ea83fe2006-06-14 12:56:19 +0000222#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000223#undef FREG
224#define FREG 25
bellard6ea83fe2006-06-14 12:56:19 +0000225#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000226#undef FREG
227#define FREG 26
bellard6ea83fe2006-06-14 12:56:19 +0000228#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000229#undef FREG
230#define FREG 27
bellard6ea83fe2006-06-14 12:56:19 +0000231#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000232#undef FREG
233#define FREG 28
bellard6ea83fe2006-06-14 12:56:19 +0000234#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000235#undef FREG
236#define FREG 29
bellard6ea83fe2006-06-14 12:56:19 +0000237#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000238#undef FREG
239#define FREG 30
bellard6ea83fe2006-06-14 12:56:19 +0000240#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000241#undef FREG
242#define FREG 31
bellard6ea83fe2006-06-14 12:56:19 +0000243#include "fop_template.c"
ths5a5012e2007-05-07 13:55:33 +0000244#undef FREG
bellard6ea83fe2006-06-14 12:56:19 +0000245
246#define FTN
247#include "fop_template.c"
248#undef FTN
249
bellard6af0bf92005-07-02 14:58:51 +0000250void op_dup_T0 (void)
251{
252 T2 = T0;
ths8f6f6022007-11-09 23:09:41 +0000253 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000254}
255
256void op_load_HI (void)
257{
thsead93602007-09-06 00:18:15 +0000258 T0 = env->HI[PARAM1][env->current_tc];
ths8f6f6022007-11-09 23:09:41 +0000259 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000260}
261
262void op_store_HI (void)
263{
thsead93602007-09-06 00:18:15 +0000264 env->HI[PARAM1][env->current_tc] = T0;
ths8f6f6022007-11-09 23:09:41 +0000265 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000266}
267
268void op_load_LO (void)
269{
thsead93602007-09-06 00:18:15 +0000270 T0 = env->LO[PARAM1][env->current_tc];
ths8f6f6022007-11-09 23:09:41 +0000271 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000272}
273
274void op_store_LO (void)
275{
thsead93602007-09-06 00:18:15 +0000276 env->LO[PARAM1][env->current_tc] = T0;
ths8f6f6022007-11-09 23:09:41 +0000277 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000278}
279
280/* Load and store */
281#define MEMSUFFIX _raw
282#include "op_mem.c"
283#undef MEMSUFFIX
284#if !defined(CONFIG_USER_ONLY)
285#define MEMSUFFIX _user
286#include "op_mem.c"
287#undef MEMSUFFIX
288
ths623a9302007-10-28 19:45:05 +0000289#define MEMSUFFIX _super
290#include "op_mem.c"
291#undef MEMSUFFIX
292
bellard6af0bf92005-07-02 14:58:51 +0000293#define MEMSUFFIX _kernel
294#include "op_mem.c"
295#undef MEMSUFFIX
296#endif
297
thsa6763a52007-05-09 09:33:33 +0000298/* Addresses computation */
299void op_addr_add (void)
300{
301/* For compatibility with 32-bit code, data reference in user mode
302 with Status_UX = 0 should be casted to 32-bit and sign extended.
303 See the MIPS64 PRA manual, section 4.10. */
thsd26bc212007-11-08 18:05:37 +0000304#if defined(TARGET_MIPS64)
ths623a9302007-10-28 19:45:05 +0000305 if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
thsa6763a52007-05-09 09:33:33 +0000306 !(env->CP0_Status & (1 << CP0St_UX)))
307 T0 = (int64_t)(int32_t)(T0 + T1);
308 else
309#endif
310 T0 += T1;
ths8f6f6022007-11-09 23:09:41 +0000311 FORCE_RET();
thsa6763a52007-05-09 09:33:33 +0000312}
313
bellard6af0bf92005-07-02 14:58:51 +0000314/* Arithmetic */
315void op_add (void)
316{
ths5dc4b742006-12-21 13:48:28 +0000317 T0 = (int32_t)((int32_t)T0 + (int32_t)T1);
ths8f6f6022007-11-09 23:09:41 +0000318 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000319}
320
321void op_addo (void)
322{
323 target_ulong tmp;
324
thsc570fd12006-12-21 01:19:56 +0000325 tmp = (int32_t)T0;
326 T0 = (int32_t)T0 + (int32_t)T1;
bellard76e050c2006-04-23 15:18:58 +0000327 if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
thsc570fd12006-12-21 01:19:56 +0000328 /* operands of same sign, result different sign */
ths1579a722007-04-05 23:16:25 +0000329 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
bellard6af0bf92005-07-02 14:58:51 +0000330 }
ths5dc4b742006-12-21 13:48:28 +0000331 T0 = (int32_t)T0;
ths8f6f6022007-11-09 23:09:41 +0000332 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000333}
334
335void op_sub (void)
336{
ths5dc4b742006-12-21 13:48:28 +0000337 T0 = (int32_t)((int32_t)T0 - (int32_t)T1);
ths8f6f6022007-11-09 23:09:41 +0000338 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000339}
340
341void op_subo (void)
342{
343 target_ulong tmp;
344
thsc570fd12006-12-21 01:19:56 +0000345 tmp = (int32_t)T0;
bellard6af0bf92005-07-02 14:58:51 +0000346 T0 = (int32_t)T0 - (int32_t)T1;
bellard76e050c2006-04-23 15:18:58 +0000347 if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
thsc570fd12006-12-21 01:19:56 +0000348 /* operands of different sign, first operand and result different sign */
ths1579a722007-04-05 23:16:25 +0000349 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
bellard6af0bf92005-07-02 14:58:51 +0000350 }
ths5dc4b742006-12-21 13:48:28 +0000351 T0 = (int32_t)T0;
ths8f6f6022007-11-09 23:09:41 +0000352 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000353}
354
355void op_mul (void)
356{
ths5dc4b742006-12-21 13:48:28 +0000357 T0 = (int32_t)((int32_t)T0 * (int32_t)T1);
ths8f6f6022007-11-09 23:09:41 +0000358 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000359}
360
ths80c27192007-04-15 21:21:33 +0000361#if HOST_LONG_BITS < 64
362void op_div (void)
363{
364 CALL_FROM_TB0(do_div);
ths8f6f6022007-11-09 23:09:41 +0000365 FORCE_RET();
ths80c27192007-04-15 21:21:33 +0000366}
367#else
bellard6af0bf92005-07-02 14:58:51 +0000368void op_div (void)
369{
370 if (T1 != 0) {
thsead93602007-09-06 00:18:15 +0000371 env->LO[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
372 env->HI[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
bellard6af0bf92005-07-02 14:58:51 +0000373 }
ths8f6f6022007-11-09 23:09:41 +0000374 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000375}
ths80c27192007-04-15 21:21:33 +0000376#endif
bellard6af0bf92005-07-02 14:58:51 +0000377
378void op_divu (void)
379{
380 if (T1 != 0) {
thsead93602007-09-06 00:18:15 +0000381 env->LO[0][env->current_tc] = (int32_t)((uint32_t)T0 / (uint32_t)T1);
382 env->HI[0][env->current_tc] = (int32_t)((uint32_t)T0 % (uint32_t)T1);
thsc570fd12006-12-21 01:19:56 +0000383 }
ths8f6f6022007-11-09 23:09:41 +0000384 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000385}
386
thsd26bc212007-11-08 18:05:37 +0000387#if defined(TARGET_MIPS64)
thsc570fd12006-12-21 01:19:56 +0000388/* Arithmetic */
389void op_dadd (void)
390{
391 T0 += T1;
ths8f6f6022007-11-09 23:09:41 +0000392 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000393}
394
395void op_daddo (void)
396{
397 target_long tmp;
398
399 tmp = T0;
400 T0 += T1;
401 if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 63) {
402 /* operands of same sign, result different sign */
ths1579a722007-04-05 23:16:25 +0000403 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
thsc570fd12006-12-21 01:19:56 +0000404 }
ths8f6f6022007-11-09 23:09:41 +0000405 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000406}
407
408void op_dsub (void)
409{
410 T0 -= T1;
ths8f6f6022007-11-09 23:09:41 +0000411 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000412}
413
414void op_dsubo (void)
415{
416 target_long tmp;
417
418 tmp = T0;
419 T0 = (int64_t)T0 - (int64_t)T1;
420 if (((tmp ^ T1) & (tmp ^ T0)) >> 63) {
421 /* operands of different sign, first operand and result different sign */
ths1579a722007-04-05 23:16:25 +0000422 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
thsc570fd12006-12-21 01:19:56 +0000423 }
ths8f6f6022007-11-09 23:09:41 +0000424 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000425}
426
427void op_dmul (void)
428{
429 T0 = (int64_t)T0 * (int64_t)T1;
ths8f6f6022007-11-09 23:09:41 +0000430 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000431}
432
thsc570fd12006-12-21 01:19:56 +0000433/* Those might call libgcc functions. */
434void op_ddiv (void)
435{
436 do_ddiv();
ths8f6f6022007-11-09 23:09:41 +0000437 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000438}
439
ths80c27192007-04-15 21:21:33 +0000440#if TARGET_LONG_BITS > HOST_LONG_BITS
thsc570fd12006-12-21 01:19:56 +0000441void op_ddivu (void)
442{
443 do_ddivu();
ths8f6f6022007-11-09 23:09:41 +0000444 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000445}
446#else
thsc570fd12006-12-21 01:19:56 +0000447void op_ddivu (void)
448{
449 if (T1 != 0) {
thsead93602007-09-06 00:18:15 +0000450 env->LO[0][env->current_tc] = T0 / T1;
451 env->HI[0][env->current_tc] = T0 % T1;
bellard6af0bf92005-07-02 14:58:51 +0000452 }
ths8f6f6022007-11-09 23:09:41 +0000453 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000454}
thsc570fd12006-12-21 01:19:56 +0000455#endif
thsd26bc212007-11-08 18:05:37 +0000456#endif /* TARGET_MIPS64 */
bellard6af0bf92005-07-02 14:58:51 +0000457
458/* Logical */
459void op_and (void)
460{
461 T0 &= T1;
ths8f6f6022007-11-09 23:09:41 +0000462 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000463}
464
465void op_nor (void)
466{
467 T0 = ~(T0 | T1);
ths8f6f6022007-11-09 23:09:41 +0000468 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000469}
470
471void op_or (void)
472{
473 T0 |= T1;
ths8f6f6022007-11-09 23:09:41 +0000474 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000475}
476
477void op_xor (void)
478{
479 T0 ^= T1;
ths8f6f6022007-11-09 23:09:41 +0000480 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000481}
482
483void op_sll (void)
484{
ths5a63bcb2007-04-05 23:20:05 +0000485 T0 = (int32_t)((uint32_t)T0 << T1);
ths8f6f6022007-11-09 23:09:41 +0000486 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000487}
488
489void op_sra (void)
490{
ths5a63bcb2007-04-05 23:20:05 +0000491 T0 = (int32_t)((int32_t)T0 >> T1);
ths8f6f6022007-11-09 23:09:41 +0000492 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000493}
494
495void op_srl (void)
496{
ths5a63bcb2007-04-05 23:20:05 +0000497 T0 = (int32_t)((uint32_t)T0 >> T1);
ths8f6f6022007-11-09 23:09:41 +0000498 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000499}
500
ths7a387ff2006-12-06 20:17:30 +0000501void op_rotr (void)
502{
503 target_ulong tmp;
504
505 if (T1) {
ths5a63bcb2007-04-05 23:20:05 +0000506 tmp = (int32_t)((uint32_t)T0 << (0x20 - T1));
507 T0 = (int32_t)((uint32_t)T0 >> T1) | tmp;
508 }
ths8f6f6022007-11-09 23:09:41 +0000509 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +0000510}
511
bellard6af0bf92005-07-02 14:58:51 +0000512void op_sllv (void)
513{
ths5dc4b742006-12-21 13:48:28 +0000514 T0 = (int32_t)((uint32_t)T1 << ((uint32_t)T0 & 0x1F));
ths8f6f6022007-11-09 23:09:41 +0000515 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000516}
517
518void op_srav (void)
519{
ths5dc4b742006-12-21 13:48:28 +0000520 T0 = (int32_t)((int32_t)T1 >> (T0 & 0x1F));
ths8f6f6022007-11-09 23:09:41 +0000521 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000522}
523
524void op_srlv (void)
525{
ths5dc4b742006-12-21 13:48:28 +0000526 T0 = (int32_t)((uint32_t)T1 >> (T0 & 0x1F));
ths8f6f6022007-11-09 23:09:41 +0000527 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000528}
529
ths7a387ff2006-12-06 20:17:30 +0000530void op_rotrv (void)
531{
532 target_ulong tmp;
533
534 T0 &= 0x1F;
535 if (T0) {
ths5dc4b742006-12-21 13:48:28 +0000536 tmp = (int32_t)((uint32_t)T1 << (0x20 - T0));
537 T0 = (int32_t)((uint32_t)T1 >> T0) | tmp;
ths7a387ff2006-12-06 20:17:30 +0000538 } else
539 T0 = T1;
ths8f6f6022007-11-09 23:09:41 +0000540 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +0000541}
542
bellard6af0bf92005-07-02 14:58:51 +0000543void op_clo (void)
544{
ths05f778c2007-10-27 13:05:54 +0000545 T0 = clo32(T0);
ths8f6f6022007-11-09 23:09:41 +0000546 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000547}
548
549void op_clz (void)
550{
ths05f778c2007-10-27 13:05:54 +0000551 T0 = clz32(T0);
ths8f6f6022007-11-09 23:09:41 +0000552 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000553}
554
thsd26bc212007-11-08 18:05:37 +0000555#if defined(TARGET_MIPS64)
thsc570fd12006-12-21 01:19:56 +0000556
557#if TARGET_LONG_BITS > HOST_LONG_BITS
558/* Those might call libgcc functions. */
559void op_dsll (void)
560{
561 CALL_FROM_TB0(do_dsll);
ths8f6f6022007-11-09 23:09:41 +0000562 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000563}
564
565void op_dsll32 (void)
566{
567 CALL_FROM_TB0(do_dsll32);
ths8f6f6022007-11-09 23:09:41 +0000568 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000569}
570
571void op_dsra (void)
572{
573 CALL_FROM_TB0(do_dsra);
ths8f6f6022007-11-09 23:09:41 +0000574 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000575}
576
577void op_dsra32 (void)
578{
579 CALL_FROM_TB0(do_dsra32);
ths8f6f6022007-11-09 23:09:41 +0000580 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000581}
582
583void op_dsrl (void)
584{
585 CALL_FROM_TB0(do_dsrl);
ths8f6f6022007-11-09 23:09:41 +0000586 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000587}
588
589void op_dsrl32 (void)
590{
591 CALL_FROM_TB0(do_dsrl32);
ths8f6f6022007-11-09 23:09:41 +0000592 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000593}
594
595void op_drotr (void)
596{
597 CALL_FROM_TB0(do_drotr);
ths8f6f6022007-11-09 23:09:41 +0000598 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000599}
600
601void op_drotr32 (void)
602{
603 CALL_FROM_TB0(do_drotr32);
ths8f6f6022007-11-09 23:09:41 +0000604 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000605}
606
607void op_dsllv (void)
608{
609 CALL_FROM_TB0(do_dsllv);
ths8f6f6022007-11-09 23:09:41 +0000610 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000611}
612
613void op_dsrav (void)
614{
615 CALL_FROM_TB0(do_dsrav);
ths8f6f6022007-11-09 23:09:41 +0000616 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000617}
618
619void op_dsrlv (void)
620{
621 CALL_FROM_TB0(do_dsrlv);
ths8f6f6022007-11-09 23:09:41 +0000622 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000623}
624
625void op_drotrv (void)
626{
627 CALL_FROM_TB0(do_drotrv);
ths8f6f6022007-11-09 23:09:41 +0000628 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000629}
630
ths05f778c2007-10-27 13:05:54 +0000631void op_dclo (void)
632{
633 CALL_FROM_TB0(do_dclo);
ths8f6f6022007-11-09 23:09:41 +0000634 FORCE_RET();
ths05f778c2007-10-27 13:05:54 +0000635}
636
637void op_dclz (void)
638{
639 CALL_FROM_TB0(do_dclz);
ths8f6f6022007-11-09 23:09:41 +0000640 FORCE_RET();
ths05f778c2007-10-27 13:05:54 +0000641}
642
thsc570fd12006-12-21 01:19:56 +0000643#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
644
645void op_dsll (void)
646{
647 T0 = T0 << T1;
ths8f6f6022007-11-09 23:09:41 +0000648 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000649}
650
651void op_dsll32 (void)
652{
653 T0 = T0 << (T1 + 32);
ths8f6f6022007-11-09 23:09:41 +0000654 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000655}
656
657void op_dsra (void)
658{
659 T0 = (int64_t)T0 >> T1;
ths8f6f6022007-11-09 23:09:41 +0000660 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000661}
662
663void op_dsra32 (void)
664{
665 T0 = (int64_t)T0 >> (T1 + 32);
ths8f6f6022007-11-09 23:09:41 +0000666 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000667}
668
669void op_dsrl (void)
670{
671 T0 = T0 >> T1;
ths8f6f6022007-11-09 23:09:41 +0000672 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000673}
674
675void op_dsrl32 (void)
676{
677 T0 = T0 >> (T1 + 32);
ths8f6f6022007-11-09 23:09:41 +0000678 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000679}
680
681void op_drotr (void)
682{
683 target_ulong tmp;
684
685 if (T1) {
thsc6d6dd72007-11-18 03:36:07 +0000686 tmp = T0 << (0x40 - T1);
687 T0 = (T0 >> T1) | tmp;
ths5a63bcb2007-04-05 23:20:05 +0000688 }
ths8f6f6022007-11-09 23:09:41 +0000689 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000690}
691
692void op_drotr32 (void)
693{
694 target_ulong tmp;
695
thsc6d6dd72007-11-18 03:36:07 +0000696 tmp = T0 << (0x40 - (32 + T1));
697 T0 = (T0 >> (32 + T1)) | tmp;
ths8f6f6022007-11-09 23:09:41 +0000698 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000699}
700
701void op_dsllv (void)
702{
703 T0 = T1 << (T0 & 0x3F);
ths8f6f6022007-11-09 23:09:41 +0000704 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000705}
706
707void op_dsrav (void)
708{
709 T0 = (int64_t)T1 >> (T0 & 0x3F);
ths8f6f6022007-11-09 23:09:41 +0000710 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000711}
712
713void op_dsrlv (void)
714{
715 T0 = T1 >> (T0 & 0x3F);
ths8f6f6022007-11-09 23:09:41 +0000716 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000717}
718
719void op_drotrv (void)
720{
721 target_ulong tmp;
722
723 T0 &= 0x3F;
724 if (T0) {
thsc6d6dd72007-11-18 03:36:07 +0000725 tmp = T1 << (0x40 - T0);
726 T0 = (T1 >> T0) | tmp;
thsc570fd12006-12-21 01:19:56 +0000727 } else
thsc6d6dd72007-11-18 03:36:07 +0000728 T0 = T1;
ths8f6f6022007-11-09 23:09:41 +0000729 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000730}
thsc570fd12006-12-21 01:19:56 +0000731
732void op_dclo (void)
733{
ths05f778c2007-10-27 13:05:54 +0000734 T0 = clo64(T0);
ths8f6f6022007-11-09 23:09:41 +0000735 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000736}
737
738void op_dclz (void)
739{
ths05f778c2007-10-27 13:05:54 +0000740 T0 = clz64(T0);
ths8f6f6022007-11-09 23:09:41 +0000741 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000742}
ths05f778c2007-10-27 13:05:54 +0000743#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
thsd26bc212007-11-08 18:05:37 +0000744#endif /* TARGET_MIPS64 */
thsc570fd12006-12-21 01:19:56 +0000745
bellard6af0bf92005-07-02 14:58:51 +0000746/* 64 bits arithmetic */
thsc570fd12006-12-21 01:19:56 +0000747#if TARGET_LONG_BITS > HOST_LONG_BITS
bellard6af0bf92005-07-02 14:58:51 +0000748void op_mult (void)
749{
750 CALL_FROM_TB0(do_mult);
ths8f6f6022007-11-09 23:09:41 +0000751 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000752}
753
754void op_multu (void)
755{
756 CALL_FROM_TB0(do_multu);
ths8f6f6022007-11-09 23:09:41 +0000757 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000758}
759
760void op_madd (void)
761{
762 CALL_FROM_TB0(do_madd);
ths8f6f6022007-11-09 23:09:41 +0000763 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000764}
765
766void op_maddu (void)
767{
768 CALL_FROM_TB0(do_maddu);
ths8f6f6022007-11-09 23:09:41 +0000769 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000770}
771
772void op_msub (void)
773{
774 CALL_FROM_TB0(do_msub);
ths8f6f6022007-11-09 23:09:41 +0000775 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000776}
777
778void op_msubu (void)
779{
780 CALL_FROM_TB0(do_msubu);
ths8f6f6022007-11-09 23:09:41 +0000781 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000782}
thsc570fd12006-12-21 01:19:56 +0000783
784#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
785
thsaa343732007-10-09 03:39:58 +0000786static always_inline uint64_t get_HILO (void)
thsc570fd12006-12-21 01:19:56 +0000787{
thsead93602007-09-06 00:18:15 +0000788 return ((uint64_t)env->HI[0][env->current_tc] << 32) |
789 ((uint64_t)(uint32_t)env->LO[0][env->current_tc]);
thsc570fd12006-12-21 01:19:56 +0000790}
791
thsaa343732007-10-09 03:39:58 +0000792static always_inline void set_HILO (uint64_t HILO)
thsc570fd12006-12-21 01:19:56 +0000793{
thsead93602007-09-06 00:18:15 +0000794 env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
795 env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
thsc570fd12006-12-21 01:19:56 +0000796}
797
798void op_mult (void)
799{
800 set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
ths8f6f6022007-11-09 23:09:41 +0000801 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000802}
803
804void op_multu (void)
805{
806 set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
ths8f6f6022007-11-09 23:09:41 +0000807 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000808}
809
810void op_madd (void)
811{
812 int64_t tmp;
813
814 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
815 set_HILO((int64_t)get_HILO() + tmp);
ths8f6f6022007-11-09 23:09:41 +0000816 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000817}
818
819void op_maddu (void)
820{
821 uint64_t tmp;
822
823 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
824 set_HILO(get_HILO() + tmp);
ths8f6f6022007-11-09 23:09:41 +0000825 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000826}
827
828void op_msub (void)
829{
830 int64_t tmp;
831
832 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
833 set_HILO((int64_t)get_HILO() - tmp);
ths8f6f6022007-11-09 23:09:41 +0000834 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000835}
836
837void op_msubu (void)
838{
839 uint64_t tmp;
840
841 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
842 set_HILO(get_HILO() - tmp);
ths8f6f6022007-11-09 23:09:41 +0000843 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000844}
845#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
846
thsd26bc212007-11-08 18:05:37 +0000847#if defined(TARGET_MIPS64)
thsc570fd12006-12-21 01:19:56 +0000848void op_dmult (void)
849{
ths5592a752007-10-26 22:35:02 +0000850 CALL_FROM_TB4(muls64, &(env->LO[0][env->current_tc]), &(env->HI[0][env->current_tc]), T0, T1);
ths8f6f6022007-11-09 23:09:41 +0000851 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000852}
853
854void op_dmultu (void)
855{
ths5592a752007-10-26 22:35:02 +0000856 CALL_FROM_TB4(mulu64, &(env->LO[0][env->current_tc]), &(env->HI[0][env->current_tc]), T0, T1);
ths8f6f6022007-11-09 23:09:41 +0000857 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +0000858}
bellard6af0bf92005-07-02 14:58:51 +0000859#endif
860
861/* Conditional moves */
862void op_movn (void)
863{
864 if (T1 != 0)
thsead93602007-09-06 00:18:15 +0000865 env->gpr[PARAM1][env->current_tc] = T0;
ths8f6f6022007-11-09 23:09:41 +0000866 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000867}
868
869void op_movz (void)
870{
871 if (T1 == 0)
thsead93602007-09-06 00:18:15 +0000872 env->gpr[PARAM1][env->current_tc] = T0;
ths8f6f6022007-11-09 23:09:41 +0000873 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000874}
875
ths7a387ff2006-12-06 20:17:30 +0000876void op_movf (void)
877{
thsead93602007-09-06 00:18:15 +0000878 if (!(env->fpu->fcr31 & PARAM1))
ths5a5012e2007-05-07 13:55:33 +0000879 T0 = T1;
ths8f6f6022007-11-09 23:09:41 +0000880 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +0000881}
882
883void op_movt (void)
884{
thsead93602007-09-06 00:18:15 +0000885 if (env->fpu->fcr31 & PARAM1)
ths5a5012e2007-05-07 13:55:33 +0000886 T0 = T1;
ths8f6f6022007-11-09 23:09:41 +0000887 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +0000888}
889
bellard6af0bf92005-07-02 14:58:51 +0000890/* Tests */
891#define OP_COND(name, cond) \
892void glue(op_, name) (void) \
893{ \
894 if (cond) { \
895 T0 = 1; \
896 } else { \
897 T0 = 0; \
898 } \
ths8f6f6022007-11-09 23:09:41 +0000899 FORCE_RET(); \
bellard6af0bf92005-07-02 14:58:51 +0000900}
901
902OP_COND(eq, T0 == T1);
903OP_COND(ne, T0 != T1);
thsf469b9d2007-05-19 17:45:43 +0000904OP_COND(ge, (target_long)T0 >= (target_long)T1);
bellard6af0bf92005-07-02 14:58:51 +0000905OP_COND(geu, T0 >= T1);
thsf469b9d2007-05-19 17:45:43 +0000906OP_COND(lt, (target_long)T0 < (target_long)T1);
bellard6af0bf92005-07-02 14:58:51 +0000907OP_COND(ltu, T0 < T1);
thsf469b9d2007-05-19 17:45:43 +0000908OP_COND(gez, (target_long)T0 >= 0);
909OP_COND(gtz, (target_long)T0 > 0);
910OP_COND(lez, (target_long)T0 <= 0);
911OP_COND(ltz, (target_long)T0 < 0);
bellard6af0bf92005-07-02 14:58:51 +0000912
ths7a387ff2006-12-06 20:17:30 +0000913/* Branches */
bellardc53be332005-10-30 21:39:19 +0000914void OPPROTO op_goto_tb0(void)
915{
916 GOTO_TB(op_goto_tb0, PARAM1, 0);
ths8f6f6022007-11-09 23:09:41 +0000917 FORCE_RET();
bellardc53be332005-10-30 21:39:19 +0000918}
919
920void OPPROTO op_goto_tb1(void)
921{
922 GOTO_TB(op_goto_tb1, PARAM1, 1);
ths8f6f6022007-11-09 23:09:41 +0000923 FORCE_RET();
bellardc53be332005-10-30 21:39:19 +0000924}
bellard6af0bf92005-07-02 14:58:51 +0000925
926/* Branch to register */
927void op_save_breg_target (void)
928{
929 env->btarget = T2;
ths8f6f6022007-11-09 23:09:41 +0000930 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000931}
932
933void op_restore_breg_target (void)
934{
935 T2 = env->btarget;
ths8f6f6022007-11-09 23:09:41 +0000936 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000937}
938
939void op_breg (void)
940{
thsead93602007-09-06 00:18:15 +0000941 env->PC[env->current_tc] = T2;
ths8f6f6022007-11-09 23:09:41 +0000942 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000943}
944
bellard6af0bf92005-07-02 14:58:51 +0000945void op_save_btarget (void)
946{
947 env->btarget = PARAM1;
ths8f6f6022007-11-09 23:09:41 +0000948 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000949}
950
thsd26bc212007-11-08 18:05:37 +0000951#if defined(TARGET_MIPS64)
ths9b9e4392007-05-28 17:03:28 +0000952void op_save_btarget64 (void)
953{
954 env->btarget = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
ths8f6f6022007-11-09 23:09:41 +0000955 FORCE_RET();
ths9b9e4392007-05-28 17:03:28 +0000956}
957#endif
958
bellard6af0bf92005-07-02 14:58:51 +0000959/* Conditional branch */
960void op_set_bcond (void)
961{
962 T2 = T0;
ths8f6f6022007-11-09 23:09:41 +0000963 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000964}
965
966void op_save_bcond (void)
967{
968 env->bcond = T2;
ths8f6f6022007-11-09 23:09:41 +0000969 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000970}
971
972void op_restore_bcond (void)
973{
974 T2 = env->bcond;
ths8f6f6022007-11-09 23:09:41 +0000975 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000976}
977
bellardc53be332005-10-30 21:39:19 +0000978void op_jnz_T2 (void)
bellard6af0bf92005-07-02 14:58:51 +0000979{
bellardc53be332005-10-30 21:39:19 +0000980 if (T2)
981 GOTO_LABEL_PARAM(1);
ths8f6f6022007-11-09 23:09:41 +0000982 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +0000983}
984
985/* CP0 functions */
ths873eb012006-12-06 17:59:07 +0000986void op_mfc0_index (void)
bellard6af0bf92005-07-02 14:58:51 +0000987{
ths9c2149c2007-01-23 22:45:22 +0000988 T0 = env->CP0_Index;
ths8f6f6022007-11-09 23:09:41 +0000989 FORCE_RET();
ths873eb012006-12-06 17:59:07 +0000990}
991
thsead93602007-09-06 00:18:15 +0000992void op_mfc0_mvpcontrol (void)
993{
994 T0 = env->mvp->CP0_MVPControl;
ths8f6f6022007-11-09 23:09:41 +0000995 FORCE_RET();
thsead93602007-09-06 00:18:15 +0000996}
997
998void op_mfc0_mvpconf0 (void)
999{
1000 T0 = env->mvp->CP0_MVPConf0;
ths8f6f6022007-11-09 23:09:41 +00001001 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001002}
1003
1004void op_mfc0_mvpconf1 (void)
1005{
1006 T0 = env->mvp->CP0_MVPConf1;
ths8f6f6022007-11-09 23:09:41 +00001007 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001008}
1009
ths873eb012006-12-06 17:59:07 +00001010void op_mfc0_random (void)
1011{
1012 CALL_FROM_TB0(do_mfc0_random);
ths8f6f6022007-11-09 23:09:41 +00001013 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001014}
1015
thsead93602007-09-06 00:18:15 +00001016void op_mfc0_vpecontrol (void)
1017{
1018 T0 = env->CP0_VPEControl;
ths8f6f6022007-11-09 23:09:41 +00001019 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001020}
1021
1022void op_mfc0_vpeconf0 (void)
1023{
1024 T0 = env->CP0_VPEConf0;
ths8f6f6022007-11-09 23:09:41 +00001025 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001026}
1027
1028void op_mfc0_vpeconf1 (void)
1029{
1030 T0 = env->CP0_VPEConf1;
ths8f6f6022007-11-09 23:09:41 +00001031 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001032}
1033
1034void op_mfc0_yqmask (void)
1035{
1036 T0 = env->CP0_YQMask;
ths8f6f6022007-11-09 23:09:41 +00001037 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001038}
1039
1040void op_mfc0_vpeschedule (void)
1041{
1042 T0 = env->CP0_VPESchedule;
ths8f6f6022007-11-09 23:09:41 +00001043 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001044}
1045
1046void op_mfc0_vpeschefback (void)
1047{
1048 T0 = env->CP0_VPEScheFBack;
ths8f6f6022007-11-09 23:09:41 +00001049 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001050}
1051
1052void op_mfc0_vpeopt (void)
1053{
1054 T0 = env->CP0_VPEOpt;
ths8f6f6022007-11-09 23:09:41 +00001055 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001056}
1057
ths873eb012006-12-06 17:59:07 +00001058void op_mfc0_entrylo0 (void)
1059{
ths9c2149c2007-01-23 22:45:22 +00001060 T0 = (int32_t)env->CP0_EntryLo0;
ths8f6f6022007-11-09 23:09:41 +00001061 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001062}
1063
thsead93602007-09-06 00:18:15 +00001064void op_mfc0_tcstatus (void)
1065{
1066 T0 = env->CP0_TCStatus[env->current_tc];
ths8f6f6022007-11-09 23:09:41 +00001067 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001068}
1069
1070void op_mftc0_tcstatus(void)
1071{
1072 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1073
1074 T0 = env->CP0_TCStatus[other_tc];
ths8f6f6022007-11-09 23:09:41 +00001075 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001076}
1077
1078void op_mfc0_tcbind (void)
1079{
1080 T0 = env->CP0_TCBind[env->current_tc];
ths8f6f6022007-11-09 23:09:41 +00001081 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001082}
1083
1084void op_mftc0_tcbind(void)
1085{
1086 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1087
1088 T0 = env->CP0_TCBind[other_tc];
ths8f6f6022007-11-09 23:09:41 +00001089 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001090}
1091
1092void op_mfc0_tcrestart (void)
1093{
1094 T0 = env->PC[env->current_tc];
ths8f6f6022007-11-09 23:09:41 +00001095 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001096}
1097
1098void op_mftc0_tcrestart(void)
1099{
1100 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1101
1102 T0 = env->PC[other_tc];
ths8f6f6022007-11-09 23:09:41 +00001103 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001104}
1105
1106void op_mfc0_tchalt (void)
1107{
1108 T0 = env->CP0_TCHalt[env->current_tc];
ths8f6f6022007-11-09 23:09:41 +00001109 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001110}
1111
1112void op_mftc0_tchalt(void)
1113{
1114 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1115
1116 T0 = env->CP0_TCHalt[other_tc];
ths8f6f6022007-11-09 23:09:41 +00001117 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001118}
1119
1120void op_mfc0_tccontext (void)
1121{
1122 T0 = env->CP0_TCContext[env->current_tc];
ths8f6f6022007-11-09 23:09:41 +00001123 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001124}
1125
1126void op_mftc0_tccontext(void)
1127{
1128 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1129
1130 T0 = env->CP0_TCContext[other_tc];
ths8f6f6022007-11-09 23:09:41 +00001131 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001132}
1133
1134void op_mfc0_tcschedule (void)
1135{
1136 T0 = env->CP0_TCSchedule[env->current_tc];
ths8f6f6022007-11-09 23:09:41 +00001137 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001138}
1139
1140void op_mftc0_tcschedule(void)
1141{
1142 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1143
1144 T0 = env->CP0_TCSchedule[other_tc];
ths8f6f6022007-11-09 23:09:41 +00001145 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001146}
1147
1148void op_mfc0_tcschefback (void)
1149{
1150 T0 = env->CP0_TCScheFBack[env->current_tc];
ths8f6f6022007-11-09 23:09:41 +00001151 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001152}
1153
1154void op_mftc0_tcschefback(void)
1155{
1156 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1157
1158 T0 = env->CP0_TCScheFBack[other_tc];
ths8f6f6022007-11-09 23:09:41 +00001159 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001160}
1161
ths873eb012006-12-06 17:59:07 +00001162void op_mfc0_entrylo1 (void)
1163{
ths9c2149c2007-01-23 22:45:22 +00001164 T0 = (int32_t)env->CP0_EntryLo1;
ths8f6f6022007-11-09 23:09:41 +00001165 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001166}
1167
1168void op_mfc0_context (void)
1169{
ths9c2149c2007-01-23 22:45:22 +00001170 T0 = (int32_t)env->CP0_Context;
ths8f6f6022007-11-09 23:09:41 +00001171 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001172}
1173
1174void op_mfc0_pagemask (void)
1175{
ths9c2149c2007-01-23 22:45:22 +00001176 T0 = env->CP0_PageMask;
ths8f6f6022007-11-09 23:09:41 +00001177 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001178}
1179
ths7a387ff2006-12-06 20:17:30 +00001180void op_mfc0_pagegrain (void)
1181{
ths9c2149c2007-01-23 22:45:22 +00001182 T0 = env->CP0_PageGrain;
ths8f6f6022007-11-09 23:09:41 +00001183 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001184}
1185
ths873eb012006-12-06 17:59:07 +00001186void op_mfc0_wired (void)
1187{
ths9c2149c2007-01-23 22:45:22 +00001188 T0 = env->CP0_Wired;
ths8f6f6022007-11-09 23:09:41 +00001189 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001190}
1191
thsead93602007-09-06 00:18:15 +00001192void op_mfc0_srsconf0 (void)
1193{
1194 T0 = env->CP0_SRSConf0;
ths8f6f6022007-11-09 23:09:41 +00001195 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001196}
1197
1198void op_mfc0_srsconf1 (void)
1199{
1200 T0 = env->CP0_SRSConf1;
ths8f6f6022007-11-09 23:09:41 +00001201 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001202}
1203
1204void op_mfc0_srsconf2 (void)
1205{
1206 T0 = env->CP0_SRSConf2;
ths8f6f6022007-11-09 23:09:41 +00001207 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001208}
1209
1210void op_mfc0_srsconf3 (void)
1211{
1212 T0 = env->CP0_SRSConf3;
ths8f6f6022007-11-09 23:09:41 +00001213 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001214}
1215
1216void op_mfc0_srsconf4 (void)
1217{
1218 T0 = env->CP0_SRSConf4;
ths8f6f6022007-11-09 23:09:41 +00001219 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001220}
1221
ths7a387ff2006-12-06 20:17:30 +00001222void op_mfc0_hwrena (void)
1223{
ths9c2149c2007-01-23 22:45:22 +00001224 T0 = env->CP0_HWREna;
ths8f6f6022007-11-09 23:09:41 +00001225 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001226}
1227
ths873eb012006-12-06 17:59:07 +00001228void op_mfc0_badvaddr (void)
1229{
ths9c2149c2007-01-23 22:45:22 +00001230 T0 = (int32_t)env->CP0_BadVAddr;
ths8f6f6022007-11-09 23:09:41 +00001231 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001232}
1233
1234void op_mfc0_count (void)
1235{
1236 CALL_FROM_TB0(do_mfc0_count);
ths8f6f6022007-11-09 23:09:41 +00001237 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001238}
1239
1240void op_mfc0_entryhi (void)
1241{
ths9c2149c2007-01-23 22:45:22 +00001242 T0 = (int32_t)env->CP0_EntryHi;
ths8f6f6022007-11-09 23:09:41 +00001243 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001244}
1245
thsead93602007-09-06 00:18:15 +00001246void op_mftc0_entryhi(void)
1247{
1248 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1249
1250 T0 = (env->CP0_EntryHi & ~0xff) | (env->CP0_TCStatus[other_tc] & 0xff);
ths8f6f6022007-11-09 23:09:41 +00001251 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001252}
1253
ths873eb012006-12-06 17:59:07 +00001254void op_mfc0_compare (void)
1255{
ths9c2149c2007-01-23 22:45:22 +00001256 T0 = env->CP0_Compare;
ths8f6f6022007-11-09 23:09:41 +00001257 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001258}
1259
1260void op_mfc0_status (void)
1261{
ths9c2149c2007-01-23 22:45:22 +00001262 T0 = env->CP0_Status;
ths8f6f6022007-11-09 23:09:41 +00001263 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001264}
1265
thsead93602007-09-06 00:18:15 +00001266void op_mftc0_status(void)
1267{
1268 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1269 uint32_t tcstatus = env->CP0_TCStatus[other_tc];
1270
1271 T0 = env->CP0_Status & ~0xf1000018;
1272 T0 |= tcstatus & (0xf << CP0TCSt_TCU0);
1273 T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
ths623a9302007-10-28 19:45:05 +00001274 T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
ths8f6f6022007-11-09 23:09:41 +00001275 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001276}
1277
ths7a387ff2006-12-06 20:17:30 +00001278void op_mfc0_intctl (void)
1279{
ths9c2149c2007-01-23 22:45:22 +00001280 T0 = env->CP0_IntCtl;
ths8f6f6022007-11-09 23:09:41 +00001281 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001282}
1283
1284void op_mfc0_srsctl (void)
1285{
ths9c2149c2007-01-23 22:45:22 +00001286 T0 = env->CP0_SRSCtl;
ths8f6f6022007-11-09 23:09:41 +00001287 FORCE_RET();
ths9c2149c2007-01-23 22:45:22 +00001288}
1289
1290void op_mfc0_srsmap (void)
1291{
1292 T0 = env->CP0_SRSMap;
ths8f6f6022007-11-09 23:09:41 +00001293 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001294}
1295
ths873eb012006-12-06 17:59:07 +00001296void op_mfc0_cause (void)
1297{
ths9c2149c2007-01-23 22:45:22 +00001298 T0 = env->CP0_Cause;
ths8f6f6022007-11-09 23:09:41 +00001299 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001300}
1301
1302void op_mfc0_epc (void)
1303{
ths9c2149c2007-01-23 22:45:22 +00001304 T0 = (int32_t)env->CP0_EPC;
ths8f6f6022007-11-09 23:09:41 +00001305 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001306}
1307
1308void op_mfc0_prid (void)
1309{
ths9c2149c2007-01-23 22:45:22 +00001310 T0 = env->CP0_PRid;
ths8f6f6022007-11-09 23:09:41 +00001311 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001312}
1313
ths7a387ff2006-12-06 20:17:30 +00001314void op_mfc0_ebase (void)
1315{
thsb29a0342007-01-24 18:01:23 +00001316 T0 = env->CP0_EBase;
ths8f6f6022007-11-09 23:09:41 +00001317 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001318}
1319
ths873eb012006-12-06 17:59:07 +00001320void op_mfc0_config0 (void)
1321{
ths9c2149c2007-01-23 22:45:22 +00001322 T0 = env->CP0_Config0;
ths8f6f6022007-11-09 23:09:41 +00001323 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001324}
1325
1326void op_mfc0_config1 (void)
1327{
ths9c2149c2007-01-23 22:45:22 +00001328 T0 = env->CP0_Config1;
ths8f6f6022007-11-09 23:09:41 +00001329 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001330}
1331
ths7a387ff2006-12-06 20:17:30 +00001332void op_mfc0_config2 (void)
1333{
ths9c2149c2007-01-23 22:45:22 +00001334 T0 = env->CP0_Config2;
ths8f6f6022007-11-09 23:09:41 +00001335 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001336}
1337
1338void op_mfc0_config3 (void)
1339{
ths9c2149c2007-01-23 22:45:22 +00001340 T0 = env->CP0_Config3;
ths8f6f6022007-11-09 23:09:41 +00001341 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001342}
1343
thse397ee32007-03-23 00:43:28 +00001344void op_mfc0_config6 (void)
1345{
1346 T0 = env->CP0_Config6;
ths8f6f6022007-11-09 23:09:41 +00001347 FORCE_RET();
thse397ee32007-03-23 00:43:28 +00001348}
1349
1350void op_mfc0_config7 (void)
1351{
1352 T0 = env->CP0_Config7;
ths8f6f6022007-11-09 23:09:41 +00001353 FORCE_RET();
thse397ee32007-03-23 00:43:28 +00001354}
1355
ths873eb012006-12-06 17:59:07 +00001356void op_mfc0_lladdr (void)
1357{
ths9c2149c2007-01-23 22:45:22 +00001358 T0 = (int32_t)env->CP0_LLAddr >> 4;
ths8f6f6022007-11-09 23:09:41 +00001359 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001360}
1361
thsfd88b6a2007-05-23 08:24:25 +00001362void op_mfc0_watchlo (void)
ths873eb012006-12-06 17:59:07 +00001363{
thsfd88b6a2007-05-23 08:24:25 +00001364 T0 = (int32_t)env->CP0_WatchLo[PARAM1];
ths8f6f6022007-11-09 23:09:41 +00001365 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001366}
1367
thsfd88b6a2007-05-23 08:24:25 +00001368void op_mfc0_watchhi (void)
ths873eb012006-12-06 17:59:07 +00001369{
thsfd88b6a2007-05-23 08:24:25 +00001370 T0 = env->CP0_WatchHi[PARAM1];
ths8f6f6022007-11-09 23:09:41 +00001371 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001372}
1373
ths7a387ff2006-12-06 20:17:30 +00001374void op_mfc0_xcontext (void)
1375{
ths9c2149c2007-01-23 22:45:22 +00001376 T0 = (int32_t)env->CP0_XContext;
ths8f6f6022007-11-09 23:09:41 +00001377 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001378}
1379
1380void op_mfc0_framemask (void)
1381{
1382 T0 = env->CP0_Framemask;
ths8f6f6022007-11-09 23:09:41 +00001383 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001384}
1385
ths873eb012006-12-06 17:59:07 +00001386void op_mfc0_debug (void)
1387{
ths9c2149c2007-01-23 22:45:22 +00001388 T0 = env->CP0_Debug;
ths873eb012006-12-06 17:59:07 +00001389 if (env->hflags & MIPS_HFLAG_DM)
1390 T0 |= 1 << CP0DB_DM;
ths8f6f6022007-11-09 23:09:41 +00001391 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001392}
1393
thsead93602007-09-06 00:18:15 +00001394void op_mftc0_debug(void)
1395{
1396 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1397
1398 /* XXX: Might be wrong, check with EJTAG spec. */
1399 T0 = (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1400 (env->CP0_Debug_tcstatus[other_tc] &
1401 ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
ths8f6f6022007-11-09 23:09:41 +00001402 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001403}
1404
ths873eb012006-12-06 17:59:07 +00001405void op_mfc0_depc (void)
1406{
ths9c2149c2007-01-23 22:45:22 +00001407 T0 = (int32_t)env->CP0_DEPC;
ths8f6f6022007-11-09 23:09:41 +00001408 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001409}
1410
ths7a387ff2006-12-06 20:17:30 +00001411void op_mfc0_performance0 (void)
1412{
ths9c2149c2007-01-23 22:45:22 +00001413 T0 = env->CP0_Performance0;
ths8f6f6022007-11-09 23:09:41 +00001414 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001415}
1416
ths873eb012006-12-06 17:59:07 +00001417void op_mfc0_taglo (void)
1418{
ths9c2149c2007-01-23 22:45:22 +00001419 T0 = env->CP0_TagLo;
ths8f6f6022007-11-09 23:09:41 +00001420 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001421}
1422
1423void op_mfc0_datalo (void)
1424{
ths9c2149c2007-01-23 22:45:22 +00001425 T0 = env->CP0_DataLo;
ths8f6f6022007-11-09 23:09:41 +00001426 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001427}
1428
ths7a387ff2006-12-06 20:17:30 +00001429void op_mfc0_taghi (void)
1430{
ths9c2149c2007-01-23 22:45:22 +00001431 T0 = env->CP0_TagHi;
ths8f6f6022007-11-09 23:09:41 +00001432 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001433}
1434
1435void op_mfc0_datahi (void)
1436{
ths9c2149c2007-01-23 22:45:22 +00001437 T0 = env->CP0_DataHi;
ths8f6f6022007-11-09 23:09:41 +00001438 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001439}
1440
ths873eb012006-12-06 17:59:07 +00001441void op_mfc0_errorepc (void)
1442{
ths9c2149c2007-01-23 22:45:22 +00001443 T0 = (int32_t)env->CP0_ErrorEPC;
ths8f6f6022007-11-09 23:09:41 +00001444 FORCE_RET();
ths873eb012006-12-06 17:59:07 +00001445}
1446
1447void op_mfc0_desave (void)
1448{
ths9c2149c2007-01-23 22:45:22 +00001449 T0 = env->CP0_DESAVE;
ths8f6f6022007-11-09 23:09:41 +00001450 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +00001451}
1452
ths8c0fdd82006-12-06 18:19:33 +00001453void op_mtc0_index (void)
bellard6af0bf92005-07-02 14:58:51 +00001454{
ths60445282007-10-23 23:58:21 +00001455 int num = 1;
1456 unsigned int tmp = env->tlb->nb_tlb;
1457
1458 do {
1459 tmp >>= 1;
1460 num <<= 1;
1461 } while (tmp);
1462 env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 & (num - 1));
ths8f6f6022007-11-09 23:09:41 +00001463 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001464}
1465
1466void op_mtc0_mvpcontrol (void)
1467{
1468 uint32_t mask = 0;
1469 uint32_t newval;
1470
1471 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
1472 mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
1473 (1 << CP0MVPCo_EVP);
1474 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1475 mask |= (1 << CP0MVPCo_STLB);
1476 newval = (env->mvp->CP0_MVPControl & ~mask) | (T0 & mask);
1477
1478 // TODO: Enable/disable shared TLB, enable/disable VPEs.
1479
1480 env->mvp->CP0_MVPControl = newval;
ths8f6f6022007-11-09 23:09:41 +00001481 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001482}
1483
1484void op_mtc0_vpecontrol (void)
1485{
1486 uint32_t mask;
1487 uint32_t newval;
1488
1489 mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
1490 (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
1491 newval = (env->CP0_VPEControl & ~mask) | (T0 & mask);
1492
1493 /* Yield scheduler intercept not implemented. */
1494 /* Gating storage scheduler intercept not implemented. */
1495
1496 // TODO: Enable/disable TCs.
1497
1498 env->CP0_VPEControl = newval;
ths8f6f6022007-11-09 23:09:41 +00001499 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001500}
1501
1502void op_mtc0_vpeconf0 (void)
1503{
1504 uint32_t mask = 0;
1505 uint32_t newval;
1506
1507 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
1508 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
1509 mask |= (0xff << CP0VPEC0_XTC);
1510 mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
1511 }
1512 newval = (env->CP0_VPEConf0 & ~mask) | (T0 & mask);
1513
1514 // TODO: TC exclusive handling due to ERL/EXL.
1515
1516 env->CP0_VPEConf0 = newval;
ths8f6f6022007-11-09 23:09:41 +00001517 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001518}
1519
1520void op_mtc0_vpeconf1 (void)
1521{
1522 uint32_t mask = 0;
1523 uint32_t newval;
1524
1525 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1526 mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
1527 (0xff << CP0VPEC1_NCP1);
1528 newval = (env->CP0_VPEConf1 & ~mask) | (T0 & mask);
1529
1530 /* UDI not implemented. */
1531 /* CP2 not implemented. */
1532
1533 // TODO: Handle FPU (CP1) binding.
1534
1535 env->CP0_VPEConf1 = newval;
ths8f6f6022007-11-09 23:09:41 +00001536 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001537}
1538
1539void op_mtc0_yqmask (void)
1540{
1541 /* Yield qualifier inputs not implemented. */
1542 env->CP0_YQMask = 0x00000000;
ths8f6f6022007-11-09 23:09:41 +00001543 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001544}
1545
1546void op_mtc0_vpeschedule (void)
1547{
1548 env->CP0_VPESchedule = T0;
ths8f6f6022007-11-09 23:09:41 +00001549 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001550}
1551
1552void op_mtc0_vpeschefback (void)
1553{
1554 env->CP0_VPEScheFBack = T0;
ths8f6f6022007-11-09 23:09:41 +00001555 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001556}
1557
1558void op_mtc0_vpeopt (void)
1559{
1560 env->CP0_VPEOpt = T0 & 0x0000ffff;
ths8f6f6022007-11-09 23:09:41 +00001561 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001562}
1563
1564void op_mtc0_entrylo0 (void)
1565{
ths7a387ff2006-12-06 20:17:30 +00001566 /* Large physaddr not implemented */
1567 /* 1k pages not implemented */
thsf1b0aa52007-05-13 18:39:10 +00001568 env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
ths8f6f6022007-11-09 23:09:41 +00001569 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001570}
1571
thsead93602007-09-06 00:18:15 +00001572void op_mtc0_tcstatus (void)
1573{
1574 uint32_t mask = env->CP0_TCStatus_rw_bitmask;
1575 uint32_t newval;
1576
1577 newval = (env->CP0_TCStatus[env->current_tc] & ~mask) | (T0 & mask);
1578
1579 // TODO: Sync with CP0_Status.
1580
1581 env->CP0_TCStatus[env->current_tc] = newval;
ths8f6f6022007-11-09 23:09:41 +00001582 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001583}
1584
1585void op_mttc0_tcstatus (void)
1586{
1587 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1588
1589 // TODO: Sync with CP0_Status.
1590
1591 env->CP0_TCStatus[other_tc] = T0;
ths8f6f6022007-11-09 23:09:41 +00001592 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001593}
1594
1595void op_mtc0_tcbind (void)
1596{
1597 uint32_t mask = (1 << CP0TCBd_TBE);
1598 uint32_t newval;
1599
1600 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1601 mask |= (1 << CP0TCBd_CurVPE);
1602 newval = (env->CP0_TCBind[env->current_tc] & ~mask) | (T0 & mask);
1603 env->CP0_TCBind[env->current_tc] = newval;
ths8f6f6022007-11-09 23:09:41 +00001604 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001605}
1606
1607void op_mttc0_tcbind (void)
1608{
1609 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1610 uint32_t mask = (1 << CP0TCBd_TBE);
1611 uint32_t newval;
1612
1613 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1614 mask |= (1 << CP0TCBd_CurVPE);
1615 newval = (env->CP0_TCBind[other_tc] & ~mask) | (T0 & mask);
1616 env->CP0_TCBind[other_tc] = newval;
ths8f6f6022007-11-09 23:09:41 +00001617 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001618}
1619
1620void op_mtc0_tcrestart (void)
1621{
1622 env->PC[env->current_tc] = T0;
1623 env->CP0_TCStatus[env->current_tc] &= ~(1 << CP0TCSt_TDS);
1624 env->CP0_LLAddr = 0ULL;
1625 /* MIPS16 not implemented. */
ths8f6f6022007-11-09 23:09:41 +00001626 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001627}
1628
1629void op_mttc0_tcrestart (void)
1630{
1631 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1632
1633 env->PC[other_tc] = T0;
1634 env->CP0_TCStatus[other_tc] &= ~(1 << CP0TCSt_TDS);
1635 env->CP0_LLAddr = 0ULL;
1636 /* MIPS16 not implemented. */
ths8f6f6022007-11-09 23:09:41 +00001637 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001638}
1639
1640void op_mtc0_tchalt (void)
1641{
1642 env->CP0_TCHalt[env->current_tc] = T0 & 0x1;
1643
1644 // TODO: Halt TC / Restart (if allocated+active) TC.
1645
ths8f6f6022007-11-09 23:09:41 +00001646 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001647}
1648
1649void op_mttc0_tchalt (void)
1650{
1651 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1652
1653 // TODO: Halt TC / Restart (if allocated+active) TC.
1654
1655 env->CP0_TCHalt[other_tc] = T0;
ths8f6f6022007-11-09 23:09:41 +00001656 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001657}
1658
1659void op_mtc0_tccontext (void)
1660{
1661 env->CP0_TCContext[env->current_tc] = T0;
ths8f6f6022007-11-09 23:09:41 +00001662 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001663}
1664
1665void op_mttc0_tccontext (void)
1666{
1667 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1668
1669 env->CP0_TCContext[other_tc] = T0;
ths8f6f6022007-11-09 23:09:41 +00001670 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001671}
1672
1673void op_mtc0_tcschedule (void)
1674{
1675 env->CP0_TCSchedule[env->current_tc] = T0;
ths8f6f6022007-11-09 23:09:41 +00001676 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001677}
1678
1679void op_mttc0_tcschedule (void)
1680{
1681 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1682
1683 env->CP0_TCSchedule[other_tc] = T0;
ths8f6f6022007-11-09 23:09:41 +00001684 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001685}
1686
1687void op_mtc0_tcschefback (void)
1688{
1689 env->CP0_TCScheFBack[env->current_tc] = T0;
ths8f6f6022007-11-09 23:09:41 +00001690 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001691}
1692
1693void op_mttc0_tcschefback (void)
1694{
1695 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1696
1697 env->CP0_TCScheFBack[other_tc] = T0;
ths8f6f6022007-11-09 23:09:41 +00001698 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001699}
1700
ths8c0fdd82006-12-06 18:19:33 +00001701void op_mtc0_entrylo1 (void)
1702{
ths7a387ff2006-12-06 20:17:30 +00001703 /* Large physaddr not implemented */
1704 /* 1k pages not implemented */
thsf1b0aa52007-05-13 18:39:10 +00001705 env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
ths8f6f6022007-11-09 23:09:41 +00001706 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001707}
1708
1709void op_mtc0_context (void)
1710{
ths534ce692007-04-11 02:13:00 +00001711 env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
ths8f6f6022007-11-09 23:09:41 +00001712 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001713}
1714
1715void op_mtc0_pagemask (void)
1716{
ths7a387ff2006-12-06 20:17:30 +00001717 /* 1k pages not implemented */
thsf2e9ebe2007-05-13 14:07:26 +00001718 env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
ths8f6f6022007-11-09 23:09:41 +00001719 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001720}
1721
1722void op_mtc0_pagegrain (void)
1723{
1724 /* SmartMIPS not implemented */
1725 /* Large physaddr not implemented */
1726 /* 1k pages not implemented */
1727 env->CP0_PageGrain = 0;
ths8f6f6022007-11-09 23:09:41 +00001728 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001729}
1730
1731void op_mtc0_wired (void)
1732{
thsead93602007-09-06 00:18:15 +00001733 env->CP0_Wired = T0 % env->tlb->nb_tlb;
ths8f6f6022007-11-09 23:09:41 +00001734 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001735}
1736
1737void op_mtc0_srsconf0 (void)
1738{
1739 env->CP0_SRSConf0 |= T0 & env->CP0_SRSConf0_rw_bitmask;
ths8f6f6022007-11-09 23:09:41 +00001740 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001741}
1742
1743void op_mtc0_srsconf1 (void)
1744{
1745 env->CP0_SRSConf1 |= T0 & env->CP0_SRSConf1_rw_bitmask;
ths8f6f6022007-11-09 23:09:41 +00001746 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001747}
1748
1749void op_mtc0_srsconf2 (void)
1750{
1751 env->CP0_SRSConf2 |= T0 & env->CP0_SRSConf2_rw_bitmask;
ths8f6f6022007-11-09 23:09:41 +00001752 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001753}
1754
1755void op_mtc0_srsconf3 (void)
1756{
1757 env->CP0_SRSConf3 |= T0 & env->CP0_SRSConf3_rw_bitmask;
ths8f6f6022007-11-09 23:09:41 +00001758 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001759}
1760
1761void op_mtc0_srsconf4 (void)
1762{
1763 env->CP0_SRSConf4 |= T0 & env->CP0_SRSConf4_rw_bitmask;
ths8f6f6022007-11-09 23:09:41 +00001764 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001765}
1766
1767void op_mtc0_hwrena (void)
1768{
1769 env->CP0_HWREna = T0 & 0x0000000F;
ths8f6f6022007-11-09 23:09:41 +00001770 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001771}
1772
1773void op_mtc0_count (void)
1774{
1775 CALL_FROM_TB2(cpu_mips_store_count, env, T0);
ths8f6f6022007-11-09 23:09:41 +00001776 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001777}
1778
1779void op_mtc0_entryhi (void)
1780{
ths0feef822007-01-01 20:35:21 +00001781 target_ulong old, val;
ths8c0fdd82006-12-06 18:19:33 +00001782
ths7a387ff2006-12-06 20:17:30 +00001783 /* 1k pages not implemented */
ths100ce982007-05-13 19:22:13 +00001784 val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
thsd26bc212007-11-08 18:05:37 +00001785#if defined(TARGET_MIPS64)
thse034e2c2007-06-23 18:04:12 +00001786 val &= env->SEGMask;
ths100ce982007-05-13 19:22:13 +00001787#endif
ths8c0fdd82006-12-06 18:19:33 +00001788 old = env->CP0_EntryHi;
1789 env->CP0_EntryHi = val;
thsead93602007-09-06 00:18:15 +00001790 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
1791 uint32_t tcst = env->CP0_TCStatus[env->current_tc] & ~0xff;
1792 env->CP0_TCStatus[env->current_tc] = tcst | (val & 0xff);
1793 }
ths8c0fdd82006-12-06 18:19:33 +00001794 /* If the ASID changes, flush qemu's TLB. */
1795 if ((old & 0xFF) != (val & 0xFF))
1796 CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
ths8f6f6022007-11-09 23:09:41 +00001797 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001798}
1799
thsead93602007-09-06 00:18:15 +00001800void op_mttc0_entryhi(void)
1801{
1802 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1803
1804 env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (T0 & ~0xff);
1805 env->CP0_TCStatus[other_tc] = (env->CP0_TCStatus[other_tc] & ~0xff) | (T0 & 0xff);
ths8f6f6022007-11-09 23:09:41 +00001806 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001807}
1808
ths8c0fdd82006-12-06 18:19:33 +00001809void op_mtc0_compare (void)
1810{
1811 CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
ths8f6f6022007-11-09 23:09:41 +00001812 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001813}
1814
1815void op_mtc0_status (void)
1816{
ths4de9b242007-01-24 01:47:51 +00001817 uint32_t val, old;
thsead93602007-09-06 00:18:15 +00001818 uint32_t mask = env->CP0_Status_rw_bitmask;
ths8c0fdd82006-12-06 18:19:33 +00001819
thsf1b0aa52007-05-13 18:39:10 +00001820 val = T0 & mask;
ths8c0fdd82006-12-06 18:19:33 +00001821 old = env->CP0_Status;
ths5a5012e2007-05-07 13:55:33 +00001822 env->CP0_Status = (env->CP0_Status & ~mask) | val;
ths08fa4ba2007-09-26 23:52:06 +00001823 CALL_FROM_TB1(compute_hflags, env);
thsf41c52f2007-04-06 18:46:01 +00001824 if (loglevel & CPU_LOG_EXEC)
1825 CALL_FROM_TB2(do_mtc0_status_debug, old, val);
ths4de9b242007-01-24 01:47:51 +00001826 CALL_FROM_TB1(cpu_mips_update_irq, env);
ths8f6f6022007-11-09 23:09:41 +00001827 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001828}
1829
thsead93602007-09-06 00:18:15 +00001830void op_mttc0_status(void)
1831{
1832 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1833 uint32_t tcstatus = env->CP0_TCStatus[other_tc];
1834
1835 env->CP0_Status = T0 & ~0xf1000018;
1836 tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0));
1837 tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((T0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
ths623a9302007-10-28 19:45:05 +00001838 tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
thsead93602007-09-06 00:18:15 +00001839 env->CP0_TCStatus[other_tc] = tcstatus;
ths8f6f6022007-11-09 23:09:41 +00001840 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001841}
1842
ths7a387ff2006-12-06 20:17:30 +00001843void op_mtc0_intctl (void)
1844{
ths42532182007-09-25 16:53:15 +00001845 /* vectored interrupts not implemented, no performance counters. */
1846 env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (T0 & 0x000002e0);
ths8f6f6022007-11-09 23:09:41 +00001847 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001848}
1849
1850void op_mtc0_srsctl (void)
1851{
thsead93602007-09-06 00:18:15 +00001852 uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
1853 env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (T0 & mask);
ths8f6f6022007-11-09 23:09:41 +00001854 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001855}
1856
ths9c2149c2007-01-23 22:45:22 +00001857void op_mtc0_srsmap (void)
1858{
thsead93602007-09-06 00:18:15 +00001859 env->CP0_SRSMap = T0;
ths8f6f6022007-11-09 23:09:41 +00001860 FORCE_RET();
ths9c2149c2007-01-23 22:45:22 +00001861}
1862
ths8c0fdd82006-12-06 18:19:33 +00001863void op_mtc0_cause (void)
1864{
ths39d51eb2007-03-18 12:43:40 +00001865 uint32_t mask = 0x00C00300;
ths42532182007-09-25 16:53:15 +00001866 uint32_t old = env->CP0_Cause;
ths39d51eb2007-03-18 12:43:40 +00001867
thse189e742007-09-24 12:48:00 +00001868 if (env->insn_flags & ISA_MIPS32R2)
ths39d51eb2007-03-18 12:43:40 +00001869 mask |= 1 << CP0Ca_DC;
1870
thse58c8ba2007-04-13 20:17:54 +00001871 env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
ths8c0fdd82006-12-06 18:19:33 +00001872
ths42532182007-09-25 16:53:15 +00001873 if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
1874 if (env->CP0_Cause & (1 << CP0Ca_DC))
1875 CALL_FROM_TB1(cpu_mips_stop_count, env);
1876 else
1877 CALL_FROM_TB1(cpu_mips_start_count, env);
1878 }
1879
ths4de9b242007-01-24 01:47:51 +00001880 /* Handle the software interrupt as an hardware one, as they
1881 are very similar */
1882 if (T0 & CP0Ca_IP_mask) {
1883 CALL_FROM_TB1(cpu_mips_update_irq, env);
ths8c0fdd82006-12-06 18:19:33 +00001884 }
ths8f6f6022007-11-09 23:09:41 +00001885 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001886}
1887
1888void op_mtc0_epc (void)
1889{
thsf1b0aa52007-05-13 18:39:10 +00001890 env->CP0_EPC = T0;
ths8f6f6022007-11-09 23:09:41 +00001891 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001892}
1893
ths7a387ff2006-12-06 20:17:30 +00001894void op_mtc0_ebase (void)
1895{
1896 /* vectored interrupts not implemented */
1897 /* Multi-CPU not implemented */
thsb29a0342007-01-24 18:01:23 +00001898 env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
ths8f6f6022007-11-09 23:09:41 +00001899 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001900}
1901
ths8c0fdd82006-12-06 18:19:33 +00001902void op_mtc0_config0 (void)
1903{
ths7bfd9342007-06-22 11:50:17 +00001904 env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (T0 & 0x00000007);
ths8f6f6022007-11-09 23:09:41 +00001905 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001906}
1907
ths7a387ff2006-12-06 20:17:30 +00001908void op_mtc0_config2 (void)
1909{
1910 /* tertiary/secondary caches not implemented */
1911 env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
ths8f6f6022007-11-09 23:09:41 +00001912 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001913}
1914
thsfd88b6a2007-05-23 08:24:25 +00001915void op_mtc0_watchlo (void)
ths8c0fdd82006-12-06 18:19:33 +00001916{
ths4e7a4a42007-04-09 14:15:41 +00001917 /* Watch exceptions for instructions, data loads, data stores
1918 not implemented. */
thsfd88b6a2007-05-23 08:24:25 +00001919 env->CP0_WatchLo[PARAM1] = (T0 & ~0x7);
ths8f6f6022007-11-09 23:09:41 +00001920 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001921}
1922
thsfd88b6a2007-05-23 08:24:25 +00001923void op_mtc0_watchhi (void)
ths8c0fdd82006-12-06 18:19:33 +00001924{
thsfd88b6a2007-05-23 08:24:25 +00001925 env->CP0_WatchHi[PARAM1] = (T0 & 0x40FF0FF8);
1926 env->CP0_WatchHi[PARAM1] &= ~(env->CP0_WatchHi[PARAM1] & T0 & 0x7);
ths8f6f6022007-11-09 23:09:41 +00001927 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001928}
1929
thsead93602007-09-06 00:18:15 +00001930void op_mtc0_xcontext (void)
1931{
1932 target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
1933 env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask);
ths8f6f6022007-11-09 23:09:41 +00001934 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001935}
1936
ths7a387ff2006-12-06 20:17:30 +00001937void op_mtc0_framemask (void)
1938{
1939 env->CP0_Framemask = T0; /* XXX */
ths8f6f6022007-11-09 23:09:41 +00001940 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001941}
1942
ths8c0fdd82006-12-06 18:19:33 +00001943void op_mtc0_debug (void)
1944{
1945 env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
1946 if (T0 & (1 << CP0DB_DM))
1947 env->hflags |= MIPS_HFLAG_DM;
1948 else
1949 env->hflags &= ~MIPS_HFLAG_DM;
ths8f6f6022007-11-09 23:09:41 +00001950 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001951}
1952
thsead93602007-09-06 00:18:15 +00001953void op_mttc0_debug(void)
1954{
1955 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1956
1957 /* XXX: Might be wrong, check with EJTAG spec. */
1958 env->CP0_Debug_tcstatus[other_tc] = T0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
1959 env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1960 (T0 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
ths8f6f6022007-11-09 23:09:41 +00001961 FORCE_RET();
thsead93602007-09-06 00:18:15 +00001962}
1963
ths8c0fdd82006-12-06 18:19:33 +00001964void op_mtc0_depc (void)
1965{
thsf1b0aa52007-05-13 18:39:10 +00001966 env->CP0_DEPC = T0;
ths8f6f6022007-11-09 23:09:41 +00001967 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001968}
1969
ths7a387ff2006-12-06 20:17:30 +00001970void op_mtc0_performance0 (void)
1971{
ths1b6fd0b2007-10-29 00:49:32 +00001972 env->CP0_Performance0 = T0 & 0x000007ff;
ths8f6f6022007-11-09 23:09:41 +00001973 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001974}
1975
ths8c0fdd82006-12-06 18:19:33 +00001976void op_mtc0_taglo (void)
1977{
ths9c2149c2007-01-23 22:45:22 +00001978 env->CP0_TagLo = T0 & 0xFFFFFCF6;
ths8f6f6022007-11-09 23:09:41 +00001979 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00001980}
1981
ths7a387ff2006-12-06 20:17:30 +00001982void op_mtc0_datalo (void)
1983{
1984 env->CP0_DataLo = T0; /* XXX */
ths8f6f6022007-11-09 23:09:41 +00001985 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001986}
1987
1988void op_mtc0_taghi (void)
1989{
1990 env->CP0_TagHi = T0; /* XXX */
ths8f6f6022007-11-09 23:09:41 +00001991 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001992}
1993
1994void op_mtc0_datahi (void)
1995{
1996 env->CP0_DataHi = T0; /* XXX */
ths8f6f6022007-11-09 23:09:41 +00001997 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00001998}
1999
ths8c0fdd82006-12-06 18:19:33 +00002000void op_mtc0_errorepc (void)
2001{
thsf1b0aa52007-05-13 18:39:10 +00002002 env->CP0_ErrorEPC = T0;
ths8f6f6022007-11-09 23:09:41 +00002003 FORCE_RET();
ths8c0fdd82006-12-06 18:19:33 +00002004}
2005
2006void op_mtc0_desave (void)
2007{
2008 env->CP0_DESAVE = T0;
ths8f6f6022007-11-09 23:09:41 +00002009 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +00002010}
2011
thsd26bc212007-11-08 18:05:37 +00002012#if defined(TARGET_MIPS64)
thsead93602007-09-06 00:18:15 +00002013void op_dmfc0_yqmask (void)
thsf1b0aa52007-05-13 18:39:10 +00002014{
thsead93602007-09-06 00:18:15 +00002015 T0 = env->CP0_YQMask;
ths8f6f6022007-11-09 23:09:41 +00002016 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002017}
2018
2019void op_dmfc0_vpeschedule (void)
2020{
2021 T0 = env->CP0_VPESchedule;
ths8f6f6022007-11-09 23:09:41 +00002022 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002023}
2024
2025void op_dmfc0_vpeschefback (void)
2026{
2027 T0 = env->CP0_VPEScheFBack;
ths8f6f6022007-11-09 23:09:41 +00002028 FORCE_RET();
thsf1b0aa52007-05-13 18:39:10 +00002029}
2030
ths9c2149c2007-01-23 22:45:22 +00002031void op_dmfc0_entrylo0 (void)
2032{
2033 T0 = env->CP0_EntryLo0;
ths8f6f6022007-11-09 23:09:41 +00002034 FORCE_RET();
ths9c2149c2007-01-23 22:45:22 +00002035}
2036
thsead93602007-09-06 00:18:15 +00002037void op_dmfc0_tcrestart (void)
2038{
2039 T0 = env->PC[env->current_tc];
ths8f6f6022007-11-09 23:09:41 +00002040 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002041}
2042
2043void op_dmfc0_tchalt (void)
2044{
2045 T0 = env->CP0_TCHalt[env->current_tc];
ths8f6f6022007-11-09 23:09:41 +00002046 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002047}
2048
2049void op_dmfc0_tccontext (void)
2050{
2051 T0 = env->CP0_TCContext[env->current_tc];
ths8f6f6022007-11-09 23:09:41 +00002052 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002053}
2054
2055void op_dmfc0_tcschedule (void)
2056{
2057 T0 = env->CP0_TCSchedule[env->current_tc];
ths8f6f6022007-11-09 23:09:41 +00002058 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002059}
2060
2061void op_dmfc0_tcschefback (void)
2062{
2063 T0 = env->CP0_TCScheFBack[env->current_tc];
ths8f6f6022007-11-09 23:09:41 +00002064 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002065}
2066
ths9c2149c2007-01-23 22:45:22 +00002067void op_dmfc0_entrylo1 (void)
2068{
2069 T0 = env->CP0_EntryLo1;
ths8f6f6022007-11-09 23:09:41 +00002070 FORCE_RET();
ths9c2149c2007-01-23 22:45:22 +00002071}
2072
2073void op_dmfc0_context (void)
2074{
2075 T0 = env->CP0_Context;
ths8f6f6022007-11-09 23:09:41 +00002076 FORCE_RET();
ths9c2149c2007-01-23 22:45:22 +00002077}
2078
2079void op_dmfc0_badvaddr (void)
2080{
2081 T0 = env->CP0_BadVAddr;
ths8f6f6022007-11-09 23:09:41 +00002082 FORCE_RET();
ths9c2149c2007-01-23 22:45:22 +00002083}
2084
2085void op_dmfc0_entryhi (void)
2086{
2087 T0 = env->CP0_EntryHi;
ths8f6f6022007-11-09 23:09:41 +00002088 FORCE_RET();
ths9c2149c2007-01-23 22:45:22 +00002089}
2090
2091void op_dmfc0_epc (void)
2092{
2093 T0 = env->CP0_EPC;
ths8f6f6022007-11-09 23:09:41 +00002094 FORCE_RET();
ths9c2149c2007-01-23 22:45:22 +00002095}
2096
ths9c2149c2007-01-23 22:45:22 +00002097void op_dmfc0_lladdr (void)
2098{
2099 T0 = env->CP0_LLAddr >> 4;
ths8f6f6022007-11-09 23:09:41 +00002100 FORCE_RET();
ths9c2149c2007-01-23 22:45:22 +00002101}
2102
thsfd88b6a2007-05-23 08:24:25 +00002103void op_dmfc0_watchlo (void)
ths9c2149c2007-01-23 22:45:22 +00002104{
thsfd88b6a2007-05-23 08:24:25 +00002105 T0 = env->CP0_WatchLo[PARAM1];
ths8f6f6022007-11-09 23:09:41 +00002106 FORCE_RET();
ths9c2149c2007-01-23 22:45:22 +00002107}
2108
2109void op_dmfc0_xcontext (void)
2110{
2111 T0 = env->CP0_XContext;
ths8f6f6022007-11-09 23:09:41 +00002112 FORCE_RET();
ths9c2149c2007-01-23 22:45:22 +00002113}
2114
2115void op_dmfc0_depc (void)
2116{
2117 T0 = env->CP0_DEPC;
ths8f6f6022007-11-09 23:09:41 +00002118 FORCE_RET();
ths9c2149c2007-01-23 22:45:22 +00002119}
2120
2121void op_dmfc0_errorepc (void)
2122{
2123 T0 = env->CP0_ErrorEPC;
ths8f6f6022007-11-09 23:09:41 +00002124 FORCE_RET();
ths9c2149c2007-01-23 22:45:22 +00002125}
thsd26bc212007-11-08 18:05:37 +00002126#endif /* TARGET_MIPS64 */
ths9c2149c2007-01-23 22:45:22 +00002127
thsead93602007-09-06 00:18:15 +00002128/* MIPS MT functions */
2129void op_mftgpr(void)
2130{
2131 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2132
2133 T0 = env->gpr[PARAM1][other_tc];
ths8f6f6022007-11-09 23:09:41 +00002134 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002135}
2136
2137void op_mftlo(void)
2138{
2139 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2140
2141 T0 = env->LO[PARAM1][other_tc];
ths8f6f6022007-11-09 23:09:41 +00002142 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002143}
2144
2145void op_mfthi(void)
2146{
2147 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2148
2149 T0 = env->HI[PARAM1][other_tc];
ths8f6f6022007-11-09 23:09:41 +00002150 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002151}
2152
2153void op_mftacx(void)
2154{
2155 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2156
2157 T0 = env->ACX[PARAM1][other_tc];
ths8f6f6022007-11-09 23:09:41 +00002158 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002159}
2160
2161void op_mftdsp(void)
2162{
2163 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2164
2165 T0 = env->DSPControl[other_tc];
ths8f6f6022007-11-09 23:09:41 +00002166 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002167}
2168
2169void op_mttgpr(void)
2170{
2171 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2172
2173 T0 = env->gpr[PARAM1][other_tc];
ths8f6f6022007-11-09 23:09:41 +00002174 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002175}
2176
2177void op_mttlo(void)
2178{
2179 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2180
2181 T0 = env->LO[PARAM1][other_tc];
ths8f6f6022007-11-09 23:09:41 +00002182 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002183}
2184
2185void op_mtthi(void)
2186{
2187 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2188
2189 T0 = env->HI[PARAM1][other_tc];
ths8f6f6022007-11-09 23:09:41 +00002190 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002191}
2192
2193void op_mttacx(void)
2194{
2195 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2196
2197 T0 = env->ACX[PARAM1][other_tc];
ths8f6f6022007-11-09 23:09:41 +00002198 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002199}
2200
2201void op_mttdsp(void)
2202{
2203 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2204
2205 T0 = env->DSPControl[other_tc];
ths8f6f6022007-11-09 23:09:41 +00002206 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002207}
2208
2209
2210void op_dmt(void)
2211{
2212 // TODO
2213 T0 = 0;
2214 // rt = T0
ths8f6f6022007-11-09 23:09:41 +00002215 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002216}
2217
2218void op_emt(void)
2219{
2220 // TODO
2221 T0 = 0;
2222 // rt = T0
ths8f6f6022007-11-09 23:09:41 +00002223 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002224}
2225
2226void op_dvpe(void)
2227{
2228 // TODO
2229 T0 = 0;
2230 // rt = T0
ths8f6f6022007-11-09 23:09:41 +00002231 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002232}
2233
2234void op_evpe(void)
2235{
2236 // TODO
2237 T0 = 0;
2238 // rt = T0
ths8f6f6022007-11-09 23:09:41 +00002239 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002240}
2241
2242void op_fork(void)
2243{
2244 // T0 = rt, T1 = rs
2245 T0 = 0;
2246 // TODO: store to TC register
ths8f6f6022007-11-09 23:09:41 +00002247 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002248}
2249
2250void op_yield(void)
2251{
2252 if (T0 < 0) {
2253 /* No scheduling policy implemented. */
2254 if (T0 != -2) {
2255 if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
2256 env->CP0_TCStatus[env->current_tc] & (1 << CP0TCSt_DT)) {
2257 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2258 env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
2259 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2260 }
2261 }
2262 } else if (T0 == 0) {
2263 if (0 /* TODO: TC underflow */) {
2264 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2265 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2266 } else {
2267 // TODO: Deallocate TC
2268 }
2269 } else if (T0 > 0) {
2270 /* Yield qualifier inputs not implemented. */
2271 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2272 env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
2273 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2274 }
2275 T0 = env->CP0_YQMask;
ths8f6f6022007-11-09 23:09:41 +00002276 FORCE_RET();
thsead93602007-09-06 00:18:15 +00002277}
2278
ths5a5012e2007-05-07 13:55:33 +00002279/* CP1 functions */
bellard6ea83fe2006-06-14 12:56:19 +00002280#if 0
2281# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
2282#else
2283# define DEBUG_FPU_STATE() do { } while(0)
2284#endif
2285
ths5a5012e2007-05-07 13:55:33 +00002286void op_cfc1 (void)
2287{
thsead93602007-09-06 00:18:15 +00002288 CALL_FROM_TB1(do_cfc1, PARAM1);
ths5a5012e2007-05-07 13:55:33 +00002289 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002290 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002291}
2292
bellard6ea83fe2006-06-14 12:56:19 +00002293void op_ctc1 (void)
2294{
thsead93602007-09-06 00:18:15 +00002295 CALL_FROM_TB1(do_ctc1, PARAM1);
bellard6ea83fe2006-06-14 12:56:19 +00002296 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002297 FORCE_RET();
bellard6ea83fe2006-06-14 12:56:19 +00002298}
2299
2300void op_mfc1 (void)
2301{
ths6ad38722007-10-24 00:10:32 +00002302 T0 = (int32_t)WT0;
bellard6ea83fe2006-06-14 12:56:19 +00002303 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002304 FORCE_RET();
bellard6ea83fe2006-06-14 12:56:19 +00002305}
2306
2307void op_mtc1 (void)
2308{
2309 WT0 = T0;
2310 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002311 FORCE_RET();
bellard6ea83fe2006-06-14 12:56:19 +00002312}
2313
ths5a5012e2007-05-07 13:55:33 +00002314void op_dmfc1 (void)
2315{
2316 T0 = DT0;
2317 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002318 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002319}
2320
2321void op_dmtc1 (void)
2322{
2323 DT0 = T0;
2324 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002325 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002326}
2327
2328void op_mfhc1 (void)
2329{
ths6ad38722007-10-24 00:10:32 +00002330 T0 = (int32_t)WTH0;
ths5a5012e2007-05-07 13:55:33 +00002331 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002332 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002333}
2334
2335void op_mthc1 (void)
2336{
2337 WTH0 = T0;
2338 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002339 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002340}
2341
bellard6ea83fe2006-06-14 12:56:19 +00002342/* Float support.
2343 Single precition routines have a "s" suffix, double precision a
ths5a5012e2007-05-07 13:55:33 +00002344 "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
2345 paired single lowwer "pl", paired single upper "pu". */
bellard6ea83fe2006-06-14 12:56:19 +00002346
2347#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
2348
bellarddd016882006-10-23 21:25:11 +00002349FLOAT_OP(cvtd, s)
2350{
thsfd4a04e2007-05-18 11:55:54 +00002351 CALL_FROM_TB0(do_float_cvtd_s);
bellarddd016882006-10-23 21:25:11 +00002352 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002353 FORCE_RET();
bellarddd016882006-10-23 21:25:11 +00002354}
bellard6ea83fe2006-06-14 12:56:19 +00002355FLOAT_OP(cvtd, w)
2356{
thsfd4a04e2007-05-18 11:55:54 +00002357 CALL_FROM_TB0(do_float_cvtd_w);
ths5a5012e2007-05-07 13:55:33 +00002358 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002359 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002360}
2361FLOAT_OP(cvtd, l)
2362{
thsfd4a04e2007-05-18 11:55:54 +00002363 CALL_FROM_TB0(do_float_cvtd_l);
ths5a5012e2007-05-07 13:55:33 +00002364 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002365 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002366}
2367FLOAT_OP(cvtl, d)
2368{
thsfd4a04e2007-05-18 11:55:54 +00002369 CALL_FROM_TB0(do_float_cvtl_d);
ths5a5012e2007-05-07 13:55:33 +00002370 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002371 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002372}
2373FLOAT_OP(cvtl, s)
2374{
thsfd4a04e2007-05-18 11:55:54 +00002375 CALL_FROM_TB0(do_float_cvtl_s);
ths5a5012e2007-05-07 13:55:33 +00002376 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002377 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002378}
2379FLOAT_OP(cvtps, s)
2380{
2381 WT2 = WT0;
2382 WTH2 = WT1;
2383 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002384 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002385}
2386FLOAT_OP(cvtps, pw)
2387{
thsfd4a04e2007-05-18 11:55:54 +00002388 CALL_FROM_TB0(do_float_cvtps_pw);
ths5a5012e2007-05-07 13:55:33 +00002389 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002390 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002391}
2392FLOAT_OP(cvtpw, ps)
2393{
thsfd4a04e2007-05-18 11:55:54 +00002394 CALL_FROM_TB0(do_float_cvtpw_ps);
bellard6ea83fe2006-06-14 12:56:19 +00002395 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002396 FORCE_RET();
bellard6ea83fe2006-06-14 12:56:19 +00002397}
bellarddd016882006-10-23 21:25:11 +00002398FLOAT_OP(cvts, d)
2399{
thsfd4a04e2007-05-18 11:55:54 +00002400 CALL_FROM_TB0(do_float_cvts_d);
bellarddd016882006-10-23 21:25:11 +00002401 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002402 FORCE_RET();
bellarddd016882006-10-23 21:25:11 +00002403}
bellard6ea83fe2006-06-14 12:56:19 +00002404FLOAT_OP(cvts, w)
2405{
thsfd4a04e2007-05-18 11:55:54 +00002406 CALL_FROM_TB0(do_float_cvts_w);
ths5a5012e2007-05-07 13:55:33 +00002407 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002408 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002409}
2410FLOAT_OP(cvts, l)
2411{
thsfd4a04e2007-05-18 11:55:54 +00002412 CALL_FROM_TB0(do_float_cvts_l);
ths5a5012e2007-05-07 13:55:33 +00002413 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002414 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002415}
2416FLOAT_OP(cvts, pl)
2417{
thsfd4a04e2007-05-18 11:55:54 +00002418 CALL_FROM_TB0(do_float_cvts_pl);
ths5a5012e2007-05-07 13:55:33 +00002419 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002420 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002421}
2422FLOAT_OP(cvts, pu)
2423{
thsfd4a04e2007-05-18 11:55:54 +00002424 CALL_FROM_TB0(do_float_cvts_pu);
bellard6ea83fe2006-06-14 12:56:19 +00002425 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002426 FORCE_RET();
bellard6ea83fe2006-06-14 12:56:19 +00002427}
2428FLOAT_OP(cvtw, s)
2429{
thsfd4a04e2007-05-18 11:55:54 +00002430 CALL_FROM_TB0(do_float_cvtw_s);
bellard6ea83fe2006-06-14 12:56:19 +00002431 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002432 FORCE_RET();
bellard6ea83fe2006-06-14 12:56:19 +00002433}
2434FLOAT_OP(cvtw, d)
2435{
thsfd4a04e2007-05-18 11:55:54 +00002436 CALL_FROM_TB0(do_float_cvtw_d);
bellard6ea83fe2006-06-14 12:56:19 +00002437 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002438 FORCE_RET();
bellard6ea83fe2006-06-14 12:56:19 +00002439}
2440
ths5a5012e2007-05-07 13:55:33 +00002441FLOAT_OP(pll, ps)
2442{
2443 DT2 = ((uint64_t)WT0 << 32) | WT1;
2444 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002445 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002446}
2447FLOAT_OP(plu, ps)
2448{
2449 DT2 = ((uint64_t)WT0 << 32) | WTH1;
2450 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002451 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002452}
2453FLOAT_OP(pul, ps)
2454{
2455 DT2 = ((uint64_t)WTH0 << 32) | WT1;
2456 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002457 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002458}
2459FLOAT_OP(puu, ps)
2460{
2461 DT2 = ((uint64_t)WTH0 << 32) | WTH1;
2462 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002463 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002464}
2465
thsfd4a04e2007-05-18 11:55:54 +00002466#define FLOAT_ROUNDOP(op, ttype, stype) \
2467FLOAT_OP(op ## ttype, stype) \
2468{ \
2469 CALL_FROM_TB0(do_float_ ## op ## ttype ## _ ## stype); \
2470 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002471 FORCE_RET(); \
bellard6ea83fe2006-06-14 12:56:19 +00002472}
2473
thsfd4a04e2007-05-18 11:55:54 +00002474FLOAT_ROUNDOP(round, l, d)
2475FLOAT_ROUNDOP(round, l, s)
2476FLOAT_ROUNDOP(round, w, d)
2477FLOAT_ROUNDOP(round, w, s)
bellard6ea83fe2006-06-14 12:56:19 +00002478
thsfd4a04e2007-05-18 11:55:54 +00002479FLOAT_ROUNDOP(trunc, l, d)
2480FLOAT_ROUNDOP(trunc, l, s)
2481FLOAT_ROUNDOP(trunc, w, d)
2482FLOAT_ROUNDOP(trunc, w, s)
bellard6ea83fe2006-06-14 12:56:19 +00002483
thsfd4a04e2007-05-18 11:55:54 +00002484FLOAT_ROUNDOP(ceil, l, d)
2485FLOAT_ROUNDOP(ceil, l, s)
2486FLOAT_ROUNDOP(ceil, w, d)
2487FLOAT_ROUNDOP(ceil, w, s)
2488
2489FLOAT_ROUNDOP(floor, l, d)
2490FLOAT_ROUNDOP(floor, l, s)
2491FLOAT_ROUNDOP(floor, w, d)
2492FLOAT_ROUNDOP(floor, w, s)
2493#undef FLOAR_ROUNDOP
bellard6ea83fe2006-06-14 12:56:19 +00002494
ths5a5012e2007-05-07 13:55:33 +00002495FLOAT_OP(movf, d)
2496{
thsead93602007-09-06 00:18:15 +00002497 if (!(env->fpu->fcr31 & PARAM1))
ths5a5012e2007-05-07 13:55:33 +00002498 DT2 = DT0;
2499 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002500 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002501}
2502FLOAT_OP(movf, s)
2503{
thsead93602007-09-06 00:18:15 +00002504 if (!(env->fpu->fcr31 & PARAM1))
ths5a5012e2007-05-07 13:55:33 +00002505 WT2 = WT0;
2506 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002507 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002508}
2509FLOAT_OP(movf, ps)
2510{
thsead93602007-09-06 00:18:15 +00002511 if (!(env->fpu->fcr31 & PARAM1)) {
ths5a5012e2007-05-07 13:55:33 +00002512 WT2 = WT0;
2513 WTH2 = WTH0;
2514 }
2515 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002516 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002517}
2518FLOAT_OP(movt, d)
2519{
thsead93602007-09-06 00:18:15 +00002520 if (env->fpu->fcr31 & PARAM1)
ths5a5012e2007-05-07 13:55:33 +00002521 DT2 = DT0;
2522 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002523 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002524}
2525FLOAT_OP(movt, s)
2526{
thsead93602007-09-06 00:18:15 +00002527 if (env->fpu->fcr31 & PARAM1)
ths5a5012e2007-05-07 13:55:33 +00002528 WT2 = WT0;
2529 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002530 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002531}
2532FLOAT_OP(movt, ps)
2533{
thsead93602007-09-06 00:18:15 +00002534 if (env->fpu->fcr31 & PARAM1) {
ths5a5012e2007-05-07 13:55:33 +00002535 WT2 = WT0;
2536 WTH2 = WTH0;
2537 }
2538 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002539 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002540}
2541FLOAT_OP(movz, d)
2542{
2543 if (!T0)
2544 DT2 = DT0;
2545 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002546 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002547}
2548FLOAT_OP(movz, s)
2549{
2550 if (!T0)
2551 WT2 = WT0;
2552 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002553 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002554}
2555FLOAT_OP(movz, ps)
2556{
2557 if (!T0) {
2558 WT2 = WT0;
2559 WTH2 = WTH0;
2560 }
2561 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002562 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002563}
2564FLOAT_OP(movn, d)
2565{
2566 if (T0)
2567 DT2 = DT0;
2568 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002569 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002570}
2571FLOAT_OP(movn, s)
2572{
2573 if (T0)
2574 WT2 = WT0;
2575 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002576 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002577}
2578FLOAT_OP(movn, ps)
2579{
2580 if (T0) {
2581 WT2 = WT0;
2582 WTH2 = WTH0;
2583 }
2584 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002585 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002586}
2587
ths57fa1fb2007-05-19 20:29:41 +00002588/* operations calling helpers, for s, d and ps */
ths8f6f6022007-11-09 23:09:41 +00002589#define FLOAT_HOP(name) \
bellard6ea83fe2006-06-14 12:56:19 +00002590FLOAT_OP(name, d) \
2591{ \
thsfd4a04e2007-05-18 11:55:54 +00002592 CALL_FROM_TB0(do_float_ ## name ## _d); \
bellard6ea83fe2006-06-14 12:56:19 +00002593 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002594 FORCE_RET(); \
bellard6ea83fe2006-06-14 12:56:19 +00002595} \
2596FLOAT_OP(name, s) \
2597{ \
thsfd4a04e2007-05-18 11:55:54 +00002598 CALL_FROM_TB0(do_float_ ## name ## _s); \
ths5a5012e2007-05-07 13:55:33 +00002599 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002600 FORCE_RET(); \
ths5a5012e2007-05-07 13:55:33 +00002601} \
2602FLOAT_OP(name, ps) \
2603{ \
thsfd4a04e2007-05-18 11:55:54 +00002604 CALL_FROM_TB0(do_float_ ## name ## _ps); \
bellard6ea83fe2006-06-14 12:56:19 +00002605 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002606 FORCE_RET(); \
bellard6ea83fe2006-06-14 12:56:19 +00002607}
ths57fa1fb2007-05-19 20:29:41 +00002608FLOAT_HOP(add)
2609FLOAT_HOP(sub)
2610FLOAT_HOP(mul)
2611FLOAT_HOP(div)
2612FLOAT_HOP(recip2)
2613FLOAT_HOP(rsqrt2)
2614FLOAT_HOP(rsqrt1)
2615FLOAT_HOP(recip1)
2616#undef FLOAT_HOP
bellard6ea83fe2006-06-14 12:56:19 +00002617
ths57fa1fb2007-05-19 20:29:41 +00002618/* operations calling helpers, for s and d */
2619#define FLOAT_HOP(name) \
2620FLOAT_OP(name, d) \
2621{ \
2622 CALL_FROM_TB0(do_float_ ## name ## _d); \
2623 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002624 FORCE_RET(); \
ths57fa1fb2007-05-19 20:29:41 +00002625} \
2626FLOAT_OP(name, s) \
2627{ \
2628 CALL_FROM_TB0(do_float_ ## name ## _s); \
2629 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002630 FORCE_RET(); \
thsfbcc6822007-05-11 09:59:10 +00002631}
ths57fa1fb2007-05-19 20:29:41 +00002632FLOAT_HOP(rsqrt)
2633FLOAT_HOP(recip)
2634#undef FLOAT_HOP
2635
2636/* operations calling helpers, for ps */
2637#define FLOAT_HOP(name) \
2638FLOAT_OP(name, ps) \
2639{ \
2640 CALL_FROM_TB0(do_float_ ## name ## _ps); \
2641 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002642 FORCE_RET(); \
ths57fa1fb2007-05-19 20:29:41 +00002643}
2644FLOAT_HOP(addr)
2645FLOAT_HOP(mulr)
2646#undef FLOAT_HOP
thsfbcc6822007-05-11 09:59:10 +00002647
ths5a5012e2007-05-07 13:55:33 +00002648/* ternary operations */
2649#define FLOAT_TERNOP(name1, name2) \
2650FLOAT_OP(name1 ## name2, d) \
2651{ \
thsead93602007-09-06 00:18:15 +00002652 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
2653 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
ths5a5012e2007-05-07 13:55:33 +00002654 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002655 FORCE_RET(); \
ths5a5012e2007-05-07 13:55:33 +00002656} \
2657FLOAT_OP(name1 ## name2, s) \
2658{ \
thsead93602007-09-06 00:18:15 +00002659 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2660 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
ths5a5012e2007-05-07 13:55:33 +00002661 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002662 FORCE_RET(); \
ths5a5012e2007-05-07 13:55:33 +00002663} \
2664FLOAT_OP(name1 ## name2, ps) \
2665{ \
thsead93602007-09-06 00:18:15 +00002666 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2667 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2668 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2669 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
ths5a5012e2007-05-07 13:55:33 +00002670 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002671 FORCE_RET(); \
ths5a5012e2007-05-07 13:55:33 +00002672}
2673FLOAT_TERNOP(mul, add)
2674FLOAT_TERNOP(mul, sub)
2675#undef FLOAT_TERNOP
2676
thsfbcc6822007-05-11 09:59:10 +00002677/* negated ternary operations */
2678#define FLOAT_NTERNOP(name1, name2) \
2679FLOAT_OP(n ## name1 ## name2, d) \
2680{ \
thsead93602007-09-06 00:18:15 +00002681 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
2682 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
pbrook5747c072007-11-17 14:53:06 +00002683 FDT2 = float64_chs(FDT2); \
thsfbcc6822007-05-11 09:59:10 +00002684 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002685 FORCE_RET(); \
thsfbcc6822007-05-11 09:59:10 +00002686} \
2687FLOAT_OP(n ## name1 ## name2, s) \
2688{ \
thsead93602007-09-06 00:18:15 +00002689 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2690 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
pbrook5747c072007-11-17 14:53:06 +00002691 FST2 = float32_chs(FST2); \
thsfbcc6822007-05-11 09:59:10 +00002692 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002693 FORCE_RET(); \
thsfbcc6822007-05-11 09:59:10 +00002694} \
2695FLOAT_OP(n ## name1 ## name2, ps) \
2696{ \
thsead93602007-09-06 00:18:15 +00002697 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2698 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2699 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2700 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
pbrook5747c072007-11-17 14:53:06 +00002701 FST2 = float32_chs(FST2); \
2702 FSTH2 = float32_chs(FSTH2); \
thsfbcc6822007-05-11 09:59:10 +00002703 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002704 FORCE_RET(); \
thsfbcc6822007-05-11 09:59:10 +00002705}
2706FLOAT_NTERNOP(mul, add)
2707FLOAT_NTERNOP(mul, sub)
2708#undef FLOAT_NTERNOP
2709
bellard6ea83fe2006-06-14 12:56:19 +00002710/* unary operations, modifying fp status */
2711#define FLOAT_UNOP(name) \
2712FLOAT_OP(name, d) \
2713{ \
ths8f6f6022007-11-09 23:09:41 +00002714 FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \
bellard6ea83fe2006-06-14 12:56:19 +00002715 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002716 FORCE_RET(); \
bellard6ea83fe2006-06-14 12:56:19 +00002717} \
2718FLOAT_OP(name, s) \
2719{ \
ths8f6f6022007-11-09 23:09:41 +00002720 FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \
bellard6ea83fe2006-06-14 12:56:19 +00002721 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002722 FORCE_RET(); \
bellard6ea83fe2006-06-14 12:56:19 +00002723}
2724FLOAT_UNOP(sqrt)
2725#undef FLOAT_UNOP
2726
2727/* unary operations, not modifying fp status */
2728#define FLOAT_UNOP(name) \
2729FLOAT_OP(name, d) \
2730{ \
2731 FDT2 = float64_ ## name(FDT0); \
2732 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002733 FORCE_RET(); \
bellard6ea83fe2006-06-14 12:56:19 +00002734} \
2735FLOAT_OP(name, s) \
2736{ \
2737 FST2 = float32_ ## name(FST0); \
2738 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002739 FORCE_RET(); \
ths5a5012e2007-05-07 13:55:33 +00002740} \
2741FLOAT_OP(name, ps) \
2742{ \
2743 FST2 = float32_ ## name(FST0); \
2744 FSTH2 = float32_ ## name(FSTH0); \
2745 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002746 FORCE_RET(); \
bellard6ea83fe2006-06-14 12:56:19 +00002747}
2748FLOAT_UNOP(abs)
2749FLOAT_UNOP(chs)
2750#undef FLOAT_UNOP
2751
2752FLOAT_OP(mov, d)
2753{
2754 FDT2 = FDT0;
2755 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002756 FORCE_RET();
bellard6ea83fe2006-06-14 12:56:19 +00002757}
2758FLOAT_OP(mov, s)
2759{
2760 FST2 = FST0;
2761 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002762 FORCE_RET();
bellard6ea83fe2006-06-14 12:56:19 +00002763}
ths5a5012e2007-05-07 13:55:33 +00002764FLOAT_OP(mov, ps)
2765{
2766 FST2 = FST0;
2767 FSTH2 = FSTH0;
2768 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002769 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002770}
2771FLOAT_OP(alnv, ps)
2772{
2773 switch (T0 & 0x7) {
2774 case 0:
2775 FST2 = FST0;
2776 FSTH2 = FSTH0;
2777 break;
2778 case 4:
2779#ifdef TARGET_WORDS_BIGENDIAN
2780 FSTH2 = FST0;
2781 FST2 = FSTH1;
2782#else
2783 FSTH2 = FST1;
2784 FST2 = FSTH0;
2785#endif
2786 break;
2787 default: /* unpredictable */
2788 break;
2789 }
2790 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002791 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002792}
bellard6ea83fe2006-06-14 12:56:19 +00002793
2794#ifdef CONFIG_SOFTFLOAT
2795#define clear_invalid() do { \
thsead93602007-09-06 00:18:15 +00002796 int flags = get_float_exception_flags(&env->fpu->fp_status); \
bellard6ea83fe2006-06-14 12:56:19 +00002797 flags &= ~float_flag_invalid; \
ths8f6f6022007-11-09 23:09:41 +00002798 set_float_exception_flags(flags, &env->fpu->fp_status); \
bellard6ea83fe2006-06-14 12:56:19 +00002799} while(0)
2800#else
2801#define clear_invalid() do { } while(0)
2802#endif
2803
2804extern void dump_fpu_s(CPUState *env);
2805
thsfd4a04e2007-05-18 11:55:54 +00002806#define CMP_OP(fmt, op) \
2807void OPPROTO op_cmp ## _ ## fmt ## _ ## op(void) \
2808{ \
2809 CALL_FROM_TB1(do_cmp ## _ ## fmt ## _ ## op, PARAM1); \
2810 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002811 FORCE_RET(); \
thsfd4a04e2007-05-18 11:55:54 +00002812} \
2813void OPPROTO op_cmpabs ## _ ## fmt ## _ ## op(void) \
2814{ \
2815 CALL_FROM_TB1(do_cmpabs ## _ ## fmt ## _ ## op, PARAM1); \
2816 DEBUG_FPU_STATE(); \
ths8f6f6022007-11-09 23:09:41 +00002817 FORCE_RET(); \
bellard6ea83fe2006-06-14 12:56:19 +00002818}
thsfd4a04e2007-05-18 11:55:54 +00002819#define CMP_OPS(op) \
2820CMP_OP(d, op) \
2821CMP_OP(s, op) \
2822CMP_OP(ps, op)
bellard6ea83fe2006-06-14 12:56:19 +00002823
thsfd4a04e2007-05-18 11:55:54 +00002824CMP_OPS(f)
2825CMP_OPS(un)
2826CMP_OPS(eq)
2827CMP_OPS(ueq)
2828CMP_OPS(olt)
2829CMP_OPS(ult)
2830CMP_OPS(ole)
2831CMP_OPS(ule)
2832CMP_OPS(sf)
2833CMP_OPS(ngle)
2834CMP_OPS(seq)
2835CMP_OPS(ngl)
2836CMP_OPS(lt)
2837CMP_OPS(nge)
2838CMP_OPS(le)
2839CMP_OPS(ngt)
2840#undef CMP_OPS
2841#undef CMP_OP
bellard6ea83fe2006-06-14 12:56:19 +00002842
2843void op_bc1f (void)
2844{
thsead93602007-09-06 00:18:15 +00002845 T0 = !!(~GET_FP_COND(env->fpu) & (0x1 << PARAM1));
ths5a5012e2007-05-07 13:55:33 +00002846 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002847 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002848}
thsfd4a04e2007-05-18 11:55:54 +00002849void op_bc1any2f (void)
ths5a5012e2007-05-07 13:55:33 +00002850{
thsead93602007-09-06 00:18:15 +00002851 T0 = !!(~GET_FP_COND(env->fpu) & (0x3 << PARAM1));
ths5a5012e2007-05-07 13:55:33 +00002852 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002853 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002854}
thsfd4a04e2007-05-18 11:55:54 +00002855void op_bc1any4f (void)
ths5a5012e2007-05-07 13:55:33 +00002856{
thsead93602007-09-06 00:18:15 +00002857 T0 = !!(~GET_FP_COND(env->fpu) & (0xf << PARAM1));
bellard6ea83fe2006-06-14 12:56:19 +00002858 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002859 FORCE_RET();
bellard6ea83fe2006-06-14 12:56:19 +00002860}
2861
2862void op_bc1t (void)
2863{
thsead93602007-09-06 00:18:15 +00002864 T0 = !!(GET_FP_COND(env->fpu) & (0x1 << PARAM1));
ths5a5012e2007-05-07 13:55:33 +00002865 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002866 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002867}
thsfd4a04e2007-05-18 11:55:54 +00002868void op_bc1any2t (void)
ths5a5012e2007-05-07 13:55:33 +00002869{
thsead93602007-09-06 00:18:15 +00002870 T0 = !!(GET_FP_COND(env->fpu) & (0x3 << PARAM1));
ths5a5012e2007-05-07 13:55:33 +00002871 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002872 FORCE_RET();
ths5a5012e2007-05-07 13:55:33 +00002873}
thsfd4a04e2007-05-18 11:55:54 +00002874void op_bc1any4t (void)
ths5a5012e2007-05-07 13:55:33 +00002875{
thsead93602007-09-06 00:18:15 +00002876 T0 = !!(GET_FP_COND(env->fpu) & (0xf << PARAM1));
bellard6ea83fe2006-06-14 12:56:19 +00002877 DEBUG_FPU_STATE();
ths8f6f6022007-11-09 23:09:41 +00002878 FORCE_RET();
bellard6ea83fe2006-06-14 12:56:19 +00002879}
bellard6ea83fe2006-06-14 12:56:19 +00002880
bellard6af0bf92005-07-02 14:58:51 +00002881void op_tlbwi (void)
2882{
thsead93602007-09-06 00:18:15 +00002883 CALL_FROM_TB0(env->tlb->do_tlbwi);
ths8f6f6022007-11-09 23:09:41 +00002884 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +00002885}
2886
2887void op_tlbwr (void)
2888{
thsead93602007-09-06 00:18:15 +00002889 CALL_FROM_TB0(env->tlb->do_tlbwr);
ths8f6f6022007-11-09 23:09:41 +00002890 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +00002891}
2892
2893void op_tlbp (void)
2894{
thsead93602007-09-06 00:18:15 +00002895 CALL_FROM_TB0(env->tlb->do_tlbp);
ths8f6f6022007-11-09 23:09:41 +00002896 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +00002897}
2898
2899void op_tlbr (void)
2900{
thsead93602007-09-06 00:18:15 +00002901 CALL_FROM_TB0(env->tlb->do_tlbr);
ths8f6f6022007-11-09 23:09:41 +00002902 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +00002903}
bellard6af0bf92005-07-02 14:58:51 +00002904
2905/* Specials */
ths6f5b89a2007-03-02 20:48:00 +00002906#if defined (CONFIG_USER_ONLY)
2907void op_tls_value (void)
2908{
ths5a5012e2007-05-07 13:55:33 +00002909 T0 = env->tls_value;
ths6f5b89a2007-03-02 20:48:00 +00002910}
2911#endif
2912
bellard6af0bf92005-07-02 14:58:51 +00002913void op_pmon (void)
2914{
2915 CALL_FROM_TB1(do_pmon, PARAM1);
ths8f6f6022007-11-09 23:09:41 +00002916 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00002917}
2918
2919void op_di (void)
2920{
ths7a387ff2006-12-06 20:17:30 +00002921 T0 = env->CP0_Status;
ths4de9b242007-01-24 01:47:51 +00002922 env->CP0_Status = T0 & ~(1 << CP0St_IE);
2923 CALL_FROM_TB1(cpu_mips_update_irq, env);
ths8f6f6022007-11-09 23:09:41 +00002924 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00002925}
2926
2927void op_ei (void)
2928{
ths7a387ff2006-12-06 20:17:30 +00002929 T0 = env->CP0_Status;
ths4de9b242007-01-24 01:47:51 +00002930 env->CP0_Status = T0 | (1 << CP0St_IE);
2931 CALL_FROM_TB1(cpu_mips_update_irq, env);
ths8f6f6022007-11-09 23:09:41 +00002932 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +00002933}
2934
2935void op_trap (void)
2936{
2937 if (T0) {
ths1579a722007-04-05 23:16:25 +00002938 CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
bellard6af0bf92005-07-02 14:58:51 +00002939 }
ths8f6f6022007-11-09 23:09:41 +00002940 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +00002941}
2942
bellard4ad40f32005-12-05 19:59:36 +00002943void op_debug (void)
2944{
ths7a387ff2006-12-06 20:17:30 +00002945 CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
ths8f6f6022007-11-09 23:09:41 +00002946 FORCE_RET();
bellard4ad40f32005-12-05 19:59:36 +00002947}
2948
bellard6af0bf92005-07-02 14:58:51 +00002949void op_set_lladdr (void)
2950{
2951 env->CP0_LLAddr = T2;
ths8f6f6022007-11-09 23:09:41 +00002952 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +00002953}
2954
thsf41c52f2007-04-06 18:46:01 +00002955void debug_pre_eret (void);
2956void debug_post_eret (void);
bellard6af0bf92005-07-02 14:58:51 +00002957void op_eret (void)
2958{
thsf41c52f2007-04-06 18:46:01 +00002959 if (loglevel & CPU_LOG_EXEC)
2960 CALL_FROM_TB0(debug_pre_eret);
ths24c7b0e2007-03-30 16:44:54 +00002961 if (env->CP0_Status & (1 << CP0St_ERL)) {
thsead93602007-09-06 00:18:15 +00002962 env->PC[env->current_tc] = env->CP0_ErrorEPC;
ths24c7b0e2007-03-30 16:44:54 +00002963 env->CP0_Status &= ~(1 << CP0St_ERL);
bellard51e11d92005-07-02 15:23:21 +00002964 } else {
thsead93602007-09-06 00:18:15 +00002965 env->PC[env->current_tc] = env->CP0_EPC;
ths24c7b0e2007-03-30 16:44:54 +00002966 env->CP0_Status &= ~(1 << CP0St_EXL);
bellard51e11d92005-07-02 15:23:21 +00002967 }
ths08fa4ba2007-09-26 23:52:06 +00002968 CALL_FROM_TB1(compute_hflags, env);
thsf41c52f2007-04-06 18:46:01 +00002969 if (loglevel & CPU_LOG_EXEC)
2970 CALL_FROM_TB0(debug_post_eret);
bellard6af0bf92005-07-02 14:58:51 +00002971 env->CP0_LLAddr = 1;
ths8f6f6022007-11-09 23:09:41 +00002972 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +00002973}
2974
2975void op_deret (void)
2976{
thsf41c52f2007-04-06 18:46:01 +00002977 if (loglevel & CPU_LOG_EXEC)
2978 CALL_FROM_TB0(debug_pre_eret);
thsead93602007-09-06 00:18:15 +00002979 env->PC[env->current_tc] = env->CP0_DEPC;
ths08fa4ba2007-09-26 23:52:06 +00002980 env->hflags &= MIPS_HFLAG_DM;
2981 CALL_FROM_TB1(compute_hflags, env);
thsf41c52f2007-04-06 18:46:01 +00002982 if (loglevel & CPU_LOG_EXEC)
2983 CALL_FROM_TB0(debug_post_eret);
ths24c7b0e2007-03-30 16:44:54 +00002984 env->CP0_LLAddr = 1;
ths8f6f6022007-11-09 23:09:41 +00002985 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00002986}
2987
2988void op_rdhwr_cpunum(void)
2989{
ths387a8fe2007-09-25 14:49:47 +00002990 if ((env->hflags & MIPS_HFLAG_CP0) ||
2991 (env->CP0_HWREna & (1 << 0)))
ths1579a722007-04-05 23:16:25 +00002992 T0 = env->CP0_EBase & 0x3ff;
ths7a387ff2006-12-06 20:17:30 +00002993 else
ths1579a722007-04-05 23:16:25 +00002994 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
ths8f6f6022007-11-09 23:09:41 +00002995 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00002996}
2997
2998void op_rdhwr_synci_step(void)
2999{
ths387a8fe2007-09-25 14:49:47 +00003000 if ((env->hflags & MIPS_HFLAG_CP0) ||
3001 (env->CP0_HWREna & (1 << 1)))
ths1579a722007-04-05 23:16:25 +00003002 T0 = env->SYNCI_Step;
ths7a387ff2006-12-06 20:17:30 +00003003 else
ths1579a722007-04-05 23:16:25 +00003004 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
ths8f6f6022007-11-09 23:09:41 +00003005 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00003006}
3007
3008void op_rdhwr_cc(void)
3009{
ths387a8fe2007-09-25 14:49:47 +00003010 if ((env->hflags & MIPS_HFLAG_CP0) ||
3011 (env->CP0_HWREna & (1 << 2)))
ths1579a722007-04-05 23:16:25 +00003012 T0 = env->CP0_Count;
ths7a387ff2006-12-06 20:17:30 +00003013 else
ths1579a722007-04-05 23:16:25 +00003014 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
ths8f6f6022007-11-09 23:09:41 +00003015 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00003016}
3017
3018void op_rdhwr_ccres(void)
3019{
ths387a8fe2007-09-25 14:49:47 +00003020 if ((env->hflags & MIPS_HFLAG_CP0) ||
3021 (env->CP0_HWREna & (1 << 3)))
ths1579a722007-04-05 23:16:25 +00003022 T0 = env->CCRes;
ths7a387ff2006-12-06 20:17:30 +00003023 else
ths1579a722007-04-05 23:16:25 +00003024 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
ths8f6f6022007-11-09 23:09:41 +00003025 FORCE_RET();
ths1579a722007-04-05 23:16:25 +00003026}
3027
bellard6af0bf92005-07-02 14:58:51 +00003028void op_save_state (void)
3029{
3030 env->hflags = PARAM1;
ths8f6f6022007-11-09 23:09:41 +00003031 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +00003032}
3033
3034void op_save_pc (void)
3035{
thsead93602007-09-06 00:18:15 +00003036 env->PC[env->current_tc] = PARAM1;
ths8f6f6022007-11-09 23:09:41 +00003037 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +00003038}
3039
thsd26bc212007-11-08 18:05:37 +00003040#if defined(TARGET_MIPS64)
ths9b9e4392007-05-28 17:03:28 +00003041void op_save_pc64 (void)
3042{
thsead93602007-09-06 00:18:15 +00003043 env->PC[env->current_tc] = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
ths8f6f6022007-11-09 23:09:41 +00003044 FORCE_RET();
ths9b9e4392007-05-28 17:03:28 +00003045}
3046#endif
3047
ths16c00cb2007-04-14 12:56:46 +00003048void op_interrupt_restart (void)
3049{
3050 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
3051 !(env->CP0_Status & (1 << CP0St_ERL)) &&
3052 !(env->hflags & MIPS_HFLAG_DM) &&
3053 (env->CP0_Status & (1 << CP0St_IE)) &&
3054 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
3055 env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
3056 CALL_FROM_TB1(do_raise_exception, EXCP_EXT_INTERRUPT);
3057 }
ths8f6f6022007-11-09 23:09:41 +00003058 FORCE_RET();
ths16c00cb2007-04-14 12:56:46 +00003059}
3060
bellard6af0bf92005-07-02 14:58:51 +00003061void op_raise_exception (void)
3062{
3063 CALL_FROM_TB1(do_raise_exception, PARAM1);
ths8f6f6022007-11-09 23:09:41 +00003064 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +00003065}
3066
3067void op_raise_exception_err (void)
3068{
3069 CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
ths8f6f6022007-11-09 23:09:41 +00003070 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +00003071}
3072
3073void op_exit_tb (void)
3074{
3075 EXIT_TB();
ths8f6f6022007-11-09 23:09:41 +00003076 FORCE_RET();
bellard6af0bf92005-07-02 14:58:51 +00003077}
3078
bellard4ad40f32005-12-05 19:59:36 +00003079void op_wait (void)
3080{
3081 env->halted = 1;
3082 CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
ths8f6f6022007-11-09 23:09:41 +00003083 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00003084}
3085
3086/* Bitfield operations. */
3087void op_ext(void)
3088{
3089 unsigned int pos = PARAM1;
3090 unsigned int size = PARAM2;
3091
thsc6d6dd72007-11-18 03:36:07 +00003092 T0 = (int32_t)((T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0));
ths8f6f6022007-11-09 23:09:41 +00003093 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00003094}
3095
3096void op_ins(void)
3097{
3098 unsigned int pos = PARAM1;
3099 unsigned int size = PARAM2;
thsf757d6f2007-04-07 01:09:17 +00003100 target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
ths7a387ff2006-12-06 20:17:30 +00003101
thsc6d6dd72007-11-18 03:36:07 +00003102 T0 = (int32_t)((T0 & ~mask) | ((T1 << pos) & mask));
ths8f6f6022007-11-09 23:09:41 +00003103 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00003104}
3105
3106void op_wsbh(void)
3107{
thsc6d6dd72007-11-18 03:36:07 +00003108 T0 = (int32_t)(((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF));
ths8f6f6022007-11-09 23:09:41 +00003109 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00003110}
3111
thsd26bc212007-11-08 18:05:37 +00003112#if defined(TARGET_MIPS64)
thsc570fd12006-12-21 01:19:56 +00003113void op_dext(void)
3114{
3115 unsigned int pos = PARAM1;
3116 unsigned int size = PARAM2;
3117
thsc6d6dd72007-11-18 03:36:07 +00003118 T0 = (T1 >> pos) & ((size < 64) ? ((1ULL << size) - 1) : ~0ULL);
ths8f6f6022007-11-09 23:09:41 +00003119 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +00003120}
3121
3122void op_dins(void)
3123{
3124 unsigned int pos = PARAM1;
3125 unsigned int size = PARAM2;
thsc6d6dd72007-11-18 03:36:07 +00003126 target_ulong mask = ((size < 64) ? ((1ULL << size) - 1) : ~0ULL) << pos;
thsc570fd12006-12-21 01:19:56 +00003127
ths171b31e2007-04-15 21:26:37 +00003128 T0 = (T0 & ~mask) | ((T1 << pos) & mask);
ths8f6f6022007-11-09 23:09:41 +00003129 FORCE_RET();
thsc570fd12006-12-21 01:19:56 +00003130}
3131
ths7a387ff2006-12-06 20:17:30 +00003132void op_dsbh(void)
3133{
3134 T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
ths8f6f6022007-11-09 23:09:41 +00003135 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00003136}
3137
3138void op_dshd(void)
3139{
thsc6d6dd72007-11-18 03:36:07 +00003140 T1 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
3141 T0 = (T1 << 32) | (T1 >> 32);
ths8f6f6022007-11-09 23:09:41 +00003142 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00003143}
thsc570fd12006-12-21 01:19:56 +00003144#endif
ths7a387ff2006-12-06 20:17:30 +00003145
3146void op_seb(void)
3147{
3148 T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
ths8f6f6022007-11-09 23:09:41 +00003149 FORCE_RET();
ths7a387ff2006-12-06 20:17:30 +00003150}
3151
3152void op_seh(void)
3153{
3154 T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
ths8f6f6022007-11-09 23:09:41 +00003155 FORCE_RET();
bellard4ad40f32005-12-05 19:59:36 +00003156}