summaryrefslogtreecommitdiff
path: root/cgias.c
diff options
context:
space:
mode:
authorJohn van Groningen2006-03-24 11:26:30 +0000
committerJohn van Groningen2006-03-24 11:26:30 +0000
commit9dac5f646c025a82c2dfb841db019fc8e1e77945 (patch)
treec98a328e09befbe34b8d338333fc9b678860c71e /cgias.c
parentoptimize shift n bitand 31 or 64 for IA32 and AMD64 (diff)
remove use of scratch register on IA32 for shift instructions (by adding
instruction with extra register), IScc, IFScc, IFBcc (by adding IFCcc instructions with extra register), ICMPW (not used anymore) prevent generating FLD and FSTP instructions between FCOMP and FNSTSW instruction
Diffstat (limited to 'cgias.c')
-rw-r--r--cgias.c289
1 files changed, 182 insertions, 107 deletions
diff --git a/cgias.c b/cgias.c
index 725595a..38d6c83 100644
--- a/cgias.c
+++ b/cgias.c
@@ -1676,14 +1676,60 @@ static void as_cmp_i_parameter (int i,struct parameter *parameter)
}
}
-static void as_cmp_instruction (struct instruction *instruction,int size_flag)
+static void as_cmp_instruction (struct instruction *instruction)
{
struct parameter parameter_0,parameter_1;
parameter_0=instruction->instruction_parameters[0];
parameter_1=instruction->instruction_parameters[1];
- if (parameter_1.parameter_type==P_INDIRECT && size_flag!=SIZE_LONG){
+ switch (parameter_0.parameter_type){
+ case P_DESCRIPTOR_NUMBER:
+ switch (parameter_1.parameter_type){
+ case P_REGISTER:
+ as_d_r2 (0201,0070,0075,parameter_0.parameter_data.l,parameter_0.parameter_offset,
+ parameter_1.parameter_data.reg.r);
+ return;
+ case P_INDIRECT:
+ as_d_id (0201,0070,parameter_0.parameter_data.l,parameter_0.parameter_offset,
+ parameter_1.parameter_offset,parameter_1.parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ as_d_x (0201,0070,parameter_0.parameter_data.l,parameter_0.parameter_offset,
+ parameter_1.parameter_offset,parameter_1.parameter_data.ir);
+ return;
+ }
+ break;
+ case P_IMMEDIATE:
+ as_cmp_i_parameter (parameter_0.parameter_data.i,&parameter_1);
+ return;
+ }
+
+ if (parameter_1.parameter_type==P_REGISTER)
+ switch (parameter_0.parameter_type){
+ case P_REGISTER:
+ as_r_r (0073,parameter_0.parameter_data.reg.r,parameter_1.parameter_data.reg.r);
+ return;
+ case P_INDIRECT:
+ as_id_r (0073,parameter_0.parameter_offset,parameter_0.parameter_data.reg.r,parameter_1.parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ as_x_r (0073,parameter_0.parameter_offset,parameter_0.parameter_data.ir,parameter_1.parameter_data.reg.r);
+ return;
+ }
+
+ internal_error_in_function ("as_cmp_instruction");
+}
+
+#if 0
+static void as_cmpw_instruction (struct instruction *instruction)
+{
+ struct parameter parameter_0,parameter_1;
+
+ parameter_0=instruction->instruction_parameters[0];
+ parameter_1=instruction->instruction_parameters[1];
+
+ if (parameter_1.parameter_type==P_INDIRECT){
/* movswl */
store_c (0017);
as_id_r (0277,instruction->instruction_parameters[1].parameter_offset,
@@ -1714,15 +1760,13 @@ static void as_cmp_instruction (struct instruction *instruction,int size_flag)
as_cmp_i_parameter (parameter_0.parameter_data.i,&parameter_1);
return;
case P_INDIRECT:
- if (size_flag==SIZE_WORD){
- /* movswl */
- store_c (0017);
- as_id_r (0277,instruction->instruction_parameters[0].parameter_offset,
- instruction->instruction_parameters[0].parameter_data.reg.r,REGISTER_O0);
-
- parameter_0.parameter_type=P_REGISTER;
- parameter_0.parameter_data.reg.r=REGISTER_O0;
- }
+ /* movswl */
+ store_c (0017);
+ as_id_r (0277,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,REGISTER_O0);
+
+ parameter_0.parameter_type=P_REGISTER;
+ parameter_0.parameter_data.reg.r=REGISTER_O0;
}
if (parameter_1.parameter_type==P_REGISTER)
@@ -1738,8 +1782,9 @@ static void as_cmp_instruction (struct instruction *instruction,int size_flag)
return;
}
- internal_error_in_function ("as_cmp_instruction");
+ internal_error_in_function ("as_cmpw_instruction");
}
+#endif
void store_label_in_data_section (LABEL *label)
{
@@ -1894,6 +1939,47 @@ static void as_shift_instruction (struct instruction *instruction,int shift_code
}
}
+static void as_shift_s_instruction (struct instruction *instruction,int shift_code)
+{
+ if (instruction->instruction_parameters[0].parameter_type!=P_REGISTER){
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ store_c (0301);
+ store_c (0300 | (shift_code<<3) | reg_num (instruction->instruction_parameters[1].parameter_data.reg.r));
+ store_c (instruction->instruction_parameters[0].parameter_data.i & 31);
+ } else
+ internal_error_in_function ("as_shift_s_instruction");
+ } else {
+ int r0,r1;
+
+ r0=instruction->instruction_parameters[0].parameter_data.reg.r;
+ r1=instruction->instruction_parameters[1].parameter_data.reg.r;
+ if (r0==REGISTER_A0){
+ store_c (0323);
+ store_c (0300 | (shift_code<<3) | reg_num (r1));
+ } else {
+ int scratch_register;
+
+ scratch_register=instruction->instruction_parameters[2].parameter_data.reg.r;
+ if (scratch_register==REGISTER_A0){
+ as_move_r_r (r0,REGISTER_A0);
+
+ store_c (0323);
+ store_c (0300 | (shift_code<<3) | reg_num (r1));
+ } else {
+ as_move_r_r (REGISTER_A0,scratch_register);
+ as_move_r_r (r0,REGISTER_A0);
+
+ if (r1==REGISTER_A0)
+ r1=scratch_register;
+ store_c (0323);
+ store_c (0300 | (shift_code<<3) | reg_num (r1));
+
+ as_move_r_r (scratch_register,REGISTER_A0);
+ }
+ }
+ }
+}
+
static void as_logic_instruction (struct instruction *instruction,int code1,int code2,int code3)
{
switch (instruction->instruction_parameters[0].parameter_type){
@@ -2705,68 +2791,33 @@ static void as_divdu_instruction (struct instruction *instruction)
static void as_set_condition_instruction (struct instruction *instruction,int condition_code)
{
int r;
+ unsigned int rn;
r=instruction->instruction_parameters[0].parameter_data.reg.r;
-
- if (r==REGISTER_A3 || r==REGISTER_A4){
-#if 1
- as_move_r_r (REGISTER_D0,REGISTER_O0);
-#else
- as_move_r_r (REGISTER_D0,r);
-#endif
+ rn=reg_num (r);
+
+ if (rn<4u){
store_c (0017);
store_c (0220 | condition_code);
- store_c (0300 | 0); /* %al */
+ store_c (0300 | rn);
-#if 1
/* movzbl */
store_c (017);
store_c (0266);
- store_c (0300 | (reg_num (r)<<3) | 0 /* %al */);
-
- as_move_r_r (REGISTER_O0,REGISTER_D0);
-#else
- /* and $1,D0 */
- store_c (0203);
- store_c (0340);
- store_c (1);
-
- store_c (0x90+reg_num (r)); /* xchg r,D0 */
-#endif
+ store_c (0300 | (rn<<3) | rn);
} else {
- int rn;
-
- switch (r){
- case REGISTER_D0:
- rn=0;
- break;
- case REGISTER_D1:
- rn=3;
- break;
- case REGISTER_A0:
- rn=1;
- break;
- case REGISTER_A1:
- rn=2;
- break;
- }
+ as_move_r_r (REGISTER_D0,r);
store_c (0017);
store_c (0220 | condition_code);
+ store_c (0300 | 0); /* %al */
- store_c (0300 | rn);
-
-#if 1
/* movzbl */
store_c (017);
store_c (0266);
- store_c (0300 | (reg_num (r)<<3) | rn);
-#else
- /* and $1,reg */
- store_c (0203);
- store_c (0340+rn);
- store_c (1);
-#endif
+ store_c (0300 | (reg_num (REGISTER_D0)<<3) | 0 /* %al */);
+
+ store_c (0x90+rn); /* xchg r,D0 */
}
}
@@ -2972,8 +3023,11 @@ struct instruction *find_next_fp_instruction (struct instruction *instruction)
switch (instruction->instruction_icode){
case IFADD: case IFSUB: case IFMUL: case IFDIV:
case IFMOVEL: case IFCMP: case IFNEG: case IFABS: case IFTST: case IFREM:
+#if 0
case IFBEQ: case IFBGE: case IFBGT: case IFBLE: case IFBLT: case IFBNE:
+#endif
case IFSEQ: case IFSGE: case IFSGT: case IFSLE: case IFSLT: case IFSNE:
+ case IFCEQ: case IFCGE: case IFCGT: case IFCLE: case IFCLT: case IFCNE:
case IFCOS: case IFSIN: case IFSQRT: case IFTAN:
case IFEXG:
case IWORD:
@@ -3673,14 +3727,8 @@ static void as_monadic_float_instruction (struct instruction *instruction,int co
#endif
}
-static void as_float_branch_instruction (struct instruction *instruction,int n)
+static void as_test_floating_point_condition_code (int n)
{
- int r;
-
- r=instruction->instruction_parameters[0].parameter_data.reg.r;
-
- as_r_r (0213,REGISTER_D0,REGISTER_O0);
-
store_c (0xdf);
store_c (0xe0); /* fnstsw %ax */
@@ -3721,6 +3769,18 @@ static void as_float_branch_instruction (struct instruction *instruction,int n)
store_c (5); /* andb $5,%ah */
break;
}
+}
+
+#if 0
+static void as_float_branch_instruction (struct instruction *instruction,int n)
+{
+ int r;
+
+ r=instruction->instruction_parameters[0].parameter_data.reg.r;
+
+ as_r_r (0213,REGISTER_D0,REGISTER_O0);
+
+ as_test_floating_point_condition_code (n);
as_r_r (0213,REGISTER_O0,REGISTER_D0);
@@ -3739,6 +3799,7 @@ static void as_float_branch_instruction (struct instruction *instruction,int n)
break;
}
}
+#endif
static void as_set_float_condition_instruction (struct instruction *instruction,int n)
{
@@ -3749,46 +3810,7 @@ static void as_set_float_condition_instruction (struct instruction *instruction,
if (r!=REGISTER_D0)
as_r_r (0213,REGISTER_D0,r);
- store_c (0xdf);
- store_c (0xe0); /* fnstsw %ax */
-
- store_c (0x80);
- store_c (0xe4); /* andb $i,%ah */
-
- switch (n){
- case 0:
- store_c (68); /* andb $68,%ah */
- store_c (0x80);
- store_c (0xf4);
- store_c (64); /* xorb $64,%ah */
- break;
- case 1:
- store_c (69); /* andb $69,%ah */
- store_c (0x80);
- store_c (0xfc);
- store_c (1); /* cmpb $1,%ah */
- break;
- case 2:
- store_c (69); /* andb $69,%ah */
- break;
- case 3:
- store_c (69); /* andb $69,%ah */
- store_c (0x80);
- store_c (0xfc);
- store_c (64); /* cmpb $64,%ah */
- break;
- case 4:
- store_c (69); /* andb $69,%ah */
- store_c (0xfe);
- store_c (0xcc); /* decb %ah */
- store_c (0x80);
- store_c (0xfc);
- store_c (64); /* cmpb $64,%ah */
- break;
- case 5:
- store_c (5); /* andb $5,%ah */
- break;
- }
+ as_test_floating_point_condition_code (n);
store_c (0x0f);
switch (n){
@@ -3807,15 +3829,37 @@ static void as_set_float_condition_instruction (struct instruction *instruction,
}
store_c (0xc0);
+#if 1
+ /* movzbl */
+ store_c (017);
+ store_c (0266);
+ store_c (0300 | (reg_num (REGISTER_D0)<<3) | 0 /* %al */);
+#else
/* and $1,D0 */
store_c (0203);
store_c (0340);
store_c (1);
+#endif
if (r!=REGISTER_D0)
store_c (0x90+reg_num (r)); /* xchg r,D0 */
}
+static void as_convert_float_condition_instruction (struct instruction *instruction,int n)
+{
+ int r;
+
+ r=instruction->instruction_parameters[0].parameter_data.reg.r;
+
+ if (r!=REGISTER_D0)
+ as_r_r (0213,REGISTER_D0,r);
+
+ as_test_floating_point_condition_code (n);
+
+ if (r!=REGISTER_D0)
+ as_r_r (0213,r,REGISTER_D0);
+}
+
#ifdef FP_STACK_OPTIMIZATIONS
static void as_fexg (struct instruction *instruction)
{
@@ -4051,7 +4095,7 @@ static void as_instructions (struct instruction *instruction)
as_sub_instruction (instruction);
break;
case ICMP:
- as_cmp_instruction (instruction,SIZE_LONG);
+ as_cmp_instruction (instruction);
break;
case IJMP:
as_jmp_instruction (instruction);
@@ -4115,6 +4159,15 @@ static void as_instructions (struct instruction *instruction)
case IASR:
as_shift_instruction (instruction,7);
break;
+ case ILSL_S:
+ as_shift_s_instruction (instruction,4);
+ break;
+ case ILSR_S:
+ as_shift_s_instruction (instruction,5);
+ break;
+ case IASR_S:
+ as_shift_s_instruction (instruction,7);
+ break;
case IMUL:
as_mul_instruction (instruction);
break;
@@ -4181,9 +4234,11 @@ static void as_instructions (struct instruction *instruction)
case ISNO:
as_set_condition_instruction (instruction,1);
break;
+#if 0
case ICMPW:
- as_cmp_instruction (instruction,SIZE_WORD);
+ as_cmpw_instruction (instruction);
break;
+#endif
case ITST:
as_tst_instruction (instruction);
break;
@@ -4248,6 +4303,7 @@ static void as_instructions (struct instruction *instruction)
case IFMUL:
as_dyadic_float_instruction (instruction,1,0xc8,0xc8); /*fmull fmul fmulp*/
break;
+#if 0
case IFBEQ:
as_float_branch_instruction (instruction,0);
break;
@@ -4266,6 +4322,7 @@ static void as_instructions (struct instruction *instruction)
case IFBNE:
as_float_branch_instruction (instruction,3);
break;
+#endif
case IFMOVEL:
as_fmovel_instruction (instruction);
break;
@@ -4302,6 +4359,24 @@ static void as_instructions (struct instruction *instruction)
case IFSNE:
as_set_float_condition_instruction (instruction,3);
break;
+ case IFCEQ:
+ as_convert_float_condition_instruction (instruction,0);
+ break;
+ case IFCGE:
+ as_convert_float_condition_instruction (instruction,5);
+ break;
+ case IFCGT:
+ as_convert_float_condition_instruction (instruction,2);
+ break;
+ case IFCLE:
+ as_convert_float_condition_instruction (instruction,4);
+ break;
+ case IFCLT:
+ as_convert_float_condition_instruction (instruction,1);
+ break;
+ case IFCNE:
+ as_convert_float_condition_instruction (instruction,3);
+ break;
case IRTSI:
as_rtsi_instruction (instruction);
break;