/* File: cgas.c Author: John van Groningen */ #include #include #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; nsize-=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>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,length255) 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; ninstruction_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<instruction_arity; for (n=1; ninstruction_parameters[n].parameter_data.reg.r; if (is_d_register (reg)) register_list |= ((unsigned)1<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_parametersinstruction_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 IMOVEDB: 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 IREM: 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])<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; nlabel_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