diff options
-rw-r--r-- | cgcalc.c | 16 | ||||
-rw-r--r-- | cgcode.c | 161 | ||||
-rw-r--r-- | cgcodep.h | 4 | ||||
-rw-r--r-- | cgconst.h | 1 | ||||
-rw-r--r-- | cgiconst.h | 3 | ||||
-rw-r--r-- | cginput.c | 5 | ||||
-rw-r--r-- | cglin.c | 179 | ||||
-rw-r--r-- | cgopt.c | 29 |
8 files changed, 378 insertions, 20 deletions
@@ -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: @@ -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) @@ -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 @@ -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 @@ -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) @@ -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) @@ -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; @@ -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(); |