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