summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgaas.c6343
-rw-r--r--cgaas.h35
-rw-r--r--cgawas.c3550
-rw-r--r--cgawas.h25
4 files changed, 9953 insertions, 0 deletions
diff --git a/cgaas.c b/cgaas.c
new file mode 100644
index 0000000..631b27e
--- /dev/null
+++ b/cgaas.c
@@ -0,0 +1,6343 @@
+/*
+ File: cgaas.c
+ Author: John van Groningen
+ Machine: opteron athlon64
+*/
+
+#define RELOCATIONS_RELATIVE_TO_EXPORTED_DATA_LABEL
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef __MWERKS__
+# define I486
+#endif
+
+#define OPTIMISE_BRANCHES
+
+#ifdef LINUX_ELF
+# define ELF
+#endif
+
+#if defined (_WINDOWS_) || defined (ELF)
+# define FUNCTION_LEVEL_LINKING
+#endif
+
+#include "cgport.h"
+
+#ifdef __MWERKS__
+# undef G_POWER
+#endif
+
+#include "cgrconst.h"
+#include "cgtypes.h"
+#include "cg.h"
+#include "cgiconst.h"
+#include "cgcode.h"
+#include "cgaas.h"
+#include "cginstructions.h"
+
+#ifdef ELF
+# include <elf.h>
+# ifndef ELF32_ST_INFO
+# define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
+# endif
+# ifndef ELF32_R_INFO
+# define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t))
+# endif
+#endif
+
+#define for_l(v,l,n) for(v=(l);v!=NULL;v=v->n)
+
+#define U4(s,v1,v2,v3,v4) s->v1;s->v2;s->v3;s->v4
+#define U5(s,v1,v2,v3,v4,v5) s->v1;s->v2;s->v3;s->v4;s->v5
+
+#ifdef FUNCTION_LEVEL_LINKING
+# define TEXT_LABEL_ID (-2)
+# define DATA_LABEL_ID (-3)
+#else
+# ifdef ELF
+# define TEXT_LABEL_ID 1
+# define DATA_LABEL_ID 2
+# else
+# define TEXT_LABEL_ID 0
+# define DATA_LABEL_ID 2
+# endif
+#endif
+
+#define IO_BUFFER_SIZE 8192
+#define BUFFER_SIZE 4096
+
+#define CODE_CONTROL_SECTION 0
+#define DATA_CONTROL_SECTION 1
+#define IMPORTED_LABEL 2
+#define EXPORTED_CODE_LABEL 3
+#define EXPORTED_DATA_LABEL 4
+
+struct object_label {
+ struct object_label * next;
+ union {
+ unsigned long offset; /* CODE_CONTROL_SECTION,DATA_CONTROL_SECTION */
+ struct label * label; /* IMPORTED_LABEL,EXPORTED_CODE_LABEL */
+ } object_label_u1;
+ union {
+ unsigned long length; /* CODE_CONTROL_SECTION,DATA_CONTROL_SECTION */
+ unsigned long string_offset; /* IMPORTED_LABEL,EXPORTED_CODE_LABEL */
+ } object_label_u2;
+ int object_label_number;
+#ifdef FUNCTION_LEVEL_LINKING
+ int object_label_n_relocations; /* CODE_CONTROL_SECTION,DATA_CONTROL_SECTION */
+ short object_label_section_n; /* CODE_CONTROL_SECTION,DATA_CONTROL_SECTION */
+#endif
+ unsigned char object_label_kind;
+ unsigned char object_section_align; /* 2 for 4, 3 for 8, 4 for 16 */
+};
+
+#define object_label_offset object_label_u1.offset
+#define object_label_label object_label_u1.label
+
+#define object_label_length object_label_u2.length
+#define object_label_string_offset object_label_u2.string_offset
+
+static struct object_label *first_object_label,**last_object_label_l;
+
+struct object_buffer {
+ struct object_buffer *next;
+ int size;
+ unsigned char data [BUFFER_SIZE];
+};
+
+static struct object_buffer *first_code_buffer,*current_code_buffer;
+static int code_buffer_free,code_buffer_offset;
+static unsigned char *code_buffer_p;
+
+static struct object_buffer *first_data_buffer,*current_data_buffer;
+static int data_buffer_free,data_buffer_offset;
+static unsigned char *data_buffer_p;
+
+static void initialize_buffers (void)
+{
+ struct object_buffer *new_code_buffer,*new_data_buffer;
+
+ new_code_buffer=memory_allocate (sizeof (struct object_buffer));
+
+ new_code_buffer->size=0;
+ new_code_buffer->next=NULL;
+
+ first_code_buffer=new_code_buffer;
+ current_code_buffer=new_code_buffer;
+ code_buffer_offset=0;
+
+ code_buffer_free=BUFFER_SIZE;
+ code_buffer_p=(void*)new_code_buffer->data;
+
+ new_data_buffer=memory_allocate (sizeof (struct object_buffer));
+
+ new_data_buffer->size=0;
+ new_data_buffer->next=NULL;
+
+ first_data_buffer=new_data_buffer;
+ current_data_buffer=new_data_buffer;
+ data_buffer_offset=0;
+
+ data_buffer_free=BUFFER_SIZE;
+ data_buffer_p=new_data_buffer->data;
+}
+
+static FILE *output_file;
+
+static void write_c (int c)
+{
+ fputc (c,output_file);
+}
+
+static void write_w (int c)
+{
+ fputc (c,output_file);
+ fputc (c>>8,output_file);
+}
+
+static void write_l (int c)
+{
+ fputc (c,output_file);
+ fputc (c>>8,output_file);
+ fputc (c>>16,output_file);
+ fputc (c>>24,output_file);
+}
+
+#define LONG_WORD_RELOCATION 0
+#define CALL_RELOCATION 1
+#define BRANCH_RELOCATION 2
+#define JUMP_RELOCATION 3
+#define SHORT_BRANCH_RELOCATION 4
+#define SHORT_JUMP_RELOCATION 5
+#define NEW_SHORT_BRANCH_RELOCATION 6
+#define NEW_SHORT_JUMP_RELOCATION 7
+#define ALIGN_RELOCATION 8
+#define DUMMY_BRANCH_RELOCATION 9
+#define PC_RELATIVE_LONG_WORD_RELOCATION 10
+#define BRANCH_SKIP_BRANCH_RELOCATION 11
+
+struct relocation {
+ struct relocation * next;
+ unsigned long relocation_offset;
+ union {
+ struct {
+ WORD s_align1;
+ WORD s_align2;
+ } u_s;
+ struct label * u_label;
+ } relocation_u;
+#ifdef FUNCTION_LEVEL_LINKING
+ struct object_label * relocation_object_label;
+#endif
+ short relocation_kind;
+};
+
+#define relocation_label relocation_u.u_label
+#define relocation_align1 relocation_u.u_s.s_align1
+#define relocation_align2 relocation_u.u_s.s_align2
+
+static void write_buffers_and_release_memory (struct object_buffer **first_buffer_l)
+{
+ struct object_buffer *buffer,*next_buffer;
+
+ for (buffer=*first_buffer_l; buffer!=NULL; buffer=next_buffer){
+ int size;
+
+ size=buffer->size;
+
+ if (fwrite (buffer->data,1,size,output_file)!=size)
+ error ("Write error");
+
+ next_buffer=buffer->next;
+
+ memory_free (buffer);
+ }
+
+ *first_buffer_l=NULL;
+}
+
+static struct relocation *first_code_relocation,**last_code_relocation_l;
+static struct relocation *first_data_relocation,**last_data_relocation_l;
+static int n_code_relocations,n_data_relocations;
+
+static int n_object_labels;
+
+static unsigned long string_table_offset;
+
+static struct object_label *code_object_label,*data_object_label;
+#ifdef FUNCTION_LEVEL_LINKING
+static int n_code_sections,n_data_sections;
+#endif
+
+struct call_and_jump {
+ struct call_and_jump *cj_next;
+ struct label *cj_call_label;
+ struct label cj_label;
+ struct label cj_jump;
+};
+
+static struct call_and_jump *first_call_and_jump,*last_call_and_jump;
+
+void initialize_assembler (FILE *output_file_d)
+{
+ output_file=output_file_d;
+#ifdef ELF
+ n_object_labels=1;
+#else
+ n_object_labels=0;
+#endif
+ setvbuf (output_file,NULL,_IOFBF,IO_BUFFER_SIZE);
+
+ first_object_label=NULL;
+ last_object_label_l=&first_object_label;
+
+ first_code_relocation=NULL;
+ first_data_relocation=NULL;
+ last_code_relocation_l=&first_code_relocation;
+ last_data_relocation_l=&first_data_relocation;
+ n_code_relocations=0;
+ n_data_relocations=0;
+
+ first_call_and_jump=NULL;
+#ifdef ELF
+ string_table_offset=13;
+#else
+ string_table_offset=4;
+#endif
+ initialize_buffers();
+
+#ifdef FUNCTION_LEVEL_LINKING
+ code_object_label=NULL;
+ n_code_sections=0;
+
+ data_object_label=NULL;
+ n_data_sections=0;
+#else
+ code_object_label=fast_memory_allocate_type (struct object_label);
+# ifdef ELF
+ ++n_object_labels;
+# else
+ n_object_labels+=2;
+# endif
+ *last_object_label_l=code_object_label;
+ last_object_label_l=&code_object_label->next;
+ code_object_label->next=NULL;
+
+ code_object_label->object_label_offset=0;
+ code_object_label->object_label_length=0;
+ code_object_label->object_label_kind=CODE_CONTROL_SECTION;
+
+ data_object_label=fast_memory_allocate_type (struct object_label);
+# ifdef ELF
+ ++n_object_labels;
+# else
+ n_object_labels+=2;
+# endif
+ *last_object_label_l=data_object_label;
+ last_object_label_l=&data_object_label->next;
+ data_object_label->next=NULL;
+
+ data_object_label->object_label_offset=0;
+ data_object_label->object_label_length=0;
+ data_object_label->object_label_kind=DATA_CONTROL_SECTION;
+ data_object_label->object_section_align=2;
+#endif
+}
+
+static void store_c (int c)
+{
+ if (code_buffer_free>0){
+ --code_buffer_free;
+ *code_buffer_p++=c;
+ } else {
+ struct object_buffer *new_buffer;
+
+ current_code_buffer->size=BUFFER_SIZE;
+
+ new_buffer=memory_allocate (sizeof (struct object_buffer));
+
+ new_buffer->size=0;
+ new_buffer->next=NULL;
+
+ current_code_buffer->next=new_buffer;
+ current_code_buffer=new_buffer;
+ code_buffer_offset+=BUFFER_SIZE;
+
+ code_buffer_free=BUFFER_SIZE-1;
+ code_buffer_p=new_buffer->data;
+
+ *code_buffer_p++=c;
+ }
+}
+
+void store_long_word_in_data_section (ULONG c)
+{
+ if (data_buffer_free>=4){
+ data_buffer_free-=4;
+ *(ULONG*)data_buffer_p=c;
+ data_buffer_p+=4;
+ } else {
+ struct object_buffer *new_buffer;
+
+ current_data_buffer->size=BUFFER_SIZE;
+
+ new_buffer=memory_allocate (sizeof (struct object_buffer));
+
+ new_buffer->size=0;
+ new_buffer->next=NULL;
+
+ current_data_buffer->next=new_buffer;
+ current_data_buffer=new_buffer;
+ data_buffer_offset+=BUFFER_SIZE;
+
+ data_buffer_free=BUFFER_SIZE-4;
+ data_buffer_p=(void*)new_buffer->data;
+
+ *(ULONG*)data_buffer_p=c;
+ data_buffer_p+=4;
+ }
+}
+
+void store_word64_in_data_section (__int64 c)
+{
+ if (data_buffer_free>=8){
+ data_buffer_free-=8;
+ *(__int64*)data_buffer_p=c;
+ data_buffer_p+=8;
+ } else {
+ store_long_word_in_data_section ((ULONG)c);
+ store_long_word_in_data_section ((ULONG)(c>>32));
+ }
+}
+
+void store_2_words_in_data_section (UWORD w1,UWORD w2)
+{
+ store_long_word_in_data_section (((UWORD)w1) | (w2<<16));
+}
+
+static void flush_code_buffer (void)
+{
+ current_code_buffer->size=BUFFER_SIZE-code_buffer_free;
+ code_buffer_offset+=BUFFER_SIZE-code_buffer_free;
+}
+
+static void flush_data_buffer (void)
+{
+ current_data_buffer->size=BUFFER_SIZE-data_buffer_free;
+ data_buffer_offset+=BUFFER_SIZE-data_buffer_free;
+}
+
+void store_abc_string_in_data_section (char *string,int length)
+{
+ unsigned char *string_p;
+
+ string_p=(unsigned char*)string;
+ store_word64_in_data_section (length);
+
+ while (length>=8){
+ store_word64_in_data_section (*(__int64*)string_p);
+ string_p+=8;
+ length-=8;
+ }
+
+ if (length>0){
+ unsigned __int64 d;
+ int shift;
+
+ d=0;
+ shift=0;
+ while (length>0){
+ d |= (unsigned __int64)string_p[0]<<shift;
+ shift+=8;
+ --length;
+ ++string_p;
+ }
+ store_word64_in_data_section (d);
+ }
+}
+
+void store_abc_string4_in_data_section (char *string,int length)
+{
+ unsigned char *string_p;
+
+ string_p=(unsigned char*)string;
+ store_long_word_in_data_section (length);
+
+ while (length>=4){
+ store_long_word_in_data_section (*(ULONG*)string_p);
+ string_p+=4;
+ length-=4;
+ }
+
+ if (length>0){
+ ULONG d;
+ int shift;
+
+ d=0;
+ shift=0;
+ while (length>0){
+ d |= string_p[0]<<shift;
+ shift+=8;
+ --length;
+ ++string_p;
+ }
+ store_long_word_in_data_section (d);
+ }
+}
+
+void store_c_string_in_data_section (char *string,int length)
+{
+ unsigned char *string_p;
+ ULONG d;
+ int shift;
+
+ string_p=(unsigned char*)string;
+
+ while (length>=4){
+ store_long_word_in_data_section (*(ULONG*)string_p);
+ string_p+=4;
+ length-=4;
+ }
+
+ d=0;
+ shift=0;
+ while (length>0){
+ d |= string_p[0]<<shift;
+ shift+=8;
+ --length;
+ ++string_p;
+ }
+ store_long_word_in_data_section (d);
+}
+
+static void store_w (UWORD i)
+{
+ store_c (i);
+ store_c (i>>8);
+}
+
+static void store_l (register ULONG i)
+{
+ store_c (i);
+ store_c (i>>8);
+ store_c (i>>16);
+ store_c (i>>24);
+}
+
+#define CURRENT_CODE_OFFSET (code_buffer_offset+(code_buffer_p-current_code_buffer->data))
+#define CURRENT_DATA_OFFSET (data_buffer_offset+(data_buffer_p-current_data_buffer->data))
+
+#ifdef FUNCTION_LEVEL_LINKING
+void as_new_data_module (void)
+{
+ struct object_label *new_object_label;
+ unsigned long current_data_offset;
+ int data_section_label_number;
+
+ new_object_label=fast_memory_allocate_type (struct object_label);
+ data_object_label=new_object_label;
+
+# ifdef ELF
+ data_section_label_number=0;
+# else
+ data_section_label_number=n_object_labels;
+ n_object_labels+=2;
+# endif
+ current_data_offset=CURRENT_DATA_OFFSET;
+
+ *last_object_label_l=new_object_label;
+ last_object_label_l=&new_object_label->next;
+ new_object_label->next=NULL;
+
+ new_object_label->object_label_offset=current_data_offset;
+ new_object_label->object_label_number=data_section_label_number;
+ new_object_label->object_label_section_n=n_data_sections;
+ ++n_data_sections;
+ new_object_label->object_label_length=0;
+ new_object_label->object_label_kind=DATA_CONTROL_SECTION;
+ new_object_label->object_section_align=2;
+}
+
+static void as_new_code_module (void)
+{
+ struct object_label *new_object_label;
+ unsigned long current_code_offset;
+ int code_section_label_number;
+
+ new_object_label=fast_memory_allocate_type (struct object_label);
+ code_object_label=new_object_label;
+
+# ifdef ELF
+ code_section_label_number=0;
+# else
+ code_section_label_number=n_object_labels;
+ n_object_labels+=2;
+# endif
+ current_code_offset=CURRENT_CODE_OFFSET;
+
+ *last_object_label_l=new_object_label;
+ last_object_label_l=&new_object_label->next;
+ new_object_label->next=NULL;
+
+ new_object_label->object_label_offset=current_code_offset;
+ new_object_label->object_label_number=code_section_label_number;
+ new_object_label->object_label_section_n=n_code_sections;
+ ++n_code_sections;
+ new_object_label->object_label_length=0;
+ new_object_label->object_label_kind=CODE_CONTROL_SECTION;
+}
+#endif
+
+static void store_label_in_code_section (struct label *label)
+{
+ struct relocation *new_relocation;
+
+ new_relocation=fast_memory_allocate_type (struct relocation);
+ ++n_code_relocations;
+
+ *last_code_relocation_l=new_relocation;
+ last_code_relocation_l=&new_relocation->next;
+ new_relocation->next=NULL;
+
+ new_relocation->relocation_label=label;
+ new_relocation->relocation_offset=CURRENT_CODE_OFFSET-4;
+ new_relocation->relocation_kind=LONG_WORD_RELOCATION;
+}
+
+static void store_relative_label_offset_in_code_section (struct label *label)
+{
+ struct relocation *new_relocation;
+
+ new_relocation=fast_memory_allocate_type (struct relocation);
+ ++n_code_relocations;
+
+ *last_code_relocation_l=new_relocation;
+ last_code_relocation_l=&new_relocation->next;
+ new_relocation->next=NULL;
+
+ new_relocation->relocation_label=label;
+ new_relocation->relocation_offset=CURRENT_CODE_OFFSET-4;
+ new_relocation->relocation_kind=PC_RELATIVE_LONG_WORD_RELOCATION;
+}
+
+static void store_label_plus_offset_in_data_section (LABEL *label,int offset)
+{
+ struct relocation *new_relocation;
+
+ store_long_word_in_data_section (offset);
+
+ new_relocation=fast_memory_allocate_type (struct relocation);
+ ++n_data_relocations;
+
+ *last_data_relocation_l=new_relocation;
+ last_data_relocation_l=&new_relocation->next;
+ new_relocation->next=NULL;
+
+ new_relocation->relocation_label=label;
+ new_relocation->relocation_offset=CURRENT_DATA_OFFSET-4;
+ new_relocation->relocation_kind=LONG_WORD_RELOCATION;
+}
+
+#define reg_num(r) (real_reg_num[(r)+8])
+
+static unsigned char real_reg_num [16] =
+{
+ 4 /*RSP*/,7 /*RDI*/,6 /*RSI*/,5 /*RBP*/,9,8,2 /*RDX*/,1 /*RCX*/,
+ 0 /*RAX*/,3 /*RBX*/,10,11,12,13,14,15
+};
+
+#define ESP (-8)
+#define EBP (-5)
+#define EAX 0
+
+#define REGISTER_O0 (-5)
+#define REGISTER_R15 7
+
+static void small_as_r (int code,int reg1)
+{
+ int reg1_n;
+
+ reg1_n=reg_num (reg1);
+ if (reg1_n & 8)
+ store_c (0x41);
+ store_c (code | (reg1_n & 7));
+}
+
+static void as_r (int code1,int code2,int reg1)
+{
+ int reg1_n;
+
+ reg1_n=reg_num (reg1);
+
+ store_c (0x48 | ((reg1_n & 8)>>3));
+ store_c (code1);
+ store_c (0300 | code2 | (reg1_n & 7));
+}
+
+static void as_move_i64_r (__int64 i,int reg1)
+{
+ int reg1_n;
+
+ reg1_n=reg_num (reg1);
+
+ store_c (0x48 | ((reg1_n & 8)>>3));
+ store_c (0270 | (reg1_n & 7));
+ store_l ((int)i);
+ store_l ((int)(i>>32));
+}
+
+static void as_move_i_r (int i,int reg1)
+{
+ int reg1_n;
+
+ reg1_n=reg_num (reg1);
+
+ store_c (0x48 | ((reg1_n & 8)>>3));
+ store_c (0xc7);
+ store_c (0xc0 | (reg1_n & 7));
+ store_l (i);
+}
+
+static void as_move_d_r (LABEL *label,int arity,int reg1)
+{
+ int reg1_n;
+
+ reg1_n=reg_num (reg1);
+
+ store_c (0x48 | ((reg1_n & 8)>>1));
+ store_c (0x8d);
+ store_c (5 | ((reg1_n & 7)<<3));
+ store_l (arity);
+ store_relative_label_offset_in_code_section (label);
+}
+
+static void as_move_l_r (LABEL *label,int reg1)
+{
+ as_move_i_r (0,reg1);
+ store_label_in_code_section (label);
+}
+
+static void as_i_r2 (int code1,int code2,int code3,int i,int reg1)
+{
+ int reg1_n;
+
+ reg1_n=reg_num (reg1);
+
+ store_c (0x48 | ((reg1_n & 8)>>3));
+ if (((signed char)i)==i){
+ store_c (code1 | 2);
+ store_c (0300 | code2 | (reg1_n & 7));
+ store_c (i);
+ } else {
+/* if (reg1==EAX)
+ store_c (code3);
+ else {
+*/
+ store_c (code1);
+ store_c (0300 | code2 | (reg1_n & 7));
+/* } */
+ store_l (i);
+ }
+}
+
+static void as_d_r2 (int code1,int code2,int code3,LABEL *label,int arity,int reg1)
+{
+ int reg1_n;
+
+ reg1_n=reg_num (reg1);
+
+ store_c (0x48 | ((reg1_n & 8)>>3));
+ if (reg1==EAX)
+ store_c (code3);
+ else {
+ store_c (code1);
+ store_c (0300 | code2 | (reg1_n & 7));
+ }
+ store_l (arity);
+ store_label_in_code_section (label);
+}
+
+static void as_r_r (int code,int reg1,int reg2)
+{
+ int reg1_n,reg2_n;
+
+ reg1_n=reg_num (reg1);
+ reg2_n=reg_num (reg2);
+
+ store_c (0x48 | ((reg2_n & 8)>>1) | ((reg1_n & 8)>>3));
+ store_c (code);
+ store_c (0300 | ((reg2_n & 7)<<3) | (reg1_n & 7));
+}
+
+static void as_017_r_r (int code,int reg1,int reg2)
+{
+ int reg1_n,reg2_n;
+
+ reg1_n=reg_num (reg1);
+ reg2_n=reg_num (reg2);
+
+ store_c (0x48 | ((reg2_n & 8)>>1) | ((reg1_n & 8)>>3));
+ store_c (017);
+ store_c (code);
+ store_c (0300 | ((reg2_n & 7)<<3) | (reg1_n & 7));
+}
+
+static void as_br_br (int code,int reg1,int reg2)
+{
+ int reg1_n,reg2_n;
+
+ reg1_n=reg_num (reg1);
+ reg2_n=reg_num (reg2);
+
+ if (reg1_n>=4 || reg2_n>=4)
+ store_c (0x40 | ((reg2_n & 8)>>1) | ((reg1_n & 8)>>3));
+ store_c (code);
+ store_c (0300 | ((reg2_n & 7)<<3) | (reg1_n & 7));
+}
+
+#define as_r_id(code,reg1,offset,reg2) as_id_r(code,offset,reg2,reg1)
+
+static void as_id_r (int code,int offset,int reg1,int reg2)
+{
+ int reg1_n,reg2_n;
+
+ reg1_n=reg_num (reg1);
+ reg2_n=reg_num (reg2);
+
+ store_c (0x48 | ((reg2_n & 8)>>1) | ((reg1_n & 8)>>3));
+ store_c (code);
+ if ((reg1_n & 7)==4/*RSP or R12*/){
+ if (offset==0){
+ store_c (0x04 | ((reg2_n & 7)<<3));
+ store_c (0044);
+ } else if (((signed char)offset)==offset){
+ store_c (0x44 | ((reg2_n & 7)<<3));
+ store_c (0044);
+ store_c (offset);
+ } else {
+ store_c (0x84 | ((reg2_n & 7)<<3));
+ store_c (0044);
+ store_l (offset);
+ }
+ } else {
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (((reg2_n & 7)<<3) | (reg1_n & 7));
+ } else if (((signed char)offset)==offset){
+ store_c (0x40 | ((reg2_n & 7)<<3) | (reg1_n & 7));
+ store_c (offset);
+ } else {
+ store_c (0x80 | ((reg2_n & 7)<<3) | (reg1_n & 7));
+ store_l (offset);
+ }
+ }
+}
+
+static void as_017_id_r (int code,int offset,int reg1,int reg2)
+{
+ int reg1_n,reg2_n;
+
+ reg1_n=reg_num (reg1);
+ reg2_n=reg_num (reg2);
+
+ store_c (0x48 | ((reg2_n & 8)>>1) | ((reg1_n & 8)>>3));
+ store_c (017);
+ store_c (code);
+ if ((reg1_n & 7)==4/*RSP or R12*/){
+ if (offset==0){
+ store_c (0x04 | ((reg2_n & 7)<<3));
+ store_c (0044);
+ } else if (((signed char)offset)==offset){
+ store_c (0x44 | ((reg2_n & 7)<<3));
+ store_c (0044);
+ store_c (offset);
+ } else {
+ store_c (0x84 | ((reg2_n & 7)<<3));
+ store_c (0044);
+ store_l (offset);
+ }
+ } else {
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (((reg2_n & 7)<<3) | (reg1_n & 7));
+ } else if (((signed char)offset)==offset){
+ store_c (0x40 | ((reg2_n & 7)<<3) | (reg1_n & 7));
+ store_c (offset);
+ } else {
+ store_c (0x80 | ((reg2_n & 7)<<3) | (reg1_n & 7));
+ store_l (offset);
+ }
+ }
+}
+
+#define as_r_x(code,reg3,offset,index_registers) as_x_r(code,offset,index_registers,reg3)
+
+static void as_x_r (int code,int offset,struct index_registers *index_registers,int reg3)
+{
+ int reg1,reg2,shift,reg1_n,reg2_n,reg3_n,x;
+
+ reg1=index_registers->a_reg.r;
+ reg2=index_registers->d_reg.r;
+
+ reg1_n=reg_num (reg1);
+ reg2_n=reg_num (reg2);
+ reg3_n=reg_num (reg3);
+
+ shift=offset & 3;
+ offset=offset>>2;
+
+ if (reg2==ESP)
+ internal_error_in_function ("as_x_r");
+
+ store_c (0x48 | ((reg3_n & 8)>>1) | ((reg2_n & 8)>>2) | ((reg1_n & 8)>>3));
+ store_c (code);
+ x=(shift<<6) | ((reg2_n & 7)<<3) | (reg1_n & 7);
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (0x04 | ((reg3_n & 7)<<3));
+ store_c (x);
+ } else if (((signed char)offset)==offset){
+ store_c (0x44 | ((reg3_n & 7)<<3));
+ store_c (x);
+ store_c (offset);
+ } else {
+ store_c (0x84 | ((reg3_n & 7)<<3));
+ store_c (x);
+ store_l (offset);
+ }
+}
+
+static void as_017_x_r (int code,int offset,struct index_registers *index_registers,int reg3)
+{
+ int reg1,reg2,shift,reg1_n,reg2_n,reg3_n,x;
+
+ reg1=index_registers->a_reg.r;
+ reg2=index_registers->d_reg.r;
+
+ reg1_n=reg_num (reg1);
+ reg2_n=reg_num (reg2);
+ reg3_n=reg_num (reg3);
+
+ shift=offset & 3;
+ offset=offset>>2;
+
+ if (reg2==ESP)
+ internal_error_in_function ("as_017_x_r");
+
+ store_c (0x48 | ((reg3_n & 8)>>1) | ((reg2_n & 8)>>2) | ((reg1_n & 8)>>3));
+ store_c (017);
+ store_c (code);
+ x=(shift<<6) | ((reg2_n & 7)<<3) | (reg1_n & 7);
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (0x04 | ((reg3_n & 7)<<3));
+ store_c (x);
+ } else if (((signed char)offset)==offset){
+ store_c (0x44 | ((reg3_n & 7)<<3));
+ store_c (x);
+ store_c (offset);
+ } else {
+ store_c (0x84 | ((reg3_n & 7)<<3));
+ store_c (x);
+ store_l (offset);
+ }
+}
+
+static void as_br_id (int code,int reg2,int offset,int reg1)
+{
+ int reg1_n,reg2_n;
+
+ reg1_n=reg_num (reg1);
+ reg2_n=reg_num (reg2);
+
+ if (reg2_n>=4 || (reg1_n & 8)!=0)
+ store_c (0x40 | ((reg2_n & 8)>>1) | ((reg1_n & 8)>>3));
+ store_c (code);
+ if ((reg1_n & 7)==4/*RSP or R12*/){
+ if (offset==0){
+ store_c (0x04 | ((reg2_n & 7)<<3));
+ store_c (0044);
+ } else if (((signed char)offset)==offset){
+ store_c (0x44 | ((reg2_n & 7)<<3));
+ store_c (0044);
+ store_c (offset);
+ } else {
+ store_c (0x84 | ((reg2_n & 7)<<3));
+ store_c (0044);
+ store_l (offset);
+ }
+ } else {
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (((reg2_n & 7)<<3) | (reg1_n & 7));
+ } else if (((signed char)offset)==offset){
+ store_c (0x40 | ((reg2_n & 7)<<3) | (reg1_n & 7));
+ store_c (offset);
+ } else {
+ store_c (0x80 | ((reg2_n & 7)<<3) | (reg1_n & 7));
+ store_l (offset);
+ }
+ }
+}
+
+static void as_br_x (int code,int reg3,int offset,struct index_registers *index_registers)
+{
+ int reg1,reg2,shift,reg1_n,reg2_n,reg3_n,x;
+
+ reg1=index_registers->a_reg.r;
+ reg2=index_registers->d_reg.r;
+
+ reg1_n=reg_num (reg1);
+ reg2_n=reg_num (reg2);
+ reg3_n=reg_num (reg3);
+
+ shift=offset & 3;
+ offset=offset>>2;
+
+ if (reg2==ESP)
+ internal_error_in_function ("as_br_x");
+
+ if (reg3_n>=4 || ((reg1_n | reg2_n) & 8)!=0)
+ store_c (0x40 | ((reg3_n & 8)>>1) | ((reg2_n & 8)>>2) | ((reg1_n & 8)>>3));
+ store_c (code);
+ x=(shift<<6) | ((reg2_n & 7)<<3) | (reg1_n & 7);
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (0x04 | ((reg3_n & 7)<<3));
+ store_c (x);
+ } else if (((signed char)offset)==offset){
+ store_c (0x44 | ((reg3_n & 7)<<3));
+ store_c (x);
+ store_c (offset);
+ } else {
+ store_c (0x84 | ((reg3_n & 7)<<3));
+ store_c (x);
+ store_l (offset);
+ }
+}
+
+static void as_id_rex (int code1,int code2,int offset,int reg1)
+{
+ int reg1_n;
+
+ reg1_n=reg_num (reg1);
+
+ if (reg1_n & 8)
+ store_c (0x41);
+ store_c (code1);
+ if ((reg1_n & 7)==4/*RSP or R12*/){
+ if (offset==0){
+ store_c (code2 | 0x04);
+ store_c (0044);
+ } else if (((signed char)offset)==offset){
+ store_c (code2 | 0x44);
+ store_c (0044);
+ store_c (offset);
+ } else {
+ store_c (code2 | 0x84);
+ store_c (0044);
+ store_l (offset);
+ }
+ } else {
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (code2 | (reg1_n & 7));
+ } else if (((signed char)offset)==offset){
+ store_c (code2 | 0x40 | (reg1_n & 7));
+ store_c (offset);
+ } else {
+ store_c (code2 | 0x80 | (reg1_n & 7));
+ store_l (offset);
+ }
+ }
+}
+
+static void as_id (int code1,int code2,int offset,int reg1)
+{
+ int reg1_n;
+
+ reg1_n=reg_num (reg1);
+
+ store_c (0x48 | ((reg1_n & 8)>>3));
+ store_c (code1);
+ if ((reg1_n & 7)==4/*RSP or R12*/){
+ if (offset==0){
+ store_c (code2 | 0x04);
+ store_c (0044);
+ } else if (((signed char)offset)==offset){
+ store_c (code2 | 0x44);
+ store_c (0044);
+ store_c (offset);
+ } else {
+ store_c (code2 | 0x84);
+ store_c (0044);
+ store_l (offset);
+ }
+ } else {
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (code2 | (reg1_n & 7));
+ } else if (((signed char)offset)==offset){
+ store_c (code2 | 0x40 | (reg1_n & 7));
+ store_c (offset);
+ } else {
+ store_c (code2 | 0x80 | (reg1_n & 7));
+ store_l (offset);
+ }
+ }
+}
+
+static void as_x_rex (int code1,int code2,int offset,struct index_registers *index_registers)
+{
+ int reg1,reg2,reg1_n,reg2_n,shift,x;
+
+ reg1=index_registers->a_reg.r;
+ reg2=index_registers->d_reg.r;
+
+ reg1_n=reg_num (reg1);
+ reg2_n=reg_num (reg2);
+
+ shift=offset & 3;
+ offset=offset>>2;
+
+ if (reg2==ESP)
+ internal_error_in_function ("as_x_rex");
+
+ if ((reg1_n | reg2_n) & 8)
+ store_c (0x40 | ((reg2_n & 8)>>2) | ((reg1_n & 8)>>3));
+ store_c (code1);
+ x=(shift<<6) | ((reg2_n & 7)<<3) | (reg1_n & 7);
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (0x04 | code2);
+ store_c (x);
+ } else if (((signed char)offset)==offset){
+ store_c (0x44 | code2);
+ store_c (x);
+ store_c (offset);
+ } else {
+ store_c (0x84 | code2);
+ store_c (x);
+ store_l (offset);
+ }
+}
+
+static void as_x (int code1,int code2,int offset,struct index_registers *index_registers)
+{
+ int reg1,reg2,reg1_n,reg2_n,shift,x;
+
+ reg1=index_registers->a_reg.r;
+ reg2=index_registers->d_reg.r;
+
+ reg1_n=reg_num (reg1);
+ reg2_n=reg_num (reg2);
+
+ shift=offset & 3;
+ offset=offset>>2;
+
+ if (reg2==ESP)
+ internal_error_in_function ("as_x");
+
+ store_c (0x48 | ((reg2_n & 8)>>2) | ((reg1_n & 8)>>3));
+ store_c (code1);
+ x=(shift<<6) | ((reg2_n & 7)<<3) | (reg1_n & 7);
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (0x04 | code2);
+ store_c (x);
+ } else if (((signed char)offset)==offset){
+ store_c (0x44 | code2);
+ store_c (x);
+ store_c (offset);
+ } else {
+ store_c (0x84 | code2);
+ store_c (x);
+ store_l (offset);
+ }
+}
+
+static void as_i_id (int code1,int code2,int i,int offset,int reg1)
+{
+ int reg1_n;
+
+ reg1_n=reg_num (reg1);
+
+ store_c (0x48 | ((reg1_n & 8)>>3));
+ store_c (code1);
+ if ((reg1_n & 7)==4/*RSP or R12*/){
+ if (offset==0){
+ store_c (code2 | 0x04);
+ store_c (0044);
+ } else if (((signed char)offset)==offset){
+ store_c (code2 | 0x44);
+ store_c (0044);
+ store_c (offset);
+ } else {
+ store_c (code2 | 0x84);
+ store_c (0044);
+ store_l (offset);
+ }
+ } else {
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (code2 | (reg1_n & 7));
+ } else if (((signed char)offset)==offset){
+ store_c (code2 | 0x40 | (reg1_n & 7));
+ store_c (offset);
+ } else {
+ store_c (code2 | 0x80 | (reg1_n & 7));
+ store_l (offset);
+ }
+ }
+ store_l (i);
+}
+
+static void as_i_id2 (int code1,int code2,int i,int offset,int reg1)
+{
+ int reg1_n;
+
+ reg1_n=reg_num (reg1);
+
+ if ((signed char)i==i)
+ code1 |= 2;
+
+ store_c (0x48 | ((reg1_n & 8)>>3));
+ store_c (code1);
+ if ((reg1_n & 7)==4/*RSP or R12*/){
+ if (offset==0){
+ store_c (code2 | 0x04);
+ store_c (0044);
+ } else if (((signed char)offset)==offset){
+ store_c (code2 | 0x44);
+ store_c (0044);
+ store_c (offset);
+ } else {
+ store_c (code2 | 0x84);
+ store_c (0044);
+ store_l (offset);
+ }
+ } else {
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (code2 | (reg1_n & 7));
+ } else if (((signed char)offset)==offset){
+ store_c (code2 | 0x40 | (reg1_n & 7));
+ store_c (offset);
+ } else {
+ store_c (code2 | 0x80 | (reg1_n & 7));
+ store_l (offset);
+ }
+ }
+ if ((signed char)i==i)
+ store_c (i);
+ else
+ store_l (i);
+}
+
+static void as_d_id (int code1,int code2,LABEL *label,int arity,int offset,int reg1)
+{
+ as_i_id (code1,code2,arity,offset,reg1);
+ store_label_in_code_section (label);
+}
+
+static void as_i_x (int code1,int code2,int i,int offset,struct index_registers *index_registers)
+{
+ int reg1,reg2,reg1_n,reg2_n,shift,x;
+
+ reg1=index_registers->a_reg.r;
+ reg2=index_registers->d_reg.r;
+
+ reg1_n=reg_num (reg1);
+ reg2_n=reg_num (reg2);
+
+ shift=offset & 3;
+ offset=offset>>2;
+
+ if (reg2==ESP)
+ internal_error_in_function ("as_i_x");
+
+ store_c (0x48 | ((reg2_n & 8)>>2) | ((reg1_n & 8)>>3));
+ store_c (code1);
+ x=(shift<<6) | ((reg2_n & 7)<<3) | (reg1_n & 7);
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (code2 | 0x04);
+ store_c (x);
+ } else if (((signed char)offset)==offset){
+ store_c (code2 | 0x44);
+ store_c (x);
+ store_c (offset);
+ } else {
+ store_c (code2 | 0x84);
+ store_c (x);
+ store_l (offset);
+ }
+ store_l (i);
+}
+
+static void as_i_x2 (int code1,int code2,int i,int offset,struct index_registers *index_registers)
+{
+ int reg1,reg2,reg1_n,reg2_n,shift,x;
+
+ reg1=index_registers->a_reg.r;
+ reg2=index_registers->d_reg.r;
+
+ reg1_n=reg_num (reg1);
+ reg2_n=reg_num (reg2);
+
+ shift=offset & 3;
+ offset=offset>>2;
+
+ if (reg2==ESP)
+ internal_error_in_function ("as_i_x2");
+
+ if ((signed char)i==i)
+ code1 |= 2;
+
+ store_c (0x48 | ((reg2_n & 8)>>2) | ((reg1_n & 8)>>3));
+ store_c (code1);
+ x=(shift<<6) | ((reg2_n & 7)<<3) | (reg1_n & 7);
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (code2 | 0x04);
+ store_c (x);
+ } else if (((signed char)offset)==offset){
+ store_c (code2 | 0x44);
+ store_c (x);
+ store_c (offset);
+ } else {
+ store_c (code2 | 0x84);
+ store_c (x);
+ store_l (offset);
+ }
+ if ((signed char)i==i)
+ store_c (i);
+ else
+ store_l (i);
+}
+
+static void as_d_x (int code1,int code2,LABEL *label,int arity,int offset,struct index_registers *index_registers)
+{
+ as_i_x (code1,code2,arity,offset,index_registers);
+ store_label_in_code_section (label);
+}
+
+static void as_r_a (int code,int reg1,LABEL *label)
+{
+ int reg1_n;
+
+ reg1_n=reg_num (reg1);
+
+ store_c (0x48 | ((reg1_n & 8)>>3));
+ store_c (code);
+ store_c (((reg1_n & 7)<<3) | 5);
+ store_l (0);
+ store_relative_label_offset_in_code_section (label);
+}
+
+static void as_sar_i_r (int i,int reg)
+{
+ int reg_n;
+
+ reg_n=reg_num (reg);
+
+ store_c (0x48 | ((reg_n & 8)>>3));
+ store_c (0301);
+ store_c (0300 | (7<<3) | (reg_n & 7));
+ store_c (i);
+}
+
+static void as_xchg_d0_rn (int r_n)
+{
+ store_c (0x48 | ((r_n & 8)>>3));
+ store_c (0x90+(r_n & 7)); /* xchg r,D0 */
+}
+
+static void as_move_parameter_reg (struct parameter *parameter,int reg)
+{
+ switch (parameter->parameter_type){
+ case P_REGISTER:
+ as_r_r (0213,parameter->parameter_data.reg.r,reg);
+ return;
+ case P_DESCRIPTOR_NUMBER:
+ as_move_d_r (parameter->parameter_data.l,parameter->parameter_offset,reg);
+ return;
+ case P_IMMEDIATE:
+ if ((int)parameter->parameter_data.imm!=parameter->parameter_data.imm)
+ as_move_i64_r (parameter->parameter_data.imm,reg);
+ else
+ as_move_i_r (parameter->parameter_data.i,reg);
+ return;
+ case P_INDIRECT:
+ as_id_r (0213,parameter->parameter_offset,parameter->parameter_data.reg.r,reg);
+ return;
+ case P_INDEXED:
+ as_x_r (0213,parameter->parameter_offset,parameter->parameter_data.ir,reg);
+ return;
+ case P_POST_INCREMENT:
+ small_as_r (0130,reg);
+ return;
+ case P_LABEL:
+ as_r_a (0213,reg,parameter->parameter_data.l);
+ return;
+ default:
+ internal_error_in_function ("as_move_parameter_reg");
+ return;
+ }
+}
+
+static void as_move_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[1].parameter_type){
+ case P_REGISTER:
+ as_move_parameter_reg (&instruction->instruction_parameters[0],
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDIRECT:
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_INDIRECT:
+ as_id_r (0213,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,REGISTER_O0);
+ as_r_id (0211,REGISTER_O0,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ as_x_r (0213,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.ir,REGISTER_O0);
+ as_r_id (0211,REGISTER_O0,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_DESCRIPTOR_NUMBER:
+#if 0
+ as_move_d_r (instruction->instruction_parameters[0].parameter_data.l,
+ instruction->instruction_parameters[0].parameter_offset,REGISTER_O0);
+ as_r_id (0211,REGISTER_O0,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+#else
+ as_d_id (0307,0,instruction->instruction_parameters[0].parameter_data.l,
+ instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+#endif
+ return;
+ case P_IMMEDIATE:
+ if ((int)instruction->instruction_parameters[0].parameter_data.imm!=instruction->instruction_parameters[0].parameter_data.imm){
+ as_move_i64_r (instruction->instruction_parameters[0].parameter_data.imm,REGISTER_O0);
+ as_r_id (0211,REGISTER_O0,instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ } else
+ as_i_id (0307,0,instruction->instruction_parameters[0].parameter_data.i,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_REGISTER:
+ as_r_id (0211,instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_POST_INCREMENT:
+ as_id_rex (0217,0,instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ default:
+ internal_error_in_function ("as_move_instruction");
+ return;
+ }
+ case P_PRE_DECREMENT:
+ if (instruction->instruction_parameters[1].parameter_data.reg.r==ESP)
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_DESCRIPTOR_NUMBER:
+ store_c (0150);
+ store_l (instruction->instruction_parameters[0].parameter_offset);
+ store_label_in_code_section (instruction->instruction_parameters[0].parameter_data.l);
+ return;
+ case P_IMMEDIATE:
+ if ((int)instruction->instruction_parameters[0].parameter_data.imm!=instruction->instruction_parameters[0].parameter_data.imm){
+ as_move_i64_r (instruction->instruction_parameters[0].parameter_data.imm,REGISTER_O0);
+ small_as_r (0120,REGISTER_O0);
+ } else {
+ int i;
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+ if ((signed char)i==i){
+ store_c (0152);
+ store_c (instruction->instruction_parameters[0].parameter_data.i);
+ } else {
+ store_c (0150);
+ store_l (instruction->instruction_parameters[0].parameter_data.i);
+ }
+ }
+ return;
+ case P_INDIRECT:
+ as_id_rex (0377,060,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ as_x_rex (0377,060,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.ir);
+ return;
+ case P_REGISTER:
+ small_as_r (0120,instruction->instruction_parameters[0].parameter_data.reg.r);
+ return;
+ }
+ internal_error_in_function ("as_move_instruction 2");
+ return;
+ case P_INDEXED:
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_INDIRECT:
+ as_id_r (0213,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,REGISTER_O0);
+ as_r_x (0211,REGISTER_O0,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.ir);
+ return;
+ case P_DESCRIPTOR_NUMBER:
+ as_d_x (0307,0,instruction->instruction_parameters[0].parameter_data.l,
+ instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.ir);
+ return;
+ case P_IMMEDIATE:
+ if ((int)instruction->instruction_parameters[0].parameter_data.imm!=instruction->instruction_parameters[0].parameter_data.imm){
+ as_move_i64_r (instruction->instruction_parameters[0].parameter_data.imm,REGISTER_O0);
+ as_r_x (0211,REGISTER_O0,instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.ir);
+ } else
+ as_i_x (0307,0,instruction->instruction_parameters[0].parameter_data.i,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.ir);
+ return;
+ case P_REGISTER:
+ as_r_x (0211,instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.ir);
+ return;
+ case P_POST_INCREMENT:
+ as_x_rex (0217,000,instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.ir);
+ return;
+ default:
+ internal_error_in_function ("as_move_instruction");
+ return;
+ }
+ case P_LABEL:
+ if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){
+ as_r_a (0211,instruction->instruction_parameters[0].parameter_data.reg.r,instruction->instruction_parameters[1].parameter_data.l);
+ return;
+ }
+ default:
+ internal_error_in_function ("as_move_instruction");
+ }
+}
+
+static void as_moveb_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[1].parameter_type){
+ case P_REGISTER:
+ {
+ int reg;
+
+ reg=instruction->instruction_parameters[1].parameter_data.reg.r;
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_REGISTER:
+ as_br_br (0212,instruction->instruction_parameters[0].parameter_data.reg.r,reg);
+ return;
+ case P_IMMEDIATE:
+ {
+ int reg_n;
+
+ reg_n=reg_num (reg);
+ if (reg_n>=4)
+ store_c (0x40 | ((reg_n & 8)>>3));
+ store_c (0260 | (reg_n & 7));
+ store_c (instruction->instruction_parameters[0].parameter_data.i);
+ return;
+ }
+ case P_INDIRECT:
+ /* movzbl */
+ as_017_id_r (0266,instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.reg.r,reg);
+ return;
+ case P_INDEXED:
+ /* movzbl */
+ as_017_x_r (0266,instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.ir,reg);
+ return;
+ }
+
+ break;
+ }
+ case P_INDIRECT:
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_IMMEDIATE:
+ {
+ int reg1,reg1_n,offset;
+
+ offset=instruction->instruction_parameters[1].parameter_offset;
+ reg1=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ reg1_n=reg_num (reg1);
+
+ if (reg1_n & 8)
+ store_c (0x41);
+ store_c (0306);
+ if ((reg1_n & 7)==4/*RSP or R12*/){
+ if (offset==0){
+ store_c (0x04);
+ store_c (0044);
+ } else if (((signed char)offset)==offset){
+ store_c (0x44);
+ store_c (0044);
+ store_c (offset);
+ } else {
+ store_c (0x84);
+ store_c (0044);
+ store_l (offset);
+ }
+ } else {
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (reg1_n & 7);
+ } else if (((signed char)offset)==offset){
+ store_c (0x40 | (reg1_n & 7));
+ store_c (offset);
+ } else {
+ store_c (0x80 | (reg1_n & 7));
+ store_l (offset);
+ }
+ }
+ store_c (instruction->instruction_parameters[0].parameter_data.i);
+ return;
+ }
+ case P_REGISTER:
+ as_br_id (0210,instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ }
+ break;
+ case P_INDEXED:
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_IMMEDIATE:
+ {
+ int reg1,reg2,reg1_n,reg2_n,shift,offset,x;
+
+ offset=instruction->instruction_parameters[1].parameter_offset;
+ reg1=instruction->instruction_parameters[1].parameter_data.ir->a_reg.r;
+ reg2=instruction->instruction_parameters[1].parameter_data.ir->d_reg.r;
+
+ reg1_n=reg_num (reg1);
+ reg2_n=reg_num (reg2);
+
+ shift=offset & 3;
+ offset=offset>>2;
+
+ if (reg2==ESP)
+ internal_error_in_function ("as_moveb_instruction");
+
+ if (((reg1_n | reg2_n) & 8)!=0)
+ store_c (0x40 | ((reg2_n & 8)>>2) | ((reg1_n & 8)>>3));
+ store_c (0306);
+ x=(shift<<6) | ((reg2_n & 7)<<3) | (reg1_n & 7);
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (0x04);
+ store_c (x);
+ } else if (((signed char)offset)==offset){
+ store_c (0x44);
+ store_c (x);
+ store_c (offset);
+ } else {
+ store_c (0x84);
+ store_c (x);
+ store_l (offset);
+ }
+ store_c (instruction->instruction_parameters[0].parameter_data.i);
+
+ return;
+ }
+ case P_REGISTER:
+ as_br_x (0210,instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.ir);
+ return;
+ }
+ break;
+ }
+ internal_error_in_function ("as_moveb_instruction");
+}
+
+static void as_movew_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[1].parameter_type){
+ case P_REGISTER:
+ {
+ int reg;
+
+ reg=instruction->instruction_parameters[1].parameter_data.reg.r;
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_REGISTER:
+ {
+ int reg1_n,reg2_n;
+
+ reg1_n=reg_num (instruction->instruction_parameters[0].parameter_data.reg.r);
+ reg2_n=reg_num (reg);
+
+ if (((reg1_n | reg2_n) & 8)!=0)
+ store_c (0x40 | ((reg2_n & 8)>>1) | ((reg1_n & 8)>>3));
+ store_c (0146);
+ store_c (0213);
+ store_c (0300 | ((reg2_n & 7)<<3) | (reg1_n & 7));
+ return;
+ }
+ case P_IMMEDIATE:
+ {
+ int reg_n;
+
+ reg_n=reg_num (reg);
+ if (reg_n>=4)
+ store_c (0x40 | ((reg_n & 8)>>3));
+ store_c (0146);
+ store_c (0270 | (reg_n & 7));
+ store_w (instruction->instruction_parameters[0].parameter_data.i);
+ return;
+ }
+ case P_INDIRECT:
+ as_017_id_r (0277,instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.reg.r,reg);
+ return;
+ case P_INDEXED:
+ as_017_x_r (0277,instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.ir,reg);
+ return;
+ }
+ break;
+ }
+ }
+ internal_error_in_function ("as_movew_instruction");
+}
+
+static void as_movesw_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[1].parameter_type){
+ case P_REGISTER:
+ {
+ int reg;
+
+ reg=instruction->instruction_parameters[1].parameter_data.reg.r;
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_REGISTER:
+ as_r_r (0x63,instruction->instruction_parameters[0].parameter_data.reg.r,reg); /* movsxd */
+ return;
+ case P_INDIRECT:
+ as_id_r (0x63,instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.reg.r,reg); /* movsxd */
+ return;
+ case P_INDEXED:
+ as_x_r (0x63,instruction->instruction_parameters[0].parameter_offset,instruction->instruction_parameters[0].parameter_data.ir,reg); /* movsxd */
+ return;
+ }
+ break;
+ }
+ }
+ internal_error_in_function ("as_movesw_instruction");
+}
+
+static void as_lea_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_LABEL:
+ as_move_d_r (instruction->instruction_parameters[0].parameter_data.l,
+ instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDIRECT:
+ as_id_r (0215,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ as_x_r (00215,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.ir,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ }
+ }
+ internal_error_in_function ("as_lea_instruction");
+}
+
+static void as_add_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_REGISTER:
+ as_r_r (0003,instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_IMMEDIATE:
+ as_i_r2 (0201,0000,0005,instruction->instruction_parameters[0].parameter_data.i,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDIRECT:
+ as_id_r (0003,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ as_x_r (0003,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.ir,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ default:
+ internal_error_in_function ("as_add_instruction");
+ return;
+ }
+}
+
+static void as_sub_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_REGISTER:
+ as_r_r (0053,instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_IMMEDIATE:
+ as_i_r2 (0201,0050,0055,instruction->instruction_parameters[0].parameter_data.i,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDIRECT:
+ as_id_r (0053,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ as_x_r (0053,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.ir,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ default:
+ internal_error_in_function ("as_sub_instruction");
+ return;
+ }
+}
+
+static void as_adc_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_REGISTER:
+ as_r_r (0023,instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_IMMEDIATE:
+ as_i_r2 (0201,0020,0025,instruction->instruction_parameters[0].parameter_data.i,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDIRECT:
+ as_id_r (0023,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ as_x_r (0023,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.ir,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ default:
+ internal_error_in_function ("as_adc_instruction");
+ return;
+ }
+}
+
+static void as_sbb_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_REGISTER:
+ as_r_r (0033,instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_IMMEDIATE:
+ as_i_r2 (0201,0030,0035,instruction->instruction_parameters[0].parameter_data.i,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDIRECT:
+ as_id_r (0033,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ as_x_r (0033,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.ir,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ default:
+ internal_error_in_function ("as_sbb_instruction");
+ return;
+ }
+}
+
+enum { SIZE_LONG, SIZE_WORD, SIZE_BYTE };
+
+static void as_cmp_i_parameter (int i,struct parameter *parameter)
+{
+ switch (parameter->parameter_type){
+ case P_REGISTER:
+ as_i_r2 (0201,0070,0075,i,parameter->parameter_data.reg.r);
+ return;
+ case P_INDIRECT:
+ as_i_id2 (0201,0070,i,parameter->parameter_offset,parameter->parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ as_i_x2 (0201,0070,i,parameter->parameter_offset,parameter->parameter_data.ir);
+ return;
+ default:
+ internal_error_in_function ("as_cmp_i_parameter");
+ }
+}
+
+static void 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){
+ /* movswl */
+ as_017_id_r (0277,instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r,REGISTER_O0);
+
+ parameter_1.parameter_type=P_REGISTER;
+ parameter_1.parameter_data.reg.r=REGISTER_O0;
+ }
+
+ switch (parameter_0.parameter_type){
+ case P_DESCRIPTOR_NUMBER:
+ switch (parameter_1.parameter_type){
+ case P_REGISTER:
+ as_d_r2 (0201,0070,0075,parameter_0.parameter_data.l,parameter_0.parameter_offset,
+ parameter_1.parameter_data.reg.r);
+ return;
+ case P_INDIRECT:
+ as_d_id (0201,0070,parameter_0.parameter_data.l,parameter_0.parameter_offset,
+ parameter_1.parameter_offset,parameter_1.parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ as_d_x (0201,0070,parameter_0.parameter_data.l,parameter_0.parameter_offset,
+ parameter_1.parameter_offset,parameter_1.parameter_data.ir);
+ return;
+ }
+ break;
+ case P_IMMEDIATE:
+ as_cmp_i_parameter (parameter_0.parameter_data.i,&parameter_1);
+ return;
+ case P_INDIRECT:
+ if (size_flag==SIZE_WORD){
+ /* movswl */
+ as_017_id_r (0277,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,REGISTER_O0);
+
+ parameter_0.parameter_type=P_REGISTER;
+ parameter_0.parameter_data.reg.r=REGISTER_O0;
+ }
+ }
+
+ if (parameter_1.parameter_type==P_REGISTER)
+ switch (parameter_0.parameter_type){
+ case P_REGISTER:
+ as_r_r (0073,parameter_0.parameter_data.reg.r,parameter_1.parameter_data.reg.r);
+ return;
+ case P_INDIRECT:
+ as_id_r (0073,parameter_0.parameter_offset,parameter_0.parameter_data.reg.r,parameter_1.parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ as_x_r (0073,parameter_0.parameter_offset,parameter_0.parameter_data.ir,parameter_1.parameter_data.reg.r);
+ return;
+ }
+
+ internal_error_in_function ("as_cmp_instruction");
+}
+
+void store_label_in_data_section (LABEL *label)
+{
+ store_label_plus_offset_in_data_section (label,0);
+}
+
+void store_descriptor_in_data_section (LABEL *label)
+{
+ store_label_plus_offset_in_data_section (label,2);
+ store_long_word_in_data_section (0);
+}
+
+static void as_branch_label (struct label *label,int relocation_kind)
+{
+ struct relocation *new_relocation;
+
+ new_relocation=fast_memory_allocate_type (struct relocation);
+
+ *last_code_relocation_l=new_relocation;
+ last_code_relocation_l=&new_relocation->next;
+ new_relocation->next=NULL;
+
+ new_relocation->relocation_label=label;
+ new_relocation->relocation_offset=CURRENT_CODE_OFFSET-4;
+#ifdef FUNCTION_LEVEL_LINKING
+ new_relocation->relocation_object_label=code_object_label;
+#endif
+ new_relocation->relocation_kind=relocation_kind;
+}
+
+static void as_jmp_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_LABEL:
+ store_c (0351);
+ store_l (0);
+ as_branch_label (instruction->instruction_parameters[0].parameter_data.l,JUMP_RELOCATION);
+ break;
+ case P_INDIRECT:
+ if (instruction->instruction_parameters[0].parameter_offset!=0){
+ as_id_r (0x63,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,REGISTER_O0); /* movsxd */
+ store_c (0377);
+ store_c (0340 | reg_num (REGISTER_O0));
+ } else
+ as_id_rex (0377,040,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ break;
+ case P_REGISTER:
+ {
+ int reg_n;
+
+ reg_n=reg_num (instruction->instruction_parameters[0].parameter_data.reg.r);
+
+ if ((reg_n & 8)!=0)
+ store_c (0x41);
+ store_c (0377);
+ store_c (0340 | (reg_n & 7));
+ break;
+ }
+ default:
+ internal_error_in_function ("as_jmp_instruction");
+ }
+}
+
+static void as_jmpp_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_LABEL:
+ {
+ int offset;
+
+ offset=instruction->instruction_parameters[0].parameter_offset;
+
+ if (offset==0){
+ store_c (0350);
+ store_l (0);
+ as_branch_label (profile_t_label,CALL_RELOCATION);
+ }
+
+ store_c (0351);
+ store_l (offset);
+ as_branch_label (instruction->instruction_parameters[0].parameter_data.l,JUMP_RELOCATION);
+ break;
+ }
+ case P_INDIRECT:
+ store_c (0350);
+ store_l (0);
+ as_branch_label (profile_t_label,CALL_RELOCATION);
+
+ if (instruction->instruction_parameters[0].parameter_offset!=0){
+ as_id_r (0x63,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,REGISTER_O0); /* movsxd */
+ store_c (0377);
+ store_c (0340 | reg_num (REGISTER_O0));
+ } else
+ as_id_rex (0377,040,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ break;
+ case P_REGISTER:
+ {
+ int reg_n;
+
+ store_c (0350);
+ store_l (0);
+ as_branch_label (profile_t_label,CALL_RELOCATION);
+
+ reg_n=reg_num (instruction->instruction_parameters[0].parameter_data.reg.r);
+
+ if ((reg_n & 8)!=0)
+ store_c (0x41);
+ store_c (0377);
+ store_c (0340 | (reg_n & 7));
+ break;
+ }
+ default:
+ internal_error_in_function ("as_jmpp_instruction");
+ }
+}
+
+static void as_jsr_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_LABEL:
+ store_c (0350);
+ store_l (0);
+ as_branch_label (instruction->instruction_parameters[0].parameter_data.l,CALL_RELOCATION);
+ break;
+ case P_INDIRECT:
+ if (instruction->instruction_parameters[0].parameter_offset!=0){
+ as_id_r (0x63,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,REGISTER_O0); /* movsxd */
+ store_c (0377);
+ store_c (0320 | reg_num (REGISTER_O0));
+ } else
+ as_id_rex (0377,020,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ break;
+ case P_REGISTER:
+ {
+ int reg_n;
+
+ reg_n=reg_num (instruction->instruction_parameters[0].parameter_data.reg.r);
+
+ if ((reg_n & 8)!=0)
+ store_c (0x41);
+ store_c (0377);
+ store_c (0320 | (reg_n & 7));
+ break;
+ }
+ default:
+ internal_error_in_function ("as_jsr_instruction");
+ }
+}
+
+static void as_branch_instruction (struct instruction *instruction,int condition_code)
+{
+ store_c (017);
+ store_c (0200 | condition_code);
+ store_l (0);
+ as_branch_label (instruction->instruction_parameters[0].parameter_data.l,BRANCH_RELOCATION);
+}
+
+static void as_move_r_r (int reg1,int reg2)
+{
+ as_r_r (0213,reg1,reg2);
+}
+
+static void as_shift_instruction (struct instruction *instruction,int shift_code)
+{
+ int r,reg_n;
+
+ r=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ reg_n=reg_num (r);
+ store_c (0x48 | ((reg_n & 8)>>3));
+ store_c (0301);
+ store_c (0300 | (shift_code<<3) | (reg_n & 7));
+ store_c (instruction->instruction_parameters[0].parameter_data.i & 31);
+ } else if (
+ instruction->instruction_parameters[0].parameter_type==P_REGISTER &&
+ instruction->instruction_parameters[0].parameter_data.reg.r==REGISTER_A0
+ ){
+ reg_n=reg_num (r);
+ store_c (0x48 | ((reg_n & 8)>>3));
+ store_c (0323);
+ store_c (0300 | (shift_code<<3) | (reg_n & 7));
+ } else {
+ as_move_r_r (REGISTER_A0,REGISTER_O0);
+
+ as_move_parameter_reg (&instruction->instruction_parameters[0],REGISTER_A0);
+
+ if (r==REGISTER_A0)
+ r=REGISTER_O0;
+
+ reg_n=reg_num (r);
+ store_c (0x48 | ((reg_n & 8)>>3));
+ store_c (0323);
+ store_c (0300 | (shift_code<<3) | (reg_n & 7));
+
+ as_move_r_r (REGISTER_O0,REGISTER_A0);
+ }
+}
+
+static void as_logic_instruction (struct instruction *instruction,int code1,int code2,int code3)
+{
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_REGISTER:
+ as_r_r (code1,instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDIRECT:
+ as_id_r (code1,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ as_x_r (code1,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.ir,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_IMMEDIATE:
+ if (instruction->instruction_parameters[1].parameter_data.reg.r==EAX){
+ store_c (0x48);
+ store_c (code3);
+ } else
+ as_r (0201,code2,instruction->instruction_parameters[1].parameter_data.reg.r);
+ store_l (instruction->instruction_parameters[0].parameter_data.i);
+ return;
+ default:
+ internal_error_in_function ("as_logic_instruction");
+ }
+}
+
+static void as_mul_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_REGISTER:
+ as_017_r_r (0257,instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ break;
+ case P_INDIRECT:
+ as_017_id_r (0257,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ break;
+ case P_INDEXED:
+ as_017_x_r (0257,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.ir,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ break;
+ case P_IMMEDIATE:
+ {
+ int r,i;
+
+ r=reg_num (instruction->instruction_parameters[1].parameter_data.reg.r);
+ i=instruction->instruction_parameters[0].parameter_data.i;
+
+ store_c (0x48 | ((r & 8)>>1) | ((r & 8)>>3));
+ if ((signed char)i==i){
+ store_c (0153);
+ store_c (0300 | ((r & 7)<<3) | (r & 7));
+ store_c (i);
+ } else {
+ store_c (0151);
+ store_c (0300 | ((r & 7)<<3) | (r & 7));
+ store_l (i);
+ }
+ break;
+ }
+ default:
+ internal_error_in_function ("as_mul_instruction");
+ }
+}
+
+static void as_parameter (int code1,int code2,struct parameter *parameter)
+{
+ switch (parameter->parameter_type){
+ case P_REGISTER:
+ as_r (code1,code2,parameter->parameter_data.reg.r);
+ break;
+ case P_INDIRECT:
+ as_id (code1,code2,parameter->parameter_offset,parameter->parameter_data.reg.r);
+ break;
+ case P_INDEXED:
+ as_x (code1,code2,parameter->parameter_offset,parameter->parameter_data.ir);
+ break;
+ default:
+ internal_error_in_function ("as_parameter");
+ }
+}
+
+/*
+ From The PowerPC Compiler Writers Guide,
+ Warren, Henry S., Jr., IBM Research Report RC 18601 [1992]. Changing Division by a
+ Constant to Multiplication in Twos Complement Arithmetic, (December 21),
+ Granlund, Torbjorn and Montgomery, Peter L. [1994]. SIGPLAN Notices, 29 (June), 61.
+*/
+
+struct ms magic (__int64 d)
+ /* must have 2 <= d <= 231-1 or -231 <= d <= -2 */
+{
+ int p;
+ unsigned __int64 ad, anc, delta, q1, r1, q2, r2, t;
+ const unsigned __int64 two63 = (unsigned __int64)1<<63;/* 263 */
+ struct ms mag;
+
+ ad = d>=0 ? d : -d;
+ t = two63 + ((unsigned __int64)d >> 63);
+ anc = t - 1 - t%ad; /* absolute value of nc */
+ p = 63; /* initialize p */
+ q1 = two63/anc; /* initialize q1 = 2p/abs(nc) */
+ r1 = two63 - q1*anc;/* initialize r1 = rem(2p,abs(nc)) */
+ q2 = two63/ad; /* initialize q2 = 2p/abs(d) */
+ r2 = two63 - q2*ad; /* initialize r2 = rem(2p,abs(d)) */
+
+ do {
+ p = p + 1;
+ q1 = 2*q1; /* update q1 = 2p/abs(nc) */
+ r1 = 2*r1; /* update r1 = rem(2p/abs(nc)) */
+ if (r1 >= anc) {/* must be unsigned comparison */
+ q1 = q1 + 1;
+ r1 = r1 - anc;
+ }
+ q2 = 2*q2; /* update q2 = 2p/abs(d) */
+ r2 = 2*r2; /* update r2 = rem(2p/abs(d)) */
+ if (r2 >= ad) { /* must be unsigned comparison */
+ q2 = q2 + 1;
+ r2 = r2 - ad;
+ }
+ delta = ad - r2;
+ } while (q1 < delta || (q1 == delta && r1 == 0));
+
+ mag.m = q2 + 1;
+ if (d < 0) mag.m = -mag.m; /* resulting magic number */
+ mag.s = p - 64; /* resulting shift */
+
+ return mag;
+}
+
+static void 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 ("as_div_rem_i_instruction");
+
+ i=instruction->instruction_parameters[0].parameter_data.i;
+
+ if (! ((i>1 || (i<-1 && i!=0x80000000))))
+ internal_error_in_function ("as_div_rem_i_instruction");
+
+ abs_i=i>=0 ? i : -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 ("as_div_rem_i_instruction");
+
+ if (sd_reg==REGISTER_A1){
+ if (tmp_reg!=REGISTER_D0)
+ as_move_r_r (REGISTER_D0,tmp_reg);
+ as_move_r_r (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)
+ as_move_r_r (REGISTER_A1,tmp_reg);
+ as_move_r_r (REGISTER_D0,REGISTER_O0);
+
+ s_reg1=REGISTER_A1;
+ s_reg2=REGISTER_O0;
+ i_reg=REGISTER_A1;
+ } else {
+ if (tmp_reg==REGISTER_D0)
+ as_move_r_r (REGISTER_A1,REGISTER_O0);
+ else if (tmp_reg==REGISTER_A1)
+ as_move_r_r (REGISTER_D0,REGISTER_O0);
+ else {
+ as_move_r_r (REGISTER_D0,REGISTER_O0);
+ as_move_r_r (REGISTER_A1,tmp_reg);
+ }
+
+ s_reg1=sd_reg;
+ s_reg2=sd_reg;
+ i_reg=REGISTER_D0;
+ }
+
+ as_move_i64_r (ms.m,i_reg);
+
+ as_r (0367,0050,s_reg1); /* imul */
+
+ if (compute_remainder)
+ as_move_r_r (s_reg2,REGISTER_D0);
+
+ if (ms.m<0)
+ as_r_r (0003,s_reg2,REGISTER_A1); /* add */
+
+ 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;
+ }
+
+ if (i>=0){
+ int s_reg2_n;
+
+ s_reg2_n=reg_num (s_reg2);
+
+ /* shr */
+ store_c (0x48 | ((s_reg2_n & 8)>>3));
+ store_c (0301);
+ store_c (0300 | (5<<3) | (s_reg2_n & 7));
+ store_c (63);
+ } else
+ as_sar_i_r (63,s_reg2);
+
+ if (ms.s>0)
+ as_sar_i_r (ms.s,REGISTER_A1);
+
+ if (!compute_remainder){
+ if (sd_reg==REGISTER_A1){
+ if (i>=0)
+ as_r_r (0003,s_reg2,REGISTER_A1); /* add */
+ else {
+ as_r_r (0053,REGISTER_A1,s_reg2); /* sub */
+ as_move_r_r (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;
+
+ /* lea */
+ as_x_r (00215,0,&index_registers,sd_reg);
+ } else {
+ as_move_r_r (s_reg2,sd_reg);
+ as_r_r (0053,REGISTER_A1,sd_reg);/* sub */
+ }
+ } else {
+ if (i>=0)
+ as_r_r (0003,REGISTER_A1,s_reg2); /* add */ /* s_reg2==sd_reg */
+ else
+ as_r_r (0053,REGISTER_A1,s_reg2); /* sub */ /* s_reg2==sd_reg */
+ }
+ } else {
+ int r,i2;
+
+ as_r_r (0003,s_reg2,REGISTER_A1); /* add */
+
+ 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){
+ /* shl */
+ store_c (0x48);
+ store_c (0301);
+ store_c (0300 | (4<<3) | reg_num (REGISTER_A1));
+ store_c (n_shifts);
+ }
+
+ as_r_r (0053,REGISTER_A1,s_reg3); /* sub */
+
+ n>>=1;
+ n_shifts=1;
+ }
+ } else {
+ /* imul */
+ r=reg_num (REGISTER_A1);
+ store_c (0x48);
+ if ((signed char)i==i){
+ store_c (0153);
+ store_c (0300 | (r<<3) | r);
+ store_c (i);
+ } else {
+ store_c (0151);
+ store_c (0300 | (r<<3) | r);
+ store_l (i);
+ }
+
+ as_r_r (0053,REGISTER_A1,s_reg3); /* sub */
+ }
+
+ if (sd_reg!=s_reg3)
+ as_move_r_r (s_reg3,sd_reg);
+ }
+
+ if (sd_reg==REGISTER_A1){
+ if (tmp_reg!=REGISTER_D0)
+ as_move_r_r (tmp_reg,REGISTER_D0);
+ } else if (sd_reg==REGISTER_D0){
+ if (tmp_reg!=REGISTER_A1)
+ as_move_r_r (tmp_reg,REGISTER_A1);
+ } else {
+ if (tmp_reg==REGISTER_D0)
+ as_move_r_r (REGISTER_O0,REGISTER_A1);
+ else if (tmp_reg==REGISTER_A1)
+ as_move_r_r (REGISTER_O0,REGISTER_D0);
+ else {
+ as_move_r_r (REGISTER_O0,REGISTER_D0);
+ as_move_r_r (tmp_reg,REGISTER_A1);
+ }
+ }
+}
+
+static void 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)){
+ internal_error_in_function ("as_div_instruction");
+ return;
+ }
+
+ if (i==1)
+ return;
+
+ log2i=0;
+ while (i>1){
+ i=i>>1;
+ ++log2i;
+ }
+
+ as_move_r_r (d_reg,REGISTER_O0);
+
+ if (log2i==1){
+ as_sar_i_r (63,REGISTER_O0);
+
+ as_r_r (0053,REGISTER_O0,d_reg); /* sub */
+ } else {
+ as_sar_i_r (63,d_reg);
+
+ /* and */
+ if (d_reg==EAX){
+ store_c (0x48);
+ store_c (045);
+ } else
+ as_r (0201,040,d_reg);
+ store_l ((1<<log2i)-1);
+
+ as_r_r (0003,REGISTER_O0,d_reg); /* add */
+ }
+
+ as_sar_i_r (log2i,d_reg);
+
+ return;
+ }
+
+ switch (d_reg){
+ case REGISTER_D0:
+ as_move_r_r (REGISTER_A1,REGISTER_O0);
+
+ /*cqo*/
+ store_c (0x48);
+ store_c (0231);
+
+ /* idivl */
+ if (instruction->instruction_parameters[0].parameter_type==P_REGISTER
+ && instruction->instruction_parameters[0].parameter_data.reg.r==REGISTER_A1)
+ {
+ as_r (0367,0070,REGISTER_O0);
+ } else if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT
+ && instruction->instruction_parameters[0].parameter_data.reg.r==REGISTER_A1)
+ {
+ as_id (0367,0070,instruction->instruction_parameters[0].parameter_offset,REGISTER_O0);
+ } else
+ as_parameter (0367,0070,&instruction->instruction_parameters[0]);
+
+ as_move_r_r (REGISTER_O0,REGISTER_A1);
+ break;
+ case REGISTER_A1:
+ as_move_r_r (REGISTER_D0,REGISTER_O0);
+ as_move_r_r (REGISTER_A1,REGISTER_D0);
+
+ /*cqo*/
+ store_c (0x48);
+ store_c (0231);
+
+ /* 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;
+
+ as_r (0367,0070,r);
+ } else 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;
+
+ as_id (0367,0070,instruction->instruction_parameters[0].parameter_offset,r);
+ } else
+ as_parameter (00367,0070,&instruction->instruction_parameters[0]);
+
+ as_move_r_r (REGISTER_D0,REGISTER_A1);
+ as_move_r_r (REGISTER_O0,REGISTER_D0);
+ break;
+ default:
+ as_move_r_r (REGISTER_A1,REGISTER_O0);
+ as_xchg_d0_rn (reg_num (d_reg)); /* xchg d_reg,D0 */
+
+ /*cqo*/
+ store_c (0x48);
+ store_c (0231);
+
+ /* 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;
+
+ as_r (0367,0070,r);
+ } else 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;
+
+ as_id (0367,0070,instruction->instruction_parameters[0].parameter_offset,r);
+ } else
+ as_parameter (0367,0070,&instruction->instruction_parameters[0]);
+
+ as_xchg_d0_rn (reg_num (d_reg)); /* xchg d_reg,D0 */
+ as_move_r_r (REGISTER_O0,REGISTER_A1);
+ }
+}
+
+static void 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 ("as_rem_instruction");
+ return;
+ }
+
+ log2i=0;
+ while (i>1){
+ i=i>>1;
+ ++log2i;
+ }
+
+ as_move_r_r (d_reg,REGISTER_O0);
+
+ if (log2i==1){
+ /* and */
+ if (d_reg==EAX){
+ store_c (0x48);
+ store_c (045);
+ } else
+ as_r (0201,040,d_reg);
+ store_l (1);
+
+ as_sar_i_r (63,REGISTER_O0);
+
+ as_r_r (0063,REGISTER_O0,d_reg); /* xor */
+ } else {
+ as_sar_i_r (31,REGISTER_O0);
+
+ /* and */
+ if (REGISTER_O0==EAX){
+ store_c (0x48);
+ store_c (045);
+ } else
+ as_r (0201,040,REGISTER_O0);
+ store_l ((1<<log2i)-1);
+
+ as_r_r (0003,REGISTER_O0,d_reg); /* add */
+
+ /* and */
+ if (d_reg==EAX){
+ store_c (0x48);
+ store_c (045);
+ } else
+ as_r (0201,040,d_reg);
+ store_l ((1<<log2i)-1);
+ }
+
+ as_r_r (0053,REGISTER_O0,d_reg); /* sub */
+
+ return;
+ }
+
+ switch (d_reg){
+ case REGISTER_D0:
+ as_move_r_r (REGISTER_A1,REGISTER_O0);
+
+ /*cqo*/
+ store_c (0x48);
+ store_c (0231);
+
+ /* idivl */
+ if (instruction->instruction_parameters[0].parameter_type==P_REGISTER
+ && instruction->instruction_parameters[0].parameter_data.reg.r==REGISTER_A1)
+ {
+ as_r (0367,0070,REGISTER_O0);
+ } else if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT
+ && instruction->instruction_parameters[0].parameter_data.reg.r==REGISTER_A1)
+ {
+ as_id (0367,0070,instruction->instruction_parameters[0].parameter_offset,REGISTER_O0);
+ } else
+ as_parameter (0367,0070,&instruction->instruction_parameters[0]);
+
+ as_move_r_r (REGISTER_A1,REGISTER_D0);
+ as_move_r_r (REGISTER_O0,REGISTER_A1);
+ break;
+ case REGISTER_A1:
+ as_move_r_r (REGISTER_D0,REGISTER_O0);
+ as_move_r_r (REGISTER_A1,REGISTER_D0);
+
+ /*cqo*/
+ store_c (0x48);
+ store_c (0231);
+ /* 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;
+
+ as_r (0367,0070,r);
+ } else 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;
+
+ as_id (0367,0070,instruction->instruction_parameters[0].parameter_offset,r);
+ } else
+ as_parameter (0367,0070,&instruction->instruction_parameters[0]);
+
+ as_move_r_r (REGISTER_O0,REGISTER_D0);
+ break;
+ default:
+ as_move_r_r (REGISTER_A1,REGISTER_O0);
+ as_xchg_d0_rn (reg_num (d_reg)); /* xchg d_reg,D0 */
+
+ /*cqo*/
+ store_c (0x48);
+ store_c (0231);
+ /* 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;
+
+ as_r (0367,0070,r);
+ } else 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;
+
+ as_id (0367,0070,instruction->instruction_parameters[0].parameter_offset,r);
+ } else
+ as_parameter (0367,0070,&instruction->instruction_parameters[0]);
+
+ as_move_r_r (d_reg,REGISTER_D0);
+ as_move_r_r (REGISTER_A1,d_reg);
+ as_move_r_r (REGISTER_O0,REGISTER_A1);
+ }
+}
+
+static void as_2move_registers (int reg1,int reg2,int reg3)
+{
+ as_move_r_r (reg2,reg3);
+ as_move_r_r (reg1,reg2);
+}
+
+static void as_3move_registers (int reg1,int reg2,int reg3,int reg4)
+{
+ as_move_r_r (reg3,reg4);
+ as_move_r_r (reg2,reg3);
+ as_move_r_r (reg1,reg2);
+}
+
+static void 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)
+ as_r (0367,040,reg_1); /* mul */
+ else {
+ as_move_r_r (REGISTER_A1,REGISTER_O0);
+ as_r (0367,040,reg_1); /* mul */
+ as_2move_registers (REGISTER_O0,REGISTER_A1,reg_1);
+ }
+ } else if (reg_1==REGISTER_A1){
+ as_2move_registers (reg_2,REGISTER_D0,REGISTER_O0);
+ as_r (0367,040,reg_1); /* mul */
+ as_2move_registers (REGISTER_O0,REGISTER_D0,reg_2);
+ } else if (reg_1==REGISTER_D0){
+ if (reg_2==REGISTER_A1){
+ as_r (0367,040,REGISTER_A1); /* mul */
+ as_xchg_d0_rn (reg_num (REGISTER_A1)); /* xchg A1,D0 */
+ } else {
+ as_move_r_r (REGISTER_A1,REGISTER_O0);
+ as_r (0367,040,reg_2); /* mul */
+ as_3move_registers (REGISTER_O0,REGISTER_A1,REGISTER_D0,reg_2);
+ }
+ } else if (reg_2==REGISTER_A1){
+ as_2move_registers (reg_2,REGISTER_D0,REGISTER_O0);
+ as_r (0367,040,reg_1); /* mul */
+ as_3move_registers (REGISTER_O0,REGISTER_D0,REGISTER_A1,reg_1);
+ } else {
+ as_xchg_d0_rn (reg_num (reg_2)); /* xchg reg_2,D0 */
+ as_move_r_r (REGISTER_A1,REGISTER_O0);
+ as_r (0367,040,reg_1); /* mul */
+ as_xchg_d0_rn (reg_num (reg_2)); /* xchg reg_2,D0 */
+ as_2move_registers (REGISTER_O0,REGISTER_A1,reg_1);
+ }
+}
+
+static void 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)
+ as_r (0367,0060,reg_1); /* div */
+ else {
+ as_2move_registers (reg_2,REGISTER_A1,REGISTER_O0);
+ as_r (0367,0060,reg_1); /* div */
+ as_2move_registers (REGISTER_O0,REGISTER_A1,reg_2);
+ }
+ } else if (reg_3==REGISTER_A1){
+ if (reg_2==REGISTER_D0){
+ as_xchg_d0_rn (reg_num (REGISTER_A1)); /* xchg A1,D0 */
+ as_r (0367,0060,REGISTER_A1); /* div */
+ as_xchg_d0_rn (reg_num (REGISTER_A1)); /* xchg A1,D0 */
+ } else {
+ as_3move_registers (reg_2,REGISTER_A1,REGISTER_D0,REGISTER_O0);
+ as_r (0367,0060,REGISTER_O0); /* div */
+ as_3move_registers (REGISTER_O0,REGISTER_D0,REGISTER_A1,reg_2);
+ }
+ } else {
+ if (reg_2==REGISTER_A1){
+ as_2move_registers (reg_3,REGISTER_D0,REGISTER_O0);
+ as_r (0367,0060,REGISTER_O0); /* div */
+ as_2move_registers (REGISTER_O0,REGISTER_D0,reg_3);
+ } else if (reg_2==REGISTER_D0){
+ as_3move_registers (reg_3,REGISTER_D0,REGISTER_A1,REGISTER_O0);
+ as_r (0367,0060,REGISTER_A1); /* div */
+ as_3move_registers (REGISTER_O0,REGISTER_A1,REGISTER_D0,reg_3);
+ } else {
+ as_xchg_d0_rn (reg_num (reg_3)); /* xchg reg_3,D0 */
+ as_2move_registers (reg_2,REGISTER_A1,REGISTER_O0);
+ as_r (0367,0060,reg_3); /* div */
+ as_2move_registers (REGISTER_O0,REGISTER_A1,reg_2);
+ as_xchg_d0_rn (reg_num (reg_3)); /* xchg reg_3,D0 */
+ }
+ }
+ } else if (reg_1==REGISTER_A1){
+ if (reg_2==REGISTER_A1){
+ if (reg_3==REGISTER_D0)
+ as_r (0367,0060,reg_1); /* div */
+ else {
+ as_2move_registers (reg_3,REGISTER_D0,REGISTER_O0);
+ as_r (0367,0060,reg_1); /* div */
+ as_2move_registers (REGISTER_O0,REGISTER_D0,reg_3);
+ }
+ } else if (reg_2==REGISTER_D0){
+ if (reg_3==REGISTER_A1){
+ as_xchg_d0_rn (reg_num (REGISTER_A1)); /* xchg A1,D0 */
+ as_r (0367,0060,REGISTER_D0); /* div */
+ as_xchg_d0_rn (reg_num (REGISTER_A1)); /* xchg A1,D0 */
+ } else {
+ as_3move_registers (reg_3,REGISTER_D0,REGISTER_A1,REGISTER_O0);
+ as_r (0367,0060,REGISTER_O0); /* div */
+ as_3move_registers (REGISTER_O0,REGISTER_A1,REGISTER_D0,reg_3);
+ }
+ } else {
+ if (reg_3==REGISTER_D0){
+ as_2move_registers (reg_2,REGISTER_A1,REGISTER_O0);
+ as_r (0367,0060,REGISTER_O0); /* div */
+ as_2move_registers (REGISTER_O0,REGISTER_A1,reg_2);
+ } else if (reg_3==REGISTER_A1){
+ as_3move_registers (reg_2,REGISTER_A1,REGISTER_D0,REGISTER_O0);
+ as_r (0367,0060,REGISTER_D0); /* div */
+ as_3move_registers (REGISTER_O0,REGISTER_D0,REGISTER_A1,reg_2);
+ } else {
+ as_r_r (0207,reg_2,REGISTER_A1); /* xchg */
+ as_2move_registers (reg_3,REGISTER_D0,REGISTER_O0);
+ as_r (0367,0060,reg_2); /* div */
+ as_2move_registers (REGISTER_O0,REGISTER_D0,reg_3);
+ as_r_r (0207,reg_2,REGISTER_A1); /* xchg */
+ }
+ }
+ } else {
+ if (reg_3==REGISTER_D0){
+ if (reg_2==REGISTER_A1){
+ as_r (0367,0060,reg_1); /* div */
+ } else {
+ as_2move_registers (reg_2,REGISTER_A1,REGISTER_O0);
+ as_r (0367,0060,reg_1); /* div */
+ as_2move_registers (REGISTER_O0,REGISTER_A1,reg_2);
+ }
+ } else if (reg_2==REGISTER_A1){
+ as_2move_registers (reg_3,REGISTER_D0,REGISTER_O0);
+ as_r (0367,0060,reg_1); /* div */
+ as_2move_registers (REGISTER_O0,REGISTER_D0,reg_3);
+ } else if (reg_2==REGISTER_D0){
+ if (reg_3==REGISTER_A1){
+ as_xchg_d0_rn (reg_num (REGISTER_A1)); /* xchg A1,D0 */
+ as_r (0367,0060,reg_1); /* div */
+ as_xchg_d0_rn (reg_num (REGISTER_A1)); /* xchg A1,D0 */
+ } else {
+ as_3move_registers (reg_3,REGISTER_D0,REGISTER_A1,REGISTER_O0);
+ as_r (0367,0060,reg_1); /* div */
+ as_3move_registers (REGISTER_O0,REGISTER_A1,REGISTER_D0,reg_3);
+ }
+ } else if (reg_2==REGISTER_A1){
+ as_3move_registers (reg_3,REGISTER_A1,REGISTER_D0,REGISTER_O0);
+ as_r (0367,0060,reg_1); /* div */
+ as_3move_registers (REGISTER_O0,REGISTER_D0,REGISTER_A1,reg_3);
+ } else {
+ as_xchg_d0_rn (reg_num (reg_3)); /* xchg reg_3,D0 */
+ as_2move_registers (reg_2,REGISTER_A1,REGISTER_O0);
+ as_r (0367,0060,reg_1); /* div */
+ as_2move_registers (REGISTER_O0,REGISTER_A1,reg_2);
+ as_xchg_d0_rn (reg_num (reg_3)); /* xchg reg_3,D0 */
+ }
+ }
+}
+
+static void as_set_condition_instruction (struct instruction *instruction,int condition_code)
+{
+ int r,r_n;
+
+ r=instruction->instruction_parameters[0].parameter_data.reg.r;
+
+ r_n=reg_num (r);
+
+ if (r_n>=4)
+ store_c (0x40 | ((r_n & 8)>>3));
+ store_c (0017);
+ store_c (0220 | condition_code);
+ store_c (0300 | (r_n & 7));
+
+ /* movzbl */
+ store_c (0x48 | ((r_n & 8)>>1) | ((r_n & 8)>>3));
+ store_c (017);
+ store_c (0266);
+ store_c (0300 | ((r_n & 7)<<3) | (r_n & 7));
+}
+
+static void as_tst_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_REGISTER:
+ {
+ int r,r_n;
+
+ r=instruction->instruction_parameters[0].parameter_data.reg.r;
+ r_n=reg_num (r);
+
+ store_c (0x48 | ((r_n & 8)>>1) | ((r_n & 8)>>3));
+ store_c (0205);
+ store_c (0300 | ((r_n & 7)<<3) | (r_n & 7));
+ break;
+ }
+ default:
+ as_cmp_i_parameter (0,&instruction->instruction_parameters[0]);
+ break;
+ }
+}
+
+static void as_btst_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){
+ int reg1;
+
+ reg1=instruction->instruction_parameters[1].parameter_data.reg.r;
+ if (reg1==EAX)
+ store_c (0250);
+ else {
+ store_c (0366);
+ store_c (0300 | reg_num (reg1));
+ }
+ store_c (instruction->instruction_parameters[0].parameter_data.i);
+ } else {
+ int reg1,reg1_n,offset;
+
+ reg1=instruction->instruction_parameters[1].parameter_data.reg.r;
+ offset=instruction->instruction_parameters[1].parameter_offset;
+
+ reg1_n=reg_num (reg1);
+
+ if (reg1_n & 8)
+ store_c (0x41);
+ store_c (0366);
+ if ((reg1_n & 7)==4/*RSP or R12*/){
+ if (offset==0){
+ store_c (0x04);
+ store_c (0044);
+ } else if (((signed char)offset)==offset){
+ store_c (0x44);
+ store_c (0044);
+ store_c (offset);
+ } else {
+ store_c (0x84);
+ store_c (0044);
+ store_l (offset);
+ }
+ } else {
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (reg1_n & 7);
+ } else if (((signed char)offset)==offset){
+ store_c (0x40 | (reg1_n & 7));
+ store_c (offset);
+ } else {
+ store_c (0x80 | (reg1_n & 7));
+ store_l (offset);
+ }
+ }
+ store_c (instruction->instruction_parameters[0].parameter_data.i);
+ }
+}
+
+static void as_exg_instruction (struct instruction *instruction)
+{
+ int r1,r2,r1_n,r2_n;
+
+ r1=instruction->instruction_parameters[0].parameter_data.reg.r;
+ r2=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ r1_n=reg_num (r1);
+ r2_n=reg_num (r2);
+
+ if (r1==REGISTER_D0)
+ as_xchg_d0_rn (r2_n); /* xchg r,D0 */
+ else if (r2==REGISTER_D0)
+ as_xchg_d0_rn (r1_n); /* xchg r,D0 */
+ else
+ as_r_r (0207,r1,r2);
+}
+
+static void as_neg_instruction (struct instruction *instruction)
+{
+ as_r (0367,0030,instruction->instruction_parameters[0].parameter_data.reg.r);
+}
+
+static void as_not_instruction (struct instruction *instruction)
+{
+ as_r (0367,0020,instruction->instruction_parameters[0].parameter_data.reg.r);
+}
+
+static void as_rtsi_instruction (struct instruction *instruction)
+{
+ store_c (0xc2);
+ store_w (instruction->instruction_parameters[0].parameter_data.i);
+}
+
+static void as_f_r (int code1,int code2,int reg1,int reg2)
+{
+ store_c (code1);
+ if ((reg1 | reg2) & 8)
+ store_c (0x40 | ((reg2 & 8)>>1) | ((reg1 & 8)>>3));
+ store_c (0x0f);
+ store_c (code2);
+ store_c (0xc0 | ((reg2 & 7)<<3) | (reg1 & 7));
+}
+
+static void as_f_id (int code1,int code2,int offset,int reg1,int d_freg)
+{
+ int reg1_n;
+
+ reg1_n=reg_num (reg1);
+
+ store_c (code1);
+ if ((d_freg | reg1_n) & 8)
+ store_c (0x40 | ((d_freg & 8)>>1) | ((reg1_n & 8)>>3));
+ store_c (0x0f);
+ store_c (code2);
+ if ((reg1_n & 7)==4/*RSP or R12*/){
+ if (offset==0){
+ store_c (0x04 | ((d_freg & 7)<<3));
+ store_c (0044);
+ } else if (((signed char)offset)==offset){
+ store_c (0x44 | ((d_freg & 7)<<3));
+ store_c (0044);
+ store_c (offset);
+ } else {
+ store_c (0x84 | ((d_freg & 7)<<3));
+ store_c (0044);
+ store_l (offset);
+ }
+ } else {
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (((d_freg & 7)<<3) | (reg1_n & 7));
+ } else if (((signed char)offset)==offset){
+ store_c (0x40 | ((d_freg & 7)<<3) | (reg1_n & 7));
+ store_c (offset);
+ } else {
+ store_c (0x80 | ((d_freg & 7)<<3) | (reg1_n & 7));
+ store_l (offset);
+ }
+ }
+}
+
+static void as_f_id_rexaw (int code1,int code2,int offset,int reg1,int d_freg)
+{
+ int reg1_n;
+
+ reg1_n=reg_num (reg1);
+
+ store_c (code1);
+ store_c (0x48 | ((d_freg & 8)>>1) | ((reg1_n & 8)>>3));
+ store_c (0x0f);
+ store_c (code2);
+ if ((reg1_n & 7)==4/*RSP or R12*/){
+ if (offset==0){
+ store_c (0x04 | ((d_freg & 7)<<3));
+ store_c (0044);
+ } else if (((signed char)offset)==offset){
+ store_c (0x44 | ((d_freg & 7)<<3));
+ store_c (0044);
+ store_c (offset);
+ } else {
+ store_c (0x84 | ((d_freg & 7)<<3));
+ store_c (0044);
+ store_l (offset);
+ }
+ } else {
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (((d_freg & 7)<<3) | (reg1_n & 7));
+ } else if (((signed char)offset)==offset){
+ store_c (0x40 | ((d_freg & 7)<<3) | (reg1_n & 7));
+ store_c (offset);
+ } else {
+ store_c (0x80 | ((d_freg & 7)<<3) | (reg1_n & 7));
+ store_l (offset);
+ }
+ }
+}
+
+static void as_f_x (int code1,int code2,int offset,struct index_registers *index_registers,int d_freg)
+{
+ int reg1,reg2,reg1_n,reg2_n,shift,x;
+
+ reg1=index_registers->a_reg.r;
+ reg2=index_registers->d_reg.r;
+
+ reg1_n=reg_num (reg1);
+ reg2_n=reg_num (reg2);
+
+ shift=offset & 3;
+ offset=offset>>2;
+
+ if (reg2==ESP)
+ internal_error_in_function ("as_f_x");
+
+ store_c (code1);
+ if ((d_freg | reg2_n | reg1_n) & 8)
+ store_c (0x40 | ((d_freg & 8)>>1) | ((reg2_n & 8)>>2) | ((reg1_n & 8)>>3));
+ store_c (0x0f);
+ store_c (code2);
+ x=(shift<<6) | ((reg2_n & 7)<<3) | (reg1_n & 7);
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (0x04 | ((d_freg & 7)<<3));
+ store_c (x);
+ } else if (((signed char)offset)==offset){
+ store_c (0x44 | ((d_freg & 7)<<3));
+ store_c (x);
+ store_c (offset);
+ } else {
+ store_c (0x84 | ((d_freg & 7)<<3));
+ store_c (x);
+ store_l (offset);
+ }
+}
+
+static void as_f_x_rexaw (int code1,int code2,int offset,struct index_registers *index_registers,int d_freg)
+{
+ int reg1,reg2,reg1_n,reg2_n,shift,x;
+
+ reg1=index_registers->a_reg.r;
+ reg2=index_registers->d_reg.r;
+
+ reg1_n=reg_num (reg1);
+ reg2_n=reg_num (reg2);
+
+ shift=offset & 3;
+ offset=offset>>2;
+
+ if (reg2==ESP)
+ internal_error_in_function ("as_f_x_rexaw");
+
+ store_c (code1);
+ store_c (0x48 | ((d_freg & 8)>>1) | ((reg2_n & 8)>>2) | ((reg1_n & 8)>>3));
+ store_c (0x0f);
+ store_c (code2);
+ x=(shift<<6) | ((reg2_n & 7)<<3) | (reg1_n & 7);
+ if (offset==0 && (reg1_n & 7)!=5/*RBP or R13*/){
+ store_c (0x04 | ((d_freg & 7)<<3));
+ store_c (x);
+ } else if (((signed char)offset)==offset){
+ store_c (0x44 | ((d_freg & 7)<<3));
+ store_c (x);
+ store_c (offset);
+ } else {
+ store_c (0x84 | ((d_freg & 7)<<3));
+ store_c (x);
+ store_l (offset);
+ }
+}
+
+static void as_f_a (int code1,int code2,LABEL *label,int d_freg)
+{
+ store_c (code1);
+ if (d_freg & 8)
+ store_c (0x40 | ((d_freg & 8)>>1));
+ store_c (0x0f);
+ store_c (code2);
+ store_c (5 | ((d_freg & 7)<<3));
+ store_l (0);
+ store_relative_label_offset_in_code_section (label);
+}
+
+static void as_f_a_rexaw (int code1,int code2,LABEL *label,int d_freg)
+{
+ store_c (code1);
+ store_c (0x48 | ((d_freg & 8)>>1));
+ store_c (0x0f);
+ store_c (code2);
+ store_c (5 | ((d_freg & 7)<<3));
+ store_l (0);
+ store_relative_label_offset_in_code_section (label);
+}
+
+static void as_f_i (int code1,int code2,DOUBLE *r_p,int d_freg)
+{
+ LABEL *new_label;
+
+ new_label=allocate_memory_from_heap (sizeof (struct label));
+
+ new_label->label_flags=DATA_LABEL;
+
+ if (data_object_label->object_section_align<3)
+ data_object_label->object_section_align=3;
+ if ((data_buffer_p-current_data_buffer->data-data_object_label->object_label_offset) & 4)
+ store_long_word_in_data_section (0);
+
+ define_data_label (new_label);
+ store_long_word_in_data_section (((LONG*)r_p)[0]);
+ store_long_word_in_data_section (((LONG*)r_p)[1]);
+
+ as_f_a (code1,code2,new_label,d_freg);
+}
+
+static void 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:
+ as_f_r (0xf2,0x10,instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDIRECT:
+ as_f_id (0x66,0x12,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_INDEXED:
+ as_f_x (0x66,0x12,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.ir,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ case P_F_IMMEDIATE:
+ as_f_i (0x66,0x12,instruction->instruction_parameters[0].parameter_data.r,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ return;
+ }
+ break;
+ case P_INDIRECT:
+ if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){
+ as_f_id (0xf2,0x11,instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ return;
+ }
+ break;
+ case P_INDEXED:
+ if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){
+ as_f_x (0xf2,0x11,instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.ir,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ return;
+ }
+ }
+ internal_error_in_function ("as_fmove_instruction");
+}
+
+static void as_dyadic_float_instruction (struct instruction *instruction,int code1,int code2)
+{
+ int d_freg;
+
+ d_freg=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_F_IMMEDIATE:
+ as_f_i (code1,code2,instruction->instruction_parameters[0].parameter_data.r,d_freg);
+ return;
+ case P_INDIRECT:
+ as_f_id (code1,code2,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,d_freg);
+ return;
+ case P_INDEXED:
+ as_f_x (code1,code2,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.ir,d_freg);
+ break;
+ case P_F_REGISTER:
+ as_f_r (code1,code2,instruction->instruction_parameters[0].parameter_data.reg.r,d_freg);
+ return;
+ default:
+ internal_error_in_function ("as_dyadic_float_instruction");
+ return;
+ }
+}
+
+LABEL *sign_real_mask_label;
+
+static void as_float_neg_instruction (struct instruction *instruction,int code)
+{
+ int d_freg;
+
+ d_freg=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_F_REGISTER:
+ if (instruction->instruction_parameters[0].parameter_data.reg.r!=d_freg)
+ as_f_r (0xf2,0x10,instruction->instruction_parameters[0].parameter_data.reg.r,d_freg);
+ break;
+ case P_INDIRECT:
+ as_f_id (0x66,0x12,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,d_freg);
+ break;
+ case P_INDEXED:
+ as_f_x (0x66,0x12,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.ir,d_freg);
+ break;
+ case P_F_IMMEDIATE:
+ as_f_i (0x66,0x12,instruction->instruction_parameters[0].parameter_data.r,d_freg);
+ break;
+ default:
+ internal_error_in_function ("as_float_neg_instruction");
+ return;
+ }
+
+ if (sign_real_mask_label==NULL){
+ LABEL *new_label;
+
+ new_label=allocate_memory_from_heap (sizeof (struct label));
+
+ new_label->label_flags=DATA_LABEL;
+
+ if (data_object_label->object_section_align<4)
+ data_object_label->object_section_align=4;
+ while ((data_buffer_p-current_data_buffer->data-data_object_label->object_label_offset) & 0xc)
+ store_long_word_in_data_section (0);
+
+ define_data_label (new_label);
+ store_long_word_in_data_section (0);
+ store_long_word_in_data_section (0x80000000);
+ store_long_word_in_data_section (0);
+ store_long_word_in_data_section (0x80000000);
+
+ sign_real_mask_label=new_label;
+ }
+
+ as_f_a (0x66,0x57,sign_real_mask_label,d_freg); /* xorpd */
+}
+
+static void as_float_branch_instruction (struct instruction *instruction,int n)
+{
+ struct label *new_label;
+
+ switch (n){
+ case 2:
+ as_branch_instruction (instruction,007); /* ja */
+ return;
+ case 5:
+ as_branch_instruction (instruction,003); /* jae */
+ return;
+ }
+
+ store_c (0x7a); /* jp */
+ store_c (6);
+
+ {
+ struct relocation *new_relocation;
+
+ new_relocation=fast_memory_allocate_type (struct relocation);
+
+ *last_code_relocation_l=new_relocation;
+ last_code_relocation_l=&new_relocation->next;
+ new_relocation->next=NULL;
+
+ new_relocation->relocation_label=NULL;
+ new_relocation->relocation_offset=CURRENT_CODE_OFFSET-1;
+#ifdef FUNCTION_LEVEL_LINKING
+ new_relocation->relocation_object_label=code_object_label;
+#endif
+ new_relocation->relocation_kind=BRANCH_SKIP_BRANCH_RELOCATION;
+ }
+
+ switch (n){
+ case 0:
+ as_branch_instruction (instruction,004); /* je */
+ break;
+ case 1:
+ as_branch_instruction (instruction,002); /* jb */
+ break;
+ case 3:
+ as_branch_instruction (instruction,005); /* jne */
+ break;
+ case 4:
+ as_branch_instruction (instruction,006); /* jbe */
+ break;
+ }
+}
+
+static void as_set_float_condition_instruction (struct instruction *instruction,int n)
+{
+ int r,r_n;
+
+ r=instruction->instruction_parameters[0].parameter_data.reg.r;
+
+ r_n=reg_num (r);
+
+ switch (n){
+ case 2:
+ /* seta */
+ if (r_n>=4)
+ store_c (0x40 | ((r_n & 8)>>3));
+ store_c (0017);
+ store_c (0220 | 7);
+ store_c (0300 | (r_n & 7));
+ break;
+ case 5:
+ /* setae */
+ if (r_n>=4)
+ store_c (0x40 | ((r_n & 8)>>3));
+ store_c (0017);
+ store_c (0220 | 3);
+ store_c (0300 | (r_n & 7));
+ break;
+ default:
+ {
+ int condition_code;
+
+ /* setnp bpl*/
+ store_c (0x40);
+ store_c (0017);
+ store_c (0220 | 0xb);
+ store_c (0300 | (5 & 7));
+
+ switch (n){
+ case 0:
+ condition_code=4; /* sete */
+ break;
+ case 1:
+ condition_code=2; /* setb */
+ break;
+ case 3:
+ condition_code=5; /*setne */
+ break;
+ case 4:
+ condition_code=6; /* setbe */
+ break;
+ }
+
+ if (r_n>=4)
+ store_c (0x40 | ((r_n & 8)>>3));
+ store_c (0017);
+ store_c (0220 | condition_code);
+ store_c (0300 | (r_n & 7));
+
+ store_c (0x40 | ((r_n & 8)>>3));
+ store_c (0x20); /* andb */
+ store_c (0xc0 | (5<<3) | (r_n & 7));
+ }
+ }
+
+ /* movzbl */
+ store_c (0x48 | ((r_n & 8)>>1) | ((r_n & 8)>>3));
+ store_c (017);
+ store_c (0266);
+ store_c (0300 | ((r_n & 7)<<3) | (r_n & 7));
+}
+
+void define_data_label (LABEL *label)
+{
+ label->label_id=DATA_LABEL_ID;
+#ifdef FUNCTION_LEVEL_LINKING
+ label->label_object_label=data_object_label;
+#endif
+ label->label_offset=CURRENT_DATA_OFFSET;
+
+ if (label->label_flags & EXPORT_LABEL){
+ struct object_label *new_object_label;
+ int string_length;
+
+ new_object_label=fast_memory_allocate_type (struct object_label);
+ *last_object_label_l=new_object_label;
+ last_object_label_l=&new_object_label->next;
+ new_object_label->next=NULL;
+
+ new_object_label->object_label_label=label;
+#if defined (RELOCATIONS_RELATIVE_TO_EXPORTED_DATA_LABEL) && defined (FUNCTION_LEVEL_LINKING)
+ new_object_label->object_label_number = n_object_labels;
+#endif
+
+ ++n_object_labels;
+
+ string_length=strlen (label->label_name);
+#ifndef ELF
+ if (string_length<8)
+ new_object_label->object_label_string_offset=0;
+ else
+#endif
+ {
+ new_object_label->object_label_string_offset=string_table_offset;
+ string_table_offset+=string_length+1;
+ }
+
+#if defined (RELOCATIONS_RELATIVE_TO_EXPORTED_DATA_LABEL) && defined (FUNCTION_LEVEL_LINKING)
+ label->label_object_label=new_object_label;
+ new_object_label->object_label_section_n = data_object_label->object_label_section_n;
+#endif
+
+ new_object_label->object_label_kind=EXPORTED_DATA_LABEL;
+ }
+}
+
+void store_descriptor_string_in_data_section (char *string,int length,LABEL *string_label)
+{
+ unsigned char *string_p;
+
+ define_data_label (string_label);
+
+ string_p=(unsigned char*)string;
+ store_long_word_in_data_section (length);
+
+ while (length>=4){
+ store_long_word_in_data_section (*(ULONG*)string_p);
+ string_p+=4;
+ length-=4;
+ }
+
+ if (length>0){
+ ULONG d;
+ int shift;
+
+ d=0;
+ shift=0;
+ while (length>0){
+ d |= string_p[0]<<shift;
+ shift+=8;
+ --length;
+ ++string_p;
+ }
+ store_long_word_in_data_section (d);
+ }
+}
+
+static void as_fmovel_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_REGISTER:
+ {
+ int reg1_n;
+
+ reg1_n=reg_num (instruction->instruction_parameters[0].parameter_data.reg.r);
+
+ store_c (0xf2);
+ store_c (0x48 | ((d_freg & 8)>>1) | ((reg1_n & 8)>>3));
+ store_c (0x0f);
+ store_c (0x2a);
+ store_c (0xc0 | ((d_freg & 7)<<3) | (reg1_n & 7));
+
+ break;
+ }
+ case P_INDIRECT:
+ as_f_id_rexaw (0xf2,0x2a,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r,d_freg);
+ break;
+ case P_INDEXED:
+ as_f_x_rexaw (0xf2,0x2a,instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.ir,d_freg);
+ break;
+ case P_IMMEDIATE:
+ {
+ LABEL *new_label;
+
+ new_label=allocate_memory_from_heap (sizeof (struct label));
+
+ new_label->label_flags=DATA_LABEL;
+
+ define_data_label (new_label);
+ store_long_word_in_data_section (instruction->instruction_parameters[0].parameter_data.i);
+
+ as_f_a_rexaw (0xf2,0x2a,new_label,d_freg);
+ break;
+ }
+ default:
+ internal_error_in_function ("as_fmovel_instruction");
+ }
+}
+
+static void as_labels (struct block_label *labels)
+{
+ for (; labels!=NULL; labels=labels->block_label_next)
+#if 0
+ if (labels->block_label_label->label_number==0)
+#endif
+ {
+ LABEL *label;
+
+ label=labels->block_label_label;
+
+ label->label_id=TEXT_LABEL_ID;
+#ifdef FUNCTION_LEVEL_LINKING
+ label->label_object_label=code_object_label;
+#endif
+ label->label_offset=CURRENT_CODE_OFFSET;
+
+ if (label->label_flags & EXPORT_LABEL){
+ struct object_label *new_object_label;
+ int string_length;
+
+ new_object_label=fast_memory_allocate_type (struct object_label);
+ *last_object_label_l=new_object_label;
+ last_object_label_l=&new_object_label->next;
+ new_object_label->next=NULL;
+
+ new_object_label->object_label_label=label;
+
+ ++n_object_labels;
+
+ string_length=strlen (label->label_name);
+#ifndef ELF
+ if (string_length<8)
+ new_object_label->object_label_string_offset=0;
+ else
+#endif
+ {
+ new_object_label->object_label_string_offset=string_table_offset;
+ string_table_offset+=string_length+1;
+ }
+
+ new_object_label->object_label_kind=EXPORTED_CODE_LABEL;
+ }
+ }
+}
+
+static void as_instructions (struct instruction *instruction)
+{
+ while (instruction!=NULL){
+ switch (instruction->instruction_icode){
+ case IMOVE:
+ as_move_instruction (instruction);
+ break;
+ case ILEA:
+ as_lea_instruction (instruction);
+ break;
+ case IADD:
+ as_add_instruction (instruction);
+ break;
+ case ISUB:
+ as_sub_instruction (instruction);
+ break;
+ case ICMP:
+ as_cmp_instruction (instruction,SIZE_LONG);
+ break;
+ case IJMP:
+ as_jmp_instruction (instruction);
+ break;
+ case IJMPP:
+ as_jmpp_instruction (instruction);
+ break;
+ case IJSR:
+ as_jsr_instruction (instruction);
+ break;
+ case IRTS:
+ store_c (0303);
+ break;
+ case IRTSP:
+ store_c (0351);
+ store_l (0);
+ as_branch_label (profile_r_label,JUMP_RELOCATION);
+ break;
+ case IBEQ:
+ as_branch_instruction (instruction,004);
+ break;
+ case IBGE:
+ as_branch_instruction (instruction,015);
+ break;
+ case IBGEU:
+ as_branch_instruction (instruction,003);
+ break;
+ case IBGT:
+ as_branch_instruction (instruction,017);
+ break;
+ case IBGTU:
+ as_branch_instruction (instruction,007);
+ break;
+ case IBLE:
+ as_branch_instruction (instruction,016);
+ break;
+ case IBLEU:
+ as_branch_instruction (instruction,006);
+ break;
+ case IBLT:
+ as_branch_instruction (instruction,014);
+ break;
+ case IBLTU:
+ as_branch_instruction (instruction,002);
+ break;
+ case IBNE:
+ as_branch_instruction (instruction,005);
+ break;
+ case IBO:
+ as_branch_instruction (instruction,0);
+ break;
+ case IBNO:
+ as_branch_instruction (instruction,1);
+ break;
+ case ILSL:
+ as_shift_instruction (instruction,4);
+ break;
+ case ILSR:
+ as_shift_instruction (instruction,5);
+ break;
+ case IASR:
+ as_shift_instruction (instruction,7);
+ break;
+ case IMUL:
+ as_mul_instruction (instruction);
+ break;
+ case IDIV:
+ as_div_instruction (instruction);
+ break;
+ case IDIVI:
+ as_div_rem_i_instruction (instruction,0);
+ break;
+ case IMOD:
+ as_rem_instruction (instruction);
+ break;
+ case IREMI:
+ as_div_rem_i_instruction (instruction,1);
+ break;
+ case IAND:
+ as_logic_instruction (instruction,0043,040,045);
+ break;
+ case IOR:
+ as_logic_instruction (instruction,0013,010,015);
+ break;
+ case IEOR:
+ as_logic_instruction (instruction,0063,060,065);
+ break;
+ case ISEQ:
+ as_set_condition_instruction (instruction,004);
+ break;
+ case ISGE:
+ as_set_condition_instruction (instruction,015);
+ break;
+ case ISGEU:
+ as_set_condition_instruction (instruction,003);
+ break;
+ case ISGT:
+ as_set_condition_instruction (instruction,017);
+ break;
+ case ISGTU:
+ as_set_condition_instruction (instruction,007);
+ break;
+ case ISLE:
+ as_set_condition_instruction (instruction,016);
+ break;
+ case ISLEU:
+ as_set_condition_instruction (instruction,006);
+ break;
+ case ISLT:
+ as_set_condition_instruction (instruction,014);
+ break;
+ case ISLTU:
+ as_set_condition_instruction (instruction,002);
+ break;
+ case ISNE:
+ as_set_condition_instruction (instruction,005);
+ break;
+ case ISO:
+ as_set_condition_instruction (instruction,0);
+ break;
+ case ISNO:
+ as_set_condition_instruction (instruction,1);
+ break;
+ case ICMPW:
+ as_cmp_instruction (instruction,SIZE_WORD);
+ break;
+ case ITST:
+ as_tst_instruction (instruction);
+ break;
+ case IBTST:
+ as_btst_instruction (instruction);
+ break;
+ case IMOVEW:
+ as_movew_instruction (instruction);
+ break;
+ case IMOVESW:
+ as_movesw_instruction (instruction);
+ break;
+ case IMOVEB:
+ as_moveb_instruction (instruction);
+ break;
+ case IEXG:
+ as_exg_instruction (instruction);
+ break;
+ case INEG:
+ as_neg_instruction (instruction);
+ break;
+ case INOT:
+ as_not_instruction (instruction);
+ break;
+ case IADC:
+ as_adc_instruction (instruction);
+ break;
+ case ISBB:
+ as_sbb_instruction (instruction);
+ break;
+ case IMULUD:
+ as_mulud_instruction (instruction);
+ break;
+ case IDIVDU:
+ as_divdu_instruction (instruction);
+ break;
+ case IWORD:
+ store_c (instruction->instruction_parameters[0].parameter_data.i);
+ break;
+ case IFMOVE:
+ as_fmove_instruction (instruction);
+ break;
+ case IFADD:
+ as_dyadic_float_instruction (instruction,0xf2,0x58);
+ break;
+ case IFSUB:
+ as_dyadic_float_instruction (instruction,0xf2,0x5c);
+ break;
+ case IFCMP:
+ as_dyadic_float_instruction (instruction,0x66,0x2f);
+ break;
+ case IFDIV:
+ as_dyadic_float_instruction (instruction,0xf2,0x5e);
+ break;
+ case IFMUL:
+ as_dyadic_float_instruction (instruction,0xf2,0x59);
+ break;
+ case IFBEQ:
+ as_float_branch_instruction (instruction,0);
+ break;
+ case IFBGE:
+ as_float_branch_instruction (instruction,5);
+ break;
+ case IFBGT:
+ as_float_branch_instruction (instruction,2);
+ break;
+ case IFBLE:
+ as_float_branch_instruction (instruction,4);
+ break;
+ case IFBLT:
+ as_float_branch_instruction (instruction,1);
+ break;
+ case IFBNE:
+ as_float_branch_instruction (instruction,3);
+ break;
+ case IFMOVEL:
+ as_fmovel_instruction (instruction);
+ break;
+ case IFSQRT:
+ as_dyadic_float_instruction (instruction,0xf2,0x51);
+ break;
+ case IFNEG:
+ as_float_neg_instruction (instruction,0xe0);
+ break;
+ case IFSEQ:
+ as_set_float_condition_instruction (instruction,0);
+ break;
+ case IFSGE:
+ as_set_float_condition_instruction (instruction,5);
+ break;
+ case IFSGT:
+ as_set_float_condition_instruction (instruction,2);
+ break;
+ case IFSLE:
+ as_set_float_condition_instruction (instruction,4);
+ break;
+ case IFSLT:
+ as_set_float_condition_instruction (instruction,1);
+ break;
+ case IFSNE:
+ as_set_float_condition_instruction (instruction,3);
+ break;
+ case IRTSI:
+ as_rtsi_instruction (instruction);
+ break;
+ default:
+ internal_error_in_function ("as_instructions");
+ }
+ instruction=instruction->instruction_next;
+ }
+}
+
+static void as_garbage_collect_test (struct basic_block *block)
+{
+ LONG n_cells;
+ struct call_and_jump *new_call_and_jump;
+
+ n_cells=block->block_n_new_heap_cells;
+
+ new_call_and_jump=allocate_memory_from_heap (sizeof (struct call_and_jump));
+ new_call_and_jump->cj_next=NULL;
+
+ switch (block->block_n_begin_a_parameter_registers){
+ case 0:
+ new_call_and_jump->cj_call_label=collect_0_label;
+ break;
+ case 1:
+ new_call_and_jump->cj_call_label=collect_1_label;
+ break;
+ case 2:
+ new_call_and_jump->cj_call_label=collect_2_label;
+ break;
+ case 3:
+ new_call_and_jump->cj_call_label=collect_3_label;
+ break;
+ default:
+ internal_error_in_function ("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;
+
+ as_i_r2 (0201,0050,0055,n_cells,REGISTER_R15); /* sub */
+
+ store_c (0x0f);
+ store_c (0x8c); /* jl */
+ store_l (0);
+ as_branch_label (&new_call_and_jump->cj_label,BRANCH_RELOCATION);
+
+ new_call_and_jump->cj_jump.label_flags=0;
+ new_call_and_jump->cj_jump.label_id=TEXT_LABEL_ID;
+#ifdef FUNCTION_LEVEL_LINKING
+ new_call_and_jump->cj_jump.label_object_label=code_object_label;
+#endif
+ new_call_and_jump->cj_jump.label_offset=CURRENT_CODE_OFFSET;
+}
+
+static void as_call_and_jump (struct call_and_jump *call_and_jump)
+{
+ call_and_jump->cj_label.label_flags=0;
+ call_and_jump->cj_label.label_id=TEXT_LABEL_ID;
+#ifdef FUNCTION_LEVEL_LINKING
+ call_and_jump->cj_label.label_object_label=code_object_label;
+#endif
+ call_and_jump->cj_label.label_offset=CURRENT_CODE_OFFSET;
+
+ store_c (0350); /* call */
+ store_l (0);
+ as_branch_label (call_and_jump->cj_call_label,CALL_RELOCATION);
+
+ store_c (0351); /* jmp */
+ store_l (0);
+ as_branch_label (&call_and_jump->cj_jump,JUMP_RELOCATION);
+}
+
+static void as_check_stack (struct basic_block *block)
+{
+ if (block->block_a_stack_check_size>0){
+ if (block->block_a_stack_check_size<=32)
+ as_r_a (0073,A_STACK_POINTER,end_a_stack_label); /* cmp */
+ else {
+ as_id_r (0215,block->block_a_stack_check_size,A_STACK_POINTER,REGISTER_O0); /* lea */
+ as_r_a (0073,REGISTER_O0,end_a_stack_label); /* cmp */
+ }
+
+ store_c (0x0f);
+ store_c (0x83); /* jae */
+ store_l (0);
+ as_branch_label (stack_overflow_label,BRANCH_RELOCATION);
+ }
+
+ if (block->block_b_stack_check_size>0){
+ if (block->block_b_stack_check_size<=32)
+ as_r_a (0073,B_STACK_POINTER,end_b_stack_label); /* cmp */
+ else {
+ as_id_r (0215,block->block_b_stack_check_size,B_STACK_POINTER,REGISTER_O0); /* lea */
+ as_r_a (0073,REGISTER_O0,end_b_stack_label); /* cmp */
+ }
+
+ store_c (0x0f);
+ store_c (0x82); /* jb */
+ store_l (0);
+ as_branch_label (stack_overflow_label,BRANCH_RELOCATION);
+ }
+}
+
+static void as_profile_call (struct basic_block *block)
+{
+ LABEL *profile_label;
+
+ as_move_d_r (block->block_profile_function_label,0,REGISTER_A4);
+
+ if (block->block_n_node_arguments>-100)
+ profile_label=block->block_profile==2 ? profile_n2_label : profile_n_label;
+ else {
+ switch (block->block_profile){
+ case 2: profile_label=profile_s2_label; break;
+ case 4: profile_label=profile_l_label; break;
+ case 5: profile_label=profile_l2_label; break;
+ default: profile_label=profile_s_label;
+ }
+ }
+ store_c (0350); /* call */
+ store_l (0);
+ as_branch_label (profile_label,CALL_RELOCATION);
+}
+
+#ifdef NEW_APPLY
+extern LABEL *add_empty_node_labels[];
+
+static void as_apply_update_entry (struct basic_block *block)
+{
+ if (block->block_profile)
+ as_profile_call (block);
+
+ if (block->block_n_node_arguments==-200){
+ store_c (0351); /* jmp */
+ store_l (0);
+ as_branch_label (block->block_ea_label,JUMP_RELOCATION);
+
+ store_c (0x90);
+ store_c (0x90);
+ store_c (0x90);
+ store_c (0x90);
+ store_c (0x90);
+ } else {
+ store_c (0350); /* call */
+ store_l (0);
+ as_branch_label (add_empty_node_labels[block->block_n_node_arguments+200],CALL_RELOCATION);
+
+ store_c (0351); /* jmp */
+ store_l (0);
+ as_branch_label (block->block_ea_label,JUMP_RELOCATION);
+ }
+
+ if (!block->block_profile){
+ store_c (0x90);
+ store_c (0x90);
+ }
+}
+#endif
+
+static void write_code (void)
+{
+ struct basic_block *block;
+ struct call_and_jump *call_and_jump;
+
+#ifdef FUNCTION_LEVEL_LINKING
+ if (first_block!=NULL && !(first_block->block_begin_module && !first_block->block_link_module))
+ first_block->block_begin_module=1;
+#endif
+
+ for_l (block,first_block,block_next){
+#ifdef FUNCTION_LEVEL_LINKING
+ if (block->block_begin_module){
+ if (block->block_link_module){
+ if (code_object_label!=NULL && CURRENT_CODE_OFFSET!=code_object_label->object_label_offset && block->block_labels){
+#ifdef OPTIMISE_BRANCHES
+ {
+ struct relocation *new_relocation;
+ int align;
+
+ new_relocation=fast_memory_allocate_type (struct relocation);
+
+ *last_code_relocation_l=new_relocation;
+ last_code_relocation_l=&new_relocation->next;
+ new_relocation->next=NULL;
+
+ align=3 & -(CURRENT_CODE_OFFSET-code_object_label->object_label_offset);
+
+ U5 (new_relocation,
+ relocation_offset=CURRENT_CODE_OFFSET,
+ relocation_kind=ALIGN_RELOCATION,
+ relocation_align1=align,
+ relocation_align2=align,
+ relocation_object_label=code_object_label);
+ }
+#endif
+#if 1
+ switch (3 & -(CURRENT_CODE_OFFSET-code_object_label->object_label_offset)){
+ case 0:
+ break;
+ case 1:
+ store_c (0x90);
+ break;
+ case 2:
+ store_c (0x48);
+ store_c (0x90);
+ break;
+ case 3:
+ store_c (0x48);
+ store_c (0213);
+ store_c (0300 | (reg_num (EBP)<<3) | reg_num (EBP));
+ break;
+ }
+#else
+ while (((CURRENT_CODE_OFFSET-code_object_label->object_label_offset) & 3)!=0)
+ store_c (0x90);
+#endif
+ {
+ struct relocation *new_relocation;
+
+ new_relocation=fast_memory_allocate_type (struct relocation);
+
+ *last_code_relocation_l=new_relocation;
+ last_code_relocation_l=&new_relocation->next;
+ new_relocation->next=NULL;
+
+ U4 (new_relocation,
+ relocation_label=block->block_labels->block_label_label,
+ relocation_offset=CURRENT_CODE_OFFSET,
+ relocation_object_label=code_object_label,
+ relocation_kind=DUMMY_BRANCH_RELOCATION);
+ }
+#ifdef FUNCTION_LEVEL_LINKING
+ as_new_code_module();
+#endif
+ *(struct object_label**)&block->block_last_instruction = code_object_label;
+ } else
+ *(struct object_label**)&block->block_last_instruction = NULL;
+ } else {
+#ifdef FUNCTION_LEVEL_LINKING
+ as_new_code_module();
+#endif
+ *(struct object_label**)&block->block_last_instruction = code_object_label;
+ }
+ } else
+ *(struct object_label**)&block->block_last_instruction = NULL;
+#endif
+
+ if (block->block_n_node_arguments>-100){
+#ifndef FUNCTION_LEVEL_LINKING
+# ifdef OPTIMISE_BRANCHES
+ {
+ struct relocation *new_relocation;
+ int align;
+
+ new_relocation=fast_memory_allocate_type (struct relocation);
+
+ *last_code_relocation_l=new_relocation;
+ last_code_relocation_l=&new_relocation->next;
+ new_relocation->next=NULL;
+
+ align=code_buffer_free & 3;
+
+ U4 (new_relocation,
+ relocation_offset=CURRENT_CODE_OFFSET,
+ relocation_kind=ALIGN_RELOCATION,
+ relocation_align1=align,
+ relocation_align2=align);
+ }
+# endif
+
+ while ((code_buffer_free & 3)!=0)
+ store_c (0x90);
+#endif
+
+ if (block->block_ea_label!=NULL){
+ extern LABEL *eval_fill_label,*eval_upd_labels[];
+ 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){
+ as_move_l_r (block->block_ea_label,REGISTER_A4);
+
+ store_c (0351);
+ store_l (0);
+ as_branch_label (eval_upd_labels[n_node_arguments],JUMP_RELOCATION);
+ } else {
+ as_move_l_r (block->block_profile_function_label,REGISTER_A4);
+
+ store_c (0351);
+ store_l (-8);
+ as_branch_label (eval_upd_labels[n_node_arguments],JUMP_RELOCATION);
+
+ as_move_l_r (block->block_ea_label,REGISTER_D0);
+
+ store_c (0xeb);
+ store_c (-21);
+
+ store_c (0x90);
+ store_c (0x90);
+ store_c (0x90);
+ }
+ } else {
+ as_move_l_r (block->block_ea_label,REGISTER_D0);
+
+ store_c (0377);
+ store_c (0340 | reg_num (REGISTER_D0)); /* jmp d0 */
+
+ store_c (0x90);
+ store_c (0x90);
+ store_c (0x90);
+ }
+
+ if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)){
+ store_l (0);
+ store_label_in_code_section (block->block_descriptor);
+ } else
+ store_l (0);
+ } else
+ if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)){
+ store_l (0);
+ store_label_in_code_section (block->block_descriptor);
+ }
+ /* else
+ store_l (0);
+ */
+
+ store_l (block->block_n_node_arguments);
+ }
+#ifdef NEW_APPLY
+ else if (block->block_n_node_arguments<-100)
+ as_apply_update_entry (block);
+#endif
+
+ as_labels (block->block_labels);
+
+ if (block->block_profile)
+ as_profile_call (block);
+
+ if (block->block_n_new_heap_cells>0)
+ as_garbage_collect_test (block);
+
+ if (check_stack && (block->block_a_stack_check_size>0 || block->block_b_stack_check_size>0))
+ as_check_stack (block);
+
+ as_instructions (block->block_instructions);
+ }
+
+ for_l (call_and_jump,first_call_and_jump,cj_next){
+#ifdef FUNCTION_LEVEL_LINKING
+ as_new_code_module();
+#endif
+ as_call_and_jump (call_and_jump);
+ }
+}
+
+static void write_string_8 (char *string)
+{
+ int i;
+
+ i=0;
+
+ while (i<8){
+ char c;
+
+ c=string[i++];
+ write_c (c);
+
+ if (c=='\0'){
+ while (i<8){
+ write_c ('\0');
+ ++i;
+ }
+ return;
+ }
+ }
+}
+
+#ifdef ELF
+static void write_zstring (char *string)
+{
+ char c;
+
+ do {
+ c=*string++;
+ write_c (c);
+ } while (c!='\0');
+}
+#endif
+
+extern char *this_module_name;
+
+#if defined (ELF) && defined (FUNCTION_LEVEL_LINKING)
+static int compute_section_strings_size (int string_size_without_digits,int n_sections)
+{
+ int section_strings_size,max_n_digits,power10_max_n_digits;
+
+ section_strings_size=0;
+ max_n_digits=1;
+ power10_max_n_digits=10;
+ while (n_sections>power10_max_n_digits){
+ section_strings_size-=power10_max_n_digits;
+ ++max_n_digits;
+ power10_max_n_digits*=10;
+ }
+ section_strings_size+=(string_size_without_digits+max_n_digits+1)*n_sections;
+
+ return section_strings_size;
+}
+
+static int n_digits (int n)
+{
+ int i,power10;
+
+ i=1;
+ power10=10;
+
+ while (n>=power10){
+ ++i;
+ power10*=10;
+ }
+
+ return i;
+}
+
+static int n_sections;
+#endif
+
+static void write_file_header_and_section_headers (void)
+{
+#ifndef ELF
+ int end_section_headers_offset;
+
+ write_w (0x8664);
+# ifdef FUNCTION_LEVEL_LINKING
+ write_w (n_code_sections+n_data_sections);
+ end_section_headers_offset=20+40*(n_code_sections+n_data_sections);
+# else
+ write_w (2);
+ end_section_headers_offset=100;
+# endif
+ write_l (0);
+ write_l (end_section_headers_offset+code_buffer_offset+data_buffer_offset+(n_code_relocations+n_data_relocations)*10);
+ write_l (n_object_labels);
+ write_w (0);
+ write_w (0x104);
+
+# ifdef FUNCTION_LEVEL_LINKING
+ {
+ struct object_label *object_label,*previous_code_object_label;
+ int code_offset,code_file_offset,code_relocations_offset;
+ struct relocation *code_relocation;
+
+ code_relocation=first_code_relocation;
+ code_offset=0;
+ code_file_offset=end_section_headers_offset;
+ code_relocations_offset=code_file_offset+code_buffer_offset+data_buffer_offset;
+
+ previous_code_object_label=NULL;
+
+ for_l (object_label,first_object_label,next){
+ if (object_label->object_label_kind==CODE_CONTROL_SECTION){
+ if (previous_code_object_label!=NULL){
+ int code_section_length,n_code_relocations_in_section;
+
+ code_section_length=object_label->object_label_offset-code_offset;
+
+ n_code_relocations_in_section=0;
+ while (code_relocation!=NULL &&
+ (code_relocation->relocation_offset < code_offset+code_section_length
+ || (code_relocation->relocation_offset==code_offset+code_section_length && code_relocation->relocation_kind==DUMMY_BRANCH_RELOCATION)))
+ {
+ code_relocation->relocation_offset-=code_offset;
+ ++n_code_relocations_in_section;
+
+ code_relocation=code_relocation->next;
+ }
+
+ previous_code_object_label->object_label_length=code_section_length;
+ previous_code_object_label->object_label_n_relocations=n_code_relocations_in_section;
+
+ write_string_8 (".text");
+
+ write_l (0);
+ write_l (0);
+ write_l (code_section_length);
+ write_l (code_file_offset+code_offset);
+
+ code_offset+=code_section_length;
+
+ write_l (code_relocations_offset);
+ write_l (0);
+ write_w (n_code_relocations_in_section);
+ write_w (0);
+ write_l ((3<<20)+0x20);
+
+ code_relocations_offset+=10*n_code_relocations_in_section;
+ }
+
+ previous_code_object_label=object_label;
+ }
+ }
+
+ if (previous_code_object_label!=NULL){
+ int code_section_length,n_code_relocations_in_section;
+
+ code_section_length=code_buffer_offset-code_offset;
+
+ n_code_relocations_in_section=0;
+ while (code_relocation!=NULL){
+ code_relocation->relocation_offset-=code_offset;
+ ++n_code_relocations_in_section;
+
+ code_relocation=code_relocation->next;
+ }
+
+ previous_code_object_label->object_label_n_relocations=n_code_relocations_in_section;
+ previous_code_object_label->object_label_length=code_section_length;
+
+ write_string_8 (".text");
+
+ write_l (0);
+ write_l (0);
+ write_l (code_section_length);
+ write_l (code_file_offset+code_offset);
+
+ write_l (code_relocations_offset);
+ write_l (0);
+ write_w (n_code_relocations_in_section);
+ write_w (0);
+ write_l ((3<<20)+0x20);
+ }
+ }
+# else
+ write_string_8 (".text");
+
+ write_l (0);
+ write_l (0);
+ write_l (code_buffer_offset);
+ write_l (end_section_headers_offset);
+ write_l (end_section_headers_offset+code_buffer_offset+data_buffer_offset);
+ write_l (0);
+ write_w (n_code_relocations);
+ write_w (0);
+ write_l (0x20);
+# endif
+
+# ifdef FUNCTION_LEVEL_LINKING
+ {
+ struct object_label *object_label,*previous_data_object_label;
+ int data_offset,data_file_offset,data_relocations_offset;
+ struct relocation *data_relocation;
+
+ data_relocation=first_data_relocation;
+ data_offset=0;
+ data_file_offset=end_section_headers_offset+code_buffer_offset;
+ data_relocations_offset=data_file_offset+data_buffer_offset+n_code_relocations*10;
+
+ previous_data_object_label=NULL;
+
+ for_l (object_label,first_object_label,next){
+ if (object_label->object_label_kind==DATA_CONTROL_SECTION){
+ if (previous_data_object_label!=NULL){
+ int data_section_length,n_data_relocations_in_section;
+
+ data_section_length=object_label->object_label_offset-data_offset;
+
+ n_data_relocations_in_section=0;
+ while (data_relocation!=NULL && data_relocation->relocation_offset < data_offset+data_section_length){
+ data_relocation->relocation_offset-=data_offset;
+ ++n_data_relocations_in_section;
+
+ data_relocation=data_relocation->next;
+ }
+
+ previous_data_object_label->object_label_length=data_section_length;
+ previous_data_object_label->object_label_n_relocations=n_data_relocations_in_section;
+
+ write_string_8 (".data");
+
+ write_l (0);
+ write_l (0);
+ write_l (data_section_length);
+ write_l (data_file_offset+data_offset);
+
+ data_offset+=data_section_length;
+
+ write_l (data_relocations_offset);
+ write_l (0);
+ write_w (n_data_relocations_in_section);
+ write_w (0);
+ write_l (((1+previous_data_object_label->object_section_align)<<20)+0x40);
+
+ data_relocations_offset+=10*n_data_relocations_in_section;
+ }
+
+ previous_data_object_label=object_label;
+ }
+ }
+
+ if (previous_data_object_label!=NULL){
+ int data_section_length,n_data_relocations_in_section;
+
+ data_section_length=data_buffer_offset-data_offset;
+
+ n_data_relocations_in_section=0;
+ while (data_relocation!=NULL){
+ data_relocation->relocation_offset-=data_offset;
+ ++n_data_relocations_in_section;
+
+ data_relocation=data_relocation->next;
+ }
+
+ previous_data_object_label->object_label_n_relocations=n_data_relocations_in_section;
+ previous_data_object_label->object_label_length=data_section_length;
+
+ write_string_8 (".data");
+
+ write_l (0);
+ write_l (0);
+ write_l (data_section_length);
+ write_l (data_file_offset+data_offset);
+
+ write_l (data_relocations_offset);
+ write_l (0);
+ write_w (n_data_relocations_in_section);
+ write_w (0);
+ write_l (((1+previous_data_object_label->object_section_align)<<20)+0x40);
+ }
+ }
+# else
+ write_string_8 (".data");
+
+ write_l (0);
+ write_l (0);
+ write_l (data_buffer_offset);
+ write_l (end_section_headers_offset+code_buffer_offset);
+ write_l (end_section_headers_offset+code_buffer_offset+data_buffer_offset+n_code_relocations*10);
+ write_l (0);
+ write_w (n_data_relocations);
+ write_w (0);
+ write_l (0x40);
+# endif
+#else
+ unsigned int offset;
+ int n_code_relocation_sections,n_data_relocation_sections;
+ int section_strings_size;
+
+# ifdef FUNCTION_LEVEL_LINKING
+ n_sections=n_code_sections+n_data_sections;
+
+ {
+ struct object_label *object_label,*previous_code_object_label,*previous_data_object_label;
+ struct relocation *code_relocation,*data_relocation;
+ int code_offset,data_offset;
+
+ code_relocation=first_code_relocation;
+ code_offset=0;
+ n_code_relocation_sections=0;
+ previous_code_object_label=NULL;
+
+ data_relocation=first_data_relocation;
+ data_offset=0;
+ n_data_relocation_sections=0;
+ previous_data_object_label=NULL;
+
+ section_strings_size=0;
+
+ for_l (object_label,first_object_label,next){
+ if (object_label->object_label_kind==CODE_CONTROL_SECTION){
+ if (previous_code_object_label!=NULL){
+ int code_section_length,n_code_relocations_in_section;
+
+ code_section_length=object_label->object_label_offset-code_offset;
+
+ n_code_relocations_in_section=0;
+ while (code_relocation!=NULL &&
+ (code_relocation->relocation_offset < code_offset+code_section_length
+ || (code_relocation->relocation_offset==code_offset+code_section_length && code_relocation->relocation_kind==DUMMY_BRANCH_RELOCATION)))
+ {
+ code_relocation->relocation_offset-=code_offset;
+ ++n_code_relocations_in_section;
+
+ code_relocation=code_relocation->next;
+ }
+
+ previous_code_object_label->object_label_length=code_section_length;
+ previous_code_object_label->object_label_n_relocations=n_code_relocations_in_section;
+
+ code_offset+=code_section_length;
+ if (n_code_relocations_in_section>0){
+ section_strings_size+=12+n_digits (previous_code_object_label->object_label_section_n);
+ ++n_code_relocation_sections;
+ }
+ }
+
+ previous_code_object_label=object_label;
+ } else if (object_label->object_label_kind==DATA_CONTROL_SECTION){
+ if (previous_data_object_label!=NULL){
+ int data_section_length,n_data_relocations_in_section;
+
+ data_section_length=object_label->object_label_offset-data_offset;
+
+ n_data_relocations_in_section=0;
+ while (data_relocation!=NULL && data_relocation->relocation_offset < data_offset+data_section_length){
+ data_relocation->relocation_offset-=data_offset;
+ ++n_data_relocations_in_section;
+
+ data_relocation=data_relocation->next;
+ }
+
+ previous_data_object_label->object_label_length=data_section_length;
+ previous_data_object_label->object_label_n_relocations=n_data_relocations_in_section;
+
+ data_offset+=data_section_length;
+ if (n_data_relocations_in_section>0){
+ section_strings_size+=12+n_digits (previous_data_object_label->object_label_section_n);
+ ++n_data_relocation_sections;
+ }
+ }
+
+ previous_data_object_label=object_label;
+ }
+ }
+
+ if (previous_code_object_label!=NULL){
+ int code_section_length,n_code_relocations_in_section;
+
+ code_section_length=code_buffer_offset-code_offset;
+
+ n_code_relocations_in_section=0;
+ while (code_relocation!=NULL){
+ code_relocation->relocation_offset-=code_offset;
+ ++n_code_relocations_in_section;
+
+ code_relocation=code_relocation->next;
+ }
+
+ previous_code_object_label->object_label_n_relocations=n_code_relocations_in_section;
+ previous_code_object_label->object_label_length=code_section_length;
+
+ if (n_code_relocations_in_section>0){
+ section_strings_size+=12+n_digits (previous_code_object_label->object_label_section_n);
+ ++n_code_relocation_sections;
+ }
+ }
+
+ if (previous_data_object_label!=NULL){
+ int data_section_length,n_data_relocations_in_section;
+
+ data_section_length=data_buffer_offset-data_offset;
+
+ n_data_relocations_in_section=0;
+ while (data_relocation!=NULL){
+ data_relocation->relocation_offset-=data_offset;
+ ++n_data_relocations_in_section;
+
+ data_relocation=data_relocation->next;
+ }
+
+ previous_data_object_label->object_label_n_relocations=n_data_relocations_in_section;
+ previous_data_object_label->object_label_length=data_section_length;
+
+ if (n_data_relocations_in_section>0){
+ section_strings_size+=12+n_digits (previous_data_object_label->object_label_section_n);
+ ++n_data_relocation_sections;
+ }
+ }
+ }
+
+ section_strings_size+=compute_section_strings_size (7,n_code_sections)+
+ compute_section_strings_size (7,n_data_sections);
+# endif
+
+ write_l (0x464c457f);
+ write_l (0x00010101);
+ write_l (0);
+ write_l (0);
+ write_l (0x00030001);
+ write_l (1);
+ write_l (0);
+ write_l (0);
+ write_l (0x34);
+ write_l (0);
+ write_l (0x00000034);
+ write_l (0x00280000);
+# ifdef FUNCTION_LEVEL_LINKING
+ write_l (0x00010000 | (n_sections+n_code_relocation_sections+n_data_relocation_sections+4));
+# else
+ write_l (0x00010008);
+# endif
+
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+# ifdef FUNCTION_LEVEL_LINKING
+ offset=0xd4+40*(n_sections+n_code_relocation_sections+n_data_relocation_sections);
+# else
+ offset=0x174;
+# endif
+
+ write_l (1);
+ write_l (SHT_STRTAB);
+ write_l (0);
+ write_l (0);
+ write_l (offset);
+# ifdef FUNCTION_LEVEL_LINKING
+ write_l ((27+section_strings_size+3) & -4);
+# else
+ write_l (60);
+# endif
+ write_l (0);
+ write_l (0);
+ write_l (1);
+ write_l (0);
+# ifdef FUNCTION_LEVEL_LINKING
+ offset+=(27+section_strings_size+3) & -4;
+# else
+ offset+=60;
+# endif
+# ifdef FUNCTION_LEVEL_LINKING
+ {
+ struct object_label *object_label;
+ int code_offset,data_offset,code_relocations_offset,data_relocations_offset,section_string_offset;
+
+ code_offset=0;
+ section_string_offset=11;
+
+ for_l (object_label,first_object_label,next){
+ if (object_label->object_label_kind==CODE_CONTROL_SECTION){
+ int code_section_length;
+
+ code_section_length=object_label->object_label_length;
+
+ write_l (section_string_offset);
+ write_l (SHT_PROGBITS);
+ write_l (SHF_ALLOC | SHF_EXECINSTR);
+ write_l (0);
+ write_l (offset+code_offset);
+ write_l (code_section_length);
+ write_l (0);
+ write_l (0);
+ write_l (4);
+ write_l (0);
+
+ section_string_offset+=8+n_digits (object_label->object_label_section_n);
+ code_offset+=code_section_length;
+ }
+ }
+ offset+=(code_offset+3) & -4;
+
+ data_offset=0;
+
+ for_l (object_label,first_object_label,next){
+ if (object_label->object_label_kind==DATA_CONTROL_SECTION){
+ int data_section_length;
+
+ data_section_length=object_label->object_label_length;
+
+ write_l (section_string_offset);
+ write_l (SHT_PROGBITS);
+ write_l (SHF_ALLOC | SHF_WRITE);
+ write_l (0);
+ write_l (offset+data_offset);
+ write_l (data_section_length);
+ write_l (0);
+ write_l (0);
+ write_l (1<<object_label->object_section_align);
+ write_l (0);
+
+ section_string_offset+=8+n_digits (object_label->object_label_section_n);
+ data_offset+=data_section_length;
+ }
+ }
+
+ offset+=(data_offset+3) & -4;
+
+ code_relocations_offset=0;
+
+ for_l (object_label,first_object_label,next){
+ if (object_label->object_label_kind==CODE_CONTROL_SECTION){
+ int n_code_relocations_in_section;
+
+ n_code_relocations_in_section=object_label->object_label_n_relocations;
+
+ if (n_code_relocations_in_section>0){
+ write_l (section_string_offset);
+ write_l (SHT_REL);
+ write_l (0);
+ write_l (0);
+ write_l (offset+code_relocations_offset);
+ write_l (8*n_code_relocations_in_section);
+ write_l (n_sections+n_code_relocation_sections+n_data_relocation_sections+2);
+ write_l (2+object_label->object_label_section_n);
+ write_l (4);
+ write_l (8);
+ section_string_offset+=12+n_digits (object_label->object_label_section_n);
+ code_relocations_offset+=8*n_code_relocations_in_section;
+ }
+ }
+ }
+ offset+=8*n_code_relocations;
+
+ data_relocations_offset=0;
+
+ for_l (object_label,first_object_label,next){
+ if (object_label->object_label_kind==DATA_CONTROL_SECTION){
+ int n_data_relocations_in_section;
+
+ n_data_relocations_in_section=object_label->object_label_n_relocations;
+
+ if (n_data_relocations_in_section>0){
+ write_l (section_string_offset);
+ write_l (SHT_REL);
+ write_l (0);
+ write_l (0);
+ write_l (offset+data_relocations_offset);
+ write_l (8*n_data_relocations_in_section);
+ write_l (n_sections+n_code_relocation_sections+n_data_relocation_sections+2);
+ write_l (2+n_code_sections+object_label->object_label_section_n);
+ write_l (4);
+ write_l (8);
+ section_string_offset+=12+n_digits (object_label->object_label_section_n);
+ data_relocations_offset+=8*n_data_relocations_in_section;
+ }
+ }
+ }
+ offset+=8*n_data_relocations;
+ }
+# else
+ write_l (11);
+ write_l (SHT_PROGBITS);
+ write_l (SHF_ALLOC | SHF_EXECINSTR);
+ write_l (0);
+ write_l (offset);
+ write_l (code_buffer_offset);
+ write_l (0);
+ write_l (0);
+ write_l (4);
+ write_l (0);
+ offset+=(code_buffer_offset+3 ) & ~3;
+
+ write_l (17);
+ write_l (SHT_PROGBITS);
+ write_l (SHF_ALLOC | SHF_WRITE);
+ write_l (0);
+ write_l (offset);
+ write_l (data_buffer_offset);
+ write_l (0);
+ write_l (0);
+ write_l (4);
+ write_l (0);
+ offset+=(data_buffer_offset+3) & ~3;
+
+ write_l (23);
+ write_l (SHT_REL);
+ write_l (0);
+ write_l (0);
+ write_l (offset);
+ write_l (8*n_code_relocations);
+ write_l (6);
+ write_l (2);
+ write_l (4);
+ write_l (8);
+ offset+=8*n_code_relocations;
+
+ write_l (33);
+ write_l (SHT_REL);
+ write_l (0);
+ write_l (0);
+ write_l (offset);
+ write_l (8*n_data_relocations);
+ write_l (6);
+ write_l (3);
+ write_l (4);
+ write_l (8);
+ offset+=8*n_data_relocations;
+# endif
+
+# ifdef FUNCTION_LEVEL_LINKING
+ write_l (11+section_strings_size);
+# else
+ write_l (43);
+# endif
+ write_l (SHT_SYMTAB);
+ write_l (0);
+ write_l (0);
+ write_l (offset);
+# ifdef FUNCTION_LEVEL_LINKING
+ write_l (16*(n_object_labels+n_sections));
+ write_l (n_sections+n_code_relocation_sections+n_data_relocation_sections+3);
+ write_l (1+n_sections);
+# else
+ write_l (16*n_object_labels);
+ write_l (7);
+ write_l (3);
+# endif
+ write_l (4);
+ write_l (16);
+# ifdef FUNCTION_LEVEL_LINKING
+ offset+=16*(n_object_labels+n_sections);
+# else
+ offset+=16*n_object_labels;
+# endif
+
+# ifdef FUNCTION_LEVEL_LINKING
+ write_l (19+section_strings_size);
+# else
+ write_l (51);
+# endif
+ write_l (SHT_STRTAB);
+ write_l (0);
+ write_l (0);
+ write_l (offset);
+ write_l (string_table_offset);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+
+ write_c (0);
+ write_zstring (".shstrtab");
+# ifdef FUNCTION_LEVEL_LINKING
+ {
+ struct object_label *object_label;
+ int section_n;
+ char section_name[20];
+
+ for (section_n=0; section_n<n_code_sections; ++section_n){
+ sprintf (section_name,".text.m%d",section_n);
+ write_zstring (section_name);
+ }
+
+ for (section_n=0; section_n<n_data_sections; ++section_n){
+ sprintf (section_name,".data.m%d",section_n);
+ write_zstring (section_name);
+ }
+
+ for_l (object_label,first_object_label,next)
+ if (object_label->object_label_kind==CODE_CONTROL_SECTION && object_label->object_label_n_relocations>0){
+ sprintf (section_name,".rel.text.m%d",object_label->object_label_section_n);
+ write_zstring (section_name);
+ }
+
+ for_l (object_label,first_object_label,next)
+ if (object_label->object_label_kind==DATA_CONTROL_SECTION && object_label->object_label_n_relocations>0){
+ sprintf (section_name,".rel.data.m%d",object_label->object_label_section_n);
+ write_zstring (section_name);
+ }
+ }
+# else
+ write_zstring (".text");
+ write_zstring (".data");
+ write_zstring (".rel.text");
+ write_zstring (".rel.data");
+# endif
+ write_zstring (".symtab");
+ write_zstring (".strtab");
+
+ if (((27+section_strings_size) & 3)!=0){
+ int n;
+
+ n=4-((27+section_strings_size) & 3);
+ do {
+ write_c (0);
+ } while (--n);
+ }
+#endif
+}
+
+#if defined (OPTIMISE_BRANCHES)
+static int search_short_branches (void)
+{
+ struct relocation *relocation;
+ struct object_buffer *object_buffer;
+ int code_buffer_offset,offset_difference;
+ struct label *label;
+ int instruction_offset,found_new_short_branch;
+ LONG v;
+
+ found_new_short_branch=0;
+ offset_difference=0;
+
+ object_buffer=first_code_buffer;
+ code_buffer_offset=0;
+
+ for_l (relocation,first_code_relocation,next){
+ switch (relocation->relocation_kind){
+ case JUMP_RELOCATION:
+ case BRANCH_RELOCATION:
+ label=relocation->relocation_label;
+
+ if (label->label_id!=TEXT_LABEL_ID)
+ break;
+
+#ifdef FUNCTION_LEVEL_LINKING
+ if (label->label_object_label!=relocation->relocation_object_label)
+ break;
+#endif
+ instruction_offset=relocation->relocation_offset;
+
+ while (instruction_offset >= code_buffer_offset+BUFFER_SIZE){
+ object_buffer=object_buffer->next;
+ code_buffer_offset+=BUFFER_SIZE;
+ }
+
+ v=label->label_offset-(instruction_offset-offset_difference);
+ if (relocation->relocation_kind==JUMP_RELOCATION)
+ --v;
+
+ if (instruction_offset-code_buffer_offset<=BUFFER_SIZE-4)
+ v += *(LONG*)(object_buffer->data+(instruction_offset-code_buffer_offset));
+ else {
+ unsigned char *p0,*p1,*p2,*p3,*end_buffer;
+
+ p0=object_buffer->data+(instruction_offset-code_buffer_offset);
+ end_buffer=object_buffer->data+BUFFER_SIZE;
+ p1=p0+1;
+ if (p1==end_buffer)
+ p1=object_buffer->next->data;
+ p2=p1+1;
+ if (p2==end_buffer)
+ p2=object_buffer->next->data;
+ p3=p2+1;
+ if (p3==end_buffer)
+ p3=object_buffer->next->data;
+
+ v+= (*p0) | (*p1<<8) | (*p2<<16) | (*p3<<24);
+ }
+
+ if (v>=-128 && v<=127){
+ if (relocation->relocation_kind==JUMP_RELOCATION)
+ relocation->relocation_kind=NEW_SHORT_JUMP_RELOCATION;
+ else
+ relocation->relocation_kind=NEW_SHORT_BRANCH_RELOCATION;
+ found_new_short_branch=1;
+ }
+
+ break;
+ case CALL_RELOCATION:
+ case LONG_WORD_RELOCATION:
+ case PC_RELATIVE_LONG_WORD_RELOCATION:
+#ifdef FUNCTION_LEVEL_LINKING
+ case DUMMY_BRANCH_RELOCATION:
+#endif
+ case BRANCH_SKIP_BRANCH_RELOCATION:
+ break;
+ case SHORT_BRANCH_RELOCATION:
+ offset_difference+=4;
+ break;
+ case SHORT_JUMP_RELOCATION:
+ offset_difference+=3;
+ break;
+ case ALIGN_RELOCATION:
+ offset_difference += relocation->relocation_align1-relocation->relocation_align2;
+ break;
+ default:
+ internal_error_in_function ("search_short_branches");
+ }
+ }
+
+ return found_new_short_branch;
+}
+
+static struct relocation *calculate_new_label_offset
+ (ULONG *label_offset_p,int *offset_difference_p,int *new_offset_difference_p,struct relocation *relocation)
+{
+ while (relocation!=NULL){
+ int offset2;
+
+ offset2=*label_offset_p-*new_offset_difference_p;
+
+ if (relocation->relocation_offset-*offset_difference_p>=offset2)
+ if (! (relocation->relocation_offset-*offset_difference_p==offset2
+ && ((relocation->relocation_kind==ALIGN_RELOCATION && relocation->relocation_align2==0)
+#ifdef FUNCTION_LEVEL_LINKING
+ || relocation->relocation_kind==DUMMY_BRANCH_RELOCATION
+#endif
+ )))
+ break;
+
+ switch (relocation->relocation_kind){
+ case NEW_SHORT_BRANCH_RELOCATION:
+ *new_offset_difference_p+=4;
+ relocation->relocation_kind=SHORT_BRANCH_RELOCATION;
+ case SHORT_BRANCH_RELOCATION:
+ *offset_difference_p+=4;
+ break;
+ case NEW_SHORT_JUMP_RELOCATION:
+ *new_offset_difference_p+=3;
+ relocation->relocation_kind=SHORT_JUMP_RELOCATION;
+ case SHORT_JUMP_RELOCATION:
+ *offset_difference_p+=3;
+ break;
+ case ALIGN_RELOCATION:
+ {
+ int new_align;
+
+#ifdef FUNCTION_LEVEL_LINKING
+ new_align= 3 & -(relocation->relocation_offset-*offset_difference_p-relocation->relocation_object_label->object_label_offset);
+#else
+ new_align= 3 & -(relocation->relocation_offset-*offset_difference_p);
+#endif
+ *offset_difference_p+=relocation->relocation_align1-new_align;
+ *new_offset_difference_p+=relocation->relocation_align2-new_align;
+ relocation->relocation_align2=new_align;
+ break;
+ }
+ }
+ relocation=relocation->next;
+ }
+
+ *label_offset_p -= *new_offset_difference_p;
+
+ return relocation;
+}
+
+static void adjust_label_offsets (void)
+{
+ struct relocation *relocation;
+ struct basic_block *block;
+ struct call_and_jump *call_and_jump;
+ int offset_difference,new_offset_difference;
+
+#ifdef FUNCTION_LEVEL_LINKING
+ struct object_label *object_label;
+
+ object_label=first_object_label;
+#endif
+
+ relocation=first_code_relocation;
+ call_and_jump=first_call_and_jump;
+
+ offset_difference=0;
+ new_offset_difference=0;
+
+ for_l (block,first_block,block_next){
+ struct block_label *labels;
+
+ for_l (labels,block->block_labels,block_label_next){
+#if 0
+ if (labels->block_label_label->label_number==0)
+#endif
+ {
+ LABEL *label;
+ int label__offset;
+
+ label=labels->block_label_label;
+ label__offset=label->label_offset;
+
+ while (call_and_jump!=NULL && call_and_jump->cj_jump.label_offset<label__offset){
+ relocation=calculate_new_label_offset
+ (&call_and_jump->cj_jump.label_offset,&offset_difference,&new_offset_difference,relocation);
+
+ call_and_jump=call_and_jump->cj_next;
+ }
+
+#ifdef FUNCTION_LEVEL_LINKING
+ while (object_label!=NULL){
+ if (object_label->object_label_kind==CODE_CONTROL_SECTION){
+ if (object_label->object_label_offset!=label__offset)
+ break;
+
+ relocation=calculate_new_label_offset
+ (&object_label->object_label_offset,&offset_difference,&new_offset_difference,relocation);
+ }
+ object_label=object_label->next;
+ }
+#endif
+ relocation=calculate_new_label_offset
+ (&label->label_offset,&offset_difference,&new_offset_difference,relocation);
+ }
+ }
+
+#ifdef FUNCTION_LEVEL_LINKING
+ while (object_label!=NULL){
+ if (object_label->object_label_kind==CODE_CONTROL_SECTION){
+ if (object_label!=(struct object_label *)block->block_last_instruction)
+ break;
+
+ while (call_and_jump!=NULL && call_and_jump->cj_jump.label_offset<object_label->object_label_offset){
+ relocation=calculate_new_label_offset
+ (&call_and_jump->cj_jump.label_offset,&offset_difference,&new_offset_difference,relocation);
+
+ call_and_jump=call_and_jump->cj_next;
+ }
+
+ relocation=calculate_new_label_offset
+ (&object_label->object_label_offset,&offset_difference,&new_offset_difference,relocation);
+ }
+ object_label=object_label->next;
+ }
+#endif
+ }
+
+ for (; call_and_jump!=NULL; call_and_jump=call_and_jump->cj_next)
+ relocation=calculate_new_label_offset
+ (&call_and_jump->cj_jump.label_offset,&offset_difference,&new_offset_difference,relocation);
+
+ for_l (call_and_jump,first_call_and_jump,cj_next){
+#ifdef FUNCTION_LEVEL_LINKING
+ while (object_label!=NULL){
+ if (object_label->object_label_kind==CODE_CONTROL_SECTION){
+ if (object_label->object_label_offset!=call_and_jump->cj_label.label_offset)
+ break;
+
+ relocation=calculate_new_label_offset
+ (&object_label->object_label_offset,&offset_difference,&new_offset_difference,relocation);
+ }
+ object_label=object_label->next;
+ }
+#endif
+ relocation=calculate_new_label_offset
+ (&call_and_jump->cj_label.label_offset,&offset_difference,&new_offset_difference,relocation);
+ }
+
+#ifdef FUNCTION_LEVEL_LINKING
+ if (object_label!=NULL)
+ internal_error_in_function ("adjust_label_offsets");
+#endif
+
+ while (relocation!=NULL){
+ if (relocation->relocation_kind==NEW_SHORT_BRANCH_RELOCATION)
+ relocation->relocation_kind=SHORT_BRANCH_RELOCATION;
+ else if (relocation->relocation_kind==NEW_SHORT_JUMP_RELOCATION)
+ relocation->relocation_kind=SHORT_JUMP_RELOCATION;
+
+ relocation=relocation->next;
+ }
+}
+
+static void relocate_short_branches_and_move_code (void)
+{
+ struct relocation *relocation,**relocation_p;
+ struct object_buffer *source_object_buffer,*destination_object_buffer;
+ int source_buffer_offset,destination_buffer_offset;
+ int source_offset;
+ int offset_difference;
+
+ source_object_buffer=first_code_buffer;
+ destination_object_buffer=first_code_buffer;
+ source_offset=0;
+ source_buffer_offset=0;
+ destination_buffer_offset=0;
+
+ offset_difference=0;
+
+ relocation_p=&first_code_relocation;
+
+ while ((relocation=*relocation_p)!=NULL){
+ struct label *label;
+ int instruction_offset,branch_opcode;
+ LONG v;
+
+ switch (relocation->relocation_kind){
+ case SHORT_BRANCH_RELOCATION:
+ label=relocation->relocation_label;
+ instruction_offset=relocation->relocation_offset-2;
+ *relocation_p=relocation->next;
+ break;
+ case SHORT_JUMP_RELOCATION:
+ label=relocation->relocation_label;
+ instruction_offset=relocation->relocation_offset-1;
+ *relocation_p=relocation->next;
+ break;
+ case CALL_RELOCATION:
+ case BRANCH_RELOCATION:
+ case JUMP_RELOCATION:
+ case LONG_WORD_RELOCATION:
+ case PC_RELATIVE_LONG_WORD_RELOCATION:
+#ifdef FUNCTION_LEVEL_LINKING
+ case DUMMY_BRANCH_RELOCATION:
+#endif
+ relocation->relocation_offset -= offset_difference;
+ relocation_p=&relocation->next;
+ continue;
+ case ALIGN_RELOCATION:
+ instruction_offset=relocation->relocation_offset;
+ *relocation_p=relocation->next;
+ break;
+ case BRANCH_SKIP_BRANCH_RELOCATION:
+ *relocation_p=relocation->next;
+ if (relocation->next->relocation_kind==SHORT_BRANCH_RELOCATION){
+ instruction_offset=relocation->relocation_offset;
+ break;
+ } else
+ continue;
+ default:
+ internal_error_in_function ("relocate_short_branches_and_move_code");
+ }
+
+ while (instruction_offset!=source_offset){
+ int n;
+
+ n=instruction_offset-source_offset;
+
+ if (source_buffer_offset==BUFFER_SIZE){
+ source_object_buffer=source_object_buffer->next;
+ source_buffer_offset=0;
+ }
+
+ if (BUFFER_SIZE-source_buffer_offset < n)
+ n = BUFFER_SIZE-source_buffer_offset;
+
+ if (destination_buffer_offset==BUFFER_SIZE){
+ destination_object_buffer=destination_object_buffer->next;
+ destination_buffer_offset=0;
+ }
+
+ if (BUFFER_SIZE-destination_buffer_offset < n)
+ n = BUFFER_SIZE-destination_buffer_offset;
+
+ memcpy (&destination_object_buffer->data[destination_buffer_offset],&source_object_buffer->data[source_buffer_offset],n);
+ destination_buffer_offset+=n;
+ source_buffer_offset+=n;
+ source_offset+=n;
+ }
+
+ if (relocation->relocation_kind==ALIGN_RELOCATION){
+ int old_align,new_align;
+
+#ifdef FUNCTION_LEVEL_LINKING
+ new_align= 3 & -(instruction_offset-offset_difference-relocation->relocation_object_label->object_label_offset);
+#else
+ new_align= 3 & -(instruction_offset-offset_difference);
+#endif
+ old_align=relocation->relocation_align1;
+
+ if (new_align!=relocation->relocation_align2)
+ internal_error_in_function ("relocate_short_branches_and_move_code");
+
+ offset_difference+=old_align-new_align;
+
+ source_buffer_offset+=old_align;
+ source_offset+=old_align;
+
+ if (source_buffer_offset>BUFFER_SIZE){
+ source_buffer_offset-=BUFFER_SIZE;
+ source_object_buffer=source_object_buffer->next;
+ }
+
+#if 1
+ if (new_align!=0){
+ if (destination_buffer_offset==BUFFER_SIZE){
+ destination_buffer_offset=0;
+ destination_object_buffer=destination_object_buffer->next;
+ }
+ switch (new_align){
+ case 1:
+ destination_object_buffer->data[destination_buffer_offset++]=0x90;
+ --new_align;
+ break;
+ case 2:
+ destination_object_buffer->data[destination_buffer_offset++]=0x48;
+
+ if (destination_buffer_offset==BUFFER_SIZE){
+ destination_buffer_offset=0;
+ destination_object_buffer=destination_object_buffer->next;
+ }
+ destination_object_buffer->data[destination_buffer_offset++]=0x90;
+ new_align-=2;
+ break;
+ case 3:
+ destination_object_buffer->data[destination_buffer_offset++]=0x48;
+
+ if (destination_buffer_offset==BUFFER_SIZE){
+ destination_buffer_offset=0;
+ destination_object_buffer=destination_object_buffer->next;
+ }
+ destination_object_buffer->data[destination_buffer_offset++]=0213;
+
+ if (destination_buffer_offset==BUFFER_SIZE){
+ destination_buffer_offset=0;
+ destination_object_buffer=destination_object_buffer->next;
+ }
+ destination_object_buffer->data[destination_buffer_offset++]=0300 | (reg_num (EBP)<<3) | reg_num (EBP);;
+ new_align-=3;
+ break;
+ }
+ }
+#else
+ while (new_align!=0){
+ if (destination_buffer_offset==BUFFER_SIZE){
+ destination_buffer_offset=0;
+ destination_object_buffer=destination_object_buffer->next;
+ }
+ destination_object_buffer->data[destination_buffer_offset]=0x90;
+ ++destination_buffer_offset;
+
+ --new_align;
+ }
+#endif
+ continue;
+ }
+
+ if (source_buffer_offset>=BUFFER_SIZE){
+ source_buffer_offset-=BUFFER_SIZE;
+ source_object_buffer=source_object_buffer->next;
+ }
+
+ if (relocation->relocation_kind==SHORT_JUMP_RELOCATION){
+ v=label->label_offset-(instruction_offset+2-offset_difference);
+
+ if (source_buffer_offset<=BUFFER_SIZE-5){
+ v += *(LONG*)(source_object_buffer->data+(source_buffer_offset+1));
+
+ } else {
+ unsigned char *p1,*p2,*p3,*p4,*end_buffer;
+
+ p1=source_object_buffer->data+(source_buffer_offset+1);
+ end_buffer=source_object_buffer->data+BUFFER_SIZE;
+ if (p1==end_buffer)
+ p1=source_object_buffer->next->data;
+ p2=p1+1;
+ if (p2==end_buffer)
+ p2=source_object_buffer->next->data;
+ p3=p2+1;
+ if (p3==end_buffer)
+ p3=source_object_buffer->next->data;
+ p4=p3+1;
+ if (p4==end_buffer)
+ p4=source_object_buffer->next->data;
+
+ v+= (*p1) | (*p2<<8) | (*p3<<16) | (*p4<<24);
+ }
+
+ branch_opcode=0xeb;
+
+ source_buffer_offset+=5;
+ source_offset+=5;
+
+ offset_difference+=3;
+ } else if (relocation->relocation_kind==SHORT_BRANCH_RELOCATION){
+ v=label->label_offset-(instruction_offset+2-offset_difference);
+
+ if (source_buffer_offset<=BUFFER_SIZE-6){
+ v += *(LONG*)(source_object_buffer->data+(source_buffer_offset+2));
+
+ branch_opcode=0x70 | (source_object_buffer->data[source_buffer_offset+1] & 0x0f);
+ } else {
+ unsigned char *p1,*p2,*p3,*p4,*p5,*end_buffer;
+
+ p1=source_object_buffer->data+(source_buffer_offset+1);
+ end_buffer=source_object_buffer->data+BUFFER_SIZE;
+ if (p1==end_buffer)
+ p1=source_object_buffer->next->data;
+ p2=p1+1;
+ if (p2==end_buffer)
+ p2=source_object_buffer->next->data;
+ p3=p2+1;
+ if (p3==end_buffer)
+ p3=source_object_buffer->next->data;
+ p4=p3+1;
+ if (p4==end_buffer)
+ p4=source_object_buffer->next->data;
+ p5=p4+1;
+ if (p5==end_buffer)
+ p5=source_object_buffer->next->data;
+
+ v+= (*p2) | (*p3<<8) | (*p4<<16) | (*p5<<24);
+
+ branch_opcode=0x70 | (*p1 & 0x0f);
+ }
+
+ source_buffer_offset+=6;
+ source_offset+=6;
+
+ offset_difference+=4;
+ } else if (relocation->relocation_kind==BRANCH_SKIP_BRANCH_RELOCATION){
+ ++source_buffer_offset;
+ ++source_offset;
+
+ if (source_buffer_offset>BUFFER_SIZE){
+ source_buffer_offset-=BUFFER_SIZE;
+ source_object_buffer=source_object_buffer->next;
+ }
+
+ destination_object_buffer->data[destination_buffer_offset]=2;
+ ++destination_buffer_offset;
+
+ continue;
+ } else
+ internal_error_in_function ("relocate_short_branches_and_move_code");
+
+ if (v<-128 || v>127)
+ internal_error_in_function ("relocate_short_branches_and_move_code");
+
+ if (source_buffer_offset>BUFFER_SIZE){
+ source_buffer_offset-=BUFFER_SIZE;
+ source_object_buffer=source_object_buffer->next;
+ }
+
+ if (destination_buffer_offset==BUFFER_SIZE){
+ destination_buffer_offset=0;
+ destination_object_buffer=destination_object_buffer->next;
+ }
+ destination_object_buffer->data[destination_buffer_offset]=branch_opcode;
+ ++destination_buffer_offset;
+
+ if (destination_buffer_offset==BUFFER_SIZE){
+ destination_buffer_offset=0;
+ destination_object_buffer=destination_object_buffer->next;
+ }
+ destination_object_buffer->data[destination_buffer_offset]=v;
+ ++destination_buffer_offset;
+ }
+
+ while (source_offset!=code_buffer_offset){
+ int n;
+
+ n=code_buffer_offset-source_offset;
+
+ if (source_buffer_offset==BUFFER_SIZE){
+ source_object_buffer=source_object_buffer->next;
+ source_buffer_offset=0;
+ }
+
+ if (BUFFER_SIZE-source_buffer_offset < n)
+ n = BUFFER_SIZE-source_buffer_offset;
+
+ if (destination_buffer_offset==BUFFER_SIZE){
+ destination_object_buffer=destination_object_buffer->next;
+ destination_buffer_offset=0;
+ }
+
+ if (BUFFER_SIZE-destination_buffer_offset < n)
+ n = BUFFER_SIZE-destination_buffer_offset;
+
+ memcpy (&destination_object_buffer->data[destination_buffer_offset],&source_object_buffer->data[source_buffer_offset],n);
+ destination_buffer_offset+=n;
+ source_buffer_offset+=n;
+ source_offset+=n;
+ }
+
+ code_buffer_offset-=offset_difference;
+
+ if (destination_object_buffer!=NULL){
+ struct object_buffer *next_destination_object_buffer;
+
+ destination_object_buffer->size=destination_buffer_offset;
+ next_destination_object_buffer=destination_object_buffer->next;
+ destination_object_buffer->next=NULL;
+
+ while (next_destination_object_buffer!=NULL){
+ destination_object_buffer=next_destination_object_buffer;
+ next_destination_object_buffer=next_destination_object_buffer->next;
+
+ memory_free (destination_object_buffer);
+ }
+ }
+}
+
+static void optimise_branches (void)
+{
+ int n;
+
+ for (n=0; n<3; ++n){
+ if (!search_short_branches())
+ break;
+
+ adjust_label_offsets();
+ }
+
+ relocate_short_branches_and_move_code();
+}
+#endif
+
+static void relocate_code (void)
+{
+ struct relocation *relocation,**relocation_p;
+ struct object_buffer *object_buffer;
+ int code_buffer_offset;
+ struct label *label;
+ int instruction_offset;
+ LONG v;
+
+ object_buffer=first_code_buffer;
+ code_buffer_offset=0;
+
+ relocation_p=&first_code_relocation;
+
+ while ((relocation=*relocation_p)!=NULL){
+ switch (relocation->relocation_kind){
+ case CALL_RELOCATION:
+ case BRANCH_RELOCATION:
+ case JUMP_RELOCATION:
+ label=relocation->relocation_label;
+ if (label->label_id==TEXT_LABEL_ID){
+ instruction_offset=relocation->relocation_offset;
+
+#ifdef FUNCTION_LEVEL_LINKING
+ if (label->label_object_label!=relocation->relocation_object_label){
+ v=label->label_offset-label->label_object_label->object_label_offset;
+# ifdef ELF
+ v-=4;
+# endif
+ ++n_code_relocations;
+ relocation_p=&relocation->next;
+ break;
+ }
+#endif
+ v=label->label_offset-(instruction_offset+4);
+ *relocation_p=relocation->next;
+ break;
+ } else {
+ ++n_code_relocations;
+ relocation_p=&relocation->next;
+#ifdef ELF
+ instruction_offset=relocation->relocation_offset;
+ v= -4;
+ break;
+#else
+ continue;
+#endif
+ }
+ case LONG_WORD_RELOCATION:
+ case PC_RELATIVE_LONG_WORD_RELOCATION:
+ relocation_p=&relocation->next;
+
+ label=relocation->relocation_label;
+
+ if (label->label_id==TEXT_LABEL_ID || (label->label_id==DATA_LABEL_ID
+#if defined (RELOCATIONS_RELATIVE_TO_EXPORTED_DATA_LABEL) && defined (FUNCTION_LEVEL_LINKING)
+ && !((label->label_flags & EXPORT_LABEL) && label->label_object_label->object_label_kind==EXPORTED_DATA_LABEL)
+#endif
+ ))
+ {
+ instruction_offset=relocation->relocation_offset;
+ v=label->label_offset;
+#ifdef FUNCTION_LEVEL_LINKING
+ v -= label->label_object_label->object_label_offset;
+#endif
+ break;
+ } else
+ continue;
+#ifdef FUNCTION_LEVEL_LINKING
+ case DUMMY_BRANCH_RELOCATION:
+ label=relocation->relocation_label;
+ if (label->label_id==TEXT_LABEL_ID){
+ if (label->label_object_label!=relocation->relocation_object_label){
+ ++n_code_relocations;
+ relocation_p=&relocation->next;
+ continue;
+ }
+ *relocation_p=relocation->next;
+ continue;
+ } else {
+ internal_error_in_function ("relocate_code");
+ *relocation_p=relocation->next;
+ }
+#endif
+ default:
+ internal_error_in_function ("relocate_code");
+ }
+
+ while (instruction_offset >= code_buffer_offset+BUFFER_SIZE){
+ object_buffer=object_buffer->next;
+ code_buffer_offset+=BUFFER_SIZE;
+ }
+
+ if (instruction_offset-code_buffer_offset<=BUFFER_SIZE-4){
+ LONG *instruction_p;
+
+ instruction_p=(LONG*)(object_buffer->data+(instruction_offset-code_buffer_offset));
+ *instruction_p += v;
+ } else {
+ unsigned char *p0,*p1,*p2,*p3,*end_buffer;
+
+ p0=object_buffer->data+(instruction_offset-code_buffer_offset);
+ end_buffer=object_buffer->data+BUFFER_SIZE;
+ p1=p0+1;
+ if (p1==end_buffer)
+ p1=object_buffer->next->data;
+ p2=p1+1;
+ if (p2==end_buffer)
+ p2=object_buffer->next->data;
+ p3=p2+1;
+ if (p3==end_buffer)
+ p3=object_buffer->next->data;
+
+ v+= (*p0) | (*p1<<8) | (*p2<<16) | (*p3<<24);
+
+ *p0=v;
+ *p1=v>>8;
+ *p2=v>>16;
+ *p3=v>>24;
+ }
+ }
+}
+
+static void relocate_data (void)
+{
+ struct relocation *relocation;
+ struct object_buffer *object_buffer;
+ int data_buffer_offset;
+
+ object_buffer=first_data_buffer;
+ data_buffer_offset=0;
+
+ for_l (relocation,first_data_relocation,next){
+ struct label *label;
+
+ label=relocation->relocation_label;
+
+ if (relocation->relocation_kind==LONG_WORD_RELOCATION){
+ if (label->label_id==TEXT_LABEL_ID || (label->label_id==DATA_LABEL_ID
+#if defined (RELOCATIONS_RELATIVE_TO_EXPORTED_DATA_LABEL) && defined (FUNCTION_LEVEL_LINKING)
+ && !((label->label_flags & EXPORT_LABEL) && label->label_object_label->object_label_kind==EXPORTED_DATA_LABEL)
+#endif
+ ))
+ {
+ int data_offset,v;
+
+ data_offset=relocation->relocation_offset;
+ while (data_offset >= data_buffer_offset+BUFFER_SIZE){
+ object_buffer=object_buffer->next;
+ data_buffer_offset+=BUFFER_SIZE;
+ }
+
+ v = label->label_offset;
+#ifdef FUNCTION_LEVEL_LINKING
+ v -= label->label_object_label->object_label_offset;
+#endif
+ if (data_offset-data_buffer_offset<=BUFFER_SIZE-4){
+ LONG *data_p;
+
+ data_p=(LONG*)(object_buffer->data+(data_offset-data_buffer_offset));
+ *data_p += v;
+ } else {
+ unsigned char *p0,*p1,*p2,*p3,*end_buffer;
+
+ p0=object_buffer->data+(data_offset-data_buffer_offset);
+ end_buffer=object_buffer->data+BUFFER_SIZE;
+ p1=p0+1;
+ if (p1==end_buffer)
+ p1=object_buffer->next->data;
+ p2=p1+1;
+ if (p2==end_buffer)
+ p2=object_buffer->next->data;
+ p3=p2+1;
+ if (p3==end_buffer)
+ p3=object_buffer->next->data;
+
+ v+= (*p0) | (*p1<<8) | (*p2<<16) | (*p3<<24);
+
+ *p0=v;
+ *p1=v>>8;
+ *p2=v>>16;
+ *p3=v>>24;
+ }
+ }
+ }
+ }
+}
+
+static void 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){
+ struct object_label *new_object_label;
+ int string_length;
+
+ new_object_label=fast_memory_allocate_type (struct object_label);
+ *last_object_label_l=new_object_label;
+ last_object_label_l=&new_object_label->next;
+ new_object_label->next=NULL;
+
+ new_object_label->object_label_label=label;
+
+ label->label_id=n_object_labels;
+ ++n_object_labels;
+
+ label->label_offset=0;
+
+ string_length=strlen (label->label_name);
+#ifndef ELF
+ if (string_length<8)
+ new_object_label->object_label_string_offset=0;
+ else
+#endif
+ {
+ new_object_label->object_label_string_offset=string_table_offset;
+ string_table_offset+=string_length+1;
+ }
+
+ new_object_label->object_label_kind=IMPORTED_LABEL;
+ }
+
+ as_import_labels (label_node->label_node_left);
+ as_import_labels (label_node->label_node_right);
+}
+
+#define C_EXT 2
+#define C_STAT 3
+
+static void write_object_labels (void)
+{
+ struct object_label *object_label;
+#if defined (RELOCATIONS_RELATIVE_TO_EXPORTED_DATA_LABEL) && defined (FUNCTION_LEVEL_LINKING)
+ struct object_label *current_text_or_data_object_label;
+
+ current_text_or_data_object_label=NULL;
+#endif
+
+#ifdef ELF
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_l (0);
+# ifndef FUNCTION_LEVEL_LINKING
+ write_l (1);
+ write_l (0);
+ write_l (0);
+ write_c (ELF32_ST_INFO (STB_LOCAL,STT_SECTION));
+ write_c (0);
+ write_w (2);
+
+ write_l (7);
+ write_l (0);
+ write_l (0);
+ write_c (ELF32_ST_INFO (STB_LOCAL,STT_SECTION));
+ write_c (0);
+ write_w (3);
+# else
+ {
+ int section_n;
+
+ for (section_n=0; section_n<n_code_sections; ++section_n){
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_c (ELF32_ST_INFO (STB_LOCAL,STT_SECTION));
+ write_c (0);
+ write_w (2+section_n);
+ }
+
+ for (section_n=0; section_n<n_data_sections; ++section_n){
+ write_l (0);
+ write_l (0);
+ write_l (0);
+ write_c (ELF32_ST_INFO (STB_LOCAL,STT_SECTION));
+ write_c (0);
+ write_w (2+n_code_sections+section_n);
+ }
+ }
+# endif
+#endif
+
+ for_l (object_label,first_object_label,next){
+ switch (object_label->object_label_kind){
+ case CODE_CONTROL_SECTION:
+ {
+#ifndef ELF
+ write_string_8 (".text");
+
+# ifdef FUNCTION_LEVEL_LINKING
+ write_l (0);
+ write_w (1+object_label->object_label_section_n);
+# else
+ write_l (object_label->object_label_offset);
+ write_w (1);
+# endif
+ write_w (0);
+ write_c (C_STAT);
+ write_c (1);
+
+ write_l (object_label->object_label_length);
+# ifdef FUNCTION_LEVEL_LINKING
+ write_w (object_label->object_label_n_relocations);
+# else
+ write_w (n_code_relocations);
+# endif
+ write_w (0);
+ write_l (0);
+ write_l (0);
+ write_w (0);
+#endif
+ break;
+ }
+ case DATA_CONTROL_SECTION:
+ {
+#if defined (RELOCATIONS_RELATIVE_TO_EXPORTED_DATA_LABEL) && defined (FUNCTION_LEVEL_LINKING)
+ current_text_or_data_object_label=object_label;
+#endif
+#ifndef ELF
+ write_string_8 (".data");
+
+# ifdef FUNCTION_LEVEL_LINKING
+ write_l (0);
+ write_w (1+n_code_sections+object_label->object_label_section_n);
+# else
+ write_l (object_label->object_label_offset);
+ write_w (2);
+# endif
+ write_w (0);
+ write_c (C_STAT);
+ write_c (1);
+
+ write_l (object_label->object_label_length);
+# ifdef FUNCTION_LEVEL_LINKING
+ write_w (object_label->object_label_n_relocations);
+# else
+ write_w (n_data_relocations);
+# endif
+ write_w (0);
+ write_l (0);
+ write_l (0);
+ write_w (0);
+#endif
+ break;
+ }
+ case IMPORTED_LABEL:
+ {
+ struct label *label;
+
+ label=object_label->object_label_label;
+#ifdef ELF
+ write_l (object_label->object_label_string_offset);
+ write_l (0);
+ write_l (0);
+ write_c (ELF32_ST_INFO (STB_GLOBAL,STT_NOTYPE));
+ write_c (0);
+ write_w (0);
+#else
+ if (object_label->object_label_string_offset==0)
+ write_string_8 (label->label_name);
+ else {
+ write_l (0);
+ write_l (object_label->object_label_string_offset);
+ }
+
+ write_l (0);
+ write_w (0);
+ write_w (0);
+ write_c (C_EXT);
+ write_c (0);
+#endif
+ break;
+ }
+ case EXPORTED_CODE_LABEL:
+ {
+ struct label *label;
+
+ label=object_label->object_label_label;
+#ifdef ELF
+ write_l (object_label->object_label_string_offset);
+# ifdef FUNCTION_LEVEL_LINKING
+ write_l (label->label_offset - label->label_object_label->object_label_offset);
+# else
+ write_l (label->label_offset);
+# endif
+ write_l (0);
+ write_c (ELF32_ST_INFO (STB_GLOBAL,STT_FUNC));
+ write_c (0);
+# ifdef FUNCTION_LEVEL_LINKING
+ write_w (2+label->label_object_label->object_label_section_n);
+# else
+ write_w (2);
+# endif
+#else
+ if (object_label->object_label_string_offset==0)
+ write_string_8 (label->label_name);
+ else {
+ write_l (0);
+ write_l (object_label->object_label_string_offset);
+ }
+
+#ifdef FUNCTION_LEVEL_LINKING
+ write_l (label->label_offset - label->label_object_label->object_label_offset);
+ write_w (1+label->label_object_label->object_label_section_n);
+#else
+ write_l (label->label_offset);
+ write_w (1);
+#endif
+ write_w (0);
+ write_c (C_EXT);
+ write_c (0);
+#endif
+ break;
+ }
+ case EXPORTED_DATA_LABEL:
+ {
+ struct label *label;
+
+ label=object_label->object_label_label;
+#ifdef ELF
+ write_l (object_label->object_label_string_offset);
+# ifdef FUNCTION_LEVEL_LINKING
+# ifdef RELOCATIONS_RELATIVE_TO_EXPORTED_DATA_LABEL
+ write_l (label->label_offset - current_text_or_data_object_label->object_label_offset);
+# else
+ write_l (label->label_offset - label->label_object_label->object_label_offset);
+# endif
+# else
+ write_l (label->label_offset);
+# endif
+ write_l (0);
+ write_c (ELF32_ST_INFO (STB_GLOBAL,STT_OBJECT));
+ write_c (0);
+# ifdef FUNCTION_LEVEL_LINKING
+ write_w (2+n_code_sections+label->label_object_label->object_label_section_n);
+# else
+ write_w (3);
+# endif
+#else
+ if (object_label->object_label_string_offset==0)
+ write_string_8 (label->label_name);
+ else {
+ write_l (0);
+ write_l (object_label->object_label_string_offset);
+ }
+
+#ifdef FUNCTION_LEVEL_LINKING
+# ifdef RELOCATIONS_RELATIVE_TO_EXPORTED_DATA_LABEL
+ write_l (label->label_offset - current_text_or_data_object_label->object_label_offset);
+# else
+ write_l (label->label_offset - label->label_object_label->object_label_offset);
+# endif
+ write_w (1+n_code_sections+label->label_object_label->object_label_section_n);
+#else
+ write_l (label->label_offset);
+ write_w (2);
+#endif
+ write_w (0);
+ write_c (C_EXT);
+ write_c (0);
+#endif
+ break;
+ }
+ default:
+ internal_error_in_function ("write_object_labels");
+ }
+ }
+}
+
+static void write_string_table (void)
+{
+ struct object_label *object_label;
+
+#ifdef ELF
+ write_c (0);
+ write_zstring (".text");
+ write_zstring (".data");
+#else
+ if (string_table_offset==4)
+ return;
+
+ write_l (string_table_offset);
+#endif
+ for_l (object_label,first_object_label,next){
+ int object_label_kind;
+
+ object_label_kind=object_label->object_label_kind;
+
+ if ((object_label_kind==IMPORTED_LABEL || object_label_kind==EXPORTED_CODE_LABEL || object_label_kind==EXPORTED_DATA_LABEL)
+ && object_label->object_label_string_offset!=0)
+ {
+ char *s,c;
+
+ s=object_label->object_label_label->label_name;
+
+ do {
+ c=*s++;
+ write_c (c);
+ } while (c!='\0');
+ }
+ }
+}
+
+#define R_ABSOLUTE 0
+#define R_ADDR32 2
+#define R_REL32 4
+
+#if defined (ELF) && defined (FUNCTION_LEVEL_LINKING)
+static int elf_label_number (struct label *label)
+{
+ int label_n;
+
+ label_n=label->label_id;
+ if (label_n==TEXT_LABEL_ID){
+ label_n=label->label_object_label->object_label_number;
+ if (label_n==0)
+ return 1+label->label_object_label->object_label_section_n;
+ else
+ return label_n+n_sections;
+ } else if (label_n==DATA_LABEL_ID){
+ label_n=label->label_object_label->object_label_number;
+ if (label_n==0)
+ return 1+n_code_sections+label->label_object_label->object_label_section_n;
+ else
+ return label_n+n_sections;
+ } else
+ return label_n+n_sections;
+}
+#endif
+
+static void write_code_relocations (void)
+{
+ struct relocation *relocation;
+
+ for_l (relocation,first_code_relocation,next){
+ switch (relocation->relocation_kind){
+ case CALL_RELOCATION:
+ case BRANCH_RELOCATION:
+ case JUMP_RELOCATION:
+ {
+ struct label *label;
+
+ label=relocation->relocation_label;
+#ifdef FUNCTION_LEVEL_LINKING
+ if (label->label_id==-1)
+#else
+ if (label->label_id<0)
+#endif
+ internal_error_in_function ("write_code_relocations");
+
+ write_l (relocation->relocation_offset);
+#ifdef ELF
+# ifdef FUNCTION_LEVEL_LINKING
+ write_l (ELF32_R_INFO (elf_label_number (label),R_386_PC32));
+# else
+ write_l (ELF32_R_INFO (label->label_id,R_386_PC32));
+# endif
+#else
+# ifdef FUNCTION_LEVEL_LINKING
+ if (label->label_id==TEXT_LABEL_ID || label->label_id==DATA_LABEL_ID)
+ write_l (label->label_object_label->object_label_number);
+ else
+# endif
+ write_l (label->label_id);
+ write_w (R_REL32);
+#endif
+ break;
+ }
+ case LONG_WORD_RELOCATION:
+ {
+ struct label *label;
+
+ label=relocation->relocation_label;
+#ifdef FUNCTION_LEVEL_LINKING
+ if (label->label_id==-1)
+#else
+ if (label->label_id<0)
+#endif
+ internal_error_in_function ("write_code_relocations");
+
+ write_l (relocation->relocation_offset);
+#ifdef ELF
+# ifdef FUNCTION_LEVEL_LINKING
+ write_l (ELF32_R_INFO (elf_label_number (label),R_386_32));
+# else
+ write_l (ELF32_R_INFO (label->label_id,R_386_32));
+# endif
+#else
+# ifdef FUNCTION_LEVEL_LINKING
+ if (label->label_id==TEXT_LABEL_ID || label->label_id==DATA_LABEL_ID)
+ write_l (label->label_object_label->object_label_number);
+ else
+# endif
+ write_l (label->label_id);
+ write_w (R_ADDR32);
+#endif
+ break;
+ }
+ case PC_RELATIVE_LONG_WORD_RELOCATION:
+ {
+ struct label *label;
+
+ label=relocation->relocation_label;
+#ifdef FUNCTION_LEVEL_LINKING
+ if (label->label_id==-1)
+#else
+ if (label->label_id<0)
+#endif
+ internal_error_in_function ("write_code_relocations");
+
+ write_l (relocation->relocation_offset);
+#ifdef ELF
+# ifdef FUNCTION_LEVEL_LINKING
+ write_l (ELF32_R_INFO (elf_label_number (label),R_386_32));
+# else
+ write_l (ELF32_R_INFO (label->label_id,R_386_32));
+# endif
+#else
+# ifdef FUNCTION_LEVEL_LINKING
+ if (label->label_id==TEXT_LABEL_ID || label->label_id==DATA_LABEL_ID)
+ write_l (label->label_object_label->object_label_number);
+ else
+# endif
+ write_l (label->label_id);
+ write_w (R_REL32);
+#endif
+ break;
+ }
+#ifdef FUNCTION_LEVEL_LINKING
+ case DUMMY_BRANCH_RELOCATION:
+ {
+ struct label *label;
+
+ label=relocation->relocation_label;
+ if (label->label_id==-1)
+ internal_error_in_function ("write_code_relocations");
+
+ write_l (relocation->relocation_offset - 4);
+#ifdef ELF
+ write_l (ELF32_R_INFO (elf_label_number (label),R_386_NONE));
+#else
+ if (label->label_id==TEXT_LABEL_ID || label->label_id==DATA_LABEL_ID)
+ write_l (label->label_object_label->object_label_number);
+ else
+ write_l (label->label_id);
+# if 1
+ write_w (R_ABSOLUTE);
+# else
+ write_w (R_REL32);
+# endif
+#endif
+ break;
+ }
+#endif
+ default:
+ internal_error_in_function ("write_code_relocations");
+ }
+ }
+}
+
+static void write_data_relocations (void)
+{
+ struct relocation *relocation;
+
+ for_l (relocation,first_data_relocation,next){
+ switch (relocation->relocation_kind){
+ case LONG_WORD_RELOCATION:
+ {
+ struct label *label;
+
+ label=relocation->relocation_label;
+#ifdef FUNCTION_LEVEL_LINKING
+ if (label->label_id==-1)
+#else
+ if (label->label_id<0)
+#endif
+ internal_error_in_function ("write_data_relocations");
+
+ write_l (relocation->relocation_offset);
+#ifdef ELF
+# ifdef FUNCTION_LEVEL_LINKING
+ write_l (ELF32_R_INFO (elf_label_number (label),R_386_32));
+# else
+ write_l (ELF32_R_INFO (label->label_id,R_386_32));
+# endif
+#else
+# ifdef FUNCTION_LEVEL_LINKING
+ if (label->label_id==TEXT_LABEL_ID || label->label_id==DATA_LABEL_ID)
+ write_l (label->label_object_label->object_label_number);
+ else
+# endif
+ write_l (label->label_id);
+ write_w (R_ADDR32);
+#endif
+ break;
+ }
+ default:
+ internal_error_in_function ("write_data_relocations");
+ }
+ }
+}
+
+void assemble_code (void)
+{
+ as_import_labels (labels);
+
+ write_code();
+
+ if (code_buffer_free & 1)
+ store_c (0x90);
+
+ flush_data_buffer();
+ flush_code_buffer();
+
+#if defined (OPTIMISE_BRANCHES)
+ optimise_branches();
+#endif
+
+#ifndef FUNCTION_LEVEL_LINKING
+ code_object_label->object_label_length=code_buffer_offset;
+ data_object_label->object_label_length=data_buffer_offset;
+#endif
+
+ relocate_code();
+ relocate_data();
+
+ write_file_header_and_section_headers();
+
+ write_buffers_and_release_memory (&first_code_buffer);
+
+#ifdef ELF
+ if ((code_buffer_offset & 3)!=0){
+ int n;
+
+ n=4-(code_buffer_offset & 3);
+ do {
+ write_c (0);
+ } while (--n);
+ }
+#endif
+
+ write_buffers_and_release_memory (&first_data_buffer);
+
+#ifdef ELF
+ if ((data_buffer_offset & 3)!=0){
+ int n;
+
+ n=4-(data_buffer_offset & 3);
+ do {
+ write_c (0);
+ } while (--n);
+ }
+#endif
+
+ write_code_relocations();
+ write_data_relocations();
+ write_object_labels();
+ write_string_table();
+}
diff --git a/cgaas.h b/cgaas.h
new file mode 100644
index 0000000..89af0dc
--- /dev/null
+++ b/cgaas.h
@@ -0,0 +1,35 @@
+
+void assemble_code (VOID);
+void initialize_assembler (FILE *file);
+void define_local_label (int id,int flag);
+void define_external_label (int id,int flag,char label_name[]);
+void store_word_in_data_section (UWORD i);
+void store_long_word_in_data_section (ULONG i);
+void define_data_label (LABEL *label);
+void store_label_in_data_section (LABEL *label);
+void store_label_offset_in_data_section (int label_id);
+void store_descriptor_in_data_section (LABEL *label);
+void store_descriptor_in_code_section (int label_id);
+void store_c_string_in_data_section (char *string,int length);
+void store_abc_string_in_data_section (char *string,int length);
+void store_abc_string4_in_data_section (char *string,int length);
+void store_c_string_in_code_section (char *string,int length);
+void store_abc_string_in_code_section (char *string,int length);
+void store_descriptor_string_in_code_section (char *string,int length,int string_code_label_id,LABEL *string_label);
+void store_label_offset_in_code_section (int label_id);
+void start_new_module (int flag);
+void store_descriptor_string_in_data_section (char *string,int length,LABEL *string_label);
+void store_2_words_in_data_section (UWORD w1,UWORD w2);
+#ifdef _WINDOWS_
+void as_new_data_module (void);
+#endif
+
+#ifndef GNU_C
+void write_version_and_options (int version,int options);
+void write_depend (char *module_name);
+#endif
+
+struct ms { __int64 m; int s; };
+
+extern struct ms magic (__int64 d);
+
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 (&parameter);
+ 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 (&parameter);
+ else if (size_flag==SIZE_WORD)
+ w_as_comma_word_parameter (&parameter);
+ 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 (&parameter);
+ 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 (&parameter);
+ else if (size_flag==SIZE_WORD)
+ w_as_comma_word_parameter (&parameter);
+ 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 (&parameter_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 (&parameter_1);
+ w_as_scratch_register();
+ if (!intel_asm)
+ w_as_comma_parameter (&parameter_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 (&parameter_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 (&parameter_1);
+ }
+ w_as_parameter (&parameter_0);
+ if (!intel_asm)
+ w_as_comma_parameter (&parameter_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();
+ }
+}
diff --git a/cgawas.h b/cgawas.h
new file mode 100644
index 0000000..2182c4c
--- /dev/null
+++ b/cgawas.h
@@ -0,0 +1,25 @@
+void initialize_write_assembly (FILE *ass_file);
+void write_assembly (VOID);
+void w_as_abc_string_and_label_in_code_section (char *string,int length,char *label_name);
+void w_as_abc_string_in_code_section (char *string,int length,int label_number);
+void w_as_c_string_in_code_section (char *string,int length,int label_number);
+void w_as_c_string_in_data_section (char *string,int length);
+void w_as_descriptor_string_in_code_section (char *string,int length,int string_code_label_id,LABEL *string_label);
+void w_as_word_in_data_section (int n);
+void w_as_label_in_data_section (char *label_name);
+void w_as_descriptor_in_data_section (char *label_name);
+void w_as_define_label (LABEL *label);
+void w_as_internal_label_value (int label_id);
+void w_as_new_module (int flag);
+void w_as_long_in_data_section (int n);
+void w_as_to_data_section (void);
+void w_as_descriptor_in_code_section (char *label_name);
+void w_as_define_data_label (int label_number);
+void w_as_labeled_c_string_in_data_section (char *string,int length,int label_number);
+void w_as_abc_string_in_data_section (char *string,int length);
+void w_as_descriptor_string_in_data_section (char *string,int length,int string_label_id,LABEL *string_label);
+void w_as_abc_string_and_label_in_data_section (char *string,int length,char *label_name);
+void w_as_c_string_and_label_in_code_section (char *string,int length,char *label_name);
+#ifdef _WINDOWS_
+void w_as_new_data_module (void);
+#endif