Revision 9a64fbe4 target-ppc/op.c
b/target-ppc/op.c | ||
---|---|---|
21 | 21 |
#include "config.h" |
22 | 22 |
#include "exec.h" |
23 | 23 |
|
24 |
//#define DEBUG_OP |
|
25 |
|
|
24 | 26 |
#define regs (env) |
25 | 27 |
#define Ts0 (int32_t)T0 |
26 | 28 |
#define Ts1 (int32_t)T1 |
... | ... | |
34 | 36 |
#define FTS1 ((float)env->ft1) |
35 | 37 |
#define FTS2 ((float)env->ft2) |
36 | 38 |
|
37 |
#define PPC_OP(name) void op_##name(void)
|
|
39 |
#define PPC_OP(name) void glue(op_, name)(void)
|
|
38 | 40 |
|
39 | 41 |
#define REG 0 |
40 | 42 |
#include "op_template.h" |
... | ... | |
145 | 147 |
} else { |
146 | 148 |
tmp = 0x02; |
147 | 149 |
} |
148 |
set_CRn(0, tmp);
|
|
150 |
env->crf[0] = tmp;
|
|
149 | 151 |
RETURN(); |
150 | 152 |
} |
151 | 153 |
|
... | ... | |
161 | 163 |
tmp = 0x02; |
162 | 164 |
} |
163 | 165 |
tmp |= xer_ov; |
164 |
set_CRn(0, tmp);
|
|
166 |
env->crf[0] = tmp;
|
|
165 | 167 |
RETURN(); |
166 | 168 |
} |
167 | 169 |
|
168 | 170 |
/* reset_Rc0 */ |
169 | 171 |
PPC_OP(reset_Rc0) |
170 | 172 |
{ |
171 |
set_CRn(0, 0x02 | xer_ov);
|
|
173 |
env->crf[0] = 0x02 | xer_ov;
|
|
172 | 174 |
RETURN(); |
173 | 175 |
} |
174 | 176 |
|
175 | 177 |
/* set_Rc0_1 */ |
176 | 178 |
PPC_OP(set_Rc0_1) |
177 | 179 |
{ |
178 |
set_CRn(0, 0x04 | xer_ov);
|
|
180 |
env->crf[0] = 0x04 | xer_ov;
|
|
179 | 181 |
RETURN(); |
180 | 182 |
} |
181 | 183 |
|
... | ... | |
186 | 188 |
RETURN(); |
187 | 189 |
} |
188 | 190 |
|
191 |
/* Constants load */ |
|
189 | 192 |
PPC_OP(set_T0) |
190 | 193 |
{ |
191 | 194 |
T0 = PARAM(1); |
... | ... | |
204 | 207 |
RETURN(); |
205 | 208 |
} |
206 | 209 |
|
207 |
/* Update time base */
|
|
208 |
PPC_OP(update_tb)
|
|
210 |
/* Generate exceptions */
|
|
211 |
PPC_OP(queue_exception_err)
|
|
209 | 212 |
{ |
210 |
T0 = regs->spr[SPR_ENCODE(268)]; |
|
211 |
T1 = T0; |
|
212 |
T0 += PARAM(1); |
|
213 |
if (T0 < T1) { |
|
214 |
T1 = regs->spr[SPR_ENCODE(269)] + 1; |
|
215 |
regs->spr[SPR_ENCODE(269)] = T1; |
|
213 |
do_queue_exception_err(PARAM(1), PARAM(2)); |
|
214 |
} |
|
215 |
|
|
216 |
PPC_OP(queue_exception) |
|
217 |
{ |
|
218 |
do_queue_exception(PARAM(1)); |
|
219 |
} |
|
220 |
|
|
221 |
PPC_OP(process_exceptions) |
|
222 |
{ |
|
223 |
if (env->exceptions != 0) { |
|
224 |
env->nip = PARAM(1); |
|
225 |
do_check_exception_state(); |
|
216 | 226 |
} |
217 |
regs->spr[SPR_ENCODE(268)] = T0; |
|
227 |
} |
|
228 |
|
|
229 |
/* Segment registers load and store with immediate index */ |
|
230 |
PPC_OP(load_srin) |
|
231 |
{ |
|
232 |
T0 = regs->sr[T1 >> 28]; |
|
233 |
RETURN(); |
|
234 |
} |
|
235 |
|
|
236 |
PPC_OP(store_srin) |
|
237 |
{ |
|
238 |
#if defined (DEBUG_OP) |
|
239 |
dump_store_sr(T1 >> 28); |
|
240 |
#endif |
|
241 |
regs->sr[T1 >> 28] = T0; |
|
242 |
RETURN(); |
|
243 |
} |
|
244 |
|
|
245 |
PPC_OP(load_sdr1) |
|
246 |
{ |
|
247 |
T0 = regs->sdr1; |
|
218 | 248 |
RETURN(); |
219 | 249 |
} |
220 | 250 |
|
221 |
PPC_OP(raise_exception)
|
|
251 |
PPC_OP(store_sdr1)
|
|
222 | 252 |
{ |
223 |
raise_exception(PARAM(1));
|
|
253 |
regs->sdr1 = T0;
|
|
224 | 254 |
RETURN(); |
225 | 255 |
} |
226 | 256 |
|
... | ... | |
229 | 259 |
EXIT_TB(); |
230 | 260 |
} |
231 | 261 |
|
262 |
/* Load/store special registers */ |
|
232 | 263 |
PPC_OP(load_cr) |
233 | 264 |
{ |
234 |
T0 = do_load_cr();
|
|
265 |
do_load_cr(); |
|
235 | 266 |
RETURN(); |
236 | 267 |
} |
237 | 268 |
|
238 | 269 |
PPC_OP(store_cr) |
239 | 270 |
{ |
240 |
do_store_cr(PARAM(1), T0);
|
|
271 |
do_store_cr(PARAM(1)); |
|
241 | 272 |
RETURN(); |
242 | 273 |
} |
243 | 274 |
|
... | ... | |
257 | 288 |
|
258 | 289 |
PPC_OP(load_xer_bc) |
259 | 290 |
{ |
260 |
T0 = xer_bc;
|
|
291 |
T1 = xer_bc;
|
|
261 | 292 |
RETURN(); |
262 | 293 |
} |
263 | 294 |
|
264 | 295 |
PPC_OP(load_xer) |
265 | 296 |
{ |
266 |
T0 = do_load_xer();
|
|
297 |
do_load_xer(); |
|
267 | 298 |
RETURN(); |
268 | 299 |
} |
269 | 300 |
|
270 | 301 |
PPC_OP(store_xer) |
271 | 302 |
{ |
272 |
do_store_xer(T0);
|
|
303 |
do_store_xer(); |
|
273 | 304 |
RETURN(); |
274 | 305 |
} |
275 | 306 |
|
276 | 307 |
PPC_OP(load_msr) |
277 | 308 |
{ |
278 |
T0 = do_load_msr();
|
|
309 |
do_load_msr(); |
|
279 | 310 |
RETURN(); |
280 | 311 |
} |
281 | 312 |
|
282 | 313 |
PPC_OP(store_msr) |
283 | 314 |
{ |
284 |
do_store_msr(T0); |
|
315 |
do_store_msr(); |
|
316 |
RETURN(); |
|
317 |
} |
|
318 |
|
|
319 |
/* SPR */ |
|
320 |
PPC_OP(load_spr) |
|
321 |
{ |
|
322 |
T0 = regs->spr[PARAM(1)]; |
|
323 |
RETURN(); |
|
324 |
} |
|
325 |
|
|
326 |
PPC_OP(store_spr) |
|
327 |
{ |
|
328 |
regs->spr[PARAM(1)] = T0; |
|
285 | 329 |
RETURN(); |
286 | 330 |
} |
287 | 331 |
|
288 | 332 |
PPC_OP(load_lr) |
289 | 333 |
{ |
290 |
regs->LR = PARAM(1); |
|
334 |
T0 = regs->lr; |
|
335 |
RETURN(); |
|
336 |
} |
|
337 |
|
|
338 |
PPC_OP(store_lr) |
|
339 |
{ |
|
340 |
regs->lr = T0; |
|
341 |
RETURN(); |
|
342 |
} |
|
343 |
|
|
344 |
PPC_OP(load_ctr) |
|
345 |
{ |
|
346 |
T0 = regs->ctr; |
|
347 |
RETURN(); |
|
348 |
} |
|
349 |
|
|
350 |
PPC_OP(store_ctr) |
|
351 |
{ |
|
352 |
regs->ctr = T0; |
|
353 |
RETURN(); |
|
354 |
} |
|
355 |
|
|
356 |
/* Update time base */ |
|
357 |
PPC_OP(update_tb) |
|
358 |
{ |
|
359 |
T0 = regs->tb[0]; |
|
360 |
T1 = T0; |
|
361 |
T0 += PARAM(1); |
|
362 |
#if defined (DEBUG_OP) |
|
363 |
dump_update_tb(PARAM(1)); |
|
364 |
#endif |
|
365 |
if (T0 < T1) { |
|
366 |
T1 = regs->tb[1] + 1; |
|
367 |
regs->tb[1] = T1; |
|
368 |
} |
|
369 |
regs->tb[0] = T0; |
|
370 |
RETURN(); |
|
371 |
} |
|
372 |
|
|
373 |
PPC_OP(load_tb) |
|
374 |
{ |
|
375 |
T0 = regs->tb[PARAM(1)]; |
|
376 |
RETURN(); |
|
377 |
} |
|
378 |
|
|
379 |
PPC_OP(store_tb) |
|
380 |
{ |
|
381 |
regs->tb[PARAM(1)] = T0; |
|
382 |
#if defined (DEBUG_OP) |
|
383 |
dump_store_tb(PARAM(1)); |
|
384 |
#endif |
|
291 | 385 |
RETURN(); |
292 | 386 |
} |
293 | 387 |
|
388 |
/* Update decrementer */ |
|
389 |
PPC_OP(update_decr) |
|
390 |
{ |
|
391 |
T0 = regs->decr; |
|
392 |
T1 = T0; |
|
393 |
T0 -= PARAM(1); |
|
394 |
regs->decr = T0; |
|
395 |
if (PARAM(1) > T1) { |
|
396 |
do_queue_exception(EXCP_DECR); |
|
397 |
} |
|
398 |
RETURN(); |
|
399 |
} |
|
400 |
|
|
401 |
PPC_OP(store_decr) |
|
402 |
{ |
|
403 |
T1 = regs->decr; |
|
404 |
regs->decr = T0; |
|
405 |
if (Ts0 < 0 && Ts1 > 0) { |
|
406 |
do_queue_exception(EXCP_DECR); |
|
407 |
} |
|
408 |
RETURN(); |
|
409 |
} |
|
410 |
|
|
411 |
PPC_OP(load_ibat) |
|
412 |
{ |
|
413 |
T0 = regs->IBAT[PARAM(1)][PARAM(2)]; |
|
414 |
} |
|
415 |
|
|
416 |
PPC_OP(store_ibat) |
|
417 |
{ |
|
418 |
#if defined (DEBUG_OP) |
|
419 |
dump_store_ibat(PARAM(1), PARAM(2)); |
|
420 |
#endif |
|
421 |
regs->IBAT[PARAM(1)][PARAM(2)] = T0; |
|
422 |
} |
|
423 |
|
|
424 |
PPC_OP(load_dbat) |
|
425 |
{ |
|
426 |
T0 = regs->DBAT[PARAM(1)][PARAM(2)]; |
|
427 |
} |
|
428 |
|
|
429 |
PPC_OP(store_dbat) |
|
430 |
{ |
|
431 |
#if defined (DEBUG_OP) |
|
432 |
dump_store_dbat(PARAM(1), PARAM(2)); |
|
433 |
#endif |
|
434 |
regs->DBAT[PARAM(1)][PARAM(2)] = T0; |
|
435 |
} |
|
436 |
|
|
294 | 437 |
/* FPSCR */ |
295 | 438 |
PPC_OP(load_fpscr) |
296 | 439 |
{ |
... | ... | |
313 | 456 |
/* Set reservation */ |
314 | 457 |
PPC_OP(set_reservation) |
315 | 458 |
{ |
316 |
regs->reserve = T1 & ~0x03; |
|
317 |
RETURN(); |
|
318 |
} |
|
319 |
|
|
320 |
/* Reset reservation */ |
|
321 |
PPC_OP(reset_reservation) |
|
322 |
{ |
|
323 |
regs->reserve = 0; |
|
459 |
regs->reserve = T0 & ~0x03; |
|
324 | 460 |
RETURN(); |
325 | 461 |
} |
326 | 462 |
|
... | ... | |
344 | 480 |
} |
345 | 481 |
|
346 | 482 |
/* Branch */ |
483 |
#if 0 |
|
484 |
#define EIP regs->nip |
|
485 |
#define TB_DO_JUMP(name, tb, n, target) JUMP_TB(name, tb, n, target) |
|
486 |
#else |
|
487 |
#define TB_DO_JUMP(name, tb, n, target) regs->nip = target; |
|
488 |
#endif |
|
489 |
|
|
347 | 490 |
#define __PPC_OP_B(name, target) \ |
348 | 491 |
PPC_OP(name) \ |
349 | 492 |
{ \ |
350 |
regs->nip = (target); \
|
|
493 |
TB_DO_JUMP(glue(op_, name), T1, 0, (target)); \
|
|
351 | 494 |
RETURN(); \ |
352 | 495 |
} |
353 | 496 |
|
354 |
#define __PPC_OP_BL(name, target) \
|
|
497 |
#define __PPC_OP_BL(name, target, link) \
|
|
355 | 498 |
PPC_OP(name) \ |
356 | 499 |
{ \ |
357 |
regs->LR = PARAM(1); \
|
|
358 |
regs->nip = (target); \
|
|
500 |
regs->lr = (link); \
|
|
501 |
TB_DO_JUMP(glue(op_, name), T1, 0, (target)); \
|
|
359 | 502 |
RETURN(); \ |
360 | 503 |
} |
361 | 504 |
|
362 |
#define PPC_OP_B(name, target) \
|
|
505 |
#define PPC_OP_B(name, target, link) \
|
|
363 | 506 |
__PPC_OP_B(name, target); \ |
364 |
__PPC_OP_BL(name##l, target)
|
|
507 |
__PPC_OP_BL(glue(name, l), target, link)
|
|
365 | 508 |
|
366 | 509 |
#define __PPC_OP_BC(name, cond, target) \ |
367 | 510 |
PPC_OP(name) \ |
368 | 511 |
{ \ |
369 | 512 |
if (cond) { \ |
370 |
T0 = (target); \
|
|
513 |
TB_DO_JUMP(glue(op_, name), T1, 1, (target)); \
|
|
371 | 514 |
} else { \ |
372 |
T0 = PARAM(1); \
|
|
515 |
TB_DO_JUMP(glue(op_, name), T1, 0, PARAM(1)); \
|
|
373 | 516 |
} \ |
374 |
regs->nip = T0; \ |
|
375 | 517 |
RETURN(); \ |
376 | 518 |
} |
377 | 519 |
|
378 | 520 |
#define __PPC_OP_BCL(name, cond, target) \ |
379 | 521 |
PPC_OP(name) \ |
380 | 522 |
{ \ |
523 |
regs->lr = PARAM(1); \ |
|
381 | 524 |
if (cond) { \ |
382 |
T0 = (target); \ |
|
383 |
regs->LR = PARAM(1); \ |
|
525 |
TB_DO_JUMP(glue(op_, name), T1, 1, (target)); \ |
|
384 | 526 |
} else { \ |
385 |
T0 = PARAM(1); \ |
|
527 |
TB_DO_JUMP(glue(op_, name), T1, 0, PARAM(1)); \ |
|
528 |
} \ |
|
529 |
RETURN(); \ |
|
530 |
} |
|
531 |
|
|
532 |
#define __PPC_OP_BCLRL(name, cond, target) \ |
|
533 |
PPC_OP(name) \ |
|
534 |
{ \ |
|
535 |
T2 = (target); \ |
|
536 |
regs->lr = PARAM(1); \ |
|
537 |
if (cond) { \ |
|
538 |
TB_DO_JUMP(glue(op_, name), T1, 1, T2); \ |
|
539 |
} else { \ |
|
540 |
TB_DO_JUMP(glue(op_, name), T1, 0, PARAM(1)); \ |
|
386 | 541 |
} \ |
387 |
regs->nip = T0; \ |
|
388 | 542 |
RETURN(); \ |
389 | 543 |
} |
390 | 544 |
|
... | ... | |
396 | 550 |
#define PPC_OP_BC(name, cond) \ |
397 | 551 |
_PPC_OP_BC(b_##name, bl_##name, cond, PARAM(2)) |
398 | 552 |
|
399 |
PPC_OP_B(b, PARAM(1)); |
|
400 |
PPC_OP_BC(ctr, (regs->CTR != 0));
|
|
401 |
PPC_OP_BC(ctr_true, (regs->CTR != 0 && (T0 & PARAM(3)) != 0));
|
|
402 |
PPC_OP_BC(ctr_false, (regs->CTR != 0 && (T0 & PARAM(3)) == 0));
|
|
403 |
PPC_OP_BC(ctrz, (regs->CTR == 0));
|
|
404 |
PPC_OP_BC(ctrz_true, (regs->CTR == 0 && (T0 & PARAM(3)) != 0));
|
|
405 |
PPC_OP_BC(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(3)) == 0));
|
|
553 |
PPC_OP_B(b, PARAM(1), PARAM(2));
|
|
554 |
PPC_OP_BC(ctr, (regs->ctr != 0));
|
|
555 |
PPC_OP_BC(ctr_true, (regs->ctr != 0 && (T0 & PARAM(3)) != 0));
|
|
556 |
PPC_OP_BC(ctr_false, (regs->ctr != 0 && (T0 & PARAM(3)) == 0));
|
|
557 |
PPC_OP_BC(ctrz, (regs->ctr == 0));
|
|
558 |
PPC_OP_BC(ctrz_true, (regs->ctr == 0 && (T0 & PARAM(3)) != 0));
|
|
559 |
PPC_OP_BC(ctrz_false, (regs->ctr == 0 && (T0 & PARAM(3)) == 0));
|
|
406 | 560 |
PPC_OP_BC(true, ((T0 & PARAM(3)) != 0)); |
407 | 561 |
PPC_OP_BC(false, ((T0 & PARAM(3)) == 0)); |
408 | 562 |
|
409 | 563 |
/* Branch to CTR */ |
410 | 564 |
#define PPC_OP_BCCTR(name, cond) \ |
411 |
_PPC_OP_BC(bctr_##name, bctrl_##name, cond, regs->CTR & ~0x03)
|
|
412 |
|
|
413 |
PPC_OP_B(bctr, regs->CTR & ~0x03);
|
|
414 |
PPC_OP_BCCTR(ctr, (regs->CTR != 0));
|
|
415 |
PPC_OP_BCCTR(ctr_true, (regs->CTR != 0 && (T0 & PARAM(2)) != 0));
|
|
416 |
PPC_OP_BCCTR(ctr_false, (regs->CTR != 0 && (T0 & PARAM(2)) == 0));
|
|
417 |
PPC_OP_BCCTR(ctrz, (regs->CTR == 0));
|
|
418 |
PPC_OP_BCCTR(ctrz_true, (regs->CTR == 0 && (T0 & PARAM(2)) != 0));
|
|
419 |
PPC_OP_BCCTR(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(2)) == 0));
|
|
565 |
_PPC_OP_BC(bctr_##name, bctrl_##name, cond, regs->ctr & ~0x03)
|
|
566 |
|
|
567 |
PPC_OP_B(bctr, regs->ctr & ~0x03, PARAM(1));
|
|
568 |
PPC_OP_BCCTR(ctr, (regs->ctr != 0));
|
|
569 |
PPC_OP_BCCTR(ctr_true, (regs->ctr != 0 && (T0 & PARAM(2)) != 0));
|
|
570 |
PPC_OP_BCCTR(ctr_false, (regs->ctr != 0 && (T0 & PARAM(2)) == 0));
|
|
571 |
PPC_OP_BCCTR(ctrz, (regs->ctr == 0));
|
|
572 |
PPC_OP_BCCTR(ctrz_true, (regs->ctr == 0 && (T0 & PARAM(2)) != 0));
|
|
573 |
PPC_OP_BCCTR(ctrz_false, (regs->ctr == 0 && (T0 & PARAM(2)) == 0));
|
|
420 | 574 |
PPC_OP_BCCTR(true, ((T0 & PARAM(2)) != 0)); |
421 | 575 |
PPC_OP_BCCTR(false, ((T0 & PARAM(2)) == 0)); |
422 | 576 |
|
423 | 577 |
/* Branch to LR */ |
424 | 578 |
#define PPC_OP_BCLR(name, cond) \ |
425 |
_PPC_OP_BC(blr_##name, blrl_##name, cond, regs->LR & ~0x03) |
|
426 |
|
|
427 |
PPC_OP_B(blr, regs->LR & ~0x03); |
|
428 |
PPC_OP_BCLR(ctr, (regs->CTR != 0)); |
|
429 |
PPC_OP_BCLR(ctr_true, (regs->CTR != 0 && (T0 & PARAM(2)) != 0)); |
|
430 |
PPC_OP_BCLR(ctr_false, (regs->CTR != 0 && (T0 & PARAM(2)) == 0)); |
|
431 |
PPC_OP_BCLR(ctrz, (regs->CTR == 0)); |
|
432 |
PPC_OP_BCLR(ctrz_true, (regs->CTR == 0 && (T0 & PARAM(2)) != 0)); |
|
433 |
PPC_OP_BCLR(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(2)) == 0)); |
|
579 |
__PPC_OP_BC(blr_##name, cond, regs->lr & ~0x03); \ |
|
580 |
__PPC_OP_BCLRL(blrl_##name, cond, regs->lr & ~0x03) |
|
581 |
|
|
582 |
__PPC_OP_B(blr, regs->lr & ~0x03); |
|
583 |
PPC_OP(blrl) |
|
584 |
{ |
|
585 |
T0 = regs->lr & ~0x03; |
|
586 |
regs->lr = PARAM(1); |
|
587 |
TB_DO_JUMP(op_blrl, T1, 0, T0); |
|
588 |
RETURN(); |
|
589 |
} |
|
590 |
PPC_OP_BCLR(ctr, (regs->ctr != 0)); |
|
591 |
PPC_OP_BCLR(ctr_true, (regs->ctr != 0 && (T0 & PARAM(2)) != 0)); |
|
592 |
PPC_OP_BCLR(ctr_false, (regs->ctr != 0 && (T0 & PARAM(2)) == 0)); |
|
593 |
PPC_OP_BCLR(ctrz, (regs->ctr == 0)); |
|
594 |
PPC_OP_BCLR(ctrz_true, (regs->ctr == 0 && (T0 & PARAM(2)) != 0)); |
|
595 |
PPC_OP_BCLR(ctrz_false, (regs->ctr == 0 && (T0 & PARAM(2)) == 0)); |
|
434 | 596 |
PPC_OP_BCLR(true, ((T0 & PARAM(2)) != 0)); |
435 | 597 |
PPC_OP_BCLR(false, ((T0 & PARAM(2)) == 0)); |
436 | 598 |
|
437 | 599 |
/* CTR maintenance */ |
438 | 600 |
PPC_OP(dec_ctr) |
439 | 601 |
{ |
440 |
regs->CTR--;
|
|
602 |
regs->ctr--;
|
|
441 | 603 |
RETURN(); |
442 | 604 |
} |
443 | 605 |
|
... | ... | |
1077 | 1239 |
/* shift right algebraic word */ |
1078 | 1240 |
PPC_OP(sraw) |
1079 | 1241 |
{ |
1080 |
Ts0 = do_sraw(Ts0, T1);
|
|
1242 |
do_sraw();
|
|
1081 | 1243 |
RETURN(); |
1082 | 1244 |
} |
1083 | 1245 |
|
... | ... | |
1106 | 1268 |
} |
1107 | 1269 |
|
1108 | 1270 |
/*** Floating-Point arithmetic ***/ |
1109 |
|
|
1110 |
/*** Floating-Point multiply-and-add ***/ |
|
1111 |
|
|
1112 |
/*** Floating-Point round & convert ***/ |
|
1113 |
|
|
1114 |
/*** Floating-Point compare ***/ |
|
1115 |
|
|
1116 |
/*** Floating-Point status & ctrl register ***/ |
|
1117 |
|
|
1118 |
/*** Integer load ***/ |
|
1119 |
#define ld16x(x) s_ext16(ld16(x)) |
|
1120 |
#define PPC_ILD_OPX(name, op) \ |
|
1121 |
PPC_OP(l##name##x_z) \ |
|
1122 |
{ \ |
|
1123 |
T1 = op(T0); \ |
|
1124 |
RETURN(); \ |
|
1125 |
} \ |
|
1126 |
PPC_OP(l##name##x) \ |
|
1127 |
{ \ |
|
1128 |
T0 += T1; \ |
|
1129 |
T1 = op(T0); \ |
|
1130 |
RETURN(); \ |
|
1131 |
} |
|
1132 |
|
|
1133 |
#define PPC_ILD_OP(name, op) \ |
|
1134 |
PPC_OP(l##name##_z) \ |
|
1135 |
{ \ |
|
1136 |
T1 = op(SPARAM(1)); \ |
|
1137 |
RETURN(); \ |
|
1138 |
} \ |
|
1139 |
PPC_OP(l##name) \ |
|
1140 |
{ \ |
|
1141 |
T0 += SPARAM(1); \ |
|
1142 |
T1 = op(T0); \ |
|
1143 |
RETURN(); \ |
|
1144 |
} \ |
|
1145 |
PPC_ILD_OPX(name, op) |
|
1146 |
|
|
1147 |
PPC_ILD_OP(bz, ld8); |
|
1148 |
PPC_ILD_OP(ha, ld16x); |
|
1149 |
PPC_ILD_OP(hz, ld16); |
|
1150 |
PPC_ILD_OP(wz, ld32); |
|
1151 |
|
|
1152 |
/*** Integer store ***/ |
|
1153 |
#define PPC_IST_OPX(name, op) \ |
|
1154 |
PPC_OP(st##name##x_z) \ |
|
1155 |
{ \ |
|
1156 |
op(T0, T1); \ |
|
1157 |
RETURN(); \ |
|
1158 |
} \ |
|
1159 |
PPC_OP(st##name##x) \ |
|
1160 |
{ \ |
|
1161 |
T0 += T1; \ |
|
1162 |
op(T0, T2); \ |
|
1163 |
RETURN(); \ |
|
1164 |
} |
|
1165 |
|
|
1166 |
#define PPC_IST_OP(name, op) \ |
|
1167 |
PPC_OP(st##name##_z) \ |
|
1168 |
{ \ |
|
1169 |
op(SPARAM(1), T0); \ |
|
1170 |
RETURN(); \ |
|
1171 |
} \ |
|
1172 |
PPC_OP(st##name) \ |
|
1173 |
{ \ |
|
1174 |
T0 += SPARAM(1); \ |
|
1175 |
op(T0, T1); \ |
|
1176 |
RETURN(); \ |
|
1177 |
} \ |
|
1178 |
PPC_IST_OPX(name, op); |
|
1179 |
|
|
1180 |
PPC_IST_OP(b, st8); |
|
1181 |
PPC_IST_OP(h, st16); |
|
1182 |
PPC_IST_OP(w, st32); |
|
1183 |
|
|
1184 |
/*** Integer load and store with byte reverse ***/ |
|
1185 |
PPC_ILD_OPX(hbr, ld16r); |
|
1186 |
PPC_ILD_OPX(wbr, ld32r); |
|
1187 |
PPC_IST_OPX(hbr, st16r); |
|
1188 |
PPC_IST_OPX(wbr, st32r); |
|
1189 |
|
|
1190 |
/*** Integer load and store multiple ***/ |
|
1191 |
PPC_OP(lmw) |
|
1271 |
/* fadd - fadd. */ |
|
1272 |
PPC_OP(fadd) |
|
1192 | 1273 |
{ |
1193 |
do_lmw(PARAM(1), SPARAM(2) + T0);
|
|
1274 |
FT0 += FT1;
|
|
1194 | 1275 |
RETURN(); |
1195 | 1276 |
} |
1196 | 1277 |
|
1197 |
PPC_OP(stmw) |
|
1278 |
/* fadds - fadds. */ |
|
1279 |
PPC_OP(fadds) |
|
1198 | 1280 |
{ |
1199 |
do_stmw(PARAM(1), SPARAM(2) + T0);
|
|
1281 |
FTS0 += FTS1;
|
|
1200 | 1282 |
RETURN(); |
1201 | 1283 |
} |
1202 | 1284 |
|
1203 |
/*** Integer load and store strings ***/
|
|
1204 |
PPC_OP(lswi)
|
|
1285 |
/* fsub - fsub. */
|
|
1286 |
PPC_OP(fsub)
|
|
1205 | 1287 |
{ |
1206 |
do_lsw(PARAM(1), PARAM(2), T0);
|
|
1288 |
FT0 -= FT1;
|
|
1207 | 1289 |
RETURN(); |
1208 | 1290 |
} |
1209 | 1291 |
|
1210 |
PPC_OP(lswx) |
|
1292 |
/* fsubs - fsubs. */ |
|
1293 |
PPC_OP(fsubs) |
|
1211 | 1294 |
{ |
1212 |
do_lsw(PARAM(1), T0, T1 + T2);
|
|
1295 |
FTS0 -= FTS1;
|
|
1213 | 1296 |
RETURN(); |
1214 | 1297 |
} |
1215 | 1298 |
|
1216 |
PPC_OP(stswi_z) |
|
1299 |
/* fmul - fmul. */ |
|
1300 |
PPC_OP(fmul) |
|
1217 | 1301 |
{ |
1218 |
do_stsw(PARAM(1), PARAM(2), 0);
|
|
1302 |
FT0 *= FT1;
|
|
1219 | 1303 |
RETURN(); |
1220 | 1304 |
} |
1221 | 1305 |
|
1222 |
PPC_OP(stswi) |
|
1306 |
/* fmuls - fmuls. */ |
|
1307 |
PPC_OP(fmuls) |
|
1223 | 1308 |
{ |
1224 |
do_stsw(PARAM(1), PARAM(2), T0);
|
|
1309 |
FTS0 *= FTS1;
|
|
1225 | 1310 |
RETURN(); |
1226 | 1311 |
} |
1227 | 1312 |
|
1228 |
PPC_OP(stswx_z) |
|
1313 |
/* fdiv - fdiv. */ |
|
1314 |
PPC_OP(fdiv) |
|
1229 | 1315 |
{ |
1230 |
do_stsw(PARAM(1), T0, T1);
|
|
1316 |
FT0 /= FT1;
|
|
1231 | 1317 |
RETURN(); |
1232 | 1318 |
} |
1233 | 1319 |
|
1234 |
PPC_OP(stswx) |
|
1320 |
/* fdivs - fdivs. */ |
|
1321 |
PPC_OP(fdivs) |
|
1235 | 1322 |
{ |
1236 |
do_stsw(PARAM(1), T0, T1 + T2);
|
|
1323 |
FTS0 /= FTS1;
|
|
1237 | 1324 |
RETURN(); |
1238 | 1325 |
} |
1239 | 1326 |
|
1240 |
/* SPR */
|
|
1241 |
PPC_OP(load_spr)
|
|
1327 |
/* fsqrt - fsqrt. */
|
|
1328 |
PPC_OP(fsqrt)
|
|
1242 | 1329 |
{ |
1243 |
T0 = regs->spr[PARAM(1)]; |
|
1330 |
do_fsqrt(); |
|
1331 |
RETURN(); |
|
1244 | 1332 |
} |
1245 | 1333 |
|
1246 |
PPC_OP(store_spr) |
|
1334 |
/* fsqrts - fsqrts. */ |
|
1335 |
PPC_OP(fsqrts) |
|
1247 | 1336 |
{ |
1248 |
regs->spr[PARAM(1)] = T0; |
|
1337 |
do_fsqrts(); |
|
1338 |
RETURN(); |
|
1249 | 1339 |
} |
1250 | 1340 |
|
1251 |
/*** Floating-point store ***/ |
|
1252 |
|
|
1253 |
PPC_OP(stfd_z_FT0) |
|
1341 |
/* fres - fres. */ |
|
1342 |
PPC_OP(fres) |
|
1254 | 1343 |
{ |
1255 |
stfq((void *)SPARAM(1), FT0); |
|
1344 |
do_fres(); |
|
1345 |
RETURN(); |
|
1256 | 1346 |
} |
1257 | 1347 |
|
1258 |
PPC_OP(stfd_FT0) |
|
1348 |
/* frsqrte - frsqrte. */ |
|
1349 |
PPC_OP(frsqrte) |
|
1259 | 1350 |
{ |
1260 |
T0 += SPARAM(1);
|
|
1261 |
stfq((void *)T0, FT0);
|
|
1351 |
do_fsqrte();
|
|
1352 |
RETURN();
|
|
1262 | 1353 |
} |
1263 | 1354 |
|
1264 |
PPC_OP(stfdx_z_FT0) |
|
1355 |
/* fsel - fsel. */ |
|
1356 |
PPC_OP(fsel) |
|
1265 | 1357 |
{ |
1266 |
stfq((void *)T0, FT0); |
|
1358 |
do_fsel(); |
|
1359 |
RETURN(); |
|
1267 | 1360 |
} |
1268 | 1361 |
|
1269 |
PPC_OP(stfdx_FT0) |
|
1362 |
/*** Floating-Point multiply-and-add ***/ |
|
1363 |
/* fmadd - fmadd. */ |
|
1364 |
PPC_OP(fmadd) |
|
1270 | 1365 |
{ |
1271 |
T0 += T1;
|
|
1272 |
stfq((void *)T0, FT0);
|
|
1366 |
FT0 = (FT0 * FT1) + FT2;
|
|
1367 |
RETURN();
|
|
1273 | 1368 |
} |
1274 | 1369 |
|
1275 |
PPC_OP(stfs_z_FT0) |
|
1370 |
/* fmadds - fmadds. */ |
|
1371 |
PPC_OP(fmadds) |
|
1276 | 1372 |
{ |
1277 |
float tmp = FT0;
|
|
1278 |
stfl((void *)SPARAM(1), tmp);
|
|
1373 |
FTS0 = (FTS0 * FTS1) + FTS2;
|
|
1374 |
RETURN();
|
|
1279 | 1375 |
} |
1280 | 1376 |
|
1281 |
PPC_OP(stfs_FT0) |
|
1377 |
/* fmsub - fmsub. */ |
|
1378 |
PPC_OP(fmsub) |
|
1282 | 1379 |
{ |
1283 |
float tmp = FT0; |
|
1284 |
T0 += SPARAM(1); |
|
1285 |
stfl((void *)T0, tmp); |
|
1380 |
FT0 = (FT0 * FT1) - FT2; |
|
1381 |
RETURN(); |
|
1286 | 1382 |
} |
1287 | 1383 |
|
1288 |
PPC_OP(stfsx_z_FT0) |
|
1384 |
/* fmsubs - fmsubs. */ |
|
1385 |
PPC_OP(fmsubs) |
|
1289 | 1386 |
{ |
1290 |
float tmp = FT0;
|
|
1291 |
stfl((void *)T0, tmp);
|
|
1387 |
FTS0 = (FTS0 * FTS1) - FTS2;
|
|
1388 |
RETURN();
|
|
1292 | 1389 |
} |
1293 | 1390 |
|
1294 |
PPC_OP(stfsx_FT0) |
|
1391 |
/* fnmadd - fnmadd. - fnmadds - fnmadds. */ |
|
1392 |
PPC_OP(fnmadd) |
|
1295 | 1393 |
{ |
1296 |
float tmp = FT0; |
|
1297 |
T0 += T1; |
|
1298 |
stfl((void *)T0, tmp); |
|
1394 |
FT0 = -((FT0 * FT1) + FT2); |
|
1395 |
RETURN(); |
|
1299 | 1396 |
} |
1300 | 1397 |
|
1301 |
/*** Floating-point load ***/
|
|
1302 |
PPC_OP(lfd_z_FT0)
|
|
1398 |
/* fnmadds - fnmadds. */
|
|
1399 |
PPC_OP(fnmadds)
|
|
1303 | 1400 |
{ |
1304 |
FT0 = ldfq((void *)SPARAM(1)); |
|
1401 |
FTS0 = -((FTS0 * FTS1) + FTS2); |
|
1402 |
RETURN(); |
|
1305 | 1403 |
} |
1306 | 1404 |
|
1307 |
PPC_OP(lfd_FT0) |
|
1405 |
/* fnmsub - fnmsub. */ |
|
1406 |
PPC_OP(fnmsub) |
|
1308 | 1407 |
{ |
1309 |
T0 += SPARAM(1);
|
|
1310 |
FT0 = ldfq((void *)T0);
|
|
1408 |
FT0 = -((FT0 * FT1) - FT2);
|
|
1409 |
RETURN();
|
|
1311 | 1410 |
} |
1312 | 1411 |
|
1313 |
PPC_OP(lfdx_z_FT0) |
|
1412 |
/* fnmsubs - fnmsubs. */ |
|
1413 |
PPC_OP(fnmsubs) |
|
1314 | 1414 |
{ |
1315 |
FT0 = ldfq((void *)T0); |
|
1415 |
FTS0 = -((FTS0 * FTS1) - FTS2); |
|
1416 |
RETURN(); |
|
1316 | 1417 |
} |
1317 | 1418 |
|
1318 |
PPC_OP(lfdx_FT0) |
|
1419 |
/*** Floating-Point round & convert ***/ |
|
1420 |
/* frsp - frsp. */ |
|
1421 |
PPC_OP(frsp) |
|
1319 | 1422 |
{ |
1320 |
T0 += T1;
|
|
1321 |
FT0 = ldfq((void *)T0);
|
|
1423 |
FT0 = FTS0;
|
|
1424 |
RETURN();
|
|
1322 | 1425 |
} |
1323 | 1426 |
|
1324 |
PPC_OP(lfs_z_FT0) |
|
1427 |
/* fctiw - fctiw. */ |
|
1428 |
PPC_OP(fctiw) |
|
1325 | 1429 |
{ |
1326 |
float tmp = ldfl((void *)SPARAM(1));
|
|
1327 |
FT0 = tmp;
|
|
1430 |
do_fctiw();
|
|
1431 |
RETURN();
|
|
1328 | 1432 |
} |
1329 | 1433 |
|
1330 |
PPC_OP(lfs_FT0) |
|
1434 |
/* fctiwz - fctiwz. */ |
|
1435 |
PPC_OP(fctiwz) |
|
1331 | 1436 |
{ |
1332 |
float tmp; |
|
1333 |
T0 += SPARAM(1); |
|
1334 |
tmp = ldfl((void *)T0); |
|
1335 |
FT0 = tmp; |
|
1437 |
do_fctiwz(); |
|
1438 |
RETURN(); |
|
1336 | 1439 |
} |
1337 | 1440 |
|
1338 |
PPC_OP(lfsx_z_FT0) |
|
1441 |
|
|
1442 |
/*** Floating-Point compare ***/ |
|
1443 |
/* fcmpu */ |
|
1444 |
PPC_OP(fcmpu) |
|
1339 | 1445 |
{ |
1340 |
float tmp; |
|
1341 |
tmp = ldfl((void *)T0); |
|
1342 |
FT0 = tmp; |
|
1446 |
do_fcmpu(); |
|
1447 |
RETURN(); |
|
1343 | 1448 |
} |
1344 | 1449 |
|
1345 |
PPC_OP(lfsx_FT0) |
|
1450 |
/* fcmpo */ |
|
1451 |
PPC_OP(fcmpo) |
|
1346 | 1452 |
{ |
1347 |
float tmp; |
|
1348 |
T0 += T1; |
|
1349 |
tmp = ldfl((void *)T0); |
|
1350 |
FT0 = tmp; |
|
1453 |
do_fcmpo(); |
|
1454 |
RETURN(); |
|
1351 | 1455 |
} |
1352 | 1456 |
|
1353 |
PPC_OP(lwarx_z) |
|
1457 |
/*** Floating-point move ***/ |
|
1458 |
/* fabs */ |
|
1459 |
PPC_OP(fabs) |
|
1354 | 1460 |
{ |
1355 |
T1 = ld32(T0); |
|
1356 |
regs->reserve = T0; |
|
1461 |
do_fabs(); |
|
1357 | 1462 |
RETURN(); |
1358 | 1463 |
} |
1359 | 1464 |
|
1360 |
PPC_OP(lwarx) |
|
1465 |
/* fnabs */ |
|
1466 |
PPC_OP(fnabs) |
|
1361 | 1467 |
{ |
1362 |
T0 += T1; |
|
1363 |
T1 = ld32(T0); |
|
1364 |
regs->reserve = T0; |
|
1468 |
do_fnabs(); |
|
1365 | 1469 |
RETURN(); |
1366 | 1470 |
} |
1367 | 1471 |
|
1368 |
PPC_OP(stwcx_z) |
|
1472 |
/* fneg */ |
|
1473 |
PPC_OP(fneg) |
|
1369 | 1474 |
{ |
1370 |
if (regs->reserve != T0) { |
|
1371 |
env->crf[0] = xer_ov; |
|
1372 |
} else { |
|
1373 |
st32(T0, T1); |
|
1374 |
env->crf[0] = xer_ov | 0x02; |
|
1375 |
} |
|
1376 |
regs->reserve = 0; |
|
1475 |
FT0 = -FT0; |
|
1377 | 1476 |
RETURN(); |
1378 | 1477 |
} |
1379 | 1478 |
|
1380 |
PPC_OP(stwcx) |
|
1479 |
/* Load and store */ |
|
1480 |
#if defined(CONFIG_USER_ONLY) |
|
1481 |
#define MEMSUFFIX _raw |
|
1482 |
#include "op_mem.h" |
|
1483 |
#else |
|
1484 |
#define MEMSUFFIX _user |
|
1485 |
#include "op_mem.h" |
|
1486 |
|
|
1487 |
#define MEMSUFFIX _kernel |
|
1488 |
#include "op_mem.h" |
|
1489 |
#endif |
|
1490 |
|
|
1491 |
/* Return from interrupt */ |
|
1492 |
PPC_OP(rfi) |
|
1381 | 1493 |
{ |
1382 |
T0 += T1; |
|
1383 |
if (regs->reserve != (T0 & ~0x03)) { |
|
1384 |
env->crf[0] = xer_ov; |
|
1385 |
} else { |
|
1386 |
st32(T0, T2); |
|
1387 |
env->crf[0] = xer_ov | 0x02; |
|
1494 |
T0 = regs->spr[SRR1] & ~0xFFFF0000; |
|
1495 |
do_store_msr(); |
|
1496 |
do_tlbia(); |
|
1497 |
dump_rfi(); |
|
1498 |
regs->nip = regs->spr[SRR0] & ~0x00000003; |
|
1499 |
if (env->exceptions != 0) { |
|
1500 |
do_check_exception_state(); |
|
1388 | 1501 |
} |
1389 |
regs->reserve = 0; |
|
1390 | 1502 |
RETURN(); |
1391 | 1503 |
} |
1392 | 1504 |
|
1393 |
PPC_OP(dcbz_z) |
|
1505 |
/* Trap word */ |
|
1506 |
PPC_OP(tw) |
|
1394 | 1507 |
{ |
1395 |
do_dcbz(); |
|
1508 |
if ((Ts0 < Ts1 && (PARAM(1) & 0x10)) || |
|
1509 |
(Ts0 > Ts1 && (PARAM(1) & 0x08)) || |
|
1510 |
(Ts0 == Ts1 && (PARAM(1) & 0x04)) || |
|
1511 |
(T0 < T1 && (PARAM(1) & 0x02)) || |
|
1512 |
(T0 > T1 && (PARAM(1) & 0x01))) |
|
1513 |
do_queue_exception_err(EXCP_PROGRAM, EXCP_TRAP); |
|
1396 | 1514 |
RETURN(); |
1397 | 1515 |
} |
1398 | 1516 |
|
1399 |
PPC_OP(dcbz)
|
|
1517 |
PPC_OP(twi)
|
|
1400 | 1518 |
{ |
1401 |
T0 += T1; |
|
1402 |
do_dcbz(); |
|
1519 |
if ((Ts0 < SPARAM(1) && (PARAM(2) & 0x10)) || |
|
1520 |
(Ts0 > SPARAM(1) && (PARAM(2) & 0x08)) || |
|
1521 |
(Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) || |
|
1522 |
(T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) || |
|
1523 |
(T0 > (uint32_t)SPARAM(1) && (PARAM(2) & 0x01))) |
|
1524 |
do_queue_exception_err(EXCP_PROGRAM, EXCP_TRAP); |
|
1403 | 1525 |
RETURN(); |
1404 | 1526 |
} |
1405 | 1527 |
|
1406 | 1528 |
/* Instruction cache block invalidate */ |
1407 |
PPC_OP(icbi_z)
|
|
1529 |
PPC_OP(icbi) |
|
1408 | 1530 |
{ |
1409 | 1531 |
do_icbi(); |
1410 | 1532 |
RETURN(); |
1411 | 1533 |
} |
1412 | 1534 |
|
1413 |
PPC_OP(icbi) |
|
1535 |
/* tlbia */ |
|
1536 |
PPC_OP(tlbia) |
|
1414 | 1537 |
{ |
1415 |
T0 += T1; |
|
1416 |
do_icbi(); |
|
1538 |
do_tlbia(); |
|
1539 |
RETURN(); |
|
1540 |
} |
|
1541 |
|
|
1542 |
/* tlbie */ |
|
1543 |
PPC_OP(tlbie) |
|
1544 |
{ |
|
1545 |
do_tlbie(); |
|
1417 | 1546 |
RETURN(); |
1418 | 1547 |
} |
Also available in: Unified diff