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 #include "defs.h"
00032 #include "erglob.h"
00033 #include "ercg.h"
00034 #include "tracing.h"
00035 #include "config.h"
00036 #include "tn.h"
00037 #include "cg_flags.h"
00038 #include "op.h"
00039 #include "cgexp.h"
00040 #include "cgexp_internals.h"
00041 #include "whirl2ops.h"
00042 #include "config_opt.h"
00043
00044 void
00045 Initialize_Branch_Variants(void)
00046 {
00047
00048 }
00049
00050
00051
00052
00053 TOP
00054 Pick_Compare_TOP (VARIANT *variant, TN **src1, TN **src2, OPS *ops)
00055 {
00056 TOP cmp = TOP_UNDEFINED;
00057
00058 if (*src1 != NULL && TN_has_value(*src1)) {
00059
00060 TN *tmp = *src1;
00061 *src1 = *src2;
00062 *src2 = tmp;
00063 *variant = Invert_BR_Variant(*variant);
00064 }
00065
00066 if (*src2 != NULL && TN_is_zero(*src2)) {
00067 switch (*variant) {
00068 case V_BR_U8LT:
00069 case V_BR_U4LT:
00070 *variant = V_BR_NEVER; break;
00071 case V_BR_U8GE:
00072 case V_BR_U4GE:
00073 *variant = V_BR_ALWAYS; break;
00074
00075 case V_BR_U4LE:
00076 *variant = V_BR_U4EQ; break;
00077
00078 case V_BR_U8LE:
00079 *variant = V_BR_U8EQ; break;
00080 }
00081 }
00082
00083
00084
00085
00086 if (*src2 == NULL)
00087 return TOP_UNDEFINED;
00088
00089
00090 switch (*variant) {
00091 case V_BR_I4EQ: cmp = TOP_setp_eq_s32; break;
00092 case V_BR_I4NE: cmp = TOP_setp_ne_s32; break;
00093 case V_BR_I4GT: cmp = TOP_setp_gt_s32; break;
00094 case V_BR_I4GE: cmp = TOP_setp_ge_s32; break;
00095 case V_BR_I4LT: cmp = TOP_setp_lt_s32; break;
00096 case V_BR_I4LE: cmp = TOP_setp_le_s32; break;
00097 case V_BR_U4EQ: cmp = TOP_setp_eq_u32; break;
00098 case V_BR_U4NE: cmp = TOP_setp_ne_u32; break;
00099 case V_BR_U4GT: cmp = TOP_setp_gt_u32; break;
00100 case V_BR_U4GE: cmp = TOP_setp_ge_u32; break;
00101 case V_BR_U4LT: cmp = TOP_setp_lt_u32; break;
00102 case V_BR_U4LE: cmp = TOP_setp_le_u32; break;
00103 case V_BR_I8EQ: cmp = TOP_setp_eq_s64; break;
00104 case V_BR_I8NE: cmp = TOP_setp_ne_s64; break;
00105 case V_BR_I8GT: cmp = TOP_setp_gt_s64; break;
00106 case V_BR_I8GE: cmp = TOP_setp_ge_s64; break;
00107 case V_BR_I8LT: cmp = TOP_setp_lt_s64; break;
00108 case V_BR_I8LE: cmp = TOP_setp_le_s64; break;
00109 case V_BR_U8EQ: cmp = TOP_setp_eq_u64; break;
00110 case V_BR_U8NE: cmp = TOP_setp_ne_u64; break;
00111 case V_BR_U8GT: cmp = TOP_setp_gt_u64; break;
00112 case V_BR_U8GE: cmp = TOP_setp_ge_u64; break;
00113 case V_BR_U8LT: cmp = TOP_setp_lt_u64; break;
00114 case V_BR_U8LE: cmp = TOP_setp_le_u64; break;
00115 case V_BR_FEQ: cmp = TOP_setp_eq_f32; break;
00116
00117 case V_BR_FNE: cmp = TOP_setp_neu_f32; break;
00118 case V_BR_FGT: cmp = TOP_setp_gt_f32; break;
00119 case V_BR_FGE: cmp = TOP_setp_ge_f32; break;
00120 case V_BR_FLT: cmp = TOP_setp_lt_f32; break;
00121 case V_BR_FLE: cmp = TOP_setp_le_f32; break;
00122 case V_BR_DEQ: cmp = TOP_setp_eq_f64; break;
00123 case V_BR_DNE: cmp = TOP_setp_neu_f64; break;
00124 case V_BR_DGT: cmp = TOP_setp_gt_f64; break;
00125 case V_BR_DGE: cmp = TOP_setp_ge_f64; break;
00126 case V_BR_DLT: cmp = TOP_setp_lt_f64; break;
00127 case V_BR_DLE: cmp = TOP_setp_le_f64; break;
00128 }
00129 return cmp;
00130 }
00131
00132
00133
00134 static void Expand_Ordered_Branch( TOP cmp_opcode, TN* src1, TN* src2,
00135 TOP jmp_opcode, TN* targ, OPS* ops )
00136 {
00137 FmtAssert( false, ("NYI") );
00138
00139 return;
00140 }
00141
00142 void Expand_Branch ( TN *targ, TN *src1, TN *src2, VARIANT variant, OPS *ops)
00143 {
00144 BOOL false_br = V_false_br(variant);
00145 VARIANT cond = V_br_condition(variant);
00146 TN *pred;
00147
00148
00149 if ( Trace_Exp2 ) {
00150 fprintf ( TFile, "<cgexp> Translating %s branch:\n",
00151 (false_br ? "false" : "true") );
00152 }
00153
00154 FmtAssert( cond <= V_BR_LAST, ("unexpected variant in Expand_Branch"));
00155 FmtAssert( cond != V_BR_NONE, ("BR_NONE variant in Expand_Branch"));
00156
00157 const TOP cmp = Pick_Compare_TOP (&cond, &src1, &src2, ops);
00158 if ( Trace_Exp2 && cond != variant) {
00159 fprintf ( TFile, "<cgexp> transformed branch cond = %llx\n", cond);
00160 }
00161
00162 switch (cond) {
00163 case V_BR_ALWAYS:
00164 case V_BR_NEVER:
00165 Is_True(cmp == TOP_UNDEFINED,
00166 ("unexpected compare op for %s", BR_Variant_Name(cond)));
00167 if ((cond == V_BR_ALWAYS) ^ false_br) {
00168
00169 Build_OP (TOP_bra_uni, targ, ops);
00170 }
00171 break;
00172 case V_BR_PEQ:
00173 case V_BR_PNE:
00174 pred = Build_RCLASS_TN (ISA_REGISTER_CLASS_predicate);
00175 Build_OP (TOP_xor_pred, pred, src1, src2, ops);
00176
00177 if ((cond == V_BR_PEQ && false_br) || (cond == V_BR_PNE && !false_br))
00178 Build_OP (TOP_bra_p, pred, targ, ops);
00179 else
00180 Build_OP (TOP_bra_np, pred, targ, ops);
00181 break;
00182 case V_BR_P_TRUE:
00183 if (false_br)
00184 Build_OP (TOP_bra_np, src1, targ, ops);
00185 else
00186 Build_OP (TOP_bra_p, src1, targ, ops);
00187 break;
00188 default:
00189 {
00190 Is_True(cmp != TOP_UNDEFINED, ("no topcode for compare"));
00191
00192 if( TN_has_value(src1) ){
00193 src1 = Expand_Mtype_Immediate_Into_Register (src1, Mtype_Of_TN(src2), ops);
00194 }
00195 if( TN_has_value(src2) ){
00196 src2 = Expand_Mtype_Immediate_Into_Register (src2, Mtype_Of_TN(src1), ops);
00197 }
00198
00199
00200 pred = Build_RCLASS_TN (ISA_REGISTER_CLASS_predicate);
00201 Build_OP (cmp, pred, src1, src2, ops);
00202 if (false_br)
00203 Build_OP (TOP_bra_np, pred, targ, ops);
00204 else
00205 Build_OP (TOP_bra_p, pred, targ, ops);
00206
00207 }
00208
00209 break;
00210 }
00211 }
00212
00213 void Exp_Indirect_Branch (TN *targ_reg, OPS *ops)
00214 {
00215 FmtAssert(FALSE, ("NYI"));
00216 }
00217
00218 void Exp_Local_Jump(BB *bb, INT64 offset, OPS *ops)
00219 {
00220 FmtAssert(FALSE, ("NYI: Exp_Local_Jump"));
00221 }
00222
00223 void Exp_Return (TN *return_address, OPS *ops)
00224 {
00225 if (ST_in_global_mem(Get_Current_PU_ST())) {
00226 Build_OP (TOP_exit, ops);
00227 } else {
00228 Build_OP (TOP_ret, ops);
00229 }
00230 }
00231
00232 void Exp_Call( OPERATOR opr, TN *return_address, TN *target, OPS *ops )
00233 {
00234 Build_OP (TOP_call, target, ops);
00235 }