Switch most MIPS FP load/stores to TCG.
[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 /* "half" load and stores.  We must do the memory access inline,
22    or fault handling won't work.  */
23
24 #ifdef TARGET_WORDS_BIGENDIAN
25 #define GET_LMASK(v) ((v) & 3)
26 #define GET_OFFSET(addr, offset) (addr + (offset))
27 #else
28 #define GET_LMASK(v) (((v) & 3) ^ 3)
29 #define GET_OFFSET(addr, offset) (addr - (offset))
30 #endif
31
32 void glue(op_lwl, MEMSUFFIX) (void)
33 {
34     target_ulong tmp;
35
36     tmp = glue(ldub, MEMSUFFIX)(T0);
37     T1 = (T1 & 0x00FFFFFF) | (tmp << 24);
38
39     if (GET_LMASK(T0) <= 2) {
40         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 1));
41         T1 = (T1 & 0xFF00FFFF) | (tmp << 16);
42     }
43
44     if (GET_LMASK(T0) <= 1) {
45         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 2));
46         T1 = (T1 & 0xFFFF00FF) | (tmp << 8);
47     }
48
49     if (GET_LMASK(T0) == 0) {
50         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 3));
51         T1 = (T1 & 0xFFFFFF00) | tmp;
52     }
53     T1 = (int32_t)T1;
54     FORCE_RET();
55 }
56
57 void glue(op_lwr, MEMSUFFIX) (void)
58 {
59     target_ulong tmp;
60
61     tmp = glue(ldub, MEMSUFFIX)(T0);
62     T1 = (T1 & 0xFFFFFF00) | tmp;
63
64     if (GET_LMASK(T0) >= 1) {
65         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -1));
66         T1 = (T1 & 0xFFFF00FF) | (tmp << 8);
67     }
68
69     if (GET_LMASK(T0) >= 2) {
70         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -2));
71         T1 = (T1 & 0xFF00FFFF) | (tmp << 16);
72     }
73
74     if (GET_LMASK(T0) == 3) {
75         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -3));
76         T1 = (T1 & 0x00FFFFFF) | (tmp << 24);
77     }
78     T1 = (int32_t)T1;
79     FORCE_RET();
80 }
81
82 void glue(op_swl, MEMSUFFIX) (void)
83 {
84     glue(stb, MEMSUFFIX)(T0, (uint8_t)(T1 >> 24));
85
86     if (GET_LMASK(T0) <= 2)
87         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 16));
88
89     if (GET_LMASK(T0) <= 1)
90         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 8));
91
92     if (GET_LMASK(T0) == 0)
93         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 3), (uint8_t)T1);
94
95     FORCE_RET();
96 }
97
98 void glue(op_swr, MEMSUFFIX) (void)
99 {
100     glue(stb, MEMSUFFIX)(T0, (uint8_t)T1);
101
102     if (GET_LMASK(T0) >= 1)
103         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
104
105     if (GET_LMASK(T0) >= 2)
106         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
107
108     if (GET_LMASK(T0) == 3)
109         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
110
111     FORCE_RET();
112 }
113
114 #if defined(TARGET_MIPS64)
115 /* "half" load and stores.  We must do the memory access inline,
116    or fault handling won't work.  */
117
118 #ifdef TARGET_WORDS_BIGENDIAN
119 #define GET_LMASK64(v) ((v) & 7)
120 #else
121 #define GET_LMASK64(v) (((v) & 7) ^ 7)
122 #endif
123
124 void glue(op_ldl, MEMSUFFIX) (void)
125 {
126     uint64_t tmp;
127
128     tmp = glue(ldub, MEMSUFFIX)(T0);
129     T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
130
131     if (GET_LMASK64(T0) <= 6) {
132         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 1));
133         T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
134     }
135
136     if (GET_LMASK64(T0) <= 5) {
137         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 2));
138         T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
139     }
140
141     if (GET_LMASK64(T0) <= 4) {
142         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 3));
143         T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
144     }
145
146     if (GET_LMASK64(T0) <= 3) {
147         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 4));
148         T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
149     }
150
151     if (GET_LMASK64(T0) <= 2) {
152         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 5));
153         T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
154     }
155
156     if (GET_LMASK64(T0) <= 1) {
157         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 6));
158         T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
159     }
160
161     if (GET_LMASK64(T0) == 0) {
162         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 7));
163         T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
164     }
165
166     FORCE_RET();
167 }
168
169 void glue(op_ldr, MEMSUFFIX) (void)
170 {
171     uint64_t tmp;
172
173     tmp = glue(ldub, MEMSUFFIX)(T0);
174     T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
175
176     if (GET_LMASK64(T0) >= 1) {
177         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -1));
178         T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp  << 8);
179     }
180
181     if (GET_LMASK64(T0) >= 2) {
182         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -2));
183         T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
184     }
185
186     if (GET_LMASK64(T0) >= 3) {
187         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -3));
188         T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
189     }
190
191     if (GET_LMASK64(T0) >= 4) {
192         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -4));
193         T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
194     }
195
196     if (GET_LMASK64(T0) >= 5) {
197         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -5));
198         T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
199     }
200
201     if (GET_LMASK64(T0) >= 6) {
202         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -6));
203         T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
204     }
205
206     if (GET_LMASK64(T0) == 7) {
207         tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -7));
208         T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
209     }
210
211     FORCE_RET();
212 }
213
214 void glue(op_sdl, MEMSUFFIX) (void)
215 {
216     glue(stb, MEMSUFFIX)(T0, (uint8_t)(T1 >> 56));
217
218     if (GET_LMASK64(T0) <= 6)
219         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 48));
220
221     if (GET_LMASK64(T0) <= 5)
222         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 40));
223
224     if (GET_LMASK64(T0) <= 4)
225         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 3), (uint8_t)(T1 >> 32));
226
227     if (GET_LMASK64(T0) <= 3)
228         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 4), (uint8_t)(T1 >> 24));
229
230     if (GET_LMASK64(T0) <= 2)
231         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 5), (uint8_t)(T1 >> 16));
232
233     if (GET_LMASK64(T0) <= 1)
234         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 6), (uint8_t)(T1 >> 8));
235
236     if (GET_LMASK64(T0) <= 0)
237         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 7), (uint8_t)T1);
238
239     FORCE_RET();
240 }
241
242 void glue(op_sdr, MEMSUFFIX) (void)
243 {
244     glue(stb, MEMSUFFIX)(T0, (uint8_t)T1);
245
246     if (GET_LMASK64(T0) >= 1)
247         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
248
249     if (GET_LMASK64(T0) >= 2)
250         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
251
252     if (GET_LMASK64(T0) >= 3)
253         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
254
255     if (GET_LMASK64(T0) >= 4)
256         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -4), (uint8_t)(T1 >> 32));
257
258     if (GET_LMASK64(T0) >= 5)
259         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -5), (uint8_t)(T1 >> 40));
260
261     if (GET_LMASK64(T0) >= 6)
262         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -6), (uint8_t)(T1 >> 48));
263
264     if (GET_LMASK64(T0) == 7)
265         glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -7), (uint8_t)(T1 >> 56));
266
267     FORCE_RET();
268 }
269 #endif /* TARGET_MIPS64 */
270
271 void glue(op_luxc1, MEMSUFFIX) (void)
272 {
273     DT0 = glue(ldq, MEMSUFFIX)(T0 & ~0x7);
274     FORCE_RET();
275 }
276 void glue(op_suxc1, MEMSUFFIX) (void)
277 {
278     glue(stq, MEMSUFFIX)(T0 & ~0x7, DT0);
279     FORCE_RET();
280 }