Statistics
| Branch: | Revision:

root / target-mips / op_helper.c @ f1ff0e89

History | View | Annotate | Download (102.8 kB)

1 6af0bf9c bellard
/*
2 6af0bf9c bellard
 *  MIPS emulation helpers for qemu.
3 5fafdf24 ths
 *
4 6af0bf9c bellard
 *  Copyright (c) 2004-2005 Jocelyn Mayer
5 6af0bf9c bellard
 *
6 6af0bf9c bellard
 * This library is free software; you can redistribute it and/or
7 6af0bf9c bellard
 * modify it under the terms of the GNU Lesser General Public
8 6af0bf9c bellard
 * License as published by the Free Software Foundation; either
9 6af0bf9c bellard
 * version 2 of the License, or (at your option) any later version.
10 6af0bf9c bellard
 *
11 6af0bf9c bellard
 * This library is distributed in the hope that it will be useful,
12 6af0bf9c bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 6af0bf9c bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 6af0bf9c bellard
 * Lesser General Public License for more details.
15 6af0bf9c bellard
 *
16 6af0bf9c bellard
 * You should have received a copy of the GNU Lesser General Public
17 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 6af0bf9c bellard
 */
19 2d0e944d ths
#include <stdlib.h>
20 3e457172 Blue Swirl
#include "cpu.h"
21 1de7afc9 Paolo Bonzini
#include "qemu/host-utils.h"
22 05f778c8 ths
23 a7812ae4 pbrook
#include "helper.h"
24 83dae095 Paolo Bonzini
25 3e457172 Blue Swirl
#if !defined(CONFIG_USER_ONLY)
26 022c62cb Paolo Bonzini
#include "exec/softmmu_exec.h"
27 3e457172 Blue Swirl
#endif /* !defined(CONFIG_USER_ONLY) */
28 3e457172 Blue Swirl
29 83dae095 Paolo Bonzini
#ifndef CONFIG_USER_ONLY
30 7db13fae Andreas Färber
static inline void cpu_mips_tlb_flush (CPUMIPSState *env, int flush_global);
31 83dae095 Paolo Bonzini
#endif
32 83dae095 Paolo Bonzini
33 6af0bf9c bellard
/*****************************************************************************/
34 6af0bf9c bellard
/* Exceptions processing helpers */
35 6af0bf9c bellard
36 5f7319cd Aurelien Jarno
static inline void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env,
37 5f7319cd Aurelien Jarno
                                                        uint32_t exception,
38 5f7319cd Aurelien Jarno
                                                        int error_code,
39 5f7319cd Aurelien Jarno
                                                        uintptr_t pc)
40 6af0bf9c bellard
{
41 0f0b9398 陳韋任 (Wei-Ren Chen)
    if (exception < EXCP_SC) {
42 93fcfe39 aliguori
        qemu_log("%s: %d %d\n", __func__, exception, error_code);
43 0f0b9398 陳韋任 (Wei-Ren Chen)
    }
44 6af0bf9c bellard
    env->exception_index = exception;
45 6af0bf9c bellard
    env->error_code = error_code;
46 5f7319cd Aurelien Jarno
47 5f7319cd Aurelien Jarno
    if (pc) {
48 5f7319cd Aurelien Jarno
        /* now we have a real cpu fault */
49 a8a826a3 Blue Swirl
        cpu_restore_state(env, pc);
50 5f7319cd Aurelien Jarno
    }
51 5f7319cd Aurelien Jarno
52 1162c041 Blue Swirl
    cpu_loop_exit(env);
53 6af0bf9c bellard
}
54 6af0bf9c bellard
55 5f7319cd Aurelien Jarno
static inline void QEMU_NORETURN do_raise_exception(CPUMIPSState *env,
56 5f7319cd Aurelien Jarno
                                                    uint32_t exception,
57 5f7319cd Aurelien Jarno
                                                    uintptr_t pc)
58 6af0bf9c bellard
{
59 5f7319cd Aurelien Jarno
    do_raise_exception_err(env, exception, 0, pc);
60 6af0bf9c bellard
}
61 6af0bf9c bellard
62 5f7319cd Aurelien Jarno
void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception,
63 5f7319cd Aurelien Jarno
                                int error_code)
64 4ad40f36 bellard
{
65 5f7319cd Aurelien Jarno
    do_raise_exception_err(env, exception, error_code, 0);
66 5f7319cd Aurelien Jarno
}
67 20503968 Blue Swirl
68 5f7319cd Aurelien Jarno
void helper_raise_exception(CPUMIPSState *env, uint32_t exception)
69 5f7319cd Aurelien Jarno
{
70 5f7319cd Aurelien Jarno
    do_raise_exception(env, exception, 0);
71 4ad40f36 bellard
}
72 4ad40f36 bellard
73 0ae43045 Aurelien Jarno
#if defined(CONFIG_USER_ONLY)
74 0ae43045 Aurelien Jarno
#define HELPER_LD(name, insn, type)                                     \
75 895c2d04 Blue Swirl
static inline type do_##name(CPUMIPSState *env, target_ulong addr,      \
76 895c2d04 Blue Swirl
                             int mem_idx)                               \
77 0ae43045 Aurelien Jarno
{                                                                       \
78 0ae43045 Aurelien Jarno
    return (type) insn##_raw(addr);                                     \
79 0ae43045 Aurelien Jarno
}
80 0ae43045 Aurelien Jarno
#else
81 0ae43045 Aurelien Jarno
#define HELPER_LD(name, insn, type)                                     \
82 895c2d04 Blue Swirl
static inline type do_##name(CPUMIPSState *env, target_ulong addr,      \
83 895c2d04 Blue Swirl
                             int mem_idx)                               \
84 0ae43045 Aurelien Jarno
{                                                                       \
85 0ae43045 Aurelien Jarno
    switch (mem_idx)                                                    \
86 0ae43045 Aurelien Jarno
    {                                                                   \
87 895c2d04 Blue Swirl
    case 0: return (type) cpu_##insn##_kernel(env, addr); break;        \
88 895c2d04 Blue Swirl
    case 1: return (type) cpu_##insn##_super(env, addr); break;         \
89 0ae43045 Aurelien Jarno
    default:                                                            \
90 895c2d04 Blue Swirl
    case 2: return (type) cpu_##insn##_user(env, addr); break;          \
91 0ae43045 Aurelien Jarno
    }                                                                   \
92 0ae43045 Aurelien Jarno
}
93 0ae43045 Aurelien Jarno
#endif
94 0ae43045 Aurelien Jarno
HELPER_LD(lbu, ldub, uint8_t)
95 0ae43045 Aurelien Jarno
HELPER_LD(lw, ldl, int32_t)
96 0ae43045 Aurelien Jarno
#ifdef TARGET_MIPS64
97 0ae43045 Aurelien Jarno
HELPER_LD(ld, ldq, int64_t)
98 0ae43045 Aurelien Jarno
#endif
99 0ae43045 Aurelien Jarno
#undef HELPER_LD
100 0ae43045 Aurelien Jarno
101 0ae43045 Aurelien Jarno
#if defined(CONFIG_USER_ONLY)
102 0ae43045 Aurelien Jarno
#define HELPER_ST(name, insn, type)                                     \
103 895c2d04 Blue Swirl
static inline void do_##name(CPUMIPSState *env, target_ulong addr,      \
104 895c2d04 Blue Swirl
                             type val, int mem_idx)                     \
105 0ae43045 Aurelien Jarno
{                                                                       \
106 0ae43045 Aurelien Jarno
    insn##_raw(addr, val);                                              \
107 0ae43045 Aurelien Jarno
}
108 0ae43045 Aurelien Jarno
#else
109 0ae43045 Aurelien Jarno
#define HELPER_ST(name, insn, type)                                     \
110 895c2d04 Blue Swirl
static inline void do_##name(CPUMIPSState *env, target_ulong addr,      \
111 895c2d04 Blue Swirl
                             type val, int mem_idx)                     \
112 0ae43045 Aurelien Jarno
{                                                                       \
113 0ae43045 Aurelien Jarno
    switch (mem_idx)                                                    \
114 0ae43045 Aurelien Jarno
    {                                                                   \
115 895c2d04 Blue Swirl
    case 0: cpu_##insn##_kernel(env, addr, val); break;                 \
116 895c2d04 Blue Swirl
    case 1: cpu_##insn##_super(env, addr, val); break;                  \
117 0ae43045 Aurelien Jarno
    default:                                                            \
118 895c2d04 Blue Swirl
    case 2: cpu_##insn##_user(env, addr, val); break;                   \
119 0ae43045 Aurelien Jarno
    }                                                                   \
120 0ae43045 Aurelien Jarno
}
121 0ae43045 Aurelien Jarno
#endif
122 0ae43045 Aurelien Jarno
HELPER_ST(sb, stb, uint8_t)
123 0ae43045 Aurelien Jarno
HELPER_ST(sw, stl, uint32_t)
124 0ae43045 Aurelien Jarno
#ifdef TARGET_MIPS64
125 0ae43045 Aurelien Jarno
HELPER_ST(sd, stq, uint64_t)
126 0ae43045 Aurelien Jarno
#endif
127 0ae43045 Aurelien Jarno
#undef HELPER_ST
128 0ae43045 Aurelien Jarno
129 d9bea114 aurel32
target_ulong helper_clo (target_ulong arg1)
130 30898801 ths
{
131 d9bea114 aurel32
    return clo32(arg1);
132 30898801 ths
}
133 30898801 ths
134 d9bea114 aurel32
target_ulong helper_clz (target_ulong arg1)
135 30898801 ths
{
136 d9bea114 aurel32
    return clz32(arg1);
137 30898801 ths
}
138 30898801 ths
139 d26bc211 ths
#if defined(TARGET_MIPS64)
140 d9bea114 aurel32
target_ulong helper_dclo (target_ulong arg1)
141 05f778c8 ths
{
142 d9bea114 aurel32
    return clo64(arg1);
143 05f778c8 ths
}
144 05f778c8 ths
145 d9bea114 aurel32
target_ulong helper_dclz (target_ulong arg1)
146 05f778c8 ths
{
147 d9bea114 aurel32
    return clz64(arg1);
148 05f778c8 ths
}
149 d26bc211 ths
#endif /* TARGET_MIPS64 */
150 c570fd16 ths
151 6af0bf9c bellard
/* 64 bits arithmetic for 32 bits hosts */
152 895c2d04 Blue Swirl
static inline uint64_t get_HILO(CPUMIPSState *env)
153 6af0bf9c bellard
{
154 b5dc7732 ths
    return ((uint64_t)(env->active_tc.HI[0]) << 32) | (uint32_t)env->active_tc.LO[0];
155 6af0bf9c bellard
}
156 6af0bf9c bellard
157 895c2d04 Blue Swirl
static inline target_ulong set_HIT0_LO(CPUMIPSState *env, uint64_t HILO)
158 e9c71dd1 ths
{
159 6fc97faf Stefan Weil
    target_ulong tmp;
160 b5dc7732 ths
    env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
161 6fc97faf Stefan Weil
    tmp = env->active_tc.HI[0] = (int32_t)(HILO >> 32);
162 6fc97faf Stefan Weil
    return tmp;
163 e9c71dd1 ths
}
164 e9c71dd1 ths
165 895c2d04 Blue Swirl
static inline target_ulong set_HI_LOT0(CPUMIPSState *env, uint64_t HILO)
166 e9c71dd1 ths
{
167 6fc97faf Stefan Weil
    target_ulong tmp = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
168 b5dc7732 ths
    env->active_tc.HI[0] = (int32_t)(HILO >> 32);
169 6fc97faf Stefan Weil
    return tmp;
170 e9c71dd1 ths
}
171 e9c71dd1 ths
172 e9c71dd1 ths
/* Multiplication variants of the vr54xx. */
173 895c2d04 Blue Swirl
target_ulong helper_muls(CPUMIPSState *env, target_ulong arg1,
174 895c2d04 Blue Swirl
                         target_ulong arg2)
175 e9c71dd1 ths
{
176 895c2d04 Blue Swirl
    return set_HI_LOT0(env, 0 - ((int64_t)(int32_t)arg1 *
177 895c2d04 Blue Swirl
                                 (int64_t)(int32_t)arg2));
178 e9c71dd1 ths
}
179 e9c71dd1 ths
180 895c2d04 Blue Swirl
target_ulong helper_mulsu(CPUMIPSState *env, target_ulong arg1,
181 895c2d04 Blue Swirl
                          target_ulong arg2)
182 e9c71dd1 ths
{
183 895c2d04 Blue Swirl
    return set_HI_LOT0(env, 0 - (uint64_t)(uint32_t)arg1 *
184 895c2d04 Blue Swirl
                       (uint64_t)(uint32_t)arg2);
185 e9c71dd1 ths
}
186 e9c71dd1 ths
187 895c2d04 Blue Swirl
target_ulong helper_macc(CPUMIPSState *env, target_ulong arg1,
188 895c2d04 Blue Swirl
                         target_ulong arg2)
189 e9c71dd1 ths
{
190 895c2d04 Blue Swirl
    return set_HI_LOT0(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 *
191 895c2d04 Blue Swirl
                       (int64_t)(int32_t)arg2);
192 e9c71dd1 ths
}
193 e9c71dd1 ths
194 895c2d04 Blue Swirl
target_ulong helper_macchi(CPUMIPSState *env, target_ulong arg1,
195 895c2d04 Blue Swirl
                           target_ulong arg2)
196 e9c71dd1 ths
{
197 895c2d04 Blue Swirl
    return set_HIT0_LO(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 *
198 895c2d04 Blue Swirl
                       (int64_t)(int32_t)arg2);
199 e9c71dd1 ths
}
200 e9c71dd1 ths
201 895c2d04 Blue Swirl
target_ulong helper_maccu(CPUMIPSState *env, target_ulong arg1,
202 895c2d04 Blue Swirl
                          target_ulong arg2)
203 e9c71dd1 ths
{
204 895c2d04 Blue Swirl
    return set_HI_LOT0(env, (uint64_t)get_HILO(env) +
205 895c2d04 Blue Swirl
                       (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
206 e9c71dd1 ths
}
207 e9c71dd1 ths
208 895c2d04 Blue Swirl
target_ulong helper_macchiu(CPUMIPSState *env, target_ulong arg1,
209 895c2d04 Blue Swirl
                            target_ulong arg2)
210 e9c71dd1 ths
{
211 895c2d04 Blue Swirl
    return set_HIT0_LO(env, (uint64_t)get_HILO(env) +
212 895c2d04 Blue Swirl
                       (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
213 e9c71dd1 ths
}
214 e9c71dd1 ths
215 895c2d04 Blue Swirl
target_ulong helper_msac(CPUMIPSState *env, target_ulong arg1,
216 895c2d04 Blue Swirl
                         target_ulong arg2)
217 e9c71dd1 ths
{
218 895c2d04 Blue Swirl
    return set_HI_LOT0(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 *
219 895c2d04 Blue Swirl
                       (int64_t)(int32_t)arg2);
220 e9c71dd1 ths
}
221 e9c71dd1 ths
222 895c2d04 Blue Swirl
target_ulong helper_msachi(CPUMIPSState *env, target_ulong arg1,
223 895c2d04 Blue Swirl
                           target_ulong arg2)
224 e9c71dd1 ths
{
225 895c2d04 Blue Swirl
    return set_HIT0_LO(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 *
226 895c2d04 Blue Swirl
                       (int64_t)(int32_t)arg2);
227 e9c71dd1 ths
}
228 e9c71dd1 ths
229 895c2d04 Blue Swirl
target_ulong helper_msacu(CPUMIPSState *env, target_ulong arg1,
230 895c2d04 Blue Swirl
                          target_ulong arg2)
231 e9c71dd1 ths
{
232 895c2d04 Blue Swirl
    return set_HI_LOT0(env, (uint64_t)get_HILO(env) -
233 895c2d04 Blue Swirl
                       (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
234 e9c71dd1 ths
}
235 e9c71dd1 ths
236 895c2d04 Blue Swirl
target_ulong helper_msachiu(CPUMIPSState *env, target_ulong arg1,
237 895c2d04 Blue Swirl
                            target_ulong arg2)
238 e9c71dd1 ths
{
239 895c2d04 Blue Swirl
    return set_HIT0_LO(env, (uint64_t)get_HILO(env) -
240 895c2d04 Blue Swirl
                       (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
241 e9c71dd1 ths
}
242 e9c71dd1 ths
243 895c2d04 Blue Swirl
target_ulong helper_mulhi(CPUMIPSState *env, target_ulong arg1,
244 895c2d04 Blue Swirl
                          target_ulong arg2)
245 e9c71dd1 ths
{
246 895c2d04 Blue Swirl
    return set_HIT0_LO(env, (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2);
247 e9c71dd1 ths
}
248 e9c71dd1 ths
249 895c2d04 Blue Swirl
target_ulong helper_mulhiu(CPUMIPSState *env, target_ulong arg1,
250 895c2d04 Blue Swirl
                           target_ulong arg2)
251 e9c71dd1 ths
{
252 895c2d04 Blue Swirl
    return set_HIT0_LO(env, (uint64_t)(uint32_t)arg1 *
253 895c2d04 Blue Swirl
                       (uint64_t)(uint32_t)arg2);
254 e9c71dd1 ths
}
255 e9c71dd1 ths
256 895c2d04 Blue Swirl
target_ulong helper_mulshi(CPUMIPSState *env, target_ulong arg1,
257 895c2d04 Blue Swirl
                           target_ulong arg2)
258 e9c71dd1 ths
{
259 895c2d04 Blue Swirl
    return set_HIT0_LO(env, 0 - (int64_t)(int32_t)arg1 *
260 895c2d04 Blue Swirl
                       (int64_t)(int32_t)arg2);
261 e9c71dd1 ths
}
262 e9c71dd1 ths
263 895c2d04 Blue Swirl
target_ulong helper_mulshiu(CPUMIPSState *env, target_ulong arg1,
264 895c2d04 Blue Swirl
                            target_ulong arg2)
265 e9c71dd1 ths
{
266 895c2d04 Blue Swirl
    return set_HIT0_LO(env, 0 - (uint64_t)(uint32_t)arg1 *
267 895c2d04 Blue Swirl
                       (uint64_t)(uint32_t)arg2);
268 e9c71dd1 ths
}
269 6af0bf9c bellard
270 e7139c44 Aurelien Jarno
#ifndef CONFIG_USER_ONLY
271 c36bbb28 Aurelien Jarno
272 a8170e5e Avi Kivity
static inline hwaddr do_translate_address(CPUMIPSState *env,
273 895c2d04 Blue Swirl
                                                      target_ulong address,
274 895c2d04 Blue Swirl
                                                      int rw)
275 c36bbb28 Aurelien Jarno
{
276 a8170e5e Avi Kivity
    hwaddr lladdr;
277 c36bbb28 Aurelien Jarno
278 c36bbb28 Aurelien Jarno
    lladdr = cpu_mips_translate_address(env, address, rw);
279 c36bbb28 Aurelien Jarno
280 c36bbb28 Aurelien Jarno
    if (lladdr == -1LL) {
281 1162c041 Blue Swirl
        cpu_loop_exit(env);
282 c36bbb28 Aurelien Jarno
    } else {
283 c36bbb28 Aurelien Jarno
        return lladdr;
284 c36bbb28 Aurelien Jarno
    }
285 c36bbb28 Aurelien Jarno
}
286 c36bbb28 Aurelien Jarno
287 e7139c44 Aurelien Jarno
#define HELPER_LD_ATOMIC(name, insn)                                          \
288 895c2d04 Blue Swirl
target_ulong helper_##name(CPUMIPSState *env, target_ulong arg, int mem_idx)  \
289 e7139c44 Aurelien Jarno
{                                                                             \
290 895c2d04 Blue Swirl
    env->lladdr = do_translate_address(env, arg, 0);                          \
291 895c2d04 Blue Swirl
    env->llval = do_##insn(env, arg, mem_idx);                                \
292 e7139c44 Aurelien Jarno
    return env->llval;                                                        \
293 e7139c44 Aurelien Jarno
}
294 e7139c44 Aurelien Jarno
HELPER_LD_ATOMIC(ll, lw)
295 e7139c44 Aurelien Jarno
#ifdef TARGET_MIPS64
296 e7139c44 Aurelien Jarno
HELPER_LD_ATOMIC(lld, ld)
297 e7139c44 Aurelien Jarno
#endif
298 e7139c44 Aurelien Jarno
#undef HELPER_LD_ATOMIC
299 e7139c44 Aurelien Jarno
300 e7139c44 Aurelien Jarno
#define HELPER_ST_ATOMIC(name, ld_insn, st_insn, almask)                      \
301 895c2d04 Blue Swirl
target_ulong helper_##name(CPUMIPSState *env, target_ulong arg1,              \
302 895c2d04 Blue Swirl
                           target_ulong arg2, int mem_idx)                    \
303 e7139c44 Aurelien Jarno
{                                                                             \
304 e7139c44 Aurelien Jarno
    target_long tmp;                                                          \
305 e7139c44 Aurelien Jarno
                                                                              \
306 e7139c44 Aurelien Jarno
    if (arg2 & almask) {                                                      \
307 e7139c44 Aurelien Jarno
        env->CP0_BadVAddr = arg2;                                             \
308 895c2d04 Blue Swirl
        helper_raise_exception(env, EXCP_AdES);                               \
309 e7139c44 Aurelien Jarno
    }                                                                         \
310 895c2d04 Blue Swirl
    if (do_translate_address(env, arg2, 1) == env->lladdr) {                  \
311 895c2d04 Blue Swirl
        tmp = do_##ld_insn(env, arg2, mem_idx);                               \
312 e7139c44 Aurelien Jarno
        if (tmp == env->llval) {                                              \
313 895c2d04 Blue Swirl
            do_##st_insn(env, arg2, arg1, mem_idx);                           \
314 e7139c44 Aurelien Jarno
            return 1;                                                         \
315 e7139c44 Aurelien Jarno
        }                                                                     \
316 e7139c44 Aurelien Jarno
    }                                                                         \
317 e7139c44 Aurelien Jarno
    return 0;                                                                 \
318 e7139c44 Aurelien Jarno
}
319 e7139c44 Aurelien Jarno
HELPER_ST_ATOMIC(sc, lw, sw, 0x3)
320 e7139c44 Aurelien Jarno
#ifdef TARGET_MIPS64
321 e7139c44 Aurelien Jarno
HELPER_ST_ATOMIC(scd, ld, sd, 0x7)
322 e7139c44 Aurelien Jarno
#endif
323 e7139c44 Aurelien Jarno
#undef HELPER_ST_ATOMIC
324 e7139c44 Aurelien Jarno
#endif
325 e7139c44 Aurelien Jarno
326 c8c2227e ths
#ifdef TARGET_WORDS_BIGENDIAN
327 c8c2227e ths
#define GET_LMASK(v) ((v) & 3)
328 c8c2227e ths
#define GET_OFFSET(addr, offset) (addr + (offset))
329 c8c2227e ths
#else
330 c8c2227e ths
#define GET_LMASK(v) (((v) & 3) ^ 3)
331 c8c2227e ths
#define GET_OFFSET(addr, offset) (addr - (offset))
332 c8c2227e ths
#endif
333 c8c2227e ths
334 895c2d04 Blue Swirl
void helper_swl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
335 895c2d04 Blue Swirl
                int mem_idx)
336 c8c2227e ths
{
337 895c2d04 Blue Swirl
    do_sb(env, arg2, (uint8_t)(arg1 >> 24), mem_idx);
338 c8c2227e ths
339 d9bea114 aurel32
    if (GET_LMASK(arg2) <= 2)
340 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 16), mem_idx);
341 c8c2227e ths
342 d9bea114 aurel32
    if (GET_LMASK(arg2) <= 1)
343 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 8), mem_idx);
344 c8c2227e ths
345 d9bea114 aurel32
    if (GET_LMASK(arg2) == 0)
346 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, 3), (uint8_t)arg1, mem_idx);
347 c8c2227e ths
}
348 c8c2227e ths
349 895c2d04 Blue Swirl
void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
350 895c2d04 Blue Swirl
                int mem_idx)
351 c8c2227e ths
{
352 895c2d04 Blue Swirl
    do_sb(env, arg2, (uint8_t)arg1, mem_idx);
353 c8c2227e ths
354 d9bea114 aurel32
    if (GET_LMASK(arg2) >= 1)
355 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx);
356 c8c2227e ths
357 d9bea114 aurel32
    if (GET_LMASK(arg2) >= 2)
358 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx);
359 c8c2227e ths
360 d9bea114 aurel32
    if (GET_LMASK(arg2) == 3)
361 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx);
362 c8c2227e ths
}
363 c8c2227e ths
364 c8c2227e ths
#if defined(TARGET_MIPS64)
365 c8c2227e ths
/* "half" load and stores.  We must do the memory access inline,
366 c8c2227e ths
   or fault handling won't work.  */
367 c8c2227e ths
368 c8c2227e ths
#ifdef TARGET_WORDS_BIGENDIAN
369 c8c2227e ths
#define GET_LMASK64(v) ((v) & 7)
370 c8c2227e ths
#else
371 c8c2227e ths
#define GET_LMASK64(v) (((v) & 7) ^ 7)
372 c8c2227e ths
#endif
373 c8c2227e ths
374 895c2d04 Blue Swirl
void helper_sdl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
375 895c2d04 Blue Swirl
                int mem_idx)
376 c8c2227e ths
{
377 895c2d04 Blue Swirl
    do_sb(env, arg2, (uint8_t)(arg1 >> 56), mem_idx);
378 c8c2227e ths
379 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 6)
380 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 48), mem_idx);
381 c8c2227e ths
382 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 5)
383 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 40), mem_idx);
384 c8c2227e ths
385 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 4)
386 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, 3), (uint8_t)(arg1 >> 32), mem_idx);
387 c8c2227e ths
388 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 3)
389 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, 4), (uint8_t)(arg1 >> 24), mem_idx);
390 c8c2227e ths
391 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 2)
392 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, 5), (uint8_t)(arg1 >> 16), mem_idx);
393 c8c2227e ths
394 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 1)
395 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, 6), (uint8_t)(arg1 >> 8), mem_idx);
396 c8c2227e ths
397 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 0)
398 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, 7), (uint8_t)arg1, mem_idx);
399 c8c2227e ths
}
400 c8c2227e ths
401 895c2d04 Blue Swirl
void helper_sdr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
402 895c2d04 Blue Swirl
                int mem_idx)
403 c8c2227e ths
{
404 895c2d04 Blue Swirl
    do_sb(env, arg2, (uint8_t)arg1, mem_idx);
405 c8c2227e ths
406 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 1)
407 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx);
408 c8c2227e ths
409 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 2)
410 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx);
411 c8c2227e ths
412 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 3)
413 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx);
414 c8c2227e ths
415 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 4)
416 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, -4), (uint8_t)(arg1 >> 32), mem_idx);
417 c8c2227e ths
418 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 5)
419 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, -5), (uint8_t)(arg1 >> 40), mem_idx);
420 c8c2227e ths
421 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 6)
422 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, -6), (uint8_t)(arg1 >> 48), mem_idx);
423 c8c2227e ths
424 d9bea114 aurel32
    if (GET_LMASK64(arg2) == 7)
425 895c2d04 Blue Swirl
        do_sb(env, GET_OFFSET(arg2, -7), (uint8_t)(arg1 >> 56), mem_idx);
426 c8c2227e ths
}
427 c8c2227e ths
#endif /* TARGET_MIPS64 */
428 c8c2227e ths
429 3c824109 Nathan Froyd
static const int multiple_regs[] = { 16, 17, 18, 19, 20, 21, 22, 23, 30 };
430 3c824109 Nathan Froyd
431 895c2d04 Blue Swirl
void helper_lwm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
432 895c2d04 Blue Swirl
                uint32_t mem_idx)
433 3c824109 Nathan Froyd
{
434 3c824109 Nathan Froyd
    target_ulong base_reglist = reglist & 0xf;
435 3c824109 Nathan Froyd
    target_ulong do_r31 = reglist & 0x10;
436 3c824109 Nathan Froyd
437 3c824109 Nathan Froyd
    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
438 3c824109 Nathan Froyd
        target_ulong i;
439 3c824109 Nathan Froyd
440 3c824109 Nathan Froyd
        for (i = 0; i < base_reglist; i++) {
441 18bba4dc Aurelien Jarno
            env->active_tc.gpr[multiple_regs[i]] =
442 18bba4dc Aurelien Jarno
                (target_long)do_lw(env, addr, mem_idx);
443 3c824109 Nathan Froyd
            addr += 4;
444 3c824109 Nathan Froyd
        }
445 3c824109 Nathan Froyd
    }
446 3c824109 Nathan Froyd
447 3c824109 Nathan Froyd
    if (do_r31) {
448 18bba4dc Aurelien Jarno
        env->active_tc.gpr[31] = (target_long)do_lw(env, addr, mem_idx);
449 3c824109 Nathan Froyd
    }
450 3c824109 Nathan Froyd
}
451 3c824109 Nathan Froyd
452 895c2d04 Blue Swirl
void helper_swm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
453 895c2d04 Blue Swirl
                uint32_t mem_idx)
454 3c824109 Nathan Froyd
{
455 3c824109 Nathan Froyd
    target_ulong base_reglist = reglist & 0xf;
456 3c824109 Nathan Froyd
    target_ulong do_r31 = reglist & 0x10;
457 3c824109 Nathan Froyd
458 3c824109 Nathan Froyd
    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
459 3c824109 Nathan Froyd
        target_ulong i;
460 3c824109 Nathan Froyd
461 3c824109 Nathan Froyd
        for (i = 0; i < base_reglist; i++) {
462 18bba4dc Aurelien Jarno
            do_sw(env, addr, env->active_tc.gpr[multiple_regs[i]], mem_idx);
463 3c824109 Nathan Froyd
            addr += 4;
464 3c824109 Nathan Froyd
        }
465 3c824109 Nathan Froyd
    }
466 3c824109 Nathan Froyd
467 3c824109 Nathan Froyd
    if (do_r31) {
468 18bba4dc Aurelien Jarno
        do_sw(env, addr, env->active_tc.gpr[31], mem_idx);
469 3c824109 Nathan Froyd
    }
470 3c824109 Nathan Froyd
}
471 3c824109 Nathan Froyd
472 3c824109 Nathan Froyd
#if defined(TARGET_MIPS64)
473 895c2d04 Blue Swirl
void helper_ldm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
474 895c2d04 Blue Swirl
                uint32_t mem_idx)
475 3c824109 Nathan Froyd
{
476 3c824109 Nathan Froyd
    target_ulong base_reglist = reglist & 0xf;
477 3c824109 Nathan Froyd
    target_ulong do_r31 = reglist & 0x10;
478 3c824109 Nathan Froyd
479 3c824109 Nathan Froyd
    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
480 3c824109 Nathan Froyd
        target_ulong i;
481 3c824109 Nathan Froyd
482 3c824109 Nathan Froyd
        for (i = 0; i < base_reglist; i++) {
483 18bba4dc Aurelien Jarno
            env->active_tc.gpr[multiple_regs[i]] = do_ld(env, addr, mem_idx);
484 3c824109 Nathan Froyd
            addr += 8;
485 3c824109 Nathan Froyd
        }
486 3c824109 Nathan Froyd
    }
487 3c824109 Nathan Froyd
488 3c824109 Nathan Froyd
    if (do_r31) {
489 18bba4dc Aurelien Jarno
        env->active_tc.gpr[31] = do_ld(env, addr, mem_idx);
490 3c824109 Nathan Froyd
    }
491 3c824109 Nathan Froyd
}
492 3c824109 Nathan Froyd
493 895c2d04 Blue Swirl
void helper_sdm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
494 895c2d04 Blue Swirl
                uint32_t mem_idx)
495 3c824109 Nathan Froyd
{
496 3c824109 Nathan Froyd
    target_ulong base_reglist = reglist & 0xf;
497 3c824109 Nathan Froyd
    target_ulong do_r31 = reglist & 0x10;
498 3c824109 Nathan Froyd
499 3c824109 Nathan Froyd
    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
500 3c824109 Nathan Froyd
        target_ulong i;
501 3c824109 Nathan Froyd
502 3c824109 Nathan Froyd
        for (i = 0; i < base_reglist; i++) {
503 18bba4dc Aurelien Jarno
            do_sd(env, addr, env->active_tc.gpr[multiple_regs[i]], mem_idx);
504 3c824109 Nathan Froyd
            addr += 8;
505 3c824109 Nathan Froyd
        }
506 3c824109 Nathan Froyd
    }
507 3c824109 Nathan Froyd
508 3c824109 Nathan Froyd
    if (do_r31) {
509 18bba4dc Aurelien Jarno
        do_sd(env, addr, env->active_tc.gpr[31], mem_idx);
510 3c824109 Nathan Froyd
    }
511 3c824109 Nathan Froyd
}
512 3c824109 Nathan Froyd
#endif
513 3c824109 Nathan Froyd
514 0eaef5aa ths
#ifndef CONFIG_USER_ONLY
515 f249412c Edgar E. Iglesias
/* SMP helpers.  */
516 b35d77d7 Andreas Färber
static bool mips_vpe_is_wfi(MIPSCPU *c)
517 f249412c Edgar E. Iglesias
{
518 259186a7 Andreas Färber
    CPUState *cpu = CPU(c);
519 b35d77d7 Andreas Färber
    CPUMIPSState *env = &c->env;
520 b35d77d7 Andreas Färber
521 f249412c Edgar E. Iglesias
    /* If the VPE is halted but otherwise active, it means it's waiting for
522 f249412c Edgar E. Iglesias
       an interrupt.  */
523 259186a7 Andreas Färber
    return cpu->halted && mips_vpe_active(env);
524 f249412c Edgar E. Iglesias
}
525 f249412c Edgar E. Iglesias
526 c3affe56 Andreas Färber
static inline void mips_vpe_wake(MIPSCPU *c)
527 f249412c Edgar E. Iglesias
{
528 f249412c Edgar E. Iglesias
    /* Dont set ->halted = 0 directly, let it be done via cpu_has_work
529 f249412c Edgar E. Iglesias
       because there might be other conditions that state that c should
530 f249412c Edgar E. Iglesias
       be sleeping.  */
531 c3affe56 Andreas Färber
    cpu_interrupt(CPU(c), CPU_INTERRUPT_WAKE);
532 f249412c Edgar E. Iglesias
}
533 f249412c Edgar E. Iglesias
534 6f4d6b09 Andreas Färber
static inline void mips_vpe_sleep(MIPSCPU *cpu)
535 f249412c Edgar E. Iglesias
{
536 259186a7 Andreas Färber
    CPUState *cs = CPU(cpu);
537 6f4d6b09 Andreas Färber
538 f249412c Edgar E. Iglesias
    /* The VPE was shut off, really go to bed.
539 f249412c Edgar E. Iglesias
       Reset any old _WAKE requests.  */
540 259186a7 Andreas Färber
    cs->halted = 1;
541 d8ed887b Andreas Färber
    cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
542 f249412c Edgar E. Iglesias
}
543 f249412c Edgar E. Iglesias
544 135dd63a Andreas Färber
static inline void mips_tc_wake(MIPSCPU *cpu, int tc)
545 f249412c Edgar E. Iglesias
{
546 135dd63a Andreas Färber
    CPUMIPSState *c = &cpu->env;
547 135dd63a Andreas Färber
548 f249412c Edgar E. Iglesias
    /* FIXME: TC reschedule.  */
549 b35d77d7 Andreas Färber
    if (mips_vpe_active(c) && !mips_vpe_is_wfi(cpu)) {
550 c3affe56 Andreas Färber
        mips_vpe_wake(cpu);
551 f249412c Edgar E. Iglesias
    }
552 f249412c Edgar E. Iglesias
}
553 f249412c Edgar E. Iglesias
554 c6679e90 Andreas Färber
static inline void mips_tc_sleep(MIPSCPU *cpu, int tc)
555 f249412c Edgar E. Iglesias
{
556 c6679e90 Andreas Färber
    CPUMIPSState *c = &cpu->env;
557 c6679e90 Andreas Färber
558 f249412c Edgar E. Iglesias
    /* FIXME: TC reschedule.  */
559 f249412c Edgar E. Iglesias
    if (!mips_vpe_active(c)) {
560 6f4d6b09 Andreas Färber
        mips_vpe_sleep(cpu);
561 f249412c Edgar E. Iglesias
    }
562 f249412c Edgar E. Iglesias
}
563 f249412c Edgar E. Iglesias
564 66afd1ad Andreas Färber
/**
565 66afd1ad Andreas Färber
 * mips_cpu_map_tc:
566 66afd1ad Andreas Färber
 * @env: CPU from which mapping is performed.
567 66afd1ad Andreas Färber
 * @tc: Should point to an int with the value of the global TC index.
568 66afd1ad Andreas Färber
 *
569 66afd1ad Andreas Färber
 * This function will transform @tc into a local index within the
570 66afd1ad Andreas Färber
 * returned #CPUMIPSState.
571 66afd1ad Andreas Färber
 */
572 66afd1ad Andreas Färber
/* FIXME: This code assumes that all VPEs have the same number of TCs,
573 b93bbdcd Edgar E. Iglesias
          which depends on runtime setup. Can probably be fixed by
574 7db13fae Andreas Färber
          walking the list of CPUMIPSStates.  */
575 895c2d04 Blue Swirl
static CPUMIPSState *mips_cpu_map_tc(CPUMIPSState *env, int *tc)
576 b93bbdcd Edgar E. Iglesias
{
577 38d8f5c8 Andreas Färber
    MIPSCPU *cpu;
578 ce3960eb Andreas Färber
    CPUState *cs;
579 38d8f5c8 Andreas Färber
    CPUState *other_cs;
580 ce3960eb Andreas Färber
    int vpe_idx;
581 b93bbdcd Edgar E. Iglesias
    int tc_idx = *tc;
582 b93bbdcd Edgar E. Iglesias
583 b93bbdcd Edgar E. Iglesias
    if (!(env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))) {
584 b93bbdcd Edgar E. Iglesias
        /* Not allowed to address other CPUs.  */
585 b93bbdcd Edgar E. Iglesias
        *tc = env->current_tc;
586 b93bbdcd Edgar E. Iglesias
        return env;
587 b93bbdcd Edgar E. Iglesias
    }
588 b93bbdcd Edgar E. Iglesias
589 ce3960eb Andreas Färber
    cs = CPU(mips_env_get_cpu(env));
590 ce3960eb Andreas Färber
    vpe_idx = tc_idx / cs->nr_threads;
591 ce3960eb Andreas Färber
    *tc = tc_idx % cs->nr_threads;
592 38d8f5c8 Andreas Färber
    other_cs = qemu_get_cpu(vpe_idx);
593 38d8f5c8 Andreas Färber
    if (other_cs == NULL) {
594 38d8f5c8 Andreas Färber
        return env;
595 38d8f5c8 Andreas Färber
    }
596 38d8f5c8 Andreas Färber
    cpu = MIPS_CPU(other_cs);
597 38d8f5c8 Andreas Färber
    return &cpu->env;
598 b93bbdcd Edgar E. Iglesias
}
599 b93bbdcd Edgar E. Iglesias
600 fe8dca8c Edgar E. Iglesias
/* The per VPE CP0_Status register shares some fields with the per TC
601 fe8dca8c Edgar E. Iglesias
   CP0_TCStatus registers. These fields are wired to the same registers,
602 fe8dca8c Edgar E. Iglesias
   so changes to either of them should be reflected on both registers.
603 fe8dca8c Edgar E. Iglesias

604 fe8dca8c Edgar E. Iglesias
   Also, EntryHi shares the bottom 8 bit ASID with TCStauts.
605 fe8dca8c Edgar E. Iglesias

606 fe8dca8c Edgar E. Iglesias
   These helper call synchronizes the regs for a given cpu.  */
607 fe8dca8c Edgar E. Iglesias
608 fe8dca8c Edgar E. Iglesias
/* Called for updates to CP0_Status.  */
609 895c2d04 Blue Swirl
static void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc)
610 fe8dca8c Edgar E. Iglesias
{
611 fe8dca8c Edgar E. Iglesias
    int32_t tcstatus, *tcst;
612 fe8dca8c Edgar E. Iglesias
    uint32_t v = cpu->CP0_Status;
613 fe8dca8c Edgar E. Iglesias
    uint32_t cu, mx, asid, ksu;
614 fe8dca8c Edgar E. Iglesias
    uint32_t mask = ((1 << CP0TCSt_TCU3)
615 fe8dca8c Edgar E. Iglesias
                       | (1 << CP0TCSt_TCU2)
616 fe8dca8c Edgar E. Iglesias
                       | (1 << CP0TCSt_TCU1)
617 fe8dca8c Edgar E. Iglesias
                       | (1 << CP0TCSt_TCU0)
618 fe8dca8c Edgar E. Iglesias
                       | (1 << CP0TCSt_TMX)
619 fe8dca8c Edgar E. Iglesias
                       | (3 << CP0TCSt_TKSU)
620 fe8dca8c Edgar E. Iglesias
                       | (0xff << CP0TCSt_TASID));
621 fe8dca8c Edgar E. Iglesias
622 fe8dca8c Edgar E. Iglesias
    cu = (v >> CP0St_CU0) & 0xf;
623 fe8dca8c Edgar E. Iglesias
    mx = (v >> CP0St_MX) & 0x1;
624 fe8dca8c Edgar E. Iglesias
    ksu = (v >> CP0St_KSU) & 0x3;
625 fe8dca8c Edgar E. Iglesias
    asid = env->CP0_EntryHi & 0xff;
626 fe8dca8c Edgar E. Iglesias
627 fe8dca8c Edgar E. Iglesias
    tcstatus = cu << CP0TCSt_TCU0;
628 fe8dca8c Edgar E. Iglesias
    tcstatus |= mx << CP0TCSt_TMX;
629 fe8dca8c Edgar E. Iglesias
    tcstatus |= ksu << CP0TCSt_TKSU;
630 fe8dca8c Edgar E. Iglesias
    tcstatus |= asid;
631 fe8dca8c Edgar E. Iglesias
632 fe8dca8c Edgar E. Iglesias
    if (tc == cpu->current_tc) {
633 fe8dca8c Edgar E. Iglesias
        tcst = &cpu->active_tc.CP0_TCStatus;
634 fe8dca8c Edgar E. Iglesias
    } else {
635 fe8dca8c Edgar E. Iglesias
        tcst = &cpu->tcs[tc].CP0_TCStatus;
636 fe8dca8c Edgar E. Iglesias
    }
637 fe8dca8c Edgar E. Iglesias
638 fe8dca8c Edgar E. Iglesias
    *tcst &= ~mask;
639 fe8dca8c Edgar E. Iglesias
    *tcst |= tcstatus;
640 fe8dca8c Edgar E. Iglesias
    compute_hflags(cpu);
641 fe8dca8c Edgar E. Iglesias
}
642 fe8dca8c Edgar E. Iglesias
643 fe8dca8c Edgar E. Iglesias
/* Called for updates to CP0_TCStatus.  */
644 895c2d04 Blue Swirl
static void sync_c0_tcstatus(CPUMIPSState *cpu, int tc,
645 895c2d04 Blue Swirl
                             target_ulong v)
646 fe8dca8c Edgar E. Iglesias
{
647 fe8dca8c Edgar E. Iglesias
    uint32_t status;
648 fe8dca8c Edgar E. Iglesias
    uint32_t tcu, tmx, tasid, tksu;
649 fe8dca8c Edgar E. Iglesias
    uint32_t mask = ((1 << CP0St_CU3)
650 fe8dca8c Edgar E. Iglesias
                       | (1 << CP0St_CU2)
651 fe8dca8c Edgar E. Iglesias
                       | (1 << CP0St_CU1)
652 fe8dca8c Edgar E. Iglesias
                       | (1 << CP0St_CU0)
653 fe8dca8c Edgar E. Iglesias
                       | (1 << CP0St_MX)
654 fe8dca8c Edgar E. Iglesias
                       | (3 << CP0St_KSU));
655 fe8dca8c Edgar E. Iglesias
656 fe8dca8c Edgar E. Iglesias
    tcu = (v >> CP0TCSt_TCU0) & 0xf;
657 fe8dca8c Edgar E. Iglesias
    tmx = (v >> CP0TCSt_TMX) & 0x1;
658 fe8dca8c Edgar E. Iglesias
    tasid = v & 0xff;
659 fe8dca8c Edgar E. Iglesias
    tksu = (v >> CP0TCSt_TKSU) & 0x3;
660 fe8dca8c Edgar E. Iglesias
661 fe8dca8c Edgar E. Iglesias
    status = tcu << CP0St_CU0;
662 fe8dca8c Edgar E. Iglesias
    status |= tmx << CP0St_MX;
663 fe8dca8c Edgar E. Iglesias
    status |= tksu << CP0St_KSU;
664 fe8dca8c Edgar E. Iglesias
665 fe8dca8c Edgar E. Iglesias
    cpu->CP0_Status &= ~mask;
666 fe8dca8c Edgar E. Iglesias
    cpu->CP0_Status |= status;
667 fe8dca8c Edgar E. Iglesias
668 fe8dca8c Edgar E. Iglesias
    /* Sync the TASID with EntryHi.  */
669 fe8dca8c Edgar E. Iglesias
    cpu->CP0_EntryHi &= ~0xff;
670 fe8dca8c Edgar E. Iglesias
    cpu->CP0_EntryHi = tasid;
671 fe8dca8c Edgar E. Iglesias
672 fe8dca8c Edgar E. Iglesias
    compute_hflags(cpu);
673 fe8dca8c Edgar E. Iglesias
}
674 fe8dca8c Edgar E. Iglesias
675 fe8dca8c Edgar E. Iglesias
/* Called for updates to CP0_EntryHi.  */
676 7db13fae Andreas Färber
static void sync_c0_entryhi(CPUMIPSState *cpu, int tc)
677 fe8dca8c Edgar E. Iglesias
{
678 fe8dca8c Edgar E. Iglesias
    int32_t *tcst;
679 fe8dca8c Edgar E. Iglesias
    uint32_t asid, v = cpu->CP0_EntryHi;
680 fe8dca8c Edgar E. Iglesias
681 fe8dca8c Edgar E. Iglesias
    asid = v & 0xff;
682 fe8dca8c Edgar E. Iglesias
683 fe8dca8c Edgar E. Iglesias
    if (tc == cpu->current_tc) {
684 fe8dca8c Edgar E. Iglesias
        tcst = &cpu->active_tc.CP0_TCStatus;
685 fe8dca8c Edgar E. Iglesias
    } else {
686 fe8dca8c Edgar E. Iglesias
        tcst = &cpu->tcs[tc].CP0_TCStatus;
687 fe8dca8c Edgar E. Iglesias
    }
688 fe8dca8c Edgar E. Iglesias
689 fe8dca8c Edgar E. Iglesias
    *tcst &= ~0xff;
690 fe8dca8c Edgar E. Iglesias
    *tcst |= asid;
691 fe8dca8c Edgar E. Iglesias
}
692 fe8dca8c Edgar E. Iglesias
693 6af0bf9c bellard
/* CP0 helpers */
694 895c2d04 Blue Swirl
target_ulong helper_mfc0_mvpcontrol(CPUMIPSState *env)
695 f1aa6320 ths
{
696 be24bb4f ths
    return env->mvp->CP0_MVPControl;
697 f1aa6320 ths
}
698 f1aa6320 ths
699 895c2d04 Blue Swirl
target_ulong helper_mfc0_mvpconf0(CPUMIPSState *env)
700 f1aa6320 ths
{
701 be24bb4f ths
    return env->mvp->CP0_MVPConf0;
702 f1aa6320 ths
}
703 f1aa6320 ths
704 895c2d04 Blue Swirl
target_ulong helper_mfc0_mvpconf1(CPUMIPSState *env)
705 f1aa6320 ths
{
706 be24bb4f ths
    return env->mvp->CP0_MVPConf1;
707 f1aa6320 ths
}
708 f1aa6320 ths
709 895c2d04 Blue Swirl
target_ulong helper_mfc0_random(CPUMIPSState *env)
710 6af0bf9c bellard
{
711 be24bb4f ths
    return (int32_t)cpu_mips_get_random(env);
712 873eb012 ths
}
713 6af0bf9c bellard
714 895c2d04 Blue Swirl
target_ulong helper_mfc0_tcstatus(CPUMIPSState *env)
715 f1aa6320 ths
{
716 b5dc7732 ths
    return env->active_tc.CP0_TCStatus;
717 f1aa6320 ths
}
718 f1aa6320 ths
719 895c2d04 Blue Swirl
target_ulong helper_mftc0_tcstatus(CPUMIPSState *env)
720 f1aa6320 ths
{
721 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
722 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
723 f1aa6320 ths
724 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
725 b93bbdcd Edgar E. Iglesias
        return other->active_tc.CP0_TCStatus;
726 b5dc7732 ths
    else
727 b93bbdcd Edgar E. Iglesias
        return other->tcs[other_tc].CP0_TCStatus;
728 f1aa6320 ths
}
729 f1aa6320 ths
730 895c2d04 Blue Swirl
target_ulong helper_mfc0_tcbind(CPUMIPSState *env)
731 f1aa6320 ths
{
732 b5dc7732 ths
    return env->active_tc.CP0_TCBind;
733 f1aa6320 ths
}
734 f1aa6320 ths
735 895c2d04 Blue Swirl
target_ulong helper_mftc0_tcbind(CPUMIPSState *env)
736 f1aa6320 ths
{
737 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
738 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
739 f1aa6320 ths
740 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
741 b93bbdcd Edgar E. Iglesias
        return other->active_tc.CP0_TCBind;
742 b5dc7732 ths
    else
743 b93bbdcd Edgar E. Iglesias
        return other->tcs[other_tc].CP0_TCBind;
744 f1aa6320 ths
}
745 f1aa6320 ths
746 895c2d04 Blue Swirl
target_ulong helper_mfc0_tcrestart(CPUMIPSState *env)
747 f1aa6320 ths
{
748 b5dc7732 ths
    return env->active_tc.PC;
749 f1aa6320 ths
}
750 f1aa6320 ths
751 895c2d04 Blue Swirl
target_ulong helper_mftc0_tcrestart(CPUMIPSState *env)
752 f1aa6320 ths
{
753 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
754 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
755 f1aa6320 ths
756 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
757 b93bbdcd Edgar E. Iglesias
        return other->active_tc.PC;
758 b5dc7732 ths
    else
759 b93bbdcd Edgar E. Iglesias
        return other->tcs[other_tc].PC;
760 f1aa6320 ths
}
761 f1aa6320 ths
762 895c2d04 Blue Swirl
target_ulong helper_mfc0_tchalt(CPUMIPSState *env)
763 f1aa6320 ths
{
764 b5dc7732 ths
    return env->active_tc.CP0_TCHalt;
765 f1aa6320 ths
}
766 f1aa6320 ths
767 895c2d04 Blue Swirl
target_ulong helper_mftc0_tchalt(CPUMIPSState *env)
768 f1aa6320 ths
{
769 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
770 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
771 f1aa6320 ths
772 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
773 b93bbdcd Edgar E. Iglesias
        return other->active_tc.CP0_TCHalt;
774 b5dc7732 ths
    else
775 b93bbdcd Edgar E. Iglesias
        return other->tcs[other_tc].CP0_TCHalt;
776 f1aa6320 ths
}
777 f1aa6320 ths
778 895c2d04 Blue Swirl
target_ulong helper_mfc0_tccontext(CPUMIPSState *env)
779 f1aa6320 ths
{
780 b5dc7732 ths
    return env->active_tc.CP0_TCContext;
781 f1aa6320 ths
}
782 f1aa6320 ths
783 895c2d04 Blue Swirl
target_ulong helper_mftc0_tccontext(CPUMIPSState *env)
784 f1aa6320 ths
{
785 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
786 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
787 f1aa6320 ths
788 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
789 b93bbdcd Edgar E. Iglesias
        return other->active_tc.CP0_TCContext;
790 b5dc7732 ths
    else
791 b93bbdcd Edgar E. Iglesias
        return other->tcs[other_tc].CP0_TCContext;
792 f1aa6320 ths
}
793 f1aa6320 ths
794 895c2d04 Blue Swirl
target_ulong helper_mfc0_tcschedule(CPUMIPSState *env)
795 f1aa6320 ths
{
796 b5dc7732 ths
    return env->active_tc.CP0_TCSchedule;
797 f1aa6320 ths
}
798 f1aa6320 ths
799 895c2d04 Blue Swirl
target_ulong helper_mftc0_tcschedule(CPUMIPSState *env)
800 f1aa6320 ths
{
801 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
802 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
803 f1aa6320 ths
804 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
805 b93bbdcd Edgar E. Iglesias
        return other->active_tc.CP0_TCSchedule;
806 b5dc7732 ths
    else
807 b93bbdcd Edgar E. Iglesias
        return other->tcs[other_tc].CP0_TCSchedule;
808 f1aa6320 ths
}
809 f1aa6320 ths
810 895c2d04 Blue Swirl
target_ulong helper_mfc0_tcschefback(CPUMIPSState *env)
811 f1aa6320 ths
{
812 b5dc7732 ths
    return env->active_tc.CP0_TCScheFBack;
813 f1aa6320 ths
}
814 f1aa6320 ths
815 895c2d04 Blue Swirl
target_ulong helper_mftc0_tcschefback(CPUMIPSState *env)
816 f1aa6320 ths
{
817 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
818 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
819 f1aa6320 ths
820 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
821 b93bbdcd Edgar E. Iglesias
        return other->active_tc.CP0_TCScheFBack;
822 b5dc7732 ths
    else
823 b93bbdcd Edgar E. Iglesias
        return other->tcs[other_tc].CP0_TCScheFBack;
824 f1aa6320 ths
}
825 f1aa6320 ths
826 895c2d04 Blue Swirl
target_ulong helper_mfc0_count(CPUMIPSState *env)
827 873eb012 ths
{
828 be24bb4f ths
    return (int32_t)cpu_mips_get_count(env);
829 6af0bf9c bellard
}
830 6af0bf9c bellard
831 895c2d04 Blue Swirl
target_ulong helper_mftc0_entryhi(CPUMIPSState *env)
832 f1aa6320 ths
{
833 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
834 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
835 f1aa6320 ths
836 fe8dca8c Edgar E. Iglesias
    return other->CP0_EntryHi;
837 f1aa6320 ths
}
838 f1aa6320 ths
839 895c2d04 Blue Swirl
target_ulong helper_mftc0_cause(CPUMIPSState *env)
840 5a25ce94 Edgar E. Iglesias
{
841 5a25ce94 Edgar E. Iglesias
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
842 5a25ce94 Edgar E. Iglesias
    int32_t tccause;
843 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
844 5a25ce94 Edgar E. Iglesias
845 5a25ce94 Edgar E. Iglesias
    if (other_tc == other->current_tc) {
846 5a25ce94 Edgar E. Iglesias
        tccause = other->CP0_Cause;
847 5a25ce94 Edgar E. Iglesias
    } else {
848 5a25ce94 Edgar E. Iglesias
        tccause = other->CP0_Cause;
849 5a25ce94 Edgar E. Iglesias
    }
850 5a25ce94 Edgar E. Iglesias
851 5a25ce94 Edgar E. Iglesias
    return tccause;
852 5a25ce94 Edgar E. Iglesias
}
853 5a25ce94 Edgar E. Iglesias
854 895c2d04 Blue Swirl
target_ulong helper_mftc0_status(CPUMIPSState *env)
855 f1aa6320 ths
{
856 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
857 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
858 b5dc7732 ths
859 fe8dca8c Edgar E. Iglesias
    return other->CP0_Status;
860 f1aa6320 ths
}
861 f1aa6320 ths
862 895c2d04 Blue Swirl
target_ulong helper_mfc0_lladdr(CPUMIPSState *env)
863 f1aa6320 ths
{
864 2a6e32dd Aurelien Jarno
    return (int32_t)(env->lladdr >> env->CP0_LLAddr_shift);
865 f1aa6320 ths
}
866 f1aa6320 ths
867 895c2d04 Blue Swirl
target_ulong helper_mfc0_watchlo(CPUMIPSState *env, uint32_t sel)
868 f1aa6320 ths
{
869 be24bb4f ths
    return (int32_t)env->CP0_WatchLo[sel];
870 f1aa6320 ths
}
871 f1aa6320 ths
872 895c2d04 Blue Swirl
target_ulong helper_mfc0_watchhi(CPUMIPSState *env, uint32_t sel)
873 f1aa6320 ths
{
874 be24bb4f ths
    return env->CP0_WatchHi[sel];
875 f1aa6320 ths
}
876 f1aa6320 ths
877 895c2d04 Blue Swirl
target_ulong helper_mfc0_debug(CPUMIPSState *env)
878 f1aa6320 ths
{
879 1a3fd9c3 ths
    target_ulong t0 = env->CP0_Debug;
880 f1aa6320 ths
    if (env->hflags & MIPS_HFLAG_DM)
881 be24bb4f ths
        t0 |= 1 << CP0DB_DM;
882 be24bb4f ths
883 be24bb4f ths
    return t0;
884 f1aa6320 ths
}
885 f1aa6320 ths
886 895c2d04 Blue Swirl
target_ulong helper_mftc0_debug(CPUMIPSState *env)
887 f1aa6320 ths
{
888 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
889 b5dc7732 ths
    int32_t tcstatus;
890 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
891 b5dc7732 ths
892 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
893 b93bbdcd Edgar E. Iglesias
        tcstatus = other->active_tc.CP0_Debug_tcstatus;
894 b5dc7732 ths
    else
895 b93bbdcd Edgar E. Iglesias
        tcstatus = other->tcs[other_tc].CP0_Debug_tcstatus;
896 f1aa6320 ths
897 f1aa6320 ths
    /* XXX: Might be wrong, check with EJTAG spec. */
898 b93bbdcd Edgar E. Iglesias
    return (other->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
899 b5dc7732 ths
            (tcstatus & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
900 f1aa6320 ths
}
901 f1aa6320 ths
902 f1aa6320 ths
#if defined(TARGET_MIPS64)
903 895c2d04 Blue Swirl
target_ulong helper_dmfc0_tcrestart(CPUMIPSState *env)
904 f1aa6320 ths
{
905 b5dc7732 ths
    return env->active_tc.PC;
906 f1aa6320 ths
}
907 f1aa6320 ths
908 895c2d04 Blue Swirl
target_ulong helper_dmfc0_tchalt(CPUMIPSState *env)
909 f1aa6320 ths
{
910 b5dc7732 ths
    return env->active_tc.CP0_TCHalt;
911 f1aa6320 ths
}
912 f1aa6320 ths
913 895c2d04 Blue Swirl
target_ulong helper_dmfc0_tccontext(CPUMIPSState *env)
914 f1aa6320 ths
{
915 b5dc7732 ths
    return env->active_tc.CP0_TCContext;
916 f1aa6320 ths
}
917 f1aa6320 ths
918 895c2d04 Blue Swirl
target_ulong helper_dmfc0_tcschedule(CPUMIPSState *env)
919 f1aa6320 ths
{
920 b5dc7732 ths
    return env->active_tc.CP0_TCSchedule;
921 f1aa6320 ths
}
922 f1aa6320 ths
923 895c2d04 Blue Swirl
target_ulong helper_dmfc0_tcschefback(CPUMIPSState *env)
924 f1aa6320 ths
{
925 b5dc7732 ths
    return env->active_tc.CP0_TCScheFBack;
926 f1aa6320 ths
}
927 f1aa6320 ths
928 895c2d04 Blue Swirl
target_ulong helper_dmfc0_lladdr(CPUMIPSState *env)
929 f1aa6320 ths
{
930 2a6e32dd Aurelien Jarno
    return env->lladdr >> env->CP0_LLAddr_shift;
931 f1aa6320 ths
}
932 f1aa6320 ths
933 895c2d04 Blue Swirl
target_ulong helper_dmfc0_watchlo(CPUMIPSState *env, uint32_t sel)
934 f1aa6320 ths
{
935 be24bb4f ths
    return env->CP0_WatchLo[sel];
936 f1aa6320 ths
}
937 f1aa6320 ths
#endif /* TARGET_MIPS64 */
938 f1aa6320 ths
939 895c2d04 Blue Swirl
void helper_mtc0_index(CPUMIPSState *env, target_ulong arg1)
940 f1aa6320 ths
{
941 f1aa6320 ths
    int num = 1;
942 f1aa6320 ths
    unsigned int tmp = env->tlb->nb_tlb;
943 f1aa6320 ths
944 f1aa6320 ths
    do {
945 f1aa6320 ths
        tmp >>= 1;
946 f1aa6320 ths
        num <<= 1;
947 f1aa6320 ths
    } while (tmp);
948 d9bea114 aurel32
    env->CP0_Index = (env->CP0_Index & 0x80000000) | (arg1 & (num - 1));
949 f1aa6320 ths
}
950 f1aa6320 ths
951 895c2d04 Blue Swirl
void helper_mtc0_mvpcontrol(CPUMIPSState *env, target_ulong arg1)
952 f1aa6320 ths
{
953 f1aa6320 ths
    uint32_t mask = 0;
954 f1aa6320 ths
    uint32_t newval;
955 f1aa6320 ths
956 f1aa6320 ths
    if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
957 f1aa6320 ths
        mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
958 f1aa6320 ths
                (1 << CP0MVPCo_EVP);
959 f1aa6320 ths
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
960 f1aa6320 ths
        mask |= (1 << CP0MVPCo_STLB);
961 d9bea114 aurel32
    newval = (env->mvp->CP0_MVPControl & ~mask) | (arg1 & mask);
962 f1aa6320 ths
963 f1aa6320 ths
    // TODO: Enable/disable shared TLB, enable/disable VPEs.
964 f1aa6320 ths
965 f1aa6320 ths
    env->mvp->CP0_MVPControl = newval;
966 f1aa6320 ths
}
967 f1aa6320 ths
968 895c2d04 Blue Swirl
void helper_mtc0_vpecontrol(CPUMIPSState *env, target_ulong arg1)
969 f1aa6320 ths
{
970 f1aa6320 ths
    uint32_t mask;
971 f1aa6320 ths
    uint32_t newval;
972 f1aa6320 ths
973 f1aa6320 ths
    mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
974 f1aa6320 ths
           (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
975 d9bea114 aurel32
    newval = (env->CP0_VPEControl & ~mask) | (arg1 & mask);
976 f1aa6320 ths
977 f1aa6320 ths
    /* Yield scheduler intercept not implemented. */
978 f1aa6320 ths
    /* Gating storage scheduler intercept not implemented. */
979 f1aa6320 ths
980 f1aa6320 ths
    // TODO: Enable/disable TCs.
981 f1aa6320 ths
982 f1aa6320 ths
    env->CP0_VPEControl = newval;
983 f1aa6320 ths
}
984 f1aa6320 ths
985 895c2d04 Blue Swirl
void helper_mttc0_vpecontrol(CPUMIPSState *env, target_ulong arg1)
986 5a25ce94 Edgar E. Iglesias
{
987 5a25ce94 Edgar E. Iglesias
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
988 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
989 5a25ce94 Edgar E. Iglesias
    uint32_t mask;
990 5a25ce94 Edgar E. Iglesias
    uint32_t newval;
991 5a25ce94 Edgar E. Iglesias
992 5a25ce94 Edgar E. Iglesias
    mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
993 5a25ce94 Edgar E. Iglesias
           (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
994 5a25ce94 Edgar E. Iglesias
    newval = (other->CP0_VPEControl & ~mask) | (arg1 & mask);
995 5a25ce94 Edgar E. Iglesias
996 5a25ce94 Edgar E. Iglesias
    /* TODO: Enable/disable TCs.  */
997 5a25ce94 Edgar E. Iglesias
998 5a25ce94 Edgar E. Iglesias
    other->CP0_VPEControl = newval;
999 5a25ce94 Edgar E. Iglesias
}
1000 5a25ce94 Edgar E. Iglesias
1001 895c2d04 Blue Swirl
target_ulong helper_mftc0_vpecontrol(CPUMIPSState *env)
1002 5a25ce94 Edgar E. Iglesias
{
1003 5a25ce94 Edgar E. Iglesias
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1004 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1005 5a25ce94 Edgar E. Iglesias
    /* FIXME: Mask away return zero on read bits.  */
1006 5a25ce94 Edgar E. Iglesias
    return other->CP0_VPEControl;
1007 5a25ce94 Edgar E. Iglesias
}
1008 5a25ce94 Edgar E. Iglesias
1009 895c2d04 Blue Swirl
target_ulong helper_mftc0_vpeconf0(CPUMIPSState *env)
1010 5a25ce94 Edgar E. Iglesias
{
1011 5a25ce94 Edgar E. Iglesias
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1012 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1013 5a25ce94 Edgar E. Iglesias
1014 5a25ce94 Edgar E. Iglesias
    return other->CP0_VPEConf0;
1015 5a25ce94 Edgar E. Iglesias
}
1016 5a25ce94 Edgar E. Iglesias
1017 895c2d04 Blue Swirl
void helper_mtc0_vpeconf0(CPUMIPSState *env, target_ulong arg1)
1018 f1aa6320 ths
{
1019 f1aa6320 ths
    uint32_t mask = 0;
1020 f1aa6320 ths
    uint32_t newval;
1021 f1aa6320 ths
1022 f1aa6320 ths
    if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
1023 f1aa6320 ths
        if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
1024 f1aa6320 ths
            mask |= (0xff << CP0VPEC0_XTC);
1025 f1aa6320 ths
        mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
1026 f1aa6320 ths
    }
1027 d9bea114 aurel32
    newval = (env->CP0_VPEConf0 & ~mask) | (arg1 & mask);
1028 f1aa6320 ths
1029 f1aa6320 ths
    // TODO: TC exclusive handling due to ERL/EXL.
1030 f1aa6320 ths
1031 f1aa6320 ths
    env->CP0_VPEConf0 = newval;
1032 f1aa6320 ths
}
1033 f1aa6320 ths
1034 895c2d04 Blue Swirl
void helper_mttc0_vpeconf0(CPUMIPSState *env, target_ulong arg1)
1035 5a25ce94 Edgar E. Iglesias
{
1036 5a25ce94 Edgar E. Iglesias
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1037 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1038 5a25ce94 Edgar E. Iglesias
    uint32_t mask = 0;
1039 5a25ce94 Edgar E. Iglesias
    uint32_t newval;
1040 5a25ce94 Edgar E. Iglesias
1041 5a25ce94 Edgar E. Iglesias
    mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
1042 5a25ce94 Edgar E. Iglesias
    newval = (other->CP0_VPEConf0 & ~mask) | (arg1 & mask);
1043 5a25ce94 Edgar E. Iglesias
1044 5a25ce94 Edgar E. Iglesias
    /* TODO: TC exclusive handling due to ERL/EXL.  */
1045 5a25ce94 Edgar E. Iglesias
    other->CP0_VPEConf0 = newval;
1046 5a25ce94 Edgar E. Iglesias
}
1047 5a25ce94 Edgar E. Iglesias
1048 895c2d04 Blue Swirl
void helper_mtc0_vpeconf1(CPUMIPSState *env, target_ulong arg1)
1049 f1aa6320 ths
{
1050 f1aa6320 ths
    uint32_t mask = 0;
1051 f1aa6320 ths
    uint32_t newval;
1052 f1aa6320 ths
1053 f1aa6320 ths
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1054 f1aa6320 ths
        mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
1055 f1aa6320 ths
                (0xff << CP0VPEC1_NCP1);
1056 d9bea114 aurel32
    newval = (env->CP0_VPEConf1 & ~mask) | (arg1 & mask);
1057 f1aa6320 ths
1058 f1aa6320 ths
    /* UDI not implemented. */
1059 f1aa6320 ths
    /* CP2 not implemented. */
1060 f1aa6320 ths
1061 f1aa6320 ths
    // TODO: Handle FPU (CP1) binding.
1062 f1aa6320 ths
1063 f1aa6320 ths
    env->CP0_VPEConf1 = newval;
1064 f1aa6320 ths
}
1065 f1aa6320 ths
1066 895c2d04 Blue Swirl
void helper_mtc0_yqmask(CPUMIPSState *env, target_ulong arg1)
1067 f1aa6320 ths
{
1068 f1aa6320 ths
    /* Yield qualifier inputs not implemented. */
1069 f1aa6320 ths
    env->CP0_YQMask = 0x00000000;
1070 f1aa6320 ths
}
1071 f1aa6320 ths
1072 895c2d04 Blue Swirl
void helper_mtc0_vpeopt(CPUMIPSState *env, target_ulong arg1)
1073 f1aa6320 ths
{
1074 d9bea114 aurel32
    env->CP0_VPEOpt = arg1 & 0x0000ffff;
1075 f1aa6320 ths
}
1076 f1aa6320 ths
1077 895c2d04 Blue Swirl
void helper_mtc0_entrylo0(CPUMIPSState *env, target_ulong arg1)
1078 f1aa6320 ths
{
1079 f1aa6320 ths
    /* Large physaddr (PABITS) not implemented */
1080 f1aa6320 ths
    /* 1k pages not implemented */
1081 d9bea114 aurel32
    env->CP0_EntryLo0 = arg1 & 0x3FFFFFFF;
1082 f1aa6320 ths
}
1083 f1aa6320 ths
1084 895c2d04 Blue Swirl
void helper_mtc0_tcstatus(CPUMIPSState *env, target_ulong arg1)
1085 f1aa6320 ths
{
1086 f1aa6320 ths
    uint32_t mask = env->CP0_TCStatus_rw_bitmask;
1087 f1aa6320 ths
    uint32_t newval;
1088 f1aa6320 ths
1089 d9bea114 aurel32
    newval = (env->active_tc.CP0_TCStatus & ~mask) | (arg1 & mask);
1090 f1aa6320 ths
1091 b5dc7732 ths
    env->active_tc.CP0_TCStatus = newval;
1092 fe8dca8c Edgar E. Iglesias
    sync_c0_tcstatus(env, env->current_tc, newval);
1093 f1aa6320 ths
}
1094 f1aa6320 ths
1095 895c2d04 Blue Swirl
void helper_mttc0_tcstatus(CPUMIPSState *env, target_ulong arg1)
1096 f1aa6320 ths
{
1097 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1098 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1099 f1aa6320 ths
1100 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
1101 b93bbdcd Edgar E. Iglesias
        other->active_tc.CP0_TCStatus = arg1;
1102 b5dc7732 ths
    else
1103 b93bbdcd Edgar E. Iglesias
        other->tcs[other_tc].CP0_TCStatus = arg1;
1104 fe8dca8c Edgar E. Iglesias
    sync_c0_tcstatus(other, other_tc, arg1);
1105 f1aa6320 ths
}
1106 f1aa6320 ths
1107 895c2d04 Blue Swirl
void helper_mtc0_tcbind(CPUMIPSState *env, target_ulong arg1)
1108 f1aa6320 ths
{
1109 f1aa6320 ths
    uint32_t mask = (1 << CP0TCBd_TBE);
1110 f1aa6320 ths
    uint32_t newval;
1111 f1aa6320 ths
1112 f1aa6320 ths
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1113 f1aa6320 ths
        mask |= (1 << CP0TCBd_CurVPE);
1114 d9bea114 aurel32
    newval = (env->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
1115 b5dc7732 ths
    env->active_tc.CP0_TCBind = newval;
1116 f1aa6320 ths
}
1117 f1aa6320 ths
1118 895c2d04 Blue Swirl
void helper_mttc0_tcbind(CPUMIPSState *env, target_ulong arg1)
1119 f1aa6320 ths
{
1120 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1121 f1aa6320 ths
    uint32_t mask = (1 << CP0TCBd_TBE);
1122 f1aa6320 ths
    uint32_t newval;
1123 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1124 f1aa6320 ths
1125 b93bbdcd Edgar E. Iglesias
    if (other->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1126 f1aa6320 ths
        mask |= (1 << CP0TCBd_CurVPE);
1127 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc) {
1128 b93bbdcd Edgar E. Iglesias
        newval = (other->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
1129 b93bbdcd Edgar E. Iglesias
        other->active_tc.CP0_TCBind = newval;
1130 b5dc7732 ths
    } else {
1131 b93bbdcd Edgar E. Iglesias
        newval = (other->tcs[other_tc].CP0_TCBind & ~mask) | (arg1 & mask);
1132 b93bbdcd Edgar E. Iglesias
        other->tcs[other_tc].CP0_TCBind = newval;
1133 b5dc7732 ths
    }
1134 f1aa6320 ths
}
1135 f1aa6320 ths
1136 895c2d04 Blue Swirl
void helper_mtc0_tcrestart(CPUMIPSState *env, target_ulong arg1)
1137 f1aa6320 ths
{
1138 d9bea114 aurel32
    env->active_tc.PC = arg1;
1139 b5dc7732 ths
    env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
1140 5499b6ff Aurelien Jarno
    env->lladdr = 0ULL;
1141 f1aa6320 ths
    /* MIPS16 not implemented. */
1142 f1aa6320 ths
}
1143 f1aa6320 ths
1144 895c2d04 Blue Swirl
void helper_mttc0_tcrestart(CPUMIPSState *env, target_ulong arg1)
1145 f1aa6320 ths
{
1146 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1147 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1148 f1aa6320 ths
1149 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc) {
1150 b93bbdcd Edgar E. Iglesias
        other->active_tc.PC = arg1;
1151 b93bbdcd Edgar E. Iglesias
        other->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
1152 b93bbdcd Edgar E. Iglesias
        other->lladdr = 0ULL;
1153 b5dc7732 ths
        /* MIPS16 not implemented. */
1154 b5dc7732 ths
    } else {
1155 b93bbdcd Edgar E. Iglesias
        other->tcs[other_tc].PC = arg1;
1156 b93bbdcd Edgar E. Iglesias
        other->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
1157 b93bbdcd Edgar E. Iglesias
        other->lladdr = 0ULL;
1158 b5dc7732 ths
        /* MIPS16 not implemented. */
1159 b5dc7732 ths
    }
1160 f1aa6320 ths
}
1161 f1aa6320 ths
1162 895c2d04 Blue Swirl
void helper_mtc0_tchalt(CPUMIPSState *env, target_ulong arg1)
1163 f1aa6320 ths
{
1164 135dd63a Andreas Färber
    MIPSCPU *cpu = mips_env_get_cpu(env);
1165 135dd63a Andreas Färber
1166 d9bea114 aurel32
    env->active_tc.CP0_TCHalt = arg1 & 0x1;
1167 f1aa6320 ths
1168 f1aa6320 ths
    // TODO: Halt TC / Restart (if allocated+active) TC.
1169 f249412c Edgar E. Iglesias
    if (env->active_tc.CP0_TCHalt & 1) {
1170 c6679e90 Andreas Färber
        mips_tc_sleep(cpu, env->current_tc);
1171 f249412c Edgar E. Iglesias
    } else {
1172 135dd63a Andreas Färber
        mips_tc_wake(cpu, env->current_tc);
1173 f249412c Edgar E. Iglesias
    }
1174 f1aa6320 ths
}
1175 f1aa6320 ths
1176 895c2d04 Blue Swirl
void helper_mttc0_tchalt(CPUMIPSState *env, target_ulong arg1)
1177 f1aa6320 ths
{
1178 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1179 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1180 135dd63a Andreas Färber
    MIPSCPU *other_cpu = mips_env_get_cpu(other);
1181 f1aa6320 ths
1182 f1aa6320 ths
    // TODO: Halt TC / Restart (if allocated+active) TC.
1183 f1aa6320 ths
1184 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
1185 b93bbdcd Edgar E. Iglesias
        other->active_tc.CP0_TCHalt = arg1;
1186 b5dc7732 ths
    else
1187 b93bbdcd Edgar E. Iglesias
        other->tcs[other_tc].CP0_TCHalt = arg1;
1188 f249412c Edgar E. Iglesias
1189 f249412c Edgar E. Iglesias
    if (arg1 & 1) {
1190 c6679e90 Andreas Färber
        mips_tc_sleep(other_cpu, other_tc);
1191 f249412c Edgar E. Iglesias
    } else {
1192 135dd63a Andreas Färber
        mips_tc_wake(other_cpu, other_tc);
1193 f249412c Edgar E. Iglesias
    }
1194 f1aa6320 ths
}
1195 f1aa6320 ths
1196 895c2d04 Blue Swirl
void helper_mtc0_tccontext(CPUMIPSState *env, target_ulong arg1)
1197 f1aa6320 ths
{
1198 d9bea114 aurel32
    env->active_tc.CP0_TCContext = arg1;
1199 f1aa6320 ths
}
1200 f1aa6320 ths
1201 895c2d04 Blue Swirl
void helper_mttc0_tccontext(CPUMIPSState *env, target_ulong arg1)
1202 f1aa6320 ths
{
1203 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1204 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1205 f1aa6320 ths
1206 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
1207 b93bbdcd Edgar E. Iglesias
        other->active_tc.CP0_TCContext = arg1;
1208 b5dc7732 ths
    else
1209 b93bbdcd Edgar E. Iglesias
        other->tcs[other_tc].CP0_TCContext = arg1;
1210 f1aa6320 ths
}
1211 f1aa6320 ths
1212 895c2d04 Blue Swirl
void helper_mtc0_tcschedule(CPUMIPSState *env, target_ulong arg1)
1213 f1aa6320 ths
{
1214 d9bea114 aurel32
    env->active_tc.CP0_TCSchedule = arg1;
1215 f1aa6320 ths
}
1216 f1aa6320 ths
1217 895c2d04 Blue Swirl
void helper_mttc0_tcschedule(CPUMIPSState *env, target_ulong arg1)
1218 f1aa6320 ths
{
1219 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1220 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1221 f1aa6320 ths
1222 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
1223 b93bbdcd Edgar E. Iglesias
        other->active_tc.CP0_TCSchedule = arg1;
1224 b5dc7732 ths
    else
1225 b93bbdcd Edgar E. Iglesias
        other->tcs[other_tc].CP0_TCSchedule = arg1;
1226 f1aa6320 ths
}
1227 f1aa6320 ths
1228 895c2d04 Blue Swirl
void helper_mtc0_tcschefback(CPUMIPSState *env, target_ulong arg1)
1229 f1aa6320 ths
{
1230 d9bea114 aurel32
    env->active_tc.CP0_TCScheFBack = arg1;
1231 f1aa6320 ths
}
1232 f1aa6320 ths
1233 895c2d04 Blue Swirl
void helper_mttc0_tcschefback(CPUMIPSState *env, target_ulong arg1)
1234 f1aa6320 ths
{
1235 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1236 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1237 f1aa6320 ths
1238 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
1239 b93bbdcd Edgar E. Iglesias
        other->active_tc.CP0_TCScheFBack = arg1;
1240 b5dc7732 ths
    else
1241 b93bbdcd Edgar E. Iglesias
        other->tcs[other_tc].CP0_TCScheFBack = arg1;
1242 f1aa6320 ths
}
1243 f1aa6320 ths
1244 895c2d04 Blue Swirl
void helper_mtc0_entrylo1(CPUMIPSState *env, target_ulong arg1)
1245 f1aa6320 ths
{
1246 f1aa6320 ths
    /* Large physaddr (PABITS) not implemented */
1247 f1aa6320 ths
    /* 1k pages not implemented */
1248 d9bea114 aurel32
    env->CP0_EntryLo1 = arg1 & 0x3FFFFFFF;
1249 f1aa6320 ths
}
1250 f1aa6320 ths
1251 895c2d04 Blue Swirl
void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1)
1252 f1aa6320 ths
{
1253 d9bea114 aurel32
    env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF);
1254 f1aa6320 ths
}
1255 f1aa6320 ths
1256 895c2d04 Blue Swirl
void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
1257 f1aa6320 ths
{
1258 f1aa6320 ths
    /* 1k pages not implemented */
1259 d9bea114 aurel32
    env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1260 f1aa6320 ths
}
1261 f1aa6320 ths
1262 895c2d04 Blue Swirl
void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
1263 f1aa6320 ths
{
1264 f1aa6320 ths
    /* SmartMIPS not implemented */
1265 f1aa6320 ths
    /* Large physaddr (PABITS) not implemented */
1266 f1aa6320 ths
    /* 1k pages not implemented */
1267 f1aa6320 ths
    env->CP0_PageGrain = 0;
1268 f1aa6320 ths
}
1269 f1aa6320 ths
1270 895c2d04 Blue Swirl
void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
1271 f1aa6320 ths
{
1272 d9bea114 aurel32
    env->CP0_Wired = arg1 % env->tlb->nb_tlb;
1273 f1aa6320 ths
}
1274 f1aa6320 ths
1275 895c2d04 Blue Swirl
void helper_mtc0_srsconf0(CPUMIPSState *env, target_ulong arg1)
1276 f1aa6320 ths
{
1277 d9bea114 aurel32
    env->CP0_SRSConf0 |= arg1 & env->CP0_SRSConf0_rw_bitmask;
1278 f1aa6320 ths
}
1279 f1aa6320 ths
1280 895c2d04 Blue Swirl
void helper_mtc0_srsconf1(CPUMIPSState *env, target_ulong arg1)
1281 f1aa6320 ths
{
1282 d9bea114 aurel32
    env->CP0_SRSConf1 |= arg1 & env->CP0_SRSConf1_rw_bitmask;
1283 f1aa6320 ths
}
1284 f1aa6320 ths
1285 895c2d04 Blue Swirl
void helper_mtc0_srsconf2(CPUMIPSState *env, target_ulong arg1)
1286 f1aa6320 ths
{
1287 d9bea114 aurel32
    env->CP0_SRSConf2 |= arg1 & env->CP0_SRSConf2_rw_bitmask;
1288 f1aa6320 ths
}
1289 f1aa6320 ths
1290 895c2d04 Blue Swirl
void helper_mtc0_srsconf3(CPUMIPSState *env, target_ulong arg1)
1291 f1aa6320 ths
{
1292 d9bea114 aurel32
    env->CP0_SRSConf3 |= arg1 & env->CP0_SRSConf3_rw_bitmask;
1293 f1aa6320 ths
}
1294 f1aa6320 ths
1295 895c2d04 Blue Swirl
void helper_mtc0_srsconf4(CPUMIPSState *env, target_ulong arg1)
1296 f1aa6320 ths
{
1297 d9bea114 aurel32
    env->CP0_SRSConf4 |= arg1 & env->CP0_SRSConf4_rw_bitmask;
1298 f1aa6320 ths
}
1299 f1aa6320 ths
1300 895c2d04 Blue Swirl
void helper_mtc0_hwrena(CPUMIPSState *env, target_ulong arg1)
1301 f1aa6320 ths
{
1302 d9bea114 aurel32
    env->CP0_HWREna = arg1 & 0x0000000F;
1303 f1aa6320 ths
}
1304 f1aa6320 ths
1305 895c2d04 Blue Swirl
void helper_mtc0_count(CPUMIPSState *env, target_ulong arg1)
1306 f1aa6320 ths
{
1307 d9bea114 aurel32
    cpu_mips_store_count(env, arg1);
1308 f1aa6320 ths
}
1309 f1aa6320 ths
1310 895c2d04 Blue Swirl
void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1)
1311 f1aa6320 ths
{
1312 f1aa6320 ths
    target_ulong old, val;
1313 f1aa6320 ths
1314 f1aa6320 ths
    /* 1k pages not implemented */
1315 d9bea114 aurel32
    val = arg1 & ((TARGET_PAGE_MASK << 1) | 0xFF);
1316 f1aa6320 ths
#if defined(TARGET_MIPS64)
1317 f1aa6320 ths
    val &= env->SEGMask;
1318 f1aa6320 ths
#endif
1319 f1aa6320 ths
    old = env->CP0_EntryHi;
1320 f1aa6320 ths
    env->CP0_EntryHi = val;
1321 f1aa6320 ths
    if (env->CP0_Config3 & (1 << CP0C3_MT)) {
1322 fe8dca8c Edgar E. Iglesias
        sync_c0_entryhi(env, env->current_tc);
1323 f1aa6320 ths
    }
1324 f1aa6320 ths
    /* If the ASID changes, flush qemu's TLB.  */
1325 f1aa6320 ths
    if ((old & 0xFF) != (val & 0xFF))
1326 f1aa6320 ths
        cpu_mips_tlb_flush(env, 1);
1327 f1aa6320 ths
}
1328 f1aa6320 ths
1329 895c2d04 Blue Swirl
void helper_mttc0_entryhi(CPUMIPSState *env, target_ulong arg1)
1330 f1aa6320 ths
{
1331 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1332 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1333 f1aa6320 ths
1334 fe8dca8c Edgar E. Iglesias
    other->CP0_EntryHi = arg1;
1335 fe8dca8c Edgar E. Iglesias
    sync_c0_entryhi(other, other_tc);
1336 f1aa6320 ths
}
1337 f1aa6320 ths
1338 895c2d04 Blue Swirl
void helper_mtc0_compare(CPUMIPSState *env, target_ulong arg1)
1339 f1aa6320 ths
{
1340 d9bea114 aurel32
    cpu_mips_store_compare(env, arg1);
1341 f1aa6320 ths
}
1342 f1aa6320 ths
1343 895c2d04 Blue Swirl
void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1)
1344 f1aa6320 ths
{
1345 f1aa6320 ths
    uint32_t val, old;
1346 f1aa6320 ths
    uint32_t mask = env->CP0_Status_rw_bitmask;
1347 f1aa6320 ths
1348 d9bea114 aurel32
    val = arg1 & mask;
1349 f1aa6320 ths
    old = env->CP0_Status;
1350 f1aa6320 ths
    env->CP0_Status = (env->CP0_Status & ~mask) | val;
1351 fe8dca8c Edgar E. Iglesias
    if (env->CP0_Config3 & (1 << CP0C3_MT)) {
1352 895c2d04 Blue Swirl
        sync_c0_status(env, env, env->current_tc);
1353 fe8dca8c Edgar E. Iglesias
    } else {
1354 fe8dca8c Edgar E. Iglesias
        compute_hflags(env);
1355 fe8dca8c Edgar E. Iglesias
    }
1356 fe8dca8c Edgar E. Iglesias
1357 c01fccd2 aurel32
    if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
1358 c01fccd2 aurel32
        qemu_log("Status %08x (%08x) => %08x (%08x) Cause %08x",
1359 c01fccd2 aurel32
                old, old & env->CP0_Cause & CP0Ca_IP_mask,
1360 c01fccd2 aurel32
                val, val & env->CP0_Cause & CP0Ca_IP_mask,
1361 c01fccd2 aurel32
                env->CP0_Cause);
1362 c01fccd2 aurel32
        switch (env->hflags & MIPS_HFLAG_KSU) {
1363 c01fccd2 aurel32
        case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
1364 c01fccd2 aurel32
        case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
1365 c01fccd2 aurel32
        case MIPS_HFLAG_KM: qemu_log("\n"); break;
1366 c01fccd2 aurel32
        default: cpu_abort(env, "Invalid MMU mode!\n"); break;
1367 31e3104f Aurelien Jarno
        }
1368 c01fccd2 aurel32
    }
1369 f1aa6320 ths
}
1370 f1aa6320 ths
1371 895c2d04 Blue Swirl
void helper_mttc0_status(CPUMIPSState *env, target_ulong arg1)
1372 f1aa6320 ths
{
1373 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1374 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1375 f1aa6320 ths
1376 b93bbdcd Edgar E. Iglesias
    other->CP0_Status = arg1 & ~0xf1000018;
1377 895c2d04 Blue Swirl
    sync_c0_status(env, other, other_tc);
1378 f1aa6320 ths
}
1379 f1aa6320 ths
1380 895c2d04 Blue Swirl
void helper_mtc0_intctl(CPUMIPSState *env, target_ulong arg1)
1381 f1aa6320 ths
{
1382 f1aa6320 ths
    /* vectored interrupts not implemented, no performance counters. */
1383 bc45a67a Edgar E. Iglesias
    env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000003e0) | (arg1 & 0x000003e0);
1384 f1aa6320 ths
}
1385 f1aa6320 ths
1386 895c2d04 Blue Swirl
void helper_mtc0_srsctl(CPUMIPSState *env, target_ulong arg1)
1387 f1aa6320 ths
{
1388 f1aa6320 ths
    uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
1389 d9bea114 aurel32
    env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (arg1 & mask);
1390 f1aa6320 ths
}
1391 f1aa6320 ths
1392 7db13fae Andreas Färber
static void mtc0_cause(CPUMIPSState *cpu, target_ulong arg1)
1393 f1aa6320 ths
{
1394 f1aa6320 ths
    uint32_t mask = 0x00C00300;
1395 5a25ce94 Edgar E. Iglesias
    uint32_t old = cpu->CP0_Cause;
1396 5dc5d9f0 Aurelien Jarno
    int i;
1397 f1aa6320 ths
1398 5a25ce94 Edgar E. Iglesias
    if (cpu->insn_flags & ISA_MIPS32R2) {
1399 f1aa6320 ths
        mask |= 1 << CP0Ca_DC;
1400 5a25ce94 Edgar E. Iglesias
    }
1401 f1aa6320 ths
1402 5a25ce94 Edgar E. Iglesias
    cpu->CP0_Cause = (cpu->CP0_Cause & ~mask) | (arg1 & mask);
1403 f1aa6320 ths
1404 5a25ce94 Edgar E. Iglesias
    if ((old ^ cpu->CP0_Cause) & (1 << CP0Ca_DC)) {
1405 5a25ce94 Edgar E. Iglesias
        if (cpu->CP0_Cause & (1 << CP0Ca_DC)) {
1406 5a25ce94 Edgar E. Iglesias
            cpu_mips_stop_count(cpu);
1407 5a25ce94 Edgar E. Iglesias
        } else {
1408 5a25ce94 Edgar E. Iglesias
            cpu_mips_start_count(cpu);
1409 5a25ce94 Edgar E. Iglesias
        }
1410 f1aa6320 ths
    }
1411 5dc5d9f0 Aurelien Jarno
1412 5dc5d9f0 Aurelien Jarno
    /* Set/reset software interrupts */
1413 5dc5d9f0 Aurelien Jarno
    for (i = 0 ; i < 2 ; i++) {
1414 5a25ce94 Edgar E. Iglesias
        if ((old ^ cpu->CP0_Cause) & (1 << (CP0Ca_IP + i))) {
1415 5a25ce94 Edgar E. Iglesias
            cpu_mips_soft_irq(cpu, i, cpu->CP0_Cause & (1 << (CP0Ca_IP + i)));
1416 5dc5d9f0 Aurelien Jarno
        }
1417 5dc5d9f0 Aurelien Jarno
    }
1418 f1aa6320 ths
}
1419 f1aa6320 ths
1420 895c2d04 Blue Swirl
void helper_mtc0_cause(CPUMIPSState *env, target_ulong arg1)
1421 5a25ce94 Edgar E. Iglesias
{
1422 5a25ce94 Edgar E. Iglesias
    mtc0_cause(env, arg1);
1423 5a25ce94 Edgar E. Iglesias
}
1424 5a25ce94 Edgar E. Iglesias
1425 895c2d04 Blue Swirl
void helper_mttc0_cause(CPUMIPSState *env, target_ulong arg1)
1426 5a25ce94 Edgar E. Iglesias
{
1427 5a25ce94 Edgar E. Iglesias
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1428 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1429 5a25ce94 Edgar E. Iglesias
1430 5a25ce94 Edgar E. Iglesias
    mtc0_cause(other, arg1);
1431 5a25ce94 Edgar E. Iglesias
}
1432 5a25ce94 Edgar E. Iglesias
1433 895c2d04 Blue Swirl
target_ulong helper_mftc0_epc(CPUMIPSState *env)
1434 5a25ce94 Edgar E. Iglesias
{
1435 5a25ce94 Edgar E. Iglesias
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1436 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1437 5a25ce94 Edgar E. Iglesias
1438 5a25ce94 Edgar E. Iglesias
    return other->CP0_EPC;
1439 5a25ce94 Edgar E. Iglesias
}
1440 5a25ce94 Edgar E. Iglesias
1441 895c2d04 Blue Swirl
target_ulong helper_mftc0_ebase(CPUMIPSState *env)
1442 5a25ce94 Edgar E. Iglesias
{
1443 5a25ce94 Edgar E. Iglesias
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1444 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1445 5a25ce94 Edgar E. Iglesias
1446 5a25ce94 Edgar E. Iglesias
    return other->CP0_EBase;
1447 5a25ce94 Edgar E. Iglesias
}
1448 5a25ce94 Edgar E. Iglesias
1449 895c2d04 Blue Swirl
void helper_mtc0_ebase(CPUMIPSState *env, target_ulong arg1)
1450 f1aa6320 ths
{
1451 f1aa6320 ths
    /* vectored interrupts not implemented */
1452 671b0f36 Hervé Poussineau
    env->CP0_EBase = (env->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000);
1453 f1aa6320 ths
}
1454 f1aa6320 ths
1455 895c2d04 Blue Swirl
void helper_mttc0_ebase(CPUMIPSState *env, target_ulong arg1)
1456 5a25ce94 Edgar E. Iglesias
{
1457 5a25ce94 Edgar E. Iglesias
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1458 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1459 5a25ce94 Edgar E. Iglesias
    other->CP0_EBase = (other->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000);
1460 5a25ce94 Edgar E. Iglesias
}
1461 5a25ce94 Edgar E. Iglesias
1462 895c2d04 Blue Swirl
target_ulong helper_mftc0_configx(CPUMIPSState *env, target_ulong idx)
1463 5a25ce94 Edgar E. Iglesias
{
1464 5a25ce94 Edgar E. Iglesias
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1465 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1466 5a25ce94 Edgar E. Iglesias
1467 5a25ce94 Edgar E. Iglesias
    switch (idx) {
1468 5a25ce94 Edgar E. Iglesias
    case 0: return other->CP0_Config0;
1469 5a25ce94 Edgar E. Iglesias
    case 1: return other->CP0_Config1;
1470 5a25ce94 Edgar E. Iglesias
    case 2: return other->CP0_Config2;
1471 5a25ce94 Edgar E. Iglesias
    case 3: return other->CP0_Config3;
1472 5a25ce94 Edgar E. Iglesias
    /* 4 and 5 are reserved.  */
1473 5a25ce94 Edgar E. Iglesias
    case 6: return other->CP0_Config6;
1474 5a25ce94 Edgar E. Iglesias
    case 7: return other->CP0_Config7;
1475 5a25ce94 Edgar E. Iglesias
    default:
1476 5a25ce94 Edgar E. Iglesias
        break;
1477 5a25ce94 Edgar E. Iglesias
    }
1478 5a25ce94 Edgar E. Iglesias
    return 0;
1479 5a25ce94 Edgar E. Iglesias
}
1480 5a25ce94 Edgar E. Iglesias
1481 895c2d04 Blue Swirl
void helper_mtc0_config0(CPUMIPSState *env, target_ulong arg1)
1482 f1aa6320 ths
{
1483 d9bea114 aurel32
    env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (arg1 & 0x00000007);
1484 f1aa6320 ths
}
1485 f1aa6320 ths
1486 895c2d04 Blue Swirl
void helper_mtc0_config2(CPUMIPSState *env, target_ulong arg1)
1487 f1aa6320 ths
{
1488 f1aa6320 ths
    /* tertiary/secondary caches not implemented */
1489 f1aa6320 ths
    env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1490 f1aa6320 ths
}
1491 f1aa6320 ths
1492 895c2d04 Blue Swirl
void helper_mtc0_lladdr(CPUMIPSState *env, target_ulong arg1)
1493 2a6e32dd Aurelien Jarno
{
1494 2a6e32dd Aurelien Jarno
    target_long mask = env->CP0_LLAddr_rw_bitmask;
1495 2a6e32dd Aurelien Jarno
    arg1 = arg1 << env->CP0_LLAddr_shift;
1496 2a6e32dd Aurelien Jarno
    env->lladdr = (env->lladdr & ~mask) | (arg1 & mask);
1497 2a6e32dd Aurelien Jarno
}
1498 2a6e32dd Aurelien Jarno
1499 895c2d04 Blue Swirl
void helper_mtc0_watchlo(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
1500 f1aa6320 ths
{
1501 f1aa6320 ths
    /* Watch exceptions for instructions, data loads, data stores
1502 f1aa6320 ths
       not implemented. */
1503 d9bea114 aurel32
    env->CP0_WatchLo[sel] = (arg1 & ~0x7);
1504 f1aa6320 ths
}
1505 f1aa6320 ths
1506 895c2d04 Blue Swirl
void helper_mtc0_watchhi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
1507 f1aa6320 ths
{
1508 d9bea114 aurel32
    env->CP0_WatchHi[sel] = (arg1 & 0x40FF0FF8);
1509 d9bea114 aurel32
    env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & arg1 & 0x7);
1510 f1aa6320 ths
}
1511 f1aa6320 ths
1512 895c2d04 Blue Swirl
void helper_mtc0_xcontext(CPUMIPSState *env, target_ulong arg1)
1513 f1aa6320 ths
{
1514 f1aa6320 ths
    target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
1515 d9bea114 aurel32
    env->CP0_XContext = (env->CP0_XContext & mask) | (arg1 & ~mask);
1516 f1aa6320 ths
}
1517 f1aa6320 ths
1518 895c2d04 Blue Swirl
void helper_mtc0_framemask(CPUMIPSState *env, target_ulong arg1)
1519 f1aa6320 ths
{
1520 d9bea114 aurel32
    env->CP0_Framemask = arg1; /* XXX */
1521 f1aa6320 ths
}
1522 f1aa6320 ths
1523 895c2d04 Blue Swirl
void helper_mtc0_debug(CPUMIPSState *env, target_ulong arg1)
1524 f1aa6320 ths
{
1525 d9bea114 aurel32
    env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (arg1 & 0x13300120);
1526 d9bea114 aurel32
    if (arg1 & (1 << CP0DB_DM))
1527 f1aa6320 ths
        env->hflags |= MIPS_HFLAG_DM;
1528 f1aa6320 ths
    else
1529 f1aa6320 ths
        env->hflags &= ~MIPS_HFLAG_DM;
1530 f1aa6320 ths
}
1531 f1aa6320 ths
1532 895c2d04 Blue Swirl
void helper_mttc0_debug(CPUMIPSState *env, target_ulong arg1)
1533 f1aa6320 ths
{
1534 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1535 d9bea114 aurel32
    uint32_t val = arg1 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
1536 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1537 f1aa6320 ths
1538 f1aa6320 ths
    /* XXX: Might be wrong, check with EJTAG spec. */
1539 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
1540 b93bbdcd Edgar E. Iglesias
        other->active_tc.CP0_Debug_tcstatus = val;
1541 b5dc7732 ths
    else
1542 b93bbdcd Edgar E. Iglesias
        other->tcs[other_tc].CP0_Debug_tcstatus = val;
1543 b93bbdcd Edgar E. Iglesias
    other->CP0_Debug = (other->CP0_Debug &
1544 b93bbdcd Edgar E. Iglesias
                     ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1545 d9bea114 aurel32
                     (arg1 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1546 f1aa6320 ths
}
1547 f1aa6320 ths
1548 895c2d04 Blue Swirl
void helper_mtc0_performance0(CPUMIPSState *env, target_ulong arg1)
1549 f1aa6320 ths
{
1550 d9bea114 aurel32
    env->CP0_Performance0 = arg1 & 0x000007ff;
1551 f1aa6320 ths
}
1552 f1aa6320 ths
1553 895c2d04 Blue Swirl
void helper_mtc0_taglo(CPUMIPSState *env, target_ulong arg1)
1554 f1aa6320 ths
{
1555 d9bea114 aurel32
    env->CP0_TagLo = arg1 & 0xFFFFFCF6;
1556 f1aa6320 ths
}
1557 f1aa6320 ths
1558 895c2d04 Blue Swirl
void helper_mtc0_datalo(CPUMIPSState *env, target_ulong arg1)
1559 f1aa6320 ths
{
1560 d9bea114 aurel32
    env->CP0_DataLo = arg1; /* XXX */
1561 f1aa6320 ths
}
1562 f1aa6320 ths
1563 895c2d04 Blue Swirl
void helper_mtc0_taghi(CPUMIPSState *env, target_ulong arg1)
1564 f1aa6320 ths
{
1565 d9bea114 aurel32
    env->CP0_TagHi = arg1; /* XXX */
1566 f1aa6320 ths
}
1567 f1aa6320 ths
1568 895c2d04 Blue Swirl
void helper_mtc0_datahi(CPUMIPSState *env, target_ulong arg1)
1569 f1aa6320 ths
{
1570 d9bea114 aurel32
    env->CP0_DataHi = arg1; /* XXX */
1571 f1aa6320 ths
}
1572 f1aa6320 ths
1573 f1aa6320 ths
/* MIPS MT functions */
1574 895c2d04 Blue Swirl
target_ulong helper_mftgpr(CPUMIPSState *env, uint32_t sel)
1575 f1aa6320 ths
{
1576 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1577 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1578 f1aa6320 ths
1579 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
1580 b93bbdcd Edgar E. Iglesias
        return other->active_tc.gpr[sel];
1581 b5dc7732 ths
    else
1582 b93bbdcd Edgar E. Iglesias
        return other->tcs[other_tc].gpr[sel];
1583 f1aa6320 ths
}
1584 f1aa6320 ths
1585 895c2d04 Blue Swirl
target_ulong helper_mftlo(CPUMIPSState *env, uint32_t sel)
1586 f1aa6320 ths
{
1587 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1588 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1589 f1aa6320 ths
1590 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
1591 b93bbdcd Edgar E. Iglesias
        return other->active_tc.LO[sel];
1592 b5dc7732 ths
    else
1593 b93bbdcd Edgar E. Iglesias
        return other->tcs[other_tc].LO[sel];
1594 f1aa6320 ths
}
1595 f1aa6320 ths
1596 895c2d04 Blue Swirl
target_ulong helper_mfthi(CPUMIPSState *env, uint32_t sel)
1597 f1aa6320 ths
{
1598 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1599 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1600 f1aa6320 ths
1601 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
1602 b93bbdcd Edgar E. Iglesias
        return other->active_tc.HI[sel];
1603 b5dc7732 ths
    else
1604 b93bbdcd Edgar E. Iglesias
        return other->tcs[other_tc].HI[sel];
1605 f1aa6320 ths
}
1606 f1aa6320 ths
1607 895c2d04 Blue Swirl
target_ulong helper_mftacx(CPUMIPSState *env, uint32_t sel)
1608 f1aa6320 ths
{
1609 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1610 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1611 f1aa6320 ths
1612 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
1613 b93bbdcd Edgar E. Iglesias
        return other->active_tc.ACX[sel];
1614 b5dc7732 ths
    else
1615 b93bbdcd Edgar E. Iglesias
        return other->tcs[other_tc].ACX[sel];
1616 f1aa6320 ths
}
1617 f1aa6320 ths
1618 895c2d04 Blue Swirl
target_ulong helper_mftdsp(CPUMIPSState *env)
1619 f1aa6320 ths
{
1620 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1621 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1622 f1aa6320 ths
1623 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
1624 b93bbdcd Edgar E. Iglesias
        return other->active_tc.DSPControl;
1625 b5dc7732 ths
    else
1626 b93bbdcd Edgar E. Iglesias
        return other->tcs[other_tc].DSPControl;
1627 f1aa6320 ths
}
1628 6af0bf9c bellard
1629 895c2d04 Blue Swirl
void helper_mttgpr(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
1630 f1aa6320 ths
{
1631 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1632 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1633 f1aa6320 ths
1634 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
1635 b93bbdcd Edgar E. Iglesias
        other->active_tc.gpr[sel] = arg1;
1636 b5dc7732 ths
    else
1637 b93bbdcd Edgar E. Iglesias
        other->tcs[other_tc].gpr[sel] = arg1;
1638 f1aa6320 ths
}
1639 f1aa6320 ths
1640 895c2d04 Blue Swirl
void helper_mttlo(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
1641 f1aa6320 ths
{
1642 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1643 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1644 f1aa6320 ths
1645 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
1646 b93bbdcd Edgar E. Iglesias
        other->active_tc.LO[sel] = arg1;
1647 b5dc7732 ths
    else
1648 b93bbdcd Edgar E. Iglesias
        other->tcs[other_tc].LO[sel] = arg1;
1649 f1aa6320 ths
}
1650 f1aa6320 ths
1651 895c2d04 Blue Swirl
void helper_mtthi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
1652 f1aa6320 ths
{
1653 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1654 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1655 f1aa6320 ths
1656 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
1657 b93bbdcd Edgar E. Iglesias
        other->active_tc.HI[sel] = arg1;
1658 b5dc7732 ths
    else
1659 b93bbdcd Edgar E. Iglesias
        other->tcs[other_tc].HI[sel] = arg1;
1660 f1aa6320 ths
}
1661 f1aa6320 ths
1662 895c2d04 Blue Swirl
void helper_mttacx(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
1663 f1aa6320 ths
{
1664 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1665 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1666 f1aa6320 ths
1667 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
1668 b93bbdcd Edgar E. Iglesias
        other->active_tc.ACX[sel] = arg1;
1669 b5dc7732 ths
    else
1670 b93bbdcd Edgar E. Iglesias
        other->tcs[other_tc].ACX[sel] = arg1;
1671 f1aa6320 ths
}
1672 f1aa6320 ths
1673 895c2d04 Blue Swirl
void helper_mttdsp(CPUMIPSState *env, target_ulong arg1)
1674 f1aa6320 ths
{
1675 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1676 895c2d04 Blue Swirl
    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1677 f1aa6320 ths
1678 b93bbdcd Edgar E. Iglesias
    if (other_tc == other->current_tc)
1679 b93bbdcd Edgar E. Iglesias
        other->active_tc.DSPControl = arg1;
1680 b5dc7732 ths
    else
1681 b93bbdcd Edgar E. Iglesias
        other->tcs[other_tc].DSPControl = arg1;
1682 f1aa6320 ths
}
1683 f1aa6320 ths
1684 f1aa6320 ths
/* MIPS MT functions */
1685 9ed5726c Nathan Froyd
target_ulong helper_dmt(void)
1686 f1aa6320 ths
{
1687 f1aa6320 ths
    // TODO
1688 9ed5726c Nathan Froyd
     return 0;
1689 f1aa6320 ths
}
1690 f1aa6320 ths
1691 9ed5726c Nathan Froyd
target_ulong helper_emt(void)
1692 f1aa6320 ths
{
1693 f1aa6320 ths
    // TODO
1694 9ed5726c Nathan Froyd
    return 0;
1695 f1aa6320 ths
}
1696 f1aa6320 ths
1697 895c2d04 Blue Swirl
target_ulong helper_dvpe(CPUMIPSState *env)
1698 f1aa6320 ths
{
1699 81bad50e Andreas Färber
    CPUMIPSState *other_cpu_env = first_cpu;
1700 f249412c Edgar E. Iglesias
    target_ulong prev = env->mvp->CP0_MVPControl;
1701 f249412c Edgar E. Iglesias
1702 f249412c Edgar E. Iglesias
    do {
1703 f249412c Edgar E. Iglesias
        /* Turn off all VPEs except the one executing the dvpe.  */
1704 81bad50e Andreas Färber
        if (other_cpu_env != env) {
1705 6f4d6b09 Andreas Färber
            MIPSCPU *other_cpu = mips_env_get_cpu(other_cpu_env);
1706 6f4d6b09 Andreas Färber
1707 81bad50e Andreas Färber
            other_cpu_env->mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP);
1708 6f4d6b09 Andreas Färber
            mips_vpe_sleep(other_cpu);
1709 f249412c Edgar E. Iglesias
        }
1710 81bad50e Andreas Färber
        other_cpu_env = other_cpu_env->next_cpu;
1711 81bad50e Andreas Färber
    } while (other_cpu_env);
1712 f249412c Edgar E. Iglesias
    return prev;
1713 f1aa6320 ths
}
1714 f1aa6320 ths
1715 895c2d04 Blue Swirl
target_ulong helper_evpe(CPUMIPSState *env)
1716 f1aa6320 ths
{
1717 81bad50e Andreas Färber
    CPUMIPSState *other_cpu_env = first_cpu;
1718 f249412c Edgar E. Iglesias
    target_ulong prev = env->mvp->CP0_MVPControl;
1719 f249412c Edgar E. Iglesias
1720 f249412c Edgar E. Iglesias
    do {
1721 b35d77d7 Andreas Färber
        MIPSCPU *other_cpu = mips_env_get_cpu(other_cpu_env);
1722 b35d77d7 Andreas Färber
1723 81bad50e Andreas Färber
        if (other_cpu_env != env
1724 81bad50e Andreas Färber
            /* If the VPE is WFI, don't disturb its sleep.  */
1725 b35d77d7 Andreas Färber
            && !mips_vpe_is_wfi(other_cpu)) {
1726 f249412c Edgar E. Iglesias
            /* Enable the VPE.  */
1727 81bad50e Andreas Färber
            other_cpu_env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
1728 c3affe56 Andreas Färber
            mips_vpe_wake(other_cpu); /* And wake it up.  */
1729 f249412c Edgar E. Iglesias
        }
1730 81bad50e Andreas Färber
        other_cpu_env = other_cpu_env->next_cpu;
1731 81bad50e Andreas Färber
    } while (other_cpu_env);
1732 f249412c Edgar E. Iglesias
    return prev;
1733 f1aa6320 ths
}
1734 f9480ffc ths
#endif /* !CONFIG_USER_ONLY */
1735 f1aa6320 ths
1736 d9bea114 aurel32
void helper_fork(target_ulong arg1, target_ulong arg2)
1737 f1aa6320 ths
{
1738 d9bea114 aurel32
    // arg1 = rt, arg2 = rs
1739 d9bea114 aurel32
    arg1 = 0;
1740 f1aa6320 ths
    // TODO: store to TC register
1741 f1aa6320 ths
}
1742 f1aa6320 ths
1743 895c2d04 Blue Swirl
target_ulong helper_yield(CPUMIPSState *env, target_ulong arg)
1744 f1aa6320 ths
{
1745 1c7242da Blue Swirl
    target_long arg1 = arg;
1746 1c7242da Blue Swirl
1747 d9bea114 aurel32
    if (arg1 < 0) {
1748 f1aa6320 ths
        /* No scheduling policy implemented. */
1749 d9bea114 aurel32
        if (arg1 != -2) {
1750 f1aa6320 ths
            if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
1751 b5dc7732 ths
                env->active_tc.CP0_TCStatus & (1 << CP0TCSt_DT)) {
1752 f1aa6320 ths
                env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1753 f1aa6320 ths
                env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
1754 895c2d04 Blue Swirl
                helper_raise_exception(env, EXCP_THREAD);
1755 f1aa6320 ths
            }
1756 f1aa6320 ths
        }
1757 d9bea114 aurel32
    } else if (arg1 == 0) {
1758 6958549d aurel32
        if (0 /* TODO: TC underflow */) {
1759 f1aa6320 ths
            env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1760 895c2d04 Blue Swirl
            helper_raise_exception(env, EXCP_THREAD);
1761 f1aa6320 ths
        } else {
1762 f1aa6320 ths
            // TODO: Deallocate TC
1763 f1aa6320 ths
        }
1764 d9bea114 aurel32
    } else if (arg1 > 0) {
1765 f1aa6320 ths
        /* Yield qualifier inputs not implemented. */
1766 f1aa6320 ths
        env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1767 f1aa6320 ths
        env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
1768 895c2d04 Blue Swirl
        helper_raise_exception(env, EXCP_THREAD);
1769 f1aa6320 ths
    }
1770 be24bb4f ths
    return env->CP0_YQMask;
1771 f1aa6320 ths
}
1772 f1aa6320 ths
1773 f1aa6320 ths
#ifndef CONFIG_USER_ONLY
1774 6af0bf9c bellard
/* TLB management */
1775 7db13fae Andreas Färber
static void cpu_mips_tlb_flush (CPUMIPSState *env, int flush_global)
1776 814b9a47 ths
{
1777 814b9a47 ths
    /* Flush qemu's TLB and discard all shadowed entries.  */
1778 814b9a47 ths
    tlb_flush (env, flush_global);
1779 ead9360e ths
    env->tlb->tlb_in_use = env->tlb->nb_tlb;
1780 814b9a47 ths
}
1781 814b9a47 ths
1782 7db13fae Andreas Färber
static void r4k_mips_tlb_flush_extra (CPUMIPSState *env, int first)
1783 814b9a47 ths
{
1784 814b9a47 ths
    /* Discard entries from env->tlb[first] onwards.  */
1785 ead9360e ths
    while (env->tlb->tlb_in_use > first) {
1786 ead9360e ths
        r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0);
1787 814b9a47 ths
    }
1788 814b9a47 ths
}
1789 814b9a47 ths
1790 895c2d04 Blue Swirl
static void r4k_fill_tlb(CPUMIPSState *env, int idx)
1791 6af0bf9c bellard
{
1792 c227f099 Anthony Liguori
    r4k_tlb_t *tlb;
1793 6af0bf9c bellard
1794 6af0bf9c bellard
    /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
1795 ead9360e ths
    tlb = &env->tlb->mmu.r4k.tlb[idx];
1796 f2e9ebef ths
    tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
1797 d26bc211 ths
#if defined(TARGET_MIPS64)
1798 e034e2c3 ths
    tlb->VPN &= env->SEGMask;
1799 100ce988 ths
#endif
1800 98c1b82b pbrook
    tlb->ASID = env->CP0_EntryHi & 0xFF;
1801 3b1c8be4 ths
    tlb->PageMask = env->CP0_PageMask;
1802 6af0bf9c bellard
    tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
1803 98c1b82b pbrook
    tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
1804 98c1b82b pbrook
    tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
1805 98c1b82b pbrook
    tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
1806 6af0bf9c bellard
    tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
1807 98c1b82b pbrook
    tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
1808 98c1b82b pbrook
    tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
1809 98c1b82b pbrook
    tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
1810 6af0bf9c bellard
    tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
1811 6af0bf9c bellard
}
1812 6af0bf9c bellard
1813 895c2d04 Blue Swirl
void r4k_helper_tlbwi(CPUMIPSState *env)
1814 6af0bf9c bellard
{
1815 286d52eb Aurelien Jarno
    r4k_tlb_t *tlb;
1816 bbc0d79c aurel32
    int idx;
1817 286d52eb Aurelien Jarno
    target_ulong VPN;
1818 286d52eb Aurelien Jarno
    uint8_t ASID;
1819 286d52eb Aurelien Jarno
    bool G, V0, D0, V1, D1;
1820 bbc0d79c aurel32
1821 bbc0d79c aurel32
    idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
1822 286d52eb Aurelien Jarno
    tlb = &env->tlb->mmu.r4k.tlb[idx];
1823 286d52eb Aurelien Jarno
    VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
1824 286d52eb Aurelien Jarno
#if defined(TARGET_MIPS64)
1825 286d52eb Aurelien Jarno
    VPN &= env->SEGMask;
1826 286d52eb Aurelien Jarno
#endif
1827 286d52eb Aurelien Jarno
    ASID = env->CP0_EntryHi & 0xff;
1828 286d52eb Aurelien Jarno
    G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
1829 286d52eb Aurelien Jarno
    V0 = (env->CP0_EntryLo0 & 2) != 0;
1830 286d52eb Aurelien Jarno
    D0 = (env->CP0_EntryLo0 & 4) != 0;
1831 286d52eb Aurelien Jarno
    V1 = (env->CP0_EntryLo1 & 2) != 0;
1832 286d52eb Aurelien Jarno
    D1 = (env->CP0_EntryLo1 & 4) != 0;
1833 286d52eb Aurelien Jarno
1834 286d52eb Aurelien Jarno
    /* Discard cached TLB entries, unless tlbwi is just upgrading access
1835 286d52eb Aurelien Jarno
       permissions on the current entry. */
1836 286d52eb Aurelien Jarno
    if (tlb->VPN != VPN || tlb->ASID != ASID || tlb->G != G ||
1837 286d52eb Aurelien Jarno
        (tlb->V0 && !V0) || (tlb->D0 && !D0) ||
1838 286d52eb Aurelien Jarno
        (tlb->V1 && !V1) || (tlb->D1 && !D1)) {
1839 286d52eb Aurelien Jarno
        r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
1840 286d52eb Aurelien Jarno
    }
1841 814b9a47 ths
1842 bbc0d79c aurel32
    r4k_invalidate_tlb(env, idx, 0);
1843 895c2d04 Blue Swirl
    r4k_fill_tlb(env, idx);
1844 6af0bf9c bellard
}
1845 6af0bf9c bellard
1846 895c2d04 Blue Swirl
void r4k_helper_tlbwr(CPUMIPSState *env)
1847 6af0bf9c bellard
{
1848 6af0bf9c bellard
    int r = cpu_mips_get_random(env);
1849 6af0bf9c bellard
1850 29929e34 ths
    r4k_invalidate_tlb(env, r, 1);
1851 895c2d04 Blue Swirl
    r4k_fill_tlb(env, r);
1852 6af0bf9c bellard
}
1853 6af0bf9c bellard
1854 895c2d04 Blue Swirl
void r4k_helper_tlbp(CPUMIPSState *env)
1855 6af0bf9c bellard
{
1856 c227f099 Anthony Liguori
    r4k_tlb_t *tlb;
1857 f2e9ebef ths
    target_ulong mask;
1858 6af0bf9c bellard
    target_ulong tag;
1859 f2e9ebef ths
    target_ulong VPN;
1860 6af0bf9c bellard
    uint8_t ASID;
1861 6af0bf9c bellard
    int i;
1862 6af0bf9c bellard
1863 3d9fb9fe bellard
    ASID = env->CP0_EntryHi & 0xFF;
1864 ead9360e ths
    for (i = 0; i < env->tlb->nb_tlb; i++) {
1865 ead9360e ths
        tlb = &env->tlb->mmu.r4k.tlb[i];
1866 f2e9ebef ths
        /* 1k pages are not supported. */
1867 f2e9ebef ths
        mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
1868 f2e9ebef ths
        tag = env->CP0_EntryHi & ~mask;
1869 f2e9ebef ths
        VPN = tlb->VPN & ~mask;
1870 bc3e45e1 Aurelien Jarno
#if defined(TARGET_MIPS64)
1871 bc3e45e1 Aurelien Jarno
        tag &= env->SEGMask;
1872 bc3e45e1 Aurelien Jarno
#endif
1873 6af0bf9c bellard
        /* Check ASID, virtual page number & size */
1874 f2e9ebef ths
        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1875 6af0bf9c bellard
            /* TLB match */
1876 9c2149c8 ths
            env->CP0_Index = i;
1877 6af0bf9c bellard
            break;
1878 6af0bf9c bellard
        }
1879 6af0bf9c bellard
    }
1880 ead9360e ths
    if (i == env->tlb->nb_tlb) {
1881 814b9a47 ths
        /* No match.  Discard any shadow entries, if any of them match.  */
1882 ead9360e ths
        for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) {
1883 6958549d aurel32
            tlb = &env->tlb->mmu.r4k.tlb[i];
1884 6958549d aurel32
            /* 1k pages are not supported. */
1885 6958549d aurel32
            mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
1886 6958549d aurel32
            tag = env->CP0_EntryHi & ~mask;
1887 6958549d aurel32
            VPN = tlb->VPN & ~mask;
1888 bc3e45e1 Aurelien Jarno
#if defined(TARGET_MIPS64)
1889 bc3e45e1 Aurelien Jarno
            tag &= env->SEGMask;
1890 bc3e45e1 Aurelien Jarno
#endif
1891 6958549d aurel32
            /* Check ASID, virtual page number & size */
1892 6958549d aurel32
            if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1893 29929e34 ths
                r4k_mips_tlb_flush_extra (env, i);
1894 6958549d aurel32
                break;
1895 6958549d aurel32
            }
1896 6958549d aurel32
        }
1897 814b9a47 ths
1898 9c2149c8 ths
        env->CP0_Index |= 0x80000000;
1899 6af0bf9c bellard
    }
1900 6af0bf9c bellard
}
1901 6af0bf9c bellard
1902 895c2d04 Blue Swirl
void r4k_helper_tlbr(CPUMIPSState *env)
1903 6af0bf9c bellard
{
1904 c227f099 Anthony Liguori
    r4k_tlb_t *tlb;
1905 09c56b84 pbrook
    uint8_t ASID;
1906 bbc0d79c aurel32
    int idx;
1907 6af0bf9c bellard
1908 09c56b84 pbrook
    ASID = env->CP0_EntryHi & 0xFF;
1909 bbc0d79c aurel32
    idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
1910 bbc0d79c aurel32
    tlb = &env->tlb->mmu.r4k.tlb[idx];
1911 4ad40f36 bellard
1912 4ad40f36 bellard
    /* If this will change the current ASID, flush qemu's TLB.  */
1913 814b9a47 ths
    if (ASID != tlb->ASID)
1914 814b9a47 ths
        cpu_mips_tlb_flush (env, 1);
1915 814b9a47 ths
1916 ead9360e ths
    r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
1917 4ad40f36 bellard
1918 6af0bf9c bellard
    env->CP0_EntryHi = tlb->VPN | tlb->ASID;
1919 3b1c8be4 ths
    env->CP0_PageMask = tlb->PageMask;
1920 7495fd0f ths
    env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
1921 7495fd0f ths
                        (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
1922 7495fd0f ths
    env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
1923 7495fd0f ths
                        (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
1924 6af0bf9c bellard
}
1925 6af0bf9c bellard
1926 895c2d04 Blue Swirl
void helper_tlbwi(CPUMIPSState *env)
1927 a7812ae4 pbrook
{
1928 895c2d04 Blue Swirl
    env->tlb->helper_tlbwi(env);
1929 a7812ae4 pbrook
}
1930 a7812ae4 pbrook
1931 895c2d04 Blue Swirl
void helper_tlbwr(CPUMIPSState *env)
1932 a7812ae4 pbrook
{
1933 895c2d04 Blue Swirl
    env->tlb->helper_tlbwr(env);
1934 a7812ae4 pbrook
}
1935 a7812ae4 pbrook
1936 895c2d04 Blue Swirl
void helper_tlbp(CPUMIPSState *env)
1937 a7812ae4 pbrook
{
1938 895c2d04 Blue Swirl
    env->tlb->helper_tlbp(env);
1939 a7812ae4 pbrook
}
1940 a7812ae4 pbrook
1941 895c2d04 Blue Swirl
void helper_tlbr(CPUMIPSState *env)
1942 a7812ae4 pbrook
{
1943 895c2d04 Blue Swirl
    env->tlb->helper_tlbr(env);
1944 a7812ae4 pbrook
}
1945 a7812ae4 pbrook
1946 2b0233ab ths
/* Specials */
1947 895c2d04 Blue Swirl
target_ulong helper_di(CPUMIPSState *env)
1948 2b0233ab ths
{
1949 2796188e ths
    target_ulong t0 = env->CP0_Status;
1950 2796188e ths
1951 be24bb4f ths
    env->CP0_Status = t0 & ~(1 << CP0St_IE);
1952 be24bb4f ths
    return t0;
1953 2b0233ab ths
}
1954 2b0233ab ths
1955 895c2d04 Blue Swirl
target_ulong helper_ei(CPUMIPSState *env)
1956 2b0233ab ths
{
1957 2796188e ths
    target_ulong t0 = env->CP0_Status;
1958 2796188e ths
1959 be24bb4f ths
    env->CP0_Status = t0 | (1 << CP0St_IE);
1960 be24bb4f ths
    return t0;
1961 2b0233ab ths
}
1962 2b0233ab ths
1963 895c2d04 Blue Swirl
static void debug_pre_eret(CPUMIPSState *env)
1964 6af0bf9c bellard
{
1965 8fec2b8c aliguori
    if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
1966 93fcfe39 aliguori
        qemu_log("ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
1967 93fcfe39 aliguori
                env->active_tc.PC, env->CP0_EPC);
1968 93fcfe39 aliguori
        if (env->CP0_Status & (1 << CP0St_ERL))
1969 93fcfe39 aliguori
            qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
1970 93fcfe39 aliguori
        if (env->hflags & MIPS_HFLAG_DM)
1971 93fcfe39 aliguori
            qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
1972 93fcfe39 aliguori
        qemu_log("\n");
1973 93fcfe39 aliguori
    }
1974 f41c52f1 ths
}
1975 f41c52f1 ths
1976 895c2d04 Blue Swirl
static void debug_post_eret(CPUMIPSState *env)
1977 f41c52f1 ths
{
1978 8fec2b8c aliguori
    if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
1979 93fcfe39 aliguori
        qemu_log("  =>  PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
1980 93fcfe39 aliguori
                env->active_tc.PC, env->CP0_EPC);
1981 93fcfe39 aliguori
        if (env->CP0_Status & (1 << CP0St_ERL))
1982 93fcfe39 aliguori
            qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
1983 93fcfe39 aliguori
        if (env->hflags & MIPS_HFLAG_DM)
1984 93fcfe39 aliguori
            qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
1985 93fcfe39 aliguori
        switch (env->hflags & MIPS_HFLAG_KSU) {
1986 93fcfe39 aliguori
        case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
1987 93fcfe39 aliguori
        case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
1988 93fcfe39 aliguori
        case MIPS_HFLAG_KM: qemu_log("\n"); break;
1989 93fcfe39 aliguori
        default: cpu_abort(env, "Invalid MMU mode!\n"); break;
1990 93fcfe39 aliguori
        }
1991 623a930e ths
    }
1992 6af0bf9c bellard
}
1993 6af0bf9c bellard
1994 895c2d04 Blue Swirl
static void set_pc(CPUMIPSState *env, target_ulong error_pc)
1995 32188a03 Nathan Froyd
{
1996 32188a03 Nathan Froyd
    env->active_tc.PC = error_pc & ~(target_ulong)1;
1997 32188a03 Nathan Froyd
    if (error_pc & 1) {
1998 32188a03 Nathan Froyd
        env->hflags |= MIPS_HFLAG_M16;
1999 32188a03 Nathan Froyd
    } else {
2000 32188a03 Nathan Froyd
        env->hflags &= ~(MIPS_HFLAG_M16);
2001 32188a03 Nathan Froyd
    }
2002 32188a03 Nathan Froyd
}
2003 32188a03 Nathan Froyd
2004 895c2d04 Blue Swirl
void helper_eret(CPUMIPSState *env)
2005 2b0233ab ths
{
2006 895c2d04 Blue Swirl
    debug_pre_eret(env);
2007 2b0233ab ths
    if (env->CP0_Status & (1 << CP0St_ERL)) {
2008 895c2d04 Blue Swirl
        set_pc(env, env->CP0_ErrorEPC);
2009 2b0233ab ths
        env->CP0_Status &= ~(1 << CP0St_ERL);
2010 2b0233ab ths
    } else {
2011 895c2d04 Blue Swirl
        set_pc(env, env->CP0_EPC);
2012 2b0233ab ths
        env->CP0_Status &= ~(1 << CP0St_EXL);
2013 2b0233ab ths
    }
2014 2b0233ab ths
    compute_hflags(env);
2015 895c2d04 Blue Swirl
    debug_post_eret(env);
2016 5499b6ff Aurelien Jarno
    env->lladdr = 1;
2017 2b0233ab ths
}
2018 2b0233ab ths
2019 895c2d04 Blue Swirl
void helper_deret(CPUMIPSState *env)
2020 2b0233ab ths
{
2021 895c2d04 Blue Swirl
    debug_pre_eret(env);
2022 895c2d04 Blue Swirl
    set_pc(env, env->CP0_DEPC);
2023 32188a03 Nathan Froyd
2024 2b0233ab ths
    env->hflags &= MIPS_HFLAG_DM;
2025 2b0233ab ths
    compute_hflags(env);
2026 895c2d04 Blue Swirl
    debug_post_eret(env);
2027 5499b6ff Aurelien Jarno
    env->lladdr = 1;
2028 2b0233ab ths
}
2029 0eaef5aa ths
#endif /* !CONFIG_USER_ONLY */
2030 2b0233ab ths
2031 895c2d04 Blue Swirl
target_ulong helper_rdhwr_cpunum(CPUMIPSState *env)
2032 2b0233ab ths
{
2033 2b0233ab ths
    if ((env->hflags & MIPS_HFLAG_CP0) ||
2034 2b0233ab ths
        (env->CP0_HWREna & (1 << 0)))
2035 2796188e ths
        return env->CP0_EBase & 0x3ff;
2036 2b0233ab ths
    else
2037 895c2d04 Blue Swirl
        helper_raise_exception(env, EXCP_RI);
2038 be24bb4f ths
2039 2796188e ths
    return 0;
2040 2b0233ab ths
}
2041 2b0233ab ths
2042 895c2d04 Blue Swirl
target_ulong helper_rdhwr_synci_step(CPUMIPSState *env)
2043 2b0233ab ths
{
2044 2b0233ab ths
    if ((env->hflags & MIPS_HFLAG_CP0) ||
2045 2b0233ab ths
        (env->CP0_HWREna & (1 << 1)))
2046 2796188e ths
        return env->SYNCI_Step;
2047 2b0233ab ths
    else
2048 895c2d04 Blue Swirl
        helper_raise_exception(env, EXCP_RI);
2049 be24bb4f ths
2050 2796188e ths
    return 0;
2051 2b0233ab ths
}
2052 2b0233ab ths
2053 895c2d04 Blue Swirl
target_ulong helper_rdhwr_cc(CPUMIPSState *env)
2054 2b0233ab ths
{
2055 2b0233ab ths
    if ((env->hflags & MIPS_HFLAG_CP0) ||
2056 2b0233ab ths
        (env->CP0_HWREna & (1 << 2)))
2057 2796188e ths
        return env->CP0_Count;
2058 2b0233ab ths
    else
2059 895c2d04 Blue Swirl
        helper_raise_exception(env, EXCP_RI);
2060 be24bb4f ths
2061 2796188e ths
    return 0;
2062 2b0233ab ths
}
2063 2b0233ab ths
2064 895c2d04 Blue Swirl
target_ulong helper_rdhwr_ccres(CPUMIPSState *env)
2065 2b0233ab ths
{
2066 2b0233ab ths
    if ((env->hflags & MIPS_HFLAG_CP0) ||
2067 2b0233ab ths
        (env->CP0_HWREna & (1 << 3)))
2068 2796188e ths
        return env->CCRes;
2069 2b0233ab ths
    else
2070 895c2d04 Blue Swirl
        helper_raise_exception(env, EXCP_RI);
2071 be24bb4f ths
2072 2796188e ths
    return 0;
2073 2b0233ab ths
}
2074 2b0233ab ths
2075 895c2d04 Blue Swirl
void helper_pmon(CPUMIPSState *env, int function)
2076 6af0bf9c bellard
{
2077 6af0bf9c bellard
    function /= 2;
2078 6af0bf9c bellard
    switch (function) {
2079 6af0bf9c bellard
    case 2: /* TODO: char inbyte(int waitflag); */
2080 b5dc7732 ths
        if (env->active_tc.gpr[4] == 0)
2081 b5dc7732 ths
            env->active_tc.gpr[2] = -1;
2082 6af0bf9c bellard
        /* Fall through */
2083 6af0bf9c bellard
    case 11: /* TODO: char inbyte (void); */
2084 b5dc7732 ths
        env->active_tc.gpr[2] = -1;
2085 6af0bf9c bellard
        break;
2086 6af0bf9c bellard
    case 3:
2087 6af0bf9c bellard
    case 12:
2088 b5dc7732 ths
        printf("%c", (char)(env->active_tc.gpr[4] & 0xFF));
2089 6af0bf9c bellard
        break;
2090 6af0bf9c bellard
    case 17:
2091 6af0bf9c bellard
        break;
2092 6af0bf9c bellard
    case 158:
2093 6af0bf9c bellard
        {
2094 b69e48a8 Stefan Weil
            unsigned char *fmt = (void *)(uintptr_t)env->active_tc.gpr[4];
2095 6af0bf9c bellard
            printf("%s", fmt);
2096 6af0bf9c bellard
        }
2097 6af0bf9c bellard
        break;
2098 6af0bf9c bellard
    }
2099 6af0bf9c bellard
}
2100 e37e863f bellard
2101 895c2d04 Blue Swirl
void helper_wait(CPUMIPSState *env)
2102 08ba7963 ths
{
2103 259186a7 Andreas Färber
    CPUState *cs = CPU(mips_env_get_cpu(env));
2104 259186a7 Andreas Färber
2105 259186a7 Andreas Färber
    cs->halted = 1;
2106 d8ed887b Andreas Färber
    cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
2107 895c2d04 Blue Swirl
    helper_raise_exception(env, EXCP_HLT);
2108 08ba7963 ths
}
2109 08ba7963 ths
2110 5fafdf24 ths
#if !defined(CONFIG_USER_ONLY)
2111 e37e863f bellard
2112 895c2d04 Blue Swirl
static void QEMU_NORETURN do_unaligned_access(CPUMIPSState *env,
2113 895c2d04 Blue Swirl
                                              target_ulong addr, int is_write,
2114 20503968 Blue Swirl
                                              int is_user, uintptr_t retaddr);
2115 4ad40f36 bellard
2116 e37e863f bellard
#define MMUSUFFIX _mmu
2117 4ad40f36 bellard
#define ALIGNED_ONLY
2118 e37e863f bellard
2119 e37e863f bellard
#define SHIFT 0
2120 022c62cb Paolo Bonzini
#include "exec/softmmu_template.h"
2121 e37e863f bellard
2122 e37e863f bellard
#define SHIFT 1
2123 022c62cb Paolo Bonzini
#include "exec/softmmu_template.h"
2124 e37e863f bellard
2125 e37e863f bellard
#define SHIFT 2
2126 022c62cb Paolo Bonzini
#include "exec/softmmu_template.h"
2127 e37e863f bellard
2128 e37e863f bellard
#define SHIFT 3
2129 022c62cb Paolo Bonzini
#include "exec/softmmu_template.h"
2130 e37e863f bellard
2131 895c2d04 Blue Swirl
static void do_unaligned_access(CPUMIPSState *env, target_ulong addr,
2132 895c2d04 Blue Swirl
                                int is_write, int is_user, uintptr_t retaddr)
2133 4ad40f36 bellard
{
2134 4ad40f36 bellard
    env->CP0_BadVAddr = addr;
2135 5f7319cd Aurelien Jarno
    do_raise_exception(env, (is_write == 1) ? EXCP_AdES : EXCP_AdEL, retaddr);
2136 4ad40f36 bellard
}
2137 4ad40f36 bellard
2138 895c2d04 Blue Swirl
void tlb_fill(CPUMIPSState *env, target_ulong addr, int is_write, int mmu_idx,
2139 20503968 Blue Swirl
              uintptr_t retaddr)
2140 e37e863f bellard
{
2141 e37e863f bellard
    int ret;
2142 e37e863f bellard
2143 97b348e7 Blue Swirl
    ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx);
2144 e37e863f bellard
    if (ret) {
2145 5f7319cd Aurelien Jarno
        do_raise_exception_err(env, env->exception_index,
2146 5f7319cd Aurelien Jarno
                               env->error_code, retaddr);
2147 e37e863f bellard
    }
2148 e37e863f bellard
}
2149 e37e863f bellard
2150 c658b94f Andreas Färber
void mips_cpu_unassigned_access(CPUState *cs, hwaddr addr,
2151 c658b94f Andreas Färber
                                bool is_write, bool is_exec, int unused,
2152 c658b94f Andreas Färber
                                unsigned size)
2153 647de6ca ths
{
2154 c658b94f Andreas Färber
    MIPSCPU *cpu = MIPS_CPU(cs);
2155 c658b94f Andreas Färber
    CPUMIPSState *env = &cpu->env;
2156 c658b94f Andreas Färber
2157 c658b94f Andreas Färber
    if (is_exec) {
2158 895c2d04 Blue Swirl
        helper_raise_exception(env, EXCP_IBE);
2159 c658b94f Andreas Färber
    } else {
2160 895c2d04 Blue Swirl
        helper_raise_exception(env, EXCP_DBE);
2161 c658b94f Andreas Färber
    }
2162 647de6ca ths
}
2163 f1aa6320 ths
#endif /* !CONFIG_USER_ONLY */
2164 fd4a04eb ths
2165 fd4a04eb ths
/* Complex FPU operations which may need stack space. */
2166 fd4a04eb ths
2167 f090c9d4 pbrook
#define FLOAT_TWO32 make_float32(1 << 30)
2168 f090c9d4 pbrook
#define FLOAT_TWO64 make_float64(1ULL << 62)
2169 05993cd0 Aurelien Jarno
#define FP_TO_INT32_OVERFLOW 0x7fffffff
2170 05993cd0 Aurelien Jarno
#define FP_TO_INT64_OVERFLOW 0x7fffffffffffffffULL
2171 8dfdb87c ths
2172 fd4a04eb ths
/* convert MIPS rounding mode in FCR31 to IEEE library */
2173 6f4fc367 Blue Swirl
static unsigned int ieee_rm[] = {
2174 fd4a04eb ths
    float_round_nearest_even,
2175 fd4a04eb ths
    float_round_to_zero,
2176 fd4a04eb ths
    float_round_up,
2177 fd4a04eb ths
    float_round_down
2178 fd4a04eb ths
};
2179 fd4a04eb ths
2180 e320d05a Stefan Weil
static inline void restore_rounding_mode(CPUMIPSState *env)
2181 e320d05a Stefan Weil
{
2182 e320d05a Stefan Weil
    set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3],
2183 e320d05a Stefan Weil
                            &env->active_fpu.fp_status);
2184 e320d05a Stefan Weil
}
2185 fd4a04eb ths
2186 e320d05a Stefan Weil
static inline void restore_flush_mode(CPUMIPSState *env)
2187 e320d05a Stefan Weil
{
2188 e320d05a Stefan Weil
    set_flush_to_zero((env->active_fpu.fcr31 & (1 << 24)) != 0,
2189 e320d05a Stefan Weil
                      &env->active_fpu.fp_status);
2190 e320d05a Stefan Weil
}
2191 41e0c701 aurel32
2192 895c2d04 Blue Swirl
target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg)
2193 fd4a04eb ths
{
2194 d9bea114 aurel32
    target_ulong arg1;
2195 6c5c1e20 ths
2196 ead9360e ths
    switch (reg) {
2197 ead9360e ths
    case 0:
2198 d9bea114 aurel32
        arg1 = (int32_t)env->active_fpu.fcr0;
2199 ead9360e ths
        break;
2200 ead9360e ths
    case 25:
2201 d9bea114 aurel32
        arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | ((env->active_fpu.fcr31 >> 23) & 0x1);
2202 ead9360e ths
        break;
2203 ead9360e ths
    case 26:
2204 d9bea114 aurel32
        arg1 = env->active_fpu.fcr31 & 0x0003f07c;
2205 ead9360e ths
        break;
2206 ead9360e ths
    case 28:
2207 d9bea114 aurel32
        arg1 = (env->active_fpu.fcr31 & 0x00000f83) | ((env->active_fpu.fcr31 >> 22) & 0x4);
2208 ead9360e ths
        break;
2209 ead9360e ths
    default:
2210 d9bea114 aurel32
        arg1 = (int32_t)env->active_fpu.fcr31;
2211 ead9360e ths
        break;
2212 ead9360e ths
    }
2213 be24bb4f ths
2214 d9bea114 aurel32
    return arg1;
2215 ead9360e ths
}
2216 ead9360e ths
2217 895c2d04 Blue Swirl
void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t reg)
2218 ead9360e ths
{
2219 ead9360e ths
    switch(reg) {
2220 fd4a04eb ths
    case 25:
2221 d9bea114 aurel32
        if (arg1 & 0xffffff00)
2222 fd4a04eb ths
            return;
2223 d9bea114 aurel32
        env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) | ((arg1 & 0xfe) << 24) |
2224 d9bea114 aurel32
                     ((arg1 & 0x1) << 23);
2225 fd4a04eb ths
        break;
2226 fd4a04eb ths
    case 26:
2227 d9bea114 aurel32
        if (arg1 & 0x007c0000)
2228 fd4a04eb ths
            return;
2229 d9bea114 aurel32
        env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfffc0f83) | (arg1 & 0x0003f07c);
2230 fd4a04eb ths
        break;
2231 fd4a04eb ths
    case 28:
2232 d9bea114 aurel32
        if (arg1 & 0x007c0000)
2233 fd4a04eb ths
            return;
2234 d9bea114 aurel32
        env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfefff07c) | (arg1 & 0x00000f83) |
2235 d9bea114 aurel32
                     ((arg1 & 0x4) << 22);
2236 fd4a04eb ths
        break;
2237 fd4a04eb ths
    case 31:
2238 d9bea114 aurel32
        if (arg1 & 0x007c0000)
2239 fd4a04eb ths
            return;
2240 d9bea114 aurel32
        env->active_fpu.fcr31 = arg1;
2241 fd4a04eb ths
        break;
2242 fd4a04eb ths
    default:
2243 fd4a04eb ths
        return;
2244 fd4a04eb ths
    }
2245 fd4a04eb ths
    /* set rounding mode */
2246 e320d05a Stefan Weil
    restore_rounding_mode(env);
2247 41e0c701 aurel32
    /* set flush-to-zero mode */
2248 e320d05a Stefan Weil
    restore_flush_mode(env);
2249 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2250 f01be154 ths
    if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & GET_FP_CAUSE(env->active_fpu.fcr31))
2251 5f7319cd Aurelien Jarno
        do_raise_exception(env, EXCP_FPE, GETPC());
2252 fd4a04eb ths
}
2253 fd4a04eb ths
2254 353ebb7a Aurelien Jarno
static inline int ieee_ex_to_mips(int xcpt)
2255 fd4a04eb ths
{
2256 353ebb7a Aurelien Jarno
    int ret = 0;
2257 353ebb7a Aurelien Jarno
    if (xcpt) {
2258 353ebb7a Aurelien Jarno
        if (xcpt & float_flag_invalid) {
2259 353ebb7a Aurelien Jarno
            ret |= FP_INVALID;
2260 353ebb7a Aurelien Jarno
        }
2261 353ebb7a Aurelien Jarno
        if (xcpt & float_flag_overflow) {
2262 353ebb7a Aurelien Jarno
            ret |= FP_OVERFLOW;
2263 353ebb7a Aurelien Jarno
        }
2264 353ebb7a Aurelien Jarno
        if (xcpt & float_flag_underflow) {
2265 353ebb7a Aurelien Jarno
            ret |= FP_UNDERFLOW;
2266 353ebb7a Aurelien Jarno
        }
2267 353ebb7a Aurelien Jarno
        if (xcpt & float_flag_divbyzero) {
2268 353ebb7a Aurelien Jarno
            ret |= FP_DIV0;
2269 353ebb7a Aurelien Jarno
        }
2270 353ebb7a Aurelien Jarno
        if (xcpt & float_flag_inexact) {
2271 353ebb7a Aurelien Jarno
            ret |= FP_INEXACT;
2272 353ebb7a Aurelien Jarno
        }
2273 353ebb7a Aurelien Jarno
    }
2274 353ebb7a Aurelien Jarno
    return ret;
2275 fd4a04eb ths
}
2276 fd4a04eb ths
2277 5f7319cd Aurelien Jarno
static inline void update_fcr31(CPUMIPSState *env, uintptr_t pc)
2278 fd4a04eb ths
{
2279 f01be154 ths
    int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->active_fpu.fp_status));
2280 fd4a04eb ths
2281 f01be154 ths
    SET_FP_CAUSE(env->active_fpu.fcr31, tmp);
2282 4a587b2c Aurelien Jarno
2283 4a587b2c Aurelien Jarno
    if (tmp) {
2284 4a587b2c Aurelien Jarno
        set_float_exception_flags(0, &env->active_fpu.fp_status);
2285 4a587b2c Aurelien Jarno
2286 4a587b2c Aurelien Jarno
        if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp) {
2287 5f7319cd Aurelien Jarno
            do_raise_exception(env, EXCP_FPE, pc);
2288 4a587b2c Aurelien Jarno
        } else {
2289 4a587b2c Aurelien Jarno
            UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp);
2290 4a587b2c Aurelien Jarno
        }
2291 4a587b2c Aurelien Jarno
    }
2292 fd4a04eb ths
}
2293 fd4a04eb ths
2294 a16336e4 ths
/* Float support.
2295 a16336e4 ths
   Single precition routines have a "s" suffix, double precision a
2296 a16336e4 ths
   "d" suffix, 32bit integer "w", 64bit integer "l", paired single "ps",
2297 a16336e4 ths
   paired single lower "pl", paired single upper "pu".  */
2298 a16336e4 ths
2299 a16336e4 ths
/* unary operations, modifying fp status  */
2300 895c2d04 Blue Swirl
uint64_t helper_float_sqrt_d(CPUMIPSState *env, uint64_t fdt0)
2301 b6d96bed ths
{
2302 5dbe90bb Aurelien Jarno
    fdt0 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
2303 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2304 5dbe90bb Aurelien Jarno
    return fdt0;
2305 b6d96bed ths
}
2306 b6d96bed ths
2307 895c2d04 Blue Swirl
uint32_t helper_float_sqrt_s(CPUMIPSState *env, uint32_t fst0)
2308 b6d96bed ths
{
2309 5dbe90bb Aurelien Jarno
    fst0 = float32_sqrt(fst0, &env->active_fpu.fp_status);
2310 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2311 5dbe90bb Aurelien Jarno
    return fst0;
2312 b6d96bed ths
}
2313 a16336e4 ths
2314 895c2d04 Blue Swirl
uint64_t helper_float_cvtd_s(CPUMIPSState *env, uint32_t fst0)
2315 fd4a04eb ths
{
2316 b6d96bed ths
    uint64_t fdt2;
2317 b6d96bed ths
2318 f01be154 ths
    fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status);
2319 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2320 b6d96bed ths
    return fdt2;
2321 fd4a04eb ths
}
2322 b6d96bed ths
2323 895c2d04 Blue Swirl
uint64_t helper_float_cvtd_w(CPUMIPSState *env, uint32_t wt0)
2324 fd4a04eb ths
{
2325 b6d96bed ths
    uint64_t fdt2;
2326 b6d96bed ths
2327 f01be154 ths
    fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status);
2328 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2329 b6d96bed ths
    return fdt2;
2330 fd4a04eb ths
}
2331 b6d96bed ths
2332 895c2d04 Blue Swirl
uint64_t helper_float_cvtd_l(CPUMIPSState *env, uint64_t dt0)
2333 fd4a04eb ths
{
2334 b6d96bed ths
    uint64_t fdt2;
2335 b6d96bed ths
2336 f01be154 ths
    fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status);
2337 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2338 b6d96bed ths
    return fdt2;
2339 fd4a04eb ths
}
2340 b6d96bed ths
2341 895c2d04 Blue Swirl
uint64_t helper_float_cvtl_d(CPUMIPSState *env, uint64_t fdt0)
2342 fd4a04eb ths
{
2343 b6d96bed ths
    uint64_t dt2;
2344 b6d96bed ths
2345 f01be154 ths
    dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
2346 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2347 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2348 05993cd0 Aurelien Jarno
        dt2 = FP_TO_INT64_OVERFLOW;
2349 4cc2e5f9 Aurelien Jarno
    }
2350 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2351 b6d96bed ths
    return dt2;
2352 fd4a04eb ths
}
2353 b6d96bed ths
2354 895c2d04 Blue Swirl
uint64_t helper_float_cvtl_s(CPUMIPSState *env, uint32_t fst0)
2355 fd4a04eb ths
{
2356 b6d96bed ths
    uint64_t dt2;
2357 b6d96bed ths
2358 f01be154 ths
    dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
2359 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2360 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2361 05993cd0 Aurelien Jarno
        dt2 = FP_TO_INT64_OVERFLOW;
2362 4cc2e5f9 Aurelien Jarno
    }
2363 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2364 b6d96bed ths
    return dt2;
2365 fd4a04eb ths
}
2366 fd4a04eb ths
2367 895c2d04 Blue Swirl
uint64_t helper_float_cvtps_pw(CPUMIPSState *env, uint64_t dt0)
2368 fd4a04eb ths
{
2369 b6d96bed ths
    uint32_t fst2;
2370 b6d96bed ths
    uint32_t fsth2;
2371 b6d96bed ths
2372 f01be154 ths
    fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2373 f01be154 ths
    fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status);
2374 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2375 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2376 fd4a04eb ths
}
2377 b6d96bed ths
2378 895c2d04 Blue Swirl
uint64_t helper_float_cvtpw_ps(CPUMIPSState *env, uint64_t fdt0)
2379 fd4a04eb ths
{
2380 b6d96bed ths
    uint32_t wt2;
2381 b6d96bed ths
    uint32_t wth2;
2382 5dbe90bb Aurelien Jarno
    int excp, excph;
2383 b6d96bed ths
2384 f01be154 ths
    wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2385 5dbe90bb Aurelien Jarno
    excp = get_float_exception_flags(&env->active_fpu.fp_status);
2386 5dbe90bb Aurelien Jarno
    if (excp & (float_flag_overflow | float_flag_invalid)) {
2387 05993cd0 Aurelien Jarno
        wt2 = FP_TO_INT32_OVERFLOW;
2388 5dbe90bb Aurelien Jarno
    }
2389 5dbe90bb Aurelien Jarno
2390 5dbe90bb Aurelien Jarno
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2391 5dbe90bb Aurelien Jarno
    wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status);
2392 5dbe90bb Aurelien Jarno
    excph = get_float_exception_flags(&env->active_fpu.fp_status);
2393 5dbe90bb Aurelien Jarno
    if (excph & (float_flag_overflow | float_flag_invalid)) {
2394 05993cd0 Aurelien Jarno
        wth2 = FP_TO_INT32_OVERFLOW;
2395 b6d96bed ths
    }
2396 5dbe90bb Aurelien Jarno
2397 5dbe90bb Aurelien Jarno
    set_float_exception_flags(excp | excph, &env->active_fpu.fp_status);
2398 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2399 5dbe90bb Aurelien Jarno
2400 b6d96bed ths
    return ((uint64_t)wth2 << 32) | wt2;
2401 fd4a04eb ths
}
2402 b6d96bed ths
2403 895c2d04 Blue Swirl
uint32_t helper_float_cvts_d(CPUMIPSState *env, uint64_t fdt0)
2404 fd4a04eb ths
{
2405 b6d96bed ths
    uint32_t fst2;
2406 b6d96bed ths
2407 f01be154 ths
    fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status);
2408 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2409 b6d96bed ths
    return fst2;
2410 fd4a04eb ths
}
2411 b6d96bed ths
2412 895c2d04 Blue Swirl
uint32_t helper_float_cvts_w(CPUMIPSState *env, uint32_t wt0)
2413 fd4a04eb ths
{
2414 b6d96bed ths
    uint32_t fst2;
2415 b6d96bed ths
2416 f01be154 ths
    fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status);
2417 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2418 b6d96bed ths
    return fst2;
2419 fd4a04eb ths
}
2420 b6d96bed ths
2421 895c2d04 Blue Swirl
uint32_t helper_float_cvts_l(CPUMIPSState *env, uint64_t dt0)
2422 fd4a04eb ths
{
2423 b6d96bed ths
    uint32_t fst2;
2424 b6d96bed ths
2425 f01be154 ths
    fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status);
2426 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2427 b6d96bed ths
    return fst2;
2428 fd4a04eb ths
}
2429 b6d96bed ths
2430 895c2d04 Blue Swirl
uint32_t helper_float_cvts_pl(CPUMIPSState *env, uint32_t wt0)
2431 fd4a04eb ths
{
2432 b6d96bed ths
    uint32_t wt2;
2433 b6d96bed ths
2434 b6d96bed ths
    wt2 = wt0;
2435 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2436 b6d96bed ths
    return wt2;
2437 fd4a04eb ths
}
2438 b6d96bed ths
2439 895c2d04 Blue Swirl
uint32_t helper_float_cvts_pu(CPUMIPSState *env, uint32_t wth0)
2440 fd4a04eb ths
{
2441 b6d96bed ths
    uint32_t wt2;
2442 b6d96bed ths
2443 b6d96bed ths
    wt2 = wth0;
2444 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2445 b6d96bed ths
    return wt2;
2446 fd4a04eb ths
}
2447 b6d96bed ths
2448 895c2d04 Blue Swirl
uint32_t helper_float_cvtw_s(CPUMIPSState *env, uint32_t fst0)
2449 fd4a04eb ths
{
2450 b6d96bed ths
    uint32_t wt2;
2451 b6d96bed ths
2452 f01be154 ths
    wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
2453 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2454 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2455 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2456 05993cd0 Aurelien Jarno
        wt2 = FP_TO_INT32_OVERFLOW;
2457 4cc2e5f9 Aurelien Jarno
    }
2458 b6d96bed ths
    return wt2;
2459 fd4a04eb ths
}
2460 b6d96bed ths
2461 895c2d04 Blue Swirl
uint32_t helper_float_cvtw_d(CPUMIPSState *env, uint64_t fdt0)
2462 fd4a04eb ths
{
2463 b6d96bed ths
    uint32_t wt2;
2464 b6d96bed ths
2465 f01be154 ths
    wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
2466 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2467 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2468 05993cd0 Aurelien Jarno
        wt2 = FP_TO_INT32_OVERFLOW;
2469 4cc2e5f9 Aurelien Jarno
    }
2470 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2471 b6d96bed ths
    return wt2;
2472 fd4a04eb ths
}
2473 fd4a04eb ths
2474 895c2d04 Blue Swirl
uint64_t helper_float_roundl_d(CPUMIPSState *env, uint64_t fdt0)
2475 fd4a04eb ths
{
2476 b6d96bed ths
    uint64_t dt2;
2477 b6d96bed ths
2478 f01be154 ths
    set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
2479 f01be154 ths
    dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
2480 e320d05a Stefan Weil
    restore_rounding_mode(env);
2481 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2482 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2483 05993cd0 Aurelien Jarno
        dt2 = FP_TO_INT64_OVERFLOW;
2484 4cc2e5f9 Aurelien Jarno
    }
2485 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2486 b6d96bed ths
    return dt2;
2487 fd4a04eb ths
}
2488 b6d96bed ths
2489 895c2d04 Blue Swirl
uint64_t helper_float_roundl_s(CPUMIPSState *env, uint32_t fst0)
2490 fd4a04eb ths
{
2491 b6d96bed ths
    uint64_t dt2;
2492 b6d96bed ths
2493 f01be154 ths
    set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
2494 f01be154 ths
    dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
2495 e320d05a Stefan Weil
    restore_rounding_mode(env);
2496 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2497 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2498 05993cd0 Aurelien Jarno
        dt2 = FP_TO_INT64_OVERFLOW;
2499 4cc2e5f9 Aurelien Jarno
    }
2500 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2501 b6d96bed ths
    return dt2;
2502 fd4a04eb ths
}
2503 b6d96bed ths
2504 895c2d04 Blue Swirl
uint32_t helper_float_roundw_d(CPUMIPSState *env, uint64_t fdt0)
2505 fd4a04eb ths
{
2506 b6d96bed ths
    uint32_t wt2;
2507 b6d96bed ths
2508 f01be154 ths
    set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
2509 f01be154 ths
    wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
2510 e320d05a Stefan Weil
    restore_rounding_mode(env);
2511 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2512 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2513 05993cd0 Aurelien Jarno
        wt2 = FP_TO_INT32_OVERFLOW;
2514 4cc2e5f9 Aurelien Jarno
    }
2515 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2516 b6d96bed ths
    return wt2;
2517 fd4a04eb ths
}
2518 b6d96bed ths
2519 895c2d04 Blue Swirl
uint32_t helper_float_roundw_s(CPUMIPSState *env, uint32_t fst0)
2520 fd4a04eb ths
{
2521 b6d96bed ths
    uint32_t wt2;
2522 b6d96bed ths
2523 f01be154 ths
    set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
2524 f01be154 ths
    wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
2525 e320d05a Stefan Weil
    restore_rounding_mode(env);
2526 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2527 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2528 05993cd0 Aurelien Jarno
        wt2 = FP_TO_INT32_OVERFLOW;
2529 4cc2e5f9 Aurelien Jarno
    }
2530 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2531 b6d96bed ths
    return wt2;
2532 fd4a04eb ths
}
2533 fd4a04eb ths
2534 895c2d04 Blue Swirl
uint64_t helper_float_truncl_d(CPUMIPSState *env, uint64_t fdt0)
2535 fd4a04eb ths
{
2536 b6d96bed ths
    uint64_t dt2;
2537 b6d96bed ths
2538 f01be154 ths
    dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
2539 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2540 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2541 05993cd0 Aurelien Jarno
        dt2 = FP_TO_INT64_OVERFLOW;
2542 4cc2e5f9 Aurelien Jarno
    }
2543 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2544 b6d96bed ths
    return dt2;
2545 fd4a04eb ths
}
2546 b6d96bed ths
2547 895c2d04 Blue Swirl
uint64_t helper_float_truncl_s(CPUMIPSState *env, uint32_t fst0)
2548 fd4a04eb ths
{
2549 b6d96bed ths
    uint64_t dt2;
2550 b6d96bed ths
2551 f01be154 ths
    dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
2552 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2553 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2554 05993cd0 Aurelien Jarno
        dt2 = FP_TO_INT64_OVERFLOW;
2555 4cc2e5f9 Aurelien Jarno
    }
2556 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2557 b6d96bed ths
    return dt2;
2558 fd4a04eb ths
}
2559 b6d96bed ths
2560 895c2d04 Blue Swirl
uint32_t helper_float_truncw_d(CPUMIPSState *env, uint64_t fdt0)
2561 fd4a04eb ths
{
2562 b6d96bed ths
    uint32_t wt2;
2563 b6d96bed ths
2564 f01be154 ths
    wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
2565 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2566 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2567 05993cd0 Aurelien Jarno
        wt2 = FP_TO_INT32_OVERFLOW;
2568 4cc2e5f9 Aurelien Jarno
    }
2569 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2570 b6d96bed ths
    return wt2;
2571 fd4a04eb ths
}
2572 b6d96bed ths
2573 895c2d04 Blue Swirl
uint32_t helper_float_truncw_s(CPUMIPSState *env, uint32_t fst0)
2574 fd4a04eb ths
{
2575 b6d96bed ths
    uint32_t wt2;
2576 b6d96bed ths
2577 f01be154 ths
    wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
2578 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2579 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2580 05993cd0 Aurelien Jarno
        wt2 = FP_TO_INT32_OVERFLOW;
2581 4cc2e5f9 Aurelien Jarno
    }
2582 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2583 b6d96bed ths
    return wt2;
2584 fd4a04eb ths
}
2585 fd4a04eb ths
2586 895c2d04 Blue Swirl
uint64_t helper_float_ceill_d(CPUMIPSState *env, uint64_t fdt0)
2587 fd4a04eb ths
{
2588 b6d96bed ths
    uint64_t dt2;
2589 b6d96bed ths
2590 f01be154 ths
    set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2591 f01be154 ths
    dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
2592 e320d05a Stefan Weil
    restore_rounding_mode(env);
2593 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2594 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2595 05993cd0 Aurelien Jarno
        dt2 = FP_TO_INT64_OVERFLOW;
2596 4cc2e5f9 Aurelien Jarno
    }
2597 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2598 b6d96bed ths
    return dt2;
2599 fd4a04eb ths
}
2600 b6d96bed ths
2601 895c2d04 Blue Swirl
uint64_t helper_float_ceill_s(CPUMIPSState *env, uint32_t fst0)
2602 fd4a04eb ths
{
2603 b6d96bed ths
    uint64_t dt2;
2604 b6d96bed ths
2605 f01be154 ths
    set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2606 f01be154 ths
    dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
2607 e320d05a Stefan Weil
    restore_rounding_mode(env);
2608 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2609 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2610 05993cd0 Aurelien Jarno
        dt2 = FP_TO_INT64_OVERFLOW;
2611 4cc2e5f9 Aurelien Jarno
    }
2612 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2613 b6d96bed ths
    return dt2;
2614 fd4a04eb ths
}
2615 b6d96bed ths
2616 895c2d04 Blue Swirl
uint32_t helper_float_ceilw_d(CPUMIPSState *env, uint64_t fdt0)
2617 fd4a04eb ths
{
2618 b6d96bed ths
    uint32_t wt2;
2619 b6d96bed ths
2620 f01be154 ths
    set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2621 f01be154 ths
    wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
2622 e320d05a Stefan Weil
    restore_rounding_mode(env);
2623 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2624 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2625 05993cd0 Aurelien Jarno
        wt2 = FP_TO_INT32_OVERFLOW;
2626 4cc2e5f9 Aurelien Jarno
    }
2627 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2628 b6d96bed ths
    return wt2;
2629 fd4a04eb ths
}
2630 b6d96bed ths
2631 895c2d04 Blue Swirl
uint32_t helper_float_ceilw_s(CPUMIPSState *env, uint32_t fst0)
2632 fd4a04eb ths
{
2633 b6d96bed ths
    uint32_t wt2;
2634 b6d96bed ths
2635 f01be154 ths
    set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2636 f01be154 ths
    wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
2637 e320d05a Stefan Weil
    restore_rounding_mode(env);
2638 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2639 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2640 05993cd0 Aurelien Jarno
        wt2 = FP_TO_INT32_OVERFLOW;
2641 4cc2e5f9 Aurelien Jarno
    }
2642 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2643 b6d96bed ths
    return wt2;
2644 fd4a04eb ths
}
2645 fd4a04eb ths
2646 895c2d04 Blue Swirl
uint64_t helper_float_floorl_d(CPUMIPSState *env, uint64_t fdt0)
2647 fd4a04eb ths
{
2648 b6d96bed ths
    uint64_t dt2;
2649 b6d96bed ths
2650 f01be154 ths
    set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2651 f01be154 ths
    dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
2652 e320d05a Stefan Weil
    restore_rounding_mode(env);
2653 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2654 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2655 05993cd0 Aurelien Jarno
        dt2 = FP_TO_INT64_OVERFLOW;
2656 4cc2e5f9 Aurelien Jarno
    }
2657 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2658 b6d96bed ths
    return dt2;
2659 fd4a04eb ths
}
2660 b6d96bed ths
2661 895c2d04 Blue Swirl
uint64_t helper_float_floorl_s(CPUMIPSState *env, uint32_t fst0)
2662 fd4a04eb ths
{
2663 b6d96bed ths
    uint64_t dt2;
2664 b6d96bed ths
2665 f01be154 ths
    set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2666 f01be154 ths
    dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
2667 e320d05a Stefan Weil
    restore_rounding_mode(env);
2668 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2669 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2670 05993cd0 Aurelien Jarno
        dt2 = FP_TO_INT64_OVERFLOW;
2671 4cc2e5f9 Aurelien Jarno
    }
2672 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2673 b6d96bed ths
    return dt2;
2674 fd4a04eb ths
}
2675 b6d96bed ths
2676 895c2d04 Blue Swirl
uint32_t helper_float_floorw_d(CPUMIPSState *env, uint64_t fdt0)
2677 fd4a04eb ths
{
2678 b6d96bed ths
    uint32_t wt2;
2679 b6d96bed ths
2680 f01be154 ths
    set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2681 f01be154 ths
    wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
2682 e320d05a Stefan Weil
    restore_rounding_mode(env);
2683 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2684 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2685 05993cd0 Aurelien Jarno
        wt2 = FP_TO_INT32_OVERFLOW;
2686 4cc2e5f9 Aurelien Jarno
    }
2687 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2688 b6d96bed ths
    return wt2;
2689 fd4a04eb ths
}
2690 b6d96bed ths
2691 895c2d04 Blue Swirl
uint32_t helper_float_floorw_s(CPUMIPSState *env, uint32_t fst0)
2692 fd4a04eb ths
{
2693 b6d96bed ths
    uint32_t wt2;
2694 b6d96bed ths
2695 f01be154 ths
    set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2696 f01be154 ths
    wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
2697 e320d05a Stefan Weil
    restore_rounding_mode(env);
2698 4cc2e5f9 Aurelien Jarno
    if (get_float_exception_flags(&env->active_fpu.fp_status)
2699 4cc2e5f9 Aurelien Jarno
        & (float_flag_invalid | float_flag_overflow)) {
2700 05993cd0 Aurelien Jarno
        wt2 = FP_TO_INT32_OVERFLOW;
2701 4cc2e5f9 Aurelien Jarno
    }
2702 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2703 b6d96bed ths
    return wt2;
2704 fd4a04eb ths
}
2705 fd4a04eb ths
2706 a16336e4 ths
/* unary operations, not modifying fp status  */
2707 b6d96bed ths
#define FLOAT_UNOP(name)                                       \
2708 c01fccd2 aurel32
uint64_t helper_float_ ## name ## _d(uint64_t fdt0)                \
2709 b6d96bed ths
{                                                              \
2710 b6d96bed ths
    return float64_ ## name(fdt0);                             \
2711 b6d96bed ths
}                                                              \
2712 c01fccd2 aurel32
uint32_t helper_float_ ## name ## _s(uint32_t fst0)                \
2713 b6d96bed ths
{                                                              \
2714 b6d96bed ths
    return float32_ ## name(fst0);                             \
2715 b6d96bed ths
}                                                              \
2716 c01fccd2 aurel32
uint64_t helper_float_ ## name ## _ps(uint64_t fdt0)               \
2717 b6d96bed ths
{                                                              \
2718 b6d96bed ths
    uint32_t wt0;                                              \
2719 b6d96bed ths
    uint32_t wth0;                                             \
2720 b6d96bed ths
                                                               \
2721 b6d96bed ths
    wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF);                 \
2722 b6d96bed ths
    wth0 = float32_ ## name(fdt0 >> 32);                       \
2723 b6d96bed ths
    return ((uint64_t)wth0 << 32) | wt0;                       \
2724 a16336e4 ths
}
2725 a16336e4 ths
FLOAT_UNOP(abs)
2726 a16336e4 ths
FLOAT_UNOP(chs)
2727 a16336e4 ths
#undef FLOAT_UNOP
2728 a16336e4 ths
2729 8dfdb87c ths
/* MIPS specific unary operations */
2730 895c2d04 Blue Swirl
uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0)
2731 8dfdb87c ths
{
2732 b6d96bed ths
    uint64_t fdt2;
2733 b6d96bed ths
2734 05993cd0 Aurelien Jarno
    fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status);
2735 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2736 b6d96bed ths
    return fdt2;
2737 8dfdb87c ths
}
2738 b6d96bed ths
2739 895c2d04 Blue Swirl
uint32_t helper_float_recip_s(CPUMIPSState *env, uint32_t fst0)
2740 8dfdb87c ths
{
2741 b6d96bed ths
    uint32_t fst2;
2742 b6d96bed ths
2743 05993cd0 Aurelien Jarno
    fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status);
2744 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2745 b6d96bed ths
    return fst2;
2746 57fa1fb3 ths
}
2747 57fa1fb3 ths
2748 895c2d04 Blue Swirl
uint64_t helper_float_rsqrt_d(CPUMIPSState *env, uint64_t fdt0)
2749 8dfdb87c ths
{
2750 b6d96bed ths
    uint64_t fdt2;
2751 b6d96bed ths
2752 f01be154 ths
    fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
2753 05993cd0 Aurelien Jarno
    fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status);
2754 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2755 b6d96bed ths
    return fdt2;
2756 8dfdb87c ths
}
2757 b6d96bed ths
2758 895c2d04 Blue Swirl
uint32_t helper_float_rsqrt_s(CPUMIPSState *env, uint32_t fst0)
2759 8dfdb87c ths
{
2760 b6d96bed ths
    uint32_t fst2;
2761 b6d96bed ths
2762 f01be154 ths
    fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
2763 05993cd0 Aurelien Jarno
    fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status);
2764 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2765 b6d96bed ths
    return fst2;
2766 8dfdb87c ths
}
2767 8dfdb87c ths
2768 895c2d04 Blue Swirl
uint64_t helper_float_recip1_d(CPUMIPSState *env, uint64_t fdt0)
2769 8dfdb87c ths
{
2770 b6d96bed ths
    uint64_t fdt2;
2771 b6d96bed ths
2772 05993cd0 Aurelien Jarno
    fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status);
2773 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2774 b6d96bed ths
    return fdt2;
2775 8dfdb87c ths
}
2776 b6d96bed ths
2777 895c2d04 Blue Swirl
uint32_t helper_float_recip1_s(CPUMIPSState *env, uint32_t fst0)
2778 8dfdb87c ths
{
2779 b6d96bed ths
    uint32_t fst2;
2780 b6d96bed ths
2781 05993cd0 Aurelien Jarno
    fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status);
2782 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2783 b6d96bed ths
    return fst2;
2784 8dfdb87c ths
}
2785 b6d96bed ths
2786 895c2d04 Blue Swirl
uint64_t helper_float_recip1_ps(CPUMIPSState *env, uint64_t fdt0)
2787 8dfdb87c ths
{
2788 b6d96bed ths
    uint32_t fst2;
2789 b6d96bed ths
    uint32_t fsth2;
2790 b6d96bed ths
2791 05993cd0 Aurelien Jarno
    fst2 = float32_div(float32_one, fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2792 05993cd0 Aurelien Jarno
    fsth2 = float32_div(float32_one, fdt0 >> 32, &env->active_fpu.fp_status);
2793 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2794 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2795 8dfdb87c ths
}
2796 8dfdb87c ths
2797 895c2d04 Blue Swirl
uint64_t helper_float_rsqrt1_d(CPUMIPSState *env, uint64_t fdt0)
2798 8dfdb87c ths
{
2799 b6d96bed ths
    uint64_t fdt2;
2800 b6d96bed ths
2801 f01be154 ths
    fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
2802 05993cd0 Aurelien Jarno
    fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status);
2803 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2804 b6d96bed ths
    return fdt2;
2805 8dfdb87c ths
}
2806 b6d96bed ths
2807 895c2d04 Blue Swirl
uint32_t helper_float_rsqrt1_s(CPUMIPSState *env, uint32_t fst0)
2808 8dfdb87c ths
{
2809 b6d96bed ths
    uint32_t fst2;
2810 b6d96bed ths
2811 f01be154 ths
    fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
2812 05993cd0 Aurelien Jarno
    fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status);
2813 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2814 b6d96bed ths
    return fst2;
2815 8dfdb87c ths
}
2816 b6d96bed ths
2817 895c2d04 Blue Swirl
uint64_t helper_float_rsqrt1_ps(CPUMIPSState *env, uint64_t fdt0)
2818 8dfdb87c ths
{
2819 b6d96bed ths
    uint32_t fst2;
2820 b6d96bed ths
    uint32_t fsth2;
2821 b6d96bed ths
2822 f01be154 ths
    fst2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2823 f01be154 ths
    fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status);
2824 05993cd0 Aurelien Jarno
    fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status);
2825 05993cd0 Aurelien Jarno
    fsth2 = float32_div(float32_one, fsth2, &env->active_fpu.fp_status);
2826 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2827 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2828 57fa1fb3 ths
}
2829 57fa1fb3 ths
2830 895c2d04 Blue Swirl
#define FLOAT_OP(name, p) void helper_float_##name##_##p(CPUMIPSState *env)
2831 b6d96bed ths
2832 fd4a04eb ths
/* binary operations */
2833 b6d96bed ths
#define FLOAT_BINOP(name)                                          \
2834 895c2d04 Blue Swirl
uint64_t helper_float_ ## name ## _d(CPUMIPSState *env,            \
2835 895c2d04 Blue Swirl
                                     uint64_t fdt0, uint64_t fdt1) \
2836 b6d96bed ths
{                                                                  \
2837 b6d96bed ths
    uint64_t dt2;                                                  \
2838 b6d96bed ths
                                                                   \
2839 f01be154 ths
    dt2 = float64_ ## name (fdt0, fdt1, &env->active_fpu.fp_status);     \
2840 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());                                    \
2841 b6d96bed ths
    return dt2;                                                    \
2842 b6d96bed ths
}                                                                  \
2843 b6d96bed ths
                                                                   \
2844 895c2d04 Blue Swirl
uint32_t helper_float_ ## name ## _s(CPUMIPSState *env,            \
2845 895c2d04 Blue Swirl
                                     uint32_t fst0, uint32_t fst1) \
2846 b6d96bed ths
{                                                                  \
2847 b6d96bed ths
    uint32_t wt2;                                                  \
2848 b6d96bed ths
                                                                   \
2849 f01be154 ths
    wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status);     \
2850 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());                                    \
2851 b6d96bed ths
    return wt2;                                                    \
2852 b6d96bed ths
}                                                                  \
2853 b6d96bed ths
                                                                   \
2854 895c2d04 Blue Swirl
uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env,           \
2855 895c2d04 Blue Swirl
                                      uint64_t fdt0,               \
2856 895c2d04 Blue Swirl
                                      uint64_t fdt1)               \
2857 b6d96bed ths
{                                                                  \
2858 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;                             \
2859 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;                                   \
2860 b6d96bed ths
    uint32_t fst1 = fdt1 & 0XFFFFFFFF;                             \
2861 b6d96bed ths
    uint32_t fsth1 = fdt1 >> 32;                                   \
2862 b6d96bed ths
    uint32_t wt2;                                                  \
2863 b6d96bed ths
    uint32_t wth2;                                                 \
2864 b6d96bed ths
                                                                   \
2865 f01be154 ths
    wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status);     \
2866 f01be154 ths
    wth2 = float32_ ## name (fsth0, fsth1, &env->active_fpu.fp_status);  \
2867 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());                                    \
2868 b6d96bed ths
    return ((uint64_t)wth2 << 32) | wt2;                           \
2869 fd4a04eb ths
}
2870 b6d96bed ths
2871 fd4a04eb ths
FLOAT_BINOP(add)
2872 fd4a04eb ths
FLOAT_BINOP(sub)
2873 fd4a04eb ths
FLOAT_BINOP(mul)
2874 fd4a04eb ths
FLOAT_BINOP(div)
2875 fd4a04eb ths
#undef FLOAT_BINOP
2876 fd4a04eb ths
2877 f54c35d1 Richard Sandiford
#define UNFUSED_FMA(prefix, a, b, c, flags)                          \
2878 f54c35d1 Richard Sandiford
{                                                                    \
2879 f54c35d1 Richard Sandiford
    a = prefix##_mul(a, b, &env->active_fpu.fp_status);              \
2880 f54c35d1 Richard Sandiford
    if ((flags) & float_muladd_negate_c) {                           \
2881 f54c35d1 Richard Sandiford
        a = prefix##_sub(a, c, &env->active_fpu.fp_status);          \
2882 f54c35d1 Richard Sandiford
    } else {                                                         \
2883 f54c35d1 Richard Sandiford
        a = prefix##_add(a, c, &env->active_fpu.fp_status);          \
2884 f54c35d1 Richard Sandiford
    }                                                                \
2885 f54c35d1 Richard Sandiford
    if ((flags) & float_muladd_negate_result) {                      \
2886 f54c35d1 Richard Sandiford
        a = prefix##_chs(a);                                         \
2887 f54c35d1 Richard Sandiford
    }                                                                \
2888 f54c35d1 Richard Sandiford
}
2889 f54c35d1 Richard Sandiford
2890 b3d6cd44 Aurelien Jarno
/* FMA based operations */
2891 b3d6cd44 Aurelien Jarno
#define FLOAT_FMA(name, type)                                        \
2892 b3d6cd44 Aurelien Jarno
uint64_t helper_float_ ## name ## _d(CPUMIPSState *env,              \
2893 b3d6cd44 Aurelien Jarno
                                     uint64_t fdt0, uint64_t fdt1,   \
2894 b3d6cd44 Aurelien Jarno
                                     uint64_t fdt2)                  \
2895 b3d6cd44 Aurelien Jarno
{                                                                    \
2896 f54c35d1 Richard Sandiford
    UNFUSED_FMA(float64, fdt0, fdt1, fdt2, type);                    \
2897 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());                                      \
2898 b3d6cd44 Aurelien Jarno
    return fdt0;                                                     \
2899 b3d6cd44 Aurelien Jarno
}                                                                    \
2900 b3d6cd44 Aurelien Jarno
                                                                     \
2901 b3d6cd44 Aurelien Jarno
uint32_t helper_float_ ## name ## _s(CPUMIPSState *env,              \
2902 b3d6cd44 Aurelien Jarno
                                     uint32_t fst0, uint32_t fst1,   \
2903 b3d6cd44 Aurelien Jarno
                                     uint32_t fst2)                  \
2904 b3d6cd44 Aurelien Jarno
{                                                                    \
2905 f54c35d1 Richard Sandiford
    UNFUSED_FMA(float32, fst0, fst1, fst2, type);                    \
2906 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());                                      \
2907 b3d6cd44 Aurelien Jarno
    return fst0;                                                     \
2908 b3d6cd44 Aurelien Jarno
}                                                                    \
2909 b3d6cd44 Aurelien Jarno
                                                                     \
2910 b3d6cd44 Aurelien Jarno
uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env,             \
2911 b3d6cd44 Aurelien Jarno
                                      uint64_t fdt0, uint64_t fdt1,  \
2912 b3d6cd44 Aurelien Jarno
                                      uint64_t fdt2)                 \
2913 b3d6cd44 Aurelien Jarno
{                                                                    \
2914 b3d6cd44 Aurelien Jarno
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;                               \
2915 b3d6cd44 Aurelien Jarno
    uint32_t fsth0 = fdt0 >> 32;                                     \
2916 b3d6cd44 Aurelien Jarno
    uint32_t fst1 = fdt1 & 0XFFFFFFFF;                               \
2917 b3d6cd44 Aurelien Jarno
    uint32_t fsth1 = fdt1 >> 32;                                     \
2918 b3d6cd44 Aurelien Jarno
    uint32_t fst2 = fdt2 & 0XFFFFFFFF;                               \
2919 b3d6cd44 Aurelien Jarno
    uint32_t fsth2 = fdt2 >> 32;                                     \
2920 b3d6cd44 Aurelien Jarno
                                                                     \
2921 f54c35d1 Richard Sandiford
    UNFUSED_FMA(float32, fst0, fst1, fst2, type);                    \
2922 f54c35d1 Richard Sandiford
    UNFUSED_FMA(float32, fsth0, fsth1, fsth2, type);                 \
2923 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());                                      \
2924 b3d6cd44 Aurelien Jarno
    return ((uint64_t)fsth0 << 32) | fst0;                           \
2925 b3d6cd44 Aurelien Jarno
}
2926 b3d6cd44 Aurelien Jarno
FLOAT_FMA(madd, 0)
2927 b3d6cd44 Aurelien Jarno
FLOAT_FMA(msub, float_muladd_negate_c)
2928 b3d6cd44 Aurelien Jarno
FLOAT_FMA(nmadd, float_muladd_negate_result)
2929 b3d6cd44 Aurelien Jarno
FLOAT_FMA(nmsub, float_muladd_negate_result | float_muladd_negate_c)
2930 b3d6cd44 Aurelien Jarno
#undef FLOAT_FMA
2931 a16336e4 ths
2932 8dfdb87c ths
/* MIPS specific binary operations */
2933 895c2d04 Blue Swirl
uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
2934 8dfdb87c ths
{
2935 f01be154 ths
    fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
2936 05993cd0 Aurelien Jarno
    fdt2 = float64_chs(float64_sub(fdt2, float64_one, &env->active_fpu.fp_status));
2937 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2938 b6d96bed ths
    return fdt2;
2939 8dfdb87c ths
}
2940 b6d96bed ths
2941 895c2d04 Blue Swirl
uint32_t helper_float_recip2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2)
2942 8dfdb87c ths
{
2943 f01be154 ths
    fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
2944 05993cd0 Aurelien Jarno
    fst2 = float32_chs(float32_sub(fst2, float32_one, &env->active_fpu.fp_status));
2945 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2946 b6d96bed ths
    return fst2;
2947 8dfdb87c ths
}
2948 b6d96bed ths
2949 895c2d04 Blue Swirl
uint64_t helper_float_recip2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
2950 8dfdb87c ths
{
2951 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2952 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;
2953 b6d96bed ths
    uint32_t fst2 = fdt2 & 0XFFFFFFFF;
2954 b6d96bed ths
    uint32_t fsth2 = fdt2 >> 32;
2955 b6d96bed ths
2956 f01be154 ths
    fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
2957 f01be154 ths
    fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
2958 05993cd0 Aurelien Jarno
    fst2 = float32_chs(float32_sub(fst2, float32_one, &env->active_fpu.fp_status));
2959 05993cd0 Aurelien Jarno
    fsth2 = float32_chs(float32_sub(fsth2, float32_one, &env->active_fpu.fp_status));
2960 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2961 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2962 8dfdb87c ths
}
2963 8dfdb87c ths
2964 895c2d04 Blue Swirl
uint64_t helper_float_rsqrt2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
2965 8dfdb87c ths
{
2966 f01be154 ths
    fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
2967 05993cd0 Aurelien Jarno
    fdt2 = float64_sub(fdt2, float64_one, &env->active_fpu.fp_status);
2968 f01be154 ths
    fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, &env->active_fpu.fp_status));
2969 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2970 b6d96bed ths
    return fdt2;
2971 8dfdb87c ths
}
2972 b6d96bed ths
2973 895c2d04 Blue Swirl
uint32_t helper_float_rsqrt2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2)
2974 8dfdb87c ths
{
2975 f01be154 ths
    fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
2976 05993cd0 Aurelien Jarno
    fst2 = float32_sub(fst2, float32_one, &env->active_fpu.fp_status);
2977 f01be154 ths
    fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
2978 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2979 b6d96bed ths
    return fst2;
2980 8dfdb87c ths
}
2981 b6d96bed ths
2982 895c2d04 Blue Swirl
uint64_t helper_float_rsqrt2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
2983 8dfdb87c ths
{
2984 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2985 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;
2986 b6d96bed ths
    uint32_t fst2 = fdt2 & 0XFFFFFFFF;
2987 b6d96bed ths
    uint32_t fsth2 = fdt2 >> 32;
2988 b6d96bed ths
2989 f01be154 ths
    fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
2990 f01be154 ths
    fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
2991 05993cd0 Aurelien Jarno
    fst2 = float32_sub(fst2, float32_one, &env->active_fpu.fp_status);
2992 05993cd0 Aurelien Jarno
    fsth2 = float32_sub(fsth2, float32_one, &env->active_fpu.fp_status);
2993 f01be154 ths
    fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
2994 f01be154 ths
    fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, &env->active_fpu.fp_status));
2995 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
2996 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2997 57fa1fb3 ths
}
2998 57fa1fb3 ths
2999 895c2d04 Blue Swirl
uint64_t helper_float_addr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1)
3000 fd4a04eb ths
{
3001 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;
3002 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;
3003 b6d96bed ths
    uint32_t fst1 = fdt1 & 0XFFFFFFFF;
3004 b6d96bed ths
    uint32_t fsth1 = fdt1 >> 32;
3005 b6d96bed ths
    uint32_t fst2;
3006 b6d96bed ths
    uint32_t fsth2;
3007 b6d96bed ths
3008 f01be154 ths
    fst2 = float32_add (fst0, fsth0, &env->active_fpu.fp_status);
3009 f01be154 ths
    fsth2 = float32_add (fst1, fsth1, &env->active_fpu.fp_status);
3010 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
3011 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
3012 fd4a04eb ths
}
3013 fd4a04eb ths
3014 895c2d04 Blue Swirl
uint64_t helper_float_mulr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1)
3015 57fa1fb3 ths
{
3016 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;
3017 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;
3018 b6d96bed ths
    uint32_t fst1 = fdt1 & 0XFFFFFFFF;
3019 b6d96bed ths
    uint32_t fsth1 = fdt1 >> 32;
3020 b6d96bed ths
    uint32_t fst2;
3021 b6d96bed ths
    uint32_t fsth2;
3022 b6d96bed ths
3023 f01be154 ths
    fst2 = float32_mul (fst0, fsth0, &env->active_fpu.fp_status);
3024 f01be154 ths
    fsth2 = float32_mul (fst1, fsth1, &env->active_fpu.fp_status);
3025 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());
3026 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
3027 57fa1fb3 ths
}
3028 57fa1fb3 ths
3029 8dfdb87c ths
/* compare operations */
3030 b6d96bed ths
#define FOP_COND_D(op, cond)                                   \
3031 895c2d04 Blue Swirl
void helper_cmp_d_ ## op(CPUMIPSState *env, uint64_t fdt0,     \
3032 895c2d04 Blue Swirl
                         uint64_t fdt1, int cc)                \
3033 b6d96bed ths
{                                                              \
3034 6a385343 Aurelien Jarno
    int c;                                                     \
3035 6a385343 Aurelien Jarno
    c = cond;                                                  \
3036 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());                                \
3037 b6d96bed ths
    if (c)                                                     \
3038 f01be154 ths
        SET_FP_COND(cc, env->active_fpu);                      \
3039 b6d96bed ths
    else                                                       \
3040 f01be154 ths
        CLEAR_FP_COND(cc, env->active_fpu);                    \
3041 b6d96bed ths
}                                                              \
3042 895c2d04 Blue Swirl
void helper_cmpabs_d_ ## op(CPUMIPSState *env, uint64_t fdt0,  \
3043 895c2d04 Blue Swirl
                            uint64_t fdt1, int cc)             \
3044 b6d96bed ths
{                                                              \
3045 b6d96bed ths
    int c;                                                     \
3046 b6d96bed ths
    fdt0 = float64_abs(fdt0);                                  \
3047 b6d96bed ths
    fdt1 = float64_abs(fdt1);                                  \
3048 b6d96bed ths
    c = cond;                                                  \
3049 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());                                \
3050 b6d96bed ths
    if (c)                                                     \
3051 f01be154 ths
        SET_FP_COND(cc, env->active_fpu);                      \
3052 b6d96bed ths
    else                                                       \
3053 f01be154 ths
        CLEAR_FP_COND(cc, env->active_fpu);                    \
3054 fd4a04eb ths
}
3055 fd4a04eb ths
3056 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
3057 3a599383 Aurelien Jarno
 * but float64_unordered_quiet() is still called. */
3058 3a599383 Aurelien Jarno
FOP_COND_D(f,   (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status), 0))
3059 3a599383 Aurelien Jarno
FOP_COND_D(un,  float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status))
3060 06a0e6b1 Aurelien Jarno
FOP_COND_D(eq,  float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
3061 211315fb Aurelien Jarno
FOP_COND_D(ueq, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
3062 06a0e6b1 Aurelien Jarno
FOP_COND_D(olt, float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
3063 06a0e6b1 Aurelien Jarno
FOP_COND_D(ult, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
3064 06a0e6b1 Aurelien Jarno
FOP_COND_D(ole, float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
3065 06a0e6b1 Aurelien Jarno
FOP_COND_D(ule, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
3066 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
3067 3a599383 Aurelien Jarno
 * but float64_unordered() is still called. */
3068 3a599383 Aurelien Jarno
FOP_COND_D(sf,  (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status), 0))
3069 3a599383 Aurelien Jarno
FOP_COND_D(ngle,float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status))
3070 06a0e6b1 Aurelien Jarno
FOP_COND_D(seq, float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
3071 06a0e6b1 Aurelien Jarno
FOP_COND_D(ngl, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
3072 06a0e6b1 Aurelien Jarno
FOP_COND_D(lt,  float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
3073 3a599383 Aurelien Jarno
FOP_COND_D(nge, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
3074 06a0e6b1 Aurelien Jarno
FOP_COND_D(le,  float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
3075 3a599383 Aurelien Jarno
FOP_COND_D(ngt, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
3076 b6d96bed ths
3077 b6d96bed ths
#define FOP_COND_S(op, cond)                                   \
3078 895c2d04 Blue Swirl
void helper_cmp_s_ ## op(CPUMIPSState *env, uint32_t fst0,     \
3079 895c2d04 Blue Swirl
                         uint32_t fst1, int cc)                \
3080 b6d96bed ths
{                                                              \
3081 6a385343 Aurelien Jarno
    int c;                                                     \
3082 6a385343 Aurelien Jarno
    c = cond;                                                  \
3083 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());                                \
3084 b6d96bed ths
    if (c)                                                     \
3085 f01be154 ths
        SET_FP_COND(cc, env->active_fpu);                      \
3086 b6d96bed ths
    else                                                       \
3087 f01be154 ths
        CLEAR_FP_COND(cc, env->active_fpu);                    \
3088 b6d96bed ths
}                                                              \
3089 895c2d04 Blue Swirl
void helper_cmpabs_s_ ## op(CPUMIPSState *env, uint32_t fst0,  \
3090 895c2d04 Blue Swirl
                            uint32_t fst1, int cc)             \
3091 b6d96bed ths
{                                                              \
3092 b6d96bed ths
    int c;                                                     \
3093 b6d96bed ths
    fst0 = float32_abs(fst0);                                  \
3094 b6d96bed ths
    fst1 = float32_abs(fst1);                                  \
3095 b6d96bed ths
    c = cond;                                                  \
3096 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());                                \
3097 b6d96bed ths
    if (c)                                                     \
3098 f01be154 ths
        SET_FP_COND(cc, env->active_fpu);                      \
3099 b6d96bed ths
    else                                                       \
3100 f01be154 ths
        CLEAR_FP_COND(cc, env->active_fpu);                    \
3101 fd4a04eb ths
}
3102 fd4a04eb ths
3103 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
3104 3a599383 Aurelien Jarno
 * but float32_unordered_quiet() is still called. */
3105 3a599383 Aurelien Jarno
FOP_COND_S(f,   (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0))
3106 3a599383 Aurelien Jarno
FOP_COND_S(un,  float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status))
3107 06a0e6b1 Aurelien Jarno
FOP_COND_S(eq,  float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
3108 211315fb Aurelien Jarno
FOP_COND_S(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
3109 06a0e6b1 Aurelien Jarno
FOP_COND_S(olt, float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))
3110 06a0e6b1 Aurelien Jarno
FOP_COND_S(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))
3111 06a0e6b1 Aurelien Jarno
FOP_COND_S(ole, float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status))
3112 06a0e6b1 Aurelien Jarno
FOP_COND_S(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status))
3113 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
3114 3a599383 Aurelien Jarno
 * but float32_unordered() is still called. */
3115 3a599383 Aurelien Jarno
FOP_COND_S(sf,  (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0))
3116 3a599383 Aurelien Jarno
FOP_COND_S(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status))
3117 06a0e6b1 Aurelien Jarno
FOP_COND_S(seq, float32_eq(fst0, fst1, &env->active_fpu.fp_status))
3118 06a0e6b1 Aurelien Jarno
FOP_COND_S(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
3119 06a0e6b1 Aurelien Jarno
FOP_COND_S(lt,  float32_lt(fst0, fst1, &env->active_fpu.fp_status))
3120 3a599383 Aurelien Jarno
FOP_COND_S(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
3121 06a0e6b1 Aurelien Jarno
FOP_COND_S(le,  float32_le(fst0, fst1, &env->active_fpu.fp_status))
3122 3a599383 Aurelien Jarno
FOP_COND_S(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_le(fst0, fst1, &env->active_fpu.fp_status))
3123 b6d96bed ths
3124 b6d96bed ths
#define FOP_COND_PS(op, condl, condh)                           \
3125 895c2d04 Blue Swirl
void helper_cmp_ps_ ## op(CPUMIPSState *env, uint64_t fdt0,     \
3126 895c2d04 Blue Swirl
                          uint64_t fdt1, int cc)                \
3127 b6d96bed ths
{                                                               \
3128 6a385343 Aurelien Jarno
    uint32_t fst0, fsth0, fst1, fsth1;                          \
3129 6a385343 Aurelien Jarno
    int ch, cl;                                                 \
3130 6a385343 Aurelien Jarno
    fst0 = fdt0 & 0XFFFFFFFF;                                   \
3131 6a385343 Aurelien Jarno
    fsth0 = fdt0 >> 32;                                         \
3132 6a385343 Aurelien Jarno
    fst1 = fdt1 & 0XFFFFFFFF;                                   \
3133 6a385343 Aurelien Jarno
    fsth1 = fdt1 >> 32;                                         \
3134 6a385343 Aurelien Jarno
    cl = condl;                                                 \
3135 6a385343 Aurelien Jarno
    ch = condh;                                                 \
3136 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());                                 \
3137 b6d96bed ths
    if (cl)                                                     \
3138 f01be154 ths
        SET_FP_COND(cc, env->active_fpu);                       \
3139 b6d96bed ths
    else                                                        \
3140 f01be154 ths
        CLEAR_FP_COND(cc, env->active_fpu);                     \
3141 b6d96bed ths
    if (ch)                                                     \
3142 f01be154 ths
        SET_FP_COND(cc + 1, env->active_fpu);                   \
3143 b6d96bed ths
    else                                                        \
3144 f01be154 ths
        CLEAR_FP_COND(cc + 1, env->active_fpu);                 \
3145 b6d96bed ths
}                                                               \
3146 895c2d04 Blue Swirl
void helper_cmpabs_ps_ ## op(CPUMIPSState *env, uint64_t fdt0,  \
3147 895c2d04 Blue Swirl
                             uint64_t fdt1, int cc)             \
3148 b6d96bed ths
{                                                               \
3149 6a385343 Aurelien Jarno
    uint32_t fst0, fsth0, fst1, fsth1;                          \
3150 6a385343 Aurelien Jarno
    int ch, cl;                                                 \
3151 6a385343 Aurelien Jarno
    fst0 = float32_abs(fdt0 & 0XFFFFFFFF);                      \
3152 6a385343 Aurelien Jarno
    fsth0 = float32_abs(fdt0 >> 32);                            \
3153 6a385343 Aurelien Jarno
    fst1 = float32_abs(fdt1 & 0XFFFFFFFF);                      \
3154 6a385343 Aurelien Jarno
    fsth1 = float32_abs(fdt1 >> 32);                            \
3155 6a385343 Aurelien Jarno
    cl = condl;                                                 \
3156 6a385343 Aurelien Jarno
    ch = condh;                                                 \
3157 5f7319cd Aurelien Jarno
    update_fcr31(env, GETPC());                                 \
3158 b6d96bed ths
    if (cl)                                                     \
3159 f01be154 ths
        SET_FP_COND(cc, env->active_fpu);                       \
3160 b6d96bed ths
    else                                                        \
3161 f01be154 ths
        CLEAR_FP_COND(cc, env->active_fpu);                     \
3162 b6d96bed ths
    if (ch)                                                     \
3163 f01be154 ths
        SET_FP_COND(cc + 1, env->active_fpu);                   \
3164 b6d96bed ths
    else                                                        \
3165 f01be154 ths
        CLEAR_FP_COND(cc + 1, env->active_fpu);                 \
3166 fd4a04eb ths
}
3167 fd4a04eb ths
3168 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
3169 3a599383 Aurelien Jarno
 * but float32_unordered_quiet() is still called. */
3170 3a599383 Aurelien Jarno
FOP_COND_PS(f,   (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0),
3171 3a599383 Aurelien Jarno
                 (float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status), 0))
3172 3a599383 Aurelien Jarno
FOP_COND_PS(un,  float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status),
3173 3a599383 Aurelien Jarno
                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status))
3174 06a0e6b1 Aurelien Jarno
FOP_COND_PS(eq,  float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
3175 06a0e6b1 Aurelien Jarno
                 float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
3176 211315fb Aurelien Jarno
FOP_COND_PS(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
3177 211315fb Aurelien Jarno
                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
3178 06a0e6b1 Aurelien Jarno
FOP_COND_PS(olt, float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status),
3179 06a0e6b1 Aurelien Jarno
                 float32_lt_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
3180 06a0e6b1 Aurelien Jarno
FOP_COND_PS(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status),
3181 06a0e6b1 Aurelien Jarno
                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
3182 06a0e6b1 Aurelien Jarno
FOP_COND_PS(ole, float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status),
3183 06a0e6b1 Aurelien Jarno
                 float32_le_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
3184 06a0e6b1 Aurelien Jarno
FOP_COND_PS(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status),
3185 06a0e6b1 Aurelien Jarno
                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_le_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
3186 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
3187 3a599383 Aurelien Jarno
 * but float32_unordered() is still called. */
3188 3a599383 Aurelien Jarno
FOP_COND_PS(sf,  (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0),
3189 3a599383 Aurelien Jarno
                 (float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status), 0))
3190 3a599383 Aurelien Jarno
FOP_COND_PS(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status),
3191 3a599383 Aurelien Jarno
                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status))
3192 06a0e6b1 Aurelien Jarno
FOP_COND_PS(seq, float32_eq(fst0, fst1, &env->active_fpu.fp_status),
3193 06a0e6b1 Aurelien Jarno
                 float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
3194 06a0e6b1 Aurelien Jarno
FOP_COND_PS(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
3195 06a0e6b1 Aurelien Jarno
                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
3196 06a0e6b1 Aurelien Jarno
FOP_COND_PS(lt,  float32_lt(fst0, fst1, &env->active_fpu.fp_status),
3197 06a0e6b1 Aurelien Jarno
                 float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
3198 3a599383 Aurelien Jarno
FOP_COND_PS(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
3199 3a599383 Aurelien Jarno
                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
3200 06a0e6b1 Aurelien Jarno
FOP_COND_PS(le,  float32_le(fst0, fst1, &env->active_fpu.fp_status),
3201 06a0e6b1 Aurelien Jarno
                 float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
3202 3a599383 Aurelien Jarno
FOP_COND_PS(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_le(fst0, fst1, &env->active_fpu.fp_status),
3203 3a599383 Aurelien Jarno
                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))