xref: /openbmc/qemu/target/mips/tcg/ldst_helper.c (revision 23a04dcdf6fa6b34933778b16ee8200027dc6e68)
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é 
604885b99aSPhilippe Mathieu-Daudé static inline target_ulong get_lmask(CPUMIPSState *env,
614885b99aSPhilippe Mathieu-Daudé                                      target_ulong value, unsigned bits)
624885b99aSPhilippe Mathieu-Daudé {
634885b99aSPhilippe Mathieu-Daudé     unsigned mask = (bits / BITS_PER_BYTE) - 1;
644885b99aSPhilippe Mathieu-Daudé 
654885b99aSPhilippe Mathieu-Daudé     value &= mask;
664885b99aSPhilippe Mathieu-Daudé 
674885b99aSPhilippe Mathieu-Daudé     if (!cpu_is_bigendian(env)) {
684885b99aSPhilippe Mathieu-Daudé         value ^= mask;
694885b99aSPhilippe Mathieu-Daudé     }
704885b99aSPhilippe Mathieu-Daudé 
714885b99aSPhilippe Mathieu-Daudé     return value;
724885b99aSPhilippe 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é {
774885b99aSPhilippe 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é 
824885b99aSPhilippe 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é 
874885b99aSPhilippe 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é 
924885b99aSPhilippe 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é {
1014885b99aSPhilippe 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é 
1064885b99aSPhilippe 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é 
1114885b99aSPhilippe 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é 
1164885b99aSPhilippe 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é 
128a2b0a27dSPhilippe Mathieu-Daudé void helper_sdl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
129a2b0a27dSPhilippe Mathieu-Daudé                 int mem_idx)
130a2b0a27dSPhilippe Mathieu-Daudé {
131*23a04dcdSPhilippe Mathieu-Daudé     target_ulong lmask = get_lmask(env, arg2, 64);
1325b3cc34cSPhilippe Mathieu-Daudé     int dir = cpu_is_bigendian(env) ? 1 : -1;
1335b3cc34cSPhilippe Mathieu-Daudé 
134a2b0a27dSPhilippe Mathieu-Daudé     cpu_stb_mmuidx_ra(env, arg2, (uint8_t)(arg1 >> 56), mem_idx, GETPC());
135a2b0a27dSPhilippe Mathieu-Daudé 
136*23a04dcdSPhilippe Mathieu-Daudé     if (lmask <= 6) {
1375b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 + 1 * dir, (uint8_t)(arg1 >> 48),
138a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
139a2b0a27dSPhilippe Mathieu-Daudé     }
140a2b0a27dSPhilippe Mathieu-Daudé 
141*23a04dcdSPhilippe Mathieu-Daudé     if (lmask <= 5) {
1425b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 + 2 * dir, (uint8_t)(arg1 >> 40),
143a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
144a2b0a27dSPhilippe Mathieu-Daudé     }
145a2b0a27dSPhilippe Mathieu-Daudé 
146*23a04dcdSPhilippe Mathieu-Daudé     if (lmask <= 4) {
1475b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 + 3 * dir, (uint8_t)(arg1 >> 32),
148a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
149a2b0a27dSPhilippe Mathieu-Daudé     }
150a2b0a27dSPhilippe Mathieu-Daudé 
151*23a04dcdSPhilippe Mathieu-Daudé     if (lmask <= 3) {
1525b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 + 4 * dir, (uint8_t)(arg1 >> 24),
153a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
154a2b0a27dSPhilippe Mathieu-Daudé     }
155a2b0a27dSPhilippe Mathieu-Daudé 
156*23a04dcdSPhilippe Mathieu-Daudé     if (lmask <= 2) {
1575b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 + 5 * dir, (uint8_t)(arg1 >> 16),
158a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
159a2b0a27dSPhilippe Mathieu-Daudé     }
160a2b0a27dSPhilippe Mathieu-Daudé 
161*23a04dcdSPhilippe Mathieu-Daudé     if (lmask <= 1) {
1625b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 + 6 * dir, (uint8_t)(arg1 >> 8),
163a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
164a2b0a27dSPhilippe Mathieu-Daudé     }
165a2b0a27dSPhilippe Mathieu-Daudé 
166*23a04dcdSPhilippe Mathieu-Daudé     if (lmask <= 0) {
1675b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 + 7 * dir, (uint8_t)arg1,
168a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
169a2b0a27dSPhilippe Mathieu-Daudé     }
170a2b0a27dSPhilippe Mathieu-Daudé }
171a2b0a27dSPhilippe Mathieu-Daudé 
172a2b0a27dSPhilippe Mathieu-Daudé void helper_sdr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
173a2b0a27dSPhilippe Mathieu-Daudé                 int mem_idx)
174a2b0a27dSPhilippe Mathieu-Daudé {
175*23a04dcdSPhilippe Mathieu-Daudé     target_ulong lmask = get_lmask(env, arg2, 64);
1765b3cc34cSPhilippe Mathieu-Daudé     int dir = cpu_is_bigendian(env) ? 1 : -1;
1775b3cc34cSPhilippe Mathieu-Daudé 
178a2b0a27dSPhilippe Mathieu-Daudé     cpu_stb_mmuidx_ra(env, arg2, (uint8_t)arg1, mem_idx, GETPC());
179a2b0a27dSPhilippe Mathieu-Daudé 
180*23a04dcdSPhilippe Mathieu-Daudé     if (lmask >= 1) {
1815b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 - 1 * dir, (uint8_t)(arg1 >> 8),
182a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
183a2b0a27dSPhilippe Mathieu-Daudé     }
184a2b0a27dSPhilippe Mathieu-Daudé 
185*23a04dcdSPhilippe Mathieu-Daudé     if (lmask >= 2) {
1865b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 - 2 * dir, (uint8_t)(arg1 >> 16),
187a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
188a2b0a27dSPhilippe Mathieu-Daudé     }
189a2b0a27dSPhilippe Mathieu-Daudé 
190*23a04dcdSPhilippe Mathieu-Daudé     if (lmask >= 3) {
1915b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 - 3 * dir, (uint8_t)(arg1 >> 24),
192a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
193a2b0a27dSPhilippe Mathieu-Daudé     }
194a2b0a27dSPhilippe Mathieu-Daudé 
195*23a04dcdSPhilippe Mathieu-Daudé     if (lmask >= 4) {
1965b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 - 4 * dir, (uint8_t)(arg1 >> 32),
197a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
198a2b0a27dSPhilippe Mathieu-Daudé     }
199a2b0a27dSPhilippe Mathieu-Daudé 
200*23a04dcdSPhilippe Mathieu-Daudé     if (lmask >= 5) {
2015b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 - 5 * dir, (uint8_t)(arg1 >> 40),
202a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
203a2b0a27dSPhilippe Mathieu-Daudé     }
204a2b0a27dSPhilippe Mathieu-Daudé 
205*23a04dcdSPhilippe Mathieu-Daudé     if (lmask >= 6) {
2065b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 - 6 * dir, (uint8_t)(arg1 >> 48),
207a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
208a2b0a27dSPhilippe Mathieu-Daudé     }
209a2b0a27dSPhilippe Mathieu-Daudé 
210*23a04dcdSPhilippe Mathieu-Daudé     if (lmask == 7) {
2115b3cc34cSPhilippe Mathieu-Daudé         cpu_stb_mmuidx_ra(env, arg2 - 7 * dir, (uint8_t)(arg1 >> 56),
212a2b0a27dSPhilippe Mathieu-Daudé                           mem_idx, GETPC());
213a2b0a27dSPhilippe Mathieu-Daudé     }
214a2b0a27dSPhilippe Mathieu-Daudé }
215a2b0a27dSPhilippe Mathieu-Daudé #endif /* TARGET_MIPS64 */
216a2b0a27dSPhilippe Mathieu-Daudé 
217a2b0a27dSPhilippe Mathieu-Daudé static const int multiple_regs[] = { 16, 17, 18, 19, 20, 21, 22, 23, 30 };
218a2b0a27dSPhilippe Mathieu-Daudé 
219a2b0a27dSPhilippe Mathieu-Daudé void helper_lwm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
220a2b0a27dSPhilippe Mathieu-Daudé                 uint32_t mem_idx)
221a2b0a27dSPhilippe Mathieu-Daudé {
222a2b0a27dSPhilippe Mathieu-Daudé     target_ulong base_reglist = reglist & 0xf;
223a2b0a27dSPhilippe Mathieu-Daudé     target_ulong do_r31 = reglist & 0x10;
224a2b0a27dSPhilippe Mathieu-Daudé 
225a2b0a27dSPhilippe Mathieu-Daudé     if (base_reglist > 0 && base_reglist <= ARRAY_SIZE(multiple_regs)) {
226a2b0a27dSPhilippe Mathieu-Daudé         target_ulong i;
227a2b0a27dSPhilippe Mathieu-Daudé 
228a2b0a27dSPhilippe Mathieu-Daudé         for (i = 0; i < base_reglist; i++) {
229a2b0a27dSPhilippe Mathieu-Daudé             env->active_tc.gpr[multiple_regs[i]] =
230a2b0a27dSPhilippe Mathieu-Daudé                 (target_long)cpu_ldl_mmuidx_ra(env, addr, mem_idx, GETPC());
231a2b0a27dSPhilippe Mathieu-Daudé             addr += 4;
232a2b0a27dSPhilippe Mathieu-Daudé         }
233a2b0a27dSPhilippe Mathieu-Daudé     }
234a2b0a27dSPhilippe Mathieu-Daudé 
235a2b0a27dSPhilippe Mathieu-Daudé     if (do_r31) {
236a2b0a27dSPhilippe Mathieu-Daudé         env->active_tc.gpr[31] =
237a2b0a27dSPhilippe Mathieu-Daudé             (target_long)cpu_ldl_mmuidx_ra(env, addr, mem_idx, GETPC());
238a2b0a27dSPhilippe Mathieu-Daudé     }
239a2b0a27dSPhilippe Mathieu-Daudé }
240a2b0a27dSPhilippe Mathieu-Daudé 
241a2b0a27dSPhilippe Mathieu-Daudé void helper_swm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
242a2b0a27dSPhilippe Mathieu-Daudé                 uint32_t mem_idx)
243a2b0a27dSPhilippe Mathieu-Daudé {
244a2b0a27dSPhilippe Mathieu-Daudé     target_ulong base_reglist = reglist & 0xf;
245a2b0a27dSPhilippe Mathieu-Daudé     target_ulong do_r31 = reglist & 0x10;
246a2b0a27dSPhilippe Mathieu-Daudé 
247a2b0a27dSPhilippe Mathieu-Daudé     if (base_reglist > 0 && base_reglist <= ARRAY_SIZE(multiple_regs)) {
248a2b0a27dSPhilippe Mathieu-Daudé         target_ulong i;
249a2b0a27dSPhilippe Mathieu-Daudé 
250a2b0a27dSPhilippe Mathieu-Daudé         for (i = 0; i < base_reglist; i++) {
251a2b0a27dSPhilippe Mathieu-Daudé             cpu_stw_mmuidx_ra(env, addr, env->active_tc.gpr[multiple_regs[i]],
252a2b0a27dSPhilippe Mathieu-Daudé                               mem_idx, GETPC());
253a2b0a27dSPhilippe Mathieu-Daudé             addr += 4;
254a2b0a27dSPhilippe Mathieu-Daudé         }
255a2b0a27dSPhilippe Mathieu-Daudé     }
256a2b0a27dSPhilippe Mathieu-Daudé 
257a2b0a27dSPhilippe Mathieu-Daudé     if (do_r31) {
258a2b0a27dSPhilippe Mathieu-Daudé         cpu_stw_mmuidx_ra(env, addr, env->active_tc.gpr[31], mem_idx, GETPC());
259a2b0a27dSPhilippe Mathieu-Daudé     }
260a2b0a27dSPhilippe Mathieu-Daudé }
261a2b0a27dSPhilippe Mathieu-Daudé 
262a2b0a27dSPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
263a2b0a27dSPhilippe Mathieu-Daudé void helper_ldm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
264a2b0a27dSPhilippe Mathieu-Daudé                 uint32_t mem_idx)
265a2b0a27dSPhilippe Mathieu-Daudé {
266a2b0a27dSPhilippe Mathieu-Daudé     target_ulong base_reglist = reglist & 0xf;
267a2b0a27dSPhilippe Mathieu-Daudé     target_ulong do_r31 = reglist & 0x10;
268a2b0a27dSPhilippe Mathieu-Daudé 
269a2b0a27dSPhilippe Mathieu-Daudé     if (base_reglist > 0 && base_reglist <= ARRAY_SIZE(multiple_regs)) {
270a2b0a27dSPhilippe Mathieu-Daudé         target_ulong i;
271a2b0a27dSPhilippe Mathieu-Daudé 
272a2b0a27dSPhilippe Mathieu-Daudé         for (i = 0; i < base_reglist; i++) {
273a2b0a27dSPhilippe Mathieu-Daudé             env->active_tc.gpr[multiple_regs[i]] =
274a2b0a27dSPhilippe Mathieu-Daudé                 cpu_ldq_mmuidx_ra(env, addr, mem_idx, GETPC());
275a2b0a27dSPhilippe Mathieu-Daudé             addr += 8;
276a2b0a27dSPhilippe Mathieu-Daudé         }
277a2b0a27dSPhilippe Mathieu-Daudé     }
278a2b0a27dSPhilippe Mathieu-Daudé 
279a2b0a27dSPhilippe Mathieu-Daudé     if (do_r31) {
280a2b0a27dSPhilippe Mathieu-Daudé         env->active_tc.gpr[31] =
281a2b0a27dSPhilippe Mathieu-Daudé             cpu_ldq_mmuidx_ra(env, addr, mem_idx, GETPC());
282a2b0a27dSPhilippe Mathieu-Daudé     }
283a2b0a27dSPhilippe Mathieu-Daudé }
284a2b0a27dSPhilippe Mathieu-Daudé 
285a2b0a27dSPhilippe Mathieu-Daudé void helper_sdm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
286a2b0a27dSPhilippe Mathieu-Daudé                 uint32_t mem_idx)
287a2b0a27dSPhilippe Mathieu-Daudé {
288a2b0a27dSPhilippe Mathieu-Daudé     target_ulong base_reglist = reglist & 0xf;
289a2b0a27dSPhilippe Mathieu-Daudé     target_ulong do_r31 = reglist & 0x10;
290a2b0a27dSPhilippe Mathieu-Daudé 
291a2b0a27dSPhilippe Mathieu-Daudé     if (base_reglist > 0 && base_reglist <= ARRAY_SIZE(multiple_regs)) {
292a2b0a27dSPhilippe Mathieu-Daudé         target_ulong i;
293a2b0a27dSPhilippe Mathieu-Daudé 
294a2b0a27dSPhilippe Mathieu-Daudé         for (i = 0; i < base_reglist; i++) {
295a2b0a27dSPhilippe Mathieu-Daudé             cpu_stq_mmuidx_ra(env, addr, env->active_tc.gpr[multiple_regs[i]],
296a2b0a27dSPhilippe Mathieu-Daudé                               mem_idx, GETPC());
297a2b0a27dSPhilippe Mathieu-Daudé             addr += 8;
298a2b0a27dSPhilippe Mathieu-Daudé         }
299a2b0a27dSPhilippe Mathieu-Daudé     }
300a2b0a27dSPhilippe Mathieu-Daudé 
301a2b0a27dSPhilippe Mathieu-Daudé     if (do_r31) {
302a2b0a27dSPhilippe Mathieu-Daudé         cpu_stq_mmuidx_ra(env, addr, env->active_tc.gpr[31], mem_idx, GETPC());
303a2b0a27dSPhilippe Mathieu-Daudé     }
304a2b0a27dSPhilippe Mathieu-Daudé }
305a2b0a27dSPhilippe Mathieu-Daudé 
306a2b0a27dSPhilippe Mathieu-Daudé #endif /* TARGET_MIPS64 */
307