From 2255def3b1d52edce2b87c30ddff0a206abda7cd Mon Sep 17 00:00:00 2001 From: John van Groningen Date: Fri, 11 Jul 2003 13:47:24 +0000 Subject: add .c and .h files --- MAIN_CLM.d | 3 + apple_main.c | 499 +++++++ cg.c | 924 ++++++++++++ cg.h | 37 + cgas.c | 3839 ++++++++++++++++++++++++++++++++++++++++++++++++ cgas.h | 23 + cgcalc.c | 2947 +++++++++++++++++++++++++++++++++++++ cgcalc.h | 15 + cgcode.h | 76 + cgconst.h | 27 + cginput.h | 2 + cginstructions.h | 60 + cgiwas.h | 25 + cglin.h | 126 ++ cgopt.h | 10 + cgpas.h | 14 + cgptoc.c | 65 + cgpwas.h | 19 + cgrconst.h | 58 + cgstack.c | 4320 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ cgstack.h | 51 + cgswas.c | 2446 +++++++++++++++++++++++++++++++ cgswas.h | 11 + cgtypes.h | 257 ++++ cgwas.c | 1846 +++++++++++++++++++++++ cgwas.h | 19 + docommand.c | 16 + docommand.h | 12 + 28 files changed, 17747 insertions(+) create mode 100644 MAIN_CLM.d create mode 100644 apple_main.c create mode 100644 cg.c create mode 100644 cg.h create mode 100644 cgas.c create mode 100644 cgas.h create mode 100644 cgcalc.c create mode 100644 cgcalc.h create mode 100644 cgcode.h create mode 100644 cgconst.h create mode 100644 cginput.h create mode 100644 cginstructions.h create mode 100644 cgiwas.h create mode 100644 cglin.h create mode 100644 cgopt.h create mode 100644 cgpas.h create mode 100644 cgptoc.c create mode 100644 cgpwas.h create mode 100644 cgrconst.h create mode 100644 cgstack.c create mode 100644 cgstack.h create mode 100644 cgswas.c create mode 100644 cgswas.h create mode 100644 cgtypes.h create mode 100644 cgwas.c create mode 100644 cgwas.h create mode 100644 docommand.c create mode 100644 docommand.h diff --git a/MAIN_CLM.d b/MAIN_CLM.d new file mode 100644 index 0000000..f4da63e --- /dev/null +++ b/MAIN_CLM.d @@ -0,0 +1,3 @@ +#if (defined (__MWERKS__) || defined (__MRC__) || defined (PROJECT_BUILDER)) && !defined (MAKE_MPW_TOOL) +# define MAIN_CLM +#endif diff --git a/apple_main.c b/apple_main.c new file mode 100644 index 0000000..0166b57 --- /dev/null +++ b/apple_main.c @@ -0,0 +1,499 @@ + +#define CLEAN2 +#define CG_PPC_XO + +#ifndef CLEAN2 +# include "compiledefines.h" +#endif + +#ifdef KARBON +# define TARGET_API_MAC_CARBON 1 +#endif + +#include +#ifndef PROJECT_BUILDER +# include +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include "AppleEvents.h" +#include "Gestalt.h" +#include "AERegistry.h" + +#ifndef CLEAN2 +#include "types.t" +#include "system.h" +#include "path_cache.h" +#include "compiler.h" +#endif + +extern void clear_inline_cache (void); + +#undef BACKGROUND +#define MW_DEBUG 0 +#define NO68K + +#ifndef BACKGROUND +# undef NO_REDIRECT_STDFILES +# undef STDIO_WINDOW +#endif + +#define LINKER +#define CODE_GENERATOR +#undef PROFILE + +#if 1 + +#define kSleepMax 50000 + +static Boolean gAppleEventsFlag, gQuitFlag; +static long gSleepVal; + +static pascal OSErr DoAEOpenApplication (const AppleEvent *theAppleEvent,AppleEvent *replyAppleEvent,long refCon) +{ + return noErr; +} + +static pascal OSErr DoAEOpenDocuments (const AppleEvent *theAppleEvent,AppleEvent *replyAppleEvent,long refCon) +{ + return errAEEventNotHandled; +} + +static pascal OSErr DoAEPrintDocuments (const AppleEvent *theAppleEvent,AppleEvent *replyAppleEvent,long refCon) +{ + return errAEEventNotHandled; +} + +static pascal OSErr DoAEQuitApplication (const AppleEvent *theAppleEvent,AppleEvent *replyAppleEvent,long refCon) +{ + gQuitFlag = true; + return noErr; +} + +#include + +extern int CallCompiler (int argc,char **argv); + +#ifdef CODE_GENERATOR +# ifdef __cplusplus + extern "C" { int generate_code (int,char **); } +# ifndef NO68K + extern int generate_code68 (int,char **); +# endif +# else + extern int generate_code (int,char **); +# ifndef NO68K + extern int generate_code68__FiPPc (int,char **); +#define generate_code68 generate_code68__FiPPc +# endif +# endif +#endif + +#if defined (LINKER) && !defined (NO68K) +# ifdef __cplusplus + extern "C" { int link_application_argc_argv (int,char **); } +# else + extern int link_application_argc_argv (int,char **); +# endif +#endif + +char return_error_string[200]; + +#ifdef CG_PPC_XO +extern int generate_code_xo (int argc,char **argv,char *return_error_string_p,int *compiler_id_p); +extern int generate_code_o (int argc,char **argv,char *return_error_string_p,int *compiler_id_p); +#endif + +#ifdef CLEAN2 +int compiler_id=-1; +#else +extern int compiler_id; +#endif + +int do_command (char *command) +{ + char *p,*(argv[257]); + int argc,result; + int redirect_stdout,redirect_stderr; + + result=0; + + redirect_stdout=0; + redirect_stderr=0; + + argc=0; + p=command; + + while (*p==' ' || *p=='\t') + ++p; + + while (*p!='\0' && argc<256){ + if (*p=='>' || *p=='³'){ + int redirection_char; + char *file_name; + + redirection_char=*p; + + ++p; + while (*p==' ' || *p=='\t') + ++p; + if (*p=='\0') + break; + + if (*p=='\''){ + char c,*d_p; + + ++p; + file_name=p; + + d_p=p; + + c=*p; + while (!(c=='\'' && p[1]!='\'') && c!='\0'){ + *d_p++=c; + if (c=='\'') + ++p; + c=*++p; + } + + if (*p=='\0'){ + *d_p='\0'; + break; + } + + *d_p='\0'; + ++p; + } else { + file_name=p; + + while (*p!=' ' && *p!='\t' && *p!='\0') + ++p; + if (*p!='\0') + *p++='\0'; + } + +#ifdef PROJECT_BUILDER + { + static char file_name_s[257]; + char *p; + + strcpy (file_name_s,"/Volumes/"); + strcat (file_name_s,file_name); + + for (p=file_name_s; *p!='\0'; ++p) + if (*p==':') + *p='/'; + + file_name=file_name_s; + } +#endif + + if (redirection_char=='>' && redirect_stdout==0){ +#ifndef NO_REDIRECT_STDFILES + freopen (file_name,"w",stdout); + redirect_stdout=1; +#endif + } else if (redirection_char=='³' && redirect_stderr==0){ +#ifndef NO_REDIRECT_STDFILES + freopen (file_name,"w",stderr); + redirect_stderr=1; +#endif + } + + if (*p=='\0') + break; + + while (*p==' ' || *p=='\t') + ++p; + continue; + } + + if (*p=='\''){ + char c,*d_p; + + ++p; + argv[argc]=p; + + d_p=p; + + c=*p; + while (!(c=='\'' && p[1]!='\'') && c!='\0'){ + *d_p++=c; + if (c=='\'') + ++p; + c=*++p; + } + + if (*p=='\0'){ + *d_p='\0'; + break; + } + + ++argc; + *d_p='\0'; + ++p; + } else { + argv[argc++]=p; + while (*p!=' ' && *p!='\t' && *p!='\0') + ++p; + + if (*p!='\0') + *p++='\0'; + } + + while (*p==' ' || *p=='\t') + ++p; + } + argv[argc]=NULL; + +/* { + int n; + + for (n=0; n0){ +#ifdef CLEAN2 + if (0) + ; +#else + if (!strcmp (argv[0],"cocl")){ + if (argc>=2 && !strcmp ("-clear_cache",argv[1])){ + result=CallCompiler (argc-2,&argv[2]); + clear_path_cache(); + clear_inline_cache(); + FreePathList(); + } else + result=CallCompiler (argc-1,&argv[1]); + } +#endif +#ifdef CODE_GENERATOR + else if (!strcmp (argv[0],"cg")) + result=generate_code (argc,&argv[0]); +#ifdef CG_PPC_XO + else if (!strcmp (argv[0],"cg_xo")) + result=generate_code_xo (argc,&argv[0],return_error_string,&compiler_id); + else if (!strcmp (argv[0],"cg_o")) + result=generate_code_o (argc,&argv[0],return_error_string,&compiler_id); +#endif + +# ifndef NO68K + else if (!strcmp (argv[0],"cg68")) + result=generate_code68 (argc,&argv[0]); +# endif +#endif +#if defined (LINKER) && !defined (NO68K) + else if (!strcmp (argv[0],"linker")) + result=link_application_argc_argv (argc,&argv[0]); +#endif +#ifndef CLEAN2 + else if (!strcmp (argv[0],"clear_cache")){ + clear_path_cache(); + clear_inline_cache(); + FreePathList(); + } +#endif + else { + result=-1; + strcpy (return_error_string,"unknown command"); + } + } + + if (redirect_stdout) + fclose (stdout); + + if (redirect_stderr) + fclose (stderr); + + return result; +} + +static char script_string[16001]; + +#ifndef CG_PPC_XO +# ifdef CLEAN2 +int compiler_id=-1; +# else +extern int compiler_id; +# endif +#endif + +pascal OSErr do_script_apple_event (const AppleEvent *apple_event,AppleEvent *replyAppleEvent,long refCon) +{ + DescType returned_type; + long actual_size; + int error; + + error=AEGetParamPtr (apple_event,keyDirectObject,'TEXT',&returned_type,&script_string,sizeof (script_string),&actual_size); + + if (error==noErr && actual_size<=16000){ + int return_error_string_length; + + script_string[actual_size]='\0'; + return_error_string[0]='\0'; + +#if !MW_DEBUG + error=do_command (script_string); +#endif + + if (compiler_id>=0){ + error += (compiler_id+1)<<1; + + compiler_id = -1; + } + + return_error_string_length=strlen (return_error_string); + if (return_error_string_length!=0){ + AEPutParamPtr (replyAppleEvent,keyErrorString,typeChar,return_error_string,return_error_string_length); + } + } + + return error; +} + +#if defined (PROJECT_BUILDER) || defined (KARBON) +# define NewAEEventHandlerProc(userRoutine) NewAEEventHandlerUPP(userRoutine) +#endif + +static void InitAppleEventsStuff (void) +{ + OSErr retCode; + + if (!gAppleEventsFlag) + return; + + retCode = AEInstallEventHandler (kCoreEventClass,kAEOpenApplication,NewAEEventHandlerProc (DoAEOpenApplication),0,false); + + if (retCode==noErr) + retCode = AEInstallEventHandler (kCoreEventClass,kAEOpenDocuments,NewAEEventHandlerProc (DoAEOpenDocuments),0,false); + + if (retCode==noErr) + retCode = AEInstallEventHandler (kCoreEventClass,kAEPrintDocuments,NewAEEventHandlerProc (DoAEPrintDocuments),0,false); + + if (retCode==noErr) + retCode = AEInstallEventHandler (kCoreEventClass,kAEQuitApplication,NewAEEventHandlerProc (DoAEQuitApplication),0,false); + + if (retCode==noErr) + retCode = AEInstallEventHandler (kAEMiscStandards,kAEDoScript,NewAEEventHandlerProc (do_script_apple_event),0,false); + + if (retCode!=noErr) + DebugStr("\pInstall event handler failed"); +} + +static void do_high_level_event (EventRecord *theEventRecPtr) +{ +#if MW_DEBUG + script_string[0]=0; +#endif + + AEProcessAppleEvent (theEventRecPtr); + +#if MW_DEBUG + if (script_string[0]){ + do_command (script_string); + script_string[0]=0; + } +#endif + +} + +extern short InstallConsole (short fd); + +#ifdef PROFILE +# include +#endif + +#ifndef PROJECT_BUILDER + +int /*clean_compiler_*/ main (void) +{ + OSErr retCode; + long gestResponse; + EventRecord mainEventRec; + Boolean eventFlag; + +#ifndef KARBON + SetApplLimit (GetApplLimit() - 200*1024); + + InitGraf (&qd.thePort); + InitFonts(); +#endif + FlushEvents (everyEvent,0); + +#ifndef BACKGROUND +# ifndef KARBON + InitWindows(); +# endif + InitCursor(); +# ifndef KARBON + InitMenus(); +# endif +#endif + +#ifndef PROJECT_BUILDER + _fcreator='3PRM'; +#endif + gQuitFlag = false; + gSleepVal = kSleepMax; + + retCode = Gestalt(gestaltAppleEventsAttr,&gestResponse); + if (retCode==noErr && (gestResponse & (1< + +#include "cgport.h" + +#ifdef ALIGN_C_CALLS +# define CG_PPC_XO +#endif + +#include +#include + +#if ! (defined (M68000) && defined (SUN)) +# define GENERATE_OBJECT_FILE +#endif + +#ifdef POWER +# define USE_SYSTEM_ALLOC 1 +/* # include "Memory.h" */ +# include "MacMemory.h" +#else +# define USE_SYSTEM_ALLOC 0 +#endif + +/* #define PERFORMANCE */ + +#include "MAIN_CLM.d" + +#ifdef PERFORMANCE +#include +TP2PerfGlobals ThePGlobals; +#endif + +#ifdef THINK_C +# include +# define NO_TOPOLOGY +#ifdef USER_INTERFACE +# include "system.h" +#else +# include "types.t" +#endif +#endif + +#include "cgrconst.h" +#include "cgtypes.h" +#include "cgcode.h" +#include "cglin.h" +#include "cgopt.h" +#ifdef _WINDOWS_ +# include "cgias.h" +# include "cgiwas.h" +#else +# ifdef SOLARIS +# include "cgswas.h" +# else +# ifdef G_POWER +# include "cgpas.h" +# include "cgpwas.h" +# else +# include "cgas.h" +# include "cgwas.h" +# endif +# endif +#endif +#include "cgstack.h" + +#include "cg.h" + +#ifdef USER_INTERFACE +# include "cginterface.t" +# include "cginterface.h" +#endif + +#include "cginput.h" + +#ifdef G_POWER +# include "cgptoc.h" +#endif + +#include + +static jmp_buf error_jmp; + +static void exit_code_generator (int r) +{ + longjmp (error_jmp,r); +} + +int list_flag; +int check_stack; +int assembly_flag; +int mc68000_flag; +int mc68881_flag; +int parallel_flag; +int check_index_flag; +int module_info_flag=1; +int profile_table_flag; +#ifdef G_POWER +int fmadd_flag=1; +#endif + +#ifdef USER_INTERFACE +# define print_error(s1) FPrintF (StdError,"%s\n",s1) +# define exit exit_code_generator +#else +# ifdef MAIN_CLM +# ifdef MAKE_MPW_TOOL +# define print_error(s1) printf("%s\n",s1) +# else +# ifdef CG_PPC_XO + static char *return_error_string; +# else + extern char return_error_string[]; +# endif +# define print_error(s1) strcpy (return_error_string,s1); +# endif +# define exit exit_code_generator +# else +/* # define print_error(s1) printf("%s\n",s1) */ +# define print_error(s1) fprintf(stderr,"%s\n",s1) +# endif +#endif + +void warning (char *error_string) +{ + print_error (error_string); +} + +void warning_s (char *error_string,char *string) +{ + char error[300]; + + sprintf (error,error_string,string); + print_error (error); +} + +void warning_i (char *error_string,int integer) +{ + char error[300]; + + sprintf (error,error_string,integer); + print_error (error); +} + +void warning_si (char *error_string,char *string,int i) +{ + char error[300]; + + sprintf (error,error_string,string,i); + print_error (error); +} + +void error (char *error_string) +{ + warning (error_string); +#ifdef PERFORMANCE + PerfDump (ThePGlobals,"\pPerform.out",0,0); + TermPerf (ThePGlobals); +#endif + exit (-1); +} + +void error_i (char *error_string,int integer) +{ + warning_i (error_string,integer); +#ifdef PERFORMANCE + PerfDump (ThePGlobals,"\pPerform.out",0,0); + TermPerf (ThePGlobals); +#endif + exit (-1); +} + +void error_s (char *error_string,char *string) +{ + warning_s (error_string,string); +#ifdef PERFORMANCE + PerfDump (ThePGlobals,"\pPerform.out",0,0); + TermPerf (ThePGlobals); +#endif + exit (-1); +} + +void error_si (char *error_string,char *string,int i) +{ + warning_si (error_string,string,i); +#ifdef PERFORMANCE + PerfDump (ThePGlobals,"\pPerform.out",0,0); + TermPerf (ThePGlobals); +#endif + exit (-1); +} + +void internal_error (char *error_string) +{ + error_s ("Internal error: %s",error_string); +} + +void internal_error_in_function (char *function_name) +{ + error_s ("Internal error in function: %s",function_name); +} + +void *memory_allocate (int size) +{ + void *memory_block; + + memory_block=malloc (size); + if (memory_block==NULL) + error ("Out of memory"); + return memory_block; +} + +#if USE_SYSTEM_ALLOC +#define system_memory_allocate_type(t) ((t*)system_memory_allocate(sizeof (t))) + +static void *system_memory_allocate (int size) +{ + char *memory_block; + + memory_block=NewPtr (size); + if (memory_block==NULL) + error ("Out of memory"); + return memory_block; +} + +#endif + +void memory_free (void *memory_block) +{ + free (memory_block); +} + +#if USE_SYSTEM_ALLOC +static void system_memory_free (void *memory_block) +{ + DisposePtr ((char*)memory_block); +} +#endif + +#ifdef THINK_C +# define MEM_BLOCK_SIZE 16380 +#else +# if defined (__MWERKS__) || defined (__MRC__) +# define MEM_BLOCK_SIZE 16384 +# else +# define MEM_BLOCK_SIZE 4092 +# endif +#endif + +struct memory_block_list +{ + char mem_block [MEM_BLOCK_SIZE]; + struct memory_block_list * mem_next_block; +}; + +static struct memory_block_list *heap; +static int first_mem_block_size; + +void *allocate_memory_from_heap (int size) +{ +#ifdef sparc + size = (size+7) & ~7; +#else + size = (size+3) & ~3; +#endif + if (first_mem_block_size+size<=MEM_BLOCK_SIZE){ + char *mem_block; + + mem_block=&heap->mem_block[first_mem_block_size]; + first_mem_block_size+=size; + return mem_block; + } else { + struct memory_block_list *new_mem_block_list; + +#if USE_SYSTEM_ALLOC + new_mem_block_list=system_memory_allocate_type (struct memory_block_list); +#else + new_mem_block_list=memory_allocate (sizeof (struct memory_block_list)); +#endif + new_mem_block_list->mem_next_block=heap; + heap=new_mem_block_list; + first_mem_block_size=size; + return new_mem_block_list->mem_block; + } +} + +void release_heap (VOID) +{ + while (heap->mem_next_block!=NULL){ + struct memory_block_list *next_mem_block; + + next_mem_block=heap->mem_next_block; +#if USE_SYSTEM_ALLOC + system_memory_free (heap); +#else + memory_free (heap); +#endif + heap=next_mem_block; + } +} + +static struct memory_block_list *memory_list; +static char *fast_mem_block; +static int fast_mem_block_size; + +static void initialize_memory (VOID) +{ + memory_list=NULL; + + first_mem_block_size=0; +#if USE_SYSTEM_ALLOC + heap=system_memory_allocate_type (struct memory_block_list); +#else + heap=memory_allocate (sizeof (struct memory_block_list)); +#endif + heap->mem_next_block=NULL; + + fast_mem_block_size=0; +#if USE_SYSTEM_ALLOC + memory_list=system_memory_allocate_type (struct memory_block_list); +#else + memory_list=memory_allocate (sizeof (struct memory_block_list)); +#endif + memory_list->mem_next_block=NULL; + fast_mem_block=memory_list->mem_block; +} + +void *fast_memory_allocate (int size) +{ +#ifdef sparc + size=(size+7) & ~7; +#else + size=(size+3) & ~3; +#endif + if (fast_mem_block_size+size<=MEM_BLOCK_SIZE){ + char *memory_block; + + memory_block=&fast_mem_block[fast_mem_block_size]; + fast_mem_block_size+=size; + return memory_block; + } else { + struct memory_block_list *new_memory_block; + +#if USE_SYSTEM_ALLOC + new_memory_block=system_memory_allocate_type (struct memory_block_list); +#else + new_memory_block=memory_allocate (sizeof (struct memory_block_list)); +#endif + new_memory_block->mem_next_block=memory_list; + memory_list=new_memory_block; + + fast_mem_block=new_memory_block->mem_block; + fast_mem_block_size=size; + + return fast_mem_block; + } +} + +static void release_memory (VOID) +{ + while (memory_list!=NULL){ + struct memory_block_list *next_mem_block; + + next_mem_block=memory_list->mem_next_block; +#if USE_SYSTEM_ALLOC + system_memory_free (memory_list); +#else + memory_free (memory_list); +#endif + memory_list=next_mem_block; + } + release_heap(); +#if USE_SYSTEM_ALLOC + system_memory_free (heap); +#else + memory_free (heap); +#endif +} + +#define IO_BUF_SIZE 8192 + +char *this_module_name; + +#ifdef GNU_C +# define FOLDER_SEPARATOR '/' +#else +# define FOLDER_SEPARATOR ':' +#endif + +#ifdef PROJECT_BUILDER +static FILE *fopen_with_file_name_conversion (char *file_name,char *mode) +{ + static char file_name_s[257]; + char *p; + + for (p=file_name; *p!='\0' && *p!=':'; ++p) + ; + + if (*p==':'){ + strcpy (file_name_s,"/Volumes/"); + strcat (file_name_s,file_name); + + for (p=file_name_s; *p!='\0'; ++p) + if (*p==':') + *p='/'; + + file_name=file_name_s; + } + + return fopen (file_name,mode); +} + +# define fopen fopen_with_file_name_conversion +#endif + +#ifdef USER_INTERFACE + +extern File abc_file; + +static File obj_file,assembly_file; + +extern int system_file; + +int generate_code (char *file_name,target_machine_type target_machine,int flags) +{ + int r; + char *module_name; + int object_file_type; + + /* + InitProfile (400,200); + freopen ("profile","w",stdout); + */ + + system_file=0; + + obj_file=NULL; + assembly_file=NULL; + abc_file=NULL; + + if (!(r=setjmp (error_jmp))){ + initialize_memory(); + + mc68000_flag=0; + mc68881_flag=1; + + switch (target_machine){ + case MAC_II: + break; + case MAC_I: + mc68000_flag=1; + mc68881_flag=0; + break; + case MAC_IISANE: + mc68881_flag=0; + break; + default: + error ("Unknown target machine"); + } + + list_flag=0; + check_stack=(flags & STACK_CHECKS)!=0; + assembly_flag=(flags & ASSEMBLY)!=0; + parallel_flag=(flags & DO_PARALLEL)!=0; + check_index_flag=(flags & CHECK_INDICES)!=0; + profile_table_flag=0; + +#ifndef GENERATE_OBJECT_FILE + assembly_flag=1; +#endif + + initialize_parser(); + initialize_coding(); + initialize_linearization(); + initialize_stacks(); + + object_file_type= + mc68000_flag ? obj00File : (mc68881_flag ? obj81File : obj20File); + + module_name=file_name+strlen (file_name); + while (module_name>file_name && module_name[-1]!=FOLDER_SEPARATOR) + --module_name; + + this_module_name=module_name; + + abc_file=FOpen (file_name,abcFile,"r"); + + if (abc_file==NULL){ + fprintf (stderr,"file \"%s.abc\" could not be opened.\n",file_name); + exit (-1); + } + + setvbuf (abc_file,NULL,_IOFBF,8192); + +#if defined (M68000) && !defined (SUN) + obj_file=FOpen (file_name,object_file_type,"wb"); + if (obj_file==NULL) + error_s ("Can't create the output file [%s]",this_module_name); + setvbuf (obj_file,NULL,_IOFBF,IO_BUF_SIZE); +#endif + + if (assembly_flag){ +#ifdef MACH_O + assembly_file=FOpen (file_name,assFile,"wb"); +#else + assembly_file=FOpen (file_name,assFile,"w"); +#endif + if (assembly_file==NULL) + error_s ("Can't create the assembly file [%s]",this_module_name); + setvbuf (assembly_file,NULL,_IOFBF,IO_BUF_SIZE); + } + +#ifdef GENERATE_OBJECT_FILE + initialize_assembler (obj_file); +#endif + if (assembly_flag) + initialize_write_assembly (assembly_file); + +#ifdef G_POWER + initialize_toc(); +#endif + + if (parse_file (abc_file)!=0){ + if (abc_file!=NULL){ + FClose (abc_file); + abc_file=NULL; + } + +#ifdef PERFORMANCE + PerfDump (ThePGlobals,"\pPerform.out",0,0); + TermPerf (ThePGlobals); +#endif + exit (-1); + } + + if (abc_file!=NULL){ + FClose (abc_file); + abc_file=NULL; + } + + if (profile_table_flag) + write_profile_table(); + + optimize_jumps(); + +#if 0 + if (list_flag){ + show_code(); + show_imports_and_exports(); + } +#endif + +#ifdef GENERATE_OBJECT_FILE + assemble_code(); +#endif + + if (assembly_flag) + write_assembly(); + +#if defined (M68000) && !defined (SUN) + if (fclose (obj_file)!=0){ + obj_file=NULL; + FDelete (file_name,object_file_type); + error_s ("Error while writing object file [%s]",this_module_name); + } +#endif + + if (assembly_flag && fclose (assembly_file)!=0){ + assembly_file=NULL; + FDelete (file_name,assFile); + error_s ("Error while writing assembly file [%s]",this_module_name); + } + + if (!(flags & KEEP_ABC) && !system_file) + FDelete (file_name,abcFile); + } else { + /* if an error occurrs : */ + if (obj_file!=NULL){ + fclose (obj_file); + FDelete (file_name,object_file_type); + } + if (assembly_file!=NULL){ + fclose (assembly_file); + FDelete (file_name,assFile); + } + if (abc_file!=NULL){ + FClose (abc_file); + abc_file=NULL; + } + } + + release_memory(); + + return r; +} + +#else + +static void argument_error (VOID) +{ + error ("Usage: cg [options] file [-o object_file] [-s assembly_file]"); +} + +#if defined (POWER) && !defined (CG_PPC_XO) +extern int compiler_id; +#endif + +#ifdef MAIN_CLM +# if !(defined (__MWERKS__) && defined (__cplusplus)) +# ifdef CG_PPC_XO +# ifdef MACH_O +int generate_code_o (int argc,char **argv,char *return_error_string_p,int *compiler_id_p) +# else +int generate_code_xo (int argc,char **argv,char *return_error_string_p,int *compiler_id_p) +# endif +# else +int generate_code (int argc,char **argv) +# endif +# else +int generate_code68 (int argc,char **argv) +# endif +#else +int main (int argc,char **argv) +#endif +{ + char *file_name; + + static FILE *abc_file,*obj_file,*assembly_file; + + int arg_n,r,file_name_length; + char *abc_file_name=NULL,*object_file_name_s=NULL,*assembly_file_name_s=NULL; + char *module_name,*object_file_name,*assembly_file_name; + + +#ifdef CG_PPC_XO + return_error_string=return_error_string_p; +#endif + +#if defined (THINK_C) + argc = ccommand (&argv); +#endif + +#ifdef PERFORMANCE + ThePGlobals=NULL; + if (!InitPerf (&ThePGlobals,4,8,1,1,"\pCODE",0,"",0,0,0,0)){ + printf ("Can't initialize performance measurement\n"); + exit (-1); + } + PerfControl (ThePGlobals,1); +#endif + + obj_file=NULL; + assembly_file=NULL; + abc_file=NULL; + + if (!(r=setjmp (error_jmp))){ + initialize_memory(); + + list_flag=0; + check_stack=0; + + mc68000_flag=0; + mc68881_flag=1; + + parallel_flag=0; + check_index_flag=0; + assembly_flag=0; +#if defined (G_POWER) && !defined (MACH_O) + profile_table_flag=1; +#else + profile_table_flag=0; +#endif + + for (arg_n=1; arg_n=argc) + argument_error(); + + file_name=argv[arg_n++]; + + module_name=file_name+strlen (file_name); + while (module_name>file_name && module_name[-1]!=FOLDER_SEPARATOR) + --module_name; + + this_module_name=module_name; + + file_name_length=strlen (file_name); + + abc_file_name=(char*)memory_allocate (file_name_length+5); + strcpy (abc_file_name,file_name); + strcat (abc_file_name,".abc"); + + object_file_name_s=(char*)memory_allocate (file_name_length+6); + strcpy (object_file_name_s,file_name); + +#if defined (G_POWER) || defined (_WINDOWS_) || defined (LINUX) || defined (sparc) +# if defined (G_POWER) && !defined (MACH_O) +# ifdef ALIGN_C_CALLS + strcat (object_file_name_s,".xo"); +# else + strcat (object_file_name_s,".cxo"); +# endif +# else + strcat (object_file_name_s,".o"); +# endif +#else +# ifdef I486 + strcat (object_file_name_s,".obj"); +# else + strcat (object_file_name_s,mc68000_flag ? ".obj0" : mc68881_flag ? ".obj2" : ".obj1"); +# endif +#endif + object_file_name=object_file_name_s; + + assembly_file_name_s=(char*)memory_allocate (file_name_length+3); + strcpy (assembly_file_name_s,file_name); + +#if (defined (M68000) && !defined (SUN)) || (defined (G_POWER) && !defined (LINUX_ELF)) + strcat (assembly_file_name_s,".a"); +#else + strcat (assembly_file_name_s,".s"); +#endif + assembly_file_name=assembly_file_name_s; + + while (arg_n +#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 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])<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 \ No newline at end of file diff --git a/cgas.h b/cgas.h new file mode 100644 index 0000000..473b83e --- /dev/null +++ b/cgas.h @@ -0,0 +1,23 @@ + +void assemble_code (VOID); +void initialize_assembler (FILE *file); +void define_local_label (int id,int flag); +void define_external_label (int id,int flag,char label_name[]); +void store_word_in_data_section (UWORD i); +void store_long_word_in_data_section (ULONG i); +void store_label_in_data_section (int label_id); +void store_label_offset_in_data_section (int label_id); +void store_descriptor_in_data_section (int label_id); +void store_descriptor_in_code_section (int label_id); +void store_c_string_in_data_section (char *string,int length); +void store_abc_string_in_data_section (char *string,int length); +void store_c_string_in_code_section (char *string,int length); +void store_abc_string_in_code_section (char *string,int length); +void store_descriptor_string_in_code_section (char *string,int length,int string_code_label_id,LABEL *string_label); +void store_label_offset_in_code_section (int label_id); +void start_new_module (int flag); + +#ifndef GNU_C +void write_version_and_options (int version,int options); +void write_depend (char *module_name); +#endif diff --git a/cgcalc.c b/cgcalc.c new file mode 100644 index 0000000..d3f06e7 --- /dev/null +++ b/cgcalc.c @@ -0,0 +1,2947 @@ +/* + File: cgcalc.c + Author: John van Groningen + At: University of Nijmegen +*/ + +#pragma segment Code1 + +#include +#include "cgport.h" +#include "cg.h" +#include "cgrconst.h" +#include "cgtypes.h" +#include "cgconst.h" + +#include "cgcalc.h" + +#include "cgstack.h" + +#define MAX(a,b) ((a)>(b)?(a):(b)) + +enum { R_NOMODE=0, R_AREGISTER, R_DREGISTER, R_MEMORY, R_IMMEDIATE }; + +#undef PRINT_DEBUG + +static void calculate_dyadic_commutative_operator (INSTRUCTION_GRAPH graph) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + int i_aregs,i_dregs; + int l_aregs,r_aregs,l_dregs,r_dregs; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (graph_1); + calculate_graph_register_uses (graph_2); + + i_aregs=graph_1->i_aregs+graph_2->i_aregs; + i_dregs=graph_1->i_dregs+graph_2->i_dregs; + + l_aregs=MAX (graph_1->u_aregs,graph_1->i_aregs+graph_2->u_aregs); + l_dregs=MAX (graph_1->u_dregs,graph_1->i_dregs+graph_2->u_dregs); + + r_aregs=MAX (graph_2->u_aregs,graph_2->i_aregs+graph_1->u_aregs); + r_dregs=MAX (graph_2->u_dregs,graph_2->i_dregs+graph_1->u_dregs); + + if (graph_1->order_mode==R_DREGISTER) + i_dregs-=graph_1->order_alterable; + else + i_aregs-=graph_1->order_alterable; + + if (graph_2->order_mode==R_DREGISTER) + i_dregs-=graph_2->order_alterable; + else + i_aregs-=graph_2->order_alterable; + + if (graph->instruction_d_min_a_cost<=0){ + ++i_dregs; + + if (l_dregsorder_mode=R_DREGISTER; + } else { + ++i_aregs; + + if (l_aregsorder_mode=R_AREGISTER; + } + + if (AD_REG_WEIGHT (l_aregs,l_dregs) < AD_REG_WEIGHT (r_aregs,r_dregs)){ + graph->u_aregs=l_aregs; + graph->u_dregs=l_dregs; + graph->order_left=1; + } else { + graph->u_aregs=r_aregs; + graph->u_dregs=r_dregs; + graph->order_left=0; + } + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + + graph->order_alterable=graph->node_count<=1; +#ifdef PRINT_DEBUG + printf ("GADD ud=%d id=%d ua=%d ia=%d\n", + graph->u_dregs,graph->i_dregs,graph->u_aregs,graph->i_aregs); +#endif +} + +static void calculate_dyadic_commutative_data_operator (INSTRUCTION_GRAPH graph) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + int i_aregs,i_dregs; + int l_aregs,r_aregs,l_dregs,r_dregs; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (graph_1); + calculate_graph_register_uses (graph_2); + + i_aregs=graph_1->i_aregs+graph_2->i_aregs; + i_dregs=graph_1->i_dregs+graph_2->i_dregs; + + l_aregs=MAX (graph_1->u_aregs,graph_1->i_aregs+graph_2->u_aregs); + l_dregs=MAX (graph_1->u_dregs,graph_1->i_dregs+graph_2->u_dregs); + + r_aregs=MAX (graph_2->u_aregs,graph_2->i_aregs+graph_1->u_aregs); + r_dregs=MAX (graph_2->u_dregs,graph_2->i_dregs+graph_1->u_dregs); + + if (graph_1->order_mode==R_DREGISTER) + i_dregs-=graph_1->order_alterable; + else + i_aregs-=graph_1->order_alterable; + + if (graph_2->order_mode==R_DREGISTER) + i_dregs-=graph_2->order_alterable; + else + i_aregs-=graph_2->order_alterable; + + if (graph_1->order_mode==R_AREGISTER && graph_2->order_mode==R_AREGISTER){ + if (l_dregsinstruction_d_min_a_cost<=0){ + ++i_dregs; + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + + if (l_aregsorder_mode=R_AREGISTER; + } + + if (AD_REG_WEIGHT (l_aregs,l_dregs) < AD_REG_WEIGHT (r_aregs,r_dregs)){ + graph->u_aregs=l_aregs; + graph->u_dregs=l_dregs; + graph->order_left=1; + } else { + graph->u_aregs=r_aregs; + graph->u_dregs=r_dregs; + graph->order_left=0; + } + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + + graph->order_alterable=graph->node_count<=1; + return; +} + +static void calculate_eor_operator (INSTRUCTION_GRAPH graph) +{ + register INSTRUCTION_GRAPH graph_1,graph_2; + int i_aregs,i_dregs; + int l_aregs,r_aregs,l_dregs,r_dregs; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (graph_1); + calculate_graph_register_uses (graph_2); + + i_aregs=graph_1->i_aregs+graph_2->i_aregs; + i_dregs=graph_1->i_dregs+graph_2->i_dregs; + + l_aregs=MAX (graph_1->u_aregs,graph_1->i_aregs+graph_2->u_aregs); + l_dregs=MAX (graph_1->u_dregs,graph_1->i_dregs+graph_2->u_dregs); + + r_aregs=MAX (graph_2->u_aregs,graph_2->i_aregs+graph_1->u_aregs); + r_dregs=MAX (graph_2->u_dregs,graph_2->i_dregs+graph_1->u_dregs); + + if (graph_1->order_mode==R_DREGISTER) + i_dregs-=graph_1->order_alterable; + else + i_aregs-=graph_1->order_alterable; + + if (graph_2->order_mode==R_DREGISTER) + i_dregs-=graph_2->order_alterable; + else + i_aregs-=graph_2->order_alterable; + + if ((graph_1->order_mode==R_AREGISTER || graph_1->order_mode==R_MEMORY) + && (graph_2->order_mode==R_AREGISTER || graph_2->order_mode==R_MEMORY)) + { + if (l_dregsinstruction_d_min_a_cost<=0){ + ++i_dregs; + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + + if (l_aregsorder_mode=R_AREGISTER; + } + + if (AD_REG_WEIGHT (l_aregs,l_dregs) < AD_REG_WEIGHT (r_aregs,r_dregs)){ + graph->u_aregs=l_aregs; + graph->u_dregs=l_dregs; + graph->order_left=1; + } else { + graph->u_aregs=r_aregs; + graph->u_dregs=r_dregs; + graph->order_left=0; + } + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + + graph->order_alterable=graph->node_count<=1; + return; +} + +static void calculate_dyadic_float_operator (INSTRUCTION_GRAPH graph) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + int i_aregs,i_dregs; + int l_aregs,r_aregs,l_dregs,r_dregs; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (graph_1); + calculate_graph_register_uses (graph_2); + + i_aregs=graph_1->i_aregs+graph_2->i_aregs; + i_dregs=graph_1->i_dregs+graph_2->i_dregs; + + l_aregs=MAX (graph_1->u_aregs,graph_1->i_aregs+graph_2->u_aregs); + l_dregs=MAX (graph_1->u_dregs,graph_1->i_dregs+graph_2->u_dregs); + + r_aregs=MAX (graph_2->u_aregs,graph_2->i_aregs+graph_1->u_aregs); + r_dregs=MAX (graph_2->u_dregs,graph_2->i_dregs+graph_1->u_dregs); + + if (graph_1->order_mode==R_DREGISTER) + i_dregs-=graph_1->order_alterable; + else + i_aregs-=graph_1->order_alterable; + + if (graph_2->order_mode==R_DREGISTER) + i_dregs-=graph_2->order_alterable; + else + i_aregs-=graph_2->order_alterable; + + ++i_dregs; + + if (l_dregsu_aregs=l_aregs; + graph->u_dregs=l_dregs; + graph->order_left=1; + } else { + graph->u_aregs=r_aregs; + graph->u_dregs=r_dregs; + graph->order_left=0; + } + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + + graph->order_mode=R_DREGISTER; + graph->order_alterable=graph->node_count<=1;; + +#ifdef PRINT_DEBUG + printf ("dyadic_float_operator ud=%d id=%d ua=%d ia=%d\n", + graph->u_dregs,graph->i_dregs,graph->u_aregs,graph->i_aregs); +#endif +} + +static void calculate_compare_descriptor_indirect ( register INSTRUCTION_GRAPH graph, + register INSTRUCTION_GRAPH graph_1) +{ + calculate_graph_register_uses (graph_1); + + graph->u_dregs=graph_1->u_dregs; + graph->u_aregs=graph_1->u_aregs; + graph->i_aregs=graph_1->i_aregs; + graph->i_dregs=graph_1->i_dregs; + + if (graph_1->order_mode==R_DREGISTER) + graph->i_dregs-=graph_1->order_alterable; + else + graph->i_aregs-=graph_1->order_alterable; + + if (graph->u_dregsi_dregs+1) + graph->u_dregs=graph->i_dregs+1; + + if (graph->instruction_d_min_a_cost<=0){ + ++graph->i_dregs; + graph->order_mode=R_DREGISTER; + } else { + ++graph->i_aregs; + if (graph->u_aregsi_aregs) + graph->u_aregs=graph->i_aregs; + graph->order_mode=R_AREGISTER; + } + + graph->order_alterable=graph->node_count<=1; +} + +static void calculate_compare_operator (INSTRUCTION_GRAPH graph) +{ + register INSTRUCTION_GRAPH graph_1,graph_2; + int i_aregs,i_dregs,l_aregs,r_aregs,l_dregs,r_dregs; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + if (graph_1->instruction_code==GLOAD_DES_ID && graph_1->node_count==1 + && graph_2->instruction_code==GLOAD_DES_I && graph_2->node_count==1){ + calculate_compare_descriptor_indirect (graph,graph_1->instruction_parameters[1].p); + return; + } + + if (graph_2->instruction_code==GLOAD_DES_ID && graph_2->node_count==1 + && graph_1->instruction_code==GLOAD_DES_I && graph_1->node_count==1){ + calculate_compare_descriptor_indirect (graph,graph_2->instruction_parameters[1].p); + return; + } + + calculate_graph_register_uses (graph_1); + calculate_graph_register_uses (graph_2); + + i_aregs=graph_1->i_aregs+graph_2->i_aregs; + i_dregs=graph_1->i_dregs+graph_2->i_dregs; + + l_aregs=MAX (graph_1->u_aregs,graph_1->i_aregs+graph_2->u_aregs); + l_dregs=MAX (graph_1->u_dregs,graph_1->i_dregs+graph_2->u_dregs); + + r_aregs=MAX (graph_2->u_aregs,graph_2->i_aregs+graph_1->u_aregs); + r_dregs=MAX (graph_2->u_dregs,graph_2->i_dregs+graph_1->u_dregs); + + if ((graph_1->order_mode==R_MEMORY && graph_2->order_mode==R_MEMORY + && !graph_1->order_alterable && !graph_2->order_alterable) + || (graph_1->order_mode==R_IMMEDIATE && graph_2->order_mode==R_IMMEDIATE)) + { + if (l_dregsorder_mode==R_DREGISTER) + i_dregs-=graph_1->order_alterable; + else + i_aregs-=graph_1->order_alterable; + + if (graph_2->order_mode==R_DREGISTER) + i_dregs-=graph_2->order_alterable; + else + i_aregs-=graph_2->order_alterable; + + if (l_dregsinstruction_d_min_a_cost<=0){ + ++i_dregs; + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + + if (l_aregsorder_mode=R_AREGISTER; + } + + if (AD_REG_WEIGHT (l_aregs,l_dregs) < AD_REG_WEIGHT (r_aregs,r_dregs)){ + graph->u_aregs=l_aregs; + graph->u_dregs=l_dregs; + graph->order_left=1; + } else { + graph->u_aregs=r_aregs; + graph->u_dregs=r_dregs; + graph->order_left=0; + } + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + + graph->order_alterable=graph->node_count<=1; +} + +static void calculate_dyadic_non_commutative_operator (INSTRUCTION_GRAPH graph) +{ + register INSTRUCTION_GRAPH graph_1,graph_2; + int i_aregs,i_dregs; + int l_aregs,r_aregs,l_dregs,r_dregs; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (graph_1); + calculate_graph_register_uses (graph_2); + + i_aregs=graph_1->i_aregs+graph_2->i_aregs; + i_dregs=graph_1->i_dregs+graph_2->i_dregs; + + l_aregs=MAX (graph_1->u_aregs,graph_1->i_aregs+graph_2->u_aregs); + l_dregs=MAX (graph_1->u_dregs,graph_1->i_dregs+graph_2->u_dregs); + + r_aregs=MAX (graph_2->u_aregs,graph_2->i_aregs+graph_1->u_aregs); + r_dregs=MAX (graph_2->u_dregs,graph_2->i_dregs+graph_1->u_dregs); + + if (graph->instruction_d_min_a_cost<=0){ + ++i_dregs; + + if (!(graph_2->order_mode==R_DREGISTER && graph_2->order_alterable)){ + if (l_dregsorder_mode=R_DREGISTER; + } else { + ++i_aregs; + + if (!(graph_2->order_mode!=R_DREGISTER && graph_2->order_alterable)){ + if (l_aregsorder_mode=R_AREGISTER; + } + + if (graph_1->order_mode==R_DREGISTER) + i_dregs-=graph_1->order_alterable; + else + i_aregs-=graph_1->order_alterable; + + if (graph_2->order_mode==R_DREGISTER) + i_dregs-=graph_2->order_alterable; + else + i_aregs-=graph_2->order_alterable; + + if (AD_REG_WEIGHT (l_aregs,l_dregs) < AD_REG_WEIGHT (r_aregs,r_dregs)){ + graph->u_aregs=l_aregs; + graph->u_dregs=l_dregs; + graph->order_left=1; + } else { + graph->u_aregs=r_aregs; + graph->u_dregs=r_dregs; + graph->order_left=0; + } + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + + graph->order_alterable=graph->node_count<=1; + return; +} + +static void calculate_dyadic_non_commutative_data_operator (INSTRUCTION_GRAPH graph) +{ + register INSTRUCTION_GRAPH graph_1,graph_2; + int i_aregs,i_dregs; + int l_aregs,r_aregs,l_dregs,r_dregs; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (graph_1); + calculate_graph_register_uses (graph_2); + + i_aregs=graph_1->i_aregs+graph_2->i_aregs; + i_dregs=graph_1->i_dregs+graph_2->i_dregs; + + l_aregs=MAX (graph_1->u_aregs,graph_1->i_aregs+graph_2->u_aregs); + l_dregs=MAX (graph_1->u_dregs,graph_1->i_dregs+graph_2->u_dregs); + + r_aregs=MAX (graph_2->u_aregs,graph_2->i_aregs+graph_1->u_aregs); + r_dregs=MAX (graph_2->u_dregs,graph_2->i_dregs+graph_1->u_dregs); + + if (!(graph_2->order_mode==R_DREGISTER && graph_2->order_alterable + && graph_1->order_mode!=R_AREGISTER)){ + if (graph_2->order_mode==R_AREGISTER){ + if (l_dregsorder_mode==R_DREGISTER) + i_dregs-=graph_1->order_alterable; + else + i_aregs-=graph_1->order_alterable; + + if (graph_2->order_mode==R_DREGISTER) + i_dregs-=graph_2->order_alterable; + else + i_aregs-=graph_2->order_alterable; + + if (graph->instruction_d_min_a_cost<=0){ + ++i_dregs; + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + + if (l_aregsorder_mode=R_AREGISTER; + } + + if (AD_REG_WEIGHT (l_aregs,l_dregs) < AD_REG_WEIGHT (r_aregs,r_dregs)){ + graph->u_aregs=l_aregs; + graph->u_dregs=l_dregs; + graph->order_left=1; + } else { + graph->u_aregs=r_aregs; + graph->u_dregs=r_dregs; + graph->order_left=0; + } + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + + graph->order_alterable=graph->node_count<=1; + return; +} + +static void calculate_mod_operator (INSTRUCTION_GRAPH graph) +{ + register INSTRUCTION_GRAPH graph_1,graph_2; + int i_aregs,i_dregs; + int l_aregs,r_aregs,l_dregs,r_dregs; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (graph_1); + calculate_graph_register_uses (graph_2); + + i_aregs=graph_1->i_aregs+graph_2->i_aregs; + i_dregs=graph_1->i_dregs+graph_2->i_dregs; + + l_aregs=MAX (graph_1->u_aregs,graph_1->i_aregs+graph_2->u_aregs); + l_dregs=MAX (graph_1->u_dregs,graph_1->i_dregs+graph_2->u_dregs); + + r_aregs=MAX (graph_2->u_aregs,graph_2->i_aregs+graph_1->u_aregs); + r_dregs=MAX (graph_2->u_dregs,graph_2->i_dregs+graph_1->u_dregs); + + if (graph_1->order_mode==R_DREGISTER) + i_dregs-=graph_1->order_alterable; + else + i_aregs-=graph_1->order_alterable; + + if (graph_2->order_mode==R_DREGISTER) + i_dregs-=graph_2->order_alterable; + else + i_aregs-=graph_2->order_alterable; + + if (l_dregsinstruction_d_min_a_cost<=0){ + ++i_dregs; + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + + if (l_aregsorder_mode=R_AREGISTER; + } + + if (AD_REG_WEIGHT (l_aregs,l_dregs) < AD_REG_WEIGHT (r_aregs,r_dregs)){ + graph->u_aregs=l_aregs; + graph->u_dregs=l_dregs; + graph->order_left=1; + } else { + graph->u_aregs=r_aregs; + graph->u_dregs=r_dregs; + graph->order_left=0; + } + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + + graph->order_alterable=graph->node_count<=1; + return; +} + +static void calculate_shift_operator (INSTRUCTION_GRAPH graph) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + int i_aregs,i_dregs; + int l_aregs,r_aregs,l_dregs,r_dregs; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (graph_1); + calculate_graph_register_uses (graph_2); + + i_aregs=graph_1->i_aregs+graph_2->i_aregs; + i_dregs=graph_1->i_dregs+graph_2->i_dregs; + + l_aregs=MAX (graph_1->u_aregs,graph_1->i_aregs+graph_2->u_aregs); + l_dregs=MAX (graph_1->u_dregs,graph_1->i_dregs+graph_2->u_dregs); + + r_aregs=MAX (graph_2->u_aregs,graph_2->i_aregs+graph_1->u_aregs); + r_dregs=MAX (graph_2->u_dregs,graph_2->i_dregs+graph_1->u_dregs); + + if (graph_1->order_mode==R_DREGISTER) + i_dregs-=graph_1->order_alterable; + else + i_aregs-=graph_1->order_alterable; + + if (graph_2->order_mode==R_DREGISTER) + i_dregs-=graph_2->order_alterable; + else + i_aregs-=graph_2->order_alterable; + + if (graph_1->order_mode==R_IMMEDIATE + || (graph_1->order_mode==R_DREGISTER && !graph_1->order_alterable)){ + if (l_dregsinstruction_d_min_a_cost<=0){ + ++i_dregs; + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + + if (l_aregsorder_mode=R_AREGISTER; + } + + if (AD_REG_WEIGHT (l_aregs,l_dregs) < AD_REG_WEIGHT (r_aregs,r_dregs)){ + graph->u_aregs=l_aregs; + graph->u_dregs=l_dregs; + graph->order_left=1; + } else { + graph->u_aregs=r_aregs; + graph->u_dregs=r_dregs; + graph->order_left=0; + } + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + + graph->order_alterable=graph->node_count<=1; +#ifdef PRINT_DEBUG + printf ("shift_operator ud=%d id=%d ua=%d ia=%d\n", + graph->u_dregs,graph->i_dregs,graph->u_aregs,graph->i_aregs); +#endif + +} + +static void calculate_arguments (INSTRUCTION_GRAPH graph,int *i_aregs_p,int *i_dregs_p,int *u_aregs_p,int *u_dregs_p) +{ + int i_aregs,i_dregs,u_aregs,u_dregs,n_arguments; + register int argument_number; + char *argument_evaluated; + + i_aregs=*i_aregs_p; + i_dregs=*i_dregs_p; + u_aregs=*u_aregs_p; + u_dregs=*u_dregs_p; + + n_arguments=graph->inode_arity; + + for (argument_number=0; argument_numberinstruction_parameters[argument_number].p; + + if (a_graph!=NULL) + calculate_graph_register_uses (a_graph); + } + + argument_evaluated=(char*)memory_allocate (sizeof (char) * n_arguments); + + for (argument_number=0; argument_numberinstruction_parameters[argument_number].p==NULL); + + for (;;){ + register int first_argument_number; + register INSTRUCTION_GRAPH a_graph_1; + + first_argument_number=0; + while (first_argument_number=n_arguments) + break; + + a_graph_1=graph->instruction_parameters[first_argument_number].p; + + for (argument_number=first_argument_number+1; argument_numberinstruction_parameters[argument_number].p; + + a=a_graph_1->i_aregs; d=a_graph_1->i_dregs; i1=AD_REG_WEIGHT (a,d); + a=a_graph_2->i_aregs; d=a_graph_2->i_dregs; i2=AD_REG_WEIGHT (a,d); + + a=a_graph_1->u_aregs; d=a_graph_1->u_dregs; u1=AD_REG_WEIGHT (a,d); + a=a_graph_2->u_aregs; d=a_graph_2->u_dregs; u2=AD_REG_WEIGHT (a,d); + + if (i1<0){ + if (i2<0 && (u2u1-i1 || (u2-i2==u1-i1 && u2u_aregs+i_aregs > u_aregs) + u_aregs=a_graph_1->u_aregs+i_aregs; + if (a_graph_1->u_dregs+i_dregs > u_dregs) + u_dregs=a_graph_1->u_dregs+i_dregs; + + i_aregs+=a_graph_1->i_aregs; + i_dregs+=a_graph_1->i_dregs; + + argument_evaluated[first_argument_number]=1; + } + + memory_free (argument_evaluated); + + *i_aregs_p=i_aregs; + *i_dregs_p=i_dregs; + *u_aregs_p=u_aregs; + *u_dregs_p=u_dregs; +} + +static void calculate_create_r_operator (INSTRUCTION_GRAPH graph) +{ + int i_aregs,i_dregs,u_aregs,u_dregs; + INSTRUCTION_GRAPH a_graph; + + a_graph=graph->instruction_parameters[0].p; + calculate_graph_register_uses (a_graph); + + u_aregs=a_graph->u_aregs; + u_dregs=a_graph->u_dregs; + i_aregs=a_graph->i_aregs; + i_dregs=a_graph->i_dregs; + + if (graph->instruction_d_min_a_cost<=0){ + ++i_dregs; + if (i_dregs>u_dregs) + u_dregs=i_dregs; + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + if (i_aregs>u_aregs) + u_aregs=i_aregs; + graph->order_mode=R_AREGISTER; + } + + if (a_graph->order_mode==R_DREGISTER) + i_dregs-=a_graph->order_alterable; + else + i_aregs-=a_graph->order_alterable; + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + graph->u_aregs=u_aregs; + graph->u_dregs=u_dregs; + + graph->order_alterable=graph->node_count<=1; +} + +static void calculate_create_operator (INSTRUCTION_GRAPH graph) +{ + register int argument_number; + int i_aregs,i_dregs,u_aregs,u_dregs; + + i_aregs=0; + i_dregs=0; + u_aregs=0; + u_dregs=0; + + calculate_arguments (graph,&i_aregs,&i_dregs,&u_aregs,&u_dregs); + + if (graph->instruction_d_min_a_cost<=0){ + ++i_dregs; + if (i_dregs>u_dregs) + u_dregs=i_dregs; + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + if (i_aregs>u_aregs) + u_aregs=i_aregs; + graph->order_mode=R_AREGISTER; + } + + for (argument_number=0; argument_numberinode_arity; ++argument_number){ + register INSTRUCTION_GRAPH a_graph; + + a_graph=graph->instruction_parameters[argument_number].p; + + if (a_graph!=NULL) + if (a_graph->order_mode==R_DREGISTER) + i_dregs-=a_graph->order_alterable; + else + i_aregs-=a_graph->order_alterable; + } + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + graph->u_aregs=u_aregs; + graph->u_dregs=u_dregs; + + graph->order_alterable=graph->node_count<=1; +} + +static void calculate_fill_r_operator (register INSTRUCTION_GRAPH graph) +{ + int i_aregs,i_dregs,u_aregs,u_dregs; + INSTRUCTION_GRAPH a_graph; + + a_graph=graph->instruction_parameters[0].p; + if (a_graph->instruction_code==GCREATE && a_graph->node_count==1){ + /* overwrite fill_r node with create_r node */ + + graph->instruction_code=GCREATE_R; + graph->instruction_parameters[0]=graph->instruction_parameters[1]; + graph->instruction_parameters[1]=graph->instruction_parameters[2]; + graph->inode_arity=2; + + calculate_create_r_operator (graph); + return; + } + + calculate_graph_register_uses (a_graph); + + u_aregs=a_graph->u_aregs; + u_dregs=a_graph->u_dregs; + i_aregs=a_graph->i_aregs; + i_dregs=a_graph->i_dregs; + + a_graph=graph->instruction_parameters[1].p; + calculate_graph_register_uses (a_graph); + + if (a_graph->u_aregs+i_aregs > u_aregs) + u_aregs=a_graph->u_aregs+i_aregs; + if (a_graph->u_dregs+i_dregs > u_dregs) + u_dregs=a_graph->u_dregs+i_dregs; + i_aregs+=a_graph->i_aregs; + i_dregs+=a_graph->i_dregs; + + if (graph->instruction_d_min_a_cost<=0){ + ++i_dregs; + if (i_dregs>u_dregs) + u_dregs=i_dregs; + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + if (i_aregs>u_aregs) + u_aregs=i_aregs; + graph->order_mode=R_AREGISTER; + } + + a_graph=graph->instruction_parameters[0].p; + if (a_graph->order_mode==R_DREGISTER) + i_dregs-=a_graph->order_alterable; + else + i_aregs-=a_graph->order_alterable; + + a_graph=graph->instruction_parameters[1].p; + if (a_graph->order_mode==R_DREGISTER) + i_dregs-=a_graph->order_alterable; + else + i_aregs-=a_graph->order_alterable; + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + graph->u_aregs=u_aregs; + graph->u_dregs=u_dregs; + + graph->order_alterable=graph->node_count<=1; +} + +static void calculate_fill_operator (register INSTRUCTION_GRAPH graph) +{ + int argument_number,i_aregs,i_dregs,u_aregs,u_dregs; + INSTRUCTION_GRAPH graph_0; +#ifdef G_POWER + int r; +#endif + + graph_0=graph->instruction_parameters[0].p; + if (graph_0->instruction_code==GCREATE && graph_0->node_count==1 + && (graph->inode_arity>3 + || (graph->inode_arity>1 + && (graph->instruction_parameters[1].p->instruction_code==GLOAD_DES_I + || graph->instruction_parameters[1].p->instruction_code==GLOAD_DES_ID +#ifdef G_POWER + || (graph->instruction_parameters[1].p->instruction_code==GGREGISTER + && (r=graph->instruction_parameters[1].p->instruction_parameters[0].i)==INT_REGISTER + || r==CHAR_REGISTER || r==REAL_REGISTER || r==BOOL_REGISTER + ) +#endif + )))) + { + /* overwrite fill node with create node */ + + graph->instruction_code=GCREATE; + for (argument_number=1; argument_numberinode_arity; ++argument_number) + graph->instruction_parameters[argument_number-1]= + graph->instruction_parameters[argument_number]; + + --graph->inode_arity; + + calculate_create_operator (graph); + return; + } + + i_aregs=0; + i_dregs=0; + u_aregs=0; + u_dregs=0; + + calculate_arguments (graph,&i_aregs,&i_dregs,&u_aregs,&u_dregs); + + if (graph->instruction_d_min_a_cost<=0){ + ++i_dregs; + if (i_dregs>u_dregs) + u_dregs=i_dregs; + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + if (i_aregs>u_aregs) + u_aregs=i_aregs; + graph->order_mode=R_AREGISTER; + } + + for (argument_number=0; argument_numberinode_arity; ++argument_number){ + register INSTRUCTION_GRAPH a_graph; + + a_graph=graph->instruction_parameters[argument_number].p; + + if (a_graph!=NULL) + if (a_graph->order_mode==R_DREGISTER) + i_dregs-=a_graph->order_alterable; + else + i_aregs-=a_graph->order_alterable; + } + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + graph->u_aregs=u_aregs; + graph->u_dregs=u_dregs; + + graph->order_alterable=graph->node_count<=1; +} + +static void calculate_movemi_operator (INSTRUCTION_GRAPH graph) +{ + register INSTRUCTION_GRAPH movem_graph,graph_2; + register int i_dregs,i_aregs,u_dregs,u_aregs; + register int argument_number; + int arity; + + movem_graph=graph->instruction_parameters[0].p; + if (movem_graph->order_mode!=R_NOMODE) + return; + + graph_2=movem_graph->instruction_parameters[1].p; + + calculate_graph_register_uses (graph_2); + + i_dregs=graph_2->i_dregs; + i_aregs=graph_2->i_aregs; + u_dregs=graph_2->u_dregs; + u_aregs=graph_2->u_aregs; + + if (graph_2->order_mode==R_DREGISTER) + i_dregs-=graph_2->order_alterable; + else + i_aregs-=graph_2->order_alterable; + + ++i_aregs; + if (u_aregsinode_arity; + + for (argument_number=0; argument_numberinstruction_parameters[2+argument_number].p; + if (a_graph!=NULL) + if (a_graph->instruction_parameters[1].i==0 + ? a_graph->instruction_d_min_a_cost<=0 + : is_d_register (a_graph->instruction_parameters[1].i>>1)) + { + ++i_dregs; + if (u_dregsinstruction_parameters[2+argument_number].p; + if (a_graph!=NULL){ + a_graph->i_dregs=i_dregs; + a_graph->i_aregs=i_aregs; + a_graph->u_dregs=u_dregs; + a_graph->u_aregs=u_aregs; + if (a_graph->instruction_parameters[1].i==0 + ? a_graph->instruction_d_min_a_cost<=0 + : is_d_register (a_graph->instruction_parameters[1].i>>1) + ) + a_graph->order_mode=R_DREGISTER; + else + a_graph->order_mode=R_AREGISTER; + a_graph->order_alterable=a_graph->node_count<=1; + } + } +} + +static void calculate_copy_operator (register INSTRUCTION_GRAPH graph) +{ + register INSTRUCTION_GRAPH graph_1,graph_2; + int i_aregs,i_dregs; + int l_aregs,l_dregs; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (graph_1); + calculate_graph_register_uses (graph_2); + + i_aregs=graph_1->i_aregs+graph_2->i_aregs; + i_dregs=graph_1->i_dregs+graph_2->i_dregs; + + l_aregs=MAX (graph_1->u_aregs,graph_1->i_aregs+graph_2->u_aregs); + l_dregs=MAX (graph_1->u_dregs,graph_1->i_dregs+graph_2->u_dregs); + + i_aregs-=graph_1->order_alterable; + i_aregs-=graph_2->order_alterable; + + graph->u_aregs=l_aregs; + graph->u_dregs=l_dregs; + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + + graph->order_alterable=graph->node_count<=1; + return; +} + +static void calculate_cnot_operator (register INSTRUCTION_GRAPH graph) +{ + register INSTRUCTION_GRAPH graph_1; + + graph_1=graph->instruction_parameters[0].p; + + calculate_graph_register_uses (graph_1); + + graph->u_aregs=graph_1->u_aregs; + graph->u_dregs=graph_1->u_dregs; + graph->i_aregs=graph_1->i_aregs; + graph->i_dregs=graph_1->i_dregs; + + if (graph_1->order_mode==R_DREGISTER) + graph->i_dregs-=graph_1->order_alterable; + else + graph->i_aregs-=graph_1->order_alterable; + + if (graph->u_dregsi_dregs+1) + graph->u_dregs=graph->i_dregs+1; + + if (graph->instruction_d_min_a_cost<=0){ + ++graph->i_dregs; + graph->order_mode=R_DREGISTER; + } else { + ++graph->i_aregs; + if (graph->u_aregsi_aregs) + graph->u_aregs=graph->i_aregs; + graph->order_mode=R_AREGISTER; + } + + graph->order_alterable=graph->node_count<=1; +} + +static void calculate_load_x_operator (register INSTRUCTION_GRAPH graph) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + int i_aregs,i_dregs,l_aregs,l_dregs,r_aregs,r_dregs; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[2].p; + + calculate_graph_register_uses (graph_1); + + if (graph_2==NULL){ + switch (graph_1->order_mode){ + case R_AREGISTER: + graph->u_dregs=graph_1->u_dregs; + graph->u_aregs=graph_1->u_aregs; + graph->i_aregs=graph_1->i_aregs; + graph->i_dregs=graph_1->i_dregs; + graph->order_alterable=graph_1->order_alterable; + break; + case R_DREGISTER: + graph->u_dregs=graph_1->u_dregs; + graph->u_aregs=MAX (graph_1->u_aregs,1+graph_1->i_aregs); + graph->i_dregs=graph_1->i_dregs-graph_1->order_alterable; + graph->i_aregs=graph_1->i_aregs+1; + graph->order_alterable=1; + break; + case R_MEMORY: + case R_IMMEDIATE: + { + int i_aregs=graph_1->i_aregs+1-graph_1->order_alterable; + graph->u_dregs=graph_1->u_dregs; + graph->u_aregs=MAX (graph_1->u_aregs,i_aregs); + graph->i_dregs=graph_1->i_dregs; + graph->i_aregs=i_aregs; + graph->order_alterable=1; + } + } + + graph->order_mode=R_MEMORY; + return; + } + + calculate_graph_register_uses (graph_2); + + i_aregs=graph_1->i_aregs+graph_2->i_aregs; + i_dregs=graph_1->i_dregs+graph_2->i_dregs; + + l_aregs=MAX (graph_1->u_aregs,graph_1->i_aregs+graph_2->u_aregs); + l_dregs=MAX (graph_1->u_dregs,graph_1->i_dregs+graph_2->u_dregs); + + r_aregs=MAX (graph_2->u_aregs,graph_2->i_aregs+graph_1->u_aregs); + r_dregs=MAX (graph_2->u_dregs,graph_2->i_dregs+graph_1->u_dregs); + + if (graph_1->order_mode==R_DREGISTER) + i_dregs-=graph_1->order_alterable; + else + i_aregs-=graph_1->order_alterable; + + if (graph_2->order_mode==R_DREGISTER) + i_dregs-=graph_2->order_alterable; + else + i_aregs-=graph_2->order_alterable; + + ++i_aregs; + if (l_aregsu_aregs=l_aregs; + graph->u_dregs=l_dregs; + graph->order_left=1; + } else { + graph->u_aregs=r_aregs; + graph->u_dregs=r_dregs; + graph->order_left=0; + } + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + + graph->order_alterable=1; + graph->order_mode=R_MEMORY; +} + +static int graph_order (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2) +{ + int i1,i2,u1,u2; + int a,d; + + a=graph_1->i_aregs; d=graph_1->i_dregs; i1=AD_REG_WEIGHT (a,d); + a=graph_2->i_aregs; d=graph_2->i_dregs; i2=AD_REG_WEIGHT (a,d); + + a=graph_1->u_aregs; d=graph_1->u_dregs; u1=AD_REG_WEIGHT (a,d); + a=graph_2->u_aregs; d=graph_2->u_dregs; u2=AD_REG_WEIGHT (a,d); + + if (i1<0) + return i2<0 && (u2u1-i1 || (u2-i2==u1-i1 && u2instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + graph_3=graph->instruction_parameters[3].p; + select_graph=graph->instruction_parameters[4].p; + + calculate_graph_register_uses (graph_1); + calculate_graph_register_uses (graph_2); + if (graph_3!=NULL) + calculate_graph_register_uses (graph_3); + + i_aregs=0; + i_dregs=0; + u_aregs=0; + u_dregs=0; + + while (select_graph!=NULL){ + switch (select_graph->instruction_code){ + case GLOAD_X: + case GLOAD_B_X: + if (graph_2==select_graph->instruction_parameters[0].p + /* */ && select_graph!=graph_1 /* added 18-5-1999 */ + ){ + calculate_graph_register_uses (select_graph); + + if (select_graph->u_aregs+i_aregs > u_aregs) + u_aregs=select_graph->u_aregs+i_aregs; + if (select_graph->u_dregs+i_dregs > u_dregs) + u_dregs=select_graph->u_dregs+i_dregs; + + i_aregs+=select_graph->i_aregs; + i_dregs+=select_graph->i_dregs; + + if (select_graph->order_mode==R_DREGISTER) + i_dregs-=select_graph->order_alterable; + else + i_aregs-=select_graph->order_alterable; + + if (select_graph->instruction_d_min_a_cost<=0) + ++i_dregs; + else + ++i_aregs; + } + + select_graph=select_graph->instruction_parameters[3].p; + break; + case GFLOAD_X: + case GREGISTER: + case GFREGISTER: + select_graph=select_graph->instruction_parameters[3].p; + break; + default: + internal_error_in_function ("calculate_store_x_operator"); + } + } + + graph_1_before_reorder=graph_1; + graph_2_before_reorder=graph_2; + graph_3_before_reorder=graph_3; + + if (graph_3==NULL){ + if (graph_order (graph_1,graph_2)) + graph->order_left=1; + else { + INSTRUCTION_GRAPH c_graph_1; + + c_graph_1=graph_1; + graph_1=graph_2; + graph_2=c_graph_1; + + graph->order_left=0; + } + } else { + int order; + + if (graph_order (graph_1,graph_2)){ + if (graph_order (graph_1,graph_3)){ + order=0; + } else { + INSTRUCTION_GRAPH c_graph_1; + + c_graph_1=graph_1; + graph_1=graph_3; + graph_3=c_graph_1; + + order=4; + } + } else { + if (graph_order (graph_2,graph_3)){ + INSTRUCTION_GRAPH c_graph_1; + + c_graph_1=graph_1; + graph_1=graph_2; + graph_2=c_graph_1; + + order=2; + } else { + INSTRUCTION_GRAPH c_graph_1; + + c_graph_1=graph_1; + graph_1=graph_3; + graph_3=c_graph_1; + + order=4; + } + } + + if (graph_order (graph_2,graph_3)){ + INSTRUCTION_GRAPH c_graph_2; + + c_graph_2=graph_2; + graph_2=graph_3; + graph_3=c_graph_2; + + ++order; + } + + graph->order_left=order; + } + + if (graph_1->u_aregs+i_aregs > u_aregs) + u_aregs=graph_1->u_aregs+i_aregs; + if (graph_1->u_dregs+i_dregs > u_dregs) + u_dregs=graph_1->u_dregs+i_dregs; + + i_aregs+=graph_1->i_aregs; + i_dregs+=graph_1->i_dregs; + + if (graph_2->u_aregs+i_aregs > u_aregs) + u_aregs=graph_2->u_aregs+i_aregs; + if (graph_2->u_dregs+i_dregs > u_dregs) + u_dregs=graph_2->u_dregs+i_dregs; + + i_aregs+=graph_2->i_aregs; + i_dregs+=graph_2->i_dregs; + + if (graph_3!=NULL){ + if (graph_3->u_aregs+i_aregs > u_aregs) + u_aregs=graph_3->u_aregs+i_aregs; + if (graph_3->u_dregs+i_dregs > u_dregs) + u_dregs=graph_3->u_dregs+i_dregs; + + i_aregs+=graph_3->i_aregs; + i_dregs+=graph_3->i_dregs; + } + + if (graph_1_before_reorder->order_mode==R_DREGISTER) + i_dregs-=graph_1_before_reorder->order_alterable; + else + i_aregs-=graph_1_before_reorder->order_alterable; + + if (graph_3_before_reorder!=NULL){ + if (graph_3_before_reorder->order_mode==R_DREGISTER) + i_dregs-=graph_3_before_reorder->order_alterable; + else + i_aregs-=graph_3_before_reorder->order_alterable; + } + + graph->order_alterable=graph_2_before_reorder->order_alterable; + if (graph_2_before_reorder->order_alterable) + if (graph_2_before_reorder->order_mode==R_DREGISTER) + --i_dregs; + else + --i_aregs; + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + graph->u_aregs=u_aregs; + graph->u_dregs=u_dregs; + + graph->order_mode=R_AREGISTER; +} + +static void calculate_monadic_float_operator (register INSTRUCTION_GRAPH graph) +{ + INSTRUCTION_GRAPH graph_1; + + graph_1=graph->instruction_parameters[0].p; + + calculate_graph_register_uses (graph_1); + + graph->u_aregs=graph_1->u_aregs; + graph->u_dregs=graph_1->u_dregs; + graph->i_aregs=graph_1->i_aregs; + graph->i_dregs=graph_1->i_dregs; + + if (graph_1->order_mode==R_DREGISTER) + graph->i_dregs-=graph_1->order_alterable; + else + graph->i_aregs-=graph_1->order_alterable; + + graph->order_mode=R_DREGISTER; + graph->order_alterable=0; +} + +static void calculate_fload_id_operator (register INSTRUCTION_GRAPH graph) +{ + register INSTRUCTION_GRAPH graph_1; + + graph_1=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (graph_1); + + graph->u_aregs=graph_1->u_aregs; + graph->u_dregs=graph_1->u_dregs; + graph->i_aregs=graph_1->i_aregs; + graph->i_dregs=graph_1->i_dregs; + + if (graph_1->order_mode==R_DREGISTER) + graph->i_dregs-=graph_1->order_alterable; + else + graph->i_aregs-=graph_1->order_alterable; + + graph->order_mode=R_DREGISTER; + graph->order_alterable=0; +} + +static void calculate_fstore_operator (register INSTRUCTION_GRAPH graph) +{ + INSTRUCTION_GRAPH a_graph; + + a_graph=graph->instruction_parameters[2].p; + + calculate_graph_register_uses (a_graph); + + graph->u_dregs=a_graph->u_dregs; + graph->u_aregs=a_graph->u_aregs; + graph->i_aregs=a_graph->i_aregs; + graph->i_dregs=a_graph->i_dregs; + + if (a_graph->order_alterable) + if (a_graph->order_mode==R_DREGISTER) + --graph->i_dregs; + else + --graph->i_aregs; + + graph->order_mode=R_DREGISTER; + graph->order_alterable=0; +} + +static void calculate_fload_x_operator (INSTRUCTION_GRAPH graph) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + int i_aregs,i_dregs,l_aregs,l_dregs,r_aregs,r_dregs; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[2].p; + + calculate_graph_register_uses (graph_1); + + if (graph_2==NULL){ + switch (graph_1->order_mode){ + case R_AREGISTER: + graph->u_dregs=graph_1->u_dregs; + graph->u_aregs=graph_1->u_aregs; + graph->i_aregs=graph_1->i_aregs; + graph->i_dregs=graph_1->i_dregs; + graph->order_alterable=graph_1->order_alterable; + break; + case R_DREGISTER: + graph->u_dregs=graph_1->u_dregs; + graph->u_aregs=MAX (graph_1->u_aregs,1+graph_1->i_aregs); + graph->i_dregs=graph_1->i_dregs-graph_1->order_alterable; + graph->i_aregs=graph_1->i_aregs+1; + graph->order_alterable=1; + break; + case R_MEMORY: + case R_IMMEDIATE: + { + int i_aregs=graph_1->i_aregs+1-graph_1->order_alterable; + graph->u_dregs=graph_1->u_dregs; + graph->u_aregs=MAX (graph_1->u_aregs,i_aregs); + graph->i_dregs=graph_1->i_dregs; + graph->i_aregs=i_aregs; + graph->order_alterable=1; + } + } + + graph->order_mode=R_MEMORY; + return; + } + + calculate_graph_register_uses (graph_2); + + i_aregs=graph_1->i_aregs+graph_2->i_aregs; + i_dregs=graph_1->i_dregs+graph_2->i_dregs; + + l_aregs=MAX (graph_1->u_aregs,graph_1->i_aregs+graph_2->u_aregs); + l_dregs=MAX (graph_1->u_dregs,graph_1->i_dregs+graph_2->u_dregs); + + r_aregs=MAX (graph_2->u_aregs,graph_2->i_aregs+graph_1->u_aregs); + r_dregs=MAX (graph_2->u_dregs,graph_2->i_dregs+graph_1->u_dregs); + + if (graph_1->order_mode==R_DREGISTER) + i_dregs-=graph_1->order_alterable; + else + i_aregs-=graph_1->order_alterable; + + if (graph_2->order_mode==R_DREGISTER) + i_dregs-=graph_2->order_alterable; + else + i_aregs-=graph_2->order_alterable; + + ++i_aregs; + if (l_aregsu_aregs=l_aregs; + graph->u_dregs=l_dregs; + graph->order_left=1; + } else { + graph->u_aregs=r_aregs; + graph->u_dregs=r_dregs; + graph->order_left=0; + } + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + + graph->order_mode=R_MEMORY; + graph->order_alterable=1; + +#ifdef PRINT_DEBUG + printf ("GFLOAD_X ud=%d id=%d ua=%d ia=%d\n", + graph->u_dregs,graph->i_dregs,graph->u_aregs,graph->i_aregs); +#endif +} + +static void calculate_fstore_x_operator (INSTRUCTION_GRAPH graph) +{ + INSTRUCTION_GRAPH graph_1,graph_2,graph_3,select_graph; + INSTRUCTION_GRAPH graph_1_before_reorder,graph_2_before_reorder,graph_3_before_reorder; + int i_aregs,i_dregs,u_aregs,u_dregs; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + graph_3=graph->instruction_parameters[3].p; + select_graph=graph->instruction_parameters[4].p; + + calculate_graph_register_uses (graph_1); + calculate_graph_register_uses (graph_2); + if (graph_3!=NULL) + calculate_graph_register_uses (graph_3); + + i_aregs=0; + i_dregs=0; + u_aregs=0; + u_dregs=0; + + while (select_graph!=NULL){ + switch (select_graph->instruction_code){ + case GFLOAD_X: + if (graph_2==select_graph->instruction_parameters[0].p){ + calculate_graph_register_uses (select_graph); + + if (select_graph->u_aregs+i_aregs > u_aregs) + u_aregs=select_graph->u_aregs+i_aregs; + if (select_graph->u_dregs+i_dregs > u_dregs) + u_dregs=select_graph->u_dregs+i_dregs; + + i_aregs+=select_graph->i_aregs; + i_dregs+=select_graph->i_dregs; + + if (select_graph->order_mode==R_DREGISTER) + i_dregs-=select_graph->order_alterable; + else + i_aregs-=select_graph->order_alterable; +#ifdef PRINT_DEBUG + printf ("GFLOAD_X in GFSTORE_X ud=%d id=%d ua=%d ia=%d\n",select_graph->u_dregs,select_graph->i_dregs,select_graph->u_aregs,select_graph->i_aregs); +#endif + } + + select_graph=select_graph->instruction_parameters[3].p; + break; + case GLOAD_X: + case GLOAD_B_X: + case GREGISTER: + case GFREGISTER: + select_graph=select_graph->instruction_parameters[3].p; + break; + default: + internal_error_in_function ("calculate_fstore_x_operator"); + } + } + + graph_1_before_reorder=graph_1; + graph_2_before_reorder=graph_2; + graph_3_before_reorder=graph_3; + + if (graph_3==NULL){ + if (graph_order (graph_1,graph_2)) + graph->order_left=1; + else { + INSTRUCTION_GRAPH c_graph_1; + + c_graph_1=graph_1; + graph_1=graph_2; + graph_2=c_graph_1; + + graph->order_left=0; + } + } else { + int order; + + if (graph_order (graph_1,graph_2)){ + if (graph_order (graph_1,graph_3)){ + order=0; + } else { + INSTRUCTION_GRAPH c_graph_1; + + c_graph_1=graph_1; + graph_1=graph_3; + graph_3=c_graph_1; + + order=4; + } + } else { + if (graph_order (graph_2,graph_3)){ + INSTRUCTION_GRAPH c_graph_1; + + c_graph_1=graph_1; + graph_1=graph_2; + graph_2=c_graph_1; + + order=2; + } else { + INSTRUCTION_GRAPH c_graph_1; + + c_graph_1=graph_1; + graph_1=graph_3; + graph_3=c_graph_1; + + order=4; + } + } + + if (graph_order (graph_2,graph_3)){ + INSTRUCTION_GRAPH c_graph_2; + + c_graph_2=graph_2; + graph_2=graph_3; + graph_3=c_graph_2; + + ++order; + } + + graph->order_left=order; + } + + if (graph_1->u_aregs+i_aregs > u_aregs) + u_aregs=graph_1->u_aregs+i_aregs; + if (graph_1->u_dregs+i_dregs > u_dregs) + u_dregs=graph_1->u_dregs+i_dregs; + + i_aregs+=graph_1->i_aregs; + i_dregs+=graph_1->i_dregs; + + if (graph_2->u_aregs+i_aregs > u_aregs) + u_aregs=graph_2->u_aregs+i_aregs; + if (graph_2->u_dregs+i_dregs > u_dregs) + u_dregs=graph_2->u_dregs+i_dregs; + + i_aregs+=graph_2->i_aregs; + i_dregs+=graph_2->i_dregs; + + if (graph_3!=NULL){ + if (graph_3->u_aregs+i_aregs > u_aregs) + u_aregs=graph_3->u_aregs+i_aregs; + if (graph_3->u_dregs+i_dregs > u_dregs) + u_dregs=graph_3->u_dregs+i_dregs; + + i_aregs+=graph_3->i_aregs; + i_dregs+=graph_3->i_dregs; + } + + if (graph_1_before_reorder->order_mode==R_DREGISTER) + i_dregs-=graph_1_before_reorder->order_alterable; + else + i_aregs-=graph_1_before_reorder->order_alterable; + + if (graph_3_before_reorder!=NULL){ + if (graph_3_before_reorder->order_mode==R_DREGISTER) + i_dregs-=graph_3_before_reorder->order_alterable; + else + i_aregs-=graph_3_before_reorder->order_alterable; + } + + graph->order_alterable=graph_2_before_reorder->order_alterable; + if (graph_2_before_reorder->order_alterable) + if (graph_2_before_reorder->order_mode==R_DREGISTER) + --i_dregs; + else + --i_aregs; + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + graph->u_aregs=u_aregs; + graph->u_dregs=u_dregs; + + graph->order_mode=R_AREGISTER; +#ifdef PRINT_DEBUG + printf ("GFSTORE_X ud=%d id=%d ua=%d ia=%d\n",graph->u_dregs,graph->i_dregs,graph->u_aregs,graph->i_aregs); +#endif +} + +static void calculate_fstore_r_operator (register INSTRUCTION_GRAPH graph) +{ + register INSTRUCTION_GRAPH a_graph; + + a_graph=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (a_graph); + + graph->u_dregs=a_graph->u_dregs; + graph->u_aregs=a_graph->u_aregs; + graph->i_aregs=a_graph->i_aregs; + graph->i_dregs=a_graph->i_dregs; + + if (a_graph->order_alterable) + if (a_graph->order_mode==R_DREGISTER) + --graph->i_dregs; + else + --graph->i_aregs; + + graph->order_mode=R_DREGISTER; + graph->order_alterable=0; +#ifdef PRINT_DEBUG + printf ("GFSTORE_R ud=%d id=%d ua=%d ia=%d\n",graph->u_dregs,graph->i_dregs,graph->u_aregs,graph->i_aregs); +#endif +} + +static void calculate_bounds_operator (INSTRUCTION_GRAPH graph) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + int i_aregs,i_dregs; + int l_aregs,r_aregs,l_dregs,r_dregs; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (graph_1); + calculate_graph_register_uses (graph_2); + + i_aregs=graph_1->i_aregs+graph_2->i_aregs; + i_dregs=graph_1->i_dregs+graph_2->i_dregs; + + l_aregs=MAX (graph_1->u_aregs,graph_1->i_aregs+graph_2->u_aregs); + l_dregs=MAX (graph_1->u_dregs,graph_1->i_dregs+graph_2->u_dregs); + + r_aregs=MAX (graph_2->u_aregs,graph_2->i_aregs+graph_1->u_aregs); + r_dregs=MAX (graph_2->u_dregs,graph_2->i_dregs+graph_1->u_dregs); + + if (graph_1->order_mode!=R_AREGISTER){ + if (l_aregsorder_mode==R_DREGISTER) + i_dregs-=graph_1->order_alterable; + else + i_aregs-=graph_1->order_alterable; + + if (graph_2->order_mode==R_DREGISTER) + i_dregs-=graph_2->order_alterable; + else + i_aregs-=graph_2->order_alterable; + + if (l_dregsorder_mode=R_DREGISTER; + + if (AD_REG_WEIGHT (l_aregs,l_dregs) < AD_REG_WEIGHT (r_aregs,r_dregs)){ + graph->u_aregs=l_aregs; + graph->u_dregs=l_dregs; + graph->order_left=1; + } else { + graph->u_aregs=r_aregs; + graph->u_dregs=r_dregs; + graph->order_left=0; + } + + graph->i_aregs=i_aregs; + graph->i_dregs=i_dregs; + + graph->order_alterable=graph->node_count<=1; +} + +void calculate_graph_register_uses (INSTRUCTION_GRAPH graph) +{ + if (graph->order_mode!=R_NOMODE) + return; + + switch (graph->instruction_code){ + case GLOAD: + { + if (graph->instruction_d_min_a_cost<=0){ + graph->u_aregs=graph->i_aregs=0; + if (graph->node_count<=1){ + graph->u_dregs=graph->i_dregs=0; + graph->order_mode=R_MEMORY; + } else { + graph->u_dregs=graph->i_dregs=1; + graph->order_mode=R_DREGISTER; + } + } else { + graph->u_dregs=graph->i_dregs=0; + if (graph->node_count<=1){ + graph->u_aregs=graph->i_aregs=0; + graph->order_mode=R_MEMORY; + } else { + graph->u_aregs=graph->i_aregs=1; + graph->order_mode=R_AREGISTER; + } + } + graph->order_alterable=0; + return; + } + case GGREGISTER: + { + graph->u_aregs=0; + graph->u_dregs=0; + graph->i_aregs=0; + graph->i_dregs=0; + graph->order_alterable=0; + if (is_d_register (graph->instruction_parameters[0].i)) + graph->order_mode=R_DREGISTER; + else + graph->order_mode=R_AREGISTER; + return; + } + case GREGISTER: + { + graph->u_aregs=0; + graph->u_dregs=0; + graph->i_aregs=0; + graph->i_dregs=0; + if (is_d_register (graph->instruction_parameters[0].i)) + graph->order_mode=R_DREGISTER; + else + graph->order_mode=R_AREGISTER; + graph->order_alterable=graph->node_count<=1; + return; + } + case GLOAD_I: + if (graph->node_count>1){ + if (graph->instruction_d_min_a_cost<=0){ + graph->u_aregs=graph->i_aregs=0; + graph->u_dregs=graph->i_dregs=1; + graph->order_mode=R_DREGISTER; + } else { + graph->u_dregs=graph->i_dregs=0; + graph->u_aregs=graph->i_aregs=1; + graph->order_mode=R_AREGISTER; + } + } else { + graph->u_aregs=graph->i_aregs=graph->u_dregs=graph->i_dregs=0; + graph->order_mode=R_IMMEDIATE; + } + graph->order_alterable=0; + return; + case GLOAD_DES_I: + if (graph->node_count>1){ + if (graph->instruction_d_min_a_cost<0){ + graph->u_aregs=graph->i_aregs=0; + graph->u_dregs=graph->i_dregs=1; + graph->order_mode=R_DREGISTER; + } else { + graph->u_dregs=graph->i_dregs=0; + graph->u_aregs=graph->i_aregs=1; + graph->order_mode=R_AREGISTER; + } + } else { + graph->u_aregs=graph->i_aregs=graph->u_dregs=graph->i_dregs=0; + graph->order_mode=R_IMMEDIATE; + } + graph->order_alterable=0; + return; + case GLEA: + if (graph->instruction_d_min_a_cost<0){ + graph->u_dregs=1; + graph->i_dregs=1; + graph->u_aregs=1; + graph->i_aregs=0; + graph->order_mode=R_DREGISTER; + } else { + graph->u_dregs=0; + graph->i_dregs=0; + graph->u_aregs=1; + graph->i_aregs=1; + graph->order_mode=R_AREGISTER; + } + graph->order_alterable=graph->node_count<=1; + return; + case GLOAD_ID: + { + INSTRUCTION_GRAPH graph_1; + + graph_1=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (graph_1); + + switch (graph_1->order_mode){ + case R_AREGISTER: + graph->u_dregs=graph_1->u_dregs; + graph->u_aregs=graph_1->u_aregs; + graph->i_aregs=graph_1->i_aregs; + graph->i_dregs=graph_1->i_dregs; + graph->order_alterable=graph_1->order_alterable; + break; + case R_DREGISTER: + graph->u_dregs=graph_1->u_dregs; + graph->u_aregs=MAX (graph_1->u_aregs,1+graph_1->i_aregs); + graph->i_dregs=graph_1->i_dregs-graph_1->order_alterable; + graph->i_aregs=graph_1->i_aregs+1; + graph->order_alterable=1; + break; + case R_MEMORY: + case R_IMMEDIATE: + { + int i_aregs=graph_1->i_aregs+1-graph_1->order_alterable; + graph->u_dregs=graph_1->u_dregs; + graph->u_aregs=MAX (graph_1->u_aregs,i_aregs); + graph->i_dregs=graph_1->i_dregs; + graph->i_aregs=i_aregs; + graph->order_alterable=1; + } + } + + graph->order_mode=R_MEMORY; + + return; + } + case GLOAD_B_ID: + { + INSTRUCTION_GRAPH graph_1; + + graph_1=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (graph_1); + + graph->u_dregs=graph_1->u_dregs; + graph->u_aregs=graph_1->u_aregs; + graph->i_aregs=graph_1->i_aregs; + graph->i_dregs=graph_1->i_dregs; + + if (graph_1->order_mode==R_DREGISTER) + graph->i_dregs-=graph_1->order_alterable; + else + graph->i_aregs-=graph_1->order_alterable; + + if (graph->i_dregs+1 > graph->u_dregs) + graph->u_dregs=graph->i_dregs+1; + + if (graph_1->instruction_d_min_a_cost<=0){ + ++graph->i_dregs; + graph->order_mode=R_DREGISTER; + } else { + if (graph->i_aregs+1 > graph->u_aregs) + graph->u_aregs=graph->i_aregs+1; + ++graph->i_aregs; + graph->order_mode=R_AREGISTER; + } + graph->order_alterable=1; + + return; + } + case GLOAD_DES_ID: + { + INSTRUCTION_GRAPH graph_1; + + graph_1=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (graph_1); + + graph->u_dregs=graph_1->u_dregs; + graph->u_aregs=graph_1->u_aregs; + graph->i_aregs=graph_1->i_aregs; + graph->i_dregs=graph_1->i_dregs; + + if (graph_1->order_mode==R_DREGISTER) + graph->i_dregs-=graph_1->order_alterable; + else + graph->i_aregs-=graph_1->order_alterable; + + if (graph_1->instruction_d_min_a_cost<0){ + if (graph->i_dregs+1 > graph->u_dregs) + graph->u_dregs=graph->i_dregs+1; + ++graph->i_dregs; + graph->order_mode=R_DREGISTER; + } else { + if (graph->i_aregs+1 > graph->u_aregs) + graph->u_aregs=graph->i_aregs+1; + ++graph->i_aregs; + graph->order_mode=R_AREGISTER; + } + graph->order_alterable=1; + + return; + } + case GLOAD_X: + case GLOAD_B_X: + calculate_load_x_operator (graph); + return; + case GSTORE: + { + INSTRUCTION_GRAPH load_graph,a_graph; + + a_graph=graph->instruction_parameters[2].p; + load_graph=graph->instruction_parameters[3].p; + + calculate_graph_register_uses (a_graph); + + graph->u_dregs=a_graph->u_dregs; + graph->u_aregs=a_graph->u_aregs; + graph->i_aregs=a_graph->i_aregs; + graph->i_dregs=a_graph->i_dregs; + + if (a_graph->order_alterable) + if (a_graph->order_mode==R_DREGISTER) + --graph->i_dregs; + else + --graph->i_aregs; + + if (load_graph!=NULL && load_graph->node_count>0 && load_graph->instruction_code==GLOAD){ + if (load_graph->instruction_d_min_a_cost<=0){ + ++graph->i_dregs; + if (graph->i_dregs>graph->u_dregs) + graph->u_dregs=graph->i_dregs; + } else { + ++graph->i_aregs; + if (graph->i_aregs>graph->u_aregs) + graph->u_aregs=graph->i_aregs; + } + } + return; + } + case GSTORE_X: + case GSTORE_B_X: + calculate_store_x_operator (graph); + return; + case GBEFORE: + case GBEFORE0: + { + INSTRUCTION_GRAPH graph_1; + int i; + + graph_1=graph->instruction_parameters[0].p; + + calculate_graph_register_uses (graph_1); + + graph->u_dregs=graph_1->u_dregs; + graph->u_aregs=graph_1->u_aregs; + graph->i_aregs=graph_1->i_aregs; + graph->i_dregs=graph_1->i_dregs; + + for (i=1; iinode_arity; ++i){ + INSTRUCTION_GRAPH graph_2; + + graph_2=graph->instruction_parameters[i].p; + + if (graph_2->instruction_d_min_a_cost<=0){ + ++graph->i_dregs; + if (graph->i_dregs>graph->u_dregs) + graph->u_dregs=graph->i_dregs; + } else { + ++graph->i_aregs; + if (graph->i_aregs>graph->u_aregs) + graph->u_aregs=graph->i_aregs; + } + } + + graph->order_alterable=graph_1->order_alterable; + return; + } + case GKEEP: + case GFKEEP: + { + INSTRUCTION_GRAPH graph_1,graph_2; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (graph_1); + calculate_graph_register_uses (graph_2); + + /* de volgende berekening is onnauwkeurig : */ + + graph->u_aregs=MAX (graph_1->u_aregs,graph_1->i_aregs+graph_2->u_aregs); + graph->u_dregs=MAX (graph_1->u_dregs,graph_1->i_dregs+graph_2->u_dregs); + + graph->i_aregs=graph_1->i_aregs+graph_2->i_aregs; + graph->i_dregs=graph_1->i_dregs+graph_2->i_dregs; + + if (graph_1->order_mode==R_DREGISTER) + graph->i_dregs-=graph_1->order_alterable; + else + graph->i_aregs-=graph_1->order_alterable; + + graph->order_mode=graph_2->order_mode; + graph->order_alterable=graph_2->order_alterable; + return; + } + case GSTORE_R: + { + INSTRUCTION_GRAPH a_graph,register_graph; + int register_number; + + register_number=graph->instruction_parameters[0].i; + a_graph=graph->instruction_parameters[1].p; + + calculate_graph_register_uses (a_graph); + + graph->u_dregs=a_graph->u_dregs; + graph->u_aregs=a_graph->u_aregs; + graph->i_aregs=a_graph->i_aregs; + graph->i_dregs=a_graph->i_dregs; + + if (a_graph->order_alterable) + if (a_graph->order_mode==R_DREGISTER) + --graph->i_dregs; + else + --graph->i_aregs; + + register_graph=NULL; + + if (is_d_register (register_number)){ + ++graph->i_dregs; + if (graph->i_dregs>graph->u_dregs) + graph->u_dregs=graph->i_dregs; + + if ((unsigned) d_reg_num (register_number) < (unsigned) N_DATA_PARAMETER_REGISTERS) + register_graph=global_block.block_graph_d_register_parameter_node[d_reg_num (register_number)]; + } else { + ++graph->i_aregs; + if (graph->i_aregs>graph->u_aregs) + graph->u_aregs=graph->i_aregs; + + if ((unsigned) a_reg_num (register_number) < (unsigned) N_ADDRESS_PARAMETER_REGISTERS) + register_graph=global_block.block_graph_a_register_parameter_node[a_reg_num (register_number)]; + } + + if (register_graph!=NULL && register_graph->node_count>0){ + if (register_graph->instruction_d_min_a_cost<=0){ + ++graph->i_dregs; + if (graph->i_dregs>graph->u_dregs) + graph->u_dregs=graph->i_dregs; + } else { + ++graph->i_aregs; + if (graph->i_aregs>graph->u_aregs) + graph->u_aregs=graph->i_aregs; + } + } + +#ifdef PRINT_DEBUG + printf ("GSTORE_R reg=%d ud=%d id=%d ua=%d ia=%d\n",register_number, + graph->u_dregs,graph->i_dregs,graph->u_aregs,graph->i_aregs); +#endif + + return; + } + case GADD: + case GADD_O: + calculate_dyadic_commutative_operator (graph); + return; + case GAND: + case GOR: + case GMUL: + case GMUL_O: + calculate_dyadic_commutative_data_operator (graph); + return; + case GCMP_EQ: + case GCMP_LT: + case GCMP_GT: + calculate_compare_operator (graph); + return; + case GSUB: + case GSUB_O: + calculate_dyadic_non_commutative_operator (graph); + return; + case GDIV: + calculate_dyadic_non_commutative_data_operator (graph); + return; + case GMOD: + calculate_mod_operator (graph); + return; + case GLSL: + case GLSR: + case GASR: + calculate_shift_operator (graph); + return; + case GCREATE: + calculate_create_operator (graph); + return; + case GCREATE_R: + calculate_create_r_operator (graph); + return; + case GFILL_R: + calculate_fill_r_operator (graph); + return; + case GFILL: + calculate_fill_operator (graph); + return; + case GEOR: + calculate_eor_operator (graph); + return; + case GCNOT: + calculate_cnot_operator (graph); + return; + case GMOVEMI: + calculate_movemi_operator (graph); + return; + case GCOPY: + calculate_copy_operator (graph); + return; + case GFADD: + case GFDIV: + case GFMUL: + case GFREM: + case GFSUB: + calculate_dyadic_float_operator (graph); + return; + case GFCMP_EQ: + case GFCMP_GT: + case GFCMP_LT: + calculate_dyadic_commutative_data_operator (graph); + return; + case GFCOS: + case GFSIN: + case GFTAN: + case GFASIN: + case GFACOS: + case GFATAN: + case GFLN: + case GFLOG10: + case GFEXP: + case GFSQRT: + case GFNEG: + calculate_monadic_float_operator (graph); + return; + case GFLOAD_ID: + calculate_fload_id_operator (graph); + return; + case GFSTORE: + calculate_fstore_operator (graph); + return; + case GFLOAD_X: + calculate_fload_x_operator (graph); + return; + case GFSTORE_X: + calculate_fstore_x_operator (graph); + return; + case GFSTORE_R: + calculate_fstore_r_operator (graph); + return; + case GFLOAD: + case GFLOAD_I: + case GFREGISTER: + graph->u_aregs=graph->i_aregs=0; + graph->u_dregs=graph->i_dregs=0; + graph->order_mode=R_DREGISTER; + graph->order_alterable=0; + return; + case GFITOR: + case GFRTOI: + graph->u_aregs=graph->i_aregs=0; + graph->u_dregs=graph->i_dregs=0; + graph->order_mode=R_DREGISTER; + graph->order_alterable=0; + return; + case GALLOCATE: + case GFJOIN: + case GFHIGH: + case GFLOW: + case GFMOVEMI: + graph->u_aregs=graph->i_aregs=0; + graph->u_dregs=graph->i_dregs=0; + graph->order_mode=R_DREGISTER; + graph->order_alterable=0; + return; + case GBOUNDS: + calculate_bounds_operator (graph); + return; + case GINDIRECTION: + case GTEST_O: + { + INSTRUCTION_GRAPH graph_1; + + graph_1=graph->instruction_parameters[0].p; + + calculate_graph_register_uses (graph_1); + + graph->u_dregs=graph_1->u_dregs; + graph->u_aregs=graph_1->u_aregs; + graph->i_aregs=graph_1->i_aregs; + graph->i_dregs=graph_1->i_dregs; + + graph->order_mode=graph_1->order_mode; + graph->order_alterable=graph_1->order_alterable; + return; + } + case GEXIT_IF: + { + INSTRUCTION_GRAPH graph_1,graph_2; + + graph_1=graph->instruction_parameters[1].p; + graph_2=graph->instruction_parameters[2].p; + + calculate_graph_register_uses (graph_1); + calculate_graph_register_uses (graph_2); + + /* de volgende berekening is onnauwkeurig : */ + + graph->u_aregs=MAX (graph_1->u_aregs,graph_1->i_aregs+graph_2->u_aregs); + graph->u_dregs=MAX (graph_1->u_dregs,graph_1->i_dregs+graph_2->u_dregs); + + graph->i_aregs=graph_1->i_aregs+graph_2->i_aregs; + graph->i_dregs=graph_1->i_dregs+graph_2->i_dregs; + + if (graph_1->order_mode==R_DREGISTER) + graph->i_dregs-=graph_1->order_alterable; + else + graph->i_aregs-=graph_1->order_alterable; + + graph->order_mode=graph_2->order_mode; + graph->order_alterable=graph_2->order_alterable; + return; + } + default: + /* printf ("%d\n",graph->instruction_code); */ + internal_error_in_function ("calculate_graph_register_uses"); + } +} + +static void count_gstore_x_node (INSTRUCTION_GRAPH graph) +{ + INSTRUCTION_GRAPH low_graph,high_graph,h_store_x_graph; + + /* optime store_x for reals */ + + low_graph=graph->instruction_parameters[0].p; + if (low_graph->instruction_code==GFLOW){ + h_store_x_graph=graph->instruction_parameters[1].p; + if (h_store_x_graph!=NULL + && h_store_x_graph->instruction_code==GSTORE_X + && graph->instruction_parameters[3].p==h_store_x_graph->instruction_parameters[3].p + && graph->instruction_parameters[2].i==h_store_x_graph->instruction_parameters[2].i+(4<<2)) + { + high_graph=h_store_x_graph->instruction_parameters[0].p; + if (high_graph->instruction_code==GFHIGH + && high_graph->instruction_parameters[0].p==low_graph->instruction_parameters[0].p) + { + graph->instruction_code=GFSTORE_X; + graph->instruction_parameters[0].p=low_graph->instruction_parameters[0].p; + graph->instruction_parameters[1].p=h_store_x_graph->instruction_parameters[1].p; + graph->instruction_parameters[2].i-=4<<2; + } + } + } + + if (++graph->node_count==1){ + count_graph (graph->instruction_parameters[0].p); + count_graph (graph->instruction_parameters[1].p); + if (graph->instruction_parameters[3].p!=NULL) + count_graph (graph->instruction_parameters[3].p); + } +} + +void count_graph (INSTRUCTION_GRAPH graph) +{ + switch (graph->instruction_code){ + case GADD: + case GADD_O: + case GAND: + case GCMP_EQ: + case GCMP_GT: + case GCMP_LT: + case GDIV: + case GFADD: + case GFCMP_EQ: + case GFCMP_GT: + case GFCMP_LT: + case GFDIV: + case GFJOIN: + case GFMUL: + case GFREM: + case GFSUB: + case GLSL: + case GLSR: + case GMOD: + case GMUL: + case GMUL_O: + case GOR: + case GSUB: + case GSUB_O: + case GEOR: + case GASR: + case GCOPY: + case GBOUNDS: + if (++graph->node_count==1){ + count_graph (graph->instruction_parameters[0].p); + count_graph (graph->instruction_parameters[1].p); + } + break; + case GCNOT: + case GFHIGH: + case GFITOR: + case GFLOW: + case GFRTOI: + case GFCOS: + case GFSIN: + case GFTAN: + case GFASIN: + case GFACOS: + case GFATAN: + case GFLN: + case GFLOG10: + case GFEXP: + case GFSQRT: + case GFNEG: + case GBEFORE0: + case GTEST_O: + if (++graph->node_count==1) + count_graph (graph->instruction_parameters[0].p); + break; + case GALLOCATE: + case GCREATE_R: + case GCREATE: + case GFILL_R: + case GFILL: + case GBEFORE: + { + int n; + + if (++graph->node_count==1){ + for (n=0; ninode_arity; ++n) + if (graph->instruction_parameters[n].p!=NULL) + count_graph (graph->instruction_parameters[n].p); + } + break; + } + case GMOVEM: + if (++graph->node_count==1) + count_graph (graph->instruction_parameters[1].p); + break; + case GMOVEMI: + case GFMOVEMI: + if (++graph->node_count==1) + count_graph (graph->instruction_parameters[0].p); + break; + case GFLOAD_ID: + case GLOAD_ID: + case GLOAD_B_ID: + case GLOAD_DES_ID: + if (++graph->node_count==1) + count_graph (graph->instruction_parameters[1].p); + break; + case GFSTORE: + case GSTORE: + if (++graph->node_count==1) + count_graph (graph->instruction_parameters[2].p); + break; + case GSTORE_R: + case GFSTORE_R: + if (++graph->node_count==1) + count_graph (graph->instruction_parameters[1].p); + break; + case GLOAD_X: + case GLOAD_B_X: + case GFLOAD_X: + if (++graph->node_count==1){ + count_graph (graph->instruction_parameters[0].p); + if (graph->instruction_parameters[2].p!=NULL) + count_graph (graph->instruction_parameters[2].p); + } + break; + case GSTORE_X: + case GSTORE_B_X: + count_gstore_x_node (graph); + break; + case GFSTORE_X: + if (++graph->node_count==1){ + count_graph (graph->instruction_parameters[0].p); + count_graph (graph->instruction_parameters[1].p); + if (graph->instruction_parameters[3].p!=NULL) + count_graph (graph->instruction_parameters[3].p); + } + break; + case GKEEP: + case GFKEEP: + if (++graph->node_count==1){ + count_graph (graph->instruction_parameters[0].p); + count_graph (graph->instruction_parameters[1].p); + } + break; + case GEXIT_IF: + if (++graph->node_count==1){ + count_graph (graph->instruction_parameters[1].p); + count_graph (graph->instruction_parameters[2].p); + } + break; + case GFLOAD: + case GFLOAD_I: + case GFREGISTER: + case GGREGISTER: + case GLEA: + case GLOAD: + case GLOAD_I: + case GLOAD_DES_I: + case GREGISTER: + ++graph->node_count; + break; + default: + internal_error_in_function ("count_graph"); + } +} + +void mark_graph_2 (register INSTRUCTION_GRAPH graph) +{ + switch (graph->instruction_code){ + case GADD: + case GADD_O: + case GAND: + case GCMP_EQ: + case GCMP_GT: + case GCMP_LT: + case GDIV: + case GFADD: + case GFCMP_EQ: + case GFCMP_GT: + case GFCMP_LT: + case GFDIV: + case GFJOIN: + case GFMUL: + case GFREM: + case GFSUB: + case GLSL: + case GLSR: + case GMOD: + case GMUL: + case GMUL_O: + case GOR: + case GSUB: + case GSUB_O: + case GEOR: + case GASR: + case GCOPY: + case GBOUNDS: + if (graph->node_mark<2){ + graph->node_mark=2; + mark_graph_2 (graph->instruction_parameters[0].p); + mark_graph_2 (graph->instruction_parameters[1].p); + } + break; + case GCNOT: + case GFHIGH: + case GFITOR: + case GFLOW: + case GFRTOI: + case GFCOS: + case GFSIN: + case GFTAN: + case GFASIN: + case GFACOS: + case GFATAN: + case GFLN: + case GFLOG10: + case GFEXP: + case GFSQRT: + case GFNEG: + case GBEFORE0: + case GTEST_O: + if (graph->node_mark<2){ + graph->node_mark=2; + mark_graph_2 (graph->instruction_parameters[0].p); + } + break; + case GALLOCATE: + case GCREATE_R: + case GCREATE: + case GFILL_R: + case GFILL: + case GBEFORE: + { + int n; + + if (graph->node_mark<2){ + graph->node_mark=2; + for (n=0; ninode_arity; ++n) + if (graph->instruction_parameters[n].p!=NULL) + mark_graph_2 (graph->instruction_parameters[n].p); + } + break; + } + case GMOVEM: + if (graph->node_mark<2){ + graph->node_mark=2; + mark_graph_2 (graph->instruction_parameters[1].p); + } + break; + case GMOVEMI: + case GFMOVEMI: + if (graph->node_mark<2){ + graph->node_mark=2; + mark_graph_2 (graph->instruction_parameters[0].p); + } + break; + case GFLOAD_ID: + case GLOAD_ID: + case GLOAD_B_ID: + case GLOAD_DES_ID: + if (graph->node_mark<2){ + graph->node_mark=2; + mark_graph_2 (graph->instruction_parameters[1].p); + } + break; + case GFSTORE: + case GSTORE: + if (graph->node_mark<2){ + graph->node_mark=2; + mark_graph_2 (graph->instruction_parameters[2].p); + } + break; + case GSTORE_R: + if (graph->node_mark<2){ + graph->node_mark=2; + mark_graph_2 (graph->instruction_parameters[1].p); + } + break; + case GLOAD_X: + case GLOAD_B_X: + case GFLOAD_X: + if (graph->node_mark<2){ + graph->node_mark=2; + mark_graph_2 (graph->instruction_parameters[0].p); + if (graph->instruction_parameters[2].p) + mark_graph_2 (graph->instruction_parameters[2].p); + } + break; + case GSTORE_X: + case GSTORE_B_X: + case GFSTORE_X: + if (graph->node_mark<2){ + graph->node_mark=2; + mark_graph_2 (graph->instruction_parameters[0].p); + mark_graph_2 (graph->instruction_parameters[1].p); + if (graph->instruction_parameters[3].p) + mark_graph_2 (graph->instruction_parameters[3].p); + } + break; + case GKEEP: + case GFKEEP: + if (graph->node_mark<2){ + graph->node_mark=2; + mark_graph_2 (graph->instruction_parameters[0].p); + mark_graph_2 (graph->instruction_parameters[1].p); + } + break; + case GEXIT_IF: + if (graph->node_mark<2){ + graph->node_mark=2; + mark_graph_2 (graph->instruction_parameters[1].p); + mark_graph_2 (graph->instruction_parameters[2].p); + } + break; + case GFLOAD: + case GFLOAD_I: + case GFREGISTER: + case GGREGISTER: + case GLEA: + case GLOAD: + case GLOAD_I: + case GLOAD_DES_I: + case GREGISTER: + graph->node_mark=2; + break; + default: + internal_error_in_function ("mark_graph_2"); + } +} + +void mark_graph_1 (register INSTRUCTION_GRAPH graph) +{ + switch (graph->instruction_code){ + case GADD: + case GADD_O: + case GAND: + case GCMP_EQ: + case GCMP_GT: + case GCMP_LT: + case GDIV: + case GFADD: + case GFCMP_EQ: + case GFCMP_GT: + case GFCMP_LT: + case GFDIV: + case GFJOIN: + case GFMUL: + case GFREM: + case GFSUB: + case GLSL: + case GLSR: + case GMOD: + case GMUL: + case GMUL_O: + case GOR: + case GSUB: + case GSUB_O: + case GEOR: + case GASR: + case GCOPY: + case GBOUNDS: + if (!graph->node_mark){ + graph->node_mark=1; + mark_graph_2 (graph->instruction_parameters[0].p); + mark_graph_2 (graph->instruction_parameters[1].p); + } + break; + case GCNOT: + case GFITOR: + case GFRTOI: + case GFCOS: + case GFSIN: + case GFTAN: + case GFASIN: + case GFACOS: + case GFATAN: + case GFLN: + case GFLOG10: + case GFEXP: + case GFSQRT: + case GFNEG: + case GBEFORE0: + case GTEST_O: + if (!graph->node_mark){ + graph->node_mark=1; + mark_graph_2 (graph->instruction_parameters[0].p); + } + break; + case GALLOCATE: + case GCREATE_R: + case GCREATE: + case GFILL_R: + case GFILL: + case GBEFORE: + { + int n; + + if (!graph->node_mark){ + graph->node_mark=1; + for (n=0; ninode_arity; ++n) + if (graph->instruction_parameters[n].p!=NULL) + mark_graph_2 (graph->instruction_parameters[n].p); + } + break; + } + case GMOVEM: + if (!graph->node_mark){ + graph->node_mark=1; + mark_graph_2 (graph->instruction_parameters[1].p); + } + break; + case GMOVEMI: + case GFMOVEMI: + if (!graph->node_mark){ + graph->node_mark=1; + mark_graph_2 (graph->instruction_parameters[0].p); + } + break; + case GFLOAD_ID: + case GLOAD_ID: + case GLOAD_B_ID: + case GLOAD_DES_ID: + if (!graph->node_mark){ + graph->node_mark=1; + mark_graph_2 (graph->instruction_parameters[1].p); + } + break; + case GFSTORE: + case GSTORE: + if (!graph->node_mark){ + graph->node_mark=1; + mark_graph_2 (graph->instruction_parameters[2].p); + } + break; + case GLOAD_X: + case GLOAD_B_X: + case GFLOAD_X: + if (!graph->node_mark){ + graph->node_mark=1; + mark_graph_2 (graph->instruction_parameters[0].p); + if (graph->instruction_parameters[2].p) + mark_graph_2 (graph->instruction_parameters[2].p); + } + break; + case GSTORE_X: + case GSTORE_B_X: + case GFSTORE_X: + if (!graph->node_mark){ + graph->node_mark=1; + mark_graph_2 (graph->instruction_parameters[0].p); + mark_graph_2 (graph->instruction_parameters[1].p); + if (graph->instruction_parameters[3].p) + mark_graph_2 (graph->instruction_parameters[3].p); + } + break; + case GSTORE_R: + if (!graph->node_mark){ + graph->node_mark=1; + mark_graph_2 (graph->instruction_parameters[1].p); + } + break; + case GKEEP: + case GFKEEP: + if (!graph->node_mark){ + graph->node_mark=1; + mark_graph_2 (graph->instruction_parameters[0].p); + mark_graph_2 (graph->instruction_parameters[1].p); + } + break; + case GEXIT_IF: + if (!graph->node_mark){ + graph->node_mark=1; + mark_graph_2 (graph->instruction_parameters[1].p); + mark_graph_2 (graph->instruction_parameters[2].p); + } + break; + case GFLOAD: + case GFLOAD_I: + case GFREGISTER: + case GGREGISTER: + case GLEA: + case GLOAD: + case GLOAD_I: + case GLOAD_DES_I: + case GREGISTER: + if (!graph->node_mark) + graph->node_mark=1; + break; + case GFHIGH: + case GFLOW: + if (!graph->node_mark){ + graph->node_mark=1; + mark_graph_1 (graph->instruction_parameters[0].p); + } + break; + default: + internal_error_in_function ("mark_graph_1"); + } +} + +void mark_and_count_graph (INSTRUCTION_GRAPH graph) +{ + mark_graph_2 (graph); + count_graph (graph); +} diff --git a/cgcalc.h b/cgcalc.h new file mode 100644 index 0000000..6eaaae5 --- /dev/null +++ b/cgcalc.h @@ -0,0 +1,15 @@ +extern void calculate_graph_register_uses (INSTRUCTION_GRAPH graph); +extern void count_graph (INSTRUCTION_GRAPH graph); +extern void mark_graph_1 (INSTRUCTION_GRAPH graph); +extern void mark_graph_2 (INSTRUCTION_GRAPH graph); +extern void mark_and_count_graph (INSTRUCTION_GRAPH graph); + +#ifdef I486 +/* # define A_FACTOR 2 */ +/* # define D_FACTOR 2 */ +# define AD_REG_WEIGHT(n_a_regs,n_d_regs) ((n_a_regs)+(n_d_regs)) +#else +/* # define A_FACTOR 7 */ +/* # define D_FACTOR 3 */ +# define AD_REG_WEIGHT(n_a_regs,n_d_regs) ((((n_a_regs)<<3)-(n_a_regs))+((n_d_regs)+(n_d_regs)+(n_d_regs))) +#endif diff --git a/cgcode.h b/cgcode.h new file mode 100644 index 0000000..7b329e8 --- /dev/null +++ b/cgcode.h @@ -0,0 +1,76 @@ + +#define g_fhighlow(gh,gl,gf) \ + (gh)=g_instruction_2 (GFHIGH,(gf),NULL); \ + (gl)=g_instruction_2 (GFLOW,(gf),(gh)); \ + (gh)->instruction_parameters[1].p=(gl) + +extern void initialize_coding (VOID); +extern void show_code (VOID); +extern void show_imports_and_exports (VOID); + +extern INSTRUCTION_GRAPH g_load (int offset,int stack); +extern INSTRUCTION_GRAPH g_fjoin (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2); +extern INSTRUCTION_GRAPH g_fregister (int float_reg); +extern INSTRUCTION_GRAPH g_fstore (int offset,int reg_1,INSTRUCTION_GRAPH graph_1, + INSTRUCTION_GRAPH graph_2,INSTRUCTION_GRAPH graph_3); +extern INSTRUCTION_GRAPH g_fstore_r (int reg_1,INSTRUCTION_GRAPH graph_1); +extern INSTRUCTION_GRAPH g_store (int offset,int reg_1,INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2); +extern INSTRUCTION_GRAPH g_store_r (int reg_1,INSTRUCTION_GRAPH graph_1); +extern INSTRUCTION_GRAPH g_register (int reg); +extern INSTRUCTION_GRAPH g_fload (int offset,int stack); +extern INSTRUCTION_GRAPH g_instruction_1 (int instruction_code,INSTRUCTION_GRAPH graph_1); +extern INSTRUCTION_GRAPH g_instruction_2 (int instruction_code,INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2); +extern INSTRUCTION_GRAPH g_new_node (int,int,int); + +#ifndef g_fhighlow +# define g_fhigh(g1) g_instruction_1(GFHIGH,(g1)) +# define g_flow(g1) g_instruction_1(GFLOW,(g1)) +#endif + +extern LABEL *enter_label (char *label_name,int label_flags); +extern LABEL *new_local_label (int label_flags); + +extern int next_label_id; +extern struct basic_block *first_block; +extern struct label_node *labels; +extern struct local_label *local_labels; +extern struct dependency_list *first_dependency; +extern LABEL + *collect_0_label,*collect_1_label,*collect_2_label, +#ifndef I486 + *collect_3_label, +#endif +#ifdef I486 + *collect_0l_label,*collect_1l_label,*collect_2l_label,*end_heap_label, +#endif +#ifdef G_POWER + *collect_00_label,*collect_01_label,*collect_02_label,*collect_03_label, + *eval_01_label,*eval_11_label,*eval_02_label,*eval_12_label,*eval_22_label, +#endif + *EMPTY_label; +#if defined (G_POWER) || defined (I486) +extern LABEL + *profile_l_label,*profile_l2_label,*profile_n_label,*profile_n2_label, + *profile_s_label,*profile_s2_label,*profile_r_label,*profile_t_label; +# ifdef G_POWER +extern LABEL *profile_ti_label; +# endif +#endif +extern INSTRUCTION_GRAPH load_indexed_list; + +extern int no_memory_profiling; + +#define PROFILE_NOT 0 +#define PROFILE_NORMAL 1 +#define PROFILE_DOUBLE 2 +#define PROFILE_TAIL 3 +#define PROFILE_CURRIED 4 +#define PROFILE_CURRIED_DOUBLE 5 + +extern LABEL *_STRING__label; +extern LABEL*copy_graph_label,*CHANNEL_label,*create_channel_label,*currentP_label,*newP_label, + *randomP_label,*suspend_label; +extern struct block_label *last_block_label; +extern LABEL *profile_table_label; + +extern void write_profile_table (void); diff --git a/cgconst.h b/cgconst.h new file mode 100644 index 0000000..29d64e6 --- /dev/null +++ b/cgconst.h @@ -0,0 +1,27 @@ + +enum { + GADD, GADD_O, GAND, GALLOCATE, GASR, GBEFORE, + GBEFORE0, GBOUNDS, GCMP_EQ, GCMP_GT, GCMP_LT, GCNOT, + GCOPY, GCREATE, GCREATE_R, GDIV, GEOR, + GFACOS, GFADD, GFASIN, GFCMP_EQ, GFCMP_GT, GFATAN, + GFCMP_LT, GFCOS, GFDIV, GFEXP, GFHIGH, GFITOR, + GFJOIN, GFKEEP, GFLN, GFLOAD, GFLOAD_I, GFLOAD_ID, + GFLOAD_X, GFLOG10, GFLOW, GFMOVEMI, GFMUL, GFNEG, + GFREM, GFRTOI, GFSIN, GFSUB, GFILL, GFILL_R, + GFREGISTER, GFSQRT, GFSTORE, GFSTORE_R, GFSTORE_X, GFTAN, + GGFREGISTER, GGREGISTER, GKEEP, GINDIRECTION, GLEA, GLOAD, + GLOAD_I, GLOAD_ID, GLOAD_X, GLOAD_B_ID, GLOAD_B_X, GLOAD_DES_ID, + GLOAD_DES_I, GLSL, GLSR, GMOD, GMOVEM, GMOVEMI, + GMUL, GMUL_O, GOR, GREGISTER, GSTORE, GSTORE_R, + GSTORE_B_X, GSTORE_X, GSUB, GSUB_O, GTEST_O, GEXIT_IF +#ifdef G_POWER + ,GCREATE_S +#endif +}; + +enum { + JSR_BLOCK, JSR_EVAL_BLOCK, APPLY_BLOCK +#ifdef G_POWER + ,JSR_BLOCK_WITH_INSTRUCTIONS +#endif +}; diff --git a/cginput.h b/cginput.h new file mode 100644 index 0000000..dd6b082 --- /dev/null +++ b/cginput.h @@ -0,0 +1,2 @@ +void initialize_parser (VOID); +int parse_file (FILE *file); diff --git a/cginstructions.h b/cginstructions.h new file mode 100644 index 0000000..88087f1 --- /dev/null +++ b/cginstructions.h @@ -0,0 +1,60 @@ +extern INSTRUCTION_GRAPH g_new_node (int instruction_code,int arity,int arg_size); +extern INSTRUCTION_GRAPH g_instruction_1 (int instruction_code,INSTRUCTION_GRAPH graph_1); +extern INSTRUCTION_GRAPH g_instruction_2 (int instruction_code,INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2); +extern INSTRUCTION_GRAPH g_instruction_2_0 (int instruction_code,INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2); +extern INSTRUCTION_GRAPH g_test_o (INSTRUCTION_GRAPH graph_1); +extern INSTRUCTION_GRAPH g_allocate (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2,int n); +extern INSTRUCTION_GRAPH g_before (INSTRUCTION_GRAPH graph_1,int n); +extern INSTRUCTION_GRAPH g_copy (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2); +extern INSTRUCTION_GRAPH g_create_1 (INSTRUCTION_GRAPH graph_1); +extern INSTRUCTION_GRAPH g_create_2 (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2); +extern INSTRUCTION_GRAPH g_create_3 (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2,INSTRUCTION_GRAPH graph_3); +extern INSTRUCTION_GRAPH g_create_m (int arity); +extern INSTRUCTION_GRAPH g_create_r (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2); +extern INSTRUCTION_GRAPH g_exit_if (LABEL *label,INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2); +extern INSTRUCTION_GRAPH g_fill_2 (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2); +extern INSTRUCTION_GRAPH g_fill_3 (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2,INSTRUCTION_GRAPH graph_3); +extern INSTRUCTION_GRAPH g_fill_4 (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2,INSTRUCTION_GRAPH graph_3,INSTRUCTION_GRAPH graph_4); +extern INSTRUCTION_GRAPH g_fill_m (INSTRUCTION_GRAPH graph_1,int arity); +extern INSTRUCTION_GRAPH g_fill_r (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2,INSTRUCTION_GRAPH graph_3); +extern INSTRUCTION_GRAPH g_fjoin (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2); +extern INSTRUCTION_GRAPH g_fload (int offset,int stack); +extern INSTRUCTION_GRAPH g_fload_i (DOUBLE v); +extern INSTRUCTION_GRAPH g_fload_id (int offset,INSTRUCTION_GRAPH graph_1); +extern INSTRUCTION_GRAPH g_fload_x (INSTRUCTION_GRAPH graph_1,int offset,int shift,INSTRUCTION_GRAPH graph_2); +extern INSTRUCTION_GRAPH g_lea (LABEL *label); +extern INSTRUCTION_GRAPH g_lea_i (LABEL *label,int offset); +extern INSTRUCTION_GRAPH g_load (int offset,int stack); +extern INSTRUCTION_GRAPH g_load_i (LONG value); +extern INSTRUCTION_GRAPH g_load_id (int offset,INSTRUCTION_GRAPH graph_1); +extern INSTRUCTION_GRAPH g_load_b_x (INSTRUCTION_GRAPH graph_1,int offset,int sign_extend,INSTRUCTION_GRAPH graph_2); +extern INSTRUCTION_GRAPH g_load_x (INSTRUCTION_GRAPH graph_1,int offset,int shift,INSTRUCTION_GRAPH graph_2); +extern INSTRUCTION_GRAPH g_load_b_id (int offset,INSTRUCTION_GRAPH graph_1); +extern INSTRUCTION_GRAPH g_load_des_i (LABEL *descriptor_label,int arity); +extern INSTRUCTION_GRAPH g_load_des_id (int offset,INSTRUCTION_GRAPH graph_1); +extern INSTRUCTION_GRAPH g_movem (int offset,INSTRUCTION_GRAPH graph_1,int n); +extern INSTRUCTION_GRAPH g_movemi (int number,INSTRUCTION_GRAPH movem_graph); +extern INSTRUCTION_GRAPH g_fregister (int float_reg); +extern INSTRUCTION_GRAPH g_fstore_x (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2,int offset,int shift,INSTRUCTION_GRAPH graph_3); +extern INSTRUCTION_GRAPH g_g_register (int reg); +extern INSTRUCTION_GRAPH g_register (int reg); +extern INSTRUCTION_GRAPH g_store (int offset,int reg_1,INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2); +extern INSTRUCTION_GRAPH g_store_b_x (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2,int offset,INSTRUCTION_GRAPH graph_3); +extern INSTRUCTION_GRAPH g_store_x (INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2,int offset,int shift,INSTRUCTION_GRAPH graph_3); +extern INSTRUCTION_GRAPH g_store_r (int reg_1,INSTRUCTION_GRAPH graph_1); + +extern LABEL *w_code_descriptor_length_and_string (char *string,int length); +extern LABEL *w_code_string (char *string,int length); +extern LABEL *w_code_length_and_string (char *string,int length); +extern void w_descriptor_string (char *string,int length,int string_code_label_id,LABEL *string_label); + +extern void init_cginstructions (void); + +extern LABEL *realloc_0_label,*realloc_1_label,*realloc_2_label,*realloc_3_label, + *schedule_0_label,*schedule_1_label,*schedule_2_label,*schedule_3_label, + *schedule_eval_label,*stack_overflow_label; + +#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS +extern LABEL *end_a_stack_label,*end_b_stack_label; +#endif + diff --git a/cgiwas.h b/cgiwas.h new file mode 100644 index 0000000..2182c4c --- /dev/null +++ b/cgiwas.h @@ -0,0 +1,25 @@ +void initialize_write_assembly (FILE *ass_file); +void write_assembly (VOID); +void w_as_abc_string_and_label_in_code_section (char *string,int length,char *label_name); +void w_as_abc_string_in_code_section (char *string,int length,int label_number); +void w_as_c_string_in_code_section (char *string,int length,int label_number); +void w_as_c_string_in_data_section (char *string,int length); +void w_as_descriptor_string_in_code_section (char *string,int length,int string_code_label_id,LABEL *string_label); +void w_as_word_in_data_section (int n); +void w_as_label_in_data_section (char *label_name); +void w_as_descriptor_in_data_section (char *label_name); +void w_as_define_label (LABEL *label); +void w_as_internal_label_value (int label_id); +void w_as_new_module (int flag); +void w_as_long_in_data_section (int n); +void w_as_to_data_section (void); +void w_as_descriptor_in_code_section (char *label_name); +void w_as_define_data_label (int label_number); +void w_as_labeled_c_string_in_data_section (char *string,int length,int label_number); +void w_as_abc_string_in_data_section (char *string,int length); +void w_as_descriptor_string_in_data_section (char *string,int length,int string_label_id,LABEL *string_label); +void w_as_abc_string_and_label_in_data_section (char *string,int length,char *label_name); +void w_as_c_string_and_label_in_code_section (char *string,int length,char *label_name); +#ifdef _WINDOWS_ +void w_as_new_data_module (void); +#endif diff --git a/cglin.h b/cglin.h new file mode 100644 index 0000000..fe6a547 --- /dev/null +++ b/cglin.h @@ -0,0 +1,126 @@ + +void show_instructions (struct instruction *instructions); +void initialize_linearization (VOID); +void evaluate_arguments_and_free_addresses (union instruction_parameter arguments[],int n_arguments); +void get_n_virtual_registers (int *n_virtual_a_regs_p,int *n_virtual_d_regs_p,int *n_virtual_f_regs_p); +void calculate_and_linearize_branch_false (LABEL *label,INSTRUCTION_GRAPH graph); +void calculate_and_linearize_branch_true (LABEL *label,INSTRUCTION_GRAPH graph); +void calculate_and_linearize_graph (INSTRUCTION_GRAPH graph); + +void free_all_aregisters (VOID); +void free_all_dregisters (VOID); +void free_all_fregisters (VOID); +void allocate_aregister (int aregister); +void allocate_dregister (int dregister); +void allocate_fregister (int fregister); +#ifdef M68000 +void instruction_pd (int instruction_code,int register_1); +#endif +void i_jmp_l (LABEL *label,int n_a_registers); +void i_jmp_id (int offset_1,int register_1,int n_a_registers); +#if ! (defined (sparc) || defined (G_POWER)) + void i_jsr_id (int offset,int register_1,int n_a_registers); + void i_jsr_l (LABEL *label,int n_a_registers); + void i_rts (void); +# ifdef I486 + void i_rts_i (int offset); + void i_rts_profile (void); + void i_jmp_r_profile (int a_reg); + void i_jmp_l_profile (LABEL *label,int offset); + void i_jmp_id_profile (int offset_1,int register_1,int n_a_registers); +# endif +#else + void i_jsr_id_id (int offset_1,int register_1,int offset_2); + void i_jsr_l_id (LABEL *label,int offset); + void i_rts (int offset_1,int offset_2); +# ifdef G_POWER + void i_rts_c (void); + void i_rts_r (int register1,int offset_1); + void i_rts_r_profile (int register1,int offset_1); + void i_jmp_l_profile (LABEL *label,int offset); + void i_jmp_id_profile (int offset_1,int register_1,int n_a_registers); + void i_rts_profile (int offset_1,int offset_2); + void i_jsr_id_idu (int offset_1,int register_1,int offset_2); + void i_jsr_l_idu (LABEL *label,int offset); +# endif +#endif +#if defined (sparc) + void i_call_l (LABEL *label); + void i_call_r (int register_1); +#elif defined (G_POWER) + void i_call_l (LABEL *label,int frame_size); + void i_call_r (int register_1,int frame_size); +#endif +void i_beq_l (LABEL *label); +#ifdef M68000 + extern LONG *i_bmi_i (VOID); + void i_bmi_l (LABEL *label); +#endif +#ifdef G_POWER + void i_and_i_r (LONG value,int register_1); + void i_bnep_l (LABEL *label); + void i_or_i_r (LONG value,int register_1); + void i_mtctr (int register_1); +#endif +#if defined (sparc) || defined (I486) || defined (G_POWER) + void i_btst_i_r (LONG i,int register_1); +#endif +void i_ext_r (int register_1); +void i_fmove_fr_fr (int register_1,int register_2); +void i_fmove_fr_id (int register_1,int offset,int register_2); +#ifdef M68000 + void i_fmove_fr_pd (int register_1,int register_2); + void i_fmove_fr_pi (int register_1,int register_2); +#endif +void i_fmove_id_fr (int offset,int register_2,int register_1); +#ifdef M68000 + void i_fmove_pd_fr (int register_1,int register_2); + void i_fmove_pi_fr (int register_1,int register_2); + void i_move_id_pd (int offset,int register_1,int register_2); +#endif +void i_move_id_id (int offset_1,int register_1,int offset_2,int register_2); +void i_move_id_r (int offset,int register_1,int register_2); +#ifdef G_POWER + void i_move_idu_r (int offset,int register_1,int register_2); + void i_move_id_idu (int offset1,int register_1,int offset2,int register_2); + void i_move_r_idu (int register_1,int offset,int register_2); + void i_movew_id_idu (int offset1,int register_1,int offset2,int register_2); + void i_movew_r_idu (int register_1,int offset,int register_2); +#endif +void i_move_i_r (LONG i,int register_1); +void i_move_l_r (LABEL *label,int register_1); +#ifdef M68000 +void i_move_pi_id (int register_1,int offset_2,int register_2); +void i_move_pi_r (int register_1,int register_2); +void i_move_pd_r (int register_1,int register_2); +#endif +#if defined (I486) + void i_move_r_l (int register_1,LABEL *label); +#endif +void i_move_r_id (int register_1,int offset,int register_2); +#ifdef M68000 +void i_move_r_pd (int register_1,int register_2); +void i_move_r_pi (int register_1,int register_2); +#endif +void i_move_r_r (int register_1,int register_2); +#ifdef M68000 +void i_movem_pd (int register_1,int n_arguments,int arguments[]); +void i_movem_pi (int register_1,int n_arguments,int arguments[]); +void i_movem_id_r (int offset,int register_1,int register_2); +void i_movew_id_pd (int offset_1,int register_1,int register_2); +void i_movew_pi_id (int register_1,int offset_2,int register_2); +void i_movew_pi_r (int register_1,int register_2); +void i_movew_r_pd (int register_1,int register_2); +#endif +void i_movew_id_r (int offset,int register_1,int register_2); +void i_lea_id_r (int offset,int register_1,int register_2); +void i_lea_l_i_r (LABEL *label,int offset,int register_1); +void i_add_i_r (LONG value,int register_1); +void i_add_r_r (int register_1,int register_2); +void i_schedule_i (int value); +void i_sub_i_r (LONG value,int register_1); +void i_tst_r (int register_1); +void i_word_i (int value); + +extern int local_data_offset; +extern int condition_to_set_instruction[]; diff --git a/cgopt.h b/cgopt.h new file mode 100644 index 0000000..7b61680 --- /dev/null +++ b/cgopt.h @@ -0,0 +1,10 @@ + +extern void optimize_jumps (VOID); +extern void optimize_stack_access (struct basic_block *block,int *a_offset_p,int *b_offset_p); +extern int do_register_allocation + (struct instruction *last_instruction,struct basic_block *basic_block, + int highest_a_register,int highest_d_register,int highest_f_register, + int not_alter_condition_codes_flag,int condition); +#ifdef G_POWER +void optimize_heap_pointer_increment (struct basic_block *block,int offset_from_heap_register); +#endif diff --git a/cgpas.h b/cgpas.h new file mode 100644 index 0000000..1e47a9a --- /dev/null +++ b/cgpas.h @@ -0,0 +1,14 @@ + +extern void assemble_code (VOID); +extern void initialize_assembler (FILE *file); +extern void define_data_label (LABEL *label); +extern void store_2_words_in_data_section (UWORD w1,UWORD w2); +extern void store_long_word_in_data_section (ULONG i); +extern void store_label_in_data_section (LABEL *label); +extern void store_descriptor_in_data_section (LABEL *label); +extern void store_c_string_in_data_section (char *string,int length); +extern void store_abc_string_in_data_section (char *string,int length); +extern void store_descriptor_string_in_data_section (char *string,int length,LABEL *string_label); + +extern void as_new_data_module (void); +extern void w_as_new_data_module (void); diff --git a/cgptoc.c b/cgptoc.c new file mode 100644 index 0000000..adb54de --- /dev/null +++ b/cgptoc.c @@ -0,0 +1,65 @@ + +#include + +#include "cgport.h" + +#ifdef G_POWER + +#include "cgrconst.h" +#include "cgtypes.h" +#include "cg.h" +#include "cgptoc.h" + +int t_label_number; + +struct toc_label *toc_labels,**last_toc_next_p; + +struct toc_label *new_toc_label (struct label *label,int offset) +{ + struct toc_label *new_toc_label,**toc_label_p; + int label_number; + + toc_label_p=&label->label_toc_labels; + + if (label->label_flags & HAS_TOC_LABELS){ + struct toc_label *toc_label; + + while (toc_label=*toc_label_p,toc_label!=NULL){ + if (toc_label->toc_label_offset==offset) + return toc_label; + + toc_label_p=&toc_label->toc_label_next; + } + } else + label->label_flags |= HAS_TOC_LABELS; + + new_toc_label=(struct toc_label*)allocate_memory_from_heap (sizeof (struct toc_label)); + + label_number=t_label_number++; + + new_toc_label->toc_t_label_number=label_number; + new_toc_label->toc_label_label=label; + new_toc_label->toc_label_offset=offset; + + *toc_label_p=new_toc_label; + new_toc_label->toc_label_next=NULL; + + *last_toc_next_p=new_toc_label; + last_toc_next_p=&new_toc_label->toc_next; + + return new_toc_label; +} + +int make_toc_label (struct label *label,int offset) +{ + return new_toc_label (label,offset)->toc_t_label_number; +} + +void initialize_toc (void) +{ + t_label_number=0; + last_toc_next_p=&toc_labels; + toc_labels=NULL; +} + +#endif diff --git a/cgpwas.h b/cgpwas.h new file mode 100644 index 0000000..aeaac61 --- /dev/null +++ b/cgpwas.h @@ -0,0 +1,19 @@ +void w_as_labeled_c_string_in_data_section (char *string,int length,int label_number); +void w_as_descriptor_in_data_section (char *label_name); +void w_as_abc_string_in_data_section (char *string,int length); +void w_as_descriptor_string_in_data_section (char *string,int length,int string_label_id,LABEL *string_label); +void w_as_long_in_data_section (int n); +void w_as_to_data_section (VOID); +void w_as_define_label (LABEL *label); +void w_as_internal_label_value (int label_id); +void w_as_word_in_data_section (int n); +void w_as_label_in_data_section (char *label_name); +void w_as_c_string_in_data_section (char *string,int length); +void w_as_abc_string_and_label_in_data_section (char *string,int length,char *label_name); +void w_as_define_data_label (int label_number); +void w_as_new_data_module (VOID); +void w_as_c_string_and_label_in_code_section (char *string,int length,char *label_name); +void initialize_write_assembly (FILE *ass_file); +void w_as_jmp_instruction (struct instruction *instruction); +void write_assembly (VOID); + diff --git a/cgrconst.h b/cgrconst.h new file mode 100644 index 0000000..4256a62 --- /dev/null +++ b/cgrconst.h @@ -0,0 +1,58 @@ + +enum { +#ifdef G_POWER + REGISTER_A11=-12, REGISTER_A10, REGISTER_A9, REGISTER_A8, +#endif + REGISTER_A7=-8, REGISTER_A6, REGISTER_A5, REGISTER_A4, + REGISTER_A3, REGISTER_A2, REGISTER_A1, REGISTER_A0, + REGISTER_D0, REGISTER_D1, REGISTER_D2, REGISTER_D3, + REGISTER_D4, REGISTER_D5, REGISTER_D6, REGISTER_D7 + +}; + +enum { REGISTER_FP0, REGISTER_FP1, REGISTER_FP2, REGISTER_FP3, + REGISTER_FP4, REGISTER_FP5, REGISTER_FP6, REGISTER_FP7 }; + +#define is_a_register(r) ((r)<0) +#define is_d_register(r) ((r)>=0) + +#define a_reg_num(r) (~(r)) /* ~n is -(n+1) */ +#define d_reg_num(r) (r) + +#define num_to_a_reg(r) (~(r)) +#define num_to_d_reg(r) (r) + +#ifdef I486 +# define A_STACK_POINTER REGISTER_A3 +# define HEAP_POINTER REGISTER_A4 +# define B_STACK_POINTER REGISTER_A5 +# define N_ADDRESS_PARAMETER_REGISTERS 2 +# define N_DATA_PARAMETER_REGISTERS 2 +# define N_FLOAT_PARAMETER_REGISTERS 7 +#else +# define A_STACK_POINTER REGISTER_A4 +# if !(defined (sparc) || defined (G_POWER)) +# define GLOBAL_DATA_REGISTER REGISTER_A5 +# else +# define RESERVE_CODE_REGISTER REGISTER_A5 +# endif +# define HEAP_POINTER REGISTER_A6 +# ifdef G_POWER +# define B_STACK_POINTER REGISTER_A11 +# else +# define B_STACK_POINTER REGISTER_A7 +# endif +# define N_ADDRESS_PARAMETER_REGISTERS 3 +# define N_DATA_PARAMETER_REGISTERS 7 +# define N_FLOAT_PARAMETER_REGISTERS 8 +#endif + +#ifdef G_POWER +# define N_REAL_A_REGISTERS 12 +# define INT_REGISTER REGISTER_A7 +# define CHAR_REGISTER REGISTER_A8 +# define REAL_REGISTER REGISTER_A9 +# define BOOL_REGISTER REGISTER_A10 +#else +# define N_REAL_A_REGISTERS 8 +#endif diff --git a/cgstack.c b/cgstack.c new file mode 100644 index 0000000..73163e5 --- /dev/null +++ b/cgstack.c @@ -0,0 +1,4320 @@ +/* + File: cgstack.c + Author: John van Groningen + At: University of Nijmegen +*/ + +#include +#include "cgport.h" +#include "cgconst.h" +#include "cgrconst.h" +#include "cgtypes.h" + +#include "cgstack.h" + +#include "cg.h" +#include "cglin.h" +#include "cgcalc.h" +#include "cgopt.h" +#include "cgcode.h" + +#define for_l(v,l,n) for(v=(l);v!=NULL;v=v->n) + +#define g_fhighlow(gh,gl,gf) \ + (gh)=g_instruction_2 (GFHIGH,(gf),NULL); \ + (gl)=g_instruction_2 (GFLOW,(gf),(gh)); \ + (gh)->instruction_parameters[1].p=(gl) + +#define ELEMENT_MAY_BE_REMOVED 1 +#define ELEMENT_USED_BEFORE_JSR 2 +#define ELEMENT_MUST_BE_REMOVED 4 +#define BEGIN_ELEMENT_MUST_BE_REMOVED 8 + +struct stack { + struct stack * stack_next; + WORD stack_offset; + WORD stack_flags; + INSTRUCTION_GRAPH stack_graph; + INSTRUCTION_GRAPH stack_load_graph; +}; + +struct a_stack { + struct a_stack * a_stack_next; + WORD a_stack_offset; + WORD a_stack_flags; + INSTRUCTION_GRAPH a_stack_graph; + INSTRUCTION_GRAPH a_stack_load_graph; +}; + +struct b_stack { + struct b_stack * b_stack_next; + WORD b_stack_offset; + WORD b_stack_flags; + INSTRUCTION_GRAPH b_stack_graph; + INSTRUCTION_GRAPH b_stack_load_graph; +}; + +/* from cgcode */ + +struct block_graph global_block; + +extern struct basic_block *last_block; +extern struct instruction *last_instruction; + +/* from cgopt.c */ +extern unsigned int end_a_registers,end_d_registers,end_f_registers; + +/* from cglin.c */ +extern int local_data_offset; + +#pragma segment Code4 + +#define allocate_struct_from_heap(a) (struct a*)allocate_memory_from_heap(sizeof (struct a)) + +INSTRUCTION_GRAPH s_get_a (int offset) +{ + register struct a_stack **element_h,*element_p,*new_element; + register int required_offset; + INSTRUCTION_GRAPH graph; + + required_offset=global_block.block_graph_a_stack_top_offset+offset; + + element_h=&global_block.block_graph_a_stack; + while ((element_p=*element_h)!=NULL){ + register int element_offset=element_p->a_stack_offset; + + if (element_offset==required_offset) + return element_p->a_stack_graph; + + if (element_offset>required_offset) + break; + + element_h=&element_p->a_stack_next; + } + + graph=g_load + (-((required_offset+global_block.block_graph_a_stack_begin_displacement+1)<<2),A_STACK_POINTER); + + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=required_offset; + new_element->a_stack_flags=0; + new_element->a_stack_graph=graph; + new_element->a_stack_load_graph=graph; + + new_element->a_stack_next=*element_h; + *element_h=new_element; + + return graph; +} + +static void s_put_a_l (int offset,INSTRUCTION_GRAPH graph,INSTRUCTION_GRAPH new_load_graph) +{ + register struct a_stack *element_p,**element_h,*new_element; + register int required_offset; + + required_offset=global_block.block_graph_a_stack_top_offset+offset; + + element_h=&global_block.block_graph_a_stack; + while ((element_p=*element_h)!=NULL){ + int element_offset=element_p->a_stack_offset; + + if (element_offset==required_offset){ + element_p->a_stack_graph=graph; + return; + } + + if (element_offset>required_offset) + break; + + element_h=&element_p->a_stack_next; + } + + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=required_offset; + new_element->a_stack_flags=0; + new_element->a_stack_graph=graph; + new_element->a_stack_load_graph=new_load_graph; + + new_element->a_stack_next=*element_h; + *element_h=new_element; +} + +void s_put_a (int offset,INSTRUCTION_GRAPH graph) +{ + s_put_a_l (offset,graph,NULL); +} + +void s_push_a (INSTRUCTION_GRAPH graph) +{ + --global_block.block_graph_a_stack_top_offset; + s_put_a (0,graph); +} + +INSTRUCTION_GRAPH s_pop_a (VOID) +{ + INSTRUCTION_GRAPH graph; + + graph=s_get_a (0); + ++global_block.block_graph_a_stack_top_offset; + + return graph; +} + +void s_remove_a (VOID) +{ + ++global_block.block_graph_a_stack_top_offset; +} + +void release_a_stack (VOID) +{ + register int n; + + global_block.block_graph_a_stack=NULL; + for (n=0; nb_stack_offset; + + if (element_offset==required_offset) + return element_p->b_stack_graph; + + if (element_offset>required_offset) + break; + + element_h=&element_p->b_stack_next; + } + + graph=g_load + ((required_offset+global_block.block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=required_offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=graph; + new_element->b_stack_load_graph=graph; + + new_element->b_stack_next=*element_h; + *element_h=new_element; + + return graph; +} + +static void s_put_b_l (int offset,INSTRUCTION_GRAPH graph,INSTRUCTION_GRAPH new_load_graph) +{ + register struct b_stack **element_h,*element_p,*new_element; + register int required_offset; + + required_offset=global_block.block_graph_b_stack_top_offset+offset; + + element_h=&global_block.block_graph_b_stack; + while ((element_p=*element_h)!=NULL){ + int element_offset=element_p->b_stack_offset; + + if (element_offset==required_offset){ + element_p->b_stack_graph=graph; + return; + } + + if (element_offset>required_offset) + break; + + element_h=&element_p->b_stack_next; + } + + new_element=allocate_struct_from_heap ( b_stack); + new_element->b_stack_offset=required_offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=graph; + new_element->b_stack_load_graph=new_load_graph; + + new_element->b_stack_next=*element_h; + *element_h=new_element; +} + +void s_put_b (int offset,INSTRUCTION_GRAPH graph) +{ + s_put_b_l (offset,graph,NULL); +} + +void s_push_b (INSTRUCTION_GRAPH graph) +{ + --global_block.block_graph_b_stack_top_offset; + s_put_b (0,graph); +} + +INSTRUCTION_GRAPH s_pop_b (VOID) +{ + INSTRUCTION_GRAPH graph; + + graph=s_get_b (0); + ++global_block.block_graph_b_stack_top_offset; + + return graph; +} + +void s_remove_b (VOID) +{ + ++global_block.block_graph_b_stack_top_offset; +} + +void release_b_stack (VOID) +{ + register int n; + + global_block.block_graph_b_stack=NULL; + + for (n=0; nN_ADDRESS_PARAMETER_REGISTERS) + a_stack_size=N_ADDRESS_PARAMETER_REGISTERS; + + last_block->block_n_begin_a_parameter_registers=a_stack_size; + global_block.block_graph_a_stack_begin_displacement=-a_stack_size; + + for (n=0; nblock_n_begin_d_parameter_registers=number_of_data_register_parameters; + + global_block.block_graph_b_stack_begin_displacement=stack_displacement; +} + +#ifdef MORE_PARAMETER_REGISTERS +void init_ab_stack (int a_stack_size,int b_stack_size,ULONG vector[]) +{ + int offset,stack_displacement,n,all_parameters_in_registers; + int number_of_data_register_parameters,number_of_float_register_parameters; + int data_offsets[N_DATA_PARAMETER_REGISTERS+N_ADDRESS_PARAMETER_REGISTERS],float_offsets[N_FLOAT_PARAMETER_REGISTERS]; + int n_data_parameter_registers,n_extra_data_parameter_registers; + + init_a_stack (a_stack_size); + + n_data_parameter_registers=N_DATA_PARAMETER_REGISTERS; + n_extra_data_parameter_registers=N_ADDRESS_PARAMETER_REGISTERS-a_stack_size; + if (n_extra_data_parameter_registers<0) + n_extra_data_parameter_registers=0; + + global_block.block_graph_begin_b_stack_size=b_stack_size; + + number_of_data_register_parameters=0; + number_of_float_register_parameters=0; + + offset=0; + stack_displacement=0; + all_parameters_in_registers=1; + + for (offset=0; offset=0) + register_graph=g_register (num_to_d_reg (d_n)); + else + register_graph=g_register (num_to_a_reg (N_ADDRESS_PARAMETER_REGISTERS+d_n)); + s_put_b_l (data_offsets[n],register_graph,register_graph); + } + + for (n=0; nblock_n_begin_d_parameter_registers=number_of_data_register_parameters; + + global_block.block_graph_b_stack_begin_displacement=stack_displacement; +} +#endif + +void insert_graph_in_b_stack (INSTRUCTION_GRAPH graph,int b_stack_size,ULONG *vector) +{ + register int offset,required_offset; + register struct b_stack **element_p,*new_element; + INSTRUCTION_GRAPH *graph_p; + + required_offset=global_block.block_graph_b_stack_top_offset; + + element_p=&global_block.block_graph_b_stack; + while (*element_p!=NULL && (*element_p)->b_stack_offsetb_stack_next; + + for (offset=0; offsetb_stack_offset>required_offset+1) && mc68881_flag){ + INSTRUCTION_GRAPH f_graph,l_graph,h_graph; + + f_graph=g_fload + ((required_offset+global_block.block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); +#ifdef g_fhighlow + g_fhighlow (h_graph,l_graph,f_graph); +#else + h_graph=g_fhigh (f_graph); + l_graph=g_flow (f_graph); +#endif + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=required_offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=h_graph; + new_element->b_stack_load_graph=h_graph; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + + element_p=&new_element->b_stack_next; + ++offset; + ++required_offset; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=required_offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=l_graph; + new_element->b_stack_load_graph=l_graph; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + + element_p=&new_element->b_stack_next; + continue; + } else { + if (*element_p==NULL || (*element_p)->b_stack_offset!=required_offset){ + INSTRUCTION_GRAPH load_graph; + + load_graph=g_load + ((required_offset+global_block.block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=required_offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=load_graph; + new_element->b_stack_load_graph=load_graph; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + } + element_p=&(*element_p)->b_stack_next; + + ++offset; + ++required_offset; + } + } + + if (*element_p==NULL || (*element_p)->b_stack_offset!=required_offset){ + INSTRUCTION_GRAPH load_graph; + + load_graph=g_load + ((required_offset+global_block.block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=required_offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=load_graph; + new_element->b_stack_load_graph=load_graph; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + } + element_p=&(*element_p)->b_stack_next; + } + + required_offset=global_block.block_graph_b_stack_top_offset-1; + + element_p=&global_block.block_graph_b_stack; + while (*element_p!=NULL && (*element_p)->b_stack_offsetb_stack_graph=NULL; + element_p=&(*element_p)->b_stack_next; + } + + if (*element_p==NULL || (*element_p)->b_stack_offset!=required_offset){ + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=required_offset; + new_element->b_stack_flags=0; + new_element->b_stack_load_graph=NULL; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + } + + graph_p=&(*element_p)->b_stack_graph; + ++required_offset; + element_p=&(*element_p)->b_stack_next; + + for (offset=0; offsetb_stack_graph; + graph_p=&(*element_p)->b_stack_graph; + element_p=&(*element_p)->b_stack_next; + } + + *graph_p=graph; + + --global_block.block_graph_b_stack_top_offset; +} + +static int count_a_stack_size (struct a_stack *a_element,register int a_stack_top_offset) +{ + int a_stack_size,offset; + + a_stack_size=0; + + while (a_element!=NULL && a_element->a_stack_offseta_stack_next; + + offset=a_stack_top_offset; + + while (a_element!=NULL && a_element->a_stack_offset==offset + && !(a_element->a_stack_flags & ELEMENT_MAY_BE_REMOVED && a_element->a_stack_graph==NULL)) + { + ++a_stack_size; + a_element=a_element->a_stack_next; + ++offset; + } + + return a_stack_size; +} + +int get_a_stack_size (VOID) +{ + return count_a_stack_size (global_block.block_graph_a_stack,global_block.block_graph_a_stack_top_offset); +} + +static int count_b_stack_size (ULONG *vector_p[],struct b_stack *b_stack,int b_stack_top_offset) +{ + register struct b_stack *first_b_element,*b_element; + register int b_stack_size,offset,i; + ULONG *vector; + + b_stack_size=0; + first_b_element=b_stack; + + while (first_b_element!=NULL && first_b_element->b_stack_offsetb_stack_next; + + offset=b_stack_top_offset; + b_element=first_b_element; + + while (b_element!=NULL && b_element->b_stack_offset==offset + && !(b_element->b_stack_flags & ELEMENT_MAY_BE_REMOVED && b_element->b_stack_graph==NULL)) + { + ++b_stack_size; + b_element=b_element->b_stack_next; + ++offset; + } + + if (b_stack_size<=VECTOR_ELEMENT_SIZE) + vector=*vector_p; + else { + vector=(ULONG*)fast_memory_allocate + (((b_stack_size+VECTOR_ELEMENT_SIZE-1)*sizeof (ULONG))>>LOG_VECTOR_ELEMENT_SIZE); + *vector_p=vector; + } + + b_element=first_b_element; + + for (i=0; ib_stack_graph)->instruction_code==GFHIGH + && (next_graph=(next_b_element=b_element->b_stack_next)->b_stack_graph)!=NULL + && next_graph->instruction_code==GFLOW + && next_graph->instruction_parameters[0].p==graph->instruction_parameters[0].p) + { + set_bit (vector,i); + ++i; + set_bit (vector,i); + ++i; + b_element=next_b_element->b_stack_next; + } else { + clear_bit (vector,i); + ++i; + b_element=b_element->b_stack_next; + } + } + + return b_stack_size; +} + +static int count_b_stack_size_2 (ULONG *vector_p[],struct b_stack *b_stack,int b_stack_top_offset) +{ + register struct b_stack *first_b_element,*b_element; + register int b_stack_size,offset,i; + ULONG *vector; + + b_stack_size=0; + first_b_element=b_stack; + + while (first_b_element!=NULL && first_b_element->b_stack_offsetb_stack_next; + + offset=b_stack_top_offset; + b_element=first_b_element; + + while (b_element!=NULL && b_element->b_stack_offset==offset + && b_element->b_stack_graph!=NULL + && b_element->b_stack_flags & ELEMENT_USED_BEFORE_JSR + /*(b_element->b_stack_graph->node_mark==2 + || ((b_element->b_stack_graph->instruction_code==GFHIGH + || b_element->b_stack_graph->instruction_code==GFLOW) + && b_element->b_stack_graph->instruction_parameters[0].p->node_mark==2)) */ + && !((b_element->b_stack_flags & ELEMENT_MAY_BE_REMOVED) + && b_element->b_stack_graph==NULL)) + { + ++b_stack_size; + b_element=b_element->b_stack_next; + ++offset; + } + + if (b_stack_size<=VECTOR_ELEMENT_SIZE) + vector=*vector_p; + else { + vector=(ULONG*)fast_memory_allocate + (((b_stack_size+VECTOR_ELEMENT_SIZE-1)*sizeof (ULONG))>>LOG_VECTOR_ELEMENT_SIZE); + *vector_p=vector; + } + + b_element=first_b_element; + + for (i=0; ib_stack_graph)!=NULL + && graph->instruction_code==GFHIGH + && (next_graph=(next_b_element=b_element->b_stack_next)->b_stack_graph)!=NULL + && next_graph->instruction_code==GFLOW + && next_graph->instruction_parameters[0].p==graph->instruction_parameters[0].p) + { + set_bit (vector,i); + ++i; + set_bit (vector,i); + ++i; + b_element=next_b_element->b_stack_next; + } else { + clear_bit (vector,i); + ++i; + b_element=b_element->b_stack_next; + } + } + + return b_stack_size; +} + +int get_b_stack_size (ULONG *vector_p[]) +{ + return count_b_stack_size (vector_p,global_block.block_graph_b_stack,global_block.block_graph_b_stack_top_offset); +} + +static void a_stack_load_register_values (int n_parameters,int n_address_parameter_registers) +{ + register struct a_stack **element_p; + register int parameter_n; + + if (n_parameters>n_address_parameter_registers) + n_parameters=n_address_parameter_registers; + + element_p=&global_block.block_graph_a_stack; + for (parameter_n=0; parameter_na_stack_offseta_stack_next; + + if (*element_p!=NULL && (*element_p)->a_stack_offset==required_offset){ + struct a_stack *element; + + element=*element_p; + if (element->a_stack_flags & ELEMENT_MAY_BE_REMOVED && element->a_stack_graph==NULL){ + graph=g_load + ((-(1+required_offset+global_block.block_graph_a_stack_begin_displacement))<<2,A_STACK_POINTER); + element->a_stack_graph=graph; + element->a_stack_load_graph=graph; + } + element_p=&(*element_p)->a_stack_next; + } else { + graph=g_load + ((-(1+required_offset+global_block.block_graph_a_stack_begin_displacement))<<2,A_STACK_POINTER); + + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=required_offset; + new_element->a_stack_flags=0; + new_element->a_stack_graph=graph; + new_element->a_stack_load_graph=graph; + + new_element->a_stack_next=*element_p; + *element_p=new_element; + element_p=&new_element->a_stack_next; + } + } +} + +static void a_stack_stores (int n_parameters,int n_address_parameter_registers) +{ + register struct a_stack *a_element; + + end_a_registers=0; + + if (n_parameters>n_address_parameter_registers) + n_parameters=n_address_parameter_registers; + + global_block.block_graph_a_stack_end_displacement=n_parameters; + + for_l (a_element,global_block.block_graph_a_stack,a_stack_next) + if (a_element->a_stack_graph!=NULL){ + if (a_element->a_stack_offseta_stack_graph=NULL; + else { + if (a_element->a_stack_offset-global_block.block_graph_a_stack_top_offseta_stack_offset-global_block.block_graph_a_stack_top_offset); + + a_element->a_stack_graph= + g_store_r (num_to_a_reg (register_number),a_element->a_stack_graph); + + end_a_registers |= ((unsigned)1<a_stack_graph==a_element->a_stack_load_graph + && a_element->a_stack_load_graph->instruction_code!=GREGISTER + ) + a_element->a_stack_graph=NULL; + else { + INSTRUCTION_GRAPH l_graph; + + l_graph=a_element->a_stack_graph; + + while (l_graph->instruction_code==GFILL) + l_graph=l_graph->instruction_parameters[0].p; + + if (l_graph!=a_element->a_stack_load_graph + || a_element->a_stack_load_graph->instruction_code==GREGISTER + ) + a_element->a_stack_graph=g_store ( + (-(1+a_element->a_stack_offset+global_block.block_graph_a_stack_begin_displacement))<<2, + A_STACK_POINTER,a_element->a_stack_graph, + a_element->a_stack_load_graph + ); + } + } + } + } +} + +static int set_basic_block_begin_a_registers + (struct a_stack **element_p,int n_a_registers,INSTRUCTION_GRAPH a_register_parameter_node[]) +{ + int offset; + + while (*element_p!=NULL && (*element_p)->a_stack_offset<0) + element_p=&(*element_p)->a_stack_next; + + for (offset=0; offseta_stack_offset==offset){ + struct a_stack *element; + + element=*element_p; + + if (element->a_stack_flags & ELEMENT_MAY_BE_REMOVED && element->a_stack_graph==NULL){ + graph=g_new_node (GREGISTER,0,sizeof (union instruction_parameter)); + graph->instruction_parameters[0].i=num_to_a_reg (n_a_registers-1-offset); + + a_register_parameter_node[n_a_registers-1-offset]=graph; + + element->a_stack_graph=graph; + element->a_stack_load_graph=graph; + } else { + graph=element->a_stack_load_graph; + if (graph!=NULL){ + graph->instruction_code=GREGISTER; + graph->inode_arity=0; + graph->instruction_parameters[0].i=num_to_a_reg (n_a_registers-1-offset); + + a_register_parameter_node[n_a_registers-1-offset]=graph; + } else + a_register_parameter_node[n_a_registers-1-offset]=NULL; + } + + element_p=&(*element_p)->a_stack_next; + } else { + struct a_stack *new_element; + + graph=g_new_node (GREGISTER,0,sizeof (union instruction_parameter)); + graph->instruction_parameters[0].i=num_to_a_reg (n_a_registers-1-offset); + + a_register_parameter_node[n_a_registers-1-offset]=graph; + + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=offset; + new_element->a_stack_flags=0; + new_element->a_stack_graph=graph; + new_element->a_stack_load_graph=graph; + + new_element->a_stack_next=*element_p; + *element_p=new_element; + element_p=&new_element->a_stack_next; + } + } + + return -n_a_registers; +} + +static void compute_a_load_offsets (register struct a_stack *a_element,int offset) +{ + for (; a_element!=NULL; a_element=a_element->a_stack_next){ + register INSTRUCTION_GRAPH load_graph; + + load_graph=a_element->a_stack_load_graph; + if (load_graph!=NULL) + switch (load_graph->instruction_code){ + case GLOAD: + load_graph->instruction_parameters[0].i= -((1+a_element->a_stack_offset)<<2)-offset; + break; + case GREGISTER: + break; + default: + internal_error_in_function ("compute_a_load_offsets"); + } + } +} + +static void b_stack_load_register_values (int n_parameters,ULONG vector[],int n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + ,int n_extra_data_parameter_registers +#endif + ) +{ + register struct b_stack **element_p; + register int parameter_n; + int number_of_d_register_parameters,number_of_f_register_parameters_m_2; + +#ifdef MORE_PARAMETER_REGISTERS + if (n_extra_data_parameter_registers<0) + n_extra_data_parameter_registers=0; +#endif + + number_of_d_register_parameters=0; + number_of_f_register_parameters_m_2=0; + + element_p=&global_block.block_graph_b_stack; + for (parameter_n=0; parameter_nb_stack_offsetb_stack_next; + + if (!test_bit (vector,parameter_n) + ? number_of_d_register_parameters++ < n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + + n_extra_data_parameter_registers +#endif + : (mc68881_flag && number_of_f_register_parameters_m_2++<(N_FLOAT_PARAMETER_REGISTERS<<1))) + { + if (*element_p!=NULL && (*element_p)->b_stack_offset==required_offset){ + register struct b_stack *element; + + element=*element_p; + if (element->b_stack_flags & ELEMENT_MAY_BE_REMOVED && element->b_stack_graph==NULL){ + graph=g_load ((required_offset+global_block.block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + element->b_stack_graph=graph; + element->b_stack_load_graph=graph; + } + element_p=&(*element_p)->b_stack_next; + } else{ + graph=g_load ((required_offset+global_block.block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=required_offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=graph; + new_element->b_stack_load_graph=graph; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + element_p=&new_element->b_stack_next; + } + } + } +} + +static void b_stack_stores (int n_parameters,ULONG vector[],int n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + ,int n_extra_data_parameter_registers, + INSTRUCTION_GRAPH a_register_parameter_nodes[],INSTRUCTION_GRAPH d_register_parameter_nodes[] +#endif + ) +{ + struct b_stack *b_element; + int n,displacement,parameter_n; + int number_of_d_register_parameters,number_of_f_register_parameters; +#ifdef MORE_PARAMETER_REGISTERS + INSTRUCTION_GRAPH *d_graphs_p[N_DATA_PARAMETER_REGISTERS+N_ADDRESS_PARAMETER_REGISTERS], + d_graphs[N_DATA_PARAMETER_REGISTERS+N_ADDRESS_PARAMETER_REGISTERS]; +#else + INSTRUCTION_GRAPH *d_graphs_p[N_DATA_PARAMETER_REGISTERS],d_graphs[N_DATA_PARAMETER_REGISTERS]; +#endif + INSTRUCTION_GRAPH *f_graphs_p[N_FLOAT_PARAMETER_REGISTERS],f_graphs[N_FLOAT_PARAMETER_REGISTERS<<1]; + +#ifdef MORE_PARAMETER_REGISTERS + if (n_extra_data_parameter_registers<0) + n_extra_data_parameter_registers=0; +#endif + + end_d_registers=0; + end_f_registers=0; + + number_of_d_register_parameters=0; + number_of_f_register_parameters=0; + + for_l (b_element,global_block.block_graph_b_stack,b_stack_next){ + INSTRUCTION_GRAPH graph; + + if (b_element->b_stack_offsetb_stack_graph=NULL; + continue; + } + + graph=b_element->b_stack_graph; + + parameter_n=b_element->b_stack_offset-global_block.block_graph_b_stack_top_offset; + if ((unsigned)parameter_n<(unsigned)n_parameters) + if (test_bit (vector,parameter_n)){ + if (number_of_f_register_parametersb_stack_next; + + if (graph==NULL || next_b_element==NULL || next_b_element->b_stack_graph==NULL) + internal_error_in_function ("b_stack_stores"); + + f_graphs[number_of_f_register_parameters]=g_fjoin (graph,next_b_element->b_stack_graph); + f_graphs_p[number_of_f_register_parameters]=&b_element->b_stack_graph; + + next_b_element->b_stack_graph=NULL; + ++number_of_f_register_parameters; + + b_element=next_b_element; + + continue; + } + } else { + if (number_of_d_register_parametersb_stack_graph; + ++number_of_d_register_parameters; + + continue; + } + } + + if (graph!=NULL){ + struct b_stack *next_b_element; + INSTRUCTION_GRAPH next_graph; + + if (graph->instruction_code==GFHIGH + && (next_b_element=b_element->b_stack_next)!=NULL + && (next_graph=next_b_element->b_stack_graph)!=NULL + && next_graph->instruction_code==GFLOW + && next_b_element->b_stack_offset==b_element->b_stack_offset+1 + && next_graph->instruction_parameters[0].p==graph->instruction_parameters[0].p + ){ + if (graph==b_element->b_stack_load_graph && + next_graph==next_b_element->b_stack_load_graph && + graph->instruction_parameters[0].p->instruction_code!=GFREGISTER) + { + b_element->b_stack_graph=NULL; + next_b_element->b_stack_graph=NULL; + } else { + b_element->b_stack_graph=g_fstore ( + (b_element->b_stack_offset+global_block.block_graph_b_stack_begin_displacement)<<2, + B_STACK_POINTER,graph->instruction_parameters[0].p, + b_element->b_stack_load_graph,next_b_element->b_stack_load_graph + ); + next_b_element->b_stack_graph=NULL; + } + b_element=next_b_element; + continue; + } + + if (graph==b_element->b_stack_load_graph && graph->instruction_code!=GREGISTER) + b_element->b_stack_graph=NULL; + else + b_element->b_stack_graph=g_store ( + (b_element->b_stack_offset+global_block.block_graph_b_stack_begin_displacement)<<2, + B_STACK_POINTER,graph,b_element->b_stack_load_graph + ); + } + } + +#ifdef MORE_PARAMETER_REGISTERS + n_extra_data_parameter_registers=number_of_d_register_parameters-n_data_parameter_registers; + if (n_extra_data_parameter_registers<0) + n_extra_data_parameter_registers=0; +#endif + + for (n=0; n=0){ + end_d_registers |= ((unsigned)1<instruction_parameters[0].i=num_to_d_reg (extra_d_reg_n); + d_register_parameter_nodes[extra_d_reg_n]=register_node; + a_register_parameter_nodes[N_ADDRESS_PARAMETER_REGISTERS+d_reg_n]=NULL; + global_block.block_graph_d_register_parameter_node[extra_d_reg_n]=register_node; + global_block.block_graph_a_register_parameter_node[N_ADDRESS_PARAMETER_REGISTERS+d_reg_n]=NULL; + } +# else + end_a_registers |= ((unsigned)1<b_stack_offsetb_stack_next; + + if (*element_p!=NULL && (*element_p)->b_stack_offset==offset){ + register struct b_stack *element; + + element=*element_p; + + if (element->b_stack_flags & ELEMENT_MAY_BE_REMOVED && element->b_stack_graph==NULL){ + graph=g_new_node (GREGISTER,0,sizeof (union instruction_parameter)); +#ifdef MORE_PARAMETER_REGISTERS + { + int d_reg_n; + + d_reg_n=n_d_registers - n_extra_data_parameter_registers; + + if (d_reg_n>=0){ + graph->instruction_parameters[0].i=num_to_d_reg (d_reg_n); + d_register_parameter_node [d_reg_n]=graph; + } else { + graph->instruction_parameters[0].i=num_to_a_reg (N_ADDRESS_PARAMETER_REGISTERS+d_reg_n); + a_register_parameter_node [N_ADDRESS_PARAMETER_REGISTERS+d_reg_n]=graph; + } + } +#else + graph->instruction_parameters[0].i=num_to_d_reg (n_d_registers); + d_register_parameter_node [n_d_registers]=graph; +#endif + element->b_stack_graph=NULL; + element->b_stack_load_graph=NULL; + } else { + graph=element->b_stack_load_graph; + if (graph!=NULL){ + if (graph->instruction_code==GFHIGH && + graph->instruction_parameters[0].p->instruction_code==GFLOAD) + { + struct b_stack *next_element; + INSTRUCTION_GRAPH fload_graph,low_graph; + + fload_graph=graph->instruction_parameters[0].p; + + next_element=element->b_stack_next; + if (next_element==NULL || next_element->b_stack_offset!=offset+1) + internal_error_in_function ("compute_b_load_offsets"); + + low_graph=next_element->b_stack_load_graph; + if (low_graph==NULL || low_graph->instruction_code!=GFLOW + || low_graph->instruction_parameters[0].p!=fload_graph) + internal_error_in_function ("compute_b_load_offsets"); + + /* added 25-10-2001 */ + low_graph->instruction_code=GLOAD; + low_graph->instruction_parameters[0].i=fload_graph->instruction_parameters[0].i+4; + low_graph->instruction_parameters[1].i=fload_graph->instruction_parameters[1].i; + /* */ + + fload_graph->instruction_code=GFJOIN; + fload_graph->instruction_parameters[0].p=graph; + fload_graph->instruction_parameters[1].p=low_graph; + } + + graph->instruction_code=GREGISTER; + graph->inode_arity=0; +#ifdef MORE_PARAMETER_REGISTERS + { + int d_reg_n; + + d_reg_n=n_d_registers - n_extra_data_parameter_registers; + + if (d_reg_n>=0){ + graph->instruction_parameters[0].i=num_to_d_reg (d_reg_n); + d_register_parameter_node[d_reg_n]=graph; + } else { + graph->instruction_parameters[0].i=num_to_a_reg (N_ADDRESS_PARAMETER_REGISTERS+d_reg_n); + a_register_parameter_node[N_ADDRESS_PARAMETER_REGISTERS+d_reg_n]=graph; + } + } +#else + graph->instruction_parameters[0].i=num_to_d_reg (n_d_registers); + d_register_parameter_node[n_d_registers]=graph; +#endif + } else +#ifdef MORE_PARAMETER_REGISTERS + { + int d_reg_n; + + d_reg_n=n_d_registers - n_extra_data_parameter_registers; + + if (d_reg_n>=0) + d_register_parameter_node[d_reg_n]=NULL; + else + a_register_parameter_node[N_ADDRESS_PARAMETER_REGISTERS+d_reg_n]=NULL; + } +#else + d_register_parameter_node[n_d_registers]=NULL; +#endif + } + + element_p=&(*element_p)->b_stack_next; + } else { + register struct b_stack *new_element; + + graph=g_new_node (GREGISTER,0,sizeof (union instruction_parameter)); +#ifdef MORE_PARAMETER_REGISTERS + { + int d_reg_n; + + d_reg_n=n_d_registers - n_extra_data_parameter_registers; + + if (d_reg_n>=0){ + graph->instruction_parameters[0].i=num_to_d_reg (d_reg_n); + d_register_parameter_node[d_reg_n]=graph; + } else { + graph->instruction_parameters[0].i=num_to_a_reg (N_ADDRESS_PARAMETER_REGISTERS+d_reg_n); + a_register_parameter_node[N_ADDRESS_PARAMETER_REGISTERS+d_reg_n]=graph; + } + } +#else + graph->instruction_parameters[0].i=num_to_d_reg (n_d_registers); + d_register_parameter_node[n_d_registers]=graph; +#endif + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=graph; + new_element->b_stack_load_graph=graph; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + element_p=&new_element->b_stack_next; + } + } + } else { + if (n_f_registers<=0) + all_parameters_in_registers=0; + else { + INSTRUCTION_GRAPH r_graph; + int f_register_not_used_flag; + register struct b_stack *element; + + --n_f_registers; + + if (all_parameters_in_registers) + --stack_displacement; + + while (*element_p!=NULL && (*element_p)->b_stack_offsetb_stack_next; + + r_graph=NULL; + + if ((element=*element_p)!=NULL){ + if (element->b_stack_offset==offset){ + if ((graph=element->b_stack_load_graph)!=NULL && + graph->instruction_code==GFHIGH) + { + r_graph=graph->instruction_parameters[0].p; + r_graph->instruction_code=GFREGISTER; + r_graph->inode_arity=0; + r_graph->instruction_parameters[0].i=n_f_registers; + } + element=element->b_stack_next; + } + if (element!=NULL && element->b_stack_offset==offset+1 && + (graph=element->b_stack_load_graph)!=NULL && + graph->instruction_code==GFLOW) + { + r_graph=graph->instruction_parameters[0].p; + r_graph->instruction_code=GFREGISTER; + r_graph->inode_arity=0; + r_graph->instruction_parameters[0].i=n_f_registers; + } + } + + if (r_graph==NULL){ + r_graph=g_new_node (GFREGISTER,0,sizeof (union instruction_parameter)); + r_graph->instruction_parameters[0].i=n_f_registers; + } + + f_register_not_used_flag=0; + + if ((element=*element_p)!=NULL && element->b_stack_offset==offset){ + if (element->b_stack_flags & ELEMENT_MAY_BE_REMOVED && element->b_stack_graph==NULL){ +#ifdef g_fhighlow + graph=g_new_node (GFHIGH,0,2*sizeof (union instruction_parameter)); + graph->instruction_parameters[1].p=NULL; +#else + graph=g_new_node (GFHIGH,0,sizeof (union instruction_parameter)); +#endif + graph->instruction_parameters[0].p=r_graph; + + element->b_stack_graph=NULL; + element->b_stack_load_graph=NULL; + } else { + graph=element->b_stack_load_graph; + if (graph!=NULL){ + graph->instruction_code=GFHIGH; + graph->inode_arity=0; + graph->instruction_parameters[0].p=r_graph; +#ifdef g_fhighlow + graph->instruction_parameters[1].p=NULL; +#endif + } else + ++f_register_not_used_flag; + } + + element_p=&(*element_p)->b_stack_next; + } else { + register struct b_stack *new_element; + +#ifdef g_fhighlow + graph=g_new_node (GFHIGH,0,2*sizeof (union instruction_parameter)); + graph->instruction_parameters[1].p=NULL; +#else + graph=g_new_node (GFHIGH,0,sizeof (union instruction_parameter)); +#endif + graph->instruction_parameters[0].p=r_graph; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=graph; + new_element->b_stack_load_graph=graph; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + element_p=&new_element->b_stack_next; + } + + ++offset; + + if (all_parameters_in_registers) + --stack_displacement; + + if (*element_p!=NULL && (*element_p)->b_stack_offset==offset){ + register struct b_stack *element; + + element=*element_p; + if (element->b_stack_flags & ELEMENT_MAY_BE_REMOVED && element->b_stack_graph==NULL){ +#ifdef g_fhighlow + graph=g_new_node (GFLOW,0,2*sizeof (union instruction_parameter)); + graph->instruction_parameters[1].p=NULL; +#else + graph=g_new_node (GFLOW,0,sizeof (union instruction_parameter)); +#endif + graph->instruction_parameters[0].p=r_graph; + + element->b_stack_graph=NULL; + element->b_stack_load_graph=NULL; + } else { + graph=element->b_stack_load_graph; + if (graph!=NULL){ + graph->instruction_code=GFLOW; + graph->inode_arity=0; + graph->instruction_parameters[0].p=r_graph; +#ifdef g_fhighlow + graph->instruction_parameters[1].p=NULL; +#endif + } else + ++f_register_not_used_flag; + } + + element_p=&(*element_p)->b_stack_next; + } else { + register struct b_stack *new_element; + +#ifdef g_fhighlow + graph=g_new_node (GFLOW,0,2*sizeof (union instruction_parameter)); + graph->instruction_parameters[1].p=NULL; +#else + graph=g_new_node (GFLOW,0,sizeof (union instruction_parameter)); +#endif + graph->instruction_parameters[0].p=r_graph; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=graph; + new_element->b_stack_load_graph=graph; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + element_p=&new_element->b_stack_next; + } + + f_register_parameter_node[n_f_registers]= + f_register_not_used_flag!=2 ? r_graph : NULL; + } + } + } + + return stack_displacement; +} + +static void compute_b_load_offsets (register struct b_stack *b_element,int offset) +{ + for (; b_element!=NULL; b_element=b_element->b_stack_next){ + register INSTRUCTION_GRAPH load_graph; + + load_graph=b_element->b_stack_load_graph; + + if (load_graph!=NULL) + switch (load_graph->instruction_code){ + case GLOAD: + load_graph->instruction_parameters[0].i= + (b_element->b_stack_offset<<2)+offset; + break; + case GREGISTER: + case GFREGISTER: + break; + case GFHIGH: + { + INSTRUCTION_GRAPH graph_1; + + graph_1=load_graph->instruction_parameters[0].p; + if (graph_1->instruction_code==GFLOAD) + graph_1->instruction_parameters[0].i = (b_element->b_stack_offset<<2)+offset; + else if (graph_1->instruction_code!=GFREGISTER) + internal_error_in_function ("compute_b_load_offsets"); + + break; + } + case GFLOW: + { + INSTRUCTION_GRAPH graph_1; + + graph_1=load_graph->instruction_parameters[0].p; + if (graph_1->instruction_code==GFLOAD) + graph_1->instruction_parameters[0].i = ((b_element->b_stack_offset-1)<<2)+offset; + else if (graph_1->instruction_code!=GFREGISTER) + internal_error_in_function ("compute_b_load_offsets"); + + break; + } + default: + internal_error_in_function ("compute_b_load_offsets"); + } + } +} + +static void remove_stack_element (struct stack **element_p) +{ + struct stack *element; + + element=(*element_p)->stack_next; + *element_p=element; + + while (element!=NULL){ + --element->stack_offset; + element=element->stack_next; + } +} + +static void remove_end_stack_element + (struct stack **element_p,int remove_offset,int stack_begin_displacement,int stack_top_offset,int b_stack_flag) +{ + struct stack *element; + INSTRUCTION_GRAPH graph_1; + int offset,flags_1,begin_offset; + + element=*element_p; + + graph_1=NULL; + flags_1=0; + + begin_offset= stack_top_offset<=0 ? stack_top_offset : 0; + + while (element!=NULL && element->stack_offsetstack_next; + element=*element_p; + } + + for (offset=begin_offset; offsetstack_offset!=offset){ + struct stack *new_element; + INSTRUCTION_GRAPH graph; + + if (!b_stack_flag) + graph=g_load (-(offset+stack_begin_displacement+1)<<2,A_STACK_POINTER); + else + graph=g_load ((offset+stack_begin_displacement)<<2,B_STACK_POINTER); + + graph->node_mark=offsetstack_offset=offset; + new_element->stack_flags=0; + new_element->stack_graph=graph; + new_element->stack_load_graph=graph; + + new_element->stack_next=element; + *element_p=new_element; + element=new_element; + } + + graph_2=graph_1; + flags_2=flags_1; + + graph_1=element->stack_graph; + flags_1=element->stack_flags; + + element->stack_graph=graph_2; + element->stack_flags= (element->stack_flags & ~ELEMENT_USED_BEFORE_JSR) | (flags_2 & ELEMENT_USED_BEFORE_JSR); + + element_p=&element->stack_next; + element=*element_p; + } + + element->stack_graph=graph_1; + element->stack_flags= (element->stack_flags & ~ELEMENT_USED_BEFORE_JSR) | (flags_1 & ELEMENT_USED_BEFORE_JSR); +} + +static void remove_begin_stack_element + (struct stack **element_p,int remove_offset,int stack_begin_displacement, + int stack_top_offset,int b_stack_flag) +{ + struct stack *element,*previous_element; + int offset,begin_offset; + + begin_offset= stack_top_offset<=0 ? stack_top_offset : 0; + + previous_element=NULL; + element=*element_p; + + while (element!=NULL && element->stack_offsetstack_next; + element=*element_p; + } + + for (offset=begin_offset; offset<=remove_offset; ++offset){ + if (element==NULL || element->stack_offset!=offset){ + struct stack *new_element; + INSTRUCTION_GRAPH graph; + + if (!b_stack_flag) + graph=g_load (-(offset+stack_begin_displacement+1)<<2,A_STACK_POINTER); + else + graph=g_load ((offset+stack_begin_displacement)<<2,B_STACK_POINTER); + + graph->node_mark= offsetstack_offset=offset; + new_element->stack_flags=0; + new_element->stack_load_graph=graph; + new_element->stack_graph=graph; + + new_element->stack_next=element; + *element_p=new_element; + element=new_element; + } + + if (previous_element==NULL || previous_element->stack_offset!=offset-1){ + struct stack *new_element; + + new_element=allocate_struct_from_heap (stack); + new_element->stack_offset=offset-1; + new_element->stack_flags=0; + new_element->stack_load_graph=NULL; + new_element->stack_graph=NULL; + + new_element->stack_next=element; + *element_p=new_element; + element_p=&new_element->stack_next; + previous_element=new_element; + } + + previous_element->stack_graph=element->stack_graph; + previous_element->stack_flags= (previous_element->stack_flags & ~ELEMENT_USED_BEFORE_JSR) + | (element->stack_flags & ELEMENT_USED_BEFORE_JSR); + + element->stack_graph=NULL; + element->stack_flags &= ~ELEMENT_USED_BEFORE_JSR; + + if (offsetstack_next; + element=*element_p; + } + } + + if (element!=NULL) + *element_p=element->stack_next; + + for (element=*element_p; element!=NULL; element=element->stack_next) + --element->stack_offset; +} + +#define INSERT_LOAD_GRAPHS + +#ifdef INSERT_LOAD_GRAPHS + static struct stack ** insert_load_graphs + (struct stack **element_p,int remove_offset,int stack_begin_displacement,int stack_top_offset,int b_stack_flag) + { + struct stack *element; + int offset,begin_offset; + + begin_offset= stack_top_offset<=0 ? stack_top_offset : 0; + + element=*element_p; + + while (element!=NULL && element->stack_offsetstack_next; + element=*element_p; + } + + for (offset=begin_offset; offsetstack_offset!=offset){ + struct stack *new_element; + INSTRUCTION_GRAPH graph; + + if (!b_stack_flag) + graph=g_load (-(offset+stack_begin_displacement+1)<<2,A_STACK_POINTER); + else + graph=g_load ((offset+stack_begin_displacement)<<2,B_STACK_POINTER); + + graph->node_mark= offsetstack_offset=offset; + new_element->stack_flags=0; + new_element->stack_load_graph=graph; + new_element->stack_graph=graph; + + new_element->stack_next=element; + *element_p=new_element; + element=new_element; + } + + element_p=&element->stack_next; + element=*element_p; + } + + return element_p; + } +#endif + +static void remove_not_used_a_stack_elements (struct block_graph *block_graph,struct block_graph *next_block_graph) +{ + struct a_stack *a_element_1,**a_element_1_p; + struct a_stack *a_element_2,**a_element_2_p; + int stack_offset_1_min_2,first_non_parameter_offset,offset; + +#ifdef DEBUG + printf ("%d %d %d %d\n",block_graph->block_graph_a_stack_top_offset, + block_graph->block_graph_end_a_stack_size, + -next_block_graph->block_graph_begin_a_stack_size, + block_graph->block_graph_used_a_stack_elements); +#endif + + a_element_1_p=&block_graph->block_graph_a_stack; + a_element_1=*a_element_1_p; + + while (a_element_1!=NULL && a_element_1->a_stack_offsetblock_graph_a_stack_top_offset){ + if (a_element_1->a_stack_flags & (ELEMENT_MUST_BE_REMOVED | BEGIN_ELEMENT_MUST_BE_REMOVED)){ + if (a_element_1->a_stack_flags & ELEMENT_MUST_BE_REMOVED) + internal_error_in_function ("remove_not_used_a_stack_elements"); + + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_a_stack, + a_element_1->a_stack_offset,block_graph->block_graph_a_stack_begin_displacement, + block_graph->block_graph_a_stack_top_offset,0); + a_element_1=*a_element_1_p; + + --block_graph->block_graph_a_stack_top_offset; + } else { + a_element_1_p=&a_element_1->a_stack_next; + a_element_1=*a_element_1_p; + } + } + + offset=block_graph->block_graph_a_stack_top_offset; + first_non_parameter_offset= block_graph->block_graph_used_a_stack_elements + +block_graph->block_graph_a_stack_top_offset; + + while (offseta_stack_offset==offset){ + if (a_element_1->a_stack_flags & (ELEMENT_MUST_BE_REMOVED | BEGIN_ELEMENT_MUST_BE_REMOVED)){ + if (a_element_1->a_stack_flags & ELEMENT_MUST_BE_REMOVED) + internal_error_in_function ("remove_not_used_a_stack_elements"); + + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_a_stack, + offset,block_graph->block_graph_a_stack_begin_displacement, + block_graph->block_graph_a_stack_top_offset,0); + a_element_1=*a_element_1_p; + + --block_graph->block_graph_a_stack_top_offset; + --first_non_parameter_offset; + } else { + a_element_1_p=&a_element_1->a_stack_next; + a_element_1=*a_element_1_p; + ++offset; + } + } + + stack_offset_1_min_2= block_graph->block_graph_a_stack_top_offset + +block_graph->block_graph_end_a_stack_size + -next_block_graph->block_graph_begin_a_stack_size; + + a_element_2_p=&next_block_graph->block_graph_a_stack; + a_element_2=*a_element_2_p; + + if (offset>=first_non_parameter_offset) + while (a_element_1!=NULL && a_element_1->a_stack_offset==offset){ + int offset_2; + + offset_2=offset-stack_offset_1_min_2; + + while (a_element_2!=NULL && a_element_2->a_stack_offseta_stack_next; + a_element_2=*a_element_2_p; + } + + if (a_element_1->a_stack_flags & ELEMENT_MUST_BE_REMOVED + || (a_element_1->a_stack_flags & BEGIN_ELEMENT_MUST_BE_REMOVED && + ( (a_element_2!=NULL && a_element_2->a_stack_offset==offset_2) + ? (a_element_2->a_stack_load_graph==NULL || !a_element_2->a_stack_load_graph->node_mark) + : offset_2block_graph_a_stack_top_offset ))) + { + remove_stack_element ((struct stack **)a_element_1_p); + a_element_1=*a_element_1_p; + --stack_offset_1_min_2; + + if (a_element_2!=NULL && a_element_2->a_stack_offset==offset_2){ + if (a_element_2->a_stack_flags & ELEMENT_MAY_BE_REMOVED) + a_element_2->a_stack_flags |= ELEMENT_MUST_BE_REMOVED; + else { + a_element_2->a_stack_flags |= BEGIN_ELEMENT_MUST_BE_REMOVED; +#ifdef INSERT_LOAD_GRAPHS + a_element_2_p=(struct a_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_a_stack,offset_2, + next_block_graph->block_graph_a_stack_begin_displacement, + next_block_graph->block_graph_a_stack_top_offset,0); +#endif + } + } else { + struct a_stack *new_element; + + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=offset_2; + new_element->a_stack_flags=BEGIN_ELEMENT_MUST_BE_REMOVED; + new_element->a_stack_graph=NULL; + new_element->a_stack_load_graph=NULL; + + new_element->a_stack_next=a_element_2; + *a_element_2_p=new_element; + a_element_2=new_element; +#ifdef INSERT_LOAD_GRAPHS + a_element_2_p=(struct a_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_a_stack,offset_2, + next_block_graph->block_graph_a_stack_begin_displacement, + next_block_graph->block_graph_a_stack_top_offset,0); +#endif + } + } else if (a_element_1->a_stack_flags & BEGIN_ELEMENT_MUST_BE_REMOVED){ + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_a_stack, + offset,block_graph->block_graph_a_stack_begin_displacement, + block_graph->block_graph_a_stack_top_offset,0); + a_element_1=*a_element_1_p; + + --block_graph->block_graph_a_stack_top_offset; + --stack_offset_1_min_2; + } else { + if ( (a_element_2!=NULL && a_element_2->a_stack_offset==offset_2) + ? (a_element_2->a_stack_load_graph==NULL || !a_element_2->a_stack_load_graph->node_mark) + : offset_2block_graph_a_stack_top_offset ) + { + remove_end_stack_element + ((struct stack **)&block_graph->block_graph_a_stack,offset, + block_graph->block_graph_a_stack_begin_displacement, + block_graph->block_graph_a_stack_top_offset,0); + a_element_1=*a_element_1_p; + + ++block_graph->block_graph_a_stack_top_offset; + + if (a_element_2!=NULL && a_element_2->a_stack_offset==offset_2){ + if (a_element_2->a_stack_flags & ELEMENT_MAY_BE_REMOVED) + a_element_2->a_stack_flags |= ELEMENT_MUST_BE_REMOVED; + else { + a_element_2->a_stack_flags |= BEGIN_ELEMENT_MUST_BE_REMOVED; +#ifdef INSERT_LOAD_GRAPHS + a_element_2_p=(struct a_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_a_stack,offset_2, + next_block_graph->block_graph_a_stack_begin_displacement, + next_block_graph->block_graph_a_stack_top_offset,0); +#endif + } + } else { + struct a_stack *new_element; + + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=offset_2; + new_element->a_stack_flags=BEGIN_ELEMENT_MUST_BE_REMOVED; + new_element->a_stack_graph=NULL; + new_element->a_stack_load_graph=NULL; + + new_element->a_stack_next=a_element_2; + *a_element_2_p=new_element; + a_element_2=new_element; +#ifdef INSERT_LOAD_GRAPHS + a_element_2_p=(struct a_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_a_stack,offset_2, + next_block_graph->block_graph_a_stack_begin_displacement, + next_block_graph->block_graph_a_stack_top_offset,0); +#endif + } + } + + ++offset; + a_element_1_p=&a_element_1->a_stack_next; + a_element_1=*a_element_1_p; + } + } + + while (a_element_1!=NULL){ + if (a_element_1->a_stack_flags & ELEMENT_MUST_BE_REMOVED){ + int offset_2; + + offset=a_element_1->a_stack_offset; + offset_2=offset-stack_offset_1_min_2; + + while (a_element_2!=NULL && a_element_2->a_stack_offseta_stack_next; + a_element_2=*a_element_2_p; + } + + remove_stack_element ((struct stack **)a_element_1_p); + a_element_1=*a_element_1_p; + + --stack_offset_1_min_2; + + if (a_element_2!=NULL && a_element_2->a_stack_offset==offset_2){ + if (a_element_2->a_stack_flags & ELEMENT_MAY_BE_REMOVED) + a_element_2->a_stack_flags |= ELEMENT_MUST_BE_REMOVED; + else { + a_element_2->a_stack_flags |= BEGIN_ELEMENT_MUST_BE_REMOVED; +#ifdef INSERT_LOAD_GRAPHS + a_element_2_p=(struct a_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_a_stack,offset_2, + next_block_graph->block_graph_a_stack_begin_displacement, + next_block_graph->block_graph_a_stack_top_offset,0); +#endif + } + } else { + struct a_stack *new_element; + + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=offset_2; + new_element->a_stack_flags=BEGIN_ELEMENT_MUST_BE_REMOVED; + new_element->a_stack_graph=NULL; + new_element->a_stack_load_graph=NULL; + + new_element->a_stack_next=a_element_2; + *a_element_2_p=new_element; + a_element_2=new_element; +#ifdef INSERT_LOAD_GRAPHS + a_element_2_p=(struct a_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_a_stack,offset_2, + next_block_graph->block_graph_a_stack_begin_displacement, + next_block_graph->block_graph_a_stack_top_offset,0); +#endif + } + } else if (a_element_1->a_stack_flags & BEGIN_ELEMENT_MUST_BE_REMOVED){ + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_a_stack, + a_element_1->a_stack_offset,block_graph->block_graph_a_stack_begin_displacement, + block_graph->block_graph_a_stack_top_offset,0); + a_element_1=*a_element_1_p; + + --block_graph->block_graph_a_stack_top_offset; + --stack_offset_1_min_2; + } else { + a_element_1_p=&a_element_1->a_stack_next; + a_element_1=*a_element_1_p; + } + } +} +#undef DEBUG + +static void remove_not_used_b_stack_elements (struct block_graph *block_graph,struct block_graph *next_block_graph) +{ + struct b_stack *b_element_1,**b_element_1_p; + struct b_stack *b_element_2,**b_element_2_p; + int stack_offset_1_min_2,first_non_parameter_offset_1,offset_1; + +#ifdef DEBUG + printf ("%d %d %d %d\n",block_graph->block_graph_b_stack_top_offset, + block_graph->block_graph_end_b_stack_size, + -next_block_graph->block_graph_begin_b_stack_size, + block_graph->block_graph_used_b_stack_elements); +#endif + + b_element_1_p=&block_graph->block_graph_b_stack; + b_element_1=*b_element_1_p; + + while (b_element_1!=NULL && b_element_1->b_stack_offsetblock_graph_b_stack_top_offset){ + if (b_element_1->b_stack_flags & (ELEMENT_MUST_BE_REMOVED | BEGIN_ELEMENT_MUST_BE_REMOVED)){ + if (b_element_1->b_stack_flags & ELEMENT_MUST_BE_REMOVED) + internal_error_in_function ("remove_not_used_b_stack_elements"); + + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_b_stack, + b_element_1->b_stack_offset,block_graph->block_graph_b_stack_begin_displacement, + block_graph->block_graph_b_stack_top_offset,1); + b_element_1=*b_element_1_p; + + --block_graph->block_graph_b_stack_top_offset; + } else { + b_element_1_p=&b_element_1->b_stack_next; + b_element_1=*b_element_1_p; + } + } + + offset_1=block_graph->block_graph_b_stack_top_offset; + first_non_parameter_offset_1= + block_graph->block_graph_used_b_stack_elements + +block_graph->block_graph_b_stack_top_offset; + + while (offset_1b_stack_offset==offset_1){ + if (b_element_1->b_stack_flags & (ELEMENT_MUST_BE_REMOVED | BEGIN_ELEMENT_MUST_BE_REMOVED)){ + if (b_element_1->b_stack_flags & ELEMENT_MUST_BE_REMOVED) + internal_error_in_function ("remove_not_used_b_stack_elements"); + + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_b_stack, + offset_1,block_graph->block_graph_b_stack_begin_displacement, + block_graph->block_graph_b_stack_top_offset,1); + b_element_1=*b_element_1_p; + + --block_graph->block_graph_b_stack_top_offset; + --first_non_parameter_offset_1; + } else { + b_element_1_p=&b_element_1->b_stack_next; + b_element_1=*b_element_1_p; + ++offset_1; + } + } + + stack_offset_1_min_2= + block_graph->block_graph_b_stack_top_offset + +block_graph->block_graph_end_b_stack_size + -next_block_graph->block_graph_begin_b_stack_size; + + b_element_2_p=&next_block_graph->block_graph_b_stack; + b_element_2=*b_element_2_p; + + if (offset_1>=first_non_parameter_offset_1) + while (b_element_1!=NULL && b_element_1->b_stack_offset==offset_1){ + INSTRUCTION_GRAPH load_graph; + int offset_2; + + offset_2=offset_1-stack_offset_1_min_2; + + while (b_element_2!=NULL && b_element_2->b_stack_offsetb_stack_next; + b_element_2=*b_element_2_p; + } + + if (b_element_1->b_stack_flags & ELEMENT_MUST_BE_REMOVED || + (b_element_1->b_stack_flags & BEGIN_ELEMENT_MUST_BE_REMOVED && + ( (b_element_2!=NULL && b_element_2->b_stack_offset==offset_2) + ? ((load_graph=b_element_2->b_stack_load_graph)==NULL || + (!load_graph->node_mark && + !((load_graph->instruction_code==GFHIGH || + load_graph->instruction_code==GFLOW) + && load_graph->instruction_parameters[0].p->node_mark))) + : offset_2block_graph_b_stack_top_offset))) + { + remove_stack_element ((struct stack **)b_element_1_p); + b_element_1=*b_element_1_p; + --stack_offset_1_min_2; + + if (b_element_2!=NULL && b_element_2->b_stack_offset==offset_2){ + if (b_element_2->b_stack_flags & ELEMENT_MAY_BE_REMOVED) + b_element_2->b_stack_flags |= ELEMENT_MUST_BE_REMOVED; + else { + b_element_2->b_stack_flags |= BEGIN_ELEMENT_MUST_BE_REMOVED; +#ifdef INSERT_LOAD_GRAPHS + b_element_2_p=(struct b_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_b_stack,offset_2, + next_block_graph->block_graph_b_stack_begin_displacement, + next_block_graph->block_graph_b_stack_top_offset,1); +#endif + } + } else { + struct b_stack *new_element; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset_2; + new_element->b_stack_flags=BEGIN_ELEMENT_MUST_BE_REMOVED; + new_element->b_stack_graph=NULL; + new_element->b_stack_load_graph=NULL; + + new_element->b_stack_next=b_element_2; + *b_element_2_p=new_element; + b_element_2=new_element; +#ifdef INSERT_LOAD_GRAPHS + b_element_2_p=(struct b_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_b_stack,offset_2, + next_block_graph->block_graph_b_stack_begin_displacement, + next_block_graph->block_graph_b_stack_top_offset,1); +#endif + } + } else if (b_element_1->b_stack_flags & BEGIN_ELEMENT_MUST_BE_REMOVED){ + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_b_stack, + offset_1,block_graph->block_graph_b_stack_begin_displacement, + block_graph->block_graph_b_stack_top_offset,1); + b_element_1=*b_element_1_p; + + --block_graph->block_graph_b_stack_top_offset; + --stack_offset_1_min_2; + } else { + if ((b_element_2!=NULL && b_element_2->b_stack_offset==offset_2) + ? ((load_graph=b_element_2->b_stack_load_graph)==NULL || + (!load_graph->node_mark && + !((load_graph->instruction_code==GFHIGH || + load_graph->instruction_code==GFLOW) + && load_graph->instruction_parameters[0].p->node_mark))) + : offset_2block_graph_b_stack_top_offset) + { + remove_end_stack_element + ((struct stack **)&block_graph->block_graph_b_stack,offset_1, + block_graph->block_graph_b_stack_begin_displacement, + block_graph->block_graph_b_stack_top_offset,1); + b_element_1=*b_element_1_p; + + ++block_graph->block_graph_b_stack_top_offset; + + if (b_element_2!=NULL && b_element_2->b_stack_offset==offset_2){ + if (b_element_2->b_stack_flags & ELEMENT_MAY_BE_REMOVED) + b_element_2->b_stack_flags |= ELEMENT_MUST_BE_REMOVED; + else { + b_element_2->b_stack_flags |= BEGIN_ELEMENT_MUST_BE_REMOVED; +#ifdef INSERT_LOAD_GRAPHS + b_element_2_p=(struct b_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_b_stack,offset_2, + next_block_graph->block_graph_b_stack_begin_displacement, + next_block_graph->block_graph_b_stack_top_offset,1); +#endif + } + } else { + struct b_stack *new_element; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset_2; + new_element->b_stack_flags=BEGIN_ELEMENT_MUST_BE_REMOVED; + new_element->b_stack_graph=NULL; + new_element->b_stack_load_graph=NULL; + + new_element->b_stack_next=b_element_2; + *b_element_2_p=new_element; + b_element_2=new_element; +#ifdef INSERT_LOAD_GRAPHS + b_element_2_p=(struct b_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_b_stack,offset_2, + next_block_graph->block_graph_b_stack_begin_displacement, + next_block_graph->block_graph_b_stack_top_offset,1); +#endif + } + } + + ++offset_1; + b_element_1_p=&b_element_1->b_stack_next; + b_element_1=*b_element_1_p; + } + } + + while (b_element_1!=NULL){ + if (b_element_1->b_stack_flags & ELEMENT_MUST_BE_REMOVED){ + int offset_2; + + offset_1=b_element_1->b_stack_offset; + offset_2=offset_1-stack_offset_1_min_2; + + while (b_element_2!=NULL && b_element_2->b_stack_offsetb_stack_next; + b_element_2=*b_element_2_p; + } + + remove_stack_element ((struct stack **)b_element_1_p); + b_element_1=*b_element_1_p; + --stack_offset_1_min_2; + + if (b_element_2!=NULL && b_element_2->b_stack_offset==offset_2){ + if (b_element_2->b_stack_flags & ELEMENT_MAY_BE_REMOVED) + b_element_2->b_stack_flags |= ELEMENT_MUST_BE_REMOVED; + else { + b_element_2->b_stack_flags |= BEGIN_ELEMENT_MUST_BE_REMOVED; +#ifdef INSERT_LOAD_GRAPHS + b_element_2_p=(struct b_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_b_stack,offset_2, + next_block_graph->block_graph_b_stack_begin_displacement, + next_block_graph->block_graph_b_stack_top_offset,1); +#endif + } + } else { + struct b_stack *new_element; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset_2; + new_element->b_stack_flags=BEGIN_ELEMENT_MUST_BE_REMOVED; + new_element->b_stack_graph=NULL; + new_element->b_stack_load_graph=NULL; + + new_element->b_stack_next=b_element_2; + *b_element_2_p=new_element; + b_element_2=new_element; +#ifdef INSERT_LOAD_GRAPHS + b_element_2_p=(struct b_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_b_stack,offset_2, + next_block_graph->block_graph_b_stack_begin_displacement, + next_block_graph->block_graph_b_stack_top_offset,1); +#endif + } + } else if (b_element_1->b_stack_flags & BEGIN_ELEMENT_MUST_BE_REMOVED){ + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_b_stack, + b_element_1->b_stack_offset,block_graph->block_graph_b_stack_begin_displacement, + block_graph->block_graph_b_stack_top_offset,1); + b_element_1=*b_element_1_p; + + --block_graph->block_graph_b_stack_top_offset; + --stack_offset_1_min_2; + } else { + b_element_1_p=&b_element_1->b_stack_next; + b_element_1=*b_element_1_p; + } + } + +} + +static void remove_not_used_stack_elements_from_last_block (struct block_graph *block_graph) +{ + struct a_stack *a_element_1,**a_element_1_p; + struct b_stack *b_element_1,**b_element_1_p; + + a_element_1_p=&block_graph->block_graph_a_stack; + a_element_1=*a_element_1_p; + + while (a_element_1!=NULL){ + if (a_element_1->a_stack_flags & BEGIN_ELEMENT_MUST_BE_REMOVED){ + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_a_stack, + a_element_1->a_stack_offset,block_graph->block_graph_a_stack_begin_displacement, + block_graph->block_graph_a_stack_top_offset,0); + a_element_1=*a_element_1_p; + + --block_graph->block_graph_a_stack_top_offset; + } else { + if (a_element_1->a_stack_flags & ELEMENT_MUST_BE_REMOVED){ + internal_error_in_function ("remove_not_used_stack_elements_from_last_block"); + } else + a_element_1_p=&a_element_1->a_stack_next; + a_element_1=*a_element_1_p; + } + } + + b_element_1_p=&block_graph->block_graph_b_stack; + b_element_1=*b_element_1_p; + + while (b_element_1!=NULL){ + if (b_element_1->b_stack_flags & BEGIN_ELEMENT_MUST_BE_REMOVED){ + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_b_stack, + b_element_1->b_stack_offset,block_graph->block_graph_b_stack_begin_displacement, + block_graph->block_graph_b_stack_top_offset,1); + b_element_1=*b_element_1_p; + + --block_graph->block_graph_b_stack_top_offset; + } else { + if (b_element_1->b_stack_flags & ELEMENT_MUST_BE_REMOVED){ + internal_error_in_function ("remove_not_used_stack_elements_from_last_block"); + } else + b_element_1_p=&b_element_1->b_stack_next; + b_element_1=*b_element_1_p; + } + } +} + +static struct block_graph *first_block_graph,*last_block_graph; + +static void insert_dummy_graphs_for_unused_a_stack_elements + (struct block_graph *block_graph,struct block_graph *next_block_graph) +{ + struct a_stack *a_element_1,**a_element_1_p; + struct a_stack *a_element_2; + int stack_offset_difference,offset,n; + int first_non_parameter_offset_1,first_non_parameter_offset_2; + +#ifdef DEBUG + printf ("%d %d %d %d\n",block_graph->block_graph_a_stack_top_offset, + block_graph->block_graph_end_a_stack_size, + -next_block_graph->block_graph_begin_a_stack_size, + block_graph->block_graph_used_a_stack_elements); +#endif + + stack_offset_difference= block_graph->block_graph_a_stack_top_offset + +block_graph->block_graph_end_a_stack_size + -next_block_graph->block_graph_begin_a_stack_size; + first_non_parameter_offset_1= block_graph->block_graph_used_a_stack_elements + +block_graph->block_graph_a_stack_top_offset; + + a_element_1_p=&block_graph->block_graph_a_stack; + a_element_1=*a_element_1_p; + + a_element_2=next_block_graph->block_graph_a_stack; + + first_non_parameter_offset_2=first_non_parameter_offset_1-stack_offset_difference; + while (a_element_2!=NULL && a_element_2->a_stack_offseta_stack_next; + + for (; a_element_2!=NULL; a_element_2=a_element_2->a_stack_next){ + INSTRUCTION_GRAPH load_graph; + + if (a_element_2->a_stack_flags & ELEMENT_MAY_BE_REMOVED + || (load_graph=a_element_2->a_stack_load_graph)==NULL + || !load_graph->node_mark) + { + offset=a_element_2->a_stack_offset+stack_offset_difference; + + while (a_element_1!=NULL && a_element_1->a_stack_offseta_stack_next; + a_element_1=*a_element_1_p; + } + + if (a_element_1==NULL || a_element_1->a_stack_offset!=offset){ + struct a_stack *new_element; +#ifdef DEBUG + printf ("%d ",offset); +#endif + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=offset; + new_element->a_stack_flags=ELEMENT_MAY_BE_REMOVED; + new_element->a_stack_graph=NULL; + new_element->a_stack_load_graph=NULL; + + new_element->a_stack_next=a_element_1; + *a_element_1_p=new_element; + a_element_1_p=&new_element->a_stack_next; + } + } + } + +#ifdef DEBUG + printf ("| "); +#endif + + a_element_1_p=&block_graph->block_graph_a_stack; + a_element_1=*a_element_1_p; + + a_element_2=next_block_graph->block_graph_a_stack; + + n=first_non_parameter_offset_1-stack_offset_difference; + if (n<0) + n=0; + + for (; nblock_graph_a_stack_top_offset; ++n){ + while (a_element_2!=NULL && a_element_2->a_stack_offseta_stack_next; + if (a_element_2==NULL || a_element_2->a_stack_offset!=n){ + + while (a_element_1!=NULL && a_element_1->a_stack_offseta_stack_next; + a_element_1=*a_element_1_p; + } + if (a_element_1==NULL || a_element_1->a_stack_offset!=n+stack_offset_difference){ + struct a_stack *new_element; +#ifdef DEBUG + printf ("%d ",n+stack_offset_difference); +#endif + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=n+stack_offset_difference; + new_element->a_stack_flags=ELEMENT_MAY_BE_REMOVED; + new_element->a_stack_graph=NULL; + new_element->a_stack_load_graph=NULL; + + new_element->a_stack_next=a_element_1; + *a_element_1_p=new_element; + a_element_1_p=&new_element->a_stack_next; + } + } + } + +#ifdef DEBUG + printf ("\n"); +#endif +} + +static void insert_dummy_graphs_for_unused_b_stack_elements + (register struct block_graph *block_graph,struct block_graph *next_block_graph) +{ + struct b_stack *b_element_1,**b_element_1_p,*b_element_2; + int stack_offset_1_min_2,offset_1,offset_2; + int first_non_parameter_offset_1,first_non_parameter_offset_2; + + /* + printf ("%d %d %d %d\n",block_graph->block_graph_b_stack_top_offset, + block_graph->block_graph_end_b_stack_size, + -next_block_graph->block_graph_begin_b_stack_size, + block_graph->block_graph_used_b_stack_elements); + */ + + stack_offset_1_min_2= + block_graph->block_graph_b_stack_top_offset + +block_graph->block_graph_end_b_stack_size + -next_block_graph->block_graph_begin_b_stack_size; + first_non_parameter_offset_1= + block_graph->block_graph_used_b_stack_elements + +block_graph->block_graph_b_stack_top_offset; + + /* + insert dummy graphs in the current block for elements for which a node + has been made in the next block, but will not be used any more + */ + + b_element_1_p=&block_graph->block_graph_b_stack; + b_element_1=*b_element_1_p; + + b_element_2=next_block_graph->block_graph_b_stack; + + first_non_parameter_offset_2=first_non_parameter_offset_1-stack_offset_1_min_2; + while (b_element_2!=NULL && b_element_2->b_stack_offsetb_stack_next; + + for (; b_element_2!=NULL; b_element_2=b_element_2->b_stack_next){ + INSTRUCTION_GRAPH load_graph; + + if (b_element_2->b_stack_flags & ELEMENT_MAY_BE_REMOVED || + ((load_graph=b_element_2->b_stack_load_graph)==NULL || + (!load_graph->node_mark && + !((load_graph->instruction_code==GFHIGH || + load_graph->instruction_code==GFLOW) && + load_graph->instruction_parameters[0].p->node_mark)))) + { + offset_1=b_element_2->b_stack_offset+stack_offset_1_min_2; + + while (b_element_1!=NULL && b_element_1->b_stack_offsetb_stack_next; + b_element_1=*b_element_1_p; + } + + if (b_element_1==NULL || b_element_1->b_stack_offset!=offset_1){ + register struct b_stack *new_element; + + /* printf ("%d ",offset_1); */ + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset_1; + new_element->b_stack_flags=ELEMENT_MAY_BE_REMOVED; + new_element->b_stack_graph=NULL; + new_element->b_stack_load_graph=NULL; + + new_element->b_stack_next=b_element_1; + *b_element_1_p=new_element; + b_element_1_p=&new_element->b_stack_next; + } + } + } + + /* printf ("| "); */ + + /* + insert dummy graphs in the current block for elements for which are popped + from the stack in the next block + */ + + b_element_1_p=&block_graph->block_graph_b_stack; + b_element_1=*b_element_1_p; + + b_element_2=next_block_graph->block_graph_b_stack; + + offset_2=first_non_parameter_offset_2; + if (offset_2<0) + offset_2=0; + + for (; offset_2block_graph_b_stack_top_offset; ++offset_2){ + while (b_element_2!=NULL && b_element_2->b_stack_offsetb_stack_next; + if (b_element_2==NULL || b_element_2->b_stack_offset!=offset_2){ + offset_1=offset_2+stack_offset_1_min_2; + while (b_element_1!=NULL && b_element_1->b_stack_offsetb_stack_next; + b_element_1=*b_element_1_p; + } + if (b_element_1==NULL || b_element_1->b_stack_offset!=offset_1){ + register struct b_stack *new_element; + + /* printf ("%d ",offset_1); */ + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset_1; + new_element->b_stack_flags=ELEMENT_MAY_BE_REMOVED; + new_element->b_stack_graph=NULL; + new_element->b_stack_load_graph=NULL; + + new_element->b_stack_next=b_element_1; + *b_element_1_p=new_element; + b_element_1_p=&new_element->b_stack_next; + } + } + } + + /* printf ("\n"); */ +} + +static void mark_stack_graphs_1 + (struct block_graph *block_graph,struct block_graph *next_block_graph,int jmp_jsr_or_rtn_flag) +{ + int stack_offset_difference,first_non_parameter_offset,offset; + struct b_stack *b_element_1,*b_element_2,**b_element_1_p; + struct a_stack *a_element; + int a_stack_top_offset,b_stack_top_offset; + + a_stack_top_offset=block_graph->block_graph_a_stack_top_offset; + a_element=block_graph->block_graph_a_stack; + + while (a_element!=NULL && a_element->a_stack_offseta_stack_next; + + for (; a_element!=NULL; a_element=a_element->a_stack_next) + if (a_element->a_stack_graph!=NULL) + mark_graph_2 (a_element->a_stack_graph); + + stack_offset_difference=block_graph->block_graph_b_stack_top_offset + +block_graph->block_graph_end_b_stack_size + -next_block_graph->block_graph_begin_b_stack_size; + first_non_parameter_offset=block_graph->block_graph_used_b_stack_elements + +block_graph->block_graph_b_stack_top_offset; + + /* + printf ("%d %d %d %d\n", + block_graph->block_graph_used_b_stack_elements, + block_graph->block_graph_b_stack_top_offset, + stack_offset_difference,first_non_parameter_offset); + */ + + b_element_2=next_block_graph->block_graph_b_stack; + + b_stack_top_offset=block_graph->block_graph_b_stack_top_offset; + b_element_1=block_graph->block_graph_b_stack; + + while (b_element_1!=NULL && b_element_1->b_stack_offsetb_stack_next; + + for (; b_element_1!=NULL; b_element_1=b_element_1->b_stack_next) + if (b_element_1->b_stack_graph!=NULL){ + /* printf ("%d",b_element_1->b_stack_offset); */ + + if (b_element_1->b_stack_offsetb_stack_flags|=ELEMENT_USED_BEFORE_JSR; + mark_graph_2 (b_element_1->b_stack_graph); + } else { + int required_offset; + + required_offset=b_element_1->b_stack_offset-stack_offset_difference; + + while (b_element_2!=NULL && b_element_2->b_stack_offsetb_stack_next; + + if (!jmp_jsr_or_rtn_flag || + block_graph->block_graph_kind!=JSR_EVAL_BLOCK || + (b_element_2!=NULL && b_element_2->b_stack_offset==required_offset + && b_element_2->b_stack_load_graph!=NULL + && (b_element_2->b_stack_load_graph->node_mark==2 || + ((b_element_2->b_stack_load_graph->instruction_code==GFHIGH + || b_element_2->b_stack_load_graph->instruction_code==GFLOW) + && b_element_2->b_stack_load_graph->instruction_parameters[0].p->node_mark==2)))) + { + b_element_1->b_stack_flags|=ELEMENT_USED_BEFORE_JSR; + mark_graph_2 (b_element_1->b_stack_graph); + } else { + mark_graph_1 (b_element_1->b_stack_graph); + /* printf ("*"); */ + } + } + /* printf (" "); */ + } + + if (block_graph->block_graph_kind==JSR_EVAL_BLOCK){ + b_element_1_p=&block_graph->block_graph_b_stack; + b_element_1=*b_element_1_p; + + for (b_element_2=next_block_graph->block_graph_b_stack; + b_element_2!=NULL; b_element_2=b_element_2->b_stack_next) + { + INSTRUCTION_GRAPH load_graph,next_load_graph,graph_1,next_graph_1; + struct b_stack *next_b_element_2,*next_b_element_1; + + load_graph=b_element_2->b_stack_load_graph; + if (load_graph!=NULL && + (load_graph->node_mark==2 || + ((load_graph->instruction_code==GFHIGH || load_graph->instruction_code==GFLOW) + && load_graph->instruction_parameters[0].p->node_mark==2)) && + (offset=b_element_2->b_stack_offset+stack_offset_difference)>=first_non_parameter_offset) + { + while (b_element_1!=NULL && b_element_1->b_stack_offsetb_stack_next; + b_element_1=*b_element_1_p; + } + + if (load_graph->instruction_code==GFHIGH && + (next_b_element_2=b_element_2->b_stack_next)!=NULL && + next_b_element_2->b_stack_offset==b_element_2->b_stack_offset+1 && + (next_load_graph=next_b_element_2->b_stack_load_graph)!=NULL && + next_load_graph->instruction_code==GFLOW && + next_load_graph->instruction_parameters[0].p==load_graph->instruction_parameters[0].p && + b_element_1!=NULL && b_element_1->b_stack_offset==offset && + (graph_1=b_element_1->b_stack_graph)!=NULL && + graph_1->instruction_code==GLOAD && + (next_b_element_1=b_element_1->b_stack_next)!=NULL && + next_b_element_1->b_stack_offset==offset+1 && + (next_graph_1=next_b_element_1->b_stack_graph)!=NULL && + next_graph_1->instruction_code==GLOAD && + graph_1->instruction_parameters[0].i+4==next_graph_1->instruction_parameters[0].i && + graph_1->instruction_parameters[1].i==next_graph_1->instruction_parameters[1].i) + { + INSTRUCTION_GRAPH f_graph; + + /* printf ("%d## ",offset); */ + + f_graph=g_fload + (graph_1->instruction_parameters[0].i,graph_1->instruction_parameters[1].i); + f_graph->node_mark=2; + + graph_1->instruction_code=GFHIGH; + graph_1->instruction_parameters[0].p=f_graph; +#ifdef g_fhighlow + graph_1->instruction_parameters[1].p=next_graph_1; +#endif + graph_1->node_mark=2; + + next_graph_1->instruction_code=GFLOW; + next_graph_1->instruction_parameters[0].p=f_graph; +#ifdef g_fhighlow + next_graph_1->instruction_parameters[1].p=graph_1; +#endif + next_graph_1->node_mark=2; + } else + if (b_element_1==NULL || b_element_1->b_stack_offset!=offset){ + if (load_graph->instruction_code==GFHIGH && + (next_b_element_2=b_element_2->b_stack_next)!=NULL && + next_b_element_2->b_stack_offset==b_element_2->b_stack_offset+1 && + (next_load_graph=next_b_element_2->b_stack_load_graph)!=NULL && + next_load_graph->instruction_code==GFLOW && + next_load_graph->instruction_parameters[0].p==load_graph->instruction_parameters[0].p && + (b_element_1==NULL || b_element_1->b_stack_offset!=offset+1)) + { + register struct b_stack *new_element; + INSTRUCTION_GRAPH f_graph,l_graph,h_graph; + + /* printf ("%d# ",offset); */ + + f_graph=g_fload + ((offset+block_graph->block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + f_graph->node_mark=2; + +#ifdef g_fhighlow + g_fhighlow (h_graph,l_graph,f_graph); +#else + h_graph=g_fhigh (f_graph); + l_graph=g_flow (f_graph); +#endif + h_graph->node_mark=2; + l_graph->node_mark=2; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset; + new_element->b_stack_flags=ELEMENT_USED_BEFORE_JSR; + new_element->b_stack_graph=h_graph; + new_element->b_stack_load_graph=h_graph; + + new_element->b_stack_next=b_element_1; + *b_element_1_p=new_element; + b_element_1_p=&new_element->b_stack_next; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset+1; + new_element->b_stack_flags=ELEMENT_USED_BEFORE_JSR; + new_element->b_stack_graph=l_graph; + new_element->b_stack_load_graph=l_graph; + + new_element->b_stack_next=b_element_1; + *b_element_1_p=new_element; + b_element_1_p=&new_element->b_stack_next; + + b_element_2=next_b_element_2; + } else { + register struct b_stack *new_element; + INSTRUCTION_GRAPH graph; + + /* printf ("%d ",offset); */ + + graph=g_load + ((offset+block_graph->block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + graph->node_mark=2; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset; + new_element->b_stack_flags=ELEMENT_USED_BEFORE_JSR; + new_element->b_stack_graph=graph; + new_element->b_stack_load_graph=graph; + + new_element->b_stack_next=b_element_1; + *b_element_1_p=new_element; + b_element_1_p=&new_element->b_stack_next; + } + } + } + } + } + + b_element_1_p=&block_graph->block_graph_b_stack; + b_element_1=*b_element_1_p; + + for (offset=block_graph->block_graph_b_stack_top_offset; offsetb_stack_offsetb_stack_next; + b_element_1=*b_element_1_p; + } + + if (b_element_1==NULL || b_element_1->b_stack_offset!=offset){ + int n; + + n=offset-block_graph->block_graph_b_stack_top_offset; + + if ((unsigned)n < (unsigned)block_graph->block_graph_end_b_stack_size + && test_bit (block_graph->block_graph_end_stack_vector,n) + && (b_element_1==NULL || b_element_1->b_stack_offset!=offset+1) + && mc68881_flag) + { + register struct b_stack *new_element; + INSTRUCTION_GRAPH f_graph,l_graph,h_graph; + + /* printf ("%d$# ",offset); */ + + f_graph=g_fload + ((offset+block_graph->block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + f_graph->node_mark=2; +#ifdef g_fhighlow + g_fhighlow (h_graph,l_graph,f_graph); +#else + h_graph=g_fhigh (f_graph); + l_graph=g_flow (f_graph); +#endif + h_graph->node_mark=2; + l_graph->node_mark=2; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset; + new_element->b_stack_flags=ELEMENT_USED_BEFORE_JSR; + new_element->b_stack_graph=h_graph; + new_element->b_stack_load_graph=h_graph; + + new_element->b_stack_next=b_element_1; + *b_element_1_p=new_element; + b_element_1_p=&new_element->b_stack_next; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset+1; + new_element->b_stack_flags=ELEMENT_USED_BEFORE_JSR; + new_element->b_stack_graph=l_graph; + new_element->b_stack_load_graph=l_graph; + + new_element->b_stack_next=b_element_1; + *b_element_1_p=new_element; + b_element_1_p=&new_element->b_stack_next; + + ++offset; + } else { + register struct b_stack *new_element; + INSTRUCTION_GRAPH graph; + + /* printf ("%d$ ",offset); */ + + graph=g_load + ((offset+block_graph->block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + graph->node_mark=2; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset; + new_element->b_stack_flags=ELEMENT_USED_BEFORE_JSR; + new_element->b_stack_graph=graph; + new_element->b_stack_load_graph=graph; + + new_element->b_stack_next=b_element_1; + *b_element_1_p=new_element; + b_element_1_p=&new_element->b_stack_next; + } + } + } + + /* printf ("\n"); */ +} + +static void mark_stack_graphs_2 (struct block_graph *block_graph) +{ + struct a_stack *a_element; + struct b_stack *b_element; + int a_stack_top_offset,b_stack_top_offset; + + a_stack_top_offset=block_graph->block_graph_a_stack_top_offset; + + a_element=block_graph->block_graph_a_stack; + + while (a_element!=NULL && a_element->a_stack_offseta_stack_next; + + for (; a_element!=NULL; a_element=a_element->a_stack_next) + if (a_element->a_stack_graph!=NULL) + mark_graph_2 (a_element->a_stack_graph); + + b_stack_top_offset=block_graph->block_graph_b_stack_top_offset; + + b_element=block_graph->block_graph_b_stack; + while (b_element!=NULL && b_element->b_stack_offsetb_stack_next; + + for (; b_element!=NULL; b_element=b_element->b_stack_next) + if (b_element->b_stack_graph!=NULL){ + b_element->b_stack_flags|=ELEMENT_USED_BEFORE_JSR; + mark_graph_2 (b_element->b_stack_graph); + } +} + +#ifndef M68000 +extern LONG offset_from_heap_register; +#endif +#ifdef G_POWER +extern LONG heap_pointer_offset_in_basic_block; +#endif + +static void allocate_registers (void) +{ + int n; + + free_all_aregisters(); + free_all_dregisters(); + free_all_fregisters(); + + for (n=0; nnode_count>0) + allocate_aregister (register_graph->instruction_parameters[0].i); + } + + for (n=0; nnode_count>0) + allocate_dregister (register_graph->instruction_parameters[0].i); + } + + if (mc68881_flag) + for (n=0; nnode_count>0) + allocate_fregister (register_graph->instruction_parameters[0].i); + } +} + +static void calculate_and_linearize_graphs (int n_elements,INSTRUCTION_GRAPH graphs[]) +{ + int n; + + local_data_offset= + (global_block.block_graph_b_stack_top_offset+ + global_block.block_graph_b_stack_begin_displacement+ + global_block.block_graph_b_stack_end_displacement)<<2; + if (local_data_offset>0) + local_data_offset=0; + + for (n=0; ninstruction_code!=GFILL) + count_graph (a_graph); + else { + int n; + + for (n=0; ninode_arity; ++n) + if (a_graph->instruction_parameters[n].p!=NULL) + count_graph (a_graph->instruction_parameters[n].p); + } + } + + allocate_registers(); + + for (n=0; na_stack_graph!=NULL) + ++n_a_elements; + + n_b_elements=0; + for_l (b_element,global_block.block_graph_b_stack,b_stack_next) + if (b_element->b_stack_graph!=NULL) + ++n_b_elements; + + if (n_a_elements+n_b_elements==0){ + *graphs_p=NULL; + return 0; + } + + graphs=(INSTRUCTION_GRAPH*)memory_allocate (sizeof (INSTRUCTION_GRAPH) * (n_a_elements+n_b_elements)); + *graphs_p=graphs; + + if (global_block.block_graph_a_stack_top_offset+ + global_block.block_graph_a_stack_begin_displacement+ + global_block.block_graph_a_stack_end_displacement<=0) + { + element_n=n_a_elements+n_b_elements; + for_l (a_element,global_block.block_graph_a_stack,a_stack_next) + if (a_element->a_stack_graph!=NULL) + graphs[--element_n]=a_element->a_stack_graph; + } else { + element_n=n_b_elements; + for_l (a_element,global_block.block_graph_a_stack,a_stack_next) + if (a_element->a_stack_graph!=NULL) + graphs[element_n++]=a_element->a_stack_graph; + } + + if (global_block.block_graph_b_stack_top_offset+ + global_block.block_graph_b_stack_begin_displacement+ + global_block.block_graph_b_stack_end_displacement<=0) + { + element_n=n_b_elements; + for_l (b_element,global_block.block_graph_b_stack,b_stack_next) + if (b_element->b_stack_graph!=NULL) + graphs[--element_n]=b_element->b_stack_graph; + } else { + element_n=0; + for_l (b_element,global_block.block_graph_b_stack,b_stack_next) + if (b_element->b_stack_graph!=NULL) + graphs[element_n++]=b_element->b_stack_graph; + } + + return n_a_elements+n_b_elements; +} + +void linearize_stack_graphs (VOID) +{ + int n_elements; + INSTRUCTION_GRAPH *graphs; + + n_elements=allocate_and_fill_graph_array (&graphs); + + if (graphs!=NULL){ + calculate_and_linearize_graphs (n_elements,graphs); + + memory_free (graphs); + } else + allocate_registers(); +} + +void linearize_stack_graphs_with_overflow_test (INSTRUCTION_GRAPH test_overflow_graph,INSTRUCTION_GRAPH store_calculate_with_overflow_graph) +{ + int n_elements; + INSTRUCTION_GRAPH *graphs; + + count_graph (store_calculate_with_overflow_graph); + + n_elements=allocate_and_fill_graph_array (&graphs); + + if (graphs!=NULL){ + int n; + + local_data_offset= (global_block.block_graph_b_stack_top_offset+ + global_block.block_graph_b_stack_begin_displacement+ + global_block.block_graph_b_stack_end_displacement)<<2; + if (local_data_offset>0) + local_data_offset=0; + + for (n=0; ninstruction_code!=GFILL) + count_graph (a_graph); + else { + int n; + + for (n=0; ninode_arity; ++n) + if (a_graph->instruction_parameters[n].p!=NULL) + count_graph (a_graph->instruction_parameters[n].p); + } + } + } + + if (test_overflow_graph->node_count==1 && store_calculate_with_overflow_graph->node_count==1 + && (store_calculate_with_overflow_graph->instruction_code==GSTORE_R + ? store_calculate_with_overflow_graph->instruction_parameters[1].p->node_count==2 + : store_calculate_with_overflow_graph->instruction_parameters[2].p->node_count==2)) + { + test_overflow_graph->node_count=0; + if (store_calculate_with_overflow_graph->instruction_code==GSTORE_R) + store_calculate_with_overflow_graph->instruction_parameters[1].p->node_count=1; + else + store_calculate_with_overflow_graph->instruction_parameters[2].p->node_count=1; + } + + allocate_registers(); + + if (graphs!=NULL){ + int n; + + for (n=0; nb_stack_graph; + if (stack_graph!=NULL && + ((stack_graph->instruction_code==GSTORE_R && stack_graph->instruction_parameters[1].p==calculate_with_overflow_graph) + || (stack_graph->instruction_code==GSTORE && stack_graph->instruction_parameters[2].p==calculate_with_overflow_graph))) + { + b_element->b_stack_graph=NULL; + return stack_graph; + } + } + + return NULL; +} + +static int block_check; +#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS +int block_a_stack_displacement,block_b_stack_displacement; +static WORD *a_check_size_p,*b_check_size_p; +#else +int block_stack_displacement; +static WORD *check_size_p; +#endif + +static int stack_access_and_adjust_a_stack_pointer (int extra_b_offset) +{ + int a_offset,b_offset,minimum_b_offset; + + a_offset=-( global_block.block_graph_a_stack_top_offset+ + global_block.block_graph_a_stack_begin_displacement+ + global_block.block_graph_a_stack_end_displacement)<<2; + b_offset=( global_block.block_graph_b_stack_top_offset+ + global_block.block_graph_b_stack_begin_displacement+ + global_block.block_graph_b_stack_end_displacement)<<2; + + minimum_b_offset= local_data_offsetblock_graph_a_stack_displacement=a_offset; + last_block_graph->block_graph_b_stack_displacement=b_offset; + } + + if (a_check_size_p==NULL){ + a_check_size=a_offset>0 ? a_offset : 0; + b_check_size=minimum_b_offset<0 ? -b_offset : 0; + + a_check_size_p=&last_block->block_a_stack_check_size; + b_check_size_p=&last_block->block_b_stack_check_size; + *a_check_size_p=a_check_size; + *b_check_size_p=b_check_size; + block_a_stack_displacement=a_offset; + block_b_stack_displacement=-b_offset; + } else { + a_check_size=block_a_stack_displacement+(a_offset>0 ? a_offset : 0); + b_check_size=block_b_stack_displacement+(minimum_b_offset<0 ? -b_offset : 0); + if (a_check_size>*a_check_size_p) + *a_check_size_p=a_check_size; + if (b_check_size>*b_check_size_p) + *b_check_size_p=b_check_size; + block_a_stack_displacement+=a_offset; + block_b_stack_displacement-=b_offset; + } + } else { + last_block->block_a_stack_check_size=a_offset>0 ? a_offset : 0; + last_block->block_b_stack_check_size=minimum_b_offset<0 ? -b_offset : 0; + } +#else + int check_size; + + if (last_block_graph!=NULL) + last_block_graph->block_graph_stack_displacement=a_offset+b_offset; + + if (check_size_p==NULL){ + check_size=(minimum_b_offset<0 ? -b_offset : 0) + (a_offset>0 ? a_offset : 0); + + check_size_p=&last_block->block_stack_check_size; + *check_size_p=check_size; + block_stack_displacement=a_offset-b_offset; + } else { + check_size=block_stack_displacement+(minimum_b_offset<0 ? -b_offset : 0) + (a_offset>0 ? a_offset : 0); + if (check_size>*check_size_p) + *check_size_p=check_size; + block_stack_displacement+=a_offset-b_offset; + } + } else + last_block->block_stack_check_size=(minimum_b_offset<0 ? -b_offset : 0) + (a_offset>0 ? a_offset : 0); +#endif + + b_offset+=extra_b_offset; + +#if defined (M68000) || defined (I486) || defined (G_POWER) + optimize_stack_access (last_block,&a_offset,&b_offset); +#endif + + if (a_offset!=0) +#ifdef I486 + i_lea_id_r (a_offset,A_STACK_POINTER,A_STACK_POINTER); +#else + if (a_offset>0) + i_add_i_r (a_offset,A_STACK_POINTER); + else + i_sub_i_r (-a_offset,A_STACK_POINTER); +#endif + + return b_offset; +} + +static void stack_access (void) +{ + register int b_offset; + + b_offset=stack_access_and_adjust_a_stack_pointer (0); + + if (b_offset!=0) +#ifdef I486 + i_lea_id_r (b_offset,B_STACK_POINTER,B_STACK_POINTER); +#else + if (b_offset>0) + i_add_i_r (b_offset,B_STACK_POINTER); + else + i_sub_i_r (-b_offset,B_STACK_POINTER); +#endif +} + +static int local_register_allocation_and_adjust_a_stack_pointer (int extra_b_offset) +{ + int n_virtual_a_regs,n_virtual_d_regs,n_virtual_f_regs; + + get_n_virtual_registers (&n_virtual_a_regs,&n_virtual_d_regs,&n_virtual_f_regs); + do_register_allocation (last_instruction,last_block,n_virtual_a_regs,n_virtual_d_regs,n_virtual_f_regs,0,0); + return stack_access_and_adjust_a_stack_pointer (extra_b_offset); +} + +void adjust_stack_pointers (void) +{ + int n_virtual_a_regs,n_virtual_d_regs,n_virtual_f_regs; + + get_n_virtual_registers (&n_virtual_a_regs,&n_virtual_d_regs,&n_virtual_f_regs); + do_register_allocation (last_instruction,last_block,n_virtual_a_regs,n_virtual_d_regs,n_virtual_f_regs,0,0); + stack_access(); +} + +int adjust_stack_pointers_without_altering_condition_codes (int float_condition,int condition) +{ + int n_virtual_a_regs,n_virtual_d_regs,n_virtual_f_regs,condition_on_stack; + + get_n_virtual_registers (&n_virtual_a_regs,&n_virtual_d_regs,&n_virtual_f_regs); + condition_on_stack=do_register_allocation (last_instruction,last_block,n_virtual_a_regs,n_virtual_d_regs,n_virtual_f_regs,1+float_condition,condition); + stack_access(); + return condition_on_stack; +} + +struct basic_block *allocate_empty_basic_block (VOID) +{ + register struct basic_block *block; + + block=(struct basic_block*)fast_memory_allocate (sizeof (struct basic_block)); + block->block_next=NULL; + block->block_instructions=NULL; + block->block_last_instruction=NULL; + block->block_labels=NULL; + block->block_n_new_heap_cells=0; + block->block_n_begin_a_parameter_registers=0; + block->block_n_begin_d_parameter_registers=0; + block->block_n_node_arguments=-100; +#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS + block->block_a_stack_check_size=0; + block->block_b_stack_check_size=0; +#else + block->block_stack_check_size=0; +#endif + block->block_begin_module=0; + block->block_profile=0; +#ifdef G_POWER + block->block_gc_kind=0; +#endif + + return block; +} + +#ifdef G_POWER +# define SMALLER_EVAL +#endif + +#ifdef M68000 +static int +#else +static void +#endif +generate_code_for_jsr_eval (int n_a_registers,int n_d_registers,int n_f_registers,int offset) +{ + int n,node_a_register; + struct basic_block *new_block; +#ifdef M68000 + int code_size; +#endif + +#if defined (sparc) || defined (I486) || defined (G_POWER) + int a_offset,b_offset; +#else + static int d_registers[]={ + REGISTER_D0,REGISTER_D1,REGISTER_D2,REGISTER_D3,REGISTER_D4, + REGISTER_D5,REGISTER_D6 + }; +#endif + + node_a_register=n_a_registers-offset-1; + + last_instruction=NULL; + + new_block=allocate_empty_basic_block(); + + new_block->block_n_begin_a_parameter_registers=n_a_registers; + new_block->block_n_begin_d_parameter_registers=n_d_registers+1; +#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS + new_block->block_a_stack_check_size=(n_a_registers)<<2; + new_block->block_b_stack_check_size=(n_d_registers<<2) + (n_f_registers<<3); +#else + new_block->block_stack_check_size=((n_a_registers+n_d_registers)<<2) + (n_f_registers<<3); +#endif + + new_block->block_next=last_block->block_next; + last_block->block_next=new_block; + last_block=new_block; + +#ifdef M68000 + code_size=0; + for (n=n_a_registers-1; n>=0; --n) + if (n!=node_a_register){ + i_move_r_pi (num_to_a_reg (n),A_STACK_POINTER); + code_size+=2; + } +#else + a_offset=0; +# ifdef SMALLER_EVAL + if (n_a_registers>1) + i_mtctr (num_to_d_reg (n_d_registers)); +# else + for (n=n_a_registers-1; n>=0; --n) + if (n!=node_a_register){ + i_move_r_id (num_to_a_reg (n),a_offset,A_STACK_POINTER); + a_offset+=4; + } + if (a_offset>0) + i_add_i_r (a_offset,A_STACK_POINTER); +# endif +#endif + +#ifndef SMALLER_EVAL + if (node_a_register!=0){ + i_move_r_r (num_to_a_reg (node_a_register),REGISTER_A0); +# ifdef M68000 + code_size+=2; +# endif + } +#endif + +#ifdef M68000 + if (n_d_registers>=4){ + i_movem_pd (B_STACK_POINTER,n_d_registers,d_registers); + code_size+=4; + } else + for (n=0; n1){ + struct label *eval_label; + + if (n_a_registers==2) + eval_label = node_a_register==0 ? eval_01_label : eval_11_label; + else + eval_label = node_a_register==0 ? eval_02_label : node_a_register==1 ? eval_12_label : eval_22_label; + + i_jsr_l_idu (eval_label,-(b_offset+4)); + } else +# endif + i_jsr_id_idu (0,num_to_d_reg (n_d_registers),-(b_offset+4)); +# else + i_jsr_id_id (0,num_to_d_reg (n_d_registers),0); +# endif +# endif +#endif + +#ifdef M68000 + for (n=n_f_registers-1; n>=0; --n){ + i_fmove_pi_fr (B_STACK_POINTER,n); + code_size+=4; + } +#else + offset=0; + for (n=n_f_registers-1; n>=0; --n){ + i_fmove_id_fr (-offset,B_STACK_POINTER,n); + offset-=8; + } +#endif + +#ifdef M68000 + if (n_d_registers>=4){ + i_movem_pi (B_STACK_POINTER,n_d_registers,d_registers); + code_size+=4; + } else + for (n=n_d_registers-1; n>=0; --n){ + i_move_pi_r (B_STACK_POINTER,num_to_d_reg (n)); + code_size+=2; + } +#else +# ifdef I486 + if (b_offset>0) + i_add_i_r (b_offset,B_STACK_POINTER); + for (n=n_d_registers-1; n>=0; --n) + i_move_pi_r (B_STACK_POINTER,num_to_d_reg (n)); +# else + for (n=n_d_registers-1; n>=0; --n){ + i_move_id_r (-offset,B_STACK_POINTER,num_to_d_reg (n)); + offset-=4; + } + if (b_offset>0) + i_add_i_r (b_offset,B_STACK_POINTER); +# endif +#endif + + if (node_a_register!=0){ + i_move_r_r (REGISTER_A0,num_to_a_reg (node_a_register)); +#ifdef M68000 + code_size+=2; +#endif + } + +#ifdef M68000 + for (n=0; n0) + i_sub_i_r (a_offset,A_STACK_POINTER); +#endif +#endif + +#ifdef M68000 + return code_size; +#endif +} + +static void generate_code_for_basic_block (struct block_graph *next_block_graph) +{ + register struct block_graph *block_graph; + struct basic_block *old_last_block; + struct instruction *block_instructions,*block_last_instruction; + int n_allocated_d_regs,n_allocated_f_regs,n_data_parameter_registers; + int end_b_stack_size; + ULONG *vector; +#ifdef M68000 + LONG *branch_offset_p; +#endif + + old_last_block=last_block; + + block_graph=last_block_graph; + /* + last_block_graph=block_graph->block_graph_previous; + if (last_block_graph!=NULL) + last_block_graph->block_graph_next=NULL; + else + first_block_graph=NULL; + */ + + last_block=block_graph->block_graph_block; + + block_instructions=last_block->block_instructions; + block_last_instruction=last_block->block_last_instruction; + + last_block->block_instructions=NULL; + last_block->block_last_instruction=NULL; + last_instruction=NULL; + + global_block=*block_graph; + if (global_block.block_graph_end_b_stack_size<=VECTOR_ELEMENT_SIZE){ + global_block.block_graph_small_end_stack_vector = *global_block.block_graph_end_stack_vector; + global_block.block_graph_end_stack_vector = &global_block.block_graph_small_end_stack_vector; + } + + n_data_parameter_registers = +#ifndef I486 + block_graph->block_graph_kind==JSR_EVAL_BLOCK ? N_DATA_PARAMETER_REGISTERS-1 : +#endif + N_DATA_PARAMETER_REGISTERS; + + if (parallel_flag) + --n_data_parameter_registers; + + end_b_stack_size=block_graph->block_graph_end_b_stack_size; + if (block_graph->block_graph_kind==JSR_BLOCK +#ifdef G_POWER + || block_graph->block_graph_kind==JSR_BLOCK_WITH_INSTRUCTIONS +#endif + ) + --end_b_stack_size; + + a_stack_load_register_values (block_graph->block_graph_end_a_stack_size,N_ADDRESS_PARAMETER_REGISTERS); + b_stack_load_register_values (end_b_stack_size,block_graph->block_graph_end_stack_vector,n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + ,N_ADDRESS_PARAMETER_REGISTERS-block_graph->block_graph_end_a_stack_size +#endif + ); + + a_stack_stores (block_graph->block_graph_end_a_stack_size,N_ADDRESS_PARAMETER_REGISTERS); + b_stack_stores (end_b_stack_size,block_graph->block_graph_end_stack_vector,n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + ,N_ADDRESS_PARAMETER_REGISTERS-block_graph->block_graph_end_a_stack_size, + block_graph->block_graph_a_register_parameter_node,block_graph->block_graph_d_register_parameter_node +#endif + ); + + linearize_stack_graphs(); + + switch (block_graph->block_graph_kind){ + case JSR_EVAL_BLOCK: + { + register int n,b_stack_size,n_data_parameter_registers; + + n_data_parameter_registers = parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS; + + adjust_stack_pointers(); + + vector=block_graph->block_graph_end_stack_vector; + b_stack_size=block_graph->block_graph_end_b_stack_size; + + n_allocated_d_regs=0; + n_allocated_f_regs=0; + + for (n=0; nblock_graph_end_a_stack_size + -block_graph->block_graph_jsr_eval_offset-1)); + i_bne_l (block_graph->block_graph_last_instruction_label); +#else + i_move_id_r (0-NODE_POINTER_OFFSET,num_to_a_reg (block_graph->block_graph_end_a_stack_size + -block_graph->block_graph_jsr_eval_offset-1), + num_to_d_reg (n_allocated_d_regs)); +# ifdef M68000 + if (check_stack || parallel_flag) + i_bmi_l (block_graph->block_graph_last_instruction_label); + else + branch_offset_p=i_bmi_i(); +# else + i_btst_i_r (2,num_to_d_reg (n_allocated_d_regs)); +# ifdef G_POWER + i_bnep_l (block_graph->block_graph_last_instruction_label); +# else + i_bne_l (block_graph->block_graph_last_instruction_label); +# endif +# endif +#endif + break; + } +#ifdef G_POWER + case JSR_BLOCK_WITH_INSTRUCTIONS: + if (block_last_instruction!=NULL){ + if (last_block->block_instructions!=NULL) + last_instruction->instruction_next=block_instructions; + else + last_block->block_instructions=block_instructions; + + last_block->block_last_instruction=block_last_instruction; + last_instruction=block_last_instruction; + block_last_instruction=NULL; + } + /* no break */ +#endif + case JSR_BLOCK: + { + register int b_offset; + +#if ! (defined (sparc) || defined (G_POWER)) + b_offset=local_register_allocation_and_adjust_a_stack_pointer + (end_b_stack_size==global_block.block_graph_b_stack_end_displacement ? 4 : 0); +#else + b_offset=local_register_allocation_and_adjust_a_stack_pointer (0); +#endif + +#ifdef G_POWER + { + int return_offset; + + return_offset = (end_b_stack_size-global_block.block_graph_b_stack_end_displacement)<<2; + + if (return_offset==0 && b_offset!=0) + i_jsr_l_idu (block_graph->block_graph_last_instruction_label,b_offset); + else { + if (b_offset!=0) + if (b_offset<0) + i_sub_i_r (-b_offset,B_STACK_POINTER); + else + i_add_i_r (b_offset,B_STACK_POINTER); + i_jsr_l_id (block_graph->block_graph_last_instruction_label,return_offset); + } + } +#else + if (b_offset!=0) +# ifdef I486 + i_lea_id_r (b_offset,B_STACK_POINTER,B_STACK_POINTER); +# else + if (b_offset<0) + i_sub_i_r (-b_offset,B_STACK_POINTER); + else + i_add_i_r (b_offset,B_STACK_POINTER); +# endif + +# if ! defined (sparc) + { + int n_a_and_f_registers,n_a_registers; + + n_a_and_f_registers=0; + + if (mc68881_flag){ + int parameter_n; + ULONG *vector; + + vector=block_graph->block_graph_end_stack_vector; + + for (parameter_n=0; parameter_nblock_graph_end_a_stack_size; + if (n_a_registers>N_ADDRESS_PARAMETER_REGISTERS) + n_a_registers=N_ADDRESS_PARAMETER_REGISTERS; + n_a_and_f_registers+=n_a_registers<<4; + + if (end_b_stack_size!=global_block.block_graph_b_stack_end_displacement) + i_jmp_l (block_graph->block_graph_last_instruction_label,n_a_and_f_registers); + else + i_jsr_l (block_graph->block_graph_last_instruction_label,n_a_and_f_registers); + } +# else + i_jsr_l_id (block_graph->block_graph_last_instruction_label, + (end_b_stack_size-global_block.block_graph_b_stack_end_displacement)<<2); +# endif +#endif + if (block_check){ +#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS + int a_stack_change,b_stack_change; + + a_stack_change= + (next_block_graph->block_graph_begin_a_stack_size+ + next_block_graph->block_graph_a_stack_begin_displacement)- + (block_graph->block_graph_end_a_stack_size- + block_graph->block_graph_a_stack_end_displacement); + b_stack_change= + (next_block_graph->block_graph_begin_b_stack_size+ + next_block_graph->block_graph_b_stack_begin_displacement)- + (block_graph->block_graph_end_b_stack_size- + block_graph->block_graph_b_stack_end_displacement); + block_a_stack_displacement+=a_stack_change<<2; + block_b_stack_displacement+=b_stack_change<<2; + block_graph->block_graph_a_stack_displacement+=a_stack_change<<2; + block_graph->block_graph_b_stack_displacement+=b_stack_change<<2; +#else + int stack_change; + + stack_change= + (next_block_graph->block_graph_begin_a_stack_size+ + next_block_graph->block_graph_a_stack_begin_displacement)- + (block_graph->block_graph_end_a_stack_size- + block_graph->block_graph_a_stack_end_displacement)+ + (next_block_graph->block_graph_begin_b_stack_size+ + next_block_graph->block_graph_b_stack_begin_displacement)- + (block_graph->block_graph_end_b_stack_size- + block_graph->block_graph_b_stack_end_displacement); + block_stack_displacement+=stack_change<<2; + block_graph->block_graph_stack_displacement+=stack_change<<2; +#endif + } + + break; + } + case APPLY_BLOCK: + { + register int b_offset; + +#if defined (sparc) || defined (G_POWER) + b_offset=local_register_allocation_and_adjust_a_stack_pointer (-4); +#else + b_offset=local_register_allocation_and_adjust_a_stack_pointer (0); +#endif + + if (b_offset!=0) + if (b_offset<0) + i_sub_i_r (-b_offset,B_STACK_POINTER); + else + i_add_i_r (b_offset,B_STACK_POINTER); + +#if defined (I486) + i_move_id_r (0,REGISTER_A1,REGISTER_A2); + i_jsr_id (4-2,REGISTER_A2,0); +#else +# ifdef M68000 +# if !defined (SUN) + i_add_r_r (GLOBAL_DATA_REGISTER,REGISTER_A2); +# endif + i_jsr_id (0,REGISTER_A2,2<<4); +# else + i_jsr_id_id (0,REGISTER_A2,0); +# endif +#endif + break; + } + default: + internal_error_in_function ("generate_code_for_basic_block"); + } + + if (block_last_instruction!=NULL){ + if (last_block->block_instructions!=NULL){ + last_instruction->instruction_next=block_instructions; + last_block->block_last_instruction=block_last_instruction; + } else { + last_block->block_instructions=block_instructions; + last_block->block_last_instruction=block_last_instruction; + } + } else + last_block->block_last_instruction=last_instruction; + + if (block_graph->block_graph_kind==JSR_EVAL_BLOCK) +#ifdef M68000 + if (!check_stack && !parallel_flag){ + *branch_offset_p + = generate_code_for_jsr_eval (block_graph->block_graph_end_a_stack_size,n_allocated_d_regs, + n_allocated_f_regs,block_graph->block_graph_jsr_eval_offset); + } else +#endif + generate_code_for_jsr_eval + (block_graph->block_graph_end_a_stack_size,n_allocated_d_regs, + n_allocated_f_regs,block_graph->block_graph_jsr_eval_offset); + + last_block=old_last_block; +} + +static int optimize_jsr_eval (struct block_graph *block_graph,int a_stack_size,struct block_graph *next_block_graph) +{ + struct a_stack *a_element,*a_element_0; + struct a_stack *begin_a_element; + int offset,n; + INSTRUCTION_GRAPH graph; + + offset=block_graph->block_graph_a_stack_top_offset; + + a_element=block_graph->block_graph_a_stack; + while (a_element!=NULL && a_element->a_stack_offseta_stack_next; + + if (a_element==NULL || a_element->a_stack_offset!=offset) + return a_stack_size; + + a_element_0=a_element; + graph=a_element->a_stack_graph; + + begin_a_element=next_block_graph->block_graph_a_stack; + while (begin_a_element!=NULL && begin_a_element->a_stack_offset<0) + begin_a_element=begin_a_element->a_stack_next; + + if ((begin_a_element!=NULL && begin_a_element->a_stack_offset==0) + ? (begin_a_element->a_stack_load_graph!=NULL + && begin_a_element->a_stack_load_graph->node_mark) + : 0>=next_block_graph->block_graph_a_stack_top_offset + ) + return a_stack_size; + + for (n=1; na_stack_next; + if (a_element==NULL || a_element->a_stack_offset!=offset+n) + return a_stack_size; + if (a_element->a_stack_graph==graph) + break; + } + + if (n>=a_stack_size) + return a_stack_size; + + remove_end_stack_element + ((struct stack **)&block_graph->block_graph_a_stack,offset, + block_graph->block_graph_a_stack_begin_displacement, + block_graph->block_graph_a_stack_top_offset,0); + /* + a_element_0->a_stack_graph=NULL; + a_element_0->a_stack_flags &= ~ELEMENT_USED_BEFORE_JSR;; + */ + ++block_graph->block_graph_a_stack_top_offset; + block_graph->block_graph_jsr_eval_offset=n-1; + + remove_begin_stack_element + ((struct stack **)&next_block_graph->block_graph_a_stack,0,next_block_graph->block_graph_a_stack_begin_displacement, + next_block_graph->block_graph_a_stack_top_offset,0); + --next_block_graph->block_graph_a_stack_top_offset; + + return a_stack_size-1; +} + +void generate_code_for_previous_blocks (int jmp_jsr_or_rtn_flag) +{ + if (check_stack){ +#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS + a_check_size_p=NULL; + b_check_size_p=NULL; +#else + check_size_p=NULL; +#endif + block_check=1; + } + + if (last_block_graph!=NULL){ + struct block_graph *block_graph,*next_block_graph; + struct block_graph end_block_graph; + + last_block->block_last_instruction=last_instruction; + + end_block_graph=global_block; + + end_block_graph.block_graph_end_a_stack_size=0; + end_block_graph.block_graph_end_b_stack_size=0; + end_block_graph.block_graph_end_stack_vector=NULL; + + mark_stack_graphs_2 (&global_block); + + next_block_graph=&end_block_graph; + for_l (block_graph,last_block_graph,block_graph_previous){ + insert_dummy_graphs_for_unused_a_stack_elements (block_graph,next_block_graph); + insert_dummy_graphs_for_unused_b_stack_elements (block_graph,next_block_graph); + + mark_stack_graphs_1 (block_graph,next_block_graph,jmp_jsr_or_rtn_flag); + if (block_graph->block_graph_kind!=JSR_EVAL_BLOCK) + jmp_jsr_or_rtn_flag=1; + + next_block_graph=block_graph; + } + + for_l (block_graph,first_block_graph,block_graph_next){ + next_block_graph=block_graph->block_graph_next; + + if (next_block_graph==NULL) + next_block_graph=&end_block_graph; + + remove_not_used_a_stack_elements (block_graph,next_block_graph); + remove_not_used_b_stack_elements (block_graph,next_block_graph); + } + remove_not_used_stack_elements_from_last_block (&end_block_graph); + + for_l (block_graph,first_block_graph,block_graph_next){ + next_block_graph=block_graph->block_graph_next; + if (next_block_graph==NULL) + next_block_graph=&end_block_graph; + + if (block_graph->block_graph_kind!=JSR_EVAL_BLOCK){ + compute_a_load_offsets (next_block_graph->block_graph_a_stack, + next_block_graph->block_graph_a_stack_begin_displacement<<2); + compute_b_load_offsets (next_block_graph->block_graph_b_stack, + next_block_graph->block_graph_b_stack_begin_displacement<<2); + } else { + int a_stack_size,b_stack_size; + ULONG *vector; + + a_stack_size=count_a_stack_size (block_graph->block_graph_a_stack, + block_graph->block_graph_a_stack_top_offset); + if (a_stack_size<1) + a_stack_size=1; + else + if (a_stack_size>N_ADDRESS_PARAMETER_REGISTERS+1) + a_stack_size=N_ADDRESS_PARAMETER_REGISTERS+1; + + block_graph->block_graph_end_stack_vector= + &block_graph->block_graph_small_end_stack_vector; + b_stack_size=count_b_stack_size_2 + (&block_graph->block_graph_end_stack_vector, + block_graph->block_graph_b_stack, + block_graph->block_graph_b_stack_top_offset); + + vector=block_graph->block_graph_end_stack_vector; + + a_stack_size=optimize_jsr_eval (block_graph,a_stack_size,next_block_graph); + + if (a_stack_size>N_ADDRESS_PARAMETER_REGISTERS) + a_stack_size=N_ADDRESS_PARAMETER_REGISTERS; + block_graph->block_graph_end_a_stack_size=a_stack_size; + block_graph->block_graph_end_b_stack_size=b_stack_size; + + if (block_graph->block_graph_next!=NULL) + next_block_graph->block_graph_block->block_n_begin_a_parameter_registers=a_stack_size; + else + last_block->block_n_begin_a_parameter_registers=a_stack_size; + + next_block_graph->block_graph_a_stack_begin_displacement= + set_basic_block_begin_a_registers + (&next_block_graph->block_graph_a_stack,a_stack_size, + next_block_graph->block_graph_a_register_parameter_node); + compute_a_load_offsets (next_block_graph->block_graph_a_stack, + next_block_graph->block_graph_a_stack_begin_displacement<<2); + + next_block_graph->block_graph_b_stack_begin_displacement= + set_basic_block_begin_d_registers + (&next_block_graph->block_graph_b_stack,b_stack_size, + block_graph->block_graph_end_stack_vector, + next_block_graph->block_graph_d_register_parameter_node, + next_block_graph->block_graph_f_register_parameter_node +#ifdef MORE_PARAMETER_REGISTERS + ,N_ADDRESS_PARAMETER_REGISTERS - a_stack_size, + next_block_graph->block_graph_a_register_parameter_node +#endif + ); + compute_b_load_offsets (next_block_graph->block_graph_b_stack, + next_block_graph->block_graph_b_stack_begin_displacement<<2); + } + } + + for_l (block_graph,first_block_graph,block_graph_next){ + struct block_graph *next_block_graph; + + last_block_graph=block_graph; + next_block_graph=block_graph->block_graph_next; + if (next_block_graph==NULL) + next_block_graph=&end_block_graph; + generate_code_for_basic_block (next_block_graph); + } + + if (check_stack){ +#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS + if (a_check_size_p!=NULL){ + struct block_graph *block_graph; + int a_stack_displacement,b_stack_displacement; + + a_stack_displacement=0; + b_stack_displacement=0; + for_l (block_graph,first_block_graph,block_graph_next){ + a_stack_displacement+=block_graph->block_graph_a_stack_displacement; + b_stack_displacement+=block_graph->block_graph_b_stack_displacement; + + if (block_graph->block_graph_kind==JSR_EVAL_BLOCK){ + struct basic_block *block; + int a_check_size,b_check_size; + + if (block_graph->block_graph_block==NULL || block_graph->block_graph_block->block_next==NULL) + internal_error_in_function ("generate_code_for_previous_blocks"); + + block=block_graph->block_graph_block->block_next; + a_check_size=block->block_a_stack_check_size; + b_check_size=block->block_b_stack_check_size; + + if (a_check_size>0 && a_stack_displacement+a_check_size<=*a_check_size_p) + block->block_a_stack_check_size=0; + if (b_check_size>0 && b_stack_displacement+b_check_size<=*b_check_size_p) + block->block_b_stack_check_size=0; + } + } + } +#else + if (check_size_p!=NULL){ + struct block_graph *block_graph; + int stack_displacement; + + stack_displacement=0; + for_l (block_graph,first_block_graph,block_graph_next){ + stack_displacement+=block_graph->block_graph_stack_displacement; + + if (block_graph->block_graph_kind==JSR_EVAL_BLOCK){ + struct basic_block *block; + int check_size; + + if (block_graph->block_graph_block==NULL || block_graph->block_graph_block->block_next==NULL) + internal_error_in_function ("generate_code_for_previous_blocks"); + + block=block_graph->block_graph_block->block_next; + check_size=block->block_stack_check_size; + + if (check_size>0 && stack_displacement+check_size<=*check_size_p) + block->block_stack_check_size=0; + } + } + } +#endif + block_check=0; + } + + first_block_graph=last_block_graph=NULL; + + global_block=end_block_graph; + + global_block.block_graph_end_a_stack_size=0; + global_block.block_graph_end_b_stack_size=0; + global_block.block_graph_end_stack_vector=NULL; + + last_instruction=last_block->block_last_instruction; + } +} + +int end_basic_block_with_registers_and_return_b_stack_offset (int n_a_parameters,int n_b_parameters,ULONG vector[],int n_address_parameter_registers) +{ + int b_stack_offset; + + a_stack_load_register_values (n_a_parameters,n_address_parameter_registers); + b_stack_load_register_values (n_b_parameters,vector,parallel_flag ? N_DATA_PARAMETER_REGISTERS-1: N_DATA_PARAMETER_REGISTERS +#ifdef MORE_PARAMETER_REGISTERS + ,n_address_parameter_registers-n_a_parameters +#endif + ); + + generate_code_for_previous_blocks (1); + + a_stack_stores (n_a_parameters,n_address_parameter_registers); + b_stack_stores (n_b_parameters,vector,parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS +#ifdef MORE_PARAMETER_REGISTERS + ,n_address_parameter_registers-n_a_parameters, + global_block.block_graph_a_register_parameter_node,global_block.block_graph_d_register_parameter_node +#endif + ); + + linearize_stack_graphs(); + b_stack_offset=local_register_allocation_and_adjust_a_stack_pointer (0); + + return b_stack_offset; +} + +void end_basic_block_with_registers (int n_a_parameters,int n_b_parameters,ULONG vector[]) +{ + int b_offset; + + b_offset=end_basic_block_with_registers_and_return_b_stack_offset (n_a_parameters,n_b_parameters,vector,N_ADDRESS_PARAMETER_REGISTERS); + + if (b_offset!=0) +#ifdef I486 + i_lea_id_r (b_offset,B_STACK_POINTER,B_STACK_POINTER); +#else + if (b_offset>0) + i_add_i_r (b_offset,B_STACK_POINTER); + else + i_sub_i_r (-b_offset,B_STACK_POINTER); +#endif +} + +void end_stack_elements (int n_a_parameters,int n_b_parameters,ULONG vector[]) +{ + int n_data_parameter_registers; + + n_data_parameter_registers = parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS; + + a_stack_load_register_values (n_a_parameters,N_ADDRESS_PARAMETER_REGISTERS); + b_stack_load_register_values (n_b_parameters,vector,n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + ,N_ADDRESS_PARAMETER_REGISTERS-n_a_parameters +#endif + ); + + a_stack_stores (n_a_parameters,N_ADDRESS_PARAMETER_REGISTERS); + b_stack_stores (n_b_parameters,vector,n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + ,N_ADDRESS_PARAMETER_REGISTERS-n_a_parameters, + global_block.block_graph_a_register_parameter_node,global_block.block_graph_d_register_parameter_node +#endif + ); +} + +void begin_new_basic_block (VOID) +{ + last_block->block_last_instruction=last_instruction; + + last_instruction=NULL; + + last_block->block_next=allocate_empty_basic_block(); + last_block=last_block->block_next; + + release_a_stack(); + release_b_stack(); + + release_heap(); + + load_indexed_list=NULL; +} + +void insert_basic_block (int block_graph_kind,int a_stack_size,int b_stack_size,ULONG *vector_p,LABEL *label) +{ + struct block_graph *new_block; + + last_block->block_last_instruction=last_instruction; + + new_block=allocate_struct_from_heap (block_graph); + + *new_block=global_block; + + new_block->block_graph_kind=block_graph_kind; + new_block->block_graph_block=last_block; + + new_block->block_graph_used_a_stack_elements=block_graph_kind==JSR_EVAL_BLOCK ? 1 : a_stack_size; + new_block->block_graph_used_b_stack_elements=b_stack_size; + + new_block->block_graph_end_a_stack_size=a_stack_size; + new_block->block_graph_end_b_stack_size=b_stack_size; + + if (b_stack_size<=VECTOR_ELEMENT_SIZE){ + new_block->block_graph_small_end_stack_vector=*vector_p; + new_block->block_graph_end_stack_vector=&new_block->block_graph_small_end_stack_vector; + } else { + int vector_size; + ULONG *vector,*old_vector; + + vector_size=(b_stack_size+VECTOR_ELEMENT_SIZE-1)>>LOG_VECTOR_ELEMENT_SIZE; + vector=(ULONG*)fast_memory_allocate (vector_size * sizeof (ULONG)); + label->label_vector=vector; + new_block->block_graph_end_stack_vector=vector; + + old_vector=vector_p; + while (vector_size>0){ + *vector++=*old_vector++; + --vector_size; + } + } + + new_block->block_graph_jsr_eval_offset=0; + new_block->block_graph_last_instruction_label=label; + + if (last_block_graph==NULL) + first_block_graph=new_block; + else + last_block_graph->block_graph_next=new_block; + new_block->block_graph_previous=last_block_graph; + new_block->block_graph_next=NULL; + last_block_graph=new_block; + + last_instruction=NULL; + + last_block->block_next=allocate_empty_basic_block(); + last_block=last_block->block_next; + + release_a_stack(); + release_b_stack(); + + load_indexed_list=NULL; +} + +void insert_basic_block_with_extra_parameters_on_stack (int block_graph_kind,int a_stack_size,int b_stack_size,ULONG *vector_p, + int extra_a_stack_size,int extra_b_stack_size,LABEL *label) +{ + insert_basic_block (block_graph_kind,a_stack_size,b_stack_size,vector_p,label); + + last_block_graph->block_graph_used_a_stack_elements+=extra_a_stack_size; + last_block_graph->block_graph_used_b_stack_elements+=extra_b_stack_size; +} + +void initialize_stacks (VOID) +{ + release_a_stack(); + + release_b_stack(); + + last_block_graph=NULL; + first_block_graph=NULL; + + block_check=0; + + load_indexed_list=NULL; +} diff --git a/cgstack.h b/cgstack.h new file mode 100644 index 0000000..e47f8b5 --- /dev/null +++ b/cgstack.h @@ -0,0 +1,51 @@ + +#define VECTOR_ELEMENT_SIZE 32 +#define VECTOR_ELEMENT_MASK 31 +#define LOG_VECTOR_ELEMENT_SIZE 5 + +#define test_bit(v,b) ((v)[(b)>>5] & (((ULONG)1) << ((b) & 31))) +#define clear_bit(v,b) (v)[(b)>>5] &= ~(((ULONG)1) << ((b) & 31)) +#define set_bit(v,b) (v)[(b)>>5] |= (((ULONG)1) << ((b) & 31)) + +extern INSTRUCTION_GRAPH s_get_b (int offset); +extern INSTRUCTION_GRAPH s_get_a (int offset); +extern INSTRUCTION_GRAPH s_pop_a (VOID); +extern INSTRUCTION_GRAPH s_pop_b (VOID); +extern void s_put_b (int offset,INSTRUCTION_GRAPH graph); +extern void s_put_a (int offset,INSTRUCTION_GRAPH graph); +extern void s_push_a (INSTRUCTION_GRAPH graph); +extern void s_push_b (INSTRUCTION_GRAPH graph); +extern void s_remove_a (VOID); +extern void s_remove_b (VOID); + +extern void initialize_stacks (VOID); +extern void init_a_stack (int a_stack_size); +extern void init_b_stack (int b_stack_size,ULONG vector[]); +#ifdef MORE_PARAMETER_REGISTERS +void init_ab_stack (int a_stack_size,int b_stack_size,ULONG vector[]); +#endif +extern int get_a_stack_size (VOID); +extern int get_b_stack_size (ULONG *vector_p[]); +extern void release_a_stack (VOID); +extern void release_b_stack (VOID); +extern void insert_graph_in_b_stack (INSTRUCTION_GRAPH graph,int b_stack_size,ULONG *vector); + +extern struct basic_block *allocate_empty_basic_block (VOID); +extern void generate_code_for_previous_blocks (int jmp_jsr_or_rtn_flag); +extern void begin_new_basic_block (VOID); +extern void insert_basic_block (int block_graph_kind,int a_stack_size,int b_stack_size,ULONG *vector_p,LABEL *label); +extern void insert_basic_block_with_extra_parameters_on_stack (int block_graph_kind,int a_stack_size,int b_stack_size, + ULONG *vector_p,int extra_a_stack_size,int extra_b_stack_size,LABEL *label); + +extern void adjust_stack_pointers (VOID); +extern void end_basic_block_with_registers (int n_a_parameters,int n_b_parameters,ULONG vector[]); +extern int end_basic_block_with_registers_and_return_b_stack_offset + (int n_a_parameters,int n_b_parameters,ULONG vector[],int n_adress_parameter_registers); +extern void end_stack_elements (int n_a_parameters,int n_b_parameters,ULONG vector[]); +extern int adjust_stack_pointers_without_altering_condition_codes (int float_condition,int condition); +extern void linearize_stack_graphs (VOID); + +extern INSTRUCTION_GRAPH search_and_remove_graph_from_b_stack (INSTRUCTION_GRAPH calculate_with_overflow_graph); +extern void linearize_stack_graphs_with_overflow_test (INSTRUCTION_GRAPH test_overflow_graph,INSTRUCTION_GRAPH store_calculate_with_overflow_graph); + +extern struct block_graph global_block; diff --git a/cgswas.c b/cgswas.c new file mode 100644 index 0000000..55d8dea --- /dev/null +++ b/cgswas.c @@ -0,0 +1,2446 @@ +/* + File: cgswas.c + Author: John van Groningen + Machine: Sun 4 + At: University of Nijmegen +*/ + +#include +#include + +#include "cgport.h" +#include "cgrconst.h" +#include "cgtypes.h" +#include "cg.h" +#include "cgiconst.h" +#include "cgcode.h" +#include "cgswas.h" + +#define GAS + +#define IO_BUF_SIZE 8192 + +#define SP_G5 + +static FILE *assembly_file; + +static void w_as_newline (VOID) +{ + putc ('\n',assembly_file); +} + +static void w_as_opcode (char *opcode) +{ + fprintf (assembly_file,"\t%s\t",opcode); +} + +static void w_as_instruction_without_parameters (char *opcode) +{ + fprintf (assembly_file,"\t%s\n",opcode); +} + +static void w_as_define_local_label (int label_number) +{ + fprintf (assembly_file,"l_%d:\n",label_number); +} + +static void w_as_define_internal_label (int label_number) +{ + fprintf (assembly_file,"i_%d:\n",label_number); +} + +void w_as_internal_label_value (int label_id) +{ + fprintf (assembly_file,"\t.word\ti_%d\n",label_id); +} + +static int in_data_section; + +void w_as_to_data_section (VOID) +{ + if (!in_data_section){ + in_data_section=1; + w_as_instruction_without_parameters (".data"); + } +} + +static void w_as_to_code_section (VOID) +{ + if (in_data_section){ + in_data_section=0; + w_as_instruction_without_parameters (".text"); + } +} + +void w_as_word_in_data_section (int n) +{ + w_as_to_data_section(); + w_as_opcode (".half"); + fprintf (assembly_file,"%d",n); + w_as_newline(); +} + +void w_as_long_in_data_section (int n) +{ + w_as_to_data_section(); + w_as_opcode (".word"); + fprintf (assembly_file,"%d",n); + w_as_newline(); +} + +void w_as_label_in_data_section (char *label_name) +{ + w_as_to_data_section (); + fprintf (assembly_file,"\t.word\t%s\n",label_name); +} + +static void w_as_label_in_code_section (char *label_name) +{ + w_as_to_code_section (); + fprintf (assembly_file,"\t.word\t%s\n",label_name); +} + +void w_as_descriptor_in_data_section (char *label_name) +{ + w_as_to_data_section (); + fprintf (assembly_file,"\t.word\t%s+2\n",label_name); +} + +#define MAX_BYTES_PER_LINE 16 + +static int w_as_data (register int n,register unsigned char *data,register int length) +{ + register int i,in_string; + + in_string=0; + + for (i=0; i=MAX_BYTES_PER_LINE){ + if (in_string){ + putc ('\"',assembly_file); + in_string=0; + } + w_as_newline(); + n=0; + } + + c=data[i]; + if (isalnum (c) || c=='_' || c==' '){ + if (!in_string){ + if (n!=0) + w_as_newline(); + w_as_opcode (".ascii"); + putc ('\"',assembly_file); + in_string=1; + } + putc (c,assembly_file); + } else { + if (n==0) + w_as_opcode (".byte"); + else { + if (in_string){ + putc ('\"',assembly_file); + w_as_newline(); + w_as_opcode (".byte"); + in_string=0; + } else + putc (',',assembly_file); + } + + fprintf (assembly_file,"0x%02x",c); + } + ++n; + } + + if (in_string){ + putc ('\"',assembly_file); + w_as_newline(); + return 0; + } else + return n; +} + +static int w_as_zeros (register int n,register int length) +{ + register int i; + + for (i=0; i=MAX_BYTES_PER_LINE){ + w_as_newline(); + n=0; + } + if (n==0) + w_as_opcode (".byte"); + else + putc (',',assembly_file); + fprintf (assembly_file,"0"); + ++n; + } + return n; +} + +void w_as_c_string_in_data_section (char *string,int length) +{ + register int n; + + w_as_to_data_section(); + + n=w_as_data (0,string,length); + n=w_as_zeros (n,4-(length & 3)); +/* n=w_as_zeros (n,length & 1 ? 1 : 2); */ + if (n>0) + w_as_newline(); +} + +void w_as_define_data_label (int label_number) +{ + w_as_to_data_section(); + + w_as_define_local_label (label_number); +} + +void w_as_labeled_c_string_in_data_section (char *string,int length,int label_number) +{ + int n; + + w_as_to_data_section(); + + w_as_define_local_label (label_number); + + n=w_as_data (0,string,length); + if (length & 3) + n=w_as_zeros (n,4-(length & 3)); + else + n=w_as_zeros (n,4); + if (n>0) + w_as_newline(); +} + +void w_as_abc_string_in_data_section (char *string,int length) +{ + int n; + + w_as_to_data_section(); + + w_as_opcode (".word"); + fprintf (assembly_file,"%d\n",length); + n=w_as_data (0,string,length); + if (length & 3) + n=w_as_zeros (n,4-(length & 3)); + if (n>0) + w_as_newline(); +} + +void w_as_descriptor_string_in_data_section + (char *string,int length,int string_label_id,LABEL *string_label) +{ + int n; + + w_as_to_data_section(); + + w_as_define_internal_label (string_label_id); + w_as_define_local_label (string_label->label_number); + + w_as_opcode (".word"); + fprintf (assembly_file,"%d\n",length); + n=w_as_data (0,string,length); + if (length & 3) + n=w_as_zeros (n,4-(length & 3)); + if (n>0) + w_as_newline(); +} + +enum { SIZE_LONG, SIZE_WORD, SIZE_BYTE }; + +static void w_as_opcode_and_d (char *opcode) +{ + fprintf (assembly_file,"\t%sd\t",opcode); +} + +static void w_as_label (char *label) +{ + int c; + + while (c=*label++,c!=0) + putc (c,assembly_file); +} + +static void w_as_colon (VOID) +{ + putc (':',assembly_file); +} + +static void w_as_define_label_name (char *label_name) +{ + w_as_label (label_name); + w_as_colon(); + w_as_newline(); +} + +void w_as_define_label (LABEL *label) +{ + if (label->label_flags & EXPORT_LABEL){ + w_as_opcode (".global"); + w_as_label (label->label_name); + w_as_newline(); + } + + w_as_label (label->label_name); + w_as_colon(); + w_as_newline(); +} + +static void w_as_local_label (int label_number) +{ + fprintf (assembly_file,"l_%d",label_number); +} + +static void w_as_internal_label (int label_number) +{ + fprintf (assembly_file,"i_%d",label_number); +} + +static void w_as_immediate (LONG i) +{ + fprintf (assembly_file,"%ld",i); +} + +void w_as_abc_string_and_label_in_data_section (char *string,int length,char *label_name) +{ + int n; + + w_as_to_data_section(); + + w_as_define_label_name (label_name); + + w_as_opcode (".long"); + fprintf (assembly_file,"%d\n",length); + n=w_as_data (0,string,length); + if (length & 3) + n=w_as_zeros (n,4-(length & 3)); + if (n>0) + w_as_newline(); +} + +static char register_type [32]="ggggggiiggiiiiiilllllllloooooooo"; +#ifdef SP_G5 +static char register_number[32]="01234767565432100123456701234567"; +#else +static char register_number[32]="01234567765432100123456701234567"; +#endif + +#define REGISTER_G0 (-16) +#define REGISTER_G5 (-11) +#define REGISTER_I6 (-10) +#define REGISTER_O0 8 +#define REGISTER_O1 9 +#define REGISTER_O7 15 + +static void w_as_indirect (int i,int reg) +{ + if (i!=0){ + if (i>0) + fprintf (assembly_file,"[%%%c%c+%d]",register_type[reg+16],register_number[reg+16],i); + else + fprintf (assembly_file,"[%%%c%c-%d]",register_type[reg+16],register_number[reg+16],-i); + } else + fprintf (assembly_file,"[%%%c%c]",register_type[reg+16],register_number[reg+16]); +} + +static void w_as_indexed (int offset,struct index_registers *index_registers) +{ + int reg1,reg2; + + if (offset!=0) + internal_error_in_function ("w_as_indexed"); + + reg1=index_registers->a_reg.r; + reg2=index_registers->d_reg.r; + fprintf (assembly_file,"[%%%c%c+%%%c%c]", + register_type[reg1+16],register_number[reg1+16], + register_type[reg2+16],register_number[reg2+16]); +} + +static void w_as_register (int reg) +{ + putc ('%',assembly_file); + putc (register_type[reg+16],assembly_file); + putc (register_number[reg+16],assembly_file); +} + +static void w_as_register_comma (int reg) +{ + putc ('%',assembly_file); + putc (register_type[reg+16],assembly_file); + putc (register_number[reg+16],assembly_file); + putc (',',assembly_file); +} + +static void w_as_register_newline (int reg) +{ + putc ('%',assembly_file); + putc (register_type[reg+16],assembly_file); + putc (register_number[reg+16],assembly_file); + putc ('\n',assembly_file); +} + +void w_as_c_string_and_label_in_code_section (char *string,int length,char *label_name) +{ + register int n; + +/* w_as_to_code_section(); */ + w_as_to_data_section(); + + w_as_define_label_name (label_name); + + n=w_as_data (0,string,length); + n=w_as_zeros (n,4-(length & 3)); + if (n>0) + w_as_newline(); +} + +static void w_as_scratch_register (void) +{ + w_as_register (REGISTER_O0); +} + +static void w_as_fp_register (int fp_reg) +{ + fprintf (assembly_file,"%%f%d",fp_reg); +} + +static void w_as_opcode_descriptor (char *opcode,char *label_name,int arity) +{ + w_as_opcode (opcode); + fprintf (assembly_file,"%s+0x%x",label_name,2/* 0x80000000 */+(arity<<3)); +} + +static void w_as_comma (VOID) +{ + putc (',',assembly_file); +} + +static void w_as_opcode_indirect (char *opcode,int offset,int reg) +{ + if (((offset << (32-13)) >> (32-13))==offset){ + w_as_opcode (opcode); + w_as_indirect (offset,reg); + } else { + w_as_opcode ("sethi"); + w_as_immediate (offset>>10); + w_as_comma(); + w_as_register (REGISTER_O1); + w_as_newline(); + + w_as_opcode ("add"); + w_as_register (REGISTER_O1); + w_as_comma(); + w_as_register (reg); + w_as_comma(); + w_as_register (REGISTER_O1); + w_as_newline(); + + w_as_opcode (opcode); + w_as_indirect (offset & 1023,REGISTER_O1); + } +} + +static void w_as_parameter (struct parameter *parameter) +{ + switch (parameter->parameter_type){ + case P_REGISTER: + w_as_register (parameter->parameter_data.reg.r); + break; + case P_LABEL: + if (parameter->parameter_data.l->label_number!=0) + w_as_local_label (parameter->parameter_data.l->label_number); + else + w_as_label (parameter->parameter_data.l->label_name); + break; + case P_INDIRECT: + w_as_indirect (parameter->parameter_offset,parameter->parameter_data.reg.r); + break; + case P_INDEXED: + w_as_indexed (parameter->parameter_offset,parameter->parameter_data.ir); + break; + case P_IMMEDIATE: + fprintf (assembly_file,"%ld",parameter->parameter_data.i); + break; + case P_F_REGISTER: + fprintf (assembly_file,"%%f%d",parameter->parameter_data.reg.r<<1); + break; + default: + internal_error_in_function ("w_as_parameter"); + } +} + +static void w_as_ld_parameter (struct parameter *parameter) +{ + if (parameter->parameter_type!=P_INDIRECT){ + w_as_opcode ("ld"); + w_as_parameter (parameter); + } else + w_as_opcode_indirect ("ld",parameter->parameter_offset,parameter->parameter_data.reg.r); +} + +static void w_as_opcode_parameter (char *opcode,struct parameter *parameter) +{ + if (parameter->parameter_type!=P_INDIRECT){ + w_as_opcode (opcode); + w_as_parameter (parameter); + } else + w_as_opcode_indirect (opcode,parameter->parameter_offset,parameter->parameter_data.reg.r); +} + +static void w_as_jump_parameter (register struct parameter *parameter) +{ + switch (parameter->parameter_type){ + case P_LABEL: + if (parameter->parameter_data.l->label_number!=0) + w_as_local_label (parameter->parameter_data.l->label_number); + else + w_as_label (parameter->parameter_data.l->label_name); + break; + case P_INDIRECT: + { + int offset,reg; + + offset=parameter->parameter_offset; + reg=parameter->parameter_data.reg.r; + + if (offset!=0) + fprintf (assembly_file,"%%%c%c+%d", + register_type[reg+16],register_number[reg+16],offset); + else + fprintf (assembly_file,"%%%c%c", + register_type[reg+16],register_number[reg+16]); + break; + } + default: + internal_error_in_function ("w_as_jump_parameter"); + } +} + +static struct parameter w_as_register_parameter (struct parameter parameter,int size_flag) +{ + switch (parameter.parameter_type){ + case P_DESCRIPTOR_NUMBER: + w_as_opcode_descriptor ("set", + parameter.parameter_data.l->label_name, + parameter.parameter_offset + ); + w_as_comma(); + w_as_register (REGISTER_O0); + w_as_newline(); + + parameter.parameter_type=P_REGISTER; + parameter.parameter_data.reg.r=REGISTER_O0; + break; + case P_IMMEDIATE: + if (parameter.parameter_data.i==0){ + parameter.parameter_type=P_REGISTER; + parameter.parameter_data.reg.r=REGISTER_G0; + } else { + w_as_opcode ("set"); + w_as_immediate (parameter.parameter_data.i); + w_as_comma(); + w_as_register (REGISTER_O0); + w_as_newline(); + + parameter.parameter_type=P_REGISTER; + parameter.parameter_data.reg.r=REGISTER_O0; + } + break; + case P_REGISTER: + break; + case P_INDIRECT: + w_as_opcode_indirect ( size_flag==SIZE_LONG ? "ld" : size_flag==SIZE_WORD ? "ldsh" : "ldub", + parameter.parameter_offset,parameter.parameter_data.reg.r); + w_as_comma(); + w_as_register (REGISTER_O0); + w_as_newline(); + + parameter.parameter_type=P_REGISTER; + parameter.parameter_data.reg.r=REGISTER_O0; + break; + case P_INDEXED: + w_as_opcode (size_flag==SIZE_LONG ? "ld" : size_flag==SIZE_WORD ? "ldsh" : "ldub"); + w_as_indexed (parameter.parameter_offset,parameter.parameter_data.ir); + w_as_comma(); + w_as_register (REGISTER_O0); + w_as_newline(); + + parameter.parameter_type=P_REGISTER; + parameter.parameter_data.reg.r=REGISTER_O0; + break; + default: + internal_error_in_function ("w_as_register_parameter"); + } + return parameter; +} + +static void w_as_move_instruction (struct instruction *instruction,int size_flag) +{ + switch (instruction->instruction_parameters[1].parameter_type){ + case P_REGISTER: + switch (instruction->instruction_parameters[0].parameter_type){ + case P_DESCRIPTOR_NUMBER: + w_as_opcode_descriptor ("set", + instruction->instruction_parameters[0].parameter_data.l->label_name, + instruction->instruction_parameters[0].parameter_offset + ); + break; + case P_IMMEDIATE: + w_as_opcode ("set"); + w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); + break; + case P_REGISTER: + w_as_opcode ("mov"); + w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); + break; + case P_INDIRECT: + w_as_opcode_indirect ( size_flag==SIZE_LONG ? "ld" : size_flag==SIZE_WORD ? "ldsh" : "ldub", + instruction->instruction_parameters[0].parameter_offset, + instruction->instruction_parameters[0].parameter_data.reg.r); + break; + case P_INDEXED: + w_as_opcode (size_flag==SIZE_LONG ? "ld" : size_flag==SIZE_WORD ? "ldsh" : "ldub"); + w_as_indexed (instruction->instruction_parameters[0].parameter_offset, + instruction->instruction_parameters[0].parameter_data.ir); + break; + default: + internal_error_in_function ("w_as_move_instruction"); + return; + } + w_as_comma(); + w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); + return; + case P_INDIRECT: + { + struct parameter parameter_0; + int offset; + + parameter_0=w_as_register_parameter (instruction->instruction_parameters[0],size_flag); + + offset=instruction->instruction_parameters[1].parameter_offset; + + if (((offset << (32-13)) >> (32-13))==offset){ + w_as_opcode (size_flag==SIZE_LONG ? "st" : size_flag==SIZE_WORD ? "sth" : "stb"); + w_as_register (parameter_0.parameter_data.reg.r); + w_as_comma(); + w_as_indirect (offset,instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); + } else { + w_as_opcode ("sethi"); + w_as_immediate (offset>>10); + w_as_comma(); + w_as_register (REGISTER_O1); + w_as_newline(); + + w_as_opcode ("add"); + w_as_register (REGISTER_O1); + w_as_comma(); + w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_comma(); + w_as_register (REGISTER_O1); + w_as_newline(); + + w_as_opcode (size_flag==SIZE_LONG ? "st" : size_flag==SIZE_WORD ? "sth" : "stb"); + w_as_register (parameter_0.parameter_data.reg.r); + w_as_comma(); + w_as_indirect (offset & 1023,REGISTER_O1); + w_as_newline(); + } + + return; + } + case P_INDEXED: + { + struct parameter parameter_0; + + parameter_0=w_as_register_parameter (instruction->instruction_parameters[0],size_flag); + + w_as_opcode (size_flag==SIZE_LONG ? "st" : size_flag==SIZE_WORD ? "sth" : "stb"); + w_as_register (parameter_0.parameter_data.reg.r); + w_as_comma(); + w_as_indexed (instruction->instruction_parameters[1].parameter_offset, + instruction->instruction_parameters[1].parameter_data.ir); + w_as_newline(); + return; + } + default: + internal_error_in_function ("w_as_move_instruction"); + } +} + +static void w_as_lea_instruction (struct instruction *instruction) +{ + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER) + switch (instruction->instruction_parameters[0].parameter_type){ + case P_LABEL: + w_as_opcode ("set"); + w_as_parameter (&instruction->instruction_parameters[0]); + if (instruction->instruction_parameters[0].parameter_offset!=0){ + int offset; + + offset=instruction->instruction_parameters[0].parameter_offset; + fprintf (assembly_file,offset>=0 ? "+%d" : "%d",offset); + } + w_as_comma(); + w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); + return; + case P_INDIRECT: + w_as_opcode ("add"); + w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_comma(); + w_as_immediate (instruction->instruction_parameters[0].parameter_offset); + w_as_comma(); + w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); + return; + case P_INDEXED: + w_as_opcode ("add"); + w_as_register (instruction->instruction_parameters[0].parameter_data.ir->a_reg.r); + w_as_comma(); + w_as_register (instruction->instruction_parameters[0].parameter_data.ir->d_reg.r); + w_as_comma(); + w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); + return; + } + + internal_error_in_function ("w_as_lea_instruction"); +} + +static void w_as_i_instruction (struct instruction *instruction,char *opcode) +{ + w_as_opcode (opcode); + w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_comma(); + w_as_immediate (instruction->instruction_parameters[2].parameter_data.i); + w_as_comma(); + w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); +} + +static void w_as_tryadic_instruction (struct instruction *instruction,char *opcode) +{ + struct parameter parameter; + + parameter=instruction->instruction_parameters[0]; + + switch (parameter.parameter_type){ + case P_IMMEDIATE: + if ((unsigned)(parameter.parameter_data.i+4096)>=(unsigned)8192){ + w_as_opcode ("set"); + w_as_immediate (parameter.parameter_data.i); + w_as_comma(); + w_as_register (REGISTER_O0); + w_as_newline(); + + parameter.parameter_type=P_REGISTER; + parameter.parameter_data.reg.r=REGISTER_O0; + } + break; + case P_INDIRECT: + w_as_opcode_indirect ("ld",parameter.parameter_offset,parameter.parameter_data.reg.r); + w_as_comma(); + w_as_register (REGISTER_O0); + w_as_newline(); + + parameter.parameter_type=P_REGISTER; + parameter.parameter_data.reg.r=REGISTER_O0; + break; + case P_INDEXED: + w_as_opcode ("ld"); + w_as_indexed (parameter.parameter_offset,parameter.parameter_data.ir); + w_as_comma(); + w_as_register (REGISTER_O0); + w_as_newline(); + + parameter.parameter_type=P_REGISTER; + parameter.parameter_data.reg.r=REGISTER_O0; + } + + w_as_opcode (opcode); + w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_comma(); + w_as_parameter (¶meter); + w_as_comma(); + w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); +} + +static void w_as_add_instruction (struct instruction *instruction) +{ + switch (instruction->instruction_parameters[0].parameter_type){ + case P_REGISTER: + w_as_opcode ("add"); + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); + return; + case P_IMMEDIATE: + if ((unsigned)(instruction->instruction_parameters[0].parameter_data.i+4096)<(unsigned)8192){ + w_as_opcode ("inc"); + w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); + w_as_comma(); + w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); + return; + } else { + w_as_opcode ("set"); + w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); + w_as_comma(); + w_as_scratch_register(); + w_as_newline(); + + w_as_opcode ("add"); + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_scratch_register(); + w_as_comma(); + w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); + return; + } + default: + w_as_ld_parameter (&instruction->instruction_parameters[0]); + w_as_comma(); + w_as_scratch_register(); + w_as_newline(); + + w_as_opcode ("add"); + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_scratch_register(); + w_as_comma(); + w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); + } +} + +static void w_as_add_o_instruction (struct instruction *instruction) +{ + switch (instruction->instruction_parameters[0].parameter_type){ + case P_REGISTER: + w_as_opcode ("addcc"); + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); + return; + case P_IMMEDIATE: + if ((unsigned)(instruction->instruction_parameters[0].parameter_data.i+4096)<(unsigned)8192){ + w_as_opcode ("inccc"); + w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); + w_as_comma(); + w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); + return; + } else { + w_as_opcode ("set"); + w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); + w_as_comma(); + w_as_scratch_register(); + w_as_newline(); + + w_as_opcode ("addcc"); + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_scratch_register(); + w_as_comma(); + w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); + return; + } + default: + w_as_ld_parameter (&instruction->instruction_parameters[0]); + w_as_comma(); + w_as_scratch_register(); + w_as_newline(); + + w_as_opcode ("addcc"); + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_scratch_register(); + w_as_comma(); + w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); + } +} + +static void w_as_sub_instruction (struct instruction *instruction) +{ + switch (instruction->instruction_parameters[0].parameter_type){ + case P_REGISTER: + w_as_opcode ("sub"); + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); + return; + case P_IMMEDIATE: + if ((unsigned)(instruction->instruction_parameters[0].parameter_data.i+4096)<(unsigned)8192){ + w_as_opcode ("dec"); + w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); + w_as_comma(); + w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); + return; + } else { + w_as_opcode ("set"); + w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); + w_as_comma(); + w_as_scratch_register(); + w_as_newline(); + + w_as_opcode ("sub"); + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_scratch_register(); + w_as_comma(); + w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); + return; + } + default: + w_as_ld_parameter (&instruction->instruction_parameters[0]); + w_as_comma(); + w_as_scratch_register(); + w_as_newline(); + + w_as_opcode ("sub"); + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_scratch_register(); + w_as_comma(); + w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); + } +} + +static void w_as_sub_o_instruction (struct instruction *instruction) +{ + switch (instruction->instruction_parameters[0].parameter_type){ + case P_REGISTER: + w_as_opcode ("subcc"); + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_register_comma (instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); + return; + case P_IMMEDIATE: + if ((unsigned)(instruction->instruction_parameters[0].parameter_data.i+4096)<(unsigned)8192){ + w_as_opcode ("deccc"); + w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); + w_as_comma(); + w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); + return; + } else { + w_as_opcode ("set"); + w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); + w_as_comma(); + w_as_scratch_register(); + w_as_newline(); + + w_as_opcode ("subcc"); + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_scratch_register(); + w_as_comma(); + w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); + return; + } + default: + w_as_ld_parameter (&instruction->instruction_parameters[0]); + w_as_comma(); + w_as_scratch_register(); + w_as_newline(); + + w_as_opcode ("subcc"); + w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_scratch_register(); + w_as_comma(); + w_as_register_newline (instruction->instruction_parameters[1].parameter_data.reg.r); + } +} + +static void w_as_cmp_instruction (struct instruction *instruction,int size_flag) +{ + struct parameter parameter_0,parameter_1; + + parameter_0=instruction->instruction_parameters[0]; + parameter_1=instruction->instruction_parameters[1]; + + if (parameter_1.parameter_type==P_INDIRECT){ + w_as_opcode_parameter (size_flag==SIZE_LONG ? "ld" : "ldsh",¶meter_1); + w_as_comma(); + w_as_register (REGISTER_O1); + w_as_newline(); + + parameter_1.parameter_type=P_REGISTER; + parameter_1.parameter_data.reg.r=REGISTER_O1; + } else if (parameter_1.parameter_type==P_INDEXED){ + w_as_opcode (size_flag==SIZE_LONG ? "ld" : "ldsh"); + + w_as_parameter (¶meter_1); + w_as_comma(); + w_as_register (REGISTER_O1); + w_as_newline(); + + parameter_1.parameter_type=P_REGISTER; + parameter_1.parameter_data.reg.r=REGISTER_O1; + } + + switch (parameter_0.parameter_type){ + case P_DESCRIPTOR_NUMBER: + w_as_opcode_descriptor ("set", + parameter_0.parameter_data.l->label_name, + parameter_0.parameter_offset + ); + w_as_comma(); + w_as_register (REGISTER_O0); + w_as_newline(); + + parameter_0.parameter_type=P_REGISTER; + parameter_0.parameter_data.reg.r=REGISTER_O0; + break; + case P_IMMEDIATE: + if ((unsigned)(parameter_0.parameter_data.i+4096)>=(unsigned)8192){ + w_as_opcode ("set"); + w_as_parameter (¶meter_0); + w_as_comma(); + w_as_register (REGISTER_O0); + w_as_newline(); + + parameter_0.parameter_type=P_REGISTER; + parameter_0.parameter_data.reg.r=REGISTER_O0; + } + break; + case P_REGISTER: + break; + default: + switch (size_flag){ + case SIZE_WORD: + w_as_opcode_parameter ("ldsh",¶meter_0); + break; + case SIZE_LONG: + w_as_opcode_parameter ("ld",¶meter_0); + break; + default: + internal_error_in_function ("w_as_cmp_instruction"); + } + w_as_comma(); + w_as_register (REGISTER_O0); + w_as_newline(); + + parameter_0.parameter_type=P_REGISTER; + parameter_0.parameter_data.reg.r=REGISTER_O0; + } + + w_as_opcode ("cmp"); + w_as_parameter (¶meter_1); + w_as_comma(); + w_as_parameter (¶meter_0); + w_as_newline(); +} + +static void w_as_tst_instruction (struct instruction *instruction,int size_flag) +{ + struct parameter parameter_0; + + parameter_0=w_as_register_parameter (instruction->instruction_parameters[0],size_flag); + + w_as_opcode (size_flag==SIZE_LONG ? "tst" : "tstb"); + w_as_register (parameter_0.parameter_data.reg.r); + w_as_newline(); +} + +static void w_as_btst_instruction (struct instruction *instruction) +{ + w_as_opcode ("btst"); + w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); + w_as_comma(); + w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); +} + +void w_as_jmp_instruction (struct instruction *instruction) +{ + if (instruction->instruction_parameters[0].parameter_type==P_LABEL){ + if (instruction->instruction_parameters[0].parameter_data.l->label_flags & LOCAL_LABEL){ + w_as_opcode ("b,a"); + w_as_jump_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); + + return; + } else + w_as_opcode ("call"); + } else + w_as_opcode ("jmp"); + + w_as_jump_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); + + w_as_instruction_without_parameters ("nop"); +} + +static void w_as_branch_instruction (struct instruction *instruction,char *opcode) +{ + w_as_opcode (opcode); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); + + w_as_instruction_without_parameters ("nop"); +} + +static void w_as_index_error_branch_instruction (struct instruction *instruction) +{ +/* w_as_opcode ("bleu"); */ + w_as_opcode ("bcs"); + fprintf (assembly_file,".+12"); + w_as_newline(); + + w_as_instruction_without_parameters ("nop"); + + w_as_opcode ("b,a"); + w_as_jump_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); +} + +static void w_as_float_branch_instruction (struct instruction *instruction,char *opcode) +{ + w_as_instruction_without_parameters ("nop"); + + w_as_opcode (opcode); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); + + w_as_instruction_without_parameters ("nop"); +} + +static char local_c_stack_overflow_label_name[]="l_c_stack_overflow"; + +/* +static void w_as_check_c_stack (void) +{ + w_as_opcode ("cmp"); + w_as_register (C_STACK_POINTER); + w_as_comma(); + w_as_register (REGISTER_G5); + w_as_newline(); + + w_as_opcode ("bleu"); + w_as_label (local_c_stack_overflow_label_name); + w_as_newline(); +} +*/ + +static void w_as_jsr_instruction (struct instruction *instruction) +{ + /* + if (check_c_stack) + w_as_check_c_stack(); + */ + + w_as_opcode ("call"); + w_as_jump_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); + + if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT){ + w_as_opcode ("st"); + w_as_register (REGISTER_O7); + w_as_comma(); + w_as_indirect (instruction->instruction_parameters[1].parameter_data.i,B_STACK_POINTER); + w_as_newline(); + } else + w_as_instruction_without_parameters ("nop"); +} + +static void w_as_rts_instruction (struct instruction *instruction) +{ + int b_offset; + + w_as_opcode_indirect ("ld",instruction->instruction_parameters[0].parameter_offset,B_STACK_POINTER); + w_as_comma(); + w_as_register (REGISTER_O7); + w_as_newline(); + + w_as_instruction_without_parameters ("retl"); + + b_offset=instruction->instruction_parameters[1].parameter_data.i; + if (b_offset==0) + w_as_instruction_without_parameters ("nop"); + else { + if (b_offset<0){ + w_as_opcode ("dec"); + w_as_immediate (-b_offset); + } else { + w_as_opcode ("inc"); + w_as_immediate (b_offset); + } + w_as_comma(); + w_as_register (B_STACK_POINTER); + w_as_newline(); + } +} + +static void w_as_set_condition_instruction (struct instruction *instruction,char *opcode) +{ + w_as_opcode ("clr"); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); + + w_as_opcode (opcode); + fprintf (assembly_file,".+8"); + w_as_newline(); + + w_as_opcode ("mov"); + fprintf (assembly_file,"-1"); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); +} + +static void w_as_set_float_condition_instruction (struct instruction *instruction,char *opcode) +{ + w_as_instruction_without_parameters ("nop"); + w_as_set_condition_instruction (instruction,opcode); +} + +static void w_as_mod_instruction (struct instruction *instruction) +{ + w_as_opcode ("mov"); + w_as_parameter (&instruction->instruction_parameters[2]); + w_as_comma(); + w_as_register (REGISTER_O0); + w_as_newline(); + + switch (instruction->instruction_parameters[0].parameter_type){ + case P_REGISTER: + w_as_opcode ("call"); + fprintf (assembly_file,".rem"); + w_as_newline(); + + w_as_opcode ("mov"); + w_as_parameter (&instruction->instruction_parameters[0]); + break; + case P_IMMEDIATE: + { + long v; + + v=instruction->instruction_parameters[0].parameter_data.i; + + if ((unsigned)(v+4096) < (unsigned)8192){ + w_as_opcode ("call"); + fprintf (assembly_file,".rem"); + w_as_newline(); + + w_as_opcode ("mov"); + w_as_immediate (v); + } else { + w_as_opcode ("sethi"); + fprintf (assembly_file,"%%hi "); +#ifdef GAS + fprintf (assembly_file,"("); +#endif + w_as_immediate (v); +#ifdef GAS + fprintf (assembly_file,")"); +#endif + w_as_comma(); + w_as_register (REGISTER_O1); + w_as_newline(); + + w_as_opcode ("call"); + fprintf (assembly_file,".rem"); + w_as_newline(); + + w_as_opcode ("or"); + w_as_register (REGISTER_O1); + w_as_comma(); + fprintf (assembly_file,"%%lo "); +#ifdef GAS + fprintf (assembly_file,"("); +#endif + w_as_immediate (v); +#ifdef GAS + fprintf (assembly_file,")"); +#endif + } + break; + } + default: + w_as_opcode ("call"); + fprintf (assembly_file,".rem"); + w_as_newline(); + + w_as_ld_parameter (&instruction->instruction_parameters[0]); + } + w_as_comma(); + w_as_register (REGISTER_O1); + w_as_newline(); + + w_as_opcode ("mov"); + w_as_register (REGISTER_O0); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); +} + +static void w_as_mul_or_div_instruction (struct instruction *instruction,char *mul_or_div_label_name) +{ + w_as_opcode ("mov"); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_comma(); + w_as_register (REGISTER_O0); + w_as_newline(); + + switch (instruction->instruction_parameters[0].parameter_type){ + case P_REGISTER: + w_as_opcode ("call"); + fprintf (assembly_file,mul_or_div_label_name); + w_as_newline(); + + w_as_opcode ("mov"); + w_as_parameter (&instruction->instruction_parameters[0]); + break; + case P_IMMEDIATE: + { + long v; + + v=instruction->instruction_parameters[0].parameter_data.i; + + if ((unsigned)(v+4096) < (unsigned)8192){ + w_as_opcode ("call"); + fprintf (assembly_file,mul_or_div_label_name); + w_as_newline(); + + w_as_opcode ("mov"); + w_as_immediate (v); + } else { + w_as_opcode ("sethi"); + fprintf (assembly_file,"%%hi "); +#ifdef GAS + fprintf (assembly_file,"("); +#endif + w_as_immediate (v); +#ifdef GAS + fprintf (assembly_file,")"); +#endif + w_as_comma(); + w_as_register (REGISTER_O1); + w_as_newline(); + + w_as_opcode ("call"); + fprintf (assembly_file,mul_or_div_label_name); + w_as_newline(); + + w_as_opcode ("or"); + w_as_register (REGISTER_O1); + w_as_comma(); + fprintf (assembly_file,"%%lo "); +#ifdef GAS + fprintf (assembly_file,"("); +#endif + w_as_immediate (v); +#ifdef GAS + fprintf (assembly_file,")"); +#endif + } + break; + } + default: + w_as_opcode ("call"); + fprintf (assembly_file,mul_or_div_label_name); + w_as_newline(); + + w_as_ld_parameter (&instruction->instruction_parameters[0]); + } + + w_as_comma(); + w_as_register (REGISTER_O1); + w_as_newline(); + + w_as_opcode ("mov"); + w_as_register (REGISTER_O0); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); +} + +static void w_as_word_instruction (struct instruction *instruction) +{ + fprintf (assembly_file,"\t.word\t%d\n", + (int)instruction->instruction_parameters[0].parameter_data.i); +} + +static struct parameter w_as_float_parameter (struct parameter parameter) +{ + switch (parameter.parameter_type){ + case P_F_IMMEDIATE: + { + int label_number=next_label_id++; + + w_as_to_data_section(); + + w_as_opcode (".align"); + fprintf (assembly_file,"8"); + w_as_newline(); + + w_as_define_internal_label (label_number); + + w_as_opcode (".double"); + fprintf (assembly_file,"0r%.20e",*parameter.parameter_data.r); + w_as_newline(); + + w_as_to_code_section(); + + w_as_opcode ("sethi"); +#ifdef GAS + fprintf (assembly_file,"%%hi (i_%d),%%o0",label_number); +#else + fprintf (assembly_file,"%%hi i_%d,%%o0",label_number); +#endif + w_as_newline(); + + w_as_opcode ("ldd"); +#ifdef GAS + fprintf (assembly_file,"[%%o0+%%lo (i_%d)]",label_number); +#else + fprintf (assembly_file,"[%%o0+%%lo i_%d]",label_number); +#endif + w_as_comma(); + w_as_fp_register (30); + w_as_newline(); + + parameter.parameter_type=P_F_REGISTER; + parameter.parameter_data.reg.r=15; + break; + } + case P_INDIRECT: + w_as_opcode ("ld"); + w_as_indirect (parameter.parameter_offset,parameter.parameter_data.reg.r); + w_as_comma(); + w_as_fp_register (30); + w_as_newline(); + + w_as_opcode ("ld"); + w_as_indirect (parameter.parameter_offset+4,parameter.parameter_data.reg.r); + w_as_comma(); + w_as_fp_register (31); + w_as_newline(); + + parameter.parameter_type=P_F_REGISTER; + parameter.parameter_data.reg.r=15; + break; + case P_INDEXED: + w_as_opcode ("add"); + w_as_register (parameter.parameter_data.ir->a_reg.r); + w_as_comma(); + w_as_register (parameter.parameter_data.ir->d_reg.r); + w_as_comma(); + w_as_register (REGISTER_O0); + w_as_newline(); + + w_as_opcode ("ld"); + w_as_indirect (parameter.parameter_offset>>2,REGISTER_O0); + w_as_comma(); + w_as_fp_register (30); + w_as_newline(); + + w_as_opcode ("ld"); + w_as_indirect ((parameter.parameter_offset>>2)+4,REGISTER_O0); + w_as_comma(); + w_as_fp_register (31); + w_as_newline(); + + parameter.parameter_type=P_F_REGISTER; + parameter.parameter_data.reg.r=15; + break; + } + return parameter; +} + +static void w_as_compare_float_instruction (struct instruction *instruction) +{ + struct parameter parameter_0; + + parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]); + + w_as_opcode_and_d ("fcmp"); + + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_comma(); + w_as_parameter (¶meter_0); + w_as_newline(); +} + +static void w_as_sqrt_float_instruction (struct instruction *instruction) +{ + struct parameter parameter_0; + + parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]); + + w_as_opcode_and_d ("fsqrt"); + + w_as_parameter (¶meter_0); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); +} + +static void w_as_neg_float_instruction (struct instruction *instruction) +{ + struct parameter parameter_0; + int freg1,freg2; + + parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]); + + freg1=parameter_0.parameter_data.reg.r; + freg2=instruction->instruction_parameters[1].parameter_data.reg.r; + + w_as_opcode ("fnegs"); + w_as_fp_register (freg1<<1); + w_as_comma(); + w_as_fp_register (freg2<<1); + w_as_newline(); + + if (freg1!=freg2){ + w_as_opcode ("fmovs"); + w_as_fp_register ((freg1<<1)+1); + w_as_comma(); + w_as_fp_register ((freg2<<1)+1); + w_as_newline(); + } +} + +static void w_as_tryadic_float_instruction (struct instruction *instruction,char *opcode) +{ + struct parameter parameter_0; + + parameter_0=w_as_float_parameter (instruction->instruction_parameters[0]); + + w_as_opcode_and_d (opcode); + + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_comma(); + w_as_parameter (¶meter_0); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); +} + +static struct instruction *w_as_fmove_instruction (struct instruction *instruction) +{ + switch (instruction->instruction_parameters[1].parameter_type){ + case P_F_REGISTER: + switch (instruction->instruction_parameters[0].parameter_type){ + case P_F_REGISTER: + { + struct instruction *next_instruction; + int reg0,reg1; + + reg0=instruction->instruction_parameters[0].parameter_data.reg.r; + reg1=instruction->instruction_parameters[1].parameter_data.reg.r; + + next_instruction=instruction->instruction_next; + if (next_instruction) + switch (next_instruction->instruction_icode){ + case IFADD: case IFSUB: case IFMUL: case IFDIV: case IFREM: + if (next_instruction->instruction_parameters[1].parameter_data.reg.r==reg1) + { + struct parameter parameter_0; + int reg_s; + + parameter_0=w_as_float_parameter (next_instruction->instruction_parameters[0]); + + reg_s=parameter_0.parameter_data.reg.r; + if (reg_s==reg1) + reg_s=reg0; + + switch (next_instruction->instruction_icode){ + case IFADD: + w_as_opcode_and_d ("fadd"); + break; + case IFSUB: + w_as_opcode_and_d ("fsub"); + break; + case IFMUL: + w_as_opcode_and_d ("fmul"); + break; + case IFDIV: + w_as_opcode_and_d ("fdiv"); + break; + case IFREM: + w_as_opcode_and_d ("frem"); + } + w_as_fp_register (reg0<<1); + w_as_comma(); + w_as_fp_register (reg_s<<1); + w_as_comma(); + w_as_fp_register (reg1<<1); + w_as_newline(); + + return next_instruction; + } + } + + w_as_opcode ("fmovs"); + w_as_fp_register (reg0<<1); + w_as_comma(); + w_as_fp_register (reg1<<1); + w_as_newline(); + + w_as_opcode ("fmovs"); + w_as_fp_register ((reg0<<1)+1); + w_as_comma(); + w_as_fp_register ((reg1<<1)+1); + w_as_newline(); + + return instruction; + } + case P_INDIRECT: + w_as_opcode ("ld"); + w_as_indirect (instruction->instruction_parameters[0].parameter_offset, + instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_comma(); + w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r<<1); + w_as_newline(); + + w_as_opcode ("ld"); + w_as_indirect (instruction->instruction_parameters[0].parameter_offset+4, + instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_comma(); + w_as_fp_register ((instruction->instruction_parameters[1].parameter_data.reg.r<<1)+1); + w_as_newline(); + + return instruction; + case P_INDEXED: + w_as_opcode ("add"); + w_as_register (instruction->instruction_parameters[0].parameter_data.ir->a_reg.r); + w_as_comma(); + w_as_register (instruction->instruction_parameters[0].parameter_data.ir->d_reg.r); + w_as_comma(); + w_as_register (REGISTER_O0); + w_as_newline(); + + w_as_opcode ("ld"); + w_as_indirect (instruction->instruction_parameters[0].parameter_offset>>2,REGISTER_O0); + w_as_comma(); + w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r<<1); + w_as_newline(); + + w_as_opcode ("ld"); + w_as_indirect ((instruction->instruction_parameters[0].parameter_offset>>2)+4,REGISTER_O0); + w_as_comma(); + w_as_fp_register ((instruction->instruction_parameters[1].parameter_data.reg.r<<1)+1); + w_as_newline(); + + return instruction; + case P_F_IMMEDIATE: + { + int label_number=next_label_id++; + + w_as_to_data_section(); + + w_as_opcode (".align"); + fprintf (assembly_file,"8"); + w_as_newline(); + + w_as_define_internal_label (label_number); + + w_as_opcode (".double"); + fprintf (assembly_file,"0r%.20e",*instruction->instruction_parameters[0].parameter_data.r); + w_as_newline(); + + w_as_to_code_section(); + + w_as_opcode ("sethi"); +#ifdef GAS + fprintf (assembly_file,"%%hi (i_%d),%%o0",label_number); +#else + fprintf (assembly_file,"%%hi i_%d,%%o0",label_number); +#endif + w_as_newline(); + + w_as_opcode ("ldd"); +#ifdef GAS + fprintf (assembly_file,"[%%o0+%%lo (i_%d)]",label_number); +#else + fprintf (assembly_file,"[%%o0+%%lo i_%d]",label_number); +#endif + w_as_comma(); + w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r<<1); + w_as_newline(); + return instruction; + } + } + break; + case P_INDIRECT: + if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){ + w_as_opcode ("st"); + w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r<<1); + w_as_comma(); + w_as_indirect (instruction->instruction_parameters[1].parameter_offset, + instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); + + w_as_opcode ("st"); + w_as_fp_register ((instruction->instruction_parameters[0].parameter_data.reg.r<<1)+1); + w_as_comma(); + w_as_indirect (instruction->instruction_parameters[1].parameter_offset+4, + instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); + return instruction; + } + break; + case P_INDEXED: + if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){ + w_as_opcode ("add"); + w_as_register (instruction->instruction_parameters[1].parameter_data.ir->a_reg.r); + w_as_comma(); + w_as_register (instruction->instruction_parameters[1].parameter_data.ir->d_reg.r); + w_as_comma(); + w_as_register (REGISTER_O0); + w_as_newline(); + + w_as_opcode ("st"); + w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r<<1); + w_as_comma(); + w_as_indirect (instruction->instruction_parameters[1].parameter_offset>>2,REGISTER_O0); + w_as_newline(); + + w_as_opcode ("st"); + w_as_fp_register ((instruction->instruction_parameters[0].parameter_data.reg.r<<1)+1); + w_as_comma(); + w_as_indirect ((instruction->instruction_parameters[1].parameter_offset>>2)+4,REGISTER_O0); + w_as_newline(); + + return instruction; + } + } + internal_error_in_function ("w_as_fmove_instruction"); + return instruction; +} + +static void w_as_fmove_hl_instruction (struct instruction *instruction) +{ + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT + && instruction->instruction_parameters[1].parameter_type==P_F_REGISTER) + { + w_as_opcode_indirect ("ld", + instruction->instruction_parameters[0].parameter_offset, + instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_comma(); + if (instruction->instruction_icode==IFMOVEHI) + w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r<<1); + else + w_as_fp_register ((instruction->instruction_parameters[1].parameter_data.reg.r<<1)+1); + + w_as_newline(); + return; + } + + internal_error_in_function ("w_as_fmove_instruction"); +} + +static void w_as_fmovel_instruction (struct instruction *instruction) +{ + if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){ + if (instruction->instruction_parameters[1].parameter_type!=P_REGISTER) + internal_error_in_function ("w_as_fmovel_instruction"); + + w_as_opcode ("fdtoi"); + w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r<<1); + w_as_comma(); + w_as_fp_register (31); + w_as_newline(); + + w_as_opcode ("st"); + w_as_fp_register (31); + w_as_comma(); + w_as_indirect (-4,REGISTER_I6); + w_as_newline(); + + w_as_opcode ("ld"); + w_as_indirect (-4,REGISTER_I6); + w_as_comma(); + w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r); + w_as_newline(); + } else { + switch (instruction->instruction_parameters[0].parameter_type){ + case P_REGISTER: + w_as_opcode ("st"); + w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_comma(); + w_as_indirect (-4,REGISTER_I6); + w_as_newline(); + + w_as_opcode ("ld"); + w_as_indirect (-4,REGISTER_I6); + w_as_comma(); + w_as_fp_register (31); + w_as_newline(); + break; + case P_INDIRECT: + w_as_opcode ("ld"); + w_as_indirect (instruction->instruction_parameters[0].parameter_offset, + instruction->instruction_parameters[0].parameter_data.reg.r); + w_as_comma(); + w_as_fp_register (31); + w_as_newline(); + break; + case P_INDEXED: + w_as_opcode ("ld"); + w_as_indexed (instruction->instruction_parameters[0].parameter_offset, + instruction->instruction_parameters[0].parameter_data.ir); + w_as_comma(); + w_as_fp_register (31); + w_as_newline(); + break; + case P_IMMEDIATE: + w_as_opcode ("set"); + w_as_immediate (instruction->instruction_parameters[0].parameter_data.i); + w_as_comma(); + w_as_scratch_register(); + w_as_newline(); + + w_as_opcode ("st"); + w_as_scratch_register(); + w_as_comma(); + w_as_indirect (-4,REGISTER_I6); + w_as_newline(); + + w_as_opcode ("ld"); + w_as_indirect (-4,REGISTER_I6); + w_as_comma(); + w_as_fp_register (31); + w_as_newline(); + break; + default: + internal_error_in_function ("w_as_fmovel_instruction"); + } + + w_as_opcode ("fitod"); + w_as_fp_register (31); + w_as_comma(); + w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r<<1); + w_as_newline(); + } +} + +static void w_as_instructions (register struct instruction *instruction) +{ + while (instruction!=NULL){ + switch (instruction->instruction_icode){ + case IMOVE: + w_as_move_instruction (instruction,SIZE_LONG); + break; + case ILEA: + w_as_lea_instruction (instruction); + break; + case IADD: + w_as_add_instruction (instruction); + break; + case IADDI: + w_as_i_instruction (instruction,"add"); + break; + case ISUB: + w_as_sub_instruction (instruction); + break; + case ICMP: + w_as_cmp_instruction (instruction,SIZE_LONG); + break; + case IJMP: + w_as_jmp_instruction (instruction); + break; + case IJSR: + w_as_jsr_instruction (instruction); + break; + case IRTS: + w_as_rts_instruction (instruction); + break; + case IBEQ: + w_as_branch_instruction (instruction,"be"); + break; + case IBGE: + w_as_branch_instruction (instruction,"bge"); + break; + case IBGT: + w_as_branch_instruction (instruction,"bg"); + break; + case IBHS: + w_as_index_error_branch_instruction (instruction); + break; + case IBLE: + w_as_branch_instruction (instruction,"ble"); + break; + case IBLT: + w_as_branch_instruction (instruction,"bl"); + break; + case IBNE: + w_as_branch_instruction (instruction,"bne"); + break; + case IBNO: + w_as_branch_instruction (instruction,"bvc"); + break; + case IBO: + w_as_branch_instruction (instruction,"bvs"); + break; + case ILSLI: + w_as_i_instruction (instruction,"sll"); + break; + case ILSL: + w_as_tryadic_instruction (instruction,"sll"); + break; + case ILSR: + w_as_tryadic_instruction (instruction,"srl"); + break; + case IASR: + w_as_tryadic_instruction (instruction,"sra"); + break; + case IMUL: + w_as_mul_or_div_instruction (instruction,".mul"); + break; + case IDIV: + w_as_mul_or_div_instruction (instruction,".div"); + break; + case IMOD: + w_as_mod_instruction (instruction); + break; + case IAND: + w_as_tryadic_instruction (instruction,"and"); + break; + case IOR: + w_as_tryadic_instruction (instruction,"or"); + break; + case IEOR: + w_as_tryadic_instruction (instruction,"xor"); + break; + case ISEQ: + w_as_set_condition_instruction (instruction,"be,a"); + break; + case ISGE: + w_as_set_condition_instruction (instruction,"bge,a"); + break; + case ISGT: + w_as_set_condition_instruction (instruction,"bg,a"); + break; + case ISLE: + w_as_set_condition_instruction (instruction,"ble,a"); + break; + case ISLT: + w_as_set_condition_instruction (instruction,"bl,a"); + break; + case ISNE: + w_as_set_condition_instruction (instruction,"bne,a"); + break; + case ISNO: + w_as_set_condition_instruction (instruction,"bvc,a"); + break; + case ISO: + w_as_set_condition_instruction (instruction,"bvs,a"); + break; + case ICMPW: + w_as_cmp_instruction (instruction,SIZE_WORD); + break; + case ITST: + w_as_tst_instruction (instruction,SIZE_LONG); + break; + case IBTST: + w_as_btst_instruction (instruction); + break; + case IMOVEW: + w_as_move_instruction (instruction,SIZE_WORD); + break; + case IMOVEB: + w_as_move_instruction (instruction,SIZE_BYTE); + break; + case IFMOVE: + instruction=w_as_fmove_instruction (instruction); + break; + case IFMOVEHI: + case IFMOVELO: + w_as_fmove_hl_instruction (instruction); + break; + case IFADD: + w_as_tryadic_float_instruction (instruction,"fadd"); + break; + case IFSUB: + w_as_tryadic_float_instruction (instruction,"fsub"); + break; + case IFCMP: + w_as_compare_float_instruction (instruction); + break; + case IFDIV: + w_as_tryadic_float_instruction (instruction,"fdiv"); + break; + case IFMUL: + w_as_tryadic_float_instruction (instruction,"fmul"); + break; + case IFREM: + w_as_tryadic_float_instruction (instruction,"frem"); + break; + case IFBEQ: + w_as_float_branch_instruction (instruction,"fbe"); + break; + case IFBGE: + w_as_float_branch_instruction (instruction,"fbge"); + break; + case IFBGT: + w_as_float_branch_instruction (instruction,"fbg"); + break; + case IFBLE: + w_as_float_branch_instruction (instruction,"fble"); + break; + case IFBLT: + w_as_float_branch_instruction (instruction,"fbl"); + break; + case IFBNE: + w_as_float_branch_instruction (instruction,"fbne"); + break; + case IFMOVEL: + w_as_fmovel_instruction (instruction); + break; + case IFSQRT: + w_as_sqrt_float_instruction (instruction); + break; + case IFNEG: + w_as_neg_float_instruction (instruction); + break; + case IFSEQ: + w_as_set_float_condition_instruction (instruction,"fbe,a"); + break; + case IFSGE: + w_as_set_float_condition_instruction (instruction,"fbge,a"); + break; + case IFSGT: + w_as_set_float_condition_instruction (instruction,"fbg,a"); + break; + case IFSLE: + w_as_set_float_condition_instruction (instruction,"fble,a"); + break; + case IFSLT: + w_as_set_float_condition_instruction (instruction,"fbl,a"); + break; + case IFSNE: + w_as_set_float_condition_instruction (instruction,"fbne,a"); + break; + case IWORD: + w_as_word_instruction (instruction); + break; + case IADDO: + w_as_add_o_instruction (instruction); + break; + case ISUBO: + w_as_sub_o_instruction (instruction); + break; + case IFTST: + default: + internal_error_in_function ("w_as_instructions"); + } + instruction=instruction->instruction_next; + } +} + +static void w_as_number_of_arguments (int n_node_arguments) +{ + w_as_opcode (".word"); + fprintf (assembly_file,"%d",n_node_arguments); + w_as_newline(); +} + + +struct call_and_jump { + struct call_and_jump *cj_next; + WORD cj_label_id; + WORD cj_jump_id; + char *cj_call_label_name; +}; + +static struct call_and_jump *first_call_and_jump,*last_call_and_jump; + +static void w_as_garbage_collect_test (register struct basic_block *block) +{ + LONG n_cells; + int label_id_1,label_id_2; + struct call_and_jump *new_call_and_jump; + + label_id_1=next_label_id++; + label_id_2=next_label_id++; + + new_call_and_jump=allocate_memory_from_heap (sizeof (struct call_and_jump)); + + new_call_and_jump->cj_next=NULL; + new_call_and_jump->cj_label_id=label_id_1; + new_call_and_jump->cj_jump_id=label_id_2; + + switch (block->block_n_begin_a_parameter_registers){ + case 0: new_call_and_jump->cj_call_label_name="collect_0"; break; + case 1: new_call_and_jump->cj_call_label_name="collect_1"; break; + case 2: new_call_and_jump->cj_call_label_name="collect_2"; break; + case 3: new_call_and_jump->cj_call_label_name="collect_3"; break; + default: internal_error_in_function ("w_as_garbage_collect_test"); + } + + if (first_call_and_jump!=NULL) + last_call_and_jump->cj_next=new_call_and_jump; + else + first_call_and_jump=new_call_and_jump; + last_call_and_jump=new_call_and_jump; + + n_cells=block->block_n_new_heap_cells; + + if (n_cells<4096){ + w_as_opcode ("deccc"); + w_as_immediate (n_cells); + w_as_comma(); + w_as_register (REGISTER_D7); + w_as_newline(); + } else { + w_as_opcode ("set"); + w_as_immediate (n_cells); + w_as_comma(); + w_as_scratch_register(); + w_as_newline(); + + w_as_opcode ("subcc"); + w_as_register (REGISTER_D7); + w_as_comma(); + w_as_scratch_register(); + w_as_comma(); + w_as_register (REGISTER_D7); + w_as_newline(); + } + + w_as_opcode ("bcs,a"); + w_as_internal_label (label_id_1); + w_as_newline (); + + w_as_opcode ("dec"); + w_as_immediate (4); + w_as_comma(); + w_as_register (B_STACK_POINTER); + w_as_newline(); + + w_as_define_internal_label (label_id_2); +} + +static void w_as_call_and_jump (struct call_and_jump *call_and_jump) +{ + w_as_define_internal_label (call_and_jump->cj_label_id); + + w_as_opcode ("call"); + w_as_label (call_and_jump->cj_call_label_name); + w_as_newline(); + + w_as_opcode ("st"); + w_as_register (REGISTER_O7); + w_as_comma(); + w_as_indirect (0,B_STACK_POINTER); + w_as_newline(); + + w_as_opcode ("b,a"); + w_as_internal_label (call_and_jump->cj_jump_id); + w_as_newline(); +} + +static void w_as_labels (struct block_label *labels) +{ + for (; labels!=NULL; labels=labels->block_label_next) + if (labels->block_label_label->label_number==0){ + LABEL *label; + + label=labels->block_label_label; + + w_as_define_label (label); + } else + w_as_define_local_label (labels->block_label_label->label_number); +} + +/* +static void init_c_stack_checking (VOID) +{ + w_as_define_label_name (local_c_stack_overflow_label_name); + w_as_opcode ("ba"); + w_as_label (c_stack_overflow_label->label_name); + w_as_newline(); + + w_as_instruction_without_parameters ("nop"); +} +*/ + +static char local_ab_stack_overflow_label_name[]="l_ab_stack_overflow"; + +/* +static void init_ab_stack_checking (VOID) +{ + w_as_define_label_name (local_ab_stack_overflow_label_name); + w_as_opcode ("ba"); + w_as_label (ab_stack_overflow_label->label_name); + w_as_newline(); + + w_as_instruction_without_parameters ("nop"); +} +*/ +/* +static void w_as_check_ab_stack (int size,int n_d_parameters,int n_a_parameters) +{ + if (size<=4){ + w_as_opcode ("cmp"); + w_as_register (A_STACK_POINTER); + w_as_comma(); + w_as_register (B_STACK_POINTER); + w_as_newline(); + + w_as_opcode ("bleu"); + } else { + w_as_opcode ("add"); + w_as_register (B_STACK_POINTER); + w_as_comma(); + w_as_immediate (size); + w_as_comma(); + w_as_register (REGISTER_O0); + w_as_newline(); + + w_as_opcode ("cmp"); + w_as_register (REGISTER_O0); + w_as_comma(); + w_as_register (A_STACK_POINTER); + w_as_newline(); + + w_as_opcode ("bgu"); + } + w_as_label (local_ab_stack_overflow_label_name); + w_as_newline(); + + w_as_instruction_without_parameters ("nop"); +} +*/ + +void initialize_write_assembly (FILE *ass_file) +{ + assembly_file=ass_file; + + in_data_section=0; + + first_call_and_jump=NULL; + + /* + if (check_c_stack) + init_c_stack_checking(); + if (check_ab_stack) + init_ab_stack_checking(); + */ +} + +static void w_as_indirect_node_entry_jump (LABEL *label) +{ + register char *new_label_name; + + new_label_name=fast_memory_allocate (strlen (label->label_name)+1+2); + strcpy (new_label_name,"j_"); + strcat (new_label_name,label->label_name); + + if (label->label_flags & EA_LABEL){ + int label_arity; + extern LABEL *eval_fill_label,*eval_upd_labels[]; + + label_arity=label->label_arity; + + if (label_arity<-2) + label_arity=1; + + if (label_arity>=0 && label->label_ea_label!=eval_fill_label){ + w_as_opcode ("sethi"); + fprintf (assembly_file,"%%hi "); +#ifdef GAS + fprintf (assembly_file,"("); +#endif + w_as_label (label->label_ea_label->label_name); +#ifdef GAS + fprintf (assembly_file,")"); +#endif + w_as_comma(); + w_as_register (REGISTER_A2); + w_as_newline(); + + w_as_opcode ("call"); + w_as_label (eval_upd_labels[label_arity]->label_name); + w_as_newline(); + + w_as_opcode ("inc"); + fprintf (assembly_file,"%%lo "); +#ifdef GAS + fprintf (assembly_file,"("); +#endif + w_as_label (label->label_ea_label->label_name); +#ifdef GAS + fprintf (assembly_file,")"); +#endif + w_as_comma(); + w_as_register (REGISTER_A2); + w_as_newline(); + } else { + w_as_opcode ("call"); + w_as_label (label->label_ea_label->label_name); + w_as_newline(); + + w_as_instruction_without_parameters ("nop"); + w_as_instruction_without_parameters ("nop"); + } + + if (label->label_arity<0 || parallel_flag){ + LABEL *descriptor_label; + + descriptor_label=label->label_descriptor; + + if (descriptor_label->label_id<0) + descriptor_label->label_id=next_label_id++; + + w_as_opcode (".long"); + w_as_label (descriptor_label->label_name); + w_as_newline(); + } else + w_as_number_of_arguments (0); + } else + if (label->label_arity<0 || parallel_flag){ + LABEL *descriptor_label; + + descriptor_label=label->label_descriptor; + + if (descriptor_label->label_id<0) + descriptor_label->label_id=next_label_id++; + + w_as_opcode (".long"); + w_as_label (descriptor_label->label_name); + w_as_newline(); + } + + w_as_number_of_arguments (label->label_arity); + + w_as_define_label_name (new_label_name); + + w_as_opcode ("call"); + w_as_label (label->label_name); + w_as_newline(); + + label->label_name=new_label_name; + + w_as_instruction_without_parameters ("nop"); +} + +static void w_as_indirect_node_entry_jumps (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_flags & NODE_ENTRY_LABEL) + w_as_indirect_node_entry_jump (label); + + w_as_indirect_node_entry_jumps (label_node->label_node_left); + w_as_indirect_node_entry_jumps (label_node->label_node_right); +} + +#ifdef SOLARIS_ +static int next_section_number; +extern char *this_module_name; +#endif + +void write_assembly (VOID) +{ + struct basic_block *block; + struct call_and_jump *call_and_jump; + +#ifdef SOLARIS_ + next_section_number=0; +#endif + + w_as_to_code_section(); + + w_as_indirect_node_entry_jumps (labels); + + for (block=first_block; block!=NULL; block=block->block_next){ +#ifdef SOLARIS_ + if (block->block_begin_module && !block->block_link_module){ + if (block->block_labels!=NULL && block->block_labels->block_label_label->label_number==0 && block->block_labels->block_label_label->label_flags & EXPORT_LABEL) + fprintf (assembly_file,"\t.section\t\".%s\",#alloc,#execinstr\n",block->block_labels->block_label_label->label_name); + else + fprintf (assembly_file,"\t.section\t\"%s.%d\",#alloc,#execinstr\n",this_module_name,next_section_number++); + } +#endif + + if (block->block_n_node_arguments>-100){ + if (block->block_ea_label!=NULL){ + int n_node_arguments; + extern LABEL *eval_fill_label,*eval_upd_labels[]; + + n_node_arguments=block->block_n_node_arguments; + + if (n_node_arguments<-2) + n_node_arguments=1; + + if (n_node_arguments>=0 && block->block_ea_label!=eval_fill_label){ + w_as_opcode ("sethi"); + fprintf (assembly_file,"%%hi "); +#ifdef GAS + fprintf (assembly_file,"("); +#endif + w_as_label (block->block_ea_label->label_name); +#ifdef GAS + fprintf (assembly_file,")"); +#endif + w_as_comma(); + w_as_register (REGISTER_A2); + w_as_newline(); + + w_as_opcode ("call"); + w_as_label (eval_upd_labels[n_node_arguments]->label_name); + w_as_newline(); + + w_as_opcode ("inc"); + fprintf (assembly_file,"%%lo "); +#ifdef GAS + fprintf (assembly_file,"("); +#endif + w_as_label (block->block_ea_label->label_name); +#ifdef GAS + fprintf (assembly_file,")"); +#endif + w_as_comma(); + w_as_register (REGISTER_A2); + w_as_newline(); + } else { + w_as_opcode ("call"); + w_as_label (block->block_ea_label->label_name); + w_as_newline(); + + w_as_instruction_without_parameters ("nop"); + w_as_instruction_without_parameters ("nop"); + } + + if (block->block_descriptor!=NULL + && (block->block_n_node_arguments<0 || parallel_flag)) + { + w_as_label_in_code_section (block->block_descriptor->label_name); + } else + w_as_number_of_arguments (0); + } else + if (block->block_descriptor!=NULL) + w_as_label_in_code_section (block->block_descriptor->label_name); + else + w_as_number_of_arguments (0); + + w_as_number_of_arguments (block->block_n_node_arguments); + } + + w_as_labels (block->block_labels); + + if (block->block_n_new_heap_cells>0) + w_as_garbage_collect_test (block); + /* + if (check_ab_stack && block->block_ab_stack_check_size>0) + w_as_check_ab_stack (block->block_ab_stack_check_size, + block->block_n_begin_d_parameter_registers,block->block_n_begin_a_parameter_registers); + */ + + w_as_instructions (block->block_instructions); + } + + for (call_and_jump=first_call_and_jump; call_and_jump!=NULL; call_and_jump=call_and_jump->cj_next) + w_as_call_and_jump (call_and_jump); + + w_as_instruction_without_parameters ("nop"); +} diff --git a/cgswas.h b/cgswas.h new file mode 100644 index 0000000..8b1264d --- /dev/null +++ b/cgswas.h @@ -0,0 +1,11 @@ +void initialize_write_assembly (FILE *ass_file); +void write_assembly (VOID); +void w_as_c_string_in_data_section (char *string,int length); +void w_as_abc_string_in_data_section (char *string,int length); +void w_as_c_string_in_code_section (char *string,int length,int label_number); +void w_as_abc_string_in_code_section (char *string,int length,int label_number); +void w_as_descriptor_string_in_code_section + (char *string,int length,int string_label_id,LABEL *string_label); +void w_as_word_in_data_section (int n); +void w_as_label_in_data_section (char *label_name); +void w_as_define_label (LABEL *label); diff --git a/cgtypes.h b/cgtypes.h new file mode 100644 index 0000000..3138062 --- /dev/null +++ b/cgtypes.h @@ -0,0 +1,257 @@ + +#ifdef I486 +# undef MORE_PARAMETER_REGISTERS +#endif + +#define NODE_POINTER_OFFSET 0 + +typedef struct label { + char * label_name; + WORD label_number; + WORD label_flags; + WORD label_a_stack_size; + WORD label_b_stack_size; +#if defined (G_POWER) || defined (_WINDOWS_) + union { + ULONG * u_vector; +# define label_vector label_u.u_vector + struct object_label * u_object_label; +# define label_object_label label_u.u_object_label + } label_u; +#else + ULONG * label_vector; +#endif +#if defined (G_POWER) || defined (I486) || defined (sparc) + union { + ULONG u0_small_vector; +# define label_small_vector label_u0.u0_small_vector + ULONG u0_offset; +# define label_offset label_u0.u0_offset + } label_u0; +#else + ULONG label_small_vector; +#endif + WORD label_id; + WORD label_arity; + struct label *label_descriptor; + union { + struct instruction_node * u_last_lea; /* for descriptors */ + struct label * u_ea_label; /* for node entry labels */ + } label_u1; + union { + struct basic_block * u_last_lea_block; /* cgcode.c */ +#ifdef G_POWER + struct toc_label * u_toc_labels; /* cgpwas.c */ +#endif + } label_u2; + WORD label_last_lea_arity; +} LABEL; + +#define label_last_lea_block label_u2.u_last_lea_block +#ifdef G_POWER +# define label_toc_labels label_u2.u_toc_labels +#endif + +#define label_last_lea label_u1.u_last_lea +#define label_ea_label label_u1.u_ea_label + +#define IMPORT_LABEL 1 +#define EXPORT_LABEL 2 +#define LOCAL_LABEL 4 +#define REGISTERS_ALLOCATED 8 +#define DATA_LABEL 16 +#define NODE_ENTRY_LABEL 32 +#define DEFERED_LABEL 64 +#define EA_LABEL 128 +#ifdef G_POWER +# define HAS_TOC_LABELS 256 +# define FAR_CONDITIONAL_JUMP_LABEL 512 +# define STRING_LABEL 1024 +# define DOT_O_BEFORE_LABEL 2048 +# define STUB_GENERATED 4096 +#endif + +struct label_node { + struct label_node * label_node_left; + struct label_node * label_node_right; + LABEL label_node_label; +}; + +struct local_label { + struct local_label *local_label_next; + struct label local_label_label; +}; + +#ifdef I486 +struct reg { + WORD r; + UWORD u; +}; +#else +struct reg { + UWORD u; + WORD r; +}; +#endif + +struct index_registers { + struct reg a_reg; + struct reg d_reg; +}; + +struct parameter { + char parameter_type; + char parameter_flags; + short parameter_offset; + union parameter_data { + LONG i; + LABEL *l; + DOUBLE *r; + struct reg reg; + struct index_registers *ir; + } parameter_data; +}; + +#ifdef G_POWER +# define NO_MTLR 16 +# define NO_MFLR 32 +#endif + +struct instruction { + struct instruction * instruction_next; + struct instruction * instruction_prev; + WORD instruction_icode; + WORD instruction_arity; + struct parameter instruction_parameters[VARIABLE_ARRAY_SIZE]; +}; + +#ifdef __cplusplus + union instruction_parameter { + struct instruction_node * p; + LABEL * l; + LONG i; + }; +#endif + +struct instruction_node { + WORD instruction_code; + WORD inode_arity; + WORD node_count; + WORD instruction_d_min_a_cost; + WORD u_aregs; + WORD u_dregs; + WORD i_aregs; + WORD i_dregs; + UBYTE node_mark; + UBYTE order_mode; + UBYTE order_alterable; + UBYTE order_left; + union instruction_parameter +#ifndef __cplusplus + { + struct instruction_node * p; + LABEL * l; + LONG i; + } +#endif + instruction_parameters[VARIABLE_ARRAY_SIZE]; +}; + +typedef struct instruction_node INSTRUCTION_NODE,*INSTRUCTION_GRAPH; + +struct block_label { + struct block_label * block_label_next; + LABEL * block_label_label; +}; + +struct basic_block { + struct basic_block * block_next; + struct instruction * block_instructions; + struct instruction * block_last_instruction; + struct block_label * block_labels; + int block_n_new_heap_cells; + WORD block_n_begin_a_parameter_registers; + WORD block_n_begin_d_parameter_registers; + WORD block_n_node_arguments; /* <0 if no .n directive */ +#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS + WORD block_a_stack_check_size; + WORD block_b_stack_check_size; +#else + WORD block_stack_check_size; +#endif + unsigned int block_begin_module:1, + block_link_module:1 +#ifdef G_POWER + ,block_gc_kind:3 + /* 0 return address in lr before and after call + 1 return address in r0 before and in lr after call + 2 return address in lr before and in r0 after call + 3 return address in r0 before and after call + */ +#endif + ,block_profile:3; + struct label * block_descriptor; /* if .n directive */ + struct label * block_ea_label; /* if .n directive */ + struct label * block_profile_function_label; +}; + +struct block_graph { + struct block_graph * block_graph_previous; + struct block_graph * block_graph_next; + struct basic_block * block_graph_block; + + WORD block_graph_begin_a_stack_size; + WORD block_graph_begin_b_stack_size; + WORD block_graph_end_a_stack_size; + WORD block_graph_end_b_stack_size; + ULONG * block_graph_end_stack_vector; + ULONG block_graph_small_end_stack_vector; + + struct a_stack * block_graph_a_stack; + WORD block_graph_a_stack_top_offset; + WORD block_graph_a_stack_begin_displacement; + WORD block_graph_a_stack_end_displacement; + WORD block_graph_used_a_stack_elements; + + struct b_stack * block_graph_b_stack; + WORD block_graph_b_stack_top_offset; + WORD block_graph_b_stack_begin_displacement; + WORD block_graph_b_stack_end_displacement; + WORD block_graph_used_b_stack_elements; + + INSTRUCTION_GRAPH block_graph_a_register_parameter_node[N_ADDRESS_PARAMETER_REGISTERS]; + INSTRUCTION_GRAPH block_graph_d_register_parameter_node[N_DATA_PARAMETER_REGISTERS +#ifdef MORE_PARAMETER_REGISTERS + + N_ADDRESS_PARAMETER_REGISTERS +#endif + ]; + INSTRUCTION_GRAPH block_graph_f_register_parameter_node[N_FLOAT_PARAMETER_REGISTERS]; + + WORD block_graph_kind; + WORD block_graph_jsr_eval_offset; + LABEL * block_graph_last_instruction_label; +#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS + WORD block_graph_a_stack_displacement; + WORD block_graph_b_stack_displacement; +#else + WORD block_graph_stack_displacement; +#endif +}; + +struct dependency_list { + struct dependency_list * dependency_next; + char * dependency_module_name; +}; + +#ifndef sparc +struct relocatable_words_list { + struct relocatable_words_list * relocatable_next; + char * relocatable_label_name; +}; +#else +struct relocatable_longs_list { + struct relocatable_longs_list * relocatable_next; + char * relocatable_label_name; + int relocatable_arity; +}; +#endif diff --git a/cgwas.c b/cgwas.c new file mode 100644 index 0000000..4958d3c --- /dev/null +++ b/cgwas.c @@ -0,0 +1,1846 @@ +/* + File: cgwas.c + Author: John van Groningen +*/ + +#include +#include +#include + +#define MODULES + +#include "cgport.h" + +#ifndef G_POWER + +#include "cgrconst.h" +#include "cgtypes.h" +#include "cg.h" +#include "cgiconst.h" +#include "cgcode.h" +#include "cginstructions.h" +#include "cgwas.h" + +#pragma segment Code5 + +#define IO_BUF_SIZE 8192 + +#ifdef SUN +# define sun_flag 1 +#else +# define sun_flag 0 +#endif + +static FILE *assembly_file; + +static void w_as_newline (VOID) +{ + putc ('\n',assembly_file); +} + +static void w_as_opcode (char *opcode) +{ + fprintf (assembly_file,"\t%s\t",opcode); +} + +static void w_as_instruction_without_parameters (char *opcode) +{ + fprintf (assembly_file,"\t%s\n",opcode); +} + +static void w_as_define_local_label (int label_number) +{ + fprintf (assembly_file,"l_%d:\n",label_number); +} + +static void w_as_define_internal_label (int label_number) +{ + fprintf (assembly_file,"i_%d:\n",label_number); +} + +#ifdef MODULES +void w_as_new_module (int flag) +{ + if (flag) + fprintf (assembly_file,";\tmodule+\n"); + else + fprintf (assembly_file,";\tmodule\n"); +} +#endif + +static int in_data_section; + +void w_as_to_data_section (VOID) +{ + if (!in_data_section){ + in_data_section=1; + w_as_instruction_without_parameters (sun_flag ? ".data" : "data"); + } +} + +static void w_as_to_code_section (VOID) +{ + if (in_data_section){ + in_data_section=0; + w_as_instruction_without_parameters (sun_flag ? ".text" : "code"); + } +} + +void w_as_internal_label_value (int label_id) +{ + w_as_to_data_section(); + if (sun_flag) + fprintf (assembly_file,"\t.long\ti_%d\n",label_id); + else { + fprintf (assembly_file,"\tdatarefs\trelative\n"); + fprintf (assembly_file,"\tdc.w\ti_%d\n",label_id); + fprintf (assembly_file,"\tdatarefs\tabsolute\n"); + } +} + +void w_as_word_in_data_section (int n) +{ + w_as_to_data_section(); + w_as_opcode (sun_flag ? ".word" : "dc.w"); + fprintf (assembly_file,"%d",n); + w_as_newline(); +} + +void w_as_long_in_data_section (long n) +{ + w_as_to_data_section(); + w_as_opcode (sun_flag ? ".long" : "dc.l"); + fprintf (assembly_file,"%d",n); + w_as_newline(); +} + +void w_as_label_in_data_section (char *label_name) +{ + w_as_to_data_section (); + if (sun_flag) + fprintf (assembly_file,"\t.long\t%s\n",label_name); + else { + fprintf (assembly_file,"\tdatarefs\trelative\n"); + fprintf (assembly_file,"\tdc.w\t%s\n",label_name); + fprintf (assembly_file,"\tdatarefs\tabsolute\n"); + } +} + +void w_as_descriptor_in_data_section (char *label_name) +{ + w_as_to_data_section (); + if (sun_flag) + fprintf (assembly_file,"\t.long\t%s\n",label_name); + else + fprintf (assembly_file,"\tdc.l\t%s\n",label_name); +} + +void w_as_descriptor_in_code_section (char *label_name) +{ + w_as_to_code_section (); + if (sun_flag) + fprintf (assembly_file,"\t.long\t%s\n",label_name); + else + fprintf (assembly_file,"\tdc.l\t%s\n",label_name); +} + +static void w_as_label_in_code_section (char *label_name) +{ + w_as_to_code_section (); + if (sun_flag) + fprintf (assembly_file,"\t.long\t%s\n",label_name); + else { + fprintf (assembly_file,"\tdatarefs\trelative\n"); + fprintf (assembly_file,"\tdc.w\t%s\n",label_name); + fprintf (assembly_file,"\tdatarefs\tabsolute\n"); + } +} + +#define MAX_BYTES_PER_LINE 16 + +static int w_as_data (int n,unsigned char *data,int length) +{ + register int i,in_string; + + in_string=0; + + for (i=0; i=MAX_BYTES_PER_LINE){ + if (in_string){ + putc ('\"',assembly_file); + in_string=0; + } + w_as_newline(); + n=0; + } + if (n==0) + w_as_opcode (sun_flag ? ".byte" : "dc.b"); + else + if (!in_string) + putc (',',assembly_file); + + c=data[i]; + if (isalnum (c) || c=='_' || c==' '){ + if (!in_string){ + putc ('\"',assembly_file); + in_string=1; + } + putc (c,assembly_file); + } else { + if (in_string){ + putc ('\"',assembly_file); + putc (',',assembly_file); + in_string=0; + } + fprintf (assembly_file,sun_flag ? "0x%02x" : "$%02x",c); + } + ++n; + } + + if (in_string) + putc ('\"',assembly_file); + + return n; +} + +static int w_as_zeros (register int n,register int length) +{ + register int i; + + for (i=0; i=MAX_BYTES_PER_LINE){ + w_as_newline(); + n=0; + } + if (n==0) + w_as_opcode (sun_flag ? ".byte" : "dc.b"); + else + putc (',',assembly_file); + fprintf (assembly_file,"0"); + ++n; + } + return n; +} + +void w_as_c_string_in_code_section (char *string,int length,int label_number) +{ + register int n; + + w_as_to_code_section(); + + w_as_define_local_label (label_number); + + n=w_as_data (0,(unsigned char *)string,length); + n=w_as_zeros (n,length & 1 ? 1 : 2); + if (n>0) + w_as_newline(); +} + +void w_as_define_local_label_in_code_section (int label_number) +{ + w_as_to_code_section(); + + w_as_define_local_label (label_number); +} + +void w_as_abc_string_in_code_section (char *string,int length) +{ + int n; + + w_as_to_code_section(); + + w_as_opcode (sun_flag ? ".long" : "dc.l"); + fprintf (assembly_file,"%d\n",length); + n=w_as_data (0,(unsigned char *)string,length); + if (length & 3) + n=w_as_zeros (n,4-(length & 3)); + if (n>0) + w_as_newline(); +} + +void w_as_c_string_in_data_section (char *string,int length) +{ + register int n; + + w_as_to_data_section(); + + n=w_as_data (0,(unsigned char *)string,length); + + n=w_as_zeros (n,4-(length & 3)); +/* n=w_as_zeros (n,length & 1 ? 1 : 2); */ + + if (n>0) + w_as_newline(); +} + +void w_as_descriptor_string_in_code_section + (char *string,int length,int string_code_label_id,LABEL *string_label) +{ + register int n; + + w_as_to_code_section(); + + w_as_define_internal_label (string_code_label_id); + + if (!sun_flag){ + fprintf (assembly_file,"\tlea\t6+*(pc),a0\n"); + fprintf (assembly_file,"\trts\n"); +#ifdef MODULES + w_as_new_module (1); +#endif + } + + w_as_define_local_label (string_label->label_number); + + w_as_opcode (sun_flag ? ".long" : "dc.l"); + fprintf (assembly_file,"%d\n",length); + n=w_as_data (0,(unsigned char *)string,length); + if (length & 3) + n=w_as_zeros (n,4-(length & 3)); + if (n>0) + w_as_newline(); +} + +enum { SIZE_LONG, SIZE_WORD, SIZE_BYTE }; + +static void w_as_opcode_and_size (char *opcode,int size_flag) +{ + switch (size_flag){ + case SIZE_BYTE: + fprintf (assembly_file,sun_flag ? "\t%sb\t" : "\t%s.b\t",opcode); + return; + case SIZE_WORD: + fprintf (assembly_file,sun_flag ? "\t%sw\t" : "\t%s.w\t",opcode); + return; + case SIZE_LONG: + fprintf (assembly_file,sun_flag ? "\t%sl\t" : "\t%s.l\t",opcode); + return; + default: + internal_error_in_function ("w_as_opcode_and_size"); + } +} + +static void w_as_opcode_and_d (char *opcode) +{ + fprintf (assembly_file,sun_flag ? "\t%sd\t" : "\t%s.d\t",opcode); +} + +static void w_as_opcode_and_x (char *opcode) +{ + fprintf (assembly_file,sun_flag ? "\t%sx\t" : "\t%s.x\t",opcode); +} + +static void w_as_label (register char *label) +{ + int c; + + while (c=*label++,c!=0) + putc (c,assembly_file); +} + +static void w_as_colon (VOID) +{ + putc (':',assembly_file); +} + +static void w_as_define_label_name (char *label_name) +{ + w_as_label (label_name); + w_as_colon(); + w_as_newline(); +} + +void w_as_define_label (LABEL *label) +{ + if (label->label_flags & EXPORT_LABEL){ + w_as_opcode (sun_flag ? ".globl" : "export"); + w_as_label (label->label_name); + w_as_newline(); + } + + w_as_label (label->label_name); + w_as_colon(); + w_as_newline(); +} + +static void w_as_local_label (int label_number) +{ + fprintf (assembly_file,"l_%d",label_number); +} + +static void w_as_internal_label (int label_number) +{ + fprintf (assembly_file,"i_%d",label_number); +} + +void w_as_abc_string_and_label_in_code_section (char *string,int length,char *label_name) +{ + int n; + + w_as_to_code_section(); + + w_as_define_label_name (label_name); + + w_as_opcode (sun_flag ? ".long" : "dc.l"); + fprintf (assembly_file,"%d\n",length); + n=w_as_data (0,(unsigned char *)string,length); + if (length & 3) + n=w_as_zeros (n,4-(length & 3)); + if (n>0) + w_as_newline(); +} + +static void w_as_immediate (LONG i) +{ + fprintf (assembly_file,"#%ld",i); +} + +static void w_as_indirect (int i,int reg) +{ + if (sun_flag) + fprintf (assembly_file,"a%d@(%d)",a_reg_num (reg),i); + else + fprintf (assembly_file,"%d(a%d)",i,a_reg_num (reg)); +} + +static void w_as_register (int reg) +{ + if (is_d_register (reg)) + fprintf (assembly_file,"d%d",d_reg_num (reg)); + else + fprintf (assembly_file,"a%d",a_reg_num (reg)); +} + +static struct relocatable_words_list *first_relocatable_word,*last_relocatable_word; +static int n_relocatable_words,n_relocatable_longs; + +static void w_as_null_descriptor (char *label_name) +{ + if (sun_flag){ + fprintf (assembly_file,"rl_%d:",n_relocatable_longs++); + w_as_opcode (".long"); + fprintf (assembly_file,"%s\n",label_name); + } else { + fprintf (assembly_file,"\tdatarefs\trelative\n"); + fprintf (assembly_file,"\tdc.w\t%s\n",label_name); + fprintf (assembly_file,"\tdatarefs\tabsolute\n"); + } +} + +static void w_as_opcode_immediate_descriptor (char *opcode,char *label_name,int arity,int size_flag) +{ + if (sun_flag){ + if (size_flag==SIZE_WORD){ + struct relocatable_words_list *new_relocatable_word; + + fprintf (assembly_file,"rw_%d:",n_relocatable_words++); + w_as_opcode (opcode); + fprintf (assembly_file,"#%d",arity<<3); + + new_relocatable_word=(struct relocatable_words_list*)fast_memory_allocate (sizeof (struct relocatable_words_list)); + new_relocatable_word->relocatable_next=NULL; + new_relocatable_word->relocatable_label_name=label_name; + if (first_relocatable_word==NULL) + first_relocatable_word=new_relocatable_word; + else + last_relocatable_word->relocatable_next=new_relocatable_word; + last_relocatable_word=new_relocatable_word; + } else { + fprintf (assembly_file,"rl_%d:",n_relocatable_longs++); + w_as_opcode (opcode); + fprintf (assembly_file,"#%s",label_name); + if (arity!=0) + fprintf (assembly_file,"+%d",arity<<3); + } + } else { + w_as_opcode (opcode); + fprintf (assembly_file,"#%s",label_name); + if (arity!=0) + fprintf (assembly_file,"+%d",arity<<2); + } +} + +static void w_as_comma (VOID) +{ + putc (',',assembly_file); +} + +static void w_as_minus (VOID) +{ + putc ('-',assembly_file); +} + +static void w_as_slash (VOID) +{ + putc ('/',assembly_file); +} + +static void w_as_parameter (register struct parameter *parameter) +{ + switch (parameter->parameter_type){ + case P_REGISTER: + { + int reg=parameter->parameter_data.reg.r; + if (is_d_register (reg)) + fprintf (assembly_file,"d%d",d_reg_num (reg)); + else + fprintf (assembly_file,"a%d",a_reg_num (reg)); + break; + } + case P_LABEL: + if (parameter->parameter_data.l->label_number!=0) + w_as_local_label (parameter->parameter_data.l->label_number); + else + w_as_label (parameter->parameter_data.l->label_name); + break; + case P_INDIRECT: + if (sun_flag){ + if (parameter->parameter_offset==0) + fprintf (assembly_file,"a%d@",a_reg_num (parameter->parameter_data.reg.r)); + else + fprintf (assembly_file,"a%d@(%d)",a_reg_num (parameter->parameter_data.reg.r), + parameter->parameter_offset); + } else { + if (parameter->parameter_offset==0) + fprintf (assembly_file,"(a%d)",a_reg_num (parameter->parameter_data.reg.r)); + else + fprintf (assembly_file,"%d(a%d)",parameter->parameter_offset, + a_reg_num (parameter->parameter_data.reg.r)); + } + break; + case P_IMMEDIATE: + fprintf (assembly_file,"#%ld",parameter->parameter_data.i); + break; + case P_POST_INCREMENT: + if (sun_flag) + fprintf (assembly_file,"a%d@+",a_reg_num (parameter->parameter_data.reg.r)); + else + fprintf (assembly_file,"(a%d)+",a_reg_num (parameter->parameter_data.reg.r)); + break; + case P_PRE_DECREMENT: + if (sun_flag) + fprintf (assembly_file,"a%d@-",a_reg_num (parameter->parameter_data.reg.r)); + else + fprintf (assembly_file,"-(a%d)",a_reg_num (parameter->parameter_data.reg.r)); + break; + case P_F_REGISTER: + fprintf (assembly_file,"fp%d",parameter->parameter_data.reg.r); + break; + case P_F_IMMEDIATE: + fprintf (assembly_file,sun_flag ? "#0r%.20e" : "#\"%g\"",*parameter->parameter_data.r); + break; + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + + index_registers=parameter->parameter_data.ir; + offset=parameter->parameter_offset; + + if ((offset & 3)==0) + fprintf (assembly_file,"%d(a%d,d%d.l)",offset>>2, + a_reg_num (index_registers->a_reg.r),d_reg_num (index_registers->d_reg.r)); + else + fprintf (assembly_file,"%d(a%d,d%d.l*%d)",offset>>2, + a_reg_num (index_registers->a_reg.r),d_reg_num (index_registers->d_reg.r), + 1<<(offset & 3)); + break; + } + default: + internal_error_in_function ("w_as_parameter"); + } +} + +static void w_as_move_instruction (struct instruction *instruction,int size_flag) +{ + if (size_flag==SIZE_LONG + && instruction->instruction_parameters[0].parameter_type==P_DESCRIPTOR_NUMBER) + { + w_as_opcode_immediate_descriptor ( + sun_flag ? "movel" : "moved", + instruction->instruction_parameters[0].parameter_data.l->label_name, + instruction->instruction_parameters[0].parameter_offset,SIZE_LONG + ); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); + return; + } + + if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){ + LONG i; + + i=instruction->instruction_parameters[0].parameter_data.i; + + 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)) + { + w_as_opcode ("moveq"); + w_as_immediate (i); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); + return; + } + + if (i==0 && instruction->instruction_parameters[1].parameter_type!=P_REGISTER){ + w_as_opcode_and_size ("clr",size_flag); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); + return; + } + } + + w_as_opcode_and_size ("move",size_flag); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); +} + +static void w_as_dyadic_instruction (struct instruction *instruction,char *opcode) +{ + w_as_opcode (opcode); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); +} + +static void w_as_lea_instruction (struct instruction *instruction) +{ + w_as_opcode ("lea"); + w_as_parameter (&instruction->instruction_parameters[0]); + if (instruction->instruction_parameters[0].parameter_type==P_LABEL && + instruction->instruction_parameters[0].parameter_offset!=0) + { + int offset; + + offset=instruction->instruction_parameters[0].parameter_offset; + fprintf (assembly_file,offset>=0 ? "+%d" : "%d",offset); + } + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); +} + +static void w_as_dyadic_float_instruction (struct instruction *instruction,char *opcode) +{ + if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER + && instruction->instruction_parameters[1].parameter_type==P_F_REGISTER) + { + if (sun_flag) + w_as_opcode_and_x (opcode); + else + w_as_opcode (opcode); + } else + w_as_opcode_and_d (opcode); + + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); +} + +static void w_as_monadic_instruction (struct instruction *instruction,char *opcode) +{ + w_as_opcode (opcode); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); +} + +static void w_as_add_instruction (struct instruction *instruction) +{ + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER + && instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE) + { + LONG i=instruction->instruction_parameters[0].parameter_data.i; + + if (i<=8 && i>=-8 && i!=0){ + if (i>0){ + w_as_opcode_and_size ("addq",SIZE_LONG); + w_as_immediate ((LONG)i); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); + } else { + w_as_opcode_and_size ("subq",SIZE_LONG); + w_as_immediate ((LONG)-i); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); + } + return; + } else { + int reg; + + reg=instruction->instruction_parameters[1].parameter_data.reg.r; + if (is_a_register (reg) && i>=-32768 && i<32768){ + w_as_opcode ("lea"); + w_as_indirect ((int)i,reg); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); + return; + } + } + } + w_as_opcode_and_size ("add",SIZE_LONG); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); +} + +static void w_as_sub_instruction (struct instruction *instruction) +{ + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER + && instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE) + { + LONG i=instruction->instruction_parameters[0].parameter_data.i; + + if (i<=8 && i>=-8 && i!=0){ + if (i>0){ + w_as_opcode_and_size ("subq",SIZE_LONG); + w_as_immediate ((LONG)i); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); + } else { + w_as_opcode_and_size ("addq",SIZE_LONG); + w_as_immediate ((LONG)-i); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); + } + return; + } else { + int reg; + + reg=instruction->instruction_parameters[1].parameter_data.reg.r; + if (is_a_register (reg) && i>-32768 && i<=32768){ + w_as_opcode ("lea"); + w_as_indirect ((int)-i,reg); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); + return; + } + } + } + w_as_opcode_and_size ("sub",SIZE_LONG); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); +} + +static void w_as_cmp_instruction (struct instruction *instruction,int size_flag) +{ + if (instruction->instruction_parameters[0].parameter_type==P_DESCRIPTOR_NUMBER){ + switch (size_flag){ + case SIZE_WORD: + w_as_opcode_immediate_descriptor ( + sun_flag ? "cmpw" : "cmpdw", + instruction->instruction_parameters[0].parameter_data.l->label_name, + instruction->instruction_parameters[0].parameter_offset,SIZE_WORD + ); + break; + case SIZE_LONG: + w_as_opcode_immediate_descriptor ( + sun_flag ? "cmpl" : "cmpd", + instruction->instruction_parameters[0].parameter_data.l->label_name, + instruction->instruction_parameters[0].parameter_offset,SIZE_LONG + ); + break; + default: + internal_error_in_function ("w_as_cmp_instruction"); + } + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); + return; + } + + if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE + && instruction->instruction_parameters[0].parameter_data.i==0 + && (instruction->instruction_parameters[1].parameter_type!=P_REGISTER + || is_d_register (instruction->instruction_parameters[1].parameter_data.reg.r))) + { + w_as_opcode_and_size ("tst",size_flag); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); + } else { + w_as_opcode_and_size ("cmp",size_flag); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); + } +} + +static void w_as_tst_instruction (struct instruction *instruction) +{ + w_as_opcode_and_size ("tst",SIZE_LONG); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); +} + +static void w_as_jsr_schedule (unsigned int n_a_and_f_registers) +{ + if (n_a_and_f_registers & 15){ + if ((n_a_and_f_registers & 15)==1){ + w_as_opcode ("fmove"); + fprintf (assembly_file,"fp0"); + } else { + w_as_opcode ("fmovem"); + fprintf (assembly_file,"fp0-fp%d",(n_a_and_f_registers & 15)-1); + } + fprintf (assembly_file,",-(sp)\n"); + } + + w_as_opcode ("jsr"); + switch (n_a_and_f_registers>>4){ + case 0: w_as_label (schedule_0_label->label_name); break; + case 1: w_as_label (schedule_1_label->label_name); break; + case 2: w_as_label (schedule_2_label->label_name); break; + case 3: w_as_label (schedule_3_label->label_name); break; + case 256>>4:w_as_label (schedule_eval_label->label_name); break; + default: internal_error_in_function ("w_as_jsr_schedule"); + } + w_as_newline(); + + if (n_a_and_f_registers & 15){ + if ((n_a_and_f_registers & 15)==1){ + w_as_opcode ("fmove"); + fprintf (assembly_file,"(sp)+,fp0\n"); + } else { + w_as_opcode ("fmovem"); + fprintf (assembly_file,"(sp)+,fp0-fp%d\n",(n_a_and_f_registers & 15)-1); + } + } +} + +static void w_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){ + w_as_opcode ("dbra"); + w_as_register (REGISTER_D6); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); + + w_as_jsr_schedule (instruction->instruction_parameters[0].parameter_offset); + } + w_as_opcode ("bra"); + } 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){ + w_as_opcode ("dbra"); + w_as_register (REGISTER_D6); + w_as_comma(); + + fprintf (assembly_file,"%d(pc)",(n_a_and_f_registers & 15) ? 16 : 8); + w_as_newline(); + + w_as_jsr_schedule (n_a_and_f_registers); + } + } + w_as_opcode (sun_flag ? "jra" : "jmp"); + } + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); +} + +static void w_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; + + w_as_opcode ("pea"); + fprintf (assembly_file,"%d(pc)",(n_a_and_f_registers & 15) ? 24 : 16); + w_as_newline(); + + w_as_opcode ("dbra"); + w_as_register (REGISTER_D6); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); + + w_as_jsr_schedule (n_a_and_f_registers); + w_as_opcode ("bra"); + } else + w_as_opcode ("bsr"); + } else { + if (parallel_flag){ + int n_a_and_f_registers; + + w_as_opcode ("dbra"); + w_as_register (REGISTER_D6); + w_as_comma(); + + 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; + + fprintf (assembly_file,"%d(pc)",(n_a_and_f_registers & 15) ? 16 : 8); + w_as_newline(); + + w_as_jsr_schedule (n_a_and_f_registers); + } + w_as_opcode (sun_flag ? "jbsr": "jsr"); + } + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); +} + +static void w_as_extb_instruction (struct instruction *instruction) +{ + if (!mc68000_flag){ + w_as_opcode_and_size ("extb",SIZE_LONG); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); + } else { + w_as_opcode_and_size ("ext",SIZE_WORD); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); + w_as_opcode_and_size ("ext",SIZE_LONG); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); + } +} + +static void w_as_set_condition_instruction (struct instruction *instruction,char *opcode) +{ + w_as_monadic_instruction (instruction,opcode); + + w_as_extb_instruction (instruction); +} + +static void w_as_movem_instruction (struct instruction *instruction) +{ + int first_register_index,last_register_index,register_index; + int previous_register,previous_count; + + w_as_opcode_and_size ("movem",SIZE_LONG); + + if (instruction->instruction_parameters[0].parameter_type!=P_REGISTER){ + w_as_parameter (&instruction->instruction_parameters[0]); + first_register_index=1; + last_register_index=instruction->instruction_arity-1; + w_as_comma(); + if (sun_flag && last_register_index==1) + previous_count=1; + else + previous_count=0; + } else { + first_register_index=0; + last_register_index=instruction->instruction_arity-2; + previous_count=0; + } + + previous_register=instruction->instruction_parameters[first_register_index].parameter_data.reg.r; + w_as_register (previous_register); + + for (register_index=first_register_index+1; register_index<=last_register_index; ++register_index){ + int reg; + + reg=instruction->instruction_parameters[register_index].parameter_data.reg.r; + if (is_d_register (reg) + ? is_d_register (previous_register) && d_reg_num (previous_register)+1==d_reg_num (reg) + : is_a_register (previous_register) && a_reg_num (previous_register)+1==a_reg_num (reg)) + { + ++previous_count; + previous_register=reg; + } else { + if (previous_count>1) + w_as_minus(); + else + w_as_slash(); + if (previous_count>0) + w_as_register (previous_register); + w_as_slash(); + w_as_register (reg); + previous_register=reg; + previous_count=0; + } + } + + if (previous_count>0){ + if (previous_count>1) + w_as_minus(); + else + w_as_slash(); + w_as_register (previous_register); + } + + if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){ + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[instruction->instruction_arity-1]); + } + + w_as_newline(); +} + +static void w_as_mod_instruction (struct instruction *instruction) +{ + w_as_opcode (sun_flag ? "divsll" : "tdivs.l"); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_colon(); + w_as_parameter (&instruction->instruction_parameters[2]); + w_as_newline(); +} + +static int next_bmove_label; + +static void w_as_bmove_instruction (struct instruction *instruction) +{ + char label_1_string[12],label_2_string[12]; + + sprintf (label_1_string,"b%d",next_bmove_label++); + sprintf (label_2_string,"b%d",next_bmove_label++); + + w_as_opcode (sun_flag ? "bras" : "bra.s"); + w_as_label (label_2_string); + w_as_newline(); + + w_as_define_label_name (label_1_string); + + w_as_opcode_and_size ("move",SIZE_LONG); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_comma(); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); + + w_as_define_label_name (label_2_string); + + w_as_opcode ("dbra"); + w_as_parameter (&instruction->instruction_parameters[2]); + w_as_comma(); + w_as_label (label_1_string); + w_as_newline(); +} + +static void w_as_eor_instruction (struct instruction *instruction) +{ + if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE + && instruction->instruction_parameters[0].parameter_data.i==-1) + { + w_as_opcode_and_size ("not",SIZE_LONG); + w_as_parameter (&instruction->instruction_parameters[1]); + w_as_newline(); + } else + w_as_dyadic_instruction (instruction,sun_flag ? "eorl" : "eor.l"); +} + +static void w_as_ext_instruction (struct instruction *instruction) +{ + w_as_opcode_and_size ("ext",SIZE_LONG); + w_as_parameter (&instruction->instruction_parameters[0]); + w_as_newline(); +} + +static void w_as_word_instruction (struct instruction *instruction) +{ + fprintf (assembly_file,sun_flag ? "\t.word\t%d\n" : "\tdc.w\t%d\n", + (int)instruction->instruction_parameters[0].parameter_data.i); +} + +static void w_as_instructions (register struct instruction *instruction) +{ + while (instruction!=NULL){ + switch (instruction->instruction_icode){ + case IMOVE: + w_as_move_instruction (instruction,SIZE_LONG); + break; + case ILEA: + w_as_lea_instruction (instruction); + break; + case IADD: + w_as_add_instruction (instruction); + break; + case ISUB: + w_as_sub_instruction (instruction); + break; + case ICMP: + w_as_cmp_instruction (instruction,SIZE_LONG); + break; + case IJMP: + w_as_jmp_instruction (instruction); + break; + case IJSR: + w_as_jsr_instruction (instruction); + break; + case IRTS: + w_as_instruction_without_parameters ("rts"); + break; + case IBEQ: + w_as_monadic_instruction (instruction,"beq"); + break; + case IBGE: + w_as_monadic_instruction (instruction,"bge"); + break; + case IBGT: + w_as_monadic_instruction (instruction,"bgt"); + break; + case IBHS: + w_as_monadic_instruction (instruction,"bhs"); + break; + case IBLE: + w_as_monadic_instruction (instruction,"ble"); + break; + case IBLT: + w_as_monadic_instruction (instruction,"blt"); + break; + case IBNE: + w_as_monadic_instruction (instruction,"bne"); + break; + case IBMI: + w_as_monadic_instruction (instruction,"bmi.s"); + break; + case ILSL: + w_as_dyadic_instruction (instruction,sun_flag ? "lsll" : "lsl.l"); + break; + case ILSR: + w_as_dyadic_instruction (instruction,sun_flag ? "lsrl" : "lsr.l"); + break; + case IASR: + w_as_dyadic_instruction (instruction,sun_flag ? "asrl" : "asr.l"); + break; + case IMUL: + w_as_dyadic_instruction (instruction,sun_flag ? "mulsl" : "muls.l"); + break; + case IDIV: + w_as_dyadic_instruction (instruction,sun_flag ? "divsl" : "divs.l"); + break; + case IEXG: + w_as_dyadic_instruction (instruction,"exg"); + break; + case IMOD: + w_as_mod_instruction (instruction); + break; + case IMOVEM: + w_as_movem_instruction (instruction); + break; + case IBMOVE: + w_as_bmove_instruction (instruction); + break; + case IAND: + w_as_dyadic_instruction (instruction,sun_flag ? "andl" : "and.l"); + break; + case IOR: + w_as_dyadic_instruction (instruction,sun_flag ? "orl" : "or.l"); + break; + case IEOR: + w_as_eor_instruction (instruction); + break; + case ISEQ: + w_as_set_condition_instruction (instruction,"seq"); + break; + case ISGE: + w_as_set_condition_instruction (instruction,"sge"); + break; + case ISGT: + w_as_set_condition_instruction (instruction,"sgt"); + break; + case ISLE: + w_as_set_condition_instruction (instruction,"sle"); + break; + case ISLT: + w_as_set_condition_instruction (instruction,"slt"); + break; + case ISNE: + w_as_set_condition_instruction (instruction,"sne"); + break; + case ICMPW: + w_as_cmp_instruction (instruction,SIZE_WORD); + break; + case ITST: + w_as_tst_instruction (instruction); + break; + case IMOVEW: + w_as_move_instruction (instruction,SIZE_WORD); + break; + case IMOVEB: + w_as_move_instruction (instruction,SIZE_BYTE); + break; + case IFMOVE: + w_as_dyadic_float_instruction (instruction,"fmove"); + break; + case IFADD: + w_as_dyadic_float_instruction (instruction,"fadd"); + break; + case IFSUB: + w_as_dyadic_float_instruction (instruction,"fsub"); + break; + case IFCMP: + w_as_dyadic_float_instruction (instruction,"fcmp"); + break; + case IFDIV: + w_as_dyadic_float_instruction (instruction,"fdiv"); + break; + case IFMUL: + w_as_dyadic_float_instruction (instruction,"fmul"); + break; + case IFREM: + w_as_dyadic_float_instruction (instruction,"frem"); + break; + case IFBEQ: + w_as_monadic_instruction (instruction,"fbeq"); + break; + case IFBGE: + w_as_monadic_instruction (instruction,"fbge"); + break; + case IFBGT: + w_as_monadic_instruction (instruction,"fbgt"); + break; + case IFBLE: + w_as_monadic_instruction (instruction,"fble"); + break; + case IFBLT: + w_as_monadic_instruction (instruction,"fblt"); + break; + case IFBNE: + w_as_monadic_instruction (instruction,"fbne"); + break; + case IFMOVEL: + w_as_dyadic_instruction (instruction,sun_flag ? "fmovel" : "fmove.l"); + break; + case IFACOS: + w_as_dyadic_float_instruction (instruction,"facos"); + break; + case IFASIN: + w_as_dyadic_float_instruction (instruction,"fasin"); + break; + case IFATAN: + w_as_dyadic_float_instruction (instruction,"fatan"); + break; + case IFCOS: + w_as_dyadic_float_instruction (instruction,"fcos"); + break; + case IFEXP: + w_as_dyadic_float_instruction (instruction,"fetox"); + break; + case IFLN: + w_as_dyadic_float_instruction (instruction,"flogn"); + break; + case IFLOG10: + w_as_dyadic_float_instruction (instruction,"flog10"); + break; + case IFNEG: + w_as_dyadic_float_instruction (instruction,"fneg"); + break; + case IFSIN: + w_as_dyadic_float_instruction (instruction,"fsin"); + break; + case IFSQRT: + w_as_dyadic_float_instruction (instruction,"fsqrt"); + break; + case IFTAN: + w_as_dyadic_float_instruction (instruction,"ftan"); + break; + case IFSEQ: + w_as_set_condition_instruction (instruction,"fseq"); + break; + case IFSGE: + w_as_set_condition_instruction (instruction,"fsge"); + break; + case IFSGT: + w_as_set_condition_instruction (instruction,"fsgt"); + break; + case IFSLE: + w_as_set_condition_instruction (instruction,"fsle"); + break; + case IFSLT: + w_as_set_condition_instruction (instruction,"fslt"); + break; + case IFSNE: + w_as_set_condition_instruction (instruction,"fsne"); + break; + case IWORD: + w_as_word_instruction (instruction); + break; + case ISCHEDULE: + w_as_jsr_schedule (instruction->instruction_parameters[0].parameter_data.i); + break; + case IEXTB: + w_as_extb_instruction (instruction); + break; + case IEXT: + w_as_ext_instruction (instruction); + break; + case IFTST: + default: + internal_error_in_function ("w_as_instructions"); + } + instruction=instruction->instruction_next; + } +} + +static void w_as_number_of_arguments (int n_node_arguments) +{ + w_as_opcode (sun_flag ? ".word" : "dc.w"); + fprintf (assembly_file,"%d",n_node_arguments); + w_as_newline(); +} + +struct call_and_jump { + struct call_and_jump *cj_next; + WORD cj_label_id; + WORD cj_jump_id; + char *cj_call_label_name; +}; + +static struct call_and_jump *first_call_and_jump,*last_call_and_jump; + +static void w_as_garbage_collect_test (register struct basic_block *block) +{ + LONG n_cells; + int label_id_1,label_id_2; + struct call_and_jump *new_call_and_jump; + + label_id_1=next_label_id++; + label_id_2=next_label_id++; + + new_call_and_jump=(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_label_name="collect_0"; break; + case 1: new_call_and_jump->cj_call_label_name="collect_1"; break; + case 2: new_call_and_jump->cj_call_label_name="collect_2"; break; + case 3: new_call_and_jump->cj_call_label_name="collect_3"; break; + default: internal_error_in_function ("w_as_garbage_collect_test"); + } + + if (first_call_and_jump!=NULL) + last_call_and_jump->cj_next=new_call_and_jump; + else + first_call_and_jump=new_call_and_jump; + last_call_and_jump=new_call_and_jump; + + n_cells=block->block_n_new_heap_cells; + if (n_cells<=8){ + w_as_opcode_and_size ("subq",SIZE_LONG); + w_as_immediate (n_cells); + w_as_comma (); + w_as_register (REGISTER_D7); + w_as_newline(); + } else if (n_cells<128 + && block->block_n_begin_d_parameter_registers < + (parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS)) + { + w_as_opcode ("moveq"); + w_as_immediate (n_cells); + w_as_comma(); + w_as_register (parallel_flag ? REGISTER_D5 : REGISTER_D6); + w_as_newline(); + + w_as_opcode_and_size ("sub",SIZE_LONG); + w_as_register (parallel_flag ? REGISTER_D5: REGISTER_D6); + w_as_comma(); + w_as_register (REGISTER_D7); + w_as_newline(); + } else { + w_as_opcode_and_size ("sub",SIZE_LONG); + w_as_immediate (n_cells); + w_as_comma(); + w_as_register (REGISTER_D7); + w_as_newline(); + } + + w_as_opcode ("bcs"); + w_as_internal_label (label_id_1); + w_as_newline (); + + w_as_define_internal_label (label_id_2); +} + +static void w_as_call_and_jump (struct call_and_jump *call_and_jump) +{ + w_as_define_internal_label (call_and_jump->cj_label_id); + + w_as_opcode (sun_flag ? "jbsr" : "jsr"); + w_as_label (call_and_jump->cj_call_label_name); + w_as_newline(); + + w_as_opcode (sun_flag ? "bra" : "jmp"); + w_as_internal_label (call_and_jump->cj_jump_id); + w_as_newline(); +} + +static void w_as_labels (register struct block_label *labels) +{ + for (; labels!=NULL; labels=labels->block_label_next) + if (labels->block_label_label->label_number==0){ + register LABEL *label; + + label=labels->block_label_label; + + w_as_define_label (label); + } +} + +static void w_as_indirect_node_entry_jump (LABEL *label) +{ + char *new_label_name; + + new_label_name=(char*)fast_memory_allocate (strlen (label->label_name)+1+2); + strcpy (new_label_name,"j_"); + strcat (new_label_name,label->label_name); + + if (label->label_flags & EA_LABEL){ + int label_arity; + extern LABEL *eval_fill_label,*eval_upd_labels[]; + + label_arity=label->label_arity; + + if (label_arity<-2) + label_arity=1; + + if (label_arity>=0 && label->label_ea_label!=eval_fill_label){ + w_as_opcode ("lea"); + w_as_label (label->label_ea_label->label_name); + w_as_comma(); + w_as_register (REGISTER_A2); + w_as_newline(); + + w_as_opcode ("jmp"); + w_as_label (eval_upd_labels[label_arity]->label_name); + w_as_newline(); + } else { + w_as_opcode ("jmp"); + w_as_label (label->label_ea_label->label_name); + w_as_newline(); + + w_as_instruction_without_parameters ("nop"); + w_as_instruction_without_parameters ("nop"); + } + + if (label->label_arity<0 || parallel_flag){ + LABEL *descriptor_label; + + descriptor_label=label->label_descriptor; + + if (descriptor_label->label_id<0) + descriptor_label->label_id=next_label_id++; + + w_as_null_descriptor (descriptor_label->label_name); + } else + w_as_number_of_arguments (0); + } else + if (label->label_arity<0 || parallel_flag){ + LABEL *descriptor_label; + + descriptor_label=label->label_descriptor; + + if (descriptor_label->label_id<0) + descriptor_label->label_id=next_label_id++; + + w_as_null_descriptor (descriptor_label->label_name); + } + + w_as_number_of_arguments (label->label_arity); + + w_as_define_label_name (new_label_name); + + w_as_opcode ("jmp"); + w_as_label (label->label_name); + w_as_newline(); + + label->label_name=new_label_name; +} + +static void w_as_indirect_defered_jump (register LABEL *label) +{ + w_as_null_descriptor (EMPTY_label->label_name); + + w_as_number_of_arguments (label->label_arity); + + w_as_define_local_label (label->label_number); + + w_as_opcode ("jmp"); + w_as_label (label->label_descriptor->label_name); + w_as_newline(); +} + +static void w_as_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){ + w_as_opcode ("import"); + w_as_label (label->label_name); + if (label->label_flags & DATA_LABEL) + fprintf (assembly_file,":data"); + w_as_newline(); + if (label->label_flags & NODE_ENTRY_LABEL){ +#ifdef MODULES + w_as_new_module (0); +#endif + w_as_indirect_node_entry_jump (label); + } + } + + w_as_import_labels (label_node->label_node_left); + w_as_import_labels (label_node->label_node_right); +} + +static void w_as_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 + w_as_new_module (0); +#endif + w_as_indirect_defered_jump (label); + } + } +} + +static void w_as_begin (VOID) +{ + fprintf (assembly_file,"\tcase\ton\n"); + fprintf (assembly_file,"\tstring\tasis\n"); + if (!mc68000_flag) + fprintf (assembly_file,"\tmachine\tmc68020\n"); + if (mc68881_flag) + fprintf (assembly_file,"\tmc68881\n"); + fprintf (assembly_file,"\tinclude\t'descriptor_macros.h'\n"); + fprintf (assembly_file,"\tproc\n"); +} + +static char local_stack_overflow_label_name[]="l_stack_overflow"; + +static void init_stack_checking (VOID) +{ + w_as_define_label_name (local_stack_overflow_label_name); + w_as_opcode (sun_flag ? "jra": "jmp"); + w_as_label (stack_overflow_label->label_name); + w_as_newline(); +} + +#define EXTRA_STACK_SPACE 2000 /* 300 */ + +static void w_as_check_stack (register struct basic_block *block) +{ + int size,n_d_parameters,n_a_parameters; + int label_id_1,label_id_2; + + 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_label_name="realloc_0"; break; + case 1: new_call_and_jump->cj_call_label_name="realloc_1"; break; + case 2: new_call_and_jump->cj_call_label_name="realloc_2"; break; + case 3: new_call_and_jump->cj_call_label_name="realloc_3"; break; + default: internal_error_in_function ("as_garbage_check_stack"); + } + + 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){ + /* CMPA.L A_STACK_POINTER,B_STACK_POINTER */ + w_as_opcode_and_size ("cmp",SIZE_LONG); + w_as_register (A_STACK_POINTER); + w_as_comma(); + w_as_register (B_STACK_POINTER); + w_as_newline(); + /* BLS */ + w_as_opcode ("bls"); + } else if (size<=127 + && n_d_parameters < + (parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS)) + { + /* MOVEQ #size,D5/D6 */ + w_as_opcode ("moveq"); + w_as_immediate (size); + w_as_comma(); + w_as_register (parallel_flag ? REGISTER_D5 : REGISTER_D6); + w_as_newline(); + /* ADD.L A_STACK_POINTER,D5/D6 */ + w_as_opcode_and_size ("add",SIZE_LONG); + w_as_register (A_STACK_POINTER); + w_as_comma(); + w_as_register (parallel_flag ? REGISTER_D5 : REGISTER_D6); + w_as_newline(); + /* CMP.L B_STACK_POINTER,D5/D6 */ + w_as_opcode_and_size ("cmp",SIZE_LONG); + w_as_register (B_STACK_POINTER); + w_as_comma(); + w_as_register (parallel_flag ? REGISTER_D5 : REGISTER_D6); + w_as_newline(); + /* BHI */ + w_as_opcode ("bhi"); + } else if (n_a_parametersdependency_next) + fprintf (assembly_file,"\tjbsr\tre_%s\n",dependency->dependency_module_name); + + fprintf (assembly_file,"rx_%s:\n",this_module_name); + fprintf (assembly_file,"\trts\n"); + + fprintf (assembly_file,"rlt_%s:\n",this_module_name); + for (n=0; nrelocatable_next) + fprintf (assembly_file,"\t.long\trw_%d,%s\n",n++,r_word->relocatable_label_name); +} + +void write_assembly (VOID) +{ + register struct basic_block *block; + register struct call_and_jump *call_and_jump; + + w_as_to_code_section(); + + release_heap(); + + if (!sun_flag) + w_as_import_labels (labels); + w_as_indirect_jumps_for_defer_labels(); + + for (block=first_block; block!=NULL; block=block->block_next){ +#ifdef MODULES + if (block->block_begin_module) + w_as_new_module (block->block_link_module); +#endif + + if (block->block_n_node_arguments>-100){ +#ifdef CLOSURE_NAMES + if (block->block_descriptor!=NULL && block->block_descriptor_or_string!=0){ + int length,n; + char *string; + + string=(char*)block->block_descriptor; + length=strlen (string); + + n=w_as_data (0,(unsigned char *)string,length); + if (length & 3) + n=w_as_zeros (n,4-(length & 3)); + if (n>0) + w_as_newline(); + + w_as_opcode (sun_flag ? ".long" : "dc.l"); + fprintf (assembly_file,"%d\n",length); + } +#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){ + w_as_opcode ("lea"); + w_as_label (block->block_ea_label->label_name); + w_as_comma(); + w_as_register (REGISTER_A2); + w_as_newline(); + + w_as_opcode ("jmp"); + w_as_label (eval_upd_labels[n_node_arguments]->label_name); + w_as_newline(); + } else { + w_as_opcode ("jmp"); + w_as_label (block->block_ea_label->label_name); + w_as_newline(); + + w_as_instruction_without_parameters ("nop"); + w_as_instruction_without_parameters ("nop"); + } + + if (block->block_descriptor!=NULL + && (block->block_n_node_arguments<0 || parallel_flag)) + { + w_as_label_in_code_section (block->block_descriptor->label_name); + } else + w_as_number_of_arguments (0); + } else + if (block->block_descriptor!=NULL /* CHANGED 30-10 */ + && (block->block_n_node_arguments<0 || parallel_flag)) + { + w_as_label_in_code_section (block->block_descriptor->label_name); + } + /* else + w_as_number_of_arguments (0); + */ + + w_as_number_of_arguments (block->block_n_node_arguments); + } + + w_as_labels (block->block_labels); + if (block->block_n_new_heap_cells>0) + w_as_garbage_collect_test (block); + if (check_stack && block->block_stack_check_size>0) + w_as_check_stack (block); + w_as_instructions (block->block_instructions); + } + + for (call_and_jump=first_call_and_jump; + call_and_jump!=NULL; call_and_jump=call_and_jump->cj_next) + { +#ifdef MODULES + w_as_new_module (0); +#endif + w_as_call_and_jump (call_and_jump); + } + + if (sun_flag) + w_as_relocation_routine(); + + if (!sun_flag){ + fprintf (assembly_file,"\tendproc\n"); + fprintf (assembly_file,"\tend\n"); + } + + release_heap(); +} + +#endif \ No newline at end of file diff --git a/cgwas.h b/cgwas.h new file mode 100644 index 0000000..f9a8215 --- /dev/null +++ b/cgwas.h @@ -0,0 +1,19 @@ +void initialize_write_assembly (FILE *ass_file); +void write_assembly (VOID); +void w_as_abc_string_and_label_in_code_section (char *string,int length,char *label_name); +void w_as_c_string_in_code_section (char *string,int length,int label_number); +void w_as_c_string_in_data_section (char *string,int length); +void w_as_descriptor_string_in_code_section + (char *string,int length,int string_code_label_id,LABEL *string_label); +void w_as_word_in_data_section (int n); +void w_as_label_in_data_section (char *label_name); +void w_as_descriptor_in_data_section (char *label_name); +void w_as_define_label (LABEL *label); +void w_as_internal_label_value (int label_id); +void w_as_new_module (int flag); +void w_as_long_in_data_section (long n); +void w_as_to_data_section (void); +void w_as_descriptor_in_code_section (char *label_name); +void w_as_define_local_label_in_code_section (int label_number); +void w_as_abc_string_in_code_section (char *string,int length); + diff --git a/docommand.c b/docommand.c new file mode 100644 index 0000000..70de990 --- /dev/null +++ b/docommand.c @@ -0,0 +1,16 @@ +typedef struct clean_string {int length; char chars [1]; } *CleanString; + +# define Clean(ignore) +# include "docommand.h" +/* + Clean string + ============ +*/ + +extern int do_command (char *command); + +int +DoCommandNullTerminated (CleanString command) +{ + return (do_command (command->chars)); +} /* DoCommandNullTerminated */ diff --git a/docommand.h b/docommand.h new file mode 100644 index 0000000..af05aa0 --- /dev/null +++ b/docommand.h @@ -0,0 +1,12 @@ +#pragma export on + +Clean (:: *DoCommandEnvironment :== Int) +/* Clean (DoCommand command :== DoCommandNullTerminated (command +++ "\0")) */ + +Clean (DoCommandNullTerminated :: String DoCommandEnvironment -> (Int, DoCommandEnvironment)) + +/* functions */ +int DoCommandNullTerminated (CleanString command); +Clean (DoCommandNullTerminated :: String DoCommandEnvironment -> (Int, DoCommandEnvironment)) + +#pragma export off -- cgit v1.2.3