97 |
97 |
Copied from gcc sources. */
|
98 |
98 |
static inline int or_mask_p(tcg_target_ulong mask)
|
99 |
99 |
{
|
|
100 |
if (mask == 0 || mask == -1) {
|
|
101 |
return 0;
|
|
102 |
}
|
100 |
103 |
mask += mask & -mask;
|
101 |
104 |
return (mask & (mask - 1)) == 0;
|
102 |
105 |
}
|
... | ... | |
213 |
216 |
case 'K':
|
214 |
217 |
ct->ct |= TCG_CT_CONST_MS11;
|
215 |
218 |
break;
|
|
219 |
case 'M':
|
|
220 |
ct->ct |= TCG_CT_CONST_AND;
|
|
221 |
break;
|
|
222 |
case 'O':
|
|
223 |
ct->ct |= TCG_CT_CONST_OR;
|
|
224 |
break;
|
216 |
225 |
default:
|
217 |
226 |
return -1;
|
218 |
227 |
}
|
... | ... | |
236 |
245 |
return check_fit_tl(val, 11);
|
237 |
246 |
} else if (ct & TCG_CT_CONST_MS11) {
|
238 |
247 |
return check_fit_tl(-val, 11);
|
|
248 |
} else if (ct & TCG_CT_CONST_AND) {
|
|
249 |
return and_mask_p(val);
|
|
250 |
} else if (ct & TCG_CT_CONST_OR) {
|
|
251 |
return or_mask_p(val);
|
239 |
252 |
}
|
240 |
253 |
return 0;
|
241 |
254 |
}
|
... | ... | |
474 |
487 |
|
475 |
488 |
static void tcg_out_ori(TCGContext *s, int ret, int arg, tcg_target_ulong m)
|
476 |
489 |
{
|
477 |
|
if (m == 0) {
|
478 |
|
tcg_out_mov(s, ret, arg);
|
479 |
|
} else if (m == -1) {
|
480 |
|
tcg_out_movi(s, TCG_TYPE_I32, ret, -1);
|
481 |
|
} else if (or_mask_p(m)) {
|
482 |
|
int bs0, bs1;
|
483 |
|
|
484 |
|
for (bs0 = 0; bs0 < 32; bs0++) {
|
485 |
|
if ((m & (1u << bs0)) != 0) {
|
486 |
|
break;
|
487 |
|
}
|
|
490 |
int bs0, bs1;
|
|
491 |
|
|
492 |
/* Note that the argument is constrained to match or_mask_p. */
|
|
493 |
for (bs0 = 0; bs0 < 32; bs0++) {
|
|
494 |
if ((m & (1u << bs0)) != 0) {
|
|
495 |
break;
|
488 |
496 |
}
|
489 |
|
for (bs1 = bs0; bs1 < 32; bs1++) {
|
490 |
|
if ((m & (1u << bs1)) == 0) {
|
491 |
|
break;
|
492 |
|
}
|
|
497 |
}
|
|
498 |
for (bs1 = bs0; bs1 < 32; bs1++) {
|
|
499 |
if ((m & (1u << bs1)) == 0) {
|
|
500 |
break;
|
493 |
501 |
}
|
494 |
|
assert(bs1 == 32 || (1ul << bs1) > m);
|
495 |
|
|
496 |
|
tcg_out_mov(s, ret, arg);
|
497 |
|
tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(-1)
|
498 |
|
| INSN_SHDEP_CP(31 - bs0) | INSN_DEP_LEN(bs1 - bs0));
|
499 |
|
} else {
|
500 |
|
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R1, m);
|
501 |
|
tcg_out_arith(s, ret, arg, TCG_REG_R1, INSN_OR);
|
502 |
502 |
}
|
|
503 |
assert(bs1 == 32 || (1ul << bs1) > m);
|
|
504 |
|
|
505 |
tcg_out_mov(s, ret, arg);
|
|
506 |
tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(-1)
|
|
507 |
| INSN_SHDEP_CP(31 - bs0) | INSN_DEP_LEN(bs1 - bs0));
|
503 |
508 |
}
|
504 |
509 |
|
505 |
510 |
static void tcg_out_andi(TCGContext *s, int ret, int arg, tcg_target_ulong m)
|
506 |
511 |
{
|
507 |
|
if (m == 0) {
|
508 |
|
tcg_out_mov(s, ret, TCG_REG_R0);
|
509 |
|
} else if (m == -1) {
|
510 |
|
tcg_out_mov(s, ret, arg);
|
511 |
|
} else if (and_mask_p(m)) {
|
512 |
|
int ls0, ls1, ms0;
|
|
512 |
int ls0, ls1, ms0;
|
513 |
513 |
|
514 |
|
for (ls0 = 0; ls0 < 32; ls0++) {
|
515 |
|
if ((m & (1u << ls0)) == 0) {
|
516 |
|
break;
|
517 |
|
}
|
|
514 |
/* Note that the argument is constrained to match and_mask_p. */
|
|
515 |
for (ls0 = 0; ls0 < 32; ls0++) {
|
|
516 |
if ((m & (1u << ls0)) == 0) {
|
|
517 |
break;
|
518 |
518 |
}
|
519 |
|
for (ls1 = ls0; ls1 < 32; ls1++) {
|
520 |
|
if ((m & (1u << ls1)) != 0) {
|
521 |
|
break;
|
522 |
|
}
|
|
519 |
}
|
|
520 |
for (ls1 = ls0; ls1 < 32; ls1++) {
|
|
521 |
if ((m & (1u << ls1)) != 0) {
|
|
522 |
break;
|
523 |
523 |
}
|
524 |
|
for (ms0 = ls1; ms0 < 32; ms0++) {
|
525 |
|
if ((m & (1u << ms0)) == 0) {
|
526 |
|
break;
|
527 |
|
}
|
|
524 |
}
|
|
525 |
for (ms0 = ls1; ms0 < 32; ms0++) {
|
|
526 |
if ((m & (1u << ms0)) == 0) {
|
|
527 |
break;
|
528 |
528 |
}
|
529 |
|
assert (ms0 == 32);
|
|
529 |
}
|
|
530 |
assert (ms0 == 32);
|
530 |
531 |
|
531 |
|
if (ls1 == 32) {
|
532 |
|
tcg_out_extr(s, ret, arg, 0, ls0, 0);
|
533 |
|
} else {
|
534 |
|
tcg_out_mov(s, ret, arg);
|
535 |
|
tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(0)
|
536 |
|
| INSN_SHDEP_CP(31 - ls0) | INSN_DEP_LEN(ls1 - ls0));
|
537 |
|
}
|
|
532 |
if (ls1 == 32) {
|
|
533 |
tcg_out_extr(s, ret, arg, 0, ls0, 0);
|
538 |
534 |
} else {
|
539 |
|
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R1, m);
|
540 |
|
tcg_out_arith(s, ret, arg, TCG_REG_R1, INSN_AND);
|
|
535 |
tcg_out_mov(s, ret, arg);
|
|
536 |
tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(0)
|
|
537 |
| INSN_SHDEP_CP(31 - ls0) | INSN_DEP_LEN(ls1 - ls0));
|
541 |
538 |
}
|
542 |
539 |
}
|
543 |
540 |
|
... | ... | |
1539 |
1536 |
|
1540 |
1537 |
{ INDEX_op_add_i32, { "r", "rZ", "ri" } },
|
1541 |
1538 |
{ INDEX_op_sub_i32, { "r", "rI", "ri" } },
|
1542 |
|
{ INDEX_op_and_i32, { "r", "rZ", "ri" } },
|
1543 |
|
{ INDEX_op_or_i32, { "r", "rZ", "ri" } },
|
|
1539 |
{ INDEX_op_and_i32, { "r", "rZ", "rM" } },
|
|
1540 |
{ INDEX_op_or_i32, { "r", "rZ", "rO" } },
|
1544 |
1541 |
{ INDEX_op_xor_i32, { "r", "rZ", "rZ" } },
|
1545 |
|
{ INDEX_op_andc_i32, { "r", "rZ", "ri" } },
|
|
1542 |
/* Note that the second argument will be inverted, which means
|
|
1543 |
we want a constant whose inversion matches M, and that O = ~M.
|
|
1544 |
See the implementation of and_mask_p. */
|
|
1545 |
{ INDEX_op_andc_i32, { "r", "rZ", "rO" } },
|
1546 |
1546 |
|
1547 |
1547 |
{ INDEX_op_mul_i32, { "r", "r", "r" } },
|
1548 |
1548 |
{ INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
|