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