00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "defs.h"
00039 #include "erglob.h"
00040 #include "ercg.h"
00041 #include "tracing.h"
00042 #include "config.h"
00043 #include "config_targ_opt.h"
00044 #include "topcode.h"
00045 #include "tn.h"
00046 #include "cg_flags.h"
00047 #include "targ_isa_lits.h"
00048 #include "op.h"
00049 #include "cg_spill.h"
00050 #include "cgexp.h"
00051 #include "cgexp_internals.h"
00052
00053 void
00054 Initialize_Branch_Variants(void)
00055 {
00056
00057 }
00058
00059
00060
00061
00062 TOP
00063 Pick_Compare_TOP (VARIANT *variant, TN **src1, TN **src2, OPS *ops)
00064 {
00065 TOP cmp;
00066 TOP cmp_i;
00067
00068 if (*src2 != NULL && TN_has_value(*src2)) {
00069
00070 TN *tmp = *src1;
00071 *src1 = *src2;
00072 *src2 = tmp;
00073 *variant = Invert_BR_Variant(*variant);
00074 }
00075
00076
00077 if (*src1 != NULL && TN_is_zero(*src1)) {
00078 switch (*variant) {
00079 case V_BR_U8LE:
00080 case V_BR_U4LE:
00081 *variant = V_BR_ALWAYS; break;
00082 case V_BR_U8GT:
00083 case V_BR_U4GT:
00084 *variant = V_BR_NEVER; break;
00085 }
00086 }
00087 if (*src2 != NULL && TN_is_zero_reg(*src2)) {
00088 switch (*variant) {
00089 case V_BR_U8LT:
00090 case V_BR_U4LT:
00091 *variant = V_BR_NEVER; break;
00092 case V_BR_U8GE:
00093 case V_BR_U4GE:
00094 *variant = V_BR_ALWAYS; break;
00095 }
00096 }
00097
00098
00099 switch (*variant) {
00100 case V_BR_I8GE: cmp_i = TOP_cmp_i_ge; cmp = TOP_cmp_ge; break;
00101 case V_BR_I8GT: cmp_i = TOP_cmp_i_gt; cmp = TOP_cmp_gt; break;
00102 case V_BR_I8LE: cmp_i = TOP_cmp_i_le; cmp = TOP_cmp_le; break;
00103 case V_BR_I8LT: cmp_i = TOP_cmp_i_lt; cmp = TOP_cmp_lt; break;
00104 case V_BR_U8GE: cmp_i = TOP_cmp_i_geu; cmp = TOP_cmp_geu; break;
00105 case V_BR_U8GT: cmp_i = TOP_cmp_i_gtu; cmp = TOP_cmp_gtu; break;
00106 case V_BR_U8LE: cmp_i = TOP_cmp_i_leu; cmp = TOP_cmp_leu; break;
00107 case V_BR_U8LT: cmp_i = TOP_cmp_i_ltu; cmp = TOP_cmp_ltu; break;
00108 case V_BR_I8EQ: cmp_i = TOP_cmp_i_eq; cmp = TOP_cmp_eq; break;
00109 case V_BR_U8EQ: cmp_i = TOP_cmp_i_eq; cmp = TOP_cmp_eq; break;
00110 case V_BR_I8NE: cmp_i = TOP_cmp_i_ne; cmp = TOP_cmp_ne; break;
00111 case V_BR_U8NE: cmp_i = TOP_cmp_i_ne; cmp = TOP_cmp_ne; break;
00112 case V_BR_I4GE: cmp_i = TOP_cmp4_i_ge; cmp = TOP_cmp4_ge; break;
00113 case V_BR_I4GT: cmp_i = TOP_cmp4_i_gt; cmp = TOP_cmp4_gt; break;
00114 case V_BR_I4LE: cmp_i = TOP_cmp4_i_le; cmp = TOP_cmp4_le; break;
00115 case V_BR_I4LT: cmp_i = TOP_cmp4_i_lt; cmp = TOP_cmp4_lt; break;
00116 case V_BR_U4GE: cmp_i = TOP_cmp4_i_geu; cmp = TOP_cmp4_geu; break;
00117 case V_BR_U4GT: cmp_i = TOP_cmp4_i_gtu; cmp = TOP_cmp4_gtu; break;
00118 case V_BR_U4LE: cmp_i = TOP_cmp4_i_leu; cmp = TOP_cmp4_leu; break;
00119 case V_BR_U4LT: cmp_i = TOP_cmp4_i_ltu; cmp = TOP_cmp4_ltu; break;
00120 case V_BR_I4EQ: cmp_i = TOP_cmp4_i_eq; cmp = TOP_cmp4_eq; break;
00121 case V_BR_U4EQ: cmp_i = TOP_cmp4_i_eq; cmp = TOP_cmp4_eq; break;
00122 case V_BR_I4NE: cmp_i = TOP_cmp4_i_ne; cmp = TOP_cmp4_ne; break;
00123 case V_BR_U4NE: cmp_i = TOP_cmp4_i_ne; cmp = TOP_cmp4_ne; break;
00124 case V_BR_FEQ:
00125 case V_BR_DEQ: cmp_i = TOP_UNDEFINED; cmp = TOP_fcmp_eq; break;
00126 case V_BR_XEQ: cmp_i = TOP_UNDEFINED; cmp = TOP_fcmp_eq; break;
00127 case V_BR_FLT:
00128 case V_BR_DLT: cmp_i = TOP_UNDEFINED; cmp = TOP_fcmp_lt; break;
00129 case V_BR_XLT: cmp_i = TOP_UNDEFINED; cmp = TOP_fcmp_lt; break;
00130 case V_BR_FLE:
00131 case V_BR_DLE: cmp_i = TOP_UNDEFINED; cmp = TOP_fcmp_le; break;
00132 case V_BR_XLE: cmp_i = TOP_UNDEFINED; cmp = TOP_fcmp_le; break;
00133 case V_BR_FNE:
00134 case V_BR_DNE: cmp_i = TOP_UNDEFINED; cmp = TOP_fcmp_neq; break;
00135 case V_BR_XNE: cmp_i = TOP_UNDEFINED; cmp = TOP_fcmp_neq; break;
00136 case V_BR_FGT:
00137 case V_BR_DGT: cmp_i = TOP_UNDEFINED; cmp = TOP_fcmp_gt; break;
00138 case V_BR_XGT: cmp_i = TOP_UNDEFINED; cmp = TOP_fcmp_gt; break;
00139 case V_BR_FGE:
00140 case V_BR_DGE: cmp_i = TOP_UNDEFINED; cmp = TOP_fcmp_ge; break;
00141 case V_BR_XGE: cmp_i = TOP_UNDEFINED; cmp = TOP_fcmp_ge; break;
00142 default: cmp_i = TOP_UNDEFINED; cmp = TOP_UNDEFINED; break;
00143 }
00144
00145
00146 if (cmp_i != TOP_UNDEFINED && *src1 != NULL && TN_has_value(*src1)) {
00147 const ISA_OPERAND_INFO *oinfo = ISA_OPERAND_Info(cmp_i);
00148 const ISA_OPERAND_VALTYP *otype = ISA_OPERAND_INFO_Operand(oinfo, 1);
00149 ISA_LIT_CLASS lc = ISA_OPERAND_VALTYP_Literal_Class(otype);
00150 if (ISA_LC_Value_In_Class(TN_value(*src1), lc))
00151 cmp = cmp_i;
00152 else
00153 *src1 = Expand_Immediate_Into_Register(*src1, ops);
00154 }
00155
00156 return cmp;
00157 }
00158
00159 void
00160 Expand_Branch ( TN *targ, TN *src1, TN *src2, VARIANT variant, OPS *ops)
00161 {
00162 TOP cmp;
00163 BOOL false_br = V_false_br(variant);
00164 VARIANT cond = V_br_condition(variant);
00165
00166
00167 if ( Trace_Exp2 ) {
00168 fprintf ( TFile, "<cgexp> Translating %s branch:\n",
00169 (false_br ? "false" : "true") );
00170 }
00171
00172 FmtAssert( cond <= V_BR_LAST, ("unexpected variant in Expand_Branch"));
00173 FmtAssert( cond != V_BR_NONE, ("BR_NONE variant in Expand_Branch"));
00174
00175 cmp = Pick_Compare_TOP (&cond, &src1, &src2, ops);
00176 if ( Trace_Exp2 ) {
00177 fprintf ( TFile, "<cgexp> transformed branch cond = %lld\n", cond);
00178 }
00179
00180 switch (cond) {
00181 case V_BR_ALWAYS:
00182 case V_BR_NEVER:
00183 Is_True(cmp == TOP_UNDEFINED,
00184 ("unexpected compare op for %s", BR_Variant_Name(cond)));
00185 if ((cond == V_BR_ALWAYS) ^ false_br) {
00186
00187 Build_OP (TOP_br, Gen_Enum_TN(ECV_ph_few), Gen_Enum_TN(ECV_dh), targ, ops);
00188 }
00189 break;
00190 case V_BR_PEQ:
00191 case V_BR_PNE:
00192 {
00193 Is_True(cmp == TOP_UNDEFINED,
00194 ("unexpected compare op for V_BR_PEQ/V_BR_PNE"));
00195 TN *p1 = Build_RCLASS_TN (ISA_REGISTER_CLASS_predicate);
00196 TN *p2 = Build_RCLASS_TN (ISA_REGISTER_CLASS_predicate);
00197 TN *tn = Build_TN_Of_Mtype (MTYPE_I8);
00198 TOP action = (cond == V_BR_PEQ) ? TOP_cmp_ne : TOP_cmp_eq;
00199
00200 if(TN_is_constant(src1))
00201 {
00202 if(TN_value(src1) == 1)
00203 src1 = True_TN;
00204 else if(TN_value(src1) == 0)
00205 src1 = Zero_TN;
00206 else
00207 FmtAssert(TN_value(src1) == 1 || TN_value(src1) == 0, ("unexpect operands for V_BR_PEQ/V_BR_PNE"));
00208 }
00209 if(TN_is_constant(src2))
00210 {
00211 if(TN_value(src2) == 1)
00212 src1 = True_TN;
00213 else if(TN_value(src2) == 0)
00214 src2 = Zero_TN;
00215 else
00216 FmtAssert(TN_value(src2) == 1 || TN_value(src2) == 0, ("unexpect operands for V_BR_PEQ/V_BR_PNE"));
00217 }
00218
00219
00220 Build_OP (TOP_mov_i, tn, True_TN, Gen_Literal_TN(1, 8), ops);
00221 Build_OP (TOP_xor_i, tn, src1, Gen_Literal_TN(1, 8), tn, ops);
00222 Build_OP (TOP_xor_i, tn, src2, Gen_Literal_TN(1, 8), tn, ops);
00223
00224
00225 Build_OP (action, p1, p2, True_TN, tn, Zero_TN, ops);
00226
00227 Build_OP (TOP_br_cond,
00228 false_br ? p2 : p1,
00229 Gen_Enum_TN(ECV_bwh_dptk),
00230 Gen_Enum_TN(ECV_ph_few),
00231 Gen_Enum_TN(ECV_dh),
00232 targ, ops);
00233 }
00234 break;
00235 case V_BR_P_TRUE:
00236 Is_True(cmp == TOP_UNDEFINED, ("unexpected compare op for V_BR_P_TRUE"));
00237 if (false_br) {
00238 DevWarn("inverted V_BR_P_TRUE");
00239 TN *tmp = Build_RCLASS_TN(ISA_REGISTER_CLASS_predicate);
00240 Exp_Pred_Complement(tmp, True_TN, src1, ops);
00241 src1 = tmp;
00242 }
00243 Build_OP (TOP_br_cond,
00244 src1,
00245 Gen_Enum_TN(ECV_bwh_dptk),
00246 Gen_Enum_TN(ECV_ph_few),
00247 Gen_Enum_TN(ECV_dh),
00248 targ, ops);
00249 break;
00250 default:
00251 {
00252
00253 FmtAssert(cmp != TOP_UNDEFINED, ("Expand_Branch: unexpected comparison"));
00254 TN *p1 = Build_RCLASS_TN (ISA_REGISTER_CLASS_predicate);
00255 TN *p2 = Build_RCLASS_TN (ISA_REGISTER_CLASS_predicate);
00256 if (TOP_is_flop(cmp)) {
00257 Build_OP (cmp, p1, p2, True_TN, Gen_Enum_TN(ECV_sf_s0), src1, src2, ops);
00258 } else {
00259 Build_OP (cmp, p1, p2, True_TN, src1, src2, ops);
00260 }
00261 Build_OP (TOP_br_cond,
00262 false_br ? p2 : p1,
00263 Gen_Enum_TN(ECV_bwh_dptk),
00264 Gen_Enum_TN(ECV_ph_few),
00265 Gen_Enum_TN(ECV_dh),
00266 targ, ops);
00267 }
00268 break;
00269 }
00270 }
00271
00272 void Exp_Indirect_Branch (TN *targ_reg, OPS *ops)
00273 {
00274 if (TN_register_class(targ_reg) != ISA_REGISTER_CLASS_branch) {
00275 TN *tmp = Build_RCLASS_TN (ISA_REGISTER_CLASS_branch);
00276 Exp_COPY (tmp, targ_reg, ops);
00277 targ_reg = tmp;
00278 }
00279 Build_OP (TOP_br_r,
00280 Gen_Enum_TN(ECV_ph_few),
00281 Gen_Enum_TN(ECV_dh),
00282 targ_reg,
00283 ops);
00284 }
00285
00286 void Exp_Local_Jump(BB *bb, INT64 offset, OPS *ops)
00287 {
00288 FmtAssert(FALSE, ("NYI: Exp_Local_Jump"));
00289 }
00290
00291 void Exp_Return (TN *return_address, OPS *ops)
00292 {
00293 Build_OP (TOP_br_ret, True_TN,
00294 Gen_Enum_TN(ECV_bwh_sptk),
00295 Gen_Enum_TN(ECV_ph_many),
00296 Gen_Enum_TN(ECV_dh),
00297 return_address, ops);
00298 }
00299
00300 void Exp_Call (OPERATOR opr, TN *return_address, TN *target, OPS *ops)
00301 {
00302 TOP top;
00303 TN *br_tmp;
00304 TN *ar_ec = Build_Dedicated_TN ( ISA_REGISTER_CLASS_application,
00305 (REGISTER)(REGISTER_MIN + 66),
00306 8);
00307 switch (opr) {
00308 case OPR_CALL:
00309 top = TOP_br_call; break;
00310 case OPR_ICALL:
00311 if ( ! Get_Trace (TP_CGEXP, 256)) {
00312
00313 OPCODE opc = OPCODE_make_op (OPR_LDID, Pointer_Mtype, Pointer_Mtype);
00314 TN *tmp1 = Build_TN_Of_Mtype (Pointer_Mtype);
00315
00316
00317
00318 if (!Constant_GP)
00319 Expand_Load (opc, GP_TN, target, Gen_Literal_TN(8, 4), V_NONE, ops);
00320
00321 Expand_Load (opc, tmp1, target, Gen_Literal_TN(0, 4), V_NONE, ops);
00322 target = tmp1;
00323 }
00324
00325 case OPR_PICCALL:
00326 top = TOP_br_r_call;
00327 br_tmp = Build_RCLASS_TN(ISA_REGISTER_CLASS_branch);
00328 Build_OP (TOP_mov_t_br, br_tmp, True_TN, target, ops);
00329 target = br_tmp;
00330 break;
00331 default:
00332 FmtAssert(FALSE, ("unexpected opr in Exp_Call"));
00333
00334 }
00335 Build_OP (top, return_address, True_TN,
00336 (opr == OPR_ICALL ? Gen_Enum_TN(ECV_bwh_dptk)
00337 : Gen_Enum_TN(ECV_bwh_sptk) ),
00338 Gen_Enum_TN(ECV_ph_many),
00339 Gen_Enum_TN(ECV_dh),
00340 target,
00341 ar_ec, ops);
00342 }