/* EPC Imp to C Translation Release 4 Version Apr 95 */ #include "imptoc.h" /** 07Apr97 p5rprocs4 */ /** Change at case NEWPOSN: of manipulateFS() to accommodate I*8 (CMcP)*/ /** 07Jan97 p5rprocs3 */ /** Tidies & flattened for translation to C */ /** 30Oct96 p5procs2.4 */ /** Added CheckRegKeyandExt for GPT */ /** 15Jly96 p5rprocs2.3 */ /** Added call of checkregconflict in claimreg etc */ /** 03Jly96 p5rprocs2.2 */ /** Added fn coutunclaimedregs */ /** 18Apr96 p5rprocs2.1 */ /** Added Rreinitialise */ /** Extended claim reg to dump bottom of Estack first */ /** 07Apr94 p5rprocs2.i */ /** Ensure eptrs are cleared by clean registers */ /** Added clear leaf call regs and release leaf call regs */ /** 10/10/93 - pilot version for PENTIUM */ /** This is derived from rprocs2.5 but PENTIUM is so odd that */ /** a P5 dependent module is required and conditional code for */ /** SPARC RS6000 & M88K has been deleted */ /** Discard fixup added after finding out how F77 implements pointers!*/ /***/ #define modulename ("rprocs") /***/ /**************************************************************************/ /** **/ /** Module Imports **/ /** **/ /**************************************************************************/ /***/ #include "cgtarget.h" /***/ #include "cgconsts.h" /***/ #include "boconsts.h" /***/ #include "archdefs.h" /***/ /*%INCLUDE "archrvars.inc" */ /***/ /***/ /**************************************************************************/ /** **/ /** global specs **/ /** **/ /**************************************************************************/ /***/ /***/ /***/ #if(Target==PENTIUM) #define targetrlit p5rlit extern void targetrlit( int ,int ,int ,int ); #define targetloadlit p5loadlit extern void targetloadlit( int ,int ); #define targetloadri p5loadri extern void targetloadri( int ,int ,int ,int ); #define targetstorei p5storeri extern void targetstorei( int ,int ,int ,int ); #define targetcopyireg p5copyireg extern void targetcopyireg( int ,int ); #define targettempspace p5tempspace extern int targettempspace( int ,int ); #define targetfopr p5fopr extern void targetfopr( int ,int ); #define targetoponly p5oponly extern void targetoponly( int ,int ,int ); #endif; /***/ /***/ extern void Stkdir( struct Stkfmt *,int ,int ); extern void Stkreg( struct Stkfmt *,int ,int ); extern void Stkfreg( struct Stkfmt *,int ,int ); extern void Gladir( struct Stkfmt *,int ,int ); extern void puthex( int ,int ); extern char * htos( int ,int ); #define targetmalloc p5malloc extern int targetmalloc( int ); #define ByteFill s_bfill extern void ByteFill( int ,int ,int ); /***/ extern struct Stkfmt Stk [Stklimit+1]; extern int CallLevel; extern int Pic; extern int Elevel; /***/ extern int RegClaimMaskA; extern int RegClaimMaskB; extern int QCIResMask; extern int QCFResMask; /***/ extern int Regvaropt; extern int diagnostics; extern int setdbx; extern int cgoptions; #define CHKOFLOW (0x200000) /* bit for soft overflow checking */ extern int Report; /***/ /***/ extern int Mmarker( void ); extern void Mabort( int ); /***/ #if(Language==PASCAL) extern int CPartWord( struct Stkfmt *); #endif; /***/ extern int Cstoreop( struct Stkfmt *,struct Stkfmt *,int ); /***/ extern char * egivename( int ); extern int FirstTarget; /***/ /***/ /**************************************************************************/ /** **/ /** local specs **/ /** **/ /**************************************************************************/ /***/ void releasecallregs( void ); void rclearcallregs( void ); void releasereg( int ); static void releaseregpair( int ); void notereguse( int ,int ,int ); void lockreg( int ); void lockregpair( int ); void unlockreg( int ); void unlockregpair( int ); int claimnamedreg( int ); int claimnamedtgt( int ); int claimnamedtgtpair( int ); void SetReguse( int ,int ,int ,int ,int ); int CheckRegKey( int ,int ,int ,int ,int ); int CheckFregKey( int ,int ,int ,int ); /***/ /**********************************************************/ /** constants local to register management **/ /**********************************************************/ /***/ /***/ static char * Eform [31+1] = { "LitVal ","ConstVal ", "RegVal ","FregVal ", "TempVal ","DirVal ","IndRegVal ", "IndTempVal ", "IndDirVal ","ConstAddr ","AddrDir ", "RegAddr ", "TempAddr ","DirAddr ","AddrDirMod ", "RegModAddr ", "TempModAddr ","DirModAddr ","IndRegModVal ", "IndTempModVal ", "IndDirModVal ","AddrDirModVal ","RegBitAddr ", "RegBitModAddr ", "IndDispModVal ","AddrDispModVal","DispModAddr ", "RegVar ", "FregVar ","FlitVal ","DirBitModAddr ", " " }; static char * EType [MaxType+1+1] = { "Unknown ","Signed ", "Real ","Unsigned", "Set ","Mis'Real","Struct ","Mis Int ", "MisUint ","Invalid "}; static char * ReguseForm [DISPLAYV+1] = { " Unknown ", " DATA AT "," CNST AT "," ADDR OF ", " HGH ADR "," INDDATA "," SCALE 1 "," SCALE 2 ", " SCALE 3 "," IND MOD "," LIT VAL "," IND REG ", " SCLRV 1 "," SCLRV 2 "," SCLRV 3 "," PARAMV ", " DISPLYI "," DISPLYV "}; /***/ /***/ /***/ struct RuseFmt{ signed char use; signed char size; short int spare; int primdata; int secdata; }; struct reginfoFmt{ unsigned char status; unsigned char cnt; signed char pair; signed char Eptrs [7]; signed char ext; signed char altext; struct RuseFmt main; struct RuseFmt alt; }; static struct reginfoFmt reginfo [REGCEILING+1]; /**/ /* NB The size field in the use field refers to the size of the remembered item*/ /* To find the size of the eitem one must go viat eptr to the Estack */ /* otherwise loading a byte and extending it changes the regmemory incorrectly*/ /**/ /**/ /* status defines claimed permlocked or locked as below */ /**/ #define PERMLOCKED 240 #define USERLOCKED 220 #define claimed 1 /* up to 4 and also indexes Eptrs */ #define free 0 static int CurrCCfield=5; /***/ /***/ /***/ /**********************************************************/ /** constants local to Recording Fixups **/ /**********************************************************/ /***/ #define FixupsInfoSize (0x8000) /*32K - Malloc space required */ #define NoteFixupsSize 2048 /* 2K */ #define MaxEntries 3840 /*max num of recordable fixups*/ #define MaxGlaOffset (0xFFFC) /*max recordable GLA offset */ #define MaxAreaId 254 /*max recordable Area Id */ struct Fixupsfmt{ int Offset /*and Tgt Area*/; int TgtOffset; }; /***/ /***/ /***/ /**********************************************************/ /** globals local to Recording Fixups **/ /**********************************************************/ /***/ static int CurMaxEntries=0; static int CurMaxGlaOffset=0; static int FixupsInfoAdr=0; static struct Fixupsfmt *Fixups; static double *FixupsInfo; static int *NoteFixups; /***/ /**************************************************************/ /** globals for Recording Stack Store Instructions for SPARC **/ /**************************************************************/ /***/ int currentFSP=16; static int usedregset; static int usedfpregset; unsigned char StackSTflags [256+1]; /*Records how the stack locations have been accessed:*/ /* Bit 0 - store flag */ /* Bit 1 - load flag */ /* Bit 2 - address taken flag */ /***/ /*****************************************************************************/ /** initialisation **/ /*****************************************************************************/ /***/ /***/ void Rinitialise() { /***************************************************/ /** called by Cinitialise for initialisation **/ /** specific to the included register allocation **/ /** and tracking code **/ /***************************************************/ /**/ FixupsInfoAdr=targetmalloc(FixupsInfoSize); NoteFixups=((int *)(FixupsInfoAdr)); Fixups=(struct Fixupsfmt*)((struct Fixupsfmt *)(FixupsInfoAdr+NoteFixupsSize)); FixupsInfo=((double *)(FixupsInfoAdr+NoteFixupsSize)); ByteFill((int)&NoteFixups [0],NoteFixupsSize,0); #if(Target==SPARC) { int i; for (i=0; i<=256; i++) { StackSTflags [i]=0; } } #endif; /**/ /* lock permanently used regs */ /**/ if (Pic!=0) reginfo [GOTREG].status=PERMLOCKED; reginfo [FRAMEPOINTER].status=PERMLOCKED; reginfo [STACKPOINTER].status=PERMLOCKED; #if(Target==RS6) reginfo [2].status=PERMLOCKED; #endif; /* Toc reg */ } /* Rinitialise */ void RReinitialise() { /***************************************************/ /** called by CReinitialise */ /***************************************************/ FixupsInfoAdr=targetmalloc(FixupsInfoSize); NoteFixups=((int *)(FixupsInfoAdr)); Fixups=(struct Fixupsfmt*)((struct Fixupsfmt *)(FixupsInfoAdr+NoteFixupsSize)); FixupsInfo=((double *)(FixupsInfoAdr+NoteFixupsSize)); ByteFill((int)&NoteFixups [0],NoteFixupsSize,0); } /***/ /*****************************************************************************/ /** SPARC specific routines **/ /*****************************************************************************/ void RInitregAllocation() { /*************************************************************************/ /** called by Cstartproc and Csideentry on SPARC to initialise the **/ /** register allocation strategy. FORTRAN has different register **/ /** allocation strategies depending on the level of optimisation. **/ /*************************************************************************/ if (Language==CCOMP || Regvaropt==0) { /* Highfreg=Largefregset - 1 */ /* Highfregpair=Largefregpairset - 1 */ /* Cfregs mask=0 */ /*=> no fregs are optimiser allocated */ } else { /* Highfreg=Smallfregset - 1 */ /* Highfregpair=Smallfregpairset - 1 */ /* Cfregs mask=Cfregs mask const */ } } /* R Initreg Allocation */ /*****************************************************************************/ /** End of SPARC specific routines **/ /*****************************************************************************/ /*****************************************************************************/ /** Fixup memory administration **/ /*****************************************************************************/ /***/ static int ScanFixups(int Offset) { /*************************************************************************/ /** Returns the Index into the array Fixups which corresponds nearest **/ /** to Offset (in GLA) **/ /*************************************************************************/ double x,y,z; int Ptr,MaxPtr,Info,wordOffset; /*****************************************************/ /* Select a Starting Point for Search of Information**/ /*****************************************************/ /**/ x=(double)Offset; y=(double)CurMaxEntries; z=(double)CurMaxGlaOffset; Ptr=((int)(((x*y) / z))); if (Ptr>0) Ptr--; /*****************************************************/ /* Scan Recorded Fixup Information **/ /*****************************************************/ /**/ MaxPtr=CurMaxEntries-1; wordOffset=(unsigned)Offset>>2; Info=(wordOffset<<8)|0xFF; while ((Ptr>=0)&&(InfoFixups [Ptr+1].Offset)) Ptr++; return Ptr; } /* Scan Fixups */ /***/ int CheckFixups(int Area,int Offset,int *TgtArea,int *TgtOffset) { /*************************************************************************/ /** Checks known Fixup information at BASE and OFFSET. Currently only **/ /** fixups in GLA are recorded **/ /** **/ /** Returns 0 for Failure **/ /** Returns 1 for Success and sets TGT AREA and TGT OFFSET **/ /*************************************************************************/ int wordOffset,NoteFixupmask,Info,Ptr; /*****************************************************/ /* Check Limits **/ /*****************************************************/ /**/ if ((Area!=GLA)||(CurMaxEntries==0)||(Offset>CurMaxGlaOffset)||(Offset<0)) { return 0; } /*****************************************************/ /* Check if Information Exists **/ /*****************************************************/ /**/ wordOffset=(unsigned)Offset>>2; NoteFixupmask=1<<(wordOffset&0x1F); if ((NoteFixups [(unsigned)wordOffset>>5]&NoteFixupmask)==0) { return 0; } /*****************************************************/ /* Scan Recorded Fixup Information **/ /*****************************************************/ /**/ Ptr=ScanFixups(Offset); Info=Fixups [Ptr].Offset; /*****************************************************/ /* Return Recorded Information **/ /*****************************************************/ /**/ if (((unsigned)Info>>8)!=wordOffset) { return 0; /*(strange - we should have found something) */ } if ((Info&0xFF)==255) return 0; /* Fixup has been discarde */ *TgtArea=Info&0xFF; *TgtOffset=Fixups [Ptr].TgtOffset; return 1; } /* Check Fixups */ /***/ void crecordfixup(int Area,int Offset,int TgtArea,int TgtOffset) { /*************************************************************************/ /** Records Fixup Information for use by CHECK FIXUPS **/ /*************************************************************************/ int wordOffset,NoteFixupsmask,Ptr,i; /*****************************************************/ /* Check Limits **/ /*****************************************************/ /**/ if ((Area!=GLA)||(TgtArea<=CODE)||(TgtArea>MaxAreaId)||(Offset>MaxGlaOffset)||(Offset<0)||(CurMaxEntries >=MaxEntries)) return ; if (Offset=Ptr; i--) { FixupsInfo [i+1]=FixupsInfo [i]; } } else { /*****************************************************/ /* Prepare to Append New Information **/ /*****************************************************/ /**/ Ptr=CurMaxEntries; CurMaxGlaOffset=Offset; } /**/ wordOffset=(unsigned)Offset>>2; Fixups [Ptr].Offset=(wordOffset<<8)|TgtArea; Fixups [Ptr].TgtOffset=TgtOffset; CurMaxEntries++; /*****************************************************/ /* Update Information Known **/ /*****************************************************/ /**/ i=(unsigned)wordOffset>>5; NoteFixupsmask=1<<(wordOffset&0x1F); NoteFixups [i]=NoteFixups [i]|NoteFixupsmask; } /* C Record Fixup */ /***/ void CDiscardFixup(int Area,int Offset) { /*************************************************************************/ /** A STORE INTO AREA & OFFSET HAS BEEN MADE. IF THERE WAS ANY FIXUP **/ /** info ASSOCIATED WITH THIS ADDRESS DISCARD IT **/ /*************************************************************************/ int wordOffset,NoteFixupmask,Info,Ptr; /*****************************************************/ /* Check Limits **/ /*****************************************************/ /**/ if ((Area!=GLA)||(CurMaxEntries==0)||(Offset>CurMaxGlaOffset)||(Offset<0)) { return ; } /*****************************************************/ /* Check if Information Exists **/ /*****************************************************/ /**/ wordOffset=(unsigned)Offset>>2; NoteFixupmask=1<<(wordOffset&0x1F); if ((NoteFixups [(unsigned)wordOffset>>5]&NoteFixupmask)==0) { return ; } /*****************************************************/ /* Scan Recorded Fixup Information **/ /*****************************************************/ /**/ Ptr=ScanFixups(Offset); Info=Fixups [Ptr].Offset; if (((unsigned)Info>>8)!=wordOffset) return ; Fixups [Ptr].Offset=Fixups [Ptr].Offset|255; /* Mark as invalid */ } /* C Discard Fixup*/ /***/ /*****************************************************************************/ /** register administration **/ /*****************************************************************************/ /***/ void rclearregs(int mode) { /*************************************************************************/ /** clear memory of all register use info - normally at proc entry **/ /** also (pro tem) at labels mode #0 **/ /*************************************************************************/ int I; struct reginfoFmt *reginf; for (I=0; I<=REGCEILING; I++) { reginf=®info [I]; if (reginf->statusmain,0,sizeof( struct RuseFmt)); memset(®inf->alt,0,sizeof( struct RuseFmt)); reginf->cnt=128; } } CurrCCfield=5; /* so 6 & 7 used first */ if ((Target==RS6)&&(mode==0)) { /* new proc */ usedregset=0x1FF8; /* 3-12 */ usedfpregset=0x3FFF; /*0-13 */ } } /* R clear regs */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void rclearleafcallregs(int proctype) { /**************************************************************************/ /** %IF proctype=1 (integer leaf routine) clear only integer regs **/ /** otherwise behave as R clear call regs (qv) **/ /**************************************************************************/ int reg,use; static const int SAVEDREGS=CALLEESAVEDREGS; struct reginfoFmt *reginf; if (proctype!=1) { rclearcallregs(); return ; } for (reg=0; reg<=FRBASE-1; reg++) { reginf=®info [reg]; use=reginf->main.use; if (reginf->status==0) { if (use<=0 || VolatileMem [use-(DATAAT)]!=0 || ((1<alt.use!=0 && ((1<alt.use-(DATAAT)]==0)) { reginf->main=reginf->alt; reginf->ext=reginf->altext; } else { memset(®inf->main,0,sizeof( struct RuseFmt)); reginf->ext=REGUNEXTENDED; } reginf->cnt=128; reginf->pair=0; memset(®inf->alt,0,sizeof( struct RuseFmt)); } } } } /*R clear leafcall regs*/ void rclearcallregs() { /**************************************************************************/ /** Clear memory of all registers except those tied to E-stack entries - **/ /** normally called after return from a procedure call. **/ /** SPARC: Note that fregs and global registers should never be locked **/ /** across a call as they are volatile. **/ /**************************************************************************/ int reg,use; struct reginfoFmt *reginf; rclearleafcallregs(1); /* Deal with integer regs */ for (reg=FIRSTFREG; reg<=LASTFREG; reg++) { reginf=®info [reg]; use=reginf->main.use; if (reginf->status==0) { if (use<=0 || VolatileMem [use-(DATAAT)]!=0 || reg<=HIGHVOLFREG) { if (use!=0 && reginf->alt.use!=0 && reg>HIGHVOLFREG && VolatileMem [reginf->alt.use-(DATAAT)]!=0) { reginf->main=reginf->alt; reginf->ext=reginf->altext; } else { memset(®inf->main,0,sizeof( struct RuseFmt)); reginf->ext=REGUNEXTENDED; } reginf->cnt=128; reginf->pair=0; memset(®inf->alt,0,sizeof( struct RuseFmt)); } } } } /* R clear call regs */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void rClearTracking() { /*************************************************************************/ /** clear memory of all register use info except for locked registers **/ /** and non-volatile tracking memories - normally called after bit **/ /** twiddling operations **/ /*************************************************************************/ int reg,use; struct reginfoFmt *reginf; for (reg=0; reg<=REGCEILING; reg++) { reginf=®info [reg]; use=reginf->main.use; if (use>0) { if (VolatileMem [use-(DATAAT)]!=0) { memset(®inf->main,0,sizeof( struct RuseFmt)); memset(®inf->alt,0,sizeof( struct RuseFmt)); reginf->cnt=128; reginf->pair=0; reginf->ext=0; reginf->altext=0; } if (VolatileMem [reginf->alt.use-(DATAAT)]!=0) memset(®info [reg].alt,0,sizeof( struct RuseFmt) ); } } } /*rClearTracking*/ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ int GetExtFlag(int Reg) { /****************************************************************/ /** Gets the status of the extension type for the given **/ /** register. This gives the type of width extension that has **/ /** been applied to the register. Only registers with actual **/ /** contents may be marked as extended. **/ /****************************************************************/ int exten; struct reginfoFmt *reginf; reginf=®info [Reg]; if (reginf->status>0) return reginf->ext; if (reginf->main.use!=0) { exten=reginf->ext; if ((reginf->alt.use==0)||(reginf->main.size<4)||(exten==REGSIGNEDEXT)||(exten==REGUNSIGNEDEXT)) { return exten; } else { return reginf->altext; } } else { return REGUNEXTENDED; } } /* GetExtFlag */ /***/ void SetExtFlag(int Reg,int Value) { /****************************************************************/ /** Marks the given register has having been width extended. **/ /** By default, registers are marked as unextended. **/ /****************************************************************/ struct reginfoFmt *reginf; reginf=®info [Reg]; reginf->ext=Value; if ((reginf->main.use!=0)&&(reginf->alt.use!=0)) { reginf->altext=Value; if (reginf->main.sizealt.size) memset(®inf->alt,0,sizeof( struct RuseFmt)); } } /* SetExtFlag */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ static void outuse(int ext,int reg,struct RuseFmt *ruse) { /*************************************************************************/ /** turns the use record to human readable form */ /*************************************************************************/ int J,K1,K2,regwidth,disp; J=ruse->use; printf(ReguseForm [J]); K1=ruse->primdata; K2=ruse->secdata; regwidth=ruse->size; if (J!=0) { if (J<=SCALE3) { if (K2>=0) printf(egivename(K2)); else puthex(K2,0); if (K1<0) { printf("-"); puthex(-K1,0); } else { printf("+"); puthex(K1,0); } } else if (J==INDMODDT) { printf("("); if (K2>=0) printf(egivename(K2)); else puthex(K2,0); disp=K1&0xFFF; if (K1<0) { K1=-(((unsigned)K1>>12)|0xFFFFF000); printf("-"); } else { K1=(unsigned)K1>>12; printf("+"); } puthex(K1,0); printf(")+"); puthex(disp,0); } else if (J==CONSTINT) { printf("0x%8X",K1); } else if (J==INDREGDT) { printf("%s",regtext [K2]); if (K1<0) { printf("-"); puthex(-K1,0); } else if (K1!=0) { printf("+"); puthex(K1,0); } } else if ((SCALERV1<=J)&&(J<=SCALERV3)) { printf("%s",regtext [K2]); } else if (J==PARAMV) { printf("%5d",K1); } else if (J==DISPLAYI) { printf("%5d",K2); /* %if J = displayv */ } else { printf("Lev"); printf("%2d",K2); printf("%6d",K1); } } if ((regwidth<4)&&(reginfo [reg].ext!=REGUNEXTENDED)) { if (reginfo [reg].ext==REGSIGNEDEXT) { printf(" [SEXT]"); } else if (reginfo [reg].ext==REGUNSIGNEDEXT) { printf(" [UEXT]"); } else { printf(" [EXT]"); } } if ((regwidth!=0)&&(regwidth!=4)) { printf(" SIZE:%1d",regwidth); } } static void DumpRegs() { /**********************************************************************/ /* Dump the contents of all the integer and floating point registers **/ /**********************************************************************/ int J,I,reg; struct reginfoFmt *reginf; for (reg=0; reg<=REGCEILING; reg++) { reginf=®info [reg]; J=reginf->status; if (J==0 && (reginf->main.use|reginf->alt.use)==0) continue ; if (J==PERMLOCKED && ((1<0) { printf(" CLAIMED "); } else { printf(" (%2x) ",reginfo [reg].cnt); } if ((0Eptrs [I-1]); printf(";"); } if ((reginf->main.use!=0)||(reginf->ext!=0)) outuse(reginf->ext,reg,®inf->main); if (reginf->alt.use!=0) { printf(" (ALT: "); outuse(reginf->altext,reg,®inf->alt); printf(") "); } if (reginf->pair!=0) { if (reginf->pair==1) printf(" [1/2]"); else if (reginf->pair==2) printf(" [2/2]"); else printf(" [???]"); } printf("\n"); } printf("current FSP=%2d\n",currentFSP); } /* Dump Regs */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ static void Pform(int Form,int Reg,int Base,int Offset,int intval,struct Stkfmt *E) { /**********************************************/ /* Print the form of an E-stack entry **/ /**********************************************/ char TempString [17] ; int Index,TempChar; Form&=31; strcpy(TempString,Eform [Form]); for (Index=1; Index<=(int)strlen(TempString); Index++) { TempChar=TempString[Index-1]; printf("%c",TempChar); if (TempChar==32) break ; } printf(" "); if (IsRegForm [Form]!=0) { if (Report!=0) { printf("%s ",regtext [Reg]); } } else if (Form==LitVal) { printf("%1d",intval); printf(" "); } else if (Form==Flitval) { printf("0x"); if (E->Size==4) printf("%8X",(*(int *)((int)&E->Rval))); else { printf("%8X",(*(int *)((int)&E->Rlval))); printf("%8X",(*(int *)((int)&E->Rlval+4))); } printf(" "); } else { printf(egivename(Base)); if (Offset<0) { printf("-"); Offset=-Offset; } else { printf("+"); } puthex(Offset,0); printf(" "); } } /* Pform */ /***/ void ShowEntry(int I,struct Stkfmt *E) { /******************************************************************/ /* This prints out nicely an Estack record call with i=-1 if not **/ /* from the E-stack dumper **/ /******************************************************************/ if (I>0) { printf("%2d:",I); } else { printf("?:"); } Pform(E->Form,E->Reg,E->Base,E->Offset,E->Intvalue,E); if (((E->Form&31)==FregVal)&&(E->Imagreg>=FRBASE)) { printf("&%s)",regtext [E->Imagreg]); } if ((Regvar>(int)(E->Form&31))&&((int)(E->Form&31)>=AddrDirMod)) { printf(" MOD BY:"); Pform(E->Modform,E->Modreg,E->ModBase,E->Modoffset,E->Modintval,E); if (E->Scale>1) printf("SCALED BY:%1d ",E->Scale); } if (E->Cmval!=0) printf(" +%2d ",E->Cmval); printf("TYPE:"); if (E->Type<=StructType) { printf(EType [E->Type]); } else { printf("%s(%1d) ",EType [StructType+1],E->Type); } printf(" SIZE:%1d",E->Size); #if (Language==PASCAL) if (CPartWord(E)!=0) { printf(" %s OFFSET",Eform [E->Modform&31]); if (E->Modform==RegBitModAddr) { if (Report!=0) printf(" Reg:%s",regtext [E->Modreg]); } else { printf(":%3d",E->Modoffset); } printf(" BITS:%3d",E->BitSize); } #endif if (E->AdId!=0) { int i,len; len=(unsigned char )E->AdId [0]; if (len<32) { printf(" HLid="); for (i=1; i<=len; i++) printf("%c",E->AdId[i]); } else printf(" HLid=%s",E->AdId); } if ((E->Flags&STKVOL)!=0) printf(" [volatile]"); if ((E->Flags&STKCONST)!=0) printf(" [constant]"); if ((E->Flags&STKSWOPPED)!=0) printf(" [swopped]"); if ((E->Flags&STKBSSWOPPED)!=0) printf(" [Base swopped]"); printf("\n"); } /* show entry */ /***/ void Cdumpestack() { /***********************************************/ /* Prints the current contents of the E-stack **/ /***********************************************/ struct Stkfmt *E; int I; if (Report!=0) DumpRegs(); if (Elevel>0) { printf("\nE-STACK:\n"); I=Elevel; while (I>0) { E=&Stk[I]; ShowEntry(I,E); I--; } } } /* C dumpestack */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void CheckConflict(int Base,int Offset,int Size) { /*****************************************************************************/ /** locates any DATAAT register memory which lies within the range: **/ /** Offset<= regdata< Offset+Size **/ /** or regdata<= Offset< regdata +4 (or +8 if Size=8) **/ /** and resets the memory of the associated register provided that both **/ /** Offset and regdata apply to the same base. **/ /*****************************************************************************/ int Info,AltInfo,reg,use,altuse; struct reginfoFmt *reginf; /***/ int datasize; for (reg=0; reg<=REGCEILING; reg++) { reginf=®info [reg]; datasize=reginf->main.size; altuse=reginf->alt.use; if ((altuse>0)&&(VolatileMem [altuse-(DATAAT)]!=0)) { AltInfo=reginf->alt.primdata; if (((reginf->alt.secdata==Base)&&(((Offset<=AltInfo)&&(AltInfo<(Offset+Size)))||((AltInfo<=Offset)&&(Offset <(AltInfo+reginf->alt.size)))))||(altuse==INDDATA)||(altuse==INDMODDT)||(altuse==INDREGDT)) /*%and Base>10*/ /*Cnsts*/{ memset(®inf->alt,0,sizeof( struct RuseFmt)); } } use=reginf->main.use; if (((DATAAT<=use)&&(use<=SCALERV3))&&(VolatileMem [use-(DATAAT)]!=0)) { Info=reginf->main.primdata; if (((reginf->main.secdata==Base)&&(((Offset<=Info)&&(Info<(Offset+Size)))||((Info<=Offset)&&(Offset <(Info+datasize)))))||(use==INDDATA)||(use==INDMODDT)||(use==INDREGDT)) /*%and Base>10*/ /*Cnsts*/{ memset(®inf->main,0,sizeof( struct RuseFmt)); if (reginf->alt.use!=0) { reginf->main=reginf->alt; reginf->ext=reginf->altext; memset(®inf->alt,0,sizeof( struct RuseFmt)); } } } } /**/ } /* Check Conflict */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void checkregconflict(int Reg) { /*****************************************************************************/ /* Makes any necessary changes to the register memory given that the **/ /* register Reg has been written to. **/ /** Upgraded for reg-reg data where the base is in secdata and the scale **/ /** and index is in primdata with the sign bit set to distinguish from **/ /** literal positive offsets **/ /*****************************************************************************/ int CheckReg,use; struct reginfoFmt *reginf; if (Regalt.use)&&(reginf->alt.use<=SCALERV3))&&((reginf->alt.secdata==Reg)||((reginf ->alt.primdata<0)&&((((unsigned)reginf->alt.primdata>>24)&15)==Reg)))&&(reginf->main.use!=0)) { memset(®inf->alt,0,sizeof( struct RuseFmt)); } use=reginf->main.use; if (((INDREGDT<=use)&&(use<=SCALERV3))&&(((reginf->main.secdata&31)==Reg)||((reginf->main.primdata< 0) &&((((unsigned)reginf->main.primdata>>24)&15)==Reg)))) { memset(®inf->main,0,sizeof( struct RuseFmt)); if (reginf->alt.use!=0) { reginf->main=reginf->alt; reginf->ext=reginf->altext; memset(®inf->alt,0,sizeof( struct RuseFmt)); } } } } } /*check reg conflict */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void CheckIndConflict(struct Stkfmt *Stk) { /****************************************************************/ /** Checks known information following an indirect update of **/ /** store and discards any register known to be affected. If **/ /** no information is available then all volatile memory **/ /** (except FORTRAN DATAAT parameter memory) is erased. **/ /****************************************************************/ int Size,Form,I,reg,use,altuse,TgtArea,TgtOffset; struct reginfoFmt *reginf; Size=Stk->Size; I=CheckFixups(Stk->Base,Stk->Offset,&TgtArea,&TgtOffset); if (I!=0) { /**/ /* we know where the pointer points to from fixup tables */ /**/ Form=Stk->Form&31; if (((IndRegModVal<=Form)&&(Form<=IndDirModVal))&&(Stk->Modform==LitVal)) { TgtOffset+=Stk->Modintval; } else if (Form!=IndDirVal) { if (TgtOffset<0) Size=0x7FFFFFFF; else Size=0x7FFFFFFF-TgtOffset; } CheckConflict(TgtArea,TgtOffset,Size); } else { /**/ /* You dont know much said the Red Queen, and thats a fact (Lewis Carrol) */ /* However we do know:- */ /* 1) Fortran Parameters are supposed to be independent */ /* 2) Read only areas cant be updated by an indirect store */ /* 3) Parameters that are pointer can not point at the local stack frame */ /**/ for (reg=0; reg<=REGCEILING; reg++) { reginf=®info [reg]; altuse=reginf->alt.use; if ((altuse!=0)&&(VolatileMem [altuse-(DATAAT)]!=0)) { if (!(((Language==FORTRAN)&&(reginf->alt.secdata==PARAMS)&&(altuse==DATAAT))||(reginf->alt.secdata==CNST )||((Stk->Base==PARAMS)&&(reginf->alt.secdata==STACK)))) { reginf->alt.use=0; } } use=reginf->main.use; if ((use>0)&&(VolatileMem [use-(DATAAT)]!=0)) { if (!(((Language==FORTRAN)&&(reginf->main.secdata==PARAMS)&&(use==DATAAT))||(reginf->main.secdata==CNST )||((Stk->Base==PARAMS)&&(reginf->main.secdata==STACK)))) { memset(®inf->main,0,sizeof( struct RuseFmt)); if (reginf->alt.use!=0) { reginf->main=reginf->alt; reginf->ext=reginf->altext; memset(®inf->alt,0,sizeof( struct RuseFmt)); } } } } } } /* Check IndConflict */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ static void MoveToaltreguse(int Reg) { /***********************************************************************/ /* Moves the current reguse register memory for the given register to **/ /* altreguse if possible. **/ /***********************************************************************/ int use; struct reginfoFmt *reginf; reginf=®info [Reg]; use=reginf->main.use; if (use>0) { reginf->alt=reginf->main; reginf->altext=reginf->ext; } } /* MoveToAltreguse */ /***/ /**/ /* Here follow the new register locking and memory routines. */ /* The new routines differ from the old in that locking (_status) and */ /* memory(_use) are separated and handled by different routines. */ /* The old style use multiplexed memory and locking information which made */ /* the implementation very knotted. The new one is simple but there are */ /* places where code generators will need to make two calls in place of one. */ /**/ void lockregister(int reg,int eitem,int size) { /*************************************************************************/ /** Locks a register without changing its memory. Can hanled pairs if **/ /** size=8 and reg is 32 bit. Locks can nest. **/ /*************************************************************************/ struct reginfoFmt *reginf,*reg1inf; struct Stkfmt *Lstk; int reg1,form; reginf=®info [reg]; if (reginf->status>=USERLOCKED) return ; if ((1<=eitem)&&(eitem<=Stklimit)) { /**/ /* unless the 'thing' is actually in the register, the size of the */ /* register is 4 bytes, as it is a pointer or offset. */ /**/ Lstk=&Stk [eitem]; form=Lstk->Form&31; if (SimpleRegForm [form]==0) size=4; } /* cannot do this reginf_main_size=size */ reginf->pair=0; reginf->status=reginf->status+1; reginf->Eptrs [reginf->status-1]=eitem; if ((reg=8)) { reg1=reg+1; reg1inf=®info [reg1]; /* cannot do this reginf_main_size=4 */ /* cannot do this reg1inf_main_size=4 */ reginf->pair=1; reg1inf->pair=2; reg1inf->status=reg1inf->status+1; reg1inf->Eptrs [reg1inf->status-1]=eitem; } } /* Lock register */ void unlockregister(int reg) { /*************************************************************************/ /** Unlocks a register. Can handle pairs **/ /*************************************************************************/ struct reginfoFmt *reginf,*reg1inf; int reg1; reginf=®info [reg]; if (reginf->status>=USERLOCKED) return ; if (reginf->status>0) reginf->status--; if (reg>=FRBASE ) /* unlocking an freg */{ if (reg!=currentFSP) { printf("Warning: Fstack access to reg %3d when top=%d\n", reg,currentFSP); } if (currentFSP>15) Mabort(977); currentFSP+=1; } if (reginf->pair==1) { reg1=reg+1; reg1inf=®info [reg1]; if (reg1inf->status>0) reg1inf->status--; if ((reginf->status|reg1inf->status)==0) { /*only unpair if unlocked */ reginf->pair=0; reg1inf->pair=0; } } } /* unlock register */ void setregmemory(int reg,int use,int primdata,int secdata,int size,int add) { /*************************************************************************/ /** set the use without changing lockstate. If add=1 old use kept **/ /*************************************************************************/ struct reginfoFmt *reginf; if (Report!=0) { printf("Setting Reg Memory %s %6d %6d %4d \n",ReguseForm [use], primdata,secdata,size); } reginf=®info [reg]; if (reginf->status>=USERLOCKED) return ; if (add==1) MoveToaltreguse(reg); else memset(®inf->alt,0,sizeof( struct RuseFmt)); reginf->main.use=use; reginf->main.size=size; reginf->main.primdata=primdata; reginf->main.secdata=secdata; reginf->ext=REGUNEXTENDED; if (reginf->pair==1) setregmemory(reg+1,use,primdata+4,secdata,size,add); /*1st*/ } /*set reg memory */ void forgetreg(int reg) { /*************************************************************************/ /** destroys the memory but does not touch lockstate */ /*************************************************************************/ struct reginfoFmt *reginf; reginf=®info [reg]; memset(®inf->main,0,sizeof( struct RuseFmt)); memset(®inf->alt,0,sizeof( struct RuseFmt)); if (reginf->statuspair==1) forgetreg(reg+1); /*1st*/ reginf->ext=0; reginf->altext=0; } if (reg0) { *newuse=olduse; } else *lock=-1; /* olduse=0 means forget and unlock */ } /* translate olduse */ void NoteAddReguse(int Reg,int Use,int Size) { /***********************************************************************/ /* Records the usage of the given register. If the given register **/ /* already contains an unstacked value then that is not altered **/ /***********************************************************************/ int newuse,lock,eitem; translateolduse(Use,&newuse,&eitem,&lock); if (lock==1) { if ((USERLOCKED>reginfo [Reg].status)&&(reginfo [Reg].status>0)) unlockregister(Reg); lockregister(Reg,eitem,Size); } } /* Note Add Reguse */ /***/ void notereguse(int Reg,int Use,int Size) { /***********************************************************************/ /* Records the usage of the given register. Any alternative register **/ /* usage is disposed of. **/ /* If Size<0 then the current reg associated size remains unchanged. **/ /***********************************************************************/ int newuse,lock,eitem; translateolduse(Use,&newuse,&eitem,&lock); if (Size<0) Size=reginfo [Reg].main.size; forgetreg(Reg); /*lose previous contents */ if (lock==-1) unlockregister(Reg); if (lock==1) { if ((USERLOCKED>reginfo [Reg].status)&&(reginfo [Reg].status>0)) unlockregister(Reg); lockregister(Reg,eitem,Size); } } /* Note Reguse */ /***/ /**/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void SetAddReguse(int Reg,int Use,int PrimData,int SecData,int Size) { /*************************************************************************/ /** Record the new contents of a register and keep the current **/ /** contents. The register is not unlocked **/ /*************************************************************************/ int newuse,lock,eitem; translateolduse(Use,&newuse,&eitem,&lock); if (lock==1) { if ((USERLOCKED>reginfo [Reg].status)&&(reginfo [Reg].status>0)) unlockregister(Reg); lockregister(Reg,eitem,Size); } setregmemory(Reg,newuse,PrimData,SecData,Size,1); } /* Set Add Reguse */ /***/ void SetReguse(int Reg,int Use,int PrimData,int SecData,int Size) { /*************************************************************************/ /** Record the new contents of a register and erase the old contents **/ /** The register is not unlocked. **/ /*************************************************************************/ int newuse,lock,eitem; translateolduse(Use,&newuse,&eitem,&lock); if (lock==1) { if ((USERLOCKED>reginfo [Reg].status)&&(reginfo [Reg].status>0)) unlockregister(Reg); lockregister(Reg,eitem,Size); } setregmemory(Reg,newuse,PrimData,SecData,Size,0); } /* Set Reguse */ /***/ void lockreg(int Reg) { /**************************************************************************/ /* Locks the given register. If the register is already locked then this **/ /* call is ignored. **/ /**************************************************************************/ struct reginfoFmt *reginf; reginf=®info [Reg]; if (reginf->status==0) lockregister(Reg,0,4); } /* lock reg */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void lockregpair(int Reg) { /*************************************************************************/ /* Locks the given register pair. **/ /*************************************************************************/ struct reginfoFmt *reginf; reginf=®info [Reg]; if (reginf->status==0) lockregister(Reg,0,8); } /* lock reg pair */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void unlockreg(int Reg) { /*************************************************************************/ /* Unlocks the given register. **/ /*************************************************************************/ unlockregister(Reg); } /* unlock reg */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void unlockregpair(int Reg) { /*************************************************************************/ /* Unlocks the given pair of registers. **/ /*************************************************************************/ unlockregister(Reg); /* copes with pairs */ } /* unlock reg pair */ void ResetReguse(int Old,int New) { /***********************************************************************/ /* Changes all registers associated with the Old E-stack entry to be **/ /* associated with the new E-stack entry. **/ /***********************************************************************/ int reg,i,j,alt; struct reginfoFmt *reginf; for (reg=0; reg<=REGCEILING; reg++) { alt=0; reginf=®info [reg]; if ((1<=reginf->status)&&(reginf->status<=4)) { for (i=1; i<=(int)reginf->status; i++) { if (reginf->Eptrs [i-1]==Old) { reginf->Eptrs [i-1]=New; alt=1; } } } while (alt!=0) { /* ensure ptrs are ordered top will be used first */ alt=0; for (i=1; i<=(int)reginf->status-1; i++) { j=reginf->Eptrs [i-1]; if ((j>(int)reginf->Eptrs [i+1-1])&&(reginf->Eptrs [i+1-1]>0)) { reginf->Eptrs [i-1]=reginf->Eptrs [i+1-1]; reginf->Eptrs [i+1-1]=j; alt=1; } } } } } /* Reset Reguse */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void CopyRegMemory(int SReg,int DReg) { /**********************************************************************/ /* Copies the register memory associated with the source register to **/ /* the destination register. The destination register is locked. **/ /**********************************************************************/ int st; struct reginfoFmt *reginf; reginf=®info [DReg]; if (reginf->status>=USERLOCKED) return ; st=reginf->status; *reginf=reginfo [SReg]; /* copy everything */ reginf->status=st; if (reginf->status==0) reginf->status=1; /*lock if unlocked */ /*Eptrs may not be set */ } /* CopyRegMemory */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ int CheckConstantOp(int OpReg1,int *Const1) { /*************************************************************************/ /* Returns 1 if the given register holds a constant value. In **/ /* this case the constant is returned in Const1. **/ /*************************************************************************/ int ruse1; struct reginfoFmt *reginf1; reginf1=®info [OpReg1]; ruse1=reginf1->main.use; if (ruse1==CONSTINT) { *Const1=reginf1->main.primdata; return 1; } else if ((ruse1!=0)&&(reginf1->alt.use==CONSTINT)) { *Const1=reginf1->alt.primdata; return 1; } return 0; } /* CheckConstanop */ /***/ /***/ int CheckConstantOps(int OpReg1,int OpReg2,int *Const1,int *Const2) { /**************************************************************************/ /* Returns 1 if the two given registers both hold constant values. In **/ /* this case the constants are returned in Const1 and Const2. **/ /**************************************************************************/ int ruse1,ruse2; struct reginfoFmt *reginf1,*reginf2; reginf1=®info [OpReg1]; reginf2=®info [OpReg2]; ruse1=reginf1->main.use; ruse2=reginf2->main.use; if (ruse1==CONSTINT) { *Const1=reginf1->main.primdata; if (ruse2==CONSTINT) { *Const2=reginf2->main.primdata; return 1; } if ((ruse2!=0)&&(reginf2->alt.use==CONSTINT)) { *Const2=reginf2->alt.primdata; return 1; } } else if ((ruse1!=0)&&(reginf1->alt.use==CONSTINT)) { *Const1=reginf1->alt.primdata; if (ruse2==CONSTINT) { *Const2=reginf2->main.primdata; return 1; } if ((ruse2!=0)&&(reginfo [OpReg2].alt.use==CONSTINT)) { *Const2=reginfo [OpReg2].alt.primdata; return 1; } } return 0; } /* CheckConstantOps */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ int registerstatus(int reg) { /*************************************************************************/ /** Returns the Status 0=free,1=singly locked >1 multiply locked **/ /*************************************************************************/ return reginfo [reg].status; } void CleanRegister(int Reg,int Bytes) { /**************************************************************************/ /* Clears the register tracking of the given register or register pair **/ /* and returns the register or pair singly locked. **/ /* Note extension flags are not changed to avoid a repeted sign extend **/ /**************************************************************************/ int Reg1,i; struct reginfoFmt *reginf,*reginf1; reginf=®info [Reg]; if ((reginf->status>1)&&(reginf->status!=USERLOCKED)) Mabort(989); memset(®inf->main,0,sizeof( struct RuseFmt)); memset(®inf->alt,0,sizeof( struct RuseFmt)); if (!(reginf->status==USERLOCKED)) reginf->status=1; if ((Reg4)) { reginf->pair=1; /*st*/ Reg1=Reg+1; reginf1=®info [Reg1]; memset(®inf1->main,0,sizeof( struct RuseFmt)); memset(®inf1->alt,0,sizeof( struct RuseFmt)) ; reginf1->pair=2; /*nd*/ } else { reginf->pair=0; } reginf->ext=REGUNEXTENDED; reginf->cnt=128; usedregset|=1<Eptrs [i-1]=0; if (Regstatus=USERLOCKED; memset(®inf->main,0,sizeof( struct RuseFmt)); memset(®inf->alt,0,sizeof( struct RuseFmt)); } void permlockreg(int reg) { /*************************************************************************/ /** Allow the register to be PERMLOCKED. Used by Fortran Complex **/ /** where up to 8 references can follow. Not proof against a call **/ /*************************************************************************/ reginfo [reg].status=PERMLOCKED; } void unlockpermreg(int Reg) { /*************************************************************************/ /** Unlocks a register which has previously been subjected to **/ /** Permlocking. The register is unlocked in such a manner so **/ /** as to preserve it's register memory. **/ /** **/ /** It is designed to unlock an address register being used by **/ /** Fortran Complex stuff. **/ /*************************************************************************/ struct reginfoFmt *reginf; reginf=®info [Reg]; if (reginf->status>=USERLOCKED) { reginf->status=0; /*Register is not PERMLOCKED*/ } else Mabort(78); } /* unlock permreg */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ static int findsafereg() { /****************************************************************************/ /** Locates a preserved register that is not currently in use. This is **/ /** used by release reg to save a value within a temporary register **/ /** rather than spilling to the stack frame. Returns a suitable register **/ /** or -1 if no register was available. **/ /****************************************************************************/ #if(Target==M88K) struct procfmt *PI; #endif; int I,J,reg,cnt,cntreg,cnt1,cntreg1; struct reginfoFmt *reginf; cnt=0; for (I=LOWTREG; I<=HIGHTREG; I++) { reg=Tregs [I]; if (reginfo [reg].status==0) cnt++; } if (cnt<=1) return -1; /* do not allocate only free reg!*/ cnt=-1; cntreg=-1; cnt1=-1; cntreg1=-1; for (I=HIGHVOLTREG+1; I<=HIGHTREG; I++) { reg=Tregs [I]; reginf=®info [reg]; if ((reginf->status==0)&&((RegClaimMaskA&(1<main.use==0)) /*reg>HIGHVOLREG %and*/{ J=reginf->cnt; if (J>cnt) { cnt=J; cntreg=reg; } if ((J>cnt1)&&(((1<0) { cntreg=cntreg1; goto FoundReg; } if (cntreg>=0) goto FoundReg; for (I=HIGHVOLTREG+1; I<=HIGHTREG; I++) { reg=Tregs [I]; reginf=®info [reg]; if ((reginf->status==0)&&((RegClaimMaskA&(1<HIGHVOLREG %and*/{ J=reginf->cnt; if (J>cnt) { cnt=J; cntreg=reg; } } } if (cntreg>=0) goto FoundReg; return -1; /*no suitable register available*/ FoundReg: return cntreg; } /* find safe reg */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ int claimsafereg() { /*************************************************************************/ /** Claims a register that will be preserved across calls **/ /*************************************************************************/ int reg,I; struct reginfoFmt *reginf; reg=findsafereg(); if (reg<0) { for (I=HIGHVOLTREG+1; I<=HIGHTREG; I++) { reg=Tregs [I]; reginf=®info [reg]; if ((reginf->statusHIGHVOLREG %and*/{ releasereg(reg); goto FoundReg; } } Mabort(8); } else reginf=®info [reg]; FoundReg: CleanRegister(reg,4); return reg; } /* claim safe reg */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ static void dorelreg(int Reg,int RelType) { /*************************************************************************/ /** Store the content of general register Reg in temp space, modifying **/ /** Estack entries as necessary **/ /** **/ /** If a volatile register is being released and a safe (preserved) **/ /** register is available, then the volatile register is saved in the **/ /** safe register rather than memory - this mechanism is to cope with **/ /** saving a function result through another function call - **/ /** ie (i*j)+(l*m) **/ /** **/ /** If RelType is non-zero then a safe register may not be used for **/ /** storage of a released register. **/ /** **/ /** M88110: This routine is also responsible for releasing a double **/ /** precision FregVal or Fregvar. **/ /*************************************************************************/ int I,disp,Form,Bytes,Sreg,Imagreg,Imagdisp,Status,Tempsize; struct Stkfmt *Lstk; struct Stkfmt Rstk,Tstk; struct reginfoFmt *reginf,*sreginf; reginf=®info [Reg]; Status=reginf->status; if ((Status!=0)&&(reginf->pair!=0)) { if (reginf->pair==1) /*st*/{ releaseregpair(Reg); } else { releaseregpair(Reg-1); } } else if (Status==0) { return ; } else if (Status>=USERLOCKED) { Mabort(52); /* cannot release a locked register */ } else { Lstk=&Stk [reginf->Eptrs [1-1]]; Form=Lstk->Form&31; Tempsize=Lstk->Size; /* space needed watch diirect complex */ if ((IsIndRegForm [Form]!=0)||((IsModForm [Form]!=0)&&(Lstk->Modreg==Reg))) { Bytes=4; /* we have a pointer */ Tempsize=4; } else if (Reg>=FRBASE) { Bytes=Lstk->Size; if (Lstk->Imagreg!=0) { Bytes=(unsigned)Bytes>>1; /*Bytes now suitable for each Complex part*/ } } else { Bytes=Lstk->Size; } if ((RelType==0)&&(Reg<=HIGHVOLREG)) { Sreg=findsafereg(); if (Sreg>=0) { Sreg=claimnamedreg(Sreg); sreginf=®info [Sreg]; *sreginf=*reginf; targetcopyireg(Reg,Sreg); /**/ reginf->status=0; /**/ /* register(s) now saved so adjust Estack records ay be several */ /**/ for (I=1; I<=Status; I++) { Lstk=&Stk [reginf->Eptrs [I-1]]; if ((IsRegForm [Lstk->Form&31]!=0)&&(Lstk->Reg==Reg)) { Lstk->Reg=Sreg; } else if ((IsModForm [Lstk->Form&31]!=0)&&(IsRegForm [Lstk->Modform&31]!=0)&&(Lstk->Modreg==Reg)) { Lstk->Modreg=Sreg; } else { Mabort(5); } } /*printstring("Estack after relase"); write(Status,2); write(Elevel,2); */ /*cdumpestack; newline */ /**/ return ; } } if (Bytes>16) Mabort(52); /* %IF Reg>=f0REG %THEN Bytes=8 */ if (Tempsize>=8) disp=targettempspace(Tempsize,8); else disp=targettempspace(4,4); if ((Form==FregVal)||(Form==Fregvar)) { if ((Reg!=currentFSP)&&(currentFSP!=Lstk->Imagreg)) Mabort(5); if (Lstk->Imagreg!=0) { Stkdir(&Tstk,disp+Bytes,Bytes); Tstk.Type=Lstk->Type; Stkfreg(&Rstk,Lstk->Imagreg,Bytes); } else { Stkdir(&Tstk,disp,Bytes); Tstk.Type=Lstk->Type; Stkfreg(&Rstk,Reg,Bytes); } Rstk.Type=Tstk.Type; } else { Stkdir(&Tstk,disp,Bytes); Stkreg(&Rstk,Reg,Bytes); } for (I=1; I<=Status; I++) { Lstk=&Stk [reginf->Eptrs [I-1]]; if (((Lstk->Reg==Reg)||((Lstk->Imagreg==Reg)&&(Reg>=FRBASE)))&&(IsRegForm [Form]!=0)) { if (SimpleRegForm [Form]!=0) { Lstk->Form=TempVal; } else { Lstk->Form=Form+1; } Lstk->Base=STACK; Lstk->Offset=Tstk.Offset; /* May have been adjusted for save area */ if ((Lstk->Imagreg==Reg)&&(Reg>=FRBASE)) Lstk->Offset=Tstk.Offset-Bytes; } else if (Lstk->Modreg==Reg) { Form=Lstk->Modform&31; if (SimpleRegForm [Form]!=0) { Lstk->Modform=TempVal; } else if (Form==IndRegVal) { Lstk->Modform=IndTempVal; } else { Mabort(5); } Lstk->Modoffset=Tstk.Offset; /* May have been adjusted for save area */ Lstk->ModBase=STACK; } else Mabort(5); } /**/ /* before we do the save which will unlock reg we must adjust Estack records */ /* there may be several */ /**/ I=Cstoreop(&Tstk,&Rstk,0); reginf->status=0; if ((Bytes>4)&&(Reg=FRBASE)&&(Lstk->Imagreg!=0)) { /************************************************************/ /** Release the Register associated with the Imaginary Part**/ /************************************************************/ /**/ Imagreg=Lstk->Reg; Imagdisp=disp; Stkdir(&Tstk,Imagdisp,Bytes); Tstk.Type=RealType; Stkfreg(&Rstk,Imagreg,Bytes); Tstk.Type=RealType; I=Cstoreop(&Tstk,&Rstk,0); reginfo [Imagreg].status=0; } }; } /* do rel reg */ /***/ void releasereg(int Reg) { /*************************************************************************/ /** Store the content of general integer register Reg in temp space, **/ /** modifying Estack entries as necessary **/ /*************************************************************************/ dorelreg(Reg,0); } /* release reg */ /***/ static void releaseregpair(int Reg) { /*************************************************************************/ /** Store the content of register pair Reg in temp space, modifying **/ /** Estack entries as necessary **/ /*************************************************************************/ int I,disp,Lsize,Status; struct Stkfmt *Lstk; struct Stkfmt Rstk,Tstk; struct reginfoFmt *reginf; reginf=®info [Reg]; Status=reginf->status; if ((Status!=0)&&(reginfo [Reg].pair!=1)) Mabort(51); /*st*/ /*register isn't paired*/ if (Status==0) { return ; } else if (Status>=USERLOCKED) { Mabort(53); /* cannot release a locked register */ } else { Lstk=&Stk [reginf->Eptrs [1-1]]; Lsize=Lstk->Size; if (Lstk->Reg!=Reg) { if ((Lsize!=16)||(Lstk->Imagreg!=Reg)) Mabort(6); releaseregpair(Lstk->Reg); } else { disp=targettempspace(Lsize,8); Stkdir(&Tstk,disp,8); Stkfreg(&Rstk,Reg,8); Rstk.Type=RealType; I=Cstoreop(&Tstk,&Rstk,0); reginf->status=0; reginfo [Reg+1].status=0; SetAddReguse(Reg,DATAAT,disp,STACK,8); if (Lsize==16) { Stkdir(&Tstk,disp+8,8); Stkfreg(&Rstk,Lstk->Imagreg,8); Rstk.Type=RealType; I=Cstoreop(&Tstk,&Rstk,0); reginfo [Lstk->Imagreg].status=0; reginfo [Lstk->Imagreg+1].status=0; } for (I=1; I<=Status; I++) { Lstk=&Stk [reginf->Eptrs [I-1]]; if (Lstk->Reg!=Reg) Mabort(6); Lstk->Form=TempVal; Lstk->Base=STACK; Lstk->Offset=Tstk.Offset; /* May have been adjusted for save area */ } } }; } /* release reg pair */ /***/ void Conditionalreleasereg(int Reg,struct Stkfmt *StkItem) { /*************************************************************************/ /** release Reg unless it is locked to Estack entry StkItem **/ /*************************************************************************/ struct Stkfmt *entry; struct reginfoFmt *reginf; reginf=®info [Reg]; if (reginf->status==1 && 1<=reginf->Eptrs [0] && reginf->Eptrs [0]<=Elevel+3) { /* Reg is locked to Estack entry -I */ entry=&Stk [reginf->Eptrs [0]]; if (entry!=StkItem || SimpleRegForm [entry->Form&31]==0 || entry->Reg!=Reg) { releasereg(Reg); memset(reginf,0,sizeof( struct reginfoFmt)); } } else { releasereg(Reg); memset(reginf,0,sizeof( struct reginfoFmt)); } } /* Conditional release reg */ /***/ void Conditionalreleasefreg(int Reg,struct Stkfmt *StkItem,int Len) { /*************************************************************************/ /** release Reg unless it is locked to Estack entry StkItem */ /*************************************************************************/ struct Stkfmt *entry; struct reginfoFmt *reginf; reginf=®info [Reg]; if (1<=reginf->status && reginf->status<3 && 1<=reginf->Eptrs [0] && reginf->Eptrs [0]<=Elevel) { /* Reg is locked to Estack entry -I */ entry=&Stk [reginf->Eptrs [0]]; if (entry!=StkItem || SimpleRegForm [entry->Form&31]==0 || entry->Reg!=Reg) { releasereg(Reg); } } else { releasereg(Reg); } if (Reg4) { Reg++; reginf=®info [Reg]; if (1<=reginf->status && reginf->status<3 && 1<=reginf->Eptrs [0] && reginf->Eptrs [0]<=Elevel) { /* Reg is locked to Estack entry -I */ entry=&Stk [reginf->Eptrs [0]]; if (entry!=StkItem || SimpleRegForm [entry->Form&31]==0 || entry->Reg!=(Reg-1)) { releasereg(Reg); } } else { releasereg(Reg); } } } /* Conditional release freg */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void freeregs() { /*************************************************************************/ /** This ensures that every register is saved. Every register on the **/ /** EStack is also saved as we use release reg. On the M88K this **/ /** routine also saves all loaded parameters but avoids touching any **/ /** register holding a condition code result. **/ /*************************************************************************/ int r,use; struct reginfoFmt *reginf; for (r=0; r<=29; r++) { /* all int regs on E-stack to be saved - except r30 on M88K */ if (r>=FRBASE) break ; reginf=®info [r]; use=reginf->status; if (use>0 && usestatus; if (use>0 && usestatus && reginf->statusstatus && reginf->statusstatus>0) releasereg(reg); } } /* release call regs */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void allocregvar(int LogReg) { /*******************************************************************/ /** Used to mark a register as allocated to a register variable. **/ /** The optimiser uses this to prevent claim reg or claim freg **/ /** allowing these registers to be used by the code generator **/ /** for other purposes. The (optimiser) logical register number **/ /** is given and the appropriate bit of RegClaimMaskA or **/ /** RegClaimMaskB for the corresponding physical register is set. **/ /*******************************************************************/ int reg; /* Map from optimiser logical to code generator physical */ /* reg=CRegVarMap(LogReg) */ reg=LogReg; /* till mapping decided */ /* Set the bit in the appropriate mask */ if (reg<32) { RegClaimMaskA|=1< 0 if the region of code over which the CSE is **/ /** live is know to contain function calls. **/ /******************************************************************/ int reg,i,regu,selregset; struct reginfoFmt *reginf; if ((Type==IntType)||(Type==UintType)) { /*! %IF (Calls = 0) %THEN high = highreg - 2 %ELSE high = LOWSAVE - 1 */ /*! Temporarily restrict integer CSE regs to the set of preservrd regs */ /*! -- there are more support routines than esup.c knows about. */ regu=-1; selregset=(1< 0 %THEN selregset=selregset&x'7fffffff'&CALLEESAVEREGS*/ for (i=LOWTREG; i<=HIGHTREG; i++) { reg=Tregs [i]; reginf=®info [reg]; if ((reginf->status==0)&&(((1<main.use==0) goto found; if (regu<0) regu=reg; } } if (regu<0) return -1; reg=regu; reginf=®info [reg]; found: forgetreg(reg); checkregconflict(reg); reginf->status=USERLOCKED; RegClaimMaskA|=1<1) topreg=HIGHTREG; cnt=-1; cntreg=-1; cnt1=-1; cntreg1=-1; for (I=LOWTREG; I<=topreg; I++) { reg=Tregs [I]; reginf=®info [reg]; if ((reginf->status==0)&&(reginf->main.use==0)&&((SelRegSet&(1<cnt) { cnt=J; cntreg=reg; } if ((J>cnt1)&&(((1<0) { reg=cntreg1; goto Note; } if (cntreg>=0) { reg=cntreg; goto Note; } /* Look for any unpaired registers with only a constant memory */ for (I=LOWTREG; I<=topreg; I++) { reg=Tregs [I]; reginf=®info [reg]; if ((reginf->status==0)&&(reginf->main.use==CONSTINT)&&((SelRegSet&(1<pair==0) ) { J=reginfo [reg].cnt+1; if (J==256) goto Note; reginfo [reg].cnt=J; if (reginfo [reg].alt.use>0) J-=5; if (J>cnt) { cnt=J; cntreg=reg; } } } if (cntreg>=0) { reg=cntreg; goto Note; } /* tries = 1,1,2*/ } for (tries=1; tries<=2; tries++) { topreg=HIGHVOLTREG; if (tries>1) topreg=HIGHTREG; cnt=-1; cntreg=-1; cnt1=-1; cntreg1=-1; /* Look for any unpaired registers with a current memory */ for (I=LOWTREG; I<=topreg; I++) { reg=Tregs [I]; reginf=®info [reg]; if ((reginf->status==0)&&((SelRegSet&(1<pair==0)) { J=reginfo [reg].cnt+1; if (J==256) goto Note; reginfo [reg].cnt=J; if (reginfo [reg].alt.use>0) J-=5; if (J>cnt) { cnt=J; cntreg=reg; } } } if (cntreg>=0) { reg=cntreg; goto Note; } /* Look for any paired registers with a current memory */ for (I=LOWTREG; I<=topreg; I++) { reg=Tregs [I]; reginf=®info [reg]; if ((reginf->status==0)&&((SelRegSet&(1<pair==1)) /*st*/{ J=reginfo [reg].cnt+1; if (J==256) goto Note; reginfo [reg].cnt=J; if (reginfo [reg].alt.use>0) J-=5; if (J>cnt) { cnt=J; cntreg=reg; } } } if (cntreg>=0) { reg=cntreg; goto Note; } /* tries = 1,1,2*/ } /* Look for any unpaired registers tied to an single E-stack entry */ level=Stklimit+1; levelreg=-1; for (I=LOWTREG; I<=HIGHTREG; I++) { reg=Tregs [I]; reginf=®info [reg]; if ((reginf->status==1)&&((RegClaimMaskA&(1<pair==0)&&((1<=reginf->Eptrs [1-1])&&(reginf ->Eptrs [1-1]<=Elevel))) { if (level>reginf->Eptrs [1-1]) { level=reginf->Eptrs [1-1]; levelreg=reg; } } } if (levelreg>=0) { reg=levelreg; releasereg(reg); goto Note; } /* We are now desperate so choose any releasable register */ for (I=LOWTREG; I<=HIGHTREG; I++) { reg=Tregs [I]; reginf=®info [reg]; if ((reginf->statuspair!=2)&&((1<=reginf->Eptrs [1-1])&&(reginf->Eptrs [1-1]<=Elevel))) /*nd*/{ releasereg(reg); goto Note; } } /* All non optimiser allocated registers were locked */ Mabort(8); Note: reginf=®info [reg]; if (reginf->pair!=0) { if (reginf->pair==1) partner=reg+1; else partner=reg-1; /*st*/ reginf->pair=0; reginfo [partner].pair=0; reginfo [partner].status=0; memset(®info [partner].alt,0,sizeof( struct RuseFmt)); memset(®info [partner].main,0,sizeof( struct RuseFmt)); reginfo [partner].cnt=128; reginfo [partner].ext=REGUNEXTENDED; CleanRegister(partner,4); } CleanRegister(reg,4); return reg; } /* claim reg */ /***/ int claimbyteopreg() { /*******************************************************************/ /* Finds an empty integer register, locks it and then returns its **/ /* number. Applies heuristic to return register whose old value **/ /* is least likely to be useful in the future. Only regs which **/ /** can be used for byte ops are returned (%AL->%DL) **/ /*******************************************************************/ static const int toptreg=3; /* cuts out esi&edi */ int tries,topreg; int I,J,reg,cnt,cntreg,cnt1,cntreg1,SelRegSet,partner; struct reginfoFmt *reginf; /* On SPARC we may not select any optimiser allocated or ?: */ /* result register */ #if((Target==SPARC)||(Target==RS6)||(Target==MIPS)||(Target==PENTIUM)) SelRegSet=~(RegClaimMaskA|QCIResMask); #endif; /* Look for any unused registers with no current memory */ for (tries=1; tries<=2; tries++) { topreg=HIGHVOLTREG; if (tries>1) topreg=toptreg; cnt=-1; cntreg=-1; cnt1=-1; cntreg1=-1; for (I=LOWTREG; I<=topreg; I++) { reg=Tregs [I]; reginf=®info [reg]; if ((reginf->status==0)&&(reginf->main.use==0)&&((SelRegSet&(1<cnt) { cnt=J; cntreg=reg; } if ((J>cnt1)&&(((1<0) { reg=cntreg1; goto Note; } if (cntreg>=0) { reg=cntreg; goto Note; } /* Look for any unpaired registers with only a constant memory */ for (I=LOWTREG; I<=topreg; I++) { reg=Tregs [I]; reginf=®info [reg]; if ((reginf->status==0)&&(reginf->main.use==CONSTINT)&&((SelRegSet&(1<pair==0) ) { J=reginfo [reg].cnt+1; if (J==256) goto Note; reginfo [reg].cnt=J; if (reginfo [reg].alt.use>0) J-=5; if (J>cnt) { cnt=J; cntreg=reg; } } } if (cntreg>=0) { reg=cntreg; goto Note; } /* Look for any unpaired registers with a current memory */ for (I=LOWTREG; I<=topreg; I++) { reg=Tregs [I]; reginf=®info [reg]; if ((reginf->status==0)&&((SelRegSet&(1<pair==0)) { J=reginfo [reg].cnt+1; if (J==256) goto Note; reginfo [reg].cnt=J; if (reginfo [reg].alt.use>0) J-=5; if (J>cnt) { cnt=J; cntreg=reg; } } } if (cntreg>=0) { reg=cntreg; goto Note; } /* Look for any paired registers with a current memory */ for (I=LOWTREG; I<=topreg; I++) { reg=Tregs [I]; reginf=®info [reg]; if ((reginf->status==0)&&((SelRegSet&(1<pair==1)) /*st*/{ J=reginfo [reg].cnt+1; if (J==256) goto Note; reginfo [reg].cnt=J; if (reginfo [reg].alt.use>0) J-=5; if (J>cnt) { cnt=J; cntreg=reg; } } } if (cntreg>=0) { reg=cntreg; goto Note; } /* tries = 1,1,2*/ } /* Look for any unpaired registers tied to an single E-stack entry */ for (I=LOWTREG; I<=toptreg; I++) { reg=Tregs [I]; reginf=®info [reg]; if ((reginf->status==1)&&((RegClaimMaskA&(1<pair==0)&&((1<=reginf->Eptrs [1-1])&&(reginf ->Eptrs [1-1]<=Elevel))) { releasereg(reg); goto Note; } } /* We are now desperate so choose any releasable register */ for (I=LOWTREG; I<=toptreg; I++) { reg=Tregs [I]; reginf=®info [reg]; if ((reginf->statuspair!=2)&&((1<=reginf->Eptrs [1-1])&&(reginf->Eptrs [1-1]<=Elevel))) /*nd*/{ releasereg(reg); goto Note; } } /* All non optimiser allocated registers were locked */ Mabort(8); Note: reginf=®info [reg]; if (reginf->pair!=0) { if (reginf->pair==1) partner=reg+1; else partner=reg-1; /*st*/ reginf->pair=0; reginfo [partner].pair=0; reginfo [partner].status=0; memset(®info [partner].alt,0,sizeof( struct RuseFmt)); memset(®info [partner].main,0,sizeof( struct RuseFmt)); reginfo [partner].cnt=128; reginfo [partner].ext=REGUNEXTENDED; } CleanRegister(reg,4); return reg; } /* claim byte opreg */ /***/ int claimregpair() { /*************************************************************************/ /** Finds an empty pair of integer registers, locks them and then **/ /** returns the number of the lower one. Applies heuristic to register **/ /** pair whose old value is least likely to be useful in the future **/ /** Where possible keeps within current registerset to avoid extra saves**/ /*************************************************************************/ Mabort(11); return -1; } /* claim reg pair */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ int claimunusedreg() { /*******************************************************************/ /* Finds an empty integer register with no associated memory, **/ /* locks it and then returns its number. This is used by **/ /* CCopybytes to grab an unused register if one is available to **/ /* reduce pipeline delays in an unrolled copying loop. Use counts **/ /* are not updated. **/ /* **/ /* Returns -1 if no suitable register was found. **/ /*******************************************************************/ int I,J,reg,cnt,cntreg,cnt1,cntreg1,SelRegSet; struct reginfoFmt *reginf; /* On SPARC we may not select any optimiser allocated or ?: */ /* result register */ #if((Target==SPARC)||(Target==RS6)||(Target==MIPS)||(Target==PENTIUM)) SelRegSet=~(RegClaimMaskA|QCIResMask); #endif; /* Look for any unused registers with no current memory */ cnt=-1; cntreg=-1; cnt1=-1; cntreg1=-1; for (I=LOWTREG; I<=HIGHTREG; I++) { reg=Tregs [I]; reginf=®info [reg]; if (reginf->status==0 && reginf->main.use==0 && (SelRegSet&(1<cnt+1; if (J>cnt) { cnt=J; cntreg=reg; } if (J>cnt1 && ((1<0) { reg=cntreg1; goto Note; } if (cntreg>=0) { reg=cntreg; goto Note; } /* Look for any unpaired registers with only a constant memory */ for (I=LOWTREG; I<=HIGHTREG; I++) { reg=Tregs [I]; reginf=®info [reg]; if (reginf->status==0 && (SelRegSet&(1<cnt+1; if (reginf->alt.use>0) J-=5; if (J>cnt) { cnt=J; cntreg=reg; } } } if (cntreg>=0) { reg=cntreg; goto Note; } /* no suitably unused register was available */ return -1; Note: CleanRegister(reg,4); return reg; } /* claim unused reg */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void manipulateFS(int op,int operand) { /*************************************************************************/ /** This routine has various facilities to enable the Estack and **/ /** register record to be maintained when the Flaoting stack is **/ /** altered pushed or popped. Normal RISC machines do not have **/ /** these meesy problems. **/ /*************************************************************************/ int i,oldreg,newreg; struct Stkfmt *Lstk; struct reginfoFmt *reginf; struct reginfoFmt Tempreginf; switch (op) { case NEWPOSN: /* Operand=new<<16!old */ /* register is a a new pos update Estack */ oldreg=operand&255; newreg=(unsigned)operand>>16; reginf=®info [oldreg]; for (i=1; i<=(int)reginf->status; i++) { if (reginf->Eptrs [i-1]>0) { int Lform; Lstk=&Stk [reginf->Eptrs [i-1]]; Lform=Lstk->Form&31; if (Lform==FregVal || Lform==Fregvar || (Lform==RegVal && Lstk->Size==8)) { if (Lstk->Reg==oldreg) Lstk->Reg=newreg; if (Lstk->Imagreg==oldreg) Lstk->Imagreg=newreg; } else { printf("Warning: Cant tidy up after FEXCH new=%d old=%d\n",newreg,oldreg); Cdumpestack(); } } } return ; case INTERCH: /* operand=new<<16!old */ /* Swop the two regitser records */ /* Updating presumed done or unnecessary */ oldreg=operand&255; newreg=(unsigned)operand>>16; reginf=®info [oldreg]; Tempreginf=*reginf; *reginf=reginfo [newreg]; reginfo [newreg]=Tempreginf; return ; case FASTTOTOP: /* bring nominated reg to top */ oldreg=operand; if (oldreg==currentFSP) return ; targetfopr(FXCH,oldreg); manipulateFS(NEWPOSN,(currentFSP<<16)|oldreg); manipulateFS(NEWPOSN,currentFSP|(oldreg<<16)); manipulateFS(INTERCH,currentFSP|(oldreg<<16)); return ; case BUBBLETOTOP: /* Bring nominated reg to top without disturbing */ /* the order of any intermediate values */ oldreg=operand; for (i=currentFSP+1; i<=oldreg; i++) { manipulateFS(FASTTOTOP,i); } return ; case FDISCARD: /* Discard nominated reg */ if (operand!=currentFSP) manipulateFS(FASTTOTOP,operand); targetfopr(FSTPd,currentFSP); unlockregister(currentFSP); return ; } } /* manipulateFS */ /***/ int claimfreg() { /*******************************************************************/ /* Finds an empty floating point register, locks it and then **/ /* returns its number. Applies heuristic to return register **/ /* whose old value is least likely to be useful in the future. **/ /** For the first fry constrains itself to volatile registers **/ /*******************************************************************/ int reg,I,J,cs,spills; struct Stkfmt *Lstk; struct reginfoFmt *reginf; if (currentFSP>FRBASE) { currentFSP-=1; reg=currentFSP; goto Note; } /**/ /* If the stack is full we must dump the bottom one */ /**/ /* printstring("Before spilling"); newline; C dumpestack */ spills=1; /* dump 1 cell unless complex */ for (reg=REGCEILING; reg>=FRBASE; reg--) { reginf=®info [reg]; if (reginf->statusEptrs [1-1]]; if ((FRBASE<=Lstk->Imagreg)&&((int)Lstk->Imagreg=currentFSP; I--) { manipulateFS(NEWPOSN,(((I+spills)<<16)|I)); manipulateFS(INTERCH,(((I+spills)<<16)|I)); /* printstring(" After INTERCH"); write(I+spills,5); write(i,5); newline*/ /* C dumpestack */ } for (I=1; I<=J-spills; I++) targetoponly(FINCSTP,0,0); currentFSP=(currentFSP+spills)-1; reg=currentFSP; /* printstring("After spilling"); newline; C dumpestack */ goto Note; } } /* All non optimiser allocated float registers were locked */ Mabort(9); Note: reginf=®info [reg]; memset(reginf,0,sizeof( struct reginfoFmt)); reginf->status=1; reginf->cnt=128; reginf->ext=REGUNEXTENDED; usedfpregset|=1<<(reg&7); return reg; } /* claim freg */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /***/ int claimunusedfreg() { /*******************************************************************/ /* Finds an empty floating point register, with no associated **/ /* register memory (used by Direct Complex operations to reduce **/ /* artifical register dependencies if spare registers are **/ /* available), locks it and then returns its number. Use counts **/ /* are not updated. **/ /* **/ /* returns -1 if no suitable register is available **/ /*******************************************************************/ return -1; /*no unused floating-point registers available*/ } /* claim unused freg */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ int claimnamedreg(int reg) { /*************************************************************************/ /** allocates the named register - the register is released if it is **/ /** locked to the Estack - aborts if the register is temporarily locked **/ /*************************************************************************/ int use; struct reginfoFmt *reginf; reginf=®info [reg]; use=reginf->status; if (use>0) { if (use>=USERLOCKED) Mabort(8); if (reginf->pair==0) { releasereg(reg); /*st*/ } else if (reginf->pair==1) { releaseregpair(reg); } else { releaseregpair(reg-1); } } memset(reginf,0,sizeof( struct reginfoFmt)); reginf->cnt=128; reginf->status=1; usedregset|=1<<(reg&31); return reg; } /* claim named reg */ /***/ int claimnamedregpair(int reg) { /*************************************************************************/ /** allocates the named register pair - the registers are released if **/ /** they are locked to the Estack - aborts if the registers are **/ /** temporarily locked **/ /*************************************************************************/ int Junk; Junk=claimnamedreg(reg); Junk=claimnamedreg(reg+1); reginfo [reg].pair=1; /*st*/ reginfo [reg+1].pair=2; /*nd*/ usedregset|=3<31 || (RegClaimMaskA&(1<status; if (((1<=status)&&(status<=3))&&((1<=reginf->Eptrs [1-1])&&(reginf->Eptrs [1-1]<=Elevel))) { releasereg(reg); } else if (status>=USERLOCKED) { Mabort(27); } else { }; } FirstTarget=0; if (reginf->statusstatus=reginf->status+1; reginf->Eptrs [reginf->status-1]=0; } memset(®inf->alt,0,sizeof( struct RuseFmt)); memset(®inf->main,0,sizeof( struct RuseFmt)); reginf->cnt=128; reginf->ext=REGUNEXTENDED; usedregset|=1<main.primdata==primdata && reginf->main.secdata==secdata && reginf->main.size==size) { ruse=reginf->main.use; if ((writeable==0 && ruse==use) || (writeable!=0 && ruse==use && reginf->status==0 && (RegClaimMaskA&(1<statusstatus=reginf->status+1; reginf->Eptrs [reginf->status-1]=0; } J=reginf->cnt-3; if (J>=0) reginf->cnt=J; return reg; } } if (reginf->alt.primdata==primdata && reginf->alt.secdata==secdata && reginf->alt.size==size && reginf->main.use!=0 && (writeable==0 || (reginf->status==0 && (RegClaimMaskA&(1<alt.use; if (ruse==use) { if (reginf->statusstatus=reginf->status+1; reginf->Eptrs [reginf->status-1]=0; } J=reginf->cnt-3; if (J>=0) reginf->cnt=J; return reg; } } } return -1; } /* CheckRegKey */ /***/ int CheckRegKeyandExt(int use,int primdata,int secdata,int size,int writeable,int Type) { /*****************************************************************************/ /** As CheckRegKey but if size <4 checks also for correct extension **/ /** if incorrect extension only is found still returns the reg **/ /*****************************************************************************/ int J,reg,ruse,resultreg; struct reginfoFmt *reginf; if (Report!=0) { printf("Checking for KeyandExt %s %5d %5d %2d %2d",ReguseForm [use], primdata,secdata,size,Type); } resultreg=-1; for (reg=0; reg<=FRBASE-1; reg++) { reginf=®info [reg]; if (reginf->main.primdata==primdata && reginf->main.secdata==secdata && reginf->main.size==size) { ruse=reginf->main.use; if ((writeable==0 && ruse==use) || (writeable!=0 && ruse==use && reginf->status==0 && (RegClaimMaskA&(1<ext==REGSIGNEDEXT) || (Type==UintType && reginf->ext==REGUNSIGNEDEXT)) goto wayout; } } if (reginf->alt.primdata==primdata && reginf->alt.secdata==secdata && reginf->alt.size==size && reginf->main.use!=0 && (writeable==0 || (reginf->status==0 && (RegClaimMaskA&(1<alt.use; if (ruse==use) { if (size==4 || (Type==IntType && reginf->altext==REGSIGNEDEXT) || (Type==UintType && reginf->altext==REGUNSIGNEDEXT)) goto wayout; } } } wayout: if (resultreg>=0) { reginf=®info [resultreg]; if (reginf->statusstatus=reginf->status+1; reginf->Eptrs [reginf->status-1]=0; } J=reginf->cnt-3; if (J>=0) reginf->cnt=J; } if (Report!=0) { printf(" --- returns %3d\n",resultreg); } return resultreg; } /* CheckRegKeyandExt */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ int checkareaaddr(int Area,int *Offset) { /*****************************************************************************/ /* Finds a register holding the address of a location in the given area. **/ /* If such a register is found then its number is returned and Offset is **/ /* set to the displacement into that area held by the register. If no **/ /* suitable register is found then -1 is returned. **/ /** If more than one is found then the one closest to original value in **/ /** offset is selected **/ /*****************************************************************************/ int reg,J,Treg,diff,Aoffset; struct reginfoFmt *reginf; Treg=-1; for (reg=0; reg<=FRBASE-1; reg++) { reginf=®info [reg]; if ((reginf->main.secdata==Area)&&(reginf->main.use==ADDROF)) { if ((Treg<0)||(abs(*Offset-reginf->main.primdata)main.primdata; diff=abs(*Offset-Aoffset); } } if ((reginf->alt.secdata==Area)&&(reginf->alt.use==ADDROF)&&(reginf->main.use!=0)) { if ((Treg<0)||(abs(*Offset-reginf->alt.primdata)alt.primdata; diff=abs(*Offset-Aoffset); } } } if (Treg>=0) { reginf=®info [Treg]; *Offset=Aoffset; J=reginf->cnt-3; if (J>=0) reginf->cnt=J; } return Treg; } /* checkareaaddr */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ int CheckCloseConst(int Const,int *Disp) { /*****************************************************************************/ /* Finds a register holding a constant within a 13 bit displacement on the **/ /* SPARC, or 16 bit displacement on the M88K, of the required constant. The **/ /* register number is returned and Disp set to the required displacement if **/ /* successful, otherwise -1 is returned. **/ /*****************************************************************************/ int J,reg,rdata,CurDisp,MinDisp,MaxDisp; struct reginfoFmt *reginf; #if(Target==SPARC) MinDisp=-4096; MaxDisp=4095; #endif; /**/ /**/ #if((Target==RS6)||(Target==MIPS)) MinDisp=0xFFFF8000; MaxDisp=0x7FFF; #endif; /**/ for (reg=0; reg<=FRBASE-1; reg++) { reginf=®info [reg]; if (reginf->main.use==CONSTINT) { rdata=reginf->main.primdata; if ((((rdata<0)||(Const>0)||(((Const)+0x80000000)>rdata))&&((rdata>0)||(Const<0)||((Const-2147483647) cnt-3; if (J>=0) reginf->cnt=J; *Disp=CurDisp; return reg; } } } if ((reginf->main.use!=0)&&(reginf->alt.use==CONSTINT)) { rdata=reginf->alt.primdata; if ((((rdata<0)||(Const>0)||(((Const)+0x80000000)>rdata))&&((rdata>0)||(Const<0)||((Const-2147483647) cnt-3; if (J>=0) reginf->cnt=J; *Disp=CurDisp; return reg; } } } } return -1; } /* CheckCloseConst */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ #if (Target==SPARC)||(Target==RS6)||(Target==MIPS)||(Target==M88K) /***/ static int checkfregguts(int use,int primdata,int secdata,int writeable,int size) { /*************************************************************************/ /** Perform the guts of checkfregkey and checkfregpair **/ /** Size distinguishes the variants **/ /*************************************************************************/ int reg,ruse,J; struct reginfoFmt *reginf; /**/ if (Target!=M88K)||(targetvariant==M88110) { /**/ /**/ for (reg=FIRSTTFREG; reg<=LASTFREG; reg++) { reginf=®info [reg]; if ((reginf->main.primdata==primdata)&&(reginf->main.secdata==secdata)&&(reginf->main.size==size)) { ruse=reginf->main.use; if (((writeable==0)&&(ruse==use))||((writeable!=0)&&((ruse==use)&&(reginf->status==0)&&((RegClaimMaskB &(1<<(reg-32)))==0)))) goto FoundMatch; } if ((reginf->alt.primdata==primdata)&&(reginf->alt.secdata==secdata)&&(reginf->main.use!=0)&&(reginf ->alt.size==size)&&((writeable==0)||((reginf->status==0)&&((RegClaimMaskB&(1<<(reg-32)))==0)))) { ruse=reginf->alt.use; if (ruse==use) goto FoundMatch; } } /**/ return -1; /**/ FoundMatch: if (!(reginf->status>=USERLOCKED)) reginf->status=reginf->status+1; if (!(reginf->status>=USERLOCKED)) reginf->Eptrs [reginf->status-1]=0; J=reginf->cnt-3; if (J>=0) reginf->cnt=J; return reg; } /* %if Target!=M88K */ return -1; } int CheckFregKey(int use,int primdata,int secdata,int writeable) { /*****************************************************************************/ /** Checks to see if an float register has been tracked to hold a given **/ /** contents. Returns a suitable register or -1 if one is not found. **/ /** If a suitable register is found then it is returned in a locked state **/ /** if previously unlocked or in a double locked state if it was already **/ /** locked. **/ /** If writeable is non-zero then only a previously compiler allocatable **/ /** unlocked register is returned as the result. **/ /** On the M88110, if nothing appropriate is found in the floating point **/ /** memory then the integer register is inspected. **/ /*****************************************************************************/ return checkfregguts(use,primdata,secdata,writeable,4); } /* CheckFregKey */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ int CheckFregPairKey(int primdata,int secdata,int writeable) { /*************************************************************************/ /** Old version confined to DATAAT only */ /*************************************************************************/ return checkfregguts(DATAAT,primdata,secdata,writeable,8); } /***/ int CheckFregPairKey2(int use,int primdata,int secdata,int writeable) { /*****************************************************************************/ /** Checks to see if a float register pair has been tracked to hold a given **/ /** content. Returns a suitable register or -1 if one is not found. **/ /** If a suitable register is found then it is returned in a locked state **/ /** if previously unlocked or in a double locked state if it was already **/ /** locked. **/ /** The register and search sizes must be identical for a valid match. **/ /** If writeable is non-zero then only a previously compiler allocatable **/ /** unlocked register pair is returned as the result. **/ /** On the M88110, it searches the integer memory first and then the **/ /** floating point memory. **/ /*****************************************************************************/ return checkfregguts(use,primdata,secdata,writeable,8); } /* CheckFregPairKey */ #endif