diff options
-rw-r--r-- | MAIN_CLM.d | 3 | ||||
-rw-r--r-- | apple_main.c | 499 | ||||
-rw-r--r-- | cg.c | 924 | ||||
-rw-r--r-- | cg.h | 37 | ||||
-rw-r--r-- | cgas.c | 3839 | ||||
-rw-r--r-- | cgas.h | 23 | ||||
-rw-r--r-- | cgcalc.c | 2947 | ||||
-rw-r--r-- | cgcalc.h | 15 | ||||
-rw-r--r-- | cgcode.h | 76 | ||||
-rw-r--r-- | cgconst.h | 27 | ||||
-rw-r--r-- | cginput.h | 2 | ||||
-rw-r--r-- | cginstructions.h | 60 | ||||
-rw-r--r-- | cgiwas.h | 25 | ||||
-rw-r--r-- | cglin.h | 126 | ||||
-rw-r--r-- | cgopt.h | 10 | ||||
-rw-r--r-- | cgpas.h | 14 | ||||
-rw-r--r-- | cgptoc.c | 65 | ||||
-rw-r--r-- | cgpwas.h | 19 | ||||
-rw-r--r-- | cgrconst.h | 58 | ||||
-rw-r--r-- | cgstack.c | 4320 | ||||
-rw-r--r-- | cgstack.h | 51 | ||||
-rw-r--r-- | cgswas.c | 2446 | ||||
-rw-r--r-- | cgswas.h | 11 | ||||
-rw-r--r-- | cgtypes.h | 257 | ||||
-rw-r--r-- | cgwas.c | 1846 | ||||
-rw-r--r-- | cgwas.h | 19 | ||||
-rw-r--r-- | docommand.c | 16 | ||||
-rw-r--r-- | docommand.h | 12 |
28 files changed, 17747 insertions, 0 deletions
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 <stdio.h> +#ifndef PROJECT_BUILDER +# include <unix.h> +# include <SIOUX.h> +#endif + +#include <quickdraw.h> +#include <fonts.h> +#include <events.h> +#include <windows.h> +#include <memory.h> +#include <resources.h> +#include <menus.h> +#include <OSUtils.h> +#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 <string.h> + +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; n<argc; ++n) + printf ("%d %s\n",n,argv[n]); + } +*/ + + if (argc>0){ +#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 <Profiler.h> +#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<<gestaltAppleEventsPresent))!=0) + gAppleEventsFlag = true; + else + gAppleEventsFlag = false; + +#if defined (STDIO_WINDOW) + SIOUXSettings.autocloseonquit=1; + SIOUXSettings.showstatusline=0; + SIOUXSettings.asktosaveonclose=0; + + printf ("\n"); +#endif + +#if !defined (BACKGROUND) && !defined (STDIO_WINDOW) + fclose (stdout); + fclose (stderr); +#endif + + InitAppleEventsStuff(); + +#ifdef PROFILE + if (ProfilerInit(/*collectSummary*/collectDetailed,bestTimeBase,10000,10)!=0) + return 0; +#endif + + while (!gQuitFlag) { + eventFlag = WaitNextEvent (everyEvent,&mainEventRec,gSleepVal,nil); + +#ifdef STDIO_WINDOW + if (SIOUXHandleOneEvent (&mainEventRec)) + continue; +#endif + if (mainEventRec.what==keyDown) + break; + + if (mainEventRec.what==kHighLevelEvent) + do_high_level_event (&mainEventRec); + } + +#ifdef PROFILE + ProfilerDump ("\pProfile"); + ProfilerTerm(); +#endif + + return 1; +} + +#endif + +#endif
\ No newline at end of file @@ -0,0 +1,924 @@ +/* + File: cg.c + Author: John van Groningen + At: University of Nijmegen +*/ + +#ifdef THINK_C +# define USER_INTERFACE +#endif + +#include <string.h> + +#include "cgport.h" + +#ifdef ALIGN_C_CALLS +# define CG_PPC_XO +#endif + +#include <stdlib.h> +#include <stdio.h> + +#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 <Perf.h> +TP2PerfGlobals ThePGlobals; +#endif + +#ifdef THINK_C +# include <console.h> +# 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 <setjmp.h> + +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 && argv[arg_n][0]=='-'; ++arg_n){ + char *s; + + s=argv[arg_n]+1; + if (!strcmp (s,"l")) + list_flag=1; + else if (!strcmp (s,"os")) + check_stack=1; + else if (!strcmp (s,"ci")) + check_index_flag=1; + else if (!strcmp (s,"p")) + parallel_flag=1; + else if (!strcmp (s,"a")) + assembly_flag=1; +#ifdef G_POWER + else if (!strcmp (s,"pt")) + profile_table_flag=1; +#endif + else if (!strcmp (s,"mc68000")){ + mc68000_flag=1; + mc68881_flag=0; + } else if (!strcmp (s,"sane")) + mc68881_flag=0; +#ifdef POWER + else if (!strcmp (s,"id") && arg_n+1<argc){ + ++arg_n; +# ifdef CG_PPC_XO + *compiler_id_p=atoi (argv[arg_n]); +# else + compiler_id=atoi (argv[arg_n]); +# endif + } +#endif + else + argument_error(); + } + +#ifndef GENERATE_OBJECT_FILE + assembly_flag=1; +#endif + + if (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<argc){ + if (arg_n+1==argc) + argument_error(); + + if (!strcmp (argv[arg_n],"-o")) + object_file_name=argv[arg_n+1]; + else if (!strcmp (argv[arg_n],"-s")){ + assembly_file_name=argv[arg_n+1]; + assembly_flag=1; + } else + argument_error(); + + arg_n+=2; + } + initialize_parser(); + initialize_coding(); + initialize_stacks(); + initialize_linearization(); + +#if 0 + abc_file=fopen (abc_file_name,"r"); +#else + abc_file=fopen (abc_file_name,"rb"); +#endif + if (abc_file==NULL) + error_s ("Can't open file %s\n",abc_file_name); + +#if defined (I486) && !defined (_WINDOWS_) + { + char *buffer; + + buffer=malloc (IO_BUF_SIZE); + if (buffer==NULL) + error ("Out of memory"); + setvbuf (abc_file,buffer,_IOFBF,IO_BUF_SIZE); + } +#else + setvbuf (abc_file,NULL,_IOFBF,IO_BUF_SIZE); +#endif + +# ifdef GENERATE_OBJECT_FILE + obj_file=fopen (object_file_name,"wb"); + if (obj_file==NULL) + error ("Can't create the object file"); + setvbuf (obj_file,NULL,_IOFBF,IO_BUF_SIZE); +# endif + + if (assembly_flag){ +#ifdef MACH_O + assembly_file=fopen (assembly_file_name,"wb"); +#else + assembly_file=fopen (assembly_file_name,"w"); +#endif + if (assembly_file==NULL) + error ("Can't create the assembly file"); +#if defined (I486) && !defined (_WINDOWS_) + { + char *buffer; + + buffer=malloc (IO_BUF_SIZE); + if (buffer==NULL) + error ("Out of memory"); + setvbuf (assembly_file,buffer,_IOFBF,IO_BUF_SIZE); + } +#else + setvbuf (assembly_file,NULL,_IOFBF,IO_BUF_SIZE); +#endif + } + +#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; + } + + exit (-1); + } + + if (fclose (abc_file)!=0){ + abc_file=NULL; + error_s ("Error while reading file %s\n",abc_file_name); + } + 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(); + +#ifdef GENERATE_OBJECT_FILE + if (fclose (obj_file)!=0){ + obj_file=NULL; + error ("Error while writing object file"); + } + obj_file=NULL; +#endif + if (assembly_flag && fclose (assembly_file)!=0){ + assembly_file=NULL; + error ("Error while writing assembly file"); + } + assembly_file=NULL; + } else { + if (obj_file!=NULL) + fclose (obj_file); + if (assembly_file!=NULL) + fclose (assembly_file); + if (abc_file!=NULL) + fclose (abc_file); + } + + if (assembly_file_name_s!=NULL) + memory_free (assembly_file_name_s); + if (object_file_name_s!=NULL) + memory_free (object_file_name_s); + if (abc_file_name!=NULL) + memory_free (abc_file_name); + + release_memory(); + +#ifdef PERFORMANCE + PerfDump (ThePGlobals,"\pPerform.out",0,0); + TermPerf (ThePGlobals); +#endif + + return r; +} + +#endif @@ -0,0 +1,37 @@ +void *memory_allocate (int size); +void memory_free (void *memory_block); +void *allocate_memory_from_heap (int size); +void *fast_memory_allocate (int size); +void release_heap (VOID); + +#define memory_allocate_type(t) ((t*)memory_allocate(sizeof(t))) +#define fast_memory_allocate_type(t) ((t*)fast_memory_allocate(sizeof(t))) +#define allocate_memory_from_heap_type(t) ((t*)allocate_memory_from_heap(sizeof(t))) + +void warning (char *error_string); +void warning_i (char *error_string,int integer); +void warning_s (char *error_string,char *string); +void warning_si (char *error_string,char *string,int i); +void error (char *error_string); +void error_i (char *error_string,int integer); +void error_s (char *error_string,char *string); +void error_si (char *error_string,char *string,int i); +void internal_error (char *error_string); +void internal_error_in_function (char *function_name); + +extern int list_flag; +extern int check_stack; +extern int assembly_flag; +extern int sun_flag; +extern int mc68000_flag; +extern int mc68881_flag; +extern int parallel_flag; +extern int check_index_flag; +extern int module_info_flag; +extern int profile_table_flag; + +#ifdef G_POWER +extern int fmadd_flag; +#endif + +extern char *this_module_name; @@ -0,0 +1,3839 @@ +/* + File: cgas.c + Author: John van Groningen +*/ + +#include <stdio.h> +#include <string.h> + +#define MODULES +#define USE_LABEL_VALUE +/* #define COUNT_RELEASES */ +#undef GENERATE_MPW_OBJECT_CODE + +#include "cgport.h" + +#ifndef G_POWER + +#include "cg.h" +#include "cgrconst.h" +#include "cgtypes.h" +#include "cgiconst.h" +#include "cgcode.h" +#include "cginstructions.h" +#include "cgas.h" + +#define for_all(v,l,n) for(v=(l);v!=NULL;v=v->n) + +extern LABEL *index_error_label; + +#pragma segment Code5 + +enum { + LBEGIN=1, + LEND, + LIMPORT, + LLABEL, + LCODE, + LDATA, + LREFERENCE, + LUDATA, + LC_REFERENCE, + LLABEL_VALUE, + LCOMMENT, + LMODULE +}; + +#define LLABEL_TEXT 0 +#define LLABEL_DATA 1 +#define LLABEL_EXTERN 2 +#define LLABEL_OFFSET 4 + +#define REFERENCE_PC 16 +#define REFERENCE_OFFSET 8 +#define REFERENCE_A5 4 +#define REFERENCE_LONG 2 +#define REFERENCE_DATA 1 + +#define LCR_WORD 2 +#define LCR_BYTE 0 +#define LCR_OFFSET 8 + +FILE *output_file; + +#ifdef THINK_C +# define IO_BUFFER_SIZE 16384 +#else +# define IO_BUFFER_SIZE 8192 +#endif + +struct object_buffer { + struct object_buffer *next; + int size; + unsigned char data [IO_BUFFER_SIZE]; +}; + +static struct object_buffer *first_buffer,*current_buffer; + +static int buffer_free; +static unsigned char *buffer_p; + +static void initialize_object_buffers (VOID) +{ + struct object_buffer *new_buffer; + + new_buffer=(struct object_buffer*)memory_allocate (sizeof (struct object_buffer)); + + new_buffer->size=0; + new_buffer->next=NULL; + + first_buffer=new_buffer; + current_buffer=new_buffer; + + buffer_free=IO_BUFFER_SIZE; + buffer_p=new_buffer->data; +} + +static void write_c (int c) +{ + if (buffer_free>0){ + --buffer_free; + *buffer_p++=c; + } else { + struct object_buffer *new_buffer; + + current_buffer->size=IO_BUFFER_SIZE; + + new_buffer=(struct object_buffer*)memory_allocate (sizeof (struct object_buffer)); + + new_buffer->size=0; + new_buffer->next=NULL; + + current_buffer->next=new_buffer; + current_buffer=new_buffer; + + buffer_free=IO_BUFFER_SIZE-1; + buffer_p=new_buffer->data; + + *buffer_p++=c; + } +} + +static void flush_object_buffer (VOID) +{ + current_buffer->size=IO_BUFFER_SIZE-buffer_free; +} + +/* object optimizer */ + +static struct object_buffer *s_buffer,*d_buffer; +static int s_free,d_free; +static unsigned char *s_buffer_p,*d_buffer_p; + +static int s_read (VOID) +{ + while (s_free==0){ + s_buffer=s_buffer->next; + if (s_buffer==NULL) + internal_error_in_function ("s_read"); + s_free=s_buffer->size; + s_buffer_p=s_buffer->data; + } + + --s_free; + return *s_buffer_p++; +} + +static void d_write (int c) +{ + while (d_free==0){ + d_buffer=d_buffer->next; + if (d_buffer==NULL) + internal_error_in_function ("d_write"); + d_free=d_buffer->size; + d_buffer_p=d_buffer->data; + } + + --d_free; + *d_buffer_p++=c; +} + +static void optimize_buffers (VOID) +{ + int c; + + s_buffer=d_buffer=first_buffer; + s_free=d_free=first_buffer->size; + s_buffer_p=d_buffer_p=first_buffer->data; + + c=s_read(); + + for (;;){ + d_write (c); + switch (c){ + case LCODE: + { + int size,n,t; + unsigned char buffer[256]; + + n=0; + size=s_read(); + for (;;){ + t=size; + while (t--) + buffer[n++]=s_read(); + if (size & 1) + s_read(); + c=s_read(); + if (c!=LCODE) + break; + else { + size=s_read(); + if (size+n>=256){ + t=n; + d_write (t); + for (n=0; n<t; ++n) + d_write (buffer[n]); + if (t & 1) + d_write (0); + d_write (LCODE); + n=0; + } + } + } + t=n; + d_write (t); + for (n=0; n<t; ++n) + d_write (buffer[n]); + if (t & 1) + d_write (0); + continue; + } + case LDATA: + { + int size; + + size=s_read(); + d_write (size); + if (size & 1) + d_write (s_read()); + while (size--) + d_write (s_read()); + c=s_read(); + continue; + } + case LUDATA: + d_write (s_read()); + d_write (s_read()); + c=s_read(); + continue; + case LLABEL_VALUE: + d_write (s_read()); + d_write (s_read()); + d_write (s_read()); + c=s_read(); + continue; + case LREFERENCE: + { + int flags; + + flags=s_read(); + d_write (flags); + d_write (s_read()); + d_write (s_read()); + if (flags & REFERENCE_OFFSET){ + d_write (s_read()); + d_write (s_read()); + } + c=s_read(); + continue; + } + case LC_REFERENCE: + { + int flags; + + flags=s_read(); + d_write (flags); + d_write (s_read()); + d_write (s_read()); + d_write (s_read()); + d_write (s_read()); + if (flags & LCR_OFFSET){ + d_write (s_read()); + d_write (s_read()); + } + c=s_read(); + continue; + } + case LLABEL: + { + int flags; + + flags=s_read(); + d_write (flags); + d_write (s_read()); + d_write (s_read()); + if (flags & LLABEL_OFFSET){ + d_write (s_read()); + d_write (s_read()); + } + if (flags & LLABEL_EXTERN){ + int size; + + size=s_read(); + d_write (size); + if (!(size & 1)) + d_write (s_read()); + while (size--) + d_write (s_read()); + } + c=s_read(); + continue; + } + case LIMPORT: + { + int size; + + d_write (s_read()); + d_write (s_read()); + d_write (s_read()); + size=s_read(); + d_write (size); + if (!(size & 1)) + d_write (s_read()); + while (size--) + d_write (s_read()); + c=s_read(); + continue; + } + case LMODULE: + d_write (s_read()); + c=s_read(); + continue; + case LBEGIN: + d_write (s_read()); + d_write (s_read()); + d_write (s_read()); + c=s_read(); + continue; + case LEND: + d_write (s_read()); + break; + default: + internal_error_in_function ("optimize_buffers"); + } + break; + } + + d_buffer->size-=d_free; + + { + struct object_buffer *buffer,*next_buffer; + + for (buffer=d_buffer->next; buffer!=NULL; buffer=next_buffer){ + next_buffer=buffer->next; + + memory_free (buffer); + } + } + + d_buffer->next=NULL; +} + +/* end object optimizer */ + +#ifdef GENERATE_MPW_OBJECT_CODE +/* mpw object conversion */ + +static int c_read (VOID) +{ + while (s_free==0){ + struct object_buffer *old_buffer; + + old_buffer=s_buffer; + s_buffer=s_buffer->next; + + memory_free (old_buffer); + + if (s_buffer==NULL) + internal_error_in_function ("c_read"); + s_free=s_buffer->size; + s_buffer_p=s_buffer->data; + } + + --s_free; + return *s_buffer_p++; +} + +static void c_write (int c) +{ + if (d_free==0){ + struct object_buffer *new_buffer; + + d_buffer->size=IO_BUFFER_SIZE; + + new_buffer=(struct object_buffer*)memory_allocate (sizeof (struct object_buffer)); + new_buffer->size=0; + new_buffer->next=NULL; + + d_buffer->next=new_buffer; + d_buffer=new_buffer; + + d_free=IO_BUFFER_SIZE; + d_buffer_p=d_buffer->data; + } + + --d_free; + *d_buffer_p++=c; +} + +enum { + O_FIRST=1, + O_LAST, + O_COMMENT, + O_DICTIONARY, + O_MODULE, + O_ENTRY, + O_SIZE, + O_CONTENTS, + O_REFERENCE, + O_C_REFERENCE +}; + +static void convert_to_mpw_object_code (VOID) +{ + struct object_buffer *first_d_buffer; + int c,code_module_id,data_module_id,segment_id; + long code_offset,data_offset; + + first_d_buffer=(struct object_buffer*)memory_allocate (sizeof (struct object_buffer)); + first_d_buffer->size=0; + first_d_buffer->next=NULL; + + d_buffer=first_d_buffer; + d_free=IO_BUFFER_SIZE; + d_buffer_p=d_buffer->data; + + s_buffer=first_buffer; + s_free=first_buffer->size; + s_buffer_p=first_buffer->data; + + segment_id=next_label_id++; + code_module_id=next_label_id++; + data_module_id=next_label_id++; + + code_offset=-1; + data_offset=-1; + + c=c_read(); + + for (;;){ + switch (c){ + case LCODE: + { + int size,n,t; + unsigned char buffer[256]; + + c_write (O_CONTENTS); + c_write (8); + + n=0; + + size=c_read(); + c_write ((size+8)>>8); + c_write (size+8); + + c_write (code_offset>>24); + c_write (code_offset>>16); + c_write (code_offset>>8); + c_write (code_offset); + + code_offset+=size; + + t=size; + while (t--) + buffer[n++]=c_read(); + if (size & 1) + c_read(); + + t=n; + for (n=0; n<t; ++n) + c_write (buffer[n]); + if (t & 1) + c_write (0); + + c=c_read(); + continue; + } + case LDATA: + { + int size; + + c_write (O_CONTENTS); + c_write (9); + + size=c_read(); + c_write ((size+8)>>8); + c_write (size+8); + + c_write (data_offset>>24); + c_write (data_offset>>16); + c_write (data_offset>>8); + c_write (data_offset); + + data_offset+=size; + + if (size & 1) + c_write (c_read()); + while (size--) + c_write (c_read()); + c=c_read(); + continue; + } + case LUDATA: + internal_error_in_function ("convert_to_mpw_object_code"); + break; + case LLABEL_VALUE: + { + int flags,id_h,id_l; + + flags=c_read(); + id_h=c_read(); + id_l=c_read(); + + if (flags & (REFERENCE_PC | REFERENCE_OFFSET)) + internal_error_in_function ("convert_to_mpw_object_code"); + + if (flags & REFERENCE_LONG){ + if (flags & REFERENCE_DATA){ + c_write (O_CONTENTS); + c_write (9); + + c_write (0); + c_write (4+8); + + c_write (data_offset>>24); + c_write (data_offset>>16); + c_write (data_offset>>8); + c_write (data_offset); + } else { + c_write (O_CONTENTS); + c_write (8); + + c_write (0); + c_write (4+8); + + c_write (code_offset>>24); + c_write (code_offset>>16); + c_write (code_offset>>8); + c_write (code_offset); + } + c_write (0); + c_write (0); + c_write (0); + c_write (0); + } else { + if (flags & REFERENCE_DATA){ + c_write (O_CONTENTS); + c_write (9); + + c_write (0); + c_write (2+8); + + c_write (data_offset>>24); + c_write (data_offset>>16); + c_write (data_offset>>8); + c_write (data_offset); + } else { + c_write (O_CONTENTS); + c_write (8); + + c_write (0); + c_write (2+8); + + c_write (code_offset>>24); + c_write (code_offset>>16); + c_write (code_offset>>8); + c_write (code_offset); + } + c_write (0); + c_write (0); + } + + c_write (O_REFERENCE); + c_write ( (flags & REFERENCE_A5 ? 128 : 0) + | (flags & REFERENCE_LONG ? 0 : 16) + | (flags & REFERENCE_DATA ? 1 : 0)); + + c_write (0); + c_write (8); + + c_write (id_h); + c_write (id_l); + + if (flags & REFERENCE_DATA){ + c_write (data_offset>>8); + c_write (data_offset); + + if (flags & REFERENCE_LONG) + data_offset+=4; + else + data_offset+=2; + } else { + c_write (code_offset>>8); + c_write (code_offset); + + if (flags & REFERENCE_LONG) + code_offset+=4; + else + code_offset+=2; + } + + c=c_read(); + continue; + } + case LREFERENCE: + { + int flags; + + flags=c_read(); + + c_write (O_REFERENCE); + c_write ( (flags & REFERENCE_A5 ? 128 : 0) + | (flags & REFERENCE_LONG ? 0 : 16) + | (flags & REFERENCE_DATA ? 1 : 0)); + + c_write (0); + c_write (8); + + c_write (c_read()); + c_write (c_read()); + + if (flags & REFERENCE_DATA){ + c_write (data_offset>>8); + c_write (data_offset); + } else { + c_write (code_offset>>8); + c_write (code_offset); + } + + if (flags & REFERENCE_OFFSET) + internal_error_in_function ("convert_to_mpw_object_code"); + + c=c_read(); + continue; + } + case LC_REFERENCE: + { + int flags; + + flags=c_read(); + + c_write (O_C_REFERENCE); + c_write ((flags & LCR_WORD ? 16 : 0) | (flags & LCR_BYTE ? 32 : 0)); + + c_write (0); + c_write (10); + + c_write (c_read()); + c_write (c_read()); + + c_write (c_read()); + c_write (c_read()); + if (flags & LCR_OFFSET) + internal_error_in_function ("convert_to_mpw_object_code"); + + c_write (code_offset>>8); + c_write (code_offset); + + c=c_read(); + continue; + } + case LLABEL: + { + int flags,id_h,id_l; + + flags=c_read(); + id_h=c_read(); + id_l=c_read(); + + if (flags & LLABEL_EXTERN){ + int size; + + size=c_read(); + + c_write (O_DICTIONARY); + c_write (0); + + c_write (0); + c_write (size+7); + + c_write (id_h); + c_write (id_l); + + c_write (size); + if (!(size & 1)) + c_write (c_read()); + while (size--) + c_write (c_read()); + } + + c_write (O_ENTRY); + c_write ((flags & LLABEL_DATA ? 1 : 0) | (flags & LLABEL_EXTERN ? 8 : 0)); + + c_write (id_h); + c_write (id_l); + + if (flags & LLABEL_DATA){ + c_write (data_offset>>24); + c_write (data_offset>>16); + c_write (data_offset>>8); + c_write (data_offset); + } else { + c_write (code_offset>>24); + c_write (code_offset>>16); + c_write (code_offset>>8); + c_write (code_offset); + } + + if (flags & LLABEL_OFFSET) + internal_error_in_function ("convert_to_mpw_object_code"); + + c=c_read(); + continue; + } + case LIMPORT: + { + int size,id_l,id_h; + + c_read(); + + id_h=c_read(); + id_l=c_read(); + size=c_read(); + + c_write (O_DICTIONARY); + c_write (0); + + c_write (0); + c_write (size+7); + + c_write (id_h); + c_write (id_l); + + c_write (size); + + if (!(size & 1)) + c_write (c_read()); + while (size--) + c_write (c_read()); + + c=c_read(); + continue; + } + case LMODULE: + { + int flag; + + flag=c_read(); + + if (code_offset!=0){ + c_write (O_MODULE); + c_write (0); + + c_write (code_module_id>>8); + c_write (code_module_id); + code_module_id=next_label_id++; + + c_write (segment_id>>8); + c_write (segment_id); + + code_offset=0; + } + + if (data_offset!=0){ + c_write (O_MODULE); + c_write (1); + + c_write (data_module_id>>8); + c_write (data_module_id); + data_module_id=next_label_id++; + + c_write (0); + c_write (0); + + data_offset=0; + } + c=c_read(); + continue; + } + case LBEGIN: + c_read(); + c_read(); + c_read(); + + c_write (O_FIRST); + c_write (1); + c_write (0); + c_write (2); + + c_write (O_DICTIONARY); + c_write (0); + + c_write (0); + c_write (7+1); + + c_write (segment_id>>8); + c_write (segment_id); + + c_write (1); + c_write ('m'); + + c=c_read(); + continue; + case LEND: + c_read(); + c_write (O_LAST); + c_write (0); + break; + default: + internal_error_in_function ("convert_to_mpw_object_code"); + } + break; + } + + d_buffer->size=IO_BUFFER_SIZE-d_free; + d_buffer->next=NULL; + + { + struct object_buffer *buffer,*next_buffer; + + for (buffer=s_buffer; buffer!=NULL; buffer=next_buffer){ + next_buffer=buffer->next; + + memory_free (buffer); + } + } + + first_buffer=first_d_buffer; +} + +/* end mpw object conversion */ +#endif + +static void write_object_buffers_and_release_memory (VOID) +{ + struct object_buffer *buffer,*next_buffer; + + for (buffer=first_buffer; buffer!=NULL; buffer=next_buffer){ + int size; + + size=buffer->size; + + if (fwrite (buffer->data,1,size,output_file)!=size) + error ("Write error"); + + next_buffer=buffer->next; + + memory_free (buffer); + } + + first_buffer=NULL; +} + +/* #define write_c(c) putc((c),output_file) */ + +static void write_w (UWORD i) +{ + write_c (i>>8); + write_c (i); +} + +static void write_l (register ULONG i) +{ + write_c (i>>24); + write_c (i>>16); + write_c (i>>8); + write_c (i); +} + +static void write_block (void *buffer,int length) +{ + char *p; + + if (length){ + p=(char*)buffer; + do + write_c (*p++); + while (--length); + } + /* + if (fwrite (buffer,1,length,output_file)!=length) + error ("Write error"); + */ +} + +static void write_s (char string[]) +{ + int length; + + length=strlen (string); + if (length>255) + length=255; + + write_c (length); + write_block (string,length); + if (!(length & 1)) + write_c (0); +} + +#ifdef MODULES +void start_new_module (int flag) +{ + write_c (LMODULE); + write_c (flag); +} +#endif + +static void import_label (int id,char label_name[]) +{ + write_c (LIMPORT); + write_c (0); + write_w (id); + write_s (label_name); +} + +void define_local_label (int id,int flag) +{ + write_c (LLABEL); + write_c (flag); + write_w (id); +} + +static void define_local_text_label (int id) +{ + write_c (LLABEL); + write_c (LLABEL_TEXT); + write_w (id); +} + +void define_external_label (int id,int flag,char label_name[]) +{ + write_c (LLABEL); + write_c (flag | LLABEL_EXTERN); + write_w (id); + write_s (label_name); +} + +void store_word_in_data_section (UWORD i) +{ + write_c (LDATA); + write_c (2); + write_w (i); +} + +void store_long_word_in_data_section (ULONG i) +{ + write_c (LDATA); + write_c (4); + write_l (i); +} + +void store_label_in_data_section (int label_id) +{ +#ifdef USE_LABEL_VALUE + write_c (LLABEL_VALUE); + write_c (REFERENCE_LONG | REFERENCE_DATA); + write_w (label_id); +#else + write_c (LREFERENCE); + write_c (REFERENCE_LONG | REFERENCE_DATA); + write_w (label_id); + write_c (LDATA); + write_c (4); + write_l (0); +#endif +} + +void store_descriptor_in_code_section (int label_id) +{ + write_c (LLABEL_VALUE); + write_c (REFERENCE_A5 | REFERENCE_LONG); + write_w (label_id); +} + +void store_descriptor_in_data_section (int label_id) +{ + write_c (LLABEL_VALUE); + write_c (REFERENCE_DATA | REFERENCE_A5 | REFERENCE_LONG); + write_w (label_id); +} + +void store_label_offset_in_data_section (int label_id) +{ +#ifdef USE_LABEL_VALUE + write_c (LLABEL_VALUE); + write_c (REFERENCE_DATA | REFERENCE_A5); + write_w (label_id); +#else + write_c (LREFERENCE); + write_c (REFERENCE_DATA | REFERENCE_A5); + write_w (label_id); + write_c (LDATA); + write_c (2); + write_w (0); +#endif +} + +void store_label_offset_in_code_section (int label_id) +{ +#ifdef USE_LABEL_VALUE + write_c (LLABEL_VALUE); + write_c (REFERENCE_A5); + write_w (label_id); +#else + write_c (LREFERENCE); + write_c (REFERENCE_A5); + write_w (label_id); + write_c (LCODE); + write_c (2); + write_w (0); +#endif +} + +static void store_text_label_in_text_section (LABEL *label) +{ + if (label->label_id<0) + label->label_id=next_label_id++; + +#ifdef USE_LABEL_VALUE + write_c (LLABEL_VALUE); + write_c (0); + write_w (label->label_id); +#else + write_c (LREFERENCE); + write_c (0); + write_w (label->label_id); + write_c (LCODE); + write_c (2); + write_w (0); +#endif +} + +void store_c_string_in_data_section (char *string,int length) +{ + int t_length; + +/* t_length=(length+1+1) & ~1; */ + t_length=(length+1+3) & ~3; + + if (t_length+1>255) + internal_error ("String too long in 'store_c_string_in_data_section'"); + + write_c (LDATA); + write_c (t_length); + write_block (string,length); + write_c (0); +/* + if (!(length & 1)) + write_c (0); +*/ + while (++length,length<t_length) + write_c (0); +} + +void store_abc_string_in_data_section (char *string,int length) +{ + int t_length=(length+4+3) & ~3; + + if (t_length>255) + internal_error ("String too long in 'store_abc_string_in_data_section'"); + + write_c (LDATA); + write_c (t_length); + write_l (length); + write_block (string,length); + while (length & 3){ + write_c (0); + ++length; + } +} + +void store_c_string_in_code_section (char *string,int length) +{ + int t_length=(length+1+1) & ~1; + + if (t_length+1>255) + internal_error ("String too long in 'store_c_string_in_code_section'"); + + write_c (LCODE); + write_c (t_length); + write_block (string,length); + write_c (0); + if (!(length & 1)) + write_c (0); +} + +void store_abc_string_in_code_section (char *string,int length) +{ + int t_length=(length+4+3) & ~3; + + if (t_length>255) + internal_error ("String too long in 'store_abc_string_in_code_section'"); + + write_c (LCODE); + write_c (t_length); + write_l (length); + write_block (string,length); + while (length & 3){ + write_c (0); + ++length; + } +} + +static void write_number_of_arguments (int number_of_arguments) +{ + write_c (LCODE); + write_c (2); + write_w (number_of_arguments); +} + +void store_descriptor_string_in_code_section + (char *string,int length,int string_code_label_id,LABEL *string_label) +{ + int t_length; + + t_length=(length+4+3) & ~3; + + if (t_length>255) + internal_error ("String too long in 'store_descriptor_string_in_code_section'"); + + write_c (LLABEL); + write_c (LLABEL_TEXT); + write_w (string_code_label_id); + + write_c (LCODE); + write_c (6); + + write_w (040772); /* LEA 4+2(PC),A0 */ + write_w (4); + write_w (0x4e75); /* RTS */ + + write_c (LMODULE); + write_c (1); + + write_c (LLABEL); + write_c (LLABEL_TEXT); + write_w (string_label->label_id); + + write_c (LCODE); + write_c (t_length); + + write_l (length); + write_block (string,length); + while (length & 3){ + write_c (0); + ++length; + } +} + +static WORD write_indirect_node_entry_jump (LABEL *label) +{ + register int new_label_id; + + new_label_id=next_label_id++; + + if (label->label_flags & EA_LABEL){ + int label_arity; + extern LABEL *eval_upd_labels[],*eval_fill_label; + LABEL *eval_upd_label; + + label_arity=label->label_arity; + + if (label_arity<-2) + label_arity=1; + + if (label_arity>=0 && label->label_ea_label!=eval_fill_label){ + write_c (LCODE); + write_c (2); + write_w (042700); + + write_c (LLABEL_VALUE); + write_c (0); + if (label->label_ea_label->label_id<0) + label->label_ea_label->label_id=next_label_id++; + write_w (label->label_ea_label->label_id); + + write_c (LCODE); + write_c (2); + write_w (047300); + + write_c (LLABEL_VALUE); + write_c (0); + eval_upd_label=eval_upd_labels[label_arity]; + if (eval_upd_label->label_id<0) + eval_upd_label->label_id=next_label_id++; + write_w (eval_upd_label->label_id); + } else { + write_c (LCODE); + write_c (2); + write_w (047300); + + write_c (LLABEL_VALUE); + write_c (0); + if (label->label_ea_label->label_id<0) + label->label_ea_label->label_id=next_label_id++; + write_w (label->label_ea_label->label_id); + + write_c (LCODE); + write_c (4); + write_w (0x4e71); + write_w (0x4e71); + } + + if (label->label_arity<0 || parallel_flag){ + LABEL *descriptor_label; + + descriptor_label=label->label_descriptor; + + if (descriptor_label->label_id<0) + descriptor_label->label_id=next_label_id++; + + store_label_offset_in_code_section (descriptor_label->label_id); + } else + write_number_of_arguments (0); + } else + if (label->label_arity<0 || parallel_flag){ + LABEL *descriptor_label; + + descriptor_label=label->label_descriptor; + + if (descriptor_label->label_id<0) + descriptor_label->label_id=next_label_id++; + + store_label_offset_in_code_section (descriptor_label->label_id); + } + + write_number_of_arguments (label->label_arity); + + define_local_text_label (new_label_id); + + write_w ((LCODE<<8)+2); + write_w (047300); + +#ifdef USE_LABEL_VALUE + write_w (LLABEL_VALUE<<8); + write_w (label->label_id); +#else + write_w (LREFERENCE<<8); + write_w (label->label_id); + + write_w ((LCODE<<8)+2); + write_w (0); +#endif + + return new_label_id; +} + +static void write_indirect_defered_jump (LABEL *label) +{ + LABEL *node_label; + + if (EMPTY_label->label_id<0) + EMPTY_label->label_id=next_label_id++; + store_label_offset_in_code_section (EMPTY_label->label_id); + + write_number_of_arguments (label->label_arity); + + if (label->label_id<0) + label->label_id=next_label_id++; + define_local_text_label (label->label_id); + + write_w ((LCODE<<8)+2); + write_w (047300); + + node_label=label->label_descriptor; + if (node_label->label_id<0) + node_label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + write_w (LLABEL_VALUE<<8); + write_w (node_label->label_id); +#else + write_w (LREFERENCE<<8); + write_w (node_label->label_id); + + write_w ((LCODE<<8)+2); + write_w (0); +#endif +} + +#ifdef COUNT_RELEASES +static int node_entry_count_label_id; +#endif + +static void import_labels (register struct label_node *label_node) +{ + register LABEL *label; + + if (label_node==NULL) + return; + + label=&label_node->label_node_label; + + if (!(label->label_flags & LOCAL_LABEL) && label->label_number==0){ + if (label->label_id<0) + label->label_id=next_label_id++; + import_label (label->label_id,label->label_name); + if (label->label_flags & NODE_ENTRY_LABEL){ +#ifdef MODULES + start_new_module (0); +#endif + label->label_id=write_indirect_node_entry_jump (label); + } + } + + import_labels (label_node->label_node_left); + import_labels (label_node->label_node_right); +} + +static void write_indirect_jumps_for_defer_labels (void) +{ + struct local_label *local_label; + + for (local_label=local_labels; local_label!=NULL; local_label=local_label->local_label_next){ + LABEL *label; + + label=&local_label->local_label_label; + if (label->label_flags & DEFERED_LABEL){ +#ifdef MODULES + start_new_module (0); +#endif + write_indirect_defered_jump (label); + } + } +} + +static void write_labels (register struct block_label *labels) +{ + for (; labels!=NULL; labels=labels->block_label_next) + if (labels->block_label_label->label_number==0){ + register LABEL *label; + register int id; + + label=labels->block_label_label; + id=label->label_id; + if (id<0){ + id=next_label_id++; + label->label_id=id; + } + + if (label->label_flags & EXPORT_LABEL) + define_external_label (id,LLABEL_TEXT,label->label_name); + else + define_local_text_label (id); + } +} + +enum { SIZE_LONG, SIZE_WORD, SIZE_BYTE }; + +static void as_addressing_mode_instruction (struct parameter *parameter,int opcode,int size_flag) +{ + UWORD buffer[10],*code_buf_p,*end_buf_p; + + code_buf_p=buffer; + end_buf_p=code_buf_p; + *end_buf_p++=(LCODE<<8)+2; + ++end_buf_p; + + switch (parameter->parameter_type){ + case P_REGISTER: + { + int reg=parameter->parameter_data.reg.r; + if (is_d_register (reg)) + opcode |= 000 | d_reg_num (reg); + else + opcode |= 010 | a_reg_num (reg); + break; + } + case P_INDIRECT: + { + int offset=parameter->parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (parameter->parameter_data.reg.r); + } else { + opcode |= 050 | a_reg_num (parameter->parameter_data.reg.r); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_POST_INCREMENT: + opcode |= 030 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_PRE_DECREMENT: + opcode |= 040 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_LABEL: + { + LABEL *label; + + opcode |= 055; + + label=parameter->parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } + case P_DESCRIPTOR_NUMBER: + { + LABEL *label; + + opcode |= 074; + + if (size_flag==SIZE_LONG){ + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++=0xffff; + } + + label=parameter->parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; + +#ifdef USE_LABEL_VALUE + if (parameter->parameter_offset==0){ + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + } else { +#endif + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + code_buf_p=end_buf_p; + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=parameter->parameter_offset << 2; +#ifdef USE_LABEL_VALUE + } +#endif + break; + } + case P_IMMEDIATE: + opcode |= 074; + if (size_flag==SIZE_LONG){ + ((UBYTE*)code_buf_p)[1]+=4; + *(*(ULONG**)&end_buf_p)++ = parameter->parameter_data.i; + } else { + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = parameter->parameter_data.i; + } + break; +/* CHANGED 27-7-92 */ + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + + offset=parameter->parameter_offset; + index_registers=parameter->parameter_data.ir; + + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = 0x800 | (d_reg_num (index_registers->d_reg.r)<<12) + | ((offset>>2) & 0xff) | ((offset & 3)<<9); + opcode |= 060 | a_reg_num (index_registers->a_reg.r); + break; + } +/* */ + default: + internal_error_in_function ("as_addressing_mode_instruction"); + } + + buffer[1]=opcode; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); +} + +static void as_immediate_data_alterable_addressing_mode + (int opcode,UWORD buffer[],UWORD *code_buf_p,UWORD *end_buf_p,struct parameter *parameter) +{ + switch (parameter->parameter_type){ + case P_REGISTER: + { + int reg=parameter->parameter_data.reg.r; + if (is_d_register (reg)) + opcode |= 000 | d_reg_num (reg); + else + internal_error_in_function ("as_immediate_data_alterable_addressing mode"); + break; + } + case P_INDIRECT: + { + int offset=parameter->parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (parameter->parameter_data.reg.r); + } else { +#ifdef USE_LABEL_VALUE + if (code_buf_p==NULL){ + code_buf_p=end_buf_p; + *end_buf_p++=LCODE<<8; + } +#endif + opcode |= 050 | a_reg_num (parameter->parameter_data.reg.r); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_POST_INCREMENT: + opcode |= 030 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_PRE_DECREMENT: + opcode |= 040 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_LABEL: + { + LABEL *label; + + opcode |= 055; + + label=parameter->parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } +/* CHANGED 27-7-92 */ + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + + offset=parameter->parameter_offset; + index_registers=parameter->parameter_data.ir; +#ifdef USE_LABEL_VALUE + if (code_buf_p==NULL){ + code_buf_p=end_buf_p; + *end_buf_p++=LCODE<<8; + } +#endif + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = 0x800 | (d_reg_num (index_registers->d_reg.r)<<12) + | ((offset>>2) & 0xff) | ((offset & 3)<<9); + opcode |= 060 | a_reg_num (index_registers->a_reg.r); + break; + } +/* */ + default: + internal_error_in_function ("as_immediate_data_alterable_addressing_mode"); + } + + buffer[1]=opcode; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); +} + +static void as_data_addressing_mode ( int opcode,UWORD buffer[],UWORD *code_buf_p, + UWORD *end_buf_p,struct parameter *parameter,int size_flag) +{ + switch (parameter->parameter_type){ + case P_REGISTER: + { + int reg=parameter->parameter_data.reg.r; + if (is_d_register (reg)) + opcode |= 000 | d_reg_num (reg); + else + internal_error_in_function ("as_data_addressing mode"); + break; + } + case P_INDIRECT: + { + int offset=parameter->parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (parameter->parameter_data.reg.r); + } else { + opcode |= 050 | a_reg_num (parameter->parameter_data.reg.r); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_POST_INCREMENT: + opcode |= 030 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_PRE_DECREMENT: + opcode |= 040 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_LABEL: + { + LABEL *label; + + opcode |= 055; + + label=parameter->parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } + case P_DESCRIPTOR_NUMBER: + { + LABEL *label; + + opcode |= 074; + + if (size_flag==SIZE_LONG){ + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++=0xffff; + } + + label=parameter->parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + if (parameter->parameter_offset==0){ + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + } else { +#endif + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=parameter->parameter_offset << 2; +#ifdef USE_LABEL_VALUE + } +#endif + break; + } + case P_IMMEDIATE: + opcode |= 074; + if (size_flag==SIZE_LONG){ + ((UBYTE*)code_buf_p)[1]+=4; + *(*(ULONG**)&end_buf_p)++ = parameter->parameter_data.i; + } else { + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = parameter->parameter_data.i; + } + break; +/* CHANGED 27-7-92 */ + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + + offset=parameter->parameter_offset; + index_registers=parameter->parameter_data.ir; + + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = 0x800 | (d_reg_num (index_registers->d_reg.r)<<12) + | ((offset>>2) & 0xff) | ((offset & 3)<<9); + opcode |= 060 | a_reg_num (index_registers->a_reg.r); + break; + } +/* */ + default: + internal_error_in_function ("as_data_addressing_mode"); + } + + buffer[1]=opcode; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); +} + +static void as_alterable_memory_addressing_mode_instruction (struct parameter *parameter,int opcode) +{ + UWORD buffer[10],*code_buf_p,*end_buf_p; + + code_buf_p=buffer; + end_buf_p=code_buf_p; + *end_buf_p++=(LCODE<<8)+2; + ++end_buf_p; + + switch (parameter->parameter_type){ + case P_INDIRECT: + { + int offset=parameter->parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (parameter->parameter_data.reg.r); + } else { + opcode |= 050 | a_reg_num (parameter->parameter_data.reg.r); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_POST_INCREMENT: + opcode |= 030 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_PRE_DECREMENT: + opcode |= 040 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_LABEL: + { + LABEL *label; + + opcode |= 055; + + label=parameter->parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + code_buf_p=end_buf_p; + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } +/* CHANGED 27-7-92 */ + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + + offset=parameter->parameter_offset; + index_registers=parameter->parameter_data.ir; + + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = 0x800 | (d_reg_num (index_registers->d_reg.r)<<12) + | ((offset>>2) & 0xff) | ((offset & 3)<<9); + opcode |= 060 | a_reg_num (index_registers->a_reg.r); + break; + } +/* */ + default: + internal_error_in_function ("as_alterable_memory_addressing_mode_instruction"); + } + + buffer[1]=opcode; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); +} + +static void as_control_addressing_mode_instruction (struct parameter *parameter,int opcode) +{ + UWORD buffer[10],*end_buf_p; + + end_buf_p=buffer; + *end_buf_p++=(LCODE<<8)+2; + + switch (parameter->parameter_type){ + case P_INDIRECT: + { + int offset=parameter->parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (parameter->parameter_data.reg.r); + *end_buf_p++=opcode; + } else { + opcode |= 050 | a_reg_num (parameter->parameter_data.reg.r); + *end_buf_p++=opcode; + ((UBYTE*)buffer)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_LABEL: + { + LABEL *label; + + label=parameter->parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; + + if (label->label_flags & DATA_LABEL){ + opcode |= 055; + *end_buf_p++=opcode; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; +#endif + } else { + *end_buf_p++=opcode; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8); +#else + *end_buf_p++=(LREFERENCE<<8); +#endif + } + + *end_buf_p++=label->label_id; +#ifndef USE_LABEL_VALUE + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } +/* CHANGED 27-7-92 */ + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + + offset=parameter->parameter_offset; + index_registers=parameter->parameter_data.ir; + opcode |= 060 | a_reg_num (index_registers->a_reg.r); + + *end_buf_p++=opcode; + ((UBYTE*)buffer)[1]+=2; + *end_buf_p++ = 0x800 | (d_reg_num (index_registers->d_reg.r)<<12) + | ((offset>>2) & 0xff) | ((offset & 3)<<9); + break; + } +/* */ + default: + internal_error_in_function ("as_control_addressing_mode_instruction"); + } + + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); +} + +static void as_fp_instruction_p (int opcode,int fp_opcode,struct parameter *parameter) +{ + UWORD buffer[14],*code_buf_p,*end_buf_p; + + buffer[0]=(LCODE<<8)+4; + buffer[2]=fp_opcode; + + code_buf_p=buffer; + end_buf_p=&buffer[3]; + + switch (parameter->parameter_type){ + case P_REGISTER: + { + int reg=parameter->parameter_data.reg.r; + if (is_d_register (reg)) + opcode |= 000 | d_reg_num (reg); + else + internal_error_in_function ("as_fp_addressing mode"); + break; + } + case P_INDIRECT: + { + int offset=parameter->parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (parameter->parameter_data.reg.r); + } else { + opcode |= 050 | a_reg_num (parameter->parameter_data.reg.r); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_POST_INCREMENT: + opcode |= 030 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_PRE_DECREMENT: + opcode |= 040 | a_reg_num (parameter->parameter_data.reg.r); + break; + case P_LABEL: + { + LABEL *label; + + opcode |= 055; + + label=parameter->parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } + case P_F_IMMEDIATE: + { + DOUBLE d; + float f; + + opcode |= 074; + + d=*parameter->parameter_data.r; + f=d; + if (d==f){ + buffer[2]&=~0x1000; + ((UBYTE*)code_buf_p)[1]+=4; + *(*(float**)&end_buf_p)++ = f; + } else { + ((UBYTE*)code_buf_p)[1]+=8; + *(*(DOUBLE**)&end_buf_p)++ = d; + } + break; + } + case P_IMMEDIATE: + { + opcode |= 074; + ((UBYTE*)code_buf_p)[1]+=4; + *(*(ULONG**)&end_buf_p)++ = parameter->parameter_data.i; + break; + } +/* CHANGED 22-7-92 */ + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + + offset=parameter->parameter_offset; + index_registers=parameter->parameter_data.ir; + + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = 0x800 | (d_reg_num (index_registers->d_reg.r)<<12) + | ((offset>>2) & 0xff) | ((offset & 3)<<9); + opcode |= 060 | a_reg_num (index_registers->a_reg.r); + break; + } +/* */ + default: + internal_error_in_function ("as_fp_instruction_p"); + } + + buffer[1]=opcode; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); +} + +static void as_move_instruction (register struct instruction *instruction,int size_flag) +{ + register UWORD opcode; + UWORD buffer[14]; + register UWORD *code_buf_p,*end_buf_p; + + code_buf_p=buffer; + end_buf_p=code_buf_p; + *end_buf_p++=(LCODE<<8)+2; + ++end_buf_p; + opcode= size_flag==SIZE_LONG ? 020000 : (size_flag==SIZE_WORD ? 030000 : 010000); + + switch (instruction->instruction_parameters[0].parameter_type){ + case P_REGISTER: + { + int reg=instruction->instruction_parameters[0].parameter_data.reg.r; + if (is_d_register (reg)) + opcode |= 000 | d_reg_num (reg); + else + opcode |= 010 | a_reg_num (reg); + break; + } + case P_INDIRECT: + { + int offset=instruction->instruction_parameters[0].parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + } else { + opcode |= 050 | a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_POST_INCREMENT: + opcode |= 030 | a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + break; + case P_PRE_DECREMENT: + opcode |= 040 | a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + break; + case P_LABEL: + { + LABEL *label; + + opcode |= 055; + + label=instruction->instruction_parameters[0].parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + code_buf_p=NULL; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + code_buf_p=end_buf_p; + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } + case P_DESCRIPTOR_NUMBER: + { + LABEL *label; + + opcode |= 074; + if (size_flag==SIZE_LONG){ + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++=0xffff; + } + + label=instruction->instruction_parameters[0].parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + if (instruction->instruction_parameters[0].parameter_offset==0){ + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + code_buf_p=NULL; + } else { +#endif + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + code_buf_p=end_buf_p; + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=instruction->instruction_parameters[0].parameter_offset << 2; +#ifdef USE_LABEL_VALUE + } +#endif + break; + } + case P_IMMEDIATE: + { + LONG i=instruction->instruction_parameters[0].parameter_data.i; + + /* MOVEQ ? */ + if (size_flag==SIZE_LONG && i<128 && i>=-128 + && instruction->instruction_parameters[1].parameter_type==P_REGISTER + && is_d_register (instruction->instruction_parameters[1].parameter_data.reg.r)){ + write_c (LCODE); + write_c (2); + write_c (0x70 | (d_reg_num + (instruction->instruction_parameters[1].parameter_data.reg.r)<<1)); + write_c (i); + return; + } + + /* CLR ? */ + if (i==0 && instruction->instruction_parameters[1].parameter_type!=P_REGISTER){ + buffer[0]=(LCODE<<8)+2; + opcode=(size_flag==SIZE_LONG) ? 041200 : (size_flag==SIZE_WORD) ? 041100 : 041000 ; + + as_data_addressing_mode (opcode,buffer,buffer,&buffer[2], + &instruction->instruction_parameters[1],size_flag); + return; + } + + if (size_flag==SIZE_LONG){ + ((UBYTE*)code_buf_p)[1]+=4; + *(ULONG*)end_buf_p=i; + end_buf_p+=2; + } else { + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++=i; + } + opcode |= 074; + break; + } +/* CHANGED 22-7-92 */ + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + + offset=instruction->instruction_parameters[0].parameter_offset; + + index_registers=instruction->instruction_parameters[0].parameter_data.ir; + + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = 0x800 | (d_reg_num (index_registers->d_reg.r)<<12) + | ((offset>>2) & 0xff) | ((offset & 3)<<9); + opcode |= 060 | a_reg_num (index_registers->a_reg.r); + break; + } +/* */ + default: + internal_error_in_function ("as_move_instruction"); + } + + switch (instruction->instruction_parameters[1].parameter_type){ + case P_REGISTER: + { + int reg=instruction->instruction_parameters[1].parameter_data.reg.r; + if (is_d_register (reg)) + opcode |= 0000 | (d_reg_num (reg)<<9); + else + opcode |= 0100 | (a_reg_num (reg)<<9); + break; + } + case P_INDIRECT: + { + int offset=instruction->instruction_parameters[1].parameter_offset; + if (offset==0){ + opcode |= 0200 | + (a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r)<<9); + } else { +#ifdef USE_LABEL_VALUE + if (code_buf_p==NULL){ + code_buf_p=end_buf_p; + *end_buf_p++=LCODE<<8; + } +#endif + opcode |= 0500 | + (a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r)<<9); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_POST_INCREMENT: + opcode |= 0300 | + (a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r)<<9); + break; + case P_PRE_DECREMENT: + opcode |= 0400 | + (a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r)<<9); + break; + case P_LABEL: + { + LABEL *label; + + opcode |= 05200; + + label=instruction->instruction_parameters[1].parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; + +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } +/* CHANGED 22-7-92 */ + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + +#ifdef USE_LABEL_VALUE + if (code_buf_p==NULL){ + code_buf_p=end_buf_p; + *end_buf_p++=LCODE<<8; + } +#endif + index_registers=instruction->instruction_parameters[1].parameter_data.ir; + offset=instruction->instruction_parameters[1].parameter_offset; + + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = 0x800 | (d_reg_num (index_registers->d_reg.r)<<12) + | ((offset>>2) & 0xff) | ((offset & 3)<<9); + opcode |= 0600 | (a_reg_num (index_registers->a_reg.r)<<9); + break; + } +/* */ + default: + internal_error_in_function ("as_move_instruction"); + } + + buffer[1]=opcode; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); +} + +static void as_lea_instruction (struct instruction *instruction) +{ + int opcode=040700 | (a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r)<<9); + + if (instruction->instruction_parameters[0].parameter_type==P_LABEL && + instruction->instruction_parameters[0].parameter_offset!=0) + { + UWORD buffer[10],*end_buf_p; + LABEL *label; + + end_buf_p=buffer; + *end_buf_p++=(LCODE<<8)+2; + + label=instruction->instruction_parameters[0].parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; + + if (label->label_flags & DATA_LABEL){ + opcode |= 055; + *end_buf_p++=opcode; + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + } else { + *end_buf_p++=opcode; + *end_buf_p++=(LREFERENCE<<8); + } + + *end_buf_p++=label->label_id; + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=instruction->instruction_parameters[0].parameter_offset; + + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); + } else + as_control_addressing_mode_instruction (&instruction->instruction_parameters[0],opcode); +} + +static void as_add_instruction (struct instruction *instruction) +{ + int opcode; + + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){ + int reg=instruction->instruction_parameters[1].parameter_data.reg.r; + + /* ADDQ, SUBQ or LEA ? */ + if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){ + LONG i=instruction->instruction_parameters[0].parameter_data.i; + + if (i<=8 && i>=-8 && i!=0){ + write_c (LCODE); + write_c (2); + if (i>0) + opcode=050200 | ((i & 7) << 9); + else + opcode=050600 | ((-i & 7) << 9); + if (is_d_register (reg)) + opcode |= d_reg_num (reg); + else + opcode |= 010 | a_reg_num (reg); + write_w (opcode); + return; + } else if (is_a_register (reg) && i>=-32768 && i<32768){ + write_c (LCODE); + write_c (4); + write_w (040750 | a_reg_num (reg) | (a_reg_num (reg)<<9)); + write_w (i); + return; + } + } + + if (is_d_register (reg)) + opcode=0150200 + (d_reg_num (reg)<<9); + else + opcode=0150700 + (a_reg_num (reg)<<9); + + as_addressing_mode_instruction (&instruction->instruction_parameters[0],opcode,SIZE_LONG); + } else if (instruction->instruction_parameters[0].parameter_type==P_REGISTER && + is_d_register (instruction->instruction_parameters[0].parameter_data.reg.r)){ + opcode=0150600 + + (d_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r)<<9); + as_alterable_memory_addressing_mode_instruction + (&instruction->instruction_parameters[1],opcode); + } else + /* ADDI not yet implemented */ + internal_error_in_function ("as_add_instruction"); +} + +static void as_sub_instruction (struct instruction *instruction) +{ + int opcode; + + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){ + int reg=instruction->instruction_parameters[1].parameter_data.reg.r; + + /* SUBQ, ADDQ or LEA ? */ + if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){ + LONG i=instruction->instruction_parameters[0].parameter_data.i; + + if (i<=8 && i>=-8 && i!=0){ + write_c (LCODE); + write_c (2); + if (i>0) + opcode=050600 | ((i & 7) << 9); + else + opcode=050200 | ((-i & 7) << 9); + if (is_d_register (reg)) + opcode |= d_reg_num (reg); + else + opcode |= 010 | a_reg_num (reg); + write_w (opcode); + return; + } else if (is_a_register (reg) && i>-32768 && i<=32768){ + write_c (LCODE); + write_c (4); + write_w (040750 | a_reg_num (reg) | (a_reg_num (reg)<<9)); + write_w (-i); + return; + } + + } + + if (is_d_register (reg)) + opcode=0110200 + (d_reg_num (reg)<<9); + else + opcode=0110700 + (a_reg_num (reg)<<9); + + as_addressing_mode_instruction (&instruction->instruction_parameters[0],opcode,SIZE_LONG); + } else if (instruction->instruction_parameters[0].parameter_type==P_REGISTER && + is_d_register (instruction->instruction_parameters[0].parameter_data.reg.r)){ + opcode=0110600 + + (d_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r)<<9); + as_alterable_memory_addressing_mode_instruction + (&instruction->instruction_parameters[1],opcode); + } else + /* SUBI not yet implemented */ + internal_error_in_function ("as_sub_instruction"); +} + +static void as_and_or_instruction (struct instruction *instruction,int opcode) +{ + UWORD buffer[14]; + int reg; + + if (instruction->instruction_parameters[1].parameter_type!=P_REGISTER || + is_a_register (reg=instruction->instruction_parameters[1].parameter_data.reg.r)) + { + internal_error_in_function ("as_and_or_instruction"); + return; + } + + opcode+=d_reg_num (reg)<<9; + + buffer[0]=(LCODE<<8)+2; + as_data_addressing_mode (opcode,buffer,buffer,&buffer[2], + &instruction->instruction_parameters[0],SIZE_LONG); +} + +static void as_eor_instruction (struct instruction *instruction) +{ + int reg_1,reg_2; + + if (instruction->instruction_parameters[1].parameter_type!=P_REGISTER || + is_a_register (reg_2=instruction->instruction_parameters[1].parameter_data.reg.r)) + { + internal_error_in_function ("as_eor_instruction"); + return; + } + + switch (instruction->instruction_parameters[0].parameter_type){ + case P_IMMEDIATE: + { + long m=instruction->instruction_parameters[0].parameter_data.i; + + if (m==-1){ /* replace EOR #-1,Dn by NOT Dn */ + write_c (LCODE); + write_c (2); + write_w (043200 | d_reg_num (reg_2)); + } else { + write_c (LCODE); + write_c (6); + write_w (005200 | d_reg_num (reg_2)); + write_l (m); + } + return; + } + case P_REGISTER: + if (is_d_register (reg_1=instruction->instruction_parameters[0].parameter_data.reg.r)){ + write_c (LCODE); + write_c (2); + write_w (0130600 | (d_reg_num (reg_1)<<9) | d_reg_num (reg_2)); + return; + } + default: + internal_error_in_function ("as_eor_instruction"); + } +} + +static void as_cmp_instruction (struct instruction *instruction,int size_flag) +{ + int opcode; + + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){ + int reg=instruction->instruction_parameters[1].parameter_data.reg.r; + + if (is_d_register (reg)){ + if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE && + instruction->instruction_parameters[0].parameter_data.i==0){ + /* CMPI #0 becomes TST */ + write_c (LCODE); + write_c (2); + write_w ((size_flag==SIZE_LONG ? 045200 : 045100) | d_reg_num (reg)); + return; + } + opcode=0130200 + (d_reg_num (reg)<<9); + } else + opcode=0130700 + (a_reg_num (reg)<<9); + + as_addressing_mode_instruction (&instruction->instruction_parameters[0],opcode,size_flag); + } else + switch (instruction->instruction_parameters[0].parameter_type){ + case P_IMMEDIATE: + { + UWORD buffer[14],*end_buf_p,opcode; + LONG i; + + i=instruction->instruction_parameters[0].parameter_data.i; + + if (i==0){ + /* CMPI #0 becomes TST */ + buffer[0]=(LCODE<<8)+2; + opcode= size_flag==SIZE_LONG ? 045200 : 045100; + as_immediate_data_alterable_addressing_mode + (opcode,buffer,buffer,&buffer[2],&instruction->instruction_parameters[1]); + } else { + if (size_flag==SIZE_LONG){ + buffer[0]=(LCODE<<8)+6; + *(ULONG*)(&buffer[2])=i; + end_buf_p=&buffer[4]; + opcode=06200; + } else { + buffer[0]=(LCODE<<8)+4; + buffer[2]=i; + end_buf_p=&buffer[3]; + opcode=06100; + } + as_immediate_data_alterable_addressing_mode + (opcode,buffer,buffer,end_buf_p,&instruction->instruction_parameters[1]); + } + break; + } + case P_DESCRIPTOR_NUMBER: + { + UWORD buffer[14],*end_buf_p,*code_buf_p,opcode; + LABEL *label; + + buffer[0]=(LCODE<<8)+2; + code_buf_p=buffer; + end_buf_p=&buffer[2]; + + if (size_flag==SIZE_LONG){ + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++=0xffff; + opcode=06200; + } else + opcode=06100; + + label=instruction->instruction_parameters[0].parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + if (instruction->instruction_parameters[0].parameter_offset==0){ + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + code_buf_p=NULL; + } else { +#endif + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + code_buf_p=end_buf_p; + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=instruction->instruction_parameters[0].parameter_offset << 2; +#ifdef USE_LABEL_VALUE + } +#endif + as_immediate_data_alterable_addressing_mode + (opcode,buffer,code_buf_p,end_buf_p,&instruction->instruction_parameters[1]); + break; + } + default: + internal_error_in_function ("as_cmp_instruction"); + } +} + +static void as_tst_instruction (struct instruction *instruction,int size_flag) +{ + UWORD buffer[14],opcode; + + buffer[0]=(LCODE<<8)+2; + opcode=045200; + + as_data_addressing_mode (opcode,buffer,buffer,&buffer[2], + &instruction->instruction_parameters[0],size_flag); +} + +static void as_branch_instruction (struct instruction *instruction,int opcode) +{ + UWORD buffer[10]; + register UWORD *buf_p; + LABEL *label; + + if (instruction->instruction_parameters[0].parameter_type!=P_LABEL) + internal_error_in_function ("as_branch_instruction"); + + label=instruction->instruction_parameters[0].parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; + + buf_p=buffer; + *buf_p++=(LCODE<<8)+2; + *buf_p++=opcode; + +#if defined (USE_LABEL_VALUE) && !defined (GENERATE_MPW_OBJECT_CODE) + *buf_p++=(LLABEL_VALUE<<8)+REFERENCE_PC; + *buf_p++=label->label_id; +#else + { + int id; + + id=next_label_id++; + *buf_p++=(LLABEL<<8); + *buf_p++=id; + *buf_p++=(LC_REFERENCE<<8)+LCR_WORD; + *buf_p++=label->label_id; + *buf_p++=id; + *buf_p++=(LCODE<<8)+2; + *buf_p++=0; + } +#endif + write_block (buffer,(UBYTE*)buf_p-(UBYTE*)buffer); +} + +static void as_short_branch_instruction (struct instruction *instruction,int opcode) +{ + switch (instruction->instruction_parameters[0].parameter_type){ + case P_LABEL: + { + LABEL *label; + UWORD buffer[10],*buf_p; + int id; + + label=instruction->instruction_parameters[0].parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; + + id=next_label_id++; + + buf_p=buffer; + *buf_p++=(LCODE<<8)+1; + *buf_p++=opcode; + + *buf_p++=(LC_REFERENCE<<8)+LCR_BYTE; + *buf_p++=label->label_id; + *buf_p++=id; + + *buf_p++=(LCODE<<8)+1; + *buf_p++=0; + + *buf_p++=(LLABEL<<8); + *buf_p++=id; + + write_block (buffer,(UBYTE*)buf_p-(UBYTE*)buffer); + return; + } + case P_IMMEDIATE: + { + int offset; + + offset=instruction->instruction_parameters[0].parameter_data.i; + + write_w ((LCODE<<8)+2); + write_w (opcode+offset); + return; + } + default: + internal_error_in_function ("as_short_branch_instruction"); + } +} + +static void as_movem_instruction (struct instruction *instruction) +{ + UWORD opcode,register_list; + UWORD buffer[10],*code_buf_p,*end_buf_p; + register unsigned int n,arity; + + code_buf_p=buffer; + end_buf_p=code_buf_p; + *end_buf_p++=(LCODE<<8)+4; + ++end_buf_p; + ++end_buf_p; + opcode=046300; + + switch (instruction->instruction_parameters[0].parameter_type){ + case P_INDIRECT: + { + int offset=instruction->instruction_parameters[0].parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + } else { + opcode |= 050 | a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + break; + } + case P_POST_INCREMENT: + opcode |= 030 | a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + break; + case P_LABEL: + { + LABEL *label; + + opcode |= 055; + + label=instruction->instruction_parameters[0].parameter_data.l; + if (label->label_id<0) + label->label_id=next_label_id++; +#ifdef USE_LABEL_VALUE + *end_buf_p++=(LLABEL_VALUE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; +#else + *end_buf_p++=(LREFERENCE<<8)+REFERENCE_A5; + *end_buf_p++=label->label_id; + + *end_buf_p++=(LCODE<<8)+2; + *end_buf_p++=0; +#endif + break; + } + case P_REGISTER: + { + int offset,reg; + + arity=instruction->instruction_arity; + + if (instruction->instruction_parameters[arity-1].parameter_type==P_PRE_DECREMENT){ + opcode = 044340 | a_reg_num (instruction->instruction_parameters[arity-1].parameter_data.reg.r); + + register_list=0; + --arity; + for (n=0; n<arity; ++n){ + register int reg; + + reg=instruction->instruction_parameters[n].parameter_data.reg.r; + if (is_d_register (reg)) + register_list |= ((unsigned)0x8000>>d_reg_num (reg)); + else + register_list |= ((unsigned)0x8000>>8+a_reg_num (reg)); + } + + buffer[1]=opcode; + buffer[2]=register_list; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); + return; + } + + if (instruction->instruction_arity!=2 + || instruction->instruction_parameters[1].parameter_type!=P_INDIRECT) + internal_error_in_function ("as_movem_instruction"); + + opcode=044300; + offset=instruction->instruction_parameters[1].parameter_offset; + if (offset==0){ + opcode |= 020 | a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r); + } else { + opcode |= 050 | a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r); + ((UBYTE*)code_buf_p)[1]+=2; + *end_buf_p++ = offset; + } + + reg=instruction->instruction_parameters[0].parameter_data.reg.r; + if (is_d_register (reg)) + register_list = ((unsigned)1<<d_reg_num (reg)); + else + register_list = ((unsigned)1<<8+a_reg_num (reg)); + + buffer[1]=opcode; + buffer[2]=register_list; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); + return; + } + default: + internal_error_in_function ("as_movem_instruction"); + } + + register_list=0; + + arity=instruction->instruction_arity; + for (n=1; n<arity; ++n){ + register int reg; + + reg=instruction->instruction_parameters[n].parameter_data.reg.r; + if (is_d_register (reg)) + register_list |= ((unsigned)1<<d_reg_num (reg)); + else + register_list |= ((unsigned)1<<8+a_reg_num (reg)); + } + + buffer[1]=opcode; + buffer[2]=register_list; + write_block (buffer,(UBYTE*)end_buf_p-(UBYTE*)buffer); +} + +static void as_shift_instruction (struct instruction *instruction,int opcode) +{ + int reg_1,reg_2; + + if (instruction->instruction_parameters[1].parameter_type!=P_REGISTER || + !is_d_register (reg_2=instruction->instruction_parameters[1].parameter_data.reg.r)) + { + internal_error_in_function ("as_shift_instruction"); + return; + } + + switch (instruction->instruction_parameters[0].parameter_type){ + case P_IMMEDIATE: + { + LONG count; + + count=instruction->instruction_parameters[0].parameter_data.i; + + if (count<=0 || count>8) + internal_error_in_function ("as_shift_instruction"); + + write_c (LCODE); + write_c (2); + write_w (opcode | ((count & 7)<<9) | d_reg_num (reg_2)); + return; + } + case P_REGISTER: + if (is_d_register (reg_1=instruction->instruction_parameters[0].parameter_data.reg.r)){ + write_c (LCODE); + write_c (2); + write_w (opcode | 040 | (d_reg_num (reg_1)<<9) | d_reg_num (reg_2)); + return; + } + default: + internal_error_in_function ("as_shift_instruction"); + } +} + +static void as_mul_instruction (struct instruction *instruction) +{ + UWORD buffer[14],opcode,reg; + + buffer[0]=(LCODE<<8)+4; + reg=instruction->instruction_parameters[1].parameter_data.reg.r; + buffer[2]=004000 | reg | (reg<<12); + opcode=046000; + + as_data_addressing_mode (opcode,buffer,buffer,&buffer[3], + &instruction->instruction_parameters[0],SIZE_LONG); +} + +static void as_div_instruction (struct instruction *instruction) +{ + UWORD buffer[14],opcode,reg_n; + + buffer[0]=(LCODE<<8)+4; + reg_n=d_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r); + buffer[2]=004000 | reg_n | (reg_n<<12); + opcode=046100; + + as_data_addressing_mode (opcode,buffer,buffer,&buffer[3], + &instruction->instruction_parameters[0],SIZE_LONG); +} + +static void as_mod_instruction (struct instruction *instruction) +{ + UWORD buffer[14],opcode; + + + buffer[0]=(LCODE<<8)+4; + buffer[2]=004000 | instruction->instruction_parameters[1].parameter_data.reg.r + | (instruction->instruction_parameters[2].parameter_data.reg.r<<12); + opcode=046100; + + as_data_addressing_mode (opcode,buffer,buffer,&buffer[3], + &instruction->instruction_parameters[0],SIZE_LONG); +} + +static void as_bmove_instruction (struct instruction *instruction) +{ + UWORD buffer[5],opcode; + + buffer[0]=(LCODE<<8)+8; + buffer[1]=0x6002; /* BRA.S *+4 */ + opcode=020000; + switch (instruction->instruction_parameters[0].parameter_type){ + case P_POST_INCREMENT: + opcode |= 030 | + a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + break; + case P_PRE_DECREMENT: + opcode |= 040 | + a_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + break; + default: + internal_error_in_function ("as_bmove_instruction"); + } + switch (instruction->instruction_parameters[1].parameter_type){ + case P_POST_INCREMENT: + opcode |= 0300 | + (a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r)<<9); + break; + case P_PRE_DECREMENT: + opcode |= 0400 | + (a_reg_num (instruction->instruction_parameters[1].parameter_data.reg.r)<<9); + break; + default: + internal_error_in_function ("as_bmove_instruction"); + } + buffer[2]=opcode; /* MOVE -(An)+,-(An)+ */ + buffer[3]=0x51c8+d_reg_num (instruction->instruction_parameters[2].parameter_data.reg.r); + buffer[4]=-4; /* DBRA Dn,*-2 */ + + write_block (buffer,10); +} + +static void as_exg_instruction (struct instruction *instruction) +{ + int opcode,reg_1,reg_2; + + reg_1=instruction->instruction_parameters[0].parameter_data.reg.r; + reg_2=instruction->instruction_parameters[1].parameter_data.reg.r; + if (is_d_register (reg_1)) + if (is_d_register (reg_2)) + opcode=0xc140+(d_reg_num (reg_1)<<9)+d_reg_num (reg_2); + else + opcode=0xc188+(d_reg_num (reg_1)<<9)+a_reg_num (reg_2); + else + if (is_d_register (reg_2)) + opcode=0xc188+(d_reg_num (reg_2)<<9)+a_reg_num (reg_1); + else + opcode=0xc148+(a_reg_num (reg_1)<<9)+a_reg_num (reg_2); + + write_c (LCODE); + write_c (2); + write_w (opcode); +} + +static void as_extb_instruction (struct instruction *instruction) +{ + int reg; + + reg=d_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + + if (!mc68000_flag){ + write_c (LCODE); + write_c (2); + write_w (044700 | d_reg_num (reg)); + } else { + write_c (LCODE); + write_c (4); + write_w (044200 | d_reg_num (reg)); + write_w (044300 | d_reg_num (reg)); + } +} + +static void as_ext_instruction (struct instruction *instruction) +{ + int reg=d_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r); + + write_c (LCODE); + write_c (2); + write_w (044300+d_reg_num (reg)); +} + +static void as_set_condition_instruction (struct instruction *instruction,int opcode) +{ + int reg_1; + + if (instruction->instruction_parameters[0].parameter_type!=P_REGISTER || + !is_d_register (reg_1=instruction->instruction_parameters[0].parameter_data.reg.r)) + { + internal_error_in_function ("as_set_condition_instruction"); + return; + } + + if (!mc68000_flag){ + write_c (LCODE); + write_c (4); + write_w (opcode | d_reg_num (reg_1)); + write_w (044700 | d_reg_num (reg_1)); + } else { + write_c (LCODE); + write_c (6); + write_w (opcode | d_reg_num (reg_1)); + write_w (044200 | d_reg_num (reg_1)); + write_w (044300 | d_reg_num (reg_1)); + } +} + +static void as_fmove_instruction (struct instruction *instruction,int size_mask) +{ + if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){ + int reg_1; + + reg_1=instruction->instruction_parameters[0].parameter_data.reg.r; + + if (instruction->instruction_parameters[1].parameter_type==P_F_REGISTER){ + int reg_2; + + reg_2=instruction->instruction_parameters[1].parameter_data.reg.r; + write_c (LCODE); + write_c (4); + write_w (0xf200); + write_w ((reg_1<<10) | (reg_2<<7)); + } else + as_fp_instruction_p (0xf200,size_mask | 0x6000 | (reg_1<<7), + &instruction->instruction_parameters[1]); + } else if (instruction->instruction_parameters[1].parameter_type==P_F_REGISTER){ + int reg_1; + + reg_1=instruction->instruction_parameters[1].parameter_data.reg.r; + as_fp_instruction_p (0xf200,size_mask | 0x4000 | (reg_1<<7), + &instruction->instruction_parameters[0]); + } else + internal_error_in_function ("as_fmove_instruction"); +} + +static void as_fp_instruction (struct instruction *instruction,int function_code) +{ + int reg_1; + + if (instruction->instruction_parameters[1].parameter_type!=P_F_REGISTER){ + internal_error_in_function ("as_fp_instruction"); + return; + } + reg_1=instruction->instruction_parameters[1].parameter_data.reg.r; + + if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){ + int reg_2; + + reg_2=instruction->instruction_parameters[0].parameter_data.reg.r; + + write_c (LCODE); + write_c (4); + write_w (0xf200); + write_w (function_code | (reg_2<<10) | (reg_1<<7)); + } else + as_fp_instruction_p (0xf200,function_code | (0x1400 | 0x4000) | (reg_1<<7), + &instruction->instruction_parameters[0]); +} + +static void as_fp_set_condition_instruction (struct instruction *instruction,int c_code) +{ + as_fp_instruction_p (0171100,c_code,&instruction->instruction_parameters[0]); + + if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){ + write_c (LCODE); + write_c (2); + write_w (044700 | d_reg_num (instruction->instruction_parameters[0].parameter_data.reg.r)); + } +} + +static void as_jsr_schedule (int n_a_and_f_registers) +{ + write_c (LCODE); + + if (n_a_and_f_registers & 15){ + write_c (6); + write_w (0xf227); + if ((n_a_and_f_registers & 15)==1) + write_w (0x6800); + else + write_w (0xe000 | (~(-1<<(n_a_and_f_registers & 15))) ); + } else + write_c (2); + + write_w (047200); + + switch (n_a_and_f_registers>>4){ + case 0: store_text_label_in_text_section (schedule_0_label); break; + case 1: store_text_label_in_text_section (schedule_1_label); break; + case 2: store_text_label_in_text_section (schedule_2_label); break; + case 3: store_text_label_in_text_section (schedule_3_label); break; + case 256>>4:store_text_label_in_text_section (schedule_eval_label); break; + default: internal_error_in_function ("as_jsr_schedule"); + } + + if (n_a_and_f_registers & 15){ + write_c (LCODE); + write_c (4); + write_w (0xf21f); + if ((n_a_and_f_registers & 15)==1) + write_w (0x4800); + else + write_w (0xd000 | ((0xff>>(n_a_and_f_registers & 15)) ^ 0xff) ); + } +} + +static void as_jmp_instruction (struct instruction *instruction) +{ + if (instruction->instruction_parameters[0].parameter_type==P_LABEL + && instruction->instruction_parameters[0].parameter_data.l->label_flags & LOCAL_LABEL) + { + if (parallel_flag){ + /* DBRA D6, */ + as_branch_instruction (instruction,0x51CE); + /* JSR schedule */ + as_jsr_schedule (instruction->instruction_parameters[0].parameter_offset); + /* BRA */ + as_branch_instruction (instruction,0x6000); + } else + as_branch_instruction (instruction,0x6000); + } else { + if (parallel_flag){ + int n_a_and_f_registers; + + if (instruction->instruction_parameters[0].parameter_type==P_LABEL) + n_a_and_f_registers=instruction->instruction_parameters[0].parameter_offset; + else + n_a_and_f_registers=instruction->instruction_parameters[0].parameter_data.reg.u; + + if (n_a_and_f_registers!=128){ + /* DBRA D6,2+n(PC) */ + write_c (LCODE); + write_c (4); + write_w (0x51CE); + + if (n_a_and_f_registers & 15) + write_w (14); + else + write_w (6); + + as_jsr_schedule (n_a_and_f_registers); + } + } + as_control_addressing_mode_instruction (&instruction->instruction_parameters[0],047300); + } +} + +static void as_jsr_instruction (struct instruction *instruction) +{ + if (instruction->instruction_parameters[0].parameter_type==P_LABEL + && instruction->instruction_parameters[0].parameter_data.l->label_flags & LOCAL_LABEL) + { + if (parallel_flag){ + int n_a_and_f_registers; + + n_a_and_f_registers=instruction->instruction_parameters[0].parameter_offset; + + /* PEA 2+n(PC) */ + write_c (LCODE); + write_c (4); + write_w (044172); + + if (n_a_and_f_registers & 15) + write_w (22); + else + write_w (14); + + /* DBRA D6, */ + as_branch_instruction (instruction,0x51CE); + as_jsr_schedule (n_a_and_f_registers); + /* BRA */ + as_branch_instruction (instruction,0x6000); + } else + as_branch_instruction (instruction,0x6100); + } else { + if (parallel_flag){ + int n_a_and_f_registers; + + if (instruction->instruction_parameters[0].parameter_type==P_LABEL) + n_a_and_f_registers=instruction->instruction_parameters[0].parameter_offset; + else + n_a_and_f_registers=instruction->instruction_parameters[0].parameter_data.reg.u; + + /* DBRA D6,2+n(PC) */ + write_c (LCODE); + write_c (4); + write_w (0x51CE); + + if (n_a_and_f_registers & 15) + write_w (14); + else + write_w (6); + + as_jsr_schedule (n_a_and_f_registers); + } + as_control_addressing_mode_instruction (&instruction->instruction_parameters[0],047200); + } +} + +struct call_and_jump { + struct call_and_jump *cj_next; + WORD cj_label_id; + WORD cj_call_id; + WORD cj_jump_id; +}; + +static struct call_and_jump *first_call_and_jump,*last_call_and_jump; + +static void as_garbage_collect_test (register struct basic_block *block) +{ + int n_cells,label_id_1,label_id_2; + struct call_and_jump *new_call_and_jump; + + label_id_1=next_label_id++; + label_id_2=next_label_id++; + + new_call_and_jump=(struct call_and_jump*)allocate_memory_from_heap (sizeof (struct call_and_jump)); + + new_call_and_jump->cj_next=NULL; + new_call_and_jump->cj_label_id=label_id_1; + new_call_and_jump->cj_jump_id=label_id_2; + switch (block->block_n_begin_a_parameter_registers){ + case 0: new_call_and_jump->cj_call_id=collect_0_label->label_id; break; + case 1: new_call_and_jump->cj_call_id=collect_1_label->label_id; break; + case 2: new_call_and_jump->cj_call_id=collect_2_label->label_id; break; + case 3: new_call_and_jump->cj_call_id=collect_3_label->label_id; break; + default: internal_error_in_function ("as_garbage_collect_test"); + } + + if (first_call_and_jump!=NULL) + last_call_and_jump->cj_next=new_call_and_jump; + else + first_call_and_jump=new_call_and_jump; + last_call_and_jump=new_call_and_jump; + + n_cells=block->block_n_new_heap_cells; + if (n_cells<=8){ + /* SUBQ.L #n,D7 */ + write_c (LCODE); + write_c (4); + write_w (050607+((n_cells & 7)<<9)); + } else if (n_cells<128 + && block->block_n_begin_d_parameter_registers < + (parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS)) + { + write_c (LCODE); + write_c (6); + if (parallel_flag){ + /* MOVEQ #n,D5 */ + /* SUB.L D5,D7 */ + write_w (075000+n_cells); + write_w (0117205); + } else { + /* MOVEQ #n,D6 */ + /* SUB.L D6,D7 */ + write_w (076000+n_cells); + write_w (0117206); + } + } else { + /* SUB.L #n,D7 */ + write_c (LCODE); + write_c (8); + write_w (0117274); + write_l (n_cells); + } + + /* BCS */ + write_c (0x65); + write_c (0); +#if defined (USE_LABEL_VALUE) && !defined (GENERATE_MPW_OBJECT_CODE) + write_c (LLABEL_VALUE); + write_c (REFERENCE_PC); + write_w (label_id_1); +#else /* l3 */ + { + int label_id; + + label_id=next_label_id++; + define_local_text_label (label_id); + /* l1 - l3 */ + write_c (LC_REFERENCE); + write_c (LCR_WORD); + write_w (label_id_1); + write_w (label_id); + write_c (LCODE); + write_c (2); + write_w (0); + } +#endif + + /* l2 */ + define_local_text_label (label_id_2); +} + +static void as_call_and_jump (struct call_and_jump *call_and_jump) +{ + /* l1 */ + define_local_text_label (call_and_jump->cj_label_id); + /* JSR collect_n */ + write_c (LCODE); + write_c (2); + write_w (047200); +#ifdef USE_LABEL_VALUE + write_c (LLABEL_VALUE); +#else + write_c (LREFERENCE); +#endif + write_c (0); + write_w (call_and_jump->cj_call_id); + write_c (LCODE); +#ifdef USE_LABEL_VALUE + write_c (2); +#else + write_c (4); + write_w (0); +#endif + /* JMP l2 */ + write_w (047300); +#ifdef USE_LABEL_VALUE + write_c (LLABEL_VALUE); + write_c (0); + write_w (call_and_jump->cj_jump_id); +#else + write_c (LREFERENCE); + write_c (0); + write_w (call_and_jump->cj_jump_id); + write_c (LCODE); + write_c (2); + write_w (0); +#endif +} + +static int local_stack_overflow_id; + +static void init_stack_checking (VOID) +{ + local_stack_overflow_id=next_label_id++; + define_local_text_label (local_stack_overflow_id); + + write_c (LCODE); + write_c (2); + write_w (047300); + +#ifdef USE_LABEL_VALUE + write_c (LLABEL_VALUE); + write_c (0); + write_w (stack_overflow_label->label_id); +#else + write_c (LREFERENCE); + write_c (0); + write_w (stack_overflow_label->label_id); + + write_c (LCODE); + write_c (2); + write_w (0); +#endif +} + +#define EXTRA_STACK_SPACE 2000 /* 300 */ + +static void as_check_stack (register struct basic_block *block) +{ + int size,n_d_parameters,n_a_parameters; + int label_id,label_id_1,label_id_2; + + label_id=next_label_id++; + + if (parallel_flag){ + struct call_and_jump *new_call_and_jump; + + label_id_1=next_label_id++; + label_id_2=next_label_id++; + + new_call_and_jump=(struct call_and_jump*)allocate_memory_from_heap (sizeof (struct call_and_jump)); + + new_call_and_jump->cj_next=NULL; + new_call_and_jump->cj_label_id=label_id_1; + new_call_and_jump->cj_jump_id=label_id_2; + switch (block->block_n_begin_a_parameter_registers){ + case 0: new_call_and_jump->cj_call_id=realloc_0_label->label_id; break; + case 1: new_call_and_jump->cj_call_id=realloc_1_label->label_id; break; + case 2: new_call_and_jump->cj_call_id=realloc_2_label->label_id; break; + case 3: new_call_and_jump->cj_call_id=realloc_3_label->label_id; break; + default: internal_error_in_function ("as_garbage_collect_test"); + } + + if (first_call_and_jump!=NULL) + last_call_and_jump->cj_next=new_call_and_jump; + else + first_call_and_jump=new_call_and_jump; + last_call_and_jump=new_call_and_jump; + } + + size=block->block_stack_check_size; +/* if (parallel_flag) */ + size+=EXTRA_STACK_SPACE; + n_d_parameters=block->block_n_begin_d_parameter_registers; + n_a_parameters=block->block_n_begin_a_parameter_registers; + + if (size<=4){ + write_c (LCODE); + write_c (4); + /* CMPA.L A_STACK_POINTER,B_STACK_POINTER */ + write_w (0130710+a_reg_num (A_STACK_POINTER)+(a_reg_num (B_STACK_POINTER)<<9)); + /* BLS */ + write_w (0x6300); + } else if (size<=127 + && n_d_parameters < + (parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS)) + { + write_c (LCODE); + write_c (8); + if (parallel_flag){ + /* MOVEQ #size,D5 */ + write_w (0x7000+(d_reg_num (REGISTER_D5)<<9)+size); + /* ADD.L A_STACK_POINTER,D5 */ + write_w (0150210+a_reg_num (A_STACK_POINTER)+(5<<9)); + /* CMP.L B_STACK_POINTER,D5 */ + write_w (0130210+a_reg_num (B_STACK_POINTER)+(5<<9)); + } else { + /* MOVEQ #size,D6 */ + write_w (0x7000+(d_reg_num (REGISTER_D6)<<9)+size); + /* ADD.L A_STACK_POINTER,D6 */ + write_w (0150210+a_reg_num (A_STACK_POINTER)+(6<<9)); + /* CMP.L B_STACK_POINTER,D6 */ + write_w (0130210+a_reg_num (B_STACK_POINTER)+(6<<9)); + } + /* BHI */ + write_w (0x6200); + } else if (n_a_parameters<N_ADDRESS_PARAMETER_REGISTERS){ + write_c (LCODE); + write_c (8); + /* LEA size(A_STACK_POINTER),A2 */ + write_w (040750 + (2<<9) + a_reg_num (A_STACK_POINTER)); + write_w (size); + /* CMPA.L B_STACK_POINTER,A2 */ + write_w (0130710+a_reg_num (B_STACK_POINTER)+(2<<9)); + /* BHI */ + write_w (0x6200); + } else { + write_c (LCODE); + write_c (10); + /* SUBA.L B_STACK_POINTER,A_STACK_POINTER */ + write_w (0110710+a_reg_num (B_STACK_POINTER)+(a_reg_num (A_STACK_POINTER)<<9)); + /* CMPA.W #-size,A_STACK_POINTER */ + write_w (0130374+(a_reg_num (A_STACK_POINTER)<<9)); + write_w (-size); + /* ADDA.L B_STACK_POINTER,A_STACK_POINTER */ + write_w (0150710+a_reg_num (B_STACK_POINTER)+(a_reg_num (A_STACK_POINTER)<<9)); + /* BGT */ + write_w (0x6E00); + } + + define_local_text_label (label_id); + + write_c (LC_REFERENCE); + write_c (LCR_WORD); + + if (!parallel_flag){ + write_w (local_stack_overflow_id); + write_w (label_id); + write_c (LCODE); + write_c (2); + write_w (0); + } else { + write_w (label_id_1); + write_w (label_id); + write_c (LCODE); + write_c (2); + write_w (0); + + define_local_text_label (label_id_2); + } +} + +static void as_word_instruction (struct instruction *instruction) +{ + write_w ((LCODE<<8)+2); + write_w ((int)instruction->instruction_parameters[0].parameter_data.i); +} + +static void write_instructions (struct instruction *instructions) +{ + register struct instruction *instruction; + + for (instruction=instructions; instruction!=NULL; instruction=instruction->instruction_next){ + switch (instruction->instruction_icode){ + case IMOVE: + as_move_instruction (instruction,SIZE_LONG); + break; + case ILEA: + as_lea_instruction (instruction); + break; + case IADD: + as_add_instruction (instruction); + break; + case ISUB: + as_sub_instruction (instruction); + break; + case ICMP: + as_cmp_instruction (instruction,SIZE_LONG); + break; + case ITST: + as_tst_instruction (instruction,SIZE_LONG); + break; + case ITSTB: + as_tst_instruction (instruction,SIZE_BYTE); + break; + case IJMP: + as_jmp_instruction (instruction); + break; + case IJSR: + as_jsr_instruction (instruction); + break; + case IRTS: +#ifdef COUNT_RELEASES + if (parallel_flag && instruction->instruction_arity){ + write_c (LCODE); + write_c (2); + write_w (0x52ad); + + write_c (LLABEL_VALUE); + write_c (REFERENCE_A5); + write_w (node_entry_count_label_id); + } +#endif + write_w ((LCODE<<8)+2); + write_w (047165); + break; + case IBGE: + as_branch_instruction (instruction,0x6C00); + break; + case IBGT: + as_branch_instruction (instruction,0x6E00); + break; + case IBHS: + as_branch_instruction (instruction,0x6400); + break; + case IBLE: + as_branch_instruction (instruction,0x6F00); + break; + case IBLT: + as_branch_instruction (instruction,0x6D00); + break; + case IBEQ: + as_branch_instruction (instruction,0x6700); + break; + case IBNE: + as_branch_instruction (instruction,0x6600); + break; + case IBMI: + as_short_branch_instruction (instruction,0x6b00); + break; + case IMOVEM: + as_movem_instruction (instruction); + break; + case IMOVEW: + as_move_instruction (instruction,SIZE_WORD); + break; + case IMOVEB: + as_move_instruction (instruction,SIZE_BYTE); + break; + case ICMPW: + as_cmp_instruction (instruction,SIZE_WORD); + break; + case ILSL: + as_shift_instruction (instruction,0160610); + break; + case ILSR: + as_shift_instruction (instruction,0160210); + break; + case IASR: + as_shift_instruction (instruction,0160200); + break; + case IMUL: + as_mul_instruction (instruction); + break; + case IDIV: + as_div_instruction (instruction); + break; + case IMOD: + as_mod_instruction (instruction); + break; + case IBMOVE: + as_bmove_instruction (instruction); + break; + case IEXG: + as_exg_instruction (instruction); + break; + case IAND: + as_and_or_instruction (instruction,0140200); + break; + case IOR: + as_and_or_instruction (instruction,0100200); + break; + case IEOR: + as_eor_instruction (instruction); + break; + case ISEQ: + as_set_condition_instruction (instruction,0x57c0); + break; + case ISGE: + as_set_condition_instruction (instruction,0x5cc0); + break; + case ISGT: + as_set_condition_instruction (instruction,0x5ec0); + break; + case ISLE: + as_set_condition_instruction (instruction,0x5fc0); + break; + case ISLT: + as_set_condition_instruction (instruction,0x5dc0); + break; + case ISNE: + as_set_condition_instruction (instruction,0x56c0); + break; + case IFMOVE: + as_fmove_instruction (instruction,0x1400); + break; + case IFADD: + as_fp_instruction (instruction,0x22); + break; + case IFSUB: + as_fp_instruction (instruction,0x28); + break; + case IFCMP: + as_fp_instruction (instruction,0x38); + break; + case IFDIV: + as_fp_instruction (instruction,0x20); + break; + case IFMUL: + as_fp_instruction (instruction,0x23); + break; + case IFREM: + as_fp_instruction (instruction,0x25); + break; + case IFBEQ: + as_branch_instruction (instruction,0xf281); + break; + case IFBGE: + as_branch_instruction (instruction,0xf293); + break; + case IFBGT: + as_branch_instruction (instruction,0xf292); + break; + case IFBLE: + as_branch_instruction (instruction,0xf295); + break; + case IFBLT: + as_branch_instruction (instruction,0xf294); + break; + case IFBNE: + as_branch_instruction (instruction,0xf28e); + break; + case IFMOVEL: + as_fmove_instruction (instruction,0); + break; + case IFACOS: + as_fp_instruction (instruction,0x1c); + break; + case IFASIN: + as_fp_instruction (instruction,0x0c); + break; + case IFATAN: + as_fp_instruction (instruction,0x0a); + break; + case IFCOS: + as_fp_instruction (instruction,0x1d); + break; + case IFEXP: + as_fp_instruction (instruction,0x10); + break; + case IFLN: + as_fp_instruction (instruction,0x14); + break; + case IFLOG10: + as_fp_instruction (instruction,0x15); + break; + case IFNEG: + as_fp_instruction (instruction,0x1a); + break; + case IFSIN: + as_fp_instruction (instruction,0xe); + break; + case IFSQRT: + as_fp_instruction (instruction,4); + break; + case IFTAN: + as_fp_instruction (instruction,0xf); + break; + case IFSEQ: + as_fp_set_condition_instruction (instruction,1); + break; + case IFSGE: + as_fp_set_condition_instruction (instruction,0x13); + break; + case IFSGT: + as_fp_set_condition_instruction (instruction,0x12); + break; + case IFSLE: + as_fp_set_condition_instruction (instruction,0x15); + break; + case IFSLT: + as_fp_set_condition_instruction (instruction,0x14); + break; + case IFSNE: + as_fp_set_condition_instruction (instruction,0xe); + break; + case IWORD: + as_word_instruction (instruction); + break; + case ISCHEDULE: + as_jsr_schedule (instruction->instruction_parameters[0].parameter_data.i); + break; + case IEXTB: + as_extb_instruction (instruction); + break; + case IEXT: + as_ext_instruction (instruction); + break; + case IFTST: + default: + internal_error_in_function ("write_instructions"); + } + } +} + +static void write_code() +{ + register struct basic_block *block; + register struct call_and_jump *call_and_jump; + + release_heap(); + + first_call_and_jump=NULL; + + for_all (block,first_block,block_next){ +#ifdef MODULES + if (block->block_begin_module) + start_new_module (block->block_link_module != 0); +#endif + if (block->block_n_node_arguments>-100){ + LABEL *label; + + label=block->block_descriptor; + +#ifdef CLOSURE_NAMES + if (label!=NULL && block->block_descriptor_or_string!=0){ + unsigned char *string_p; + char *string; + ULONG string_length; + int length; + + string=(char*)block->block_descriptor; + string_length=strlen (string); + + string_p=(unsigned char*)string; + length=string_length; + + write_c (LCODE); + write_c ((string_length+7) & ~3); + + while (length>=4){ + write_l (*(ULONG*)string_p); + string_p+=4; + length-=4; + } + + if (length>0){ + ULONG d; + int shift; + + d=0; + shift=24; + while (length>0){ + d |= ((ULONG)string_p[0])<<shift; + shift-=8; + --length; + ++string_p; + } + write_l (d); + } + + write_l ((string_length<<2) | (string_length<<10) | (string_length<<18) | (string_length<<26) | 0x00010203); + } +#endif + + if (block->block_ea_label!=NULL){ + int n_node_arguments; + extern LABEL *eval_fill_label,*eval_upd_labels[]; + + n_node_arguments=block->block_n_node_arguments; + if (n_node_arguments<-2) + n_node_arguments=1; + + if (n_node_arguments>=0 && block->block_ea_label!=eval_fill_label){ + write_c (LCODE); + write_c (2); + write_w (042700); + + write_c (LLABEL_VALUE); + write_c (0); + if (block->block_ea_label->label_id<0) + block->block_ea_label->label_id=next_label_id++; + write_w (block->block_ea_label->label_id); + + write_c (LCODE); + write_c (2); + write_w (047300); + + write_c (LLABEL_VALUE); + write_c (0); + write_w (eval_upd_labels[n_node_arguments]->label_id); + } else { + write_c (LCODE); + write_c (2); + write_w (047300); + + write_c (LLABEL_VALUE); + write_c (0); + if (block->block_ea_label->label_id<0) + block->block_ea_label->label_id=next_label_id++; + write_w (block->block_ea_label->label_id); + + write_c (LCODE); + write_c (4); + write_w (0x4e71); + write_w (0x4e71); + } + if (block->block_descriptor!=NULL + && (block->block_n_node_arguments<0 || parallel_flag)) + { + if (label->label_id<0) + label->label_id=next_label_id++; + store_label_offset_in_code_section (label->label_id); + } else + write_number_of_arguments (0); + } else + if (label!=NULL + && (block->block_n_node_arguments<0 || parallel_flag)) + { + if (label->label_id<0) + label->label_id=next_label_id++; + store_label_offset_in_code_section (label->label_id); + } + /* else + write_number_of_arguments (0); */ + + write_number_of_arguments (block->block_n_node_arguments); + } + + write_labels (block->block_labels); + if (block->block_n_new_heap_cells>0) + as_garbage_collect_test (block); + if (check_stack && block->block_stack_check_size>0) + as_check_stack (block); + write_instructions (block->block_instructions); + } + + for_all (call_and_jump,first_call_and_jump,cj_next) + { +#ifdef MODULES + start_new_module (0); +#endif + as_call_and_jump (call_and_jump); + } + + release_heap(); +} + +void write_version_and_options (int version,int options) +{ +#ifndef GENERATE_MPW_OBJECT_CODE + putc (LCOMMENT,output_file); + putc (4,output_file); + + putc (version>>8,output_file); + putc (version,output_file); + + putc (options>>8,output_file); + putc (options,output_file); +#endif +} + +void write_depend (char *module_name) +{ +#ifndef GENERATE_MPW_OBJECT_CODE + int l,n; + + l=strlen (module_name); + putc (LCOMMENT,output_file); + putc (l,output_file); + + for (n=0; n<l; ++n) + putc (module_name[n],output_file); + + if (l & 1) + putc (0,output_file); +#endif +} + +void initialize_assembler (FILE *output_file_d) +{ + output_file=output_file_d; + + setvbuf (output_file,NULL,_IOFBF,IO_BUFFER_SIZE); + + initialize_object_buffers(); + +#ifndef GENERATE_MPW_OBJECT_CODE + putc (LBEGIN,output_file); + putc (0,output_file); + putc (0,output_file); + putc (0,output_file); +#else + write_c (LBEGIN); + write_c (0); + write_w (0); +#endif + + if (check_stack && !parallel_flag) + init_stack_checking(); +} + +void assemble_code () +{ + import_labels (labels); + + write_indirect_jumps_for_defer_labels(); + +#ifdef COUNT_RELEASES + if (parallel_flag){ + node_entry_count_label_id=next_label_id++; + import_label (node_entry_count_label_id,"node_entry_count"); + } +#endif + + if (index_error_label!=NULL && !(index_error_label->label_flags & EXPORT_LABEL)){ + int new_index_error_label; + + new_index_error_label=next_label_id++; + define_local_text_label (new_index_error_label); + + write_w ((LCODE<<8)+2); + write_w (047300); + + write_w (LLABEL_VALUE<<8); + write_w (index_error_label->label_id); + + index_error_label->label_id=new_index_error_label; + } + + write_code(); + + write_c (LEND); + write_c (0); + + flush_object_buffer(); + + optimize_buffers(); + +#ifdef GENERATE_MPW_OBJECT_CODE + convert_to_mpw_object_code(); +#endif + + write_object_buffers_and_release_memory(); + +#ifndef GENERATE_MPW_OBJECT_CODE + fseek (output_file,2l,0); + + putc (next_label_id>>8,output_file); + putc (next_label_id,output_file); +#endif +} + +#endif
\ No newline at end of file @@ -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 <stdio.h> +#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_dregs<i_dregs) + l_dregs=i_dregs; + if (r_dregs<i_dregs) + r_dregs=i_dregs; + + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + + if (l_aregs<i_aregs) + l_aregs=i_aregs; + if (r_aregs<i_aregs) + r_aregs=i_aregs; + + graph->order_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_dregs<i_dregs+2) + l_dregs=i_dregs+2; + if (r_dregs<i_dregs+2) + r_dregs=i_dregs+2; + } else { + if (l_dregs<i_dregs+1) + l_dregs=i_dregs+1; + if (r_dregs<i_dregs+1) + r_dregs=i_dregs+1; + } + + if (graph->instruction_d_min_a_cost<=0){ + ++i_dregs; + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + + if (l_aregs<i_aregs) + l_aregs=i_aregs; + if (r_aregs<i_aregs) + r_aregs=i_aregs; + + graph->order_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_dregs<i_dregs+2) + l_dregs=i_dregs+2; + if (r_dregs<i_dregs+2) + r_dregs=i_dregs+2; + } else { + if (l_dregs<i_dregs+1) + l_dregs=i_dregs+1; + if (r_dregs<i_dregs+1) + r_dregs=i_dregs+1; + } + + if (graph->instruction_d_min_a_cost<=0){ + ++i_dregs; + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + + if (l_aregs<i_aregs) + l_aregs=i_aregs; + if (r_aregs<i_aregs) + r_aregs=i_aregs; + + graph->order_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_dregs<i_dregs) + l_dregs=i_dregs; + if (r_dregs<i_dregs) + r_dregs=i_dregs; + + 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_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_dregs<graph->i_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_aregs<graph->i_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_dregs<i_dregs+1) + l_dregs=i_dregs+1; + if (r_dregs<i_dregs+1) + r_dregs=i_dregs+1; + } + + 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_dregs<i_dregs+1) + l_dregs=i_dregs+1; + if (r_dregs<i_dregs+1) + r_dregs=i_dregs+1; + + if (graph->instruction_d_min_a_cost<=0){ + ++i_dregs; + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + + if (l_aregs<i_aregs) + l_aregs=i_aregs; + if (r_aregs<i_aregs) + r_aregs=i_aregs; + + graph->order_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_dregs<i_dregs) + l_dregs=i_dregs; + if (r_dregs<i_dregs) + r_dregs=i_dregs; + } + + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + + if (!(graph_2->order_mode!=R_DREGISTER && graph_2->order_alterable)){ + if (l_aregs<i_aregs) + l_aregs=i_aregs; + if (r_aregs<i_aregs) + r_aregs=i_aregs; + } + + graph->order_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_dregs<i_dregs+2) + l_dregs=i_dregs+2; + if (r_dregs<i_dregs+2) + r_dregs=i_dregs+2; + } else { + if (l_dregs<i_dregs+1) + l_dregs=i_dregs+1; + if (r_dregs<i_dregs+1) + r_dregs=i_dregs+1; + } + } + + 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; + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + + if (l_aregs<i_aregs) + l_aregs=i_aregs; + if (r_aregs<i_aregs) + r_aregs=i_aregs; + + graph->order_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_dregs<i_dregs+2) + l_dregs=i_dregs+2; + if (r_dregs<i_dregs+2) + r_dregs=i_dregs+2; + + if (graph->instruction_d_min_a_cost<=0){ + ++i_dregs; + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + + if (l_aregs<i_aregs) + l_aregs=i_aregs; + if (r_aregs<i_aregs) + r_aregs=i_aregs; + + graph->order_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_dregs<i_dregs+1) + l_dregs=i_dregs+1; + if (r_dregs<i_dregs+1) + r_dregs=i_dregs+1; + } else { + if (l_dregs<i_dregs+2) + l_dregs=i_dregs+2; + if (r_dregs<i_dregs+2) + r_dregs=i_dregs+2; + } + + if (graph->instruction_d_min_a_cost<=0){ + ++i_dregs; + graph->order_mode=R_DREGISTER; + } else { + ++i_aregs; + + if (l_aregs<i_aregs) + l_aregs=i_aregs; + if (r_aregs<i_aregs) + r_aregs=i_aregs; + + graph->order_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_number<n_arguments; ++argument_number){ + INSTRUCTION_GRAPH a_graph; + + a_graph=graph->instruction_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_number<n_arguments; ++argument_number) + argument_evaluated[argument_number]= + (graph->instruction_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 && argument_evaluated[first_argument_number]) + ++first_argument_number; + + if (first_argument_number>=n_arguments) + break; + + a_graph_1=graph->instruction_parameters[first_argument_number].p; + + for (argument_number=first_argument_number+1; argument_number<n_arguments; ++argument_number){ + if (!argument_evaluated[argument_number]){ + INSTRUCTION_GRAPH a_graph_2; + int i1,i2,u1,u2; + int a,d; + + a_graph_2=graph->instruction_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 && (u2<u1 || (u1==u2 && i2<i1))){ + first_argument_number=argument_number; + a_graph_1=a_graph_2; + } + } else if (i1==0){ + if (i2<0 || (i2==0 && u2<u1)){ + first_argument_number=argument_number; + a_graph_1=a_graph_2; + } + } else { + if (i2<=0 || (u2-i2>u1-i1 || (u2-i2==u1-i1 && u2<u1))){ + first_argument_number=argument_number; + a_graph_1=a_graph_2; + } + } + } + } + + if (a_graph_1->u_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_number<graph->inode_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_number<graph->inode_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_number<graph->inode_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_aregs<i_aregs) + u_aregs=i_aregs; + + arity=movem_graph->inode_arity; + + for (argument_number=0; argument_number<arity; ++argument_number){ + register INSTRUCTION_GRAPH a_graph; + + if (argument_number==arity-1) + --i_aregs; + + a_graph=movem_graph->instruction_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_dregs<i_dregs) + u_dregs=i_dregs; + } else { + ++i_aregs; + if (u_aregs<i_aregs) + u_aregs=i_aregs; + } + } + + for (argument_number=0; argument_number<arity; ++argument_number){ + register INSTRUCTION_GRAPH a_graph; + + a_graph=movem_graph->instruction_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_dregs<graph->i_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_aregs<graph->i_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_aregs<i_aregs) + l_aregs=i_aregs; + if (r_aregs<i_aregs) + r_aregs=i_aregs; + + 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=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 && (u2<u1 || (u1==u2 && i2<i1)); + else if (i1==0) + return i2<0 || (i2==0 && u2<u1); + else + return i2<=0 || (u2-i2>u1-i1 || (u2-i2==u1-i1 && u2<u1)); +} + +static void calculate_store_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 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_aregs<i_aregs) + l_aregs=i_aregs; + if (r_aregs<i_aregs) + r_aregs=i_aregs; + + 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_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_aregs<i_aregs+1) + l_aregs=i_aregs+1; + if (r_aregs<i_aregs+1) + r_aregs=i_aregs+1; + } + + 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_dregs<i_dregs+1) + l_dregs=i_dregs+1; + if (r_dregs<i_dregs+1) + r_dregs=i_dregs+1; + + ++i_dregs; + graph->order_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; i<graph->inode_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; n<graph->inode_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; n<graph->inode_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; n<graph->inode_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 @@ -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[]; @@ -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 @@ -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 <stdlib.h> + +#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 <stdio.h> +#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; n<N_ADDRESS_PARAMETER_REGISTERS; ++n) + global_block.block_graph_a_register_parameter_node[n]=NULL; + + global_block.block_graph_begin_a_stack_size=0; + global_block.block_graph_a_stack_top_offset=0; + global_block.block_graph_a_stack_begin_displacement=0; + global_block.block_graph_a_stack_end_displacement=0; +} + +INSTRUCTION_GRAPH s_get_b (int offset) +{ + register struct b_stack **element_h,*element_p,*new_element; + register int required_offset; + INSTRUCTION_GRAPH graph; + + 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) + 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; n<N_DATA_PARAMETER_REGISTERS +#ifdef MORE_PARAMETER_REGISTERS + + N_ADDRESS_PARAMETER_REGISTERS +#endif + ; ++n) + global_block.block_graph_d_register_parameter_node[n]=NULL; + + for (n=0; n<N_FLOAT_PARAMETER_REGISTERS; ++n) + global_block.block_graph_f_register_parameter_node[n]=NULL; + + global_block.block_graph_begin_b_stack_size=0; + global_block.block_graph_b_stack_top_offset=0; + global_block.block_graph_b_stack_begin_displacement=0; + global_block.block_graph_b_stack_end_displacement=0; +} + +void init_a_stack (int a_stack_size) +{ + int n; + + global_block.block_graph_begin_a_stack_size=a_stack_size; + + if (a_stack_size>N_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; n<a_stack_size; ++n){ + INSTRUCTION_GRAPH register_graph; + int a_register; + + a_register=num_to_a_reg (a_stack_size-1-n); + + register_graph=g_register (a_register); + s_put_a_l (n,register_graph,register_graph); + } +} + +void init_b_stack (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 +#ifdef MORE_PARAMETER_REGISTERS + + N_ADDRESS_PARAMETER_REGISTERS +#endif + ],float_offsets[N_FLOAT_PARAMETER_REGISTERS]; + + 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<b_stack_size;){ + if (test_bit (vector,offset)){ + if (mc68881_flag){ + if (number_of_float_register_parameters<N_FLOAT_PARAMETER_REGISTERS){ + float_offsets [number_of_float_register_parameters++]=offset; + + if (all_parameters_in_registers) + stack_displacement-=2; + } else { + INSTRUCTION_GRAPH f_graph,h_graph,l_graph; + + f_graph=g_fload ((offset+stack_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 + s_put_b_l (offset+1,l_graph,l_graph); + s_put_b_l (offset,h_graph,h_graph); + + all_parameters_in_registers=0; + } + } else + all_parameters_in_registers=0; + offset+=2; + } else { + if (number_of_data_register_parameters < (parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS)){ + data_offsets [number_of_data_register_parameters++]=offset; + + if (all_parameters_in_registers) + --stack_displacement; + } else + all_parameters_in_registers=0; + offset+=1; + } + } + + for (n=0; n<number_of_data_register_parameters; ++n){ + INSTRUCTION_GRAPH register_graph; + + register_graph=g_register (num_to_d_reg (number_of_data_register_parameters-1-n)); + s_put_b_l (data_offsets[n],register_graph,register_graph); + } + + for (n=0; n<number_of_float_register_parameters; ++n){ + INSTRUCTION_GRAPH register_graph,h_graph,l_graph; + register int offset; + + register_graph=g_fregister (number_of_float_register_parameters-1-n); + +#ifdef g_fhighlow + g_fhighlow (h_graph,l_graph,register_graph); +#else + h_graph=g_fhigh (register_graph); + l_graph=g_flow (register_graph); +#endif + offset=float_offsets[n]; + + s_put_b_l (offset+1,l_graph,l_graph); + s_put_b_l (offset,h_graph,h_graph); + } + + last_block->block_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<b_stack_size;){ + if (test_bit (vector,offset)){ + if (mc68881_flag){ + if (number_of_float_register_parameters<N_FLOAT_PARAMETER_REGISTERS){ + float_offsets [number_of_float_register_parameters++]=offset; + + if (all_parameters_in_registers) + stack_displacement-=2; + } else { + INSTRUCTION_GRAPH f_graph,h_graph,l_graph; + + f_graph=g_fload ((offset+stack_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 + s_put_b_l (offset+1,l_graph,l_graph); + s_put_b_l (offset,h_graph,h_graph); + + all_parameters_in_registers=0; + } + } else + all_parameters_in_registers=0; + offset+=2; + } else { + if (number_of_data_register_parameters < + (parallel_flag ? n_data_parameter_registers-1 : n_data_parameter_registers) + n_extra_data_parameter_registers) + { + data_offsets [number_of_data_register_parameters++]=offset; + + if (all_parameters_in_registers) + --stack_displacement; + } else + all_parameters_in_registers=0; + offset+=1; + } + } + + n_extra_data_parameter_registers=number_of_data_register_parameters-n_data_parameter_registers; + if (n_extra_data_parameter_registers<0) + n_extra_data_parameter_registers=0; + + for (n=0; n<number_of_data_register_parameters; ++n){ + INSTRUCTION_GRAPH register_graph; + int d_n; + + d_n=(number_of_data_register_parameters-1-n)-n_extra_data_parameter_registers; + + if (d_n>=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; n<number_of_float_register_parameters; ++n){ + INSTRUCTION_GRAPH register_graph,h_graph,l_graph; + register int offset; + + register_graph=g_fregister (number_of_float_register_parameters-1-n); + +#ifdef g_fhighlow + g_fhighlow (h_graph,l_graph,register_graph); +#else + h_graph=g_fhigh (register_graph); + l_graph=g_flow (register_graph); +#endif + offset=float_offsets[n]; + + s_put_b_l (offset+1,l_graph,l_graph); + s_put_b_l (offset,h_graph,h_graph); + } + + last_block->block_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_offset<required_offset) + element_p=&(*element_p)->b_stack_next; + + for (offset=0; offset<b_stack_size; ++offset,++required_offset){ + if (test_bit (vector,offset)){ + if ((*element_p==NULL || (*element_p)->b_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_offset<required_offset){ + (*element_p)->b_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; offset<b_stack_size; ++offset){ + *graph_p=(*element_p)->b_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_offset<a_stack_top_offset) + a_element=a_element->a_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_offset<b_stack_top_offset) + first_b_element=first_b_element->b_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; i<b_stack_size; ){ + register struct b_stack *next_b_element; + INSTRUCTION_GRAPH graph,next_graph; + + if (i<b_stack_size-1 + && (graph=b_element->b_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_offset<b_stack_top_offset) + first_b_element=first_b_element->b_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; i<b_stack_size; ){ + register struct b_stack *next_b_element; + INSTRUCTION_GRAPH graph,next_graph; + + if (i<b_stack_size-1 + && (graph=b_element->b_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_n<n_parameters; ++parameter_n){ + struct a_stack *new_element; + int required_offset; + INSTRUCTION_GRAPH graph; + + required_offset=global_block.block_graph_a_stack_top_offset+parameter_n; + + while (*element_p!=NULL && (*element_p)->a_stack_offset<required_offset) + element_p=&(*element_p)->a_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_offset<global_block.block_graph_a_stack_top_offset) + a_element->a_stack_graph=NULL; + else { + if (a_element->a_stack_offset-global_block.block_graph_a_stack_top_offset<n_parameters){ + register int register_number; + + register_number=n_parameters-1-(a_element->a_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<<register_number); + } else { + if (a_element->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; offset<n_a_registers; ++offset){ + INSTRUCTION_GRAPH graph; + + if (*element_p!=NULL && (*element_p)->a_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_n<n_parameters; ++parameter_n){ + struct b_stack *new_element; + int required_offset; + INSTRUCTION_GRAPH graph; + + required_offset=global_block.block_graph_b_stack_top_offset+parameter_n; + + while (*element_p!=NULL && (*element_p)->b_stack_offset<required_offset) + element_p=&(*element_p)->b_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_offset<global_block.block_graph_b_stack_top_offset){ + b_element->b_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_parameters<N_FLOAT_PARAMETER_REGISTERS && mc68881_flag){ + struct b_stack *next_b_element; + + next_b_element=b_element->b_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_parameters<n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + + n_extra_data_parameter_registers +#endif + ){ + d_graphs[number_of_d_register_parameters]=graph; + d_graphs_p[number_of_d_register_parameters]=&b_element->b_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<number_of_d_register_parameters; ++n) + if (d_graphs[n]!=NULL){ + register int d_reg_n; + +#ifdef MORE_PARAMETER_REGISTERS + d_reg_n=(number_of_d_register_parameters-1-n)-n_extra_data_parameter_registers; + + if (d_reg_n>=0){ + end_d_registers |= ((unsigned)1<<d_reg_n); + + *d_graphs_p[n]=g_store_r (num_to_d_reg (d_reg_n),d_graphs[n]); + } else { +# if 1 + int extra_d_reg_n; + + extra_d_reg_n=n_data_parameter_registers-1-d_reg_n; + + end_d_registers |= ((unsigned)1<<extra_d_reg_n); + + *d_graphs_p[n]=g_store_r (num_to_d_reg (extra_d_reg_n),d_graphs[n]); + + if (a_register_parameter_nodes[N_ADDRESS_PARAMETER_REGISTERS+d_reg_n]!=NULL){ + INSTRUCTION_GRAPH register_node; + + register_node=a_register_parameter_nodes[N_ADDRESS_PARAMETER_REGISTERS+d_reg_n]; + register_node->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<<N_ADDRESS_PARAMETER_REGISTERS+d_reg_n); + + *d_graphs_p[n]=g_store_r (num_to_a_reg (N_ADDRESS_PARAMETER_REGISTERS+d_reg_n),d_graphs[n]); +# endif + } +#else + d_reg_n=number_of_d_register_parameters-1-n; + + end_d_registers |= ((unsigned)1<<d_reg_n); + + *d_graphs_p[n]=g_store_r (num_to_d_reg (d_reg_n),d_graphs[n]); +#endif + } + + for (n=0; n<number_of_f_register_parameters; ++n) + if (f_graphs[n]!=NULL){ + register int f_reg_n; + + f_reg_n=number_of_f_register_parameters-1-n; + + end_f_registers |= ((unsigned)1<<f_reg_n); + + *f_graphs_p[n]=g_fstore_r (f_reg_n,f_graphs[n]); + } + + displacement=0; + number_of_d_register_parameters=0; + number_of_f_register_parameters=0; + + for (parameter_n=0; parameter_n<n_parameters; ++parameter_n) + if (test_bit (vector,parameter_n)){ + if (number_of_f_register_parameters<N_FLOAT_PARAMETER_REGISTERS + && mc68881_flag) + { + ++number_of_f_register_parameters; + displacement+=2; + ++parameter_n; + } else + break; + } else { + if (number_of_d_register_parameters<n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + + n_extra_data_parameter_registers +#endif + ){ + ++number_of_d_register_parameters; + ++displacement; + } else + break; + } + + global_block.block_graph_b_stack_end_displacement=displacement; +} + +static int set_basic_block_begin_d_registers + (struct b_stack **element_p,int b_stack_size,ULONG vector[], + INSTRUCTION_GRAPH d_register_parameter_node[],INSTRUCTION_GRAPH f_register_parameter_node[] +#ifdef MORE_PARAMETER_REGISTERS + ,int n_extra_data_parameter_registers,INSTRUCTION_GRAPH a_register_parameter_node[] +#endif + ) +{ + register int offset,stack_displacement; + register int n_d_registers,n_f_registers,all_parameters_in_registers; + register int n_data_parameter_registers; + + n_data_parameter_registers = + (parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS) +#ifdef MORE_PARAMETER_REGISTERS + + n_extra_data_parameter_registers +#endif + ; + + n_d_registers=0; + n_f_registers=0; + + for (offset=0; offset<b_stack_size; ++offset) + if (!test_bit (vector,offset)){ +#ifdef I486 + if (n_d_registers<n_data_parameter_registers) +#else + if (n_d_registers<n_data_parameter_registers-1) +#endif + ++n_d_registers; + } else { + if (n_f_registers<N_FLOAT_PARAMETER_REGISTERS && mc68881_flag) + ++n_f_registers; + ++offset; + } + + stack_displacement=0; + all_parameters_in_registers=1; + + for (offset=0; offset<b_stack_size; ++offset){ + register INSTRUCTION_GRAPH graph; + + if (!test_bit (vector,offset)){ + if (n_d_registers<=0) + all_parameters_in_registers=0; + else { + --n_d_registers; + + if (all_parameters_in_registers) + --stack_displacement; + + while (*element_p!=NULL && (*element_p)->b_stack_offset<offset) + element_p=&(*element_p)->b_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_offset<offset) + element_p=&(*element_p)->b_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_offset<begin_offset){ + element_p=&element->stack_next; + element=*element_p; + } + + for (offset=begin_offset; offset<remove_offset; ++offset){ + INSTRUCTION_GRAPH graph_2; + int flags_2; + + 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=offset<stack_top_offset ? 0 : 2; + + new_element=allocate_struct_from_heap (stack); + new_element->stack_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_offset<begin_offset){ + previous_element=element; + element_p=&element->stack_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= offset<stack_top_offset ? 0 : 2; + + new_element=allocate_struct_from_heap (stack); + new_element->stack_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 (offset<remove_offset){ + previous_element=element; + element_p=&element->stack_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_offset<begin_offset){ + element_p=&element->stack_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= offset<stack_top_offset ? 0 : 2; + + new_element=allocate_struct_from_heap (stack); + new_element->stack_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_offset<block_graph->block_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 (offset<first_non_parameter_offset && a_element_1!=NULL && a_element_1->a_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_offset<offset_2){ + a_element_2_p=&a_element_2->a_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_2<next_block_graph->block_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_2<next_block_graph->block_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_offset<offset_2){ + a_element_2_p=&a_element_2->a_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_offset<block_graph->block_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_1<first_non_parameter_offset_1 && b_element_1!=NULL && b_element_1->b_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_offset<offset_2){ + b_element_2_p=&b_element_2->b_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_2<next_block_graph->block_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_2<next_block_graph->block_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_offset<offset_2){ + b_element_2_p=&b_element_2->b_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_offset<first_non_parameter_offset_2) + a_element_2=a_element_2->a_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_offset<offset){ + a_element_1_p=&a_element_1->a_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 (; n<next_block_graph->block_graph_a_stack_top_offset; ++n){ + while (a_element_2!=NULL && a_element_2->a_stack_offset<n) + a_element_2=a_element_2->a_stack_next; + if (a_element_2==NULL || a_element_2->a_stack_offset!=n){ + + while (a_element_1!=NULL && a_element_1->a_stack_offset<n+stack_offset_difference){ + a_element_1_p=&a_element_1->a_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_offset<first_non_parameter_offset_2) + b_element_2=b_element_2->b_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_offset<offset_1){ + b_element_1_p=&b_element_1->b_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_2<next_block_graph->block_graph_b_stack_top_offset; ++offset_2){ + while (b_element_2!=NULL && b_element_2->b_stack_offset<offset_2) + b_element_2=b_element_2->b_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_offset<offset_1){ + b_element_1_p=&b_element_1->b_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_offset<a_stack_top_offset) + a_element=a_element->a_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_offset<b_stack_top_offset) + b_element_1=b_element_1->b_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_offset<first_non_parameter_offset){ + b_element_1->b_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_offset<required_offset) + b_element_2=b_element_2->b_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_offset<offset){ + b_element_1_p=&b_element_1->b_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; offset<first_non_parameter_offset; ++offset){ + while (b_element_1!=NULL && b_element_1->b_stack_offset<offset){ + b_element_1_p=&b_element_1->b_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_offset<a_stack_top_offset) + a_element=a_element->a_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_offset<b_stack_top_offset) + b_element=b_element->b_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; n<N_ADDRESS_PARAMETER_REGISTERS; ++n){ + INSTRUCTION_GRAPH register_graph; + + register_graph=global_block.block_graph_a_register_parameter_node[n]; + if (register_graph!=NULL && register_graph->node_count>0) + allocate_aregister (register_graph->instruction_parameters[0].i); + } + + for (n=0; n<N_DATA_PARAMETER_REGISTERS +#ifdef MORE_PARAMETER_REGISTERS + + N_ADDRESS_PARAMETER_REGISTERS +#endif + ; ++n){ + INSTRUCTION_GRAPH register_graph; + + register_graph=global_block.block_graph_d_register_parameter_node[n]; + + if (register_graph!=NULL && register_graph->node_count>0) + allocate_dregister (register_graph->instruction_parameters[0].i); + } + + if (mc68881_flag) + for (n=0; n<N_FLOAT_PARAMETER_REGISTERS; ++n){ + INSTRUCTION_GRAPH register_graph; + + register_graph=global_block.block_graph_f_register_parameter_node[n]; + + if (register_graph!=NULL && register_graph->node_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; n<n_elements; ++n){ + INSTRUCTION_GRAPH a_graph; + + a_graph=graphs[n]; + + if (a_graph->instruction_code!=GFILL) + count_graph (a_graph); + else { + int n; + + for (n=0; n<a_graph->inode_arity; ++n) + if (a_graph->instruction_parameters[n].p!=NULL) + count_graph (a_graph->instruction_parameters[n].p); + } + } + + allocate_registers(); + + for (n=0; n<n_elements; ++n) + calculate_graph_register_uses (graphs[n]); + +#ifndef M68000 + offset_from_heap_register=0; +#endif +#ifdef G_POWER + heap_pointer_offset_in_basic_block=0; +#endif + + evaluate_arguments_and_free_addresses ((union instruction_parameter*)graphs,n_elements); + +#ifndef M68000 + if (offset_from_heap_register!=0) +# ifdef G_POWER + optimize_heap_pointer_increment (last_block,offset_from_heap_register); +# else + i_add_i_r (offset_from_heap_register,HEAP_POINTER); +# endif +#endif +} + +static int allocate_and_fill_graph_array (INSTRUCTION_GRAPH **graphs_p) +{ + int element_n,n_a_elements,n_b_elements; + struct a_stack *a_element; + struct b_stack *b_element; + INSTRUCTION_GRAPH *graphs; + + n_a_elements=0; + for_l (a_element,global_block.block_graph_a_stack,a_stack_next) + if (a_element->a_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; n<n_elements; ++n){ + INSTRUCTION_GRAPH a_graph; + + a_graph=graphs[n]; + + if (a_graph->instruction_code!=GFILL) + count_graph (a_graph); + else { + int n; + + for (n=0; n<a_graph->inode_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; n<n_elements; ++n) + calculate_graph_register_uses (graphs[n]); + +#ifndef M68000 + offset_from_heap_register=0; +#endif +#ifdef G_POWER + heap_pointer_offset_in_basic_block=0; +#endif + + evaluate_arguments_and_free_addresses ((union instruction_parameter*)graphs,n_elements); + +#ifndef M68000 + if (offset_from_heap_register!=0) +# ifdef G_POWER + optimize_heap_pointer_increment (last_block,offset_from_heap_register); +# else + i_add_i_r (offset_from_heap_register,HEAP_POINTER); +# endif +#endif + + memory_free (graphs); + } + + calculate_and_linearize_graph (store_calculate_with_overflow_graph); +} + +INSTRUCTION_GRAPH search_and_remove_graph_from_b_stack (INSTRUCTION_GRAPH calculate_with_overflow_graph) +{ + struct b_stack *b_element; + + for_l (b_element,global_block.block_graph_b_stack,b_stack_next){ + INSTRUCTION_GRAPH stack_graph; + + stack_graph=b_element->b_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_offset<b_offset ? local_data_offset : b_offset; + + if (block_check){ +#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS + int a_check_size,b_check_size; + + if (last_block_graph!=NULL){ + last_block_graph->block_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; n<n_d_registers; ++n){ + i_move_r_pd (num_to_d_reg (n),B_STACK_POINTER); + code_size+=2; + } +#else + b_offset=0; +# ifdef I486 + for (n=0; n<n_d_registers; ++n) + i_move_r_pd (num_to_d_reg (n),B_STACK_POINTER); +# else + for (n=0; n<n_d_registers; ++n){ + b_offset+=4; + i_move_r_id (num_to_d_reg (n),-b_offset,B_STACK_POINTER); + } +# endif +#endif + +#ifdef M68000 + for (n=0; n<n_f_registers; ++n){ + i_fmove_fr_pd (n,B_STACK_POINTER); + code_size+=4; + } +#else + for (n=0; n<n_f_registers; ++n){ + b_offset+=8; + i_fmove_fr_id (n,-b_offset,B_STACK_POINTER); + } +# ifdef I486 + if (b_offset) + i_sub_i_r (b_offset,B_STACK_POINTER); +# else +# if !defined (G_POWER) + i_sub_i_r (b_offset+4,B_STACK_POINTER); +# endif +# endif +#endif + +#ifdef M68000 + i_move_r_r (num_to_d_reg (n_d_registers),REGISTER_A1); + i_jsr_id (0,REGISTER_A1,256); + code_size+=4; +#else +# if defined (I486) + i_jsr_id (0,num_to_a_reg (node_a_register),0); +# else +# if defined (G_POWER) +# ifdef SMALLER_EVAL + if (n_a_registers>1){ + 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; n<n_a_registers; ++n) + if (n!=node_a_register){ + i_move_pd_r (A_STACK_POINTER,num_to_a_reg (n)); + code_size+=2; + } +#else + offset=0; +# ifdef G_POWER + { + int last_a_register; + + last_a_register=n_a_registers-1; + if (last_a_register==node_a_register) + --last_a_register; + + for (n=0; n<n_a_registers; ++n) + if (n!=node_a_register){ + offset-=4; + if (n==last_a_register) + i_move_idu_r (offset,A_STACK_POINTER,num_to_a_reg (n)); + else + i_move_id_r (offset,A_STACK_POINTER,num_to_a_reg (n)); + } + } +# else + for (n=0; n<n_a_registers; ++n) + if (n!=node_a_register){ + offset-=4; + i_move_id_r (offset,A_STACK_POINTER,num_to_a_reg (n)); + } + if (a_offset>0) + 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; n<b_stack_size; ++n) + if (!test_bit (vector,n)){ +#ifdef I486 + if (n_allocated_d_regs<n_data_parameter_registers) +#else + if (n_allocated_d_regs<n_data_parameter_registers-1) +#endif + ++n_allocated_d_regs; + } else { + if (n_allocated_f_regs<N_FLOAT_PARAMETER_REGISTERS && mc68881_flag) + ++n_allocated_f_regs; + ++n; + } +#ifdef I486 + i_btst_i_id (2,0,num_to_a_reg (block_graph->block_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_n<end_b_stack_size; ++parameter_n) + if (test_bit (vector,parameter_n)) + if (n_a_and_f_registers<N_FLOAT_PARAMETER_REGISTERS){ + ++n_a_and_f_registers; + ++parameter_n; + } else + break; + } + + n_a_registers=block_graph->block_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_offset<offset) + a_element=a_element->a_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; n<a_stack_size; ++n){ + a_element=a_element->a_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 <stdio.h> +#include <string.h> + +#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<length; ++i){ + int c; + + if (n>=MAX_BYTES_PER_LINE){ + if (in_string){ + putc ('\"',assembly_file); + in_string=0; + } + w_as_newline(); + n=0; + } + + c=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<length; ++i){ + if (n>=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 @@ -0,0 +1,1846 @@ +/* + File: cgwas.c + Author: John van Groningen +*/ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#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<length; ++i){ + int c; + + if (n>=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<length; ++i){ + if (n>=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_parameters<N_ADDRESS_PARAMETER_REGISTERS){ + /* LEA size(A_STACK_POINTER),A2 */ + w_as_opcode ("lea"); + w_as_indirect (size,A_STACK_POINTER); + w_as_comma(); + w_as_register (REGISTER_A2); + w_as_newline(); + /* CMPA.L B_STACK_POINTER,A2 */ + w_as_opcode_and_size ("cmp",SIZE_LONG); + w_as_register (B_STACK_POINTER); + w_as_comma(); + w_as_register (REGISTER_A2); + w_as_newline(); + /* BHI */ + w_as_opcode ("bhi"); + } else { + /* SUBA.L B_STACK_POINTER,A_STACK_POINTER */ + w_as_opcode_and_size ("sub",SIZE_LONG); + w_as_register (B_STACK_POINTER); + w_as_comma(); + w_as_register (A_STACK_POINTER); + w_as_newline(); + /* CMPA.W #-size,A_STACK_POINTER */ + w_as_opcode_and_size ("cmp",SIZE_WORD); + w_as_immediate (-size); + w_as_comma(); + w_as_register (A_STACK_POINTER); + w_as_newline(); + /* ADDA.L B_STACK_POINTER,A_STACK_POINTER */ + w_as_opcode_and_size ("add",SIZE_LONG); + w_as_register (B_STACK_POINTER); + w_as_comma(); + w_as_register (A_STACK_POINTER); + w_as_newline(); + /* BGT */ + w_as_opcode ("bgt"); + } + + if (!parallel_flag){ + w_as_label (local_stack_overflow_label_name); + w_as_newline(); + } else { + w_as_internal_label (label_id_1); + w_as_newline (); + + w_as_define_internal_label (label_id_2); + } +} + +void initialize_write_assembly (FILE *ass_file) +{ + assembly_file=ass_file; + + next_bmove_label=0; + in_data_section=0; + first_relocatable_word=NULL; + last_relocatable_word=NULL; + n_relocatable_words=0; + n_relocatable_longs=0; + + first_call_and_jump=NULL; + + if (!sun_flag) + w_as_begin(); + + if (check_stack && !parallel_flag) + init_stack_checking(); +} + +static void w_as_relocation_routine (VOID) +{ + struct dependency_list *dependency; + struct relocatable_words_list *r_word; + int n; + + fprintf (assembly_file,"rf_%s:\t.word\t0\n",this_module_name); + fprintf (assembly_file,"\t.globl\tre_%s\n",this_module_name); + fprintf (assembly_file,"re_%s:\n",this_module_name); + fprintf (assembly_file,"\ttstb\trf_%s\n",this_module_name); + fprintf (assembly_file,"\tbne\trx_%s\n",this_module_name); + fprintf (assembly_file,"\tst\trf_%s\n",this_module_name); + + fprintf (assembly_file,"\tmovel\t#%d,d0\n",n_relocatable_longs); + fprintf (assembly_file,"\tmovel\t#%d,d1\n",n_relocatable_words); + fprintf (assembly_file,"\tlea\trlt_%s,a0\n",this_module_name); + fprintf (assembly_file,"\tlea\trwt_%s,a1\n",this_module_name); + fprintf (assembly_file,"\tjbsr\ta2@\n"); + + for (dependency=first_dependency; dependency!=NULL; dependency=dependency->dependency_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; n<n_relocatable_longs; ++n) + fprintf (assembly_file,"\t.long\trl_%d\n",n); + + fprintf (assembly_file,"rwt_%s:\n",this_module_name); + n=0; + for (r_word=first_relocatable_word; r_word!=NULL; r_word=r_word->relocatable_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 @@ -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 |