summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn van Groningen2003-05-13 13:32:28 +0000
committerJohn van Groningen2003-05-13 13:32:28 +0000
commitd17bd94108dcdf97a1caa452c506aae1e2eb0a39 (patch)
tree1f4decf38bce9f681d08d9d660da47229b9d5a99
parentoptimize division and remainder of power of 2 (diff)
optimize remainder of power of 2 for ia32
-rw-r--r--cgias.c65
-rw-r--r--cgiwas.c92
-rw-r--r--cglin.c2
3 files changed, 130 insertions, 29 deletions
diff --git a/cgias.c b/cgias.c
index 456c37d..c441505 100644
--- a/cgias.c
+++ b/cgias.c
@@ -1954,6 +1954,7 @@ static void as_div_instruction (struct instruction *instruction)
as_r_r (0003,REGISTER_O0,d_reg); /* add */
}
+ /* sar */
store_c (0301);
store_c (0300 | (7<<3) | reg_num (d_reg));
store_c (log2i);
@@ -2056,12 +2057,72 @@ static void as_div_instruction (struct instruction *instruction)
}
}
-static void as_mod_instruction (struct instruction *instruction)
+static void as_rem_instruction (struct instruction *instruction)
{
int d_reg;
d_reg=instruction->instruction_parameters[1].parameter_data.reg.r;
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ int i,log2i;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+
+ if (! ((i & (i-1))==0 && i>1)){
+ internal_error_in_function ("as_rem_instruction");
+ return;
+ }
+
+ log2i=0;
+ while (i>1){
+ i=i>>1;
+ ++log2i;
+ }
+
+ as_move_r_r (d_reg,REGISTER_O0);
+
+ if (log2i==1){
+ /* and */
+ if (d_reg==EAX)
+ store_c (045);
+ else
+ as_r (0201,040,d_reg);
+ store_l (1);
+
+ /* sar */
+ store_c (0301);
+ store_c (0300 | (7<<3) | reg_num (REGISTER_O0));
+ store_c (31);
+
+ as_r_r (0063,REGISTER_O0,d_reg); /* xor */
+ } else {
+ /* sar */
+ store_c (0301);
+ store_c (0300 | (7<<3) | reg_num (REGISTER_O0));
+ store_c (31);
+
+ /* and */
+ if (REGISTER_O0==EAX)
+ store_c (045);
+ else
+ as_r (0201,040,REGISTER_O0);
+ store_l ((1<<log2i)-1);
+
+ as_r_r (0003,REGISTER_O0,d_reg); /* add */
+
+ /* and */
+ if (d_reg==EAX)
+ store_c (045);
+ else
+ as_r (0201,040,d_reg);
+ store_l ((1<<log2i)-1);
+ }
+
+ as_r_r (0053,REGISTER_O0,d_reg); /* sub */
+
+ return;
+ }
+
switch (d_reg){
case REGISTER_D0:
as_move_r_r (REGISTER_A1,REGISTER_O0);
@@ -3530,7 +3591,7 @@ static void as_instructions (struct instruction *instruction)
as_div_instruction (instruction);
break;
case IMOD:
- as_mod_instruction (instruction);
+ as_rem_instruction (instruction);
break;
case IAND:
as_logic_instruction (instruction,0043,040,045);
diff --git a/cgiwas.c b/cgiwas.c
index 24cb953..2075c32 100644
--- a/cgiwas.c
+++ b/cgiwas.c
@@ -733,6 +733,18 @@ static void w_as_register_register_newline (int reg1,int reg2)
w_as_newline();
}
+static void w_as_immediate_register_newline (int i,int reg)
+{
+ if (!intel_asm){
+ w_as_immediate (i);
+ w_as_comma_register (reg);
+ } else {
+ w_as_register_comma (reg);
+ w_as_immediate (i);
+ }
+ w_as_newline();
+}
+
static void w_as_move_instruction (struct instruction *instruction,int size_flag)
{
switch (instruction->instruction_parameters[1].parameter_type){
@@ -1531,43 +1543,23 @@ static void w_as_div_instruction (struct instruction *instruction)
if (log2i==1){
w_as_opcode ("sar");
- if (intel_asm)
- w_as_register_comma (REGISTER_O0);
- w_as_immediate (31);
- if (!intel_asm)
- w_as_comma_register (REGISTER_O0);
- w_as_newline();
+ w_as_immediate_register_newline (31,REGISTER_O0);
w_as_opcode ("sub");
w_as_register_register_newline (REGISTER_O0,d_reg);
} else {
w_as_opcode ("sar");
- if (intel_asm)
- w_as_register_comma (d_reg);
- w_as_immediate (31);
- if (!intel_asm)
- w_as_comma_register (d_reg);
- w_as_newline();
+ w_as_immediate_register_newline (31,d_reg);
w_as_opcode ("and");
- if (intel_asm)
- w_as_register_comma (d_reg);
- w_as_immediate ((1<<log2i)-1);
- if (!intel_asm)
- w_as_comma_register (d_reg);
- w_as_newline();
+ w_as_immediate_register_newline ((1<<log2i)-1,d_reg);
w_as_opcode ("add");
w_as_register_register_newline (REGISTER_O0,d_reg);
}
w_as_opcode ("sar");
- if (intel_asm)
- w_as_register_comma (d_reg);
- w_as_immediate (log2i);
- if (!intel_asm)
- w_as_comma_register (d_reg);
- w_as_newline();
+ w_as_immediate_register_newline (log2i,d_reg);
return;
}
@@ -1693,12 +1685,60 @@ static void w_as_div_instruction (struct instruction *instruction)
}
}
-static void w_as_mod_instruction (struct instruction *instruction)
+static void w_as_rem_instruction (struct instruction *instruction)
{
int d_reg;
d_reg=instruction->instruction_parameters[1].parameter_data.reg.r;
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ int i,log2i;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+
+ if (! ((i & (i-1))==0 && i>1)){
+ internal_error_in_function ("w_as_rem_instruction");
+ return;
+ }
+
+ log2i=0;
+ while (i>1){
+ i=i>>1;
+ ++log2i;
+ }
+
+ w_as_opcode_movl();
+ w_as_register_register_newline (d_reg,REGISTER_O0);
+
+ if (log2i==1){
+ w_as_opcode ("and");
+ w_as_immediate_register_newline (1,d_reg);
+
+ w_as_opcode ("sar");
+ w_as_immediate_register_newline (31,REGISTER_O0);
+
+ w_as_opcode ("xor");
+ w_as_register_register_newline (REGISTER_O0,d_reg);
+ } else {
+ w_as_opcode ("sar");
+ w_as_immediate_register_newline (31,REGISTER_O0);
+
+ w_as_opcode ("and");
+ w_as_immediate_register_newline ((1<<log2i)-1,REGISTER_O0);
+
+ w_as_opcode ("add");
+ w_as_register_register_newline (REGISTER_O0,d_reg);
+
+ w_as_opcode ("and");
+ w_as_immediate_register_newline ((1<<log2i)-1,d_reg);
+ }
+
+ w_as_opcode ("sub");
+ w_as_register_register_newline (REGISTER_O0,d_reg);
+
+ return;
+ }
+
switch (d_reg){
case REGISTER_D0:
w_as_opcode_movl();
@@ -2724,7 +2764,7 @@ static void w_as_instructions (register struct instruction *instruction)
w_as_div_instruction (instruction);
break;
case IMOD:
- w_as_mod_instruction (instruction);
+ w_as_rem_instruction (instruction);
break;
case IAND:
w_as_dyadic_instruction (instruction,intel_asm ? "and" : "andl");
diff --git a/cglin.c b/cglin.c
index 17ed82d..5f7092e 100644
--- a/cglin.c
+++ b/cglin.c
@@ -3384,7 +3384,7 @@ static void linearize_div_mod_operator (int i_instruction_code,INSTRUCTION_GRAPH
to_data_addressing_mode (&ad_1);
# ifdef I486
- if ((ad_1.ad_mode==P_IMMEDIATE && !((ad_1.ad_offset & (ad_1.ad_offset-1))==0 && ad_1.ad_offset>0)) || ad_1.ad_mode==P_INDEXED)
+ if ((ad_1.ad_mode==P_IMMEDIATE && !((ad_1.ad_offset & (ad_1.ad_offset-1))==0 && (i_instruction_code==IMOD ? ad_1.ad_offset>1 : ad_1.ad_offset>0))) || ad_1.ad_mode==P_INDEXED)
in_data_register (&ad_1);
# endif