Revision 76a66253 target-ppc/op_mem.h
b/target-ppc/op_mem.h | ||
---|---|---|
1 |
/* External helpers */ |
|
2 |
void glue(do_lsw, MEMSUFFIX) (int dst); |
|
3 |
void glue(do_stsw, MEMSUFFIX) (int src); |
|
1 |
/* |
|
2 |
* PowerPC emulation micro-operations for qemu. |
|
3 |
* |
|
4 |
* Copyright (c) 2003-2007 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 |
*/ |
|
4 | 20 |
|
5 | 21 |
static inline uint16_t glue(ld16r, MEMSUFFIX) (target_ulong EA) |
6 | 22 |
{ |
... | ... | |
11 | 27 |
static inline int32_t glue(ld16rs, MEMSUFFIX) (target_ulong EA) |
12 | 28 |
{ |
13 | 29 |
int16_t tmp = glue(lduw, MEMSUFFIX)(EA); |
14 |
return ((tmp & 0xFF00) >> 8) | ((tmp & 0x00FF) << 8); |
|
30 |
return (int16_t)((tmp & 0xFF00) >> 8) | ((tmp & 0x00FF) << 8);
|
|
15 | 31 |
} |
16 | 32 |
|
17 | 33 |
static inline uint32_t glue(ld32r, MEMSUFFIX) (target_ulong EA) |
... | ... | |
80 | 96 |
/*** Integer load and store multiple ***/ |
81 | 97 |
PPC_OP(glue(lmw, MEMSUFFIX)) |
82 | 98 |
{ |
83 |
int dst = PARAM(1); |
|
84 |
|
|
85 |
for (; dst < 32; dst++, T0 += 4) { |
|
86 |
ugpr(dst) = glue(ldl, MEMSUFFIX)(T0); |
|
87 |
} |
|
99 |
glue(do_lmw, MEMSUFFIX)(PARAM1); |
|
88 | 100 |
RETURN(); |
89 | 101 |
} |
90 | 102 |
|
91 |
PPC_OP(glue(stmw, MEMSUFFIX))
|
|
103 |
PPC_OP(glue(lmw_le, MEMSUFFIX))
|
|
92 | 104 |
{ |
93 |
int src = PARAM(1); |
|
94 |
|
|
95 |
for (; src < 32; src++, T0 += 4) { |
|
96 |
glue(stl, MEMSUFFIX)(T0, ugpr(src)); |
|
97 |
} |
|
105 |
glue(do_lmw_le, MEMSUFFIX)(PARAM1); |
|
98 | 106 |
RETURN(); |
99 | 107 |
} |
100 | 108 |
|
101 |
PPC_OP(glue(lmw_le, MEMSUFFIX))
|
|
109 |
PPC_OP(glue(stmw, MEMSUFFIX))
|
|
102 | 110 |
{ |
103 |
int dst = PARAM(1); |
|
104 |
|
|
105 |
for (; dst < 32; dst++, T0 += 4) { |
|
106 |
ugpr(dst) = glue(ld32r, MEMSUFFIX)(T0); |
|
107 |
} |
|
111 |
glue(do_stmw, MEMSUFFIX)(PARAM1); |
|
108 | 112 |
RETURN(); |
109 | 113 |
} |
110 | 114 |
|
111 | 115 |
PPC_OP(glue(stmw_le, MEMSUFFIX)) |
112 | 116 |
{ |
113 |
int src = PARAM(1); |
|
114 |
|
|
115 |
for (; src < 32; src++, T0 += 4) { |
|
116 |
glue(st32r, MEMSUFFIX)(T0, ugpr(src)); |
|
117 |
} |
|
117 |
glue(do_stmw_le, MEMSUFFIX)(PARAM1); |
|
118 | 118 |
RETURN(); |
119 | 119 |
} |
120 | 120 |
|
... | ... | |
125 | 125 |
RETURN(); |
126 | 126 |
} |
127 | 127 |
|
128 |
void glue(do_lsw_le, MEMSUFFIX) (int dst); |
|
129 | 128 |
PPC_OP(glue(lswi_le, MEMSUFFIX)) |
130 | 129 |
{ |
131 | 130 |
glue(do_lsw_le, MEMSUFFIX)(PARAM(1)); |
... | ... | |
139 | 138 |
*/ |
140 | 139 |
PPC_OP(glue(lswx, MEMSUFFIX)) |
141 | 140 |
{ |
142 |
if (T1 > 0) {
|
|
143 |
if ((PARAM(1) < PARAM(2) && (PARAM(1) + T1) > PARAM(2)) ||
|
|
144 |
(PARAM(1) < PARAM(3) && (PARAM(1) + T1) > PARAM(3))) {
|
|
141 |
if (unlikely(T1 > 0)) {
|
|
142 |
if (unlikely((PARAM1 < PARAM2 && (PARAM1 + T1) > PARAM2) ||
|
|
143 |
(PARAM1 < PARAM3 && (PARAM1 + T1) > PARAM3))) {
|
|
145 | 144 |
do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX); |
146 | 145 |
} else { |
147 | 146 |
glue(do_lsw, MEMSUFFIX)(PARAM(1)); |
... | ... | |
152 | 151 |
|
153 | 152 |
PPC_OP(glue(lswx_le, MEMSUFFIX)) |
154 | 153 |
{ |
155 |
if (T1 > 0) {
|
|
156 |
if ((PARAM(1) < PARAM(2) && (PARAM(1) + T1) > PARAM(2)) ||
|
|
157 |
(PARAM(1) < PARAM(3) && (PARAM(1) + T1) > PARAM(3))) {
|
|
154 |
if (unlikely(T1 > 0)) {
|
|
155 |
if (unlikely((PARAM1 < PARAM2 && (PARAM1 + T1) > PARAM2) ||
|
|
156 |
(PARAM1 < PARAM3 && (PARAM1 + T1) > PARAM3))) {
|
|
158 | 157 |
do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX); |
159 | 158 |
} else { |
160 | 159 |
glue(do_lsw_le, MEMSUFFIX)(PARAM(1)); |
... | ... | |
169 | 168 |
RETURN(); |
170 | 169 |
} |
171 | 170 |
|
172 |
void glue(do_stsw_le, MEMSUFFIX) (int src); |
|
173 | 171 |
PPC_OP(glue(stsw_le, MEMSUFFIX)) |
174 | 172 |
{ |
175 | 173 |
glue(do_stsw_le, MEMSUFFIX)(PARAM(1)); |
... | ... | |
180 | 178 |
#define PPC_STF_OP(name, op) \ |
181 | 179 |
PPC_OP(glue(glue(st, name), MEMSUFFIX)) \ |
182 | 180 |
{ \ |
183 |
glue(op, MEMSUFFIX)(T0, FT1); \
|
|
181 |
glue(op, MEMSUFFIX)(T0, FT0); \
|
|
184 | 182 |
RETURN(); \ |
185 | 183 |
} |
186 | 184 |
|
... | ... | |
228 | 226 |
#define PPC_LDF_OP(name, op) \ |
229 | 227 |
PPC_OP(glue(glue(l, name), MEMSUFFIX)) \ |
230 | 228 |
{ \ |
231 |
FT1 = glue(op, MEMSUFFIX)(T0); \
|
|
229 |
FT0 = glue(op, MEMSUFFIX)(T0); \
|
|
232 | 230 |
RETURN(); \ |
233 | 231 |
} |
234 | 232 |
|
... | ... | |
277 | 275 |
/* Load and set reservation */ |
278 | 276 |
PPC_OP(glue(lwarx, MEMSUFFIX)) |
279 | 277 |
{ |
280 |
if (T0 & 0x03) {
|
|
278 |
if (unlikely(T0 & 0x03)) {
|
|
281 | 279 |
do_raise_exception(EXCP_ALIGN); |
282 | 280 |
} else { |
283 |
T1 = glue(ldl, MEMSUFFIX)(T0); |
|
284 |
regs->reserve = T0; |
|
281 |
T1 = glue(ldl, MEMSUFFIX)(T0);
|
|
282 |
regs->reserve = T0;
|
|
285 | 283 |
} |
286 | 284 |
RETURN(); |
287 | 285 |
} |
288 | 286 |
|
289 | 287 |
PPC_OP(glue(lwarx_le, MEMSUFFIX)) |
290 | 288 |
{ |
291 |
if (T0 & 0x03) {
|
|
289 |
if (unlikely(T0 & 0x03)) {
|
|
292 | 290 |
do_raise_exception(EXCP_ALIGN); |
293 | 291 |
} else { |
294 |
T1 = glue(ld32r, MEMSUFFIX)(T0); |
|
295 |
regs->reserve = T0; |
|
292 |
T1 = glue(ld32r, MEMSUFFIX)(T0);
|
|
293 |
regs->reserve = T0;
|
|
296 | 294 |
} |
297 | 295 |
RETURN(); |
298 | 296 |
} |
... | ... | |
300 | 298 |
/* Store with reservation */ |
301 | 299 |
PPC_OP(glue(stwcx, MEMSUFFIX)) |
302 | 300 |
{ |
303 |
if (T0 & 0x03) {
|
|
301 |
if (unlikely(T0 & 0x03)) {
|
|
304 | 302 |
do_raise_exception(EXCP_ALIGN); |
305 | 303 |
} else { |
306 |
if (regs->reserve != T0) {
|
|
304 |
if (unlikely(regs->reserve != T0)) {
|
|
307 | 305 |
env->crf[0] = xer_ov; |
308 | 306 |
} else { |
309 | 307 |
glue(stl, MEMSUFFIX)(T0, T1); |
310 | 308 |
env->crf[0] = xer_ov | 0x02; |
311 | 309 |
} |
312 | 310 |
} |
313 |
regs->reserve = 0;
|
|
311 |
regs->reserve = -1;
|
|
314 | 312 |
RETURN(); |
315 | 313 |
} |
316 | 314 |
|
317 | 315 |
PPC_OP(glue(stwcx_le, MEMSUFFIX)) |
318 | 316 |
{ |
319 |
if (T0 & 0x03) {
|
|
317 |
if (unlikely(T0 & 0x03)) {
|
|
320 | 318 |
do_raise_exception(EXCP_ALIGN); |
321 | 319 |
} else { |
322 |
if (regs->reserve != T0) {
|
|
320 |
if (unlikely(regs->reserve != T0)) {
|
|
323 | 321 |
env->crf[0] = xer_ov; |
324 | 322 |
} else { |
325 | 323 |
glue(st32r, MEMSUFFIX)(T0, T1); |
326 | 324 |
env->crf[0] = xer_ov | 0x02; |
327 | 325 |
} |
328 | 326 |
} |
329 |
regs->reserve = 0;
|
|
327 |
regs->reserve = -1;
|
|
330 | 328 |
RETURN(); |
331 | 329 |
} |
332 | 330 |
|
... | ... | |
340 | 338 |
glue(stl, MEMSUFFIX)(T0 + 0x14, 0); |
341 | 339 |
glue(stl, MEMSUFFIX)(T0 + 0x18, 0); |
342 | 340 |
glue(stl, MEMSUFFIX)(T0 + 0x1C, 0); |
341 |
#if DCACHE_LINE_SIZE == 64 |
|
342 |
/* XXX: cache line size should be 64 for POWER & PowerPC 601 */ |
|
343 |
glue(stl, MEMSUFFIX)(T0 + 0x20UL, 0); |
|
344 |
glue(stl, MEMSUFFIX)(T0 + 0x24UL, 0); |
|
345 |
glue(stl, MEMSUFFIX)(T0 + 0x28UL, 0); |
|
346 |
glue(stl, MEMSUFFIX)(T0 + 0x2CUL, 0); |
|
347 |
glue(stl, MEMSUFFIX)(T0 + 0x30UL, 0); |
|
348 |
glue(stl, MEMSUFFIX)(T0 + 0x34UL, 0); |
|
349 |
glue(stl, MEMSUFFIX)(T0 + 0x38UL, 0); |
|
350 |
glue(stl, MEMSUFFIX)(T0 + 0x3CUL, 0); |
|
351 |
#endif |
|
343 | 352 |
RETURN(); |
344 | 353 |
} |
345 | 354 |
|
... | ... | |
368 | 377 |
RETURN(); |
369 | 378 |
} |
370 | 379 |
|
380 |
/* XXX: those micro-ops need tests ! */ |
|
381 |
/* PowerPC 601 specific instructions (POWER bridge) */ |
|
382 |
void OPPROTO glue(op_POWER_lscbx, MEMSUFFIX) (void) |
|
383 |
{ |
|
384 |
/* When byte count is 0, do nothing */ |
|
385 |
if (likely(T1 > 0)) { |
|
386 |
glue(do_POWER_lscbx, MEMSUFFIX)(PARAM1, PARAM2, PARAM3); |
|
387 |
} |
|
388 |
RETURN(); |
|
389 |
} |
|
390 |
|
|
391 |
/* POWER2 quad load and store */ |
|
392 |
/* XXX: TAGs are not managed */ |
|
393 |
void OPPROTO glue(op_POWER2_lfq, MEMSUFFIX) (void) |
|
394 |
{ |
|
395 |
glue(do_POWER2_lfq, MEMSUFFIX)(); |
|
396 |
RETURN(); |
|
397 |
} |
|
398 |
|
|
399 |
void glue(op_POWER2_lfq_le, MEMSUFFIX) (void) |
|
400 |
{ |
|
401 |
glue(do_POWER2_lfq_le, MEMSUFFIX)(); |
|
402 |
RETURN(); |
|
403 |
} |
|
404 |
|
|
405 |
void OPPROTO glue(op_POWER2_stfq, MEMSUFFIX) (void) |
|
406 |
{ |
|
407 |
glue(do_POWER2_stfq, MEMSUFFIX)(); |
|
408 |
RETURN(); |
|
409 |
} |
|
410 |
|
|
411 |
void OPPROTO glue(op_POWER2_stfq_le, MEMSUFFIX) (void) |
|
412 |
{ |
|
413 |
glue(do_POWER2_stfq_le, MEMSUFFIX)(); |
|
414 |
RETURN(); |
|
415 |
} |
|
416 |
|
|
371 | 417 |
#undef MEMSUFFIX |
Also available in: Unified diff