/* File: cgpwas.c Machine: Power Macintosh Author: John van Groningen Copyright: University of Nijmegen */ #include #include #include #include #include "cgport.h" #ifdef MACH_O #define GNU_SYNTAX #endif #undef ONLY_REGISTER_NUMBERS #ifdef GNU_SYNTAX # define IF_GNU(a,b) a #else # define IF_GNU(a,b) b #endif #ifdef MACH_O # define IF_MACH_O(a,b) a #else # define IF_MACH_O(a,b) b #endif #ifndef MACH_O # define NEWLINE_STRING "\015" # define NEWLINE_CHAR '\015' #else # define NEWLINE_STRING "\012" # define NEWLINE_CHAR '\012' #endif #ifdef G_POWER #include "cgrconst.h" #include "cgtypes.h" #include "cg.h" #include "cgiconst.h" #include "cgcode.h" #include "cginstructions.h" #include "cgptoc.h" #include "cgpwas.h" #ifdef GNU_C # include #endif #define FP_REVERSE_SUB_DIV_OPERANDS 1 #define for_l(v,l,n) for(v=(l);v!=NULL;v=v->n) #define IO_BUF_SIZE 8192 static FILE *assembly_file; static void w_as_newline (VOID) { putc (NEWLINE_CHAR,assembly_file); } static void w_as_opcode (char *opcode) { fprintf (assembly_file,"\t%s\t",opcode); } static void w_as_instruction_without_parameters (char *opcode) { fprintf (assembly_file,"\t%s" NEWLINE_STRING,opcode); } static void w_as_define_local_label (int label_number) { fprintf (assembly_file,"l_%d:" NEWLINE_STRING,label_number); } static void w_as_define_internal_label (int label_number) { fprintf (assembly_file,"i_%d:" NEWLINE_STRING,label_number); } #define DC_L IF_GNU (".long","dc.l") #define DC_B IF_GNU (".byte","dc.b") void w_as_internal_label_value (int label_id) { fprintf (assembly_file,"\t" DC_L "\ti_%d" NEWLINE_STRING,label_id); } static int in_data_section; static int data_module_number,code_module_number; static void w_as_new_code_module (VOID) { ++code_module_number; #ifdef GNU_SYNTAX fprintf (assembly_file,IF_MACH_O ("\t.text" NEWLINE_STRING,"\t.section\t\".text\"" NEWLINE_STRING)); #else fprintf (assembly_file,"\tcsect\t.m_%d{PR}" NEWLINE_STRING,code_module_number); #endif in_data_section=0; } static void w_as_to_code_section (VOID) { if (in_data_section){ in_data_section=0; #ifdef GNU_SYNTAX fprintf (assembly_file,IF_MACH_O ("\t.text" NEWLINE_STRING,"\t.section\t\".text\"" NEWLINE_STRING)); #else fprintf (assembly_file,"\tcsect\t.m_%d{PR}" NEWLINE_STRING,code_module_number); #endif } } void w_as_new_data_module (VOID) { ++data_module_number; #ifdef GNU_SYNTAX fprintf (assembly_file,IF_MACH_O ("\t.data" NEWLINE_STRING,"\t.section\t\".data\"" NEWLINE_STRING)); #else fprintf (assembly_file,"\tcsect\t.d_%d{RW}" NEWLINE_STRING,data_module_number); #endif in_data_section=1; } void w_as_to_data_section (VOID) { if (!in_data_section){ in_data_section=1; #ifdef GNU_SYNTAX fprintf (assembly_file,IF_MACH_O ("\t.data" NEWLINE_STRING,"\t.section\t\".data\"" NEWLINE_STRING)); #else fprintf (assembly_file,"\tcsect\t.d_%d{RW}" NEWLINE_STRING,data_module_number); #endif } } void w_as_word_in_data_section (int n) { w_as_to_data_section(); w_as_opcode (IF_GNU (IF_MACH_O (".short",".word"),"dc.w")); fprintf (assembly_file,"%d",n); w_as_newline(); } void w_as_long_in_data_section (int n) { w_as_to_data_section(); w_as_opcode (DC_L); fprintf (assembly_file,"%d",n); w_as_newline(); } void w_as_label_in_data_section (char *label_name) { w_as_to_data_section (); fprintf (assembly_file,"\t" DC_L "\t%s" NEWLINE_STRING,label_name); } static void w_as_label_in_code_section (char *label_name) { w_as_to_code_section (); fprintf (assembly_file,"\t" DC_L "\t%s" NEWLINE_STRING,label_name); } void w_as_descriptor_in_data_section (char *label_name) { w_as_to_data_section (); fprintf (assembly_file,"\t" DC_L "\t%s+2" NEWLINE_STRING,label_name); } #define MAX_BYTES_PER_LINE 16 static int w_as_data (int n,char *data_p,int length) { int i,in_string; unsigned char *data; data=(unsigned char*)data_p; in_string=0; for (i=0; i=MAX_BYTES_PER_LINE){ if (in_string){ putc (IF_GNU ('\"','\''),assembly_file); in_string=0; } w_as_newline(); n=0; } c=data[i]; if (isalnum (c) || c=='_' || c==' '){ if (!in_string){ if (n!=0) w_as_newline(); w_as_opcode (IF_MACH_O (".ascii",DC_B)); putc (IF_GNU ('\"','\''),assembly_file); in_string=1; } putc (c,assembly_file); } else { if (n==0) w_as_opcode (DC_B); else { if (in_string){ putc (IF_GNU ('\"','\''),assembly_file); w_as_newline(); w_as_opcode (DC_B); in_string=0; } else putc (',',assembly_file); } fprintf (assembly_file,"0x%02x",c); } ++n; } if (in_string){ putc (IF_GNU ('\"','\''),assembly_file); w_as_newline(); return 0; } else return n; } static int w_as_zeros (int n,int length) { int i; for (i=0; i=MAX_BYTES_PER_LINE){ w_as_newline(); n=0; } if (n==0) w_as_opcode (DC_B); else putc (',',assembly_file); fprintf (assembly_file,"0"); ++n; } return n; } void w_as_c_string_in_data_section (char *string,int length) { int n; w_as_to_data_section(); n=w_as_data (0,string,length); if (length & 3) n=w_as_zeros (n,4-(length & 3)); else n=w_as_zeros (n,4); w_as_newline(); } void w_as_define_data_label (int label_number) { w_as_to_data_section(); w_as_define_local_label (label_number); } void w_as_abc_string_in_data_section (char *string,int length) { int n; w_as_to_data_section(); w_as_opcode (DC_L); fprintf (assembly_file,"%d" NEWLINE_STRING,length); n=w_as_data (0,string,length); if (length & 3) n=w_as_zeros (n,4-(length & 3)); if (n>0) w_as_newline(); } void w_as_labeled_c_string_in_data_section (char *string,int length,int label_number) { int n; w_as_to_data_section(); w_as_define_local_label (label_number); n=w_as_data (0,string,length); if (length & 3) n=w_as_zeros (n,4-(length & 3)); else n=w_as_zeros (n,4); if (n>0) w_as_newline(); } void w_as_descriptor_string_in_data_section (char *string,int length,int string_label_id,LABEL *string_label) { int n; w_as_to_data_section(); w_as_define_internal_label (string_label_id); w_as_define_local_label (string_label->label_number); w_as_opcode (DC_L); fprintf (assembly_file,"%d" NEWLINE_STRING,length); n=w_as_data (0,string,length); if (length & 3) n=w_as_zeros (n,4-(length & 3)); if (n>0) w_as_newline(); } enum { SIZE_LONG, SIZE_WORD, SIZE_BYTE }; static void w_as_opcode_and_d (char *opcode) { fprintf (assembly_file,"\t%sd\t",opcode); } static void w_as_label (char *label) { int c; while (c=*label++,c!=0) putc (c,assembly_file); } static void w_as_colon (VOID) { putc (':',assembly_file); } static void w_as_define_label_name (char *label_name) { w_as_label (label_name); w_as_colon(); w_as_newline(); } void w_as_define_label (LABEL *label) { if (label->label_flags & EXPORT_LABEL){ w_as_opcode (IF_GNU (IF_MACH_O (".globl",".global"),"export")); w_as_label (label->label_name); w_as_newline(); } w_as_label (label->label_name); w_as_colon(); w_as_newline(); } static void w_as_local_label (int label_number) { fprintf (assembly_file,"l_%d",label_number); } static void w_as_internal_label (int label_number) { fprintf (assembly_file,"i_%d",label_number); } static void w_as_immediate (LONG i) { fprintf (assembly_file,"%ld",i); } void w_as_abc_string_and_label_in_data_section (char *string,int length,char *label_name) { int n; w_as_to_data_section(); w_as_define_label_name (label_name); w_as_opcode (DC_L); fprintf (assembly_file,"%d" NEWLINE_STRING,length); n=w_as_data (0,string,length); if (length & 3) n=w_as_zeros (n,4-(length & 3)); if (n>0) w_as_newline(); } #define REGISTER_O0 (-13) #define REGISTER_O1 (-23) #define REGISTER_R0 (-24) #define RTOC (-22) #define REGISTER_R3 (-21) #define REGISTER_SP (-12) static unsigned char real_reg_num [32] = { 0,12,2,3,4,5,6,7,8,9,10,11,1,13,14,15, 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 }; #define reg_num(r) (real_reg_num[(r)+24]) static void w_as_indirect (int i,int reg) { #ifdef ONLY_REGISTER_NUMBERS if (i>=0) fprintf (assembly_file,"%d(%d)",i,reg_num (reg)); else fprintf (assembly_file,"-%d(%d)",-i,reg_num (reg)); #else if (i>=0) fprintf (assembly_file,"%d(r%d)",i,reg_num (reg)); else fprintf (assembly_file,"-%d(r%d)",-i,reg_num (reg)); #endif } static void w_as_indexed (int offset,struct index_registers *index_registers) { int reg1,reg2; if (offset!=0) internal_error_in_function ("w_as_indexed"); reg1=index_registers->a_reg.r; reg2=index_registers->d_reg.r; #ifdef ONLY_REGISTER_NUMBERS fprintf (assembly_file,"%d,%d",reg_num (reg1),reg_num (reg2)); #else fprintf (assembly_file,"r%d,r%d",reg_num (reg1),reg_num (reg2)); #endif } static void w_as_register (int reg) { #ifdef ONLY_REGISTER_NUMBERS fprintf (assembly_file,"%d",reg_num (reg)); #else fprintf (assembly_file,"r%d",reg_num (reg)); #endif } static void w_as_register_comma (int reg) { #ifdef ONLY_REGISTER_NUMBERS fprintf (assembly_file,"%d,",reg_num (reg)); #else fprintf (assembly_file,"r%d,",reg_num (reg)); #endif } static void w_as_register_newline (int reg) { #ifdef ONLY_REGISTER_NUMBERS fprintf (assembly_file,"%d" NEWLINE_STRING,reg_num (reg)); #else fprintf (assembly_file,"r%d" NEWLINE_STRING,reg_num (reg)); #endif } void w_as_c_string_and_label_in_code_section (char *string,int length,char *label_name) { int n; /* w_as_to_code_section(); */ w_as_to_data_section(); w_as_define_label_name (label_name); n=w_as_data (0,string,length); n=w_as_zeros (n,4-(length & 3)); if (n>0) w_as_newline(); } static void w_as_scratch_register (void) { w_as_register (REGISTER_O0); } static void w_as_fp_register (int fp_reg) { #ifdef ONLY_REGISTER_NUMBERS fprintf (assembly_file,"%d",fp_reg+14); #else fprintf (assembly_file,IF_MACH_O ("f%d","fp%d"),fp_reg+14); #endif } static void w_as_fp_register_comma (int fp_reg) { #ifdef ONLY_REGISTER_NUMBERS fprintf (assembly_file,"%d,",fp_reg+14); #else fprintf (assembly_file,IF_MACH_O ("f%d,","fp%d,"),fp_reg+14); #endif } static void w_as_comma (VOID) { putc (',',assembly_file); } static void w_as_toc_label (struct toc_label *toc_label) { struct label *label; int offset,t_label_number; offset=toc_label->toc_label_offset; label=toc_label->toc_label_label; t_label_number=toc_label->toc_t_label_number; if (offset!=0){ w_as_opcode ("tc"); fprintf (assembly_file,"t_%d{TC}",t_label_number); w_as_comma(); if (label->label_number!=0) w_as_local_label (label->label_number); else w_as_label (label->label_name); if (offset>=0) fprintf (assembly_file,"+%d" NEWLINE_STRING,offset); else fprintf (assembly_file,"-%d" NEWLINE_STRING,-offset); } else { w_as_opcode ("tc"); fprintf (assembly_file,"t_%d{TC}",t_label_number); w_as_comma(); if (label->label_number!=0) w_as_local_label (label->label_number); else w_as_label (label->label_name); w_as_newline(); } } #ifdef GNU_SYNTAX static void load_label (struct label *label,int offset,int reg) { w_as_opcode ("lis"); w_as_register_comma (reg); # ifdef MACH_O fprintf (assembly_file,"ha16("); # endif if (label->label_number!=0) w_as_local_label (label->label_number); else w_as_label (label->label_name); if (offset!=0){ if (offset>=0) fprintf (assembly_file,"+%d",offset); else fprintf (assembly_file,"-%d",-offset); } # ifdef MACH_O fprintf (assembly_file,")" NEWLINE_STRING); # else fprintf (assembly_file,"@ha" NEWLINE_STRING); # endif w_as_opcode ("addi"); w_as_register_comma (reg); w_as_register_comma (reg); # ifdef MACH_O fprintf (assembly_file,"lo16("); # endif if (label->label_number!=0) w_as_local_label (label->label_number); else w_as_label (label->label_name); if (offset!=0){ if (offset>=0) fprintf (assembly_file,"+%d",offset); else fprintf (assembly_file,"-%d",-offset); } # ifdef MACH_O fprintf (assembly_file,")" NEWLINE_STRING); # else fprintf (assembly_file,"@l" NEWLINE_STRING); # endif } #endif static void w_as_load_descriptor (struct parameter *parameter,int reg) { #ifdef GNU_SYNTAX load_label (parameter->parameter_data.l,2+(parameter->parameter_offset<<3),reg); #else int t_label_number; t_label_number=make_toc_label (parameter->parameter_data.l,2+(parameter->parameter_offset<<3)); w_as_opcode ("lwz"); w_as_register_comma (reg); fprintf (assembly_file,"t_%d{TC}(RTOC)" NEWLINE_STRING,t_label_number); #endif } static void w_as_load_label_parameter (struct parameter *parameter,int reg) { #ifdef GNU_SYNTAX load_label (parameter->parameter_data.l,parameter->parameter_offset,reg); #else int t_label_number; t_label_number=make_toc_label (parameter->parameter_data.l,parameter->parameter_offset); w_as_opcode ("lwz"); w_as_register_comma (reg); fprintf (assembly_file,"t_%d{TC}(RTOC)" NEWLINE_STRING,t_label_number); #endif } static void w_as_load_label (struct label *label,int reg) { #ifdef GNU_SYNTAX load_label (label,0,reg); #else int t_label_number; t_label_number=make_toc_label (label,0); w_as_opcode ("lwz"); w_as_register_comma (reg); fprintf (assembly_file,"t_%d{TC}(RTOC)" NEWLINE_STRING,t_label_number); #endif } static void w_as_load_label_with_offset (struct label *label,int offset,int reg) { #ifdef GNU_SYNTAX load_label (label,offset,reg); #else int t_label_number; t_label_number=make_toc_label (label,offset); w_as_opcode ("lwz"); w_as_register_comma (reg); fprintf (assembly_file,"t_%d{TC}(RTOC)" NEWLINE_STRING,t_label_number); #endif } static void w_as_parameter (register struct parameter *parameter) { switch (parameter->parameter_type){ case P_REGISTER: w_as_register (parameter->parameter_data.reg.r); break; case P_LABEL: if (parameter->parameter_data.l->label_number!=0) w_as_local_label (parameter->parameter_data.l->label_number); else w_as_label (parameter->parameter_data.l->label_name); break; case P_INDIRECT: w_as_indirect (parameter->parameter_offset,parameter->parameter_data.reg.r); break; case P_INDEXED: w_as_indexed (parameter->parameter_offset,parameter->parameter_data.ir); break; case P_IMMEDIATE: fprintf (assembly_file,"%ld",parameter->parameter_data.i); break; case P_F_REGISTER: #ifdef ONLY_REGISTER_NUMBERS fprintf (assembly_file,"%d",parameter->parameter_data.reg.r+14); #else fprintf (assembly_file,IF_MACH_O ("f%d","fp%d"),parameter->parameter_data.reg.r+14); #endif break; default: internal_error_in_function ("w_as_parameter"); } } static int w_as_register_parameter (struct parameter parameter,int size_flag) { switch (parameter.parameter_type){ case P_DESCRIPTOR_NUMBER: w_as_load_descriptor (¶meter,REGISTER_O0); return REGISTER_O0; case P_IMMEDIATE: { int i; i=parameter.parameter_data.i; if (i!=(WORD)i){ w_as_opcode ("lis"); w_as_register_comma (REGISTER_O0); w_as_immediate ((i-(WORD)i)>>16); w_as_newline(); i=(WORD)i; w_as_opcode ("addi"); w_as_register_comma (REGISTER_O0); w_as_register_comma (REGISTER_O0); w_as_immediate (i); w_as_newline(); } else { w_as_opcode ("li"); w_as_register_comma (REGISTER_O0); w_as_immediate (i); w_as_newline(); } return REGISTER_O0; } case P_REGISTER: return parameter.parameter_data.reg.r; case P_INDIRECT: w_as_opcode (size_flag==SIZE_LONG ? "lwz" : size_flag==SIZE_WORD ? "lha" : /* "ldsb" */ "lbz"); w_as_register_comma (REGISTER_O0); w_as_indirect (parameter.parameter_offset,parameter.parameter_data.reg.r); w_as_newline(); return REGISTER_O0; case P_INDIRECT_WITH_UPDATE: w_as_opcode (size_flag==SIZE_LONG ? "lwzu" : size_flag==SIZE_WORD ? "lhau" : /* "ldsb" */ "lbzu"); w_as_register_comma (REGISTER_O0); w_as_indirect (parameter.parameter_offset,parameter.parameter_data.reg.r); w_as_newline(); return REGISTER_O0; case P_INDEXED: w_as_opcode (size_flag==SIZE_LONG ? "lwzx" : size_flag==SIZE_WORD ? "lhax" : /*"ldsbx" */ "lbzx" ); w_as_register_comma (REGISTER_O0); w_as_indexed (parameter.parameter_offset,parameter.parameter_data.ir); w_as_newline(); return REGISTER_O0; default: internal_error_in_function ("w_as_register_parameter"); return REGISTER_O0; } } static void w_as_move_instruction (struct instruction *instruction,int size_flag) { switch (instruction->instruction_parameters[1].parameter_type){ case P_REGISTER: switch (instruction->instruction_parameters[0].parameter_type){ case P_DESCRIPTOR_NUMBER: w_as_load_descriptor ( &instruction->instruction_parameters[0], instruction->instruction_parameters[1].parameter_data.reg.r ); return; case P_IMMEDIATE: { int i,r; i=instruction->instruction_parameters[0].parameter_data.i; r=instruction->instruction_parameters[1].parameter_data.reg.r; if (i!=(WORD)i){ w_as_opcode ("lis"); w_as_register_comma (r); w_as_immediate ((i-(WORD)i)>>16); w_as_newline(); i=(WORD)i; w_as_opcode ("addi"); w_as_register_comma (r); w_as_register_comma (r); w_as_immediate (i); w_as_newline(); } else { w_as_opcode ("li"); w_as_register_comma (r); w_as_immediate (i); w_as_newline(); } return; } case P_REGISTER: w_as_opcode ("mr"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); w_as_newline(); return; case P_INDIRECT: w_as_opcode (size_flag==SIZE_LONG ? "lwz" : size_flag==SIZE_WORD ? "lha" : "lbz"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_indirect (instruction->instruction_parameters[0].parameter_offset, instruction->instruction_parameters[0].parameter_data.reg.r); w_as_newline(); return; case P_INDIRECT_WITH_UPDATE: w_as_opcode (size_flag==SIZE_LONG ? "lwzu" : size_flag==SIZE_WORD ? "lhau" : "lbzu"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_indirect (instruction->instruction_parameters[0].parameter_offset, instruction->instruction_parameters[0].parameter_data.reg.r); w_as_newline(); return; case P_INDEXED: w_as_opcode (size_flag==SIZE_LONG ? "lwzx" : size_flag==SIZE_WORD ? "lhax" : "lbzx"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_indexed (instruction->instruction_parameters[0].parameter_offset, instruction->instruction_parameters[0].parameter_data.ir); w_as_newline(); return; default: internal_error_in_function ("w_as_move_instruction"); return; } case P_INDIRECT: { int reg; reg=w_as_register_parameter (instruction->instruction_parameters[0],size_flag); w_as_opcode (size_flag==SIZE_LONG ? "stw" : size_flag==SIZE_WORD ? "sth" : "stb"); w_as_register_comma (reg); w_as_indirect (instruction->instruction_parameters[1].parameter_offset, instruction->instruction_parameters[1].parameter_data.reg.r); w_as_newline(); return; } case P_INDIRECT_WITH_UPDATE: { int reg; reg=w_as_register_parameter (instruction->instruction_parameters[0],size_flag); w_as_opcode (size_flag==SIZE_LONG ? "stwu" : size_flag==SIZE_WORD ? "sthu" : "stbu"); w_as_register_comma (reg); w_as_indirect (instruction->instruction_parameters[1].parameter_offset, instruction->instruction_parameters[1].parameter_data.reg.r); w_as_newline(); return; } case P_INDEXED: { int reg; reg=w_as_register_parameter (instruction->instruction_parameters[0],size_flag); w_as_opcode (size_flag==SIZE_LONG ? "stwx" : size_flag==SIZE_WORD ? "sthx" : "stbx"); w_as_register_comma (reg); w_as_indexed (instruction->instruction_parameters[1].parameter_offset, instruction->instruction_parameters[1].parameter_data.ir); w_as_newline(); return; } case P_INDIRECT_HP: { int reg1,reg2; LONG offset; reg1=w_as_register_parameter (instruction->instruction_parameters[0],size_flag); offset=instruction->instruction_parameters[1].parameter_data.i; reg2=HEAP_POINTER; if (offset!=(WORD)offset){ w_as_opcode ("addis"); w_as_register_comma (REGISTER_O0); w_as_register_comma (reg2); w_as_immediate ((offset-(WORD)offset)>>16); w_as_newline(); reg2=REGISTER_O0; offset=(WORD)offset; } w_as_opcode (size_flag==SIZE_LONG ? "stw" : size_flag==SIZE_WORD ? "sth" : "stb"); w_as_register_comma (reg1); w_as_indirect (offset,reg2); w_as_newline(); return; } default: internal_error_in_function ("w_as_move_instruction"); } } static void w_as_lea_instruction (struct instruction *instruction) { if (instruction->instruction_parameters[1].parameter_type==P_REGISTER) switch (instruction->instruction_parameters[0].parameter_type){ case P_LABEL: w_as_load_label_parameter (&instruction->instruction_parameters[0], instruction->instruction_parameters[1].parameter_data.reg.r); return; case P_INDIRECT: w_as_opcode ("addi"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r); w_as_immediate (instruction->instruction_parameters[0].parameter_offset); w_as_newline(); return; case P_INDEXED: w_as_opcode ("add"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[0].parameter_data.ir->a_reg.r); w_as_register (instruction->instruction_parameters[0].parameter_data.ir->d_reg.r); w_as_newline(); return; } internal_error_in_function ("w_as_lea_instruction"); } static void w_as_or_or_eor_instruction (struct instruction *instruction,char *opcode) { if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){ long i; i=instruction->instruction_parameters[0].parameter_data.i; if ((unsigned short) i != i){ int h; h=(unsigned)i >> (unsigned)16; fprintf (assembly_file,"\t%sis\t",opcode); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_immediate (h); w_as_newline(); i=(unsigned short)i; } fprintf (assembly_file,"\t%si\t",opcode); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_immediate (i); w_as_newline(); } else { int reg; reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG); w_as_opcode (opcode); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register (reg); w_as_newline(); } } static void w_as_tryadic_instruction (struct instruction *instruction,char *opcode) { if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){ fprintf (assembly_file,"\t%si\t",opcode); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_parameter (&instruction->instruction_parameters[0]); w_as_newline(); } else { int reg; reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG); w_as_opcode (opcode); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register (reg); w_as_newline(); } } static void w_as_i_instruction (struct instruction *instruction,char *opcode) { w_as_opcode (opcode); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r); w_as_immediate (instruction->instruction_parameters[2].parameter_data.i); w_as_newline(); } static void w_as_and_instruction (struct instruction *instruction) { int reg; if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){ int i,i2; i=instruction->instruction_parameters[0].parameter_data.i; if (i==(UWORD)i){ w_as_opcode ("andi."); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_immediate (i); w_as_newline(); return; } else if (((UWORD)i)==0){ w_as_opcode ("andis."); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_immediate (((unsigned int)i)>>16); w_as_newline(); return; } else if (i2=i | (i-1),(i2 & (i2+1))==0){ int n_leading_0_bits,n_leading_0_bits_and_1_bits; n_leading_0_bits = __cntlzw (i); n_leading_0_bits_and_1_bits = __cntlzw (i ^ ((unsigned)0xffffffffu>>(unsigned)n_leading_0_bits)); w_as_opcode ("rlwinm"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_immediate (0); w_as_comma(); w_as_immediate (n_leading_0_bits); w_as_comma(); w_as_immediate (n_leading_0_bits_and_1_bits-1); w_as_newline(); return; } else { w_as_opcode ("lis"); w_as_register_comma (REGISTER_O0); w_as_immediate ((i-(WORD)i)>>16); w_as_newline(); i=(WORD)i; w_as_opcode ("addi"); w_as_register_comma (REGISTER_O0); w_as_register_comma (REGISTER_O0); w_as_immediate (i); w_as_newline(); reg=REGISTER_O0; w_as_opcode ("and"); } } else { reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG); w_as_opcode ("and"); } w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register (reg); w_as_newline(); } static void w_as_add_instruction (struct instruction *instruction) { switch (instruction->instruction_parameters[0].parameter_type){ case P_REGISTER: w_as_opcode ("add"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); w_as_newline(); return; case P_IMMEDIATE: { int i,r; i=instruction->instruction_parameters[0].parameter_data.i; r=instruction->instruction_parameters[1].parameter_data.reg.r; if (i!=(WORD)i){ w_as_opcode ("addis"); w_as_register_comma (r); w_as_register_comma (r); w_as_immediate ((i-(WORD)i)>>16); w_as_newline(); i=(WORD)i; } w_as_opcode ("addi"); w_as_register_comma (r); w_as_register_comma (r); w_as_immediate (i); w_as_newline(); return; } default: { int reg; reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG); w_as_opcode ("add"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register (reg); w_as_newline(); } } } static void w_as_extb_instruction (struct instruction *instruction) { int reg; reg=instruction->instruction_parameters[0].parameter_data.reg.r; w_as_opcode ("extsb"); w_as_register_comma (reg); w_as_register (reg); w_as_newline(); } static void w_as_addo_instruction (struct instruction *instruction) { int reg; reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG); w_as_opcode ("addo."); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register (reg); w_as_newline(); } static void w_as_sub_instruction (struct instruction *instruction) { switch (instruction->instruction_parameters[0].parameter_type){ case P_REGISTER: w_as_opcode ("sub"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); w_as_newline(); return; case P_IMMEDIATE: { int i,r; i= -instruction->instruction_parameters[0].parameter_data.i; r=instruction->instruction_parameters[1].parameter_data.reg.r; if (i!=(WORD)i){ w_as_opcode ("addis"); w_as_register_comma (r); w_as_register_comma (r); w_as_immediate ((i-(WORD)i)>>16); w_as_newline(); i=(WORD)i; } w_as_opcode ("addi"); w_as_register_comma (r); w_as_register_comma (r); w_as_immediate (i); w_as_newline(); return; } default: { int reg; reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG); w_as_opcode ("sub"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register (reg); w_as_newline(); } } } static void w_as_subo_instruction (struct instruction *instruction) { int reg; reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG); w_as_opcode ("subo."); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register (reg); w_as_newline(); } static void w_as_cmp_instruction (struct instruction *instruction) { struct parameter parameter_0,parameter_1; parameter_0=instruction->instruction_parameters[0]; parameter_1=instruction->instruction_parameters[1]; if (parameter_1.parameter_type==P_INDIRECT || parameter_1.parameter_type==P_INDEXED){ if (parameter_1.parameter_type==P_INDIRECT) w_as_opcode ("lwz"); else w_as_opcode ("lwzx"); w_as_register_comma (REGISTER_O1); w_as_parameter (¶meter_1); w_as_newline(); parameter_1.parameter_type=P_REGISTER; parameter_1.parameter_data.reg.r=REGISTER_O1; } switch (parameter_0.parameter_type){ case P_DESCRIPTOR_NUMBER: w_as_load_descriptor (¶meter_0,REGISTER_O0); parameter_0.parameter_type=P_REGISTER; parameter_0.parameter_data.reg.r=REGISTER_O0; break; case P_REGISTER: break; case P_IMMEDIATE: { int i; i=parameter_0.parameter_data.i; if (i!=(WORD)i){ w_as_opcode ("lis"); w_as_register_comma (REGISTER_O0); w_as_immediate ((i-(WORD)i)>>16); w_as_newline(); i=(WORD)i; w_as_opcode ("addi"); w_as_register_comma (REGISTER_O0); w_as_register_comma (REGISTER_O0); w_as_immediate (i); w_as_newline(); parameter_0.parameter_type=P_REGISTER; parameter_0.parameter_data.reg.r=REGISTER_O0; } break; } case P_INDIRECT: w_as_opcode ("lwz"); w_as_register_comma (REGISTER_O0); w_as_parameter (¶meter_0); w_as_newline(); parameter_0.parameter_type=P_REGISTER; parameter_0.parameter_data.reg.r=REGISTER_O0; break; case P_INDEXED: w_as_opcode ("lwzx"); w_as_register_comma (REGISTER_O0); w_as_parameter (¶meter_0); w_as_newline(); parameter_0.parameter_type=P_REGISTER; parameter_0.parameter_data.reg.r=REGISTER_O0; break; } w_as_opcode (parameter_0.parameter_type==P_IMMEDIATE ? "cmpwi" : "cmpw"); w_as_immediate (0); w_as_comma(); w_as_parameter (¶meter_1); w_as_comma(); w_as_parameter (¶meter_0); w_as_newline(); } #if 0 static void w_as_cmpw_instruction (struct instruction *instruction) { struct parameter parameter_0,parameter_1; parameter_0=instruction->instruction_parameters[0]; parameter_1=instruction->instruction_parameters[1]; if (parameter_1.parameter_type==P_INDIRECT || parameter_1.parameter_type==P_INDEXED){ if (parameter_1.parameter_type==P_INDIRECT) w_as_opcode ("lha"); else w_as_opcode ("lhax"); w_as_register_comma (REGISTER_O1); w_as_parameter (¶meter_1); w_as_newline(); parameter_1.parameter_type=P_REGISTER; parameter_1.parameter_data.reg.r=REGISTER_O1; } switch (parameter_0.parameter_type){ case P_DESCRIPTOR_NUMBER: w_as_load_descriptor (¶meter_0,REGISTER_O0); parameter_0.parameter_type=P_REGISTER; parameter_0.parameter_data.reg.r=REGISTER_O0; break; case P_REGISTER: break; case P_IMMEDIATE: { int i; i=parameter_0.parameter_data.i; if (i!=(WORD)i){ w_as_opcode ("lis"); w_as_register_comma (REGISTER_O0); w_as_immediate ((i-(WORD)i)>>16); w_as_newline(); i=(WORD)i; w_as_opcode ("addi"); w_as_register_comma (REGISTER_O0); w_as_register_comma (REGISTER_O0); w_as_immediate (i); w_as_newline(); parameter_0.parameter_type=P_REGISTER; parameter_0.parameter_data.reg.r=REGISTER_O0; } break; } case P_INDIRECT: w_as_opcode ("lha"); w_as_register_comma (REGISTER_O0); w_as_parameter (¶meter_0); w_as_newline(); parameter_0.parameter_type=P_REGISTER; parameter_0.parameter_data.reg.r=REGISTER_O0; break; case P_INDEXED: w_as_opcode ("lhax"); w_as_register_comma (REGISTER_O0); w_as_parameter (¶meter_0); w_as_newline(); parameter_0.parameter_type=P_REGISTER; parameter_0.parameter_data.reg.r=REGISTER_O0; break; } w_as_opcode (parameter_0.parameter_type==P_IMMEDIATE ? "cmpwi" : "cmpw"); w_as_immediate (0); w_as_comma(); w_as_parameter (¶meter_1); w_as_comma(); w_as_parameter (¶meter_0); w_as_newline(); } #endif static void w_as_cmplw_instruction (struct instruction *instruction) { w_as_opcode ("lwz"); w_as_register_comma (REGISTER_O0); w_as_parameter (&instruction->instruction_parameters[0]); w_as_newline(); w_as_opcode ("cmplw"); w_as_immediate (0); w_as_comma(); w_as_parameter (&instruction->instruction_parameters[1]); w_as_comma(); w_as_register (REGISTER_O0); w_as_newline(); } static void w_as_tst_instruction (struct instruction *instruction) { int reg; reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG); w_as_opcode ("cmpwi"); w_as_immediate (0); w_as_comma(); w_as_register_comma (reg); w_as_immediate (0); w_as_newline(); } static void w_as_btst_instruction (struct instruction *instruction) { w_as_opcode ("andi."); w_as_register_comma (REGISTER_O0); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); w_as_newline(); } void w_as_jmp_instruction (struct instruction *instruction) { struct parameter *parameter0; parameter0=&instruction->instruction_parameters[0]; switch (parameter0->parameter_type){ case P_LABEL: w_as_opcode ("b"); if (parameter0->parameter_data.l->label_number!=0) w_as_local_label (parameter0->parameter_data.l->label_number); else w_as_label (parameter0->parameter_data.l->label_name); w_as_newline(); return; case P_INDIRECT: { int offset,reg; offset=parameter0->parameter_offset; reg=parameter0->parameter_data.reg.r; if (offset!=0){ w_as_opcode ("la"); w_as_register_comma (REGISTER_O0); w_as_indirect (offset,reg); w_as_newline(); w_as_opcode ("mtctr"); w_as_register (REGISTER_O0); w_as_newline(); } else { w_as_opcode ("mtctr"); w_as_register (reg); w_as_newline(); } w_as_instruction_without_parameters ("bctr"); return; } default: internal_error_in_function ("w_as_jmp_instruction"); } } static void w_as_jmpp_instruction (struct instruction *instruction) { struct parameter *parameter0; parameter0=&instruction->instruction_parameters[0]; switch (parameter0->parameter_type){ case P_LABEL: { int offset; offset=instruction->instruction_parameters[0].parameter_offset; if (offset==0){ w_as_opcode ("mflr"); w_as_register (REGISTER_R0); w_as_newline(); w_as_opcode ("bl"); w_as_label ("profile_t"); w_as_newline(); } w_as_opcode ("b"); if (instruction->instruction_parameters[0].parameter_data.l->label_number!=0) w_as_local_label (instruction->instruction_parameters[0].parameter_data.l->label_number); else w_as_label (instruction->instruction_parameters[0].parameter_data.l->label_name); if (offset!=0) fprintf (assembly_file,"+%d",offset); w_as_newline(); return; } case P_INDIRECT: { int offset,reg; offset=parameter0->parameter_offset; reg=parameter0->parameter_data.reg.r; if (offset!=0){ w_as_opcode ("la"); w_as_register_comma (REGISTER_O0); w_as_indirect (offset,reg); w_as_newline(); w_as_opcode ("mtctr"); w_as_register (REGISTER_O0); w_as_newline(); } else { w_as_opcode ("mtctr"); w_as_register (reg); w_as_newline(); } w_as_opcode ("b"); w_as_label ("profile_ti"); w_as_newline(); return; } default: internal_error_in_function ("w_as_jmpp_instruction"); } } static void w_as_neg_instruction (struct instruction *instruction) { w_as_opcode ("neg"); w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r); w_as_register_newline (instruction->instruction_parameters[0].parameter_data.reg.r); } static void w_as_not_instruction (struct instruction *instruction) { w_as_opcode ("nand"); w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r); w_as_register_newline (instruction->instruction_parameters[0].parameter_data.reg.r); } struct call_and_jump { struct call_and_jump * cj_next; WORD cj_label_id; WORD cj_jump_id; /* or -1 for far conditional jump */ char * cj_call_label_name; }; static struct call_and_jump *first_call_and_jump,*last_call_and_jump; static struct call_and_jump *allocate_new_call_and_jump (void) { struct call_and_jump *new_call_and_jump; new_call_and_jump=allocate_memory_from_heap_type (struct call_and_jump); new_call_and_jump->cj_next=NULL; if (first_call_and_jump!=NULL) last_call_and_jump->cj_next=new_call_and_jump; else first_call_and_jump=new_call_and_jump; last_call_and_jump=new_call_and_jump; return new_call_and_jump; } static void w_as_branch_instruction (struct instruction *instruction,char *opcode) { w_as_opcode (opcode); if (instruction->instruction_parameters[0].parameter_data.l->label_flags & FAR_CONDITIONAL_JUMP_LABEL){ struct call_and_jump *new_call_and_jump; int label_id; label_id=next_label_id++; new_call_and_jump=allocate_new_call_and_jump(); new_call_and_jump->cj_call_label_name=instruction->instruction_parameters[0].parameter_data.l->label_name; new_call_and_jump->cj_label_id=label_id; new_call_and_jump->cj_jump_id=-1; w_as_internal_label (label_id); } else w_as_parameter (&instruction->instruction_parameters[0]); w_as_newline(); } static void w_as_index_error_branch_instruction (struct instruction *instruction) { w_as_opcode ("blt+"); fprintf (assembly_file,".+8"); w_as_newline(); w_as_opcode ("b"); w_as_parameter (&instruction->instruction_parameters[0]); w_as_newline(); } static void w_as_branchno_instruction (struct instruction *instruction) { w_as_opcode ("bns"); w_as_parameter (&instruction->instruction_parameters[0]); w_as_newline(); w_as_opcode ("mcrxr"); w_as_immediate (0); w_as_newline(); w_as_opcode ("bng"); w_as_parameter (&instruction->instruction_parameters[0]); w_as_newline(); } static void w_as_brancho_instruction (struct instruction *instruction) { w_as_opcode ("bns"); fprintf (assembly_file,IF_GNU ("$+12","*+12")); w_as_newline(); w_as_opcode ("mcrxr"); w_as_immediate (0); w_as_newline(); w_as_opcode ("bgt"); w_as_parameter (&instruction->instruction_parameters[0]); w_as_newline(); } #ifdef MACH_O struct stub { char *stub_label_name; struct stub *stub_next; }; static struct stub *first_stub,**next_stub_l; static void write_stub (char *label_name,int stub_n) { fprintf (assembly_file,".picsymbol_stub" NEWLINE_STRING); fprintf (assembly_file,"L_%s$stub:" NEWLINE_STRING,label_name); fprintf (assembly_file,"\t.indirect_symbol _%s" NEWLINE_STRING,label_name); fprintf (assembly_file,"\tmflr\tr0" NEWLINE_STRING); fprintf (assembly_file,"\tbcl\t20,31,L%d$pb" NEWLINE_STRING,stub_n); fprintf (assembly_file,"L%d$pb:" NEWLINE_STRING,stub_n); fprintf (assembly_file,"\tmflr\tr11" NEWLINE_STRING); fprintf (assembly_file,"\taddis\tr11,r11,ha16(L%d$lz-L%d$pb)" NEWLINE_STRING,stub_n,stub_n); fprintf (assembly_file,"\tmtlr\tr0" NEWLINE_STRING); fprintf (assembly_file,"\tlwz\tr12,lo16(L%d$lz-L%d$pb)(r11)" NEWLINE_STRING,stub_n,stub_n); fprintf (assembly_file,"\tmtctr\tr12" NEWLINE_STRING); fprintf (assembly_file,"\taddi\tr11,r11,lo16(L%d$lz-L%d$pb )" NEWLINE_STRING,stub_n,stub_n); fprintf (assembly_file,"\tbctr" NEWLINE_STRING); fprintf (assembly_file,".lazy_symbol_pointer" NEWLINE_STRING); fprintf (assembly_file,"L%d$lz:" NEWLINE_STRING,stub_n); fprintf (assembly_file,".indirect_symbol _%s" NEWLINE_STRING,label_name); fprintf (assembly_file,"\t.long\tdyld_stub_binding_helper" NEWLINE_STRING); } static void write_stubs (void) { struct stub *stub; int stub_n; stub_n=1; for_l (stub,first_stub,stub_next){ write_stub (stub->stub_label_name,stub_n); ++stub_n; } } #endif static void w_as_jsr_instruction (struct instruction *instruction) { struct parameter *parameter0; parameter0=&instruction->instruction_parameters[0]; if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){ int frame_size; frame_size=instruction->instruction_parameters[1].parameter_data.i; if (parameter0->parameter_type==P_REGISTER){ #ifdef MACH_O w_as_opcode ("mtctr"); w_as_register (parameter0->parameter_data.reg.r); w_as_newline(); #else w_as_opcode ("lwz"); w_as_register_comma (REGISTER_O1); w_as_indirect (0,parameter0->parameter_data.reg.r); w_as_newline(); w_as_opcode ("stw"); w_as_register_comma (RTOC); w_as_indirect (20-(frame_size+28),B_STACK_POINTER); w_as_newline(); w_as_opcode ("lwz"); w_as_register_comma (RTOC); w_as_indirect (4,parameter0->parameter_data.reg.r); w_as_newline(); w_as_opcode ("mtctr"); w_as_register (REGISTER_O1); w_as_newline(); #endif } if (!(instruction->instruction_arity & NO_MFLR)){ w_as_opcode ("mflr"); w_as_register (REGISTER_R0); w_as_newline(); } #ifdef ALIGN_C_CALLS # if 0 w_as_opcode ("mr"); w_as_register_comma (REGISTER_O0); w_as_register (B_STACK_POINTER); w_as_newline(); w_as_opcode ("ori"); w_as_register_comma (B_STACK_POINTER); w_as_register_comma (B_STACK_POINTER); w_as_immediate (28); w_as_newline(); # endif w_as_opcode ("stw"); w_as_register_comma (REGISTER_R0); w_as_indirect (-28-4,B_STACK_POINTER); w_as_newline(); w_as_opcode ("stwu"); w_as_register_comma (REGISTER_O0); w_as_indirect (-(frame_size+28),B_STACK_POINTER); w_as_newline(); #else w_as_opcode ("stw"); w_as_register_comma (REGISTER_R0); w_as_indirect (-4,B_STACK_POINTER); w_as_newline(); w_as_opcode ("stwu"); w_as_register_comma (B_STACK_POINTER); w_as_indirect (-frame_size,B_STACK_POINTER); w_as_newline(); #endif if (parameter0->parameter_type==P_REGISTER){ w_as_instruction_without_parameters ("bctrl"); #ifdef MACH_O w_as_instruction_without_parameters ("nop"); #else w_as_opcode ("lwz"); w_as_register_comma (RTOC); w_as_indirect (20,B_STACK_POINTER); w_as_newline(); #endif } else { w_as_opcode ("bl"); if (parameter0->parameter_data.l->label_number!=0) w_as_local_label (parameter0->parameter_data.l->label_number); else #ifdef MACH_O { char *label_name; label_name=parameter0->parameter_data.l->label_name; if (label_name[0]=='_'){ int c; struct stub *new_stub; putc ('L',assembly_file); putc ('_',assembly_file); ++label_name; if (!(parameter0->parameter_data.l->label_flags & STUB_GENERATED)){ parameter0->parameter_data.l->label_flags |= STUB_GENERATED; new_stub=allocate_memory_from_heap (sizeof (struct stub)); new_stub->stub_label_name=label_name; *next_stub_l=new_stub; next_stub_l=&new_stub->stub_next; new_stub->stub_next=NULL; } while (c=*label_name++,c!=0) putc (c,assembly_file); fprintf (assembly_file,"$stub"); } else w_as_label (label_name); } #else w_as_label (parameter0->parameter_data.l->label_name); #endif w_as_newline(); w_as_instruction_without_parameters ("nop"); } #ifdef ALIGN_C_CALLS w_as_opcode ("lwz"); w_as_register_comma (REGISTER_R0); w_as_indirect (frame_size-4,B_STACK_POINTER); w_as_newline(); w_as_opcode ("lwz"); w_as_register_comma (B_STACK_POINTER); w_as_indirect (0,B_STACK_POINTER); w_as_newline(); #else w_as_opcode ("lwz"); w_as_register_comma (REGISTER_R0); w_as_indirect (frame_size-4,B_STACK_POINTER); w_as_newline(); w_as_opcode ("addi"); w_as_register_comma (B_STACK_POINTER); w_as_register_comma (B_STACK_POINTER); w_as_immediate (frame_size); w_as_newline(); #endif if (!(instruction->instruction_arity & NO_MTLR)){ w_as_opcode ("mtlr"); w_as_register (REGISTER_R0); w_as_newline(); } return; } if (parameter0->parameter_type==P_INDIRECT){ int offset,reg; offset=parameter0->parameter_offset; reg=parameter0->parameter_data.reg.r; if (offset!=0){ w_as_opcode ("la"); w_as_register_comma (REGISTER_O0); w_as_indirect (offset,reg); w_as_newline(); w_as_opcode ("mtctr"); w_as_register (REGISTER_O0); w_as_newline(); } else { w_as_opcode ("mtctr"); w_as_register (reg); w_as_newline(); } } if (!(instruction->instruction_arity & NO_MFLR)){ w_as_opcode ("mflr"); w_as_register (REGISTER_R0); w_as_newline(); } w_as_opcode (instruction->instruction_parameters[1].parameter_type==P_INDIRECT_WITH_UPDATE ? "stwu" : "stw"); w_as_register_comma (REGISTER_R0); w_as_indirect (instruction->instruction_parameters[1].parameter_data.i,B_STACK_POINTER); w_as_newline(); switch (parameter0->parameter_type){ case P_LABEL: w_as_opcode ("bl"); if (parameter0->parameter_data.l->label_number!=0) w_as_local_label (parameter0->parameter_data.l->label_number); else w_as_label (parameter0->parameter_data.l->label_name); break; case P_INDIRECT: w_as_opcode ("bctrl"); break; default: internal_error_in_function ("w_as_jsr_instruction"); } w_as_newline(); if (!(instruction->instruction_arity & NO_MTLR)){ w_as_opcode ("mtlr"); w_as_register (REGISTER_R0); w_as_newline(); } } static void w_as_call_and_jump (struct call_and_jump *call_and_jump) { w_as_new_code_module(); w_as_define_internal_label (call_and_jump->cj_label_id); if (call_and_jump->cj_jump_id==-1){ w_as_opcode ("b"); w_as_label (call_and_jump->cj_call_label_name); w_as_newline(); } else { w_as_opcode ("mflr"); w_as_register (REGISTER_R0); w_as_newline(); w_as_opcode ("bl"); w_as_label (call_and_jump->cj_call_label_name); w_as_newline(); w_as_opcode ("b"); w_as_internal_label (call_and_jump->cj_jump_id); w_as_newline(); } } static void w_as_rts_begin (struct instruction *instruction) { LONG b_offset; if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT){ w_as_opcode ("lwz"); w_as_register_comma (REGISTER_R0); w_as_indirect (instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.reg.r); } else { w_as_opcode ("mr"); w_as_register_comma (REGISTER_R0); w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); } w_as_newline(); b_offset=instruction->instruction_parameters[1].parameter_data.i; if (b_offset!=0){ if (b_offset!=(WORD) b_offset){ w_as_opcode ("addis"); w_as_register_comma (B_STACK_POINTER); w_as_register_comma (B_STACK_POINTER); w_as_immediate ((b_offset-(WORD)b_offset)>>16); w_as_newline(); b_offset=(WORD)b_offset; } w_as_opcode ("addi"); w_as_register_comma (B_STACK_POINTER); w_as_register_comma (B_STACK_POINTER); w_as_immediate (b_offset); w_as_newline(); } } static void w_as_rts_instruction (struct instruction *instruction) { if (instruction->instruction_arity>0) w_as_rts_begin (instruction); w_as_instruction_without_parameters ("blr"); } static void w_as_rtsp_instruction (struct instruction *instruction) { w_as_rts_begin (instruction); w_as_opcode ("b"); w_as_label ("profile_r"); w_as_newline(); } static void w_as_set_condition_instruction (struct instruction *instruction,char *opcode) { w_as_opcode ("li"); w_as_parameter (&instruction->instruction_parameters[0]); w_as_comma(); w_as_immediate (0); w_as_newline(); w_as_opcode (opcode); fprintf (assembly_file,IF_GNU ("$+8","*+8")); w_as_newline(); w_as_opcode ("li"); w_as_parameter (&instruction->instruction_parameters[0]); w_as_comma(); w_as_immediate (-1); w_as_newline(); } static void w_as_setno_condition_instruction (struct instruction *instruction) { w_as_opcode ("li"); w_as_parameter (&instruction->instruction_parameters[0]); w_as_comma(); w_as_immediate (0); w_as_newline(); w_as_opcode ("bns"); fprintf (assembly_file,IF_GNU ("$+12","*+12")); w_as_newline(); w_as_opcode ("mcrxr"); w_as_immediate (0); w_as_newline(); w_as_opcode ("bgt"); fprintf (assembly_file,IF_GNU ("$+8","*+8")); w_as_newline(); w_as_opcode ("li"); w_as_parameter (&instruction->instruction_parameters[0]); w_as_comma(); w_as_immediate (-1); w_as_newline(); } static void w_as_seto_condition_instruction (struct instruction *instruction) { w_as_opcode ("li"); w_as_parameter (&instruction->instruction_parameters[0]); w_as_comma(); w_as_immediate (0); w_as_newline(); w_as_opcode ("bns"); fprintf (assembly_file,IF_GNU ("$+16","*+16")); w_as_newline(); w_as_opcode ("mcrxr"); w_as_immediate (0); w_as_newline(); w_as_opcode ("bng"); fprintf (assembly_file,IF_GNU ("$+8","*+8")); w_as_newline(); w_as_opcode ("li"); w_as_parameter (&instruction->instruction_parameters[0]); w_as_comma(); w_as_immediate (-1); w_as_newline(); } static void w_as_divi (int i,int s_reg,int d_reg) { struct ms ms; ms=magic (abs (i)); w_as_opcode ("lis"); w_as_register_comma (REGISTER_O0); w_as_immediate ((ms.m-(WORD)ms.m)>>16); w_as_newline(); w_as_opcode ("addi"); w_as_register_comma (REGISTER_O0); w_as_register_comma (REGISTER_O0); w_as_immediate ((WORD)ms.m); w_as_newline(); w_as_opcode ("mulhw"); w_as_register_comma (REGISTER_O0); w_as_register_comma (REGISTER_O0); w_as_register_newline (s_reg); if (ms.m<0){ w_as_opcode ("add"); w_as_register_comma (REGISTER_O0); w_as_register_comma (REGISTER_O0); w_as_register_newline (s_reg); } w_as_opcode (i>=0 ? "srwi" : "srawi"); w_as_register_comma (d_reg); w_as_register_comma (s_reg); w_as_immediate (31); w_as_newline(); if (ms.s>0){ w_as_opcode ("srawi"); w_as_register_comma (REGISTER_O0); w_as_register_comma (REGISTER_O0); w_as_immediate (ms.s); w_as_newline(); } w_as_opcode (i>=0 ? "add" : "sub"); w_as_register_comma (d_reg); w_as_register_comma (d_reg); w_as_register_newline (REGISTER_O0); } static void w_as_rem_instruction (struct instruction *instruction) { int reg; if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){ int i,sd_reg; i=instruction->instruction_parameters[0].parameter_data.i; if (i<0 && i!=0x80000000) i=-i; if ((i & (i-1))==0 && i>1){ int log2i; log2i=0; while (i>1){ i=i>>1; ++log2i; } sd_reg=instruction->instruction_parameters[1].parameter_data.reg.r; w_as_opcode ("srawi"); w_as_register_comma (REGISTER_O1); w_as_register_comma (sd_reg); w_as_immediate (31); w_as_newline(); if (log2i==1){ w_as_opcode ("andi."); w_as_register_comma (sd_reg); w_as_register_comma (sd_reg); w_as_immediate (1); w_as_newline(); w_as_opcode ("xor"); w_as_register_comma (sd_reg); w_as_register_comma (sd_reg); w_as_register_newline (REGISTER_O1); } else { w_as_opcode ("rlwinm"); w_as_register_comma (REGISTER_O1); w_as_register_comma (REGISTER_O1); w_as_immediate (0); w_as_comma(); w_as_immediate (32-log2i); w_as_comma(); w_as_immediate (31); w_as_newline(); w_as_opcode ("add"); w_as_register_comma (sd_reg); w_as_register_comma (sd_reg); w_as_register_newline (REGISTER_O1); w_as_opcode ("rlwinm"); w_as_register_comma (sd_reg); w_as_register_comma (sd_reg); w_as_immediate (0); w_as_comma(); w_as_immediate (32-log2i); w_as_comma(); w_as_immediate (31); w_as_newline(); } w_as_opcode ("sub"); w_as_register_comma (sd_reg); w_as_register_comma (sd_reg); w_as_register_newline (REGISTER_O1); return; } else if (i>1 || (i<-1 && i!=0x80000000)){ int i2; sd_reg=instruction->instruction_parameters[1].parameter_data.reg.r; w_as_divi (i,sd_reg,REGISTER_O1); i2=i & (i-1); if ((i2 & (i2-1))==0){ unsigned int n; int n_shifts; n=i; n_shifts=0; while (n>0){ while ((n & 1)==0){ n>>=1; ++n_shifts; } if (n_shifts>0){ w_as_opcode ("slwi"); w_as_register_comma (REGISTER_O1); w_as_register_comma (REGISTER_O1); w_as_immediate (n_shifts); w_as_newline(); } w_as_opcode ("sub"); w_as_register_comma (sd_reg); w_as_register_comma (sd_reg); w_as_register_newline (REGISTER_O1); n>>=1; n_shifts=1; } } else { if (i!=(WORD)i){ w_as_opcode ("lis"); w_as_register_comma (REGISTER_O0); w_as_immediate ((i-(WORD)i)>>16); w_as_newline(); i=(WORD)i; w_as_opcode ("addi"); w_as_register_comma (REGISTER_O0); w_as_register_comma (REGISTER_O0); w_as_immediate (i); w_as_newline(); w_as_opcode ("mullw"); w_as_register_comma (REGISTER_O1); w_as_register_comma (REGISTER_O1); w_as_register_newline (REGISTER_O0); } else { w_as_opcode ("mulli"); w_as_register_comma (REGISTER_O1); w_as_register_comma (REGISTER_O1); w_as_immediate (i); w_as_newline(); } w_as_opcode ("sub"); w_as_register_comma (sd_reg); w_as_register_comma (sd_reg); w_as_register_newline (REGISTER_O1); } return; } } reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG); w_as_opcode ("divw"); w_as_register_comma (REGISTER_O1); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_newline (reg); w_as_opcode ("mullw"); w_as_register_comma (REGISTER_O1); w_as_register_comma (REGISTER_O1); w_as_register_newline (reg); w_as_opcode ("sub"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_newline (REGISTER_O1); } static void w_as_div_instruction (struct instruction *instruction) { int reg; if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){ int i,sd_reg; i=instruction->instruction_parameters[0].parameter_data.i; if ((i & (i-1))==0 && i>0){ int log2i; if (i==1) return; log2i=0; while (i>1){ i=i>>1; ++log2i; } sd_reg=instruction->instruction_parameters[1].parameter_data.reg.r; w_as_opcode ("srawi"); w_as_register_comma (sd_reg); w_as_register_comma (sd_reg); w_as_immediate (log2i); w_as_newline(); w_as_opcode ("addze"); w_as_register_comma (sd_reg); w_as_register_newline (sd_reg); return; } else if (i>1 || (i<-1 && i!=0x80000000)){ sd_reg=instruction->instruction_parameters[1].parameter_data.reg.r; w_as_divi (i,sd_reg,sd_reg); return; } } reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG); w_as_opcode ("divw"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_newline (reg); } static void w_as_divu_instruction (struct instruction *instruction) { int reg; reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG); w_as_opcode ("divwu"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_register_newline (reg); } static void w_as_mul_instruction (struct instruction *instruction) { int r,reg; r=instruction->instruction_parameters[1].parameter_data.reg.r; switch (instruction->instruction_parameters[0].parameter_type){ case P_IMMEDIATE: { int i; i=instruction->instruction_parameters[0].parameter_data.i; if (i!=(WORD)i){ w_as_opcode ("lis"); w_as_register_comma (REGISTER_O0); w_as_immediate ((i-(WORD)i)>>16); w_as_newline(); i=(WORD)i; w_as_opcode ("addi"); w_as_register_comma (REGISTER_O0); w_as_register_comma (REGISTER_O0); w_as_immediate (i); w_as_newline(); } else { w_as_opcode ("mulli"); w_as_register_comma (r); w_as_register_comma (r); w_as_immediate (i); w_as_newline(); return; } reg=REGISTER_O0; break; } default: reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG); } w_as_opcode ("mullw"); w_as_register_comma (r); w_as_register_comma (r); w_as_register (reg); w_as_newline(); } static void w_as_umulh_instruction (struct instruction *instruction) { int r,reg; r=instruction->instruction_parameters[1].parameter_data.reg.r; reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG); w_as_opcode ("mulhwu"); w_as_register_comma (r); w_as_register_comma (r); w_as_register (reg); w_as_newline(); } static void w_as_mulo_instruction (struct instruction *instruction) { int r,reg; reg=w_as_register_parameter (instruction->instruction_parameters[0],SIZE_LONG); r=instruction->instruction_parameters[1].parameter_data.reg.r; w_as_opcode ("mullwo."); w_as_register_comma (r); w_as_register_comma (r); w_as_register (reg); w_as_newline(); } static int next_bmove_label; static void w_as_word_instruction (struct instruction *instruction) { fprintf (assembly_file,"\t" DC_L "\t%d" NEWLINE_STRING, (int)instruction->instruction_parameters[0].parameter_data.i); } static void w_as_load_float_immediate (double float_value,int fp_reg) { int label_number,t_label_number; struct label *new_label; new_label=(struct label*)allocate_memory_from_heap (sizeof (struct label)); label_number=next_label_id++; w_as_to_data_section(); #ifdef GNU_SYNTAX fprintf (assembly_file,"\t.align\t8" NEWLINE_STRING); #else fprintf (assembly_file,"\talign\t3" NEWLINE_STRING); #endif new_label->label_flags=0; new_label->label_number=label_number; /* w_as_define_internal_label (label_number); */ w_as_define_local_label (label_number); #ifdef GNU_SYNTAX w_as_opcode (".double"); fprintf (assembly_file,"0d%.20e",float_value); #else w_as_opcode ("dc.d"); fprintf (assembly_file,"\"%.20e\"",float_value); #endif w_as_newline(); /* w_as_instruction_without_parameters ("toc"); w_as_opcode ("tc"); fprintf (assembly_file,"t_%d{TC}",t_label_number); w_as_comma(); w_as_internal_label (label_number); w_as_newline(); */ #ifndef GNU_SYNTAX t_label_number=make_toc_label (new_label,0); #endif w_as_to_code_section(); w_as_opcode (IF_GNU ("lis","lwz")); w_as_scratch_register(); w_as_comma(); #ifdef GNU_SYNTAX # ifdef MACH_O fprintf (assembly_file,"ha16("); # endif w_as_local_label (label_number); # ifdef MACH_O fprintf (assembly_file,")" NEWLINE_STRING); # else fprintf (assembly_file,"@ha" NEWLINE_STRING); # endif #else fprintf (assembly_file,"t_%d{TC}(RTOC)" NEWLINE_STRING,t_label_number); #endif w_as_opcode ("lfd"); w_as_fp_register_comma (fp_reg); #ifdef GNU_SYNTAX # ifdef MACH_O fprintf (assembly_file,"lo16("); # endif w_as_local_label (label_number); # ifdef MACH_O fprintf (assembly_file,")("); # else fprintf (assembly_file,"@l("); # endif w_as_scratch_register(); fprintf (assembly_file,")" NEWLINE_STRING); #else w_as_indirect (0,REGISTER_O0); w_as_newline(); #endif /*++t_label_number; */ } static struct parameter w_as_float_parameter (struct parameter parameter) { switch (parameter.parameter_type){ case P_F_IMMEDIATE: w_as_load_float_immediate (*parameter.parameter_data.r,17); parameter.parameter_type=P_F_REGISTER; parameter.parameter_data.reg.r=17; break; case P_INDIRECT: w_as_opcode ("lfd"); w_as_fp_register_comma (17); w_as_indirect (parameter.parameter_offset,parameter.parameter_data.reg.r); w_as_newline(); parameter.parameter_type=P_F_REGISTER; parameter.parameter_data.reg.r=17; break; case P_INDEXED: w_as_opcode ("lfdx"); w_as_fp_register_comma (17); w_as_indexed (parameter.parameter_offset,parameter.parameter_data.ir); w_as_newline(); parameter.parameter_type=P_F_REGISTER; parameter.parameter_data.reg.r=17; break; } return parameter; } static void w_as_compare_float_instruction (struct instruction *instruction) { struct parameter parameter_0; parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]); w_as_opcode ("fcmpu"); w_as_immediate (0); w_as_comma(); w_as_parameter (&instruction->instruction_parameters[1]); w_as_comma(); w_as_parameter (¶meter_0); w_as_newline(); } static void w_as_dyadic_float_instruction (struct instruction *instruction,char *opcode) { struct parameter parameter_0; parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]); w_as_opcode (opcode); w_as_parameter (&instruction->instruction_parameters[1]); w_as_comma(); w_as_parameter (¶meter_0); w_as_newline(); } static void w_as_tryadic_float_instruction (struct instruction *instruction,char *opcode) { struct parameter parameter_0; parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]); w_as_opcode (opcode); w_as_parameter (&instruction->instruction_parameters[1]); w_as_comma(); w_as_parameter (&instruction->instruction_parameters[1]); w_as_comma(); w_as_parameter (¶meter_0); w_as_newline(); } #ifdef FMADD #define FP_REG_LAST_USE 4 static struct instruction *w_as_fmul_instruction (struct instruction *instruction) { struct instruction *next_instruction; next_instruction=instruction->instruction_next; if (fmadd_flag && next_instruction!=NULL) if (next_instruction->instruction_icode==IFADD){ if (next_instruction->instruction_parameters[0].parameter_type==P_F_REGISTER && next_instruction->instruction_parameters[0].parameter_data.reg.r!=next_instruction->instruction_parameters[1].parameter_data.reg.r) { if (next_instruction->instruction_parameters[0].parameter_flags & FP_REG_LAST_USE && next_instruction->instruction_parameters[0].parameter_data.reg.r==instruction->instruction_parameters[1].parameter_data.reg.r) { struct parameter parameter_0; parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]); w_as_opcode ("fmadd"); w_as_fp_register_comma (next_instruction->instruction_parameters[1].parameter_data.reg.r); w_as_parameter (¶meter_0); w_as_comma(); w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_parameter (&next_instruction->instruction_parameters[1]); w_as_newline(); return next_instruction; } else if (next_instruction->instruction_parameters[1].parameter_data.reg.r==instruction->instruction_parameters[1].parameter_data.reg.r){ struct parameter parameter_0; parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]); w_as_opcode ("fmadd"); w_as_fp_register_comma (next_instruction->instruction_parameters[1].parameter_data.reg.r); w_as_parameter (¶meter_0); w_as_comma(); w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_parameter (&next_instruction->instruction_parameters[0]); w_as_newline(); return next_instruction; } } else if (next_instruction->instruction_parameters[1].parameter_data.reg.r==instruction->instruction_parameters[1].parameter_data.reg.r){ if (next_instruction->instruction_parameters[0].parameter_type==P_F_IMMEDIATE){ struct parameter parameter_0; parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]); w_as_load_float_immediate (*next_instruction->instruction_parameters[0].parameter_data.r,16); w_as_opcode ("fmadd"); w_as_fp_register_comma (next_instruction->instruction_parameters[1].parameter_data.reg.r); w_as_parameter (¶meter_0); w_as_comma(); w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_fp_register (16); w_as_newline(); return next_instruction; } else if ( next_instruction->instruction_parameters[0].parameter_type==P_INDIRECT){ struct parameter parameter_0; parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]); w_as_opcode ("lfd"); w_as_fp_register_comma (16); w_as_indirect (next_instruction->instruction_parameters[0].parameter_offset,next_instruction->instruction_parameters[0].parameter_data.reg.r); w_as_newline(); w_as_opcode ("fmadd"); w_as_fp_register_comma (next_instruction->instruction_parameters[1].parameter_data.reg.r); w_as_parameter (¶meter_0); w_as_comma(); w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_fp_register (16); w_as_newline(); return next_instruction; } } } else if (next_instruction->instruction_icode==IFSUB){ if (next_instruction->instruction_parameters[0].parameter_type==P_F_REGISTER && next_instruction->instruction_parameters[0].parameter_data.reg.r!=next_instruction->instruction_parameters[1].parameter_data.reg.r) { if (next_instruction->instruction_parameters[0].parameter_flags & FP_REG_LAST_USE && next_instruction->instruction_parameters[0].parameter_data.reg.r==instruction->instruction_parameters[1].parameter_data.reg.r) { struct parameter parameter_0; parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]); if (next_instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS) w_as_opcode ("fmsub"); else w_as_opcode ("fnmsub"); w_as_parameter (&next_instruction->instruction_parameters[1]); w_as_comma(); w_as_parameter (¶meter_0); w_as_comma(); w_as_parameter (&instruction->instruction_parameters[1]); w_as_comma(); w_as_parameter (&next_instruction->instruction_parameters[1]); w_as_newline(); return next_instruction; } else if (next_instruction->instruction_parameters[1].parameter_data.reg.r==instruction->instruction_parameters[1].parameter_data.reg.r){ struct parameter parameter_0; parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]); if (next_instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS) w_as_opcode ("fnmsub"); else w_as_opcode ("fmsub"); w_as_parameter (&next_instruction->instruction_parameters[1]); w_as_comma(); w_as_parameter (¶meter_0); w_as_comma(); w_as_parameter (&instruction->instruction_parameters[1]); w_as_comma(); w_as_parameter (&next_instruction->instruction_parameters[0]); w_as_newline(); return next_instruction; } } else if (next_instruction->instruction_parameters[1].parameter_data.reg.r==instruction->instruction_parameters[1].parameter_data.reg.r){ if (next_instruction->instruction_parameters[0].parameter_type==P_F_IMMEDIATE){ struct parameter parameter_0; parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]); w_as_load_float_immediate (*next_instruction->instruction_parameters[0].parameter_data.r,16); if (next_instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS) w_as_opcode ("fnmsub"); else w_as_opcode ("fmsub"); w_as_fp_register_comma (next_instruction->instruction_parameters[1].parameter_data.reg.r); w_as_parameter (¶meter_0); w_as_comma(); w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_fp_register (16); w_as_newline(); return next_instruction; } else if (next_instruction->instruction_parameters[0].parameter_type==P_INDIRECT){ struct parameter parameter_0; parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]); w_as_opcode ("lfd"); w_as_fp_register_comma (16); w_as_indirect (next_instruction->instruction_parameters[0].parameter_offset,next_instruction->instruction_parameters[0].parameter_data.reg.r); w_as_newline(); if (next_instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS) w_as_opcode ("fnmsub"); else w_as_opcode ("fmsub"); w_as_fp_register_comma (next_instruction->instruction_parameters[1].parameter_data.reg.r); w_as_parameter (¶meter_0); w_as_comma(); w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_fp_register (16); w_as_newline(); return next_instruction; } } } w_as_tryadic_float_instruction (instruction,"fmul"); return instruction; } #endif static void w_as_tryadic_reversed_float_instruction (struct instruction *instruction,char *opcode) { struct parameter parameter_0; parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]); w_as_opcode (opcode); w_as_parameter (&instruction->instruction_parameters[1]); w_as_comma(); w_as_parameter (¶meter_0); w_as_comma(); w_as_parameter (&instruction->instruction_parameters[1]); w_as_newline(); } static struct instruction *w_as_fmove_instruction (struct instruction *instruction) { switch (instruction->instruction_parameters[1].parameter_type){ case P_F_REGISTER: switch (instruction->instruction_parameters[0].parameter_type){ case P_F_REGISTER: { struct instruction *next_instruction; int reg0,reg1; reg0=instruction->instruction_parameters[0].parameter_data.reg.r; reg1=instruction->instruction_parameters[1].parameter_data.reg.r; next_instruction=instruction->instruction_next; if (next_instruction) switch (next_instruction->instruction_icode){ case IFADD: case IFSUB: case IFMUL: case IFDIV: case IFREM: if (next_instruction->instruction_parameters[1].parameter_data.reg.r==reg1) { struct parameter parameter_0; int reg_s; parameter_0=w_as_float_parameter (next_instruction->instruction_parameters[0]); reg_s=parameter_0.parameter_data.reg.r; if (reg_s==reg1) reg_s=reg0; switch (next_instruction->instruction_icode){ case IFADD: w_as_opcode ("fadd"); break; case IFSUB: if (instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS){ int reg0_copy; reg0_copy=reg0; reg0=reg_s; reg_s=reg0_copy; } w_as_opcode ("fsub"); break; case IFMUL: #ifdef FMADD { struct instruction *next_of_next_instruction; next_of_next_instruction=next_instruction->instruction_next; if (fmadd_flag && next_of_next_instruction!=NULL){ if (next_of_next_instruction->instruction_icode==IFADD){ if (next_of_next_instruction->instruction_parameters[0].parameter_type==P_F_REGISTER && next_of_next_instruction->instruction_parameters[0].parameter_data.reg.r==reg1 && next_of_next_instruction->instruction_parameters[0].parameter_flags & FP_REG_LAST_USE && next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r!=reg1) { w_as_opcode ("fmadd"); w_as_parameter (&next_of_next_instruction->instruction_parameters[1]); w_as_comma(); w_as_fp_register_comma (reg0); w_as_fp_register_comma (reg_s); w_as_parameter (&next_of_next_instruction->instruction_parameters[1]); w_as_newline(); return next_of_next_instruction; } else if (next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r==reg1){ if (next_of_next_instruction->instruction_parameters[0].parameter_type==P_F_IMMEDIATE){ w_as_load_float_immediate (*next_of_next_instruction->instruction_parameters[0].parameter_data.r,16); w_as_opcode ("fmadd"); w_as_fp_register_comma (reg1); w_as_fp_register_comma (reg0); w_as_fp_register_comma (reg_s); w_as_fp_register (16); w_as_newline(); return next_of_next_instruction; } else if ( next_of_next_instruction->instruction_parameters[0].parameter_type==P_INDIRECT){ w_as_opcode ("lfd"); w_as_fp_register_comma (16); w_as_indirect (next_of_next_instruction->instruction_parameters[0].parameter_offset,next_of_next_instruction->instruction_parameters[0].parameter_data.reg.r); w_as_newline(); w_as_opcode ("fmadd"); w_as_fp_register_comma (reg1); w_as_fp_register_comma (reg0); w_as_fp_register_comma (reg_s); w_as_fp_register (16); w_as_newline(); return next_of_next_instruction; } } } else if (next_of_next_instruction->instruction_icode==IFSUB && next_of_next_instruction->instruction_parameters[0].parameter_type==P_F_REGISTER && next_of_next_instruction->instruction_parameters[0].parameter_data.reg.r!=next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r) { if (next_of_next_instruction->instruction_parameters[0].parameter_flags & FP_REG_LAST_USE && next_of_next_instruction->instruction_parameters[0].parameter_data.reg.r==reg1) { if (next_of_next_instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS) w_as_opcode ("fmsub"); else w_as_opcode ("fnmsub"); w_as_parameter (&next_of_next_instruction->instruction_parameters[1]); w_as_comma(); w_as_fp_register_comma (reg0); w_as_fp_register_comma (reg_s); w_as_parameter (&next_of_next_instruction->instruction_parameters[1]); w_as_newline(); return next_of_next_instruction; } else if (next_of_next_instruction->instruction_parameters[1].parameter_data.reg.r==reg1){ if (next_of_next_instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS) w_as_opcode ("fnmsub"); else w_as_opcode ("fmsub"); w_as_parameter (&next_of_next_instruction->instruction_parameters[1]); w_as_comma(); w_as_fp_register_comma (reg0); w_as_fp_register_comma (reg_s); w_as_parameter (&next_of_next_instruction->instruction_parameters[0]); w_as_newline(); return next_of_next_instruction; } } } } #endif w_as_opcode ("fmul"); break; case IFDIV: if (instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS){ int reg0_copy; reg0_copy=reg0; reg0=reg_s; reg_s=reg0_copy; } w_as_opcode ("fdiv"); break; case IFREM: w_as_opcode ("frem"); } w_as_fp_register_comma (reg1); w_as_fp_register_comma (reg0); w_as_fp_register (reg_s); w_as_newline(); return next_instruction; } } w_as_opcode ("fmr"); w_as_fp_register_comma (reg1); w_as_fp_register (reg0); w_as_newline(); return instruction; } case P_INDIRECT: w_as_opcode ("lfd"); w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_indirect (instruction->instruction_parameters[0].parameter_offset, instruction->instruction_parameters[0].parameter_data.reg.r); w_as_newline(); return instruction; case P_F_IMMEDIATE: w_as_load_float_immediate (*instruction->instruction_parameters[0].parameter_data.r,instruction->instruction_parameters[1].parameter_data.reg.r); return instruction; case P_INDEXED: w_as_opcode ("lfdx"); w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_indexed (instruction->instruction_parameters[0].parameter_offset, instruction->instruction_parameters[0].parameter_data.ir); w_as_newline(); return instruction; } break; case P_INDIRECT: if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){ w_as_opcode ("stfd"); w_as_fp_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r); w_as_indirect (instruction->instruction_parameters[1].parameter_offset, instruction->instruction_parameters[1].parameter_data.reg.r); w_as_newline(); return instruction; } break; case P_INDEXED: if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){ w_as_opcode ("stfdx"); w_as_fp_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r); w_as_indexed (instruction->instruction_parameters[1].parameter_offset, instruction->instruction_parameters[1].parameter_data.ir); w_as_newline(); return instruction; } break; } internal_error_in_function ("w_as_fmove_instruction"); return instruction; } extern LABEL *r_to_i_buffer_label; static void w_as_fmovel_instruction (struct instruction *instruction) { if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){ if (instruction->instruction_parameters[1].parameter_type!=P_REGISTER) internal_error_in_function ("w_as_fmovel_instruction"); w_as_opcode ("fctiw"); w_as_fp_register_comma (17); w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r); w_as_newline(); w_as_load_label (r_to_i_buffer_label,REGISTER_O0); w_as_opcode ("stfd"); w_as_fp_register_comma (17); w_as_indirect (0,REGISTER_O0); w_as_newline(); w_as_opcode ("lwz"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_indirect (4,REGISTER_O0); w_as_newline(); } else { int reg; int label_number,t_label_number; struct label *new_label; switch (instruction->instruction_parameters[0].parameter_type){ case P_REGISTER: reg=instruction->instruction_parameters[0].parameter_data.reg.r; break; case P_INDIRECT: w_as_opcode ("lwz"); w_as_register_comma (REGISTER_O0); w_as_indirect ( instruction->instruction_parameters[0].parameter_offset, instruction->instruction_parameters[0].parameter_data.reg.r); w_as_newline(); reg=REGISTER_O0; break; case P_IMMEDIATE: w_as_opcode ("li"); w_as_register_comma (REGISTER_O0); w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); w_as_newline(); reg=REGISTER_O0; break; default: internal_error_in_function ("w_as_fmovel_instruction"); } label_number=next_label_id++; new_label=(struct label*)allocate_memory_from_heap (sizeof (struct label)); new_label->label_flags=0; new_label->label_number=label_number; w_as_to_data_section(); #ifdef GNU_SYNTAX fprintf (assembly_file,"\t.align\t8" NEWLINE_STRING); #else fprintf (assembly_file,"\talign\t3" NEWLINE_STRING); #endif /* w_as_define_internal_label (label_number); */ w_as_define_local_label (label_number); fprintf (assembly_file, "\t" DC_L "\t0x43300000" NEWLINE_STRING "\t" DC_L "\t0x00000000" NEWLINE_STRING "\t" DC_L "\t0x43300000" NEWLINE_STRING "\t" DC_L "\t0x80000000" NEWLINE_STRING ); /* w_as_instruction_without_parameters ("toc"); w_as_opcode ("tc"); fprintf (assembly_file,"t_%d{TC}",t_label_number); w_as_comma(); w_as_internal_label (label_number); w_as_newline(); */ #ifndef GNU_SYNTAX t_label_number=make_toc_label (new_label,0); #endif w_as_to_code_section(); /* lwz o1,t_n{TC}(RTOC) xoris o0,reg,0x8000 lfd fp31,8(o1) stw o0,4(o1) lfd freg,0(o1) fsub freg,freg,fp31 */ #ifdef GNU_SYNTAX load_label (new_label,0,REGISTER_O1); #else w_as_opcode ("lwz"); w_as_register_comma (REGISTER_O1); fprintf (assembly_file,"t_%d{TC}(RTOC)" NEWLINE_STRING,t_label_number); #endif w_as_opcode ("xoris"); w_as_register_comma (REGISTER_O0); w_as_register_comma (reg); w_as_immediate (0x8000); w_as_newline(); w_as_opcode ("lfd"); w_as_fp_register_comma (17); w_as_indirect (8,REGISTER_O1); w_as_newline(); w_as_opcode ("stw"); w_as_register_comma (REGISTER_O0); w_as_indirect (4,REGISTER_O1); w_as_newline(); w_as_opcode ("lfd"); w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_indirect (0,REGISTER_O1); w_as_newline(); w_as_opcode ("fsub"); w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_fp_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_fp_register (17); w_as_newline(); /* ++t_label_number; */ } } static void w_as_instructions (register struct instruction *instruction) { while (instruction!=NULL){ switch (instruction->instruction_icode){ case IMOVE: w_as_move_instruction (instruction,SIZE_LONG); break; case ILEA: w_as_lea_instruction (instruction); break; case IADD: w_as_add_instruction (instruction); break; case IADDI: w_as_i_instruction (instruction,"addi"); break; case ISUB: w_as_sub_instruction (instruction); break; case ICMP: w_as_cmp_instruction (instruction); break; case IJMP: w_as_jmp_instruction (instruction); break; case IJSR: w_as_jsr_instruction (instruction); break; case IRTS: w_as_rts_instruction (instruction); break; case IBEQ: w_as_branch_instruction (instruction,"beq"); break; case IBGE: w_as_branch_instruction (instruction,"bge"); break; case IBGT: w_as_branch_instruction (instruction,"bgt"); break; case IBLE: w_as_branch_instruction (instruction,"ble"); break; case IBLT: w_as_branch_instruction (instruction,"blt"); break; case IBNE: w_as_branch_instruction (instruction,"bne"); break; case IBNEP: w_as_branch_instruction (instruction,"bne+"); break; case IBHS: w_as_index_error_branch_instruction (instruction); break; case IBNO: w_as_branchno_instruction (instruction); break; case IBO: w_as_brancho_instruction (instruction); break; case ICMPLW: w_as_cmplw_instruction (instruction); break; case ILSLI: w_as_i_instruction (instruction,"slwi"); break; case ILSL: w_as_tryadic_instruction (instruction,"slw"); break; case ILSR: w_as_tryadic_instruction (instruction,"srw"); break; case IASR: w_as_tryadic_instruction (instruction,"sraw"); break; case IMUL: w_as_mul_instruction (instruction); break; case IDIV: w_as_div_instruction (instruction); break; case IDIVU: w_as_divu_instruction (instruction); break; case IREM: w_as_rem_instruction (instruction); break; case IAND: w_as_and_instruction (instruction); break; case IOR: w_as_or_or_eor_instruction (instruction,"or"); break; case IEOR: w_as_or_or_eor_instruction (instruction,"xor"); break; case ISEQ: w_as_set_condition_instruction (instruction,"bne"); break; case ISGE: w_as_set_condition_instruction (instruction,"blt"); break; case ISGT: w_as_set_condition_instruction (instruction,"ble"); break; case ISLE: w_as_set_condition_instruction (instruction,"bgt"); break; case ISLT: w_as_set_condition_instruction (instruction,"bge"); break; case ISNE: w_as_set_condition_instruction (instruction,"beq"); break; case ISNO: w_as_setno_condition_instruction (instruction); break; case ISO: w_as_seto_condition_instruction (instruction); break; #if 0 case ICMPW: w_as_cmpw_instruction (instruction); break; #endif case ITST: w_as_tst_instruction (instruction); break; case IBTST: w_as_btst_instruction (instruction); break; case IMOVEDB: w_as_move_instruction (instruction,SIZE_WORD); break; case IMOVEB: w_as_move_instruction (instruction,SIZE_BYTE); break; case IEXTB: w_as_extb_instruction (instruction); break; case INEG: w_as_neg_instruction (instruction); break; case INOT: w_as_not_instruction (instruction); break; case IFMOVE: instruction=w_as_fmove_instruction (instruction); break; case IFABS: w_as_dyadic_float_instruction (instruction,"fabs"); break; case IFADD: w_as_tryadic_float_instruction (instruction,"fadd"); break; case IFCMP: w_as_compare_float_instruction (instruction); break; case IFDIV: if (instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS) w_as_tryadic_reversed_float_instruction (instruction,"fdiv"); else w_as_tryadic_float_instruction (instruction,"fdiv"); break; case IFMUL: #ifdef FMADD instruction=w_as_fmul_instruction (instruction); #else w_as_tryadic_float_instruction (instruction,"fmul"); #endif break; case IFNEG: w_as_dyadic_float_instruction (instruction,"fneg"); break; case IFREM: w_as_tryadic_float_instruction (instruction,"frem"); break; case IFSUB: if (instruction->instruction_parameters[1].parameter_flags & FP_REVERSE_SUB_DIV_OPERANDS) w_as_tryadic_reversed_float_instruction (instruction,"fsub"); else w_as_tryadic_float_instruction (instruction,"fsub"); break; case IFBEQ: w_as_branch_instruction (instruction,"beq"); break; case IFBGE: w_as_branch_instruction (instruction,"bge"); break; case IFBGT: w_as_branch_instruction (instruction,"bgt"); break; case IFBLE: w_as_branch_instruction (instruction,"ble"); break; case IFBLT: w_as_branch_instruction (instruction,"blt"); break; case IFBNE: w_as_branch_instruction (instruction,"bne"); break; case IFMOVEL: w_as_fmovel_instruction (instruction); break; case IFSEQ: w_as_set_condition_instruction (instruction,"bne"); break; case IFSGE: w_as_set_condition_instruction (instruction,"blt"); break; case IFSGT: w_as_set_condition_instruction (instruction,"ble"); break; case IFSLE: w_as_set_condition_instruction (instruction,"bgt"); break; case IFSLT: w_as_set_condition_instruction (instruction,"bge"); break; case IFSNE: w_as_set_condition_instruction (instruction,"beq"); break; case IWORD: w_as_word_instruction (instruction); break; case IMTCTR: w_as_opcode ("mtctr"); w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); w_as_newline(); break; case IJMPP: w_as_jmpp_instruction (instruction); break; case IRTSP: w_as_rtsp_instruction (instruction); break; case IADDO: w_as_addo_instruction (instruction); break; case ISUBO: w_as_subo_instruction (instruction); break; case IMULO: w_as_mulo_instruction (instruction); break; case IUMULH: w_as_umulh_instruction (instruction); break; case IFTST: default: internal_error_in_function ("w_as_instructions"); } instruction=instruction->instruction_next; } } static void w_as_number_of_arguments (int n_node_arguments) { w_as_opcode (DC_L); fprintf (assembly_file,"%d",n_node_arguments); w_as_newline(); } static void w_as_garbage_collect_test (register struct basic_block *block) { LONG n_cells; struct call_and_jump *new_call_and_jump; n_cells= -block->block_n_new_heap_cells; if (n_cells!=(WORD) n_cells){ w_as_opcode ("addis"); w_as_register_comma (REGISTER_D7); w_as_register_comma (REGISTER_D7); w_as_immediate ((n_cells-(WORD)n_cells)>>16); w_as_newline(); n_cells=(WORD)n_cells; } w_as_opcode ("addic."); w_as_register_comma (REGISTER_D7); w_as_register_comma (REGISTER_D7); w_as_immediate (n_cells); w_as_newline(); new_call_and_jump=allocate_new_call_and_jump(); if (block->block_gc_kind!=0){ int label_id_1; label_id_1=next_label_id++; new_call_and_jump->cj_label_id=label_id_1; new_call_and_jump->cj_jump_id=-1; switch (block->block_n_begin_a_parameter_registers){ case 0: new_call_and_jump->cj_call_label_name="collect_00"; break; case 1: new_call_and_jump->cj_call_label_name="collect_01"; break; case 2: new_call_and_jump->cj_call_label_name="collect_02"; break; case 3: new_call_and_jump->cj_call_label_name="collect_03"; break; default: internal_error_in_function ("w_as_garbage_collect_test"); } if (block->block_gc_kind==2){ w_as_opcode ("mflr"); w_as_register (REGISTER_R0); w_as_newline(); } w_as_opcode ("bltl-"); w_as_internal_label (label_id_1); w_as_newline(); if (block->block_gc_kind==1){ w_as_opcode ("mtlr"); w_as_register (REGISTER_R0); w_as_newline(); } } else { int label_id_1,label_id_2; label_id_1=next_label_id++; label_id_2=next_label_id++; new_call_and_jump->cj_label_id=label_id_1; new_call_and_jump->cj_jump_id=label_id_2; switch (block->block_n_begin_a_parameter_registers){ case 0: new_call_and_jump->cj_call_label_name="collect_0"; break; case 1: new_call_and_jump->cj_call_label_name="collect_1"; break; case 2: new_call_and_jump->cj_call_label_name="collect_2"; break; case 3: new_call_and_jump->cj_call_label_name="collect_3"; break; default: internal_error_in_function ("w_as_garbage_collect_test"); } w_as_opcode ("blt"); w_as_internal_label (label_id_1); w_as_newline (); w_as_define_internal_label (label_id_2); } } static void w_as_check_stack (struct basic_block *block) { #ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS if (block->block_a_stack_check_size>0){ w_as_load_label (end_a_stack_label,REGISTER_O0); w_as_opcode ("addi"); w_as_register_comma (REGISTER_O1); w_as_register_comma (A_STACK_POINTER); w_as_immediate (block->block_a_stack_check_size); w_as_newline(); w_as_opcode ("lwz"); w_as_register_comma (REGISTER_O0); w_as_indirect (0,REGISTER_O0); w_as_newline(); w_as_opcode ("cmpw"); w_as_immediate (0); w_as_comma(); w_as_register_comma (REGISTER_O1); w_as_register (REGISTER_O0); w_as_newline(); w_as_opcode ("ble+"); fprintf (assembly_file,".+8"); w_as_newline(); w_as_opcode ("b"); w_as_label (stack_overflow_label->label_name); w_as_newline(); } if (block->block_b_stack_check_size>0){ w_as_load_label (end_b_stack_label,REGISTER_O0); w_as_opcode ("addi"); w_as_register_comma (REGISTER_O1); w_as_register_comma (B_STACK_POINTER); w_as_immediate (block->block_b_stack_check_size); w_as_newline(); w_as_opcode ("lwz"); w_as_register_comma (REGISTER_O0); w_as_indirect (0,REGISTER_O0); w_as_newline(); w_as_opcode ("cmpw"); w_as_immediate (0); w_as_comma(); w_as_register_comma (REGISTER_O1); w_as_register (REGISTER_O0); w_as_newline(); w_as_opcode ("bgt+"); fprintf (assembly_file,".+8"); w_as_newline(); w_as_opcode ("b"); w_as_label (stack_overflow_label->label_name); w_as_newline(); } #else int size; size=block->block_stack_check_size+1024; w_as_opcode ("sub"); w_as_register_comma (REGISTER_O0); w_as_register_comma (B_STACK_POINTER); w_as_register (A_STACK_POINTER); w_as_newline(); w_as_opcode ("cmpwi"); w_as_register_comma (REGISTER_O0); w_as_immediate (size); w_as_newline(); w_as_opcode ("ble"); w_as_label (stack_overflow_label->label_name); w_as_newline(); #endif } static void w_as_labels (register struct block_label *labels) { for (; labels!=NULL; labels=labels->block_label_next) if (labels->block_label_label->label_number==0){ LABEL *label; label=labels->block_label_label; w_as_define_label (label); } else w_as_define_local_label (labels->block_label_label->label_number); } void initialize_write_assembly (FILE *ass_file) { assembly_file=ass_file; next_bmove_label=0; in_data_section=0; first_call_and_jump=NULL; #ifndef GNU_SYNTAX fprintf (assembly_file,"\tstring\tasis" NEWLINE_STRING); #endif data_module_number=0; code_module_number=0; } static void w_as_import_labels (register struct label_node *label_node) { LABEL *label; if (label_node==NULL) return; label=&label_node->label_node_label; if (!(label->label_flags & LOCAL_LABEL) && label->label_number==0){ w_as_opcode (IF_GNU (IF_MACH_O (".globl",".global"),"import")); #ifdef MACH_O if (label->label_name[0]=='_'){ char *label_name; int c; label_name=label->label_name; putc ('_',assembly_file); ++label_name; while (c=*label_name++,c!=0) putc (c,assembly_file); } else w_as_label (label->label_name); #else w_as_label (label->label_name); #endif w_as_newline(); } w_as_import_labels (label_node->label_node_left); 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; extern LABEL *eval_fill_label,*eval_upd_labels[]; 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){ w_as_load_label (block->block_ea_label,REGISTER_A2); if (!block->block_profile){ w_as_opcode ("b"); w_as_label (eval_upd_labels[n_node_arguments]->label_name); w_as_newline(); w_as_instruction_without_parameters ("nop"); #ifdef GNU_SYNTAX w_as_instruction_without_parameters ("nop"); #endif } else { if (profile_table_flag){ w_as_opcode ("b"); w_as_label (eval_upd_labels[n_node_arguments]->label_name); fprintf (assembly_file,"-8"); w_as_newline(); w_as_load_label_with_offset (profile_table_label,32764,REGISTER_R3); w_as_opcode ("addi"); w_as_register_comma (REGISTER_R3); w_as_register_comma (REGISTER_R3); w_as_immediate (block->block_profile_function_label->label_arity-32764); w_as_newline(); w_as_opcode ("b"); fprintf (assembly_file,IF_GNU ("$-16","*-16")); w_as_newline(); } else { w_as_load_label (block->block_profile_function_label,REGISTER_R3); w_as_opcode ("b"); w_as_label (eval_upd_labels[n_node_arguments]->label_name); fprintf (assembly_file,"-8"); w_as_newline(); } } } else { w_as_opcode ("b"); w_as_label (block->block_ea_label->label_name); w_as_newline(); w_as_instruction_without_parameters ("nop"); w_as_instruction_without_parameters ("nop"); #ifdef GNU_SYNTAX w_as_instruction_without_parameters ("nop"); w_as_instruction_without_parameters ("nop"); #endif } if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)) #ifdef GNU_SYNTAX w_as_label_in_code_section (block->block_descriptor->label_name); #else w_as_load_label (block->block_descriptor,REGISTER_R0); #endif else w_as_number_of_arguments (0); } else { if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)) #ifdef GNU_SYNTAX w_as_label_in_code_section (block->block_descriptor->label_name); #else w_as_load_label (block->block_descriptor,REGISTER_R0); #endif /* else w_as_number_of_arguments (0); */ } w_as_number_of_arguments (block->block_n_node_arguments); } static void w_as_profile_call (struct basic_block *block) { if (profile_table_flag){ w_as_load_label_with_offset (profile_table_label,32764,REGISTER_R3); w_as_opcode ("mflr"); w_as_register (REGISTER_R0); w_as_newline(); w_as_opcode ("addi"); w_as_register_comma (REGISTER_R3); w_as_register_comma (REGISTER_R3); w_as_immediate (block->block_profile_function_label->label_arity-32764); w_as_newline(); } else { w_as_load_label (block->block_profile_function_label,REGISTER_R3); w_as_opcode ("mflr"); w_as_register (REGISTER_R0); w_as_newline(); } w_as_opcode ("bl"); 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 ("b"); 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"); } else { w_as_opcode ("mflr"); w_as_register (REGISTER_R0); w_as_newline(); w_as_opcode ("bl"); w_as_label (add_empty_node_labels[block->block_n_node_arguments+200]->label_name); w_as_newline(); w_as_opcode ("mtlr"); w_as_register (REGISTER_R0); w_as_newline(); w_as_opcode ("b"); w_as_label (block->block_ea_label->label_name); w_as_newline(); } } #endif void write_assembly (VOID) { struct basic_block *block; struct call_and_jump *call_and_jump; struct toc_label *toc_label; #ifdef MACH_O first_stub=NULL; next_stub_l=&first_stub; #endif w_as_to_code_section(); w_as_import_labels (labels); for_l (block,first_block,block_next){ if (block->block_begin_module && !block->block_link_module){ if (first_call_and_jump!=NULL){ struct call_and_jump *call_and_jump; for_l (call_and_jump,first_call_and_jump,cj_next) w_as_call_and_jump (call_and_jump); first_call_and_jump=NULL; } w_as_new_code_module(); } if (block->block_n_node_arguments>-100){ 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_profile_call (block); if (block->block_n_new_heap_cells!=0) w_as_garbage_collect_test (block); if (check_stack #ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS && (block->block_a_stack_check_size>0 || block->block_b_stack_check_size>0) #else && block->block_stack_check_size>0 #endif ) w_as_check_stack (block); w_as_instructions (block->block_instructions); } for_l (call_and_jump,first_call_and_jump,cj_next) w_as_call_and_jump (call_and_jump); *last_toc_next_p=NULL; #ifndef GNU_SYNTAX w_as_instruction_without_parameters ("toc"); for_l (toc_label,toc_labels,toc_next) w_as_toc_label (toc_label); #endif #ifdef MACH_O write_stubs(); #endif } #endif