summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgcalc.c16
-rw-r--r--cgcode.c161
-rw-r--r--cgcodep.h4
-rw-r--r--cgconst.h1
-rw-r--r--cgiconst.h3
-rw-r--r--cginput.c5
-rw-r--r--cglin.c179
-rw-r--r--cgopt.c29
8 files changed, 378 insertions, 20 deletions
diff --git a/cgcalc.c b/cgcalc.c
index bb9faf7..34a9128 100644
--- a/cgcalc.c
+++ b/cgcalc.c
@@ -2411,6 +2411,10 @@ void calculate_graph_register_uses (INSTRUCTION_GRAPH graph)
#if defined (I486) || defined (G_POWER)
case GDIVU:
#endif
+#ifdef I486
+ case GFLOORDIV:
+ case GMOD:
+#endif
calculate_dyadic_non_commutative_data_operator (graph);
return;
case GREM:
@@ -2730,6 +2734,10 @@ void count_graph (INSTRUCTION_GRAPH graph)
#if defined (I486) || defined (G_POWER)
case GDIVU:
#endif
+#ifdef I486
+ case GFLOORDIV:
+ case GMOD:
+#endif
case GFADD:
case GFCMP_EQ:
case GFCMP_GT:
@@ -2942,6 +2950,10 @@ void mark_graph_2 (register INSTRUCTION_GRAPH graph)
#if defined (I486) || defined (G_POWER)
case GDIVU:
#endif
+#ifdef I486
+ case GFLOORDIV:
+ case GMOD:
+#endif
case GFADD:
case GFCMP_EQ:
case GFCMP_GT:
@@ -3170,6 +3182,10 @@ void mark_graph_1 (register INSTRUCTION_GRAPH graph)
#if defined (I486) || defined (G_POWER)
case GDIVU:
#endif
+#ifdef I486
+ case GFLOORDIV:
+ case GMOD:
+#endif
case GFADD:
case GFCMP_EQ:
case GFCMP_GT:
diff --git a/cgcode.c b/cgcode.c
index 6773d70..70a2311 100644
--- a/cgcode.c
+++ b/cgcode.c
@@ -254,7 +254,9 @@ int no_time_profiling;
#define g_fdiv(g1,g2) g_instruction_2(GFDIV,(g1),(g2))
#define g_fitor(g1) g_instruction_1(GFITOR,(g1))
-
+#ifdef I486
+# define g_floordiv(g1,g2) g_instruction_2(GFLOORDIV,(g1),(g2))
+#endif
#define g_fmul(g1,g2) g_instruction_2(GFMUL,(g1),(g2))
#define g_frem(g1,g2) g_instruction_2(GFREM,(g1),(g2))
#define g_frtoi(g1) g_instruction_1(GFRTOI,(g1))
@@ -263,6 +265,7 @@ int no_time_profiling;
#define g_lsr(g1,g2) g_instruction_2(GLSR,(g1),(g2))
#define g_rem(g1,g2) g_instruction_2(GREM,(g1),(g2))
#ifdef I486
+# define g_mod(g1,g2) g_instruction_2(GMOD,(g1),(g2))
# define g_remu(g1,g2) g_instruction_2(GREMU,(g1),(g2))
#endif
#define g_mul(g1,g2) g_instruction_2(GMUL,(g1),(g2))
@@ -3550,6 +3553,70 @@ void code_fillcaf (char *label_name,int a_stack_size,int b_stack_size)
}
}
+#ifdef I486
+void code_floordivI (VOID)
+{
+ INSTRUCTION_GRAPH graph_1,graph_2,graph_3;
+
+ graph_1=s_pop_b();
+ graph_2=s_get_b (0);
+
+ if (graph_2->instruction_code==GLOAD_I){
+ int n;
+
+ n=graph_2->instruction_parameters[0].i;
+ if (n>0 && (n & (n-1))==0){
+ int n_bits;
+
+ n_bits=0;
+ while (n>2){
+ n_bits+=2;
+ n>>=2;
+ }
+ n_bits+=n-1;
+
+ if (n_bits==0)
+ graph_3=graph_1;
+ else
+ graph_3=g_asr (g_load_i (n_bits),graph_1);
+ s_put_b (0,graph_3);
+
+ return;
+ } else if (n<0 && ((-n) & ((-n)-1))==0){
+ INSTRUCTION_GRAPH graph_4;
+ unsigned int i;
+ int n_bits;
+
+ i=-n;
+ n_bits=0;
+ while (i>2){
+ n_bits+=2;
+ i>>=2;
+ }
+ n_bits+=i-1;
+
+ if (n_bits==0)
+ graph_3=g_neg (graph_1);
+ else {
+ graph_4 = g_neg (g_and (g_load_i ((-n)-1),graph_1));
+ if (n_bits>1) /* not for -2 */
+ graph_4 = g_asr (g_load_i (n_bits),graph_4);
+ graph_3 = g_sub (g_asr (g_load_i (n_bits),graph_1),graph_4);
+ }
+
+ s_put_b (0,graph_3);
+
+ return;
+ } else
+ /* prevent sharing to optimise divide by constant */
+ graph_2=g_load_i (n);
+ }
+
+ graph_3=g_floordiv (graph_2,graph_1);
+ s_put_b (0,graph_3);
+}
+#endif
+
void code_get_desc_arity (int a_offset)
{
INSTRUCTION_GRAPH graph_1,graph_2,graph_3,graph_4,graph_5,graph_6,graph_7;
@@ -4630,6 +4697,98 @@ void code_ltU (VOID)
s_put_b (0,graph_3);
}
+
+void code_modI (VOID)
+{
+ INSTRUCTION_GRAPH graph_1,graph_2,graph_3;
+
+ graph_1=s_pop_b();
+ graph_2=s_get_b (0);
+
+ if (graph_2->instruction_code==GLOAD_I){
+ int n;
+
+ n=graph_2->instruction_parameters[0].i;
+ if (n>0){
+ int n2;
+
+ n2=n & (n-1);
+ if (n2==0)
+ graph_3=g_and (g_load_i (n-1),graph_1);
+ else {
+ INSTRUCTION_GRAPH graph_4;
+
+ graph_4=g_floordiv (g_load_i (n),graph_1);
+
+ if ((n2 & (n2-1))==0){
+ int bit_1,bit_2;
+
+ bit_1=0;
+ while ((n & 1)==0){
+ ++bit_1;
+ n=n>>1;
+ }
+ n=n>>1;
+ bit_2=1;
+ while ((n & 1)==0){
+ ++bit_2;
+ n=n>>1;
+ }
+
+ if (bit_1>0)
+ graph_4=g_lsl (g_load_i (bit_1),graph_4);
+ graph_3=g_sub (graph_4,graph_1);
+ graph_4=g_lsl (g_load_i (bit_2),graph_4);
+ graph_3=g_sub (graph_4,graph_3);
+ } else
+ graph_3=g_sub (g_mul (graph_2,graph_4),graph_1);
+ }
+ s_put_b (0,graph_3);
+ return;
+ } else if (n<0){
+ int n2;
+
+ n2=(-n) & ((-n)-1);
+ if (n2==0)
+ graph_3=g_neg (g_and (g_load_i ((-n)-1),g_neg (graph_1)));
+ else {
+ INSTRUCTION_GRAPH graph_4;
+
+ graph_4=g_floordiv (g_load_i (n),graph_1);
+
+ n = -n;
+
+ if ((n2 & (n2-1))==0){
+ int bit_1,bit_2;
+
+ bit_1=0;
+ while ((n & 1)==0){
+ ++bit_1;
+ n=n>>1;
+ }
+ n=n>>1;
+ bit_2=1;
+ while ((n & 1)==0){
+ ++bit_2;
+ n=n>>1;
+ }
+
+ if (bit_1>0)
+ graph_4=g_lsl (g_load_i (bit_1),graph_4);
+ graph_3=g_add (graph_4,graph_1);
+ graph_4=g_lsl (g_load_i (bit_2),graph_4);
+ graph_3=g_add (graph_4,graph_3);
+ } else
+ graph_3=g_add (g_mul (g_load_i (n),graph_4),graph_1);
+ }
+ s_put_b (0,graph_3);
+ return;
+ }
+ }
+
+ graph_3=g_mod (graph_2,graph_1);
+ s_put_b (0,graph_3);
+}
#endif
void code_remI (VOID)
diff --git a/cgcodep.h b/cgcodep.h
index e9ee954..a313e97 100644
--- a/cgcodep.h
+++ b/cgcodep.h
@@ -117,6 +117,9 @@ void code_fillI_b (int b_offset,int a_offset);
void code_fillR (double value,int a_offset);
void code_fillR_b (int b_offset,int a_offset);
void code_fill_a (int from_offset,int to_offset);
+#ifdef I486
+void code_floordivI (VOID);
+#endif
void code_get_desc_arity (int a_offset);
void code_get_node_arity (int a_offset);
void code_get_desc0_number (void);
@@ -156,6 +159,7 @@ void code_ltI (VOID);
void code_ltR (VOID);
#ifdef I486
void code_ltU (VOID);
+void code_modI (VOID);
#endif
void code_remI (VOID);
#ifdef I486
diff --git a/cgconst.h b/cgconst.h
index cc8a44a..4e6d1b1 100644
--- a/cgconst.h
+++ b/cgconst.h
@@ -29,6 +29,7 @@ enum {
,GDIVU
#endif
#ifdef I486
+ ,GFLOORDIV, GMOD
,GADDDU, GDIVDU, GMULUD, GREMU, GRESULT0, GRESULT1, GSUBDU
,GFLOAD_S_X,GFSTORE_S_X
#endif
diff --git a/cgiconst.h b/cgiconst.h
index dcd1af1..fb5b138 100644
--- a/cgiconst.h
+++ b/cgiconst.h
@@ -66,7 +66,8 @@ enum {
,IFEXG
#endif
#if defined (I486)
- ,IADC ,IRTSI, IDIVI, IREMI, IREMU, IMULUD, IDIVDU, ISBB
+ ,IADC ,ISBB, IRTSI
+ ,IDIVI, IREMI, IREMU, IFLOORDIV, IMOD, IMULUD, IDIVDU
,IFLOADS, IFMOVES
#endif
#if defined (I486) || defined (G_POWER)
diff --git a/cginput.c b/cginput.c
index 9f860bc..91f2f26 100644
--- a/cginput.c
+++ b/cginput.c
@@ -1990,6 +1990,9 @@ static void put_instructions_in_table (void)
put_instruction_name ("fillR_b", parse_instruction_n_n, code_fillR_b );
put_instruction_name ("fill_a", parse_instruction_n_n, code_fill_a );
put_instruction_name ("fill_r", parse_instruction_a_n_n_n_n_n, code_fill_r );
+#ifdef I486
+ put_instruction_name ("floordivI", parse_instruction, code_floordivI );
+#endif
put_instruction_name ("getWL", parse_instruction_n, code_dummy );
put_instruction_name ("get_desc_arity", parse_instruction_n, code_get_desc_arity );
put_instruction_name ("get_desc_flags_b", parse_instruction, code_get_desc_flags_b );
@@ -2034,8 +2037,8 @@ static void put_instructions_in_table (void)
put_instruction_name ("ltR", parse_instruction, code_ltR );
#ifdef I486
put_instruction_name ("ltU", parse_instruction, code_ltU );
+ put_instruction_name ("modI", parse_instruction, code_modI );
#endif
- put_instruction_name ("modI", parse_instruction, code_remI );
put_instruction_name ("mulI", parse_instruction, code_mulI );
put_instruction_name ("mulR", parse_instruction, code_mulR );
#if defined (I486) || defined (G_POWER)
diff --git a/cglin.c b/cglin.c
index 447ffb9..2c9bffb 100644
--- a/cglin.c
+++ b/cglin.c
@@ -3991,6 +3991,80 @@ static void linearize_rem_operator (int i_instruction_code,INSTRUCTION_GRAPH gra
#endif
#ifdef I486
+static void linearize_floordiv_mod_operator (int i_instruction_code,INSTRUCTION_GRAPH graph,ADDRESS *ad_p)
+{
+ INSTRUCTION_GRAPH graph_1,graph_2;
+ ADDRESS ad_1,ad_2;
+ int reg_1,tmp_reg;
+
+ graph_1=graph->instruction_parameters[0].p;
+ graph_2=graph->instruction_parameters[1].p;
+
+ if (graph->order_left){
+ linearize_graph (graph_1,&ad_1);
+ linearize_graph (graph_2,&ad_2);
+ } else {
+ linearize_graph (graph_2,&ad_2);
+ linearize_graph (graph_1,&ad_1);
+ }
+
+ {
+ int i;
+
+ if (ad_1.ad_mode==P_IMMEDIATE && i_instruction_code==IFLOORDIV &&
+ (i=ad_1.ad_offset, (i>1 || (i<-1 && i!=0x80000000))))
+ {
+ int tmp_reg2;
+
+ if (try_allocate_register_number (REGISTER_D0)){
+ tmp_reg2=REGISTER_D0;
+ in_alterable_data_register (&ad_2);
+ } else {
+ in_alterable_data_register (&ad_2);
+ tmp_reg2=get_dregister();
+ }
+ if (try_allocate_register_number (REGISTER_A1))
+ tmp_reg=REGISTER_A1;
+ else
+ tmp_reg=get_dregister();
+ instruction_r_r_r_i (i_instruction_code,tmp_reg2,ad_2.ad_register,tmp_reg,i);
+ free_register (tmp_reg2);
+ } else {
+ in_preferred_alterable_register (&ad_2,REGISTER_D0);
+ in_alterable_data_register (&ad_1);
+
+ if (try_allocate_register_number (REGISTER_A1))
+ tmp_reg=REGISTER_A1;
+ else
+ tmp_reg=get_dregister();
+ instruction_ad_r_r (i_instruction_code,&ad_1,ad_2.ad_register,tmp_reg);
+ }
+ }
+
+ free_register (tmp_reg);
+
+ --*ad_2.ad_count_p;
+ reg_1=ad_2.ad_register;
+
+ if (graph->instruction_d_min_a_cost>0){
+ int areg;
+
+ areg=get_aregister();
+ i_move_r_r (reg_1,areg);
+ free_dregister (reg_1);
+ reg_1=areg;
+ }
+
+ ad_p->ad_mode=P_REGISTER;
+ ad_p->ad_register=reg_1;
+
+ ad_p->ad_count_p=&graph->node_count;
+ if (*ad_p->ad_count_p>1)
+ register_node (graph,reg_1);
+}
+#endif
+
+#ifdef I486
static int linearize_first_graph_first (INSTRUCTION_GRAPH a_graph_1,INSTRUCTION_GRAPH a_graph_2)
{
int i1,i2,u1,u2;
@@ -8835,6 +8909,14 @@ static void linearize_graph (INSTRUCTION_GRAPH graph,ADDRESS *ad_p)
linearize_rem_operator (IREM,graph,ad_p);
return;
#endif
+#ifdef I486
+ case GFLOORDIV:
+ linearize_floordiv_mod_operator (IFLOORDIV,graph,ad_p);
+ return;
+ case GMOD:
+ linearize_floordiv_mod_operator (IMOD,graph,ad_p);
+ return;
+#endif
case GCMP_EQ:
linearize_compare_operator (CEQ,CEQ,graph,ad_p);
return;
@@ -9313,20 +9395,80 @@ void initialize_linearization (VOID)
#if 0
static char *i_instruction_names[] = {
- "ADD", "AND", "ASR", "BEQ", "BGE", "BGT", "BHS",
- "BLE", "BLT", "BMI", "BMOVE", "BNE", "CMP", "CMPW",
- "DIV", "EOR", "EXG", "EXT", "FACOS", "FADD", "FASIN",
- "FATAN", "FBEQ", "FBGE", "FBGT", "FBLE", "FBLT", "FBNE",
- "FCMP", "FCOS", "FDIV", "FEXP", "FLN", "FLOG10", "FMUL",
- "FREM", "FSEQ", "FSGE", "FSGT", "FSIN", "FSLE", "FSLT",
- "FSNE", "FSQRT", "FSUB", "FTAN", "FTST", "FMOVE", "FMOVEL",
- "JMP", "JSR", "LEA", "LSL", "LSR", "MOD", "MOVE",
- "MOVEB", "MOVEM", "MOVEW", "MUL", "OR", "RTS", "SEQ",
- "SGE", "SGT", "SLE", "SLT", "SNE", "SUB", "TST",
- "TSTB", "WORD"
+ "ADD", "AND", "ASR", "BEQ", "BGE", "BGEU", "BGT",
+ "BGTU", "BLE", "BLEU", "BLT", "BLTU", "BNE", "BNO",
+ "BO", "CMP", "DIV", "EOR", "EXG", "EXT", "FADD",
+#if ! (defined (I486) && !defined (G_A64))
+ "FBEQ", "FBGE", "FBGT", "FBLE", "FBLT", "FBNE",
+#endif
+ "FABS",
+ "FCMP", "FCOS", "FDIV", "FMUL", "FNEG", "FREM", "FSEQ",
+ "FSGE", "FSGT", "FSIN", "FSLE", "FSLT", "FSNE", "FSUB",
+ "FTAN", "FTST", "FMOVE", "FMOVEL", "JMP", "JSR", "LEA",
+ "LSL", "LSR", "MOD", "MOVE", "MOVEB", "MOVEDB", "MUL",
+ "NEG", "OR", "RTS", "SCHEDULE", "SEQ", "SGE", "SGEU",
+ "SGT", "SGTU", "SLE", "SLEU", "SLT", "SLTU", "SNE",
+ "SNO", "SO", "SUB", "TST", "WORD"
+#if !defined (G_POWER)
+ ,"FSQRT"
+#endif
+#ifdef M68000
+ ,"CMPW"
+ ,"FACOS", "FASIN", "FATAN", "FEXP", "FLN", "FLOG10",
+ "BMI", "BMOVE", "MOVEM", "TSTB"
+#endif
+#if defined (M68000) || defined (G_POWER)
+ ,"EXTB"
+#endif
+#ifndef M68000
+ ,"BTST"
+#endif
+#ifdef sparc
+ ,"FMOVEHI", "FMOVELO"
+#endif
+#ifdef G_POWER
+ ,"BNEP","MTCTR"
+#endif
+#if defined (G_POWER) || defined (sparc)
+ ,"ADDI", "LSLI"
+ ,"ADDO", "SUBO"
+#endif
+#ifdef I486
+ ,"ASR_S","LSL_S","LSR_S"
+#endif
+#if defined (I486) && !defined (G_A64)
+ ,"FCEQ", "FCGE", "FCGT", "FCLE", "FCLT", "FCNE"
+ ,"FSINCOS"
+#endif
+#ifdef G_POWER
+ ,"CMPLW"
+ ,"MULO"
+#endif
+#if defined (G_POWER) || defined (I486)
+ ,"JMPP" ,"RTSP", "NOT"
+#endif
+#if defined (I486) && defined (FP_STACK_OPTIMIZATIONS)
+ ,"FEXG"
+#endif
+#if defined (I486)
+ ,"ADC" ,"RTSI", "DIVI", "REMI", "REMU", "MULUD", "DIVDU", "SBB"
+ ,"FLOADS", "FMOVES"
+#endif
+#if defined (I486) || defined (G_POWER)
+ ,"DIVU"
+#endif
+#ifdef G_POWER
+ ,"UMULH"
+#endif
+#ifdef G_AI64
+ ,"LOADSQB", "MOVEQB", "FCVT2S"
+#endif
+#if 1
+ ,"CMPXCHG", "XADD"
+#endif
};
-static void show_parameter (register struct parameter *parameter)
+static void show_parameter (struct parameter *parameter)
{
switch (parameter->parameter_type){
case P_REGISTER:
@@ -9385,13 +9527,16 @@ static void show_parameter (register struct parameter *parameter)
}
}
-void show_instructions (register struct instruction *instructions)
+void show_instructions (struct instruction *instructions)
{
while (instructions!=NULL){
- register struct parameter *parameter;
- register int n_parameters;
-
- printf ("%s ",i_instruction_names[instructions->instruction_icode]);
+ struct parameter *parameter;
+ int n_parameters;
+
+ if (instructions->instruction_icode<sizeof (i_instruction_names)/sizeof(char*))
+ printf ("%s ",i_instruction_names[instructions->instruction_icode]);
+ else
+ printf ("?%d ",instructions->instruction_icode);
n_parameters=instructions->instruction_arity;
parameter=instructions->instruction_parameters;
diff --git a/cgopt.c b/cgopt.c
index 8b8710c..f27a14f 100644
--- a/cgopt.c
+++ b/cgopt.c
@@ -422,6 +422,7 @@ IF_G_RISC (case IADDI: case ILSLI:)
IF_G_SPARC (case IADDO: case ISUBO: )
#ifdef I486
case IDIVI: case IREMI: case IREMU: case IMULUD: case IDIVDU:
+ case IFLOORDIV: case IMOD:
#endif
#if (defined (I486) && !defined (I486_USE_SCRATCH_REGISTER)) || defined (G_POWER)
case IDIVU:
@@ -680,6 +681,8 @@ static void compute_maximum_b_stack_offsets (register int b_offset)
instruction->instruction_icode!=IASR_S &&
instruction->instruction_icode!=ILSL_S &&
instruction->instruction_icode!=ILSR_S &&
+ instruction->instruction_icode!=IFLOORDIV &&
+ instruction->instruction_icode!=IMOD &&
#endif
instruction->instruction_icode!=IREM)
#ifdef M68000
@@ -918,6 +921,8 @@ void optimize_stack_access (struct basic_block *block,int *a_offset_p,int *b_off
instruction->instruction_icode!=IASR_S &&
instruction->instruction_icode!=ILSL_S &&
instruction->instruction_icode!=ILSR_S &&
+ instruction->instruction_icode!=IFLOORDIV &&
+ instruction->instruction_icode!=IMOD &&
instruction->instruction_icode!=IREM)
internal_error_in_function ("optimize_stack_access");
/* only first argument of mod might be register indirect */
@@ -1689,6 +1694,16 @@ IF_G_RISC (case IADDI: case ILSLI:)
use_parameter (&instruction->instruction_parameters[0]);
break;
#endif
+#ifdef I486
+ case IFLOORDIV: case IMOD:
+ define_parameter (&instruction->instruction_parameters[2]);
+ use_parameter (&instruction->instruction_parameters[1]);
+ if (instruction->instruction_arity==4)
+ define_parameter (&instruction->instruction_parameters[0]);
+ else
+ use_parameter (&instruction->instruction_parameters[0]);
+ break;
+#endif
#if 0
case IFBEQ: case IFBGE: case IFBGT: case IFBLE: case IFBLT: case IFBNE:
define_scratch_register();
@@ -4033,6 +4048,20 @@ IF_G_RISC (case IADDI: case ILSLI:)
# endif
break;
#endif
+#ifdef I486
+ case IFLOORDIV: case IMOD:
+ if (instruction->instruction_arity==4)
+ use_3_same_type_registers
+ (&instruction->instruction_parameters[0].parameter_data.reg,DEF,
+ &instruction->instruction_parameters[1].parameter_data.reg,USE_DEF,
+ &instruction->instruction_parameters[2].parameter_data.reg,DEF,D_REGISTER);
+ else
+ use_3_same_type_registers
+ (&instruction->instruction_parameters[0].parameter_data.reg,USE,
+ &instruction->instruction_parameters[1].parameter_data.reg,USE_DEF,
+ &instruction->instruction_parameters[2].parameter_data.reg,DEF,D_REGISTER);
+ break;
+#endif
#if 0
case IFBEQ: case IFBGE: case IFBGT: case IFBLE: case IFBLT: case IFBNE:
use_scratch_register();