294 |
294 |
tcg_temp_free(addr);
|
295 |
295 |
}
|
296 |
296 |
|
297 |
|
static inline void gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
|
298 |
|
int32_t disp, int mask)
|
|
297 |
static void gen_bcond_pcload(DisasContext *ctx, int32_t disp, int lab_true)
|
299 |
298 |
{
|
300 |
|
int l1, l2;
|
|
299 |
int lab_over = gen_new_label();
|
|
300 |
|
|
301 |
tcg_gen_movi_i64(cpu_pc, ctx->pc);
|
|
302 |
tcg_gen_br(lab_over);
|
|
303 |
gen_set_label(lab_true);
|
|
304 |
tcg_gen_movi_i64(cpu_pc, ctx->pc + (int64_t)(disp << 2));
|
|
305 |
gen_set_label(lab_over);
|
|
306 |
}
|
|
307 |
|
|
308 |
static void gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
|
|
309 |
int32_t disp, int mask)
|
|
310 |
{
|
|
311 |
int lab_true = gen_new_label();
|
301 |
312 |
|
302 |
|
l1 = gen_new_label();
|
303 |
|
l2 = gen_new_label();
|
304 |
313 |
if (likely(ra != 31)) {
|
305 |
314 |
if (mask) {
|
306 |
315 |
TCGv tmp = tcg_temp_new();
|
307 |
316 |
tcg_gen_andi_i64(tmp, cpu_ir[ra], 1);
|
308 |
|
tcg_gen_brcondi_i64(cond, tmp, 0, l1);
|
|
317 |
tcg_gen_brcondi_i64(cond, tmp, 0, lab_true);
|
309 |
318 |
tcg_temp_free(tmp);
|
310 |
|
} else
|
311 |
|
tcg_gen_brcondi_i64(cond, cpu_ir[ra], 0, l1);
|
|
319 |
} else {
|
|
320 |
tcg_gen_brcondi_i64(cond, cpu_ir[ra], 0, lab_true);
|
|
321 |
}
|
312 |
322 |
} else {
|
313 |
323 |
/* Very uncommon case - Do not bother to optimize. */
|
314 |
324 |
TCGv tmp = tcg_const_i64(0);
|
315 |
|
tcg_gen_brcondi_i64(cond, tmp, 0, l1);
|
|
325 |
tcg_gen_brcondi_i64(cond, tmp, 0, lab_true);
|
316 |
326 |
tcg_temp_free(tmp);
|
317 |
327 |
}
|
318 |
|
tcg_gen_movi_i64(cpu_pc, ctx->pc);
|
319 |
|
tcg_gen_br(l2);
|
320 |
|
gen_set_label(l1);
|
321 |
|
tcg_gen_movi_i64(cpu_pc, ctx->pc + (int64_t)(disp << 2));
|
322 |
|
gen_set_label(l2);
|
|
328 |
gen_bcond_pcload(ctx, disp, lab_true);
|
323 |
329 |
}
|
324 |
330 |
|
325 |
|
static inline void gen_fbcond(DisasContext *ctx, int opc, int ra, int32_t disp)
|
|
331 |
/* Generate a forward TCG branch to LAB_TRUE if RA cmp 0.0.
|
|
332 |
This is complicated by the fact that -0.0 compares the same as +0.0. */
|
|
333 |
|
|
334 |
static void gen_fbcond_internal(TCGCond cond, TCGv src, int lab_true)
|
326 |
335 |
{
|
327 |
|
int l1, l2;
|
|
336 |
int lab_false = -1;
|
|
337 |
uint64_t mzero = 1ull << 63;
|
328 |
338 |
TCGv tmp;
|
329 |
|
TCGv src;
|
330 |
339 |
|
331 |
|
l1 = gen_new_label();
|
332 |
|
l2 = gen_new_label();
|
333 |
|
if (ra != 31) {
|
334 |
|
tmp = tcg_temp_new();
|
335 |
|
src = cpu_fir[ra];
|
336 |
|
} else {
|
337 |
|
tmp = tcg_const_i64(0);
|
338 |
|
src = tmp;
|
339 |
|
}
|
340 |
|
switch (opc) {
|
341 |
|
case 0x31: /* FBEQ */
|
342 |
|
gen_helper_cmpfeq(tmp, src);
|
343 |
|
break;
|
344 |
|
case 0x32: /* FBLT */
|
345 |
|
gen_helper_cmpflt(tmp, src);
|
346 |
|
break;
|
347 |
|
case 0x33: /* FBLE */
|
348 |
|
gen_helper_cmpfle(tmp, src);
|
|
340 |
switch (cond) {
|
|
341 |
case TCG_COND_LE:
|
|
342 |
case TCG_COND_GT:
|
|
343 |
/* For <= or >, the -0.0 value directly compares the way we want. */
|
|
344 |
tcg_gen_brcondi_i64(cond, src, 0, lab_true);
|
349 |
345 |
break;
|
350 |
|
case 0x35: /* FBNE */
|
351 |
|
gen_helper_cmpfne(tmp, src);
|
|
346 |
|
|
347 |
case TCG_COND_EQ:
|
|
348 |
case TCG_COND_NE:
|
|
349 |
/* For == or !=, we can simply mask off the sign bit and compare. */
|
|
350 |
/* ??? Assume that the temporary is reclaimed at the branch. */
|
|
351 |
tmp = tcg_temp_new();
|
|
352 |
tcg_gen_andi_i64(tmp, src, mzero - 1);
|
|
353 |
tcg_gen_brcondi_i64(cond, tmp, 0, lab_true);
|
352 |
354 |
break;
|
353 |
|
case 0x36: /* FBGE */
|
354 |
|
gen_helper_cmpfge(tmp, src);
|
|
355 |
|
|
356 |
case TCG_COND_GE:
|
|
357 |
/* For >=, emit two branches to the destination. */
|
|
358 |
tcg_gen_brcondi_i64(cond, src, 0, lab_true);
|
|
359 |
tcg_gen_brcondi_i64(TCG_COND_EQ, src, mzero, lab_true);
|
355 |
360 |
break;
|
356 |
|
case 0x37: /* FBGT */
|
357 |
|
gen_helper_cmpfgt(tmp, src);
|
|
361 |
|
|
362 |
case TCG_COND_LT:
|
|
363 |
/* For <, first filter out -0.0 to what will be the fallthru. */
|
|
364 |
lab_false = gen_new_label();
|
|
365 |
tcg_gen_brcondi_i64(TCG_COND_EQ, src, mzero, lab_false);
|
|
366 |
tcg_gen_brcondi_i64(cond, src, 0, lab_true);
|
|
367 |
gen_set_label(lab_false);
|
358 |
368 |
break;
|
|
369 |
|
359 |
370 |
default:
|
360 |
371 |
abort();
|
361 |
372 |
}
|
362 |
|
tcg_gen_brcondi_i64(TCG_COND_NE, tmp, 0, l1);
|
363 |
|
tcg_gen_movi_i64(cpu_pc, ctx->pc);
|
364 |
|
tcg_gen_br(l2);
|
365 |
|
gen_set_label(l1);
|
366 |
|
tcg_gen_movi_i64(cpu_pc, ctx->pc + (int64_t)(disp << 2));
|
367 |
|
gen_set_label(l2);
|
|
373 |
}
|
|
374 |
|
|
375 |
static void gen_fbcond(DisasContext *ctx, TCGCond cond, int ra, int32_t disp)
|
|
376 |
{
|
|
377 |
int lab_true;
|
|
378 |
|
|
379 |
if (unlikely(ra == 31)) {
|
|
380 |
/* Very uncommon case, but easier to optimize it to an integer
|
|
381 |
comparison than continuing with the floating point comparison. */
|
|
382 |
gen_bcond(ctx, cond, ra, disp, 0);
|
|
383 |
return;
|
|
384 |
}
|
|
385 |
|
|
386 |
lab_true = gen_new_label();
|
|
387 |
gen_fbcond_internal(cond, cpu_fir[ra], lab_true);
|
|
388 |
gen_bcond_pcload(ctx, disp, lab_true);
|
368 |
389 |
}
|
369 |
390 |
|
370 |
391 |
static inline void gen_cmov(TCGCond inv_cond, int ra, int rb, int rc,
|
... | ... | |
399 |
420 |
gen_set_label(l1);
|
400 |
421 |
}
|
401 |
422 |
|
|
423 |
static void gen_fcmov(TCGCond inv_cond, int ra, int rb, int rc)
|
|
424 |
{
|
|
425 |
TCGv va = cpu_fir[ra];
|
|
426 |
int l1;
|
|
427 |
|
|
428 |
if (unlikely(rc == 31))
|
|
429 |
return;
|
|
430 |
if (unlikely(ra == 31)) {
|
|
431 |
/* ??? Assume that the temporary is reclaimed at the branch. */
|
|
432 |
va = tcg_const_i64(0);
|
|
433 |
}
|
|
434 |
|
|
435 |
l1 = gen_new_label();
|
|
436 |
gen_fbcond_internal(inv_cond, va, l1);
|
|
437 |
|
|
438 |
if (rb != 31)
|
|
439 |
tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[rb]);
|
|
440 |
else
|
|
441 |
tcg_gen_movi_i64(cpu_fir[rc], 0);
|
|
442 |
gen_set_label(l1);
|
|
443 |
}
|
|
444 |
|
402 |
445 |
#define FARITH2(name) \
|
403 |
446 |
static inline void glue(gen_f, name)(int rb, int rc) \
|
404 |
447 |
{ \
|
... | ... | |
482 |
525 |
FARITH3(cpysn)
|
483 |
526 |
FARITH3(cpyse)
|
484 |
527 |
|
485 |
|
#define FCMOV(name) \
|
486 |
|
static inline void glue(gen_f, name)(int ra, int rb, int rc) \
|
487 |
|
{ \
|
488 |
|
int l1; \
|
489 |
|
TCGv tmp; \
|
490 |
|
\
|
491 |
|
if (unlikely(rc == 31)) \
|
492 |
|
return; \
|
493 |
|
\
|
494 |
|
l1 = gen_new_label(); \
|
495 |
|
tmp = tcg_temp_new(); \
|
496 |
|
if (ra != 31) { \
|
497 |
|
tmp = tcg_temp_new(); \
|
498 |
|
gen_helper_ ## name (tmp, cpu_fir[ra]); \
|
499 |
|
} else { \
|
500 |
|
tmp = tcg_const_i64(0); \
|
501 |
|
gen_helper_ ## name (tmp, tmp); \
|
502 |
|
} \
|
503 |
|
tcg_gen_brcondi_i64(TCG_COND_EQ, tmp, 0, l1); \
|
504 |
|
if (rb != 31) \
|
505 |
|
tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[ra]); \
|
506 |
|
else \
|
507 |
|
tcg_gen_movi_i64(cpu_fir[rc], 0); \
|
508 |
|
gen_set_label(l1); \
|
509 |
|
}
|
510 |
|
FCMOV(cmpfeq)
|
511 |
|
FCMOV(cmpfne)
|
512 |
|
FCMOV(cmpflt)
|
513 |
|
FCMOV(cmpfge)
|
514 |
|
FCMOV(cmpfle)
|
515 |
|
FCMOV(cmpfgt)
|
516 |
|
|
517 |
528 |
static inline uint64_t zapnot_mask(uint8_t lit)
|
518 |
529 |
{
|
519 |
530 |
uint64_t mask = 0;
|
... | ... | |
1871 |
1882 |
break;
|
1872 |
1883 |
case 0x02A:
|
1873 |
1884 |
/* FCMOVEQ */
|
1874 |
|
gen_fcmpfeq(ra, rb, rc);
|
|
1885 |
gen_fcmov(TCG_COND_NE, ra, rb, rc);
|
1875 |
1886 |
break;
|
1876 |
1887 |
case 0x02B:
|
1877 |
1888 |
/* FCMOVNE */
|
1878 |
|
gen_fcmpfne(ra, rb, rc);
|
|
1889 |
gen_fcmov(TCG_COND_EQ, ra, rb, rc);
|
1879 |
1890 |
break;
|
1880 |
1891 |
case 0x02C:
|
1881 |
1892 |
/* FCMOVLT */
|
1882 |
|
gen_fcmpflt(ra, rb, rc);
|
|
1893 |
gen_fcmov(TCG_COND_GE, ra, rb, rc);
|
1883 |
1894 |
break;
|
1884 |
1895 |
case 0x02D:
|
1885 |
1896 |
/* FCMOVGE */
|
1886 |
|
gen_fcmpfge(ra, rb, rc);
|
|
1897 |
gen_fcmov(TCG_COND_LT, ra, rb, rc);
|
1887 |
1898 |
break;
|
1888 |
1899 |
case 0x02E:
|
1889 |
1900 |
/* FCMOVLE */
|
1890 |
|
gen_fcmpfle(ra, rb, rc);
|
|
1901 |
gen_fcmov(TCG_COND_GT, ra, rb, rc);
|
1891 |
1902 |
break;
|
1892 |
1903 |
case 0x02F:
|
1893 |
1904 |
/* FCMOVGT */
|
1894 |
|
gen_fcmpfgt(ra, rb, rc);
|
|
1905 |
gen_fcmov(TCG_COND_LE, ra, rb, rc);
|
1895 |
1906 |
break;
|
1896 |
1907 |
case 0x030:
|
1897 |
1908 |
/* CVTQL */
|
... | ... | |
2482 |
2493 |
ret = 1;
|
2483 |
2494 |
break;
|
2484 |
2495 |
case 0x31: /* FBEQ */
|
|
2496 |
gen_fbcond(ctx, TCG_COND_EQ, ra, disp21);
|
|
2497 |
ret = 1;
|
|
2498 |
break;
|
2485 |
2499 |
case 0x32: /* FBLT */
|
|
2500 |
gen_fbcond(ctx, TCG_COND_LT, ra, disp21);
|
|
2501 |
ret = 1;
|
|
2502 |
break;
|
2486 |
2503 |
case 0x33: /* FBLE */
|
2487 |
|
gen_fbcond(ctx, opc, ra, disp21);
|
|
2504 |
gen_fbcond(ctx, TCG_COND_LE, ra, disp21);
|
2488 |
2505 |
ret = 1;
|
2489 |
2506 |
break;
|
2490 |
2507 |
case 0x34:
|
... | ... | |
2495 |
2512 |
ret = 1;
|
2496 |
2513 |
break;
|
2497 |
2514 |
case 0x35: /* FBNE */
|
|
2515 |
gen_fbcond(ctx, TCG_COND_NE, ra, disp21);
|
|
2516 |
ret = 1;
|
|
2517 |
break;
|
2498 |
2518 |
case 0x36: /* FBGE */
|
|
2519 |
gen_fbcond(ctx, TCG_COND_GE, ra, disp21);
|
|
2520 |
ret = 1;
|
|
2521 |
break;
|
2499 |
2522 |
case 0x37: /* FBGT */
|
2500 |
|
gen_fbcond(ctx, opc, ra, disp21);
|
|
2523 |
gen_fbcond(ctx, TCG_COND_GT, ra, disp21);
|
2501 |
2524 |
ret = 1;
|
2502 |
2525 |
break;
|
2503 |
2526 |
case 0x38:
|