summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAIN_CLM.d3
-rw-r--r--apple_main.c499
-rw-r--r--cg.c924
-rw-r--r--cg.h37
-rw-r--r--cgas.c3839
-rw-r--r--cgas.h23
-rw-r--r--cgcalc.c2947
-rw-r--r--cgcalc.h15
-rw-r--r--cgcode.h76
-rw-r--r--cgconst.h27
-rw-r--r--cginput.h2
-rw-r--r--cginstructions.h60
-rw-r--r--cgiwas.h25
-rw-r--r--cglin.h126
-rw-r--r--cgopt.h10
-rw-r--r--cgpas.h14
-rw-r--r--cgptoc.c65
-rw-r--r--cgpwas.h19
-rw-r--r--cgrconst.h58
-rw-r--r--cgstack.c4320
-rw-r--r--cgstack.h51
-rw-r--r--cgswas.c2446
-rw-r--r--cgswas.h11
-rw-r--r--cgtypes.h257
-rw-r--r--cgwas.c1846
-rw-r--r--cgwas.h19
-rw-r--r--docommand.c16
-rw-r--r--docommand.h12
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
diff --git a/cg.c b/cg.c
new file mode 100644
index 0000000..9db12d3
--- /dev/null
+++ b/cg.c
@@ -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
diff --git a/cg.h b/cg.h
new file mode 100644
index 0000000..32ab55d
--- /dev/null
+++ b/cg.h
@@ -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;
diff --git a/cgas.c b/cgas.c
new file mode 100644
index 0000000..5e6cc27
--- /dev/null
+++ b/cgas.c
@@ -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
diff --git a/cgas.h b/cgas.h
new file mode 100644
index 0000000..473b83e
--- /dev/null
+++ b/cgas.h
@@ -0,0 +1,23 @@
+
+void assemble_code (VOID);
+void initialize_assembler (FILE *file);
+void define_local_label (int id,int flag);
+void define_external_label (int id,int flag,char label_name[]);
+void store_word_in_data_section (UWORD i);
+void store_long_word_in_data_section (ULONG i);
+void store_label_in_data_section (int label_id);
+void store_label_offset_in_data_section (int label_id);
+void store_descriptor_in_data_section (int label_id);
+void store_descriptor_in_code_section (int label_id);
+void store_c_string_in_data_section (char *string,int length);
+void store_abc_string_in_data_section (char *string,int length);
+void store_c_string_in_code_section (char *string,int length);
+void store_abc_string_in_code_section (char *string,int length);
+void store_descriptor_string_in_code_section (char *string,int length,int string_code_label_id,LABEL *string_label);
+void store_label_offset_in_code_section (int label_id);
+void start_new_module (int flag);
+
+#ifndef GNU_C
+void write_version_and_options (int version,int options);
+void write_depend (char *module_name);
+#endif
diff --git a/cgcalc.c b/cgcalc.c
new file mode 100644
index 0000000..d3f06e7
--- /dev/null
+++ b/cgcalc.c
@@ -0,0 +1,2947 @@
+/*
+ File: cgcalc.c
+ Author: John van Groningen
+ At: University of Nijmegen
+*/
+
+#pragma segment Code1
+
+#include <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
diff --git a/cglin.h b/cglin.h
new file mode 100644
index 0000000..fe6a547
--- /dev/null
+++ b/cglin.h
@@ -0,0 +1,126 @@
+
+void show_instructions (struct instruction *instructions);
+void initialize_linearization (VOID);
+void evaluate_arguments_and_free_addresses (union instruction_parameter arguments[],int n_arguments);
+void get_n_virtual_registers (int *n_virtual_a_regs_p,int *n_virtual_d_regs_p,int *n_virtual_f_regs_p);
+void calculate_and_linearize_branch_false (LABEL *label,INSTRUCTION_GRAPH graph);
+void calculate_and_linearize_branch_true (LABEL *label,INSTRUCTION_GRAPH graph);
+void calculate_and_linearize_graph (INSTRUCTION_GRAPH graph);
+
+void free_all_aregisters (VOID);
+void free_all_dregisters (VOID);
+void free_all_fregisters (VOID);
+void allocate_aregister (int aregister);
+void allocate_dregister (int dregister);
+void allocate_fregister (int fregister);
+#ifdef M68000
+void instruction_pd (int instruction_code,int register_1);
+#endif
+void i_jmp_l (LABEL *label,int n_a_registers);
+void i_jmp_id (int offset_1,int register_1,int n_a_registers);
+#if ! (defined (sparc) || defined (G_POWER))
+ void i_jsr_id (int offset,int register_1,int n_a_registers);
+ void i_jsr_l (LABEL *label,int n_a_registers);
+ void i_rts (void);
+# ifdef I486
+ void i_rts_i (int offset);
+ void i_rts_profile (void);
+ void i_jmp_r_profile (int a_reg);
+ void i_jmp_l_profile (LABEL *label,int offset);
+ void i_jmp_id_profile (int offset_1,int register_1,int n_a_registers);
+# endif
+#else
+ void i_jsr_id_id (int offset_1,int register_1,int offset_2);
+ void i_jsr_l_id (LABEL *label,int offset);
+ void i_rts (int offset_1,int offset_2);
+# ifdef G_POWER
+ void i_rts_c (void);
+ void i_rts_r (int register1,int offset_1);
+ void i_rts_r_profile (int register1,int offset_1);
+ void i_jmp_l_profile (LABEL *label,int offset);
+ void i_jmp_id_profile (int offset_1,int register_1,int n_a_registers);
+ void i_rts_profile (int offset_1,int offset_2);
+ void i_jsr_id_idu (int offset_1,int register_1,int offset_2);
+ void i_jsr_l_idu (LABEL *label,int offset);
+# endif
+#endif
+#if defined (sparc)
+ void i_call_l (LABEL *label);
+ void i_call_r (int register_1);
+#elif defined (G_POWER)
+ void i_call_l (LABEL *label,int frame_size);
+ void i_call_r (int register_1,int frame_size);
+#endif
+void i_beq_l (LABEL *label);
+#ifdef M68000
+ extern LONG *i_bmi_i (VOID);
+ void i_bmi_l (LABEL *label);
+#endif
+#ifdef G_POWER
+ void i_and_i_r (LONG value,int register_1);
+ void i_bnep_l (LABEL *label);
+ void i_or_i_r (LONG value,int register_1);
+ void i_mtctr (int register_1);
+#endif
+#if defined (sparc) || defined (I486) || defined (G_POWER)
+ void i_btst_i_r (LONG i,int register_1);
+#endif
+void i_ext_r (int register_1);
+void i_fmove_fr_fr (int register_1,int register_2);
+void i_fmove_fr_id (int register_1,int offset,int register_2);
+#ifdef M68000
+ void i_fmove_fr_pd (int register_1,int register_2);
+ void i_fmove_fr_pi (int register_1,int register_2);
+#endif
+void i_fmove_id_fr (int offset,int register_2,int register_1);
+#ifdef M68000
+ void i_fmove_pd_fr (int register_1,int register_2);
+ void i_fmove_pi_fr (int register_1,int register_2);
+ void i_move_id_pd (int offset,int register_1,int register_2);
+#endif
+void i_move_id_id (int offset_1,int register_1,int offset_2,int register_2);
+void i_move_id_r (int offset,int register_1,int register_2);
+#ifdef G_POWER
+ void i_move_idu_r (int offset,int register_1,int register_2);
+ void i_move_id_idu (int offset1,int register_1,int offset2,int register_2);
+ void i_move_r_idu (int register_1,int offset,int register_2);
+ void i_movew_id_idu (int offset1,int register_1,int offset2,int register_2);
+ void i_movew_r_idu (int register_1,int offset,int register_2);
+#endif
+void i_move_i_r (LONG i,int register_1);
+void i_move_l_r (LABEL *label,int register_1);
+#ifdef M68000
+void i_move_pi_id (int register_1,int offset_2,int register_2);
+void i_move_pi_r (int register_1,int register_2);
+void i_move_pd_r (int register_1,int register_2);
+#endif
+#if defined (I486)
+ void i_move_r_l (int register_1,LABEL *label);
+#endif
+void i_move_r_id (int register_1,int offset,int register_2);
+#ifdef M68000
+void i_move_r_pd (int register_1,int register_2);
+void i_move_r_pi (int register_1,int register_2);
+#endif
+void i_move_r_r (int register_1,int register_2);
+#ifdef M68000
+void i_movem_pd (int register_1,int n_arguments,int arguments[]);
+void i_movem_pi (int register_1,int n_arguments,int arguments[]);
+void i_movem_id_r (int offset,int register_1,int register_2);
+void i_movew_id_pd (int offset_1,int register_1,int register_2);
+void i_movew_pi_id (int register_1,int offset_2,int register_2);
+void i_movew_pi_r (int register_1,int register_2);
+void i_movew_r_pd (int register_1,int register_2);
+#endif
+void i_movew_id_r (int offset,int register_1,int register_2);
+void i_lea_id_r (int offset,int register_1,int register_2);
+void i_lea_l_i_r (LABEL *label,int offset,int register_1);
+void i_add_i_r (LONG value,int register_1);
+void i_add_r_r (int register_1,int register_2);
+void i_schedule_i (int value);
+void i_sub_i_r (LONG value,int register_1);
+void i_tst_r (int register_1);
+void i_word_i (int value);
+
+extern int local_data_offset;
+extern int condition_to_set_instruction[];
diff --git a/cgopt.h b/cgopt.h
new file mode 100644
index 0000000..7b61680
--- /dev/null
+++ b/cgopt.h
@@ -0,0 +1,10 @@
+
+extern void optimize_jumps (VOID);
+extern void optimize_stack_access (struct basic_block *block,int *a_offset_p,int *b_offset_p);
+extern int do_register_allocation
+ (struct instruction *last_instruction,struct basic_block *basic_block,
+ int highest_a_register,int highest_d_register,int highest_f_register,
+ int not_alter_condition_codes_flag,int condition);
+#ifdef G_POWER
+void optimize_heap_pointer_increment (struct basic_block *block,int offset_from_heap_register);
+#endif
diff --git a/cgpas.h b/cgpas.h
new file mode 100644
index 0000000..1e47a9a
--- /dev/null
+++ b/cgpas.h
@@ -0,0 +1,14 @@
+
+extern void assemble_code (VOID);
+extern void initialize_assembler (FILE *file);
+extern void define_data_label (LABEL *label);
+extern void store_2_words_in_data_section (UWORD w1,UWORD w2);
+extern void store_long_word_in_data_section (ULONG i);
+extern void store_label_in_data_section (LABEL *label);
+extern void store_descriptor_in_data_section (LABEL *label);
+extern void store_c_string_in_data_section (char *string,int length);
+extern void store_abc_string_in_data_section (char *string,int length);
+extern void store_descriptor_string_in_data_section (char *string,int length,LABEL *string_label);
+
+extern void as_new_data_module (void);
+extern void w_as_new_data_module (void);
diff --git a/cgptoc.c b/cgptoc.c
new file mode 100644
index 0000000..adb54de
--- /dev/null
+++ b/cgptoc.c
@@ -0,0 +1,65 @@
+
+#include <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 (&parameter);
+ 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",&parameter_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 (&parameter_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 (&parameter_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",&parameter_0);
+ break;
+ case SIZE_LONG:
+ w_as_opcode_parameter ("ld",&parameter_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 (&parameter_1);
+ w_as_comma();
+ w_as_parameter (&parameter_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 (&parameter_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 (&parameter_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 (&parameter_0);
+ w_as_comma();
+ w_as_parameter (&instruction->instruction_parameters[1]);
+ w_as_newline();
+}
+
+static struct instruction *w_as_fmove_instruction (struct instruction *instruction)
+{
+ switch (instruction->instruction_parameters[1].parameter_type){
+ case P_F_REGISTER:
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_F_REGISTER:
+ {
+ struct instruction *next_instruction;
+ int reg0,reg1;
+
+ reg0=instruction->instruction_parameters[0].parameter_data.reg.r;
+ reg1=instruction->instruction_parameters[1].parameter_data.reg.r;
+
+ next_instruction=instruction->instruction_next;
+ if (next_instruction)
+ switch (next_instruction->instruction_icode){
+ case IFADD: case IFSUB: case IFMUL: case IFDIV: case IFREM:
+ if (next_instruction->instruction_parameters[1].parameter_data.reg.r==reg1)
+ {
+ struct parameter parameter_0;
+ int reg_s;
+
+ parameter_0=w_as_float_parameter (next_instruction->instruction_parameters[0]);
+
+ reg_s=parameter_0.parameter_data.reg.r;
+ if (reg_s==reg1)
+ reg_s=reg0;
+
+ switch (next_instruction->instruction_icode){
+ case IFADD:
+ w_as_opcode_and_d ("fadd");
+ break;
+ case IFSUB:
+ w_as_opcode_and_d ("fsub");
+ break;
+ case IFMUL:
+ w_as_opcode_and_d ("fmul");
+ break;
+ case IFDIV:
+ w_as_opcode_and_d ("fdiv");
+ break;
+ case IFREM:
+ w_as_opcode_and_d ("frem");
+ }
+ w_as_fp_register (reg0<<1);
+ w_as_comma();
+ w_as_fp_register (reg_s<<1);
+ w_as_comma();
+ w_as_fp_register (reg1<<1);
+ w_as_newline();
+
+ return next_instruction;
+ }
+ }
+
+ w_as_opcode ("fmovs");
+ w_as_fp_register (reg0<<1);
+ w_as_comma();
+ w_as_fp_register (reg1<<1);
+ w_as_newline();
+
+ w_as_opcode ("fmovs");
+ w_as_fp_register ((reg0<<1)+1);
+ w_as_comma();
+ w_as_fp_register ((reg1<<1)+1);
+ w_as_newline();
+
+ return instruction;
+ }
+ case P_INDIRECT:
+ w_as_opcode ("ld");
+ w_as_indirect (instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_comma();
+ w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r<<1);
+ w_as_newline();
+
+ w_as_opcode ("ld");
+ w_as_indirect (instruction->instruction_parameters[0].parameter_offset+4,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_comma();
+ w_as_fp_register ((instruction->instruction_parameters[1].parameter_data.reg.r<<1)+1);
+ w_as_newline();
+
+ return instruction;
+ case P_INDEXED:
+ w_as_opcode ("add");
+ w_as_register (instruction->instruction_parameters[0].parameter_data.ir->a_reg.r);
+ w_as_comma();
+ w_as_register (instruction->instruction_parameters[0].parameter_data.ir->d_reg.r);
+ w_as_comma();
+ w_as_register (REGISTER_O0);
+ w_as_newline();
+
+ w_as_opcode ("ld");
+ w_as_indirect (instruction->instruction_parameters[0].parameter_offset>>2,REGISTER_O0);
+ w_as_comma();
+ w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r<<1);
+ w_as_newline();
+
+ w_as_opcode ("ld");
+ w_as_indirect ((instruction->instruction_parameters[0].parameter_offset>>2)+4,REGISTER_O0);
+ w_as_comma();
+ w_as_fp_register ((instruction->instruction_parameters[1].parameter_data.reg.r<<1)+1);
+ w_as_newline();
+
+ return instruction;
+ case P_F_IMMEDIATE:
+ {
+ int label_number=next_label_id++;
+
+ w_as_to_data_section();
+
+ w_as_opcode (".align");
+ fprintf (assembly_file,"8");
+ w_as_newline();
+
+ w_as_define_internal_label (label_number);
+
+ w_as_opcode (".double");
+ fprintf (assembly_file,"0r%.20e",*instruction->instruction_parameters[0].parameter_data.r);
+ w_as_newline();
+
+ w_as_to_code_section();
+
+ w_as_opcode ("sethi");
+#ifdef GAS
+ fprintf (assembly_file,"%%hi (i_%d),%%o0",label_number);
+#else
+ fprintf (assembly_file,"%%hi i_%d,%%o0",label_number);
+#endif
+ w_as_newline();
+
+ w_as_opcode ("ldd");
+#ifdef GAS
+ fprintf (assembly_file,"[%%o0+%%lo (i_%d)]",label_number);
+#else
+ fprintf (assembly_file,"[%%o0+%%lo i_%d]",label_number);
+#endif
+ w_as_comma();
+ w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r<<1);
+ w_as_newline();
+ return instruction;
+ }
+ }
+ break;
+ case P_INDIRECT:
+ if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){
+ w_as_opcode ("st");
+ w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r<<1);
+ w_as_comma();
+ w_as_indirect (instruction->instruction_parameters[1].parameter_offset,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_newline();
+
+ w_as_opcode ("st");
+ w_as_fp_register ((instruction->instruction_parameters[0].parameter_data.reg.r<<1)+1);
+ w_as_comma();
+ w_as_indirect (instruction->instruction_parameters[1].parameter_offset+4,
+ instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_newline();
+ return instruction;
+ }
+ break;
+ case P_INDEXED:
+ if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){
+ w_as_opcode ("add");
+ w_as_register (instruction->instruction_parameters[1].parameter_data.ir->a_reg.r);
+ w_as_comma();
+ w_as_register (instruction->instruction_parameters[1].parameter_data.ir->d_reg.r);
+ w_as_comma();
+ w_as_register (REGISTER_O0);
+ w_as_newline();
+
+ w_as_opcode ("st");
+ w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r<<1);
+ w_as_comma();
+ w_as_indirect (instruction->instruction_parameters[1].parameter_offset>>2,REGISTER_O0);
+ w_as_newline();
+
+ w_as_opcode ("st");
+ w_as_fp_register ((instruction->instruction_parameters[0].parameter_data.reg.r<<1)+1);
+ w_as_comma();
+ w_as_indirect ((instruction->instruction_parameters[1].parameter_offset>>2)+4,REGISTER_O0);
+ w_as_newline();
+
+ return instruction;
+ }
+ }
+ internal_error_in_function ("w_as_fmove_instruction");
+ return instruction;
+}
+
+static void w_as_fmove_hl_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT
+ && instruction->instruction_parameters[1].parameter_type==P_F_REGISTER)
+ {
+ w_as_opcode_indirect ("ld",
+ instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_comma();
+ if (instruction->instruction_icode==IFMOVEHI)
+ w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r<<1);
+ else
+ w_as_fp_register ((instruction->instruction_parameters[1].parameter_data.reg.r<<1)+1);
+
+ w_as_newline();
+ return;
+ }
+
+ internal_error_in_function ("w_as_fmove_instruction");
+}
+
+static void w_as_fmovel_instruction (struct instruction *instruction)
+{
+ if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){
+ if (instruction->instruction_parameters[1].parameter_type!=P_REGISTER)
+ internal_error_in_function ("w_as_fmovel_instruction");
+
+ w_as_opcode ("fdtoi");
+ w_as_fp_register (instruction->instruction_parameters[0].parameter_data.reg.r<<1);
+ w_as_comma();
+ w_as_fp_register (31);
+ w_as_newline();
+
+ w_as_opcode ("st");
+ w_as_fp_register (31);
+ w_as_comma();
+ w_as_indirect (-4,REGISTER_I6);
+ w_as_newline();
+
+ w_as_opcode ("ld");
+ w_as_indirect (-4,REGISTER_I6);
+ w_as_comma();
+ w_as_register (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_newline();
+ } else {
+ switch (instruction->instruction_parameters[0].parameter_type){
+ case P_REGISTER:
+ w_as_opcode ("st");
+ w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_comma();
+ w_as_indirect (-4,REGISTER_I6);
+ w_as_newline();
+
+ w_as_opcode ("ld");
+ w_as_indirect (-4,REGISTER_I6);
+ w_as_comma();
+ w_as_fp_register (31);
+ w_as_newline();
+ break;
+ case P_INDIRECT:
+ w_as_opcode ("ld");
+ w_as_indirect (instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_comma();
+ w_as_fp_register (31);
+ w_as_newline();
+ break;
+ case P_INDEXED:
+ w_as_opcode ("ld");
+ w_as_indexed (instruction->instruction_parameters[0].parameter_offset,
+ instruction->instruction_parameters[0].parameter_data.ir);
+ w_as_comma();
+ w_as_fp_register (31);
+ w_as_newline();
+ break;
+ case P_IMMEDIATE:
+ w_as_opcode ("set");
+ w_as_immediate (instruction->instruction_parameters[0].parameter_data.i);
+ w_as_comma();
+ w_as_scratch_register();
+ w_as_newline();
+
+ w_as_opcode ("st");
+ w_as_scratch_register();
+ w_as_comma();
+ w_as_indirect (-4,REGISTER_I6);
+ w_as_newline();
+
+ w_as_opcode ("ld");
+ w_as_indirect (-4,REGISTER_I6);
+ w_as_comma();
+ w_as_fp_register (31);
+ w_as_newline();
+ break;
+ default:
+ internal_error_in_function ("w_as_fmovel_instruction");
+ }
+
+ w_as_opcode ("fitod");
+ w_as_fp_register (31);
+ w_as_comma();
+ w_as_fp_register (instruction->instruction_parameters[1].parameter_data.reg.r<<1);
+ w_as_newline();
+ }
+}
+
+static void w_as_instructions (register struct instruction *instruction)
+{
+ while (instruction!=NULL){
+ switch (instruction->instruction_icode){
+ case IMOVE:
+ w_as_move_instruction (instruction,SIZE_LONG);
+ break;
+ case ILEA:
+ w_as_lea_instruction (instruction);
+ break;
+ case IADD:
+ w_as_add_instruction (instruction);
+ break;
+ case IADDI:
+ w_as_i_instruction (instruction,"add");
+ break;
+ case ISUB:
+ w_as_sub_instruction (instruction);
+ break;
+ case ICMP:
+ w_as_cmp_instruction (instruction,SIZE_LONG);
+ break;
+ case IJMP:
+ w_as_jmp_instruction (instruction);
+ break;
+ case IJSR:
+ w_as_jsr_instruction (instruction);
+ break;
+ case IRTS:
+ w_as_rts_instruction (instruction);
+ break;
+ case IBEQ:
+ w_as_branch_instruction (instruction,"be");
+ break;
+ case IBGE:
+ w_as_branch_instruction (instruction,"bge");
+ break;
+ case IBGT:
+ w_as_branch_instruction (instruction,"bg");
+ break;
+ case IBHS:
+ w_as_index_error_branch_instruction (instruction);
+ break;
+ case IBLE:
+ w_as_branch_instruction (instruction,"ble");
+ break;
+ case IBLT:
+ w_as_branch_instruction (instruction,"bl");
+ break;
+ case IBNE:
+ w_as_branch_instruction (instruction,"bne");
+ break;
+ case IBNO:
+ w_as_branch_instruction (instruction,"bvc");
+ break;
+ case IBO:
+ w_as_branch_instruction (instruction,"bvs");
+ break;
+ case ILSLI:
+ w_as_i_instruction (instruction,"sll");
+ break;
+ case ILSL:
+ w_as_tryadic_instruction (instruction,"sll");
+ break;
+ case ILSR:
+ w_as_tryadic_instruction (instruction,"srl");
+ break;
+ case IASR:
+ w_as_tryadic_instruction (instruction,"sra");
+ break;
+ case IMUL:
+ w_as_mul_or_div_instruction (instruction,".mul");
+ break;
+ case IDIV:
+ w_as_mul_or_div_instruction (instruction,".div");
+ break;
+ case IMOD:
+ w_as_mod_instruction (instruction);
+ break;
+ case IAND:
+ w_as_tryadic_instruction (instruction,"and");
+ break;
+ case IOR:
+ w_as_tryadic_instruction (instruction,"or");
+ break;
+ case IEOR:
+ w_as_tryadic_instruction (instruction,"xor");
+ break;
+ case ISEQ:
+ w_as_set_condition_instruction (instruction,"be,a");
+ break;
+ case ISGE:
+ w_as_set_condition_instruction (instruction,"bge,a");
+ break;
+ case ISGT:
+ w_as_set_condition_instruction (instruction,"bg,a");
+ break;
+ case ISLE:
+ w_as_set_condition_instruction (instruction,"ble,a");
+ break;
+ case ISLT:
+ w_as_set_condition_instruction (instruction,"bl,a");
+ break;
+ case ISNE:
+ w_as_set_condition_instruction (instruction,"bne,a");
+ break;
+ case ISNO:
+ w_as_set_condition_instruction (instruction,"bvc,a");
+ break;
+ case ISO:
+ w_as_set_condition_instruction (instruction,"bvs,a");
+ break;
+ case ICMPW:
+ w_as_cmp_instruction (instruction,SIZE_WORD);
+ break;
+ case ITST:
+ w_as_tst_instruction (instruction,SIZE_LONG);
+ break;
+ case IBTST:
+ w_as_btst_instruction (instruction);
+ break;
+ case IMOVEW:
+ w_as_move_instruction (instruction,SIZE_WORD);
+ break;
+ case IMOVEB:
+ w_as_move_instruction (instruction,SIZE_BYTE);
+ break;
+ case IFMOVE:
+ instruction=w_as_fmove_instruction (instruction);
+ break;
+ case IFMOVEHI:
+ case IFMOVELO:
+ w_as_fmove_hl_instruction (instruction);
+ break;
+ case IFADD:
+ w_as_tryadic_float_instruction (instruction,"fadd");
+ break;
+ case IFSUB:
+ w_as_tryadic_float_instruction (instruction,"fsub");
+ break;
+ case IFCMP:
+ w_as_compare_float_instruction (instruction);
+ break;
+ case IFDIV:
+ w_as_tryadic_float_instruction (instruction,"fdiv");
+ break;
+ case IFMUL:
+ w_as_tryadic_float_instruction (instruction,"fmul");
+ break;
+ case IFREM:
+ w_as_tryadic_float_instruction (instruction,"frem");
+ break;
+ case IFBEQ:
+ w_as_float_branch_instruction (instruction,"fbe");
+ break;
+ case IFBGE:
+ w_as_float_branch_instruction (instruction,"fbge");
+ break;
+ case IFBGT:
+ w_as_float_branch_instruction (instruction,"fbg");
+ break;
+ case IFBLE:
+ w_as_float_branch_instruction (instruction,"fble");
+ break;
+ case IFBLT:
+ w_as_float_branch_instruction (instruction,"fbl");
+ break;
+ case IFBNE:
+ w_as_float_branch_instruction (instruction,"fbne");
+ break;
+ case IFMOVEL:
+ w_as_fmovel_instruction (instruction);
+ break;
+ case IFSQRT:
+ w_as_sqrt_float_instruction (instruction);
+ break;
+ case IFNEG:
+ w_as_neg_float_instruction (instruction);
+ break;
+ case IFSEQ:
+ w_as_set_float_condition_instruction (instruction,"fbe,a");
+ break;
+ case IFSGE:
+ w_as_set_float_condition_instruction (instruction,"fbge,a");
+ break;
+ case IFSGT:
+ w_as_set_float_condition_instruction (instruction,"fbg,a");
+ break;
+ case IFSLE:
+ w_as_set_float_condition_instruction (instruction,"fble,a");
+ break;
+ case IFSLT:
+ w_as_set_float_condition_instruction (instruction,"fbl,a");
+ break;
+ case IFSNE:
+ w_as_set_float_condition_instruction (instruction,"fbne,a");
+ break;
+ case IWORD:
+ w_as_word_instruction (instruction);
+ break;
+ case IADDO:
+ w_as_add_o_instruction (instruction);
+ break;
+ case ISUBO:
+ w_as_sub_o_instruction (instruction);
+ break;
+ case IFTST:
+ default:
+ internal_error_in_function ("w_as_instructions");
+ }
+ instruction=instruction->instruction_next;
+ }
+}
+
+static void w_as_number_of_arguments (int n_node_arguments)
+{
+ w_as_opcode (".word");
+ fprintf (assembly_file,"%d",n_node_arguments);
+ w_as_newline();
+}
+
+
+struct call_and_jump {
+ struct call_and_jump *cj_next;
+ WORD cj_label_id;
+ WORD cj_jump_id;
+ char *cj_call_label_name;
+};
+
+static struct call_and_jump *first_call_and_jump,*last_call_and_jump;
+
+static void w_as_garbage_collect_test (register struct basic_block *block)
+{
+ LONG n_cells;
+ int label_id_1,label_id_2;
+ struct call_and_jump *new_call_and_jump;
+
+ label_id_1=next_label_id++;
+ label_id_2=next_label_id++;
+
+ new_call_and_jump=allocate_memory_from_heap (sizeof (struct call_and_jump));
+
+ new_call_and_jump->cj_next=NULL;
+ new_call_and_jump->cj_label_id=label_id_1;
+ new_call_and_jump->cj_jump_id=label_id_2;
+
+ switch (block->block_n_begin_a_parameter_registers){
+ case 0: new_call_and_jump->cj_call_label_name="collect_0"; break;
+ case 1: new_call_and_jump->cj_call_label_name="collect_1"; break;
+ case 2: new_call_and_jump->cj_call_label_name="collect_2"; break;
+ case 3: new_call_and_jump->cj_call_label_name="collect_3"; break;
+ default: internal_error_in_function ("w_as_garbage_collect_test");
+ }
+
+ if (first_call_and_jump!=NULL)
+ last_call_and_jump->cj_next=new_call_and_jump;
+ else
+ first_call_and_jump=new_call_and_jump;
+ last_call_and_jump=new_call_and_jump;
+
+ n_cells=block->block_n_new_heap_cells;
+
+ if (n_cells<4096){
+ w_as_opcode ("deccc");
+ w_as_immediate (n_cells);
+ w_as_comma();
+ w_as_register (REGISTER_D7);
+ w_as_newline();
+ } else {
+ w_as_opcode ("set");
+ w_as_immediate (n_cells);
+ w_as_comma();
+ w_as_scratch_register();
+ w_as_newline();
+
+ w_as_opcode ("subcc");
+ w_as_register (REGISTER_D7);
+ w_as_comma();
+ w_as_scratch_register();
+ w_as_comma();
+ w_as_register (REGISTER_D7);
+ w_as_newline();
+ }
+
+ w_as_opcode ("bcs,a");
+ w_as_internal_label (label_id_1);
+ w_as_newline ();
+
+ w_as_opcode ("dec");
+ w_as_immediate (4);
+ w_as_comma();
+ w_as_register (B_STACK_POINTER);
+ w_as_newline();
+
+ w_as_define_internal_label (label_id_2);
+}
+
+static void w_as_call_and_jump (struct call_and_jump *call_and_jump)
+{
+ w_as_define_internal_label (call_and_jump->cj_label_id);
+
+ w_as_opcode ("call");
+ w_as_label (call_and_jump->cj_call_label_name);
+ w_as_newline();
+
+ w_as_opcode ("st");
+ w_as_register (REGISTER_O7);
+ w_as_comma();
+ w_as_indirect (0,B_STACK_POINTER);
+ w_as_newline();
+
+ w_as_opcode ("b,a");
+ w_as_internal_label (call_and_jump->cj_jump_id);
+ w_as_newline();
+}
+
+static void w_as_labels (struct block_label *labels)
+{
+ for (; labels!=NULL; labels=labels->block_label_next)
+ if (labels->block_label_label->label_number==0){
+ LABEL *label;
+
+ label=labels->block_label_label;
+
+ w_as_define_label (label);
+ } else
+ w_as_define_local_label (labels->block_label_label->label_number);
+}
+
+/*
+static void init_c_stack_checking (VOID)
+{
+ w_as_define_label_name (local_c_stack_overflow_label_name);
+ w_as_opcode ("ba");
+ w_as_label (c_stack_overflow_label->label_name);
+ w_as_newline();
+
+ w_as_instruction_without_parameters ("nop");
+}
+*/
+
+static char local_ab_stack_overflow_label_name[]="l_ab_stack_overflow";
+
+/*
+static void init_ab_stack_checking (VOID)
+{
+ w_as_define_label_name (local_ab_stack_overflow_label_name);
+ w_as_opcode ("ba");
+ w_as_label (ab_stack_overflow_label->label_name);
+ w_as_newline();
+
+ w_as_instruction_without_parameters ("nop");
+}
+*/
+/*
+static void w_as_check_ab_stack (int size,int n_d_parameters,int n_a_parameters)
+{
+ if (size<=4){
+ w_as_opcode ("cmp");
+ w_as_register (A_STACK_POINTER);
+ w_as_comma();
+ w_as_register (B_STACK_POINTER);
+ w_as_newline();
+
+ w_as_opcode ("bleu");
+ } else {
+ w_as_opcode ("add");
+ w_as_register (B_STACK_POINTER);
+ w_as_comma();
+ w_as_immediate (size);
+ w_as_comma();
+ w_as_register (REGISTER_O0);
+ w_as_newline();
+
+ w_as_opcode ("cmp");
+ w_as_register (REGISTER_O0);
+ w_as_comma();
+ w_as_register (A_STACK_POINTER);
+ w_as_newline();
+
+ w_as_opcode ("bgu");
+ }
+ w_as_label (local_ab_stack_overflow_label_name);
+ w_as_newline();
+
+ w_as_instruction_without_parameters ("nop");
+}
+*/
+
+void initialize_write_assembly (FILE *ass_file)
+{
+ assembly_file=ass_file;
+
+ in_data_section=0;
+
+ first_call_and_jump=NULL;
+
+ /*
+ if (check_c_stack)
+ init_c_stack_checking();
+ if (check_ab_stack)
+ init_ab_stack_checking();
+ */
+}
+
+static void w_as_indirect_node_entry_jump (LABEL *label)
+{
+ register char *new_label_name;
+
+ new_label_name=fast_memory_allocate (strlen (label->label_name)+1+2);
+ strcpy (new_label_name,"j_");
+ strcat (new_label_name,label->label_name);
+
+ if (label->label_flags & EA_LABEL){
+ int label_arity;
+ extern LABEL *eval_fill_label,*eval_upd_labels[];
+
+ label_arity=label->label_arity;
+
+ if (label_arity<-2)
+ label_arity=1;
+
+ if (label_arity>=0 && label->label_ea_label!=eval_fill_label){
+ w_as_opcode ("sethi");
+ fprintf (assembly_file,"%%hi ");
+#ifdef GAS
+ fprintf (assembly_file,"(");
+#endif
+ w_as_label (label->label_ea_label->label_name);
+#ifdef GAS
+ fprintf (assembly_file,")");
+#endif
+ w_as_comma();
+ w_as_register (REGISTER_A2);
+ w_as_newline();
+
+ w_as_opcode ("call");
+ w_as_label (eval_upd_labels[label_arity]->label_name);
+ w_as_newline();
+
+ w_as_opcode ("inc");
+ fprintf (assembly_file,"%%lo ");
+#ifdef GAS
+ fprintf (assembly_file,"(");
+#endif
+ w_as_label (label->label_ea_label->label_name);
+#ifdef GAS
+ fprintf (assembly_file,")");
+#endif
+ w_as_comma();
+ w_as_register (REGISTER_A2);
+ w_as_newline();
+ } else {
+ w_as_opcode ("call");
+ w_as_label (label->label_ea_label->label_name);
+ w_as_newline();
+
+ w_as_instruction_without_parameters ("nop");
+ w_as_instruction_without_parameters ("nop");
+ }
+
+ if (label->label_arity<0 || parallel_flag){
+ LABEL *descriptor_label;
+
+ descriptor_label=label->label_descriptor;
+
+ if (descriptor_label->label_id<0)
+ descriptor_label->label_id=next_label_id++;
+
+ w_as_opcode (".long");
+ w_as_label (descriptor_label->label_name);
+ w_as_newline();
+ } else
+ w_as_number_of_arguments (0);
+ } else
+ if (label->label_arity<0 || parallel_flag){
+ LABEL *descriptor_label;
+
+ descriptor_label=label->label_descriptor;
+
+ if (descriptor_label->label_id<0)
+ descriptor_label->label_id=next_label_id++;
+
+ w_as_opcode (".long");
+ w_as_label (descriptor_label->label_name);
+ w_as_newline();
+ }
+
+ w_as_number_of_arguments (label->label_arity);
+
+ w_as_define_label_name (new_label_name);
+
+ w_as_opcode ("call");
+ w_as_label (label->label_name);
+ w_as_newline();
+
+ label->label_name=new_label_name;
+
+ w_as_instruction_without_parameters ("nop");
+}
+
+static void w_as_indirect_node_entry_jumps (register struct label_node *label_node)
+{
+ register LABEL *label;
+
+ if (label_node==NULL)
+ return;
+
+ label=&label_node->label_node_label;
+
+ if (!(label->label_flags & LOCAL_LABEL) && label->label_number==0)
+ if (label->label_flags & NODE_ENTRY_LABEL)
+ w_as_indirect_node_entry_jump (label);
+
+ w_as_indirect_node_entry_jumps (label_node->label_node_left);
+ w_as_indirect_node_entry_jumps (label_node->label_node_right);
+}
+
+#ifdef SOLARIS_
+static int next_section_number;
+extern char *this_module_name;
+#endif
+
+void write_assembly (VOID)
+{
+ struct basic_block *block;
+ struct call_and_jump *call_and_jump;
+
+#ifdef SOLARIS_
+ next_section_number=0;
+#endif
+
+ w_as_to_code_section();
+
+ w_as_indirect_node_entry_jumps (labels);
+
+ for (block=first_block; block!=NULL; block=block->block_next){
+#ifdef SOLARIS_
+ if (block->block_begin_module && !block->block_link_module){
+ if (block->block_labels!=NULL && block->block_labels->block_label_label->label_number==0 && block->block_labels->block_label_label->label_flags & EXPORT_LABEL)
+ fprintf (assembly_file,"\t.section\t\".%s\",#alloc,#execinstr\n",block->block_labels->block_label_label->label_name);
+ else
+ fprintf (assembly_file,"\t.section\t\"%s.%d\",#alloc,#execinstr\n",this_module_name,next_section_number++);
+ }
+#endif
+
+ if (block->block_n_node_arguments>-100){
+ if (block->block_ea_label!=NULL){
+ int n_node_arguments;
+ extern LABEL *eval_fill_label,*eval_upd_labels[];
+
+ n_node_arguments=block->block_n_node_arguments;
+
+ if (n_node_arguments<-2)
+ n_node_arguments=1;
+
+ if (n_node_arguments>=0 && block->block_ea_label!=eval_fill_label){
+ w_as_opcode ("sethi");
+ fprintf (assembly_file,"%%hi ");
+#ifdef GAS
+ fprintf (assembly_file,"(");
+#endif
+ w_as_label (block->block_ea_label->label_name);
+#ifdef GAS
+ fprintf (assembly_file,")");
+#endif
+ w_as_comma();
+ w_as_register (REGISTER_A2);
+ w_as_newline();
+
+ w_as_opcode ("call");
+ w_as_label (eval_upd_labels[n_node_arguments]->label_name);
+ w_as_newline();
+
+ w_as_opcode ("inc");
+ fprintf (assembly_file,"%%lo ");
+#ifdef GAS
+ fprintf (assembly_file,"(");
+#endif
+ w_as_label (block->block_ea_label->label_name);
+#ifdef GAS
+ fprintf (assembly_file,")");
+#endif
+ w_as_comma();
+ w_as_register (REGISTER_A2);
+ w_as_newline();
+ } else {
+ w_as_opcode ("call");
+ w_as_label (block->block_ea_label->label_name);
+ w_as_newline();
+
+ w_as_instruction_without_parameters ("nop");
+ w_as_instruction_without_parameters ("nop");
+ }
+
+ if (block->block_descriptor!=NULL
+ && (block->block_n_node_arguments<0 || parallel_flag))
+ {
+ w_as_label_in_code_section (block->block_descriptor->label_name);
+ } else
+ w_as_number_of_arguments (0);
+ } else
+ if (block->block_descriptor!=NULL)
+ w_as_label_in_code_section (block->block_descriptor->label_name);
+ else
+ w_as_number_of_arguments (0);
+
+ w_as_number_of_arguments (block->block_n_node_arguments);
+ }
+
+ w_as_labels (block->block_labels);
+
+ if (block->block_n_new_heap_cells>0)
+ w_as_garbage_collect_test (block);
+ /*
+ if (check_ab_stack && block->block_ab_stack_check_size>0)
+ w_as_check_ab_stack (block->block_ab_stack_check_size,
+ block->block_n_begin_d_parameter_registers,block->block_n_begin_a_parameter_registers);
+ */
+
+ w_as_instructions (block->block_instructions);
+ }
+
+ for (call_and_jump=first_call_and_jump; call_and_jump!=NULL; call_and_jump=call_and_jump->cj_next)
+ w_as_call_and_jump (call_and_jump);
+
+ w_as_instruction_without_parameters ("nop");
+}
diff --git a/cgswas.h b/cgswas.h
new file mode 100644
index 0000000..8b1264d
--- /dev/null
+++ b/cgswas.h
@@ -0,0 +1,11 @@
+void initialize_write_assembly (FILE *ass_file);
+void write_assembly (VOID);
+void w_as_c_string_in_data_section (char *string,int length);
+void w_as_abc_string_in_data_section (char *string,int length);
+void w_as_c_string_in_code_section (char *string,int length,int label_number);
+void w_as_abc_string_in_code_section (char *string,int length,int label_number);
+void w_as_descriptor_string_in_code_section
+ (char *string,int length,int string_label_id,LABEL *string_label);
+void w_as_word_in_data_section (int n);
+void w_as_label_in_data_section (char *label_name);
+void w_as_define_label (LABEL *label);
diff --git a/cgtypes.h b/cgtypes.h
new file mode 100644
index 0000000..3138062
--- /dev/null
+++ b/cgtypes.h
@@ -0,0 +1,257 @@
+
+#ifdef I486
+# undef MORE_PARAMETER_REGISTERS
+#endif
+
+#define NODE_POINTER_OFFSET 0
+
+typedef struct label {
+ char * label_name;
+ WORD label_number;
+ WORD label_flags;
+ WORD label_a_stack_size;
+ WORD label_b_stack_size;
+#if defined (G_POWER) || defined (_WINDOWS_)
+ union {
+ ULONG * u_vector;
+# define label_vector label_u.u_vector
+ struct object_label * u_object_label;
+# define label_object_label label_u.u_object_label
+ } label_u;
+#else
+ ULONG * label_vector;
+#endif
+#if defined (G_POWER) || defined (I486) || defined (sparc)
+ union {
+ ULONG u0_small_vector;
+# define label_small_vector label_u0.u0_small_vector
+ ULONG u0_offset;
+# define label_offset label_u0.u0_offset
+ } label_u0;
+#else
+ ULONG label_small_vector;
+#endif
+ WORD label_id;
+ WORD label_arity;
+ struct label *label_descriptor;
+ union {
+ struct instruction_node * u_last_lea; /* for descriptors */
+ struct label * u_ea_label; /* for node entry labels */
+ } label_u1;
+ union {
+ struct basic_block * u_last_lea_block; /* cgcode.c */
+#ifdef G_POWER
+ struct toc_label * u_toc_labels; /* cgpwas.c */
+#endif
+ } label_u2;
+ WORD label_last_lea_arity;
+} LABEL;
+
+#define label_last_lea_block label_u2.u_last_lea_block
+#ifdef G_POWER
+# define label_toc_labels label_u2.u_toc_labels
+#endif
+
+#define label_last_lea label_u1.u_last_lea
+#define label_ea_label label_u1.u_ea_label
+
+#define IMPORT_LABEL 1
+#define EXPORT_LABEL 2
+#define LOCAL_LABEL 4
+#define REGISTERS_ALLOCATED 8
+#define DATA_LABEL 16
+#define NODE_ENTRY_LABEL 32
+#define DEFERED_LABEL 64
+#define EA_LABEL 128
+#ifdef G_POWER
+# define HAS_TOC_LABELS 256
+# define FAR_CONDITIONAL_JUMP_LABEL 512
+# define STRING_LABEL 1024
+# define DOT_O_BEFORE_LABEL 2048
+# define STUB_GENERATED 4096
+#endif
+
+struct label_node {
+ struct label_node * label_node_left;
+ struct label_node * label_node_right;
+ LABEL label_node_label;
+};
+
+struct local_label {
+ struct local_label *local_label_next;
+ struct label local_label_label;
+};
+
+#ifdef I486
+struct reg {
+ WORD r;
+ UWORD u;
+};
+#else
+struct reg {
+ UWORD u;
+ WORD r;
+};
+#endif
+
+struct index_registers {
+ struct reg a_reg;
+ struct reg d_reg;
+};
+
+struct parameter {
+ char parameter_type;
+ char parameter_flags;
+ short parameter_offset;
+ union parameter_data {
+ LONG i;
+ LABEL *l;
+ DOUBLE *r;
+ struct reg reg;
+ struct index_registers *ir;
+ } parameter_data;
+};
+
+#ifdef G_POWER
+# define NO_MTLR 16
+# define NO_MFLR 32
+#endif
+
+struct instruction {
+ struct instruction * instruction_next;
+ struct instruction * instruction_prev;
+ WORD instruction_icode;
+ WORD instruction_arity;
+ struct parameter instruction_parameters[VARIABLE_ARRAY_SIZE];
+};
+
+#ifdef __cplusplus
+ union instruction_parameter {
+ struct instruction_node * p;
+ LABEL * l;
+ LONG i;
+ };
+#endif
+
+struct instruction_node {
+ WORD instruction_code;
+ WORD inode_arity;
+ WORD node_count;
+ WORD instruction_d_min_a_cost;
+ WORD u_aregs;
+ WORD u_dregs;
+ WORD i_aregs;
+ WORD i_dregs;
+ UBYTE node_mark;
+ UBYTE order_mode;
+ UBYTE order_alterable;
+ UBYTE order_left;
+ union instruction_parameter
+#ifndef __cplusplus
+ {
+ struct instruction_node * p;
+ LABEL * l;
+ LONG i;
+ }
+#endif
+ instruction_parameters[VARIABLE_ARRAY_SIZE];
+};
+
+typedef struct instruction_node INSTRUCTION_NODE,*INSTRUCTION_GRAPH;
+
+struct block_label {
+ struct block_label * block_label_next;
+ LABEL * block_label_label;
+};
+
+struct basic_block {
+ struct basic_block * block_next;
+ struct instruction * block_instructions;
+ struct instruction * block_last_instruction;
+ struct block_label * block_labels;
+ int block_n_new_heap_cells;
+ WORD block_n_begin_a_parameter_registers;
+ WORD block_n_begin_d_parameter_registers;
+ WORD block_n_node_arguments; /* <0 if no .n directive */
+#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS
+ WORD block_a_stack_check_size;
+ WORD block_b_stack_check_size;
+#else
+ WORD block_stack_check_size;
+#endif
+ unsigned int block_begin_module:1,
+ block_link_module:1
+#ifdef G_POWER
+ ,block_gc_kind:3
+ /* 0 return address in lr before and after call
+ 1 return address in r0 before and in lr after call
+ 2 return address in lr before and in r0 after call
+ 3 return address in r0 before and after call
+ */
+#endif
+ ,block_profile:3;
+ struct label * block_descriptor; /* if .n directive */
+ struct label * block_ea_label; /* if .n directive */
+ struct label * block_profile_function_label;
+};
+
+struct block_graph {
+ struct block_graph * block_graph_previous;
+ struct block_graph * block_graph_next;
+ struct basic_block * block_graph_block;
+
+ WORD block_graph_begin_a_stack_size;
+ WORD block_graph_begin_b_stack_size;
+ WORD block_graph_end_a_stack_size;
+ WORD block_graph_end_b_stack_size;
+ ULONG * block_graph_end_stack_vector;
+ ULONG block_graph_small_end_stack_vector;
+
+ struct a_stack * block_graph_a_stack;
+ WORD block_graph_a_stack_top_offset;
+ WORD block_graph_a_stack_begin_displacement;
+ WORD block_graph_a_stack_end_displacement;
+ WORD block_graph_used_a_stack_elements;
+
+ struct b_stack * block_graph_b_stack;
+ WORD block_graph_b_stack_top_offset;
+ WORD block_graph_b_stack_begin_displacement;
+ WORD block_graph_b_stack_end_displacement;
+ WORD block_graph_used_b_stack_elements;
+
+ INSTRUCTION_GRAPH block_graph_a_register_parameter_node[N_ADDRESS_PARAMETER_REGISTERS];
+ INSTRUCTION_GRAPH block_graph_d_register_parameter_node[N_DATA_PARAMETER_REGISTERS
+#ifdef MORE_PARAMETER_REGISTERS
+ + N_ADDRESS_PARAMETER_REGISTERS
+#endif
+ ];
+ INSTRUCTION_GRAPH block_graph_f_register_parameter_node[N_FLOAT_PARAMETER_REGISTERS];
+
+ WORD block_graph_kind;
+ WORD block_graph_jsr_eval_offset;
+ LABEL * block_graph_last_instruction_label;
+#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS
+ WORD block_graph_a_stack_displacement;
+ WORD block_graph_b_stack_displacement;
+#else
+ WORD block_graph_stack_displacement;
+#endif
+};
+
+struct dependency_list {
+ struct dependency_list * dependency_next;
+ char * dependency_module_name;
+};
+
+#ifndef sparc
+struct relocatable_words_list {
+ struct relocatable_words_list * relocatable_next;
+ char * relocatable_label_name;
+};
+#else
+struct relocatable_longs_list {
+ struct relocatable_longs_list * relocatable_next;
+ char * relocatable_label_name;
+ int relocatable_arity;
+};
+#endif
diff --git a/cgwas.c b/cgwas.c
new file mode 100644
index 0000000..4958d3c
--- /dev/null
+++ b/cgwas.c
@@ -0,0 +1,1846 @@
+/*
+ File: cgwas.c
+ Author: John van Groningen
+*/
+
+#include <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
diff --git a/cgwas.h b/cgwas.h
new file mode 100644
index 0000000..f9a8215
--- /dev/null
+++ b/cgwas.h
@@ -0,0 +1,19 @@
+void initialize_write_assembly (FILE *ass_file);
+void write_assembly (VOID);
+void w_as_abc_string_and_label_in_code_section (char *string,int length,char *label_name);
+void w_as_c_string_in_code_section (char *string,int length,int label_number);
+void w_as_c_string_in_data_section (char *string,int length);
+void w_as_descriptor_string_in_code_section
+ (char *string,int length,int string_code_label_id,LABEL *string_label);
+void w_as_word_in_data_section (int n);
+void w_as_label_in_data_section (char *label_name);
+void w_as_descriptor_in_data_section (char *label_name);
+void w_as_define_label (LABEL *label);
+void w_as_internal_label_value (int label_id);
+void w_as_new_module (int flag);
+void w_as_long_in_data_section (long n);
+void w_as_to_data_section (void);
+void w_as_descriptor_in_code_section (char *label_name);
+void w_as_define_local_label_in_code_section (int label_number);
+void w_as_abc_string_in_code_section (char *string,int length);
+
diff --git a/docommand.c b/docommand.c
new file mode 100644
index 0000000..70de990
--- /dev/null
+++ b/docommand.c
@@ -0,0 +1,16 @@
+typedef struct clean_string {int length; char chars [1]; } *CleanString;
+
+# define Clean(ignore)
+# include "docommand.h"
+/*
+ Clean string
+ ============
+*/
+
+extern int do_command (char *command);
+
+int
+DoCommandNullTerminated (CleanString command)
+{
+ return (do_command (command->chars));
+} /* DoCommandNullTerminated */
diff --git a/docommand.h b/docommand.h
new file mode 100644
index 0000000..af05aa0
--- /dev/null
+++ b/docommand.h
@@ -0,0 +1,12 @@
+#pragma export on
+
+Clean (:: *DoCommandEnvironment :== Int)
+/* Clean (DoCommand command :== DoCommandNullTerminated (command +++ "\0")) */
+
+Clean (DoCommandNullTerminated :: String DoCommandEnvironment -> (Int, DoCommandEnvironment))
+
+/* functions */
+int DoCommandNullTerminated (CleanString command);
+Clean (DoCommandNullTerminated :: String DoCommandEnvironment -> (Int, DoCommandEnvironment))
+
+#pragma export off