|
|
1.1 root 1: /*
2: * MIPS emulation helpers for qemu.
1.1.1.6 root 3: *
1.1 root 4: * Copyright (c) 2004-2005 Jocelyn Mayer
5: *
6: * This library is free software; you can redistribute it and/or
7: * modify it under the terms of the GNU Lesser General Public
8: * License as published by the Free Software Foundation; either
9: * version 2 of the License, or (at your option) any later version.
10: *
11: * This library is distributed in the hope that it will be useful,
12: * but WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: * Lesser General Public License for more details.
15: *
16: * You should have received a copy of the GNU Lesser General Public
1.1.1.8 ! root 17: * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1 root 18: */
1.1.1.6 root 19: #include <stdlib.h>
1.1 root 20: #include "exec.h"
21:
1.1.1.6 root 22: #include "host-utils.h"
1.1 root 23:
1.1.1.7 root 24: #include "helper.h"
1.1 root 25: /*****************************************************************************/
26: /* Exceptions processing helpers */
27:
1.1.1.8 ! root 28: void helper_raise_exception_err (uint32_t exception, int error_code)
1.1 root 29: {
30: #if 1
1.1.1.7 root 31: if (exception < 0x100)
32: qemu_log("%s: %d %d\n", __func__, exception, error_code);
1.1 root 33: #endif
34: env->exception_index = exception;
35: env->error_code = error_code;
36: cpu_loop_exit();
37: }
38:
1.1.1.8 ! root 39: void helper_raise_exception (uint32_t exception)
1.1 root 40: {
1.1.1.8 ! root 41: helper_raise_exception_err(exception, 0);
1.1 root 42: }
43:
1.1.1.8 ! root 44: void helper_interrupt_restart (void)
1.1.1.2 root 45: {
1.1.1.7 root 46: if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
47: !(env->CP0_Status & (1 << CP0St_ERL)) &&
48: !(env->hflags & MIPS_HFLAG_DM) &&
49: (env->CP0_Status & (1 << CP0St_IE)) &&
50: (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
51: env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
1.1.1.8 ! root 52: helper_raise_exception(EXCP_EXT_INTERRUPT);
1.1.1.7 root 53: }
54: }
1.1.1.2 root 55:
1.1.1.7 root 56: #if !defined(CONFIG_USER_ONLY)
57: static void do_restore_state (void *pc_ptr)
58: {
59: TranslationBlock *tb;
60: unsigned long pc = (unsigned long) pc_ptr;
61:
62: tb = tb_find_pc (pc);
63: if (tb) {
64: cpu_restore_state (tb, env, pc, NULL);
65: }
1.1.1.2 root 66: }
1.1.1.7 root 67: #endif
1.1.1.2 root 68:
1.1.1.8 ! root 69: target_ulong helper_clo (target_ulong arg1)
1.1.1.2 root 70: {
1.1.1.8 ! root 71: return clo32(arg1);
1.1.1.2 root 72: }
73:
1.1.1.8 ! root 74: target_ulong helper_clz (target_ulong arg1)
1.1.1.6 root 75: {
1.1.1.8 ! root 76: return clz32(arg1);
1.1.1.6 root 77: }
1.1 root 78:
1.1.1.6 root 79: #if defined(TARGET_MIPS64)
1.1.1.8 ! root 80: target_ulong helper_dclo (target_ulong arg1)
1.1.1.7 root 81: {
1.1.1.8 ! root 82: return clo64(arg1);
1.1.1.7 root 83: }
84:
1.1.1.8 ! root 85: target_ulong helper_dclz (target_ulong arg1)
1.1.1.7 root 86: {
1.1.1.8 ! root 87: return clz64(arg1);
1.1.1.7 root 88: }
89: #endif /* TARGET_MIPS64 */
90:
91: /* 64 bits arithmetic for 32 bits hosts */
92: static inline uint64_t get_HILO (void)
93: {
94: return ((uint64_t)(env->active_tc.HI[0]) << 32) | (uint32_t)env->active_tc.LO[0];
95: }
96:
97: static inline void set_HILO (uint64_t HILO)
98: {
99: env->active_tc.LO[0] = (int32_t)HILO;
100: env->active_tc.HI[0] = (int32_t)(HILO >> 32);
101: }
102:
1.1.1.8 ! root 103: static inline void set_HIT0_LO (target_ulong arg1, uint64_t HILO)
1.1.1.7 root 104: {
105: env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
1.1.1.8 ! root 106: arg1 = env->active_tc.HI[0] = (int32_t)(HILO >> 32);
1.1.1.7 root 107: }
108:
1.1.1.8 ! root 109: static inline void set_HI_LOT0 (target_ulong arg1, uint64_t HILO)
1.1.1.7 root 110: {
1.1.1.8 ! root 111: arg1 = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
1.1.1.7 root 112: env->active_tc.HI[0] = (int32_t)(HILO >> 32);
113: }
114:
115: /* Multiplication variants of the vr54xx. */
1.1.1.8 ! root 116: target_ulong helper_muls (target_ulong arg1, target_ulong arg2)
1.1.1.7 root 117: {
1.1.1.8 ! root 118: set_HI_LOT0(arg1, 0 - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
1.1.1.7 root 119:
1.1.1.8 ! root 120: return arg1;
1.1.1.7 root 121: }
122:
1.1.1.8 ! root 123: target_ulong helper_mulsu (target_ulong arg1, target_ulong arg2)
1.1.1.7 root 124: {
1.1.1.8 ! root 125: set_HI_LOT0(arg1, 0 - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
1.1.1.7 root 126:
1.1.1.8 ! root 127: return arg1;
1.1.1.7 root 128: }
129:
1.1.1.8 ! root 130: target_ulong helper_macc (target_ulong arg1, target_ulong arg2)
1.1.1.7 root 131: {
1.1.1.8 ! root 132: set_HI_LOT0(arg1, ((int64_t)get_HILO()) + ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
1.1.1.7 root 133:
1.1.1.8 ! root 134: return arg1;
1.1.1.7 root 135: }
136:
1.1.1.8 ! root 137: target_ulong helper_macchi (target_ulong arg1, target_ulong arg2)
1.1.1.7 root 138: {
1.1.1.8 ! root 139: set_HIT0_LO(arg1, ((int64_t)get_HILO()) + ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
1.1.1.7 root 140:
1.1.1.8 ! root 141: return arg1;
1.1.1.7 root 142: }
143:
1.1.1.8 ! root 144: target_ulong helper_maccu (target_ulong arg1, target_ulong arg2)
1.1.1.7 root 145: {
1.1.1.8 ! root 146: set_HI_LOT0(arg1, ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
1.1.1.7 root 147:
1.1.1.8 ! root 148: return arg1;
1.1.1.7 root 149: }
150:
1.1.1.8 ! root 151: target_ulong helper_macchiu (target_ulong arg1, target_ulong arg2)
1.1.1.7 root 152: {
1.1.1.8 ! root 153: set_HIT0_LO(arg1, ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
1.1.1.7 root 154:
1.1.1.8 ! root 155: return arg1;
1.1.1.7 root 156: }
157:
1.1.1.8 ! root 158: target_ulong helper_msac (target_ulong arg1, target_ulong arg2)
1.1.1.7 root 159: {
1.1.1.8 ! root 160: set_HI_LOT0(arg1, ((int64_t)get_HILO()) - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
1.1.1.7 root 161:
1.1.1.8 ! root 162: return arg1;
1.1.1.7 root 163: }
164:
1.1.1.8 ! root 165: target_ulong helper_msachi (target_ulong arg1, target_ulong arg2)
1.1.1.7 root 166: {
1.1.1.8 ! root 167: set_HIT0_LO(arg1, ((int64_t)get_HILO()) - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
1.1.1.7 root 168:
1.1.1.8 ! root 169: return arg1;
1.1.1.7 root 170: }
171:
1.1.1.8 ! root 172: target_ulong helper_msacu (target_ulong arg1, target_ulong arg2)
1.1.1.7 root 173: {
1.1.1.8 ! root 174: set_HI_LOT0(arg1, ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
1.1.1.7 root 175:
1.1.1.8 ! root 176: return arg1;
1.1.1.7 root 177: }
178:
1.1.1.8 ! root 179: target_ulong helper_msachiu (target_ulong arg1, target_ulong arg2)
1.1.1.7 root 180: {
1.1.1.8 ! root 181: set_HIT0_LO(arg1, ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
1.1.1.7 root 182:
1.1.1.8 ! root 183: return arg1;
1.1.1.7 root 184: }
185:
1.1.1.8 ! root 186: target_ulong helper_mulhi (target_ulong arg1, target_ulong arg2)
1.1.1.7 root 187: {
1.1.1.8 ! root 188: set_HIT0_LO(arg1, (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2);
1.1.1.7 root 189:
1.1.1.8 ! root 190: return arg1;
1.1.1.7 root 191: }
192:
1.1.1.8 ! root 193: target_ulong helper_mulhiu (target_ulong arg1, target_ulong arg2)
1.1.1.7 root 194: {
1.1.1.8 ! root 195: set_HIT0_LO(arg1, (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
1.1.1.7 root 196:
1.1.1.8 ! root 197: return arg1;
1.1.1.7 root 198: }
199:
1.1.1.8 ! root 200: target_ulong helper_mulshi (target_ulong arg1, target_ulong arg2)
1.1.1.7 root 201: {
1.1.1.8 ! root 202: set_HIT0_LO(arg1, 0 - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
1.1.1.7 root 203:
1.1.1.8 ! root 204: return arg1;
1.1.1.7 root 205: }
206:
1.1.1.8 ! root 207: target_ulong helper_mulshiu (target_ulong arg1, target_ulong arg2)
1.1.1.7 root 208: {
1.1.1.8 ! root 209: set_HIT0_LO(arg1, 0 - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
1.1.1.7 root 210:
1.1.1.8 ! root 211: return arg1;
1.1.1.7 root 212: }
213:
214: #ifdef TARGET_MIPS64
1.1.1.8 ! root 215: void helper_dmult (target_ulong arg1, target_ulong arg2)
1.1.1.7 root 216: {
1.1.1.8 ! root 217: muls64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
1.1.1.7 root 218: }
219:
1.1.1.8 ! root 220: void helper_dmultu (target_ulong arg1, target_ulong arg2)
1.1.1.7 root 221: {
1.1.1.8 ! root 222: mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
1.1.1.7 root 223: }
224: #endif
225:
226: #ifdef TARGET_WORDS_BIGENDIAN
227: #define GET_LMASK(v) ((v) & 3)
228: #define GET_OFFSET(addr, offset) (addr + (offset))
229: #else
230: #define GET_LMASK(v) (((v) & 3) ^ 3)
231: #define GET_OFFSET(addr, offset) (addr - (offset))
232: #endif
233:
1.1.1.8 ! root 234: target_ulong helper_lwl(target_ulong arg1, target_ulong arg2, int mem_idx)
1.1.1.7 root 235: {
236: target_ulong tmp;
237:
238: #ifdef CONFIG_USER_ONLY
239: #define ldfun ldub_raw
240: #else
241: int (*ldfun)(target_ulong);
242:
243: switch (mem_idx)
244: {
245: case 0: ldfun = ldub_kernel; break;
246: case 1: ldfun = ldub_super; break;
247: default:
248: case 2: ldfun = ldub_user; break;
249: }
250: #endif
1.1.1.8 ! root 251: tmp = ldfun(arg2);
! 252: arg1 = (arg1 & 0x00FFFFFF) | (tmp << 24);
1.1.1.7 root 253:
1.1.1.8 ! root 254: if (GET_LMASK(arg2) <= 2) {
! 255: tmp = ldfun(GET_OFFSET(arg2, 1));
! 256: arg1 = (arg1 & 0xFF00FFFF) | (tmp << 16);
1.1.1.7 root 257: }
258:
1.1.1.8 ! root 259: if (GET_LMASK(arg2) <= 1) {
! 260: tmp = ldfun(GET_OFFSET(arg2, 2));
! 261: arg1 = (arg1 & 0xFFFF00FF) | (tmp << 8);
1.1.1.7 root 262: }
263:
1.1.1.8 ! root 264: if (GET_LMASK(arg2) == 0) {
! 265: tmp = ldfun(GET_OFFSET(arg2, 3));
! 266: arg1 = (arg1 & 0xFFFFFF00) | tmp;
1.1.1.7 root 267: }
1.1.1.8 ! root 268: return (int32_t)arg1;
1.1.1.7 root 269: }
270:
1.1.1.8 ! root 271: target_ulong helper_lwr(target_ulong arg1, target_ulong arg2, int mem_idx)
1.1.1.7 root 272: {
273: target_ulong tmp;
274:
275: #ifdef CONFIG_USER_ONLY
276: #define ldfun ldub_raw
277: #else
278: int (*ldfun)(target_ulong);
279:
280: switch (mem_idx)
281: {
282: case 0: ldfun = ldub_kernel; break;
283: case 1: ldfun = ldub_super; break;
284: default:
285: case 2: ldfun = ldub_user; break;
286: }
287: #endif
1.1.1.8 ! root 288: tmp = ldfun(arg2);
! 289: arg1 = (arg1 & 0xFFFFFF00) | tmp;
1.1.1.7 root 290:
1.1.1.8 ! root 291: if (GET_LMASK(arg2) >= 1) {
! 292: tmp = ldfun(GET_OFFSET(arg2, -1));
! 293: arg1 = (arg1 & 0xFFFF00FF) | (tmp << 8);
1.1.1.7 root 294: }
295:
1.1.1.8 ! root 296: if (GET_LMASK(arg2) >= 2) {
! 297: tmp = ldfun(GET_OFFSET(arg2, -2));
! 298: arg1 = (arg1 & 0xFF00FFFF) | (tmp << 16);
1.1.1.7 root 299: }
300:
1.1.1.8 ! root 301: if (GET_LMASK(arg2) == 3) {
! 302: tmp = ldfun(GET_OFFSET(arg2, -3));
! 303: arg1 = (arg1 & 0x00FFFFFF) | (tmp << 24);
1.1.1.7 root 304: }
1.1.1.8 ! root 305: return (int32_t)arg1;
1.1.1.7 root 306: }
307:
1.1.1.8 ! root 308: void helper_swl(target_ulong arg1, target_ulong arg2, int mem_idx)
1.1.1.7 root 309: {
310: #ifdef CONFIG_USER_ONLY
311: #define stfun stb_raw
312: #else
313: void (*stfun)(target_ulong, int);
314:
315: switch (mem_idx)
316: {
317: case 0: stfun = stb_kernel; break;
318: case 1: stfun = stb_super; break;
319: default:
320: case 2: stfun = stb_user; break;
321: }
322: #endif
1.1.1.8 ! root 323: stfun(arg2, (uint8_t)(arg1 >> 24));
1.1.1.7 root 324:
1.1.1.8 ! root 325: if (GET_LMASK(arg2) <= 2)
! 326: stfun(GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 16));
1.1.1.7 root 327:
1.1.1.8 ! root 328: if (GET_LMASK(arg2) <= 1)
! 329: stfun(GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 8));
1.1.1.7 root 330:
1.1.1.8 ! root 331: if (GET_LMASK(arg2) == 0)
! 332: stfun(GET_OFFSET(arg2, 3), (uint8_t)arg1);
1.1.1.7 root 333: }
334:
1.1.1.8 ! root 335: void helper_swr(target_ulong arg1, target_ulong arg2, int mem_idx)
1.1.1.7 root 336: {
337: #ifdef CONFIG_USER_ONLY
338: #define stfun stb_raw
339: #else
340: void (*stfun)(target_ulong, int);
341:
342: switch (mem_idx)
343: {
344: case 0: stfun = stb_kernel; break;
345: case 1: stfun = stb_super; break;
346: default:
347: case 2: stfun = stb_user; break;
348: }
349: #endif
1.1.1.8 ! root 350: stfun(arg2, (uint8_t)arg1);
1.1.1.7 root 351:
1.1.1.8 ! root 352: if (GET_LMASK(arg2) >= 1)
! 353: stfun(GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8));
1.1.1.7 root 354:
1.1.1.8 ! root 355: if (GET_LMASK(arg2) >= 2)
! 356: stfun(GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16));
1.1.1.7 root 357:
1.1.1.8 ! root 358: if (GET_LMASK(arg2) == 3)
! 359: stfun(GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24));
1.1.1.7 root 360: }
361:
362: #if defined(TARGET_MIPS64)
363: /* "half" load and stores. We must do the memory access inline,
364: or fault handling won't work. */
365:
366: #ifdef TARGET_WORDS_BIGENDIAN
367: #define GET_LMASK64(v) ((v) & 7)
368: #else
369: #define GET_LMASK64(v) (((v) & 7) ^ 7)
370: #endif
371:
1.1.1.8 ! root 372: target_ulong helper_ldl(target_ulong arg1, target_ulong arg2, int mem_idx)
1.1.1.7 root 373: {
374: uint64_t tmp;
375:
376: #ifdef CONFIG_USER_ONLY
377: #define ldfun ldub_raw
378: #else
379: int (*ldfun)(target_ulong);
380:
381: switch (mem_idx)
382: {
383: case 0: ldfun = ldub_kernel; break;
384: case 1: ldfun = ldub_super; break;
385: default:
386: case 2: ldfun = ldub_user; break;
387: }
388: #endif
1.1.1.8 ! root 389: tmp = ldfun(arg2);
! 390: arg1 = (arg1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
1.1.1.7 root 391:
1.1.1.8 ! root 392: if (GET_LMASK64(arg2) <= 6) {
! 393: tmp = ldfun(GET_OFFSET(arg2, 1));
! 394: arg1 = (arg1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
1.1.1.7 root 395: }
396:
1.1.1.8 ! root 397: if (GET_LMASK64(arg2) <= 5) {
! 398: tmp = ldfun(GET_OFFSET(arg2, 2));
! 399: arg1 = (arg1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
1.1.1.7 root 400: }
401:
1.1.1.8 ! root 402: if (GET_LMASK64(arg2) <= 4) {
! 403: tmp = ldfun(GET_OFFSET(arg2, 3));
! 404: arg1 = (arg1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
1.1.1.7 root 405: }
406:
1.1.1.8 ! root 407: if (GET_LMASK64(arg2) <= 3) {
! 408: tmp = ldfun(GET_OFFSET(arg2, 4));
! 409: arg1 = (arg1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
1.1.1.7 root 410: }
411:
1.1.1.8 ! root 412: if (GET_LMASK64(arg2) <= 2) {
! 413: tmp = ldfun(GET_OFFSET(arg2, 5));
! 414: arg1 = (arg1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
1.1.1.7 root 415: }
416:
1.1.1.8 ! root 417: if (GET_LMASK64(arg2) <= 1) {
! 418: tmp = ldfun(GET_OFFSET(arg2, 6));
! 419: arg1 = (arg1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
1.1.1.7 root 420: }
421:
1.1.1.8 ! root 422: if (GET_LMASK64(arg2) == 0) {
! 423: tmp = ldfun(GET_OFFSET(arg2, 7));
! 424: arg1 = (arg1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
1.1.1.7 root 425: }
426:
1.1.1.8 ! root 427: return arg1;
1.1.1.7 root 428: }
429:
1.1.1.8 ! root 430: target_ulong helper_ldr(target_ulong arg1, target_ulong arg2, int mem_idx)
1.1.1.7 root 431: {
432: uint64_t tmp;
433:
434: #ifdef CONFIG_USER_ONLY
435: #define ldfun ldub_raw
436: #else
437: int (*ldfun)(target_ulong);
438:
439: switch (mem_idx)
440: {
441: case 0: ldfun = ldub_kernel; break;
442: case 1: ldfun = ldub_super; break;
443: default:
444: case 2: ldfun = ldub_user; break;
445: }
446: #endif
1.1.1.8 ! root 447: tmp = ldfun(arg2);
! 448: arg1 = (arg1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
1.1.1.7 root 449:
1.1.1.8 ! root 450: if (GET_LMASK64(arg2) >= 1) {
! 451: tmp = ldfun(GET_OFFSET(arg2, -1));
! 452: arg1 = (arg1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
1.1.1.7 root 453: }
454:
1.1.1.8 ! root 455: if (GET_LMASK64(arg2) >= 2) {
! 456: tmp = ldfun(GET_OFFSET(arg2, -2));
! 457: arg1 = (arg1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
1.1.1.7 root 458: }
459:
1.1.1.8 ! root 460: if (GET_LMASK64(arg2) >= 3) {
! 461: tmp = ldfun(GET_OFFSET(arg2, -3));
! 462: arg1 = (arg1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
1.1.1.7 root 463: }
464:
1.1.1.8 ! root 465: if (GET_LMASK64(arg2) >= 4) {
! 466: tmp = ldfun(GET_OFFSET(arg2, -4));
! 467: arg1 = (arg1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
1.1.1.7 root 468: }
469:
1.1.1.8 ! root 470: if (GET_LMASK64(arg2) >= 5) {
! 471: tmp = ldfun(GET_OFFSET(arg2, -5));
! 472: arg1 = (arg1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
1.1.1.7 root 473: }
474:
1.1.1.8 ! root 475: if (GET_LMASK64(arg2) >= 6) {
! 476: tmp = ldfun(GET_OFFSET(arg2, -6));
! 477: arg1 = (arg1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
1.1.1.7 root 478: }
479:
1.1.1.8 ! root 480: if (GET_LMASK64(arg2) == 7) {
! 481: tmp = ldfun(GET_OFFSET(arg2, -7));
! 482: arg1 = (arg1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
1.1.1.7 root 483: }
484:
1.1.1.8 ! root 485: return arg1;
1.1.1.7 root 486: }
487:
1.1.1.8 ! root 488: void helper_sdl(target_ulong arg1, target_ulong arg2, int mem_idx)
1.1.1.7 root 489: {
490: #ifdef CONFIG_USER_ONLY
491: #define stfun stb_raw
492: #else
493: void (*stfun)(target_ulong, int);
494:
495: switch (mem_idx)
496: {
497: case 0: stfun = stb_kernel; break;
498: case 1: stfun = stb_super; break;
499: default:
500: case 2: stfun = stb_user; break;
501: }
502: #endif
1.1.1.8 ! root 503: stfun(arg2, (uint8_t)(arg1 >> 56));
1.1.1.7 root 504:
1.1.1.8 ! root 505: if (GET_LMASK64(arg2) <= 6)
! 506: stfun(GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 48));
1.1.1.7 root 507:
1.1.1.8 ! root 508: if (GET_LMASK64(arg2) <= 5)
! 509: stfun(GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 40));
1.1.1.7 root 510:
1.1.1.8 ! root 511: if (GET_LMASK64(arg2) <= 4)
! 512: stfun(GET_OFFSET(arg2, 3), (uint8_t)(arg1 >> 32));
1.1.1.7 root 513:
1.1.1.8 ! root 514: if (GET_LMASK64(arg2) <= 3)
! 515: stfun(GET_OFFSET(arg2, 4), (uint8_t)(arg1 >> 24));
1.1.1.7 root 516:
1.1.1.8 ! root 517: if (GET_LMASK64(arg2) <= 2)
! 518: stfun(GET_OFFSET(arg2, 5), (uint8_t)(arg1 >> 16));
1.1.1.7 root 519:
1.1.1.8 ! root 520: if (GET_LMASK64(arg2) <= 1)
! 521: stfun(GET_OFFSET(arg2, 6), (uint8_t)(arg1 >> 8));
1.1.1.7 root 522:
1.1.1.8 ! root 523: if (GET_LMASK64(arg2) <= 0)
! 524: stfun(GET_OFFSET(arg2, 7), (uint8_t)arg1);
1.1.1.7 root 525: }
526:
1.1.1.8 ! root 527: void helper_sdr(target_ulong arg1, target_ulong arg2, int mem_idx)
1.1.1.7 root 528: {
529: #ifdef CONFIG_USER_ONLY
530: #define stfun stb_raw
531: #else
532: void (*stfun)(target_ulong, int);
533:
534: switch (mem_idx)
535: {
536: case 0: stfun = stb_kernel; break;
537: case 1: stfun = stb_super; break;
538: default:
539: case 2: stfun = stb_user; break;
540: }
541: #endif
1.1.1.8 ! root 542: stfun(arg2, (uint8_t)arg1);
1.1.1.7 root 543:
1.1.1.8 ! root 544: if (GET_LMASK64(arg2) >= 1)
! 545: stfun(GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8));
1.1.1.7 root 546:
1.1.1.8 ! root 547: if (GET_LMASK64(arg2) >= 2)
! 548: stfun(GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16));
1.1.1.7 root 549:
1.1.1.8 ! root 550: if (GET_LMASK64(arg2) >= 3)
! 551: stfun(GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24));
1.1.1.7 root 552:
1.1.1.8 ! root 553: if (GET_LMASK64(arg2) >= 4)
! 554: stfun(GET_OFFSET(arg2, -4), (uint8_t)(arg1 >> 32));
1.1.1.7 root 555:
1.1.1.8 ! root 556: if (GET_LMASK64(arg2) >= 5)
! 557: stfun(GET_OFFSET(arg2, -5), (uint8_t)(arg1 >> 40));
1.1.1.7 root 558:
1.1.1.8 ! root 559: if (GET_LMASK64(arg2) >= 6)
! 560: stfun(GET_OFFSET(arg2, -6), (uint8_t)(arg1 >> 48));
1.1.1.7 root 561:
1.1.1.8 ! root 562: if (GET_LMASK64(arg2) == 7)
! 563: stfun(GET_OFFSET(arg2, -7), (uint8_t)(arg1 >> 56));
1.1.1.7 root 564: }
565: #endif /* TARGET_MIPS64 */
566:
567: #ifndef CONFIG_USER_ONLY
568: /* CP0 helpers */
1.1.1.8 ! root 569: target_ulong helper_mfc0_mvpcontrol (void)
1.1.1.7 root 570: {
571: return env->mvp->CP0_MVPControl;
572: }
573:
1.1.1.8 ! root 574: target_ulong helper_mfc0_mvpconf0 (void)
1.1.1.7 root 575: {
576: return env->mvp->CP0_MVPConf0;
577: }
578:
1.1.1.8 ! root 579: target_ulong helper_mfc0_mvpconf1 (void)
1.1.1.7 root 580: {
581: return env->mvp->CP0_MVPConf1;
582: }
583:
1.1.1.8 ! root 584: target_ulong helper_mfc0_random (void)
1.1.1.7 root 585: {
586: return (int32_t)cpu_mips_get_random(env);
587: }
588:
1.1.1.8 ! root 589: target_ulong helper_mfc0_tcstatus (void)
1.1.1.7 root 590: {
591: return env->active_tc.CP0_TCStatus;
592: }
593:
1.1.1.8 ! root 594: target_ulong helper_mftc0_tcstatus(void)
1.1.1.7 root 595: {
596: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
597:
598: if (other_tc == env->current_tc)
599: return env->active_tc.CP0_TCStatus;
600: else
601: return env->tcs[other_tc].CP0_TCStatus;
602: }
603:
1.1.1.8 ! root 604: target_ulong helper_mfc0_tcbind (void)
1.1.1.7 root 605: {
606: return env->active_tc.CP0_TCBind;
607: }
608:
1.1.1.8 ! root 609: target_ulong helper_mftc0_tcbind(void)
1.1.1.7 root 610: {
611: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
612:
613: if (other_tc == env->current_tc)
614: return env->active_tc.CP0_TCBind;
615: else
616: return env->tcs[other_tc].CP0_TCBind;
617: }
618:
1.1.1.8 ! root 619: target_ulong helper_mfc0_tcrestart (void)
1.1.1.7 root 620: {
621: return env->active_tc.PC;
622: }
623:
1.1.1.8 ! root 624: target_ulong helper_mftc0_tcrestart(void)
1.1.1.7 root 625: {
626: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
627:
628: if (other_tc == env->current_tc)
629: return env->active_tc.PC;
630: else
631: return env->tcs[other_tc].PC;
632: }
633:
1.1.1.8 ! root 634: target_ulong helper_mfc0_tchalt (void)
1.1.1.7 root 635: {
636: return env->active_tc.CP0_TCHalt;
637: }
638:
1.1.1.8 ! root 639: target_ulong helper_mftc0_tchalt(void)
1.1.1.7 root 640: {
641: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
642:
643: if (other_tc == env->current_tc)
644: return env->active_tc.CP0_TCHalt;
645: else
646: return env->tcs[other_tc].CP0_TCHalt;
647: }
648:
1.1.1.8 ! root 649: target_ulong helper_mfc0_tccontext (void)
1.1.1.7 root 650: {
651: return env->active_tc.CP0_TCContext;
652: }
653:
1.1.1.8 ! root 654: target_ulong helper_mftc0_tccontext(void)
1.1.1.5 root 655: {
1.1.1.7 root 656: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
657:
658: if (other_tc == env->current_tc)
659: return env->active_tc.CP0_TCContext;
660: else
661: return env->tcs[other_tc].CP0_TCContext;
1.1.1.5 root 662: }
663:
1.1.1.8 ! root 664: target_ulong helper_mfc0_tcschedule (void)
1.1.1.5 root 665: {
1.1.1.7 root 666: return env->active_tc.CP0_TCSchedule;
1.1.1.5 root 667: }
668:
1.1.1.8 ! root 669: target_ulong helper_mftc0_tcschedule(void)
1.1.1.5 root 670: {
1.1.1.7 root 671: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
672:
673: if (other_tc == env->current_tc)
674: return env->active_tc.CP0_TCSchedule;
675: else
676: return env->tcs[other_tc].CP0_TCSchedule;
1.1.1.5 root 677: }
678:
1.1.1.8 ! root 679: target_ulong helper_mfc0_tcschefback (void)
1.1.1.5 root 680: {
1.1.1.7 root 681: return env->active_tc.CP0_TCScheFBack;
1.1.1.5 root 682: }
683:
1.1.1.8 ! root 684: target_ulong helper_mftc0_tcschefback(void)
1.1.1.5 root 685: {
1.1.1.7 root 686: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
687:
688: if (other_tc == env->current_tc)
689: return env->active_tc.CP0_TCScheFBack;
690: else
691: return env->tcs[other_tc].CP0_TCScheFBack;
692: }
693:
1.1.1.8 ! root 694: target_ulong helper_mfc0_count (void)
1.1.1.7 root 695: {
696: return (int32_t)cpu_mips_get_count(env);
697: }
698:
1.1.1.8 ! root 699: target_ulong helper_mftc0_entryhi(void)
1.1.1.7 root 700: {
701: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
702: int32_t tcstatus;
703:
704: if (other_tc == env->current_tc)
705: tcstatus = env->active_tc.CP0_TCStatus;
706: else
707: tcstatus = env->tcs[other_tc].CP0_TCStatus;
708:
709: return (env->CP0_EntryHi & ~0xff) | (tcstatus & 0xff);
710: }
711:
1.1.1.8 ! root 712: target_ulong helper_mftc0_status(void)
1.1.1.7 root 713: {
714: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
715: target_ulong t0;
716: int32_t tcstatus;
717:
718: if (other_tc == env->current_tc)
719: tcstatus = env->active_tc.CP0_TCStatus;
720: else
721: tcstatus = env->tcs[other_tc].CP0_TCStatus;
722:
723: t0 = env->CP0_Status & ~0xf1000018;
724: t0 |= tcstatus & (0xf << CP0TCSt_TCU0);
725: t0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
726: t0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
727:
728: return t0;
729: }
730:
1.1.1.8 ! root 731: target_ulong helper_mfc0_lladdr (void)
1.1.1.7 root 732: {
733: return (int32_t)env->CP0_LLAddr >> 4;
734: }
735:
1.1.1.8 ! root 736: target_ulong helper_mfc0_watchlo (uint32_t sel)
1.1.1.7 root 737: {
738: return (int32_t)env->CP0_WatchLo[sel];
739: }
740:
1.1.1.8 ! root 741: target_ulong helper_mfc0_watchhi (uint32_t sel)
1.1.1.7 root 742: {
743: return env->CP0_WatchHi[sel];
744: }
745:
1.1.1.8 ! root 746: target_ulong helper_mfc0_debug (void)
1.1.1.7 root 747: {
748: target_ulong t0 = env->CP0_Debug;
749: if (env->hflags & MIPS_HFLAG_DM)
750: t0 |= 1 << CP0DB_DM;
751:
752: return t0;
753: }
754:
1.1.1.8 ! root 755: target_ulong helper_mftc0_debug(void)
1.1.1.7 root 756: {
757: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
758: int32_t tcstatus;
759:
760: if (other_tc == env->current_tc)
761: tcstatus = env->active_tc.CP0_Debug_tcstatus;
762: else
763: tcstatus = env->tcs[other_tc].CP0_Debug_tcstatus;
764:
765: /* XXX: Might be wrong, check with EJTAG spec. */
766: return (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
767: (tcstatus & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
768: }
769:
770: #if defined(TARGET_MIPS64)
1.1.1.8 ! root 771: target_ulong helper_dmfc0_tcrestart (void)
1.1.1.7 root 772: {
773: return env->active_tc.PC;
774: }
775:
1.1.1.8 ! root 776: target_ulong helper_dmfc0_tchalt (void)
1.1.1.7 root 777: {
778: return env->active_tc.CP0_TCHalt;
779: }
780:
1.1.1.8 ! root 781: target_ulong helper_dmfc0_tccontext (void)
1.1.1.7 root 782: {
783: return env->active_tc.CP0_TCContext;
784: }
785:
1.1.1.8 ! root 786: target_ulong helper_dmfc0_tcschedule (void)
1.1.1.7 root 787: {
788: return env->active_tc.CP0_TCSchedule;
789: }
790:
1.1.1.8 ! root 791: target_ulong helper_dmfc0_tcschefback (void)
1.1.1.7 root 792: {
793: return env->active_tc.CP0_TCScheFBack;
794: }
795:
1.1.1.8 ! root 796: target_ulong helper_dmfc0_lladdr (void)
1.1.1.7 root 797: {
798: return env->CP0_LLAddr >> 4;
799: }
800:
1.1.1.8 ! root 801: target_ulong helper_dmfc0_watchlo (uint32_t sel)
1.1.1.7 root 802: {
803: return env->CP0_WatchLo[sel];
804: }
805: #endif /* TARGET_MIPS64 */
806:
1.1.1.8 ! root 807: void helper_mtc0_index (target_ulong arg1)
1.1.1.7 root 808: {
809: int num = 1;
810: unsigned int tmp = env->tlb->nb_tlb;
811:
812: do {
813: tmp >>= 1;
814: num <<= 1;
815: } while (tmp);
1.1.1.8 ! root 816: env->CP0_Index = (env->CP0_Index & 0x80000000) | (arg1 & (num - 1));
1.1.1.7 root 817: }
818:
1.1.1.8 ! root 819: void helper_mtc0_mvpcontrol (target_ulong arg1)
1.1.1.7 root 820: {
821: uint32_t mask = 0;
822: uint32_t newval;
823:
824: if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
825: mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
826: (1 << CP0MVPCo_EVP);
827: if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
828: mask |= (1 << CP0MVPCo_STLB);
1.1.1.8 ! root 829: newval = (env->mvp->CP0_MVPControl & ~mask) | (arg1 & mask);
1.1.1.7 root 830:
831: // TODO: Enable/disable shared TLB, enable/disable VPEs.
832:
833: env->mvp->CP0_MVPControl = newval;
834: }
835:
1.1.1.8 ! root 836: void helper_mtc0_vpecontrol (target_ulong arg1)
1.1.1.7 root 837: {
838: uint32_t mask;
839: uint32_t newval;
840:
841: mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
842: (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
1.1.1.8 ! root 843: newval = (env->CP0_VPEControl & ~mask) | (arg1 & mask);
1.1.1.7 root 844:
845: /* Yield scheduler intercept not implemented. */
846: /* Gating storage scheduler intercept not implemented. */
847:
848: // TODO: Enable/disable TCs.
849:
850: env->CP0_VPEControl = newval;
851: }
852:
1.1.1.8 ! root 853: void helper_mtc0_vpeconf0 (target_ulong arg1)
1.1.1.7 root 854: {
855: uint32_t mask = 0;
856: uint32_t newval;
857:
858: if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
859: if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
860: mask |= (0xff << CP0VPEC0_XTC);
861: mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
862: }
1.1.1.8 ! root 863: newval = (env->CP0_VPEConf0 & ~mask) | (arg1 & mask);
1.1.1.7 root 864:
865: // TODO: TC exclusive handling due to ERL/EXL.
866:
867: env->CP0_VPEConf0 = newval;
868: }
869:
1.1.1.8 ! root 870: void helper_mtc0_vpeconf1 (target_ulong arg1)
1.1.1.7 root 871: {
872: uint32_t mask = 0;
873: uint32_t newval;
874:
875: if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
876: mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
877: (0xff << CP0VPEC1_NCP1);
1.1.1.8 ! root 878: newval = (env->CP0_VPEConf1 & ~mask) | (arg1 & mask);
1.1.1.7 root 879:
880: /* UDI not implemented. */
881: /* CP2 not implemented. */
882:
883: // TODO: Handle FPU (CP1) binding.
884:
885: env->CP0_VPEConf1 = newval;
886: }
887:
1.1.1.8 ! root 888: void helper_mtc0_yqmask (target_ulong arg1)
1.1.1.7 root 889: {
890: /* Yield qualifier inputs not implemented. */
891: env->CP0_YQMask = 0x00000000;
892: }
893:
1.1.1.8 ! root 894: void helper_mtc0_vpeopt (target_ulong arg1)
1.1.1.7 root 895: {
1.1.1.8 ! root 896: env->CP0_VPEOpt = arg1 & 0x0000ffff;
1.1.1.7 root 897: }
898:
1.1.1.8 ! root 899: void helper_mtc0_entrylo0 (target_ulong arg1)
1.1.1.7 root 900: {
901: /* Large physaddr (PABITS) not implemented */
902: /* 1k pages not implemented */
1.1.1.8 ! root 903: env->CP0_EntryLo0 = arg1 & 0x3FFFFFFF;
1.1.1.7 root 904: }
905:
1.1.1.8 ! root 906: void helper_mtc0_tcstatus (target_ulong arg1)
1.1.1.7 root 907: {
908: uint32_t mask = env->CP0_TCStatus_rw_bitmask;
909: uint32_t newval;
910:
1.1.1.8 ! root 911: newval = (env->active_tc.CP0_TCStatus & ~mask) | (arg1 & mask);
1.1.1.7 root 912:
913: // TODO: Sync with CP0_Status.
914:
915: env->active_tc.CP0_TCStatus = newval;
916: }
917:
1.1.1.8 ! root 918: void helper_mttc0_tcstatus (target_ulong arg1)
1.1.1.7 root 919: {
920: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
921:
922: // TODO: Sync with CP0_Status.
923:
924: if (other_tc == env->current_tc)
1.1.1.8 ! root 925: env->active_tc.CP0_TCStatus = arg1;
1.1.1.7 root 926: else
1.1.1.8 ! root 927: env->tcs[other_tc].CP0_TCStatus = arg1;
1.1.1.7 root 928: }
929:
1.1.1.8 ! root 930: void helper_mtc0_tcbind (target_ulong arg1)
1.1.1.7 root 931: {
932: uint32_t mask = (1 << CP0TCBd_TBE);
933: uint32_t newval;
934:
935: if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
936: mask |= (1 << CP0TCBd_CurVPE);
1.1.1.8 ! root 937: newval = (env->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
1.1.1.7 root 938: env->active_tc.CP0_TCBind = newval;
939: }
940:
1.1.1.8 ! root 941: void helper_mttc0_tcbind (target_ulong arg1)
1.1.1.7 root 942: {
943: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
944: uint32_t mask = (1 << CP0TCBd_TBE);
945: uint32_t newval;
946:
947: if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
948: mask |= (1 << CP0TCBd_CurVPE);
949: if (other_tc == env->current_tc) {
1.1.1.8 ! root 950: newval = (env->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
1.1.1.7 root 951: env->active_tc.CP0_TCBind = newval;
952: } else {
1.1.1.8 ! root 953: newval = (env->tcs[other_tc].CP0_TCBind & ~mask) | (arg1 & mask);
1.1.1.7 root 954: env->tcs[other_tc].CP0_TCBind = newval;
955: }
956: }
957:
1.1.1.8 ! root 958: void helper_mtc0_tcrestart (target_ulong arg1)
1.1.1.7 root 959: {
1.1.1.8 ! root 960: env->active_tc.PC = arg1;
1.1.1.7 root 961: env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
962: env->CP0_LLAddr = 0ULL;
963: /* MIPS16 not implemented. */
964: }
965:
1.1.1.8 ! root 966: void helper_mttc0_tcrestart (target_ulong arg1)
1.1.1.7 root 967: {
968: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
969:
970: if (other_tc == env->current_tc) {
1.1.1.8 ! root 971: env->active_tc.PC = arg1;
1.1.1.7 root 972: env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
973: env->CP0_LLAddr = 0ULL;
974: /* MIPS16 not implemented. */
975: } else {
1.1.1.8 ! root 976: env->tcs[other_tc].PC = arg1;
1.1.1.7 root 977: env->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
978: env->CP0_LLAddr = 0ULL;
979: /* MIPS16 not implemented. */
980: }
981: }
982:
1.1.1.8 ! root 983: void helper_mtc0_tchalt (target_ulong arg1)
1.1.1.7 root 984: {
1.1.1.8 ! root 985: env->active_tc.CP0_TCHalt = arg1 & 0x1;
1.1.1.7 root 986:
987: // TODO: Halt TC / Restart (if allocated+active) TC.
988: }
989:
1.1.1.8 ! root 990: void helper_mttc0_tchalt (target_ulong arg1)
1.1.1.7 root 991: {
992: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
993:
994: // TODO: Halt TC / Restart (if allocated+active) TC.
995:
996: if (other_tc == env->current_tc)
1.1.1.8 ! root 997: env->active_tc.CP0_TCHalt = arg1;
1.1.1.7 root 998: else
1.1.1.8 ! root 999: env->tcs[other_tc].CP0_TCHalt = arg1;
1.1.1.7 root 1000: }
1001:
1.1.1.8 ! root 1002: void helper_mtc0_tccontext (target_ulong arg1)
1.1.1.7 root 1003: {
1.1.1.8 ! root 1004: env->active_tc.CP0_TCContext = arg1;
1.1.1.7 root 1005: }
1006:
1.1.1.8 ! root 1007: void helper_mttc0_tccontext (target_ulong arg1)
1.1.1.7 root 1008: {
1009: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1010:
1011: if (other_tc == env->current_tc)
1.1.1.8 ! root 1012: env->active_tc.CP0_TCContext = arg1;
1.1.1.7 root 1013: else
1.1.1.8 ! root 1014: env->tcs[other_tc].CP0_TCContext = arg1;
1.1.1.7 root 1015: }
1016:
1.1.1.8 ! root 1017: void helper_mtc0_tcschedule (target_ulong arg1)
1.1.1.7 root 1018: {
1.1.1.8 ! root 1019: env->active_tc.CP0_TCSchedule = arg1;
1.1.1.7 root 1020: }
1021:
1.1.1.8 ! root 1022: void helper_mttc0_tcschedule (target_ulong arg1)
1.1.1.7 root 1023: {
1024: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1025:
1026: if (other_tc == env->current_tc)
1.1.1.8 ! root 1027: env->active_tc.CP0_TCSchedule = arg1;
1.1.1.7 root 1028: else
1.1.1.8 ! root 1029: env->tcs[other_tc].CP0_TCSchedule = arg1;
1.1.1.5 root 1030: }
1031:
1.1.1.8 ! root 1032: void helper_mtc0_tcschefback (target_ulong arg1)
1.1.1.5 root 1033: {
1.1.1.8 ! root 1034: env->active_tc.CP0_TCScheFBack = arg1;
1.1.1.5 root 1035: }
1036:
1.1.1.8 ! root 1037: void helper_mttc0_tcschefback (target_ulong arg1)
1.1.1.5 root 1038: {
1.1.1.7 root 1039: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.5 root 1040:
1.1.1.7 root 1041: if (other_tc == env->current_tc)
1.1.1.8 ! root 1042: env->active_tc.CP0_TCScheFBack = arg1;
1.1.1.7 root 1043: else
1.1.1.8 ! root 1044: env->tcs[other_tc].CP0_TCScheFBack = arg1;
1.1.1.5 root 1045: }
1046:
1.1.1.8 ! root 1047: void helper_mtc0_entrylo1 (target_ulong arg1)
1.1.1.5 root 1048: {
1.1.1.7 root 1049: /* Large physaddr (PABITS) not implemented */
1050: /* 1k pages not implemented */
1.1.1.8 ! root 1051: env->CP0_EntryLo1 = arg1 & 0x3FFFFFFF;
1.1.1.5 root 1052: }
1053:
1.1.1.8 ! root 1054: void helper_mtc0_context (target_ulong arg1)
1.1.1.5 root 1055: {
1.1.1.8 ! root 1056: env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF);
1.1.1.5 root 1057: }
1058:
1.1.1.8 ! root 1059: void helper_mtc0_pagemask (target_ulong arg1)
1.1.1.5 root 1060: {
1.1.1.7 root 1061: /* 1k pages not implemented */
1.1.1.8 ! root 1062: env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1.1.1.5 root 1063: }
1064:
1.1.1.8 ! root 1065: void helper_mtc0_pagegrain (target_ulong arg1)
1.1.1.5 root 1066: {
1.1.1.7 root 1067: /* SmartMIPS not implemented */
1068: /* Large physaddr (PABITS) not implemented */
1069: /* 1k pages not implemented */
1070: env->CP0_PageGrain = 0;
1.1.1.5 root 1071: }
1072:
1.1.1.8 ! root 1073: void helper_mtc0_wired (target_ulong arg1)
1.1.1.5 root 1074: {
1.1.1.8 ! root 1075: env->CP0_Wired = arg1 % env->tlb->nb_tlb;
1.1.1.6 root 1076: }
1077:
1.1.1.8 ! root 1078: void helper_mtc0_srsconf0 (target_ulong arg1)
1.1.1.6 root 1079: {
1.1.1.8 ! root 1080: env->CP0_SRSConf0 |= arg1 & env->CP0_SRSConf0_rw_bitmask;
1.1.1.6 root 1081: }
1082:
1.1.1.8 ! root 1083: void helper_mtc0_srsconf1 (target_ulong arg1)
1.1.1.6 root 1084: {
1.1.1.8 ! root 1085: env->CP0_SRSConf1 |= arg1 & env->CP0_SRSConf1_rw_bitmask;
1.1.1.5 root 1086: }
1.1.1.6 root 1087:
1.1.1.8 ! root 1088: void helper_mtc0_srsconf2 (target_ulong arg1)
1.1.1.6 root 1089: {
1.1.1.8 ! root 1090: env->CP0_SRSConf2 |= arg1 & env->CP0_SRSConf2_rw_bitmask;
1.1.1.6 root 1091: }
1092:
1.1.1.8 ! root 1093: void helper_mtc0_srsconf3 (target_ulong arg1)
1.1.1.6 root 1094: {
1.1.1.8 ! root 1095: env->CP0_SRSConf3 |= arg1 & env->CP0_SRSConf3_rw_bitmask;
1.1.1.6 root 1096: }
1097:
1.1.1.8 ! root 1098: void helper_mtc0_srsconf4 (target_ulong arg1)
1.1 root 1099: {
1.1.1.8 ! root 1100: env->CP0_SRSConf4 |= arg1 & env->CP0_SRSConf4_rw_bitmask;
1.1 root 1101: }
1102:
1.1.1.8 ! root 1103: void helper_mtc0_hwrena (target_ulong arg1)
1.1 root 1104: {
1.1.1.8 ! root 1105: env->CP0_HWREna = arg1 & 0x0000000F;
1.1 root 1106: }
1107:
1.1.1.8 ! root 1108: void helper_mtc0_count (target_ulong arg1)
1.1 root 1109: {
1.1.1.8 ! root 1110: cpu_mips_store_count(env, arg1);
1.1 root 1111: }
1112:
1.1.1.8 ! root 1113: void helper_mtc0_entryhi (target_ulong arg1)
1.1 root 1114: {
1.1.1.7 root 1115: target_ulong old, val;
1116:
1117: /* 1k pages not implemented */
1.1.1.8 ! root 1118: val = arg1 & ((TARGET_PAGE_MASK << 1) | 0xFF);
1.1.1.7 root 1119: #if defined(TARGET_MIPS64)
1120: val &= env->SEGMask;
1121: #endif
1122: old = env->CP0_EntryHi;
1123: env->CP0_EntryHi = val;
1124: if (env->CP0_Config3 & (1 << CP0C3_MT)) {
1125: uint32_t tcst = env->active_tc.CP0_TCStatus & ~0xff;
1126: env->active_tc.CP0_TCStatus = tcst | (val & 0xff);
1127: }
1128: /* If the ASID changes, flush qemu's TLB. */
1129: if ((old & 0xFF) != (val & 0xFF))
1130: cpu_mips_tlb_flush(env, 1);
1131: }
1132:
1.1.1.8 ! root 1133: void helper_mttc0_entryhi(target_ulong arg1)
1.1.1.7 root 1134: {
1135: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1136: int32_t tcstatus;
1137:
1.1.1.8 ! root 1138: env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (arg1 & ~0xff);
1.1.1.7 root 1139: if (other_tc == env->current_tc) {
1.1.1.8 ! root 1140: tcstatus = (env->active_tc.CP0_TCStatus & ~0xff) | (arg1 & 0xff);
1.1.1.7 root 1141: env->active_tc.CP0_TCStatus = tcstatus;
1142: } else {
1.1.1.8 ! root 1143: tcstatus = (env->tcs[other_tc].CP0_TCStatus & ~0xff) | (arg1 & 0xff);
1.1.1.7 root 1144: env->tcs[other_tc].CP0_TCStatus = tcstatus;
1145: }
1.1 root 1146: }
1147:
1.1.1.8 ! root 1148: void helper_mtc0_compare (target_ulong arg1)
1.1 root 1149: {
1.1.1.8 ! root 1150: cpu_mips_store_compare(env, arg1);
1.1 root 1151: }
1152:
1.1.1.8 ! root 1153: void helper_mtc0_status (target_ulong arg1)
1.1 root 1154: {
1.1.1.7 root 1155: uint32_t val, old;
1156: uint32_t mask = env->CP0_Status_rw_bitmask;
1.1 root 1157:
1.1.1.8 ! root 1158: val = arg1 & mask;
1.1.1.7 root 1159: old = env->CP0_Status;
1160: env->CP0_Status = (env->CP0_Status & ~mask) | val;
1161: compute_hflags(env);
1.1.1.8 ! root 1162: if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
! 1163: qemu_log("Status %08x (%08x) => %08x (%08x) Cause %08x",
! 1164: old, old & env->CP0_Cause & CP0Ca_IP_mask,
! 1165: val, val & env->CP0_Cause & CP0Ca_IP_mask,
! 1166: env->CP0_Cause);
! 1167: switch (env->hflags & MIPS_HFLAG_KSU) {
! 1168: case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
! 1169: case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
! 1170: case MIPS_HFLAG_KM: qemu_log("\n"); break;
! 1171: default: cpu_abort(env, "Invalid MMU mode!\n"); break;
! 1172: }
! 1173: }
1.1.1.7 root 1174: cpu_mips_update_irq(env);
1.1 root 1175: }
1176:
1.1.1.8 ! root 1177: void helper_mttc0_status(target_ulong arg1)
1.1 root 1178: {
1.1.1.7 root 1179: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1180: int32_t tcstatus = env->tcs[other_tc].CP0_TCStatus;
1.1 root 1181:
1.1.1.8 ! root 1182: env->CP0_Status = arg1 & ~0xf1000018;
! 1183: tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (arg1 & (0xf << CP0St_CU0));
! 1184: tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((arg1 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
! 1185: tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((arg1 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
1.1.1.7 root 1186: if (other_tc == env->current_tc)
1187: env->active_tc.CP0_TCStatus = tcstatus;
1188: else
1189: env->tcs[other_tc].CP0_TCStatus = tcstatus;
1.1 root 1190: }
1191:
1.1.1.8 ! root 1192: void helper_mtc0_intctl (target_ulong arg1)
1.1 root 1193: {
1.1.1.7 root 1194: /* vectored interrupts not implemented, no performance counters. */
1.1.1.8 ! root 1195: env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (arg1 & 0x000002e0);
1.1 root 1196: }
1197:
1.1.1.8 ! root 1198: void helper_mtc0_srsctl (target_ulong arg1)
1.1.1.6 root 1199: {
1.1.1.7 root 1200: uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
1.1.1.8 ! root 1201: env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (arg1 & mask);
1.1.1.6 root 1202: }
1203:
1.1.1.8 ! root 1204: void helper_mtc0_cause (target_ulong arg1)
1.1.1.6 root 1205: {
1.1.1.7 root 1206: uint32_t mask = 0x00C00300;
1207: uint32_t old = env->CP0_Cause;
1208:
1209: if (env->insn_flags & ISA_MIPS32R2)
1210: mask |= 1 << CP0Ca_DC;
1211:
1.1.1.8 ! root 1212: env->CP0_Cause = (env->CP0_Cause & ~mask) | (arg1 & mask);
1.1.1.7 root 1213:
1214: if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
1215: if (env->CP0_Cause & (1 << CP0Ca_DC))
1216: cpu_mips_stop_count(env);
1217: else
1218: cpu_mips_start_count(env);
1219: }
1220:
1221: /* Handle the software interrupt as an hardware one, as they
1222: are very similar */
1.1.1.8 ! root 1223: if (arg1 & CP0Ca_IP_mask) {
1.1.1.7 root 1224: cpu_mips_update_irq(env);
1225: }
1.1.1.6 root 1226: }
1227:
1.1.1.8 ! root 1228: void helper_mtc0_ebase (target_ulong arg1)
1.1.1.6 root 1229: {
1.1.1.7 root 1230: /* vectored interrupts not implemented */
1231: /* Multi-CPU not implemented */
1.1.1.8 ! root 1232: env->CP0_EBase = 0x80000000 | (arg1 & 0x3FFFF000);
1.1.1.6 root 1233: }
1234:
1.1.1.8 ! root 1235: void helper_mtc0_config0 (target_ulong arg1)
1.1.1.6 root 1236: {
1.1.1.8 ! root 1237: env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (arg1 & 0x00000007);
1.1.1.6 root 1238: }
1239:
1.1.1.8 ! root 1240: void helper_mtc0_config2 (target_ulong arg1)
1.1.1.6 root 1241: {
1.1.1.7 root 1242: /* tertiary/secondary caches not implemented */
1243: env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1.1.1.6 root 1244: }
1245:
1.1.1.8 ! root 1246: void helper_mtc0_watchlo (target_ulong arg1, uint32_t sel)
1.1.1.6 root 1247: {
1.1.1.7 root 1248: /* Watch exceptions for instructions, data loads, data stores
1249: not implemented. */
1.1.1.8 ! root 1250: env->CP0_WatchLo[sel] = (arg1 & ~0x7);
1.1.1.6 root 1251: }
1252:
1.1.1.8 ! root 1253: void helper_mtc0_watchhi (target_ulong arg1, uint32_t sel)
1.1.1.6 root 1254: {
1.1.1.8 ! root 1255: env->CP0_WatchHi[sel] = (arg1 & 0x40FF0FF8);
! 1256: env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & arg1 & 0x7);
1.1.1.6 root 1257: }
1258:
1.1.1.8 ! root 1259: void helper_mtc0_xcontext (target_ulong arg1)
1.1.1.6 root 1260: {
1.1.1.7 root 1261: target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
1.1.1.8 ! root 1262: env->CP0_XContext = (env->CP0_XContext & mask) | (arg1 & ~mask);
1.1.1.6 root 1263: }
1264:
1.1.1.8 ! root 1265: void helper_mtc0_framemask (target_ulong arg1)
1.1.1.6 root 1266: {
1.1.1.8 ! root 1267: env->CP0_Framemask = arg1; /* XXX */
1.1.1.6 root 1268: }
1269:
1.1.1.8 ! root 1270: void helper_mtc0_debug (target_ulong arg1)
1.1.1.6 root 1271: {
1.1.1.8 ! root 1272: env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (arg1 & 0x13300120);
! 1273: if (arg1 & (1 << CP0DB_DM))
1.1.1.7 root 1274: env->hflags |= MIPS_HFLAG_DM;
1275: else
1276: env->hflags &= ~MIPS_HFLAG_DM;
1.1.1.6 root 1277: }
1278:
1.1.1.8 ! root 1279: void helper_mttc0_debug(target_ulong arg1)
1.1.1.6 root 1280: {
1.1.1.7 root 1281: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.8 ! root 1282: uint32_t val = arg1 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
1.1.1.7 root 1283:
1284: /* XXX: Might be wrong, check with EJTAG spec. */
1285: if (other_tc == env->current_tc)
1286: env->active_tc.CP0_Debug_tcstatus = val;
1287: else
1288: env->tcs[other_tc].CP0_Debug_tcstatus = val;
1289: env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1.1.1.8 ! root 1290: (arg1 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1.1.1.6 root 1291: }
1292:
1.1.1.8 ! root 1293: void helper_mtc0_performance0 (target_ulong arg1)
1.1.1.6 root 1294: {
1.1.1.8 ! root 1295: env->CP0_Performance0 = arg1 & 0x000007ff;
1.1.1.6 root 1296: }
1297:
1.1.1.8 ! root 1298: void helper_mtc0_taglo (target_ulong arg1)
1.1.1.5 root 1299: {
1.1.1.8 ! root 1300: env->CP0_TagLo = arg1 & 0xFFFFFCF6;
1.1.1.5 root 1301: }
1302:
1.1.1.8 ! root 1303: void helper_mtc0_datalo (target_ulong arg1)
1.1.1.5 root 1304: {
1.1.1.8 ! root 1305: env->CP0_DataLo = arg1; /* XXX */
1.1.1.5 root 1306: }
1307:
1.1.1.8 ! root 1308: void helper_mtc0_taghi (target_ulong arg1)
1.1.1.5 root 1309: {
1.1.1.8 ! root 1310: env->CP0_TagHi = arg1; /* XXX */
1.1.1.5 root 1311: }
1312:
1.1.1.8 ! root 1313: void helper_mtc0_datahi (target_ulong arg1)
1.1.1.5 root 1314: {
1.1.1.8 ! root 1315: env->CP0_DataHi = arg1; /* XXX */
1.1.1.5 root 1316: }
1317:
1.1.1.7 root 1318: /* MIPS MT functions */
1.1.1.8 ! root 1319: target_ulong helper_mftgpr(uint32_t sel)
1.1.1.5 root 1320: {
1.1.1.7 root 1321: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1322:
1323: if (other_tc == env->current_tc)
1324: return env->active_tc.gpr[sel];
1325: else
1326: return env->tcs[other_tc].gpr[sel];
1.1.1.5 root 1327: }
1328:
1.1.1.8 ! root 1329: target_ulong helper_mftlo(uint32_t sel)
1.1.1.5 root 1330: {
1.1.1.7 root 1331: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1332:
1333: if (other_tc == env->current_tc)
1334: return env->active_tc.LO[sel];
1335: else
1336: return env->tcs[other_tc].LO[sel];
1.1.1.5 root 1337: }
1338:
1.1.1.8 ! root 1339: target_ulong helper_mfthi(uint32_t sel)
1.1.1.5 root 1340: {
1.1.1.7 root 1341: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1342:
1343: if (other_tc == env->current_tc)
1344: return env->active_tc.HI[sel];
1345: else
1346: return env->tcs[other_tc].HI[sel];
1.1.1.5 root 1347: }
1348:
1.1.1.8 ! root 1349: target_ulong helper_mftacx(uint32_t sel)
1.1.1.5 root 1350: {
1.1.1.7 root 1351: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1352:
1353: if (other_tc == env->current_tc)
1354: return env->active_tc.ACX[sel];
1355: else
1356: return env->tcs[other_tc].ACX[sel];
1.1.1.2 root 1357: }
1358:
1.1.1.8 ! root 1359: target_ulong helper_mftdsp(void)
1.1.1.2 root 1360: {
1.1.1.7 root 1361: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1362:
1363: if (other_tc == env->current_tc)
1364: return env->active_tc.DSPControl;
1365: else
1366: return env->tcs[other_tc].DSPControl;
1.1.1.2 root 1367: }
1368:
1.1.1.8 ! root 1369: void helper_mttgpr(target_ulong arg1, uint32_t sel)
1.1.1.2 root 1370: {
1.1.1.7 root 1371: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1372:
1373: if (other_tc == env->current_tc)
1.1.1.8 ! root 1374: env->active_tc.gpr[sel] = arg1;
1.1.1.7 root 1375: else
1.1.1.8 ! root 1376: env->tcs[other_tc].gpr[sel] = arg1;
1.1.1.2 root 1377: }
1378:
1.1.1.8 ! root 1379: void helper_mttlo(target_ulong arg1, uint32_t sel)
1.1.1.2 root 1380: {
1.1.1.7 root 1381: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1382:
1383: if (other_tc == env->current_tc)
1.1.1.8 ! root 1384: env->active_tc.LO[sel] = arg1;
1.1.1.7 root 1385: else
1.1.1.8 ! root 1386: env->tcs[other_tc].LO[sel] = arg1;
1.1.1.2 root 1387: }
1388:
1.1.1.8 ! root 1389: void helper_mtthi(target_ulong arg1, uint32_t sel)
1.1.1.2 root 1390: {
1.1.1.7 root 1391: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1392:
1393: if (other_tc == env->current_tc)
1.1.1.8 ! root 1394: env->active_tc.HI[sel] = arg1;
1.1.1.7 root 1395: else
1.1.1.8 ! root 1396: env->tcs[other_tc].HI[sel] = arg1;
1.1.1.2 root 1397: }
1.1.1.5 root 1398:
1.1.1.8 ! root 1399: void helper_mttacx(target_ulong arg1, uint32_t sel)
1.1.1.5 root 1400: {
1.1.1.7 root 1401: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.5 root 1402:
1.1.1.7 root 1403: if (other_tc == env->current_tc)
1.1.1.8 ! root 1404: env->active_tc.ACX[sel] = arg1;
1.1.1.7 root 1405: else
1.1.1.8 ! root 1406: env->tcs[other_tc].ACX[sel] = arg1;
1.1.1.7 root 1407: }
1.1.1.2 root 1408:
1.1.1.8 ! root 1409: void helper_mttdsp(target_ulong arg1)
1.1 root 1410: {
1.1.1.7 root 1411: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1412:
1413: if (other_tc == env->current_tc)
1.1.1.8 ! root 1414: env->active_tc.DSPControl = arg1;
1.1.1.7 root 1415: else
1.1.1.8 ! root 1416: env->tcs[other_tc].DSPControl = arg1;
1.1.1.5 root 1417: }
1.1 root 1418:
1.1.1.7 root 1419: /* MIPS MT functions */
1.1.1.8 ! root 1420: target_ulong helper_dmt(target_ulong arg1)
1.1.1.5 root 1421: {
1.1.1.7 root 1422: // TODO
1.1.1.8 ! root 1423: arg1 = 0;
! 1424: // rt = arg1
1.1.1.7 root 1425:
1.1.1.8 ! root 1426: return arg1;
1.1 root 1427: }
1428:
1.1.1.8 ! root 1429: target_ulong helper_emt(target_ulong arg1)
1.1 root 1430: {
1.1.1.7 root 1431: // TODO
1.1.1.8 ! root 1432: arg1 = 0;
! 1433: // rt = arg1
1.1.1.7 root 1434:
1.1.1.8 ! root 1435: return arg1;
1.1.1.5 root 1436: }
1.1 root 1437:
1.1.1.8 ! root 1438: target_ulong helper_dvpe(target_ulong arg1)
1.1.1.5 root 1439: {
1.1.1.7 root 1440: // TODO
1.1.1.8 ! root 1441: arg1 = 0;
! 1442: // rt = arg1
1.1.1.7 root 1443:
1.1.1.8 ! root 1444: return arg1;
1.1 root 1445: }
1446:
1.1.1.8 ! root 1447: target_ulong helper_evpe(target_ulong arg1)
1.1.1.4 root 1448: {
1.1.1.7 root 1449: // TODO
1.1.1.8 ! root 1450: arg1 = 0;
! 1451: // rt = arg1
1.1.1.4 root 1452:
1.1.1.8 ! root 1453: return arg1;
1.1.1.7 root 1454: }
1455: #endif /* !CONFIG_USER_ONLY */
1.1.1.4 root 1456:
1.1.1.8 ! root 1457: void helper_fork(target_ulong arg1, target_ulong arg2)
1.1.1.7 root 1458: {
1.1.1.8 ! root 1459: // arg1 = rt, arg2 = rs
! 1460: arg1 = 0;
1.1.1.7 root 1461: // TODO: store to TC register
1462: }
1463:
1.1.1.8 ! root 1464: target_ulong helper_yield(target_ulong arg1)
1.1.1.7 root 1465: {
1.1.1.8 ! root 1466: if (arg1 < 0) {
1.1.1.7 root 1467: /* No scheduling policy implemented. */
1.1.1.8 ! root 1468: if (arg1 != -2) {
1.1.1.7 root 1469: if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
1470: env->active_tc.CP0_TCStatus & (1 << CP0TCSt_DT)) {
1471: env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1472: env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
1.1.1.8 ! root 1473: helper_raise_exception(EXCP_THREAD);
1.1.1.7 root 1474: }
1475: }
1.1.1.8 ! root 1476: } else if (arg1 == 0) {
1.1.1.7 root 1477: if (0 /* TODO: TC underflow */) {
1478: env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1.1.1.8 ! root 1479: helper_raise_exception(EXCP_THREAD);
1.1.1.7 root 1480: } else {
1481: // TODO: Deallocate TC
1482: }
1.1.1.8 ! root 1483: } else if (arg1 > 0) {
1.1.1.7 root 1484: /* Yield qualifier inputs not implemented. */
1485: env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1486: env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
1.1.1.8 ! root 1487: helper_raise_exception(EXCP_THREAD);
1.1.1.4 root 1488: }
1.1.1.7 root 1489: return env->CP0_YQMask;
1.1.1.4 root 1490: }
1491:
1.1.1.7 root 1492: #ifndef CONFIG_USER_ONLY
1.1 root 1493: /* TLB management */
1.1.1.5 root 1494: void cpu_mips_tlb_flush (CPUState *env, int flush_global)
1.1 root 1495: {
1.1.1.5 root 1496: /* Flush qemu's TLB and discard all shadowed entries. */
1497: tlb_flush (env, flush_global);
1.1.1.6 root 1498: env->tlb->tlb_in_use = env->tlb->nb_tlb;
1.1.1.5 root 1499: }
1.1 root 1500:
1.1.1.6 root 1501: static void r4k_mips_tlb_flush_extra (CPUState *env, int first)
1.1.1.5 root 1502: {
1503: /* Discard entries from env->tlb[first] onwards. */
1.1.1.6 root 1504: while (env->tlb->tlb_in_use > first) {
1505: r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0);
1.1 root 1506: }
1507: }
1508:
1.1.1.6 root 1509: static void r4k_fill_tlb (int idx)
1.1 root 1510: {
1.1.1.6 root 1511: r4k_tlb_t *tlb;
1.1 root 1512:
1513: /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
1.1.1.6 root 1514: tlb = &env->tlb->mmu.r4k.tlb[idx];
1515: tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
1516: #if defined(TARGET_MIPS64)
1517: tlb->VPN &= env->SEGMask;
1518: #endif
1.1.1.3 root 1519: tlb->ASID = env->CP0_EntryHi & 0xFF;
1.1.1.5 root 1520: tlb->PageMask = env->CP0_PageMask;
1.1 root 1521: tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
1.1.1.3 root 1522: tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
1523: tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
1524: tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
1.1 root 1525: tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
1.1.1.3 root 1526: tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
1527: tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
1528: tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
1.1 root 1529: tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
1530: }
1531:
1.1.1.8 ! root 1532: void r4k_helper_tlbwi (void)
1.1 root 1533: {
1.1.1.7 root 1534: int idx;
1535:
1536: idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
1537:
1.1.1.5 root 1538: /* Discard cached TLB entries. We could avoid doing this if the
1539: tlbwi is just upgrading access permissions on the current entry;
1540: that might be a further win. */
1.1.1.6 root 1541: r4k_mips_tlb_flush_extra (env, env->tlb->nb_tlb);
1.1.1.5 root 1542:
1.1.1.7 root 1543: r4k_invalidate_tlb(env, idx, 0);
1544: r4k_fill_tlb(idx);
1.1 root 1545: }
1546:
1.1.1.8 ! root 1547: void r4k_helper_tlbwr (void)
1.1 root 1548: {
1549: int r = cpu_mips_get_random(env);
1550:
1.1.1.6 root 1551: r4k_invalidate_tlb(env, r, 1);
1552: r4k_fill_tlb(r);
1.1 root 1553: }
1554:
1.1.1.8 ! root 1555: void r4k_helper_tlbp (void)
1.1 root 1556: {
1.1.1.6 root 1557: r4k_tlb_t *tlb;
1558: target_ulong mask;
1.1 root 1559: target_ulong tag;
1.1.1.6 root 1560: target_ulong VPN;
1.1 root 1561: uint8_t ASID;
1562: int i;
1563:
1.1.1.4 root 1564: ASID = env->CP0_EntryHi & 0xFF;
1.1.1.6 root 1565: for (i = 0; i < env->tlb->nb_tlb; i++) {
1566: tlb = &env->tlb->mmu.r4k.tlb[i];
1567: /* 1k pages are not supported. */
1568: mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
1569: tag = env->CP0_EntryHi & ~mask;
1570: VPN = tlb->VPN & ~mask;
1.1 root 1571: /* Check ASID, virtual page number & size */
1.1.1.6 root 1572: if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1.1 root 1573: /* TLB match */
1.1.1.5 root 1574: env->CP0_Index = i;
1.1 root 1575: break;
1576: }
1577: }
1.1.1.6 root 1578: if (i == env->tlb->nb_tlb) {
1.1.1.5 root 1579: /* No match. Discard any shadow entries, if any of them match. */
1.1.1.6 root 1580: for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) {
1.1.1.7 root 1581: tlb = &env->tlb->mmu.r4k.tlb[i];
1582: /* 1k pages are not supported. */
1583: mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
1584: tag = env->CP0_EntryHi & ~mask;
1585: VPN = tlb->VPN & ~mask;
1586: /* Check ASID, virtual page number & size */
1587: if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1.1.1.6 root 1588: r4k_mips_tlb_flush_extra (env, i);
1.1.1.7 root 1589: break;
1590: }
1591: }
1.1.1.5 root 1592:
1593: env->CP0_Index |= 0x80000000;
1.1 root 1594: }
1595: }
1596:
1.1.1.8 ! root 1597: void r4k_helper_tlbr (void)
1.1 root 1598: {
1.1.1.6 root 1599: r4k_tlb_t *tlb;
1.1.1.3 root 1600: uint8_t ASID;
1.1.1.7 root 1601: int idx;
1.1 root 1602:
1.1.1.3 root 1603: ASID = env->CP0_EntryHi & 0xFF;
1.1.1.7 root 1604: idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
1605: tlb = &env->tlb->mmu.r4k.tlb[idx];
1.1.1.2 root 1606:
1607: /* If this will change the current ASID, flush qemu's TLB. */
1.1.1.5 root 1608: if (ASID != tlb->ASID)
1609: cpu_mips_tlb_flush (env, 1);
1610:
1.1.1.6 root 1611: r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
1.1.1.2 root 1612:
1.1 root 1613: env->CP0_EntryHi = tlb->VPN | tlb->ASID;
1.1.1.5 root 1614: env->CP0_PageMask = tlb->PageMask;
1615: env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
1616: (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
1617: env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
1618: (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
1.1 root 1619: }
1620:
1.1.1.8 ! root 1621: void helper_tlbwi(void)
1.1.1.7 root 1622: {
1.1.1.8 ! root 1623: env->tlb->helper_tlbwi();
1.1.1.7 root 1624: }
1625:
1.1.1.8 ! root 1626: void helper_tlbwr(void)
1.1.1.7 root 1627: {
1.1.1.8 ! root 1628: env->tlb->helper_tlbwr();
1.1.1.7 root 1629: }
1630:
1.1.1.8 ! root 1631: void helper_tlbp(void)
1.1.1.7 root 1632: {
1.1.1.8 ! root 1633: env->tlb->helper_tlbp();
1.1.1.7 root 1634: }
1635:
1.1.1.8 ! root 1636: void helper_tlbr(void)
1.1.1.7 root 1637: {
1.1.1.8 ! root 1638: env->tlb->helper_tlbr();
1.1.1.7 root 1639: }
1640:
1641: /* Specials */
1.1.1.8 ! root 1642: target_ulong helper_di (void)
1.1.1.7 root 1643: {
1644: target_ulong t0 = env->CP0_Status;
1.1.1.2 root 1645:
1.1.1.7 root 1646: env->CP0_Status = t0 & ~(1 << CP0St_IE);
1647: cpu_mips_update_irq(env);
1648:
1649: return t0;
1650: }
1651:
1.1.1.8 ! root 1652: target_ulong helper_ei (void)
1.1 root 1653: {
1.1.1.7 root 1654: target_ulong t0 = env->CP0_Status;
1655:
1656: env->CP0_Status = t0 | (1 << CP0St_IE);
1657: cpu_mips_update_irq(env);
1658:
1659: return t0;
1.1 root 1660: }
1661:
1.1.1.7 root 1662: static void debug_pre_eret (void)
1.1 root 1663: {
1.1.1.7 root 1664: if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
1665: qemu_log("ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
1666: env->active_tc.PC, env->CP0_EPC);
1667: if (env->CP0_Status & (1 << CP0St_ERL))
1668: qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
1669: if (env->hflags & MIPS_HFLAG_DM)
1670: qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
1671: qemu_log("\n");
1.1 root 1672: }
1673: }
1674:
1.1.1.7 root 1675: static void debug_post_eret (void)
1.1 root 1676: {
1.1.1.7 root 1677: if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
1678: qemu_log(" => PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
1679: env->active_tc.PC, env->CP0_EPC);
1680: if (env->CP0_Status & (1 << CP0St_ERL))
1681: qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
1682: if (env->hflags & MIPS_HFLAG_DM)
1683: qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
1684: switch (env->hflags & MIPS_HFLAG_KSU) {
1685: case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
1686: case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
1687: case MIPS_HFLAG_KM: qemu_log("\n"); break;
1688: default: cpu_abort(env, "Invalid MMU mode!\n"); break;
1689: }
1690: }
1.1.1.6 root 1691: }
1692:
1.1.1.8 ! root 1693: void helper_eret (void)
1.1.1.6 root 1694: {
1.1.1.7 root 1695: debug_pre_eret();
1696: if (env->CP0_Status & (1 << CP0St_ERL)) {
1697: env->active_tc.PC = env->CP0_ErrorEPC;
1698: env->CP0_Status &= ~(1 << CP0St_ERL);
1699: } else {
1700: env->active_tc.PC = env->CP0_EPC;
1701: env->CP0_Status &= ~(1 << CP0St_EXL);
1.1 root 1702: }
1.1.1.7 root 1703: compute_hflags(env);
1704: debug_post_eret();
1705: env->CP0_LLAddr = 1;
1706: }
1707:
1.1.1.8 ! root 1708: void helper_deret (void)
1.1.1.7 root 1709: {
1710: debug_pre_eret();
1711: env->active_tc.PC = env->CP0_DEPC;
1712: env->hflags &= MIPS_HFLAG_DM;
1713: compute_hflags(env);
1714: debug_post_eret();
1715: env->CP0_LLAddr = 1;
1716: }
1717: #endif /* !CONFIG_USER_ONLY */
1718:
1.1.1.8 ! root 1719: target_ulong helper_rdhwr_cpunum(void)
1.1.1.7 root 1720: {
1721: if ((env->hflags & MIPS_HFLAG_CP0) ||
1722: (env->CP0_HWREna & (1 << 0)))
1723: return env->CP0_EBase & 0x3ff;
1724: else
1.1.1.8 ! root 1725: helper_raise_exception(EXCP_RI);
1.1.1.7 root 1726:
1727: return 0;
1728: }
1729:
1.1.1.8 ! root 1730: target_ulong helper_rdhwr_synci_step(void)
1.1.1.7 root 1731: {
1732: if ((env->hflags & MIPS_HFLAG_CP0) ||
1733: (env->CP0_HWREna & (1 << 1)))
1734: return env->SYNCI_Step;
1735: else
1.1.1.8 ! root 1736: helper_raise_exception(EXCP_RI);
1.1.1.7 root 1737:
1738: return 0;
1739: }
1740:
1.1.1.8 ! root 1741: target_ulong helper_rdhwr_cc(void)
1.1.1.7 root 1742: {
1743: if ((env->hflags & MIPS_HFLAG_CP0) ||
1744: (env->CP0_HWREna & (1 << 2)))
1745: return env->CP0_Count;
1746: else
1.1.1.8 ! root 1747: helper_raise_exception(EXCP_RI);
1.1.1.7 root 1748:
1749: return 0;
1750: }
1751:
1.1.1.8 ! root 1752: target_ulong helper_rdhwr_ccres(void)
1.1.1.7 root 1753: {
1754: if ((env->hflags & MIPS_HFLAG_CP0) ||
1755: (env->CP0_HWREna & (1 << 3)))
1756: return env->CCRes;
1757: else
1.1.1.8 ! root 1758: helper_raise_exception(EXCP_RI);
1.1.1.7 root 1759:
1760: return 0;
1.1 root 1761: }
1762:
1.1.1.8 ! root 1763: void helper_pmon (int function)
1.1 root 1764: {
1765: function /= 2;
1766: switch (function) {
1767: case 2: /* TODO: char inbyte(int waitflag); */
1.1.1.7 root 1768: if (env->active_tc.gpr[4] == 0)
1769: env->active_tc.gpr[2] = -1;
1.1 root 1770: /* Fall through */
1771: case 11: /* TODO: char inbyte (void); */
1.1.1.7 root 1772: env->active_tc.gpr[2] = -1;
1.1 root 1773: break;
1774: case 3:
1775: case 12:
1.1.1.7 root 1776: printf("%c", (char)(env->active_tc.gpr[4] & 0xFF));
1.1 root 1777: break;
1778: case 17:
1779: break;
1780: case 158:
1781: {
1.1.1.7 root 1782: unsigned char *fmt = (void *)(unsigned long)env->active_tc.gpr[4];
1.1 root 1783: printf("%s", fmt);
1784: }
1785: break;
1786: }
1787: }
1788:
1.1.1.8 ! root 1789: void helper_wait (void)
1.1.1.7 root 1790: {
1791: env->halted = 1;
1.1.1.8 ! root 1792: helper_raise_exception(EXCP_HLT);
1.1.1.7 root 1793: }
1794:
1.1.1.6 root 1795: #if !defined(CONFIG_USER_ONLY)
1.1 root 1796:
1.1.1.2 root 1797: static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr);
1798:
1.1 root 1799: #define MMUSUFFIX _mmu
1.1.1.2 root 1800: #define ALIGNED_ONLY
1.1 root 1801:
1802: #define SHIFT 0
1803: #include "softmmu_template.h"
1804:
1805: #define SHIFT 1
1806: #include "softmmu_template.h"
1807:
1808: #define SHIFT 2
1809: #include "softmmu_template.h"
1810:
1811: #define SHIFT 3
1812: #include "softmmu_template.h"
1813:
1.1.1.2 root 1814: static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr)
1815: {
1816: env->CP0_BadVAddr = addr;
1817: do_restore_state (retaddr);
1.1.1.8 ! root 1818: helper_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL);
1.1.1.2 root 1819: }
1820:
1.1.1.6 root 1821: void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1.1 root 1822: {
1823: TranslationBlock *tb;
1824: CPUState *saved_env;
1825: unsigned long pc;
1826: int ret;
1827:
1828: /* XXX: hack to restore env in all cases, even if not called from
1829: generated code */
1830: saved_env = env;
1831: env = cpu_single_env;
1.1.1.6 root 1832: ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1.1 root 1833: if (ret) {
1834: if (retaddr) {
1835: /* now we have a real cpu fault */
1836: pc = (unsigned long)retaddr;
1837: tb = tb_find_pc(pc);
1838: if (tb) {
1839: /* the PC is inside the translated code. It means that we have
1840: a virtual CPU fault */
1841: cpu_restore_state(tb, env, pc, NULL);
1842: }
1843: }
1.1.1.8 ! root 1844: helper_raise_exception_err(env->exception_index, env->error_code);
1.1 root 1845: }
1846: env = saved_env;
1847: }
1848:
1.1.1.6 root 1849: void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1.1.1.7 root 1850: int unused, int size)
1.1.1.6 root 1851: {
1852: if (is_exec)
1.1.1.8 ! root 1853: helper_raise_exception(EXCP_IBE);
1.1.1.6 root 1854: else
1.1.1.8 ! root 1855: helper_raise_exception(EXCP_DBE);
1.1.1.6 root 1856: }
1.1.1.7 root 1857: #endif /* !CONFIG_USER_ONLY */
1.1.1.6 root 1858:
1859: /* Complex FPU operations which may need stack space. */
1860:
1861: #define FLOAT_ONE32 make_float32(0x3f8 << 20)
1862: #define FLOAT_ONE64 make_float64(0x3ffULL << 52)
1863: #define FLOAT_TWO32 make_float32(1 << 30)
1864: #define FLOAT_TWO64 make_float64(1ULL << 62)
1865: #define FLOAT_QNAN32 0x7fbfffff
1866: #define FLOAT_QNAN64 0x7ff7ffffffffffffULL
1867: #define FLOAT_SNAN32 0x7fffffff
1868: #define FLOAT_SNAN64 0x7fffffffffffffffULL
1869:
1870: /* convert MIPS rounding mode in FCR31 to IEEE library */
1871: unsigned int ieee_rm[] = {
1872: float_round_nearest_even,
1873: float_round_to_zero,
1874: float_round_up,
1875: float_round_down
1876: };
1877:
1878: #define RESTORE_ROUNDING_MODE \
1.1.1.7 root 1879: set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], &env->active_fpu.fp_status)
1.1.1.6 root 1880:
1.1.1.8 ! root 1881: #define RESTORE_FLUSH_MODE \
! 1882: set_flush_to_zero((env->active_fpu.fcr31 & (1 << 24)) != 0, &env->active_fpu.fp_status);
! 1883:
! 1884: target_ulong helper_cfc1 (uint32_t reg)
1.1.1.6 root 1885: {
1.1.1.8 ! root 1886: target_ulong arg1;
1.1.1.7 root 1887:
1.1.1.6 root 1888: switch (reg) {
1889: case 0:
1.1.1.8 ! root 1890: arg1 = (int32_t)env->active_fpu.fcr0;
1.1.1.6 root 1891: break;
1892: case 25:
1.1.1.8 ! root 1893: arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | ((env->active_fpu.fcr31 >> 23) & 0x1);
1.1.1.6 root 1894: break;
1895: case 26:
1.1.1.8 ! root 1896: arg1 = env->active_fpu.fcr31 & 0x0003f07c;
1.1.1.6 root 1897: break;
1898: case 28:
1.1.1.8 ! root 1899: arg1 = (env->active_fpu.fcr31 & 0x00000f83) | ((env->active_fpu.fcr31 >> 22) & 0x4);
1.1.1.6 root 1900: break;
1901: default:
1.1.1.8 ! root 1902: arg1 = (int32_t)env->active_fpu.fcr31;
1.1.1.6 root 1903: break;
1904: }
1.1.1.7 root 1905:
1.1.1.8 ! root 1906: return arg1;
1.1.1.6 root 1907: }
1908:
1.1.1.8 ! root 1909: void helper_ctc1 (target_ulong arg1, uint32_t reg)
1.1.1.6 root 1910: {
1911: switch(reg) {
1912: case 25:
1.1.1.8 ! root 1913: if (arg1 & 0xffffff00)
1.1.1.6 root 1914: return;
1.1.1.8 ! root 1915: env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) | ((arg1 & 0xfe) << 24) |
! 1916: ((arg1 & 0x1) << 23);
1.1.1.6 root 1917: break;
1918: case 26:
1.1.1.8 ! root 1919: if (arg1 & 0x007c0000)
1.1.1.6 root 1920: return;
1.1.1.8 ! root 1921: env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfffc0f83) | (arg1 & 0x0003f07c);
1.1.1.6 root 1922: break;
1923: case 28:
1.1.1.8 ! root 1924: if (arg1 & 0x007c0000)
1.1.1.6 root 1925: return;
1.1.1.8 ! root 1926: env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfefff07c) | (arg1 & 0x00000f83) |
! 1927: ((arg1 & 0x4) << 22);
1.1.1.6 root 1928: break;
1929: case 31:
1.1.1.8 ! root 1930: if (arg1 & 0x007c0000)
1.1.1.6 root 1931: return;
1.1.1.8 ! root 1932: env->active_fpu.fcr31 = arg1;
1.1.1.6 root 1933: break;
1934: default:
1935: return;
1936: }
1937: /* set rounding mode */
1938: RESTORE_ROUNDING_MODE;
1.1.1.8 ! root 1939: /* set flush-to-zero mode */
! 1940: RESTORE_FLUSH_MODE;
1.1.1.7 root 1941: set_float_exception_flags(0, &env->active_fpu.fp_status);
1942: if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & GET_FP_CAUSE(env->active_fpu.fcr31))
1.1.1.8 ! root 1943: helper_raise_exception(EXCP_FPE);
1.1.1.6 root 1944: }
1945:
1.1.1.7 root 1946: static inline char ieee_ex_to_mips(char xcpt)
1.1.1.6 root 1947: {
1948: return (xcpt & float_flag_inexact) >> 5 |
1949: (xcpt & float_flag_underflow) >> 3 |
1950: (xcpt & float_flag_overflow) >> 1 |
1951: (xcpt & float_flag_divbyzero) << 1 |
1952: (xcpt & float_flag_invalid) << 4;
1953: }
1954:
1.1.1.7 root 1955: static inline char mips_ex_to_ieee(char xcpt)
1.1.1.6 root 1956: {
1957: return (xcpt & FP_INEXACT) << 5 |
1958: (xcpt & FP_UNDERFLOW) << 3 |
1959: (xcpt & FP_OVERFLOW) << 1 |
1960: (xcpt & FP_DIV0) >> 1 |
1961: (xcpt & FP_INVALID) >> 4;
1962: }
1963:
1.1.1.7 root 1964: static inline void update_fcr31(void)
1.1.1.6 root 1965: {
1.1.1.7 root 1966: int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->active_fpu.fp_status));
1.1.1.6 root 1967:
1.1.1.7 root 1968: SET_FP_CAUSE(env->active_fpu.fcr31, tmp);
1969: if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp)
1.1.1.8 ! root 1970: helper_raise_exception(EXCP_FPE);
1.1.1.6 root 1971: else
1.1.1.7 root 1972: UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp);
1.1.1.6 root 1973: }
1974:
1.1.1.7 root 1975: /* Float support.
1976: Single precition routines have a "s" suffix, double precision a
1977: "d" suffix, 32bit integer "w", 64bit integer "l", paired single "ps",
1978: paired single lower "pl", paired single upper "pu". */
1979:
1980: /* unary operations, modifying fp status */
1.1.1.8 ! root 1981: uint64_t helper_float_sqrt_d(uint64_t fdt0)
1.1.1.7 root 1982: {
1983: return float64_sqrt(fdt0, &env->active_fpu.fp_status);
1984: }
1.1.1.6 root 1985:
1.1.1.8 ! root 1986: uint32_t helper_float_sqrt_s(uint32_t fst0)
1.1.1.6 root 1987: {
1.1.1.7 root 1988: return float32_sqrt(fst0, &env->active_fpu.fp_status);
1989: }
1990:
1.1.1.8 ! root 1991: uint64_t helper_float_cvtd_s(uint32_t fst0)
1.1.1.7 root 1992: {
1993: uint64_t fdt2;
1994:
1995: set_float_exception_flags(0, &env->active_fpu.fp_status);
1996: fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 1997: update_fcr31();
1.1.1.7 root 1998: return fdt2;
1.1.1.6 root 1999: }
1.1.1.7 root 2000:
1.1.1.8 ! root 2001: uint64_t helper_float_cvtd_w(uint32_t wt0)
1.1.1.6 root 2002: {
1.1.1.7 root 2003: uint64_t fdt2;
2004:
2005: set_float_exception_flags(0, &env->active_fpu.fp_status);
2006: fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status);
1.1.1.6 root 2007: update_fcr31();
1.1.1.7 root 2008: return fdt2;
1.1.1.6 root 2009: }
1.1.1.7 root 2010:
1.1.1.8 ! root 2011: uint64_t helper_float_cvtd_l(uint64_t dt0)
1.1.1.6 root 2012: {
1.1.1.7 root 2013: uint64_t fdt2;
2014:
2015: set_float_exception_flags(0, &env->active_fpu.fp_status);
2016: fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status);
1.1.1.6 root 2017: update_fcr31();
1.1.1.7 root 2018: return fdt2;
1.1.1.6 root 2019: }
1.1.1.7 root 2020:
1.1.1.8 ! root 2021: uint64_t helper_float_cvtl_d(uint64_t fdt0)
1.1.1.6 root 2022: {
1.1.1.7 root 2023: uint64_t dt2;
2024:
2025: set_float_exception_flags(0, &env->active_fpu.fp_status);
2026: dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2027: update_fcr31();
1.1.1.7 root 2028: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2029: dt2 = FLOAT_SNAN64;
2030: return dt2;
1.1.1.6 root 2031: }
1.1.1.7 root 2032:
1.1.1.8 ! root 2033: uint64_t helper_float_cvtl_s(uint32_t fst0)
1.1.1.6 root 2034: {
1.1.1.7 root 2035: uint64_t dt2;
2036:
2037: set_float_exception_flags(0, &env->active_fpu.fp_status);
2038: dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2039: update_fcr31();
1.1.1.7 root 2040: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2041: dt2 = FLOAT_SNAN64;
2042: return dt2;
1.1.1.6 root 2043: }
2044:
1.1.1.8 ! root 2045: uint64_t helper_float_cvtps_pw(uint64_t dt0)
1.1.1.6 root 2046: {
1.1.1.7 root 2047: uint32_t fst2;
2048: uint32_t fsth2;
2049:
2050: set_float_exception_flags(0, &env->active_fpu.fp_status);
2051: fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2052: fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status);
1.1.1.6 root 2053: update_fcr31();
1.1.1.7 root 2054: return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6 root 2055: }
1.1.1.7 root 2056:
1.1.1.8 ! root 2057: uint64_t helper_float_cvtpw_ps(uint64_t fdt0)
1.1.1.6 root 2058: {
1.1.1.7 root 2059: uint32_t wt2;
2060: uint32_t wth2;
2061:
2062: set_float_exception_flags(0, &env->active_fpu.fp_status);
2063: wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2064: wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status);
1.1.1.6 root 2065: update_fcr31();
1.1.1.7 root 2066: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) {
2067: wt2 = FLOAT_SNAN32;
2068: wth2 = FLOAT_SNAN32;
2069: }
2070: return ((uint64_t)wth2 << 32) | wt2;
1.1.1.6 root 2071: }
1.1.1.7 root 2072:
1.1.1.8 ! root 2073: uint32_t helper_float_cvts_d(uint64_t fdt0)
1.1.1.6 root 2074: {
1.1.1.7 root 2075: uint32_t fst2;
2076:
2077: set_float_exception_flags(0, &env->active_fpu.fp_status);
2078: fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2079: update_fcr31();
1.1.1.7 root 2080: return fst2;
1.1.1.6 root 2081: }
1.1.1.7 root 2082:
1.1.1.8 ! root 2083: uint32_t helper_float_cvts_w(uint32_t wt0)
1.1.1.6 root 2084: {
1.1.1.7 root 2085: uint32_t fst2;
2086:
2087: set_float_exception_flags(0, &env->active_fpu.fp_status);
2088: fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status);
1.1.1.6 root 2089: update_fcr31();
1.1.1.7 root 2090: return fst2;
1.1.1.6 root 2091: }
1.1.1.7 root 2092:
1.1.1.8 ! root 2093: uint32_t helper_float_cvts_l(uint64_t dt0)
1.1.1.6 root 2094: {
1.1.1.7 root 2095: uint32_t fst2;
2096:
2097: set_float_exception_flags(0, &env->active_fpu.fp_status);
2098: fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status);
1.1.1.6 root 2099: update_fcr31();
1.1.1.7 root 2100: return fst2;
1.1.1.6 root 2101: }
1.1.1.7 root 2102:
1.1.1.8 ! root 2103: uint32_t helper_float_cvts_pl(uint32_t wt0)
1.1.1.6 root 2104: {
1.1.1.7 root 2105: uint32_t wt2;
2106:
2107: set_float_exception_flags(0, &env->active_fpu.fp_status);
2108: wt2 = wt0;
1.1.1.6 root 2109: update_fcr31();
1.1.1.7 root 2110: return wt2;
1.1.1.6 root 2111: }
1.1.1.7 root 2112:
1.1.1.8 ! root 2113: uint32_t helper_float_cvts_pu(uint32_t wth0)
1.1.1.6 root 2114: {
1.1.1.7 root 2115: uint32_t wt2;
2116:
2117: set_float_exception_flags(0, &env->active_fpu.fp_status);
2118: wt2 = wth0;
1.1.1.6 root 2119: update_fcr31();
1.1.1.7 root 2120: return wt2;
1.1.1.6 root 2121: }
1.1.1.7 root 2122:
1.1.1.8 ! root 2123: uint32_t helper_float_cvtw_s(uint32_t fst0)
1.1.1.6 root 2124: {
1.1.1.7 root 2125: uint32_t wt2;
2126:
2127: set_float_exception_flags(0, &env->active_fpu.fp_status);
2128: wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2129: update_fcr31();
1.1.1.7 root 2130: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2131: wt2 = FLOAT_SNAN32;
2132: return wt2;
1.1.1.6 root 2133: }
1.1.1.7 root 2134:
1.1.1.8 ! root 2135: uint32_t helper_float_cvtw_d(uint64_t fdt0)
1.1.1.6 root 2136: {
1.1.1.7 root 2137: uint32_t wt2;
2138:
2139: set_float_exception_flags(0, &env->active_fpu.fp_status);
2140: wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2141: update_fcr31();
1.1.1.7 root 2142: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2143: wt2 = FLOAT_SNAN32;
2144: return wt2;
1.1.1.6 root 2145: }
2146:
1.1.1.8 ! root 2147: uint64_t helper_float_roundl_d(uint64_t fdt0)
1.1.1.6 root 2148: {
1.1.1.7 root 2149: uint64_t dt2;
2150:
2151: set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
2152: dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2153: RESTORE_ROUNDING_MODE;
2154: update_fcr31();
1.1.1.7 root 2155: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2156: dt2 = FLOAT_SNAN64;
2157: return dt2;
1.1.1.6 root 2158: }
1.1.1.7 root 2159:
1.1.1.8 ! root 2160: uint64_t helper_float_roundl_s(uint32_t fst0)
1.1.1.6 root 2161: {
1.1.1.7 root 2162: uint64_t dt2;
2163:
2164: set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
2165: dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2166: RESTORE_ROUNDING_MODE;
2167: update_fcr31();
1.1.1.7 root 2168: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2169: dt2 = FLOAT_SNAN64;
2170: return dt2;
1.1.1.6 root 2171: }
1.1.1.7 root 2172:
1.1.1.8 ! root 2173: uint32_t helper_float_roundw_d(uint64_t fdt0)
1.1.1.6 root 2174: {
1.1.1.7 root 2175: uint32_t wt2;
2176:
2177: set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
2178: wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2179: RESTORE_ROUNDING_MODE;
2180: update_fcr31();
1.1.1.7 root 2181: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2182: wt2 = FLOAT_SNAN32;
2183: return wt2;
1.1.1.6 root 2184: }
1.1.1.7 root 2185:
1.1.1.8 ! root 2186: uint32_t helper_float_roundw_s(uint32_t fst0)
1.1.1.6 root 2187: {
1.1.1.7 root 2188: uint32_t wt2;
2189:
2190: set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
2191: wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2192: RESTORE_ROUNDING_MODE;
2193: update_fcr31();
1.1.1.7 root 2194: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2195: wt2 = FLOAT_SNAN32;
2196: return wt2;
1.1.1.6 root 2197: }
2198:
1.1.1.8 ! root 2199: uint64_t helper_float_truncl_d(uint64_t fdt0)
1.1.1.6 root 2200: {
1.1.1.7 root 2201: uint64_t dt2;
2202:
2203: dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2204: update_fcr31();
1.1.1.7 root 2205: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2206: dt2 = FLOAT_SNAN64;
2207: return dt2;
1.1.1.6 root 2208: }
1.1.1.7 root 2209:
1.1.1.8 ! root 2210: uint64_t helper_float_truncl_s(uint32_t fst0)
1.1.1.6 root 2211: {
1.1.1.7 root 2212: uint64_t dt2;
2213:
2214: dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2215: update_fcr31();
1.1.1.7 root 2216: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2217: dt2 = FLOAT_SNAN64;
2218: return dt2;
1.1.1.6 root 2219: }
1.1.1.7 root 2220:
1.1.1.8 ! root 2221: uint32_t helper_float_truncw_d(uint64_t fdt0)
1.1.1.6 root 2222: {
1.1.1.7 root 2223: uint32_t wt2;
2224:
2225: wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2226: update_fcr31();
1.1.1.7 root 2227: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2228: wt2 = FLOAT_SNAN32;
2229: return wt2;
1.1.1.6 root 2230: }
1.1.1.7 root 2231:
1.1.1.8 ! root 2232: uint32_t helper_float_truncw_s(uint32_t fst0)
1.1.1.6 root 2233: {
1.1.1.7 root 2234: uint32_t wt2;
2235:
2236: wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2237: update_fcr31();
1.1.1.7 root 2238: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2239: wt2 = FLOAT_SNAN32;
2240: return wt2;
1.1.1.6 root 2241: }
2242:
1.1.1.8 ! root 2243: uint64_t helper_float_ceill_d(uint64_t fdt0)
1.1.1.6 root 2244: {
1.1.1.7 root 2245: uint64_t dt2;
2246:
2247: set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2248: dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2249: RESTORE_ROUNDING_MODE;
2250: update_fcr31();
1.1.1.7 root 2251: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2252: dt2 = FLOAT_SNAN64;
2253: return dt2;
1.1.1.6 root 2254: }
1.1.1.7 root 2255:
1.1.1.8 ! root 2256: uint64_t helper_float_ceill_s(uint32_t fst0)
1.1.1.6 root 2257: {
1.1.1.7 root 2258: uint64_t dt2;
2259:
2260: set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2261: dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2262: RESTORE_ROUNDING_MODE;
2263: update_fcr31();
1.1.1.7 root 2264: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2265: dt2 = FLOAT_SNAN64;
2266: return dt2;
1.1.1.6 root 2267: }
1.1.1.7 root 2268:
1.1.1.8 ! root 2269: uint32_t helper_float_ceilw_d(uint64_t fdt0)
1.1.1.6 root 2270: {
1.1.1.7 root 2271: uint32_t wt2;
2272:
2273: set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2274: wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2275: RESTORE_ROUNDING_MODE;
2276: update_fcr31();
1.1.1.7 root 2277: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2278: wt2 = FLOAT_SNAN32;
2279: return wt2;
1.1.1.6 root 2280: }
1.1.1.7 root 2281:
1.1.1.8 ! root 2282: uint32_t helper_float_ceilw_s(uint32_t fst0)
1.1.1.6 root 2283: {
1.1.1.7 root 2284: uint32_t wt2;
2285:
2286: set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2287: wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2288: RESTORE_ROUNDING_MODE;
2289: update_fcr31();
1.1.1.7 root 2290: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2291: wt2 = FLOAT_SNAN32;
2292: return wt2;
1.1.1.6 root 2293: }
2294:
1.1.1.8 ! root 2295: uint64_t helper_float_floorl_d(uint64_t fdt0)
1.1.1.6 root 2296: {
1.1.1.7 root 2297: uint64_t dt2;
2298:
2299: set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2300: dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2301: RESTORE_ROUNDING_MODE;
2302: update_fcr31();
1.1.1.7 root 2303: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2304: dt2 = FLOAT_SNAN64;
2305: return dt2;
1.1.1.6 root 2306: }
1.1.1.7 root 2307:
1.1.1.8 ! root 2308: uint64_t helper_float_floorl_s(uint32_t fst0)
1.1.1.6 root 2309: {
1.1.1.7 root 2310: uint64_t dt2;
2311:
2312: set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2313: dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2314: RESTORE_ROUNDING_MODE;
2315: update_fcr31();
1.1.1.7 root 2316: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2317: dt2 = FLOAT_SNAN64;
2318: return dt2;
1.1.1.6 root 2319: }
1.1.1.7 root 2320:
1.1.1.8 ! root 2321: uint32_t helper_float_floorw_d(uint64_t fdt0)
1.1.1.6 root 2322: {
1.1.1.7 root 2323: uint32_t wt2;
2324:
2325: set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2326: wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2327: RESTORE_ROUNDING_MODE;
2328: update_fcr31();
1.1.1.7 root 2329: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2330: wt2 = FLOAT_SNAN32;
2331: return wt2;
1.1.1.6 root 2332: }
1.1.1.7 root 2333:
1.1.1.8 ! root 2334: uint32_t helper_float_floorw_s(uint32_t fst0)
1.1.1.6 root 2335: {
1.1.1.7 root 2336: uint32_t wt2;
2337:
2338: set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2339: wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2340: RESTORE_ROUNDING_MODE;
2341: update_fcr31();
1.1.1.7 root 2342: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2343: wt2 = FLOAT_SNAN32;
2344: return wt2;
2345: }
2346:
2347: /* unary operations, not modifying fp status */
2348: #define FLOAT_UNOP(name) \
1.1.1.8 ! root 2349: uint64_t helper_float_ ## name ## _d(uint64_t fdt0) \
1.1.1.7 root 2350: { \
2351: return float64_ ## name(fdt0); \
2352: } \
1.1.1.8 ! root 2353: uint32_t helper_float_ ## name ## _s(uint32_t fst0) \
1.1.1.7 root 2354: { \
2355: return float32_ ## name(fst0); \
2356: } \
1.1.1.8 ! root 2357: uint64_t helper_float_ ## name ## _ps(uint64_t fdt0) \
1.1.1.7 root 2358: { \
2359: uint32_t wt0; \
2360: uint32_t wth0; \
2361: \
2362: wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF); \
2363: wth0 = float32_ ## name(fdt0 >> 32); \
2364: return ((uint64_t)wth0 << 32) | wt0; \
2365: }
2366: FLOAT_UNOP(abs)
2367: FLOAT_UNOP(chs)
2368: #undef FLOAT_UNOP
1.1.1.6 root 2369:
2370: /* MIPS specific unary operations */
1.1.1.8 ! root 2371: uint64_t helper_float_recip_d(uint64_t fdt0)
1.1.1.6 root 2372: {
1.1.1.7 root 2373: uint64_t fdt2;
2374:
2375: set_float_exception_flags(0, &env->active_fpu.fp_status);
2376: fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2377: update_fcr31();
1.1.1.7 root 2378: return fdt2;
1.1.1.6 root 2379: }
1.1.1.7 root 2380:
1.1.1.8 ! root 2381: uint32_t helper_float_recip_s(uint32_t fst0)
1.1.1.6 root 2382: {
1.1.1.7 root 2383: uint32_t fst2;
2384:
2385: set_float_exception_flags(0, &env->active_fpu.fp_status);
2386: fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2387: update_fcr31();
1.1.1.7 root 2388: return fst2;
1.1.1.6 root 2389: }
2390:
1.1.1.8 ! root 2391: uint64_t helper_float_rsqrt_d(uint64_t fdt0)
1.1.1.6 root 2392: {
1.1.1.7 root 2393: uint64_t fdt2;
2394:
2395: set_float_exception_flags(0, &env->active_fpu.fp_status);
2396: fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
2397: fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status);
1.1.1.6 root 2398: update_fcr31();
1.1.1.7 root 2399: return fdt2;
1.1.1.6 root 2400: }
1.1.1.7 root 2401:
1.1.1.8 ! root 2402: uint32_t helper_float_rsqrt_s(uint32_t fst0)
1.1.1.6 root 2403: {
1.1.1.7 root 2404: uint32_t fst2;
2405:
2406: set_float_exception_flags(0, &env->active_fpu.fp_status);
2407: fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
2408: fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
1.1.1.6 root 2409: update_fcr31();
1.1.1.7 root 2410: return fst2;
1.1.1.6 root 2411: }
2412:
1.1.1.8 ! root 2413: uint64_t helper_float_recip1_d(uint64_t fdt0)
1.1.1.6 root 2414: {
1.1.1.7 root 2415: uint64_t fdt2;
2416:
2417: set_float_exception_flags(0, &env->active_fpu.fp_status);
2418: fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2419: update_fcr31();
1.1.1.7 root 2420: return fdt2;
1.1.1.6 root 2421: }
1.1.1.7 root 2422:
1.1.1.8 ! root 2423: uint32_t helper_float_recip1_s(uint32_t fst0)
1.1.1.6 root 2424: {
1.1.1.7 root 2425: uint32_t fst2;
2426:
2427: set_float_exception_flags(0, &env->active_fpu.fp_status);
2428: fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2429: update_fcr31();
1.1.1.7 root 2430: return fst2;
1.1.1.6 root 2431: }
1.1.1.7 root 2432:
1.1.1.8 ! root 2433: uint64_t helper_float_recip1_ps(uint64_t fdt0)
1.1.1.6 root 2434: {
1.1.1.7 root 2435: uint32_t fst2;
2436: uint32_t fsth2;
2437:
2438: set_float_exception_flags(0, &env->active_fpu.fp_status);
2439: fst2 = float32_div(FLOAT_ONE32, fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2440: fsth2 = float32_div(FLOAT_ONE32, fdt0 >> 32, &env->active_fpu.fp_status);
1.1.1.6 root 2441: update_fcr31();
1.1.1.7 root 2442: return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6 root 2443: }
2444:
1.1.1.8 ! root 2445: uint64_t helper_float_rsqrt1_d(uint64_t fdt0)
1.1.1.6 root 2446: {
1.1.1.7 root 2447: uint64_t fdt2;
2448:
2449: set_float_exception_flags(0, &env->active_fpu.fp_status);
2450: fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
2451: fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status);
1.1.1.6 root 2452: update_fcr31();
1.1.1.7 root 2453: return fdt2;
1.1.1.6 root 2454: }
1.1.1.7 root 2455:
1.1.1.8 ! root 2456: uint32_t helper_float_rsqrt1_s(uint32_t fst0)
1.1.1.6 root 2457: {
1.1.1.7 root 2458: uint32_t fst2;
2459:
2460: set_float_exception_flags(0, &env->active_fpu.fp_status);
2461: fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
2462: fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
1.1.1.6 root 2463: update_fcr31();
1.1.1.7 root 2464: return fst2;
1.1.1.6 root 2465: }
1.1.1.7 root 2466:
1.1.1.8 ! root 2467: uint64_t helper_float_rsqrt1_ps(uint64_t fdt0)
1.1.1.6 root 2468: {
1.1.1.7 root 2469: uint32_t fst2;
2470: uint32_t fsth2;
2471:
2472: set_float_exception_flags(0, &env->active_fpu.fp_status);
2473: fst2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2474: fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status);
2475: fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
2476: fsth2 = float32_div(FLOAT_ONE32, fsth2, &env->active_fpu.fp_status);
1.1.1.6 root 2477: update_fcr31();
1.1.1.7 root 2478: return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6 root 2479: }
2480:
1.1.1.8 ! root 2481: #define FLOAT_OP(name, p) void helper_float_##name##_##p(void)
1.1.1.7 root 2482:
1.1.1.6 root 2483: /* binary operations */
1.1.1.7 root 2484: #define FLOAT_BINOP(name) \
1.1.1.8 ! root 2485: uint64_t helper_float_ ## name ## _d(uint64_t fdt0, uint64_t fdt1) \
1.1.1.7 root 2486: { \
2487: uint64_t dt2; \
2488: \
2489: set_float_exception_flags(0, &env->active_fpu.fp_status); \
2490: dt2 = float64_ ## name (fdt0, fdt1, &env->active_fpu.fp_status); \
2491: update_fcr31(); \
2492: if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) \
2493: dt2 = FLOAT_QNAN64; \
2494: return dt2; \
2495: } \
2496: \
1.1.1.8 ! root 2497: uint32_t helper_float_ ## name ## _s(uint32_t fst0, uint32_t fst1) \
1.1.1.7 root 2498: { \
2499: uint32_t wt2; \
2500: \
2501: set_float_exception_flags(0, &env->active_fpu.fp_status); \
2502: wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \
1.1.1.6 root 2503: update_fcr31(); \
1.1.1.7 root 2504: if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) \
2505: wt2 = FLOAT_QNAN32; \
2506: return wt2; \
2507: } \
2508: \
1.1.1.8 ! root 2509: uint64_t helper_float_ ## name ## _ps(uint64_t fdt0, uint64_t fdt1) \
1.1.1.7 root 2510: { \
2511: uint32_t fst0 = fdt0 & 0XFFFFFFFF; \
2512: uint32_t fsth0 = fdt0 >> 32; \
2513: uint32_t fst1 = fdt1 & 0XFFFFFFFF; \
2514: uint32_t fsth1 = fdt1 >> 32; \
2515: uint32_t wt2; \
2516: uint32_t wth2; \
2517: \
2518: set_float_exception_flags(0, &env->active_fpu.fp_status); \
2519: wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \
2520: wth2 = float32_ ## name (fsth0, fsth1, &env->active_fpu.fp_status); \
1.1.1.6 root 2521: update_fcr31(); \
1.1.1.7 root 2522: if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) { \
2523: wt2 = FLOAT_QNAN32; \
2524: wth2 = FLOAT_QNAN32; \
2525: } \
2526: return ((uint64_t)wth2 << 32) | wt2; \
1.1.1.6 root 2527: }
1.1.1.7 root 2528:
1.1.1.6 root 2529: FLOAT_BINOP(add)
2530: FLOAT_BINOP(sub)
2531: FLOAT_BINOP(mul)
2532: FLOAT_BINOP(div)
2533: #undef FLOAT_BINOP
2534:
1.1.1.7 root 2535: /* ternary operations */
2536: #define FLOAT_TERNOP(name1, name2) \
1.1.1.8 ! root 2537: uint64_t helper_float_ ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1, \
1.1.1.7 root 2538: uint64_t fdt2) \
2539: { \
2540: fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status); \
2541: return float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status); \
2542: } \
2543: \
1.1.1.8 ! root 2544: uint32_t helper_float_ ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1, \
1.1.1.7 root 2545: uint32_t fst2) \
2546: { \
2547: fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \
2548: return float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \
2549: } \
2550: \
1.1.1.8 ! root 2551: uint64_t helper_float_ ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1, \
1.1.1.7 root 2552: uint64_t fdt2) \
2553: { \
2554: uint32_t fst0 = fdt0 & 0XFFFFFFFF; \
2555: uint32_t fsth0 = fdt0 >> 32; \
2556: uint32_t fst1 = fdt1 & 0XFFFFFFFF; \
2557: uint32_t fsth1 = fdt1 >> 32; \
2558: uint32_t fst2 = fdt2 & 0XFFFFFFFF; \
2559: uint32_t fsth2 = fdt2 >> 32; \
2560: \
2561: fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \
2562: fsth0 = float32_ ## name1 (fsth0, fsth1, &env->active_fpu.fp_status); \
2563: fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \
2564: fsth2 = float32_ ## name2 (fsth0, fsth2, &env->active_fpu.fp_status); \
2565: return ((uint64_t)fsth2 << 32) | fst2; \
2566: }
2567:
2568: FLOAT_TERNOP(mul, add)
2569: FLOAT_TERNOP(mul, sub)
2570: #undef FLOAT_TERNOP
2571:
2572: /* negated ternary operations */
2573: #define FLOAT_NTERNOP(name1, name2) \
1.1.1.8 ! root 2574: uint64_t helper_float_n ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1, \
1.1.1.7 root 2575: uint64_t fdt2) \
2576: { \
2577: fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status); \
2578: fdt2 = float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status); \
2579: return float64_chs(fdt2); \
2580: } \
2581: \
1.1.1.8 ! root 2582: uint32_t helper_float_n ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1, \
1.1.1.7 root 2583: uint32_t fst2) \
2584: { \
2585: fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \
2586: fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \
2587: return float32_chs(fst2); \
2588: } \
2589: \
1.1.1.8 ! root 2590: uint64_t helper_float_n ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1,\
1.1.1.7 root 2591: uint64_t fdt2) \
2592: { \
2593: uint32_t fst0 = fdt0 & 0XFFFFFFFF; \
2594: uint32_t fsth0 = fdt0 >> 32; \
2595: uint32_t fst1 = fdt1 & 0XFFFFFFFF; \
2596: uint32_t fsth1 = fdt1 >> 32; \
2597: uint32_t fst2 = fdt2 & 0XFFFFFFFF; \
2598: uint32_t fsth2 = fdt2 >> 32; \
2599: \
2600: fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \
2601: fsth0 = float32_ ## name1 (fsth0, fsth1, &env->active_fpu.fp_status); \
2602: fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \
2603: fsth2 = float32_ ## name2 (fsth0, fsth2, &env->active_fpu.fp_status); \
2604: fst2 = float32_chs(fst2); \
2605: fsth2 = float32_chs(fsth2); \
2606: return ((uint64_t)fsth2 << 32) | fst2; \
2607: }
2608:
2609: FLOAT_NTERNOP(mul, add)
2610: FLOAT_NTERNOP(mul, sub)
2611: #undef FLOAT_NTERNOP
2612:
1.1.1.6 root 2613: /* MIPS specific binary operations */
1.1.1.8 ! root 2614: uint64_t helper_float_recip2_d(uint64_t fdt0, uint64_t fdt2)
1.1.1.6 root 2615: {
1.1.1.7 root 2616: set_float_exception_flags(0, &env->active_fpu.fp_status);
2617: fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
2618: fdt2 = float64_chs(float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status));
1.1.1.6 root 2619: update_fcr31();
1.1.1.7 root 2620: return fdt2;
1.1.1.6 root 2621: }
1.1.1.7 root 2622:
1.1.1.8 ! root 2623: uint32_t helper_float_recip2_s(uint32_t fst0, uint32_t fst2)
1.1.1.6 root 2624: {
1.1.1.7 root 2625: set_float_exception_flags(0, &env->active_fpu.fp_status);
2626: fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
2627: fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status));
1.1.1.6 root 2628: update_fcr31();
1.1.1.7 root 2629: return fst2;
1.1.1.6 root 2630: }
1.1.1.7 root 2631:
1.1.1.8 ! root 2632: uint64_t helper_float_recip2_ps(uint64_t fdt0, uint64_t fdt2)
1.1.1.6 root 2633: {
1.1.1.7 root 2634: uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2635: uint32_t fsth0 = fdt0 >> 32;
2636: uint32_t fst2 = fdt2 & 0XFFFFFFFF;
2637: uint32_t fsth2 = fdt2 >> 32;
2638:
2639: set_float_exception_flags(0, &env->active_fpu.fp_status);
2640: fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
2641: fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
2642: fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status));
2643: fsth2 = float32_chs(float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status));
1.1.1.6 root 2644: update_fcr31();
1.1.1.7 root 2645: return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6 root 2646: }
2647:
1.1.1.8 ! root 2648: uint64_t helper_float_rsqrt2_d(uint64_t fdt0, uint64_t fdt2)
1.1.1.6 root 2649: {
1.1.1.7 root 2650: set_float_exception_flags(0, &env->active_fpu.fp_status);
2651: fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
2652: fdt2 = float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status);
2653: fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, &env->active_fpu.fp_status));
1.1.1.6 root 2654: update_fcr31();
1.1.1.7 root 2655: return fdt2;
1.1.1.6 root 2656: }
1.1.1.7 root 2657:
1.1.1.8 ! root 2658: uint32_t helper_float_rsqrt2_s(uint32_t fst0, uint32_t fst2)
1.1.1.6 root 2659: {
1.1.1.7 root 2660: set_float_exception_flags(0, &env->active_fpu.fp_status);
2661: fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
2662: fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status);
2663: fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
1.1.1.6 root 2664: update_fcr31();
1.1.1.7 root 2665: return fst2;
1.1.1.6 root 2666: }
1.1.1.7 root 2667:
1.1.1.8 ! root 2668: uint64_t helper_float_rsqrt2_ps(uint64_t fdt0, uint64_t fdt2)
1.1.1.6 root 2669: {
1.1.1.7 root 2670: uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2671: uint32_t fsth0 = fdt0 >> 32;
2672: uint32_t fst2 = fdt2 & 0XFFFFFFFF;
2673: uint32_t fsth2 = fdt2 >> 32;
2674:
2675: set_float_exception_flags(0, &env->active_fpu.fp_status);
2676: fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
2677: fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
2678: fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status);
2679: fsth2 = float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status);
2680: fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
2681: fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, &env->active_fpu.fp_status));
1.1.1.6 root 2682: update_fcr31();
1.1.1.7 root 2683: return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6 root 2684: }
2685:
1.1.1.8 ! root 2686: uint64_t helper_float_addr_ps(uint64_t fdt0, uint64_t fdt1)
1.1.1.6 root 2687: {
1.1.1.7 root 2688: uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2689: uint32_t fsth0 = fdt0 >> 32;
2690: uint32_t fst1 = fdt1 & 0XFFFFFFFF;
2691: uint32_t fsth1 = fdt1 >> 32;
2692: uint32_t fst2;
2693: uint32_t fsth2;
2694:
2695: set_float_exception_flags(0, &env->active_fpu.fp_status);
2696: fst2 = float32_add (fst0, fsth0, &env->active_fpu.fp_status);
2697: fsth2 = float32_add (fst1, fsth1, &env->active_fpu.fp_status);
1.1.1.6 root 2698: update_fcr31();
1.1.1.7 root 2699: return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6 root 2700: }
2701:
1.1.1.8 ! root 2702: uint64_t helper_float_mulr_ps(uint64_t fdt0, uint64_t fdt1)
1.1.1.6 root 2703: {
1.1.1.7 root 2704: uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2705: uint32_t fsth0 = fdt0 >> 32;
2706: uint32_t fst1 = fdt1 & 0XFFFFFFFF;
2707: uint32_t fsth1 = fdt1 >> 32;
2708: uint32_t fst2;
2709: uint32_t fsth2;
2710:
2711: set_float_exception_flags(0, &env->active_fpu.fp_status);
2712: fst2 = float32_mul (fst0, fsth0, &env->active_fpu.fp_status);
2713: fsth2 = float32_mul (fst1, fsth1, &env->active_fpu.fp_status);
1.1.1.6 root 2714: update_fcr31();
1.1.1.7 root 2715: return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6 root 2716: }
2717:
2718: /* compare operations */
1.1.1.7 root 2719: #define FOP_COND_D(op, cond) \
1.1.1.8 ! root 2720: void helper_cmp_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
1.1.1.7 root 2721: { \
2722: int c = cond; \
2723: update_fcr31(); \
2724: if (c) \
2725: SET_FP_COND(cc, env->active_fpu); \
2726: else \
2727: CLEAR_FP_COND(cc, env->active_fpu); \
2728: } \
1.1.1.8 ! root 2729: void helper_cmpabs_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
1.1.1.7 root 2730: { \
2731: int c; \
2732: fdt0 = float64_abs(fdt0); \
2733: fdt1 = float64_abs(fdt1); \
2734: c = cond; \
2735: update_fcr31(); \
2736: if (c) \
2737: SET_FP_COND(cc, env->active_fpu); \
2738: else \
2739: CLEAR_FP_COND(cc, env->active_fpu); \
1.1.1.6 root 2740: }
2741:
1.1.1.7 root 2742: static int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
1.1.1.6 root 2743: {
2744: if (float64_is_signaling_nan(a) ||
2745: float64_is_signaling_nan(b) ||
2746: (sig && (float64_is_nan(a) || float64_is_nan(b)))) {
2747: float_raise(float_flag_invalid, status);
2748: return 1;
2749: } else if (float64_is_nan(a) || float64_is_nan(b)) {
2750: return 1;
2751: } else {
2752: return 0;
2753: }
2754: }
2755:
2756: /* NOTE: the comma operator will make "cond" to eval to false,
2757: * but float*_is_unordered() is still called. */
1.1.1.7 root 2758: FOP_COND_D(f, (float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status), 0))
2759: FOP_COND_D(un, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status))
2760: FOP_COND_D(eq, !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
2761: FOP_COND_D(ueq, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
2762: FOP_COND_D(olt, !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
2763: FOP_COND_D(ult, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
2764: FOP_COND_D(ole, !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
2765: FOP_COND_D(ule, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
1.1.1.6 root 2766: /* NOTE: the comma operator will make "cond" to eval to false,
2767: * but float*_is_unordered() is still called. */
1.1.1.7 root 2768: FOP_COND_D(sf, (float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status), 0))
2769: FOP_COND_D(ngle,float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status))
2770: FOP_COND_D(seq, !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
2771: FOP_COND_D(ngl, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
2772: FOP_COND_D(lt, !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
2773: FOP_COND_D(nge, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
2774: FOP_COND_D(le, !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
2775: FOP_COND_D(ngt, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
2776:
2777: #define FOP_COND_S(op, cond) \
1.1.1.8 ! root 2778: void helper_cmp_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
1.1.1.7 root 2779: { \
2780: int c = cond; \
2781: update_fcr31(); \
2782: if (c) \
2783: SET_FP_COND(cc, env->active_fpu); \
2784: else \
2785: CLEAR_FP_COND(cc, env->active_fpu); \
2786: } \
1.1.1.8 ! root 2787: void helper_cmpabs_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
1.1.1.7 root 2788: { \
2789: int c; \
2790: fst0 = float32_abs(fst0); \
2791: fst1 = float32_abs(fst1); \
2792: c = cond; \
2793: update_fcr31(); \
2794: if (c) \
2795: SET_FP_COND(cc, env->active_fpu); \
2796: else \
2797: CLEAR_FP_COND(cc, env->active_fpu); \
1.1.1.6 root 2798: }
2799:
1.1.1.7 root 2800: static flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
1.1.1.6 root 2801: {
2802: if (float32_is_signaling_nan(a) ||
2803: float32_is_signaling_nan(b) ||
2804: (sig && (float32_is_nan(a) || float32_is_nan(b)))) {
2805: float_raise(float_flag_invalid, status);
2806: return 1;
2807: } else if (float32_is_nan(a) || float32_is_nan(b)) {
2808: return 1;
2809: } else {
2810: return 0;
2811: }
2812: }
2813:
2814: /* NOTE: the comma operator will make "cond" to eval to false,
2815: * but float*_is_unordered() is still called. */
1.1.1.7 root 2816: FOP_COND_S(f, (float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status), 0))
2817: FOP_COND_S(un, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status))
2818: FOP_COND_S(eq, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status))
2819: FOP_COND_S(ueq, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
2820: FOP_COND_S(olt, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
2821: FOP_COND_S(ult, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
2822: FOP_COND_S(ole, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
2823: FOP_COND_S(ule, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status))
1.1.1.6 root 2824: /* NOTE: the comma operator will make "cond" to eval to false,
2825: * but float*_is_unordered() is still called. */
1.1.1.7 root 2826: FOP_COND_S(sf, (float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status), 0))
2827: FOP_COND_S(ngle,float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status))
2828: FOP_COND_S(seq, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status))
2829: FOP_COND_S(ngl, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
2830: FOP_COND_S(lt, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
2831: FOP_COND_S(nge, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
2832: FOP_COND_S(le, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
2833: FOP_COND_S(ngt, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status))
2834:
2835: #define FOP_COND_PS(op, condl, condh) \
1.1.1.8 ! root 2836: void helper_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
1.1.1.7 root 2837: { \
2838: uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF); \
2839: uint32_t fsth0 = float32_abs(fdt0 >> 32); \
2840: uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF); \
2841: uint32_t fsth1 = float32_abs(fdt1 >> 32); \
2842: int cl = condl; \
2843: int ch = condh; \
2844: \
2845: update_fcr31(); \
2846: if (cl) \
2847: SET_FP_COND(cc, env->active_fpu); \
2848: else \
2849: CLEAR_FP_COND(cc, env->active_fpu); \
2850: if (ch) \
2851: SET_FP_COND(cc + 1, env->active_fpu); \
2852: else \
2853: CLEAR_FP_COND(cc + 1, env->active_fpu); \
2854: } \
1.1.1.8 ! root 2855: void helper_cmpabs_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
1.1.1.7 root 2856: { \
2857: uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF); \
2858: uint32_t fsth0 = float32_abs(fdt0 >> 32); \
2859: uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF); \
2860: uint32_t fsth1 = float32_abs(fdt1 >> 32); \
2861: int cl = condl; \
2862: int ch = condh; \
2863: \
2864: update_fcr31(); \
2865: if (cl) \
2866: SET_FP_COND(cc, env->active_fpu); \
2867: else \
2868: CLEAR_FP_COND(cc, env->active_fpu); \
2869: if (ch) \
2870: SET_FP_COND(cc + 1, env->active_fpu); \
2871: else \
2872: CLEAR_FP_COND(cc + 1, env->active_fpu); \
1.1.1.6 root 2873: }
2874:
2875: /* NOTE: the comma operator will make "cond" to eval to false,
2876: * but float*_is_unordered() is still called. */
1.1.1.7 root 2877: FOP_COND_PS(f, (float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status), 0),
2878: (float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status), 0))
2879: FOP_COND_PS(un, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status),
2880: float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status))
2881: FOP_COND_PS(eq, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status),
2882: !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
2883: FOP_COND_PS(ueq, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
2884: float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
2885: FOP_COND_PS(olt, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
2886: !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
2887: FOP_COND_PS(ult, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
2888: float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
2889: FOP_COND_PS(ole, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status),
2890: !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
2891: FOP_COND_PS(ule, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status),
2892: float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
1.1.1.6 root 2893: /* NOTE: the comma operator will make "cond" to eval to false,
2894: * but float*_is_unordered() is still called. */
1.1.1.7 root 2895: FOP_COND_PS(sf, (float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status), 0),
2896: (float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status), 0))
2897: FOP_COND_PS(ngle,float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status),
2898: float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status))
2899: FOP_COND_PS(seq, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status),
2900: !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
2901: FOP_COND_PS(ngl, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
2902: float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
2903: FOP_COND_PS(lt, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
2904: !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
2905: FOP_COND_PS(nge, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
2906: float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
2907: FOP_COND_PS(le, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status),
2908: !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
2909: FOP_COND_PS(ngt, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status),
2910: float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.