diff options
author | John van Groningen | 2003-05-13 13:30:16 +0000 |
---|---|---|
committer | John van Groningen | 2003-05-13 13:30:16 +0000 |
commit | ba0529e7606b690d858e70bbd6a2edc6cd4cf758 (patch) | |
tree | 051c8fdf2df7e9239a6a3d6b2372cd7be044a4fe /cgpwas.c | |
parent | cgcodep.h (diff) |
optimize division and remainder of power of 2
Diffstat (limited to 'cgpwas.c')
-rw-r--r-- | cgpwas.c | 3421 |
1 files changed, 3421 insertions, 0 deletions
diff --git a/cgpwas.c b/cgpwas.c new file mode 100644 index 0000000..23f7add --- /dev/null +++ b/cgpwas.c @@ -0,0 +1,3421 @@ +/* + File: cgpwas.c + Machine: Power Macintosh + Author: John van Groningen + Copyright: University of Nijmegen +*/ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#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" + +#define for_l(v,l,n) for(v=(l);v!=NULL;v=v->n) + +#define FSUB_FDIV_REVERSED + +#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<length; ++i){ + int c; + + if (n>=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<length; ++i){ + if (n>=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 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_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; + + 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 { + 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,int size_flag) +{ + 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 (size_flag==SIZE_LONG ? "lwz" : "lha"); + else + w_as_opcode (size_flag==SIZE_LONG ? "lwzx" : "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: + switch (size_flag){ + case SIZE_WORD: + w_as_opcode ("lha"); + break; + case SIZE_LONG: + w_as_opcode ("lwz"); + break; + default: + internal_error_in_function ("w_as_cmp_instruction"); + } + 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: + switch (size_flag){ + case SIZE_WORD: + w_as_opcode ("lhax"); + break; + case SIZE_LONG: + w_as_opcode ("lwzx"); + break; + default: + internal_error_in_function ("w_as_cmp_instruction"); + } + 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(); +} + +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"); + } +} + +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){ + w_as_opcode ("mtctr"); + w_as_register (parameter0->parameter_data.reg.r); + w_as_newline(); + } + + 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,REGISTER_SP); + w_as_newline(); + + w_as_opcode ("stwu"); + w_as_register_comma (REGISTER_O0); + w_as_indirect (-(frame_size+28),REGISTER_SP); + w_as_newline(); +#else + w_as_opcode ("stw"); + w_as_register_comma (REGISTER_R0); + w_as_indirect (-4,REGISTER_SP); + w_as_newline(); + + w_as_opcode ("stwu"); + w_as_register_comma (REGISTER_SP); + w_as_indirect (-frame_size,REGISTER_SP); + w_as_newline(); +#endif + + if (parameter0->parameter_type==P_REGISTER){ + w_as_instruction_without_parameters ("bctrl"); + } 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,REGISTER_SP); + w_as_newline(); + + w_as_opcode ("lwz"); + w_as_register_comma (REGISTER_SP); + w_as_indirect (0,REGISTER_SP); + w_as_newline(); +#else + w_as_opcode ("lwz"); + w_as_register_comma (REGISTER_R0); + w_as_indirect (frame_size-4,REGISTER_SP); + w_as_newline(); + + w_as_opcode ("addi"); + w_as_register_comma (REGISTER_SP); + w_as_register_comma (REGISTER_SP); + 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_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 & (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; + } + } + + 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; + } + } + + 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_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_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 (fp_reg); + w_as_comma(); +#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 (17); + w_as_comma(); + 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 (17); + w_as_comma(); + 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_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]); + + w_as_opcode ("fmadd"); + + 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_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]); + +# ifdef FSUB_FDIV_REVERSED + if (next_instruction->instruction_parameters[1].parameter_flags) + w_as_opcode ("fmsub"); + else +# endif + 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]); + +# ifdef FSUB_FDIV_REVERSED + if (next_instruction->instruction_parameters[1].parameter_flags) + w_as_opcode ("fnmsub"); + else +# endif + 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; + } + } + } + + w_as_tryadic_float_instruction (instruction,"fmul"); + + return instruction; +} +#endif + +#ifdef FSUB_FDIV_REVERSED +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(); +} +#endif + +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: +#ifdef FSUB_FDIV_REVERSED + if (instruction->instruction_parameters[1].parameter_flags){ + int reg0_copy; + + reg0_copy=reg0; + reg0=reg_s; + reg_s=reg0_copy; + } +#endif + + 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 && + 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 (reg0); + w_as_comma(); + w_as_fp_register (reg_s); + w_as_comma(); + 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_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) + { +# ifdef FSUB_FDIV_REVERSED + if (next_of_next_instruction->instruction_parameters[1].parameter_flags) + w_as_opcode ("fmsub"); + else +# endif + w_as_opcode ("fnmsub"); + + w_as_parameter (&next_of_next_instruction->instruction_parameters[1]); + w_as_comma(); + w_as_fp_register (reg0); + w_as_comma(); + w_as_fp_register (reg_s); + w_as_comma(); + 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){ +# ifdef FSUB_FDIV_REVERSED + if (next_of_next_instruction->instruction_parameters[1].parameter_flags) + w_as_opcode ("fnmsub"); + else +# endif + w_as_opcode ("fmsub"); + + w_as_parameter (&next_of_next_instruction->instruction_parameters[1]); + w_as_comma(); + w_as_fp_register (reg0); + w_as_comma(); + w_as_fp_register (reg_s); + w_as_comma(); + 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: +#ifdef FSUB_FDIV_REVERSED + if (instruction->instruction_parameters[1].parameter_flags){ + int reg0_copy; + + reg0_copy=reg0; + reg0=reg_s; + reg_s=reg0_copy; + } +#endif + w_as_opcode ("fdiv"); + break; + case IFREM: + w_as_opcode ("frem"); + } + w_as_fp_register (reg1); + w_as_comma(); + w_as_fp_register (reg0); + w_as_comma(); + w_as_fp_register (reg_s); + w_as_newline(); + + return next_instruction; + } + } + + w_as_opcode ("fmr"); + w_as_fp_register (reg1); + w_as_comma(); + w_as_fp_register (reg0); + w_as_newline(); + + return instruction; + } + case P_INDIRECT: + w_as_opcode ("lfd"); + w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_comma(); + 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 (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_comma(); + 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 (instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_comma(); + 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 (instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_comma(); + 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 (17); + w_as_comma(); + 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 (17); + w_as_comma(); + 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 (17); + w_as_comma(); + 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 (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_comma(); + w_as_indirect (0,REGISTER_O1); + w_as_newline(); + + w_as_opcode ("fsub"); + w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_comma(); + w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_comma(); + 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,SIZE_LONG); + 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 IMOD: + 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; + case ICMPW: + w_as_cmp_instruction (instruction,SIZE_WORD); + break; + case ITST: + w_as_tst_instruction (instruction); + break; + case IBTST: + w_as_btst_instruction (instruction); + break; + case IMOVEW: + 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 IFMOVE: + instruction=w_as_fmove_instruction (instruction); + break; + case IFADD: + w_as_tryadic_float_instruction (instruction,"fadd"); + break; + case IFCMP: + w_as_compare_float_instruction (instruction); + break; + case IFDIV: +#ifdef FSUB_FDIV_REVERSED + if (instruction->instruction_parameters[1].parameter_flags) + w_as_tryadic_reversed_float_instruction (instruction,"fdiv"); + else +#endif + 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: +#ifdef FSUB_FDIV_REVERSED + if (instruction->instruction_parameters[1].parameter_flags) + w_as_tryadic_reversed_float_instruction (instruction,"fsub"); + else +#endif + 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 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_a_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); +} + +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){ + 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); + } + + w_as_labels (block->block_labels); + + if (block->block_profile){ + 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(); + } + + 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 |