Revision dbb30fe6 target-alpha/translate.c
b/target-alpha/translate.c | ||
---|---|---|
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: |
Also available in: Unified diff