/* File: cgswas.c Author: John van Groningen Machine: Sun 4 At: University of Nijmegen */ #include #include #include "cgport.h" #include "cgrconst.h" #include "cgtypes.h" #include "cg.h" #include "cgiconst.h" #include "cgcode.h" #include "cgswas.h" #define GAS #define IO_BUF_SIZE 8192 #define SP_G5 #undef ALIGN_REAL_ARRAYS #ifdef ALIGN_REAL_ARRAYS # define LOAD_STORE_ALIGNED_REAL 4 #endif static FILE *assembly_file; static void w_as_newline (VOID) { putc ('\n',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\n",opcode); } static void w_as_define_local_label (int label_number) { fprintf (assembly_file,"l_%d:\n",label_number); } static void w_as_define_internal_label (int label_number) { fprintf (assembly_file,"i_%d:\n",label_number); } void w_as_internal_label_value (int label_id) { fprintf (assembly_file,"\t.word\ti_%d\n",label_id); } static int in_data_section; #ifdef FUNCTION_LEVEL_LINKING void w_as_new_data_module (void) { } #endif void w_as_to_data_section (VOID) { if (!in_data_section){ in_data_section=1; w_as_instruction_without_parameters (".data"); } } static void w_as_to_code_section (VOID) { if (in_data_section){ in_data_section=0; w_as_instruction_without_parameters (".text"); } } void w_as_word_in_data_section (int n) { w_as_to_data_section(); w_as_opcode (".half"); 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 (".word"); 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.word\t%s\n",label_name); } static void w_as_label_in_code_section (char *label_name) { w_as_to_code_section (); fprintf (assembly_file,"\t.word\t%s\n",label_name); } void w_as_descriptor_in_data_section (char *label_name) { w_as_to_data_section (); fprintf (assembly_file,"\t.word\t%s+2\n",label_name); } #define MAX_BYTES_PER_LINE 16 static int w_as_data (register int n,register unsigned char *data,register int length) { int i,in_string; in_string=0; for (i=0; i=MAX_BYTES_PER_LINE){ if (in_string){ putc ('\"',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 (".ascii"); putc ('\"',assembly_file); in_string=1; n=0; } putc (c,assembly_file); } else { if (n==0) w_as_opcode (".byte"); else { if (in_string){ putc ('\"',assembly_file); w_as_newline(); w_as_opcode (".byte"); in_string=0; n=0; } else putc (',',assembly_file); } fprintf (assembly_file,"0x%02x",c); } ++n; } if (in_string){ putc ('\"',assembly_file); w_as_newline(); return 0; } else return n; } static int w_as_zeros (register int n,register int length) { register int i; for (i=0; i=MAX_BYTES_PER_LINE){ w_as_newline(); n=0; } if (n==0) w_as_opcode (".byte"); else putc (',',assembly_file); fprintf (assembly_file,"0"); ++n; } return n; } void w_as_c_string_in_data_section (char *string,int length) { register int n; w_as_to_data_section(); n=w_as_data (0,string,length); n=w_as_zeros (n,4-(length & 3)); /* n=w_as_zeros (n,length & 1 ? 1 : 2); */ if (n>0) 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_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_abc_string_in_data_section (char *string,int length) { int n; w_as_to_data_section(); w_as_opcode (".word"); fprintf (assembly_file,"%d\n",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_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 (".word"); fprintf (assembly_file,"%d\n",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 (".global"); 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 (".long"); fprintf (assembly_file,"%d\n",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(); } static char register_type [32]="ggggggiiggiiiiiilllllllloooooooo"; #ifdef SP_G5 static char register_number[32]="01234767565432100123456701234567"; #else static char register_number[32]="01234567765432100123456701234567"; #endif #define REGISTER_G0 (-16) #define REGISTER_G5 (-11) #define REGISTER_I6 (-10) #define REGISTER_O0 8 #define REGISTER_O1 9 #define REGISTER_O7 15 static void w_as_indirect (int i,int reg) { if (i!=0){ if (i>0) fprintf (assembly_file,"[%%%c%c+%d]",register_type[reg+16],register_number[reg+16],i); else fprintf (assembly_file,"[%%%c%c-%d]",register_type[reg+16],register_number[reg+16],-i); } else fprintf (assembly_file,"[%%%c%c]",register_type[reg+16],register_number[reg+16]); } 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; fprintf (assembly_file,"[%%%c%c+%%%c%c]", register_type[reg1+16],register_number[reg1+16], register_type[reg2+16],register_number[reg2+16]); } static void w_as_register (int reg) { putc ('%',assembly_file); putc (register_type[reg+16],assembly_file); putc (register_number[reg+16],assembly_file); } static void w_as_register_comma (int reg) { putc ('%',assembly_file); putc (register_type[reg+16],assembly_file); putc (register_number[reg+16],assembly_file); putc (',',assembly_file); } static void w_as_register_newline (int reg) { putc ('%',assembly_file); putc (register_type[reg+16],assembly_file); putc (register_number[reg+16],assembly_file); putc ('\n',assembly_file); } void w_as_c_string_and_label_in_code_section (char *string,int length,char *label_name) { register 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) { fprintf (assembly_file,"%%f%d",fp_reg); } static void w_as_fp_register_newline (int fp_reg) { fprintf (assembly_file,"%%f%d\n",fp_reg); } static void w_as_opcode_descriptor (char *opcode,char *label_name,int arity) { w_as_opcode (opcode); fprintf (assembly_file,"%s+0x%x",label_name,2/* 0x80000000 */+(arity<<3)); } static void w_as_comma (VOID) { putc (',',assembly_file); } static void w_as_opcode_indirect (char *opcode,int offset,int reg) { if (((offset << (32-13)) >> (32-13))==offset){ w_as_opcode (opcode); w_as_indirect (offset,reg); } else { w_as_opcode ("sethi"); w_as_immediate (offset>>10); w_as_comma(); w_as_register (REGISTER_O1); w_as_newline(); w_as_opcode ("add"); w_as_register (REGISTER_O1); w_as_comma(); w_as_register (reg); w_as_comma(); w_as_register (REGISTER_O1); w_as_newline(); w_as_opcode (opcode); w_as_indirect (offset & 1023,REGISTER_O1); } } static void w_as_parameter (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: fprintf (assembly_file,"%%f%d",parameter->parameter_data.reg.r<<1); break; default: internal_error_in_function ("w_as_parameter"); } } static void w_as_ld_parameter (struct parameter *parameter) { if (parameter->parameter_type!=P_INDIRECT){ w_as_opcode ("ld"); w_as_parameter (parameter); } else w_as_opcode_indirect ("ld",parameter->parameter_offset,parameter->parameter_data.reg.r); } static void w_as_opcode_parameter (char *opcode,struct parameter *parameter) { if (parameter->parameter_type!=P_INDIRECT){ w_as_opcode (opcode); w_as_parameter (parameter); } else w_as_opcode_indirect (opcode,parameter->parameter_offset,parameter->parameter_data.reg.r); } static void w_as_jump_parameter (register struct parameter *parameter) { switch (parameter->parameter_type){ 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: { int offset,reg; offset=parameter->parameter_offset; reg=parameter->parameter_data.reg.r; if (offset!=0) fprintf (assembly_file,"%%%c%c+%d", register_type[reg+16],register_number[reg+16],offset); else fprintf (assembly_file,"%%%c%c", register_type[reg+16],register_number[reg+16]); break; } default: internal_error_in_function ("w_as_jump_parameter"); } } static struct parameter w_as_register_parameter (struct parameter parameter,int size_flag) { switch (parameter.parameter_type){ case P_DESCRIPTOR_NUMBER: w_as_opcode_descriptor ("set", parameter.parameter_data.l->label_name, parameter.parameter_offset ); w_as_comma(); w_as_register (REGISTER_O0); w_as_newline(); parameter.parameter_type=P_REGISTER; parameter.parameter_data.reg.r=REGISTER_O0; break; case P_IMMEDIATE: if (parameter.parameter_data.i==0){ parameter.parameter_type=P_REGISTER; parameter.parameter_data.reg.r=REGISTER_G0; } else { w_as_opcode ("set"); w_as_immediate (parameter.parameter_data.i); w_as_comma(); w_as_register (REGISTER_O0); w_as_newline(); parameter.parameter_type=P_REGISTER; parameter.parameter_data.reg.r=REGISTER_O0; } break; case P_REGISTER: break; case P_INDIRECT: w_as_opcode_indirect ( size_flag==SIZE_LONG ? "ld" : size_flag==SIZE_WORD ? "ldsh" : "ldub", parameter.parameter_offset,parameter.parameter_data.reg.r); w_as_comma(); w_as_register (REGISTER_O0); w_as_newline(); parameter.parameter_type=P_REGISTER; parameter.parameter_data.reg.r=REGISTER_O0; break; case P_INDEXED: w_as_opcode (size_flag==SIZE_LONG ? "ld" : size_flag==SIZE_WORD ? "ldsh" : "ldub"); w_as_indexed (parameter.parameter_offset,parameter.parameter_data.ir); w_as_comma(); w_as_register (REGISTER_O0); w_as_newline(); parameter.parameter_type=P_REGISTER; parameter.parameter_data.reg.r=REGISTER_O0; break; default: internal_error_in_function ("w_as_register_parameter"); } return parameter; } 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_opcode_descriptor ("set", instruction->instruction_parameters[0].parameter_data.l->label_name, instruction->instruction_parameters[0].parameter_offset ); break; case P_IMMEDIATE: w_as_opcode ("set"); w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); break; case P_REGISTER: w_as_opcode ("mov"); w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); break; case P_INDIRECT: w_as_opcode_indirect ( size_flag==SIZE_LONG ? "ld" : size_flag==SIZE_WORD ? "ldsh" : "ldub", instruction->instruction_parameters[0].parameter_offset, instruction->instruction_parameters[0].parameter_data.reg.r); break; case P_INDEXED: w_as_opcode (size_flag==SIZE_LONG ? "ld" : size_flag==SIZE_WORD ? "ldsh" : "ldub"); w_as_indexed (instruction->instruction_parameters[0].parameter_offset, instruction->instruction_parameters[0].parameter_data.ir); break; default: internal_error_in_function ("w_as_move_instruction"); return; } w_as_comma(); w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_newline(); return; case P_INDIRECT: { struct parameter parameter_0; int offset; parameter_0=w_as_register_parameter (instruction->instruction_parameters[0],size_flag); offset=instruction->instruction_parameters[1].parameter_offset; if (((offset << (32-13)) >> (32-13))==offset){ w_as_opcode (size_flag==SIZE_LONG ? "st" : size_flag==SIZE_WORD ? "sth" : "stb"); w_as_register (parameter_0.parameter_data.reg.r); w_as_comma(); w_as_indirect (offset,instruction->instruction_parameters[1].parameter_data.reg.r); w_as_newline(); } else { w_as_opcode ("sethi"); w_as_immediate (offset>>10); w_as_comma(); w_as_register (REGISTER_O1); w_as_newline(); w_as_opcode ("add"); w_as_register (REGISTER_O1); w_as_comma(); w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_comma(); w_as_register (REGISTER_O1); w_as_newline(); w_as_opcode (size_flag==SIZE_LONG ? "st" : size_flag==SIZE_WORD ? "sth" : "stb"); w_as_register (parameter_0.parameter_data.reg.r); w_as_comma(); w_as_indirect (offset & 1023,REGISTER_O1); w_as_newline(); } return; } case P_INDEXED: { struct parameter parameter_0; parameter_0=w_as_register_parameter (instruction->instruction_parameters[0],size_flag); w_as_opcode (size_flag==SIZE_LONG ? "st" : size_flag==SIZE_WORD ? "sth" : "stb"); w_as_register (parameter_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; } 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_opcode ("set"); w_as_parameter (&instruction->instruction_parameters[0]); if (instruction->instruction_parameters[0].parameter_offset!=0){ int offset; offset=instruction->instruction_parameters[0].parameter_offset; fprintf (assembly_file,offset>=0 ? "+%d" : "%d",offset); } w_as_comma(); w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_newline(); return; case P_INDIRECT: w_as_opcode ("add"); w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); w_as_comma(); w_as_immediate (instruction->instruction_parameters[0].parameter_offset); w_as_comma(); w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_newline(); return; case P_INDEXED: w_as_opcode ("add"); w_as_register (instruction->instruction_parameters[0].parameter_data.ir->a_reg.r); w_as_comma(); w_as_register (instruction->instruction_parameters[0].parameter_data.ir->d_reg.r); w_as_comma(); w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_newline(); return; } internal_error_in_function ("w_as_lea_instruction"); } static void w_as_i_instruction (struct instruction *instruction,char *opcode) { w_as_opcode (opcode); w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); w_as_comma(); w_as_immediate (instruction->instruction_parameters[2].parameter_data.i); w_as_comma(); w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_newline(); } static void w_as_tryadic_instruction (struct instruction *instruction,char *opcode) { struct parameter parameter; parameter=instruction->instruction_parameters[0]; switch (parameter.parameter_type){ case P_IMMEDIATE: if ((unsigned)(parameter.parameter_data.i+4096)>=(unsigned)8192){ w_as_opcode ("set"); w_as_immediate (parameter.parameter_data.i); w_as_comma(); w_as_register (REGISTER_O0); w_as_newline(); parameter.parameter_type=P_REGISTER; parameter.parameter_data.reg.r=REGISTER_O0; } break; case P_INDIRECT: w_as_opcode_indirect ("ld",parameter.parameter_offset,parameter.parameter_data.reg.r); w_as_comma(); w_as_register (REGISTER_O0); w_as_newline(); parameter.parameter_type=P_REGISTER; parameter.parameter_data.reg.r=REGISTER_O0; break; case P_INDEXED: w_as_opcode ("ld"); w_as_indexed (parameter.parameter_offset,parameter.parameter_data.ir); w_as_comma(); w_as_register (REGISTER_O0); w_as_newline(); parameter.parameter_type=P_REGISTER; parameter.parameter_data.reg.r=REGISTER_O0; } w_as_opcode (opcode); w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_comma(); w_as_parameter (¶meter); w_as_comma(); w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); 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[0].parameter_data.reg.r); w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); return; case P_IMMEDIATE: if ((unsigned)(instruction->instruction_parameters[0].parameter_data.i+4096)<(unsigned)8192){ w_as_opcode ("inc"); w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); w_as_comma(); w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); return; } else { w_as_opcode ("set"); w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); w_as_comma(); w_as_scratch_register(); w_as_newline(); w_as_opcode ("add"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_scratch_register(); w_as_comma(); w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); return; } default: w_as_ld_parameter (&instruction->instruction_parameters[0]); w_as_comma(); w_as_scratch_register(); w_as_newline(); w_as_opcode ("add"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_scratch_register(); w_as_comma(); w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); } } static void w_as_add_o_instruction (struct instruction *instruction) { switch (instruction->instruction_parameters[0].parameter_type){ case P_REGISTER: w_as_opcode ("addcc"); 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_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); return; case P_IMMEDIATE: if ((unsigned)(instruction->instruction_parameters[0].parameter_data.i+4096)<(unsigned)8192){ w_as_opcode ("inccc"); w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); w_as_comma(); w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); return; } else { w_as_opcode ("set"); w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); w_as_comma(); w_as_scratch_register(); w_as_newline(); w_as_opcode ("addcc"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_scratch_register(); w_as_comma(); w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); return; } default: w_as_ld_parameter (&instruction->instruction_parameters[0]); w_as_comma(); w_as_scratch_register(); w_as_newline(); w_as_opcode ("addcc"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_scratch_register(); w_as_comma(); w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); } } 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[0].parameter_data.reg.r); w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); return; case P_IMMEDIATE: if ((unsigned)(instruction->instruction_parameters[0].parameter_data.i+4096)<(unsigned)8192){ w_as_opcode ("dec"); w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); w_as_comma(); w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); return; } else { w_as_opcode ("set"); w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); w_as_comma(); w_as_scratch_register(); w_as_newline(); w_as_opcode ("sub"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_scratch_register(); w_as_comma(); w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); return; } default: w_as_ld_parameter (&instruction->instruction_parameters[0]); w_as_comma(); w_as_scratch_register(); w_as_newline(); w_as_opcode ("sub"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_scratch_register(); w_as_comma(); w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); } } static void w_as_sub_o_instruction (struct instruction *instruction) { switch (instruction->instruction_parameters[0].parameter_type){ case P_REGISTER: w_as_opcode ("subcc"); 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_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); return; case P_IMMEDIATE: if ((unsigned)(instruction->instruction_parameters[0].parameter_data.i+4096)<(unsigned)8192){ w_as_opcode ("deccc"); w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); w_as_comma(); w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); return; } else { w_as_opcode ("set"); w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); w_as_comma(); w_as_scratch_register(); w_as_newline(); w_as_opcode ("subcc"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_scratch_register(); w_as_comma(); w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); return; } default: w_as_ld_parameter (&instruction->instruction_parameters[0]); w_as_comma(); w_as_scratch_register(); w_as_newline(); w_as_opcode ("subcc"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_scratch_register(); w_as_comma(); w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); } } 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){ w_as_opcode_parameter ("ld",¶meter_1); w_as_comma(); w_as_register (REGISTER_O1); w_as_newline(); parameter_1.parameter_type=P_REGISTER; parameter_1.parameter_data.reg.r=REGISTER_O1; } else if (parameter_1.parameter_type==P_INDEXED){ w_as_opcode ("ld"); w_as_parameter (¶meter_1); w_as_comma(); w_as_register (REGISTER_O1); 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_opcode_descriptor ("set", parameter_0.parameter_data.l->label_name, parameter_0.parameter_offset ); w_as_comma(); w_as_register (REGISTER_O0); w_as_newline(); parameter_0.parameter_type=P_REGISTER; parameter_0.parameter_data.reg.r=REGISTER_O0; break; case P_IMMEDIATE: if ((unsigned)(parameter_0.parameter_data.i+4096)>=(unsigned)8192){ w_as_opcode ("set"); w_as_parameter (¶meter_0); w_as_comma(); w_as_register (REGISTER_O0); w_as_newline(); parameter_0.parameter_type=P_REGISTER; parameter_0.parameter_data.reg.r=REGISTER_O0; } break; case P_REGISTER: break; default: w_as_opcode_parameter ("ld",¶meter_0); w_as_comma(); w_as_register (REGISTER_O0); w_as_newline(); parameter_0.parameter_type=P_REGISTER; parameter_0.parameter_data.reg.r=REGISTER_O0; } w_as_opcode ("cmp"); 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){ w_as_opcode_parameter ("ldsh",¶meter_1); w_as_comma(); w_as_register (REGISTER_O1); w_as_newline(); parameter_1.parameter_type=P_REGISTER; parameter_1.parameter_data.reg.r=REGISTER_O1; } else if (parameter_1.parameter_type==P_INDEXED){ w_as_opcode ("ldsh"); w_as_parameter (¶meter_1); w_as_comma(); w_as_register (REGISTER_O1); 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_opcode_descriptor ("set", parameter_0.parameter_data.l->label_name, parameter_0.parameter_offset ); w_as_comma(); w_as_register (REGISTER_O0); w_as_newline(); parameter_0.parameter_type=P_REGISTER; parameter_0.parameter_data.reg.r=REGISTER_O0; break; case P_IMMEDIATE: if ((unsigned)(parameter_0.parameter_data.i+4096)>=(unsigned)8192){ w_as_opcode ("set"); w_as_parameter (¶meter_0); w_as_comma(); w_as_register (REGISTER_O0); w_as_newline(); parameter_0.parameter_type=P_REGISTER; parameter_0.parameter_data.reg.r=REGISTER_O0; } break; case P_REGISTER: break; default: w_as_opcode_parameter ("ldsh",¶meter_0); w_as_comma(); w_as_register (REGISTER_O0); w_as_newline(); parameter_0.parameter_type=P_REGISTER; parameter_0.parameter_data.reg.r=REGISTER_O0; } w_as_opcode ("cmp"); w_as_parameter (¶meter_1); w_as_comma(); w_as_parameter (¶meter_0); w_as_newline(); } #endif static void w_as_tst_instruction (struct instruction *instruction,int size_flag) { struct parameter parameter_0; parameter_0=w_as_register_parameter (instruction->instruction_parameters[0],size_flag); w_as_opcode (size_flag==SIZE_LONG ? "tst" : "tstb"); w_as_register (parameter_0.parameter_data.reg.r); w_as_newline(); } static void w_as_btst_instruction (struct instruction *instruction) { w_as_opcode ("btst"); w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); w_as_comma(); w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_newline(); } void w_as_jmp_instruction (struct instruction *instruction) { if (instruction->instruction_parameters[0].parameter_type==P_LABEL){ if (instruction->instruction_parameters[0].parameter_data.l->label_flags & LOCAL_LABEL){ w_as_opcode ("b,a"); w_as_jump_parameter (&instruction->instruction_parameters[0]); w_as_newline(); return; } else w_as_opcode ("call"); } else w_as_opcode ("jmp"); w_as_jump_parameter (&instruction->instruction_parameters[0]); w_as_newline(); w_as_instruction_without_parameters ("nop"); } static void w_as_branch_instruction (struct instruction *instruction,char *opcode) { w_as_opcode (opcode); w_as_parameter (&instruction->instruction_parameters[0]); w_as_newline(); w_as_instruction_without_parameters ("nop"); } static void w_as_index_error_branch_instruction (struct instruction *instruction) { /* w_as_opcode ("bleu"); */ w_as_opcode ("bcs"); fprintf (assembly_file,".+12"); w_as_newline(); w_as_instruction_without_parameters ("nop"); w_as_opcode ("b,a"); w_as_jump_parameter (&instruction->instruction_parameters[0]); w_as_newline(); } static void w_as_float_branch_instruction (struct instruction *instruction,char *opcode) { w_as_instruction_without_parameters ("nop"); w_as_opcode (opcode); w_as_parameter (&instruction->instruction_parameters[0]); w_as_newline(); w_as_instruction_without_parameters ("nop"); } static char local_c_stack_overflow_label_name[]="l_c_stack_overflow"; /* static void w_as_check_c_stack (void) { w_as_opcode ("cmp"); w_as_register (C_STACK_POINTER); w_as_comma(); w_as_register (REGISTER_G5); w_as_newline(); w_as_opcode ("bleu"); w_as_label (local_c_stack_overflow_label_name); w_as_newline(); } */ static void w_as_jsr_instruction (struct instruction *instruction) { /* if (check_c_stack) w_as_check_c_stack(); */ w_as_opcode ("call"); w_as_jump_parameter (&instruction->instruction_parameters[0]); w_as_newline(); if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT){ w_as_opcode ("st"); w_as_register (REGISTER_O7); w_as_comma(); w_as_indirect (instruction->instruction_parameters[1].parameter_data.i,B_STACK_POINTER); w_as_newline(); } else w_as_instruction_without_parameters ("nop"); } static void w_as_rts_instruction (struct instruction *instruction) { int b_offset; w_as_opcode_indirect ("ld",instruction->instruction_parameters[0].parameter_offset,B_STACK_POINTER); w_as_comma(); w_as_register (REGISTER_O7); w_as_newline(); w_as_instruction_without_parameters ("retl"); b_offset=instruction->instruction_parameters[1].parameter_data.i; if (b_offset==0) w_as_instruction_without_parameters ("nop"); else { if (b_offset<0){ w_as_opcode ("dec"); w_as_immediate (-b_offset); } else { w_as_opcode ("inc"); w_as_immediate (b_offset); } w_as_comma(); w_as_register (B_STACK_POINTER); w_as_newline(); } } static void w_as_set_condition_instruction (struct instruction *instruction,char *opcode) { w_as_opcode ("clr"); w_as_parameter (&instruction->instruction_parameters[0]); w_as_newline(); w_as_opcode (opcode); fprintf (assembly_file,".+8"); w_as_newline(); w_as_opcode ("mov"); fprintf (assembly_file,"-1"); w_as_comma(); w_as_parameter (&instruction->instruction_parameters[0]); w_as_newline(); } static void w_as_set_float_condition_instruction (struct instruction *instruction,char *opcode) { w_as_instruction_without_parameters ("nop"); w_as_set_condition_instruction (instruction,opcode); } static void w_as_mod_instruction (struct instruction *instruction) { w_as_opcode ("mov"); w_as_parameter (&instruction->instruction_parameters[2]); w_as_comma(); w_as_register (REGISTER_O0); w_as_newline(); switch (instruction->instruction_parameters[0].parameter_type){ case P_REGISTER: w_as_opcode ("call"); fprintf (assembly_file,".rem"); w_as_newline(); w_as_opcode ("mov"); w_as_parameter (&instruction->instruction_parameters[0]); break; case P_IMMEDIATE: { long v; v=instruction->instruction_parameters[0].parameter_data.i; if ((unsigned)(v+4096) < (unsigned)8192){ w_as_opcode ("call"); fprintf (assembly_file,".rem"); w_as_newline(); w_as_opcode ("mov"); w_as_immediate (v); } else { w_as_opcode ("sethi"); fprintf (assembly_file,"%%hi "); #ifdef GAS fprintf (assembly_file,"("); #endif w_as_immediate (v); #ifdef GAS fprintf (assembly_file,")"); #endif w_as_comma(); w_as_register (REGISTER_O1); w_as_newline(); w_as_opcode ("call"); fprintf (assembly_file,".rem"); w_as_newline(); w_as_opcode ("or"); w_as_register (REGISTER_O1); w_as_comma(); fprintf (assembly_file,"%%lo "); #ifdef GAS fprintf (assembly_file,"("); #endif w_as_immediate (v); #ifdef GAS fprintf (assembly_file,")"); #endif } break; } default: w_as_opcode ("call"); fprintf (assembly_file,".rem"); w_as_newline(); w_as_ld_parameter (&instruction->instruction_parameters[0]); } w_as_comma(); w_as_register (REGISTER_O1); w_as_newline(); w_as_opcode ("mov"); w_as_register (REGISTER_O0); w_as_comma(); w_as_parameter (&instruction->instruction_parameters[1]); w_as_newline(); } static void w_as_mul_or_div_instruction (struct instruction *instruction,char *mul_or_div_label_name) { w_as_opcode ("mov"); w_as_parameter (&instruction->instruction_parameters[1]); w_as_comma(); w_as_register (REGISTER_O0); w_as_newline(); switch (instruction->instruction_parameters[0].parameter_type){ case P_REGISTER: w_as_opcode ("call"); fprintf (assembly_file,mul_or_div_label_name); w_as_newline(); w_as_opcode ("mov"); w_as_parameter (&instruction->instruction_parameters[0]); break; case P_IMMEDIATE: { long v; v=instruction->instruction_parameters[0].parameter_data.i; if ((unsigned)(v+4096) < (unsigned)8192){ w_as_opcode ("call"); fprintf (assembly_file,mul_or_div_label_name); w_as_newline(); w_as_opcode ("mov"); w_as_immediate (v); } else { w_as_opcode ("sethi"); fprintf (assembly_file,"%%hi "); #ifdef GAS fprintf (assembly_file,"("); #endif w_as_immediate (v); #ifdef GAS fprintf (assembly_file,")"); #endif w_as_comma(); w_as_register (REGISTER_O1); w_as_newline(); w_as_opcode ("call"); fprintf (assembly_file,mul_or_div_label_name); w_as_newline(); w_as_opcode ("or"); w_as_register (REGISTER_O1); w_as_comma(); fprintf (assembly_file,"%%lo "); #ifdef GAS fprintf (assembly_file,"("); #endif w_as_immediate (v); #ifdef GAS fprintf (assembly_file,")"); #endif } break; } default: w_as_opcode ("call"); fprintf (assembly_file,mul_or_div_label_name); w_as_newline(); w_as_ld_parameter (&instruction->instruction_parameters[0]); } w_as_comma(); w_as_register (REGISTER_O1); w_as_newline(); w_as_opcode ("mov"); w_as_register (REGISTER_O0); w_as_comma(); w_as_parameter (&instruction->instruction_parameters[1]); w_as_newline(); } static void w_as_word_instruction (struct instruction *instruction) { fprintf (assembly_file,"\t.word\t%d\n", (int)instruction->instruction_parameters[0].parameter_data.i); } static void w_as_neg_instruction (struct instruction *instruction) { w_as_opcode ("sub"); w_as_register_comma (REGISTER_G0); w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r); w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); w_as_newline(); } static void w_as_load_float_indirect (struct parameter *parameter_p,int f_reg) { #ifdef ALIGN_REAL_ARRAYS if (parameter_p->parameter_flags & LOAD_STORE_ALIGNED_REAL){ w_as_opcode ("ldd"); w_as_indirect (parameter_p->parameter_offset,parameter_p->parameter_data.reg.r); w_as_comma(); w_as_fp_register (f_reg<<1); w_as_newline(); } else { #endif w_as_opcode ("ld"); w_as_indirect (parameter_p->parameter_offset,parameter_p->parameter_data.reg.r); w_as_comma(); w_as_fp_register (f_reg<<1); w_as_newline(); w_as_opcode ("ld"); w_as_indirect (parameter_p->parameter_offset+4,parameter_p->parameter_data.reg.r); w_as_comma(); w_as_fp_register ((f_reg<<1)+1); w_as_newline(); #ifdef ALIGN_REAL_ARRAYS } #endif } static void w_as_load_float_indexed (struct parameter *parameter_p,int f_reg) { int offset; offset=parameter_p->parameter_offset>>2; #ifdef ALIGN_REAL_ARRAYS if (parameter_p->parameter_flags & LOAD_STORE_ALIGNED_REAL){ if (offset==0){ w_as_opcode ("ldd"); w_as_indexed (offset,parameter_p->parameter_data.ir); w_as_comma(); w_as_fp_register (f_reg<<1); w_as_newline(); } else { w_as_opcode ("add"); w_as_register_comma (parameter_p->parameter_data.ir->a_reg.r); w_as_register_comma (parameter_p->parameter_data.ir->d_reg.r); w_as_register_newline (REGISTER_O0); w_as_opcode ("ldd"); w_as_indirect (offset,REGISTER_O0); w_as_comma(); w_as_fp_register (f_reg<<1); w_as_newline(); } } else { #endif w_as_opcode ("add"); w_as_register_comma (parameter_p->parameter_data.ir->a_reg.r); w_as_register_comma (parameter_p->parameter_data.ir->d_reg.r); w_as_register_newline (REGISTER_O0); w_as_opcode ("ld"); w_as_indirect (offset,REGISTER_O0); w_as_comma(); w_as_fp_register (f_reg<<1); w_as_newline(); w_as_opcode ("ld"); w_as_indirect (offset+4,REGISTER_O0); w_as_comma(); w_as_fp_register ((f_reg<<1)+1); w_as_newline(); #ifdef ALIGN_REAL_ARRAYS } #endif } static int w_as_float_parameter (struct parameter parameter) { switch (parameter.parameter_type){ case P_F_IMMEDIATE: { int label_number=next_label_id++; w_as_to_data_section(); w_as_opcode (".align"); fprintf (assembly_file,"8"); w_as_newline(); w_as_define_internal_label (label_number); w_as_opcode (".double"); fprintf (assembly_file,"0r%.20e",*parameter.parameter_data.r); w_as_newline(); w_as_to_code_section(); w_as_opcode ("sethi"); #ifdef GAS fprintf (assembly_file,"%%hi (i_%d),%%o0",label_number); #else fprintf (assembly_file,"%%hi i_%d,%%o0",label_number); #endif w_as_newline(); w_as_opcode ("ldd"); #ifdef GAS fprintf (assembly_file,"[%%o0+%%lo (i_%d)]",label_number); #else fprintf (assembly_file,"[%%o0+%%lo i_%d]",label_number); #endif w_as_comma(); w_as_fp_register (30); w_as_newline(); return 15; } case P_INDIRECT: #ifdef ALIGN_REAL_ARRAYS if (parameter.parameter_flags & LOAD_STORE_ALIGNED_REAL){ w_as_opcode ("ldd"); w_as_indirect (parameter.parameter_offset,parameter.parameter_data.reg.r); w_as_comma(); w_as_fp_register (30); w_as_newline(); } else { #endif w_as_opcode ("ld"); w_as_indirect (parameter.parameter_offset,parameter.parameter_data.reg.r); w_as_comma(); w_as_fp_register (30); w_as_newline(); w_as_opcode ("ld"); w_as_indirect (parameter.parameter_offset+4,parameter.parameter_data.reg.r); w_as_comma(); w_as_fp_register (31); w_as_newline(); #ifdef ALIGN_REAL_ARRAYS } #endif return 15; case P_INDEXED: { int offset; offset=parameter.parameter_offset>>2; #ifdef ALIGN_REAL_ARRAYS if (parameter.parameter_flags & LOAD_STORE_ALIGNED_REAL){ if (offset==0){ w_as_opcode ("ldd"); w_as_indexed (offset,parameter.parameter_data.ir); w_as_comma(); w_as_fp_register (30); w_as_newline(); } else { w_as_opcode ("add"); w_as_register_comma (parameter.parameter_data.ir->a_reg.r); w_as_register_comma (parameter.parameter_data.ir->d_reg.r); w_as_register_newline (REGISTER_O0); w_as_opcode ("ldd"); w_as_indirect (offset,REGISTER_O0); w_as_comma(); w_as_fp_register (30); w_as_newline(); } } else { #endif w_as_opcode ("add"); w_as_register_comma (parameter.parameter_data.ir->a_reg.r); w_as_register_comma (parameter.parameter_data.ir->d_reg.r); w_as_register_newline (REGISTER_O0); w_as_opcode ("ld"); w_as_indirect (offset,REGISTER_O0); w_as_comma(); w_as_fp_register (30); w_as_newline(); w_as_opcode ("ld"); w_as_indirect (offset+4,REGISTER_O0); w_as_comma(); w_as_fp_register (31); w_as_newline(); #ifdef ALIGN_REAL_ARRAYS } #endif return 15; case P_F_REGISTER: return parameter.parameter_data.reg.r; } } internal_error_in_function ("w_as_float_parameter"); return 0; } static void w_as_compare_float_instruction (struct instruction *instruction) { int f_reg; f_reg=w_as_float_parameter (instruction->instruction_parameters[0]); w_as_opcode_and_d ("fcmp"); w_as_parameter (&instruction->instruction_parameters[1]); w_as_comma(); w_as_fp_register (f_reg<<1); w_as_newline(); } static void w_as_sqrt_float_instruction (struct instruction *instruction) { int f_reg; f_reg=w_as_float_parameter (instruction->instruction_parameters[0]); w_as_opcode_and_d ("fsqrt"); w_as_fp_register (f_reg<<1); w_as_comma(); w_as_parameter (&instruction->instruction_parameters[1]); w_as_newline(); } static void w_as_neg_or_abs_float_instruction (struct instruction *instruction,char *opcode) { int freg1,freg2; freg2=instruction->instruction_parameters[1].parameter_data.reg.r; switch (instruction->instruction_parameters[0].parameter_type){ case P_INDIRECT: w_as_load_float_indirect (&instruction->instruction_parameters[0],freg2); freg1=freg2; break; case P_INDEXED: w_as_load_float_indexed (&instruction->instruction_parameters[0],freg2); freg1=freg2; break; default: freg1=w_as_float_parameter (instruction->instruction_parameters[0]); } w_as_opcode (opcode); w_as_fp_register (freg1<<1); w_as_comma(); w_as_fp_register_newline (freg2<<1); if (freg1!=freg2){ w_as_opcode ("fmovs"); w_as_fp_register ((freg1<<1)+1); w_as_comma(); w_as_fp_register_newline ((freg2<<1)+1); } } static void w_as_tryadic_float_instruction (struct instruction *instruction,char *opcode) { int freg; freg=w_as_float_parameter (instruction->instruction_parameters[0]); w_as_opcode_and_d (opcode); w_as_parameter (&instruction->instruction_parameters[1]); w_as_comma(); w_as_fp_register (freg<<1); 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) { int reg_s; reg_s=w_as_float_parameter (next_instruction->instruction_parameters[0]); if (reg_s==reg1) reg_s=reg0; switch (next_instruction->instruction_icode){ case IFADD: w_as_opcode_and_d ("fadd"); break; case IFSUB: w_as_opcode_and_d ("fsub"); break; case IFMUL: w_as_opcode_and_d ("fmul"); break; case IFDIV: w_as_opcode_and_d ("fdiv"); break; case IFREM: w_as_opcode_and_d ("frem"); } w_as_fp_register (reg0<<1); w_as_comma(); w_as_fp_register (reg_s<<1); w_as_comma(); w_as_fp_register (reg1<<1); w_as_newline(); return next_instruction; } } w_as_opcode ("fmovs"); w_as_fp_register (reg0<<1); w_as_comma(); w_as_fp_register (reg1<<1); w_as_newline(); w_as_opcode ("fmovs"); w_as_fp_register ((reg0<<1)+1); w_as_comma(); w_as_fp_register ((reg1<<1)+1); w_as_newline(); return instruction; } case P_INDIRECT: w_as_load_float_indirect (&instruction->instruction_parameters[0], instruction->instruction_parameters[1].parameter_data.reg.r); return instruction; case P_INDEXED: w_as_load_float_indexed (&instruction->instruction_parameters[0], instruction->instruction_parameters[1].parameter_data.reg.r); return instruction; case P_F_IMMEDIATE: { int label_number=next_label_id++; w_as_to_data_section(); w_as_opcode (".align"); fprintf (assembly_file,"8"); w_as_newline(); w_as_define_internal_label (label_number); w_as_opcode (".double"); fprintf (assembly_file,"0r%.20e",*instruction->instruction_parameters[0].parameter_data.r); w_as_newline(); w_as_to_code_section(); w_as_opcode ("sethi"); #ifdef GAS fprintf (assembly_file,"%%hi (i_%d),%%o0",label_number); #else fprintf (assembly_file,"%%hi i_%d,%%o0",label_number); #endif w_as_newline(); w_as_opcode ("ldd"); #ifdef GAS fprintf (assembly_file,"[%%o0+%%lo (i_%d)]",label_number); #else fprintf (assembly_file,"[%%o0+%%lo i_%d]",label_number); #endif w_as_comma(); w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r<<1); w_as_newline(); return instruction; } } break; case P_INDIRECT: if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){ #ifdef ALIGN_REAL_ARRAYS if (instruction->instruction_parameters[1].parameter_flags & LOAD_STORE_ALIGNED_REAL){ w_as_opcode ("std"); w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r<<1); 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; } #endif w_as_opcode ("st"); w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r<<1); w_as_comma(); w_as_indirect (instruction->instruction_parameters[1].parameter_offset, instruction->instruction_parameters[1].parameter_data.reg.r); w_as_newline(); w_as_opcode ("st"); w_as_fp_register ((instruction->instruction_parameters[0].parameter_data.reg.r<<1)+1); w_as_comma(); w_as_indirect (instruction->instruction_parameters[1].parameter_offset+4, instruction->instruction_parameters[1].parameter_data.reg.r); w_as_newline(); return instruction; } break; case P_INDEXED: { int offset; offset=instruction->instruction_parameters[1].parameter_offset>>2; #ifdef ALIGN_REAL_ARRAYS if (instruction->instruction_parameters[1].parameter_flags & LOAD_STORE_ALIGNED_REAL){ if (offset==0){ w_as_opcode ("std"); w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r<<1); w_as_comma(); w_as_indexed (offset,instruction->instruction_parameters[1].parameter_data.ir); w_as_newline(); } else { w_as_opcode ("add"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.ir->a_reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.ir->d_reg.r); w_as_register_newline (REGISTER_O0); w_as_opcode ("std"); w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r<<1); w_as_comma(); w_as_indirect (offset,REGISTER_O0); w_as_newline(); } return instruction; } #endif if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){ w_as_opcode ("add"); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.ir->a_reg.r); w_as_register_comma (instruction->instruction_parameters[1].parameter_data.ir->d_reg.r); w_as_register_newline (REGISTER_O0); w_as_opcode ("st"); w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r<<1); w_as_comma(); w_as_indirect (offset,REGISTER_O0); w_as_newline(); w_as_opcode ("st"); w_as_fp_register ((instruction->instruction_parameters[0].parameter_data.reg.r<<1)+1); w_as_comma(); w_as_indirect (offset+4,REGISTER_O0); w_as_newline(); return instruction; } } } internal_error_in_function ("w_as_fmove_instruction"); return instruction; } static void w_as_fmove_hl_instruction (struct instruction *instruction) { if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT && instruction->instruction_parameters[1].parameter_type==P_F_REGISTER) { w_as_opcode_indirect ("ld", instruction->instruction_parameters[0].parameter_offset, instruction->instruction_parameters[0].parameter_data.reg.r); w_as_comma(); if (instruction->instruction_icode==IFMOVEHI) w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r<<1); else w_as_fp_register ((instruction->instruction_parameters[1].parameter_data.reg.r<<1)+1); w_as_newline(); return; } internal_error_in_function ("w_as_fmove_instruction"); } 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 ("fdtoi"); w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r<<1); w_as_comma(); w_as_fp_register (31); w_as_newline(); w_as_opcode ("st"); w_as_fp_register (31); w_as_comma(); w_as_indirect (-4,REGISTER_I6); w_as_newline(); w_as_opcode ("ld"); w_as_indirect (-4,REGISTER_I6); w_as_comma(); w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); w_as_newline(); } else { switch (instruction->instruction_parameters[0].parameter_type){ case P_REGISTER: w_as_opcode ("st"); w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); w_as_comma(); w_as_indirect (-4,REGISTER_I6); w_as_newline(); w_as_opcode ("ld"); w_as_indirect (-4,REGISTER_I6); w_as_comma(); w_as_fp_register (31); w_as_newline(); break; case P_INDIRECT: w_as_opcode ("ld"); w_as_indirect (instruction->instruction_parameters[0].parameter_offset, instruction->instruction_parameters[0].parameter_data.reg.r); w_as_comma(); w_as_fp_register (31); w_as_newline(); break; case P_INDEXED: w_as_opcode ("ld"); w_as_indexed (instruction->instruction_parameters[0].parameter_offset, instruction->instruction_parameters[0].parameter_data.ir); w_as_comma(); w_as_fp_register (31); w_as_newline(); break; case P_IMMEDIATE: w_as_opcode ("set"); w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); w_as_comma(); w_as_scratch_register(); w_as_newline(); w_as_opcode ("st"); w_as_scratch_register(); w_as_comma(); w_as_indirect (-4,REGISTER_I6); w_as_newline(); w_as_opcode ("ld"); w_as_indirect (-4,REGISTER_I6); w_as_comma(); w_as_fp_register (31); w_as_newline(); break; default: internal_error_in_function ("w_as_fmovel_instruction"); } w_as_opcode ("fitod"); w_as_fp_register (31); w_as_comma(); w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r<<1); w_as_newline(); } } 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,"add"); 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,"be"); break; case IBGE: w_as_branch_instruction (instruction,"bge"); break; case IBGT: w_as_branch_instruction (instruction,"bg"); break; case IBHS: w_as_index_error_branch_instruction (instruction); break; case IBLE: w_as_branch_instruction (instruction,"ble"); break; case IBLT: w_as_branch_instruction (instruction,"bl"); break; case IBNE: w_as_branch_instruction (instruction,"bne"); break; case IBNO: w_as_branch_instruction (instruction,"bvc"); break; case IBO: w_as_branch_instruction (instruction,"bvs"); break; case ILSLI: w_as_i_instruction (instruction,"sll"); break; case ILSL: w_as_tryadic_instruction (instruction,"sll"); break; case ILSR: w_as_tryadic_instruction (instruction,"srl"); break; case IASR: w_as_tryadic_instruction (instruction,"sra"); break; case IMUL: w_as_mul_or_div_instruction (instruction,".mul"); break; case IDIV: w_as_mul_or_div_instruction (instruction,".div"); break; case IREM: w_as_mod_instruction (instruction); break; case IAND: w_as_tryadic_instruction (instruction,"and"); break; case IOR: w_as_tryadic_instruction (instruction,"or"); break; case IEOR: w_as_tryadic_instruction (instruction,"xor"); break; case ISEQ: w_as_set_condition_instruction (instruction,"be,a"); break; case ISGE: w_as_set_condition_instruction (instruction,"bge,a"); break; case ISGT: w_as_set_condition_instruction (instruction,"bg,a"); break; case ISLE: w_as_set_condition_instruction (instruction,"ble,a"); break; case ISLT: w_as_set_condition_instruction (instruction,"bl,a"); break; case ISNE: w_as_set_condition_instruction (instruction,"bne,a"); break; case ISNO: w_as_set_condition_instruction (instruction,"bvc,a"); break; case ISO: w_as_set_condition_instruction (instruction,"bvs,a"); break; #if 0 case ICMPW: w_as_cmpw_instruction (instruction); break; #endif case ITST: w_as_tst_instruction (instruction,SIZE_LONG); 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 INEG: w_as_neg_instruction (instruction); break; case IFMOVE: instruction=w_as_fmove_instruction (instruction); break; case IFMOVEHI: case IFMOVELO: w_as_fmove_hl_instruction (instruction); break; case IFADD: w_as_tryadic_float_instruction (instruction,"fadd"); break; case IFSUB: w_as_tryadic_float_instruction (instruction,"fsub"); break; case IFCMP: w_as_compare_float_instruction (instruction); break; case IFDIV: w_as_tryadic_float_instruction (instruction,"fdiv"); break; case IFMUL: w_as_tryadic_float_instruction (instruction,"fmul"); break; case IFREM: w_as_tryadic_float_instruction (instruction,"frem"); break; case IFBEQ: w_as_float_branch_instruction (instruction,"fbe"); break; case IFBGE: w_as_float_branch_instruction (instruction,"fbge"); break; case IFBGT: w_as_float_branch_instruction (instruction,"fbg"); break; case IFBLE: w_as_float_branch_instruction (instruction,"fble"); break; case IFBLT: w_as_float_branch_instruction (instruction,"fbl"); break; case IFBNE: w_as_float_branch_instruction (instruction,"fbne"); break; case IFMOVEL: w_as_fmovel_instruction (instruction); break; case IFSQRT: w_as_sqrt_float_instruction (instruction); break; case IFNEG: w_as_neg_or_abs_float_instruction (instruction,"fnegs"); break; case IFABS: w_as_neg_or_abs_float_instruction (instruction,"fabss"); break; case IFSEQ: w_as_set_float_condition_instruction (instruction,"fbe,a"); break; case IFSGE: w_as_set_float_condition_instruction (instruction,"fbge,a"); break; case IFSGT: w_as_set_float_condition_instruction (instruction,"fbg,a"); break; case IFSLE: w_as_set_float_condition_instruction (instruction,"fble,a"); break; case IFSLT: w_as_set_float_condition_instruction (instruction,"fbl,a"); break; case IFSNE: w_as_set_float_condition_instruction (instruction,"fbne,a"); break; case IWORD: w_as_word_instruction (instruction); break; case IADDO: w_as_add_o_instruction (instruction); break; case ISUBO: w_as_sub_o_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 (".word"); fprintf (assembly_file,"%d",n_node_arguments); w_as_newline(); } struct call_and_jump { struct call_and_jump *cj_next; WORD cj_label_id; WORD cj_jump_id; char *cj_call_label_name; }; static struct call_and_jump *first_call_and_jump,*last_call_and_jump; static void w_as_garbage_collect_test (register struct basic_block *block) { LONG n_cells; int label_id_1,label_id_2; struct call_and_jump *new_call_and_jump; label_id_1=next_label_id++; label_id_2=next_label_id++; new_call_and_jump=allocate_memory_from_heap (sizeof (struct call_and_jump)); new_call_and_jump->cj_next=NULL; 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"); } 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; n_cells=block->block_n_new_heap_cells; if (n_cells<4096){ w_as_opcode ("deccc"); w_as_immediate (n_cells); w_as_comma(); w_as_register (REGISTER_D7); w_as_newline(); } else { w_as_opcode ("set"); w_as_immediate (n_cells); w_as_comma(); w_as_scratch_register(); w_as_newline(); w_as_opcode ("subcc"); w_as_register (REGISTER_D7); w_as_comma(); w_as_scratch_register(); w_as_comma(); w_as_register (REGISTER_D7); w_as_newline(); } w_as_opcode ("bcs,a"); w_as_internal_label (label_id_1); w_as_newline (); w_as_opcode ("dec"); w_as_immediate (4); w_as_comma(); w_as_register (B_STACK_POINTER); w_as_newline(); w_as_define_internal_label (label_id_2); } static void w_as_call_and_jump (struct call_and_jump *call_and_jump) { w_as_define_internal_label (call_and_jump->cj_label_id); w_as_opcode ("call"); w_as_label (call_and_jump->cj_call_label_name); w_as_newline(); w_as_opcode ("st"); w_as_register (REGISTER_O7); w_as_comma(); w_as_indirect (0,B_STACK_POINTER); w_as_newline(); w_as_opcode ("b,a"); w_as_internal_label (call_and_jump->cj_jump_id); w_as_newline(); } static void w_as_labels (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); } /* static void init_c_stack_checking (VOID) { w_as_define_label_name (local_c_stack_overflow_label_name); w_as_opcode ("ba"); w_as_label (c_stack_overflow_label->label_name); w_as_newline(); w_as_instruction_without_parameters ("nop"); } */ static char local_ab_stack_overflow_label_name[]="l_ab_stack_overflow"; /* static void init_ab_stack_checking (VOID) { w_as_define_label_name (local_ab_stack_overflow_label_name); w_as_opcode ("ba"); w_as_label (ab_stack_overflow_label->label_name); w_as_newline(); w_as_instruction_without_parameters ("nop"); } */ /* static void w_as_check_ab_stack (int size,int n_d_parameters,int n_a_parameters) { if (size<=4){ w_as_opcode ("cmp"); w_as_register (A_STACK_POINTER); w_as_comma(); w_as_register (B_STACK_POINTER); w_as_newline(); w_as_opcode ("bleu"); } else { w_as_opcode ("add"); w_as_register (B_STACK_POINTER); w_as_comma(); w_as_immediate (size); w_as_comma(); w_as_register (REGISTER_O0); w_as_newline(); w_as_opcode ("cmp"); w_as_register (REGISTER_O0); w_as_comma(); w_as_register (A_STACK_POINTER); w_as_newline(); w_as_opcode ("bgu"); } w_as_label (local_ab_stack_overflow_label_name); w_as_newline(); w_as_instruction_without_parameters ("nop"); } */ void initialize_write_assembly (FILE *ass_file) { assembly_file=ass_file; in_data_section=0; first_call_and_jump=NULL; /* if (check_c_stack) init_c_stack_checking(); if (check_ab_stack) init_ab_stack_checking(); */ } static void w_as_indirect_node_entry_jump (LABEL *label) { register char *new_label_name; new_label_name=fast_memory_allocate (strlen (label->label_name)+1+2); strcpy (new_label_name,"j_"); strcat (new_label_name,label->label_name); if (label->label_flags & EA_LABEL){ int label_arity; extern LABEL *eval_fill_label,*eval_upd_labels[]; label_arity=label->label_arity; if (label_arity<-2) label_arity=1; if (label_arity>=0 && label->label_ea_label!=eval_fill_label){ w_as_opcode ("sethi"); fprintf (assembly_file,"%%hi "); #ifdef GAS fprintf (assembly_file,"("); #endif w_as_label (label->label_ea_label->label_name); #ifdef GAS fprintf (assembly_file,")"); #endif w_as_comma(); w_as_register (REGISTER_A2); w_as_newline(); w_as_opcode ("call"); w_as_label (eval_upd_labels[label_arity]->label_name); w_as_newline(); w_as_opcode ("inc"); fprintf (assembly_file,"%%lo "); #ifdef GAS fprintf (assembly_file,"("); #endif w_as_label (label->label_ea_label->label_name); #ifdef GAS fprintf (assembly_file,")"); #endif w_as_comma(); w_as_register (REGISTER_A2); w_as_newline(); } else { w_as_opcode ("call"); w_as_label (label->label_ea_label->label_name); w_as_newline(); w_as_instruction_without_parameters ("nop"); w_as_instruction_without_parameters ("nop"); } if (label->label_arity<0 || parallel_flag){ LABEL *descriptor_label; descriptor_label=label->label_descriptor; if (descriptor_label->label_id<0) descriptor_label->label_id=next_label_id++; w_as_opcode (".long"); w_as_label (descriptor_label->label_name); w_as_newline(); } else w_as_number_of_arguments (0); } else if (label->label_arity<0 || parallel_flag){ LABEL *descriptor_label; descriptor_label=label->label_descriptor; if (descriptor_label->label_id<0) descriptor_label->label_id=next_label_id++; w_as_opcode (".long"); w_as_label (descriptor_label->label_name); w_as_newline(); } w_as_number_of_arguments (label->label_arity); w_as_define_label_name (new_label_name); w_as_opcode ("call"); w_as_label (label->label_name); w_as_newline(); label->label_name=new_label_name; w_as_instruction_without_parameters ("nop"); } static void w_as_indirect_node_entry_jumps (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) if (label->label_flags & NODE_ENTRY_LABEL) w_as_indirect_node_entry_jump (label); w_as_indirect_node_entry_jumps (label_node->label_node_left); w_as_indirect_node_entry_jumps (label_node->label_node_right); } #ifdef SOLARIS_ static int next_section_number; extern char *this_module_name; #endif #ifdef NEW_APPLY extern LABEL *add_empty_node_labels[]; static void w_as_apply_update_entry (struct basic_block *block) { if (block->block_n_node_arguments==-200){ w_as_opcode ("ba,a"); 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 ("dec"); w_as_immediate (4); w_as_comma(); w_as_register_newline (B_STACK_POINTER); w_as_opcode ("call"); w_as_label (add_empty_node_labels[block->block_n_node_arguments+200]->label_name); w_as_newline(); w_as_opcode ("st"); w_as_register (REGISTER_O7); w_as_comma(); w_as_indirect (0,B_STACK_POINTER); w_as_newline(); w_as_opcode ("ba,a"); 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; #ifdef SOLARIS_ next_section_number=0; #endif w_as_to_code_section(); w_as_indirect_node_entry_jumps (labels); for (block=first_block; block!=NULL; block=block->block_next){ #ifdef SOLARIS_ if (block->block_begin_module && !block->block_link_module){ if (block->block_labels!=NULL && block->block_labels->block_label_label->label_number==0 && block->block_labels->block_label_label->label_flags & EXPORT_LABEL) fprintf (assembly_file,"\t.section\t\".%s\",#alloc,#execinstr\n",block->block_labels->block_label_label->label_name); else fprintf (assembly_file,"\t.section\t\"%s.%d\",#alloc,#execinstr\n",this_module_name,next_section_number++); } #endif 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_opcode ("sethi"); fprintf (assembly_file,"%%hi "); #ifdef GAS fprintf (assembly_file,"("); #endif w_as_label (block->block_ea_label->label_name); #ifdef GAS fprintf (assembly_file,")"); #endif w_as_comma(); w_as_register (REGISTER_A2); w_as_newline(); w_as_opcode ("call"); w_as_label (eval_upd_labels[n_node_arguments]->label_name); w_as_newline(); w_as_opcode ("inc"); fprintf (assembly_file,"%%lo "); #ifdef GAS fprintf (assembly_file,"("); #endif w_as_label (block->block_ea_label->label_name); #ifdef GAS fprintf (assembly_file,")"); #endif w_as_comma(); w_as_register (REGISTER_A2); w_as_newline(); } else { w_as_opcode ("call"); w_as_label (block->block_ea_label->label_name); w_as_newline(); w_as_instruction_without_parameters ("nop"); w_as_instruction_without_parameters ("nop"); } if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag)) { w_as_label_in_code_section (block->block_descriptor->label_name); } else w_as_number_of_arguments (0); } else if (block->block_descriptor!=NULL) w_as_label_in_code_section (block->block_descriptor->label_name); else w_as_number_of_arguments (0); w_as_number_of_arguments (block->block_n_node_arguments); } #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_n_new_heap_cells>0) w_as_garbage_collect_test (block); /* if (check_ab_stack && block->block_ab_stack_check_size>0) w_as_check_ab_stack (block->block_ab_stack_check_size, block->block_n_begin_d_parameter_registers,block->block_n_begin_a_parameter_registers); */ w_as_instructions (block->block_instructions); } for (call_and_jump=first_call_and_jump; call_and_jump!=NULL; call_and_jump=call_and_jump->cj_next) w_as_call_and_jump (call_and_jump); w_as_instruction_without_parameters ("nop"); }