void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg,
unsigned int ofs, unsigned int len)
{
+ uint32_t mask;
+
tcg_debug_assert(ofs < 32);
tcg_debug_assert(len > 0);
tcg_debug_assert(len <= 32);
tcg_gen_op4ii_i32(INDEX_op_extract, ret, arg, ofs, len);
return;
}
+
+ mask = (1u << len) - 1;
if (ofs == 0) {
- tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
+ tcg_gen_andi_i32(ret, arg, mask);
return;
}
return;
}
- /* ??? Ideally we'd know what values are available for immediate AND.
- Assume that 8 bits are available, plus the special case of 16,
- so that we get ext8u, ext16u. */
- switch (len) {
- case 1 ... 8: case 16:
+ if (tcg_op_imm_match(INDEX_op_and, TCG_TYPE_I32, mask)) {
tcg_gen_shri_i32(ret, arg, ofs);
- tcg_gen_andi_i32(ret, ret, (1u << len) - 1);
- break;
- default:
+ tcg_gen_andi_i32(ret, ret, mask);
+ } else {
tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
tcg_gen_shri_i32(ret, ret, 32 - len);
- break;
}
}
void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg,
unsigned int ofs, unsigned int len)
{
+ uint64_t mask;
+
tcg_debug_assert(ofs < 64);
tcg_debug_assert(len > 0);
tcg_debug_assert(len <= 64);
tcg_gen_op4ii_i64(INDEX_op_extract, ret, arg, ofs, len);
return;
}
+
+ mask = (1ull << len) - 1;
if (ofs == 0) {
- tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
+ tcg_gen_andi_i64(ret, arg, mask);
return;
}
return;
}
- /* ??? Ideally we'd know what values are available for immediate AND.
- Assume that 8 bits are available, plus the special cases of 16 and 32,
- so that we get ext8u, ext16u, and ext32u. */
- switch (len) {
- case 1 ... 8: case 16: case 32:
+ if (tcg_op_imm_match(INDEX_op_and, TCG_TYPE_I64, mask)) {
tcg_gen_shri_i64(ret, arg, ofs);
- tcg_gen_andi_i64(ret, ret, (1ull << len) - 1);
- break;
- default:
+ tcg_gen_andi_i64(ret, ret, mask);
+ } else {
tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
tcg_gen_shri_i64(ret, ret, 64 - len);
- break;
}
}