diff options
author | John van Groningen | 2005-01-19 10:52:58 +0000 |
---|---|---|
committer | John van Groningen | 2005-01-19 10:52:58 +0000 |
commit | 35929d022753195e9461fca5ff9d1b4aa82f7868 (patch) | |
tree | c8c66e7466637e2b0c59f47e1b4bf104119b42fe | |
parent | add divU for the PowerPC (diff) |
implement mulUUL and divLU instructions for IA32,
define acos, asin, exp, ln and log10 instructons only for M68000 platform,
add code for jsr_ap and jmp_ap instructions (not yet enabled)
-rw-r--r-- | cgcalc.c | 222 | ||||
-rw-r--r-- | cgcode.c | 271 | ||||
-rw-r--r-- | cgcodep.h | 16 | ||||
-rw-r--r-- | cgconst.h | 28 | ||||
-rw-r--r-- | cgias.c | 403 | ||||
-rw-r--r-- | cgiconst.h | 2 | ||||
-rw-r--r-- | cginput.c | 32 | ||||
-rw-r--r-- | cgiwas.c | 480 | ||||
-rw-r--r-- | cglin.c | 267 | ||||
-rw-r--r-- | cgopt.c | 54 | ||||
-rw-r--r-- | cgport.h | 1 |
11 files changed, 1406 insertions, 370 deletions
@@ -241,9 +241,116 @@ static void calculate_eor_operator (INSTRUCTION_GRAPH graph) graph->i_dregs=i_dregs; graph->order_alterable=graph->node_count<=1; - return; } +#ifdef I486 +static void calculate_mulud_operator (INSTRUCTION_GRAPH graph) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + int i_aregs,i_dregs,l_aregs,r_aregs,l_dregs,r_dregs; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (graph_1); + calculate_graph_register_uses (graph_2); + + i_aregs=graph_1->i_aregs+graph_2->i_aregs; + i_dregs=graph_1->i_dregs+graph_2->i_dregs; + + l_aregs=MAX (graph_1->u_aregs,graph_1->i_aregs+graph_2->u_aregs); + l_dregs=MAX (graph_1->u_dregs,graph_1->i_dregs+graph_2->u_dregs); + + r_aregs=MAX (graph_2->u_aregs,graph_2->i_aregs+graph_1->u_aregs); + r_dregs=MAX (graph_2->u_dregs,graph_2->i_dregs+graph_1->u_dregs); + + if (graph_1->order_mode==R_DREGISTER) + i_dregs-=graph_1->order_alterable; + else + i_aregs-=graph_1->order_alterable; + + if (graph_2->order_mode==R_DREGISTER) + i_dregs-=graph_2->order_alterable; + else + i_aregs-=graph_2->order_alterable; + + i_dregs+=2; + + if (l_dregs<i_dregs) + l_dregs=i_dregs; + if (r_dregs<i_dregs) + r_dregs=i_dregs; + + graph->order_mode=R_DREGISTER; + + if (AD_REG_WEIGHT (l_aregs,l_dregs) < AD_REG_WEIGHT (r_aregs,r_dregs)){ + graph->u_aregs=l_aregs; + graph->u_dregs=l_dregs; + graph->order_left=1; + } else { + graph->u_aregs=r_aregs; + graph->u_dregs=r_dregs; + graph->order_left=0; + } + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + + graph->order_alterable=0; +} + +static void calculate_divdu_operator (INSTRUCTION_GRAPH graph) +{ + INSTRUCTION_GRAPH graph_1,graph_2,graph_3; + int i_aregs,i_dregs,aregs,dregs; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + graph_3=graph->instruction_parameters[2].p; + + calculate_graph_register_uses (graph_1); + calculate_graph_register_uses (graph_2); + calculate_graph_register_uses (graph_3); + + i_aregs=graph_1->i_aregs+graph_2->i_aregs+graph_3->i_aregs; + i_dregs=graph_1->i_dregs+graph_2->i_dregs+graph_3->i_dregs; + + aregs=MAX ( MAX (graph_1->u_aregs,graph_1->i_aregs+graph_2->u_aregs), + graph_1->i_aregs+graph_2->i_aregs+graph_3->u_aregs); + dregs=MAX ( MAX (graph_1->u_dregs,graph_1->i_dregs+graph_2->u_dregs), + graph_1->i_dregs+graph_2->i_dregs+graph_3->u_dregs); + + if (graph_1->order_mode==R_DREGISTER) + i_dregs-=graph_1->order_alterable; + else + i_aregs-=graph_1->order_alterable; + + if (graph_2->order_mode==R_DREGISTER) + i_dregs-=graph_2->order_alterable; + else + i_aregs-=graph_2->order_alterable; + + if (graph_3->order_mode==R_DREGISTER) + i_dregs-=graph_3->order_alterable; + else + i_aregs-=graph_3->order_alterable; + + i_dregs+=2; + + if (dregs<i_dregs) + dregs=i_dregs; + + graph->order_mode=R_DREGISTER; + + graph->u_aregs=aregs; + graph->u_dregs=dregs; + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + + graph->order_alterable=0; +} +#endif + static void calculate_dyadic_float_operator (INSTRUCTION_GRAPH graph) { INSTRUCTION_GRAPH graph_1,graph_2; @@ -2334,15 +2441,17 @@ void calculate_graph_register_uses (INSTRUCTION_GRAPH graph) case GFCOS: case GFSIN: case GFTAN: + case GFATAN: + case GFSQRT: + case GFNEG: + case GFABS: +#ifdef M68000 case GFASIN: case GFACOS: - case GFATAN: case GFLN: case GFLOG10: case GFEXP: - case GFSQRT: - case GFNEG: - case GFABS: +#endif calculate_monadic_float_operator (graph); return; case GFLOAD_ID: @@ -2433,6 +2542,29 @@ void calculate_graph_register_uses (INSTRUCTION_GRAPH graph) graph->order_alterable=graph_2->order_alterable; return; } +#ifdef I486 + case GRESULT0: + case GRESULT1: + { + INSTRUCTION_GRAPH graph_0; + + graph_0=graph->instruction_parameters[0].p; + if (graph_0->order_mode==R_NOMODE) + if (graph->instruction_code==GMULUD) + calculate_mulud_operator (graph_0); + else + calculate_divdu_operator (graph_0); + + graph->order_mode=R_DREGISTER; + graph->u_aregs=graph_0->u_aregs; + graph->u_dregs=graph_0->u_dregs; + graph->i_aregs=graph_0->i_aregs; + graph->i_dregs=graph_0->i_dregs; + + graph->order_alterable=graph->node_count<=1; + return; + } +#endif default: /* printf ("%d\n",graph->instruction_code); */ internal_error_in_function ("calculate_graph_register_uses"); @@ -2515,6 +2647,9 @@ void count_graph (INSTRUCTION_GRAPH graph) #ifdef G_POWER case GUMULH: #endif +#ifdef I486 + case GMULUD: +#endif if (++graph->node_count==1){ count_graph (graph->instruction_parameters[0].p); count_graph (graph->instruction_parameters[1].p); @@ -2528,21 +2663,27 @@ void count_graph (INSTRUCTION_GRAPH graph) case GFCOS: case GFSIN: case GFTAN: + case GFATAN: + case GFSQRT: + case GFNEG: + case GFABS: +#ifdef M68000 case GFASIN: case GFACOS: - case GFATAN: case GFLN: case GFLOG10: case GFEXP: - case GFSQRT: - case GFNEG: - case GFABS: +#endif case GNEG: #if defined (I486) || defined (G_POWER) case GNOT: #endif case GBEFORE0: case GTEST_O: +#ifdef I486 + case GRESULT0: + case GRESULT1: +#endif if (++graph->node_count==1) count_graph (graph->instruction_parameters[0].p); break; @@ -2633,6 +2774,15 @@ void count_graph (INSTRUCTION_GRAPH graph) case GREGISTER: ++graph->node_count; break; +#ifdef I486 + case GDIVDU: + if (++graph->node_count==1){ + count_graph (graph->instruction_parameters[0].p); + count_graph (graph->instruction_parameters[1].p); + count_graph (graph->instruction_parameters[2].p); + } + break; +#endif default: internal_error_in_function ("count_graph"); } @@ -2680,6 +2830,9 @@ void mark_graph_2 (register INSTRUCTION_GRAPH graph) #ifdef G_POWER case GUMULH: #endif +#ifdef I486 + case GMULUD: +#endif if (graph->node_mark<2){ graph->node_mark=2; mark_graph_2 (graph->instruction_parameters[0].p); @@ -2694,21 +2847,27 @@ void mark_graph_2 (register INSTRUCTION_GRAPH graph) case GFCOS: case GFSIN: case GFTAN: + case GFATAN: + case GFSQRT: + case GFNEG: + case GFABS: +#ifdef M68000 case GFASIN: case GFACOS: - case GFATAN: case GFLN: case GFLOG10: case GFEXP: - case GFSQRT: - case GFNEG: - case GFABS: +#endif case GNEG: #if defined (I486) || defined (G_POWER) case GNOT: #endif case GBEFORE0: case GTEST_O: +#ifdef I486 + case GRESULT0: + case GRESULT1: +#endif if (graph->node_mark<2){ graph->node_mark=2; mark_graph_2 (graph->instruction_parameters[0].p); @@ -2813,6 +2972,16 @@ void mark_graph_2 (register INSTRUCTION_GRAPH graph) case GREGISTER: graph->node_mark=2; break; +#ifdef I486 + case GDIVDU: + if (graph->node_mark<2){ + graph->node_mark=2; + mark_graph_2 (graph->instruction_parameters[0].p); + mark_graph_2 (graph->instruction_parameters[1].p); + mark_graph_2 (graph->instruction_parameters[2].p); + } + break; +#endif default: internal_error_in_function ("mark_graph_2"); } @@ -2860,6 +3029,9 @@ void mark_graph_1 (register INSTRUCTION_GRAPH graph) #ifdef G_POWER case GUMULH: #endif +#ifdef I486 + case GMULUD: +#endif if (!graph->node_mark){ graph->node_mark=1; mark_graph_2 (graph->instruction_parameters[0].p); @@ -2872,21 +3044,27 @@ void mark_graph_1 (register INSTRUCTION_GRAPH graph) case GFCOS: case GFSIN: case GFTAN: + case GFATAN: + case GFSQRT: + case GFNEG: + case GFABS: +#ifdef M68000 case GFASIN: case GFACOS: - case GFATAN: case GFLN: case GFLOG10: case GFEXP: - case GFSQRT: - case GFNEG: - case GFABS: +#endif #if defined (I486) || defined (G_POWER) case GNEG: case GNOT: #endif case GBEFORE0: case GTEST_O: +#ifdef I486 + case GRESULT0: + case GRESULT1: +#endif if (!graph->node_mark){ graph->node_mark=1; mark_graph_2 (graph->instruction_parameters[0].p); @@ -2999,6 +3177,16 @@ void mark_graph_1 (register INSTRUCTION_GRAPH graph) mark_graph_1 (graph->instruction_parameters[0].p); } break; +#ifdef I486 + case GDIVDU: + if (!graph->node_mark){ + graph->node_mark=1; + mark_graph_2 (graph->instruction_parameters[0].p); + mark_graph_2 (graph->instruction_parameters[1].p); + mark_graph_2 (graph->instruction_parameters[2].p); + } + break; +#endif default: internal_error_in_function ("mark_graph_1"); } @@ -208,10 +208,8 @@ int no_time_profiling; #define g_fcmp_gt(g1,g2) g_instruction_2(GFCMP_GT,(g1),(g2)) #define g_fcmp_lt(g1,g2) g_instruction_2(GFCMP_LT,(g1),(g2)) #define g_fdiv(g1,g2) g_instruction_2(GFDIV,(g1),(g2)) -#define g_fexp(g1) g_instruction_1(GFEXP,(g1)) #define g_fitor(g1) g_instruction_1(GFITOR,(g1)) -#define g_fln(g1) g_instruction_1(GFLN,(g1)) #define g_fmul(g1,g2) g_instruction_2(GFMUL,(g1),(g2)) #define g_frem(g1,g2) g_instruction_2(GFREM,(g1),(g2)) @@ -272,10 +270,13 @@ static LABEL *halt_label,*cmp_string_label,*eqD_label, LABEL *new_int_reducer_label,*channelP_label,*stop_reducer_label,*send_request_label, *send_graph_label,*string_to_string_node_label,*cat_string_label; -static LABEL *add_real,*sub_real,*mul_real,*div_real,*eq_real,*gt_real,*lt_real, - *i_to_r_real,*r_to_i_real,*sqrt_real,*exp_real,*ln_real,*log10_real, - *cos_real,*sin_real,*tan_real,*acos_real,*asin_real,*atan_real, - *pow_real,*entier_real_label; +#ifdef M68000 +static LABEL *add_real,*sub_real,*mul_real,*div_real,*eq_real,*gt_real,*lt_real; +#endif + +static LABEL *i_to_r_real,*r_to_i_real,*sqrt_real,*exp_real,*ln_real,*log10_real, + *cos_real,*sin_real,*tan_real,*acos_real,*asin_real,*atan_real,*pow_real, + *entier_real_label; LABEL *copy_graph_label,*CHANNEL_label,*create_channel_label,*currentP_label,*newP_label, *randomP_label,*suspend_label; @@ -288,6 +289,10 @@ static LABEL *small_integers_label,*static_characters_label; LABEL *eval_fill_label,*eval_upd_labels[33]; +#ifdef NEW_APPLY +LABEL *add_empty_node_labels[33]; +#endif + static LABEL *print_r_arg_label,*push_t_r_args_label,*push_a_r_args_label; LABEL *index_error_label; @@ -491,16 +496,15 @@ void code_absR (void) void code_acosR (VOID) { #ifdef M68000 - if (!mc68881_flag){ -#endif - if (acos_real==NULL) - acos_real=enter_label ("acos_real",IMPORT_LABEL); - code_monadic_sane_operator (acos_real); - init_b_stack (2,r_vector); -#ifdef M68000 - } else + if (mc68881_flag){ code_monadic_real_operator (GFACOS); + return + } #endif + if (acos_real==NULL) + acos_real=enter_label ("acos_real",IMPORT_LABEL); + code_monadic_sane_operator (acos_real); + init_b_stack (2,r_vector); } void code_addI (VOID) @@ -595,16 +599,15 @@ void code_and (VOID) void code_asinR (VOID) { #ifdef M68000 - if (!mc68881_flag){ -#endif - if (asin_real==NULL) - asin_real=enter_label ("asin_real",IMPORT_LABEL); - code_monadic_sane_operator (asin_real); - init_b_stack (2,r_vector); -#ifdef M68000 - } else + if (mc68881_flag){ code_monadic_real_operator (GFASIN); + return; + } #endif + if (asin_real==NULL) + asin_real=enter_label ("asin_real",IMPORT_LABEL); + code_monadic_sane_operator (asin_real); + init_b_stack (2,r_vector); } void code_atanR (VOID) @@ -1840,6 +1843,30 @@ void code_divU (VOID) } #endif +#ifdef I486 +void code_divLU (VOID) +{ + INSTRUCTION_GRAPH graph_1,graph_2,graph_3,graph_4,graph_5,graph_6; + + graph_3=s_get_b (2); + graph_2=s_get_b (1); + graph_1=s_pop_b(); + + graph_4=g_new_node (GDIVDU,3,3*sizeof (union instruction_parameter)); + graph_4->instruction_parameters[0].p=graph_1; + graph_4->instruction_parameters[1].p=graph_2; + graph_4->instruction_parameters[2].p=graph_3; + + graph_5=g_instruction_2 (GRESULT1,graph_4,NULL); + graph_6=g_instruction_2 (GRESULT0,graph_4,NULL); + graph_5->instruction_parameters[1].p=graph_6; + graph_6->instruction_parameters[1].p=graph_5; + + s_put_b (1,graph_5); + s_put_b (0,graph_6); +} +#endif + void code_entierR (VOID) { if (entier_real_label==NULL) @@ -2238,16 +2265,15 @@ void code_exit_false (char label_name[]) void code_expR (VOID) { #ifdef M68000 - if (!mc68881_flag){ -#endif - if (exp_real==NULL) - exp_real=enter_label ("exp_real",IMPORT_LABEL); - code_monadic_sane_operator (exp_real); - init_b_stack (2,r_vector); -#ifdef M68000 - } else + if (mc68881_flag){ code_monadic_real_operator (GFEXP); + return; + } #endif + if (exp_real==NULL) + exp_real=enter_label ("exp_real",IMPORT_LABEL); + code_monadic_sane_operator (exp_real); + init_b_stack (2,r_vector); } void code_fill_r (char descriptor_name[],int a_size,int b_size,int root_offset,int a_offset,int b_offset) @@ -3441,63 +3467,70 @@ static struct basic_block *profile_function_block; int profile_flag=PROFILE_NORMAL; -static void code_jmp_ap_ (void) +static void code_jmp_ap_ (int n_apply_args) { + if (n_apply_args==1){ #if defined (I486) - end_basic_block_with_registers (2,0,e_vector); - i_move_id_r (0,REGISTER_A1,REGISTER_A2); + end_basic_block_with_registers (2,0,e_vector); + i_move_id_r (0,REGISTER_A1,REGISTER_A2); # ifdef PROFILE - if (profile_function_label!=NULL) - i_jmp_id_profile (4-2,REGISTER_A2,0); - else + if (profile_function_label!=NULL) + i_jmp_id_profile (4-2,REGISTER_A2,0); + else # endif - i_jmp_id (4-2,REGISTER_A2,0); + i_jmp_id (4-2,REGISTER_A2,0); #else - INSTRUCTION_GRAPH graph_1,graph_2,graph_3,graph_4,graph_5; + INSTRUCTION_GRAPH graph_1,graph_2,graph_3,graph_4,graph_5; - graph_1=s_get_a (0); + graph_1=s_get_a (0); # if defined (sparc) || defined (G_POWER) # pragma unused (graph_3,graph_4) - graph_2=g_load_id (0,graph_1); - graph_5=g_load_id (4-2,graph_2); + graph_2=g_load_id (0,graph_1); + graph_5=g_load_id (4-2,graph_2); # else - graph_2=g_load_des_id (DESCRIPTOR_OFFSET,graph_1); - graph_3=g_g_register (GLOBAL_DATA_REGISTER); + graph_2=g_load_des_id (DESCRIPTOR_OFFSET,graph_1); + graph_3=g_g_register (GLOBAL_DATA_REGISTER); - graph_4=g_add (graph_3,graph_2); + graph_4=g_add (graph_3,graph_2); # if defined (M68000) && !defined (SUN) - graph_5=g_load_des_id (2,graph_4); + graph_5=g_load_des_id (2,graph_4); # else - graph_5=g_load_id (4,graph_4); + graph_5=g_load_id (4,graph_4); # endif # endif - s_push_a (graph_5); + s_push_a (graph_5); - end_basic_block_with_registers (3,0,e_vector); + end_basic_block_with_registers (3,0,e_vector); # if defined (M68000) && !defined (SUN) - i_add_r_r (GLOBAL_DATA_REGISTER,REGISTER_A2); + i_add_r_r (GLOBAL_DATA_REGISTER,REGISTER_A2); # endif # ifdef PROFILE - if (profile_function_label!=NULL) - i_jmp_id_profile (0,REGISTER_A2,2<<4); - else + if (profile_function_label!=NULL) + i_jmp_id_profile (0,REGISTER_A2,2<<4); + else # endif - i_jmp_id (0,REGISTER_A2,2<<4); + i_jmp_id (0,REGISTER_A2,2<<4); #endif - demand_flag=0; + demand_flag=0; - reachable=0; + reachable=0; - begin_new_basic_block(); + begin_new_basic_block(); + } else { + char ap_label_name[32]; + + sprintf (ap_label_name,"ap_%d",n_apply_args); + code_jmp (ap_label_name); + } } void code_jmp (char label_name[]) { if (!strcmp (label_name,"e__system__sAP")) - code_jmp_ap_(); + code_jmp_ap_(1); else { LABEL *label; int a_stack_size,b_stack_size,n_a_and_f_registers; @@ -3581,10 +3614,10 @@ void code_jmp (char label_name[]) } } -void code_jmp_ap (void) +void code_jmp_ap (int n_apply_args) { - code_d (2,0,e_vector); - code_jmp_ap_(); + code_d (1+n_apply_args,0,e_vector); + code_jmp_ap_ (n_apply_args); } void code_label (char *label_name); @@ -3864,46 +3897,53 @@ static int too_many_b_stack_parameters_for_registers (int b_stack_size,int n_dat } #endif -static void code_jsr_ap_ (void) +static void code_jsr_ap_ (int n_apply_args) { INSTRUCTION_GRAPH graph_1,graph_2,graph_3,graph_4,graph_5; + if (n_apply_args==1){ #if !defined (I486) - graph_1=s_get_a (0); + graph_1=s_get_a (0); # if defined (sparc) || defined (G_POWER) # pragma unused (graph_3,graph_4) - graph_2=g_load_id (0,graph_1); - graph_5=g_load_id (4-2,graph_2); + graph_2=g_load_id (0,graph_1); + graph_5=g_load_id (4-2,graph_2); # else - graph_2=g_load_des_id (DESCRIPTOR_OFFSET,graph_1); - graph_3=g_g_register (GLOBAL_DATA_REGISTER); - graph_4=g_add (graph_3,graph_2); + graph_2=g_load_des_id (DESCRIPTOR_OFFSET,graph_1); + graph_3=g_g_register (GLOBAL_DATA_REGISTER); + graph_4=g_add (graph_3,graph_2); # if defined (M68000) && !defined (SUN) - graph_5=g_load_des_id (2,graph_4); + graph_5=g_load_des_id (2,graph_4); # else - graph_5=g_load_id (4,graph_4); + graph_5=g_load_id (4,graph_4); # endif # endif - s_push_a (graph_5); + s_push_a (graph_5); #endif - if (demand_flag) - offered_after_jsr=1; - demand_flag=0; + if (demand_flag) + offered_after_jsr=1; + demand_flag=0; #if defined (I486) - insert_basic_block (APPLY_BLOCK,2,0,e_vector,NULL); + insert_basic_block (APPLY_BLOCK,2,0,e_vector,NULL); #else - insert_basic_block (APPLY_BLOCK,3,0,e_vector,NULL); + insert_basic_block (APPLY_BLOCK,3,0,e_vector,NULL); #endif - init_a_stack (1); + init_a_stack (1); + } else { + char ap_label_name[32]; + + sprintf (ap_label_name,"ap_%d",n_apply_args); + code_jsr (ap_label_name); + } } void code_jsr (char label_name[]) { if (!strcmp (label_name,"e__system__sAP")) - code_jsr_ap_(); + code_jsr_ap_ (1); else { LABEL *label; INSTRUCTION_GRAPH graph; @@ -3953,10 +3993,10 @@ void code_jsr (char label_name[]) } } -void code_jsr_ap (void) +void code_jsr_ap (int n_apply_args) { - code_d (2,0,e_vector); - code_jsr_ap_(); + code_d (1+n_apply_args,0,e_vector); + code_jsr_ap_ (n_apply_args); code_o (1,0,e_vector); } @@ -4064,31 +4104,29 @@ void code_keep (int a_offset_1,int a_offset_2) void code_lnR (VOID) { #ifdef M68000 - if (!mc68881_flag){ -#endif - if (ln_real==NULL) - ln_real=enter_label ("ln_real",IMPORT_LABEL); - code_monadic_sane_operator (ln_real); - init_b_stack (2,r_vector); -#ifdef M68000 - } else + if (mc68881_flag){ code_monadic_real_operator (GFLN); + return; + } #endif + if (ln_real==NULL) + ln_real=enter_label ("ln_real",IMPORT_LABEL); + code_monadic_sane_operator (ln_real); + init_b_stack (2,r_vector); } void code_log10R (VOID) { #ifdef M68000 - if (!mc68881_flag){ -#endif - if (log10_real==NULL) - log10_real=enter_label ("log10_real",IMPORT_LABEL); - code_monadic_sane_operator (log10_real); - init_b_stack (2,r_vector); -#ifdef M68000 - } else + if (mc68881_flag){ code_monadic_real_operator (GFLOG10); + return; + } #endif + if (log10_real==NULL) + log10_real=enter_label ("log10_real",IMPORT_LABEL); + code_monadic_sane_operator (log10_real); + init_b_stack (2,r_vector); } void code_ltC (VOID) @@ -4291,17 +4329,27 @@ void code_mulI (VOID) #endif } -#ifdef G_POWER -void code_umulIIL (VOID) +#if defined (I486) || defined (G_POWER) +void code_mulUUL (VOID) { INSTRUCTION_GRAPH graph_1,graph_2,graph_3,graph_4; +# ifdef I486 + INSTRUCTION_GRAPH graph_5; +# endif - graph_1=s_get_b (1); - graph_2=s_get_b (0); + graph_1=s_get_b (0); + graph_2=s_get_b (1); +# ifdef G_POWER graph_3=g_mul (graph_1,graph_2); graph_4=g_umulh (graph_1,graph_2); - +# else + graph_5=g_instruction_2 (GMULUD,graph_1,graph_2); + graph_3=g_instruction_2 (GRESULT1,graph_5,NULL); + graph_4=g_instruction_2 (GRESULT0,graph_5,NULL); + graph_3->instruction_parameters[1].p=graph_4; + graph_4->instruction_parameters[1].p=graph_3; +#endif s_put_b (1,graph_3); s_put_b (0,graph_4); } @@ -4345,6 +4393,22 @@ void code_mulR (VOID) #endif } +#ifdef NEW_APPLY +void code_a (int n_apply_args,char *ea_label_name) +{ + LABEL *label; + char add_empty_node_label_name[32]; + + last_block->block_n_node_arguments=-200+n_apply_args; + last_block->block_ea_label=enter_label (ea_label_name,0); + + if (n_apply_args>0 && add_empty_node_labels[n_apply_args]==NULL){ + sprintf (add_empty_node_label_name,"add_empty_node_%d",n_apply_args); + add_empty_node_labels[n_apply_args]=enter_label (add_empty_node_label_name,IMPORT_LABEL); + } +} +#endif + void code_n (int number_of_arguments,char *descriptor_name,char *ea_label_name) { LABEL *label; @@ -8599,6 +8663,11 @@ void initialize_coding (VOID) for (n=0; n<=32; ++n) eval_upd_labels[n]=NULL; +#ifdef NEW_APPLY + for (n=0; n<=32; ++n) + add_empty_node_labels[n]=NULL; +#endif + for (n=0; n<=MAX_YET_ARGS_NEEDED_ARITY; ++n) yet_args_needed_labels[n]=NULL; @@ -62,6 +62,9 @@ void code_create_channel (char *label_name); void code_decI (VOID); void code_del_args (int source_offset,int n_arguments,int destination_offset); void code_divI (VOID); +#ifdef I486 +void code_divLU (VOID); +#endif void code_divR (VOID); #if defined (I486) || defined (G_POWER) void code_divU (VOID); @@ -129,13 +132,13 @@ void code_ItoC (VOID); void code_ItoP (VOID); void code_ItoR (VOID); void code_jmp (char label_name[]); -void code_jmp_ap (void); +void code_jmp_ap (int n_args); void code_jmp_eval (VOID); void code_jmp_eval_upd (VOID); void code_jmp_false (char label_name[]); void code_jmp_true (char label_name[]); void code_jsr (char label_name[]); -void code_jsr_ap (void); +void code_jsr_ap (int n_args); void code_jsr_eval (int a_offset); void code_lnR (VOID); void code_log10R (VOID); @@ -154,6 +157,9 @@ void code_mulI (VOID); void code_mulIo (VOID); #endif void code_mulR (VOID); +#if defined (I486) || defined (G_POWER) +void code_mulUUL (VOID); +#endif void code_negI (void); void code_negR (VOID); void code_new_ext_reducer (char descriptor_name[],int a_offset); @@ -260,11 +266,11 @@ void code_updatepop_a (int a_offset_1,int a_offset_2); void code_update_b (int b_offset_1,int b_offset_2); void code_updatepop_b (int b_offset_1,int b_offset_2); void code_updateS (int source_offset,int destination_offset); -#ifdef G_POWER -void code_umulIIL (VOID); -#endif void code_xor (VOID); +#ifdef NEW_APPLY +void code_a (int number_of_arguments,char *ea_label_name); +#endif void code_caf (char *label_name,int a_size,int b_size); void code_comp (int version,char *options); void code_d (int da,int db,ULONG vector[]); @@ -3,18 +3,17 @@ enum { GADD, GADD_O, GAND, GALLOCATE, GASR, GBEFORE, GBEFORE0, GBOUNDS, GCMP_EQ, GCMP_GT, GCMP_GTU, GCMP_LT, GCMP_LTU, GCNOT, GCOPY, GCREATE, GCREATE_R, GDIV, - GEOR, GFABS, GFACOS, GFADD, GFASIN, GFCMP_EQ, - GFCMP_GT, GFATAN, GFCMP_LT, GFCOS, GFDIV, GFEXP, - GFHIGH, GFITOR, GFJOIN, GFKEEP, GFLN, GFLOAD, - GFLOAD_I, GFLOAD_ID, GFLOAD_X, GFLOG10, GFLOW, GFMOVEMI, - GFMUL, GFNEG, GFREM, GFRTOI, GFSIN, GFSUB, - GFILL, GFILL_R, GFREGISTER, GFSQRT, GFSTORE, GFSTORE_R, - GFSTORE_X, GFTAN, GGFREGISTER, GGREGISTER, GKEEP, GINDIRECTION, - GLEA, GLOAD, GLOAD_I, GLOAD_ID, GLOAD_X, GLOAD_B_ID, - GLOAD_B_X, GLOAD_DES_ID, GLOAD_DES_I, GLSL, GLSR, GMOD, - GMOVEM, GMOVEMI, GMUL, GMUL_O, GNEG, GOR, - GREGISTER, GSTORE, GSTORE_R, GSTORE_B_X, GSTORE_X, GSUB, - GSUB_O, GTEST_O, GEXIT_IF + GEOR, GFABS, GFADD, GFCMP_EQ, GFCMP_GT, GFATAN, + GFCMP_LT, GFCOS, GFDIV, GFHIGH, GFITOR, GFJOIN, + GFKEEP, GFLOAD, GFLOAD_I, GFLOAD_ID, GFLOAD_X, GFLOW, + GFMOVEMI, GFMUL, GFNEG, GFREM, GFRTOI, GFSIN, + GFSUB, GFILL, GFILL_R, GFREGISTER, GFSQRT, GFSTORE, + GFSTORE_R, GFSTORE_X, GFTAN, GGFREGISTER, GGREGISTER, GKEEP, + GINDIRECTION, GLEA, GLOAD, GLOAD_I, GLOAD_ID, GLOAD_X, + GLOAD_B_ID, GLOAD_B_X, GLOAD_DES_ID, GLOAD_DES_I, GLSL, GLSR, + GMOD, GMOVEM, GMOVEMI, GMUL, GMUL_O, GNEG, + GOR, GREGISTER, GSTORE, GSTORE_R, GSTORE_B_X, GSTORE_X, + GSUB, GSUB_O, GTEST_O, GEXIT_IF #if defined (I486) || defined (G_POWER) ,GNOT #endif @@ -25,7 +24,10 @@ enum { ,GDIVU #endif #ifdef I486 - ,GREMU + ,GREMU, GMULUD, GDIVDU, GRESULT0, GRESULT1 +#endif +#ifdef M68000 + ,GFACOS, GFASIN, GFEXP, GFLN, GFLOG10 #endif }; @@ -2425,7 +2425,7 @@ static void as_rem_instruction (struct instruction *instruction,int unsigned_rem as_move_r_r (REGISTER_O0,REGISTER_D0); break; - default: + default: as_move_r_r (REGISTER_A1,REGISTER_O0); store_c (0x90+reg_num (d_reg)); /* xchg d_reg,D0 */ @@ -2467,6 +2467,177 @@ static void as_rem_instruction (struct instruction *instruction,int unsigned_rem } } +static void as_2move_registers (int reg1,int reg2,int reg3) +{ + as_move_r_r (reg2,reg3); + as_move_r_r (reg1,reg2); +} + +static void as_3move_registers (int reg1,int reg2,int reg3,int reg4) +{ + as_move_r_r (reg3,reg4); + as_move_r_r (reg2,reg3); + as_move_r_r (reg1,reg2); +} + +static void as_mulud_instruction (struct instruction *instruction) +{ + int reg_1,reg_2; + + reg_1=instruction->instruction_parameters[0].parameter_data.reg.r; + reg_2=instruction->instruction_parameters[1].parameter_data.reg.r; + + if (reg_2==REGISTER_D0){ + if (reg_1==REGISTER_A1) + as_r (0367,040,reg_1); /* mul */ + else { + as_move_r_r (REGISTER_A1,REGISTER_O0); + as_r (0367,040,reg_1); /* mul */ + as_2move_registers (REGISTER_O0,REGISTER_A1,reg_1); + } + } else if (reg_1==REGISTER_A1){ + as_2move_registers (reg_2,REGISTER_D0,REGISTER_O0); + as_r (0367,040,reg_1); /* mul */ + as_2move_registers (REGISTER_O0,REGISTER_D0,reg_2); + } else if (reg_1==REGISTER_D0){ + if (reg_2==REGISTER_A1){ + as_r (0367,040,REGISTER_A1); /* mul */ + store_c (0x90+reg_num (REGISTER_A1)); /* xchg A1,D0 */ + } else { + as_move_r_r (REGISTER_A1,REGISTER_O0); + as_r (0367,040,reg_2); /* mul */ + as_3move_registers (REGISTER_O0,REGISTER_A1,REGISTER_D0,reg_2); + } + } else if (reg_2==REGISTER_A1){ + as_2move_registers (reg_2,REGISTER_D0,REGISTER_O0); + as_r (0367,040,reg_1); /* mul */ + as_3move_registers (REGISTER_O0,REGISTER_D0,REGISTER_A1,reg_1); + } else { + store_c (0x90+reg_num (reg_2)); /* xchg reg_2,D0 */ + as_move_r_r (REGISTER_A1,REGISTER_O0); + as_r (0367,040,reg_1); /* mul */ + store_c (0x90+reg_num (reg_2)); /* xchg reg_2,D0 */ + as_2move_registers (REGISTER_O0,REGISTER_A1,reg_1); + } +} + +static void as_divdu_instruction (struct instruction *instruction) +{ + int reg_1,reg_2,reg_3; + + reg_1=instruction->instruction_parameters[0].parameter_data.reg.r; + reg_2=instruction->instruction_parameters[1].parameter_data.reg.r; + reg_3=instruction->instruction_parameters[2].parameter_data.reg.r; + + if (reg_1==REGISTER_D0){ + if (reg_3==REGISTER_D0){ + if (reg_2==REGISTER_A1) + as_r (0367,0060,reg_1); /* div */ + else { + as_2move_registers (reg_2,REGISTER_A1,REGISTER_O0); + as_r (0367,0060,reg_1); /* div */ + as_2move_registers (REGISTER_O0,REGISTER_A1,reg_2); + } + } else if (reg_3==REGISTER_A1){ + if (reg_2==REGISTER_D0){ + store_c (0x90+reg_num (REGISTER_A1)); /* xchg A1,D0 */ + as_r (0367,0060,REGISTER_A1); /* div */ + store_c (0x90+reg_num (REGISTER_A1)); /* xchg A1,D0 */ + } else { + as_3move_registers (reg_2,REGISTER_A1,REGISTER_D0,REGISTER_O0); + as_r (0367,0060,REGISTER_O0); /* div */ + as_3move_registers (REGISTER_O0,REGISTER_D0,REGISTER_A1,reg_2); + } + } else { + if (reg_2==REGISTER_A1){ + as_2move_registers (reg_3,REGISTER_D0,REGISTER_O0); + as_r (0367,0060,REGISTER_O0); /* div */ + as_2move_registers (REGISTER_O0,REGISTER_D0,reg_3); + } else if (reg_2==REGISTER_D0){ + as_3move_registers (reg_3,REGISTER_D0,REGISTER_A1,REGISTER_O0); + as_r (0367,0060,REGISTER_A1); /* div */ + as_3move_registers (REGISTER_O0,REGISTER_A1,REGISTER_D0,reg_3); + } else { + store_c (0x90+reg_num (reg_3)); /* xchg reg_3,D0 */ + as_2move_registers (reg_2,REGISTER_A1,REGISTER_O0); + as_r (0367,0060,reg_3); /* div */ + as_2move_registers (REGISTER_O0,REGISTER_A1,reg_2); + store_c (0x90+reg_num (reg_3)); /* xchg reg_3,D0 */ + } + } + } else if (reg_1==REGISTER_A1){ + if (reg_2==REGISTER_A1){ + if (reg_3==REGISTER_D0) + as_r (0367,0060,reg_1); /* div */ + else { + as_2move_registers (reg_3,REGISTER_D0,REGISTER_O0); + as_r (0367,0060,reg_1); /* div */ + as_2move_registers (REGISTER_O0,REGISTER_D0,reg_3); + } + } else if (reg_2==REGISTER_D0){ + if (reg_3==REGISTER_A1){ + store_c (0x90+reg_num (REGISTER_A1)); /* xchg A1,D0 */ + as_r (0367,0060,REGISTER_D0); /* div */ + store_c (0x90+reg_num (REGISTER_A1)); /* xchg A1,D0 */ + } else { + as_3move_registers (reg_3,REGISTER_D0,REGISTER_A1,REGISTER_O0); + as_r (0367,0060,REGISTER_O0); /* div */ + as_3move_registers (REGISTER_O0,REGISTER_A1,REGISTER_D0,reg_3); + } + } else { + if (reg_3==REGISTER_D0){ + as_2move_registers (reg_2,REGISTER_A1,REGISTER_O0); + as_r (0367,0060,REGISTER_O0); /* div */ + as_2move_registers (REGISTER_O0,REGISTER_A1,reg_2); + } else if (reg_3==REGISTER_A1){ + as_3move_registers (reg_2,REGISTER_A1,REGISTER_D0,REGISTER_O0); + as_r (0367,0060,REGISTER_D0); /* div */ + as_3move_registers (REGISTER_O0,REGISTER_D0,REGISTER_A1,reg_2); + } else { + as_r_r (0207,reg_2,REGISTER_A1); /* xchg */ + as_2move_registers (reg_3,REGISTER_D0,REGISTER_O0); + as_r (0367,0060,reg_2); /* div */ + as_2move_registers (REGISTER_O0,REGISTER_D0,reg_3); + as_r_r (0207,reg_2,REGISTER_A1); /* xchg */ + } + } + } else { + if (reg_3==REGISTER_D0){ + if (reg_2==REGISTER_A1){ + as_r (0367,0060,reg_1); /* div */ + } else { + as_2move_registers (reg_2,REGISTER_A1,REGISTER_O0); + as_r (0367,0060,reg_1); /* div */ + as_2move_registers (REGISTER_O0,REGISTER_A1,reg_2); + } + } else if (reg_2==REGISTER_A1){ + as_2move_registers (reg_3,REGISTER_D0,REGISTER_O0); + as_r (0367,0060,reg_1); /* div */ + as_2move_registers (REGISTER_O0,REGISTER_D0,reg_3); + } else if (reg_2==REGISTER_D0){ + if (reg_3==REGISTER_A1){ + store_c (0x90+reg_num (REGISTER_A1)); /* xchg A1,D0 */ + as_r (0367,0060,reg_1); /* div */ + store_c (0x90+reg_num (REGISTER_A1)); /* xchg A1,D0 */ + } else { + as_3move_registers (reg_3,REGISTER_D0,REGISTER_A1,REGISTER_O0); + as_r (0367,0060,reg_1); /* div */ + as_3move_registers (REGISTER_O0,REGISTER_A1,REGISTER_D0,reg_3); + } + } else if (reg_2==REGISTER_A1){ + as_3move_registers (reg_3,REGISTER_A1,REGISTER_D0,REGISTER_O0); + as_r (0367,0060,reg_1); /* div */ + as_3move_registers (REGISTER_O0,REGISTER_D0,REGISTER_A1,reg_3); + } else { + store_c (0x90+reg_num (reg_3)); /* xchg reg_3,D0 */ + as_2move_registers (reg_2,REGISTER_A1,REGISTER_O0); + as_r (0367,0060,reg_1); /* div */ + as_2move_registers (REGISTER_O0,REGISTER_A1,reg_2); + store_c (0x90+reg_num (reg_3)); /* xchg reg_3,D0 */ + } + } +} + static void as_set_condition_instruction (struct instruction *instruction,int condition_code) { int r; @@ -3970,6 +4141,12 @@ static void as_instructions (struct instruction *instruction) case INOT: as_not_instruction (instruction); break; + case IMULUD: + as_mulud_instruction (instruction); + break; + case IDIVDU: + as_divdu_instruction (instruction); + break; case IWORD: store_c (instruction->instruction_parameters[0].parameter_data.i); break; @@ -4179,6 +4356,135 @@ static void as_check_stack (struct basic_block *block) } } +static void as_profile_call (struct basic_block *block) +{ + LABEL *profile_label; + + as_move_d_r (block->block_profile_function_label,0,REGISTER_A2); + + if (block->block_n_node_arguments>-100) + profile_label=block->block_profile==2 ? profile_n2_label : profile_n_label; + else { + switch (block->block_profile){ + case 2: profile_label=profile_s2_label; break; + case 4: profile_label=profile_l_label; break; + case 5: profile_label=profile_l2_label; break; + default: profile_label=profile_s_label; + } + } + store_c (0350); + store_l (0); + as_branch_label (profile_label,CALL_RELOCATION); +} + +#ifdef NEW_APPLY +extern LABEL *add_empty_node_labels[]; + +static void as_apply_update_entry (struct basic_block *block) +{ + if (block->block_profile) + as_profile_call (block); + + if (block->block_n_node_arguments==-200){ + store_c (0351); + store_l (0); + as_branch_label (block->block_ea_label,JUMP_RELOCATION); + + store_c (0x90); + store_c (0x90); + store_c (0x90); + store_c (0x90); + store_c (0x90); + } else { + store_c (0350); /* call */ + store_l (0); + as_branch_label (add_empty_node_labels[block->block_n_node_arguments+200],CALL_RELOCATION); + + store_c (0351); + store_l (0); + as_branch_label (block->block_ea_label,JUMP_RELOCATION); + } + + if (!block->block_profile){ + store_c (0x90); + store_c (0x90); + } +} +#endif + +static void as_node_entry_info (struct basic_block *block) +{ + if (block->block_ea_label!=NULL){ + extern LABEL *eval_fill_label,*eval_upd_labels[]; + int n_node_arguments; + + n_node_arguments=block->block_n_node_arguments; + if (n_node_arguments<-2) + n_node_arguments=1; + + if (n_node_arguments>=0 && block->block_ea_label!=eval_fill_label){ +#if 1 + if (!block->block_profile){ + as_move_l_r (block->block_ea_label,REGISTER_A2); + + store_c (0351); + store_l (0); + as_branch_label (eval_upd_labels[n_node_arguments],JUMP_RELOCATION); + + store_c (0x90); + store_c (0x90); + } else { + store_c (0351); + store_l (-7); + as_branch_label (eval_upd_labels[n_node_arguments],JUMP_RELOCATION); + + store_c (0x90); + store_c (0x90); + store_c (0x90); + + as_move_l_r (block->block_ea_label,REGISTER_D0); + as_move_l_r (block->block_profile_function_label,REGISTER_A2); + + store_c (0xeb); + store_c (-20); + } +#else + as_move_l_r (eval_upd_labels[n_node_arguments],REGISTER_D0); + as_move_l_r (block->block_ea_label,REGISTER_A2); + + store_c (0377); + store_c (0340 | reg_num (REGISTER_D0)); /* jmp d0 */ +#endif + } else { + as_move_l_r (block->block_ea_label,REGISTER_D0); + + store_c (0377); + store_c (0340 | reg_num (REGISTER_D0)); /* jmp d0 */ + + store_c (0x90); + store_c (0x90); + store_c (0x90); + store_c (0x90); + store_c (0x90); + } + + if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)){ + store_l (0); + store_label_in_code_section (block->block_descriptor); + } else + store_l (0); + } else + if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)){ + store_l (0); + store_label_in_code_section (block->block_descriptor); + } + /* else + store_l (0); + */ + + store_l (block->block_n_node_arguments); +} + static void write_code (void) { struct basic_block *block; @@ -4294,98 +4600,17 @@ static void write_code (void) store_c (0x90); #endif - if (block->block_ea_label!=NULL){ - extern LABEL *eval_fill_label,*eval_upd_labels[]; - int n_node_arguments; - - n_node_arguments=block->block_n_node_arguments; - if (n_node_arguments<-2) - n_node_arguments=1; - - if (n_node_arguments>=0 && block->block_ea_label!=eval_fill_label){ -#if 1 - if (!block->block_profile){ - as_move_l_r (block->block_ea_label,REGISTER_A2); - - store_c (0351); - store_l (0); - as_branch_label (eval_upd_labels[n_node_arguments],JUMP_RELOCATION); - - store_c (0x90); - store_c (0x90); - } else { - store_c (0351); - store_l (-7); - as_branch_label (eval_upd_labels[n_node_arguments],JUMP_RELOCATION); - - store_c (0x90); - store_c (0x90); - store_c (0x90); - - as_move_l_r (block->block_ea_label,REGISTER_D0); - as_move_l_r (block->block_profile_function_label,REGISTER_A2); - - store_c (0xeb); - store_c (-20); - } -#else - as_move_l_r (eval_upd_labels[n_node_arguments],REGISTER_D0); - as_move_l_r (block->block_ea_label,REGISTER_A2); - - store_c (0377); - store_c (0340 | reg_num (REGISTER_D0)); /* jmp d0 */ -#endif - } else { - as_move_l_r (block->block_ea_label,REGISTER_D0); - - store_c (0377); - store_c (0340 | reg_num (REGISTER_D0)); /* jmp d0 */ - - store_c (0x90); - store_c (0x90); - store_c (0x90); - store_c (0x90); - store_c (0x90); - } - - if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)){ - store_l (0); - store_label_in_code_section (block->block_descriptor); - } else - store_l (0); - } else - if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)){ - store_l (0); - store_label_in_code_section (block->block_descriptor); - } - /* else - store_l (0); - */ - - store_l (block->block_n_node_arguments); + as_node_entry_info (block); } +#ifdef NEW_APPLY + else if (block->block_n_node_arguments<-100) + as_apply_update_entry (block); +#endif as_labels (block->block_labels); - if (block->block_profile){ - LABEL *profile_label; - - as_move_d_r (block->block_profile_function_label,0,REGISTER_A2); - - if (block->block_n_node_arguments>-100) - profile_label=block->block_profile==2 ? profile_n2_label : profile_n_label; - else { - switch (block->block_profile){ - case 2: profile_label=profile_s2_label; break; - case 4: profile_label=profile_l_label; break; - case 5: profile_label=profile_l2_label; break; - default: profile_label=profile_s_label; - } - } - store_c (0350); - store_l (0); - as_branch_label (profile_label,CALL_RELOCATION); - } + if (block->block_profile) + as_profile_call (block); if (block->block_n_new_heap_cells>0) as_garbage_collect_test (block); @@ -55,7 +55,7 @@ enum { ,IFEXG #endif #if defined (I486) - ,IRTSI, IDIVI, IREMI, IREMU + ,IRTSI, IDIVI, IREMI, IREMU, IMULUD, IDIVDU #endif #if defined (I486) || defined (G_POWER) ,IDIVU @@ -1168,6 +1168,22 @@ static int parse_directive (InstructionP instruction) return 1; } +#ifdef NEW_APPLY +static int parse_directive_a (InstructionP instruction) +{ + LONG n; + STRING s; + + if (!parse_integer (&n)) + return 0; + + parse_label (s); + instruction->instruction_code_function ((int)n,s); + + return 1; +} +#endif + static int parse_directive_n (InstructionP instruction) { LONG n; @@ -1761,6 +1777,9 @@ static void put_instructions_in_table (void) put_instruction_name ("decI", parse_instruction, code_decI ); put_instruction_name ("del_args", parse_instruction_n_n_n, code_del_args ); put_instruction_name ("divI", parse_instruction, code_divI ); +#ifdef I486 + put_instruction_name ("divLU", parse_instruction, code_divLU ); +#endif put_instruction_name ("divR", parse_instruction, code_divR ); #if defined (I486) || defined (G_POWER) put_instruction_name ("divU", parse_instruction, code_divU ); @@ -1832,13 +1851,13 @@ static void put_instructions_in_table (void) put_instruction_name ("ItoP", parse_instruction, code_ItoP ); put_instruction_name ("ItoR", parse_instruction, code_ItoR ); put_instruction_name ("jmp", parse_instruction_a, code_jmp ); - put_instruction_name ("jmp_ap", parse_instruction, code_jmp_ap ); + put_instruction_name ("jmp_ap", parse_instruction_n, code_jmp_ap ); put_instruction_name ("jmp_eval", parse_instruction, code_jmp_eval ); put_instruction_name ("jmp_eval_upd", parse_instruction, code_jmp_eval_upd ); put_instruction_name ("jmp_false", parse_instruction_a, code_jmp_false ); put_instruction_name ("jmp_true", parse_instruction_a, code_jmp_true ); put_instruction_name ("jsr", parse_instruction_a, code_jsr ); - put_instruction_name ("jsr_ap", parse_instruction, code_jsr_ap ); + put_instruction_name ("jsr_ap", parse_instruction_n, code_jsr_ap ); put_instruction_name ("jsr_eval", parse_instruction_n, code_jsr_eval ); put_instruction_name ("lnR", parse_instruction, code_lnR ); put_instruction_name ("log10R", parse_instruction, code_log10R ); @@ -1851,6 +1870,9 @@ static void put_instructions_in_table (void) 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) + put_instruction_name ("mulUUL", parse_instruction, code_mulUUL ); +#endif put_instruction_name ("negI", parse_instruction, code_negI ); put_instruction_name ("negR", parse_instruction, code_negR ); put_instruction_name ("new_ext_reducer",parse_instruction_a_n, code_new_ext_reducer ); @@ -1970,13 +1992,13 @@ static void put_instructions_in_table2 (void) put_instruction_name ("updatepop_b", parse_instruction_n_n, code_updatepop_b ); put_instruction_name ("updateS", parse_instruction_n_n, code_updateS ); put_instruction_name ("update", parse_instruction_a_n_n, code_update ); -#ifdef G_POWER - put_instruction_name ("umulIIL", parse_instruction, code_umulIIL ); -#endif put_instruction_name ("xor%", parse_instruction, code_xor ); put_instruction_name (".caf", parse_instruction_a_n_n, code_caf ); put_instruction_name (".code", parse_directive_n_n_n, code_dummy ); put_instruction_name (".comp", parse_directive_n_l, code_comp ); +#ifdef NEW_APPLY + put_instruction_name (".a", parse_directive_a, code_a ); +#endif put_instruction_name (".d", parse_directive_n_n_t, code_d ); put_instruction_name (".depend", parse_directive_depend, code_depend ); put_instruction_name (".desc", parse_directive_desc, code_desc ); @@ -734,6 +734,13 @@ static void w_as_register_register_newline (int reg1,int reg2) w_as_newline(); } +static void w_as_opcode_register_newline (char *opcode,int reg1) +{ + w_as_opcode (opcode); + w_as_register (reg1); + w_as_newline(); +} + static void w_as_opcode_register_register_newline (char *opcode,int reg1,int reg2) { w_as_opcode (opcode); @@ -2045,6 +2052,177 @@ static void w_as_rem_instruction (struct instruction *instruction,int unsigned_r } } +static void w_as_2movl_registers (int reg1,int reg2,int reg3) +{ + w_as_movl_register_register_newline (reg2,reg3); + w_as_movl_register_register_newline (reg1,reg2); +} + +static void w_as_3movl_registers (int reg1,int reg2,int reg3,int reg4) +{ + w_as_movl_register_register_newline (reg3,reg4); + w_as_movl_register_register_newline (reg2,reg3); + w_as_movl_register_register_newline (reg1,reg2); +} + +static void w_as_mulud_instruction (struct instruction *instruction) +{ + int reg_1,reg_2; + + reg_1=instruction->instruction_parameters[0].parameter_data.reg.r; + reg_2=instruction->instruction_parameters[1].parameter_data.reg.r; + + if (reg_2==REGISTER_D0){ + if (reg_1==REGISTER_A1){ + w_as_opcode_register_newline ("mul",reg_1); + } else { + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("mul",reg_1); + w_as_2movl_registers (REGISTER_O0,REGISTER_A1,reg_1); + } + } else if (reg_1==REGISTER_A1){ + w_as_2movl_registers (reg_2,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("mul",reg_1); + w_as_2movl_registers (REGISTER_O0,REGISTER_D0,reg_2); + } else if (reg_1==REGISTER_D0){ + if (reg_2==REGISTER_A1){ + w_as_opcode_register_newline ("mul",REGISTER_A1); + w_as_opcode_register_register_newline ("xchg",REGISTER_A1,REGISTER_D0); + } else { + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("mul",reg_2); + w_as_3movl_registers (REGISTER_O0,REGISTER_A1,REGISTER_D0,reg_2); + } + } else if (reg_2==REGISTER_A1){ + w_as_2movl_registers (reg_2,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("mul",reg_1); + w_as_3movl_registers (REGISTER_O0,REGISTER_D0,REGISTER_A1,reg_1); + } else { + w_as_opcode_register_register_newline ("xchg",reg_2,REGISTER_D0); + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("mul",reg_1); + w_as_opcode_register_register_newline ("xchg",reg_2,REGISTER_D0); + w_as_2movl_registers (REGISTER_O0,REGISTER_A1,reg_1); + } +} + +static void w_as_divdu_instruction (struct instruction *instruction) +{ + int reg_1,reg_2,reg_3; + + reg_1=instruction->instruction_parameters[0].parameter_data.reg.r; + reg_2=instruction->instruction_parameters[1].parameter_data.reg.r; + reg_3=instruction->instruction_parameters[2].parameter_data.reg.r; + + if (reg_1==REGISTER_D0){ + if (reg_3==REGISTER_D0){ + if (reg_2==REGISTER_A1) + w_as_opcode_register_newline ("div",reg_1); + else { + w_as_2movl_registers (reg_2,REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_1); + w_as_2movl_registers (REGISTER_O0,REGISTER_A1,reg_2); + } + } else if (reg_3==REGISTER_A1){ + if (reg_2==REGISTER_D0){ + w_as_opcode_register_register_newline ("xchg",REGISTER_A1,REGISTER_D0); + w_as_opcode_register_newline ("div",REGISTER_A1); + w_as_opcode_register_register_newline ("xchg",REGISTER_A1,REGISTER_D0); + } else { + w_as_3movl_registers (reg_2,REGISTER_A1,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("div",REGISTER_O0); + w_as_3movl_registers (REGISTER_O0,REGISTER_D0,REGISTER_A1,reg_2); + } + } else { + if (reg_2==REGISTER_A1){ + w_as_2movl_registers (reg_3,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("div",REGISTER_O0); + w_as_2movl_registers (REGISTER_O0,REGISTER_D0,reg_3); + } else if (reg_2==REGISTER_D0){ + w_as_3movl_registers (reg_3,REGISTER_D0,REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("div",REGISTER_A1); + w_as_3movl_registers (REGISTER_O0,REGISTER_A1,REGISTER_D0,reg_3); + } else { + w_as_opcode_register_register_newline ("xchg",reg_3,REGISTER_D0); + w_as_2movl_registers (reg_2,REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_3); + w_as_2movl_registers (REGISTER_O0,REGISTER_A1,reg_2); + w_as_opcode_register_register_newline ("xchg",reg_3,REGISTER_D0); + } + } + } else if (reg_1==REGISTER_A1){ + if (reg_2==REGISTER_A1){ + if (reg_3==REGISTER_D0) + w_as_opcode_register_newline ("div",reg_1); + else { + w_as_2movl_registers (reg_3,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_1); + w_as_2movl_registers (REGISTER_O0,REGISTER_D0,reg_3); + } + } else if (reg_2==REGISTER_D0){ + if (reg_3==REGISTER_A1){ + w_as_opcode_register_register_newline ("xchg",REGISTER_A1,REGISTER_D0); + w_as_opcode_register_newline ("div",REGISTER_D0); + w_as_opcode_register_register_newline ("xchg",REGISTER_A1,REGISTER_D0); + } else { + w_as_3movl_registers (reg_3,REGISTER_D0,REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("div",REGISTER_O0); + w_as_3movl_registers (REGISTER_O0,REGISTER_A1,REGISTER_D0,reg_3); + } + } else { + if (reg_3==REGISTER_D0){ + w_as_2movl_registers (reg_2,REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("div",REGISTER_O0); + w_as_2movl_registers (REGISTER_O0,REGISTER_A1,reg_2); + } else if (reg_3==REGISTER_A1){ + w_as_3movl_registers (reg_2,REGISTER_A1,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("div",REGISTER_D0); + w_as_3movl_registers (REGISTER_O0,REGISTER_D0,REGISTER_A1,reg_2); + } else { + w_as_opcode_register_register_newline ("xchg",reg_2,REGISTER_A1); + w_as_2movl_registers (reg_3,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_2); + w_as_2movl_registers (REGISTER_O0,REGISTER_D0,reg_3); + w_as_opcode_register_register_newline ("xchg",reg_2,REGISTER_A1); + } + } + } else { + if (reg_3==REGISTER_D0){ + if (reg_2==REGISTER_A1){ + w_as_opcode_register_newline ("div",reg_1); + } else { + w_as_2movl_registers (reg_2,REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_1); + w_as_2movl_registers (REGISTER_O0,REGISTER_A1,reg_2); + } + } else if (reg_2==REGISTER_A1){ + w_as_2movl_registers (reg_3,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_1); + w_as_2movl_registers (REGISTER_O0,REGISTER_D0,reg_3); + } else if (reg_2==REGISTER_D0){ + if (reg_3==REGISTER_A1){ + w_as_opcode_register_register_newline ("xchg",REGISTER_A1,REGISTER_D0); + w_as_opcode_register_newline ("div",reg_1); + w_as_opcode_register_register_newline ("xchg",REGISTER_A1,REGISTER_D0); + } else { + w_as_3movl_registers (reg_3,REGISTER_D0,REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_1); + w_as_3movl_registers (REGISTER_O0,REGISTER_A1,REGISTER_D0,reg_3); + } + } else if (reg_2==REGISTER_A1){ + w_as_3movl_registers (reg_3,REGISTER_A1,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_1); + w_as_3movl_registers (REGISTER_O0,REGISTER_D0,REGISTER_A1,reg_3); + } else { + w_as_opcode_register_register_newline ("xchg",reg_3,REGISTER_D0); + w_as_2movl_registers (reg_2,REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_1); + w_as_2movl_registers (REGISTER_O0,REGISTER_A1,reg_2); + w_as_opcode_register_register_newline ("xchg",reg_3,REGISTER_D0); + } + } +} + static void w_as_word_instruction (struct instruction *instruction) { fprintf (assembly_file,"\t.byte\t%d\n", @@ -3071,6 +3249,12 @@ static void w_as_instructions (register struct instruction *instruction) case INOT: w_as_monadic_instruction (instruction,intel_asm ? "not" : "notl"); break; + case IMULUD: + w_as_mulud_instruction (instruction); + break; + case IDIVDU: + w_as_divdu_instruction (instruction); + break; case IFMOVE: instruction=w_as_fmove_instruction (instruction); break; @@ -3501,6 +3685,170 @@ static void w_as_import_labels (struct label_node *label_node) w_as_import_labels (label_node->label_node_right); } +static void w_as_node_entry_info (struct basic_block *block) +{ + if (block->block_ea_label!=NULL){ + int n_node_arguments; + + n_node_arguments=block->block_n_node_arguments; + if (n_node_arguments<-2) + n_node_arguments=1; + + if (n_node_arguments>=0 && block->block_ea_label!=eval_fill_label){ +#if 1 + if (!block->block_profile){ + w_as_opcode_movl(); + if (intel_asm) + w_as_register_comma (REGISTER_A2); + w_as_immediate_label (block->block_ea_label->label_name); + if (!intel_asm) + w_as_comma_register (REGISTER_A2); + w_as_newline(); + + w_as_opcode ("jmp"); + w_as_label (eval_upd_labels[n_node_arguments]->label_name); + w_as_newline(); + + w_as_instruction_without_parameters ("nop"); + w_as_instruction_without_parameters ("nop"); + } else { + w_as_opcode ("jmp"); + w_as_label (eval_upd_labels[n_node_arguments]->label_name); + fprintf (assembly_file,"-7"); + w_as_newline(); + + w_as_instruction_without_parameters ("nop"); + w_as_instruction_without_parameters ("nop"); + w_as_instruction_without_parameters ("nop"); + + w_as_opcode_movl(); + if (intel_asm) + w_as_register_comma (REGISTER_D0); + w_as_immediate_label (block->block_ea_label->label_name); + if (!intel_asm) + w_as_comma_register (REGISTER_D0); + w_as_newline(); + + w_as_opcode_movl(); + if (intel_asm) + w_as_register_comma (REGISTER_A2); + w_as_descriptor (block->block_profile_function_label,0); + if (!intel_asm) + w_as_comma_register (REGISTER_A2); + w_as_newline(); + + w_as_opcode ("jmp"); + fprintf (assembly_file,".-18"); + w_as_newline(); + } +#else + w_as_opcode_movl(); + if (intel_asm) + w_as_register_comma (REGISTER_D0); + w_as_immediate_label (eval_upd_labels[n_node_arguments]->label_name); + if (!intel_asm) + w_as_comma_register (REGISTER_D0); + w_as_newline(); + + w_as_opcode_movl(); + if (intel_asm) + w_as_register_comma (REGISTER_A2); + w_as_immediate_label (block->block_ea_label->label_name); + if (!intel_asm) + w_as_comma_register (REGISTER_A2); + w_as_newline(); + + w_as_opcode ("jmp"); + w_as_register (REGISTER_D0); + w_as_newline(); +#endif + } else { + w_as_opcode_movl(); + if (intel_asm) + w_as_register_comma (REGISTER_D0); + w_as_immediate_label (block->block_ea_label->label_name); + if (!intel_asm) + w_as_comma_register (REGISTER_D0); + w_as_newline(); + + w_as_opcode ("jmp"); + w_as_register (REGISTER_D0); + w_as_newline(); + + w_as_space (5); + } + + if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)) + w_as_label_in_code_section (block->block_descriptor->label_name); + else + w_as_number_of_arguments (0); + } else + if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)) + w_as_label_in_code_section (block->block_descriptor->label_name); + + w_as_number_of_arguments (block->block_n_node_arguments); +} + +static void w_as_profile_call (struct basic_block *block) +{ + w_as_opcode_movl(); + if (intel_asm) + w_as_scratch_register_comma(); + w_as_descriptor (block->block_profile_function_label,0); + if (!intel_asm) + w_as_comma_scratch_register(); + w_as_newline(); + + w_as_opcode ("call"); + + if (block->block_n_node_arguments>-100) + w_as_label (block->block_profile==2 ? "profile_n2" : "profile_n"); + else { + switch (block->block_profile){ + case 2: w_as_label ("profile_s2"); break; + case 4: w_as_label ("profile_l"); break; + case 5: w_as_label ("profile_l2"); break; + default: w_as_label ("profile_s"); + } + } + w_as_newline(); +} + +#ifdef NEW_APPLY +extern LABEL *add_empty_node_labels[]; + +static void w_as_apply_update_entry (struct basic_block *block) +{ + if (block->block_profile) + w_as_profile_call (block); + + if (block->block_n_node_arguments==-200){ + w_as_opcode ("jmp"); + w_as_label (block->block_ea_label->label_name); + w_as_newline(); + + w_as_instruction_without_parameters ("nop"); + w_as_instruction_without_parameters ("nop"); + w_as_instruction_without_parameters ("nop"); + w_as_instruction_without_parameters ("nop"); + w_as_instruction_without_parameters ("nop"); + } else { + w_as_opcode ("call"); + w_as_label (add_empty_node_labels[block->block_n_node_arguments+200]->label_name); + w_as_newline(); + + w_as_opcode ("jmp"); + w_as_label (block->block_ea_label->label_name); + w_as_newline(); + } + + if (!block->block_profile){ + w_as_instruction_without_parameters ("nop"); + w_as_instruction_without_parameters ("nop"); + } +} +#endif + void write_assembly (VOID) { struct basic_block *block; @@ -3523,135 +3871,17 @@ void write_assembly (VOID) for_l (block,first_block,block_next){ if (block->block_n_node_arguments>-100){ w_as_align (2); - - if (block->block_ea_label!=NULL){ - int n_node_arguments; - - n_node_arguments=block->block_n_node_arguments; - if (n_node_arguments<-2) - n_node_arguments=1; - - if (n_node_arguments>=0 && block->block_ea_label!=eval_fill_label){ -#if 1 - if (!block->block_profile){ - w_as_opcode_movl(); - if (intel_asm) - w_as_register_comma (REGISTER_A2); - w_as_immediate_label (block->block_ea_label->label_name); - if (!intel_asm) - w_as_comma_register (REGISTER_A2); - w_as_newline(); - - w_as_opcode ("jmp"); - w_as_label (eval_upd_labels[n_node_arguments]->label_name); - w_as_newline(); - - w_as_instruction_without_parameters ("nop"); - w_as_instruction_without_parameters ("nop"); - } else { - w_as_opcode ("jmp"); - w_as_label (eval_upd_labels[n_node_arguments]->label_name); - fprintf (assembly_file,"-7"); - w_as_newline(); - - w_as_instruction_without_parameters ("nop"); - w_as_instruction_without_parameters ("nop"); - w_as_instruction_without_parameters ("nop"); - - w_as_opcode_movl(); - if (intel_asm) - w_as_register_comma (REGISTER_D0); - w_as_immediate_label (block->block_ea_label->label_name); - if (!intel_asm) - w_as_comma_register (REGISTER_D0); - w_as_newline(); - - w_as_opcode_movl(); - if (intel_asm) - w_as_register_comma (REGISTER_A2); - w_as_descriptor (block->block_profile_function_label,0); - if (!intel_asm) - w_as_comma_register (REGISTER_A2); - w_as_newline(); - - w_as_opcode ("jmp"); - fprintf (assembly_file,".-18"); - w_as_newline(); - } -#else - w_as_opcode_movl(); - if (intel_asm) - w_as_register_comma (REGISTER_D0); - w_as_immediate_label (eval_upd_labels[n_node_arguments]->label_name); - if (!intel_asm) - w_as_comma_register (REGISTER_D0); - w_as_newline(); - - w_as_opcode_movl(); - if (intel_asm) - w_as_register_comma (REGISTER_A2); - w_as_immediate_label (block->block_ea_label->label_name); - if (!intel_asm) - w_as_comma_register (REGISTER_A2); - w_as_newline(); - - w_as_opcode ("jmp"); - w_as_register (REGISTER_D0); - w_as_newline(); -#endif - } else { - w_as_opcode_movl(); - if (intel_asm) - w_as_register_comma (REGISTER_D0); - w_as_immediate_label (block->block_ea_label->label_name); - if (!intel_asm) - w_as_comma_register (REGISTER_D0); - w_as_newline(); - - w_as_opcode ("jmp"); - w_as_register (REGISTER_D0); - w_as_newline(); - - w_as_space (5); - } - - if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)) - w_as_label_in_code_section (block->block_descriptor->label_name); - else - w_as_number_of_arguments (0); - } else - - if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)) - w_as_label_in_code_section (block->block_descriptor->label_name); - - w_as_number_of_arguments (block->block_n_node_arguments); + w_as_node_entry_info (block); } +#ifdef NEW_APPLY + else if (block->block_n_node_arguments<-100) + w_as_apply_update_entry (block); +#endif w_as_labels (block->block_labels); - if (block->block_profile){ - w_as_opcode_movl(); - if (intel_asm) - w_as_scratch_register_comma(); - w_as_descriptor (block->block_profile_function_label,0); - if (!intel_asm) - w_as_comma_scratch_register(); - w_as_newline(); - - w_as_opcode ("call"); - - if (block->block_n_node_arguments>-100) - w_as_label (block->block_profile==2 ? "profile_n2" : "profile_n"); - else { - switch (block->block_profile){ - case 2: w_as_label ("profile_s2"); break; - case 4: w_as_label ("profile_l"); break; - case 5: w_as_label ("profile_l2"); break; - default: w_as_label ("profile_s"); - } - } - w_as_newline(); - } + if (block->block_profile) + w_as_profile_call (block); if (block->block_n_new_heap_cells>0) w_as_garbage_collect_test (block); @@ -78,7 +78,7 @@ static struct instruction *i_new_instruction (int instruction_code,int arity,int static struct instruction *i_new_instruction1 (int instruction_code) { - register struct instruction *instruction; + struct instruction *instruction; instruction=(struct instruction*)fast_memory_allocate (sizeof (struct instruction)+sizeof (struct parameter)); @@ -98,7 +98,7 @@ static struct instruction *i_new_instruction1 (int instruction_code) static struct instruction *i_new_instruction2 (int instruction_code) { - register struct instruction *instruction; + struct instruction *instruction; instruction=(struct instruction*)fast_memory_allocate (sizeof (struct instruction)+2*sizeof (struct parameter)); @@ -116,6 +116,26 @@ static struct instruction *i_new_instruction2 (int instruction_code) return instruction; } +static struct instruction *i_new_instruction3 (int instruction_code) +{ + struct instruction *instruction; + + instruction=(struct instruction*)fast_memory_allocate (sizeof (struct instruction)+3*sizeof (struct parameter)); + + U4(instruction, instruction_next=NULL, + instruction_prev=last_instruction, + instruction_icode=instruction_code, + instruction_arity=3); + + if (last_block->block_instructions==NULL) + last_block->block_instructions=instruction; + else + last_instruction->instruction_next=instruction; + last_instruction=instruction; + + return instruction; +} + void i_add_i_r (LONG value,int register_1) { struct instruction *instruction; @@ -807,6 +827,24 @@ void i_call_r (int register_1,int frame_size) } #endif +#ifdef I486 +void i_divdu_r_r_r (int register_1,int register_2,int register_3) +{ + struct instruction *instruction; + + instruction=i_new_instruction3 (IDIVDU); + + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_2); + + S2 (instruction->instruction_parameters[2], parameter_type=P_REGISTER, + parameter_data.i=register_3); +} +#endif + void i_lea_id_r (int offset,int register_1,int register_2) { register struct instruction *instruction; @@ -1574,6 +1612,21 @@ void i_movew_r_pd (int register_1,int register_2) } #endif +#ifdef I486 +void i_mulud_r_r (int register_1,int register_2) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IMULUD); + + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_2); +} +#endif + #ifdef G_POWER void i_or_i_r (LONG value,int register_1) { @@ -2256,7 +2309,7 @@ static void instruction_ad_pi (int instruction_code,ADDRESS *ad_p,int register_1 static void instruction_ad_r (int instruction_code,ADDRESS *ad_p,int register_1) { - register struct instruction *instruction; + struct instruction *instruction; instruction=i_new_instruction2 (instruction_code); @@ -2314,7 +2367,7 @@ static void instruction_l (int instruction_code,LABEL *label) static void instruction_ad_r_r (int instruction_code,ADDRESS *ad_p,int register_1,int register_2) { - register struct instruction *instruction; + struct instruction *instruction; instruction=i_new_instruction (instruction_code,3,3*sizeof (struct parameter)); @@ -2329,7 +2382,7 @@ static void instruction_ad_r_r (int instruction_code,ADDRESS *ad_p,int register_ static void instruction_r (int instruction_code,int register_1) { - register struct instruction *instruction; + struct instruction *instruction; instruction=i_new_instruction1 (instruction_code); @@ -2522,7 +2575,7 @@ static void in_data_register (register ADDRESS *ad_p) ad_p->ad_count=1; } -static void in_alterable_data_register (register ADDRESS *ad_p) +static void in_alterable_data_register (ADDRESS *ad_p) { int dreg; @@ -2615,6 +2668,119 @@ static void in_alterable_data_register (register ADDRESS *ad_p) ad_p->ad_count=1; } +#ifdef I486 +static void in_preferred_alterable_register (ADDRESS *ad_p,int preferred_reg) +{ + int dreg; + + switch (ad_p->ad_mode){ + case P_REGISTER: + if (*ad_p->ad_count_p==1) + return; + + --*ad_p->ad_count_p; + if (try_allocate_register_number (preferred_reg)) + dreg=preferred_reg; + else + dreg=get_dregister(); + i_move_r_r (ad_p->ad_register,dreg); + break; + case P_IMMEDIATE: + if (try_allocate_register_number (preferred_reg)) + dreg=preferred_reg; + else + dreg=get_dregister(); + i_move_i_r (ad_p->ad_offset,dreg); + break; + case P_INDIRECT: + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + if (try_allocate_register_number (preferred_reg)) + dreg=preferred_reg; + else + dreg=get_dregister(); + i_move_id_r (ad_p->ad_offset,ad_p->ad_register,dreg); + break; + case P_DESCRIPTOR_NUMBER: + if (try_allocate_register_number (preferred_reg)) + dreg=preferred_reg; + else + dreg=get_dregister(); + i_move_d_r (ad_p->ad_label,ad_p->ad_offset,dreg); + break; + case P_INDEXED: + { + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_p->ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; + + if (load_x_graph->inode_arity & LOAD_X_TO_ADDRESS){ + load_x_graph->inode_arity ^= (LOAD_X_TO_ADDRESS | LOAD_X_TO_REGISTER); + if (i_ad_p->ad_mode==P_INDEXED){ + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + + if (try_allocate_register_number (preferred_reg)) + dreg=preferred_reg; + else + dreg=get_dregister(); + i_move_x_r (i_ad_p->ad_offset,i_ad_p->ad_areg,i_ad_p->ad_dreg,dreg); + } else { + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + if (try_allocate_register_number (preferred_reg)) + dreg=preferred_reg; + else + dreg=get_dregister(); + i_move_id_r (i_ad_p->ad_offset,i_ad_p->ad_register,dreg); + } + i_ad_p->ad_register=dreg; + } else { + dreg=i_ad_p->ad_register; + + if (is_d_register (dreg)){ + if (*i_ad_p->ad_count_p>1){ + int old_dreg; + + old_dreg=dreg; + if (try_allocate_register_number (preferred_reg)) + dreg=preferred_reg; + else + dreg=get_dregister(); + i_move_r_r (old_dreg,dreg); + --*i_ad_p->ad_count_p; + } + } else { + int areg; + + areg=dreg; + if (try_allocate_register_number (preferred_reg)) + dreg=preferred_reg; + else + dreg=get_dregister(); + i_move_r_r (areg,dreg); + if (--*i_ad_p->ad_count_p==0) + free_aregister (areg); + } + } + break; + } + default: + internal_error_in_function ("in_alterable_data register"); + return; + } + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=dreg; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=1; +} +#endif + static void in_address_register (register ADDRESS *ad_p) { int areg; @@ -2924,7 +3090,7 @@ static void linearize_dyadic_commutative_operator (int i_instruction_code,INSTRU static void linearize_dyadic_commutative_data_operator (int i_instruction_code,INSTRUCTION_GRAPH graph,ADDRESS *ad_p) { - register INSTRUCTION_GRAPH graph_1,graph_2; + INSTRUCTION_GRAPH graph_1,graph_2; ADDRESS ad_1,ad_2; int reg_1; @@ -3600,6 +3766,87 @@ static void linearize_mod_operator (int i_instruction_code,INSTRUCTION_GRAPH gra } #endif +#ifdef I486 +static void linearize_mulud_or_divdu_operator (INSTRUCTION_GRAPH result_graph,ADDRESS *ad_p) +{ + INSTRUCTION_GRAPH graph,result_graph2; + ADDRESS ad_1,ad_2; + int reg_1,reg_2; + + graph=result_graph->instruction_parameters[0].p; + + if (graph->instruction_code==GMULUD){ + INSTRUCTION_GRAPH graph_1,graph_2; + + 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); + } + + in_preferred_alterable_register (&ad_2,REGISTER_D0); + in_preferred_alterable_register (&ad_1,REGISTER_A1); + + reg_1=ad_1.ad_register; + reg_2=ad_2.ad_register; + i_mulud_r_r (reg_1,reg_2); + } else { + INSTRUCTION_GRAPH graph_1,graph_2,graph_3; + ADDRESS ad_3; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + graph_3=graph->instruction_parameters[2].p; + + linearize_graph (graph_1,&ad_1); + linearize_graph (graph_2,&ad_2); + linearize_graph (graph_3,&ad_3); + + in_preferred_alterable_register (&ad_2,REGISTER_D0); + in_preferred_alterable_register (&ad_1,REGISTER_A1); + in_register (&ad_3); + + reg_1=ad_1.ad_register; + reg_2=ad_2.ad_register; + if (--*ad_3.ad_count_p==0) + free_register (ad_3.ad_register); + i_divdu_r_r_r (ad_3.ad_register,reg_1,reg_2); + } + + result_graph2=result_graph->instruction_parameters[1].p; + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_count_p=&result_graph->node_count; + + if (result_graph->instruction_code==GRESULT0){ + ad_p->ad_register=reg_1; + if (result_graph->node_count>1) + register_node (result_graph,reg_1); + if (result_graph2->node_count>0) + register_node (result_graph2,reg_2); + else { + --*ad_2.ad_count_p; + free_register (reg_2); + } + } else { + ad_p->ad_register=reg_2; + if (result_graph->node_count>1) + register_node (result_graph,reg_2); + if (result_graph2->node_count>0) + register_node (result_graph2,reg_1); + else { + --*ad_1.ad_count_p; + free_register (reg_1); + } + } +} +#endif + static void linearize_shift_operator (int i_instruction_code,INSTRUCTION_GRAPH graph,ADDRESS *ad_p) { INSTRUCTION_GRAPH graph_1,graph_2; @@ -7795,6 +8042,12 @@ static void linearize_graph (INSTRUCTION_GRAPH graph,ADDRESS *ad_p) linearize_dyadic_commutative_data_operator (IUMULH,graph,ad_p); return; #endif +#ifdef I486 + case GRESULT0: + case GRESULT1: + linearize_mulud_or_divdu_operator (graph,ad_p); + return; +#endif default: /* printf ("%d %d\n",(int)graph,graph->instruction_code); */ internal_error_in_function ("linearize_graph"); @@ -415,10 +415,10 @@ static int get_argument_size (int instruction_code) IF_G_RISC (case IADDI: case ILSLI:) IF_G_SPARC (case IADDO: case ISUBO: ) #ifdef I486 - case IDIVI: case IREMI: case IREMU: + case IDIVI: case IREMI: case IREMU: case IMULUD: case IDIVDU: #endif #if (defined (I486) && !defined (I486_USE_SCRATCH_REGISTER)) || defined (G_POWER) - case IDIVU: + case IDIVU: #endif IF_G_POWER ( case IUMULH: ) return 4; @@ -669,7 +669,8 @@ static void compute_maximum_b_stack_offsets (register int b_offset) #ifdef I486 instruction->instruction_icode!=IDIVI && instruction->instruction_icode!=IREMI && - instruction->instruction_icode!=IREMU && + instruction->instruction_icode!=IREMU && + instruction->instruction_icode!=IDIVDU && #endif instruction->instruction_icode!=IMOD) #ifdef M68000 @@ -904,6 +905,7 @@ void optimize_stack_access (struct basic_block *block,int *a_offset_p,int *b_off if (instruction->instruction_icode!=IDIVI && instruction->instruction_icode!=IREMI && instruction->instruction_icode!=IREMU && + instruction->instruction_icode!=IDIVDU && instruction->instruction_icode!=IMOD) internal_error_in_function ("optimize_stack_access"); /* only first argument of mod might be register indirect */ @@ -1516,6 +1518,9 @@ static void store_next_uses (struct instruction *instruction) case IDIV: case ICMPW: #endif +#if defined (I486) && !defined (I486_USE_SCRATCH_REGISTER) + case IMULUD: +#endif #if (defined (I486) && !defined (I486_USE_SCRATCH_REGISTER)) || defined (G_POWER) case IDIVU: #endif @@ -1546,7 +1551,7 @@ IF_G_POWER ( case IUMULH: ) use_parameter (&instruction->instruction_parameters[1]); use_parameter (&instruction->instruction_parameters[0]); break; - case IDIV: case IMOD: case IDIVU: case IREMU: + case IDIV: case IMOD: case IDIVU: case IREMU: case IMULUD: define_scratch_register(); use_parameter (&instruction->instruction_parameters[1]); use_parameter (&instruction->instruction_parameters[0]); @@ -1641,6 +1646,16 @@ IF_G_RISC (case IADDI: case ILSLI:) use_parameter (&instruction->instruction_parameters[0]); break; #endif +#ifdef I486 + case IDIVDU: +# ifdef I486_USE_SCRATCH_REGISTER + define_scratch_register(); +# endif + use_parameter (&instruction->instruction_parameters[2]); + use_parameter (&instruction->instruction_parameters[1]); + use_parameter (&instruction->instruction_parameters[0]); + break; +#endif #ifdef I486_USE_SCRATCH_REGISTER case IFBEQ: case IFBGE: case IFBGT: case IFBLE: case IFBLT: case IFBNE: define_scratch_register(); @@ -3054,7 +3069,7 @@ static void use_3_same_type_registers reg_alloc=f_reg_alloc; break; default: - internal_error_in_function ("use_2_same_type_registers"); + internal_error_in_function ("use_3_same_type_registers"); return; } @@ -3600,7 +3615,7 @@ static void instruction_def (struct instruction *instruction) } } -static void instruction_exg_usedef_usedef (struct instruction *instruction) +static void instruction_usedef_usedef (struct instruction *instruction) { register_use_2 ( &instruction->instruction_parameters[0].parameter_data.reg,USE_DEF, &instruction->instruction_parameters[1].parameter_data.reg,USE_DEF); @@ -3917,8 +3932,19 @@ IF_G_RISC (case IADDI: case ILSLI:) #endif break; case IEXG: - instruction_exg_usedef_usedef (instruction); + instruction_usedef_usedef (instruction); break; +#ifdef I486 + case IMULUD: +# ifdef I486_USE_SCRATCH_REGISTER + use_scratch_register(); +# endif + instruction_usedef_usedef (instruction); +# ifdef I486_USE_SCRATCH_REGISTER + allocate_scratch_register=1; +# endif + break; +#endif #if defined (I486) && defined (FP_STACK_OPTIMIZATIONS) case IFEXG: instruction_fexg_usedef_usedef (instruction); @@ -3957,6 +3983,20 @@ IF_G_RISC (case IADDI: case ILSLI:) instruction_bmove_use_use_use (instruction); break; #endif +#ifdef I486 + case IDIVDU: +# ifdef I486_USE_SCRATCH_REGISTER + use_scratch_register(); +# endif + 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,USE_DEF,D_REGISTER); +# ifdef I486_USE_SCRATCH_REGISTER + allocate_scratch_register=1; +# endif + break; +#endif #ifdef I486_USE_SCRATCH_REGISTER case IFBEQ: case IFBGE: case IFBGT: case IFBLE: case IFBLT: case IFBNE: use_scratch_register(); @@ -1,5 +1,6 @@ #define FINALIZERS +#undef NEW_APPLY #if defined (__MWERKS__) || defined (__MRC__) # define POWER |