Statistics
| Branch: | Revision:

root / target-mips / op_mem.c @ 4e9f8537

History | View | Annotate | Download (9.7 kB)

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 = (int32_t)((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
    RETURN();
109
}
110

    
111
void glue(op_lwr, MEMSUFFIX) (void)
112
{
113
    target_ulong tmp;
114

    
115
    tmp = glue(ldub, MEMSUFFIX)(T0);
116
    T1 = (T1 & 0xFFFFFF00) | tmp;
117

    
118
    if (GET_LMASK(T0) >= 1) {
119
        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -1));
120
        T1 = (T1 & 0xFFFF00FF) | (tmp << 8);
121
    }
122

    
123
    if (GET_LMASK(T0) >= 2) {
124
        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -2));
125
        T1 = (T1 & 0xFF00FFFF) | (tmp << 16);
126
    }
127

    
128
    if (GET_LMASK(T0) == 3) {
129
        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -3));
130
        T1 = (T1 & 0x00FFFFFF) | (tmp << 24);
131
    }
132
    RETURN();
133
}
134

    
135
void glue(op_swl, MEMSUFFIX) (void)
136
{
137
    glue(stb, MEMSUFFIX)(T0, (uint8_t)(T1 >> 24));
138

    
139
    if (GET_LMASK(T0) <= 2)
140
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 16));
141

    
142
    if (GET_LMASK(T0) <= 1)
143
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 8));
144

    
145
    if (GET_LMASK(T0) == 0)
146
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 3), (uint8_t)T1);
147

    
148
    RETURN();
149
}
150

    
151
void glue(op_swr, MEMSUFFIX) (void)
152
{
153
    glue(stb, MEMSUFFIX)(T0, (uint8_t)T1);
154

    
155
    if (GET_LMASK(T0) >= 1)
156
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
157

    
158
    if (GET_LMASK(T0) >= 2)
159
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
160

    
161
    if (GET_LMASK(T0) == 3)
162
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
163

    
164
    RETURN();
165
}
166

    
167
void glue(op_ll, MEMSUFFIX) (void)
168
{
169
    T1 = T0;
170
    T0 = glue(ldl, MEMSUFFIX)(T0);
171
    env->CP0_LLAddr = T1;
172
    RETURN();
173
}
174

    
175
void glue(op_sc, MEMSUFFIX) (void)
176
{
177
    CALL_FROM_TB0(dump_sc);
178
    if (T0 & 0x3) {
179
        env->CP0_BadVAddr = T0;
180
        CALL_FROM_TB1(do_raise_exception, EXCP_AdES);
181
    }
182
    if (T0 == env->CP0_LLAddr) {
183
        glue(stl, MEMSUFFIX)(T0, T1);
184
        T0 = 1;
185
    } else {
186
        T0 = 0;
187
    }
188
    RETURN();
189
}
190

    
191
#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
192
void glue(op_ld, MEMSUFFIX) (void)
193
{
194
    T0 = glue(ldq, MEMSUFFIX)(T0);
195
    RETURN();
196
}
197

    
198
void glue(op_sd, MEMSUFFIX) (void)
199
{
200
    glue(stq, MEMSUFFIX)(T0, T1);
201
    RETURN();
202
}
203

    
204
/* "half" load and stores.  We must do the memory access inline,
205
   or fault handling won't work.  */
206

    
207
#ifdef TARGET_WORDS_BIGENDIAN
208
#define GET_LMASK64(v) ((v) & 7)
209
#else
210
#define GET_LMASK64(v) (((v) & 7) ^ 7)
211
#endif
212

    
213
void glue(op_ldl, MEMSUFFIX) (void)
214
{
215
    uint64_t tmp;
216

    
217
    tmp = glue(ldub, MEMSUFFIX)(T0);
218
    T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
219

    
220
    if (GET_LMASK64(T0) <= 6) {
221
        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 1));
222
        T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
223
    }
224

    
225
    if (GET_LMASK64(T0) <= 5) {
226
        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 2));
227
        T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
228
    }
229

    
230
    if (GET_LMASK64(T0) <= 4) {
231
        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 3));
232
        T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
233
    }
234

    
235
    if (GET_LMASK64(T0) <= 3) {
236
        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 4));
237
        T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
238
    }
239

    
240
    if (GET_LMASK64(T0) <= 2) {
241
        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 5));
242
        T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
243
    }
244

    
245
    if (GET_LMASK64(T0) <= 1) {
246
        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 6));
247
        T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
248
    }
249

    
250
    if (GET_LMASK64(T0) == 0) {
251
        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 7));
252
        T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
253
    }
254

    
255
    RETURN();
256
}
257

    
258
void glue(op_ldr, MEMSUFFIX) (void)
259
{
260
    uint64_t tmp;
261

    
262
    tmp = glue(ldub, MEMSUFFIX)(T0);
263
    T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
264

    
265
    if (GET_LMASK64(T0) >= 1) {
266
        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -1));
267
        T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp  << 8);
268
    }
269

    
270
    if (GET_LMASK64(T0) >= 2) {
271
        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -2));
272
        T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
273
    }
274

    
275
    if (GET_LMASK64(T0) >= 3) {
276
        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -3));
277
        T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
278
    }
279

    
280
    if (GET_LMASK64(T0) >= 4) {
281
        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -4));
282
        T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
283
    }
284

    
285
    if (GET_LMASK64(T0) >= 5) {
286
        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -5));
287
        T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
288
    }
289

    
290
    if (GET_LMASK64(T0) >= 6) {
291
        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -6));
292
        T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
293
    }
294

    
295
    if (GET_LMASK64(T0) == 7) {
296
        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -7));
297
        T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
298
    }
299

    
300
    RETURN();
301
}
302

    
303
void glue(op_sdl, MEMSUFFIX) (void)
304
{
305
    glue(stb, MEMSUFFIX)(T0, (uint8_t)(T1 >> 56));
306

    
307
    if (GET_LMASK64(T0) <= 6)
308
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 48));
309

    
310
    if (GET_LMASK64(T0) <= 5)
311
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 40));
312

    
313
    if (GET_LMASK64(T0) <= 4)
314
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 3), (uint8_t)(T1 >> 32));
315

    
316
    if (GET_LMASK64(T0) <= 3)
317
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 4), (uint8_t)(T1 >> 24));
318

    
319
    if (GET_LMASK64(T0) <= 2)
320
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 5), (uint8_t)(T1 >> 16));
321

    
322
    if (GET_LMASK64(T0) <= 1)
323
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 6), (uint8_t)(T1 >> 8));
324

    
325
    if (GET_LMASK64(T0) <= 0)
326
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 7), (uint8_t)T1);
327

    
328
    RETURN();
329
}
330

    
331
void glue(op_sdr, MEMSUFFIX) (void)
332
{
333
    glue(stb, MEMSUFFIX)(T0, (uint8_t)T1);
334

    
335
    if (GET_LMASK64(T0) >= 1)
336
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
337

    
338
    if (GET_LMASK64(T0) >= 2)
339
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
340

    
341
    if (GET_LMASK64(T0) >= 3)
342
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
343

    
344
    if (GET_LMASK64(T0) >= 4)
345
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -4), (uint8_t)(T1 >> 32));
346

    
347
    if (GET_LMASK64(T0) >= 5)
348
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -5), (uint8_t)(T1 >> 40));
349

    
350
    if (GET_LMASK64(T0) >= 6)
351
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -6), (uint8_t)(T1 >> 48));
352

    
353
    if (GET_LMASK64(T0) == 7)
354
        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -7), (uint8_t)(T1 >> 56));
355

    
356
    RETURN();
357
}
358

    
359
void glue(op_lld, MEMSUFFIX) (void)
360
{
361
    T1 = T0;
362
    T0 = glue(ldq, MEMSUFFIX)(T0);
363
    env->CP0_LLAddr = T1;
364
    RETURN();
365
}
366

    
367
void glue(op_scd, MEMSUFFIX) (void)
368
{
369
    CALL_FROM_TB0(dump_sc);
370
    if (T0 & 0x7) {
371
        env->CP0_BadVAddr = T0;
372
        CALL_FROM_TB1(do_raise_exception, EXCP_AdES);
373
    }
374
    if (T0 == env->CP0_LLAddr) {
375
        glue(stq, MEMSUFFIX)(T0, T1);
376
        T0 = 1;
377
    } else {
378
        T0 = 0;
379
    }
380
    RETURN();
381
}
382
#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
383

    
384
void glue(op_lwc1, MEMSUFFIX) (void)
385
{
386
    WT0 = glue(ldl, MEMSUFFIX)(T0);
387
    RETURN();
388
}
389
void glue(op_swc1, MEMSUFFIX) (void)
390
{
391
    glue(stl, MEMSUFFIX)(T0, WT0);
392
    RETURN();
393
}
394
void glue(op_ldc1, MEMSUFFIX) (void)
395
{
396
    DT0 = glue(ldq, MEMSUFFIX)(T0);
397
    RETURN();
398
}
399
void glue(op_sdc1, MEMSUFFIX) (void)
400
{
401
    glue(stq, MEMSUFFIX)(T0, DT0);
402
    RETURN();
403
}
404
void glue(op_luxc1, MEMSUFFIX) (void)
405
{
406
    DT0 = glue(ldq, MEMSUFFIX)(T0 & ~0x7);
407
    RETURN();
408
}
409
void glue(op_suxc1, MEMSUFFIX) (void)
410
{
411
    glue(stq, MEMSUFFIX)(T0 & ~0x7, DT0);
412
    RETURN();
413
}