#ifdef ANDROID # define SOFT_FP_CC #endif #define NO_REG_OR_PAD 128 #define PAD_4_AFTER 129 #ifndef THUMB # define i_move_idaa_r i_move_id_r # define i_move_r_idaa i_move_r_id # define REGISTER_R0 REGISTER_D4 #else # define REGISTER_R0 REGISTER_D1 #endif void code_ccall (char *c_function_name,char *s,int length) { LABEL *label; int l,min_index; int a_offset,b_offset,a_result_offset,b_result_offset; int result,a_o,b_o,float_parameters; int n_clean_b_register_parameters,clean_b_register_parameter_n; int n_extra_clean_b_register_parameters; int first_pointer_result_index,callee_pops_arguments,save_state_in_global_variables; int function_address_parameter; int c_offset,c_register_parameter_n,c_register_pair_parameter_n,c_parameter_offset; #ifndef SOFT_FP_CC int c_fp_register_parameter_n; #endif int c_parameter_padding; int previous_word_l; unsigned char reg_or_pad[100]; /* 128 = no_reg_or_pad, <128 = reg number, 129 = pad 4 bytes after */ function_address_parameter=0; if (length>100) error_s (ccall_error_string,c_function_name); for (l=0; l=c_register_pair_parameter_n) ++c_register_parameter_n; else c_register_parameter_n=c_register_pair_parameter_n+2; } else { previous_word_l = l; c_parameter_offset+=STACK_ELEMENT_SIZE; } b_offset+=STACK_ELEMENT_SIZE; if (!float_parameters) ++n_clean_b_register_parameters; continue; case 'r': if (c_register_parameter_n<4){ reg_or_pad[l] = c_register_parameter_n; if (c_register_parameter_n>=c_register_pair_parameter_n) ++c_register_parameter_n; else c_register_parameter_n=c_register_pair_parameter_n; } else { previous_word_l = l; c_parameter_offset+=STACK_ELEMENT_SIZE; } float_parameters=1; b_offset+=8; continue; case 'R': float_parameters=1; b_offset+=8; #ifdef SOFT_FP_CC if (c_register_parameter_n<4){ if ((c_register_parameter_n & 1)==0){ reg_or_pad[l] = c_register_parameter_n; c_register_parameter_n+=2; c_register_pair_parameter_n = c_register_parameter_n; previous_word_l = -1; continue; } else { if (c_register_pair_parameter_n<=c_register_parameter_n) c_register_pair_parameter_n = c_register_parameter_n+1; if (c_register_pair_parameter_n<4){ reg_or_pad[l] = c_register_pair_parameter_n; c_register_pair_parameter_n+=2; previous_word_l = -1; continue; } else c_register_parameter_n=4; } } #else if (c_fp_register_parameter_n<8){ reg_or_pad[l] = c_fp_register_parameter_n++; continue; } #endif if (c_parameter_offset & 4){ if (previous_word_l<0 || reg_or_pad[previous_word_l]!=NO_REG_OR_PAD) internal_error_in_function ("code_ccall"); reg_or_pad[previous_word_l]=PAD_4_AFTER; c_parameter_padding+=4; c_parameter_offset+=4; } c_parameter_offset+=8; previous_word_l = -1; continue; case 'S': case 's': case 'A': if (c_register_parameter_n<4){ reg_or_pad[l] = c_register_parameter_n; if (c_register_parameter_n>=c_register_pair_parameter_n) ++c_register_parameter_n; else c_register_parameter_n=c_register_pair_parameter_n+2; } else { previous_word_l = l; c_parameter_offset+=STACK_ELEMENT_SIZE; } a_offset+=STACK_ELEMENT_SIZE; continue; case 'O': case 'F': if (function_address_parameter) error_s (ccall_error_string,c_function_name); function_address_parameter=s[l]; while (l+1=length) error_s (ccall_error_string,c_function_name); n_extra_clean_b_register_parameters=0; for (++l; lN_DATA_PARAMETER_REGISTERS){ n_clean_b_register_parameters=N_DATA_PARAMETER_REGISTERS; n_extra_clean_b_register_parameters=0; } else if (n_clean_b_register_parameters+n_extra_clean_b_register_parameters>N_DATA_PARAMETER_REGISTERS) n_extra_clean_b_register_parameters=N_DATA_PARAMETER_REGISTERS-n_clean_b_register_parameters; end_basic_block_with_registers (0,n_clean_b_register_parameters+n_extra_clean_b_register_parameters,e_vector); b_offset-=n_clean_b_register_parameters<=c_register_pair_parameter_n) ++c_register_parameter_n; else c_register_parameter_n=c_register_pair_parameter_n+2; } else c_parameter_offset+=STACK_ELEMENT_SIZE; b_result_offset+=STACK_ELEMENT_SIZE; continue; case 'R': if (c_register_parameter_n<4){ reg_or_pad[l] = c_register_parameter_n; if (c_register_parameter_n>=c_register_pair_parameter_n) ++c_register_parameter_n; else c_register_parameter_n=c_register_pair_parameter_n+2; } else c_parameter_offset+=STACK_ELEMENT_SIZE; b_result_offset+=8; continue; case 'S': if (c_register_parameter_n<4){ reg_or_pad[l] = c_register_parameter_n; if (c_register_parameter_n>=c_register_pair_parameter_n) ++c_register_parameter_n; else c_register_parameter_n=c_register_pair_parameter_n+2; } else c_parameter_offset+=STACK_ELEMENT_SIZE; a_result_offset+=STACK_ELEMENT_SIZE; continue; case 'A': if (c_register_parameter_n<4){ reg_or_pad[l] = c_register_parameter_n; if (c_register_parameter_n>=c_register_pair_parameter_n) ++c_register_parameter_n; else c_register_parameter_n=c_register_pair_parameter_n+2; } else c_parameter_offset+=STACK_ELEMENT_SIZE; ++l; a_result_offset+=STACK_ELEMENT_SIZE; continue; } } if (!function_address_parameter) label = enter_c_function_name_label (c_function_name); { int c_offset_before_pushing_arguments,function_address_reg,function_address_s_index; 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; #ifndef THUMB i_move_r_r (B_STACK_POINTER,REGISTER_A2); if (c_parameter_offset & 4){ 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); } #else if (c_parameter_offset & 4){ i_addi_r_r (-4,B_STACK_POINTER,REGISTER_A3); i_move_r_r (B_STACK_POINTER,REGISTER_A2); i_ori_r_r (4,REGISTER_A3,REGISTER_A3); } else { i_move_r_r (B_STACK_POINTER,REGISTER_A2); i_andi_r_r (-8,REGISTER_A2,REGISTER_A3); } i_move_r_r (REGISTER_A3,B_STACK_POINTER); #endif for (l=length-1; l>=first_pointer_result_index; --l){ switch (s[l]){ case 'I': case 'p': b_o-=STACK_ELEMENT_SIZE; if (reg_or_pad[l]=0; --l){ switch (s[l]){ case 'I': case 'p': case 'S': case 's': case 'A': if (reg_or_pad[l]>=NO_REG_OR_PAD){ if (reg_or_pad[l]==PAD_4_AFTER) c_offset_1+=4; c_offset_1+=STACK_ELEMENT_SIZE; } break; case 'R': if (reg_or_pad[l]>=NO_REG_OR_PAD) c_offset_1+=8; break; case 'O': case 'F': case '*': case ']': while (l>=0 && (s[l]!='F' && s[l]!='O')) --l; if (reg_or_pad[l]>=NO_REG_OR_PAD) 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 l,c_offset_2,not_finished; #ifdef THUMB int new_reg[2]; new_reg[0]=new_reg[1]=-1; #else int new_reg[5]; new_reg[0]=new_reg[1]=new_reg[2]=new_reg[3]=new_reg[4]=-1; /* [0] not used */ #endif c_offset_2 = c_offset_1; reg_n=0; for (l=min_index-1; l>=0; --l){ switch (s[l]){ case 'I': case 'p': if (reg_or_pad[l]=NO_REG_OR_PAD){ if (reg_or_pad[l]==PAD_4_AFTER) c_offset_2-=4; c_offset_2-=STACK_ELEMENT_SIZE; } break; case 'R': if (reg_or_pad[l]>=NO_REG_OR_PAD) c_offset_2-=8; break; case 'O': case 'F': case '*': case ']': while (l>=0 && (s[l]!='F' && s[l]!='O')) --l; if (reg_or_pad[l]=0 && n!=reg_n){ if (new_reg[0]!=reg_n && new_reg[1]!=reg_n){ i_move_r_r (REGISTER_D0+n,REGISTER_D0+reg_n); new_reg[reg_n]=-1; } else not_finished=1; } } #else for (reg_n=1; reg_n<=4; ++reg_n){ int n; n=new_reg[reg_n]; if (n>=0 && n!=reg_n){ 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; } } #endif } 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 (reg_or_pad[l]=0 && (s[l]!='F' && s[l]!='O')) --l; if (reg_or_pad[l]=first_pointer_result_index; --l){ switch (s[l]){ case 'I': case 'p': b_o-=STACK_ELEMENT_SIZE; if (reg_or_pad[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_idaa (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