42f5e2ba3f9f1b7919e96a9eff02b4bec6f69e11
[qemu] / target-mips / op_mem.c
1 /*
2  *  MIPS emulation memory micro-operations for qemu.
3  *
4  *  Copyright (c) 2004-2005 Jocelyn Mayer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 /* Standard loads and stores */
22 void glue(op_lb, MEMSUFFIX) (void)
23 {
24     T0 = glue(ldsb, MEMSUFFIX)(T0);
25     RETURN();
26 }
27
28 void glue(op_lbu, MEMSUFFIX) (void)
29 {
30     T0 = glue(ldub, MEMSUFFIX)(T0);
31     RETURN();
32 }
33
34 void glue(op_sb, MEMSUFFIX) (void)
35 {
36     glue(stb, MEMSUFFIX)(T0, T1);
37     RETURN();
38 }
39
40 void glue(op_lh, MEMSUFFIX) (void)
41 {
42     T0 = glue(ldsw, MEMSUFFIX)(T0);
43     RETURN();
44 }
45
46 void glue(op_lhu, MEMSUFFIX) (void)
47 {
48     T0 = glue(lduw, MEMSUFFIX)(T0);
49     RETURN();
50 }
51
52 void glue(op_sh, MEMSUFFIX) (void)
53 {
54     glue(stw, MEMSUFFIX)(T0, T1);
55     RETURN();
56 }
57
58 void glue(op_lw, MEMSUFFIX) (void)
59 {
60     T0 = glue(ldl, MEMSUFFIX)(T0);
61     RETURN();
62 }
63
64 void glue(op_lwu, MEMSUFFIX) (void)
65 {
66     T0 = (uint32_t)glue(ldl, MEMSUFFIX)(T0);
67     RETURN();
68 }
69
70 void glue(op_sw, MEMSUFFIX) (void)
71 {
72     glue(stl, MEMSUFFIX)(T0, T1);
73     RETURN();
74 }
75
76 /* "half" load and stores.  We must do the memory access inline,
77    or fault handling won't work.  */
78
79 #ifdef TARGET_WORDS_BIGENDIAN
80 #define GET_LMASK(v) ((v) & 3)
81 #define GET_OFFSET(addr, offset) (addr + (offset))
82 #else
83 #define GET_LMASK(v) (((v) & 3) ^ 3)
84 #define GET_OFFSET(addr, offset) (addr - (offset))
85 #endif
86
87 void glue(op_lwl, MEMSUFFIX) (void)
88 {
89     target_ulong tmp;
90
91     tmp = glue(ldub, MEMSUFFIX)(T0);
92     T1 = (T1 & 0x00FFFFFF) | (tmp << 24);
93
94     if (GET_LMASK(T0) <= 2) {
95         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 1));
96         T1 = (T1 & 0xFF00FFFF) | (tmp << 16);
97     }
98
99     if (GET_LMASK(T0) <= 1) {
100         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 2));
101         T1 = (T1 & 0xFFFF00FF) | (tmp << 8);
102     }
103
104     if (GET_LMASK(T0) == 0) {
105         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 3));
106         T1 = (T1 & 0xFFFFFF00) | tmp;
107     }
108     T1 = (int32_t)T1;
109     RETURN();
110 }
111
112 void glue(op_lwr, MEMSUFFIX) (void)
113 {
114     target_ulong tmp;
115
116     tmp = glue(ldub, MEMSUFFIX)(T0);
117     T1 = (T1 & 0xFFFFFF00) | tmp;
118
119     if (GET_LMASK(T0) >= 1) {
120         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -1));
121         T1 = (T1 & 0xFFFF00FF) | (tmp << 8);
122     }
123
124     if (GET_LMASK(T0) >= 2) {
125         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -2));
126         T1 = (T1 & 0xFF00FFFF) | (tmp << 16);
127     }
128
129     if (GET_LMASK(T0) == 3) {
130         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -3));
131         T1 = (T1 & 0x00FFFFFF) | (tmp << 24);
132     }
133     T1 = (int32_t)T1;
134     RETURN();
135 }
136
137 void glue(op_swl, MEMSUFFIX) (void)
138 {
139     glue(stb, MEMSUFFIX)(T0, (uint8_t)(T1 >> 24));
140
141     if (GET_LMASK(T0) <= 2)
142         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 16));
143
144     if (GET_LMASK(T0) <= 1)
145         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 8));
146
147     if (GET_LMASK(T0) == 0)
148         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 3), (uint8_t)T1);
149
150     RETURN();
151 }
152
153 void glue(op_swr, MEMSUFFIX) (void)
154 {
155     glue(stb, MEMSUFFIX)(T0, (uint8_t)T1);
156
157     if (GET_LMASK(T0) >= 1)
158         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
159
160     if (GET_LMASK(T0) >= 2)
161         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
162
163     if (GET_LMASK(T0) == 3)
164         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
165
166     RETURN();
167 }
168
169 void glue(op_ll, MEMSUFFIX) (void)
170 {
171     T1 = T0;
172     T0 = glue(ldl, MEMSUFFIX)(T0);
173     env->CP0_LLAddr = T1;
174     RETURN();
175 }
176
177 void glue(op_sc, MEMSUFFIX) (void)
178 {
179     CALL_FROM_TB0(dump_sc);
180     if (T0 & 0x3) {
181         env->CP0_BadVAddr = T0;
182         CALL_FROM_TB1(do_raise_exception, EXCP_AdES);
183     }
184     if (T0 == env->CP0_LLAddr) {
185         glue(stl, MEMSUFFIX)(T0, T1);
186         T0 = 1;
187     } else {
188         T0 = 0;
189     }
190     RETURN();
191 }
192
193 #if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
194 void glue(op_ld, MEMSUFFIX) (void)
195 {
196     T0 = glue(ldq, MEMSUFFIX)(T0);
197     RETURN();
198 }
199
200 void glue(op_sd, MEMSUFFIX) (void)
201 {
202     glue(stq, MEMSUFFIX)(T0, T1);
203     RETURN();
204 }
205
206 /* "half" load and stores.  We must do the memory access inline,
207    or fault handling won't work.  */
208
209 #ifdef TARGET_WORDS_BIGENDIAN
210 #define GET_LMASK64(v) ((v) & 7)
211 #else
212 #define GET_LMASK64(v) (((v) & 7) ^ 7)
213 #endif
214
215 void glue(op_ldl, MEMSUFFIX) (void)
216 {
217     uint64_t tmp;
218
219     tmp = glue(ldub, MEMSUFFIX)(T0);
220     T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
221
222     if (GET_LMASK64(T0) <= 6) {
223         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 1));
224         T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
225     }
226
227     if (GET_LMASK64(T0) <= 5) {
228         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 2));
229         T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
230     }
231
232     if (GET_LMASK64(T0) <= 4) {
233         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 3));
234         T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
235     }
236
237     if (GET_LMASK64(T0) <= 3) {
238         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 4));
239         T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
240     }
241
242     if (GET_LMASK64(T0) <= 2) {
243         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 5));
244         T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
245     }
246
247     if (GET_LMASK64(T0) <= 1) {
248         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 6));
249         T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
250     }
251
252     if (GET_LMASK64(T0) == 0) {
253         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 7));
254         T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
255     }
256
257     RETURN();
258 }
259
260 void glue(op_ldr, MEMSUFFIX) (void)
261 {
262     uint64_t tmp;
263
264     tmp = glue(ldub, MEMSUFFIX)(T0);
265     T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
266
267     if (GET_LMASK64(T0) >= 1) {
268         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -1));
269         T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp  << 8);
270     }
271
272     if (GET_LMASK64(T0) >= 2) {
273         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -2));
274         T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
275     }
276
277     if (GET_LMASK64(T0) >= 3) {
278         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -3));
279         T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
280     }
281
282     if (GET_LMASK64(T0) >= 4) {
283         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -4));
284         T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
285     }
286
287     if (GET_LMASK64(T0) >= 5) {
288         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -5));
289         T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
290     }
291
292     if (GET_LMASK64(T0) >= 6) {
293         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -6));
294         T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
295     }
296
297     if (GET_LMASK64(T0) == 7) {
298         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -7));
299         T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
300     }
301
302     RETURN();
303 }
304
305 void glue(op_sdl, MEMSUFFIX) (void)
306 {
307     glue(stb, MEMSUFFIX)(T0, (uint8_t)(T1 >> 56));
308
309     if (GET_LMASK64(T0) <= 6)
310         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 48));
311
312     if (GET_LMASK64(T0) <= 5)
313         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 40));
314
315     if (GET_LMASK64(T0) <= 4)
316         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 3), (uint8_t)(T1 >> 32));
317
318     if (GET_LMASK64(T0) <= 3)
319         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 4), (uint8_t)(T1 >> 24));
320
321     if (GET_LMASK64(T0) <= 2)
322         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 5), (uint8_t)(T1 >> 16));
323
324     if (GET_LMASK64(T0) <= 1)
325         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 6), (uint8_t)(T1 >> 8));
326
327     if (GET_LMASK64(T0) <= 0)
328         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 7), (uint8_t)T1);
329
330     RETURN();
331 }
332
333 void glue(op_sdr, MEMSUFFIX) (void)
334 {
335     glue(stb, MEMSUFFIX)(T0, (uint8_t)T1);
336
337     if (GET_LMASK64(T0) >= 1)
338         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
339
340     if (GET_LMASK64(T0) >= 2)
341         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
342
343     if (GET_LMASK64(T0) >= 3)
344         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
345
346     if (GET_LMASK64(T0) >= 4)
347         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -4), (uint8_t)(T1 >> 32));
348
349     if (GET_LMASK64(T0) >= 5)
350         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -5), (uint8_t)(T1 >> 40));
351
352     if (GET_LMASK64(T0) >= 6)
353         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -6), (uint8_t)(T1 >> 48));
354
355     if (GET_LMASK64(T0) == 7)
356         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -7), (uint8_t)(T1 >> 56));
357
358     RETURN();
359 }
360
361 void glue(op_lld, MEMSUFFIX) (void)
362 {
363     T1 = T0;
364     T0 = glue(ldq, MEMSUFFIX)(T0);
365     env->CP0_LLAddr = T1;
366     RETURN();
367 }
368
369 void glue(op_scd, MEMSUFFIX) (void)
370 {
371     CALL_FROM_TB0(dump_sc);
372     if (T0 & 0x7) {
373         env->CP0_BadVAddr = T0;
374         CALL_FROM_TB1(do_raise_exception, EXCP_AdES);
375     }
376     if (T0 == env->CP0_LLAddr) {
377         glue(stq, MEMSUFFIX)(T0, T1);
378         T0 = 1;
379     } else {
380         T0 = 0;
381     }
382     RETURN();
383 }
384 #endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
385
386 void glue(op_lwc1, MEMSUFFIX) (void)
387 {
388     WT0 = glue(ldl, MEMSUFFIX)(T0);
389     RETURN();
390 }
391 void glue(op_swc1, MEMSUFFIX) (void)
392 {
393     glue(stl, MEMSUFFIX)(T0, WT0);
394     RETURN();
395 }
396 void glue(op_ldc1, MEMSUFFIX) (void)
397 {
398     DT0 = glue(ldq, MEMSUFFIX)(T0);
399     RETURN();
400 }
401 void glue(op_sdc1, MEMSUFFIX) (void)
402 {
403     glue(stq, MEMSUFFIX)(T0, DT0);
404     RETURN();
405 }
406 void glue(op_luxc1, MEMSUFFIX) (void)
407 {
408     DT0 = glue(ldq, MEMSUFFIX)(T0 & ~0x7);
409     RETURN();
410 }
411 void glue(op_suxc1, MEMSUFFIX) (void)
412 {
413     glue(stq, MEMSUFFIX)(T0 & ~0x7, DT0);
414     RETURN();
415 }