diff options
author | John van Groningen | 2011-11-15 15:18:22 +0000 |
---|---|---|
committer | John van Groningen | 2011-11-15 15:18:22 +0000 |
commit | 142921d821af2fec06f5b956ce8d769382b6ed52 (patch) | |
tree | 0ceb1b2f819831e76c3c99098b2855b8f75d4294 | |
parent | fix adding large immediate values (>32 bit) on 64 bit processors (diff) |
also optimize division by large constants (>32 bits) on 64 bit processors
-rw-r--r-- | cgaas.c | 154 | ||||
-rw-r--r-- | cgawas.c | 75 | ||||
-rw-r--r-- | cglin.c | 37 |
3 files changed, 170 insertions, 96 deletions
@@ -1397,6 +1397,30 @@ static void as_sar_i_r (int i,int reg) store_c (i); } +static void as_shl_i_r (int i,int reg) +{ + int reg_n; + + reg_n=reg_num (reg); + + store_c (0x48 | ((reg_n & 8)>>3)); + store_c (0301); + store_c (0300 | (4<<3) | (reg_n & 7)); + store_c (i); +} + +static void as_shr_i_r (int i,int reg) +{ + int reg_n; + + reg_n=reg_num (reg); + + store_c (0x48 | ((reg_n & 8)>>3)); + store_c (0301); + store_c (0300 | (5<<3) | (reg_n & 7)); + store_c (i); +} + static void as_xchg_d0_rn (int r_n) { store_c (0x48 | ((r_n & 8)>>3)); @@ -2624,15 +2648,16 @@ struct ms magic (int_64 d) static void as_div_rem_i_instruction (struct instruction *instruction,int compute_remainder) { - int s_reg1,s_reg2,s_reg3,i,sd_reg,i_reg,tmp_reg,abs_i; + int s_reg1,s_reg2,s_reg3,sd_reg,i_reg,tmp_reg; struct ms ms; + int_64 i,abs_i; if (instruction->instruction_parameters[0].parameter_type!=P_IMMEDIATE) internal_error_in_function ("as_div_rem_i_instruction"); - i=instruction->instruction_parameters[0].parameter_data.i; + i=instruction->instruction_parameters[0].parameter_data.imm; - if (! ((i>1 || (i<-1 && i!=0x80000000)))) + if (! ((i>1 || (i<-1 && i!=0x8000000000000000ll)))) internal_error_in_function ("as_div_rem_i_instruction"); abs_i=i>=0 ? i : -i; @@ -2697,17 +2722,9 @@ static void as_div_rem_i_instruction (struct instruction *instruction,int comput s_reg3=REGISTER_D0; } - if (i>=0){ - int s_reg2_n; - - s_reg2_n=reg_num (s_reg2); - - /* shr */ - store_c (0x48 | ((s_reg2_n & 8)>>3)); - store_c (0301); - store_c (0300 | (5<<3) | (s_reg2_n & 7)); - store_c (63); - } else + if (i>=0) + as_shr_i_r (63,s_reg2); + else as_sar_i_r (63,s_reg2); if (ms.s>0) @@ -2741,13 +2758,14 @@ static void as_div_rem_i_instruction (struct instruction *instruction,int comput as_r_r (0053,REGISTER_A1,s_reg2); /* sub */ /* s_reg2==sd_reg */ } } else { - int r,i2; + int r; + int_64 i2; as_r_r (0003,s_reg2,REGISTER_A1); /* add */ i2=i & (i-1); if ((i2 & (i2-1))==0){ - unsigned int n; + uint_64 n; int n_shifts; n=i; @@ -2759,13 +2777,8 @@ static void as_div_rem_i_instruction (struct instruction *instruction,int comput ++n_shifts; } - if (n_shifts>0){ - /* shl */ - store_c (0x48); - store_c (0301); - store_c (0300 | (4<<3) | reg_num (REGISTER_A1)); - store_c (n_shifts); - } + if (n_shifts>0) + as_shl_i_r (n_shifts,REGISTER_A1); as_r_r (0053,REGISTER_A1,s_reg3); /* sub */ @@ -2774,16 +2787,22 @@ static void as_div_rem_i_instruction (struct instruction *instruction,int comput } } else { /* imul */ - r=reg_num (REGISTER_A1); - store_c (0x48); - if ((signed char)i==i){ - store_c (0153); - store_c (0300 | (r<<3) | r); - store_c (i); + if (((int)i)==i){ + r=reg_num (REGISTER_A1); + store_c (0x48); + if ((signed char)i==i){ + store_c (0153); + store_c (0300 | (r<<3) | r); + store_c (i); + } else { + store_c (0151); + store_c (0300 | (r<<3) | r); + store_l (i); + } } else { - store_c (0151); - store_c (0300 | (r<<3) | r); - store_l (i); + as_move_i64_r (i,s_reg2); + + as_017_r_r (0257,s_reg2,REGISTER_A1); /* imul */ } as_r_r (0053,REGISTER_A1,s_reg3); /* sub */ @@ -2818,9 +2837,10 @@ static void as_div_instruction (struct instruction *instruction) d_reg=instruction->instruction_parameters[1].parameter_data.reg.r; if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){ - int i,log2i; + int_64 i; + int log2i; - i=instruction->instruction_parameters[0].parameter_data.i; + i=instruction->instruction_parameters[0].parameter_data.imm; if (! ((i & (i-1))==0 && i>0)){ internal_error_in_function ("as_div_instruction"); @@ -2843,15 +2863,20 @@ static void as_div_instruction (struct instruction *instruction) as_r_r (0053,REGISTER_O0,d_reg); /* sub */ } else { - as_sar_i_r (63,d_reg); + if (log2i<32){ + as_sar_i_r (63,d_reg); - /* and */ - if (d_reg==EAX){ - store_c (0x48); - store_c (045); - } else - as_r (0201,040,d_reg); - store_l ((1<<log2i)-1); + /* and */ + if (d_reg==EAX){ + store_c (0x48); + store_c (045); + } else + as_r (0201,040,d_reg); + store_l ((1<<log2i)-1); + } else { + as_sar_i_r (log2i-1,d_reg); + as_shr_i_r (64-log2i,d_reg); + } as_r_r (0003,REGISTER_O0,d_reg); /* add */ } @@ -2966,11 +2991,12 @@ static void as_rem_instruction (struct instruction *instruction) d_reg=instruction->instruction_parameters[1].parameter_data.reg.r; if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){ - int i,log2i; + int log2i; + int_64 i; - i=instruction->instruction_parameters[0].parameter_data.i; + i=instruction->instruction_parameters[0].parameter_data.imm; - if (i<0 && i!=0x80000000) + if (i<0 && i!=0x8000000000000000ll) i=-i; if (! ((i & (i-1))==0 && i>1)){ @@ -2999,25 +3025,31 @@ static void as_rem_instruction (struct instruction *instruction) as_r_r (0063,REGISTER_O0,d_reg); /* xor */ } else { - as_sar_i_r (31,REGISTER_O0); - - /* and */ - if (REGISTER_O0==EAX){ - store_c (0x48); - store_c (045); - } else - as_r (0201,040,REGISTER_O0); - store_l ((1<<log2i)-1); + as_sar_i_r (63,REGISTER_O0); as_r_r (0003,REGISTER_O0,d_reg); /* add */ - /* and */ - if (d_reg==EAX){ - store_c (0x48); - store_c (045); - } else - as_r (0201,040,d_reg); - store_l ((1<<log2i)-1); + if (log2i<32){ + /* and */ + if (REGISTER_O0==EAX){ + store_c (0x48); + store_c (045); + } else + as_r (0201,040,REGISTER_O0); + store_l ((1<<log2i)-1); + + /* and */ + if (d_reg==EAX){ + store_c (0x48); + store_c (045); + } else + as_r (0201,040,d_reg); + store_l ((1<<log2i)-1); + } else { + as_shr_i_r (64-log2i,REGISTER_O0); + as_shl_i_r (64-log2i,d_reg); + as_shr_i_r (64-log2i,d_reg); + } } as_r_r (0053,REGISTER_O0,d_reg); /* sub */ @@ -1981,18 +1981,19 @@ static void w_as_set_float_condition_instruction (struct instruction *instructio static void w_as_div_rem_i_instruction (struct instruction *instruction,int compute_remainder) { - int s_reg1,s_reg2,s_reg3,i,sd_reg,i_reg,tmp_reg,abs_i; + int s_reg1,s_reg2,s_reg3,sd_reg,i_reg,tmp_reg; struct ms ms; + int_64 i,abs_i; if (instruction->instruction_parameters[0].parameter_type!=P_IMMEDIATE) internal_error_in_function ("w_as_div_rem_i_instruction"); - - i=instruction->instruction_parameters[0].parameter_data.i; - if (! ((i>1 || (i<-1 && i!=0x80000000)))) + i=instruction->instruction_parameters[0].parameter_data.imm; + + if (! ((i>1 || (i<-1 && i!=0x8000000000000000ll)))) internal_error_in_function ("w_as_div_rem_i_instruction"); - abs_i=abs (i); + abs_i=i>=0 ? i : -i; if (compute_remainder) i=abs_i; @@ -2096,13 +2097,13 @@ static void w_as_div_rem_i_instruction (struct instruction *instruction,int comp } else w_as_opcode_register_register_newline (i>=0 ? "add" : "sub",REGISTER_A1,s_reg2); /* s_reg2==sd_reg */ } else { - int i2; + int_64 i2; w_as_opcode_register_register_newline ("add",s_reg2,REGISTER_A1); i2=i & (i-1); if ((i2 & (i2-1))==0){ - unsigned int n; + uint_64 n; int n_shifts; n=i; @@ -2125,8 +2126,15 @@ static void w_as_div_rem_i_instruction (struct instruction *instruction,int comp n_shifts=1; } } else { - w_as_opcode (intel_asm ? "imul" : "imulq"); - w_as_immediate_register_newline (i,REGISTER_A1); + if (((int)i)==i){ + w_as_opcode (intel_asm ? "imul" : "imull"); + w_as_immediate_register_newline (i,REGISTER_A1); + } else { + w_as_opcode_movl(); + w_as_immediate_register_newline (i,s_reg2); + + w_as_opcode_register_register_newline (intel_asm ? "imul" : "imull",s_reg2,REGISTER_A1); + } w_as_opcode_register_register_newline ("sub",REGISTER_A1,s_reg3); } @@ -2160,9 +2168,10 @@ static void w_as_div_instruction (struct instruction *instruction) d_reg=instruction->instruction_parameters[1].parameter_data.reg.r; if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){ - int i,log2i; + int_64 i; + int log2i; - i=instruction->instruction_parameters[0].parameter_data.i; + i=instruction->instruction_parameters[0].parameter_data.imm; if ((i & (i-1))==0 && i>0){ if (i==1) @@ -2182,11 +2191,19 @@ static void w_as_div_instruction (struct instruction *instruction) w_as_opcode_register_register_newline ("sub",REGISTER_O0,d_reg); } else { - w_as_opcode ("sar"); - w_as_immediate_register_newline (63,d_reg); + if (log2i<32){ + w_as_opcode ("sar"); + w_as_immediate_register_newline (63,d_reg); - w_as_opcode ("and"); - w_as_immediate_register_newline ((1<<log2i)-1,d_reg); + w_as_opcode ("and"); + w_as_immediate_register_newline ((1<<log2i)-1,d_reg); + } else { + w_as_opcode ("sar"); + w_as_immediate_register_newline (log2i-1,d_reg); + + w_as_opcode ("shr"); + w_as_immediate_register_newline (64-log2i,d_reg); + } w_as_opcode_register_register_newline ("add",REGISTER_O0,d_reg); } @@ -2319,11 +2336,12 @@ static void w_as_rem_instruction (struct instruction *instruction) d_reg=instruction->instruction_parameters[1].parameter_data.reg.r; if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){ - int i,log2i; + int log2i; + int_64 i; - i=instruction->instruction_parameters[0].parameter_data.i; + i=instruction->instruction_parameters[0].parameter_data.imm; - if (i<0 && i!=0x80000000) + if (i<0 && i!=0x8000000000000000ll) i=-i; if (! ((i & (i-1))==0 && i>1)){ @@ -2351,13 +2369,24 @@ static void w_as_rem_instruction (struct instruction *instruction) w_as_opcode ("sar"); w_as_immediate_register_newline (63,REGISTER_O0); - w_as_opcode ("and"); - w_as_immediate_register_newline ((1<<log2i)-1,REGISTER_O0); - w_as_opcode_register_register_newline ("add",REGISTER_O0,d_reg); - w_as_opcode ("and"); - w_as_immediate_register_newline ((1<<log2i)-1,d_reg); + if (log2i<32){ + w_as_opcode ("and"); + w_as_immediate_register_newline ((1<<log2i)-1,REGISTER_O0); + + w_as_opcode ("and"); + w_as_immediate_register_newline ((1<<log2i)-1,d_reg); + } else { + w_as_opcode ("shr"); + w_as_immediate_register_newline (64-log2i,REGISTER_O0); + + w_as_opcode ("shl"); + w_as_immediate_register_newline (64-log2i,d_reg); + + w_as_opcode ("shr"); + w_as_immediate_register_newline (64-log2i,d_reg); + } } w_as_opcode_register_register_newline ("sub",REGISTER_O0,d_reg); @@ -3943,27 +3943,36 @@ static void linearize_div_rem_operator (int i_instruction_code,INSTRUCTION_GRAPH linearize_graph (graph_2,&ad_2); linearize_graph (graph_1,&ad_1); } - +# ifdef I486 + in_preferred_alterable_register (&ad_2,REGISTER_D0); +# else in_alterable_data_register (&ad_2); - to_data_addressing_mode (&ad_1); - +# endif # ifdef I486 if (ad_1.ad_mode==P_IMMEDIATE){ if (i_instruction_code==IDIVU || i_instruction_code==IREMU){ in_data_register (&ad_1); instruction_ad_r (i_instruction_code,&ad_1,ad_2.ad_register); } else { - int i; + CleanInt i; i=ad_1.ad_offset; +# ifndef G_A64 if (i_instruction_code==IREM && i<0 && i!=0x80000000) +# else + if (i_instruction_code==IREM && i<0 && i!=0x8000000000000000ll) +# endif i=-i; - - if ((i & (i-1))==0 && (i_instruction_code==IREM ? i>1 : i>0)) + + if ((i & (i-1))==0 && (i_instruction_code==IREM ? i>1 : i>0)){ instruction_ad_r (i_instruction_code,&ad_1,ad_2.ad_register); - else if (i>1 || (i<-1 && i!=0x80000000)){ +# ifndef G_A64 + } else if (i>1 || (i<-1 && i!=0x80000000)){ +# else + } else if (i>1 || (i<-1 && i!=0x8000000000000000ll)){ +# endif int tmp_reg; - + tmp_reg=get_dregister(); instruction_ad_r_r (i_instruction_code==IDIV ? IDIVI : IREMI,&ad_1,ad_2.ad_register,tmp_reg); free_dregister (tmp_reg); @@ -3973,6 +3982,7 @@ static void linearize_div_rem_operator (int i_instruction_code,INSTRUCTION_GRAPH } } } else { + to_data_addressing_mode (&ad_1); if (ad_1.ad_mode==P_INDEXED) in_data_register (&ad_1); instruction_ad_r (i_instruction_code,&ad_1,ad_2.ad_register); @@ -3983,7 +3993,7 @@ static void linearize_div_rem_operator (int i_instruction_code,INSTRUCTION_GRAPH --*ad_2.ad_count_p; reg_1=ad_2.ad_register; - + if (graph->instruction_d_min_a_cost>0){ int areg; @@ -4071,10 +4081,14 @@ static void linearize_floordiv_mod_operator (int i_instruction_code,INSTRUCTION_ } { - int i; + CleanInt i; if (ad_1.ad_mode==P_IMMEDIATE && i_instruction_code==IFLOORDIV && +# ifndef G_A64 (i=ad_1.ad_offset, (i>1 || (i<-1 && i!=0x80000000)))) +# else + (i=ad_1.ad_offset, (i>1 || (i<-1 && i!=0x8000000000000000ll)))) +# endif { int tmp_reg2; @@ -6751,9 +6765,8 @@ static void linearize_dyadic_commutative_float_operator (int instruction_code,re } if (ad_1.ad_mode==P_F_REGISTER && *ad_1.ad_count_p==1 - /* added 17-3-1999: prefer result in lowest register number */ + /* prefer result in lowest register number */ && !(ad_2.ad_mode==P_F_REGISTER && *ad_2.ad_count_p==1 && ad_2.ad_register<ad_1.ad_register) - /* */ ){ reg_1=ad_1.ad_register; instruction_ad_fr (instruction_code,&ad_2,reg_1); |