xref: /openbmc/qemu/target/mips/tcg/ldst_helper.c (revision 4885b99a6e05d16f40af18a062a5cb45fa92ec27)
1a2b0a27dSPhilippe Mathieu-Daudé /*
2a2b0a27dSPhilippe Mathieu-Daudé  *  MIPS emulation load/store helpers for QEMU.
3a2b0a27dSPhilippe Mathieu-Daudé  *
4a2b0a27dSPhilippe Mathieu-Daudé  *  Copyright (c) 2004-2005 Jocelyn Mayer
5a2b0a27dSPhilippe Mathieu-Daudé  *
6a2b0a27dSPhilippe Mathieu-Daudé  * SPDX-License-Identifier: LGPL-2.1-or-later
7a2b0a27dSPhilippe Mathieu-Daudé  *
8a2b0a27dSPhilippe Mathieu-Daudé  * This library is free software; you can redistribute it and/or
9a2b0a27dSPhilippe Mathieu-Daudé  * modify it under the terms of the GNU Lesser General Public
10a2b0a27dSPhilippe Mathieu-Daudé  * License as published by the Free Software Foundation; either
11a2b0a27dSPhilippe Mathieu-Daudé  * version 2.1 of the License, or (at your option) any later version.
12a2b0a27dSPhilippe Mathieu-Daudé  *
13a2b0a27dSPhilippe Mathieu-Daudé  * This library is distributed in the hope that it will be useful,
14a2b0a27dSPhilippe Mathieu-Daudé  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15a2b0a27dSPhilippe Mathieu-Daudé  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16a2b0a27dSPhilippe Mathieu-Daudé  * Lesser General Public License for more details.
17a2b0a27dSPhilippe Mathieu-Daudé  *
18a2b0a27dSPhilippe Mathieu-Daudé  * You should have received a copy of the GNU Lesser General Public
19a2b0a27dSPhilippe Mathieu-Daudé  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20a2b0a27dSPhilippe Mathieu-Daudé  *
21a2b0a27dSPhilippe Mathieu-Daudé  */
22a2b0a27dSPhilippe Mathieu-Daudé 
23a2b0a27dSPhilippe Mathieu-Daudé #include "qemu/osdep.h"
24a2b0a27dSPhilippe Mathieu-Daudé #include "cpu.h"
25a2b0a27dSPhilippe Mathieu-Daudé #include "exec/helper-proto.h"
26a2b0a27dSPhilippe Mathieu-Daudé #include "exec/exec-all.h"
27a2b0a27dSPhilippe Mathieu-Daudé #include "exec/memop.h"
28a2b0a27dSPhilippe Mathieu-Daudé #include "internal.h"
29a2b0a27dSPhilippe Mathieu-Daudé 
30a2b0a27dSPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
31a2b0a27dSPhilippe Mathieu-Daudé 
32a2b0a27dSPhilippe Mathieu-Daudé #define HELPER_LD_ATOMIC(name, insn, almask, do_cast)                         \
33a2b0a27dSPhilippe Mathieu-Daudé target_ulong helper_##name(CPUMIPSState *env, target_ulong arg, int mem_idx)  \
34a2b0a27dSPhilippe Mathieu-Daudé {                                                                             \
35a2b0a27dSPhilippe Mathieu-Daudé     if (arg & almask) {                                                       \
36a2b0a27dSPhilippe Mathieu-Daudé         if (!(env->hflags & MIPS_HFLAG_DM)) {                                 \
37a2b0a27dSPhilippe Mathieu-Daudé             env->CP0_BadVAddr = arg;                                          \
38a2b0a27dSPhilippe Mathieu-Daudé         }                                                                     \
39a2b0a27dSPhilippe Mathieu-Daudé         do_raise_exception(env, EXCP_AdEL, GETPC());                          \
40a2b0a27dSPhilippe Mathieu-Daudé     }                                                                         \
41a2b0a27dSPhilippe Mathieu-Daudé     env->CP0_LLAddr = cpu_mips_translate_address(env, arg, MMU_DATA_LOAD,     \
42a2b0a27dSPhilippe Mathieu-Daudé                                                  GETPC());                    \
43a2b0a27dSPhilippe Mathieu-Daudé     env->lladdr = arg;                                                        \
44a2b0a27dSPhilippe Mathieu-Daudé     env->llval = do_cast cpu_##insn##_mmuidx_ra(env, arg, mem_idx, GETPC());  \
45a2b0a27dSPhilippe Mathieu-Daudé     return env->llval;                                                        \
46a2b0a27dSPhilippe Mathieu-Daudé }
47a2b0a27dSPhilippe Mathieu-Daudé HELPER_LD_ATOMIC(ll, ldl, 0x3, (target_long)(int32_t))
48a2b0a27dSPhilippe Mathieu-Daudé #ifdef TARGET_MIPS64
49a2b0a27dSPhilippe Mathieu-Daudé HELPER_LD_ATOMIC(lld, ldq, 0x7, (target_ulong))
50a2b0a27dSPhilippe Mathieu-Daudé #endif
51a2b0a27dSPhilippe Mathieu-Daudé #undef HELPER_LD_ATOMIC
52a2b0a27dSPhilippe Mathieu-Daudé 
53a2b0a27dSPhilippe Mathieu-Daudé #endif /* !CONFIG_USER_ONLY */
54a2b0a27dSPhilippe Mathieu-Daudé 
555b3cc34cSPhilippe Mathieu-Daudé static inline bool cpu_is_bigendian(CPUMIPSState *env)
565b3cc34cSPhilippe Mathieu-Daudé {
575b3cc34cSPhilippe Mathieu-Daudé     return extract32(env->CP0_Config0, CP0C0_BE, 1);
585b3cc34cSPhilippe Mathieu-Daudé }
595b3cc34cSPhilippe Mathieu-Daudé 
60*4885b99aSPhilippe Mathieu-Daudé static inline target_ulong get_lmask(CPUMIPSState *env,
61*4885b99aSPhilippe Mathieu-Daudé                                      target_ulong value, unsigned bits)
62*4885b99aSPhilippe Mathieu-Daudé {
63*4885b99aSPhilippe Mathieu-Daudé     unsigned mask = (bits / BITS_PER_BYTE) - 1;
64*4885b99aSPhilippe Mathieu-Daudé 
65*4885b99aSPhilippe Mathieu-Daudé     value &= mask;
66*4885b99aSPhilippe Mathieu-Daudé 
67*4885b99aSPhilippe Mathieu-Daudé     if (!cpu_is_bigendian(env)) {
68*4885b99aSPhilippe Mathieu-Daudé         value ^= mask;
69*4885b99aSPhilippe Mathieu-Daudé     }
70*4885b99aSPhilippe Mathieu-Daudé 
71*4885b99aSPhilippe Mathieu-Daudé     return value;
72*4885b99aSPhilippe Mathieu-Daudé }
73a2b0a27dSPhilippe Mathieu-Daudé 
74a2b0a27dSPhilippe Mathieu-Daudé void helper_swl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
75a2b0a27dSPhilippe Mathieu-Daudé                 int mem_idx)
76a2b0a27dSPhilippe Mathieu-Daudé {
77*4885b99aSPhilippe Mathieu-Daudé     target_ulong lmask = get_lmask(env, arg2, 32);
785b3cc34cSPhilippe Mathieu-Daudé     int dir = cpu_is_bigendian(env) ? 1 : -1;
795b3cc34cSPhilippe Mathieu-Daudé 
80a2b0a27dSPhilippe Mathieu-Daudé     cpu_stb_mmuidx_ra(env, arg2, (uint8_t)(arg1 >> 24), mem_idx, GETPC());
81a2b0a27dSPhilippe Mathieu-Daudé 
82*4885b99aSPhilippe Mathieu-Daudé     if (lmask <= 2) {
835b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 + 1 * dir, (uint8_t)(arg1 >> 16),
84a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
85a2b0a27dSPhilippe Mathieu-Daudé     }
86a2b0a27dSPhilippe Mathieu-Daudé 
87*4885b99aSPhilippe Mathieu-Daudé     if (lmask <= 1) {
885b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 + 2 * dir, (uint8_t)(arg1 >> 8),
89a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
90a2b0a27dSPhilippe Mathieu-Daudé     }
91a2b0a27dSPhilippe Mathieu-Daudé 
92*4885b99aSPhilippe Mathieu-Daudé     if (lmask == 0) {
935b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 + 3 * dir, (uint8_t)arg1,
94a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
95a2b0a27dSPhilippe Mathieu-Daudé     }
96a2b0a27dSPhilippe Mathieu-Daudé }
97a2b0a27dSPhilippe Mathieu-Daudé 
98a2b0a27dSPhilippe Mathieu-Daudé void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
99a2b0a27dSPhilippe Mathieu-Daudé                 int mem_idx)
100a2b0a27dSPhilippe Mathieu-Daudé {
101*4885b99aSPhilippe Mathieu-Daudé     target_ulong lmask = get_lmask(env, arg2, 32);
1025b3cc34cSPhilippe Mathieu-Daudé     int dir = cpu_is_bigendian(env) ? 1 : -1;
1035b3cc34cSPhilippe Mathieu-Daudé 
104a2b0a27dSPhilippe Mathieu-Daudé     cpu_stb_mmuidx_ra(env, arg2, (uint8_t)arg1, mem_idx, GETPC());
105a2b0a27dSPhilippe Mathieu-Daudé 
106*4885b99aSPhilippe Mathieu-Daudé     if (lmask >= 1) {
1075b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 - 1 * dir, (uint8_t)(arg1 >> 8),
108a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
109a2b0a27dSPhilippe Mathieu-Daudé     }
110a2b0a27dSPhilippe Mathieu-Daudé 
111*4885b99aSPhilippe Mathieu-Daudé     if (lmask >= 2) {
1125b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 - 2 * dir, (uint8_t)(arg1 >> 16),
113a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
114a2b0a27dSPhilippe Mathieu-Daudé     }
115a2b0a27dSPhilippe Mathieu-Daudé 
116*4885b99aSPhilippe Mathieu-Daudé     if (lmask == 3) {
1175b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 - 3 * dir, (uint8_t)(arg1 >> 24),
118a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
119a2b0a27dSPhilippe Mathieu-Daudé     }
120a2b0a27dSPhilippe Mathieu-Daudé }
121a2b0a27dSPhilippe Mathieu-Daudé 
122a2b0a27dSPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
123a2b0a27dSPhilippe Mathieu-Daudé /*
124a2b0a27dSPhilippe Mathieu-Daudé  * "half" load and stores.  We must do the memory access inline,
125a2b0a27dSPhilippe Mathieu-Daudé  * or fault handling won't work.
126a2b0a27dSPhilippe Mathieu-Daudé  */
127a2b0a27dSPhilippe Mathieu-Daudé #ifdef TARGET_WORDS_BIGENDIAN
128a2b0a27dSPhilippe Mathieu-Daudé #define GET_LMASK64(v) ((v) & 7)
129a2b0a27dSPhilippe Mathieu-Daudé #else
130a2b0a27dSPhilippe Mathieu-Daudé #define GET_LMASK64(v) (((v) & 7) ^ 7)
131a2b0a27dSPhilippe Mathieu-Daudé #endif
132a2b0a27dSPhilippe Mathieu-Daudé 
133a2b0a27dSPhilippe Mathieu-Daudé void helper_sdl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
134a2b0a27dSPhilippe Mathieu-Daudé                 int mem_idx)
135a2b0a27dSPhilippe Mathieu-Daudé {
1365b3cc34cSPhilippe Mathieu-Daudé     int dir = cpu_is_bigendian(env) ? 1 : -1;
1375b3cc34cSPhilippe Mathieu-Daudé 
138a2b0a27dSPhilippe Mathieu-Daudé     cpu_stb_mmuidx_ra(env, arg2, (uint8_t)(arg1 >> 56), mem_idx, GETPC());
139a2b0a27dSPhilippe Mathieu-Daudé 
140a2b0a27dSPhilippe Mathieu-Daudé     if (GET_LMASK64(arg2) <= 6) {
1415b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 + 1 * dir, (uint8_t)(arg1 >> 48),
142a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
143a2b0a27dSPhilippe Mathieu-Daudé     }
144a2b0a27dSPhilippe Mathieu-Daudé 
145a2b0a27dSPhilippe Mathieu-Daudé     if (GET_LMASK64(arg2) <= 5) {
1465b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 + 2 * dir, (uint8_t)(arg1 >> 40),
147a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
148a2b0a27dSPhilippe Mathieu-Daudé     }
149a2b0a27dSPhilippe Mathieu-Daudé 
150a2b0a27dSPhilippe Mathieu-Daudé     if (GET_LMASK64(arg2) <= 4) {
1515b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 + 3 * dir, (uint8_t)(arg1 >> 32),
152a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
153a2b0a27dSPhilippe Mathieu-Daudé     }
154a2b0a27dSPhilippe Mathieu-Daudé 
155a2b0a27dSPhilippe Mathieu-Daudé     if (GET_LMASK64(arg2) <= 3) {
1565b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 + 4 * dir, (uint8_t)(arg1 >> 24),
157a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
158a2b0a27dSPhilippe Mathieu-Daudé     }
159a2b0a27dSPhilippe Mathieu-Daudé 
160a2b0a27dSPhilippe Mathieu-Daudé     if (GET_LMASK64(arg2) <= 2) {
1615b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 + 5 * dir, (uint8_t)(arg1 >> 16),
162a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
163a2b0a27dSPhilippe Mathieu-Daudé     }
164a2b0a27dSPhilippe Mathieu-Daudé 
165a2b0a27dSPhilippe Mathieu-Daudé     if (GET_LMASK64(arg2) <= 1) {
1665b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 + 6 * dir, (uint8_t)(arg1 >> 8),
167a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
168a2b0a27dSPhilippe Mathieu-Daudé     }
169a2b0a27dSPhilippe Mathieu-Daudé 
170a2b0a27dSPhilippe Mathieu-Daudé     if (GET_LMASK64(arg2) <= 0) {
1715b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 + 7 * dir, (uint8_t)arg1,
172a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
173a2b0a27dSPhilippe Mathieu-Daudé     }
174a2b0a27dSPhilippe Mathieu-Daudé }
175a2b0a27dSPhilippe Mathieu-Daudé 
176a2b0a27dSPhilippe Mathieu-Daudé void helper_sdr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
177a2b0a27dSPhilippe Mathieu-Daudé                 int mem_idx)
178a2b0a27dSPhilippe Mathieu-Daudé {
1795b3cc34cSPhilippe Mathieu-Daudé     int dir = cpu_is_bigendian(env) ? 1 : -1;
1805b3cc34cSPhilippe Mathieu-Daudé 
181a2b0a27dSPhilippe Mathieu-Daudé     cpu_stb_mmuidx_ra(env, arg2, (uint8_t)arg1, mem_idx, GETPC());
182a2b0a27dSPhilippe Mathieu-Daudé 
183a2b0a27dSPhilippe Mathieu-Daudé     if (GET_LMASK64(arg2) >= 1) {
1845b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 - 1 * dir, (uint8_t)(arg1 >> 8),
185a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
186a2b0a27dSPhilippe Mathieu-Daudé     }
187a2b0a27dSPhilippe Mathieu-Daudé 
188a2b0a27dSPhilippe Mathieu-Daudé     if (GET_LMASK64(arg2) >= 2) {
1895b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 - 2 * dir, (uint8_t)(arg1 >> 16),
190a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
191a2b0a27dSPhilippe Mathieu-Daudé     }
192a2b0a27dSPhilippe Mathieu-Daudé 
193a2b0a27dSPhilippe Mathieu-Daudé     if (GET_LMASK64(arg2) >= 3) {
1945b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 - 3 * dir, (uint8_t)(arg1 >> 24),
195a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
196a2b0a27dSPhilippe Mathieu-Daudé     }
197a2b0a27dSPhilippe Mathieu-Daudé 
198a2b0a27dSPhilippe Mathieu-Daudé     if (GET_LMASK64(arg2) >= 4) {
1995b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 - 4 * dir, (uint8_t)(arg1 >> 32),
200a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
201a2b0a27dSPhilippe Mathieu-Daudé     }
202a2b0a27dSPhilippe Mathieu-Daudé 
203a2b0a27dSPhilippe Mathieu-Daudé     if (GET_LMASK64(arg2) >= 5) {
2045b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 - 5 * dir, (uint8_t)(arg1 >> 40),
205a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
206a2b0a27dSPhilippe Mathieu-Daudé     }
207a2b0a27dSPhilippe Mathieu-Daudé 
208a2b0a27dSPhilippe Mathieu-Daudé     if (GET_LMASK64(arg2) >= 6) {
2095b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 - 6 * dir, (uint8_t)(arg1 >> 48),
210a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
211a2b0a27dSPhilippe Mathieu-Daudé     }
212a2b0a27dSPhilippe Mathieu-Daudé 
213a2b0a27dSPhilippe Mathieu-Daudé     if (GET_LMASK64(arg2) == 7) {
2145b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 - 7 * dir, (uint8_t)(arg1 >> 56),
215a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
216a2b0a27dSPhilippe Mathieu-Daudé     }
217a2b0a27dSPhilippe Mathieu-Daudé }
218a2b0a27dSPhilippe Mathieu-Daudé #endif /* TARGET_MIPS64 */
219a2b0a27dSPhilippe Mathieu-Daudé 
220a2b0a27dSPhilippe Mathieu-Daudé static const int multiple_regs[] = { 16, 17, 18, 19, 20, 21, 22, 23, 30 };
221a2b0a27dSPhilippe Mathieu-Daudé 
222a2b0a27dSPhilippe Mathieu-Daudé void helper_lwm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
223a2b0a27dSPhilippe Mathieu-Daudé                 uint32_t mem_idx)
224a2b0a27dSPhilippe Mathieu-Daudé {
225a2b0a27dSPhilippe Mathieu-Daudé     target_ulong base_reglist = reglist & 0xf;
226a2b0a27dSPhilippe Mathieu-Daudé     target_ulong do_r31 = reglist & 0x10;
227a2b0a27dSPhilippe Mathieu-Daudé 
228a2b0a27dSPhilippe Mathieu-Daudé     if (base_reglist > 0 && base_reglist <= ARRAY_SIZE(multiple_regs)) {
229a2b0a27dSPhilippe Mathieu-Daudé         target_ulong i;
230a2b0a27dSPhilippe Mathieu-Daudé 
231a2b0a27dSPhilippe Mathieu-Daudé         for (i = 0; i < base_reglist; i++) {
232a2b0a27dSPhilippe Mathieu-Daudé             env->active_tc.gpr[multiple_regs[i]] =
233a2b0a27dSPhilippe Mathieu-Daudé                 (target_long)cpu_ldl_mmuidx_ra(env, addr, mem_idx, GETPC());
234a2b0a27dSPhilippe Mathieu-Daudé             addr += 4;
235a2b0a27dSPhilippe Mathieu-Daudé         }
236a2b0a27dSPhilippe Mathieu-Daudé     }
237a2b0a27dSPhilippe Mathieu-Daudé 
238a2b0a27dSPhilippe Mathieu-Daudé     if (do_r31) {
239a2b0a27dSPhilippe Mathieu-Daudé         env->active_tc.gpr[31] =
240a2b0a27dSPhilippe Mathieu-Daudé             (target_long)cpu_ldl_mmuidx_ra(env, addr, mem_idx, GETPC());
241a2b0a27dSPhilippe Mathieu-Daudé     }
242a2b0a27dSPhilippe Mathieu-Daudé }
243a2b0a27dSPhilippe Mathieu-Daudé 
244a2b0a27dSPhilippe Mathieu-Daudé void helper_swm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
245a2b0a27dSPhilippe Mathieu-Daudé                 uint32_t mem_idx)
246a2b0a27dSPhilippe Mathieu-Daudé {
247a2b0a27dSPhilippe Mathieu-Daudé     target_ulong base_reglist = reglist & 0xf;
248a2b0a27dSPhilippe Mathieu-Daudé     target_ulong do_r31 = reglist & 0x10;
249a2b0a27dSPhilippe Mathieu-Daudé 
250a2b0a27dSPhilippe Mathieu-Daudé     if (base_reglist > 0 && base_reglist <= ARRAY_SIZE(multiple_regs)) {
251a2b0a27dSPhilippe Mathieu-Daudé         target_ulong i;
252a2b0a27dSPhilippe Mathieu-Daudé 
253a2b0a27dSPhilippe Mathieu-Daudé         for (i = 0; i < base_reglist; i++) {
254a2b0a27dSPhilippe Mathieu-Daudé             cpu_stw_mmuidx_ra(env, addr, env->active_tc.gpr[multiple_regs[i]],
255a2b0a27dSPhilippe Mathieu-Daudé                               mem_idx, GETPC());
256a2b0a27dSPhilippe Mathieu-Daudé             addr += 4;
257a2b0a27dSPhilippe Mathieu-Daudé         }
258a2b0a27dSPhilippe Mathieu-Daudé     }
259a2b0a27dSPhilippe Mathieu-Daudé 
260a2b0a27dSPhilippe Mathieu-Daudé     if (do_r31) {
261a2b0a27dSPhilippe Mathieu-Daudé         cpu_stw_mmuidx_ra(env, addr, env->active_tc.gpr[31], mem_idx, GETPC());
262a2b0a27dSPhilippe Mathieu-Daudé     }
263a2b0a27dSPhilippe Mathieu-Daudé }
264a2b0a27dSPhilippe Mathieu-Daudé 
265a2b0a27dSPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
266a2b0a27dSPhilippe Mathieu-Daudé void helper_ldm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
267a2b0a27dSPhilippe Mathieu-Daudé                 uint32_t mem_idx)
268a2b0a27dSPhilippe Mathieu-Daudé {
269a2b0a27dSPhilippe Mathieu-Daudé     target_ulong base_reglist = reglist & 0xf;
270a2b0a27dSPhilippe Mathieu-Daudé     target_ulong do_r31 = reglist & 0x10;
271a2b0a27dSPhilippe Mathieu-Daudé 
272a2b0a27dSPhilippe Mathieu-Daudé     if (base_reglist > 0 && base_reglist <= ARRAY_SIZE(multiple_regs)) {
273a2b0a27dSPhilippe Mathieu-Daudé         target_ulong i;
274a2b0a27dSPhilippe Mathieu-Daudé 
275a2b0a27dSPhilippe Mathieu-Daudé         for (i = 0; i < base_reglist; i++) {
276a2b0a27dSPhilippe Mathieu-Daudé             env->active_tc.gpr[multiple_regs[i]] =
277a2b0a27dSPhilippe Mathieu-Daudé                 cpu_ldq_mmuidx_ra(env, addr, mem_idx, GETPC());
278a2b0a27dSPhilippe Mathieu-Daudé             addr += 8;
279a2b0a27dSPhilippe Mathieu-Daudé         }
280a2b0a27dSPhilippe Mathieu-Daudé     }
281a2b0a27dSPhilippe Mathieu-Daudé 
282a2b0a27dSPhilippe Mathieu-Daudé     if (do_r31) {
283a2b0a27dSPhilippe Mathieu-Daudé         env->active_tc.gpr[31] =
284a2b0a27dSPhilippe Mathieu-Daudé             cpu_ldq_mmuidx_ra(env, addr, mem_idx, GETPC());
285a2b0a27dSPhilippe Mathieu-Daudé     }
286a2b0a27dSPhilippe Mathieu-Daudé }
287a2b0a27dSPhilippe Mathieu-Daudé 
288a2b0a27dSPhilippe Mathieu-Daudé void helper_sdm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
289a2b0a27dSPhilippe Mathieu-Daudé                 uint32_t mem_idx)
290a2b0a27dSPhilippe Mathieu-Daudé {
291a2b0a27dSPhilippe Mathieu-Daudé     target_ulong base_reglist = reglist & 0xf;
292a2b0a27dSPhilippe Mathieu-Daudé     target_ulong do_r31 = reglist & 0x10;
293a2b0a27dSPhilippe Mathieu-Daudé 
294a2b0a27dSPhilippe Mathieu-Daudé     if (base_reglist > 0 && base_reglist <= ARRAY_SIZE(multiple_regs)) {
295a2b0a27dSPhilippe Mathieu-Daudé         target_ulong i;
296a2b0a27dSPhilippe Mathieu-Daudé 
297a2b0a27dSPhilippe Mathieu-Daudé         for (i = 0; i < base_reglist; i++) {
298a2b0a27dSPhilippe Mathieu-Daudé             cpu_stq_mmuidx_ra(env, addr, env->active_tc.gpr[multiple_regs[i]],
299a2b0a27dSPhilippe Mathieu-Daudé                               mem_idx, GETPC());
300a2b0a27dSPhilippe Mathieu-Daudé             addr += 8;
301a2b0a27dSPhilippe Mathieu-Daudé         }
302a2b0a27dSPhilippe Mathieu-Daudé     }
303a2b0a27dSPhilippe Mathieu-Daudé 
304a2b0a27dSPhilippe Mathieu-Daudé     if (do_r31) {
305a2b0a27dSPhilippe Mathieu-Daudé         cpu_stq_mmuidx_ra(env, addr, env->active_tc.gpr[31], mem_idx, GETPC());
306a2b0a27dSPhilippe Mathieu-Daudé     }
307a2b0a27dSPhilippe Mathieu-Daudé }
308a2b0a27dSPhilippe Mathieu-Daudé 
309a2b0a27dSPhilippe Mathieu-Daudé #endif /* TARGET_MIPS64 */
310