diff options
Diffstat (limited to 'cgas.c')
-rw-r--r-- | cgas.c | 3839 |
1 files changed, 3839 insertions, 0 deletions
@@ -0,0 +1,3839 @@ +/* + File: cgas.c + Author: John van Groningen +*/ + +#include <stdio.h> +#include <string.h> + +#define MODULES +#define USE_LABEL_VALUE +/* #define COUNT_RELEASES */ +#undef GENERATE_MPW_OBJECT_CODE + +#include "cgport.h" + +#ifndef G_POWER + +#include "cg.h" +#include "cgrconst.h" +#include "cgtypes.h" +#include "cgiconst.h" +#include "cgcode.h" +#include "cginstructions.h" +#include "cgas.h" + +#define for_all(v,l,n) for(v=(l);v!=NULL;v=v->n) + +extern LABEL *index_error_label; + +#pragma segment Code5 + +enum { + LBEGIN=1, + LEND, + LIMPORT, + LLABEL, + LCODE, + LDATA, + LREFERENCE, + LUDATA, + LC_REFERENCE, + LLABEL_VALUE, + LCOMMENT, + LMODULE +}; + +#define LLABEL_TEXT 0 +#define LLABEL_DATA 1 +#define LLABEL_EXTERN 2 +#define LLABEL_OFFSET 4 + +#define REFERENCE_PC 16 +#define REFERENCE_OFFSET 8 +#define REFERENCE_A5 4 +#define REFERENCE_LONG 2 +#define REFERENCE_DATA 1 + +#define LCR_WORD 2 +#define LCR_BYTE 0 +#define LCR_OFFSET 8 + +FILE *output_file; + +#ifdef THINK_C +# define IO_BUFFER_SIZE 16384 +#else +# define IO_BUFFER_SIZE 8192 +#endif + +struct object_buffer { + struct object_buffer *next; + int size; + unsigned char data [IO_BUFFER_SIZE]; +}; + +static struct object_buffer *first_buffer,*current_buffer; + +static int buffer_free; +static unsigned char *buffer_p; + +static void initialize_object_buffers (VOID) +{ + struct object_buffer *new_buffer; + + new_buffer=(struct object_buffer*)memory_allocate (sizeof (struct object_buffer)); + + new_buffer->size=0; + new_buffer->next=NULL; + + first_buffer=new_buffer; + current_buffer=new_buffer; + + buffer_free=IO_BUFFER_SIZE; + buffer_p=new_buffer->data; +} + +static void write_c (int c) +{ + if (buffer_free>0){ + --buffer_free; + *buffer_p++=c; + } else { + struct object_buffer *new_buffer; + + current_buffer->size=IO_BUFFER_SIZE; + + new_buffer=(struct object_buffer*)memory_allocate (sizeof (struct object_buffer)); + + new_buffer->size=0; + new_buffer->next=NULL; + + current_buffer->next=new_buffer; + current_buffer=new_buffer; + + buffer_free=IO_BUFFER_SIZE-1; + buffer_p=new_buffer->data; + + *buffer_p++=c; + } +} + +static void flush_object_buffer (VOID) +{ + current_buffer->size=IO_BUFFER_SIZE-buffer_free; +} + +/* object optimizer */ + +static struct object_buffer *s_buffer,*d_buffer; +static int s_free,d_free; +static unsigned char *s_buffer_p,*d_buffer_p; + +static int s_read (VOID) +{ + while (s_free==0){ + s_buffer=s_buffer->next; + if (s_buffer==NULL) + internal_error_in_function ("s_read"); + s_free=s_buffer->size; + s_buffer_p=s_buffer->data; + } + + --s_free; + return *s_buffer_p++; +} + +static void d_write (int c) +{ + while (d_free==0){ + d_buffer=d_buffer->next; + if (d_buffer==NULL) + internal_error_in_function ("d_write"); + d_free=d_buffer->size; + d_buffer_p=d_buffer->data; + } + + --d_free; + *d_buffer_p++=c; +} + +static void optimize_buffers (VOID) +{ + int c; + + s_buffer=d_buffer=first_buffer; + s_free=d_free=first_buffer->size; + s_buffer_p=d_buffer_p=first_buffer->data; + + c=s_read(); + + for (;;){ + d_write (c); + switch (c){ + case LCODE: + { + int size,n,t; + unsigned char buffer[256]; + + n=0; + size=s_read(); + for (;;){ + t=size; + while (t--) + buffer[n++]=s_read(); + if (size & 1) + s_read(); + c=s_read(); + if (c!=LCODE) + break; + else { + size=s_read(); + if (size+n>=256){ + t=n; + d_write (t); + for (n=0; n<t; ++n) + d_write (buffer[n]); + if (t & 1) + d_write (0); + d_write (LCODE); + n=0; + } + } + } + t=n; + d_write (t); + for (n=0; n<t; ++n) + d_write (buffer[n]); + if (t & 1) + d_write (0); + continue; + } + case LDATA: + { + int size; + + size=s_read(); + d_write (size); + if (size & 1) + d_write (s_read()); + while (size--) + d_write (s_read()); + c=s_read(); + continue; + } + case LUDATA: + d_write (s_read()); + d_write (s_read()); + c=s_read(); + continue; + case LLABEL_VALUE: + d_write (s_read()); + d_write (s_read()); + d_write (s_read()); + c=s_read(); + continue; + case LREFERENCE: + { + int flags; + + flags=s_read(); + d_write (flags); + d_write (s_read()); + d_write (s_read()); + if (flags & REFERENCE_OFFSET){ + d_write (s_read()); + d_write (s_read()); + } + c=s_read(); + continue; + } + case LC_REFERENCE: + { + int flags; + + flags=s_read(); + d_write (flags); + d_write (s_read()); + d_write (s_read()); + d_write (s_read()); + d_write (s_read()); + if (flags & LCR_OFFSET){ + d_write (s_read()); + d_write (s_read()); + } + c=s_read(); + continue; + } + case LLABEL: + { + int flags; + + flags=s_read(); + d_write (flags); + d_write (s_read()); + d_write (s_read()); + if (flags & LLABEL_OFFSET){ + d_write (s_read()); + d_write (s_read()); + } + if (flags & LLABEL_EXTERN){ + int size; + + size=s_read(); + d_write (size); + if (!(size & 1)) + d_write (s_read()); + while (size--) + d_write (s_read()); + } + c=s_read(); + continue; + } + case LIMPORT: + { + int size; + + d_write (s_read()); + d_write (s_read()); + d_write (s_read()); + size=s_read(); + d_write (size); + if (!(size & 1)) + d_write (s_read()); + while (size--) + d_write (s_read()); + c=s_read(); + continue; + } + case LMODULE: + d_write (s_read()); + c=s_read(); + continue; + case LBEGIN: + d_write (s_read()); + d_write (s_read()); + d_write (s_read()); + c=s_read(); + continue; + case LEND: + d_write (s_read()); + break; + default: + internal_error_in_function ("optimize_buffers"); + } + break; + } + + d_buffer->size-=d_free; + + { + struct object_buffer *buffer,*next_buffer; + + for (buffer=d_buffer->next; buffer!=NULL; buffer=next_buffer){ + next_buffer=buffer->next; + + memory_free (buffer); + } + } + + d_buffer->next=NULL; +} + +/* end object optimizer */ + +#ifdef GENERATE_MPW_OBJECT_CODE +/* mpw object conversion */ + +static int c_read (VOID) +{ + while (s_free==0){ + struct object_buffer *old_buffer; + + old_buffer=s_buffer; + s_buffer=s_buffer->next; + + memory_free (old_buffer); + + if (s_buffer==NULL) + internal_error_in_function ("c_read"); + s_free=s_buffer->size; + s_buffer_p=s_buffer->data; + } + + --s_free; + return *s_buffer_p++; +} + +static void c_write (int c) +{ + if (d_free==0){ + struct object_buffer *new_buffer; + + d_buffer->size=IO_BUFFER_SIZE; + + new_buffer=(struct object_buffer*)memory_allocate (sizeof (struct object_buffer)); + new_buffer->size=0; + new_buffer->next=NULL; + + d_buffer->next=new_buffer; + d_buffer=new_buffer; + + d_free=IO_BUFFER_SIZE; + d_buffer_p=d_buffer->data; + } + + --d_free; + *d_buffer_p++=c; +} + +enum { + O_FIRST=1, + O_LAST, + O_COMMENT, + O_DICTIONARY, + O_MODULE, + O_ENTRY, + O_SIZE, + O_CONTENTS, + O_REFERENCE, + O_C_REFERENCE +}; + +static void convert_to_mpw_object_code (VOID) +{ + struct object_buffer *first_d_buffer; + int c,code_module_id,data_module_id,segment_id; + long code_offset,data_offset; + + first_d_buffer=(struct object_buffer*)memory_allocate (sizeof (struct object_buffer)); + first_d_buffer->size=0; + first_d_buffer->next=NULL; + + d_buffer=first_d_buffer; + d_free=IO_BUFFER_SIZE; + d_buffer_p=d_buffer->data; + + s_buffer=first_buffer; + s_free=first_buffer->size; + s_buffer_p=first_buffer->data; + + segment_id=next_label_id++; + code_module_id=next_label_id++; + data_module_id=next_label_id++; + + code_offset=-1; + data_offset=-1; + + c=c_read(); + + for (;;){ + switch (c){ + case LCODE: + { + int size,n,t; + unsigned char buffer[256]; + + c_write (O_CONTENTS); + c_write (8); + + n=0; + + size=c_read(); + c_write ((size+8)>>8); + c_write (size+8); + + c_write (code_offset>>24); + c_write (code_offset>>16); + c_write (code_offset>>8); + c_write (code_offset); + + code_offset+=size; + + t=size; + while (t--) + buffer[n++]=c_read(); + if (size & 1) + c_read(); + + t=n; + for (n=0; n<t; ++n) + c_write (buffer[n]); + if (t & 1) + c_write (0); + + c=c_read(); + continue; + } + case LDATA: + { + int size; + + c_write (O_CONTENTS); + c_write (9); + + size=c_read(); + c_write ((size+8)>>8); + c_write (size+8); + + c_write (data_offset>>24); + c_write (data_offset>>16); + c_write (data_offset>>8); + c_write (data_offset); + + data_offset+=size; + + if (size & 1) + c_write (c_read()); + while (size--) + c_write (c_read()); + c=c_read(); + continue; + } + case LUDATA: + internal_error_in_function ("convert_to_mpw_object_code"); + break; + case LLABEL_VALUE: + { + int flags,id_h,id_l; + + flags=c_read(); + id_h=c_read(); + id_l=c_read(); + + if (flags & (REFERENCE_PC | REFERENCE_OFFSET)) + internal_error_in_function ("convert_to_mpw_object_code"); + + if (flags & REFERENCE_LONG){ + if (flags & REFERENCE_DATA){ + c_write (O_CONTENTS); + c_write (9); + + c_write (0); + c_write (4+8); + + c_write (data_offset>>24); + c_write (data_offset>>16); + c_write (data_offset>>8); + c_write (data_offset); + } else { + c_write (O_CONTENTS); + c_write (8); + + c_write (0); + c_write (4+8); + + c_write (code_offset>>24); + c_write (code_offset>>16); + c_write (code_offset>>8); + c_write (code_offset); + } + c_write (0); + c_write (0); + c_write (0); + c_write (0); + } else { + if (flags & REFERENCE_DATA){ + c_write (O_CONTENTS); + c_write (9); + + c_write (0); + c_write (2+8); + + c_write (data_offset>>24); + c_write (data_offset>>16); + c_write (data_offset>>8); + c_write (data_offset); + } else { + c_write (O_CONTENTS); + c_write (8); + + c_write (0); + c_write (2+8); + + c_write (code_offset>>24); + c_write (code_offset>>16); + c_write (code_offset>>8); + c_write (code_offset); + } + c_write (0); + c_write (0); + } + + c_write (O_REFERENCE); + c_write ( (flags & REFERENCE_A5 ? 128 : 0) + | (flags & REFERENCE_LONG ? 0 : 16) + | (flags & REFERENCE_DATA ? 1 : 0)); + + c_write (0); + c_write (8); + + c_write (id_h); + c_write (id_l); + + if (flags & REFERENCE_DATA){ + c_write (data_offset>>8); + c_write (data_offset); + + if (flags & REFERENCE_LONG) + data_offset+=4; + else + data_offset+=2; + } else { + c_write (code_offset>>8); + c_write (code_offset); + + if (flags & REFERENCE_LONG) + code_offset+=4; + else + code_offset+=2; + } + + c=c_read(); + continue; + } + case LREFERENCE: + { + int flags; + + flags=c_read(); + + c_write (O_REFERENCE); + c_write ( (flags & REFERENCE_A5 ? 128 : 0) + | (flags & REFERENCE_LONG ? 0 : 16) + | (flags & REFERENCE_DATA ? 1 : 0)); + + c_write (0); + c_write (8); + + c_write (c_read()); + c_write (c_read()); + + if (flags & REFERENCE_DATA){ + c_write (data_offset>>8); + c_write (data_offset); + } else { + c_write (code_offset>>8); + c_write (code_offset); + } + + if (flags & REFERENCE_OFFSET) + internal_error_in_function ("convert_to_mpw_object_code"); + + c=c_read(); + continue; + } + case LC_REFERENCE: + { + int flags; + + flags=c_read(); + + c_write (O_C_REFERENCE); + c_write ((flags & LCR_WORD ? 16 : 0) | (flags & LCR_BYTE ? 32 : 0)); + + c_write (0); + c_write (10); + + c_write (c_read()); + c_write (c_read()); + + c_write (c_read()); + c_write (c_read()); + if (flags & LCR_OFFSET) + internal_error_in_function ("convert_to_mpw_object_code"); + + c_write (code_offset>>8); + c_write (code_offset); + + c=c_read(); + continue; + } + case LLABEL: + { + int flags,id_h,id_l; + + flags=c_read(); + id_h=c_read(); + id_l=c_read(); + + if (flags & LLABEL_EXTERN){ + int size; + + size=c_read(); + + c_write (O_DICTIONARY); + c_write (0); + + c_write (0); + c_write (size+7); + + c_write (id_h); + c_write (id_l); + + c_write (size); + if (!(size & 1)) + c_write (c_read()); + while (size--) + c_write (c_read()); + } + + c_write (O_ENTRY); + c_write ((flags & LLABEL_DATA ? 1 : 0) | (flags & LLABEL_EXTERN ? 8 : 0)); + + c_write (id_h); + c_write (id_l); + + if (flags & LLABEL_DATA){ + c_write (data_offset>>24); + c_write (data_offset>>16); + c_write (data_offset>>8); + c_write (data_offset); + } else { + c_write (code_offset>>24); + c_write (code_offset>>16); + c_write (code_offset>>8); + c_write (code_offset); + } + + if (flags & LLABEL_OFFSET) + internal_error_in_function ("convert_to_mpw_object_code"); + + c=c_read(); + continue; + } + case LIMPORT: + { + int size,id_l,id_h; + + c_read(); + + id_h=c_read(); + id_l=c_read(); + size=c_read(); + + c_write (O_DICTIONARY); + c_write (0); + + c_write (0); + c_write (size+7); + + c_write (id_h); + c_write (id_l); + + c_write (size); + + if (!(size & 1)) + c_write (c_read()); + while (size--) + c_write (c_read()); + + c=c_read(); + continue; + } + case LMODULE: + { + int flag; + + flag=c_read(); + + if (code_offset!=0){ + c_write (O_MODULE); + c_write (0); + + c_write (code_module_id>>8); + c_write (code_module_id); + code_module_id=next_label_id++; + + c_write (segment_id>>8); + c_write (segment_id); + + code_offset=0; + } + + if (data_offset!=0){ + c_write (O_MODULE); + c_write (1); + + c_write (data_module_id>>8); + c_write (data_module_id); + data_module_id=next_label_id++; + + c_write (0); + c_write (0); + + data_offset=0; + } + c=c_read(); + continue; + } + case LBEGIN: + c_read(); + c_read(); + c_read(); + + c_write (O_FIRST); + c_write (1); + c_write (0); + c_write (2); + + c_write (O_DICTIONARY); + c_write (0); + + c_write (0); + c_write (7+1); + + c_write (segment_id>>8); + c_write (segment_id); + + c_write (1); + c_write ('m'); + + c=c_read(); + continue; + case LEND: + c_read(); + c_write (O_LAST); + c_write (0); + break; + default: + internal_error_in_function ("convert_to_mpw_object_code"); + } + break; + } + + d_buffer->size=IO_BUFFER_SIZE-d_free; + d_buffer->next=NULL; + + { + struct object_buffer *buffer,*next_buffer; + + for (buffer=s_buffer; buffer!=NULL; buffer=next_buffer){ + next_buffer=buffer->next; + + memory_free (buffer); + } + } + + first_buffer=first_d_buffer; +} + +/* end mpw object conversion */ +#endif + +static void write_object_buffers_and_release_memory (VOID) +{ + struct object_buffer *buffer,*next_buffer; + + for (buffer=first_buffer; 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=NULL; +} + +/* #define write_c(c) putc((c),output_file) */ + +static void write_w (UWORD i) +{ + write_c (i>>8); + write_c (i); +} + +static void write_l (register ULONG i) +{ + write_c (i>>24); + write_c (i>>16); + write_c (i>>8); + write_c (i); +} + +static void write_block (void *buffer,int length) +{ + char *p; + + if (length){ + p=(char*)buffer; + do + write_c (*p++); + while (--length); + } + /* + if (fwrite (buffer,1,length,output_file)!=length) + error ("Write error"); + */ +} + +static void write_s (char string[]) +{ + int length; + + length=strlen (string); + if (length>255) + length=255; + + write_c (length); + write_block (string,length); + if (!(length & 1)) + write_c (0); +} + +#ifdef MODULES +void start_new_module (int flag) +{ + write_c (LMODULE); + write_c (flag); +} +#endif + +static void import_label (int id,char label_name[]) +{ + write_c (LIMPORT); + write_c (0); + write_w (id); + write_s (label_name); +} + +void define_local_label (int id,int flag) +{ + write_c (LLABEL); + write_c (flag); + write_w (id); +} + +static void define_local_text_label (int id) +{ + write_c (LLABEL); + write_c (LLABEL_TEXT); + write_w (id); +} + +void define_external_label (int id,int flag,char label_name[]) +{ + write_c (LLABEL); + write_c (flag | LLABEL_EXTERN); + write_w (id); + write_s (label_name); +} + +void store_word_in_data_section (UWORD i) +{ + write_c (LDATA); + write_c (2); + write_w (i); +} + +void store_long_word_in_data_section (ULONG i) +{ + write_c (LDATA); + write_c (4); + write_l (i); +} + +void store_label_in_data_section (int label_id) +{ +#ifdef USE_LABEL_VALUE + write_c (LLABEL_VALUE); + write_c (REFERENCE_LONG | REFERENCE_DATA); + write_w (label_id); +#else + write_c (LREFERENCE); + write_c (REFERENCE_LONG | REFERENCE_DATA); + write_w (label_id); + write_c (LDATA); + write_c (4); + write_l (0); +#endif +} + +void store_descriptor_in_code_section (int label_id) +{ + write_c (LLABEL_VALUE); + write_c (REFERENCE_A5 | REFERENCE_LONG); + write_w (label_id); +} + +void store_descriptor_in_data_section (int label_id) +{ + write_c (LLABEL_VALUE); + write_c (REFERENCE_DATA | REFERENCE_A5 | REFERENCE_LONG); + write_w (label_id); +} + +void store_label_offset_in_data_section (int label_id) +{ +#ifdef USE_LABEL_VALUE + write_c (LLABEL_VALUE); + write_c (REFERENCE_DATA | REFERENCE_A5); + write_w (label_id); +#else + write_c (LREFERENCE); + write_c (REFERENCE_DATA | REFERENCE_A5); + write_w (label_id); + write_c (LDATA); + write_c (2); + write_w (0); +#endif +} + +void store_label_offset_in_code_section (int label_id) +{ +#ifdef USE_LABEL_VALUE + write_c (LLABEL_VALUE); + write_c (REFERENCE_A5); + write_w (label_id); +#else + write_c (LREFERENCE); + write_c (REFERENCE_A5); + write_w (label_id); + write_c (LCODE); + write_c (2); + write_w (0); +#endif +} + +static void store_text_label_in_text_section (LABEL *label) +{ + if (label->label_id<0) + label->label_id=next_label_id++; + +#ifdef USE_LABEL_VALUE + write_c (LLABEL_VALUE); + write_c (0); + write_w (label->label_id); +#else + write_c (LREFERENCE); + write_c (0); + write_w (label->label_id); + write_c (LCODE); + write_c (2); + write_w (0); +#endif +} + +void store_c_string_in_data_section (char *string,int length) +{ + int t_length; + +/* t_length=(length+1+1) & ~1; */ + t_length=(length+1+3) & ~3; + + if (t_length+1>255) + internal_error ("String too long in 'store_c_string_in_data_section'"); + + write_c (LDATA); + write_c (t_length); + write_block (string,length); + write_c (0); +/* + if (!(length & 1)) + write_c (0); +*/ + while (++length,length<t_length) + write_c (0); +} + +void store_abc_string_in_data_section (char *string,int length) +{ + int t_length=(length+4+3) & ~3; + + if (t_length>255) + internal_error ("String too long in 'store_abc_string_in_data_section'"); + + write_c (LDATA); + write_c (t_length); + write_l (length); + write_block (string,length); + while (length & 3){ + write_c (0); + ++length; + } +} + +void store_c_string_in_code_section (char *string,int length) +{ + int t_length=(length+1+1) & ~1; + + if (t_length+1>255) + internal_error ("String too long in 'store_c_string_in_code_section'"); + + write_c (LCODE); + write_c (t_length); + write_block (string,length); + write_c (0); + if (!(length & 1)) + write_c (0); +} + +void store_abc_string_in_code_section (char *string,int length) +{ + int t_length=(length+4+3) & ~3; + + if (t_length>255) + internal_error ("String too long in 'store_abc_string_in_code_section'"); + + write_c (LCODE); + write_c (t_length); + write_l (length); + write_block (string,length); + while (length & 3){ + write_c (0); + ++length; + } +} + +static void write_number_of_arguments (int number_of_arguments) +{ + write_c (LCODE); + write_c (2); + write_w (number_of_arguments); +} + +void store_descriptor_string_in_code_section + (char *string,int length,int string_code_label_id,LABEL *string_label) +{ + int t_length; + + t_length=(length+4+3) & ~3; + + if (t_length>255) + internal_error ("String too long in 'store_descriptor_string_in_code_section'"); + + write_c (LLABEL); + write_c (LLABEL_TEXT); + write_w (string_code_label_id); + + write_c (LCODE); + write_c (6); + + write_w (040772); /* LEA 4+2(PC),A0 */ + write_w (4); + write_w (0x4e75); /* RTS */ + + write_c (LMODULE); + write_c (1); + + write_c (LLABEL); + write_c (LLABEL_TEXT); + write_w (string_label->label_id); + + write_c (LCODE); + write_c (t_length); + + write_l (length); + write_block (string,length); + while (length & 3){ + write_c (0); + ++length; + } +} + +static WORD write_indirect_node_entry_jump (LABEL *label) +{ + register int new_label_id; + + new_label_id=next_label_id++; + + if (label->label_flags & EA_LABEL){ + int label_arity; + extern LABEL *eval_upd_labels[],*eval_fill_label; + LABEL *eval_upd_label; + + label_arity=label->label_arity; + + if (label_arity<-2) + label_arity=1; + + if (label_arity>=0 && label->label_ea_label!=eval_fill_label){ + write_c (LCODE); + write_c (2); + write_w (042700); + + write_c (LLABEL_VALUE); + write_c (0); + if (label->label_ea_label->label_id<0) + label->label_ea_label->label_id=next_label_id++; + write_w (label->label_ea_label->label_id); + + write_c (LCODE); + write_c (2); + write_w (047300); + + write_c (LLABEL_VALUE); + write_c (0); + eval_upd_label=eval_upd_labels[label_arity]; + if (eval_upd_label->label_id<0) + eval_upd_label->label_id=next_label_id++; + write_w (eval_upd_label->label_id); + } else { + write_c (LCODE); + write_c (2); + write_w (047300); + + write_c (LLABEL_VALUE); + write_c (0); + if (label->label_ea_label->label_id<0) + label->label_ea_label->label_id=next_label_id++; + write_w (label->label_ea_label->label_id); + + write_c (LCODE); + write_c (4); + write_w (0x4e71); + write_w (0x4e71); + } + + if (label->label_arity<0 || parallel_flag){ + LABEL *descriptor_label; + + descriptor_label=label->label_descriptor; + + if (descriptor_label->label_id<0) + descriptor_label->label_id=next_label_id++; + + store_label_offset_in_code_section (descriptor_label->label_id); + } else + write_number_of_arguments (0); + } else + if (label->label_arity<0 || parallel_flag){ + LABEL *descriptor_label; + + descriptor_label=label->label_descriptor; + + if (descriptor_label->label_id<0) + descriptor_label->label_id=next_label_id++; + + store_label_offset_in_code_section (descriptor_label->label_id); + } + + write_number_of_arguments (label->label_arity); + + define_local_text_label (new_label_id); + + write_w ((LCODE<<8)+2); + write_w (047300); + +#ifdef USE_LABEL_VALUE + write_w (LLABEL_VALUE<<8); + write_w (label->label_id); +#else + write_w (LREFERENCE<<8); + write_w (label->label_id); + + write_w ((LCODE<<8)+2); + write_w (0); +#endif + + return new_label_id; +} + +static void write_indirect_defered_jump (LABEL *label) +{ + LABEL *node_label; + + if (EMPTY_label->label_id<0) + EMPTY_label->label_id=next_label_id++; + store_label_offset_in_code_section (EMPTY_label->label_id); + + write_number_of_arguments (label->label_arity); + + if (label->label_id<0) + label->label_id=next_label_id++; + define_local_text_label (label->label_id); + + write_w ((LCODE<<8)+2); + write_w (047300); + + node_label=label->label_descriptor; + if (node_label->label_id<0) + node_label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + write_w (LLABEL_VALUE<<8); + write_w (node_label->label_id); +#else + write_w (LREFERENCE<<8); + write_w (node_label->label_id); + + write_w ((LCODE<<8)+2); + write_w (0); +#endif +} + +#ifdef COUNT_RELEASES +static int node_entry_count_label_id; +#endif + +static void import_labels (register struct label_node *label_node) +{ + register 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_id<0) + label->label_id=next_label_id++; + import_label (label->label_id,label->label_name); + if (label->label_flags & NODE_ENTRY_LABEL){ +#ifdef MODULES + start_new_module (0); +#endif + label->label_id=write_indirect_node_entry_jump (label); + } + } + + import_labels (label_node->label_node_left); + import_labels (label_node->label_node_right); +} + +static void write_indirect_jumps_for_defer_labels (void) +{ + struct local_label *local_label; + + for (local_label=local_labels; local_label!=NULL; local_label=local_label->local_label_next){ + LABEL *label; + + label=&local_label->local_label_label; + if (label->label_flags & DEFERED_LABEL){ +#ifdef MODULES + start_new_module (0); +#endif + write_indirect_defered_jump (label); + } + } +} + +static void write_labels (register struct block_label *labels) +{ + for (; labels!=NULL; labels=labels->block_label_next) + if (labels->block_label_label->label_number==0){ + register LABEL *label; + register int id; + + label=labels->block_label_label; + id=label->label_id; + if (id<0){ + id=next_label_id++; + label->label_id=id; + } + + if (label->label_flags & EXPORT_LABEL) + define_external_label (id,LLABEL_TEXT,label->label_name); + else + define_local_text_label (id); + } +} + +enum { SIZE_LONG, SIZE_WORD, SIZE_BYTE }; + +static void as_addressing_mode_instruction (struct parameter *parameter,int opcode,int size_flag) +{ + UWORD buffer[10],*code_buf_p,*end_buf_p; + + code_buf_p=buffer; + end_buf_p=code_buf_p; + *end_buf_p++=(LCODE<<8)+2; + ++end_buf_p; + + switch (parameter->parameter_type){ + case P_REGISTER: + { + int reg=parameter->parameter_data.reg.r; + if (is_d_register (reg)) + opcode |= 000 | d_reg_num (reg); + else + opcode |= 010 | a_reg_num (reg); + break; + } + case P_INDIRECT: + { + int offset=parameter->parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (parameter->parameter_data.reg.r); + } else { + opcode |= 050 | a_reg_num (parameter->parameter_data.reg.r); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_POST_INCREMENT: + opcode |= 030 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_PRE_DECREMENT: + opcode |= 040 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_LABEL: + { + LABEL *label; + + opcode |= 055; + + label=parameter->parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } + case P_DESCRIPTOR_NUMBER: + { + LABEL *label; + + opcode |= 074; + + if (size_flag==SIZE_LONG){ + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++=0xffff; + } + + label=parameter->parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; + +#ifdef USE_LABEL_VALUE + if (parameter->parameter_offset==0){ + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + } else { +#endif + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + code_buf_p=end_buf_p; + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=parameter->parameter_offset << 2; +#ifdef USE_LABEL_VALUE + } +#endif + break; + } + case P_IMMEDIATE: + opcode |= 074; + if (size_flag==SIZE_LONG){ + ((UBYTE*)code_buf_p)[1]+=4; + *(*(ULONG**)&end_buf_p)++ = parameter->parameter_data.i; + } else { + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = parameter->parameter_data.i; + } + break; +/* CHANGED 27-7-92 */ + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + + offset=parameter->parameter_offset; + index_registers=parameter->parameter_data.ir; + + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = 0x800 | (d_reg_num (index_registers->d_reg.r)<<12) + | ((offset>>2) & 0xff) | ((offset & 3)<<9); + opcode |= 060 | a_reg_num (index_registers->a_reg.r); + break; + } +/* */ + default: + internal_error_in_function ("as_addressing_mode_instruction"); + } + + buffer[1]=opcode; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); +} + +static void as_immediate_data_alterable_addressing_mode + (int opcode,UWORD buffer[],UWORD *code_buf_p,UWORD *end_buf_p,struct parameter *parameter) +{ + switch (parameter->parameter_type){ + case P_REGISTER: + { + int reg=parameter->parameter_data.reg.r; + if (is_d_register (reg)) + opcode |= 000 | d_reg_num (reg); + else + internal_error_in_function ("as_immediate_data_alterable_addressing mode"); + break; + } + case P_INDIRECT: + { + int offset=parameter->parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (parameter->parameter_data.reg.r); + } else { +#ifdef USE_LABEL_VALUE + if (code_buf_p==NULL){ + code_buf_p=end_buf_p; + *end_buf_p++=LCODE<<8; + } +#endif + opcode |= 050 | a_reg_num (parameter->parameter_data.reg.r); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_POST_INCREMENT: + opcode |= 030 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_PRE_DECREMENT: + opcode |= 040 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_LABEL: + { + LABEL *label; + + opcode |= 055; + + label=parameter->parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } +/* CHANGED 27-7-92 */ + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + + offset=parameter->parameter_offset; + index_registers=parameter->parameter_data.ir; +#ifdef USE_LABEL_VALUE + if (code_buf_p==NULL){ + code_buf_p=end_buf_p; + *end_buf_p++=LCODE<<8; + } +#endif + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = 0x800 | (d_reg_num (index_registers->d_reg.r)<<12) + | ((offset>>2) & 0xff) | ((offset & 3)<<9); + opcode |= 060 | a_reg_num (index_registers->a_reg.r); + break; + } +/* */ + default: + internal_error_in_function ("as_immediate_data_alterable_addressing_mode"); + } + + buffer[1]=opcode; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); +} + +static void as_data_addressing_mode ( int opcode,UWORD buffer[],UWORD *code_buf_p, + UWORD *end_buf_p,struct parameter *parameter,int size_flag) +{ + switch (parameter->parameter_type){ + case P_REGISTER: + { + int reg=parameter->parameter_data.reg.r; + if (is_d_register (reg)) + opcode |= 000 | d_reg_num (reg); + else + internal_error_in_function ("as_data_addressing mode"); + break; + } + case P_INDIRECT: + { + int offset=parameter->parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (parameter->parameter_data.reg.r); + } else { + opcode |= 050 | a_reg_num (parameter->parameter_data.reg.r); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_POST_INCREMENT: + opcode |= 030 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_PRE_DECREMENT: + opcode |= 040 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_LABEL: + { + LABEL *label; + + opcode |= 055; + + label=parameter->parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } + case P_DESCRIPTOR_NUMBER: + { + LABEL *label; + + opcode |= 074; + + if (size_flag==SIZE_LONG){ + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++=0xffff; + } + + label=parameter->parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + if (parameter->parameter_offset==0){ + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + } else { +#endif + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=parameter->parameter_offset << 2; +#ifdef USE_LABEL_VALUE + } +#endif + break; + } + case P_IMMEDIATE: + opcode |= 074; + if (size_flag==SIZE_LONG){ + ((UBYTE*)code_buf_p)[1]+=4; + *(*(ULONG**)&end_buf_p)++ = parameter->parameter_data.i; + } else { + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = parameter->parameter_data.i; + } + break; +/* CHANGED 27-7-92 */ + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + + offset=parameter->parameter_offset; + index_registers=parameter->parameter_data.ir; + + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = 0x800 | (d_reg_num (index_registers->d_reg.r)<<12) + | ((offset>>2) & 0xff) | ((offset & 3)<<9); + opcode |= 060 | a_reg_num (index_registers->a_reg.r); + break; + } +/* */ + default: + internal_error_in_function ("as_data_addressing_mode"); + } + + buffer[1]=opcode; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); +} + +static void as_alterable_memory_addressing_mode_instruction (struct parameter *parameter,int opcode) +{ + UWORD buffer[10],*code_buf_p,*end_buf_p; + + code_buf_p=buffer; + end_buf_p=code_buf_p; + *end_buf_p++=(LCODE<<8)+2; + ++end_buf_p; + + switch (parameter->parameter_type){ + case P_INDIRECT: + { + int offset=parameter->parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (parameter->parameter_data.reg.r); + } else { + opcode |= 050 | a_reg_num (parameter->parameter_data.reg.r); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_POST_INCREMENT: + opcode |= 030 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_PRE_DECREMENT: + opcode |= 040 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_LABEL: + { + LABEL *label; + + opcode |= 055; + + label=parameter->parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + code_buf_p=end_buf_p; + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } +/* CHANGED 27-7-92 */ + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + + offset=parameter->parameter_offset; + index_registers=parameter->parameter_data.ir; + + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = 0x800 | (d_reg_num (index_registers->d_reg.r)<<12) + | ((offset>>2) & 0xff) | ((offset & 3)<<9); + opcode |= 060 | a_reg_num (index_registers->a_reg.r); + break; + } +/* */ + default: + internal_error_in_function ("as_alterable_memory_addressing_mode_instruction"); + } + + buffer[1]=opcode; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); +} + +static void as_control_addressing_mode_instruction (struct parameter *parameter,int opcode) +{ + UWORD buffer[10],*end_buf_p; + + end_buf_p=buffer; + *end_buf_p++=(LCODE<<8)+2; + + switch (parameter->parameter_type){ + case P_INDIRECT: + { + int offset=parameter->parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (parameter->parameter_data.reg.r); + *end_buf_p++=opcode; + } else { + opcode |= 050 | a_reg_num (parameter->parameter_data.reg.r); + *end_buf_p++=opcode; + ((UBYTE*)buffer)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_LABEL: + { + LABEL *label; + + label=parameter->parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; + + if (label->label_flags & DATA_LABEL){ + opcode |= 055; + *end_buf_p++=opcode; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; +#endif + } else { + *end_buf_p++=opcode; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8); +#else + *end_buf_p++=(LREFERENCE<<8); +#endif + } + + *end_buf_p++=label->label_id; +#ifndef USE_LABEL_VALUE + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } +/* CHANGED 27-7-92 */ + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + + offset=parameter->parameter_offset; + index_registers=parameter->parameter_data.ir; + opcode |= 060 | a_reg_num (index_registers->a_reg.r); + + *end_buf_p++=opcode; + ((UBYTE*)buffer)[1]+=2; + *end_buf_p++ = 0x800 | (d_reg_num (index_registers->d_reg.r)<<12) + | ((offset>>2) & 0xff) | ((offset & 3)<<9); + break; + } +/* */ + default: + internal_error_in_function ("as_control_addressing_mode_instruction"); + } + + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); +} + +static void as_fp_instruction_p (int opcode,int fp_opcode,struct parameter *parameter) +{ + UWORD buffer[14],*code_buf_p,*end_buf_p; + + buffer[0]=(LCODE<<8)+4; + buffer[2]=fp_opcode; + + code_buf_p=buffer; + end_buf_p=&buffer[3]; + + switch (parameter->parameter_type){ + case P_REGISTER: + { + int reg=parameter->parameter_data.reg.r; + if (is_d_register (reg)) + opcode |= 000 | d_reg_num (reg); + else + internal_error_in_function ("as_fp_addressing mode"); + break; + } + case P_INDIRECT: + { + int offset=parameter->parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (parameter->parameter_data.reg.r); + } else { + opcode |= 050 | a_reg_num (parameter->parameter_data.reg.r); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_POST_INCREMENT: + opcode |= 030 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_PRE_DECREMENT: + opcode |= 040 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_LABEL: + { + LABEL *label; + + opcode |= 055; + + label=parameter->parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } + case P_F_IMMEDIATE: + { + DOUBLE d; + float f; + + opcode |= 074; + + d=*parameter->parameter_data.r; + f=d; + if (d==f){ + buffer[2]&=~0x1000; + ((UBYTE*)code_buf_p)[1]+=4; + *(*(float**)&end_buf_p)++ = f; + } else { + ((UBYTE*)code_buf_p)[1]+=8; + *(*(DOUBLE**)&end_buf_p)++ = d; + } + break; + } + case P_IMMEDIATE: + { + opcode |= 074; + ((UBYTE*)code_buf_p)[1]+=4; + *(*(ULONG**)&end_buf_p)++ = parameter->parameter_data.i; + break; + } +/* CHANGED 22-7-92 */ + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + + offset=parameter->parameter_offset; + index_registers=parameter->parameter_data.ir; + + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = 0x800 | (d_reg_num (index_registers->d_reg.r)<<12) + | ((offset>>2) & 0xff) | ((offset & 3)<<9); + opcode |= 060 | a_reg_num (index_registers->a_reg.r); + break; + } +/* */ + default: + internal_error_in_function ("as_fp_instruction_p"); + } + + buffer[1]=opcode; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); +} + +static void as_move_instruction (register struct instruction *instruction,int size_flag) +{ + register UWORD opcode; + UWORD buffer[14]; + register UWORD *code_buf_p,*end_buf_p; + + code_buf_p=buffer; + end_buf_p=code_buf_p; + *end_buf_p++=(LCODE<<8)+2; + ++end_buf_p; + opcode= size_flag==SIZE_LONG ? 020000 : (size_flag==SIZE_WORD ? 030000 : 010000); + + switch (instruction->instruction_parameters[0].parameter_type){ + case P_REGISTER: + { + int reg=instruction->instruction_parameters[0].parameter_data.reg.r; + if (is_d_register (reg)) + opcode |= 000 | d_reg_num (reg); + else + opcode |= 010 | a_reg_num (reg); + break; + } + case P_INDIRECT: + { + int offset=instruction->instruction_parameters[0].parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + } else { + opcode |= 050 | a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_POST_INCREMENT: + opcode |= 030 | a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + break; + case P_PRE_DECREMENT: + opcode |= 040 | a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + break; + case P_LABEL: + { + LABEL *label; + + opcode |= 055; + + label=instruction->instruction_parameters[0].parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + code_buf_p=NULL; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + code_buf_p=end_buf_p; + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } + case P_DESCRIPTOR_NUMBER: + { + LABEL *label; + + opcode |= 074; + if (size_flag==SIZE_LONG){ + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++=0xffff; + } + + label=instruction->instruction_parameters[0].parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + if (instruction->instruction_parameters[0].parameter_offset==0){ + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + code_buf_p=NULL; + } else { +#endif + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + code_buf_p=end_buf_p; + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=instruction->instruction_parameters[0].parameter_offset << 2; +#ifdef USE_LABEL_VALUE + } +#endif + break; + } + case P_IMMEDIATE: + { + LONG i=instruction->instruction_parameters[0].parameter_data.i; + + /* MOVEQ ? */ + if (size_flag==SIZE_LONG && i<128 && i>=-128 + && instruction->instruction_parameters[1].parameter_type==P_REGISTER + && is_d_register (instruction->instruction_parameters[1].parameter_data.reg.r)){ + write_c (LCODE); + write_c (2); + write_c (0x70 | (d_reg_num + (instruction->instruction_parameters[1].parameter_data.reg.r)<<1)); + write_c (i); + return; + } + + /* CLR ? */ + if (i==0 && instruction->instruction_parameters[1].parameter_type!=P_REGISTER){ + buffer[0]=(LCODE<<8)+2; + opcode=(size_flag==SIZE_LONG) ? 041200 : (size_flag==SIZE_WORD) ? 041100 : 041000 ; + + as_data_addressing_mode (opcode,buffer,buffer,&buffer[2], + &instruction->instruction_parameters[1],size_flag); + return; + } + + if (size_flag==SIZE_LONG){ + ((UBYTE*)code_buf_p)[1]+=4; + *(ULONG*)end_buf_p=i; + end_buf_p+=2; + } else { + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++=i; + } + opcode |= 074; + break; + } +/* CHANGED 22-7-92 */ + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + + offset=instruction->instruction_parameters[0].parameter_offset; + + index_registers=instruction->instruction_parameters[0].parameter_data.ir; + + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = 0x800 | (d_reg_num (index_registers->d_reg.r)<<12) + | ((offset>>2) & 0xff) | ((offset & 3)<<9); + opcode |= 060 | a_reg_num (index_registers->a_reg.r); + break; + } +/* */ + default: + internal_error_in_function ("as_move_instruction"); + } + + switch (instruction->instruction_parameters[1].parameter_type){ + case P_REGISTER: + { + int reg=instruction->instruction_parameters[1].parameter_data.reg.r; + if (is_d_register (reg)) + opcode |= 0000 | (d_reg_num (reg)<<9); + else + opcode |= 0100 | (a_reg_num (reg)<<9); + break; + } + case P_INDIRECT: + { + int offset=instruction->instruction_parameters[1].parameter_offset; + if (offset==0){ + opcode |= 0200 | + (a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r)<<9); + } else { +#ifdef USE_LABEL_VALUE + if (code_buf_p==NULL){ + code_buf_p=end_buf_p; + *end_buf_p++=LCODE<<8; + } +#endif + opcode |= 0500 | + (a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r)<<9); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_POST_INCREMENT: + opcode |= 0300 | + (a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r)<<9); + break; + case P_PRE_DECREMENT: + opcode |= 0400 | + (a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r)<<9); + break; + case P_LABEL: + { + LABEL *label; + + opcode |= 05200; + + label=instruction->instruction_parameters[1].parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; + +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } +/* CHANGED 22-7-92 */ + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + +#ifdef USE_LABEL_VALUE + if (code_buf_p==NULL){ + code_buf_p=end_buf_p; + *end_buf_p++=LCODE<<8; + } +#endif + index_registers=instruction->instruction_parameters[1].parameter_data.ir; + offset=instruction->instruction_parameters[1].parameter_offset; + + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = 0x800 | (d_reg_num (index_registers->d_reg.r)<<12) + | ((offset>>2) & 0xff) | ((offset & 3)<<9); + opcode |= 0600 | (a_reg_num (index_registers->a_reg.r)<<9); + break; + } +/* */ + default: + internal_error_in_function ("as_move_instruction"); + } + + buffer[1]=opcode; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); +} + +static void as_lea_instruction (struct instruction *instruction) +{ + int opcode=040700 | (a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r)<<9); + + if (instruction->instruction_parameters[0].parameter_type==P_LABEL && + instruction->instruction_parameters[0].parameter_offset!=0) + { + UWORD buffer[10],*end_buf_p; + LABEL *label; + + end_buf_p=buffer; + *end_buf_p++=(LCODE<<8)+2; + + label=instruction->instruction_parameters[0].parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; + + if (label->label_flags & DATA_LABEL){ + opcode |= 055; + *end_buf_p++=opcode; + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + } else { + *end_buf_p++=opcode; + *end_buf_p++=(LREFERENCE<<8); + } + + *end_buf_p++=label->label_id; + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=instruction->instruction_parameters[0].parameter_offset; + + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); + } else + as_control_addressing_mode_instruction (&instruction->instruction_parameters[0],opcode); +} + +static void as_add_instruction (struct instruction *instruction) +{ + int opcode; + + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){ + int reg=instruction->instruction_parameters[1].parameter_data.reg.r; + + /* ADDQ, SUBQ or LEA ? */ + if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){ + LONG i=instruction->instruction_parameters[0].parameter_data.i; + + if (i<=8 && i>=-8 && i!=0){ + write_c (LCODE); + write_c (2); + if (i>0) + opcode=050200 | ((i & 7) << 9); + else + opcode=050600 | ((-i & 7) << 9); + if (is_d_register (reg)) + opcode |= d_reg_num (reg); + else + opcode |= 010 | a_reg_num (reg); + write_w (opcode); + return; + } else if (is_a_register (reg) && i>=-32768 && i<32768){ + write_c (LCODE); + write_c (4); + write_w (040750 | a_reg_num (reg) | (a_reg_num (reg)<<9)); + write_w (i); + return; + } + } + + if (is_d_register (reg)) + opcode=0150200 + (d_reg_num (reg)<<9); + else + opcode=0150700 + (a_reg_num (reg)<<9); + + as_addressing_mode_instruction (&instruction->instruction_parameters[0],opcode,SIZE_LONG); + } else if (instruction->instruction_parameters[0].parameter_type==P_REGISTER && + is_d_register (instruction->instruction_parameters[0].parameter_data.reg.r)){ + opcode=0150600 + + (d_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r)<<9); + as_alterable_memory_addressing_mode_instruction + (&instruction->instruction_parameters[1],opcode); + } else + /* ADDI not yet implemented */ + internal_error_in_function ("as_add_instruction"); +} + +static void as_sub_instruction (struct instruction *instruction) +{ + int opcode; + + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){ + int reg=instruction->instruction_parameters[1].parameter_data.reg.r; + + /* SUBQ, ADDQ or LEA ? */ + if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){ + LONG i=instruction->instruction_parameters[0].parameter_data.i; + + if (i<=8 && i>=-8 && i!=0){ + write_c (LCODE); + write_c (2); + if (i>0) + opcode=050600 | ((i & 7) << 9); + else + opcode=050200 | ((-i & 7) << 9); + if (is_d_register (reg)) + opcode |= d_reg_num (reg); + else + opcode |= 010 | a_reg_num (reg); + write_w (opcode); + return; + } else if (is_a_register (reg) && i>-32768 && i<=32768){ + write_c (LCODE); + write_c (4); + write_w (040750 | a_reg_num (reg) | (a_reg_num (reg)<<9)); + write_w (-i); + return; + } + + } + + if (is_d_register (reg)) + opcode=0110200 + (d_reg_num (reg)<<9); + else + opcode=0110700 + (a_reg_num (reg)<<9); + + as_addressing_mode_instruction (&instruction->instruction_parameters[0],opcode,SIZE_LONG); + } else if (instruction->instruction_parameters[0].parameter_type==P_REGISTER && + is_d_register (instruction->instruction_parameters[0].parameter_data.reg.r)){ + opcode=0110600 + + (d_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r)<<9); + as_alterable_memory_addressing_mode_instruction + (&instruction->instruction_parameters[1],opcode); + } else + /* SUBI not yet implemented */ + internal_error_in_function ("as_sub_instruction"); +} + +static void as_and_or_instruction (struct instruction *instruction,int opcode) +{ + UWORD buffer[14]; + int reg; + + if (instruction->instruction_parameters[1].parameter_type!=P_REGISTER || + is_a_register (reg=instruction->instruction_parameters[1].parameter_data.reg.r)) + { + internal_error_in_function ("as_and_or_instruction"); + return; + } + + opcode+=d_reg_num (reg)<<9; + + buffer[0]=(LCODE<<8)+2; + as_data_addressing_mode (opcode,buffer,buffer,&buffer[2], + &instruction->instruction_parameters[0],SIZE_LONG); +} + +static void as_eor_instruction (struct instruction *instruction) +{ + int reg_1,reg_2; + + if (instruction->instruction_parameters[1].parameter_type!=P_REGISTER || + is_a_register (reg_2=instruction->instruction_parameters[1].parameter_data.reg.r)) + { + internal_error_in_function ("as_eor_instruction"); + return; + } + + switch (instruction->instruction_parameters[0].parameter_type){ + case P_IMMEDIATE: + { + long m=instruction->instruction_parameters[0].parameter_data.i; + + if (m==-1){ /* replace EOR #-1,Dn by NOT Dn */ + write_c (LCODE); + write_c (2); + write_w (043200 | d_reg_num (reg_2)); + } else { + write_c (LCODE); + write_c (6); + write_w (005200 | d_reg_num (reg_2)); + write_l (m); + } + return; + } + case P_REGISTER: + if (is_d_register (reg_1=instruction->instruction_parameters[0].parameter_data.reg.r)){ + write_c (LCODE); + write_c (2); + write_w (0130600 | (d_reg_num (reg_1)<<9) | d_reg_num (reg_2)); + return; + } + default: + internal_error_in_function ("as_eor_instruction"); + } +} + +static void as_cmp_instruction (struct instruction *instruction,int size_flag) +{ + int opcode; + + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){ + int reg=instruction->instruction_parameters[1].parameter_data.reg.r; + + if (is_d_register (reg)){ + if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE && + instruction->instruction_parameters[0].parameter_data.i==0){ + /* CMPI #0 becomes TST */ + write_c (LCODE); + write_c (2); + write_w ((size_flag==SIZE_LONG ? 045200 : 045100) | d_reg_num (reg)); + return; + } + opcode=0130200 + (d_reg_num (reg)<<9); + } else + opcode=0130700 + (a_reg_num (reg)<<9); + + as_addressing_mode_instruction (&instruction->instruction_parameters[0],opcode,size_flag); + } else + switch (instruction->instruction_parameters[0].parameter_type){ + case P_IMMEDIATE: + { + UWORD buffer[14],*end_buf_p,opcode; + LONG i; + + i=instruction->instruction_parameters[0].parameter_data.i; + + if (i==0){ + /* CMPI #0 becomes TST */ + buffer[0]=(LCODE<<8)+2; + opcode= size_flag==SIZE_LONG ? 045200 : 045100; + as_immediate_data_alterable_addressing_mode + (opcode,buffer,buffer,&buffer[2],&instruction->instruction_parameters[1]); + } else { + if (size_flag==SIZE_LONG){ + buffer[0]=(LCODE<<8)+6; + *(ULONG*)(&buffer[2])=i; + end_buf_p=&buffer[4]; + opcode=06200; + } else { + buffer[0]=(LCODE<<8)+4; + buffer[2]=i; + end_buf_p=&buffer[3]; + opcode=06100; + } + as_immediate_data_alterable_addressing_mode + (opcode,buffer,buffer,end_buf_p,&instruction->instruction_parameters[1]); + } + break; + } + case P_DESCRIPTOR_NUMBER: + { + UWORD buffer[14],*end_buf_p,*code_buf_p,opcode; + LABEL *label; + + buffer[0]=(LCODE<<8)+2; + code_buf_p=buffer; + end_buf_p=&buffer[2]; + + if (size_flag==SIZE_LONG){ + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++=0xffff; + opcode=06200; + } else + opcode=06100; + + label=instruction->instruction_parameters[0].parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + if (instruction->instruction_parameters[0].parameter_offset==0){ + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + code_buf_p=NULL; + } else { +#endif + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + code_buf_p=end_buf_p; + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=instruction->instruction_parameters[0].parameter_offset << 2; +#ifdef USE_LABEL_VALUE + } +#endif + as_immediate_data_alterable_addressing_mode + (opcode,buffer,code_buf_p,end_buf_p,&instruction->instruction_parameters[1]); + break; + } + default: + internal_error_in_function ("as_cmp_instruction"); + } +} + +static void as_tst_instruction (struct instruction *instruction,int size_flag) +{ + UWORD buffer[14],opcode; + + buffer[0]=(LCODE<<8)+2; + opcode=045200; + + as_data_addressing_mode (opcode,buffer,buffer,&buffer[2], + &instruction->instruction_parameters[0],size_flag); +} + +static void as_branch_instruction (struct instruction *instruction,int opcode) +{ + UWORD buffer[10]; + register UWORD *buf_p; + LABEL *label; + + if (instruction->instruction_parameters[0].parameter_type!=P_LABEL) + internal_error_in_function ("as_branch_instruction"); + + label=instruction->instruction_parameters[0].parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; + + buf_p=buffer; + *buf_p++=(LCODE<<8)+2; + *buf_p++=opcode; + +#if defined (USE_LABEL_VALUE) && !defined (GENERATE_MPW_OBJECT_CODE) + *buf_p++=(LLABEL_VALUE<<8)+REFERENCE_PC; + *buf_p++=label->label_id; +#else + { + int id; + + id=next_label_id++; + *buf_p++=(LLABEL<<8); + *buf_p++=id; + *buf_p++=(LC_REFERENCE<<8)+LCR_WORD; + *buf_p++=label->label_id; + *buf_p++=id; + *buf_p++=(LCODE<<8)+2; + *buf_p++=0; + } +#endif + write_block (buffer,(UBYTE*)buf_p-(UBYTE*)buffer); +} + +static void as_short_branch_instruction (struct instruction *instruction,int opcode) +{ + switch (instruction->instruction_parameters[0].parameter_type){ + case P_LABEL: + { + LABEL *label; + UWORD buffer[10],*buf_p; + int id; + + label=instruction->instruction_parameters[0].parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; + + id=next_label_id++; + + buf_p=buffer; + *buf_p++=(LCODE<<8)+1; + *buf_p++=opcode; + + *buf_p++=(LC_REFERENCE<<8)+LCR_BYTE; + *buf_p++=label->label_id; + *buf_p++=id; + + *buf_p++=(LCODE<<8)+1; + *buf_p++=0; + + *buf_p++=(LLABEL<<8); + *buf_p++=id; + + write_block (buffer,(UBYTE*)buf_p-(UBYTE*)buffer); + return; + } + case P_IMMEDIATE: + { + int offset; + + offset=instruction->instruction_parameters[0].parameter_data.i; + + write_w ((LCODE<<8)+2); + write_w (opcode+offset); + return; + } + default: + internal_error_in_function ("as_short_branch_instruction"); + } +} + +static void as_movem_instruction (struct instruction *instruction) +{ + UWORD opcode,register_list; + UWORD buffer[10],*code_buf_p,*end_buf_p; + register unsigned int n,arity; + + code_buf_p=buffer; + end_buf_p=code_buf_p; + *end_buf_p++=(LCODE<<8)+4; + ++end_buf_p; + ++end_buf_p; + opcode=046300; + + switch (instruction->instruction_parameters[0].parameter_type){ + case P_INDIRECT: + { + int offset=instruction->instruction_parameters[0].parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + } else { + opcode |= 050 | a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_POST_INCREMENT: + opcode |= 030 | a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + break; + case P_LABEL: + { + LABEL *label; + + opcode |= 055; + + label=instruction->instruction_parameters[0].parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } + case P_REGISTER: + { + int offset,reg; + + arity=instruction->instruction_arity; + + if (instruction->instruction_parameters[arity-1].parameter_type==P_PRE_DECREMENT){ + opcode = 044340 | a_reg_num (instruction->instruction_parameters[arity-1].parameter_data.reg.r); + + register_list=0; + --arity; + for (n=0; n<arity; ++n){ + register int reg; + + reg=instruction->instruction_parameters[n].parameter_data.reg.r; + if (is_d_register (reg)) + register_list |= ((unsigned)0x8000>>d_reg_num (reg)); + else + register_list |= ((unsigned)0x8000>>8+a_reg_num (reg)); + } + + buffer[1]=opcode; + buffer[2]=register_list; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); + return; + } + + if (instruction->instruction_arity!=2 + || instruction->instruction_parameters[1].parameter_type!=P_INDIRECT) + internal_error_in_function ("as_movem_instruction"); + + opcode=044300; + offset=instruction->instruction_parameters[1].parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r); + } else { + opcode |= 050 | a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + + reg=instruction->instruction_parameters[0].parameter_data.reg.r; + if (is_d_register (reg)) + register_list = ((unsigned)1<<d_reg_num (reg)); + else + register_list = ((unsigned)1<<8+a_reg_num (reg)); + + buffer[1]=opcode; + buffer[2]=register_list; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); + return; + } + default: + internal_error_in_function ("as_movem_instruction"); + } + + register_list=0; + + arity=instruction->instruction_arity; + for (n=1; n<arity; ++n){ + register int reg; + + reg=instruction->instruction_parameters[n].parameter_data.reg.r; + if (is_d_register (reg)) + register_list |= ((unsigned)1<<d_reg_num (reg)); + else + register_list |= ((unsigned)1<<8+a_reg_num (reg)); + } + + buffer[1]=opcode; + buffer[2]=register_list; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); +} + +static void as_shift_instruction (struct instruction *instruction,int opcode) +{ + int reg_1,reg_2; + + if (instruction->instruction_parameters[1].parameter_type!=P_REGISTER || + !is_d_register (reg_2=instruction->instruction_parameters[1].parameter_data.reg.r)) + { + internal_error_in_function ("as_shift_instruction"); + return; + } + + switch (instruction->instruction_parameters[0].parameter_type){ + case P_IMMEDIATE: + { + LONG count; + + count=instruction->instruction_parameters[0].parameter_data.i; + + if (count<=0 || count>8) + internal_error_in_function ("as_shift_instruction"); + + write_c (LCODE); + write_c (2); + write_w (opcode | ((count & 7)<<9) | d_reg_num (reg_2)); + return; + } + case P_REGISTER: + if (is_d_register (reg_1=instruction->instruction_parameters[0].parameter_data.reg.r)){ + write_c (LCODE); + write_c (2); + write_w (opcode | 040 | (d_reg_num (reg_1)<<9) | d_reg_num (reg_2)); + return; + } + default: + internal_error_in_function ("as_shift_instruction"); + } +} + +static void as_mul_instruction (struct instruction *instruction) +{ + UWORD buffer[14],opcode,reg; + + buffer[0]=(LCODE<<8)+4; + reg=instruction->instruction_parameters[1].parameter_data.reg.r; + buffer[2]=004000 | reg | (reg<<12); + opcode=046000; + + as_data_addressing_mode (opcode,buffer,buffer,&buffer[3], + &instruction->instruction_parameters[0],SIZE_LONG); +} + +static void as_div_instruction (struct instruction *instruction) +{ + UWORD buffer[14],opcode,reg_n; + + buffer[0]=(LCODE<<8)+4; + reg_n=d_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r); + buffer[2]=004000 | reg_n | (reg_n<<12); + opcode=046100; + + as_data_addressing_mode (opcode,buffer,buffer,&buffer[3], + &instruction->instruction_parameters[0],SIZE_LONG); +} + +static void as_mod_instruction (struct instruction *instruction) +{ + UWORD buffer[14],opcode; + + + buffer[0]=(LCODE<<8)+4; + buffer[2]=004000 | instruction->instruction_parameters[1].parameter_data.reg.r + | (instruction->instruction_parameters[2].parameter_data.reg.r<<12); + opcode=046100; + + as_data_addressing_mode (opcode,buffer,buffer,&buffer[3], + &instruction->instruction_parameters[0],SIZE_LONG); +} + +static void as_bmove_instruction (struct instruction *instruction) +{ + UWORD buffer[5],opcode; + + buffer[0]=(LCODE<<8)+8; + buffer[1]=0x6002; /* BRA.S *+4 */ + opcode=020000; + switch (instruction->instruction_parameters[0].parameter_type){ + case P_POST_INCREMENT: + opcode |= 030 | + a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + break; + case P_PRE_DECREMENT: + opcode |= 040 | + a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + break; + default: + internal_error_in_function ("as_bmove_instruction"); + } + switch (instruction->instruction_parameters[1].parameter_type){ + case P_POST_INCREMENT: + opcode |= 0300 | + (a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r)<<9); + break; + case P_PRE_DECREMENT: + opcode |= 0400 | + (a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r)<<9); + break; + default: + internal_error_in_function ("as_bmove_instruction"); + } + buffer[2]=opcode; /* MOVE -(An)+,-(An)+ */ + buffer[3]=0x51c8+d_reg_num (instruction->instruction_parameters[2].parameter_data.reg.r); + buffer[4]=-4; /* DBRA Dn,*-2 */ + + write_block (buffer,10); +} + +static void as_exg_instruction (struct instruction *instruction) +{ + int opcode,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 (is_d_register (reg_1)) + if (is_d_register (reg_2)) + opcode=0xc140+(d_reg_num (reg_1)<<9)+d_reg_num (reg_2); + else + opcode=0xc188+(d_reg_num (reg_1)<<9)+a_reg_num (reg_2); + else + if (is_d_register (reg_2)) + opcode=0xc188+(d_reg_num (reg_2)<<9)+a_reg_num (reg_1); + else + opcode=0xc148+(a_reg_num (reg_1)<<9)+a_reg_num (reg_2); + + write_c (LCODE); + write_c (2); + write_w (opcode); +} + +static void as_extb_instruction (struct instruction *instruction) +{ + int reg; + + reg=d_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + + if (!mc68000_flag){ + write_c (LCODE); + write_c (2); + write_w (044700 | d_reg_num (reg)); + } else { + write_c (LCODE); + write_c (4); + write_w (044200 | d_reg_num (reg)); + write_w (044300 | d_reg_num (reg)); + } +} + +static void as_ext_instruction (struct instruction *instruction) +{ + int reg=d_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + + write_c (LCODE); + write_c (2); + write_w (044300+d_reg_num (reg)); +} + +static void as_set_condition_instruction (struct instruction *instruction,int opcode) +{ + int reg_1; + + if (instruction->instruction_parameters[0].parameter_type!=P_REGISTER || + !is_d_register (reg_1=instruction->instruction_parameters[0].parameter_data.reg.r)) + { + internal_error_in_function ("as_set_condition_instruction"); + return; + } + + if (!mc68000_flag){ + write_c (LCODE); + write_c (4); + write_w (opcode | d_reg_num (reg_1)); + write_w (044700 | d_reg_num (reg_1)); + } else { + write_c (LCODE); + write_c (6); + write_w (opcode | d_reg_num (reg_1)); + write_w (044200 | d_reg_num (reg_1)); + write_w (044300 | d_reg_num (reg_1)); + } +} + +static void as_fmove_instruction (struct instruction *instruction,int size_mask) +{ + if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){ + int reg_1; + + reg_1=instruction->instruction_parameters[0].parameter_data.reg.r; + + if (instruction->instruction_parameters[1].parameter_type==P_F_REGISTER){ + int reg_2; + + reg_2=instruction->instruction_parameters[1].parameter_data.reg.r; + write_c (LCODE); + write_c (4); + write_w (0xf200); + write_w ((reg_1<<10) | (reg_2<<7)); + } else + as_fp_instruction_p (0xf200,size_mask | 0x6000 | (reg_1<<7), + &instruction->instruction_parameters[1]); + } else if (instruction->instruction_parameters[1].parameter_type==P_F_REGISTER){ + int reg_1; + + reg_1=instruction->instruction_parameters[1].parameter_data.reg.r; + as_fp_instruction_p (0xf200,size_mask | 0x4000 | (reg_1<<7), + &instruction->instruction_parameters[0]); + } else + internal_error_in_function ("as_fmove_instruction"); +} + +static void as_fp_instruction (struct instruction *instruction,int function_code) +{ + int reg_1; + + if (instruction->instruction_parameters[1].parameter_type!=P_F_REGISTER){ + internal_error_in_function ("as_fp_instruction"); + return; + } + reg_1=instruction->instruction_parameters[1].parameter_data.reg.r; + + if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){ + int reg_2; + + reg_2=instruction->instruction_parameters[0].parameter_data.reg.r; + + write_c (LCODE); + write_c (4); + write_w (0xf200); + write_w (function_code | (reg_2<<10) | (reg_1<<7)); + } else + as_fp_instruction_p (0xf200,function_code | (0x1400 | 0x4000) | (reg_1<<7), + &instruction->instruction_parameters[0]); +} + +static void as_fp_set_condition_instruction (struct instruction *instruction,int c_code) +{ + as_fp_instruction_p (0171100,c_code,&instruction->instruction_parameters[0]); + + if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){ + write_c (LCODE); + write_c (2); + write_w (044700 | d_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r)); + } +} + +static void as_jsr_schedule (int n_a_and_f_registers) +{ + write_c (LCODE); + + if (n_a_and_f_registers & 15){ + write_c (6); + write_w (0xf227); + if ((n_a_and_f_registers & 15)==1) + write_w (0x6800); + else + write_w (0xe000 | (~(-1<<(n_a_and_f_registers & 15))) ); + } else + write_c (2); + + write_w (047200); + + switch (n_a_and_f_registers>>4){ + case 0: store_text_label_in_text_section (schedule_0_label); break; + case 1: store_text_label_in_text_section (schedule_1_label); break; + case 2: store_text_label_in_text_section (schedule_2_label); break; + case 3: store_text_label_in_text_section (schedule_3_label); break; + case 256>>4:store_text_label_in_text_section (schedule_eval_label); break; + default: internal_error_in_function ("as_jsr_schedule"); + } + + if (n_a_and_f_registers & 15){ + write_c (LCODE); + write_c (4); + write_w (0xf21f); + if ((n_a_and_f_registers & 15)==1) + write_w (0x4800); + else + write_w (0xd000 | ((0xff>>(n_a_and_f_registers & 15)) ^ 0xff) ); + } +} + +static void as_jmp_instruction (struct instruction *instruction) +{ + if (instruction->instruction_parameters[0].parameter_type==P_LABEL + && instruction->instruction_parameters[0].parameter_data.l->label_flags & LOCAL_LABEL) + { + if (parallel_flag){ + /* DBRA D6, */ + as_branch_instruction (instruction,0x51CE); + /* JSR schedule */ + as_jsr_schedule (instruction->instruction_parameters[0].parameter_offset); + /* BRA */ + as_branch_instruction (instruction,0x6000); + } else + as_branch_instruction (instruction,0x6000); + } else { + if (parallel_flag){ + int n_a_and_f_registers; + + if (instruction->instruction_parameters[0].parameter_type==P_LABEL) + n_a_and_f_registers=instruction->instruction_parameters[0].parameter_offset; + else + n_a_and_f_registers=instruction->instruction_parameters[0].parameter_data.reg.u; + + if (n_a_and_f_registers!=128){ + /* DBRA D6,2+n(PC) */ + write_c (LCODE); + write_c (4); + write_w (0x51CE); + + if (n_a_and_f_registers & 15) + write_w (14); + else + write_w (6); + + as_jsr_schedule (n_a_and_f_registers); + } + } + as_control_addressing_mode_instruction (&instruction->instruction_parameters[0],047300); + } +} + +static void as_jsr_instruction (struct instruction *instruction) +{ + if (instruction->instruction_parameters[0].parameter_type==P_LABEL + && instruction->instruction_parameters[0].parameter_data.l->label_flags & LOCAL_LABEL) + { + if (parallel_flag){ + int n_a_and_f_registers; + + n_a_and_f_registers=instruction->instruction_parameters[0].parameter_offset; + + /* PEA 2+n(PC) */ + write_c (LCODE); + write_c (4); + write_w (044172); + + if (n_a_and_f_registers & 15) + write_w (22); + else + write_w (14); + + /* DBRA D6, */ + as_branch_instruction (instruction,0x51CE); + as_jsr_schedule (n_a_and_f_registers); + /* BRA */ + as_branch_instruction (instruction,0x6000); + } else + as_branch_instruction (instruction,0x6100); + } else { + if (parallel_flag){ + int n_a_and_f_registers; + + if (instruction->instruction_parameters[0].parameter_type==P_LABEL) + n_a_and_f_registers=instruction->instruction_parameters[0].parameter_offset; + else + n_a_and_f_registers=instruction->instruction_parameters[0].parameter_data.reg.u; + + /* DBRA D6,2+n(PC) */ + write_c (LCODE); + write_c (4); + write_w (0x51CE); + + if (n_a_and_f_registers & 15) + write_w (14); + else + write_w (6); + + as_jsr_schedule (n_a_and_f_registers); + } + as_control_addressing_mode_instruction (&instruction->instruction_parameters[0],047200); + } +} + +struct call_and_jump { + struct call_and_jump *cj_next; + WORD cj_label_id; + WORD cj_call_id; + WORD cj_jump_id; +}; + +static struct call_and_jump *first_call_and_jump,*last_call_and_jump; + +static void as_garbage_collect_test (register struct basic_block *block) +{ + int n_cells,label_id_1,label_id_2; + struct call_and_jump *new_call_and_jump; + + label_id_1=next_label_id++; + label_id_2=next_label_id++; + + new_call_and_jump=(struct 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_id=collect_0_label->label_id; break; + case 1: new_call_and_jump->cj_call_id=collect_1_label->label_id; break; + case 2: new_call_and_jump->cj_call_id=collect_2_label->label_id; break; + case 3: new_call_and_jump->cj_call_id=collect_3_label->label_id; break; + default: internal_error_in_function ("as_garbage_collect_test"); + } + + if (first_call_and_jump!=NULL) + last_call_and_jump->cj_next=new_call_and_jump; + else + first_call_and_jump=new_call_and_jump; + last_call_and_jump=new_call_and_jump; + + n_cells=block->block_n_new_heap_cells; + if (n_cells<=8){ + /* SUBQ.L #n,D7 */ + write_c (LCODE); + write_c (4); + write_w (050607+((n_cells & 7)<<9)); + } else if (n_cells<128 + && block->block_n_begin_d_parameter_registers < + (parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS)) + { + write_c (LCODE); + write_c (6); + if (parallel_flag){ + /* MOVEQ #n,D5 */ + /* SUB.L D5,D7 */ + write_w (075000+n_cells); + write_w (0117205); + } else { + /* MOVEQ #n,D6 */ + /* SUB.L D6,D7 */ + write_w (076000+n_cells); + write_w (0117206); + } + } else { + /* SUB.L #n,D7 */ + write_c (LCODE); + write_c (8); + write_w (0117274); + write_l (n_cells); + } + + /* BCS */ + write_c (0x65); + write_c (0); +#if defined (USE_LABEL_VALUE) && !defined (GENERATE_MPW_OBJECT_CODE) + write_c (LLABEL_VALUE); + write_c (REFERENCE_PC); + write_w (label_id_1); +#else /* l3 */ + { + int label_id; + + label_id=next_label_id++; + define_local_text_label (label_id); + /* l1 - l3 */ + write_c (LC_REFERENCE); + write_c (LCR_WORD); + write_w (label_id_1); + write_w (label_id); + write_c (LCODE); + write_c (2); + write_w (0); + } +#endif + + /* l2 */ + define_local_text_label (label_id_2); +} + +static void as_call_and_jump (struct call_and_jump *call_and_jump) +{ + /* l1 */ + define_local_text_label (call_and_jump->cj_label_id); + /* JSR collect_n */ + write_c (LCODE); + write_c (2); + write_w (047200); +#ifdef USE_LABEL_VALUE + write_c (LLABEL_VALUE); +#else + write_c (LREFERENCE); +#endif + write_c (0); + write_w (call_and_jump->cj_call_id); + write_c (LCODE); +#ifdef USE_LABEL_VALUE + write_c (2); +#else + write_c (4); + write_w (0); +#endif + /* JMP l2 */ + write_w (047300); +#ifdef USE_LABEL_VALUE + write_c (LLABEL_VALUE); + write_c (0); + write_w (call_and_jump->cj_jump_id); +#else + write_c (LREFERENCE); + write_c (0); + write_w (call_and_jump->cj_jump_id); + write_c (LCODE); + write_c (2); + write_w (0); +#endif +} + +static int local_stack_overflow_id; + +static void init_stack_checking (VOID) +{ + local_stack_overflow_id=next_label_id++; + define_local_text_label (local_stack_overflow_id); + + write_c (LCODE); + write_c (2); + write_w (047300); + +#ifdef USE_LABEL_VALUE + write_c (LLABEL_VALUE); + write_c (0); + write_w (stack_overflow_label->label_id); +#else + write_c (LREFERENCE); + write_c (0); + write_w (stack_overflow_label->label_id); + + write_c (LCODE); + write_c (2); + write_w (0); +#endif +} + +#define EXTRA_STACK_SPACE 2000 /* 300 */ + +static void as_check_stack (register struct basic_block *block) +{ + int size,n_d_parameters,n_a_parameters; + int label_id,label_id_1,label_id_2; + + label_id=next_label_id++; + + if (parallel_flag){ + struct call_and_jump *new_call_and_jump; + + label_id_1=next_label_id++; + label_id_2=next_label_id++; + + new_call_and_jump=(struct 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_id=realloc_0_label->label_id; break; + case 1: new_call_and_jump->cj_call_id=realloc_1_label->label_id; break; + case 2: new_call_and_jump->cj_call_id=realloc_2_label->label_id; break; + case 3: new_call_and_jump->cj_call_id=realloc_3_label->label_id; break; + default: internal_error_in_function ("as_garbage_collect_test"); + } + + if (first_call_and_jump!=NULL) + last_call_and_jump->cj_next=new_call_and_jump; + else + first_call_and_jump=new_call_and_jump; + last_call_and_jump=new_call_and_jump; + } + + size=block->block_stack_check_size; +/* if (parallel_flag) */ + size+=EXTRA_STACK_SPACE; + n_d_parameters=block->block_n_begin_d_parameter_registers; + n_a_parameters=block->block_n_begin_a_parameter_registers; + + if (size<=4){ + write_c (LCODE); + write_c (4); + /* CMPA.L A_STACK_POINTER,B_STACK_POINTER */ + write_w (0130710+a_reg_num (A_STACK_POINTER)+(a_reg_num (B_STACK_POINTER)<<9)); + /* BLS */ + write_w (0x6300); + } else if (size<=127 + && n_d_parameters < + (parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS)) + { + write_c (LCODE); + write_c (8); + if (parallel_flag){ + /* MOVEQ #size,D5 */ + write_w (0x7000+(d_reg_num (REGISTER_D5)<<9)+size); + /* ADD.L A_STACK_POINTER,D5 */ + write_w (0150210+a_reg_num (A_STACK_POINTER)+(5<<9)); + /* CMP.L B_STACK_POINTER,D5 */ + write_w (0130210+a_reg_num (B_STACK_POINTER)+(5<<9)); + } else { + /* MOVEQ #size,D6 */ + write_w (0x7000+(d_reg_num (REGISTER_D6)<<9)+size); + /* ADD.L A_STACK_POINTER,D6 */ + write_w (0150210+a_reg_num (A_STACK_POINTER)+(6<<9)); + /* CMP.L B_STACK_POINTER,D6 */ + write_w (0130210+a_reg_num (B_STACK_POINTER)+(6<<9)); + } + /* BHI */ + write_w (0x6200); + } else if (n_a_parameters<N_ADDRESS_PARAMETER_REGISTERS){ + write_c (LCODE); + write_c (8); + /* LEA size(A_STACK_POINTER),A2 */ + write_w (040750 + (2<<9) + a_reg_num (A_STACK_POINTER)); + write_w (size); + /* CMPA.L B_STACK_POINTER,A2 */ + write_w (0130710+a_reg_num (B_STACK_POINTER)+(2<<9)); + /* BHI */ + write_w (0x6200); + } else { + write_c (LCODE); + write_c (10); + /* SUBA.L B_STACK_POINTER,A_STACK_POINTER */ + write_w (0110710+a_reg_num (B_STACK_POINTER)+(a_reg_num (A_STACK_POINTER)<<9)); + /* CMPA.W #-size,A_STACK_POINTER */ + write_w (0130374+(a_reg_num (A_STACK_POINTER)<<9)); + write_w (-size); + /* ADDA.L B_STACK_POINTER,A_STACK_POINTER */ + write_w (0150710+a_reg_num (B_STACK_POINTER)+(a_reg_num (A_STACK_POINTER)<<9)); + /* BGT */ + write_w (0x6E00); + } + + define_local_text_label (label_id); + + write_c (LC_REFERENCE); + write_c (LCR_WORD); + + if (!parallel_flag){ + write_w (local_stack_overflow_id); + write_w (label_id); + write_c (LCODE); + write_c (2); + write_w (0); + } else { + write_w (label_id_1); + write_w (label_id); + write_c (LCODE); + write_c (2); + write_w (0); + + define_local_text_label (label_id_2); + } +} + +static void as_word_instruction (struct instruction *instruction) +{ + write_w ((LCODE<<8)+2); + write_w ((int)instruction->instruction_parameters[0].parameter_data.i); +} + +static void write_instructions (struct instruction *instructions) +{ + register struct instruction *instruction; + + for (instruction=instructions; instruction!=NULL; instruction=instruction->instruction_next){ + switch (instruction->instruction_icode){ + case IMOVE: + as_move_instruction (instruction,SIZE_LONG); + 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 ITST: + as_tst_instruction (instruction,SIZE_LONG); + break; + case ITSTB: + as_tst_instruction (instruction,SIZE_BYTE); + break; + case IJMP: + as_jmp_instruction (instruction); + break; + case IJSR: + as_jsr_instruction (instruction); + break; + case IRTS: +#ifdef COUNT_RELEASES + if (parallel_flag && instruction->instruction_arity){ + write_c (LCODE); + write_c (2); + write_w (0x52ad); + + write_c (LLABEL_VALUE); + write_c (REFERENCE_A5); + write_w (node_entry_count_label_id); + } +#endif + write_w ((LCODE<<8)+2); + write_w (047165); + break; + case IBGE: + as_branch_instruction (instruction,0x6C00); + break; + case IBGT: + as_branch_instruction (instruction,0x6E00); + break; + case IBHS: + as_branch_instruction (instruction,0x6400); + break; + case IBLE: + as_branch_instruction (instruction,0x6F00); + break; + case IBLT: + as_branch_instruction (instruction,0x6D00); + break; + case IBEQ: + as_branch_instruction (instruction,0x6700); + break; + case IBNE: + as_branch_instruction (instruction,0x6600); + break; + case IBMI: + as_short_branch_instruction (instruction,0x6b00); + break; + case IMOVEM: + as_movem_instruction (instruction); + break; + case IMOVEW: + as_move_instruction (instruction,SIZE_WORD); + break; + case IMOVEB: + as_move_instruction (instruction,SIZE_BYTE); + break; + case ICMPW: + as_cmp_instruction (instruction,SIZE_WORD); + break; + case ILSL: + as_shift_instruction (instruction,0160610); + break; + case ILSR: + as_shift_instruction (instruction,0160210); + break; + case IASR: + as_shift_instruction (instruction,0160200); + break; + case IMUL: + as_mul_instruction (instruction); + break; + case IDIV: + as_div_instruction (instruction); + break; + case IMOD: + as_mod_instruction (instruction); + break; + case IBMOVE: + as_bmove_instruction (instruction); + break; + case IEXG: + as_exg_instruction (instruction); + break; + case IAND: + as_and_or_instruction (instruction,0140200); + break; + case IOR: + as_and_or_instruction (instruction,0100200); + break; + case IEOR: + as_eor_instruction (instruction); + break; + case ISEQ: + as_set_condition_instruction (instruction,0x57c0); + break; + case ISGE: + as_set_condition_instruction (instruction,0x5cc0); + break; + case ISGT: + as_set_condition_instruction (instruction,0x5ec0); + break; + case ISLE: + as_set_condition_instruction (instruction,0x5fc0); + break; + case ISLT: + as_set_condition_instruction (instruction,0x5dc0); + break; + case ISNE: + as_set_condition_instruction (instruction,0x56c0); + break; + case IFMOVE: + as_fmove_instruction (instruction,0x1400); + break; + case IFADD: + as_fp_instruction (instruction,0x22); + break; + case IFSUB: + as_fp_instruction (instruction,0x28); + break; + case IFCMP: + as_fp_instruction (instruction,0x38); + break; + case IFDIV: + as_fp_instruction (instruction,0x20); + break; + case IFMUL: + as_fp_instruction (instruction,0x23); + break; + case IFREM: + as_fp_instruction (instruction,0x25); + break; + case IFBEQ: + as_branch_instruction (instruction,0xf281); + break; + case IFBGE: + as_branch_instruction (instruction,0xf293); + break; + case IFBGT: + as_branch_instruction (instruction,0xf292); + break; + case IFBLE: + as_branch_instruction (instruction,0xf295); + break; + case IFBLT: + as_branch_instruction (instruction,0xf294); + break; + case IFBNE: + as_branch_instruction (instruction,0xf28e); + break; + case IFMOVEL: + as_fmove_instruction (instruction,0); + break; + case IFACOS: + as_fp_instruction (instruction,0x1c); + break; + case IFASIN: + as_fp_instruction (instruction,0x0c); + break; + case IFATAN: + as_fp_instruction (instruction,0x0a); + break; + case IFCOS: + as_fp_instruction (instruction,0x1d); + break; + case IFEXP: + as_fp_instruction (instruction,0x10); + break; + case IFLN: + as_fp_instruction (instruction,0x14); + break; + case IFLOG10: + as_fp_instruction (instruction,0x15); + break; + case IFNEG: + as_fp_instruction (instruction,0x1a); + break; + case IFSIN: + as_fp_instruction (instruction,0xe); + break; + case IFSQRT: + as_fp_instruction (instruction,4); + break; + case IFTAN: + as_fp_instruction (instruction,0xf); + break; + case IFSEQ: + as_fp_set_condition_instruction (instruction,1); + break; + case IFSGE: + as_fp_set_condition_instruction (instruction,0x13); + break; + case IFSGT: + as_fp_set_condition_instruction (instruction,0x12); + break; + case IFSLE: + as_fp_set_condition_instruction (instruction,0x15); + break; + case IFSLT: + as_fp_set_condition_instruction (instruction,0x14); + break; + case IFSNE: + as_fp_set_condition_instruction (instruction,0xe); + break; + case IWORD: + as_word_instruction (instruction); + break; + case ISCHEDULE: + as_jsr_schedule (instruction->instruction_parameters[0].parameter_data.i); + break; + case IEXTB: + as_extb_instruction (instruction); + break; + case IEXT: + as_ext_instruction (instruction); + break; + case IFTST: + default: + internal_error_in_function ("write_instructions"); + } + } +} + +static void write_code() +{ + register struct basic_block *block; + register struct call_and_jump *call_and_jump; + + release_heap(); + + first_call_and_jump=NULL; + + for_all (block,first_block,block_next){ +#ifdef MODULES + if (block->block_begin_module) + start_new_module (block->block_link_module != 0); +#endif + if (block->block_n_node_arguments>-100){ + LABEL *label; + + label=block->block_descriptor; + +#ifdef CLOSURE_NAMES + if (label!=NULL && block->block_descriptor_or_string!=0){ + unsigned char *string_p; + char *string; + ULONG string_length; + int length; + + string=(char*)block->block_descriptor; + string_length=strlen (string); + + string_p=(unsigned char*)string; + length=string_length; + + write_c (LCODE); + write_c ((string_length+7) & ~3); + + while (length>=4){ + write_l (*(ULONG*)string_p); + string_p+=4; + length-=4; + } + + if (length>0){ + ULONG d; + int shift; + + d=0; + shift=24; + while (length>0){ + d |= ((ULONG)string_p[0])<<shift; + shift-=8; + --length; + ++string_p; + } + write_l (d); + } + + write_l ((string_length<<2) | (string_length<<10) | (string_length<<18) | (string_length<<26) | 0x00010203); + } +#endif + + 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){ + write_c (LCODE); + write_c (2); + write_w (042700); + + write_c (LLABEL_VALUE); + write_c (0); + if (block->block_ea_label->label_id<0) + block->block_ea_label->label_id=next_label_id++; + write_w (block->block_ea_label->label_id); + + write_c (LCODE); + write_c (2); + write_w (047300); + + write_c (LLABEL_VALUE); + write_c (0); + write_w (eval_upd_labels[n_node_arguments]->label_id); + } else { + write_c (LCODE); + write_c (2); + write_w (047300); + + write_c (LLABEL_VALUE); + write_c (0); + if (block->block_ea_label->label_id<0) + block->block_ea_label->label_id=next_label_id++; + write_w (block->block_ea_label->label_id); + + write_c (LCODE); + write_c (4); + write_w (0x4e71); + write_w (0x4e71); + } + if (block->block_descriptor!=NULL + && (block->block_n_node_arguments<0 || parallel_flag)) + { + if (label->label_id<0) + label->label_id=next_label_id++; + store_label_offset_in_code_section (label->label_id); + } else + write_number_of_arguments (0); + } else + if (label!=NULL + && (block->block_n_node_arguments<0 || parallel_flag)) + { + if (label->label_id<0) + label->label_id=next_label_id++; + store_label_offset_in_code_section (label->label_id); + } + /* else + write_number_of_arguments (0); */ + + write_number_of_arguments (block->block_n_node_arguments); + } + + write_labels (block->block_labels); + if (block->block_n_new_heap_cells>0) + as_garbage_collect_test (block); + if (check_stack && block->block_stack_check_size>0) + as_check_stack (block); + write_instructions (block->block_instructions); + } + + for_all (call_and_jump,first_call_and_jump,cj_next) + { +#ifdef MODULES + start_new_module (0); +#endif + as_call_and_jump (call_and_jump); + } + + release_heap(); +} + +void write_version_and_options (int version,int options) +{ +#ifndef GENERATE_MPW_OBJECT_CODE + putc (LCOMMENT,output_file); + putc (4,output_file); + + putc (version>>8,output_file); + putc (version,output_file); + + putc (options>>8,output_file); + putc (options,output_file); +#endif +} + +void write_depend (char *module_name) +{ +#ifndef GENERATE_MPW_OBJECT_CODE + int l,n; + + l=strlen (module_name); + putc (LCOMMENT,output_file); + putc (l,output_file); + + for (n=0; n<l; ++n) + putc (module_name[n],output_file); + + if (l & 1) + putc (0,output_file); +#endif +} + +void initialize_assembler (FILE *output_file_d) +{ + output_file=output_file_d; + + setvbuf (output_file,NULL,_IOFBF,IO_BUFFER_SIZE); + + initialize_object_buffers(); + +#ifndef GENERATE_MPW_OBJECT_CODE + putc (LBEGIN,output_file); + putc (0,output_file); + putc (0,output_file); + putc (0,output_file); +#else + write_c (LBEGIN); + write_c (0); + write_w (0); +#endif + + if (check_stack && !parallel_flag) + init_stack_checking(); +} + +void assemble_code () +{ + import_labels (labels); + + write_indirect_jumps_for_defer_labels(); + +#ifdef COUNT_RELEASES + if (parallel_flag){ + node_entry_count_label_id=next_label_id++; + import_label (node_entry_count_label_id,"node_entry_count"); + } +#endif + + if (index_error_label!=NULL && !(index_error_label->label_flags & EXPORT_LABEL)){ + int new_index_error_label; + + new_index_error_label=next_label_id++; + define_local_text_label (new_index_error_label); + + write_w ((LCODE<<8)+2); + write_w (047300); + + write_w (LLABEL_VALUE<<8); + write_w (index_error_label->label_id); + + index_error_label->label_id=new_index_error_label; + } + + write_code(); + + write_c (LEND); + write_c (0); + + flush_object_buffer(); + + optimize_buffers(); + +#ifdef GENERATE_MPW_OBJECT_CODE + convert_to_mpw_object_code(); +#endif + + write_object_buffers_and_release_memory(); + +#ifndef GENERATE_MPW_OBJECT_CODE + fseek (output_file,2l,0); + + putc (next_label_id>>8,output_file); + putc (next_label_id,output_file); +#endif +} + +#endif
\ No newline at end of file |