diff options
Diffstat (limited to 'cginstructions.c')
-rw-r--r-- | cginstructions.c | 385 |
1 files changed, 336 insertions, 49 deletions
diff --git a/cginstructions.c b/cginstructions.c index 25ea347..6aa80bf 100644 --- a/cginstructions.c +++ b/cginstructions.c @@ -24,18 +24,17 @@ #ifdef G_POWER # include "cgpas.h" # include "cgpwas.h" -#else -# ifdef I486 +#elif defined (I486) # include "cgias.h" # include "cgiwas.h" -# else -# ifdef SOLARIS +#elif defined (ARM) +# include "cgarmas.h" +# include "cgarmwas.h" +#elif defined (SOLARIS) # include "cgswas.h" -# else +#else # include "cgas.h" # include "cgwas.h" -# endif -# endif #endif #if defined (THREAD32) || defined (THREAD64) # include "cgiconst.h" @@ -58,7 +57,7 @@ extern LABEL * system_sp_label, *string_to_string_node_label,*int_array_to_node_label,*real_array_to_node_label, *new_int_reducer_label,*channelP_label,*stop_reducer_label,*send_request_label,*send_graph_label; -#if (defined (I486) && !defined (THREAD64)) || defined (G_POWER) +#if ((defined (I486) || defined (ARM)) && !defined (THREAD64)) || defined (G_POWER) LABEL *saved_heap_p_label,*saved_a_stack_p_label; #endif #ifdef MACH_O @@ -70,7 +69,11 @@ LABEL *tlsp_tls_index_label; extern struct basic_block *last_block; -extern ULONG e_vector[],i_vector[],i_i_vector[],i_i_i_vector[],r_vector[]; +extern ULONG e_vector[],i_vector[],i_i_vector[],i_i_i_vector[], +#ifdef ARM + i_i_i_i_i_vector[], +#endif + r_vector[]; extern int reachable; extern int line_number; /* from cginput.c */ @@ -671,7 +674,7 @@ INSTRUCTION_GRAPH g_fload_x (INSTRUCTION_GRAPH graph_1,int offset,int shift,INST return instruction; } -#ifdef I486 +#if defined (I486) || defined (ARM) INSTRUCTION_GRAPH g_fload_s_x (INSTRUCTION_GRAPH graph_1,int offset,int shift,INSTRUCTION_GRAPH graph_2) { INSTRUCTION_GRAPH instruction; @@ -862,7 +865,7 @@ INSTRUCTION_GRAPH g_load_des_i (LABEL *descriptor_label,int arity) instruction=g_new_node (GLOAD_DES_I,0,2*sizeof (union instruction_parameter)); instruction->instruction_parameters[0].l=descriptor_label; -#ifdef I486 +#if defined (I486) || defined (ARM) # ifdef MACH_O64 instruction->instruction_parameters[1].i=(arity<<4)+2; # else @@ -994,7 +997,7 @@ INSTRUCTION_GRAPH g_fstore_x (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_ return instruction; } -#ifdef I486 +#if defined (I486) || defined (ARM) INSTRUCTION_GRAPH g_fstore_s_x (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2,int offset,int shift,INSTRUCTION_GRAPH graph_3) { INSTRUCTION_GRAPH instruction; @@ -1581,7 +1584,7 @@ void code_push_args_u (int a_offset,int arity,int n_arguments) *--graph_p=graph_4; s_push_a (graph_4); } else { -#ifndef I486 +#if ! (defined (I486) || defined (ARM)) if (n_arguments>=8){ #endif while (n_arguments!=0){ @@ -1593,7 +1596,7 @@ void code_push_args_u (int a_offset,int arity,int n_arguments) *--graph_p=graph_5; s_push_a (graph_5); } -#ifndef I486 +#if ! (defined (I486) || defined (ARM)) } else { graph_4=g_movem (0-NODE_POINTER_OFFSET,graph_3,n_arguments); while (n_arguments!=0){ @@ -3637,7 +3640,7 @@ static void push_extra_clean_b_register_parameters (int n_extra_clean_b_register #endif } -#if (defined (sparc) && !defined (SOLARIS)) || (defined (I486) && !defined (LINUX_ELF) && !defined (G_AI64)) || (defined (G_POWER) && !defined (LINUX_ELF)) || defined (MACH_O) || defined (MACH_O64) +#if (defined (sparc) && !defined (SOLARIS)) || ((defined (I486) || defined (ARM)) && !defined (LINUX_ELF) && !defined (G_AI64)) || (defined (G_POWER) && !defined (LINUX_ELF)) || defined (MACH_O) || defined (MACH_O64) static LABEL *enter_c_function_name_label (char *c_function_name) { char label_name [202]; @@ -3729,21 +3732,18 @@ void code_ccall (char *c_function_name,char *s,int length) int first_pointer_result_index,callee_pops_arguments,save_state_in_global_variables; int function_address_parameter; int n_a_c_in_clean_out_parameters_size,n_b_c_in_clean_out_parameters_size; + int c_offset; -#if defined (sparc) || defined (G_POWER) - int c_parameter_n; -# ifdef G_POWER - int c_offset; -# endif -#elif defined (I486) - int c_offset; -#else - error ("ABC instruction 'ccall' not implemented"); +#if ! (defined (sparc) || defined (G_POWER) || defined (I486) || defined (ARM)) + error ("ABC instruction 'ccall' not implemented"); +#endif +#if defined (sparc) || defined (G_POWER) || defined (ARM) + int c_parameter_n; #endif #if defined (G_POWER) || (defined (G_A64) && (defined (LINUX_ELF) || defined (MACH_O64))) - int c_fp_parameter_n; - - c_fp_parameter_n=0; + int c_fp_parameter_n; + + c_fp_parameter_n=0; #endif function_address_parameter=0; @@ -3752,7 +3752,7 @@ void code_ccall (char *c_function_name,char *s,int length) ++s; --length; save_state_in_global_variables=1; -#if (defined (I486) && !defined (THREAD64)) || defined (G_POWER) +#if ((defined (I486) || defined (ARM)) && !defined (THREAD64)) || defined (G_POWER) if (saved_heap_p_label==NULL) saved_heap_p_label=enter_label ("saved_heap_p",IMPORT_LABEL); if (saved_a_stack_p_label==NULL) @@ -3772,7 +3772,7 @@ void code_ccall (char *c_function_name,char *s,int length) } else callee_pops_arguments=0; -#if defined (sparc) || defined (I486) || defined (G_POWER) +#if defined (sparc) || defined (I486) || defined (G_POWER) || defined (ARM) float_parameters=0; a_offset=0; @@ -3792,14 +3792,14 @@ void code_ccall (char *c_function_name,char *s,int length) b_offset+=STACK_ELEMENT_SIZE; if (!float_parameters) ++n_clean_b_register_parameters; -#if defined (I486) && !defined (G_AI64) +# if (defined (I486) || defined (ARM)) && !defined (G_AI64) if (s[l+1]=='>'){ ++l; n_b_c_in_clean_out_parameters_size+=STACK_ELEMENT_SIZE; } -#endif +# endif continue; -# if defined (I486) || defined (G_POWER) +# if defined (I486) || defined (ARM) || defined (G_POWER) case 'r': # endif case 'R': @@ -3813,12 +3813,12 @@ void code_ccall (char *c_function_name,char *s,int length) case 's': case 'A': a_offset+=STACK_ELEMENT_SIZE; -#if defined (I486) && !defined (G_AI64) +# if (defined (I486) || defined (ARM)) && !defined (G_AI64) if (s[l+1]=='>'){ ++l; n_a_c_in_clean_out_parameters_size+=STACK_ELEMENT_SIZE; } -#endif +# endif continue; case 'O': case 'F': @@ -4638,7 +4638,7 @@ void code_ccall (char *c_function_name,char *s,int length) c_offset_before_pushing_arguments=c_offset; - n_c_parameters=((a_offset+b_offset+a_result_offset+b_result_offset)>>3)+n_clean_b_register_parameters; + n_c_parameters=((a_offset+b_offset+a_result_offset+b_result_offset)>>STACK_ELEMENT_LOG_SIZE)+n_clean_b_register_parameters; used_clean_b_parameter_registers = ((1<<n_clean_b_register_parameters)-1)<<n_extra_clean_b_register_parameters; c_parameter_n=n_c_parameters; n_c_fp_register_parameters = c_fp_parameter_n<=8 ? c_fp_parameter_n : 8; @@ -5088,7 +5088,7 @@ void code_ccall (char *c_function_name,char *s,int length) c_offset_before_pushing_arguments=c_offset; - c_parameter_n=((a_offset+b_offset+a_result_offset+b_result_offset)>>3)+n_clean_b_register_parameters; + c_parameter_n=((a_offset+b_offset+a_result_offset+b_result_offset)>>STACK_ELEMENT_LOG_SIZE)+n_clean_b_register_parameters; i_move_r_r (B_STACK_POINTER,REGISTER_RBP); # ifdef THREAD64 @@ -5460,6 +5460,281 @@ void code_ccall (char *c_function_name,char *s,int length) error_s (ccall_error_string,c_function_name); } # endif + +#elif defined (ARM) + + { + int c_offset_before_pushing_arguments,function_address_reg,c_parameter_n; + + a_o=-b_result_offset-a_result_offset; + b_o=0; + + if (a_result_offset+b_result_offset>b_offset){ + i_sub_i_r (a_result_offset+b_result_offset-b_offset,B_STACK_POINTER); + c_offset=a_result_offset+b_result_offset; + } + + c_offset_before_pushing_arguments=c_offset; + + c_parameter_n=((a_offset+b_offset+a_result_offset+b_result_offset)>>STACK_ELEMENT_LOG_SIZE)+n_clean_b_register_parameters; + + i_move_r_r (B_STACK_POINTER,REGISTER_A2); + + if (c_parameter_n>=4 && (c_parameter_n & 1)!=0){ + i_sub_i_r (4,B_STACK_POINTER); + i_or_i_r (4,B_STACK_POINTER); + } else { + i_and_i_r (-8,B_STACK_POINTER); + } + + for (l=length-1; l>=first_pointer_result_index; --l){ + switch (s[l]){ + case 'I': + case 'p': + b_o-=STACK_ELEMENT_SIZE; + if (--c_parameter_n<4) + i_lea_id_r (b_o+c_offset_before_pushing_arguments,REGISTER_A2,REGISTER_D4-c_parameter_n); + else { + i_lea_id_r (b_o+c_offset_before_pushing_arguments,REGISTER_A2,REGISTER_A3); + i_move_r_pd (REGISTER_A3,B_STACK_POINTER); + c_offset+=STACK_ELEMENT_SIZE; + } + break; + case 'i': + case 'r': + --l; + case 'S': + if (--c_parameter_n<4) + i_lea_id_r (a_o+c_offset_before_pushing_arguments,REGISTER_A2,REGISTER_D4-c_parameter_n); + else { + i_lea_id_r (a_o+c_offset_before_pushing_arguments,REGISTER_A2,REGISTER_A3); + i_move_r_pd (REGISTER_A3,B_STACK_POINTER); + c_offset+=STACK_ELEMENT_SIZE; + } + a_o+=STACK_ELEMENT_SIZE; + break; + case 'V': + break; + default: + error_s (ccall_error_string,c_function_name); + } + } + + { + int last_register_parameter_index,reg_n,c_offset_1; + + last_register_parameter_index=-1; + + reg_n=0; + l=0; + while (reg_n<n_clean_b_register_parameters && l<min_index){ + if (s[l]=='I' || s[l]=='p' || s[l]=='F' || s[l]=='O'){ + ++reg_n; + last_register_parameter_index=l; + } + ++l; + } + + c_offset_1=0; + + { + int c_parameter_n_1,l; + + c_parameter_n_1 = c_parameter_n; + for (l=min_index-1; l>=0; --l){ + switch (s[l]){ + case 'I': + case 'p': + case 'S': + case 's': + if (--c_parameter_n_1>=4) + c_offset_1+=STACK_ELEMENT_SIZE; + break; + } + } + + if (c_offset_1!=0){ + i_sub_i_r (c_offset_1,B_STACK_POINTER); + c_offset += c_offset_1; + } + } + + { + int c_parameter_n_2,l,c_offset_2,not_finished,new_reg[5]; + + new_reg[0]=new_reg[1]=new_reg[2]=new_reg[3]=new_reg[4]=-1; /* [0] not used */ + + c_offset_2 = c_offset_1; + c_parameter_n_2 = c_parameter_n; + reg_n=0; + for (l=min_index-1; l>=0; --l){ + switch (s[l]){ + case 'I': + case 'p': + if (--c_parameter_n_2<4){ + if (l<=last_register_parameter_index){ + new_reg [4-c_parameter_n_2] = n_extra_clean_b_register_parameters+reg_n; + ++reg_n; + } + } else { + c_offset_2-=STACK_ELEMENT_SIZE; + if (l<=last_register_parameter_index){ + i_move_r_id (REGISTER_D0+n_extra_clean_b_register_parameters+reg_n,c_offset_2,B_STACK_POINTER); + ++reg_n; + } + } + break; + case 'S': + case 's': + if (--c_parameter_n_2>=4) + c_offset_2-=STACK_ELEMENT_SIZE; + break; + } + } + + do { + not_finished=0; + for (reg_n=1; reg_n<=4; ++reg_n){ + int n; + + n=new_reg[reg_n]; + if (n>=0 && n!=reg_n){ + if (n>4 || n==0){ + i_move_r_r (REGISTER_D0+n,REGISTER_D0+reg_n); + new_reg[reg_n]=-1; + } else if (new_reg[1]!=reg_n && new_reg[2]!=reg_n && new_reg[3]!=reg_n && new_reg[4]!=reg_n){ + i_move_r_r (REGISTER_D0+n,REGISTER_D0+reg_n); + new_reg[reg_n]=-1; + } else + not_finished=1; + } + } + } while (not_finished); /* infinite loop in case of cycle */ + } + + reg_n=0; + a_o=-a_offset; + b_o=0; + for (l=min_index-1; l>=0; --l){ + switch (s[l]){ + case 'I': + case 'p': + if (--c_parameter_n<4){ + if (l<=last_register_parameter_index){ + /* i_move_r_r (REGISTER_D0+n_extra_clean_b_register_parameters+reg_n,REGISTER_D4-c_parameter_n); */ + ++reg_n; + } else { + b_o-=STACK_ELEMENT_SIZE; + i_move_id_r (b_o+c_offset_before_pushing_arguments,REGISTER_A2,REGISTER_D4-c_parameter_n); + } + } else { + c_offset_1-=STACK_ELEMENT_SIZE; + if (l<=last_register_parameter_index){ + /* i_move_r_id (REGISTER_D0+n_extra_clean_b_register_parameters+reg_n,c_offset_1,B_STACK_POINTER); */ + ++reg_n; + } else { + b_o-=STACK_ELEMENT_SIZE; + i_move_id_r (b_o+c_offset_before_pushing_arguments,REGISTER_A2,6/*r12*/); + i_move_r_id (6/*r12*/,c_offset_1,B_STACK_POINTER); + } + } + break; + case 'S': + if (--c_parameter_n<4){ + i_move_id_r (a_o,A_STACK_POINTER,REGISTER_D4-c_parameter_n); + i_add_i_r (STACK_ELEMENT_SIZE,REGISTER_D4-c_parameter_n); + } else { + c_offset_1-=STACK_ELEMENT_SIZE; + i_move_id_r (a_o,A_STACK_POINTER,REGISTER_A0); + i_add_i_r (STACK_ELEMENT_SIZE,REGISTER_A0); + i_move_r_id (REGISTER_A0,c_offset_1,B_STACK_POINTER); + } + a_o+=STACK_ELEMENT_SIZE; + break; + case 's': + if (--c_parameter_n<4){ + i_move_id_r (a_o,A_STACK_POINTER,REGISTER_D4-c_parameter_n); + i_add_i_r (2*STACK_ELEMENT_SIZE,REGISTER_D4-c_parameter_n); + } else { + c_offset_1-=STACK_ELEMENT_SIZE; + i_move_id_r (a_o,A_STACK_POINTER,REGISTER_A0); + i_add_i_r (2*STACK_ELEMENT_SIZE,REGISTER_A0); + i_move_r_id (REGISTER_A0,c_offset_1,B_STACK_POINTER); + } + a_o+=STACK_ELEMENT_SIZE; + break; + default: + error_s (ccall_error_string,c_function_name); + } + } + } + + if (!function_address_parameter) + i_call_l (label); + else + i_call_r (function_address_reg); + + if (c_offset_before_pushing_arguments-(b_result_offset+a_result_offset)==0) + i_move_r_r (REGISTER_A2,B_STACK_POINTER); + else + i_lea_id_r (c_offset_before_pushing_arguments-(b_result_offset+a_result_offset),REGISTER_A2,B_STACK_POINTER); + } + + if (a_offset!=0) + i_sub_i_r (a_offset,A_STACK_POINTER); + + for (l=length-1; l>=first_pointer_result_index; --l){ + switch (s[l]){ + case 'I': + case 'p': + case 'R': + case 'V': + break; + case 'S': + if (string_to_string_node_label==NULL) + string_to_string_node_label=enter_label ("string_to_string_node",IMPORT_LABEL); + i_move_pi_r (B_STACK_POINTER,REGISTER_A0); + i_jsr_l_idu (string_to_string_node_label,-4); + i_move_r_id (REGISTER_A0,0,A_STACK_POINTER); + i_add_i_r (STACK_ELEMENT_SIZE,A_STACK_POINTER); + break; + default: + error_s (ccall_error_string,c_function_name); + } + } + + b_o=0; + for (l=first_pointer_result_index; l<length; ++l){ + switch (s[l]){ + case 'I': + case 'p': + b_o+=STACK_ELEMENT_SIZE; + break; + case 'S': + case 'V': + break; + default: + error_s (ccall_error_string,c_function_name); + } + } + + switch (result){ + case 'I': + case 'p': + begin_new_basic_block(); + init_b_stack (5,i_i_i_i_i_vector); + s_put_b (4,s_get_b (0)); + s_remove_b(); + s_remove_b(); + s_remove_b(); + s_remove_b(); + break; + case 'V': + begin_new_basic_block(); + break; + default: + error_s (ccall_error_string,c_function_name); + } #endif } @@ -5521,7 +5796,7 @@ static void load_constant_registers (void) static void save_registers_before_clean_call (void) { -#if defined (I486) +#if defined (I486) || defined (ARM) # ifdef G_AI64 i_sub_i_r (144,B_STACK_POINTER); @@ -5614,7 +5889,7 @@ static void save_registers_before_clean_call (void) static void restore_registers_after_clean_call (void) { -#if defined (I486) +#if defined (I486) || defined (ARM) # ifdef G_AI64 # ifdef THREAD64 @@ -5847,7 +6122,7 @@ static void call_pthread_getspecific (int n_integer_parameters,int n_float_param } #endif -#ifdef I486 +#if defined (I486) || defined (ARM) # ifdef G_AI64 # define REGISTER_EBP_OR_RBP (-5) # else @@ -5857,7 +6132,7 @@ static void call_pthread_getspecific (int n_integer_parameters,int n_float_param void code_centry (char *c_function_name,char *clean_function_label,char *s,int length) { -#if defined (I486) || defined (G_POWER) +#if defined (I486) || defined (ARM) || defined (G_POWER) struct block_label *new_label; LABEL *label; int i,n,callee_pops_arguments,n_integer_and_float_parameters; @@ -5906,7 +6181,7 @@ void code_centry (char *c_function_name,char *clean_function_label,char *s,int l c=s[i]; if (c=='I') ++n_integer_parameters; -#if defined (I486) +#if defined (I486) || defined (ARM) else if (c=='R'){ ++n_float_parameters; float_parameter_or_result=1; @@ -5934,7 +6209,7 @@ void code_centry (char *c_function_name,char *clean_function_label,char *s,int l else if (c=='I'){ integer_c_function_result=1; ++n_integer_results; -#if defined (I486) +#if defined (I486) || defined (ARM) } else if (c=='R'){ float_c_function_result=1; ++n_float_results; @@ -5963,7 +6238,7 @@ void code_centry (char *c_function_name,char *clean_function_label,char *s,int l c=s[i]; if (c=='I') ++n_integer_results; -#if defined (I486) +#if defined (I486) || defined (ARM) else if (c=='R'){ ++n_float_results; float_parameter_or_result=1; @@ -5993,7 +6268,7 @@ void code_centry (char *c_function_name,char *clean_function_label,char *s,int l string_or_array_c_function_result=string_c_function_result+array_c_function_result; -#ifdef I486 +#if defined (I486) || defined (ARM) if (n_integer_results==0 && n_float_results==0 && n_string_or_array_results==0) #else if (n_integer_results!=1) @@ -6006,7 +6281,7 @@ void code_centry (char *c_function_name,char *clean_function_label,char *s,int l n_integer_and_float_parameters=n_integer_parameters+n_float_parameters; #endif -# if (defined (sparc) && !defined (SOLARIS)) || (defined (I486) && !defined (LINUX_ELF) && !defined (G_AI64)) || (defined (G_POWER) && !defined (LINUX_ELF)) || defined (MACH_O) || defined (MACH_O64) +# if (defined (sparc) && !defined (SOLARIS)) || ((defined (I486) || defined (ARM)) && !defined (LINUX_ELF) && !defined (G_AI64)) || (defined (G_POWER) && !defined (LINUX_ELF)) || defined (MACH_O) || defined (MACH_O64) { char label_name [202]; @@ -6094,7 +6369,7 @@ void code_centry (char *c_function_name,char *clean_function_label,char *s,int l } #endif -#if defined (I486) +#if defined (I486) || defined (ARM) if (n_string_or_array_parameters!=0){ int i,offset; @@ -6126,7 +6401,11 @@ void code_centry (char *c_function_name,char *clean_function_label,char *s,int l string_to_string_node_label=enter_string_to_string_node_label(); offset-=STACK_ELEMENT_SIZE; i_move_id_r (offset,B_STACK_POINTER,REGISTER_A0); +# ifndef ARM i_jsr_l (string_to_string_node_label,0); +# else + i_jsr_l_idu (string_to_string_node_label,-4); +# endif i_move_r_id (REGISTER_A0,0,A_STACK_POINTER); i_add_i_r (STACK_ELEMENT_SIZE,A_STACK_POINTER); } else if (c=='i'){ @@ -6135,7 +6414,11 @@ void code_centry (char *c_function_name,char *clean_function_label,char *s,int l int_array_to_node_label=enter_label ("int_array_to_node",IMPORT_LABEL); offset-=STACK_ELEMENT_SIZE; i_move_id_r (offset,B_STACK_POINTER,REGISTER_A0); +# ifndef ARM i_jsr_l (int_array_to_node_label,0); +# else + i_jsr_l_idu (int_array_to_node_label,-4); +# endif i_move_r_id (REGISTER_A0,0,A_STACK_POINTER); i_add_i_r (STACK_ELEMENT_SIZE,A_STACK_POINTER); } else if (c=='r'){ @@ -6144,7 +6427,11 @@ void code_centry (char *c_function_name,char *clean_function_label,char *s,int l real_array_to_node_label=enter_label ("real_array_to_node",IMPORT_LABEL); offset-=STACK_ELEMENT_SIZE; i_move_id_r (offset,B_STACK_POINTER,REGISTER_A0); +# ifndef ARM i_jsr_l (real_array_to_node_label,0); +# else + i_jsr_l_idu (real_array_to_node_label,-4); +# endif i_move_r_id (REGISTER_A0,0,A_STACK_POINTER); i_add_i_r (STACK_ELEMENT_SIZE,A_STACK_POINTER); } else @@ -6169,7 +6456,7 @@ void code_centry (char *c_function_name,char *clean_function_label,char *s,int l init_a_stack (0); init_b_stack (0,e_vector); -#if defined (I486) +#if defined (I486) || defined (ARM) if (n_string_or_array_parameters!=0){ int i,offset; @@ -6949,7 +7236,7 @@ void init_cginstructions (void) profile_function_label=NULL; profile_flag=PROFILE_NORMAL; -#if defined (G_POWER) || defined (I486) +#if defined (G_POWER) || defined (I486) || defined (ARM) profile_l_label=NULL; profile_l2_label=NULL; profile_n_label=NULL; @@ -6962,7 +7249,7 @@ void init_cginstructions (void) profile_ti_label=NULL; # endif #endif -#if (defined (I486) && !defined (THREAD64)) || defined (G_POWER) +#if ((defined (I486) || defined (ARM)) && !defined (THREAD64)) || defined (G_POWER) saved_heap_p_label=NULL; saved_a_stack_p_label=NULL; #endif |