diff options
Diffstat (limited to 'cgawas.c')
-rw-r--r-- | cgawas.c | 3550 |
1 files changed, 3550 insertions, 0 deletions
diff --git a/cgawas.c b/cgawas.c new file mode 100644 index 0000000..ca61f3b --- /dev/null +++ b/cgawas.c @@ -0,0 +1,3550 @@ +/* + File: cgawas.c + Author: John van Groningen + Machine: opteron athlon64 +*/ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <stdlib.h> + +#undef GENERATIONAL_GC +#define LEA_ADDRESS + +#include "cgport.h" +#include "cgrconst.h" +#include "cgtypes.h" +#include "cg.h" +#include "cgiconst.h" +#include "cgcode.h" +#include "cginstructions.h" +#include "cgaas.h" + +#include "cgiwas.h" + +int intel_asm=1; + +#define for_l(v,l,n) for(v=(l);v!=NULL;v=v->n) + +#define IO_BUF_SIZE 8192 + +static FILE *assembly_file; + +static void w_as_newline (VOID) +{ + putc ('\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_local_data_label (int label_number) +{ + fprintf (assembly_file,intel_asm ? "l_%d label ptr\n" : "l_%d:\n",label_number); +} + +static void w_as_define_internal_label (int label_number) +{ + fprintf (assembly_file,"i_%d:\n",label_number); +} + +static void w_as_define_internal_data_label (int label_number) +{ + fprintf (assembly_file,intel_asm ? "i_%d label ptr\n" : "i_%d:\n",label_number); +} + +void w_as_internal_label_value (int label_id) +{ + fprintf (assembly_file,intel_asm ? "\tdd\ti_%d\n" : "\t.long\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"); + } +} + +#ifdef DATA_IN_CODE_SECTION +# define w_as_to_data_section w_as_to_code_section +#endif + +static void w_as_to_code_section (VOID) +{ + if (in_data_section){ + in_data_section=0; + w_as_instruction_without_parameters (intel_asm ? ".code" : ".text"); + } +} + +static void w_as_align (int i) +{ +#if defined (DOS) || defined (_WINDOWS_) || defined (LINUX_ELF) + fprintf (assembly_file,intel_asm ? "\talign\t%d\n" : "\t.align\t%d\n",1<<i); +#else + fprintf (assembly_file,intel_asm ? "\talign\t%d\n" : "\t.align\t%d\n",i); +#endif +} + +static void w_as_space (int i) +{ + if (intel_asm){ + if (i>0){ + w_as_opcode ("db"); + fprintf (assembly_file,"0"); + while (--i>0) + fprintf (assembly_file,",0"); + w_as_newline(); + } + } else + fprintf (assembly_file,"\t.space\t%d\n",i); +} + +void w_as_word_in_data_section (int n) +{ + w_as_to_data_section(); + w_as_opcode (intel_asm ? "dw" : ".word"); + fprintf (assembly_file,"%d",n); + w_as_newline(); +} + +void w_as_long_in_data_section (int n) +{ +#ifdef DATA_IN_CODE_SECTION + if (!in_data_section){ + in_data_section=1; + w_as_instruction_without_parameters (".data"); + } +#else + w_as_to_data_section(); +#endif + w_as_opcode (intel_asm ? "dd" : ".long"); + fprintf (assembly_file,"%d",n); + w_as_newline(); +} + +static void print_int64 (unsigned __int64 n) +{ + static char digits[32]; + char *p; +/* + if (n<0){ + fputc ('-',assembly_file); + n=-n; + } +*/ + p=&digits[31]; + *p='\0'; + while (n>9){ + unsigned __int64 m; + + m=n/10; + *--p='0'+(n-10*m); + n=m; + } + *--p='0'+n; + + fprintf (assembly_file,p); +} + +void w_as_word64_in_data_section (__int64 n) +{ +#ifdef DATA_IN_CODE_SECTION + if (!in_data_section){ + in_data_section=1; + w_as_instruction_without_parameters (".data"); + } +#else + w_as_to_data_section(); +#endif + w_as_opcode (intel_asm ? "dq" : ".long"); + + if ((int)n==n) + fprintf (assembly_file,"%I64i",n); + else + fprintf (assembly_file,"%I64u",n); + + w_as_newline(); +} + +void w_as_label_in_data_section (char *label_name) +{ + w_as_to_data_section (); + fprintf (assembly_file,intel_asm ? "\tdd\t%s\n" : "\t.long\t%s\n",label_name); +} + +static void w_as_label_in_code_section (char *label_name) +{ + w_as_to_code_section (); + fprintf (assembly_file,intel_asm ? "\tdd\t%s\n" : "\t.long\t%s\n",label_name); +} + +void w_as_descriptor_in_data_section (char *label_name) +{ + w_as_to_data_section(); + w_as_align (3); + fprintf (assembly_file,intel_asm ? "\tdq\t%s+2\n" : "\t.long\t%s+2\n",label_name); +} + +#define MAX_BYTES_PER_LINE 16 + +static int w_as_data (int n,char *data,int length) +{ + int i,in_string; + + in_string=0; + + for (i=0; i<length; ++i){ + int c; + + if (n>=MAX_BYTES_PER_LINE){ + if (in_string){ + putc ('\"',assembly_file); + in_string=0; + } + w_as_newline(); + n=0; + } + + c=((unsigned char*)data)[i]; + if (isalnum (c) || c=='_' || c==' '){ + if (!in_string){ + if (n!=0) + w_as_newline(); + w_as_opcode (intel_asm ? "db" : ".ascii"); + putc ('\"',assembly_file); + in_string=1; + } + putc (c,assembly_file); + } else { + if (n==0) + w_as_opcode (intel_asm ? "db" : ".byte"); + else { + if (in_string){ + putc ('\"',assembly_file); + w_as_newline(); + w_as_opcode (intel_asm ? "db" : ".byte"); + in_string=0; + } else + putc (',',assembly_file); + } + + fprintf (assembly_file,intel_asm ? "%02xh" : "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<length; ++i){ + if (n>=MAX_BYTES_PER_LINE){ + w_as_newline(); + n=0; + } + if (n==0) + w_as_opcode (intel_asm ? "db" : ".byte"); + else + putc (',',assembly_file); + fprintf (assembly_file,"0"); + ++n; + } + return n; +} + +void w_as_define_data_label (int label_number) +{ + w_as_to_data_section(); + + w_as_define_local_data_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_data_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_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)); + /* CHANGED 30-7-92 */ + 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 (intel_asm ? "dq" : ".long"); + fprintf (assembly_file,"%d\n",length); + n=w_as_data (0,string,length); + if (length & 7) + n=w_as_zeros (n,8-(length & 7)); + 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_data_label (string_label_id); + w_as_define_local_data_label (string_label->label_number); + + w_as_opcode (intel_asm ? "dd" : ".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(); +} + +enum { SIZE_LONG, SIZE_WORD, SIZE_BYTE }; + +static void w_as_label (char *label) +{ + int c; + + while ((c=*label++)!=0) + putc (c,assembly_file); +} + +static void w_as_immediate_label (char *label) +{ + int c; + + if (!intel_asm) + putc ('$',assembly_file); + else + fprintf (assembly_file,"offset "); + 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(); +} + +static void w_as_define_data_label_name (char *label_name) +{ + w_as_label (label_name); + if (intel_asm) + fprintf (assembly_file," label ptr"); + else + w_as_colon(); + w_as_newline(); +} + +void w_as_define_label (LABEL *label) +{ + if (label->label_flags & EXPORT_LABEL){ + w_as_opcode (intel_asm ? "public" : ".globl"); + w_as_label (label->label_name); + w_as_newline(); + } + + w_as_label (label->label_name); + if (intel_asm) + fprintf (assembly_file,"\tlabel ptr"); + else + w_as_colon(); + w_as_newline(); +} + +static void w_as_define_code_label (LABEL *label) +{ + if (label->label_flags & EXPORT_LABEL){ + w_as_opcode (intel_asm ? "public" : ".globl"); + 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 (__int64 i) +{ + if ((int)i==i) + fprintf (assembly_file,intel_asm ? "%I64i" : "$%I64u",i); + else + fprintf (assembly_file,intel_asm ? "%I64u" : "$%I64u",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_data_label_name (label_name); + + w_as_opcode (intel_asm ? "dd" : ".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_name_char1[16]="sdsb98dcab111111"; +static char register_name_char2[16]="piip xxxx012345"; + +static char *byte_register_name[16]= {"spl","dil","sil","bpl","r9b","r8b","dl","cl","al","bl", + "r10b","r11b","r12b","r13b","r14b","r15b"}; + +#define REGISTER_O0 (-5) +#define REGISTER_R8 (-3) +#define REGISTER_R9 (-4) +#define REGISTER_R15 7 + +static void w_as_indirect (int i,int reg) +{ + if (!intel_asm){ + if (i!=0){ + fprintf (assembly_file,"%d(%%r%c%c)",i,register_name_char1[reg+8],register_name_char2[reg+8]); + } else + fprintf (assembly_file,"(%%r%c%c)",register_name_char1[reg+8],register_name_char2[reg+8]); + } else { + if (i>0) + fprintf (assembly_file,"%d[r%c%c]",i,register_name_char1[reg+8],register_name_char2[reg+8]); + else if (i==0) + fprintf (assembly_file,"[r%c%c]",register_name_char1[reg+8],register_name_char2[reg+8]); + else + fprintf (assembly_file,"(%d)[r%c%c]",i,register_name_char1[reg+8],register_name_char2[reg+8]); + } +} + +static void w_as_indexed (int offset,struct index_registers *index_registers) +{ + int reg1,reg2,shift; + + reg1=index_registers->a_reg.r; + reg2=index_registers->d_reg.r; + + shift=offset & 3; + offset=offset>>2; + + if (offset!=0){ + if (!intel_asm || offset>0){ + if (shift!=0) + fprintf (assembly_file,intel_asm ? "%d[r%c%c+r%c%c*%d]" : "%d(%%r%c%c,%%r%c%c,%d)",offset, + register_name_char1[reg1+8],register_name_char2[reg1+8], + register_name_char1[reg2+8],register_name_char2[reg2+8],1<<shift); + else + fprintf (assembly_file,intel_asm ? "%d[r%c%c+r%c%c]" : "%d(%%r%c%c,%%r%c%c)",offset, + register_name_char1[reg1+8],register_name_char2[reg1+8], + register_name_char1[reg2+8],register_name_char2[reg2+8]); + } else { + if (shift!=0) + fprintf (assembly_file,"(%d)[r%c%c+r%c%c*%d]",offset, + register_name_char1[reg1+8],register_name_char2[reg1+8], + register_name_char1[reg2+8],register_name_char2[reg2+8],1<<shift); + else + fprintf (assembly_file,"(%d)[r%c%c+r%c%c]",offset, + register_name_char1[reg1+8],register_name_char2[reg1+8], + register_name_char1[reg2+8],register_name_char2[reg2+8]); + } + } else { + if (shift!=0) + fprintf (assembly_file,intel_asm ? "[r%c%c+r%c%c*%d]" : "(%%r%c%c,%%r%c%c,%d)", + register_name_char1[reg1+8],register_name_char2[reg1+8], + register_name_char1[reg2+8],register_name_char2[reg2+8],1<<shift); + else + fprintf (assembly_file,intel_asm ? "[r%c%c+r%c%c]" : "(%%r%c%c,%%r%c%c)", + register_name_char1[reg1+8],register_name_char2[reg1+8], + register_name_char1[reg2+8],register_name_char2[reg2+8]); + } +} + +static void w_as_register (int reg) +{ + if (!intel_asm) + putc ('%',assembly_file); + putc ('r',assembly_file); + putc (register_name_char1[reg+8],assembly_file); + putc (register_name_char2[reg+8],assembly_file); +} + +static void w_as_comma (VOID) +{ + putc (',',assembly_file); +} + +static void w_as_register_comma (int reg) +{ + w_as_register (reg); + w_as_comma(); +} + +static void w_as_comma_register (int reg) +{ + w_as_comma(); + w_as_register (reg); +} + +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_data_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_scratch_register_comma (void) +{ + w_as_register (REGISTER_O0); + w_as_comma(); +} + +static void w_as_comma_scratch_register (void) +{ + w_as_comma(); + w_as_register (REGISTER_O0); +} + +static void w_as_fp_register (int fp_reg) +{ + fprintf (assembly_file,intel_asm ? "xmm%d" : "%%xmm%d",fp_reg); +} + +static void w_as_fp_register_newline (int fp_reg) +{ + fprintf (assembly_file,intel_asm ? "xmm%d\n" : "%%xmm%d\n",fp_reg); +} + +static void w_as_descriptor (LABEL *label,int arity) +{ + if (!intel_asm) + putc ('$',assembly_file); + else + fprintf (assembly_file,"offset "); + + if (label->label_number!=0) + w_as_local_label (label->label_number); + else + w_as_label (label->label_name); + + if (arity!=0) + if (arity>0) + fprintf (assembly_file,"+%d",arity); + else + fprintf (assembly_file,"-%d",-arity); +} + +static void w_as_lea_descriptor (LABEL *label,int arity,int register_1) +{ + w_as_opcode (intel_asm ? "lea" : "leal"); + + if (intel_asm) + w_as_register_comma (register_1); + + if (label->label_number!=0) + w_as_local_label (label->label_number); + else + w_as_label (label->label_name); + + if (arity!=0) + if (arity>0) + fprintf (assembly_file,"+%d",arity); + else + fprintf (assembly_file,"-%d",-arity); + + if (!intel_asm) + w_as_comma_register (register_1); + w_as_newline(); +} + +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 (intel_asm) + fprintf (assembly_file,"offset "); + 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_IMMEDIATE: + fprintf (assembly_file,intel_asm ? "%ld" : "$%ld",parameter->parameter_data.i); + 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_F_REGISTER: + fprintf (assembly_file,intel_asm ? "xmm%d" : "%%xmm%d",parameter->parameter_data.reg.r<<1); + break; + default: + internal_error_in_function ("w_as_parameter"); + } +} + +static void w_as_branch_parameter (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; + default: + internal_error_in_function ("w_as_branch_parameter"); + } +} + +static void w_as_parameter_comma (struct parameter *parameter) +{ + w_as_parameter (parameter); + w_as_comma(); +} + +static void w_as_comma_parameter (struct parameter *parameter) +{ + w_as_comma(); + w_as_parameter (parameter); +} + +static void w_as_comma_word_parameter (struct parameter *parameter) +{ + int reg; + + w_as_comma(); + if (parameter->parameter_type!=P_REGISTER) + internal_error_in_function ("w_as_comma_word_parameter"); + + reg=parameter->parameter_data.reg.r; + + putc (register_name_char1[reg+8],assembly_file); + putc (register_name_char2[reg+8],assembly_file); +} + +static void w_as_byte_register (int reg) +{ + fprintf (assembly_file,"%s",byte_register_name[reg+8]); +} + +static void w_as_byte_register_comma (int reg) +{ + w_as_byte_register (reg); + w_as_comma(); +} + +static void w_as_comma_byte_register (int reg) +{ + w_as_comma(); + w_as_byte_register (reg); +} + +static void w_as_call_or_jump (struct parameter *parameter,char *opcode) +{ + switch (parameter->parameter_type){ + case P_LABEL: + w_as_opcode (opcode); + + 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 (!intel_asm){ + w_as_opcode (opcode); + if (offset!=0) + fprintf (assembly_file,"%d(%%r%c%c)", + offset,register_name_char1[reg+8],register_name_char2[reg+8]); + else + fprintf (assembly_file,"(%%r%c%c)", + register_name_char1[reg+8],register_name_char2[reg+8]); + } else { +#if 1 + if (offset!=0){ + w_as_opcode ("movsxd"); + /* + if (reg==REGISTER_R8 || reg==REGISTER_R9) + fprintf (assembly_file,"r%cd",register_name_char1[reg+8]); + else + fprintf (assembly_file,"r%c%cd",register_name_char1[reg+8],register_name_char2[reg+8]); + */ + /* + fprintf (assembly_file,"ebp"); + */ + w_as_scratch_register(); + w_as_comma(); + if (offset>0) + fprintf (assembly_file, + "dword ptr %d[r%c%c]",offset, + register_name_char1[reg+8],register_name_char2[reg+8]); + else + fprintf (assembly_file, + "dword ptr (%d)[r%c%c]",offset, + register_name_char1[reg+8],register_name_char2[reg+8]); + + w_as_newline(); + + reg=REGISTER_O0; + } +#endif + w_as_opcode (opcode); + fprintf (assembly_file,"near ptr "); + if (offset>0) + fprintf (assembly_file, +#if 1 + "r%c%c", +#else + "%d[r%c%c]",offset, +#endif + register_name_char1[reg+8],register_name_char2[reg+8]); + else if (offset==0) + fprintf (assembly_file,"[r%c%c]", + register_name_char1[reg+8],register_name_char2[reg+8]); + else + fprintf (assembly_file, +#if 1 + "r%c%c", +#else + "(%d)[r%c%c]",offset, +#endif + register_name_char1[reg+8],register_name_char2[reg+8]); + } + break; + } + case P_REGISTER: + { + int reg; + + w_as_opcode (opcode); + + reg=parameter->parameter_data.reg.r; + + fprintf (assembly_file,intel_asm ? "r%c%c" : "%%r%c%c",register_name_char1[reg+8],register_name_char2[reg+8]); + break; + } + default: + internal_error_in_function ("w_as_jump_parameter"); + } + w_as_newline(); +} + +static void w_as_opcode_movl (void) +{ + w_as_opcode (intel_asm ? "mov" : "movl"); +} + +static void w_as_opcode_move (int size_flag) +{ + w_as_opcode (intel_asm ? (size_flag==SIZE_LONG ? "mov" : size_flag==SIZE_WORD ? "movsx" : "movzx") + : (size_flag==SIZE_LONG ? "movl" : size_flag==SIZE_WORD ? "movswl" : "movzbl") + ); +} + +static void w_as_register_register_newline (int reg1,int reg2) +{ + if (intel_asm) + w_as_register_comma (reg2); + w_as_register (reg1); + if (!intel_asm) + w_as_comma_register (reg2); + w_as_newline(); +} + +static void w_as_opcode_register_newline (char *opcode,int reg1) +{ + w_as_opcode (opcode); + w_as_register (reg1); + w_as_newline(); +} + +static void w_as_opcode_register_register_newline (char *opcode,int reg1,int reg2) +{ + w_as_opcode (opcode); + w_as_register_register_newline (reg1,reg2); +} + +static void w_as_movl_register_register_newline (int reg1,int reg2) +{ + w_as_opcode_movl(); + w_as_register_register_newline (reg1,reg2); +} + +static void w_as_immediate_register_newline (__int64 i,int reg) +{ + if (!intel_asm){ + w_as_immediate (i); + w_as_comma_register (reg); + } else { + w_as_register_comma (reg); + w_as_immediate (i); + } + w_as_newline(); +} + +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: +#ifdef LEA_ADDRESS + w_as_lea_descriptor ( + instruction->instruction_parameters[0].parameter_data.l, + instruction->instruction_parameters[0].parameter_offset, + instruction->instruction_parameters[1].parameter_data.reg.r + ); + return; +#else + w_as_opcode_movl(); + if (intel_asm) + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_descriptor ( + instruction->instruction_parameters[0].parameter_data.l, + instruction->instruction_parameters[0].parameter_offset + ); + break; +#endif + case P_IMMEDIATE: + w_as_opcode_movl(); + if (intel_asm) + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_immediate (instruction->instruction_parameters[0].parameter_data.imm); + break; + case P_INDIRECT: + w_as_opcode_move (size_flag); + if (intel_asm){ + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + if (size_flag!=SIZE_LONG) + fprintf (assembly_file,size_flag==SIZE_WORD ? "word ptr " : "byte ptr "); + } + w_as_indirect (instruction->instruction_parameters[0].parameter_offset, + instruction->instruction_parameters[0].parameter_data.reg.r); + break; + case P_INDEXED: + w_as_opcode_move (size_flag); + if (intel_asm){ + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + if (size_flag!=SIZE_LONG) + fprintf (assembly_file,size_flag==SIZE_WORD ? "word ptr " : "byte ptr "); + } + w_as_indexed (instruction->instruction_parameters[0].parameter_offset, + instruction->instruction_parameters[0].parameter_data.ir); + break; + case P_REGISTER: + w_as_opcode_movl(); + if (intel_asm) + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); + break; + case P_POST_INCREMENT: + w_as_opcode (intel_asm ? "pop" : "popl"); + w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); + return; + case P_LABEL: + w_as_opcode_movl(); + if (intel_asm){ + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + fprintf (assembly_file,"offset "); + } + 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); + break; + default: + internal_error_in_function ("w_as_move_instruction"); + return; + } + if (!intel_asm) + w_as_comma_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); + return; + case P_INDIRECT: + { + struct parameter parameter; + + parameter=instruction->instruction_parameters[0]; + + switch (parameter.parameter_type){ + case P_INDIRECT: + w_as_opcode_move (size_flag); + if (intel_asm){ + w_as_scratch_register_comma(); + if (size_flag!=SIZE_LONG) + fprintf (assembly_file,size_flag==SIZE_WORD ? "word ptr " : "byte ptr "); + } + w_as_indirect (parameter.parameter_offset,parameter.parameter_data.reg.r); + if (!intel_asm) + w_as_comma_scratch_register(); + w_as_newline(); + + parameter.parameter_type=P_REGISTER; + parameter.parameter_data.reg.r=REGISTER_O0; + break; + case P_INDEXED: + w_as_opcode_move (size_flag); + if (intel_asm){ + w_as_scratch_register_comma(); + if (size_flag!=SIZE_LONG) + fprintf (assembly_file,size_flag==SIZE_WORD ? "word ptr " : "byte ptr "); + } + w_as_indexed (parameter.parameter_offset,parameter.parameter_data.ir); + if (!intel_asm) + w_as_comma_scratch_register(); + w_as_newline(); + + parameter.parameter_type=P_REGISTER; + parameter.parameter_data.reg.r=REGISTER_O0; + break; + case P_DESCRIPTOR_NUMBER: +#ifdef LEA_ADDRESS + w_as_lea_descriptor (parameter.parameter_data.l,parameter.parameter_offset,REGISTER_O0); + + w_as_opcode_movl(); + if (intel_asm){ + w_as_indirect (instruction->instruction_parameters[1].parameter_offset, + instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_comma(); + } + w_as_scratch_register(); +#else + w_as_opcode_movl(); + if (intel_asm){ + fprintf (assembly_file,size_flag==SIZE_LONG ? "qword ptr " : size_flag==SIZE_WORD ? "word ptr " : "byte ptr "); + w_as_indirect (instruction->instruction_parameters[1].parameter_offset, + instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_comma(); + } + w_as_descriptor (parameter.parameter_data.l,parameter.parameter_offset); +#endif + if (!intel_asm){ + w_as_comma(); + w_as_indirect (instruction->instruction_parameters[1].parameter_offset, + instruction->instruction_parameters[1].parameter_data.reg.r); + } + w_as_newline(); + return; + case P_IMMEDIATE: + if ((int)parameter.parameter_data.imm!=parameter.parameter_data.imm){ + w_as_opcode_movl(); + if (intel_asm) + w_as_scratch_register_comma(); + w_as_immediate (parameter.parameter_data.imm); + if (!intel_asm) + w_as_comma_scratch_register(); + w_as_newline(); + + parameter.parameter_type=P_REGISTER; + parameter.parameter_data.reg.r=REGISTER_O0; + } + break; + case P_REGISTER: + break; + case P_POST_INCREMENT: + w_as_opcode (intel_asm ? "pop" : "popl"); + w_as_indirect (instruction->instruction_parameters[1].parameter_offset, + instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); + return; + default: + internal_error_in_function ("w_as_move"); + } + + if (size_flag==SIZE_BYTE && parameter.parameter_type==P_REGISTER && parameter.parameter_data.reg.r<REGISTER_A1){ + int reg,reg1; + + reg=parameter.parameter_data.reg.r; + + w_as_opcode_register_register_newline ("xchg",reg,REGISTER_D0); + + reg1=instruction->instruction_parameters[1].parameter_data.reg.r; + if (reg1==reg) + reg1=REGISTER_D0; + else if (reg1==REGISTER_D0) + reg1=reg; + + w_as_opcode (intel_asm ? "mov" : "movb"); + if (!intel_asm) + w_as_register_comma (REGISTER_D0); + w_as_indirect (instruction->instruction_parameters[1].parameter_offset,reg1); + if (intel_asm){ + if (parameter.parameter_type!=P_REGISTER) + internal_error_in_function ("w_as_move_instruction"); + w_as_comma_byte_register (REGISTER_D0); + } + w_as_newline(); + + w_as_opcode_register_register_newline ("xchg",reg,REGISTER_D0); + + return; + } + + w_as_opcode (intel_asm ? "mov" : (size_flag==SIZE_LONG ? "movl" : size_flag==SIZE_WORD ? "movw" : "movb")); + if (!intel_asm) + w_as_parameter_comma (¶meter); + else if (parameter.parameter_type==P_IMMEDIATE) + fprintf (assembly_file,size_flag==SIZE_LONG ? "qword ptr " : size_flag==SIZE_WORD ? "word ptr " : "byte ptr "); + w_as_indirect (instruction->instruction_parameters[1].parameter_offset, + instruction->instruction_parameters[1].parameter_data.reg.r); + if (intel_asm){ + if (size_flag==SIZE_LONG || parameter.parameter_type==P_IMMEDIATE) + w_as_comma_parameter (¶meter); + else if (size_flag==SIZE_WORD) + w_as_comma_word_parameter (¶meter); + else { + if (parameter.parameter_type!=P_REGISTER) + internal_error_in_function ("w_as_move_instruction"); + w_as_comma_byte_register (parameter.parameter_data.reg.r); + } + } + w_as_newline(); + return; + } + case P_PRE_DECREMENT: + if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE && + (int)instruction->instruction_parameters[0].parameter_data.imm!=instruction->instruction_parameters[0].parameter_data.imm) + { + w_as_opcode_movl(); + if (intel_asm) + w_as_scratch_register_comma(); + w_as_immediate (instruction->instruction_parameters[0].parameter_data.imm); + if (!intel_asm) + w_as_comma_scratch_register(); + w_as_newline(); + + w_as_opcode (intel_asm ? "push" : "pushl"); + w_as_scratch_register(); + w_as_newline(); + } else { + w_as_opcode (intel_asm ? "push" : "pushl"); + if (instruction->instruction_parameters[0].parameter_type==P_DESCRIPTOR_NUMBER) + w_as_descriptor (instruction->instruction_parameters[0].parameter_data.l,instruction->instruction_parameters[0].parameter_offset); + else + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); + } + return; + case P_INDEXED: + { + struct parameter parameter; + + parameter=instruction->instruction_parameters[0]; + + switch (parameter.parameter_type){ + case P_INDIRECT: + w_as_opcode_move (size_flag); + if (intel_asm){ + w_as_scratch_register_comma(); + if (size_flag!=SIZE_LONG) + fprintf (assembly_file,size_flag==SIZE_WORD ? "word ptr " : "byte ptr "); + } + w_as_indirect (parameter.parameter_offset,parameter.parameter_data.reg.r); + if (!intel_asm) + w_as_comma_scratch_register(); + w_as_newline(); + + parameter.parameter_type=P_REGISTER; + parameter.parameter_data.reg.r=REGISTER_O0; + break; + case P_DESCRIPTOR_NUMBER: + w_as_opcode_movl(); + if (intel_asm){ + w_as_indexed (instruction->instruction_parameters[1].parameter_offset, + instruction->instruction_parameters[1].parameter_data.ir); + w_as_comma(); + } + w_as_descriptor (parameter.parameter_data.l,parameter.parameter_offset); + if (!intel_asm){ + w_as_comma(); + w_as_indexed (instruction->instruction_parameters[1].parameter_offset, + instruction->instruction_parameters[1].parameter_data.ir); + } + w_as_newline(); + return; + case P_IMMEDIATE: + if ((int)parameter.parameter_data.imm!=parameter.parameter_data.imm){ + w_as_opcode_movl(); + if (intel_asm) + w_as_scratch_register_comma(); + w_as_immediate (parameter.parameter_data.imm); + if (!intel_asm) + w_as_comma_scratch_register(); + w_as_newline(); + + parameter.parameter_type=P_REGISTER; + parameter.parameter_data.reg.r=REGISTER_O0; + } + break; + case P_REGISTER: + break; + case P_POST_INCREMENT: + w_as_opcode (intel_asm ? "pop" : "popl"); + 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"); + } + + if (size_flag==SIZE_BYTE && parameter.parameter_type==P_REGISTER && parameter.parameter_data.reg.r<REGISTER_A1){ + int reg,reg1,reg2; + struct index_registers index_registers; + + reg=parameter.parameter_data.reg.r; + + w_as_opcode_register_register_newline ("xchg",reg,REGISTER_D0); + + reg1=instruction->instruction_parameters[1].parameter_data.ir->a_reg.r; + reg2=instruction->instruction_parameters[1].parameter_data.ir->d_reg.r; + + if (reg1==reg) + reg1=REGISTER_D0; + else if (reg1==REGISTER_D0) + reg1=reg; + + if (reg2==reg) + reg2=REGISTER_D0; + else if (reg2==REGISTER_D0) + reg2=reg; + + index_registers.a_reg.r=reg1; + index_registers.d_reg.r=reg2; + + w_as_opcode (intel_asm ? "mov" : "movb"); + if (!intel_asm) + w_as_register_comma (REGISTER_D0); + w_as_indexed (instruction->instruction_parameters[1].parameter_offset,&index_registers); + if (intel_asm){ + if (parameter.parameter_type!=P_REGISTER) + internal_error_in_function ("w_as_move_instruction"); + w_as_comma_byte_register (REGISTER_D0); + } + w_as_newline(); + + w_as_opcode_register_register_newline ("xchg",reg,REGISTER_D0); + + return; + } + + w_as_opcode (intel_asm ? "mov" : (size_flag==SIZE_LONG ? "movl" : size_flag==SIZE_WORD ? "movw" : "movb")); + if (!intel_asm) + w_as_parameter_comma (¶meter); + else if (parameter.parameter_type==P_IMMEDIATE) + fprintf (assembly_file,size_flag==SIZE_LONG ? "qword ptr " : size_flag==SIZE_WORD ? "word ptr " : "byte ptr "); + w_as_indexed (instruction->instruction_parameters[1].parameter_offset, + instruction->instruction_parameters[1].parameter_data.ir); + if (intel_asm){ + if (size_flag==SIZE_LONG || parameter.parameter_type==P_IMMEDIATE) + w_as_comma_parameter (¶meter); + else if (size_flag==SIZE_WORD) + w_as_comma_word_parameter (¶meter); + else { + if (parameter.parameter_type!=P_REGISTER) + internal_error_in_function ("w_as_move_instruction"); + w_as_comma_byte_register (parameter.parameter_data.reg.r); + } + } + w_as_newline(); + return; + } + case P_LABEL: + if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){ + w_as_opcode_movl(); + if (!intel_asm){ + w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r); + fprintf (assembly_file,"offset "); + } + if (instruction->instruction_parameters[1].parameter_data.l->label_number!=0) + w_as_local_label (instruction->instruction_parameters[1].parameter_data.l->label_number); + else + w_as_label (instruction->instruction_parameters[1].parameter_data.l->label_name); + if (intel_asm) + w_as_comma_register (instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_newline(); + return; + } + default: + internal_error_in_function ("w_as_move_instruction"); + } +} + +static void w_as_movesw_instruction (struct instruction *instruction) +{ + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){ + switch (instruction->instruction_parameters[0].parameter_type){ + case P_INDIRECT: + w_as_opcode ("movsxd"); + if (intel_asm){ + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + fprintf (assembly_file,"word ptr "); + } + w_as_indirect (instruction->instruction_parameters[0].parameter_offset, + instruction->instruction_parameters[0].parameter_data.reg.r); + break; + case P_INDEXED: + w_as_opcode ("movsxd"); + if (intel_asm){ + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + fprintf (assembly_file,"word ptr "); + } + w_as_indexed (instruction->instruction_parameters[0].parameter_offset, + instruction->instruction_parameters[0].parameter_data.ir); + break; + case P_REGISTER: + w_as_opcode ("movsxd"); + if (intel_asm) + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); + break; + default: + internal_error_in_function ("w_as_movesw_instruction"); + return; + } + if (!intel_asm) + w_as_comma_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); + return; + } + internal_error_in_function ("w_as_movesw_instruction"); +} + +static void w_as_lea_instruction (struct instruction *instruction) +{ + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){ + w_as_opcode (intel_asm ? "lea" : "leal"); + + if (intel_asm) + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_parameter (&instruction->instruction_parameters[0]); + if (instruction->instruction_parameters[0].parameter_type==P_LABEL + && instruction->instruction_parameters[0].parameter_offset!=0) + { + int offset; + + offset=instruction->instruction_parameters[0].parameter_offset; + fprintf (assembly_file,offset>=0 ? "+%d" : "%d",offset); + } + if (!intel_asm) + w_as_comma_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_dyadic_instruction (struct instruction *instruction,char *opcode) +{ + w_as_opcode (opcode); + if (intel_asm){ + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_parameter (&instruction->instruction_parameters[0]); + } else { + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_comma_register (instruction->instruction_parameters[1].parameter_data.reg.r); + } + w_as_newline(); +} + +static void w_as_monadic_instruction (struct instruction *instruction,char *opcode) +{ + w_as_opcode (opcode); + w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_newline(); +} + +static void w_as_shift_instruction (struct instruction *instruction,char *opcode) +{ + if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){ + w_as_opcode (opcode); + if (intel_asm) + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_immediate (instruction->instruction_parameters[0].parameter_data.i & 31); + if (!intel_asm) + w_as_comma_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); + } else if ( + instruction->instruction_parameters[0].parameter_type==P_REGISTER && + instruction->instruction_parameters[0].parameter_data.reg.r==REGISTER_A0 + ){ + w_as_opcode (opcode); + if (intel_asm) + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + fprintf (assembly_file,intel_asm ? "cl" : "%%cl"); + if (!intel_asm) + w_as_comma_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); + } else { + int r; + + w_as_movl_register_register_newline (REGISTER_A0,REGISTER_O0); + + w_as_opcode_movl(); + if (intel_asm) + w_as_register_comma (REGISTER_A0); + w_as_parameter (&instruction->instruction_parameters[0]); + if (!intel_asm) + w_as_comma_register (REGISTER_A0); + w_as_newline(); + + w_as_opcode (opcode); + if (!intel_asm) + fprintf (assembly_file,"%%cl,"); + r=instruction->instruction_parameters[1].parameter_data.reg.r; + if (r==REGISTER_A0) + w_as_scratch_register(); + else + w_as_register (r); + if (intel_asm) + fprintf (assembly_file,",cl"); + w_as_newline(); + + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_A0); + } +} + +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 && size_flag!=SIZE_LONG){ + w_as_opcode (intel_asm ? "movsx" : "movswl"); + + if (intel_asm) + w_as_scratch_register_comma(); + w_as_parameter (¶meter_1); + if (!intel_asm) + w_as_comma_scratch_register(); + w_as_newline(); + + parameter_1.parameter_type=P_REGISTER; + parameter_1.parameter_data.reg.r=REGISTER_O0; + } + + switch (parameter_0.parameter_type){ + case P_DESCRIPTOR_NUMBER: + w_as_lea_descriptor (parameter_0.parameter_data.l,parameter_0.parameter_offset,REGISTER_O0); + + w_as_opcode (intel_asm ? "cmp" : "cmpl"); + if (intel_asm) + w_as_parameter_comma (¶meter_1); + w_as_scratch_register(); + if (!intel_asm) + w_as_comma_parameter (¶meter_1); + w_as_newline(); + return; + case P_INDIRECT: + if (size_flag==SIZE_WORD){ + w_as_opcode (intel_asm ? "movsx" : "movswl"); + if (intel_asm) + w_as_scratch_register_comma(); + w_as_parameter (¶meter_0); + if (!intel_asm) + w_as_comma_scratch_register(); + w_as_newline(); + + parameter_0.parameter_type=P_REGISTER; + parameter_0.parameter_data.reg.r=REGISTER_O0; + } + } + + w_as_opcode (intel_asm ? "cmp" : "cmpl"); + if (intel_asm){ + if (parameter_0.parameter_type==P_IMMEDIATE && parameter_1.parameter_type!=P_REGISTER) + fprintf (assembly_file,"qword ptr "); + w_as_parameter_comma (¶meter_1); + } + w_as_parameter (¶meter_0); + if (!intel_asm) + w_as_comma_parameter (¶meter_1); + w_as_newline(); +} + +static void w_as_tst_instruction (struct instruction *instruction,int size_flag) +{ + switch (instruction->instruction_parameters[0].parameter_type){ + case P_INDIRECT: + w_as_opcode (intel_asm ? "cmp" : (size_flag==SIZE_LONG ? "cmpl" : "cmpb")); + if (intel_asm){ + fprintf (assembly_file,size_flag==SIZE_LONG ? "qword ptr " : "byte ptr "); + w_as_indirect (instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_comma(); + } + w_as_immediate (0); + if (!intel_asm){ + w_as_comma(); + w_as_indirect (instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.reg.r); + } + w_as_newline(); + break; + case P_INDEXED: + w_as_opcode (intel_asm ? "cmp" : (size_flag==SIZE_LONG ? "cmpl" : "cmpb")); + if (intel_asm){ + w_as_indexed (instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.ir); + w_as_comma(); + } + w_as_immediate (0); + if (!intel_asm){ + w_as_comma(); + w_as_indexed (instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.ir); + } + w_as_newline(); + break; + case P_REGISTER: + w_as_opcode (intel_asm ? "test" : "testl"); + w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_comma_register (instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_newline(); + break; + default: + internal_error_in_function ("w_as_tst_instruction"); + } +} + +static void w_as_btst_instruction (struct instruction *instruction) +{ + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){ + w_as_opcode (intel_asm ? "test" : "testb"); + if (intel_asm) + w_as_byte_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); + if (!intel_asm) + w_as_comma_byte_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); + } else { + w_as_opcode (intel_asm ? "test" : "testb"); + if (intel_asm){ + fprintf (assembly_file,"byte ptr "); + w_as_indirect (instruction->instruction_parameters[1].parameter_offset,instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_comma(); + } + w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); + if (!intel_asm){ + w_as_comma(); + w_as_indirect (instruction->instruction_parameters[1].parameter_offset,instruction->instruction_parameters[1].parameter_data.reg.r); + } + w_as_newline(); + } +} + +void w_as_jmp_instruction (struct instruction *instruction) +{ + w_as_call_or_jump (&instruction->instruction_parameters[0],"jmp"); +} + +void w_as_jmpp_instruction (struct instruction *instruction) +{ + struct parameter *parameter_p; + + parameter_p=&instruction->instruction_parameters[0]; + + switch (parameter_p->parameter_type){ + case P_LABEL: + { + int offset; + + offset=parameter_p->parameter_offset; + + if (offset==0){ + w_as_opcode ("call"); + w_as_label ("profile_t"); + w_as_newline(); + } + + w_as_opcode ("jmp"); + if (parameter_p->parameter_data.l->label_number!=0) + w_as_local_label (parameter_p->parameter_data.l->label_number); + else + w_as_label (parameter_p->parameter_data.l->label_name); + + if (offset!=0) + fprintf (assembly_file,"+%d",offset); + + break; + } + case P_INDIRECT: + case P_REGISTER: + w_as_opcode ("call"); + w_as_label ("profile_t"); + w_as_newline(); + + w_as_call_or_jump (&instruction->instruction_parameters[0],"jmp"); + return; + default: + internal_error_in_function ("w_as_jmpp_instruction"); + } + + w_as_newline(); +} + +static void w_as_branch_instruction (struct instruction *instruction,char *opcode) +{ + w_as_opcode (opcode); + w_as_branch_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); +} + +static void w_as_float_branch_instruction (struct instruction *instruction,int n) +{ + int label_number; + + switch (n){ + case 2: + w_as_opcode ("ja"); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); + return; + case 5: + w_as_opcode ("jae"); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); + return; + } + + label_number=next_label_id++; + + w_as_opcode ("jp"); + w_as_internal_label (label_number); + w_as_newline(); + + switch (n){ + case 0: + w_as_opcode ("je"); + break; + case 1: + w_as_opcode ("jb"); + break; + case 3: + w_as_opcode ("jne"); + break; + case 4: + w_as_opcode ("jbe"); + break; + } + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); + + w_as_define_internal_label (label_number); +} + +static void w_as_jsr_instruction (struct instruction *instruction) +{ + w_as_call_or_jump (&instruction->instruction_parameters[0],"call"); +} + +static void w_as_set_condition_instruction (struct instruction *instruction,char *opcode) +{ + int r; + + r=instruction->instruction_parameters[0].parameter_data.reg.r; + + w_as_opcode (opcode); + w_as_byte_register (r); + w_as_newline(); + + w_as_opcode (intel_asm ? "movzx" : "movzbl"); + if (intel_asm) + w_as_register_comma (r); + w_as_byte_register (r); + if (!intel_asm) + w_as_comma_register (r); + w_as_newline(); +} + +static void w_as_set_float_condition_instruction (struct instruction *instruction,int n) +{ + int r; + + r=instruction->instruction_parameters[0].parameter_data.reg.r; + + switch (n){ + case 2: + w_as_opcode ("seta"); + w_as_byte_register (r); + w_as_newline(); + break; + case 5: + w_as_opcode ("setae"); + w_as_byte_register (r); + w_as_newline(); + break; + default: + w_as_opcode ("setnp"); + fprintf (assembly_file,"bpl"); + w_as_newline(); + + switch (n){ + case 0: + w_as_opcode ("sete"); + break; + case 1: + w_as_opcode ("setb"); + break; + case 3: + w_as_opcode ("setne"); + break; + case 4: + w_as_opcode ("setbe"); + break; + } + w_as_byte_register (r); + w_as_newline(); + + w_as_opcode ("and"); + w_as_byte_register (r); + w_as_comma(); + fprintf (assembly_file,"bpl"); + w_as_newline(); + } + + w_as_opcode ("movzx"); + w_as_register_comma (r); + w_as_byte_register (r); + w_as_newline(); +} + +static void w_as_div_rem_i_instruction (struct instruction *instruction,int compute_remainder) +{ + int s_reg1,s_reg2,s_reg3,i,sd_reg,i_reg,tmp_reg,abs_i; + struct ms ms; + + if (instruction->instruction_parameters[0].parameter_type!=P_IMMEDIATE) + internal_error_in_function ("w_as_div_rem_i_instruction"); + + i=instruction->instruction_parameters[0].parameter_data.i; + + if (! ((i>1 || (i<-1 && i!=0x80000000)))) + internal_error_in_function ("w_as_div_rem_i_instruction"); + + abs_i=abs (i); + + if (compute_remainder) + i=abs_i; + + ms=magic (abs_i); + + sd_reg=instruction->instruction_parameters[1].parameter_data.reg.r; + tmp_reg=instruction->instruction_parameters[2].parameter_data.reg.r; + + if (sd_reg==tmp_reg) + internal_error_in_function ("w_as_div_rem_i_instruction"); + + if (sd_reg==REGISTER_A1){ + if (tmp_reg!=REGISTER_D0) + w_as_movl_register_register_newline (REGISTER_D0,tmp_reg); + + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); + + s_reg1=sd_reg; + s_reg2=REGISTER_O0; + i_reg=REGISTER_D0; + } else if (sd_reg==REGISTER_D0){ + if (tmp_reg!=REGISTER_A1) + w_as_movl_register_register_newline (REGISTER_A1,tmp_reg); + + w_as_movl_register_register_newline (REGISTER_D0,REGISTER_O0); + + s_reg1=REGISTER_A1; + s_reg2=REGISTER_O0; + i_reg=REGISTER_A1; + } else { + if (tmp_reg==REGISTER_D0) + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); + else if (tmp_reg==REGISTER_A1) + w_as_movl_register_register_newline (REGISTER_D0,REGISTER_O0); + else { + w_as_movl_register_register_newline (REGISTER_D0,REGISTER_O0); + w_as_movl_register_register_newline (REGISTER_A1,tmp_reg); + } + + s_reg1=sd_reg; + s_reg2=sd_reg; + i_reg=REGISTER_D0; + } + + w_as_opcode_movl(); + w_as_immediate_register_newline (ms.m,i_reg); + + w_as_opcode (intel_asm ? "imul" : "imull"); + w_as_register (s_reg1); + w_as_newline(); + + if (compute_remainder) + w_as_movl_register_register_newline (s_reg2,REGISTER_D0); + + if (ms.m<0) + w_as_opcode_register_register_newline ("add",s_reg2,REGISTER_A1); + + if (compute_remainder){ + if (s_reg2==sd_reg && s_reg2!=REGISTER_D0 && s_reg2!=REGISTER_A1){ + s_reg3=s_reg2; + s_reg2=REGISTER_D0; + } else + s_reg3=REGISTER_D0; + } + + w_as_opcode (i>=0 ? "shr" : "sar"); + w_as_immediate_register_newline (63,s_reg2); + + if (ms.s>0){ + w_as_opcode ("sar"); + w_as_immediate_register_newline (ms.s,REGISTER_A1); + } + + if (!compute_remainder){ + if (sd_reg==REGISTER_A1){ + if (i>=0) + w_as_opcode_register_register_newline ("add",s_reg2,REGISTER_A1); + else { + w_as_opcode_register_register_newline ("sub",REGISTER_A1,s_reg2); + w_as_movl_register_register_newline (s_reg2,sd_reg); + } + } else if (sd_reg==REGISTER_D0){ + struct index_registers index_registers; + + if (i>=0){ + index_registers.a_reg.r=REGISTER_A1; + index_registers.d_reg.r=s_reg2; + + w_as_opcode (intel_asm ? "lea" : "leal"); + if (intel_asm) + w_as_register_comma (sd_reg); + w_as_indexed (0,&index_registers); + if (!intel_asm) + w_as_comma_register (sd_reg); + w_as_newline(); + } else { + w_as_movl_register_register_newline (s_reg2,sd_reg); + w_as_opcode_register_register_newline ("sub",REGISTER_A1,sd_reg); + } + } else + w_as_opcode_register_register_newline (i>=0 ? "add" : "sub",REGISTER_A1,s_reg2); /* s_reg2==sd_reg */ + } else { + int i2; + + w_as_opcode_register_register_newline ("add",s_reg2,REGISTER_A1); + + i2=i & (i-1); + if ((i2 & (i2-1))==0){ + unsigned int n; + int n_shifts; + + n=i; + + n_shifts=0; + while (n>0){ + while ((n & 1)==0){ + n>>=1; + ++n_shifts; + } + + if (n_shifts>0){ + w_as_opcode ("shl"); + w_as_immediate_register_newline (n_shifts,REGISTER_A1); + } + + w_as_opcode_register_register_newline ("sub",REGISTER_A1,s_reg3); + + n>>=1; + n_shifts=1; + } + } else { + w_as_opcode (intel_asm ? "imul" : "imull"); + w_as_immediate_register_newline (i,REGISTER_A1); + + w_as_opcode_register_register_newline ("sub",REGISTER_A1,s_reg3); + } + + if (sd_reg!=s_reg3) + w_as_movl_register_register_newline (s_reg3,sd_reg); + } + + if (sd_reg==REGISTER_A1){ + if (tmp_reg!=REGISTER_D0) + w_as_movl_register_register_newline (tmp_reg,REGISTER_D0); + } else if (sd_reg==REGISTER_D0){ + if (tmp_reg!=REGISTER_A1) + w_as_movl_register_register_newline (tmp_reg,REGISTER_A1); + } else { + if (tmp_reg==REGISTER_D0) + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_A1); + else if (tmp_reg==REGISTER_A1) + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_D0); + else { + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_D0); + w_as_movl_register_register_newline (tmp_reg,REGISTER_A1); + } + } +} + +static void w_as_div_instruction (struct instruction *instruction) +{ + int d_reg; + + d_reg=instruction->instruction_parameters[1].parameter_data.reg.r; + + if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){ + int i,log2i; + + i=instruction->instruction_parameters[0].parameter_data.i; + + if ((i & (i-1))==0 && i>0){ + if (i==1) + return; + + log2i=0; + while (i>1){ + i=i>>1; + ++log2i; + } + + w_as_movl_register_register_newline (d_reg,REGISTER_O0); + + if (log2i==1){ + w_as_opcode ("sar"); + w_as_immediate_register_newline (63,REGISTER_O0); + + w_as_opcode_register_register_newline ("sub",REGISTER_O0,d_reg); + } else { + w_as_opcode ("sar"); + w_as_immediate_register_newline (63,d_reg); + + w_as_opcode ("and"); + w_as_immediate_register_newline ((1<<log2i)-1,d_reg); + + w_as_opcode_register_register_newline ("add",REGISTER_O0,d_reg); + } + + w_as_opcode ("sar"); + w_as_immediate_register_newline (log2i,d_reg); + + return; + } else { + internal_error_in_function ("w_as_div_instruction"); + return; + } + } + + switch (d_reg){ + case REGISTER_D0: + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); + + w_as_instruction_without_parameters ("cqo"); + + w_as_opcode (intel_asm ? "idiv" : "idivl"); + if (instruction->instruction_parameters[0].parameter_type==P_REGISTER + && instruction->instruction_parameters[0].parameter_data.reg.r==REGISTER_A1) + { + w_as_scratch_register(); + } else { + if (intel_asm) + fprintf (assembly_file,"qword ptr "); + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT + && instruction->instruction_parameters[0].parameter_data.reg.r==REGISTER_A1) + { + w_as_indirect (instruction->instruction_parameters[0].parameter_offset,REGISTER_O0); + } else + w_as_parameter (&instruction->instruction_parameters[0]); + } + w_as_newline(); + + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_A1); + break; + case REGISTER_A1: + w_as_movl_register_register_newline (REGISTER_D0,REGISTER_O0); + + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_D0); + + w_as_instruction_without_parameters ("cqo"); + + w_as_opcode (intel_asm ? "idiv" : "idivl"); + if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){ + int r; + + r=instruction->instruction_parameters[0].parameter_data.reg.r; + if (r==REGISTER_D0) + r=REGISTER_O0; + else if (r==REGISTER_A1) + r=REGISTER_D0; + + w_as_register (r); + } else { + if (intel_asm) + fprintf (assembly_file,"qword ptr "); + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT){ + int r; + + r=instruction->instruction_parameters[0].parameter_data.reg.r; + if (r==REGISTER_D0) + r=REGISTER_O0; + else if (r==REGISTER_A1) + r=REGISTER_D0; + + w_as_indirect (instruction->instruction_parameters[0].parameter_offset,r); + } else + w_as_parameter (&instruction->instruction_parameters[0]); + } + w_as_newline(); + + w_as_movl_register_register_newline (REGISTER_D0,REGISTER_A1); + + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_D0); + break; + default: + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); + + w_as_opcode_register_register_newline ("xchg",REGISTER_D0,d_reg); + + w_as_instruction_without_parameters ("cqo"); + + w_as_opcode (intel_asm ? "idiv" : "idivl"); + if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){ + int r; + + r=instruction->instruction_parameters[0].parameter_data.reg.r; + if (r==REGISTER_D0) + r=d_reg; + else if (r==REGISTER_A1) + r=REGISTER_O0; + else if (r==d_reg) + r=REGISTER_D0; + + w_as_register (r); + } else { + if (intel_asm) + fprintf (assembly_file,"qword ptr "); + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT){ + int r; + + r=instruction->instruction_parameters[0].parameter_data.reg.r; + if (r==REGISTER_D0) + r=d_reg; + else if (r==REGISTER_A1) + r=REGISTER_O0; + else if (r==d_reg) + r=REGISTER_D0; + + w_as_indirect (instruction->instruction_parameters[0].parameter_offset,r); + } else + w_as_parameter (&instruction->instruction_parameters[0]); + } + w_as_newline(); + + w_as_opcode_register_register_newline ("xchg",REGISTER_D0,d_reg); + + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_A1); + } +} + +static void w_as_rem_instruction (struct instruction *instruction) +{ + int d_reg; + + d_reg=instruction->instruction_parameters[1].parameter_data.reg.r; + + if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){ + int i,log2i; + + i=instruction->instruction_parameters[0].parameter_data.i; + + if (i<0 && i!=0x80000000) + i=-i; + + if (! ((i & (i-1))==0 && i>1)){ + internal_error_in_function ("w_as_rem_instruction"); + return; + } + + log2i=0; + while (i>1){ + i=i>>1; + ++log2i; + } + + w_as_movl_register_register_newline (d_reg,REGISTER_O0); + + if (log2i==1){ + w_as_opcode ("and"); + w_as_immediate_register_newline (1,d_reg); + + w_as_opcode ("sar"); + w_as_immediate_register_newline (63,REGISTER_O0); + + w_as_opcode_register_register_newline ("xor",REGISTER_O0,d_reg); + } else { + w_as_opcode ("sar"); + w_as_immediate_register_newline (63,REGISTER_O0); + + w_as_opcode ("and"); + w_as_immediate_register_newline ((1<<log2i)-1,REGISTER_O0); + + w_as_opcode_register_register_newline ("add",REGISTER_O0,d_reg); + + w_as_opcode ("and"); + w_as_immediate_register_newline ((1<<log2i)-1,d_reg); + } + + w_as_opcode_register_register_newline ("sub",REGISTER_O0,d_reg); + + return; + } + + switch (d_reg){ + case REGISTER_D0: + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); + + w_as_instruction_without_parameters ("cqo"); + + w_as_opcode ("idivl"); + if (instruction->instruction_parameters[0].parameter_type==P_REGISTER + && instruction->instruction_parameters[0].parameter_data.reg.r==REGISTER_A1) + { + w_as_scratch_register(); + } else { + if (intel_asm) + fprintf (assembly_file,"qword ptr "); + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT + && instruction->instruction_parameters[0].parameter_data.reg.r==REGISTER_A1) + { + w_as_indirect (instruction->instruction_parameters[0].parameter_offset,REGISTER_O0); + } else + w_as_parameter (&instruction->instruction_parameters[0]); + } + w_as_newline(); + + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_D0); + + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_A1); + + break; + case REGISTER_A1: + w_as_movl_register_register_newline (REGISTER_D0,REGISTER_O0); + + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_D0); + + w_as_instruction_without_parameters ("cqo"); + + w_as_opcode ("idivl"); + if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){ + int r; + + r=instruction->instruction_parameters[0].parameter_data.reg.r; + if (r==REGISTER_D0) + r=REGISTER_O0; + else if (r==REGISTER_A1) + r=REGISTER_D0; + + w_as_register (r); + } else { + if (intel_asm) + fprintf (assembly_file,"qword ptr "); + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT){ + int r; + + r=instruction->instruction_parameters[0].parameter_data.reg.r; + if (r==REGISTER_D0) + r=REGISTER_O0; + else if (r==REGISTER_A1) + r=REGISTER_D0; + + w_as_indirect (instruction->instruction_parameters[0].parameter_offset,r); + } else + w_as_parameter (&instruction->instruction_parameters[0]); + } + w_as_newline(); + + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_D0); + break; + default: + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); + + w_as_opcode_register_register_newline ("xchg",REGISTER_D0,d_reg); + + w_as_instruction_without_parameters ("cqo"); + + w_as_opcode (intel_asm ? "idiv" : "idivl"); + if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){ + int r; + + r=instruction->instruction_parameters[0].parameter_data.reg.r; + if (r==REGISTER_D0) + r=d_reg; + else if (r==REGISTER_A1) + r=REGISTER_O0; + else if (r==d_reg) + r=REGISTER_D0; + + w_as_register (r); + } else { + if (intel_asm) + fprintf (assembly_file,"qword ptr "); + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT){ + int r; + + r=instruction->instruction_parameters[0].parameter_data.reg.r; + if (r==REGISTER_D0) + r=d_reg; + else if (r==REGISTER_A1) + r=REGISTER_O0; + else if (r==d_reg) + r=REGISTER_D0; + + w_as_indirect (instruction->instruction_parameters[0].parameter_offset,r); + } else + w_as_parameter (&instruction->instruction_parameters[0]); + } + w_as_newline(); + + w_as_movl_register_register_newline (d_reg,REGISTER_D0); + + w_as_movl_register_register_newline (REGISTER_A1,d_reg); + + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_A1); + } +} + +static void w_as_2movl_registers (int reg1,int reg2,int reg3) +{ + w_as_movl_register_register_newline (reg2,reg3); + w_as_movl_register_register_newline (reg1,reg2); +} + +static void w_as_3movl_registers (int reg1,int reg2,int reg3,int reg4) +{ + w_as_movl_register_register_newline (reg3,reg4); + w_as_movl_register_register_newline (reg2,reg3); + w_as_movl_register_register_newline (reg1,reg2); +} + +static void w_as_mulud_instruction (struct instruction *instruction) +{ + int reg_1,reg_2; + + reg_1=instruction->instruction_parameters[0].parameter_data.reg.r; + reg_2=instruction->instruction_parameters[1].parameter_data.reg.r; + + if (reg_2==REGISTER_D0){ + if (reg_1==REGISTER_A1){ + w_as_opcode_register_newline ("mul",reg_1); + } else { + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("mul",reg_1); + w_as_2movl_registers (REGISTER_O0,REGISTER_A1,reg_1); + } + } else if (reg_1==REGISTER_A1){ + w_as_2movl_registers (reg_2,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("mul",reg_1); + w_as_2movl_registers (REGISTER_O0,REGISTER_D0,reg_2); + } else if (reg_1==REGISTER_D0){ + if (reg_2==REGISTER_A1){ + w_as_opcode_register_newline ("mul",REGISTER_A1); + w_as_opcode_register_register_newline ("xchg",REGISTER_A1,REGISTER_D0); + } else { + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("mul",reg_2); + w_as_3movl_registers (REGISTER_O0,REGISTER_A1,REGISTER_D0,reg_2); + } + } else if (reg_2==REGISTER_A1){ + w_as_2movl_registers (reg_2,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("mul",reg_1); + w_as_3movl_registers (REGISTER_O0,REGISTER_D0,REGISTER_A1,reg_1); + } else { + w_as_opcode_register_register_newline ("xchg",reg_2,REGISTER_D0); + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("mul",reg_1); + w_as_opcode_register_register_newline ("xchg",reg_2,REGISTER_D0); + w_as_2movl_registers (REGISTER_O0,REGISTER_A1,reg_1); + } +} + +static void w_as_divdu_instruction (struct instruction *instruction) +{ + int reg_1,reg_2,reg_3; + + reg_1=instruction->instruction_parameters[0].parameter_data.reg.r; + reg_2=instruction->instruction_parameters[1].parameter_data.reg.r; + reg_3=instruction->instruction_parameters[2].parameter_data.reg.r; + + if (reg_1==REGISTER_D0){ + if (reg_3==REGISTER_D0){ + if (reg_2==REGISTER_A1) + w_as_opcode_register_newline ("div",reg_1); + else { + w_as_2movl_registers (reg_2,REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_1); + w_as_2movl_registers (REGISTER_O0,REGISTER_A1,reg_2); + } + } else if (reg_3==REGISTER_A1){ + if (reg_2==REGISTER_D0){ + w_as_opcode_register_register_newline ("xchg",REGISTER_A1,REGISTER_D0); + w_as_opcode_register_newline ("div",REGISTER_A1); + w_as_opcode_register_register_newline ("xchg",REGISTER_A1,REGISTER_D0); + } else { + w_as_3movl_registers (reg_2,REGISTER_A1,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("div",REGISTER_O0); + w_as_3movl_registers (REGISTER_O0,REGISTER_D0,REGISTER_A1,reg_2); + } + } else { + if (reg_2==REGISTER_A1){ + w_as_2movl_registers (reg_3,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("div",REGISTER_O0); + w_as_2movl_registers (REGISTER_O0,REGISTER_D0,reg_3); + } else if (reg_2==REGISTER_D0){ + w_as_3movl_registers (reg_3,REGISTER_D0,REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("div",REGISTER_A1); + w_as_3movl_registers (REGISTER_O0,REGISTER_A1,REGISTER_D0,reg_3); + } else { + w_as_opcode_register_register_newline ("xchg",reg_3,REGISTER_D0); + w_as_2movl_registers (reg_2,REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_3); + w_as_2movl_registers (REGISTER_O0,REGISTER_A1,reg_2); + w_as_opcode_register_register_newline ("xchg",reg_3,REGISTER_D0); + } + } + } else if (reg_1==REGISTER_A1){ + if (reg_2==REGISTER_A1){ + if (reg_3==REGISTER_D0) + w_as_opcode_register_newline ("div",reg_1); + else { + w_as_2movl_registers (reg_3,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_1); + w_as_2movl_registers (REGISTER_O0,REGISTER_D0,reg_3); + } + } else if (reg_2==REGISTER_D0){ + if (reg_3==REGISTER_A1){ + w_as_opcode_register_register_newline ("xchg",REGISTER_A1,REGISTER_D0); + w_as_opcode_register_newline ("div",REGISTER_D0); + w_as_opcode_register_register_newline ("xchg",REGISTER_A1,REGISTER_D0); + } else { + w_as_3movl_registers (reg_3,REGISTER_D0,REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("div",REGISTER_O0); + w_as_3movl_registers (REGISTER_O0,REGISTER_A1,REGISTER_D0,reg_3); + } + } else { + if (reg_3==REGISTER_D0){ + w_as_2movl_registers (reg_2,REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("div",REGISTER_O0); + w_as_2movl_registers (REGISTER_O0,REGISTER_A1,reg_2); + } else if (reg_3==REGISTER_A1){ + w_as_3movl_registers (reg_2,REGISTER_A1,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("div",REGISTER_D0); + w_as_3movl_registers (REGISTER_O0,REGISTER_D0,REGISTER_A1,reg_2); + } else { + w_as_opcode_register_register_newline ("xchg",reg_2,REGISTER_A1); + w_as_2movl_registers (reg_3,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_2); + w_as_2movl_registers (REGISTER_O0,REGISTER_D0,reg_3); + w_as_opcode_register_register_newline ("xchg",reg_2,REGISTER_A1); + } + } + } else { + if (reg_3==REGISTER_D0){ + if (reg_2==REGISTER_A1){ + w_as_opcode_register_newline ("div",reg_1); + } else { + w_as_2movl_registers (reg_2,REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_1); + w_as_2movl_registers (REGISTER_O0,REGISTER_A1,reg_2); + } + } else if (reg_2==REGISTER_A1){ + w_as_2movl_registers (reg_3,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_1); + w_as_2movl_registers (REGISTER_O0,REGISTER_D0,reg_3); + } else if (reg_2==REGISTER_D0){ + if (reg_3==REGISTER_A1){ + w_as_opcode_register_register_newline ("xchg",REGISTER_A1,REGISTER_D0); + w_as_opcode_register_newline ("div",reg_1); + w_as_opcode_register_register_newline ("xchg",REGISTER_A1,REGISTER_D0); + } else { + w_as_3movl_registers (reg_3,REGISTER_D0,REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_1); + w_as_3movl_registers (REGISTER_O0,REGISTER_A1,REGISTER_D0,reg_3); + } + } else if (reg_2==REGISTER_A1){ + w_as_3movl_registers (reg_3,REGISTER_A1,REGISTER_D0,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_1); + w_as_3movl_registers (REGISTER_O0,REGISTER_D0,REGISTER_A1,reg_3); + } else { + w_as_opcode_register_register_newline ("xchg",reg_3,REGISTER_D0); + w_as_2movl_registers (reg_2,REGISTER_A1,REGISTER_O0); + w_as_opcode_register_newline ("div",reg_1); + w_as_2movl_registers (REGISTER_O0,REGISTER_A1,reg_2); + w_as_opcode_register_register_newline ("xchg",reg_3,REGISTER_D0); + } + } +} + +static void w_as_word_instruction (struct instruction *instruction) +{ + fprintf (assembly_file,"\t.byte\t%d\n", + (int)instruction->instruction_parameters[0].parameter_data.i); +} + +#ifdef DATA_IN_CODE_SECTION + struct float_constant { + DOUBLE * float_constant_r_p; + int float_constant_label_number; + struct float_constant * float_constant_next; + }; + + struct float_constant *first_float_constant,**float_constant_l; + + static void w_as_float_constant (int label_number,DOUBLE *r_p) + { + struct float_constant *new_float_constant; + + new_float_constant=allocate_memory_from_heap (sizeof (struct float_constant)); + + new_float_constant->float_constant_r_p=r_p; + new_float_constant->float_constant_label_number=label_number; + + *float_constant_l=new_float_constant; + float_constant_l=&new_float_constant->float_constant_next; + + new_float_constant->float_constant_next=NULL; + } + + static void write_float_constants() + { + struct float_constant *float_constant; + + float_constant=first_float_constant; + + if (float_constant!=NULL){ + w_as_align (3); + + for (; float_constant!=NULL; float_constant=float_constant->float_constant_next){ + w_as_define_internal_data_label (float_constant->float_constant_label_number); + + w_as_opcode (intel_asm ? "dq" : ".double"); + fprintf (assembly_file,intel_asm ? "%.20e" : "0r%.20e",*float_constant->float_constant_r_p); + w_as_newline(); + } + } + } +#else + static void w_as_float_constant (int label_number,DOUBLE *r_p) + { + w_as_to_data_section(); + + w_as_align (3); + + w_as_define_internal_data_label (label_number); + + w_as_opcode (intel_asm ? "dq" : ".double"); + fprintf (assembly_file,intel_asm ? "%.20e" : "0r%.20e",*r_p); + w_as_newline(); + + w_as_to_code_section(); + } +#endif + +static void w_as_opcode_parameter_newline (char *opcode,struct parameter *parameter_p) +{ + switch (parameter_p->parameter_type){ + case P_F_IMMEDIATE: + { + int label_number; + + label_number=next_label_id++; + + w_as_float_constant (label_number,parameter_p->parameter_data.r); + + fprintf (assembly_file,intel_asm ? "\t%s\tqword ptr i_%d" : "\t%sl\ti_%d",opcode,label_number); + w_as_newline(); + break; + } + case P_INDIRECT: + fprintf (assembly_file,intel_asm ? "\t%s\tqword ptr " : "\t%sl\t",opcode); + w_as_indirect (parameter_p->parameter_offset,parameter_p->parameter_data.reg.r); + w_as_newline(); + break; + case P_INDEXED: + fprintf (assembly_file,intel_asm ? "\t%s\tqword ptr " : "\t%sl\t",opcode); + w_as_indexed (parameter_p->parameter_offset,parameter_p->parameter_data.ir); + w_as_newline(); + break; + case P_F_REGISTER: + w_as_opcode (opcode); + if (intel_asm) + fprintf (assembly_file,"st,"); + w_as_fp_register_newline (parameter_p->parameter_data.reg.r); + break; + default: + internal_error_in_function ("w_as_opcode_parameter_newline"); + return; + } +} + +static void w_as_dyadic_float_instruction (struct instruction *instruction,char *opcode) +{ + int d_freg; + + d_freg=instruction->instruction_parameters[1].parameter_data.reg.r; + + switch (instruction->instruction_parameters[0].parameter_type){ + case P_F_IMMEDIATE: + { + int label_number; + + label_number=next_label_id++; + + w_as_float_constant (label_number,instruction->instruction_parameters[0].parameter_data.r); + + w_as_opcode (opcode); + w_as_fp_register (d_freg); + w_as_comma(); + fprintf (assembly_file,"qword ptr i_%d",label_number); + break; + } + case P_INDIRECT: + w_as_opcode (opcode); + w_as_fp_register (d_freg); + w_as_comma(); + w_as_indirect (instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.reg.r); + break; + case P_INDEXED: + w_as_opcode (opcode); + w_as_fp_register (d_freg); + w_as_comma(); + w_as_indexed (instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.ir); + break; + case P_F_REGISTER: + w_as_opcode (opcode); + w_as_fp_register (d_freg); + w_as_comma(); + w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r); + break; + default: + internal_error_in_function ("w_as_dyadic_float_instruction"); + return; + } + w_as_newline(); +} + +static int sign_real_mask_imported=0; + +static void w_as_float_neg_instruction (struct instruction *instruction) +{ + int d_freg; + + d_freg=instruction->instruction_parameters[1].parameter_data.reg.r; + + switch (instruction->instruction_parameters[0].parameter_type){ + case P_F_IMMEDIATE: + { + int label_number=next_label_id++; + + w_as_float_constant (label_number,instruction->instruction_parameters[0].parameter_data.r); + + w_as_opcode ("movlpd"); + w_as_fp_register (d_freg); + w_as_comma(); + fprintf (assembly_file,"qword ptr i_%d",label_number); + w_as_newline(); + break; + } + case P_INDIRECT: + w_as_opcode ("movlpd"); + w_as_fp_register (d_freg); + w_as_comma(); + fprintf (assembly_file,"qword ptr "); + w_as_indirect (instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_newline(); + break; + case P_INDEXED: + w_as_opcode ("movlpd"); + w_as_fp_register (d_freg); + w_as_comma(); + fprintf (assembly_file,"qword ptr "); + w_as_indexed (instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.ir); + w_as_newline(); + break; + case P_F_REGISTER: + if (instruction->instruction_parameters[0].parameter_data.reg.r!=d_freg){ + w_as_opcode ("movsd"); + w_as_fp_register (d_freg); + w_as_comma(); + w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_newline(); + } + break; + default: + internal_error_in_function ("w_as_float_neg_instruction"); + return; + } + + if (!sign_real_mask_imported){ + w_as_opcode ("extrn"); + fprintf (assembly_file,"sign_real_mask:near"); + w_as_newline(); + + sign_real_mask_imported=1; + } + + w_as_opcode ("xorpd"); + w_as_fp_register (d_freg); + w_as_comma(); + fprintf (assembly_file,"oword ptr sign_real_mask"); + w_as_newline(); +} + +static void 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: + w_as_opcode ("movsd"); + w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_comma(); + w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r); + break; + case P_INDIRECT: + w_as_opcode ("movlpd"); + w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_comma(); + if (intel_asm) + fprintf (assembly_file,"qword ptr "); + w_as_indirect (instruction->instruction_parameters[0].parameter_offset, + instruction->instruction_parameters[0].parameter_data.reg.r); + break; + case P_INDEXED: + w_as_opcode ("movlpd"); + w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_comma(); + if (intel_asm) + fprintf (assembly_file,"qword ptr "); + w_as_indexed (instruction->instruction_parameters[0].parameter_offset, + instruction->instruction_parameters[0].parameter_data.ir); + break; + case P_F_IMMEDIATE: + { + int label_number=next_label_id++; + + w_as_float_constant (label_number,instruction->instruction_parameters[0].parameter_data.r); + + w_as_opcode ("movlpd"); + w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_comma(); + if (intel_asm) + fprintf (assembly_file,"qword ptr "); + fprintf (assembly_file,"i_%d",label_number); + break; + } + default: + internal_error_in_function ("w_as_fmove_instruction"); + return; + } + w_as_newline(); + return; + case P_INDIRECT: + case P_INDEXED: + if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){ + int s_freg; + + s_freg=instruction->instruction_parameters[0].parameter_data.reg.r; + + w_as_opcode ("movsd"); + if (intel_asm) + fprintf (assembly_file,"qword ptr "); + if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT) + w_as_indirect (instruction->instruction_parameters[1].parameter_offset, + instruction->instruction_parameters[1].parameter_data.reg.r); + else + w_as_indexed (instruction->instruction_parameters[1].parameter_offset, + instruction->instruction_parameters[1].parameter_data.ir); + + w_as_comma(); + w_as_fp_register (s_freg); + w_as_newline(); + return; + } + } + internal_error_in_function ("w_as_fmove_instruction"); + return; +} + +static int int_to_real_scratch_imported=0; + +static void w_as_fmovel_instruction (struct instruction *instruction) +{ + if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER) + internal_error_in_function ("w_as_fmovel_instruction"); + else { + switch (instruction->instruction_parameters[0].parameter_type){ + case P_REGISTER: + w_as_opcode ("cvtsi2sd"); + w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_comma_register (instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_newline(); + break; + case P_INDIRECT: + w_as_opcode ("cvtsi2sd"); + 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(); + break; + case P_INDEXED: + w_as_opcode ("cvtsi2sd"); + 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(); + break; + case P_IMMEDIATE: + { + int label_number=next_label_id++; + + w_as_to_data_section(); + + w_as_align (2); + + w_as_define_internal_data_label (label_number); + + w_as_opcode (intel_asm ? "dd" : ".long"); + fprintf (assembly_file,"%d",instruction->instruction_parameters[0].parameter_data.i); + w_as_newline(); + + w_as_to_code_section(); + + w_as_opcode ("cvtsi2sd"); + w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_comma(); + fprintf (assembly_file,"qword ptr i_%d",label_number); + w_as_newline(); + break; + } + default: + internal_error_in_function ("w_as_fmovel_instruction"); + } + } +} + +static void w_as_rtsi_instruction (struct instruction *instruction) +{ + w_as_opcode ("ret"); + w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); + w_as_newline(); +} + +static void w_as_rtsp_instruction (void) +{ + w_as_opcode ("jmp"); + w_as_label ("profile_r"); + 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_dyadic_instruction (instruction,intel_asm ? "add" : "addl"); + break; + case ISUB: + w_as_dyadic_instruction (instruction,intel_asm ? "sub" : "subl"); + break; + case ICMP: + w_as_cmp_instruction (instruction,SIZE_LONG); + break; + case IJMP: + w_as_jmp_instruction (instruction); + break; + case IJMPP: + w_as_jmpp_instruction (instruction); + break; + case IJSR: + w_as_jsr_instruction (instruction); + break; + case IRTS: + w_as_instruction_without_parameters ("ret"); + break; + case IRTSP: + w_as_rtsp_instruction(); + break; + case IBEQ: + w_as_branch_instruction (instruction,"je"); + break; + case IBGE: + w_as_branch_instruction (instruction,"jge"); + break; + case IBGEU: + w_as_branch_instruction (instruction,"jae"); + break; + case IBGT: + w_as_branch_instruction (instruction,"jg"); + break; + case IBGTU: + w_as_branch_instruction (instruction,"ja"); + break; + case IBLE: + w_as_branch_instruction (instruction,"jle"); + break; + case IBLEU: + w_as_branch_instruction (instruction,"jbe"); + break; + case IBLT: + w_as_branch_instruction (instruction,"jl"); + break; + case IBLTU: + w_as_branch_instruction (instruction,"jb"); + break; + case IBNE: + w_as_branch_instruction (instruction,"jne"); + break; + case IBO: + w_as_branch_instruction (instruction,"jo"); + break; + case IBNO: + w_as_branch_instruction (instruction,"jno"); + break; + case ILSL: + w_as_shift_instruction (instruction,"shl"); + break; + case ILSR: + w_as_shift_instruction (instruction,"shr"); + break; + case IASR: + w_as_shift_instruction (instruction,"sar"); + break; + case IMUL: + w_as_dyadic_instruction (instruction,intel_asm ? "imul" : "imull"); + break; + case IDIV: + w_as_div_instruction (instruction); + break; + case IDIVI: + w_as_div_rem_i_instruction (instruction,0); + break; + case IMOD: + w_as_rem_instruction (instruction); + break; + case IREMI: + w_as_div_rem_i_instruction (instruction,1); + break; + case IAND: + w_as_dyadic_instruction (instruction,intel_asm ? "and" : "andl"); + break; + case IOR: + w_as_dyadic_instruction (instruction,intel_asm ? "or" : "orl"); + break; + case IEOR: + w_as_dyadic_instruction (instruction,intel_asm ? "xor" : "xorl"); + break; + case ISEQ: + w_as_set_condition_instruction (instruction,"sete"); + break; + case ISGE: + w_as_set_condition_instruction (instruction,"setge"); + break; + case ISGEU: + w_as_set_condition_instruction (instruction,"setae"); + break; + case ISGT: + w_as_set_condition_instruction (instruction,"setg"); + break; + case ISGTU: + w_as_set_condition_instruction (instruction,"seta"); + break; + case ISLE: + w_as_set_condition_instruction (instruction,"setle"); + break; + case ISLEU: + w_as_set_condition_instruction (instruction,"setbe"); + break; + case ISLT: + w_as_set_condition_instruction (instruction,"setl"); + break; + case ISLTU: + w_as_set_condition_instruction (instruction,"setb"); + break; + case ISNE: + w_as_set_condition_instruction (instruction,"setne"); + break; + case ISO: + w_as_set_condition_instruction (instruction,"seto"); + break; + case ISNO: + w_as_set_condition_instruction (instruction,"setno"); + break; + case ICMPW: + w_as_cmp_instruction (instruction,SIZE_WORD); + break; + case ITST: + w_as_tst_instruction (instruction,SIZE_LONG); + break; + case IBTST: + w_as_btst_instruction (instruction); + break; + case IMOVEW: + w_as_move_instruction (instruction,SIZE_WORD); + break; + case IMOVESW: + w_as_movesw_instruction (instruction); + break; + case IMOVEB: + w_as_move_instruction (instruction,SIZE_BYTE); + break; + case IEXG: + w_as_dyadic_instruction (instruction,"xchg"); + break; + case INEG: + w_as_monadic_instruction (instruction,intel_asm ? "neg" : "negl"); + break; + case INOT: + w_as_monadic_instruction (instruction,intel_asm ? "not" : "notl"); + break; + case IADC: + w_as_dyadic_instruction (instruction,"adc"); + break; + case ISBB: + w_as_dyadic_instruction (instruction,intel_asm ? "sbb" : "sbbl"); + break; + case IMULUD: + w_as_mulud_instruction (instruction); + break; + case IDIVDU: + w_as_divdu_instruction (instruction); + break; + case IFMOVE: + w_as_fmove_instruction (instruction); + break; + case IFADD: + w_as_dyadic_float_instruction (instruction,"addsd"); + break; + case IFSUB: + w_as_dyadic_float_instruction (instruction,"subsd"); + break; + case IFCMP: + w_as_dyadic_float_instruction (instruction,"comisd"); + break; + case IFDIV: + w_as_dyadic_float_instruction (instruction,"divsd"); + break; + case IFMUL: + w_as_dyadic_float_instruction (instruction,"mulsd"); + break; + case IFBEQ: + w_as_float_branch_instruction (instruction,0); + break; + case IFBGE: + w_as_float_branch_instruction (instruction,5); + break; + case IFBGT: + w_as_float_branch_instruction (instruction,2); + break; + case IFBLE: + w_as_float_branch_instruction (instruction,4); + break; + case IFBLT: + w_as_float_branch_instruction (instruction,1); + break; + case IFBNE: + w_as_float_branch_instruction (instruction,3); + break; + case IFMOVEL: + w_as_fmovel_instruction (instruction); + break; + case IFSQRT: + w_as_dyadic_float_instruction (instruction,"sqrtsd"); + break; + case IFNEG: + w_as_float_neg_instruction (instruction); + break; + case IFSEQ: + w_as_set_float_condition_instruction (instruction,0); + break; + case IFSGE: + w_as_set_float_condition_instruction (instruction,5); + break; + case IFSGT: + w_as_set_float_condition_instruction (instruction,2); + break; + case IFSLE: + w_as_set_float_condition_instruction (instruction,4); + break; + case IFSLT: + w_as_set_float_condition_instruction (instruction,1); + break; + case IFSNE: + w_as_set_float_condition_instruction (instruction,3); + break; + case IWORD: + w_as_word_instruction (instruction); + break; + case IRTSI: + w_as_rtsi_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 (intel_asm ? "dd" : ".long"); + 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 (struct basic_block *block) +{ + LONG n_cells; + int label_id_1,label_id_2; + struct call_and_jump *new_call_and_jump; + + n_cells=block->block_n_new_heap_cells; + + 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"); + return; + } + + 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; + + w_as_opcode (intel_asm ? "sub" : "subl"); + if (intel_asm) + w_as_register_comma (REGISTER_R15); + w_as_immediate (n_cells); + if (!intel_asm) + w_as_comma_register (REGISTER_R15); + w_as_newline(); + + w_as_opcode ("jl"); + + w_as_internal_label (label_id_1); + 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 ("jmp"); + w_as_internal_label (call_and_jump->cj_jump_id); + w_as_newline(); +} + +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) + w_as_define_code_label (labels->block_label_label); + else + w_as_define_local_label (labels->block_label_label->label_number); +} + +static void w_as_check_stack (struct basic_block *block) +{ + if (block->block_a_stack_check_size>0){ + if (block->block_a_stack_check_size<=32){ + w_as_opcode (intel_asm ? "cmp" : "cmpl"); + if (intel_asm) + w_as_register_comma (A_STACK_POINTER); + fprintf (assembly_file,end_a_stack_label->label_name); + if (!intel_asm) + w_as_comma_register (A_STACK_POINTER); + } else { + w_as_opcode (intel_asm ? "lea" : "leal"); + if (intel_asm) + w_as_scratch_register_comma(); + w_as_indirect (block->block_a_stack_check_size,A_STACK_POINTER); + if (!intel_asm) + w_as_comma_scratch_register(); + w_as_newline(); + + w_as_opcode (intel_asm ? "cmp" : "cmpl"); + if (intel_asm) + w_as_scratch_register_comma(); + fprintf (assembly_file,end_a_stack_label->label_name); + if (!intel_asm) + w_as_comma_scratch_register(); + } + w_as_newline(); + + w_as_opcode ("jae"); + w_as_label (stack_overflow_label->label_name); + w_as_newline(); + } + + if (block->block_b_stack_check_size>0){ + if (block->block_b_stack_check_size<=32){ + w_as_opcode (intel_asm ? "cmp" : "cmpl"); + if (intel_asm) + w_as_register_comma (B_STACK_POINTER); + fprintf (assembly_file,end_b_stack_label->label_name); + if (!intel_asm) + w_as_comma_register (B_STACK_POINTER); + } else { + w_as_opcode (intel_asm ? "lea" : "leal"); + if (intel_asm) + w_as_scratch_register_comma(); + w_as_indirect (block->block_b_stack_check_size,B_STACK_POINTER); + if (!intel_asm) + w_as_comma_scratch_register(); + w_as_newline(); + + w_as_opcode (intel_asm ? "cmp" : "cmpl"); + if (intel_asm) + w_as_scratch_register_comma(); + fprintf (assembly_file,end_b_stack_label->label_name); + if (!intel_asm) + w_as_comma_scratch_register(); + } + w_as_newline(); + + w_as_opcode ("jb"); + w_as_label (stack_overflow_label->label_name); + w_as_newline(); + } +} + +void initialize_write_assembly (FILE *ass_file) +{ + assembly_file=ass_file; + + in_data_section=0; + + first_call_and_jump=NULL; + int_to_real_scratch_imported=0; +} + +#ifndef GENERATIONAL_GC +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); + + w_as_align (2); + + 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_movl(); + w_as_immediate_label (eval_upd_labels[label_arity]->label_name); + w_as_comma(); + w_as_register (REGISTER_D0); + w_as_newline(); + + w_as_opcode_movl(); + w_as_immediate_label (label->label_ea_label->label_name); + w_as_comma(); + w_as_register (REGISTER_A4); + w_as_newline(); + + w_as_opcode ("jmp"); + w_as_register (REGISTER_D0); + w_as_newline(); + } else { + w_as_opcode_movl(); + w_as_immediate_label (label->label_ea_label->label_name); + w_as_comma(); + w_as_register (REGISTER_D0); + w_as_newline(); + + w_as_opcode ("jmp"); + w_as_register (REGISTER_D0); + w_as_newline(); + + w_as_space (5); + } + + if (label->label_arity<0 || parallel_flag || module_info_flag){ + LABEL *descriptor_label; + + descriptor_label=label->label_descriptor; + + if (descriptor_label->label_id<0) + descriptor_label->label_id=next_label_id++; + + w_as_label_in_code_section (descriptor_label->label_name); + } else + w_as_number_of_arguments (0); + } else + if (label->label_arity<0 || parallel_flag || module_info_flag){ + LABEL *descriptor_label; + + descriptor_label=label->label_descriptor; + + if (descriptor_label->label_id<0) + descriptor_label->label_id=next_label_id++; + + w_as_label_in_code_section (descriptor_label->label_name); + } + + w_as_number_of_arguments (label->label_arity); + + w_as_define_label_name (new_label_name); + + w_as_opcode ("jmp"); + w_as_label (label->label_name); + w_as_newline(); + + label->label_name=new_label_name; +} + +static void w_as_indirect_node_entry_jumps (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) + 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); +} +#endif + +extern LABEL *eval_fill_label,*eval_upd_labels[]; + +static void w_as_import_labels (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 ("extrn"); + fprintf (assembly_file,"%s:near",label->label_name); + w_as_newline(); + } + + w_as_import_labels (label_node->label_node_left); + w_as_import_labels (label_node->label_node_right); +} + +static void w_as_profile_call (struct basic_block *block) +{ + w_as_opcode_movl(); + if (intel_asm) + w_as_scratch_register_comma(); + w_as_descriptor (block->block_profile_function_label,0); + if (!intel_asm) + w_as_comma_scratch_register(); + w_as_newline(); + + w_as_opcode ("call"); + + if (block->block_n_node_arguments>-100) + w_as_label (block->block_profile==2 ? "profile_n2" : "profile_n"); + else { + switch (block->block_profile){ + case 2: w_as_label ("profile_s2"); break; + case 4: w_as_label ("profile_l"); break; + case 5: w_as_label ("profile_l2"); break; + default: w_as_label ("profile_s"); + } + } + w_as_newline(); +} + +#ifdef NEW_APPLY +extern LABEL *add_empty_node_labels[]; + +static void w_as_apply_update_entry (struct basic_block *block) +{ + if (block->block_profile) + w_as_profile_call (block); + + if (block->block_n_node_arguments==-200){ + w_as_opcode ("jmp"); + 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"); + w_as_instruction_without_parameters ("nop"); + w_as_instruction_without_parameters ("nop"); + } else { + 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 ("jmp"); + w_as_label (block->block_ea_label->label_name); + w_as_newline(); + } + + if (!block->block_profile){ + w_as_instruction_without_parameters ("nop"); + w_as_instruction_without_parameters ("nop"); + } +} +#endif + +void write_assembly (VOID) +{ + struct basic_block *block; + struct call_and_jump *call_and_jump; + + if (intel_asm) + w_as_import_labels (labels); + + w_as_to_code_section(); + +#ifdef DATA_IN_CODE_SECTION + float_constant_l=&first_float_constant; + first_float_constant=NULL; +#endif + +/* +#ifndef GENERATIONAL_GC + w_as_indirect_node_entry_jumps (labels); +#endif +*/ + + for_l (block,first_block,block_next){ + if (block->block_n_node_arguments>-100){ + w_as_align (2); + +#ifdef GENERATIONAL_GC + 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_movl(); + w_as_immediate_label (eval_upd_labels[n_node_arguments]->label_name); + fprintf (assembly_file,"_push"); + w_as_comma_register (REGISTER_D0); + w_as_newline(); + + w_as_opcode_movl(); + w_as_immediate_label (block->block_ea_label->label_name); + w_as_comma(); w_as_register (REGISTER_A4); w_as_newline(); + + w_as_opcode ("jmp"); + w_as_register (REGISTER_D0); + w_as_newline(); + } else { + w_as_opcode_movl(); + w_as_immediate_label (block->block_ea_label->label_name); + fprintf (assembly_file,"_push"); + w_as_comma(); w_as_register (REGISTER_D0); w_as_newline(); + + w_as_opcode ("jmp"); w_as_register (REGISTER_D0); w_as_newline(); + + w_as_space (5); + } + + if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_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); + w_as_opcode (intel_asm ? "push" : "pushl"); fprintf (assembly_file,intel_asm ? "offset push_updated_node" : "$push_updated_node"); w_as_newline(); + w_as_opcode ("jmp"); fprintf (assembly_file,".+23"); w_as_newline(); + w_as_space (1); +#endif /* GENERATIONAL_GC */ + + if (block->block_ea_label!=NULL){ + int n_node_arguments; + + 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){ + if (!block->block_profile){ + w_as_opcode ("lea"); + if (intel_asm) + w_as_register_comma (REGISTER_A4); + w_as_label (block->block_ea_label->label_name); + if (!intel_asm) + w_as_comma_register (REGISTER_A4); + w_as_newline(); + + w_as_opcode ("jmp"); + w_as_label (eval_upd_labels[n_node_arguments]->label_name); + w_as_newline(); + } else { + w_as_opcode_movl(); + if (intel_asm) + w_as_register_comma (REGISTER_A4); + w_as_descriptor (block->block_profile_function_label,0); + if (!intel_asm) + w_as_comma_register (REGISTER_A4); + w_as_newline(); + + w_as_opcode ("jmp"); + w_as_label (eval_upd_labels[n_node_arguments]->label_name); + fprintf (assembly_file,"-8"); + w_as_newline(); + + w_as_opcode ("lea"); + if (intel_asm) + w_as_register_comma (REGISTER_D0); + w_as_label (block->block_ea_label->label_name); + if (!intel_asm) + w_as_comma_register (REGISTER_D0); + w_as_newline(); + + w_as_opcode ("jmp"); + fprintf (assembly_file,".-19"); + 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 ("lea"); + if (intel_asm) + w_as_register_comma (REGISTER_D0); + w_as_label (block->block_ea_label->label_name); + if (!intel_asm) + w_as_comma_register (REGISTER_D0); + w_as_newline(); + + w_as_opcode ("jmp"); + w_as_register (REGISTER_D0); + w_as_newline(); + + w_as_space (3); + } + + if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)) + w_as_label_in_code_section (block->block_descriptor->label_name); + else + w_as_number_of_arguments (0); + } else + +#ifdef GENERATIONAL_GC + { + w_as_space (12); + + if (block->block_descriptor!=NULL) +#else + if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)) +#endif + w_as_label_in_code_section (block->block_descriptor->label_name); +#ifdef GENERATIONAL_GC + else + w_as_number_of_arguments (0); +#endif +#ifdef GENERATIONAL_GC + } +#endif + 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_profile) + w_as_profile_call (block); + + if (block->block_n_new_heap_cells>0) + w_as_garbage_collect_test (block); + + if (check_stack && (block->block_a_stack_check_size>0 || block->block_b_stack_check_size>0)) + 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); + +#ifdef DATA_IN_CODE_SECTION + write_float_constants(); +#endif + + if (intel_asm){ + w_as_opcode ("end"); + w_as_newline(); + } +} |