/* EPC Imp to C Translation Release 4 Version Apr 95 */ #include "imptoc.h" #undef PI /** 30Jan98 mprocs18.1*/ /** Changed Mcall to accept bitmask rather than proctype */ /** Fortunately only calls from mprocs are affected */ /** Chnaged Substiyute to correct IndDirVal Problem in C */ /** 12Oct97 mprocs18 */ /** Added Mtrampcall for KAI parallel stuff */ /** 30Sep97 mprocs17.2*/ /** More careful about unasspat since some compilers separate th 2 word */ #define modulename ("mprocs") /** 23Apr96 mprocs17.1*/ /** Added Extra Mabort message for 64 bit integers */ /** 17Apr96 mprocs17*/ /** Translated to C and hand finished */ /** Corrections (several) to unassigned checking on PPC Solaris ABI **/ /** Added AndyK code for leaf SP calls (like mexpcall) **/ /** Changed to Msetoptions2 and set pic ax extern */ /** Change to Mprecall for MIPS when a Floatval is 1st par */ /** 13Feb96 mprocs16.1*/ /** Added code to work with elfput in C */ /** Corrected rounring of framesize in tidy frags */ /** 14Dec95 mprocs16*/ /** Added Mcurrentvalue a target independent variant of Ccurrentvalue */ /** Adding this to Mprocs should reduce maintainence */ /** Removable destroyable bit for Pentium profiling */ /** Remove the cror in Mcall for AIX calls via ptr as the linker */ /** does not convert these to TOC reloads. The TOC is reloaded */ /** in rs6 callind */ /** 02Oct95 mprocs15.4*/ /* More care over hidden parameters in Mprecall so Fortran chars */ /** are not confused with structures(pds) */ /** Used global string exnameprepend rather than "_" to amend USLC names*/ /** Added MonetimeLabel to improve ADI ADSYM code(pds) */ /** Added a new bit in callprops to indicate the procedure has */ /** varargs. Needed for the Power Sunsoft ABI but not restricted */ /** to RS6 targets(pds). */ /** 18Sep95 mprocs15.3*/ /** Correction to Mprecall for Sparc only. For calls within calls muc!* decrement SP enough to deal with varargs case and also to protect the struct */ /** return pointer which may also be on stack */ /** 08Aug95 mprocs15.2*/ /** Changes to Mexpcall and Mspcall for USLC */ /** Mapped ParI array to allow >199 params in a single call */ /** Sunsoft special in Minitialise */ /** 03Aug95 mprocs15.1*/ /** Ensured there is always a procrag at level0 in case of rogue */ /** handles being requested(pds) */ /** 24Jly95 mprocs15*/ /** Changes in Mtidy end to detect DBXINFO added at level 0 and */ /** move it to head of current proc. This eases front end problems */ /** of getting correct line information for fns in includes */ /** 01Jun95 mprocs14.5*/ /** Changes to remove put references for USLC */ /** Increased the switcsize needed for a dense switch */ /** 08May95 mprocs14.4*/ /** Added Mreinitialise for repositary scheme(pds) */ /** Merged in AK chnages for SunOS(pds) */ /** 06Apr95 mprocs14.3*/ /** Changes to mexpcall to pass sparc real*16 by address and accept */ /** result as a stucture */ /** Removed historic M88k special from fm Mbrac */ /** Added code in Mstartproc and Mcall for early detection of */ /** recursion and to protect the tail recursion label from */ /** being optimised away. This facilitates the implementation */ /** ot the tail recursion optimisation in target procs(pds) */ /** 23Mar95 mprocs14.2*/ /** Ensured generate entry die only called for Unix5.4 macheines */ /** Calls cvalidatejumps for all targets. Dummies may be reqd */ /** 20Mar95 mprocs14.1*/ /** Changed Mstartproc for m88k to LOad Gla reg in the usual way */ /** 06Feb95 mprocs14*/ /** Added code in the Mparaminfo family to cope with real*16 with */ /** real*8 alignment. Further cahnges may be needed if the MIPS */ /** ABI specifies 16 byte alignment when extended for real*16 */ /** Also moved some MIP special code in M tidy proc to wrapper sequence*/ /** Changed Mexpcall and Mspcall ti pass correct type info to Exname */ /** 27Jan95 mprocs13.10*/ /** In Minitialise remove GOT setting up. Done also in elfput(pds) */ /** Corrected Mtidyproc for fns returning int*8&real*16(pds) */ /** this requires boc15.6.inc as include file */ /** 02Nov94 mprocs13.9*/ /** Changes to layout of conds for easier translation to C */ /** Corrected Mtidyproc for fns returning int*8(pds) */ /** this requires boc15.5.inc as include file */ /** 18Oct94 mprocs13.8*/ /** Corrected Sunsoft unassigned filling */ /** Added NO COALESCE HEAD to first rs6 frag so wrappers locatable */ /** 01Sep94 mprocs13.7*/ /** Added code for m88k profiling which was omitted. */ /** Correction to previous change to include Nonvirtual fp (alloca) */ /** 09Aug94 mprocs13.6.1*/ /** Changed Mgetfpparamoffset to handle parameter holes. Fixed Mtidyproc*/ /** to give procedure NON VIRTUAL FP flag if stack frame bigger than */ /** 32K. (rt) */ /** 02Aug94 mprocs13.6*/ /** Correction to merge */ /** Output Sunsofts TBT before rather than after the proc body */ /** Added code for Sunsoft parameter passing on POWER */ /** 01Aug94 mprocs13.5*/ /** Merge of RT and PDS working versions. (rt) */ /** 29Jul94 mprocs13.4*/ /** Changes for use of 'do wrapping' for RS6000/POWER. */ /** 01Aug94 mprocs13.3.2*/ /** Changed RS/6000 AIX TOC reload to NOPs to support C since we */ /** don't known if a procedure is internal or not. (rt) */ /** 27Jul94 mprocs13.3.1*/ /** Added calls to target DefAssSymbol to define symbols which are */ /** external for some assemblers. (rt) */ /** 22Jul94 mprocs13.3*/ /** Changes to allow 2 different ABIs on rs6000(pds) */ /** 18Jly94 mprocs13.2*/ /** Changes for MIPS switches no longer in text segment */ /** 28Jun94 mprocs13.1*/ /** Changes for parallel Fortran which HAS nested procedures(in effect)*/ /** Changed profiling code for Pentium which uses a NON STANDARD call */ /** 21Apr94 mprocs13*/ /** Changed target accessindrr, target accessindri and target access */ /** parameters. Changed calculation of register set for MIPS */ /** do wrapping. Changed clearing of register clearing in Mcall to */ /** prevent MIPS GOT reload picking up bogus register tracking info. (rt)*/ /** 07Apr94 mprocs12.3*/ /** Added leaf call reg routines for PENTIUM. (pds) */ /** 24Mar94 mprocs12.2*/ /** Always pass three parameters to target frlabel. Add back in Mcodeon*/ /** (although functionally redundant). Also put arrays for support calls*/ /** back into include file. (pds) */ /** 11Apr94 mprocs12.1.1*/ /** In Mtidyproc, correct stack unassigned fill count for SPARC to use */ /** PI_framesize rather than localsize. (ak) */ /** 17Mar94 mprocs12.1*/ /** Merge of GIS development SPARC code generator with latest generic */ /** version. (rt) */ /**------------------------ START OF PENTIUM CHANGES ---------------------------*/ /** 15Mar94 mprocs11.4*/ /** Added code to mtidyend so that any wrappers are added before */ /** a DBXINFO instruction if this was the last instruction planted */ /** 24Feb94 mprocs11.3*/ /** Added code for dealing with MIPS got save word >32K from LNB */ /** Reenabled code in Mfrlabel disabled by RT (pds) */ /** Marked GOT loading & saving with privprop 'GOT RED TAPE' */ /** 11Feb94 mprocs11.2*/ /** Added code for setting diagdisp on mips and PENTIUM. Originally this*/ /** was missing for side entries. Also some rationalisation of setting */ /** and post filling of diagdisp(pds) */ /** 25Jan94 mprocs11.1*/ /** Additional code for MIPS to prevent Fortran Parameter checking data */ /** being overwritten by the unassigned pattern(pds) */ /** 10Nov93 mprocs11*/ /** Added code for Pentium(pds) */ /** Also merged in change from TAM */ /** Added MAdjustOptions and changed MSetOptions accordingly. */ /** Part of fix for B405. (tkr) */ /** MSetOpnd will now process a chain of opernads */ /**------------------------- END OF PENTIUM CHANGES ----------------------------*/ /** 07Jan94 mprocs12*/ /** Merge of M88K and SPARC code generators for GIS port to SPARC. (rt)*/ /**----------------------- START OF SPARC F90 CHANGES --------------------------*/ /** 13Sep93 mprocs4.7.2*/ /** in Mstartproc and Msideentry, if profiling on SPARC then */ /** clear register memory after calling mcount (OUTPARAM1REG */ /** may contain a large (>4K) GLA address and will thus be */ /** in the register memory). */ /** 10Sep93 */ /** in Mstartproc and Msideentry, remove the double load of */ /** the Gla register if generating PIC code for SPARC. */ /** 06Sep93 */ /** Made exrecheads an allocatable, extendable, array (required */ /** by Fortran90 when generating Dwarf). */ /** 13Aug93 */ /** Correction to Mtidyend: exdata -> exfix */ /** 10Aug93 mprocs4.7.1*/ /** In Mfrlabel, add SPARC to the list of targets that fully */ /** support Efrlabel and modify the spec of target frlabel */ /** to additionally pass the address of the current fragment. */ /** 06Aug93 */ /** In Mgetprocref, initialise the store reserved for the */ /** fixup to zero (on Solaris fixups gets added to the */ /** original contents) */ /***/ /** In Msideentry, use the constant STOREINTVAL, and not */ /** 'INTVAL+4' when calling targetaccess to store the */ /** diagdisp */ /** 02Aug93 */ /** In Mstartproc, allow Fortran90 to have a display */ /** 09July93 */ /** In Mstartproc, dont forget to store the caller stack frame */ /** address after filling the stack with the unassigned pattern */ /** if argument checks are on */ /** 06July93 mprocs4.7*/ /** Further changes from andy-s mprocs46.6.i merged in */ /** Allow dummy fixups in maddrlabel for assembler or gotfix */ /**------------------------ END OF SPARC F90 CHANGES ---------------------------*/ /** 03Nov93 mprocs11*/ /** Merge of MIPS, USL C and C++ M88K code generators. Added */ /** Mexname function. (rt) */ /**----------------------- START OF M88K USL C CHANGES -------------------------*/ /** 06Sep93 mprocs4.2*/ /** Mgetname added for USL C. */ /**------------------------ END OF M88K USL C CHANGES --------------------------*/ /**------------------------ START OF M88K C++ CHANGES --------------------------*/ /** mprocs42.2*/ /** 09Nov92 .Introduced code to deal with code handles and introduced */ /** MProcFrameSize. (si) */ /** mprocs42.1*/ /** 27Jan92 .Changed ESetProcRef and MGetUniqueProcKey to take extra */ /** id parameter. This allows multiple fixups to be made to an */ /** external function with only a single external reference. (rt) */ /**------------------------- END OF M88K C++ CHANGES ---------------------------*/ /** 14Oct93 mprocs10.4*/ /** Made B FreeAllocation work at all procedural levels and */ /** deleted calls to B InitAllocation, which is now redundant. (rt) */ /** 08Oct93 mprocs10.3*/ /** Added call to abi init in tidy frags for mips specific ABI */ /** requirement. (rt) */ /** 20Sep93 mprocs10.2*/ /** Made Exrecheads an extendable array and added code to extend */ /** if it overflows (F90 requirement) */ /** Corrections to PIC code for MIPs(pds) */ /** 27Aug93 mprocs10.1*/ /** Removed references to shrink wrapping optimisation. Handle new */ /** RETURNS SREAL and RETURNS DREAL flags. Removed HAS LARGE STACK flag */ /** setting. (rt) */ /** mprocs10*/ /** 17Aug93 */ /** Modified setting of registers referenced by return jump instruction */ /** to handle case of FORTRAN subroutine with side entries returning */ /** 11Aug93 mprocs9.i */ /** Further changes from andy-s mprocs46.6.i merged in */ /** mprocs9*/ /** 27Jul93 */ /** If generating code for procedure with unknown control flow then */ /** clear all register tracing information on a call. (rt) */ /** mprocs8*/ /** 25Jul93 */ /** Set new flags HAS LARGE STACK and NO REG EXPAN to handle pathological*/ /** cases for global scheduler changing stack frame size. (rt) */ /** mprocs7*/ /** 22Jul93 */ /** Clear fragment chain head pointer for global fragments after */ /** they have been generated and set up a new empty fragment. Fixed */ /** Mtidyend to handle code in level 0 generated after last Eprocend. */ /** Add MEndProcs to generate any outstanding level 0 instructions. (rt)*/ /** mprocs6*/ /** 19Jul93 */ /** Modified stack frame size calculation so that wrapping instructions */ /** generated after stack frame size is calculated. This is required since*/ /** we won't know if we need a real frame pointer until the stack frame */ /** size is known. Changed Msetopnd to remove unncessary check for signed*/ /** arithmetic when setting new stack frame size. (rt) */ /** mprocs5*/ /** 14Jun93 */ /** Merge of MIPS and SPARC versions for GIS port. Renamed CScheduleProc*/ /** to COptimiseProc. Handled change of stack frame size ofter optimisation*/ /** and removed insertion of discarded psuedo ops. Renamed uses of */ /** _fragbusy to _fragsize. Renamed _maxparsize to _outparsize. Changed */ /** Mtidyend to fix up addressed labels via the stored fragment start */ /** address. Added UnkCntrlFlow for global scheduler. Also handle malloc*/ /** failure more gracefully - suggest user recompiles without */ /** optimisation. Added parameter to CCall call to indicate if a display*/ /** register is being passed to the function or not. Also added support */ /** for line prefixes. These give the complete path by which a source */ /** line is included in the code if it appears by virtue of an inlining.*/ /** The new routine MPrintLine prints a full line number including */ /** including any prefix and MAddLinePrefix generates a line prefix */ /** record. Also changed dynamic memory allocation to use B Malloc and */ /** and B Free. Make return instruction reference the returned */ /** registers. Call B InitAllocation and B FreeAllocation to handle */ /** allocation of fragments at procedural level 1. (rt) */ /** 10Jun93 mprocs4.6*/ /** Added mnotecodefix and made Mtidyproc a function. (pds) */ /** 03Jun93 mprocs4.5*/ /** Further changes to getprockey family and mtidyend for C++ */ /** to aid setting up virtual tables */ /* 20May93 mprocs4.4*/ /** Used addiu for stackframes */ /* 17Apr93 mprocs4.3*/ /** Added Mgetname for USL C and updated M adjust par and */ /** M paraminfo family for complete realigning of params */ /** that can be required if there is a hidden parameter */ /** and also long reals(pds) */ /** Also added and checked the .init/.fini bits in Mstartproc */ /* 16Apr93 mprocs4.2*/ /** support note entry info eyc for Mips (gm) */ /* 16Mar93 mprocs4.1*/ /** Changed Mtidyend to force out unrefenced symbols for FORTRAN */ /** which uses this to link in blockdata but not for C or others */ /** which rely on this not happening.(pds) */ /* 07Mar93 mprocs4*/ /** includedNote Entry Info, Note Entry Codead, Output DBX Entries */ /** introduled by sl for 88K dwarf generation. */ /** Common RS6000, MIPS and 88K (gm) */ /* 24Nov92 mprocs3*/ /** Revamped for MIPs including reincorporating Mabort and */ /** using the generic prefix target mapped via alias to the specific */ /** prefixes rs6,sparc,mips,88k88110 etc */ /* 30Sep92 mprocs2.6*/ /** Provides support for Ebrac (sdb-dbx inner blocks) */ /** Also supports C floats as parameter when these differ */ /** from normal real values (as on RS6000) */ /* 03Aug92 mprocs2.5*/ /* Additional code to restrict the procref descriptor coding */ /* to RS6000 only and provide the old code for other targets */ /* 11Jun92 mprocs2.4*/ /* Introduces code regions to assist the BEO remove rendundant instrns */ /* 03Jun92 mprocs2.3.i */ /** Changes to exdata and Mgetprockey to distinguish integernal and external*/ /** procs. This was formerly done by having no names for internals but when*/ /* names were added for SDB & DBX ambiguities were introduced. These bit*/ /** me in the bum when trying to do AIX linkage with descriptors, glue code*/ /** and TOCs. All internal procs must be introduced with Enextproc which*/ /** sets a new bit (2**2) in Exdata_Flags. */ /***/ /** 15May92 mprocs2.2.i */ /** Adjusts parameter if the fn returns an aggregate */ /** mprocs42 */ /** 25 Sep 91 .Removed the instruction, fragment and label handling */ /** routines and relocated them to the bprocs module. The bprocs */ /** module is a generic back-end optimiser that is designed to */ /** operate with all code generators, including non EMachine 4. The*/ /** generic backend optimiser operates using the instruction and */ /** fragment chains poineered on EMachine 4. Thus chain handling is*/ /** no longer specific to EMachine 4 and is therefore no longer */ /** sited in this EMachine 4 specific module. The following routines*/ /** were moved and renamed to start with the bprocs module naming */ /** prefix: */ /***/ /** M labrecad ---> B labrecad */ /** M locate label ---> B locate label */ /** M new instr ---> B new instr */ /** M delete instr ---> B delete instr */ /** M insert instr ---> B insert instr */ /** M append instr ---> B append instr */ /** M curinstraddr ---> B curinstraddr */ /** M curfraginstr ---> B curfraginstr */ /** newfrag ---> B newfrag */ /** M break frag ---> B break frag */ /** delete frags ---> B delete frags */ /***/ /** 19/08/89 definitive version created */ /***/ /**************************************************************************/ /** **/ /** EPCL back end for RISC chips **/ /** **/ /**************************************************************************/ /***/ /***/ #include "cgtarget.h" /***/ #include "cgconsts.h" /***/ #include "boconsts.h" /***/ #include "archdefs.h" /***/ #include "archspnames.h" /***/ /***/ /***/ /**************************************************************************/ /** **/ /** Imports **/ /** **/ /**************************************************************************/ /***/ extern int epermspace( int ,int ); /*user supplied*/ extern int etempspace( int ,int ); /*user supplied*/ /***/ #include "prototypes.h" /***/ #if(Language==FORTRAN) /** New ENTRY variables for dwarf */ /*SL update*/ struct entryfmt{ char name[256]; int lab; int labad; int codead; }; #define MAXENTRYS 100 /*max no. of ENTRY statements for -g*/ static struct entryfmt EntryRecs [MAXENTRYS+1]; static int NumEntrys; /*current number of ENTRYs found for a routine*/ /***/ #endif /***/ /**************************************************************************/ /** **/ /** Constant definitions **/ /** **/ /**************************************************************************/ /***/ #define IMULT 3 /*03*/ /* (Etos-1) * (Etos) => (Etos) */ #define DISCARD 48 /*30*/ /* discard (Etos) */ #define CVTII 136 /*88*/ /* (int Etos-1) => int size(Etos) */ #define ESTORE 184 /*B8*/ /* ((Etos)) = (Etos-1) */ #define PUSHVAL 186 /*BA*/ /* push (Etos) as value param */ #define PUSHADDR 187 /*BB*/ /* push (Etos) as ref param */ /***/ #define NO 0 #define YES 1 /***/ #define ubswrecheads 31 static int ubexrecheads=31; #define ublabadheads 31 #define maxexrecheads (0xFFFF) static int *exrecheads; /***/ #define curmax 87 static char * Text [curmax] = { /*00*/ "Mswitchjump fails to find switchid", "Mswitchentry fails to find switchid", "Mswitchlabel fails to find switchid", "Release reg pair fails to find regs", "Release reg fails to find regs", "Release freg pair fails to find regs", "Release freg fails to find regs", "Claim reg fails", "Claim freg fails", "Claim reg pair fails", /*10*/ "Claim freg pair fails", "Load Int with size greater than target supports", "Attempt to index a constant or float", "Invalid attempt to Refer", "Invalid op to Int Unary Op", "Invalid op to Real Unary Op", "Stklimit exceeded", "Invalid reference to a leaf procedure", "Invalid op to Ccomparebytes", "Invalid use of CStackpf", /*20*/ "Invalid use of CReferpf", "Mswtabad fails to find switchid", "Invalid op to Bit Op", "Load Int with float destination reg", "Load Int with real not of size 4", "Load Real with int destination reg", "Claim named tgt fails", "Load Real with int not of size 4", "CPushParam - only 1,2 or 4 byte int params supported", "CPushParam - cannot deal with complex parameters", /*30*/ "StructVal/StringVal should be handled by CPushBytes", "CPushBytes - invalid parameter type", "CShift - illegal opcode", "CLoadRegvars: No Regvar storage area found", "Invalid Op in CX Operation", "Inconsistant sizes in ECSTORE", "Sparse switch table overflow", "Mparaminfo called too often", "Malloc Space: malloc() returned NULL", "Invalid instruction class", /*40*/ "Invalid instruction variant", "Illegal use of FRAMEPOINTER", "Only 1,2 or 4 byte integer parameters supported", "COMPLEX parameters unsupported", "Bad form in StkAccess", "labrecheads table overflow", "labadheads table overflow", "swrecheads table overflow", "exrecheads table overflow", "malloc() failure - try recompiling without optimisation", /*50*/ "Illegal attempt to release unpaired regs", "Illegally locked register", "Illegally locked register pair", "Illegally locked float register", "Unmatched source/target languages", "Illegal opcode in EJump", "Illegal stack duplication", "Illegal non-literal power", "Condition codes not set", "Illegal operation in GenInstructions", /*60*/ "Illegal calling order in LogStk", "Erefer requires an operand", "Inconsistent E-stack", "Epsave requires an operand", "Evsave requires an operand", "Non-empty stack at Elabel", "Too many labels in Enewlab", "Label not found in Estmtlabel", "PUSHBYTES requires a literal operand", "Base must be positive for Epsave", /*70*/ "ELogNeg requires an operand", "ELogStk requires an operand", "ECJump requires an operand", "FreeRegs unable to save locked register", "Negative PARAMS offset is illegal", "PUSHSTR not implemented", "ParI has not been set", "Invalid use of Perm-unlocking", "Invalid user of register $0", "Invalid CA handle provided", /*80*/ "Exrecheads realloction malloc failed", "Odd register pair allocated", "Attempt to call illegal negative id", "Reassignment to Regvar already on Estack", "Use of unclaimed register varaible", "64-bit integer operands not supported for this operator", "Trampoline calls may not ne nested or recursive" }; /***/ /***/ /**************************************************************************/ /** **/ /** Global data **/ /** **/ /**************************************************************************/ /***/ extern struct Stkfmt Stk [Stklimit+1]; extern int Elevel; extern int ModifyCC; /***/ extern int GlobCodeReport; /***/ /***/ static int swrecheads [ubswrecheads+1]; static int labadheads [ublabadheads+1]; /***/ static struct paramfmt ParamInfo [20+1]; /* 0 unused - 19 nested calls */ static struct paramfmt *ParI; int calllevel; static int *Parwords; static int FreeParword; int FirstDisplayLevel; int MainFrameOffset=-1; int UnkCntrlFlow; int CheckOverflow=0; /**/ /***/ static int report; static int cgoptions; /*as passed in by ftncomp or gccompile*/ #define CHKOFLOW (0x200000) /* bit for soft overflow checks */ static int ProcNum; static int setdbx; static int setlineno; static int diagnostics; static int profile; static int Lineprof; static int primecodelisting; static int FPUtraps; static int paramchecks; static int codelisting; static int PLToffset; extern int Pic; /*0 => defaults/ 1 => call pic libs / >1 => generate pic*/ static int fixedca; /***/ static int LinePrefixAddr; static int LinePrefixIndex; /***/ #define Firstuserexname 11 static int Numexnames; static int Numswkeys; static int Numareakeys; static int Numconstrecs; static int Numlabadkeys; /***/ static int Nextlabtag; static int Nextplabel; int Labadjust; #define INITLABTAG 250000 #define INITPLABEL 66000 /***/ int currentPIaddr; static struct procfmt ProcInfo [19+1]; static struct procfmt *PI; /* points to current ProcInfo entry */ /***/ static int UnassignedWords[2] ={UnassignedPattern,UnassignedPattern}; static int UnassignedDisp; /*displacement in Gla of the unassigned pattern*/ /***/ #if(Target==PENTIUM) int Maxareakey; static char ProfileName [8]="_mcount"; /* Pentium non standard here too!*/ #else static char ProfileName [8]="mcount"; #endif static int ProfileId=0; /*Mprockey Id for ProfileName*/ static int bufaddr=0; static int /* Here for Mreinitialise to reset */ buftop=-1; /***/ int GOTareaId=PLT; /*Mprockey Id for GOTname*/ /*%OWNSTRING(20) GOTname = "GLOBAL_OFFSET_TABLE_" */ /***/ /**************************************************************************/ /** **/ /** Switch record management **/ /** **/ /**************************************************************************/ /***/ static int swrecad(int index) { /****************************************************************/ /** Provide the address of the switch record with given index **/ /****************************************************************/ int Scale,I,J; Scale=3; I=(unsigned)index>>9; /* units of 512 entries (4K bytes) */ if (I>ubswrecheads) Mabort(48); /* swrecheads table overflow */ J=swrecheads [I]; if (J==0) { J=(int)BMalloc(4096,1,MASWRECADAREA); swrecheads [I]=J; } return J+((index&0x1FF)<=1; i--) { swrec=(struct Swrecfmt*)(swrecad(i)); if (swrec->key==Switchid) return swrec->tab; } Mabort(22); return 0; } /*M swtabad*/ /***/ static void reclaimswspace(int oldkey) { /*************************************************************************/ /** Free the space used by any switches in the current proc **/ /*************************************************************************/ int i; struct Swrecfmt *swrec; for (i=Numswkeys; i>=oldkey+1; i--) { /* oldkey is last sw in prev proc */ swrec=(struct Swrecfmt*)(swrecad(i)); BFree((void *)swrec->tab); memset(swrec,0,sizeof( struct Swrecfmt)); } Numswkeys=oldkey; } /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ /**************************************************************************/ /** **/ /** External proc record management **/ /** **/ /**************************************************************************/ /***/ /***/ struct Exdatafmt *exrecad(int index) { /****************************************************************/ /** Provide the address of the record for an external record **/ /** with given index **/ /****************************************************************/ int I,J,oldsize,newsize,adr; I=(unsigned)index>>6; /* units of 64 entries (64*Exdatasize bytes) */ if (I>ubexrecheads) { if ((I!=(ubexrecheads+1))||(I>=maxexrecheads)) Mabort(49); /* exrecheads table overflow */ /**/ oldsize=4*(ubexrecheads+1); newsize=2*oldsize; if (report!=0) { printf(" Expand exrecheads from %d to %d entries\n", ubexrecheads+1,(unsigned)newsize>>2); } adr=(int)BMalloc(newsize,1,MAEXRECADAREA); if (adr==0) Mabort(81); /**/ memcpy( (void *)adr, &exrecheads [0],oldsize); memset( (void *)(adr+oldsize),0,newsize-oldsize); BFree((void *)&exrecheads [0]); exrecheads=((int *)(adr)); ubexrecheads=((unsigned)newsize>>2)-1; } /**/ J=exrecheads [I]; if (J==0) { J=(int)BMalloc(64*Exdatasize,1,MAEXRECADAREA); exrecheads [I]=J; memset((void *)J,0,64*Exdatasize); } return (struct Exdatafmt *)(J+((index&0x3F)*Exdatasize)); } /* exrecad */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void TidyMcode(int Level,int *PLTsize) { *PLTsize=PLToffset; } /* Tidy Mcode */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ /***/ /**************************************************************************/ /** **/ /** switch processing **/ /** **/ /**************************************************************************/ /***/ /***/ int Mprivatelabel() { /****************************************************************/ /** provide the next private label index **/ /****************************************************************/ int I; I=Nextplabel; Nextplabel++; return I; } /* Mprivatelabel */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ static void Switchdef(int Mode,int Lower,int Entries,int Switchid,int Errlab,int *Swtabad) { /****************************************************************/ /** define a switch - mode is as follows: **/ /** 1 - NO INDEX JUMP **/ /** 2 - INDEX JUMP (to generate code to jump to the **/ /** switch label) **/ /** 3 - SPARSE SWITCH (for sparse switches) **/ /** (Entries actual label used) **/ /****************************************************************/ int I,J; struct Swtabfmt *Tab; struct Swrecfmt *swrec; #if((Language==FORTRAN)&&(LanguageVariant==FORTRAN77)) Switchid+=Labadjust; #endif Numswkeys++; swrec=(struct Swrecfmt*)(swrecad(Numswkeys)); swrec->key=Switchid; if (Entries<=3) Mode=SPARSESWITCH; if ((Target==PENTIUM)&&(Entries<=5)) Mode=SPARSESWITCH; if (Mode!=SPARSESWITCH) /* claim space for full table */{ *Swtabad=(int)BMalloc((Entries*4)+swtabbasesize,1,MADENSESWITCHTABLE); } else { *Swtabad=(int)BMalloc((Entries*8)+swtabbasesize,1,MASPARSESWITCHTABLE); } Tab=(struct Swtabfmt*)(*Swtabad); swrec->tab=*Swtabad; Tab->Reffrag=(int)PI->curfrag; Tab->SlotsUsed=0; Tab->Mode=Mode; Tab->Lower=Lower; Tab->Labbase=Nextplabel; Tab->SwitchId=Switchid; /* we want to reserve as few labels as possible for the switch */ Nextplabel=(Nextplabel+Entries)+1; Tab->Entries=Entries; if (Errlab>0) { J=BLocateLabel(Errlab+Labadjust,0); if (J<0) J=-J; } else J=-1; if (Mode!=SPARSESWITCH) /* set up labels to jump to default */{ for (I=0; I<=Entries-1; I++) { Tab->u0.R [I]=J; } } Tab->Rangelab=J; } /* Switchdef */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void Mswitch(int Mode,int Lower,int Entries,int Switchid,int Errlab) { /****************************************************************/ /** define a switch, and if Mode# 1 then generate the code to **/ /** jump to the switch label **/ /****************************************************************/ int Swtabad; /*********************************************************/ /* define the switch **/ /*********************************************************/ /**/ Switchdef(Mode,Lower,Entries,Switchid,Errlab,&Swtabad); /*********************************************************/ /* generate the index-checking and jumping code **/ /*********************************************************/ /**/ Cswitch(Switchid,Swtabad); } /* Mswitch */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void Mfswitch(int Lower,int Entries,int Switchid,int Errlab,struct Stkfmt *Stk) { /****************************************************************/ /** define a switch, load (ETOS), perform optional range **/ /** checking, and generate code to jump to the switch label. **/ /** Negative entries mean use SPARSE variant. **/ /** On most machines SPARSE is faster for up to 3 labels as **/ /** Range check is had for free. **/ /****************************************************************/ int Swtabad; /*********************************************************/ /* define the switch **/ /*********************************************************/ /**/ if (Entries<=3) { Switchdef(SPARSESWITCH,Lower,abs(Entries),Switchid,Errlab,&Swtabad); } else { Switchdef(NOINDEXJUMP,Lower,Entries,Switchid,Errlab,&Swtabad); } /*********************************************************/ /* generate the index-checking **/ /*********************************************************/ /**/ Cswitchjump(Switchid,Swtabad,Stk); /*********************************************************/ /* generate the switch jump **/ /*********************************************************/ /**/ Cswitch(Switchid,Swtabad); } /* Mfswitch */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void Mswitchjump(int Switchid,struct Stkfmt *Stk) { /****************************************************************/ /** transfer to switch code with given index **/ /****************************************************************/ struct Swrecfmt *swrec; int I; for (I=1; I<=Numswkeys; I++) { swrec=(struct Swrecfmt*)(swrecad(I)); if (swrec->key==Switchid) { Cswitchjump(Switchid,swrec->tab,Stk); return ; } } Mabort(1); /*Mswitchjump fails to find switchid*/ } /* Mswitchjump */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ static void DumpSwitchTable(struct Swtabfmt *Tab) { int i,used,Mode; Mode=Tab->Mode; if (Mode==SPARSESWITCH) { used=Tab->SlotsUsed-1; for (i=0; i<=used; i++) { printf("%d : Entry = %d, label = %d\n/",i,Tab->u0.S [i].Entry,Tab->u0.S [i].Label); } } } /* routine DumpSwitchTable */ /***/ /**/ /* Copyright (c) 1990 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void Mswitchentry(int Switchid,int Entry) { /****************************************************************/ /** define the current point as a switch label **/ /****************************************************************/ struct Swrecfmt *swrec; int I,lrecndx,Index; struct lrecfmt *lrec; struct Swtabfmt *Tab; struct fragfmt *f; Index=Entry; for (I=1; I<=Numswkeys; I++) { swrec=(struct Swrecfmt*)(swrecad(I)); if (swrec->key==Switchid) { Tab=(struct Swtabfmt*)(swrec->tab); if (report!=0) DumpSwitchTable(Tab); if (Tab->Mode!=SPARSESWITCH) { Entry-=Tab->Lower; /* sparse switches check if already given as default */ } else { Entry=-1; for (I=0; I<=Tab->SlotsUsed-1; I++) { if (Tab->u0.S [I].Entry==Index) { Entry=I; break ; } } if (Entry==-1) { Entry=Tab->SlotsUsed; Tab->SlotsUsed=Tab->SlotsUsed+1; } } lrecndx=BLocateLabel(((Tab->Labbase+Entry)+1)+Labadjust,0); lrec=BLabRecAd(lrecndx); if (lrec->frag!=NULL) { f=lrec->frag; /* forget previous definition of */ f->labindex=NULL; /* this switch entry */ lrec->frag=NULL; } Mlabel((Tab->Labbase+Entry)+1); if (Tab->Mode==SPARSESWITCH) { /* for a sparse switch we build a table of constant/label pairs */ /* and then later use these to plant a series of IF THEN GOTOs */ Tab->u0.S [Entry].Entry=Index; /* X in case X: */ Tab->u0.S [Entry].Label=((Tab->Labbase+Entry)+1)+Labadjust; /* non-sparse table */ } else { Tab->u0.R [Entry]=lrecndx; } return ; } } Mabort(2); } /* Mswitchentry*/ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void Mswitchlabel(int Switchid,int Entry,int Labelid) { /****************************************************************/ /** define the switch entry as the nominated label **/ /****************************************************************/ struct Swrecfmt *swrec; int I,J; struct Swtabfmt *Tab; #if((Language==FORTRAN)&&(LanguageVariant==FORTRAN77)) Switchid+=Labadjust; #endif for (I=1; I<=Numswkeys; I++) { swrec=(struct Swrecfmt*)(swrecad(I)); if (swrec->key==Switchid) { Tab=(struct Swtabfmt*)(swrec->tab); if (Tab->Mode==SPARSESWITCH) { J=Tab->SlotsUsed; Tab->SlotsUsed=Tab->SlotsUsed+1; Tab->u0.S [J].Entry=Entry; Tab->u0.S [J].Label=Labelid+Labadjust; } else { if (EntryLower) { /* do unsigned subtract */ Entry=(Entry&0x7FFFFFFF)-Tab->Lower; if (Entry<0) Entry&=0x7FFFFFFF; } else { Entry-=Tab->Lower; } Tab->u0.R [Entry]=BLocateLabel(Labelid+Labadjust,0); } return ; } } Mabort(3); } /* Mswitchlabel */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ /***/ /**************************************************************************/ /** **/ /** label and line number processing **/ /** **/ /**************************************************************************/ /***/ /***/ void Mlabel(int label) { /****************************************************************/ /** define the current point as the nominated label **/ /****************************************************************/ struct fragfmt *Frag; Frag=PI->curfrag; if ((Frag->labindex!=0)||(PI->fragsize!=0)) BBreakFrag(0); Frag=PI->curfrag; Frag->labindex=BLocateLabel(label+Labadjust,1); /**/ rclearregs(1); /* update register memory */ } /* Mlabel */ /***/ void Mgloballabel(int Label) { /*************************************************************************/ /** define the current point as the nominated global label Ie one **/ /** that can be reached by out of block jump or exception **/ struct fragfmt *Frag; Frag=PI->curfrag; if ((Frag->labindex!=0)||(PI->fragsize!=0)) BBreakFrag(0); Frag=PI->curfrag; Frag->labindex=BLocateLabel(Label+Labadjust,1); Frag->props|=GLOBALLABFRAG; /**/ rclearregs(1); /* update register memory */ } /* Mgloballabel */ /*************************************************************************/ /***/ void Mfrlabel(int label,int count) { /****************************************************************/ /** define the current point as the nominated label **/ /** as Mlabel but only used for "count" forward refs **/ /** consequently may not have to discard 100 of register **/ /** tracking information **/ /****************************************************************/ struct fragfmt *Frag,*LFrag; struct lrecfmt *lrec; int index; Frag=PI->curfrag; if ((Frag->labindex!=0)||(PI->fragsize!=0)) BBreakFrag(0); Frag=PI->curfrag; index=BLocateLabel(label+Labadjust,1); Frag->labindex=index; lrec=BLabRecAd(index); /**/ /*RT %IF Language # CCOMP %OR LanguageVariant # USLC %THENSTART */ if (count<=0) { count=0; LFrag=lrec->freffrag; while ((int)LFrag!=0) { if (index==LFrag->labref) count++; LFrag=(struct fragfmt*)(LFrag->nextfrag); } } /*RT %FINISH */ /**/ if (((Language!=CCOMP)||(LanguageVariant!=USLC))&&(count==0)) return ; /* never referenced*/ /* The above restriction is due to a bug in USLC which has been fixed */ /* on some platforms. There are code advantages in restoring this line */ /* if working with a corrected C front end */ if ((count>0)&&(count<3)) { #if((Target==RS6)||(Target==MIPS)||(Target==SPARC)||(Target==PENTIUM)) ARCH(frlabel(Frag->labindex,count,(int)PI->curfrag)); return ; #endif } /**/ /*if no target dependent routine provided clear all register tracking */ /**/ rclearregs(1); /* update register memory */ } /* Mfrlabel */ /***/ void MonetimeLabel(int label) { /*************************************************************************/ /** Here is a label that the Front End warrants is used only once **/ /** If it is a forward ref do an Mfrlabel else Mlabel **/ /*************************************************************************/ struct fragfmt *Frag; struct lrecfmt *lrec; int index; Frag=PI->curfrag; if ((Frag->labindex!=0)||(PI->fragsize!=0)) BBreakFrag(0); Frag=PI->curfrag; index=BLocateLabel(label+Labadjust,1); Frag->labindex=index; lrec=BLabRecAd(index); if (lrec->freffrag!=PI->curfrag) { ARCH(frlabel(Frag->labindex,1,(int)PI->curfrag)); } else { rclearregs(1); /* update register memory lose all tracking*/ } } /*Monetimelabel*/ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ static int labadad(int index) { /****************************************************************/ /** Provide the address of the label reference record with **/ /** given index **/ /****************************************************************/ int Scale,I,J; Scale=16; I=(unsigned)index>>6; /* units of 64 entries (1024 bytes) */ if (I>ublabadheads) Mabort(47); /* labadheads table overflow */ J=labadheads [I]; if (J==0) { J=(int)BMalloc(1024,1,MALABADADAREA); labadheads [I]=J; } return J+((index&0x3F)*Scale); } /* labadad */ /***/ /**/ /* Copyright (c) 1991 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void Maddrlabel(int label,int area,int offset) { /****************************************************************/ /** note a location to be fixed up with a label address **/ /****************************************************************/ struct labadfmt *labad; Numlabadkeys++; labad=(struct labadfmt*)(labadad(Numlabadkeys)); labad->labkey=BLocateLabel(label+Labadjust,0); labad->area=area; labad->offset=offset; labad->reffrag=(int)PI->curfrag; } /* Maddrlabel */ /***/ int Maddressedlabel(int labkey) { /****************************************************************/ /** Return 1 if labkey refers to a label which has had its */ /** address taken, else return 0. */ /****************************************************************/ struct labadfmt *labad; int i; if (Numlabadkeys>0) { for (i=1; i<=Numlabadkeys; i++) { labad=(struct labadfmt*)(labadad(i)); if (labad->labkey==labkey) return 1; } } return 0; } /* M addressed label */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void Mplabel(int label) { /****************************************************************/ /** define the current point as the nominated private label **/ /** this is used only when no register memory can be affected **/ /****************************************************************/ struct fragfmt *Frag; Frag=PI->curfrag; if ((Frag->labindex!=0)||(PI->fragsize!=0)) BBreakFrag(0); Frag=PI->curfrag; Frag->labindex=BLocateLabel(label+Labadjust,1); } /* Mplabel */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void Mline(int lineno,int prefix) { /****************************************************************/ /** note that the current point is the start of nominated line **/ /****************************************************************/ struct instrfmt *instr; if (lineno!=0) { codelisting=primecodelisting; /*if IMP switch on after preamble*/ instr=BNewInstr(); instr->group=LINENUMBER; instr->u1.immval=lineno; instr->u0.offset=prefix; /**/ if ((PI->proclevel>0)&&(setlineno!=0)) { estklit(lineno); estkdir(STACK,PI->markerad-12,0,4); eop(ESTORE); } /**/ } } /* Mline */ /***/ /**/ /* Copyright (c) 1993 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void MPrintLine(int line,int prefix) { /****************************************************************/ /** Prints the given line number with the given line prefix **/ /****************************************************************/ CPrintLine(line,prefix); } /*MPrintLine*/ /***/ /**/ /* Copyright (c) 1993 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ int MAddLinePrefix(int line,int prefix) { /****************************************************************/ /** Creates a new line prefix out of the given line number and **/ /** an existing prefix. Returns the address of the prefix **/ /** record. **/ /****************************************************************/ struct LinePrefixFmt *LinePrefix; if ((LinePrefixAddr==0)||((LinePrefixIndex+SIZELINEPREFIXFMT)>SIZELINEPREFIXCHUNK)) { LinePrefixAddr=(int)BMalloc(SIZELINEPREFIXCHUNK,1,MALINEPREFIXES); LinePrefixIndex=0; } LinePrefix=(struct LinePrefixFmt*)(LinePrefixAddr+LinePrefixIndex); LinePrefix->line=line; LinePrefix->parent=prefix; LinePrefixIndex+=SIZELINEPREFIXFMT; return (int)LinePrefix; } /* MAddLinePrefix */ /***/ /**/ /* Copyright (c) 1993 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void Mlinedebug(int Lineno) { /********************************************************************/ /** note that the nominated line requires debugging info generated **/ /********************************************************************/ struct instrfmt *instr; if (Lineno!=0) { instr=BNewInstr(); instr->group=LINEDEBUG; instr->u1.immval=Lineno; } } /*Mlinedebug*/ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ /***/ /**************************************************************************/ /** **/ /** code fragment processing **/ /** **/ /**************************************************************************/ /***/ /***/ static void tidyfrags(int proclevel,int procfrag) { /****************************************************************/ /** process all the fragments for the current procedure and **/ /** generate the code and fixups as requested **/ /****************************************************************/ static int procbaseca; struct fragfmt *frag; struct Swtabfmt *Tab; int K,passes,nextfrag; if (PI->fragsize!=0) BBreakFrag(0); passes=0; #if(Target==MIPS) if (fixedca==0) ARCH(abiinit(&fixedca)); /* put ABI specific marker at head of code */ #endif Cprocessproc(); /***/ /** extra pass - procedure peephole optimisations and scheduling */ /***/ COptimiseProc(); /***/ /** update the procedure descriptor with the new frame size - this may have been*/ /** altered by the optimisations */ /***/ PI->framesize=(PARAMBASE+PI->saveareasize)+PI->localsize; #if(Target!=PENTIUM) /* outgoing parameters pushed on stack so not included in stack */ /* frame size on pentium */ PI->framesize=PI->framesize+PI->outparsize; #endif PI->framesize=(PI->framesize+7)&(-8); if ((Target==RS6)) { PI->framesize=(PI->framesize+15)&(-16); } PI->ffsize=PARAMBASE+PI->saveareasize; #if(Target!=PENTIUM) /* outgoing parameters pushed on stack so not included in stack */ /* frame size on pentium */ PI->ffsize=PI->ffsize+PI->outparsize; #endif PI->ffsize=(PI->ffsize+7)&(-8); #if((Target==RS6)&&(TargetABI==SunsoftABI)) if (proclevel>0) CgenerateTBT(&fixedca,codelisting); /* o-p IBM traceback table*/ #endif procbaseca=fixedca; /***/ /** first pass - fixing all label addresses */ /***/ again: nextfrag=procfrag; /*first fragment for this procedure*/ while (nextfrag!=0) { frag=(struct fragfmt*)(nextfrag); nextfrag=(int)frag->nextfrag; #if(Target==MIPS) if (passes==0) eliminatehazards(frag); #endif Cestablishca(frag,&fixedca /*updating fixedca*/); /**/ /* if switch tables go into text segment allow the space */ /**/ if ((Target!=MIPS)&&(frag->switchtab!=0)) { Tab=(struct Swtabfmt*)(frag->switchtab); if (Tab->Mode!=SPARSESWITCH) { fixedca=((fixedca+(Tab->Entries<<2))+3)&(-4); /*word align*/ } } } /***/ /** extra pass for targets with short jumps check all jumps will reach */ /***/ K=0; nextfrag=procfrag; while (nextfrag!=0) { frag=(struct fragfmt*)(nextfrag); nextfrag=(int)frag->nextfrag; K+=Cvalidatejumps(frag); } if (K>0) { /* some jumps have been expanded */ fixedca=procbaseca; /* Must reestablish address and check again */ passes++; goto again; } /***/ /** second pass - fill in all the jumps and request fixups */ /***/ /***/ nextfrag=procfrag; /*first fragment for this procedure*/ while (nextfrag!=0) { frag=(struct fragfmt*)(nextfrag); nextfrag=(int)frag->nextfrag; #if((Target==SPARC)||(OutputASSEMBLER==Negative)) Cgeneratefrag(frag); #endif if (((Target!=SPARC)&&(OutputASSEMBLER==Positive))||(codelisting!=0)) { Cdisasfrag(frag); } } #if(Target==RS6) if (((TargetABI==AIXABI)||(TargetABI==ADIABI))&&(proclevel>0)) CgenerateTBT(&fixedca,codelisting); /* o-p IBM traceback table */ #endif #if(Language==FORTRAN) if ((Target==MIPS)&&(setdbx!=0)) /*SL update*/{ struct lrecfmt *Lrec; int lindex,I; for (I=1; I<=NumEntrys; I++) { lindex=BLocateLabel(EntryRecs [I].lab+Labadjust,0); Lrec=BLabRecAd(lindex); /*label record for jump back*/ EntryRecs [I].labad=Lrec->frag->address; } NumEntrys=0; }; #endif /***/ /** reclaim fragment and instruction record space */ /***/ BFreeAllocation(); } /* tidy frags */ /***/ int MGetProcOffset(int Id) { struct Exdatafmt *Exdata; #if(!((OutputASSEMBLER==Positive)&&(Language==CCOMP))) Exdata=exrecad(Id); if (Exdata->PutId==0) { Exdata->PutId=pxname(Exdata->flags,Exdata->Name); } return Exdata->PutId; #endif } /* MGetProcOffset */ /***/ void MEndProcs() { /******************************************************************/ /** Generates code for any outstanding level 0 instructions - no **/ /** further code should be generated after this call **/ /******************************************************************/ struct fragfmt *Level0; int PIaddr,rangeproc; Level0=(struct fragfmt*)(ProcInfo [0].procfrag); if (((int)Level0!=0)&&(Level0->firstinstr!=0)) { PI=&ProcInfo [0]; PIaddr=(int)&ProcInfo [0]; currentPIaddr=PIaddr; CsetPI(PI); BSetPI(PIaddr); rangeproc=BGetTraceProc(); if ((rangeproc==0)||(rangeproc==PI->procnum)) { Creport(GlobCodeReport); } else { Creport(0); } tidyfrags(0,(int)ProcInfo [0].procfrag); ProcInfo [0].procfrag=0; ProcInfo [0].curfrag=0; } } /* MEndProcs */ /***/ void Mtidyend(int *codesize) { /****************************************************************/ /** Generate fixups for referenced procedures **/ /** Set codesize **/ /****************************************************************/ struct fragfmt *labelfrag,*Level0; struct Exdatafmt *Exdata,*Exfix; struct labadfmt *labad; struct lrecfmt *Lrec; int I,PIaddr,rangeproc; /* generate any code passed in level 0 after the last Eprocend */ Level0=(struct fragfmt*)(ProcInfo [0].procfrag); if (((int)Level0!=0)&&(Level0->firstinstr!=0)) { PI=&ProcInfo [0]; PIaddr=(int)&ProcInfo [0]; currentPIaddr=PIaddr; CsetPI(PI); BSetPI(PIaddr); rangeproc=BGetTraceProc(); if ((rangeproc==0)||(rangeproc==PI->procnum)) { Creport(GlobCodeReport); } else { Creport(0); } tidyfrags(0,(int)ProcInfo [0].procfrag); } *codesize=fixedca; /***/ #if(!((OutputASSEMBLER==Positive)&&(Language==CCOMP))) for (I=Firstuserexname; I<=Numexnames; I++) { Exfix=exrecad(I); Exdata=Exfix; if (Exfix->backlink!=0) Exdata=exrecad(Exfix->backlink); /**/ /* If the symbol not defined to put and not defined by use (ca set) */ /* then define it as an external symbol */ /**/ if ((Exdata->PutId==0)&& ((Language==FORTRAN)||((Exdata->Props&0x100)!=0)|| (Exdata->Refad!=0)||(Exdata->Desrefad!=0)||(Exfix->backlink!=0))) { /* Avoid putting a redundant symbol into symtable */ Exdata->PutId=pxname(Exdata->flags,Exdata->Name); } if (Exfix->Refad!=0) { if (Exdata->Ca>0) { pfix2(Exfix->Area,Exfix->Refad,CODE,Exdata->Ca,0); } else { pfix2(Exfix->Area,Exfix->Refad,Exdata->PutId,0,0); } } /**/ /* the next block is not required unless descriptors are used for formal procedures*/ /**/ if ((Target==RS6)&&(Exfix->Desrefad!=0)) { if (Exdata->DesId==0) { Exdata->DesId=pxname(1,Exdata->Name); /* no dot */ pfix2(GLA,Exfix->Desrefad,Exdata->DesId,0,0); } } }; #endif /***/ /***/ /** Output any special symbols required */ /***/ #if(Target==RS6) ARCH(outspecialsyms()); #endif /***/ /***/ /** fix up any label addresses */ /***/ /***/ #if (OutputASSEMBLER!=Positive || Language!=CCOMP) if (Numlabadkeys>0) { for (I=1; I<=Numlabadkeys; I++) { labad=(struct labadfmt*)(labadad(I)); Lrec=BLabRecAd(labad->labkey); /* check if dummy to prevent optimisation */ if (!((labad->area==0)&&(labad->offset==0))) { labelfrag=Lrec->frag; pd4(labad->area,labad->offset,0); pfix2(labad->area,labad->offset,1,labelfrag->address,0); } } } #endif } /* Mtidyend */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ /***/ /**************************************************************************/ /** **/ /** setmarker support **/ /** **/ /**************************************************************************/ /***/ /***/ struct instrfmt *Mmarker() { /****************************************************************/ /** note the current instruction to relate subsequent call of **/ /** msetopd **/ /****************************************************************/ struct instrfmt *instr; instr=BNewInstr(); instr->group=MARKER; return instr; } /* Mmarker */ /***/ int Mbrac(int type,int privateinfo) { /*************************************************************************/ /** Puts a private marker in the code for updating sdb-dbx tables **/ /*************************************************************************/ struct instrfmt *instr; instr=BNewInstr(); instr->opcode=type; instr->group=DBXINFO; instr->u1.immval=privateinfo; return (int)instr; } /* Mbrac */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ int Mnotecodefix(int area,int offset,int toffset) { /*************************************************************************/ /** Put a marker into code so as to be able to fix area & offset **/ /** to point to current address + toffset **/ /*************************************************************************/ struct instrfmt *instr; instr=BNewInstr(); instr->area=area; instr->u0.offset=offset; instr->u1.immval=toffset; instr->group=FIXUPPOINT; return (int)instr; } /* Mnotecodefix */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void Msetopd(struct instrfmt *Markerinstr,int NewValue) { /****************************************************************/ /** substitute or add the new value for the lit in the **/ /** instruction following markerid. **/ /** If the procedure has side entries their must be a chain of **/ /** markers linked by _immval. Other _immval must be zero. **/ /****************************************************************/ struct instrfmt *instr; int origval,nextid,Markerid; Markerid=(int)Markerinstr; if (Markerid<0) { printf("Dangerous and unsupported Code Gen Facility called \n"); Markerinstr=(struct instrfmt*)(-Markerid); } instr=Markerinstr; nextid=instr->u1.immval; origval=NewValue; /* save for chain */ if (instr->group!=MARKER) Mabort(999); instr=instr->nextinstr; #if(Target==SPARC) if (instr->opcode==SETHI) { struct instrfmt *nextinstr; /**/ nextinstr=instr->nextinstr; if (Markerid<0) { /* add to existing */ NewValue=(NewValue+(instr->u1.immval<<10))+nextinstr->u1.immval; } /**/ if ((-4096<=NewValue)&&(NewValue<=4095)) { nextinstr->u1.immval=NewValue; nextinstr->rs1=0; /*%g0*/ BDeleteInstr(instr,1); } else { instr->u1.immval=(unsigned)NewValue>>10; if ((NewValue&0x3FF)==0) BDeleteInstr(nextinstr,1); else nextinstr->u1.immval=NewValue&0x3FF; ; } BDeleteInstr(Markerinstr,1); if (nextid!=0) Msetopd((struct instrfmt *)nextid,origval); return; } if (instr->opcode==SAVE) { /* default instructions are: */ /* sethi %hi(0), %g2 */ /* or %g2, 0, %g2 */ /* marker */ /* save %sp, %g2, %sp */ if (NewValue<-4096) { instr=instr->previnstr; /* marker */ instr=instr->previnstr; /* or */ instr=instr->previnstr; /* sethi */ instr->u1.immval=(unsigned)NewValue>>10; NewValue&=0x3FF; if (NewValue==0) BDeleteInstr(instr->nextinstr,1); else { instr=instr->nextinstr; instr->u1.immval=NewValue; } BDeleteInstr(instr->nextinstr,1) /* throw marker away */; } else { BDeleteInstr(instr->previnstr,1) /* throw marker away */; BDeleteInstr(instr->previnstr,1) /* throw or away */; BDeleteInstr(instr->previnstr,1) /* throw sethi away */; instr->variant=REGOPIMM; /* convert to immed. */ instr->u1.immval=NewValue; /* and plug */ instr->rref=(1<opcode==cau) { struct instrfmt *nextinstr; /**/ /* rs6000 32 bit operand as used to claim stack frames */ /* cut down to immval if possible */ /**/ nextinstr=instr->nextinstr; if (Markerid<0) NewValue+=(instr->u1.immval<<16)|nextinstr->u1.immval; /**/ if ((-32768<=NewValue)&&(NewValue<=32767)) { BDeleteInstr(instr,1); /*throw away cau */ nextinstr->opcode=cal; nextinstr->u1.immval=NewValue; nextinstr->rs1=0; /* may not have been correc*/ nextinstr->group=10; instr=(struct instrfmt*)(nextinstr->nextinstr); if (instr->opcode==stux) { BDeleteInstr(nextinstr,1); /*throw away cal */ instr->opcode=stu; /*change to immediate form */ instr->u1.immval=NewValue; instr->rdef=1<rs1; instr->rref=(1<rs1)|(1<rd); } } else { instr->u1.immval=(unsigned)NewValue>>16; nextinstr->u1.immval=NewValue&0xFFFF; } BDeleteInstr(Markerinstr,1); if (nextid!=0) Msetopd((struct instrfmt *)nextid,origval); return; }; /* Traget=rs6000*/ #endif #if(Target==MIPS) if (instr->opcode==lui) { struct instrfmt *nextinstr; /**/ /* MIPS 32 stack frame claim is used cut down if possible */ /**/ nextinstr=instr->nextinstr; if (Markerid<0) NewValue+=(instr->u1.immval<<16)|nextinstr->u1.immval; /**/ if ((-32768<=NewValue)&&(NewValue<=32767)) { BDeleteInstr(instr,1); /*throw away lui */ struct instrfmt *instr; nextinstr->opcode=addi; nextinstr->u1.immval=NewValue; nextinstr->rs1=0; /* may not have been correct*/ nextinstr->group=6; instr=(struct instrfmt*)(nextinstr->nextinstr); if (instr->opcode==add) { BDeleteInstr(nextinstr,1); /*throw away cal */ instr->opcode=addiu; /*change to immediate form */ instr->group=INTOPSu; instr->u1.immval=NewValue; instr->rdef=1<rs1; instr->rref=(1<rs1)|(1<rd); } } else { instr->u1.immval=(unsigned)NewValue>>16; nextinstr->u1.immval=NewValue&0xFFFF; } BDeleteInstr(Markerinstr,1); if (nextid!=0) Msetopd((struct instrfmt *)nextid,origval); return; }; /* Target = mips */ #endif /**/ if (Markerid<0) { /* add to existing */ instr->u1.immval=instr->u1.immval+NewValue; } else { instr->u1.immval=NewValue; } BDeleteInstr(Markerinstr,1); if (nextid!=0) Msetopd((struct instrfmt *)nextid,origval); } /* Msetopd */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ /***/ /**************************************************************************/ /** **/ /** procedure administration **/ /** **/ /**************************************************************************/ /***/ /***/ int Mgetuniqueprockey(char * S,int area,int offset,int Id) { /****************************************************************/ /** Set up a unique fixup to proc with name S **/ /** It has to be unique because int *fn() = fred can be **/ /** re-assigned later in the program. **/ /** However the proc is not unique and its name may be Known **/ /** Id > 0. Return the Id (exrecad index) given or created **/ /****************************************************************/ struct Exdatafmt *Exdata; Numexnames++; Exdata=exrecad(Numexnames); memset(Exdata,0,sizeof( struct Exdatafmt)); strcpy(Exdata->Name,S); Exdata->Refad=offset; Exdata->Area=area; Exdata->Ca=-1; /*will be >=0 when entry address is known*/ Exdata->Props=0x100; /* means do not re-use */ if (Id<0) Id=Numexnames; else Exdata->backlink=Id; return Id; } /* Mgetuniqueprockey */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ int Mgetprockey(int Flags,char * S) { /****************************************************************/ /** S # "" return a unique index, possibly already assigned, **/ /** through which to reference this external procedure **/ /** = "" providing a key in advance for an internal proc **/ /** **/ /** Flags = 0 if S is allowed to be subsequently modified in **/ /** accordance with normal UNIX naming conventions **/ /** Flags = 1 if S may not be changed (by PUT or anyone else) **/ /** Flags&2 must be zero nonzero means a data xref(AIX) **/ /** Flags&4 set if internal **/ /** Flags&8 set if symbol has no self aliases **/ /** Flags&16 set if symbol is refernced in call on AIX **/ /** Flags&32 set if symbol is an entry point **/ /** Flags&64 set if symbol is data item requiring a TOC entry **/ /** Flags&128 set if proc has no GOT refs in PIC **/ /** Flags&256 set if proc has been entered after GOT setup **/ /****************************************************************/ struct Exdatafmt *Exdata; int I; if ((Numexnames>0)&&(strcmp(S,"")!=0)&&((Flags&4)==0)) /*not internal*/{ for (I=1; I<=Numexnames; I++) { Exdata=exrecad(I); if ((strcmp(Exdata->Name,S)==0)&&((Exdata->flags&7)==Flags)&& ((Exdata->Props&0x100)==0)) { return I; } } } Numexnames++; Exdata=exrecad(Numexnames); memset(Exdata,0,sizeof( struct Exdatafmt)); strcpy(Exdata->Name,S); Exdata->Refad=0; /*no space for reference allocated until required*/ Exdata->Ca=-1; /*will be >=0 when entry address is known*/ if (strcmp(S,"")==0) Flags|=4; /* call from Enextproc */ Exdata->flags=Flags; return Numexnames; } /* Mgetprockey */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void Mnoteentry(char * S,int Id) { /****************************************************************/ /** record that Id, obtained by Mgetprockey(""), is S **/ /****************************************************************/ struct Exdatafmt *Exdata; Exdata=exrecad(Id); strcpy(Exdata->Name,S); if ((Language==CCOMP)&&(LanguageVariant==USLC)&&(S[1-1]=='.')) Exdata->flags=Exdata->flags|4; } /* Mnoteentry */ /***/ void Mareaalign(int Id,int Align) { /*************************************************************************/ /** Specify the alignment needs of area Id **/ /*************************************************************************/ struct Exdatafmt *exdata; exdata=exrecad(Id); if ((Align<=0)||((Align&(Align-1))!=0)) Align=1; exdata->align=Align; } /*M area align*/ /***/ int MSetEntityProps(int Id,int type,int vector) { /*************************************************************************/ /** Specify the properties of of external symbol or procedure. If type **/ /** is 0 then the following procedure properties may be added to the **/ /** procedure using the following bits in vector. If type is 1 then the **/ /** properties may be removed. This should only be used on ids **/ /** representing internal or external procedures: **/ /** 2**0 Set if external **/ /** 2**1 Set if main entry **/ /** 2**2 Set if display not required (Implied for FORTRAN & C) **/ /** 2**3 Set if there are no local variables **/ /** 2**4 Set if this is a side entry **/ /** 2**5 Set if there are no internal blocks or procedures **/ /** 2**6 Set to fill the stack with the unassigned pattern **/ /** 2**7 Set if this procedure contains side entries **/ /** 2**8 Used by Mtidyend for pfix calls **/ /** 2**9 Set if this procedure returns an aggregate **/ /** 2**10 Set if there are no pointers or aliases to locals **/ /** 2**11 Set if this proc is to be called from .init **/ /** 2**12 Set if this proc is to be called from .fini **/ /** 2**13 Set if proc contains calls with unknown control flow **/ /** 2**14 Set is proc has unknown return flow **/ /** 2**15 Set if proc is a special buffer handling function **/ /** **/ /** If type is 2 then the following symbol flags may be added to the **/ /** symbol. If type is 3 then the flags may be removed: **/ /** 2**0 Set if symbol name not to be changed by PUT **/ /** 2**1 Set if symbol is data external reference on AIX **/ /** 2**2 Set if symbol is internal **/ /** 2**3 Set if symbol has no self aliases for internal pointers **/ /** 2**4 Set if symbol represents a called function on AIX **/ /** 2**5 Set if symbol defined as an entry point **/ /** 2**6 Set if symbol is data item requiring a TOC entry on AIX **/ /** **/ /** The new set of procedure properties or symbol flags are returned. **/ /*************************************************************************/ struct Exdatafmt *exdata; exdata=exrecad(Id); if (type==0) { exdata->Props|=vector&0xFFFF; return exdata->Props; } else if (type==1) { exdata->Props&=~(vector&0xFFFF); return exdata->Props; } else if (type==2) { exdata->flags=exdata->flags|vector; return exdata->flags; } else if (type==3) { exdata->flags=exdata->flags&(~vector); return exdata->flags; }; Mabort(80); return 0; } /*M SetEntityProps*/ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ int MgetAreaAlign(int Id) { /*************************************************************************/ /** Returns the mininum alignment essential for are Id **/ /*************************************************************************/ struct Exdatafmt *exdata; exdata=exrecad(Id); return exdata->align; } /*M get areaalign */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void Mgetprocaddr(char * S) { /****************************************************************/ /** stack a location which will contain the procedure address **/ /** this procedure ignores the protocol for procedure arguments**/ /****************************************************************/ int Id; struct Exdatafmt *exdata; Id=Mgetprockey(0,S); exdata=exrecad(Id); if (exdata->Refad==0) { exdata->Refad=epermspace(4,4); exdata->Area=GLA; } estkdir(exdata->Area,exdata->Refad,0,4); } /* Mgetprocaddr */ /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ int Msetprocref(int area,int offset,char * S,int Id) { return Mgetuniqueprockey(S,area,offset,Id); } /* Msetprocref */ /***/ #if((Language==CCOMP)&&(LanguageVariant==USLC)) char * Mgetname2(int id) { /*************************************************************************/ /** Return the name of an external symbol for use by front end **/ /** outputting assembler. Prepend prefix for externals **/ /*************************************************************************/ struct Exdatafmt *exdata; unsigned char Firstchar; exdata=exrecad(id); Firstchar=(*(unsigned char *)((int)exdata->Name+1)); if ((Firstchar=='.')||(Firstchar=='@')) return exdata->Name; return imp_concat(exnameprepend,exdata->Name); }; /*Mgetname2*/ #endif /***/ char * Mgetname(int id) { /*************************************************************************/ /** Return the address of the name of an external symbol for use **/ /** by front end outputting assembler **/ /*************************************************************************/ struct Exdatafmt *exdata; exdata=exrecad(id); return exdata->Name; } /*Mgetname*/ /***/ char * Mexname(char * stname) { static char S[256]; if (Target==SPARC || OutputASSEMBLER==Negative || stname[0]==64 || stname[0]=='.') { return stname; } else { strcpy(exnameprepend,S); strcat(S,stname); return S; } } /* Mexname */ /***/ #if((Target==RS6)&&(TargetABI==AIXABI)) /* version for procedure descriptors RS6 (AIX) and EMAS are the only candidates*/ void Mgetprocref(int Id,int Level) { /****************************************************************/ /** stack a location which will contain the procedure address **/ /** this procedure takes account of the protocol for procedure **/ /** arguments **/ /** All languages have to use the protocol because of the TOC **/ /** Short cuts used by C and Fortran etc may well not work **/ /****************************************************************/ int refoff,refarea; struct Exdatafmt *Exdata; Exdata=exrecad(Id); if ((Level<=(FirstDisplayLevel-1))&&((Exdata->flags&4)==0)) { /* passing external */ if (Exdata->Desrefad==0) Exdata->Desrefad=epermspace(4,4); pd4(GLA,Exdata->Desrefad,0); estkdir(GLA,Exdata->Desrefad,0,4); /* return desc ptr */ return ; } /**/ /* section for internal procs also externals with forward references(specs) */ /**/ if (Exdata->Refad==0) { Exdata->Refad=epermspace(4,4); Exdata->Area=GLA; } estkdir(Exdata->Area,Exdata->Refad,0,4); if (Level<=(FirstDisplayLevel-1)) { refoff=epermspace(12,4); refarea=GLA; /* put in GLA so it persists */ } else { refoff=etempspace(12,4) /* Others need a 3-word struct with : */; refarea=STACK; } estkdir(refarea,refoff,0,4); eop(ESTORE); /* .entrypoint address in word 1 */ Level++; /* %spec level -> body level */ if (Level<=FirstDisplayLevel) { estklit(0); } else { PI->privprops|=CALLSINTERNAL; estkaddr(STACK,-(((Level-FirstDisplayLevel)+1)<<2),0,4); } Cstackr(TOCREG,4) /* Toc register */; estkdir(refarea,refoff+4,0,4); eop(ESTORE); /* TOC pointer in word 2 */ estkdir(refarea,refoff+8,0,4); eop(ESTORE); /* .zero or display pointer in word 3 */ estkaddr(refarea,refoff,0,4) /* leave address of struct on Estack */; } /* Mgetprocref */ /***/ /*not RS6*/ #else /***/ void Mgetprocref(int Id,int Level) { /****************************************************************/ /** stack a location which will contain the procedure address **/ /** this procedure takes account of the protocol for procedure **/ /** arguments **/ /****************************************************************/ int refoff; struct Exdatafmt *Exdata; Exdata=exrecad(Id); #if((Language==CCOMP)&&(LanguageVariant==USLC)) estkaddr(Id,0,0,4); return ; #else if (Exdata->Refad==0) { Exdata->Refad=epermspace(4,4); Exdata->Area=GLA; pd4(GLA,Exdata->Refad,0); } estkdir(Exdata->Area,Exdata->Refad,0,4); /* PASCAL, MODULA, C and C++ just need the address of entrypoint */ if ((Language==IMP)) { refoff=etempspace(8,4) /* Others need a 2-word struct with : */; estkdir(STACK,refoff,0,4); eop(ESTORE); /* .entrypoint address in word 1 */ Level++; /* %spec level -> body level */ if (Level<=FirstDisplayLevel) { estklit(0); } else { PI->privprops|=CALLSINTERNAL; #if(Target==PENTIUM) estkaddr(STACK,0,0,4) /* Hardware copies display */; #else estkaddr(STACK,-(((Level-FirstDisplayLevel)+1)<<2),0,4); #endif } estkdir(STACK,refoff+4,0,4); eop(ESTORE); /* .zero or display pointer in word 2 */ estkaddr(STACK,refoff,0,4) /* leave address of struct on Estack */; } #if (Language==FORTRAN && LanguageVariant==FORTRAN90) if (Exdata->flags&4) PI->privprops|=CALLSINTERNAL; #endif #endif } /* Mgetprocref */ /***/ /*non RS6 version*/ #endif /***/ /**/ /* Copyright (c) 1989 Edinburgh Portable Compilers Ltd. All Rights Reserved.*/ /**/ /***/ void Mprecall(int Aparamprops) { /****************************************************************/ /** perform any actions necessary prior to planting parameters **/ /** note param properties **/ /** param info is preserved for nested calls **/ /****************************************************************/ int i,hidden,parbits; if (calllevel>0) { /* a nested Mprecall - maybe need to save already-loaded param regs */ /**/ /**/ /* There is a nasty problem with deeply nested calls when the parameters are */ /* constructed in the callers space. New space is required for each set */ /* of parameters unless NONE(not just the last) of the outer calls have */ /* any parameters placed. Consequently we always allocate new space unless */ /* calllevel=1 (First level of nesting) and no parameters have yet been passed*/ /* There is an optimisation for deeper nesting but it occurs too rarely */ /* for it to be worth implementing */ /**/ #if(Target==SPARC) if ((calllevel>1)||(ParI->loadedpars!=0)) { i=((*(int *)(Aparamprops+4))+11)&(~7); if (i<32) i=32; /* May be varargs rt which spills 6 always */ ARCH(oplit(SUB,STACKPOINTER,i,STACKPOINTER)) /* preserve the*/; ParI->stackadj=i; /* current param*/ }; #endif /**/ #if(Target==RS6) if (((calllevel>1)||(ParI->loadedpars!=0))) { i=((*(int *)(Aparamprops+4))+7)&(-8); if (i<32) i=32; ARCH(oplit(addi,STACKPOINTER,-(i+24)),STACKPOINTER); ARCH(storeri(st,FRAMEPOINTER,STACKPOINTER,0)); PI->privprops|=NESTEDCALLS; ParI->stackadj=i+24; }; #endif /**/ /**/ #if(Target==MIPS) if (((calllevel>1)||(ParI->loadedpars!=0))) { i=((*(int *)(Aparamprops+4))+7)&(-8); if (i<16) i=16; ARCH(oplit(addiu,STACKPOINTER,-i,STACKPOINTER)); ARCH(modinstrprops(0,FRAMEMODIFY,0,0)); ParI->stackadj=i; PI->privprops|=NESTEDCALLS; }; #endif } calllevel+=1; ParI=&ParamInfo [calllevel]; CsetParI(ParI); hidden=0; parbits=0; memset(ParI,0,sizeof( struct paramfmt)); ParI->numpars=(*(int *)(Aparamprops)); ParI->paramsize=(*(int *)(Aparamprops+4)); ParI->firstpar=FreeParword; ParI->nextpar=FreeParword; #if(Target==PENTIUM) /* but discriptor array is Fward */ i=ParI->numpars-1; while (i>=0) { Parwords [FreeParword]=(*(int *)((Aparamprops+8)+(i<<2))); parbits|=1<<(((unsigned)Parwords [FreeParword]>>24)&15); i--; FreeParword++; } #else i=0; while (inumpars) { Parwords [FreeParword]=(*(int *)((Aparamprops+8)+(i<<2))); parbits|=1<<(((unsigned)Parwords [FreeParword]>>24)&15); i++; FreeParword++; } #endif if (((Target==RS6)||(Target==MIPS)||(Target==PENTIUM)) && ((parbits&((1<