aboutsummaryrefslogtreecommitdiff
path: root/tcg/s390/tcg-target.inc.c
diff options
context:
space:
mode:
Diffstat (limited to 'tcg/s390/tcg-target.inc.c')
-rw-r--r--tcg/s390/tcg-target.inc.c68
1 files changed, 30 insertions, 38 deletions
diff --git a/tcg/s390/tcg-target.inc.c b/tcg/s390/tcg-target.inc.c
index d34649eb13..e075b4844a 100644
--- a/tcg/s390/tcg-target.inc.c
+++ b/tcg/s390/tcg-target.inc.c
@@ -41,7 +41,7 @@
#define TCG_CT_CONST_MULI 0x100
#define TCG_CT_CONST_ORI 0x200
#define TCG_CT_CONST_XORI 0x400
-#define TCG_CT_CONST_CMPI 0x800
+#define TCG_CT_CONST_U31 0x800
#define TCG_CT_CONST_ADLI 0x1000
#define TCG_CT_CONST_ZERO 0x2000
@@ -398,7 +398,18 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
ct->ct |= TCG_CT_CONST_XORI;
break;
case 'C':
- ct->ct |= TCG_CT_CONST_CMPI;
+ /* ??? We have no insight here into whether the comparison is
+ signed or unsigned. The COMPARE IMMEDIATE insn uses a 32-bit
+ signed immediate, and the COMPARE LOGICAL IMMEDIATE insn uses
+ a 32-bit unsigned immediate. If we were to use the (semi)
+ obvious "val == (int32_t)val" we would be enabling unsigned
+ comparisons vs very large numbers. The only solution is to
+ take the intersection of the ranges. */
+ /* ??? Another possible solution is to simply lie and allow all
+ constants here and force the out-of-range values into a temp
+ register in tgen_cmp when we have knowledge of the actual
+ comparison code in use. */
+ ct->ct |= TCG_CT_CONST_U31;
break;
case 'Z':
ct->ct |= TCG_CT_CONST_ZERO;
@@ -463,35 +474,6 @@ static int tcg_match_xori(TCGType type, tcg_target_long val)
return 1;
}
-/* Imediates to be used with comparisons. */
-
-static int tcg_match_cmpi(TCGType type, tcg_target_long val)
-{
- if (s390_facilities & FACILITY_EXT_IMM) {
- /* The COMPARE IMMEDIATE instruction is available. */
- if (type == TCG_TYPE_I32) {
- /* We have a 32-bit immediate and can compare against anything. */
- return 1;
- } else {
- /* ??? We have no insight here into whether the comparison is
- signed or unsigned. The COMPARE IMMEDIATE insn uses a 32-bit
- signed immediate, and the COMPARE LOGICAL IMMEDIATE insn uses
- a 32-bit unsigned immediate. If we were to use the (semi)
- obvious "val == (int32_t)val" we would be enabling unsigned
- comparisons vs very large numbers. The only solution is to
- take the intersection of the ranges. */
- /* ??? Another possible solution is to simply lie and allow all
- constants here and force the out-of-range values into a temp
- register in tgen_cmp when we have knowledge of the actual
- comparison code in use. */
- return val >= 0 && val <= 0x7fffffff;
- }
- } else {
- /* Only the LOAD AND TEST instruction is available. */
- return val == 0;
- }
-}
-
/* Immediates to be used with add2/sub2. */
static int tcg_match_add2i(TCGType type, tcg_target_long val)
@@ -537,8 +519,8 @@ static int tcg_target_const_match(tcg_target_long val, TCGType type,
return tcg_match_ori(type, val);
} else if (ct & TCG_CT_CONST_XORI) {
return tcg_match_xori(type, val);
- } else if (ct & TCG_CT_CONST_CMPI) {
- return tcg_match_cmpi(type, val);
+ } else if (ct & TCG_CT_CONST_U31) {
+ return val >= 0 && val <= 0x7fffffff;
} else if (ct & TCG_CT_CONST_ZERO) {
return val == 0;
}
@@ -2252,7 +2234,9 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
static const TCGTargetOpDef r_L = { .args_ct_str = { "r", "L" } };
static const TCGTargetOpDef L_L = { .args_ct_str = { "L", "L" } };
+ static const TCGTargetOpDef r_ri = { .args_ct_str = { "r", "ri" } };
static const TCGTargetOpDef r_rC = { .args_ct_str = { "r", "rC" } };
+ static const TCGTargetOpDef r_rZ = { .args_ct_str = { "r", "rZ" } };
static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
static const TCGTargetOpDef r_0_ri = { .args_ct_str = { "r", "0", "ri" } };
static const TCGTargetOpDef r_0_rK = { .args_ct_str = { "r", "0", "rK" } };
@@ -2320,8 +2304,10 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
return &r_r_ri;
case INDEX_op_brcond_i32:
+ /* Without EXT_IMM, only the LOAD AND TEST insn is available. */
+ return (s390_facilities & FACILITY_EXT_IMM ? &r_ri : &r_rZ);
case INDEX_op_brcond_i64:
- return &r_rC;
+ return (s390_facilities & FACILITY_EXT_IMM ? &r_rC : &r_rZ);
case INDEX_op_bswap16_i32:
case INDEX_op_bswap16_i64:
@@ -2366,16 +2352,22 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_setcond_i32:
case INDEX_op_setcond_i64:
{
- static const TCGTargetOpDef setc
+ /* Without EXT_IMM, only the LOAD AND TEST insn is available. */
+ static const TCGTargetOpDef setc_z
+ = { .args_ct_str = { "r", "r", "rZ" } };
+ static const TCGTargetOpDef setc_c
= { .args_ct_str = { "r", "r", "rC" } };
- return &setc;
+ return (s390_facilities & FACILITY_EXT_IMM ? &setc_c : &setc_z);
}
case INDEX_op_movcond_i32:
case INDEX_op_movcond_i64:
{
- static const TCGTargetOpDef movc
+ /* Without EXT_IMM, only the LOAD AND TEST insn is available. */
+ static const TCGTargetOpDef movc_z
+ = { .args_ct_str = { "r", "r", "rZ", "r", "0" } };
+ static const TCGTargetOpDef movc_c
= { .args_ct_str = { "r", "r", "rC", "r", "0" } };
- return &movc;
+ return (s390_facilities & FACILITY_EXT_IMM ? &movc_c : &movc_z);
}
case INDEX_op_div2_i32:
case INDEX_op_div2_i64: