summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn van Groningen2011-11-15 15:18:22 +0000
committerJohn van Groningen2011-11-15 15:18:22 +0000
commit142921d821af2fec06f5b956ce8d769382b6ed52 (patch)
tree0ceb1b2f819831e76c3c99098b2855b8f75d4294
parentfix 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.c154
-rw-r--r--cgawas.c75
-rw-r--r--cglin.c37
3 files changed, 170 insertions, 96 deletions
diff --git a/cgaas.c b/cgaas.c
index 0e95b8f..81796a4 100644
--- a/cgaas.c
+++ b/cgaas.c
@@ -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 */
diff --git a/cgawas.c b/cgawas.c
index f1522d6..3254c40 100644
--- a/cgawas.c
+++ b/cgawas.c
@@ -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);
diff --git a/cglin.c b/cglin.c
index 5f04c28..bd0a176 100644
--- a/cglin.c
+++ b/cglin.c
@@ -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);