|
@@ -3035,6 +3035,10 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
|
|
|
|
|
|
case INDEX_op_extract_i64:
|
|
|
if (a2 + args[3] == 32) {
|
|
|
+ if (a2 == 0) {
|
|
|
+ tcg_out_ext32u(s, a0, a1);
|
|
|
+ break;
|
|
|
+ }
|
|
|
/* This is a 32-bit zero-extending right shift. */
|
|
|
tcg_out_mov(s, TCG_TYPE_I32, a0, a1);
|
|
|
tcg_out_shifti(s, SHIFT_SHR, a0, a2);
|
|
@@ -3042,28 +3046,53 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
|
|
|
}
|
|
|
/* FALLTHRU */
|
|
|
case INDEX_op_extract_i32:
|
|
|
- /* On the off-chance that we can use the high-byte registers.
|
|
|
- Otherwise we emit the same ext16 + shift pattern that we
|
|
|
- would have gotten from the normal tcg-op.c expansion. */
|
|
|
- tcg_debug_assert(a2 == 8 && args[3] == 8);
|
|
|
- if (a1 < 4 && a0 < 8) {
|
|
|
- tcg_out_modrm(s, OPC_MOVZBL, a0, a1 + 4);
|
|
|
- } else {
|
|
|
+ if (a2 == 0 && args[3] == 8) {
|
|
|
+ tcg_out_ext8u(s, a0, a1);
|
|
|
+ } else if (a2 == 0 && args[3] == 16) {
|
|
|
tcg_out_ext16u(s, a0, a1);
|
|
|
- tcg_out_shifti(s, SHIFT_SHR, a0, 8);
|
|
|
+ } else if (a2 == 8 && args[3] == 8) {
|
|
|
+ /*
|
|
|
+ * On the off-chance that we can use the high-byte registers.
|
|
|
+ * Otherwise we emit the same ext16 + shift pattern that we
|
|
|
+ * would have gotten from the normal tcg-op.c expansion.
|
|
|
+ */
|
|
|
+ if (a1 < 4 && a0 < 8) {
|
|
|
+ tcg_out_modrm(s, OPC_MOVZBL, a0, a1 + 4);
|
|
|
+ } else {
|
|
|
+ tcg_out_ext16u(s, a0, a1);
|
|
|
+ tcg_out_shifti(s, SHIFT_SHR, a0, 8);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ g_assert_not_reached();
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
- case INDEX_op_sextract_i32:
|
|
|
- /* We don't implement sextract_i64, as we cannot sign-extend to
|
|
|
- 64-bits without using the REX prefix that explicitly excludes
|
|
|
- access to the high-byte registers. */
|
|
|
- tcg_debug_assert(a2 == 8 && args[3] == 8);
|
|
|
- if (a1 < 4 && a0 < 8) {
|
|
|
- tcg_out_modrm(s, OPC_MOVSBL, a0, a1 + 4);
|
|
|
+ case INDEX_op_sextract_i64:
|
|
|
+ if (a2 == 0 && args[3] == 8) {
|
|
|
+ tcg_out_ext8s(s, TCG_TYPE_I64, a0, a1);
|
|
|
+ } else if (a2 == 0 && args[3] == 16) {
|
|
|
+ tcg_out_ext16s(s, TCG_TYPE_I64, a0, a1);
|
|
|
+ } else if (a2 == 0 && args[3] == 32) {
|
|
|
+ tcg_out_ext32s(s, a0, a1);
|
|
|
} else {
|
|
|
+ g_assert_not_reached();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case INDEX_op_sextract_i32:
|
|
|
+ if (a2 == 0 && args[3] == 8) {
|
|
|
+ tcg_out_ext8s(s, TCG_TYPE_I32, a0, a1);
|
|
|
+ } else if (a2 == 0 && args[3] == 16) {
|
|
|
tcg_out_ext16s(s, TCG_TYPE_I32, a0, a1);
|
|
|
- tcg_out_shifti(s, SHIFT_SAR, a0, 8);
|
|
|
+ } else if (a2 == 8 && args[3] == 8) {
|
|
|
+ if (a1 < 4 && a0 < 8) {
|
|
|
+ tcg_out_modrm(s, OPC_MOVSBL, a0, a1 + 4);
|
|
|
+ } else {
|
|
|
+ tcg_out_ext16s(s, TCG_TYPE_I32, a0, a1);
|
|
|
+ tcg_out_shifti(s, SHIFT_SAR, a0, 8);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ g_assert_not_reached();
|
|
|
}
|
|
|
break;
|
|
|
|
|
@@ -3746,6 +3775,7 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
|
|
|
case INDEX_op_extract_i32:
|
|
|
case INDEX_op_extract_i64:
|
|
|
case INDEX_op_sextract_i32:
|
|
|
+ case INDEX_op_sextract_i64:
|
|
|
case INDEX_op_ctpop_i32:
|
|
|
case INDEX_op_ctpop_i64:
|
|
|
return C_O1_I1(r, r);
|