Statistics
| Branch: | Revision:

root / target-mips / op_mem.c @ 9f77c1cd

History | View | Annotate | Download (9.8 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 = (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
}