! File: CODE.BLI ! ! This work was supported by the Advanced Research ! Projects Agency of the Office of the Secretary of ! Defense (F44620-73-C-0074) and is monitored by the ! Air Force Office of Scientific Research. ! Module CODE= Begin ! ! CODE MODULE ! ------------ ! ! SEPT. 1972 ! WULF,JOHNSSON,WEINSTOCK ! LATER ADDITIONS: ! LEVERETT,KNUEVEN ! ! THIS MODULE PRODUCES THE ACTUAL PDP-11 MACHINE CODE. IT IS ! EXECUTED AFTER DELAYING AND TEMP-NAME BINDING. THEREFORE ESSENTIALLY ! ALL RELEVANT INFORMATION IS KNOWN. THE PRIMARY FUNCTION OF 'CODE', ! IN ADDITION TO GENERATING THE CODE, IS TO DO THE (RATHER EXTENSIVE) ! SPECIAL CASE ANALYSIS TO PRODUCE LOCALLY OPTIMAL CODE. THUS, FOR ! EXAMPLE, IT IS CODE THAT DETERMINES THE OPTIMAL SEQUENCE OF MASKING, ! ROTATE AND/OR SHIFT, AND 'SWAB' INSTRUCTIONS TO ISOLATE A SUBFIELD ! AND TO ALIGN IT AT A SPECIFIED LOCATION IN A WORD. ! ! THE MAJOR PORTIONS OF CODE ARE: ! ! 1. CODE/LABEL PLACEMENT ! THESE ROUTINES ACTUALLY EMIT THE CODE AND/OR ! LABELS IN A FORM SUITABLE FOR PROCESSING ! BY THE 'FINAL' MODULE. THE CODE REPRESENTATION ! CREATED BY THE ROUTINES IS A DOUBLY LINKED ! LIST -- ITS PRECISE FORM IS IRRELEVANT TO ! THIS MODULE, HOWEVER. ! ! 2. 'VERY-TEMP' ALLOCATION ! IN A FEW CASES THE FACT THAT AN ADDITIONAL ! TEMPORARY IS NEEDED IS NOT KNOWN UNTIL CODE-GENERATION ! TIME, THUS THE TEMPORARIES WILL NOT HAVE ! BEEN ALLOCATED BY 'TNBIND'. THE NECESSARY ! ROUTINES ARE DUPLICATED FROM TNBIND IN ORDER ! ALLOCATE THESE TEMPS 'ON THE FLY' DURING ! CODE-GENERATION. THE SAME PHILOSOPHY FOR ! ALLOCATION IS USED IN CODE AS IN TNBIND, ! ESPECIALLY WRT. LON'S AND FON'S,AS IN ! TNBIND. THEREFORE THEY WILL NOT BE DISCUSSED ! HERE. ! ! 3. ADDRESS GENERATION ! THIS SET OF ROUTINES, OF WHICH 'GMA' AND ! 'GMA8' ARE THE PRINCIPAL ONES, ARE SERVICE ! ROUTINES WHICH GENERATE THE ADDRESS FORMAT ! NEEDED BY 'FINAL'. THE PARAMETER ! TO EACH OF THESE ROUTINES IS A LEXEME -- ! IT MAY BE A LITERAL LEXEME, ST-LEXEME, OR ! GT-LEXEME. IN EACH CASE THE APPROPRIATE ADDRESS ! IS GENERATED. ! THE DIFFERENCE BETWEEN GMA AND GMA8 IS ONLY ! THAT GMA8 GENERATES THE ADDRESS OF THE HIGH ! BYTE OF THE WORD. ! ! 4. MOVE GENERATION ! THESE ROUTINES, PRIMARILY 'SIMPLEMOVE' AND ! 'GENMOVE', ARE SERVICE ROUTINE WHICH WILL ! GENERATE A DATA MOVE -- IF (AND ONLY IF) ! ONE IS ACTUALLY REQUIRED. SIMPLEMOVE ALWAYS ! MOVES AN ENTIRE WORD. GENMOVE WILL MOVE AN ! ARBITRARY FIELD OF ONE WORD TO AN ARBITRARY ! FIELD OF ANOTHER WORD. GENMOVE MAKES EXTENSIVE ! USE OF THE FIELD-ISOLATION AND ALIGNMENT ! ROUTINES -- SEE BELOW. ! ! 5. FIELD ISOLATION AND ALIGNMENT ! THIS SET OF ROUTINES PROVIDES THE PRIMITIVES ! FOR ISOLATING AN ARBITRARY SUBFIELD OF A ! WORD AND ALIGNING THE FIELD TO AN ARBITRARY ! POSITION IN THE WORD. ! ! 6. COMPARISON GENERATION ! THIS SET OF SERVICE ROUTINES GENERATES ! COMPARISONS BETWEEN ARBITRARY OPERANDS, WHICH ! IN PARTICULAR MAY BE SUBFIELDS OF A WORD, AND ! GENERATES BRANCHES TO SPECIFIED LABELS. THIS ! IS IN GENERAL A SIMPLE TASK, BUT THE SPECIAL ! CASE ANALYSIS IS ESPECIALLY EXTENSIVE HERE. ! ! 7. NODE-SPECIFIC ROUTINES ! CODE GENERATION IS EFFECTED BY AN EXECUTION-ORDER ! TREE WALK AND CALLING NODE-SPECIFIC ROUTINES ! AT EACH NODE. THESE ROUTINES ACTUALLY CONTROL ! THE CODE TO BE GENERATED FOR EACH NODE. THIS ! SECTION CONTAINS THESE ROUTINES. A GOOD EXAMPLE ! OF THE SPECIAL CASE ANALYSIS DONE BY THESE ! ROUTINES MAY BE FOUND BY LOOKING AT 'GID' WHICH ! GENERATES THE CODE FOR INCR/DECR STATEMENTS. ! ! 8. CODE & FREEUNDER ! THE SWITCHING TO THE NODE-SPECIFIC ROUTINES ! IS DONE HERE, AS ELSEWHERE IN THE COMPILER, ! BY SWITCHING THROUGH A 'PLIT'. THE ROUTINE ! 'CODE' ACTS AS THE CENTRAL SWITCHING AGENT. ! AS EACH NODE IS COMPLETED BY CODE THE ROUTINE ! 'FREEUNDER' IS CALLED BY IT TO RELEASE THE ! SPACE FOR THAT PORTION OF THE TREE WHICH IS ! NO LONGER NEEDED. THUS THE SPACE CONSUMED BY ! THE EMITTED CODE IS LARGELY THAT ! RELEASED FROM THE TREE. ! ! 9. CODEDRIVER ! THIS ROUTINE IS CALLED FROM 'GENIT' IN ! DRIVER TO INITIATE THE CODE GENERATION PROCESS. ! IT DOES THE NECESSARY INITIALIZATION AND ! CLEAN-UP. ! Require 'Bliss'; External Routine OUTINST : Novalue; External DYTEMPS; Own REGSCHNGD : Integer, NODVT : Integer, NOVTCNT : Integer, PLSTCNT : Integer, SIGLAB : Ref CELL, SAMETOG : Integer; ! MISC. EXTERNALS FOR CODE ONLY Structure ADRWD[P,S,E] = [8]ADRWD; External ALTERSRCDST : Vector[,Byte], OPBYTES : Vector[,Byte], OPERTYPE : Vector[,Byte]; ! LABEL HANDLING ! -------------- ! allocate a new label cell Routine GENLABEL = Begin Return NEWLABCELL(LAB_COMP,GETLABEL()) End; ! place a place at the current location Routine PLACELABEL(LAB : Ref CELL) : Novalue = Begin NCELL = AFTER(.NCELL,.LAB); NCELL[cel_min_loc] = .LOC End; ! generate a label reference operand Routine REFLABEL(LAB : Ref CELL,FRM : Ref CELL,OTYPE) = Begin Local C : Ref CELL; C = GETCELL(CELL_REF,SZ_CELL_REF); C[cel_ref_ef] = .LAB; C[cel_ref_rf] = .FRM; C[cel_class] = .OTYPE; PUSHBOT(.C[cel_ref_ef],.C); Return BUILDOPD(OPND_LABEL,RELATIVE,PC,.C) End; ! generate a label address reference operand (used only by GCASE) Routine IMMLAB(LAB : Ref CELL,FRM : Ref CELL,OTYPE) = Begin Local C : Ref CELL; C = GETCELL(CELL_REF,SZ_CELL_REF); C[cel_ref_ef] = .LAB; C[cel_ref_rf] = .FRM; C[cel_class] = .OTYPE; PUSHBOT(.C[cel_ref_ef],.C); Return BUILDOPD(OPND_LABEL,IMMEDIATE,PC,.C) End; Routine NODELABEL(NODE : Ref GT) = Begin If .NODE[gt_label] Eql 0 Then NODE[gt_label] = NEWLABCELL(LAB_COMP,GETLABEL()); Return .NODE[gt_label] End; Routine USERLABEL(LABST : Ref ST) = Begin If .LABST[st_lab_cell] Eql 0 Then LABST[st_lab_cell] = NEWLABCELL(LAB_USER,.LABST); Return .LABST[st_lab_cell] End; ! LIST-OF-NAME-DESCRIPTORS HANDLING ! ----------------------------------- Routine SEARCHLL(HEAD : Ref CELL,LABS,LABN) = Begin Local PTR : Ref CELL; PTR = .HEAD[cel_prev]; While TRUE Do Begin If .LABS Gtr .PTR[cel_sym_name] Then Exitloop; If .LABS Eql .PTR[cel_sym_name] And .LABN Geq .PTR[cel_sym_disp] Then Exitloop; PTR = .PTR[cel_prev] End; If .LABS Eql .PTR[cel_sym_name] And .LABN Eql .PTR[cel_sym_disp] Then Return .PTR Else Return AFTER(.PTR,NEWLABCELL(.LABS,.LABN)) End; ! EMIT CODE INTO INSTRUCTION STREAM ! --------------------------------- Routine PUTADR(ADR : Ref ADRVARSTR,A : ADRWD,BYTES) : Novalue = Begin Bind IMMEDZERO = ADRPLIT(2,PC,ADDR_IMMED,NAME_NORMAL,0) : ADRVARSTR; Bind ADRTYPE = Uplit Byte( ADDR_REG, ! R ADDR_MEMORY, ! @R ADDR_MEMORY, ! (R)+ ADDR_INDIRECT, ! @(R)+ ADDR_MEMORY, ! -(R) ADDR_INDIRECT, ! @-(R) ADDR_MEMORY, ! n(R) ADDR_INDIRECT, ! @n(R) UNUSED, ! PC UNUSED, ! @PC ADDR_IMMED, ! # ADDR_MEMORY, ! @# UNUSED, ! UNUSED, ! ADDR_MEMORY, ! n(PC) ADDR_INDIRECT) ! @n(PC) : Vector[,Byte]; COPYADR(.ADR,IMMEDZERO); If (.A Eql SP) Or .A Then BYTES = 2; ADR[adr_mode] = .A; ADR[adr_reg] = .A; If (.ADR[adr_mode] And 6) Eql INDEXED Or .ADR[adr_reg] Eql PC Then Case .A From LO_OPND_TYPE To HI_OPND_TYPE Of Set [Inrange]: 0; [OPND_NORMAL]: Begin ADR[adr_disp] = .A; If .A<31,1> Then ADR[adr_name_type] = NAME_FORMAL End; [OPND_NAME]: Begin ADR[adr_disp] = .ST[.A,cel_sym_disp]; ADR[adr_name] = .ST[.A,cel_sym_name] End; [OPND_LABEL]: Begin ADR[adr_name_type] = NAME_LABEL; ADR[adr_name] = .A End; [OPND_ERROR]: Begin ADR[adr_name_type] = NAME_ERROR; ADR[adr_disp] = .A End Tes; If .ADR[adr_reg] Eql SP And .ADR[adr_name] Eql 0 And .ADR[adr_mode] Neq GENREG Then ADR[adr_name] = 1; If (.ADR[adr_mode] And 6) Eql AUTOINCR And .ADR[adr_reg] Neq PC Then Begin ADR[adr_disp] = -.BYTES; ADR[adr_delta] = .BYTES; End Else If (.ADR[adr_mode] And 6) Eql AUTODECR Then ADR[adr_delta] = -.BYTES; ADR[adr_type] = .ADRTYPE[.ADR[adr_mode]+ (If .ADR[adr_reg] Eql PC Then 8 Else 0)] End; Routine CKREGSCHNGD(OP : Integer,S : ADRWD,D : ADRWD) : Novalue = Begin Macro NOTER(X)=REGSCHNGD<.X,1> = TRUE %, NOTEZ=REGSCHNGD<0,1> = TRUE %, RS(X)= If .X Eql GENREG Then NOTER(X) %, CR(X)= If ONEOF(.X,AUTOINCR,AUTOINCR+DEFERRED, AUTODECR,AUTODECR+DEFERRED) Then NOTER(X) %; Case .OPERTYPE[.OP] From LO_OPTYPE To HI_OPTYPE Of Set [OPTYPE_NOP]: If .OP Eql PIOT Then NOTEZ; [OPTYPE_ONE]: Begin If .ALTERSRCDST[.OP] Then RS(S); CR(S) End; [OPTYPE_TWO]: Begin CR(D); If .ALTERSRCDST[.OP] Then RS(D); CR(S) End; [OPTYPE_BR]: CR(S); [OPTYPE_JSR]: Begin CR(D); NOTEZ; RS(S) End; [OPTYPE_RTS]: RS(S); [OPTYPE_TRAP]: NOTEZ; [OPTYPE_WORD,OPTYPE_CASE]: 0 Tes End; Routine PUTCODE(WHERE : Ref CELL,OPT : Integer,OP : Integer,S : ADRWD,D : ADRWD) = Begin Local BYTES : Integer; CKREGSCHNGD(.OP,.S,.D); NCELL = AFTER(.NCELL,.WHERE); NCELL[cel_min_loc] = LOC = .LOC+1; NCELL[cel_class] = .OPT; NCELL[cel_code] = .OP; BYTES = .OPBYTES[.OP]; If HASSOURCE(.OP) Then PUTADR(NCELL[cel_src],.S,.BYTES); If HASDEST(.OP) Then PUTADR(NCELL[cel_dst],.D,.BYTES); Case .OPERTYPE[.OP] From LO_OPTYPE To HI_OPTYPE Of Set [Inrange]: 0; [OPTYPE_NOP]: If .OP Eql PINLINE Then NCELL[cel_inl_arg] = .S; [OPTYPE_JSR,OPTYPE_RTS]: NCELL[cel_src_reg] = .S; [OPTYPE_TRAP]: NCELL[cel_src_disp] = .S; [OPTYPE_WORD]: If .D Then NCELL[cel_hydra_word] = TRUE Tes; Return .NCELL End; Bind OPTYPLIT = UPlit Byte ( INST_INLINE, ! INLINE UNUSED, ! PMOV=1, UNUSED, ! PMOVB=2, UNUSED, ! PCMP=3, UNUSED, ! PCMPB=4, UNUSED, ! PBIT=5, UNUSED, ! PBITB=6, UNUSED, ! PBIC=7, UNUSED, ! PBICB=8, UNUSED, ! PBIS=9, UNUSED, ! PBISB=10, INST_ADD_IMMED, ! PADD=11, INST_ADD_IMMED, ! PSUB=12, UNUSED, ! PCLR=13, UNUSED, ! PCLRB=14, UNUSED, ! PCOM=15, UNUSED, ! PCOMB=16, UNUSED, ! PINC=17, UNUSED, ! PINCB=18, UNUSED, ! PDEC=19, UNUSED, ! PDECB=20, UNUSED, ! PNEG=21, UNUSED, ! PNEGB=22, UNUSED, ! PADC=23, UNUSED, ! PADCB=24, UNUSED, ! PSBC=25, UNUSED, ! PSBCB=26, UNUSED, ! PTST=27, UNUSED, ! PTSTB=28, UNUSED, ! PROR=29, UNUSED, ! PRORB=30, UNUSED, ! PROL=31, UNUSED, ! PROLB=32, UNUSED, ! PASR=33, UNUSED, ! PASRB=34, UNUSED, ! PASL=35, UNUSED, ! PASLB=36, UNUSED, ! PJMP=37, UNUSED, ! PSWAB=38, UNUSED, ! PJSR=39, UNUSED, ! PRTS=40, UNUSED, ! PHALT=41, UNUSED, ! PWAIT=42, UNUSED, ! PRTI=43, UNUSED, ! PIOT=44, UNUSED, ! PRESET=45, UNUSED, ! PEMT=46, UNUSED, ! PTRAP=47, INST_UNCOND_JUMP,! PBR=48, INST_UNCOND_JUMP,! PNBR=49, INST_COND_JUMP, ! PBNE=50, INST_COND_JUMP, ! PBEQ=51, INST_COND_JUMP, ! PBGE=52, INST_COND_JUMP, ! PBLT=53, INST_COND_JUMP, ! PBLE=54, INST_COND_JUMP, ! PBGT=55, INST_COND_JUMP, ! PBPL=56, INST_COND_JUMP, ! PBMI=57, INST_COND_JUMP, ! PBHI=58, INST_COND_JUMP, ! PBLOS=59, INST_COND_JUMP, ! PBVC=60, INST_COND_JUMP, ! PBVS=61, INST_COND_JUMP, ! PBHIS=62, INST_COND_JUMP, ! PBLO=63, UNUSED, ! PNOP=64, UNUSED, ! PCLC=65, UNUSED, ! PCLVC=66, UNUSED, ! PWORD=67, INST_CASE_PARAM,! PCASE=68, UNUSED, ! PMFPI=69, UNUSED, ! PMFPD=70, UNUSED, ! PMTPI=71, UNUSED, ! PMTPD=72, 0,0 ) : Vector[,Byte]; Routine ISLIT(L : Ref GT) = Begin If .L Eql T_LITERAL Then Return .L Else If .L[gt_type] Neq S_NODE Then Return 0 Else If .L Then Return .L Else Return 0 End; Routine CLITVALUE(L : Ref GT) = Begin If .L Eql T_LITERAL Then Return .L Else Return .L[gt_disp_16] End; Macro ISZERO(L)= (ISLIT(L) And CLITVALUE(L) Eql 0) %; Routine ISIMMEDIATE(ADR)= Begin Bind X=(BUILDOPD(OPND_NORMAL,IMMEDIATE,PC,0)^(-32)); Return .ADR<32,32> Eql X End; Routine EMIT(OP : Integer,S : ADRWD,D : ADRWD) : Novalue = Begin Local PCELL : Ref CELL, TYPE : Integer; PCELL = NEWCODECELL(); TYPE = .OPTYPLIT[.OP]; Case .TYPE From LO_INST_TYPE To HI_INST_TYPE Of Set [INST_NORMAL]: If .OP Eql PJMP Then TYPE = INST_UNCOND_JUMP; [INST_CASE_PARAM]: Begin D = REFLABEL(.D,.PCELL,.TYPE); S = REFLABEL(.S,.PCELL,.TYPE) End; [INST_INLINE]: 0; [INST_UNCOND_JUMP]: S = REFLABEL(.S,.PCELL,.TYPE); [INST_ADD_IMMED]: If Not ISIMMEDIATE(.S) Then TYPE = UNUSED; [INST_COND_JUMP]: S = REFLABEL(.S,.PCELL,.TYPE) Tes; PUTCODE(.PCELL,.TYPE,.OP,.S,.D) End; ! GET HIGHLY TEMPORARY CELLS WITHIN A NODE LIFE ! --------------------------------------------- Macro ISOKPUSHVT=(.NOVTCNT Eql 0) %, OKTOPDYTEMP=(.NODVT Eql 0 And .DYTEMPS Geq 2) %, OKALLDYTMPS=(.NODVT Eql 0 And .DYTEMPS Geq 4) %; Macro SETNOPUSHVT=NOVTCNT = .NOVTCNT+1 %, RESETPUSHVT=NOVTCNT = .NOVTCNT-1 %, SETNODYNVT=NODVT = .NODVT+1 %, RESETDYNVT=NODVT = .NODVT-1 %; ! TRY THE OPEN VERY TEMPS Routine TRYOPVTEMPS(T : Ref GT) = Begin Incr I From 0 To .VTEMPS[stk_idx] Do If TRYFIT(.T,VTEMPS[stk_item(.I)]) Then SUCCESS; FAIL End; ! OPEN A NEW VERY TEMP Routine TRYCLVTEMPS(T : Ref GT) = Begin Local TX : Ref GT, TR : Ref TNREPR, R : Ref ITEM; PUSHSTK(VTEMPS); R = VTEMPS[stk_item(.VTEMPS[stk_idx])]; OPENLIST(.R); TRYFIT(.T,.R); ! NOTE THIS WILL (SHOULD) ALWAYS WORK TR = .R; Until (TR = .TR[itm_rlink]) Eqla .R Do Begin TX = .TR[tnr_ptr]; TX[tn_type] = BNDLOCAL; TX[gt_reg] = SP; TX[gt_mode] = INDEXED; TX[gt_disp] = .VTEMPS[stk_idx] * 2 End End; Routine COPYTNDATA(TN : Ref GT) : Novalue = Begin Local L : Ref TNREPR, P : Ref GT; L = .TN[tn_bind_list]; ! 'L' points to a list header. move to the first element of the list L = .L[itm_rlink]; P = .L[tnr_ptr]; TN[tn_type] = .P[tn_type]; TN[gt_reg] = .P[gt_reg]; TN[gt_mode] = .P[gt_mode]; TN[gt_disp] = .P[gt_disp] End; Routine MARKANDCOPY(TN : Ref GT) : Novalue = Begin Local LST : Ref TNREPR, L : Ref TNREPR, N : Integer, P : Ref GT; LST = .TN[tn_bind_list]; N = (.LST-REGS[0]) / 8; L = .LST[itm_rlink]; P = .L[tnr_ptr]; P[tn_type] = BNDREG; P[gt_reg] = .N; COPYTNDATA(.TN) End; Routine MAKEPUSHVT(T : Ref GT) : Novalue = Begin If .VTN[gt_dtdelete] Eql DTDONTCARE Then VTN[gt_dtdelete] = .DYTEMPS; T[tn_type] = BNDPUSH; T[gt_reg] = SP; T[gt_mode] = INDEXED; T[gt_disp] = -(.MAXLOCALS+.STATICSIZE+.DYTEMPS+2) End; Routine VERYTEMP(X : Ref GT) = Begin Local T : Ref GT; T = GETTN(); T[tn_lon_fu] = .LON; T[tn_lon_lu] = .LON; T[tn_fon_fu] = .FON; T[tn_fon_lu] = .FON; If .X Gequ 8 And .X[tn_bind_list] Neqa 0 And TRYFIT(.T,.X[tn_bind_list]) Then COPYTNDATA(.T) Else If TRYOPREG(.T) Then COPYTNDATA(.T) Else If OKTOPDYTEMP And TRYSPDYTEMP(.T,(.DYTEMPS-2)/2) Then COPYTNDATA(.T) Else If ISOKPUSHVT Then MAKEPUSHVT(.T) Else If OKALLDYTMPS And TRYDYTEMPS(.T) Then COPYTNDATA(.T) Else If TRYOPSTEMPS(.T) Then COPYTNDATA(.T) Else If TRYCLREG(.T) Then MARKANDCOPY(.T) Else If TRYOPVTEMPS(.T) Then COPYTNDATA(.T) Else TRYCLVTEMPS(.T); Return .T End; Routine VERYTMPREG= Begin Local T : Ref GT; T = GETTN(); T[tn_lon_fu] = .LON; T[tn_lon_lu] = .LON; T[tn_fon_fu] = .FON; T[tn_fon_lu] = .FON; If TRYOPREG(.T) Then COPYTNDATA(.T) Else If OKTOPDYTEMP And TRYSPDYTEMP(.T,(.DYTEMPS-2)/2) Then COPYTNDATA(.T) Else If ISOKPUSHVT Then MAKEPUSHVT(.T) Else T = 0; Return .T End; ! ROUTINES TO HANDLE GENERATION OF MACHINE ADDRESSING FORMATS ! ------------------------------------------------------------ Macro ALOCAL(X) = BUILDOPD(OPND_NORMAL,INDEXED,SP,XLO(X)) %, DEFER(Z) = ((Z) Or ((DEFERRED)^_POS(gma_mode))) %, INDEXEDBY(R,X,T)= BUILDOPD(T,INDEXED,REGNUM(R),X) %, LOCALOFFSET(ZZZ)= (((.MAXLOCALS+.STATICSIZE+.DYTEMPS) +.ZZZ[gt_disp_16])And %x'ffff') %, MAKLIT(L) = (LITLEXEME((L) And %x'ffff')+FLD_K_LIT+FLD_K_IMM) %, MAKNAM(N) = (LEXOUT(0,N)+FLD_K_LIT+FLD_K_IMM) %, NODEFER(Z) = ((Z) And (Not((DEFERRED)^_POS(gma_mode)))) %, NXTBYTEADR(A) = BUMPBYTEADR(A,1) %, PROGCTR = BUILDOPD(OPND_NORMAL,GENREG,PC,UNUSED) %, PUSHED = BUILDOPD(OPND_NORMAL,AUTODECR,SP,UNUSED) %, POPPED = BUILDOPD(OPND_NORMAL,AUTOINCR,SP,UNUSED) %, STACKPTR = BUILDOPD(OPND_NORMAL,GENREG,SP,UNUSED) %, XLO(X) = (((.MAXLOCALS+.STATICSIZE+.DYTEMPS)+X) And %x'ffff') %, XREG(X) = BUILDOPD(OPND_NORMAL,GENREG,X,UNUSED) %, XTOS = BUILDOPD(OPND_NORMAL,DEFERRED,SP,UNUSED) %, ZPOPPED = BUILDOPD(OPND_NORMAL,AUTOINCR,0,UNUSED) %; Forward Routine GMA, ISREG, NOMOVREQD, REGNUM; Macro FLD_K_FORMAL = 1^31 %; Routine NAMEDESC(N : Ref ST) = Begin Local L : Integer, B : Ref ST; B = BASESYM(.N); L = .N[gt_disp]-.B[gt_disp]; Return SEARCHLL(.NLHEAD,.B,.L) End; Routine BUMPNAMEDESC(D : Ref CELL,N)= Begin Return SEARCHLL(.NLHEAD,.D[cel_sym_name],.D[cel_sym_disp]+.N) End; Routine BUMPBYTEADR(ADR : ADRWD,N : Integer) = Begin Case .ADR From 0 To 7 Of Set [GENREG,AUTODECR,AUTODECR+DEFERRED]: PUNT(581); [GENREG+DEFERRED]: Begin ADR = INDEXED; ADR = .N End; ! auto-increment in this situation may only be PC mode [AUTOINCR,AUTOINCR+DEFERRED,INDEXED]: If .ADR Eql OPND_NORMAL Then ADR = .ADR+.N Else ADR = BUMPNAMEDESC(.ADR,.N); [INDEXED+DEFERRED]: ! this can't be right? If .ADR Neq OPND_NORMAL Then ADR = BUMPNAMEDESC(.ADR,.N) Else Begin Local T : Ref GT; T = VERYTEMP(0); EMIT(PMOV,NODEFER(.ADR),GMA(.T)); If ISREG(.T) Then Return BUILDOPD(OPND_NORMAL,INDEXED,REGNUM(.T),.N); EMIT(PADD,GMA(MAKLIT(.N)),GMA(.T)); Return DEFER(GMA(.T)) End Tes; Return .ADR End; Routine ISIDT(N : Ref GT) = Begin If .N Eql S_NODE Then Return .N[rw_destroyable] Else Return 0 End; Routine FORGOTTEN(NODE : Ref GT,OP1 : Ref GT) = Begin Local TN : Ref GT; TN = .NODE[gt_reg]; If .TN Lss 8 Then Return FALSE; If .TN[tn_type] Eql BNDNCSE Then Return TRUE; If .TN[tn_request] Neq MEMREQDB Then Return FALSE; If .TN[gt_reg] Eql .OP1 Then Return TRUE; If .OP1 Neq T_NODE Then Return FALSE; Return FORGOTTEN(.OP1,.OP1[gt_arg1]) End; Routine ISDESTROYABLE(N : Ref GT) = Begin If .N Eql T_NODE Then Return .N[rw_destroyable] And .N[gt_mode] Eql GENREG Else If .N Eql T_LITERAL Then Return FALSE Else If .N[gt_type] Eql S_TEMPNAME Then Return (.N[tn_lon_lu] Lequ .LON And .N[tn_fon_lu] Lequ .FON) Else Return FALSE End; Routine ISREG(R : Ref GT) = Begin If .R Lss 8 THEN Return TRUE; If .R Eql T_LITERAL THEN Return FALSE; Selectone .R[gt_type] Of Set [S_REGISTER]: Return TRUE; [S_LOCAL]: If .R[gt_reg] Lss 8 Then Return FALSE Else Return ISREG(.R[gt_reg]); [S_TEMPNAME]: Begin If .R[tn_type] Eql BNDREG Then Return TRUE; If .R[tn_request] Eql MEMREQDB Then If .R[tn_type] Eql 0 Or .R[tn_type] Eql BNDPREF Then If Not .R[tn_v_lit] Then Return ISREG(.R[gt_reg]); Return FALSE End; [S_NODE]: If .R[gt_mode] Eql GENREG Then Return ISREG(.R[gt_reg]) Else Return FALSE; [Otherwise]: Return FALSE Tes End; Routine REGNUM(R : Ref GT) = Begin While .R Geqa 8 Do R = .R[gt_reg]; Return .R End; Routine LOCDEF(NODE : Ref GT) = Begin While .NODE[gt_reg] Gtra 8 Do NODE = .NODE[gt_reg]; Return .NODE End; Routine LOCDF1(NODE : Ref GT) = Begin While TRUE Do Begin If .NODE[gt_type] Eql S_TEMPNAME Then If .NODE[tn_v_lit] Then Return .NODE[tn_literal]; If .NODE[gt_reg] Lssa 8 Then Exitloop; NODE = .NODE[gt_reg] End; Return .NODE End; Routine GETOFFSET(NODE : Ref GT) = Begin Local S : Ref ST; ! if the displacement is not a symbol If Not .NODE[gt_v_symoff] Then Return .NODE[gt_disp_16]; ! get the dispacement symbol S = .NODE[gt_disp]; If .S[gt_type] Eql S_LOCAL Then Return LOCALOFFSET(S) Else If .S[gt_type] Eql S_FORMAL Then Return LOCALOFFSET(S)+FLD_K_FORMAL Else Return NAMEDESC(.NODE[gt_disp]) End; Routine ISCHEAP(NODE : Ref GT) = Begin If ISREG(.NODE) Then Return TRUE; NODE = LOCDF1(.NODE); If .NODE Eql T_LITERAL Then Return FALSE; If ISSTVAR(NODE) Then If .NODE[gt_mode] Neq GENREG Then Return FALSE; NODE = LOCALOFFSET(NODE); Return .NODE Eql 0 Or .NODE Eql 1^16-2 End; Routine GMOFF(NODE : Ref GT) = Begin If .NODE[gt_v_symoff] Then Return GMA(MAKNAM(.NODE[gt_disp])) Else Return BUILDOPD(OPND_NORMAL,IMMEDIATE,PC,.NODE[gt_disp_16]) End; ! ! generate a memory address ! ! input ! 'NODE' is a lexeme for which an address is to be ! generated. It may be a literal, node, symbol, or ! a tempname. 'NODE' includes any state bits. ! The state bits of interest are ! and . ! note: the field is only checked for T_LITERAL. ! for all other types, the [gt_type] field is used. ! several routines take advantage of this. Routine GMA(NODE : Ref GT)= Begin Local S : Ref GT, L : Integer, TN : Ref GT, T : ADRWD, NMODE : Integer, O : Ref GT, TY : Integer; ! IF NAMING A REGISTER If .NODE Lssu 8 Then Return BUILDOPD(OPND_NORMAL,GENREG,.NODE,0); ! NOW HANDLE LITERAL LEXEMES If .NODE Eql T_LITERAL Then If .NODE Then Return BUILDOPD(OPND_NORMAL,IMMEDIATE,PC,CLITVALUE(.NODE)) Else Return BUILDOPD(OPND_NORMAL,ABSOLUTE,PC,CLITVALUE(.NODE)); ! IN ALL REMAINING CASES WE USE THE TYPE FIELD IN THE NODE If .NODE[gt_type] Eql S_TEMPNAME Then Begin ! if a stack reference, generate either -(SP) or n(SP) If .NODE[tn_type] Eql BNDPUSH Then If LOCALOFFSET(NODE) Gtr 1^15 Then Begin DYTEMPS = .DYTEMPS+2; Return BUILDOPD(OPND_NORMAL,AUTODECR,SP,UNUSED) End Else Return BUILDOPD(OPND_NORMAL,INDEXED,SP,LOCALOFFSET(NODE)); ! this tempname is bound to another lexeme or another tempname. If .NODE[tn_request] Eql MEMREQDB Then If .NODE[tn_type] Eql 0 Or .NODE[tn_type] Eql BNDPREF Then If .NODE[tn_v_lit] Then Return GMA(.NODE[tn_literal]) Else ! note: the high 32 bits contains the state flags. the field ! is irrevalent as long as it is not T_LITERAL Return GMA(LEXOUT(.NODE<32,32,0>,.NODE[gt_reg])); ! if this tempname is bound to a register If .NODE[tn_type] Eql BNDREG Then Return BUILDOPD(OPND_NORMAL,GENREG,.NODE[gt_reg],0); ! use the regsiter and mode in the tempname Return BUILDOPD(OPND_NORMAL,.NODE[gt_mode],.NODE[gt_reg],LOCALOFFSET(NODE)) End; ! GRAPH TABLE CASES If .NODE[gt_type] Eql S_NODE Then Begin ! if delay folded this node to a constant If .NODE Then ! if a literal used as a value If .NODE Then Return BUILDOPD(If .NODE[gt_v_symoff] Then OPND_NAME Else OPND_NORMAL, IMMEDIATE,PC,GETOFFSET(.NODE)) Else ! if a literal used as an address (can it not be a symbol offset also?) Return BUILDOPD(OPND_NORMAL,ABSOLUTE,PC,.NODE[gt_disp_16]); ! get the mode and handle the normal cases NMODE = .NODE[gt_mode]; If .NMODE Eql GENREG Then Return GMA(.NODE[gt_reg]); If .NMODE Eql GENREG+DEFERRED Then Return DEFER(GMA(.NODE[gt_reg])); ! get the offset and determine whether it is absolute or relocatable O = GETOFFSET(.NODE); If Not .NODE[gt_v_symoff] Then TY = OPND_NORMAL Else Begin S = .NODE[gt_disp]; If ONEOF(.S[gt_type],S_LOCAL,S_FORMAL) Then TY = OPND_NORMAL Else TY = OPND_NAME End; ! handle '(R)+' and '@(R)+' If (.NMODE And 6) Eql AUTOINCR Then Return BUILDOPD(.TY,If .NODE[rw_immediate] Then IMMEDIATE Else .NMODE, REGNUM(.NODE[gt_reg]),.O); ! at this point, the mode may only be AUTODECR or INDEXED. Since ! only FINAL may generate AUTODECR it is an error if we see it here. If (.NMODE And 6) Neq INDEXED Then PUNT(580); ! for indexed modes, there is always a tempname. TN = .NODE[gt_reg]; ! if the tempname is used as a value If .NODE Then Return GMA(.TN); ! the tempname is being used as an address. ! if a named-cse usage then reference the symbol and defer as necessary If .TN Gtru 7 And .TN[tn_type] Eql BNDNCSE Then Begin T = GMA(LEXOUT(T_SYMBOL,.TN[gt_reg])); If .NMODE Then T = DEFER(.T); Return .T End; ! if a register reference If ISREG(.TN) Then Return BUILDOPD(.TY,.NMODE,REGNUM(.TN),.O); ! at this point we want an address and what we have is an index register ! and an offset. we need to return the sum of the two and not the ! contents of what they point to. ! if called from SAMEADDR and friends, just return a unique descriptor If .SAMETOG Neq 0 Then Return -(.TN^32+(3 And .NMODE)^16+.O); T = VERYTEMP(0); EMIT(PMOV,GMA(.TN),GMA(.T)); If ISREG(.T) Then Return BUILDOPD(.TY,.NMODE,REGNUM(.T),.O); EMIT(PADD,GMOFF(.NODE),GMA(.T)); If .NMODE Eql INDEXED+DEFERRED Then EMIT(PMOV,DEFER(GMA(.T)),GMA(.T)); Return DEFER(GMA(.T)) End; ! SYMBOL TABLE CASES Selectone .NODE[gt_type] Of Set [S_REGISTER]: Return GMA(.NODE[gt_reg]); [S_LOCAL]: ! if bound to a register or a stack location If .NODE[gt_reg] Gequ 8 Then Return GMA(.NODE[gt_reg]) Else Return BUILDOPD(OPND_NORMAL,INDEXED,SP,LOCALOFFSET(NODE)); [S_FORMAL]: ! if bound to a register or a stack location If .NODE[gt_reg] Gequ 8 Then Return GMA(.NODE[gt_reg]) Else Return BUILDOPD(OPND_NORMAL,INDEXED,SP,FLD_K_FORMAL+LOCALOFFSET(NODE)); [S_GLOBAL,S_EXTERNAL]: ! PIC seems to mean that the code may float but variables are fixed. ! this means that absolute addresses must be used for PIC code at ! all times but relative addressing may be used for non-PIC code. Begin L = (If .NODE Then IMMEDIATE Else If .swit_pic Then ABSOLUTE Else RELATIVE); Return BUILDOPD(OPND_NAME,.L,PC,NAMEDESC(.NODE)) End; [S_OWN,S_ROUTINE,S_GBL_ROUTINE,S_FORWARD]: Return BUILDOPD(OPND_NAME, If .NODE Then IMMEDIATE Else RELATIVE, PC, NAMEDESC(.NODE)) Tes; PUNT(580); Return 0 End; ! OF GMA Routine GMA8(OPND : Ref GT) = Begin Local X : ADRWD; X = GMA(.OPND); If Not ISLIT(.OPND) Then If .OPND[gt_pos] Eql 8 Then X = NXTBYTEADR(.X); Return .X End; ! ROUTINES TO HANDLE GENERAL DATA MOVES ! ------------------------------------- Forward Routine CLEARFIELD : Novalue, MAKEDESTROYABLE, DIAL, ISMOVSELF, SHIFT : Novalue, ISOLATE : Novalue, MASK, GENBITTEST : Novalue, POSITIONIT; Macro PICK8(INSTR,POS,SIZ)= Begin If (POS)+(SIZ) Leq 8 Then %Name(INSTR,B) Else INSTR End %; Routine CK08(NODE : Ref GT) = Begin If .NODE Eql T_SYMBOL Then Begin If .NODE[gt_pos] Eql 0 And .NODE[gt_len] Eql 8 Then Return TRUE; Return FALSE End; If .NODE Neq T_NODE Then Return FALSE; If .NODE[gt_pos] Lss 8 Then If .NODE[gt_pos]+.NODE[gt_len] Leq 8 Then Return TRUE; Return FALSE End; Macro CHECK08(NX)=CK08(NX) %; Routine SIMPLEMOVE(O1 : Ref GT,O2 : Ref GT) : Novalue = Begin Local A1 : ADRWD, A2 : ADRWD; If .O1 Neq .O2 Then Begin A1 = GMA(.O1); A2 = GMA(.O2); If .A1 Neq .A2 Then If Not ISMOVSELF(.A1,.A2) Then If CHECK08(.O1) Then EMIT(PMOVB,.A1,.A2) Else If CHECK08(.O2) Then EMIT(PMOVB,.A1,.A2) Else EMIT(PMOV,.A1,.A2) End End; Routine ISMOVSELF(S : Ref GT,D : Ref GT)= Begin Macro PCRETURN=Return .S Eql PC %, COMBINE(MODE1,MODE2)=(MODE1*8 + MODE2) %; If .S Eql .D Then Return TRUE; If .S Neq .D Then Return FALSE; If .S Neq .D Then Return FALSE; Selectone COMBINE(.S,.D) Of Set [COMBINE(0,0)]: Return TRUE; [COMBINE(1,1)]: Return TRUE; [COMBINE(6,6)]: Return TRUE; [COMBINE(7,7)]: Return TRUE; [COMBINE(3,3)]: PCRETURN; [COMBINE(6,3)]: PCRETURN; [COMBINE(3,6)]: PCRETURN; [Otherwise]: Return FALSE Tes End; Routine SAMEADDR(O1 : Ref GT,O2 : Ref GT) = Begin Local SDTD : Integer, A1 : ADRWD, A2 : ADRWD; SDTD = .DYTEMPS; SAMETOG = .SAMETOG+1; A1 = GMA(.O1); A2 = GMA(.O2); DYTEMPS = .SDTD; SAMETOG = .SAMETOG-1; Return ISMOVSELF(.A1,.A2) End; Routine SAMEWORD(O1 : Ref GT,O2 : Ref GT) = Begin Local SDTD : Integer, A1 : ADRWD, A2 : ADRWD; SDTD = .DYTEMPS; SAMETOG = .SAMETOG+1; A1 = GMA(.O1) And (-2); A2 = GMA(.O2) And (-2); DYTEMPS = .SDTD; SAMETOG = .SAMETOG-1; Return ISMOVSELF(.A1,.A2) End; Routine OVERLAP(P1 : Integer,S1 : Integer,P2 : Integer,S2 : Integer)= Begin S1 = .S1+.P1; S2 = .S2+.P2; Return .S2 Geq .P1 And .P2 Leq .S1 End; Routine REG8(R : Ref GT)= Begin If .R[gt_pos] Neq 8 Then Return GMA(.R); R = MAKEDESTROYABLE(.R); If ISREG(.R) Then Begin EMIT(PSWAB,GMA(.R),0); Return GMA(.R) End Else Return NXTBYTEADR(GMA(.R)) End; Routine NOMOVREQD(O1 : Ref GT,O2 : Ref GT)= Begin If .O1 Eql T_LITERAL Or .O2 Eql T_LITERAL Then Return .O1 Eql .O2; If .O1 Neq .O2 Then If .O1+.O2 Gtr PFNONE+PF016 Then Return FALSE; Return SAMEADDR(.O1,.O2) End; Routine DEPENDON(S : Ref GT,D : Ref GT) = Begin Local RESULT : Boolean, T : ADRWD, E : ADRWD, SDTD : Integer; If ISREG(.D) Then Return REGNUM(.S) Eql REGNUM(.D) Else Begin SDTD = .DYTEMPS; SAMETOG = .SAMETOG+1; T = GMA(.S); If .T Lss 0 Then T = GMA(.S[gt_reg]); E = GMA(.D); If .E Lss 0 Then E = GMA(.D[gt_reg]); RESULT = (NODEFER(.T) And (-2)) Eql (.E And (-2)); DYTEMPS = .SDTD; SAMETOG = .SAMETOG-1; Return .RESULT End End; Routine GENMOVE(O1 : Ref GT,O2 : Ref GT) : Novalue = Begin Local P1 : Integer, P2 : Integer, T : ADRWD, SPC : Boolean, C, X, BS, L, LAB : Ref CELL, POS1 : Integer, POS2 : Integer, SIZE1 : Integer, SIZE2 : Integer, S, CHP : Boolean, XBIT, OP; Bind GMOVPLIT = UPlit Byte( 0,0,1,8,5,1, 0,0,1,8,5,1, 2,2,1,8,5,1, 7,7,6,8,8,6, 3,3,4,8,5,4, 2,2,1,8,5,1) : Vector[,Byte]; If .O1 Eql .O2 Then Return; P1 = .O1; P2 = .O2; If Not .swit_quick Then If NOMOVREQD(.O1,.O2) Then Return; Case .GMOVPLIT[.P1*6+.P2] From 0 To 8 Of Set [0]: ! 0 - FULL WORD TO FULL WORD If ISZERO(.O1) Then EMIT(PCLR,GMA(.O2),0) Else EMIT(PMOV,GMA(.O1),GMA(.O2)); [1]: ! 1 - MOVE TO <0,8> OR <8,8> FROM <0,16>, <0,8> OR <8,8> If ISREG(.O2) Then Begin POS2 = .O2[gt_pos]; If ISLIT(.O1) Then Begin T = CLITVALUE(.O1); If (.T And 255) Neq 255 Then CLEARFIELD(.O2,.POS2,8); If .T Neq 0 Then EMIT(PICK8(PBIS,.POS2,8), GMA(MAKLIT(.T^.POS2)), GMA(.O2)); Return End; T = .O1; If DEPENDON(.O1,.O2) Then Begin T = VERYTEMP(0); SIMPLEMOVE(.O1,.T) End; If .POS2 Eql 8 Or (ISREG(.T) And .P1 Eql PF88) Then T = DIAL(.T,.O1[gt_pos],.O1[gt_len],.POS2,8); CLEARFIELD(.O2,.POS2,8); If .POS2 Eql 0 And Not ISREG(.T) Then Begin EMIT(PBISB,GMA8(.T),GMA(.O2)); Return End; EMIT(PICK8(PBIS,.POS2,8),GMA(.T),GMA(.O2)) End Else If ISLIT(.O1) Then If CLITVALUE(.O1) Eql 0 Then EMIT(PCLRB,GMA8(.O2),0) Else EMIT(PMOVB,GMA(.O1),GMA8(.O2)) Else If ISREG(.O1) And .O1[gt_pos] Neq 0 Then Begin If Not DEPENDON(.O2,.O1) Then Begin T = GMA(.O1); EMIT(PSWAB,.T,0); EMIT(PMOVB,.T,GMA8(.O2)); EMIT(PSWAB,.T,0) End Else Begin T = VERYTEMP(0); SIMPLEMOVE(.O1,.T); T = REG8(.T); EMIT(PMOVB,.T,GMA8(.O2)) End End Else EMIT(PMOVB,GMA8(.O1),GMA8(.O2)); [2]: ! 2 - MOVE TO 0,16 FROM 0,8 OR 8,8 Begin If SAMEWORD(.O1,.O2) Then Begin SHIFT(.O1,.O1[gt_pos],0,8); ISOLATE(.O2,0,.O1[gt_len]); Return End; If DEPENDON(.O1,.O2) Then Begin EMIT(PMOVB,GMA8(.O1),GMA(.O2)); CLEARFIELD(.O2,8,8); Return End; If ISREG(.O1) And .O1[gt_pos] Eql 8 Then Begin SIMPLEMOVE(.O1,.O2); EMIT(PCLRB,GMA(.O2),0); EMIT(PSWAB,GMA(.O2),0) End Else Begin EMIT(PCLR,GMA(.O2),0); EMIT(PBISB,GMA8(.O1),GMA(.O2)) End End; [3]: ! 3 - MOVE TO 0,16 FROM ARBITRARY FIELD Begin T = .O2; If Not SAMEWORD(.O1,.O2) Then If Not ISCHEAP(.O2) Then If .O1[gt_pos] Neq 0 Then Begin O2 = VERYTMPREG(); If .O2 Eql 0 Then O2 = .T End; SIMPLEMOVE(.O1,.O2); SHIFT(.O2,.O1[gt_pos],0,.O1[gt_len]); ISOLATE(.O2,0,.O1[gt_len]); SIMPLEMOVE(.O2,.T) End; [4]: ! 4 - MOVE TO 0,8 OR 8,8 FROM ARBITRARY FIELD Begin T = .O1; If DEPENDON(.O1,.O2) Then Begin T = VERYTEMP(0); SIMPLEMOVE(.O1,.T) End; SPC = ISREG(.O2) And .O2[gt_pos] Eql 8; If .SPC Or .O1[gt_len] Lss 8 Then T = DIAL(.T,.O1[gt_pos],.O1[gt_len],8*.SPC,8) Else T = POSITIONIT(.T,.O1[gt_pos],0,8); If .SPC Then Begin CLEARFIELD(.O2,8,8); EMIT(PBIS,GMA(.T),GMA(.O2)) End Else EMIT(PMOVB,GMA(.T),GMA8(.O2)) End; [5]: ! 5 - ARBITRARY FIELD TO ARBITRARY FIELD Begin BS = -1; C = -1; POS2 = .O2[gt_pos]; SIZE2 = .O2[gt_len]; If ISLIT(.O1) Then Begin L = CLITVALUE(.O1); X = MASK(0,.SIZE2,0); L = .L And .X; If .L Eql .X Then C = 0; If .L Eql 0 Then BS = 0; T = MAKLIT(.L^.POS2) End Else Begin If .O1[gt_type] Eql S_TEMPNAME Then Begin POS1 = 0; SIZE1 = 16 End Else Begin POS1 = .O1[gt_pos]; SIZE1 = .O1[gt_len] End; T = DIAL(.O1,.POS1,.SIZE1,.POS2,.SIZE2) End; If .C Neq 0 Then CLEARFIELD(.O2,.POS2,.SIZE2); If .BS Neq 0 Then EMIT(PICK8(PBIS,.POS2,.SIZE2),GMA(.T),GMA(.O2)) End; [6]: ! 6 - MOVE TO 0,8 OR 8,8 FROM E,1 Begin CHP = 0; P1 = .O1[gt_pos]; SPC = (ISREG(.O2) And .O2[gt_pos] Eql 8); If DEPENDON(.O1,.O2) Or (SAMEWORD(.O1,.O2) And OVERLAP(.P1,.O1[gt_len],.O2[gt_pos],.O2[gt_len])) Then Begin T = VERYTEMP(0); If ISCHEAP(.T) And Not .SPC Then Begin CHP = -1; S = .O2; O2 = .T End Else Begin SIMPLEMOVE(.O1,.T); O1 = .T End End; CLEARFIELD(.O2,.O2[gt_pos],.O2[gt_len]); LAB = GENLABEL(); GENBITTEST(.O1,.P1,.LAB); If Not .SPC Then EMIT(PINCB,GMA8(.O2),0) Else EMIT(PBIS,GMA(MAKLIT(1^8)),GMA(.O2)); PLACELABEL(.LAB); If .CHP Then EMIT(PMOVB,GMA(.O2),GMA8(.S)) End; [7]: ! 7 - MOVE TO 0,16 FROM E,1 Begin CHP = FALSE; P1 = .O1[gt_pos]; If SAMEWORD(.O1,.O2) Then Begin If (.P1 Mod 8) Leq 2 Then Begin SHIFT(.O1,.P1,0,1); ISOLATE(.O2,0,1); Return End; CHP = TRUE End Else If DEPENDON(.O1,.O2) Then CHP = TRUE; If .CHP Then Begin T = VERYTEMP(0); If ISCHEAP(.T) Then Begin S = .O2; O2 = .T End Else Begin CHP = 0; SIMPLEMOVE(.O1,.T); O1 = .T End End; EMIT(PCLR,GMA(.O2),0); LAB = GENLABEL(); GENBITTEST(.O1,.P1,.LAB); EMIT(PINC,GMA(.O2),0); PLACELABEL(.LAB); If .CHP Then EMIT(PMOV,GMA(.O2),GMA(.S)) End; [8]: ! 8 - MOVE TO/FROM ARBITRARY ONE BIT FIELD Begin If ISLIT(.O1) Then Begin T = CLITVALUE(.O1); XBIT = GMA(MAKLIT(MASK(.O2[gt_pos],1,0))); If .O2[gt_pos]+.O2[gt_len] Leq 8 Then OP = (If .T Then PBISB Else PBICB) Else OP = (If .T Then PBIS Else PBIC); EMIT(.OP,.XBIT,GMA(.O2)); Return End; P1 = (If .O1[gt_type] Eql S_TEMPNAME Then 0 Else .O1[gt_pos]); If DEPENDON(.O1,.O2) Or (SAMEWORD(.O1,.O2) And OVERLAP(.P1,.O1[gt_len],.O2[gt_pos],.O2[gt_len])) Then Begin T = VERYTEMP(0); SIMPLEMOVE(.O1,.T); O1 = .T End; CLEARFIELD(.O2,.O2[gt_pos],.O2[gt_len]); LAB = GENLABEL(); GENBITTEST(.O1,.P1,.LAB); POS2 = .O2[gt_pos]; If .POS2 Eql 0 Then EMIT(PINCB,GMA(.O2),0) Else If .POS2 Eql 8 And Not(ISREG(.O2)) Then EMIT(PINCB,GMA8(.O2),0) Else EMIT(PICK8(PBIS,.POS2,1),GMA(MAKLIT(1^.POS2)),GMA(.O2)); PLACELABEL(.LAB); End Tes End; ! OF GENMOVE Macro TTN(Z)=(1^(Z)) %, TTM(Z)=(TTN(Z)-1) %; Routine MAKEDESTROYABLE(XOPND : Ref GT) = Begin Local T : Ref GT; If Not ISDESTROYABLE(.XOPND) Then Begin T = VERYTEMP(.XOPND[gt_reg]); SIMPLEMOVE(.XOPND,.T) End Else If .XOPND[gt_type] Eql S_TEMPNAME Then Return .XOPND Else Begin T = .XOPND[gt_reg]; If .XOPND[gt_mode] Neq GENREG Then SIMPLEMOVE(.XOPND,.T) End; Return .T End; Bind MASKS = Uplit Word( 0, TTM(1), TTM(2), TTM(3), TTM(4), TTM(5), TTM(6), TTM(7), TTM(8), TTM(9), TTM(10), TTM(11), TTM(12), TTM(13), TTM(14), TTM(15), TTM(16)) : Vector[,Word]; Routine MASK(POS : Integer,SIZ : Integer,COMP : Boolean)= Begin Local X : Integer; X = (.MASKS[.SIZ])^.POS; If .COMP Then X = Not(.X); Return .X And %x'7fffffff' End; Routine CLEARMASK(XOPND : Ref GT,MSK : Integer) : Novalue = Begin Local LOCN : ADRWD; MSK = .MSK And %x'ffff'; If .MSK Eql 0 Then Return; If CHECK08(.XOPND) Then MSK = .MSK And 255; LOCN = GMA(.XOPND); Selectone .MSK Of Set [%x'ffff']: EMIT(PCLR,.LOCN,0); [%x'00ff']: EMIT(PCLRB,.LOCN,0); [%x'ff00']: If Not ISREG(.XOPND) Then EMIT(PCLRB,NXTBYTEADR(.LOCN),0) Else EMIT(If .MSK Leq 255 Then PBICB Else PBIC, GMA(MAKLIT(.MSK)),.LOCN); [Otherwise]: EMIT(If .MSK Leq 255 Then PBICB Else PBIC,GMA(MAKLIT(.MSK)),.LOCN) Tes End; Routine CLEARFIELD(XOPND : Ref GT,P : Integer,S : Integer) : Novalue = Begin CLEARMASK(.XOPND,MASK(.P,.S,0)) End; Routine ISOLATE(XOPND : Ref GT,P : Integer,S : Integer) : Novalue = Begin CLEARMASK(.XOPND,MASK(.P,.S,1)) End; Routine SHIFT(XOPND : Ref GT,XFP : Integer,XTP : Integer,SZ : Integer) : Novalue = Begin Local DIST : Integer, RL : Boolean, SB : Boolean, RB : Boolean, SA : Boolean, SHIFTROT : Boolean, OP : Integer, LAB : Ref CELL, ADR : ADRWD, ADR1 : ADRWD; ! compute the shift distance and return if no shift required DIST = .XTP - .XFP; If .DIST Eql 0 Then Return FALSE; ADR = GMA(.XOPND); ! if shifting the sign bit to 2,3,10, or 11 then generate: ! ! BIC #m,X ; this tests the sign bit! ! BPL 1$ ! COM X l flip all bits ! 1$: If .SZ Eql 1 And .XFP Eql 15 And .ADR Neq 0 Then If ONEOF(.XTP,2,3,4,10,11) Then Begin LAB = GENLABEL(); EMIT(PBIC,GMA(MAKLIT(1^.XTP)),.ADR); EMIT(PBPL,.LAB,0); EMIT(PCOM,.ADR,0); PLACELABEL(.LAB); Return FALSE End; RL = FALSE; SB = FALSE; RB = FALSE; SA = FALSE; SHIFTROT = FALSE; ! if a right shift If .DIST Lss 0 Then Begin RL = TRUE; DIST = -.DIST End; ! for a shift of 13,14, or 15 bits, rotate around the top If .DIST Gtr 12 Then Begin RL = Not .RL; DIST = 17 - .DIST; SHIFTROT = TRUE End; ! if more than 7 bits then use a SWAB If .DIST Gtr 7 Then Begin SB = TRUE; DIST = .DIST-8 End; If .DIST Gtr 4 Then Begin Local A; If .SZ Gtr 8 Then Begin If Not .RL Or .DIST Neq 5 Then Begin RB = TRUE; SHIFTROT = TRUE; If .RL Then SA = 8-.DIST Else SB = TRUE; DIST = 8-.DIST; RL = Not .RL End End Else Begin A = (If .RL Then 16-(.XFP+.SZ) Else .XFP); SA = Min(.A,8-.DIST); If .SA Eql 0 Then SB = TRUE; DIST = 8-.DIST; RL = Not .RL End End; ADR1 = .ADR; If .SB+(.SA Neq 0)+.DIST+.RB Gtr 1 Then If .ADR Neq 0 Then Begin ADR = VERYTMPREG(); If .ADR Eql 0 Then ADR = .ADR1 Else Begin GENMOVE(.XOPND,.ADR); ADR = GMA(.ADR) End End; ! generate a SWAB if necessary If .SB Then EMIT(PSWAB,.ADR,0); ! generate an RORB If .RB And .RL Then EMIT(PRORB,.ADR,0); OP = (If .RL Then PASR Else PASL); If .SHIFTROT Then OP = .OP + (PROR - PASR); ! ASR TO ROR, ASL TO ROL While (DIST = .DIST-1) Geq 0 Do Begin EMIT(.OP,.ADR,0); If .DIST Eql 0 And .RB And Not .RL Then EMIT(PROLB,.ADR,0); SA = .SA - 1; If .SA Eql 0 Then EMIT(PSWAB,.ADR,0) End; If .ADR Neq .ADR1 Then EMIT(PMOV,.ADR,.ADR1); !TRUE IFF OLD CARRY BIT HAS BEEN ROTATED INTO WORD Return .SHIFTROT And Not .SB End; Routine POSITIONIT(X : Ref GT,XFP : Integer,XTP : Integer,SZ : Integer)= Begin Local T : Ref GT; If .SZ Leq 8 And .XFP Eql 8 And .XTP Eql 0 Then If Not ISIDT(.X) Then If Not ISREG(.X) Then Begin T = VERYTEMP(.X[gt_reg]); EMIT(PMOVB,GMA8(.X),GMA(.T)); Return .T End; T = MAKEDESTROYABLE(.X); SHIFT(.T,.XFP,.XTP,.SZ); Return .T End; Routine DIAL(XOPND : Ref GT,XFP,XFS,XTP,XTS) = Begin Local S : Integer, T : Ref GT; S = Min(.XFS,.XTS); T = POSITIONIT(.XOPND,.XFP,.XTP,.S); ISOLATE(.T,.XTP,.S); Return .T End; Routine ALIGNX(O1 : Ref Vector,O2 : Ref Vector) : Novalue = Begin Local N1 : Ref GT, N2 : Ref GT, X1 : Ref GT, X2 : Ref GT, T1 : Ref GT, T2 : Ref GT, T : Boolean; N1 = .O1[0]; N2 = .O2[0]; If .N1[gt_pos] Gtr .N2[gt_pos] Then (X1 = .N2; X2 = .N1; T = 0) Else (X1 = .N1; X2 = .N2; T = 1); T1 = MAKEDESTROYABLE(.X1); ISOLATE(.T1,.X1[gt_pos],.X1[gt_len]); T2 = DIAL(.X2,.X2[gt_pos],.X2[gt_len],.X1[gt_pos],16); If .T Then (O1[0] = .T1; O2[0] = .T2) Else (O1[0] = .T2; O2[0] = .T1) End; ! TEST-BRANCH SPECIAL CASE ROUTINES ! --------------------------------------- Routine GENBITTEST(OPND : Ref GT,IBIT,FLAB) : Novalue = Begin Local OPC1 : Integer, OPC2 : Integer, ADR : ADRWD, SPC : Boolean; If ISLIT(.OPND) Then Begin If (CLITVALUE(.OPND) And (1^.IBIT)) Eql 0 Then EMIT(PBR,.FLAB,0); Return End; SPC = TRUE; ADR = GMA(.OPND); If .IBIT Eql 15 Then Begin OPC1 = PTST; OPC2 = PBPL End Else If .IBIT Eql 7 Then Begin OPC1 = PTSTB; OPC2 = PBPL End Else If Not ISDESTROYABLE(.OPND) Then SPC = FALSE Else Selectone .IBIT Of Set [0]: Begin OPC1 = PROR; OPC2 = PBHIS End; [14]: Begin OPC1 = PASL; OPC2 = PBPL End; [6]: Begin OPC1 = PASLB; OPC2 = PBPL End; [Otherwise]: SPC = FALSE Tes; If Not .SPC Then Begin OPC1 = PICK8(PBIT,.IBIT,1); EMIT(.OPC1,GMA(MAKLIT(MASK(.IBIT,1,0))),.ADR); OPC2 = PBEQ End Else EMIT(.OPC1,.ADR,0); EMIT(.OPC2,.FLAB,0) End; Bind RELOPTAB = Uplit Byte( PBGT, PBLE, PBLT, PBGE, PBEQ, PBNE, 0,0,0,0,0, ! not,eqv,and,or,xor PBHI, PBLOS, PBLO, PBHIS, PBEQ, PBNE) : Vector[,Byte]; Bind CRELOP = Uplit Byte( PBNE,PBEQ,PBLE,PBGT,PBGE,PBLT,0,0,PBLO,PBHIS,0,0,PBLOS,PBHI) : Vector[,Byte]; Routine MAPTOUNSIGNED(OP : Integer)= Begin Selectone .OP Of Set [PBGT]: Return PBHI; [PBGE]: Return PBHIS; [PBLT]: Return PBLO; [PBLE]: Return PBLOS; [Otherwise]: Return OP Tes End; Macro CONVERSERELATIONAL(OP)=(.CRELOP[OP - PBNE]) %; Macro REVERSERELATIONAL(OP)=((OP) Xor 1) %; Routine COMPARE(OP1 : Ref GT,OP2 : Ref GT,RELOP : Integer,LAB : Ref GT) : Novalue = Begin EMIT(PCMP,GMA(.OP1),GMA(.OP2)); EMIT(.RELOP,.LAB,0) End; Routine COMPAREBYTE(OP1 : Ref GT,OP2 : Ref GT,RELOP : Integer,LAB : Ref GT) : Novalue = Begin EMIT(PCMPB,GMA8(.OP1),GMA8(.OP2)); EMIT(MAPTOUNSIGNED(.RELOP),.LAB,0) End; Routine REALCOMPARE(OP1 : Ref GT,OP2 : Ref GT,RELOP : Integer,LAB : Ref GT) : Novalue = Begin Local T : Ref GT; Bind SSPLIT = UPlit Byte( 0,0,2,2,2,2, 0,0,2,2,2,2, 3,3,1,4,4,1, 3,3,4,4,4,4, 3,3,4,4,4,4, 3,3,1,4,4,1) : Vector[,Byte]; Case .SSPLIT[.OP1*6+.OP2] From 0 To 4 Of Set [0]: !0 -- FULL WORD COMPARISON COMPARE(.OP1,.OP2,.RELOP,.LAB); [1]: !1 -- BYTE-BYTE COMPARISON If (ISREG(.OP1) And .OP1 Neq PF08) Or (ISREG(.OP2) And .OP2 Neq PF08) Then Begin ALIGNX(OP1,OP2); COMPARE(.OP1,.OP2,MAPTOUNSIGNED(.RELOP),.LAB) End Else COMPAREBYTE(.OP1,.OP2,.RELOP,.LAB); [2]: !2 -- FULL WORD WITH SOMETHING SMALLER Begin T = DIAL(.OP2,.OP2[gt_pos],.OP2[gt_len],0,16); COMPARE(.OP1,.T,.RELOP,.LAB) End; [3]: !3 -- SOMETHING SMALLER WITH FULL WORD Begin T = DIAL(.OP1,.OP1[gt_pos],.OP1[gt_len],0,16); COMPARE(.T,.OP2,.RELOP,.LAB) End; [4]: !4 -- BOTH ARE FUNNY FIELDS Begin ALIGNX(OP1,OP2); COMPARE(.OP1,.OP2,MAPTOUNSIGNED(.RELOP),.LAB) End Tes End; Routine LITCOMPARE(OP1 : Ref GT,L : Ref GT,RELOP : Integer,LAB : Ref GT) : Novalue = Begin Local T : Integer, T1 : Ref GT, L1 : Ref CELL, CASINDEX : Integer, N : Integer; Bind O1SS = Uplit Byte(0,0,1,2,3,1) : Vector[,Byte]; CASINDEX = .O1SS[.OP1]; If .OP1 Eql PF88 Then If ISREG(.OP1) Then CASINDEX = 3; Case .CASINDEX From 0 To 3 Of Set [0]: !0 -- FULL WORD CASES Begin N = (If ISLIT(.L) Then CLITVALUE(.L) Else 999); If .N Eql 0 Then Begin EMIT(PTST,GMA(.OP1),0); EMIT(.RELOP,.LAB,0) End Else If Abs(.N) Eql 1 And ISDESTROYABLE(.OP1) Then Begin If .N Eql 1 Then EMIT(PDEC,GMA(.OP1),0) Else EMIT(PINC,GMA(.OP1),0); EMIT(.RELOP,.LAB,0) End Else COMPARE(.OP1,.L,.RELOP,.LAB) End; [1]: !1 -- BYTE CASES Begin N = (If ISLIT(.L) Then CLITVALUE(.L) Else 999); RELOP = MAPTOUNSIGNED(.RELOP); If .N Eql 0 Then Begin EMIT(PTSTB,GMA8(.OP1),0); EMIT(.RELOP,.LAB,0) End Else If Abs(.N) Eql 1 And ISDESTROYABLE(.OP1) Then Begin If .N Eql 1 Then EMIT(PDECB,GMA8(.OP1),0) Else EMIT(PINCB,GMA8(.OP1),0); EMIT(.RELOP,.LAB,0) End Else COMPAREBYTE(.OP1,.L,.RELOP,.LAB) End; [2]: !2 -- ONE BIT CASES Begin T = CLITVALUE(.L); If .T Eql 0 Or .T Eql 1 Then If .RELOP Eql PBEQ Or .RELOP Eql PBNE Then Begin If (.T Eql 0) Eqv (.RELOP Eql PBEQ) Then GENBITTEST(.OP1,.OP1[gt_pos],.LAB) Else Begin L1 = GENLABEL(); GENBITTEST(.OP1,.OP1[gt_pos],.L1); EMIT(PBR,.L1,0); PLACELABEL(.L1) End; Return End; If .T Lss 0 Then If .RELOP Eql PBGT Or .RELOP Eql PBGE Then EMIT(PBR,.LAB,0); If .T Gtr 1 Then If .RELOP Eql PBLT Or .RELOP Eql PBLE Then EMIT(PBR,.LAB,0) End; [3]: !3 -- GENERAL SUBFIELD CASES Begin T = CLITVALUE(.L); If .T Eql 0 Then Begin RELOP = MAPTOUNSIGNED(.RELOP); Selectone .RELOP Of Set [PBHI]: RELOP = PBNE; [PBHIS]: RELOP = PBR; [PBLOS]: RELOP = PBEQ; [PBLO]: Return; Tes; If .RELOP Neq PBR Then EMIT(PICK8(PBIT,.OP1[gt_pos],.OP1[gt_len]), GMA(.OP1), GMA(MAKLIT(MASK(.OP1[gt_pos],.OP1[gt_len],0)))); EMIT(.RELOP,.LAB,0); Return End; If .T Gtr 0 Then Begin If (.T^(.OP1[gt_pos]) Eql ((.T^(.OP1[gt_pos])) And %x'ffff')) Then Begin T1 = MAKEDESTROYABLE(.OP1); ISOLATE(.T1,.OP1[gt_pos],.OP1[gt_len]); COMPARE(.T1,MAKLIT(.T^(.OP1[gt_pos])), MAPTOUNSIGNED(.RELOP),.LAB); Return End End; T1 = DIAL(.OP1,.OP1[gt_pos],.OP1[gt_len],0,16); COMPARE(.T1,.L,.RELOP,.LAB) End Tes End; Routine GENCOMPARE(OP1 : Ref GT,OP2 : Ref GT,OPX : Integer, LABT : Ref GT,LABF : Ref GT,SENSE : Boolean) : Novalue = Begin Local RELOP : Integer; RELOP = .RELOPTAB[.OPX - RELOPBASE]; If .SENSE Then RELOP = CONVERSERELATIONAL(.RELOP); If .LABT Eql 0 Then Begin RELOP = REVERSERELATIONAL(.RELOP); LABT = .LABF; LABF = 0 End; If .OP2 Eql T_LITERAL Then LITCOMPARE(.OP1,.OP2,.RELOP,.LABT) Else If .OP1 Eql T_LITERAL Then Begin RELOP = CONVERSERELATIONAL(.RELOP); LITCOMPARE(.OP2,.OP1,.RELOP,.LABT) End Else REALCOMPARE(.OP1,.OP2,.RELOP,.LABT); If .LABF Neq 0 Then EMIT(PBR,.LABF,0); End; Macro COMPAREFALSE(X1,X2,NX,XL)= GENCOMPARE(X1,X2,NX,XL,0,0) %; Routine BITLIT(O1 : Ref GT,O2 : Ref GT) : Novalue = Begin Local L : ADRWD, P : Integer, S : Integer; P = .O1[gt_pos]; S = .O1[gt_len]; L = GMA(MAKLIT(CLITVALUE(.O2)^.P And .MASKS[.P+.S])); EMIT(PICK8(PBIT,.P,.S),.L,GMA(.O1)) End; Routine BITX(O1 : Ref GT,O2 : Ref GT,ENE : Boolean,LAB : Ref GT) : Novalue = Begin Local P : Integer, S : Integer; Bind BITPLIT = Uplit Byte( 0,0,1,2,2,1, 0,0,1,2,2,1, 1,1,1,2,2,1, 2,2,2,2,2,2, 2,2,2,2,2,2, 1,1,1,2,2,1) : Vector[,Byte]; If ISLIT(.O1) Then BITLIT(.O2,.O1) Else If ISLIT(.O2) Then BITLIT(.O1,.O2) Else Case .BITPLIT[.O1*6+.O2] From 0 To 2 Of Set [0]: ! 0 - BIT EMIT(PBIT,GMA(.O1),GMA(.O2)); [1]: ! 1 - BITB Begin If .O1 Eql PF88 Then If ISREG(.O1) Then O1 = POSITIONIT(.O1,8,0,8); If .O2 Eql PF88 Then If ISREG(.O2) Then O2 = POSITIONIT(.O2,8,0,8); EMIT(PBITB,GMA8(.O1),GMA8(.O2)) End; [2]: ! 2 - SUBFIELD CASES Begin S = Min(.O1[gt_len],.O2[gt_len]); If .O1[gt_pos] Leq .O2[gt_pos] Then (P = .O1[gt_pos]; O2 = DIAL(.O2,.O2[gt_pos],.O2[gt_len],.P,.S)) Else (P = .O2[gt_pos]; O1 = DIAL(.O1,.O1[gt_pos],.O1[gt_len],.P,.S)); EMIT(PICK8(PBIT,.P,.S),GMA(.O1),GMA(.O2)); End Tes; EMIT(If .ENE Then PBNE Else PBEQ,.LAB,0) End; !!! THE FOLLOWING ROUTINES ARE THE NODE-SPECIFIC CODE GENERATORS !!! -------------------------------------------------------------- Forward Routine CODE : Novalue; Macro ADJUSTSTACK= If .NODE[gt_dtdelete] Neq DTDONTCARE And .NODE[gt_dtdelete] Neq .DYTEMPS Then Begin EMIT(PADD,GMA(MAKLIT(.DYTEMPS-.NODE[gt_dtdelete])),STACKPTR); DYTEMPS = .NODE[gt_dtdelete] End %, CHECKFORFLOW= (If .NODE[rw_flow] Then GFLOW(.NODE)) %, CODELST(LST)= PULSELIST(PULSECODE,LST,0) %, LASTOPERAND= gt_argv(.NODE[gt_argc]-1) %, PICKTARGET(T,N)= If .NODE[gt_v_tpath] Then (T = .NODE[gt_arg2]; N = .NODE[gt_arg1]) Else (T = .NODE[gt_arg1]; N = .NODE[gt_arg2]) %, STARTFREE(L1,L2)= Begin If Not EMPTY(L1) Or Not EMPTY(L2) Then PLSTCNT = .PLSTCNT-1 End %, STOPFREE(L1,L2)= Begin If Not EMPTY(L1) Or Not EMPTY(L2) Then PLSTCNT = .PLSTCNT+1 End %; Structure GOALWD[P,S,E]=[8]GOALWD; Macro GSIZEF = 0,32,0 %, GPOSF = 32,32,0 %; Macro GOALS(P,S) = ((P)^32 Or (S)) %, FULLWD = GOALS(0,16) %; Routine SETNEWPS(NODE : Ref GT,P : Integer,S : Integer) = Begin NODE[gt_pos] = .P; NODE[gt_len] = .S; If .S Eql 1 Then NODE[rw_ptr_state] = PFE1 Else If .P Eql 0 Then If .S Eql 8 Then NODE[rw_ptr_state] = PF08 Else If .S Eql 16 Then NODE[rw_ptr_state] = PF016 Else NODE[rw_ptr_state] = PFOTHER Else If .P Eql 8 And .S Eql 8 Then NODE[rw_ptr_state] = PF88 Else NODE[rw_ptr_state] = PFOTHER; NODE = .NODE[rw_ptr_state]; Return .NODE End; Routine GFLOW(NODE : Ref GT) : Novalue = Begin ADJUSTSTACK; GENBITTEST(.NODE,.NODE[gt_pos],NODELABEL(.NODE[gt_lab_f])); EMIT(PBR,NODELABEL(.NODE[gt_lab_t]),0) End; Routine PULSECODE(NODE : Ref GT,P) : Novalue = Begin Local L : Ref GT, LR : Boolean, RFF : Integer, LDT : Integer; RFF = .NODE[rw_real_flow]; If .RFF Eql RFFLOW Then Return; L = .NODE[gt_label]; LR = .NODE[gt_v_lab_req]; LDT = .NODE[gt_dtdelete]; NODE[rw_flow] = FALSE; NODE[gt_label] = 0; NODE[gt_v_lab_req] = FALSE; NODE[gt_dtdelete] = DTDONTCARE; NODE[gt_v_mustgencode] = TRUE; PLSTCNT = .PLSTCNT+1; CODE(NODE,FULLWD); PLSTCNT = .PLSTCNT-1; NODE[gt_v_lab_req] = .LR; NODE[gt_label] = .L; NODE[rw_real_flow] = .RFF; NODE[gt_dtdelete] = .LDT End; Routine GAS(NODE : Ref GT,GOAL : GOALWD,OP) = Begin Local TAR : Ref GT, NTAR : Ref GT, TMP : Ref GT, L : Ref GT, INCORDEC : Boolean; INCORDEC = FALSE; TMP = .NODE[gt_reg]; CODE(NODE[gt_arg1],FULLWD); CODE(NODE[gt_arg2],FULLWD); If .NODE[rw_real_flow] Eql RFNONE Then Return .NODE; PICKTARGET(TAR,NTAR); If .NODE[rc_mov_offset] Then EMIT(PMOV,GMOFF(.NODE),GMA(.TMP)); If .NODE[rc_mov_target] Then GENMOVE(.TAR,.TMP); If .NODE[rc_negate] Then EMIT(PNEG,GMA(.TMP),0); If .NODE[rc_operate] Then Begin If .NTAR[rw_ptr_state] Gtr PF016 Then Begin L = VERYTEMP(.NTAR[gt_reg]); GENMOVE(.NTAR,.L); NTAR = .L End; EMIT(.OP,GMA(.NTAR),GMA(.TMP)) End; ! IF OFFSET IS LITERAL, GET ITS ABSOLUTE VALUE, TO ! TRY TO GET AS MANY INCB'S AND DECB'S AS POSSIBLE. If .NODE[rc_add_offset] Xor .NODE[rc_sub_offset] Then If Not .NODE[gt_v_symoff] And .NODE[gt_disp_16] Lss 0 Then Begin NODE[gt_disp] = -.NODE[gt_disp_16]; NODE[rc_add_offset] = Not .NODE[rc_add_offset]; NODE[rc_sub_offset] = Not .NODE[rc_sub_offset] End; ! NO NEED TO TEST [SYMOFFF] IF THE ABOVE IS TRUE! If .NODE[rc_add_offset] Then If .NODE[gt_disp_16] Eql 1 Then Begin EMIT(PICK8(PINC,.GOAL,.GOAL),GMA(.TMP),0); INCORDEC = TRUE End Else EMIT(PADD,GMOFF(.NODE),GMA(.TMP)); If .NODE[rc_sub_offset] Then If .NODE[gt_disp_16] Eql 1 Then Begin EMIT(PICK8(PDEC,.GOAL,.GOAL),GMA(.TMP),0); INCORDEC = TRUE End Else EMIT(PSUB,GMOFF(.NODE),GMA(.TMP)); CHECKFORFLOW; If .INCORDEC Then If .GOAL Eql GOALS(0,8) Then Return SETNEWPS(.NODE,0,8); Return .NODE End; Routine GADD(NODE : Ref GT,GOAL : GOALWD) = Begin Return GAS(.NODE,.GOAL,PADD) End; Routine GSUB(NODE : Ref GT,GOAL : GOALWD) = Begin Return GAS(.NODE,.GOAL,PSUB) End; Routine GSTORE(NODE : Ref GT,GOAL : GOALWD) = Begin Local TAR : Ref GT, NTAR : Ref GT, TGOAL : GOALWD; TAR = (If .NODE[gt_v_tpath] Then .NODE[gt_arg2] Else .NODE[gt_arg1]); TGOAL = (If .TAR Eql T_LITERAL Then FULLWD Else GOALS(.TAR[gt_pos],.TAR[gt_len])); CODE(NODE[gt_arg1],If .NODE[gt_v_tpath] Then .TGOAL Else FULLWD); CODE(NODE[gt_arg2],If .NODE[gt_v_tpath] Then FULLWD Else .TGOAL); PICKTARGET(TAR,NTAR); If .TGOAL Neq GOALS(0,16) Then If .NTAR Eql T_LITERAL Or .TGOAL Eql GOALS(.NTAR[gt_pos],.NTAR[gt_len]) Then NODE = SETNEWPS(.NODE,.TGOAL,.TGOAL); If .NODE[rw_real] Then Begin GENMOVE(.NTAR,.NODE[gt_reg]); GENMOVE(.NODE[gt_reg],.TAR) End Else GENMOVE(.NTAR,.TAR); CHECKFORFLOW; Return .NODE End; Routine GDOT(NODE : Ref GT,GOAL : GOALWD) = Begin CODE(NODE[gt_arg1],FULLWD); CHECKFORFLOW; Return .NODE End; Routine GXNULL(NODE : Ref GT,GOAL : GOALWD) = Begin CHECKFORFLOW; Return .NODE End; Routine GNULL(NODE : Ref GT,GOAL : GOALWD) = Begin CODE(NODE[gt_arg1],FULLWD); If .NODE[rw_real_flow] Neq RFNONE Then GENMOVE(.NODE[gt_arg1],.NODE[gt_reg]); CHECKFORFLOW; Return .NODE End; Routine GBNULL(NODE : Ref GT,GOAL : GOALWD) = Begin CODE(NODE[gt_arg1],FULLWD); CODE(NODE[gt_arg2],FULLWD); CHECKFORFLOW; Return .NODE End; Routine GLOADNODE(NODE : Ref GT,GOAL : GOALWD) = Begin Macro OFFSETLIT=GMA(MAKLIT(LOCALOFFSET(OPR))) %; Local X : ADRWD, OPR : Ref GT; CODE(NODE[gt_arg1],FULLWD); OPR = .NODE[gt_arg1]; If .NODE[rw_real_flow] Eql RFNONE Then Return .NODE; If .NODE[rc_mov_target] Then If .OPR Eql T_LITERAL Then GENMOVE(.NODE[gt_arg1],.NODE[gt_reg]) Else If .OPR[gt_type] Eql S_NODE Then GENMOVE(.NODE[gt_arg1],.NODE[gt_reg]) Else If Not(.OPR) Then GENMOVE(.NODE[gt_arg1],.NODE[gt_reg]) Else If Not FORGOTTEN(.NODE,.NODE[gt_arg1]) Then Begin ! WE HAVE AN ST ENTRY WITH THE IMMF BIT ON X = GMA(.NODE[gt_reg]); Select .OPR[gt_type] Of Set [S_LOCAL]: Begin OPR = LOCDEF(.OPR); flg_stack_addr = TRUE; If LOCALOFFSET(OPR) Eql 0 And .X Neq PUSHED Then EMIT(PMOV,STACKPTR,.X) Else Begin EMIT(PMOV,OFFSETLIT,.X); EMIT(PADD,STACKPTR,GMA(.NODE[gt_reg])) End End; [S_FORMAL]: Begin EMIT(PMOV,(OFFSETLIT)+FLD_K_FORMAL,.X); EMIT(PADD,STACKPTR,GMA(.NODE[gt_reg])) End; [Otherwise]: EMIT(PMOV,GMA(.OPR),.X) Tes End; If .NODE[rc_add_offset] Then EMIT(PADD,GMOFF(.NODE),GMA(.NODE[gt_reg])); If .NODE[rc_negate] Then EMIT(PICK8(PNEG,.GOAL,.GOAL),GMA(.NODE[gt_reg]),0); If .NODE[rc_complement] Then EMIT(PICK8(PCOM,.GOAL,.GOAL),GMA(.NODE[gt_reg]),0); CHECKFORFLOW; If .GOAL Eql GOALS(0,8) Then If .NODE[rc_negate] Or .NODE[rc_complement] Then Return SETNEWPS(.NODE,0,8); Return .NODE End; Routine GREL(NODE : Ref GT,GOAL : GOALWD) = Begin Local L : Ref CELL; CODE(NODE[gt_arg1],FULLWD); CODE(NODE[gt_arg2],FULLWD); If .NODE[rw_flow] Then Begin SETNOPUSHVT; ADJUSTSTACK End; Case .NODE[rw_real_flow] From 0 To 3 Of Set [RFNONE]: 0; [RFREAL]: Begin EMIT(PCLR,GMA(.NODE[gt_reg]),0); L = GENLABEL(); GENCOMPARE(.NODE[gt_arg1],.NODE[gt_arg2],.NODE[gt_code],0,.L,.NODE[gt_v_tpath]); EMIT(PINC,GMA(.NODE[gt_reg]),0); PLACELABEL(.L) End; [RFFLOW]: GENCOMPARE(.NODE[gt_arg1], .NODE[gt_arg2], .NODE[gt_code], NODELABEL(.NODE[gt_lab_t]), NODELABEL(.NODE[gt_lab_f]), .NODE[gt_v_tpath]); [RFBOTH]: Begin EMIT(PCLR,GMA(.NODE[gt_reg]),0); GENCOMPARE(.NODE[gt_arg1],.NODE[gt_arg2],.NODE[gt_code],0, NODELABEL(.NODE[gt_lab_f]),.NODE[gt_v_tpath]); EMIT(PINC,GMA(.NODE[gt_reg]),0); EMIT(PBR,NODELABEL(.NODE[gt_lab_t]),0) End Tes; If .NODE[rw_flow] Then RESETPUSHVT; Return .NODE End; Routine GBIT(NODE : Ref GT,GOAL : GOALWD) = Begin Local L : Ref CELL; CODE(NODE[gt_arg1],FULLWD); CODE(NODE[gt_arg2],FULLWD); If .NODE[rw_flow] Then Begin SETNOPUSHVT; ADJUSTSTACK End; Case .NODE[rw_real_flow] From 0 To 3 Of Set [RFNONE]: 0; [RFREAL]: Begin EMIT(PCLR,GMA(.NODE[gt_reg]),0); L = GENLABEL(); BITX(.NODE[gt_arg1],.NODE[gt_arg2],Not .NODE[rw_complemented],.L); EMIT(PINC,GMA(.NODE[gt_reg]),0); PLACELABEL(.L) End; [RFFLOW]: Begin BITX(.NODE[gt_arg1],.NODE[gt_arg2],.NODE[rw_complemented],NODELABEL(.NODE[gt_lab_t])); EMIT(PBR,NODELABEL(.NODE[gt_lab_f]),0) End; [RFBOTH]: Begin EMIT(PCLR,GMA(.NODE[gt_reg]),0); BITX(.NODE[gt_arg1],.NODE[gt_arg2],Not .NODE[rw_complemented], NODELABEL(.NODE[gt_lab_f])); EMIT(PINC,GMA(.NODE[gt_reg]),0); EMIT(PBR,NODELABEL(.NODE[gt_lab_t]),0) End Tes; If .NODE[rw_flow] Then RESETPUSHVT; Return .NODE End; Literal XNT = 0, ! MOVE NON-TARGET TO DISTINCT TEMPORARY CN = 1, ! COMPLEMENT NON-TARGET CT = 2, ! COMPLEMENT TEMP CX = 3, ! COMPLEMENT X (COPY OF NON-TARGET) BISNT = 4, ! BIS NON-TARGET TO TARGET BISXT = 5, ! BIS X TO TARGET BISTX = 6, ! BIS TARGET TO X BICNT = 7, ! BIC NON-TARGET TO TARGET BICXT = 8, ! BIC X TO TARGET BICTX = 9; ! BIC TARGET TO X Routine GBOOL(NODE : Ref GT,GOAL : GOALWD,OPS : Ref Vector,FILL : Boolean) = Begin Local NT : Ref GT, XNT2 : Ref GT, T : Ref GT, X : Ref GT, RPOS : Integer, RSIZ : Integer, TPOS : Integer, TSIZ : Integer; CODE(NODE[gt_arg1],.GOAL); CODE(NODE[gt_arg2],.GOAL); If Not(.NODE[rw_real]) Then Return .NODE; PICKTARGET(T,NT); XNT2 = .NT; If .NODE[rc_mov_target] Then SIMPLEMOVE(.T,.NODE[gt_reg]); ! YES, THIS CAN HAPPEN, E.G. ' #340 AND Not .X ' ! IN WHICH THE TARGET SUBNODE WILL BE THE ' #340 '. If ISLIT(.T) Then Begin TPOS = 0; TSIZ = 16 End Else Begin TPOS = .T[gt_pos]; TSIZ = .T[gt_len] End; If ISLIT(.NT) Then Begin RPOS = Min(.GOAL,.TPOS); RSIZ = .GOAL; If .RPOS Lss .TPOS Then SHIFT(.NODE[gt_reg],.TPOS,.RPOS,Min(.TSIZ,.RSIZ)); If .TSIZ Lss .RSIZ Then ISOLATE(.NODE[gt_reg],.RPOS,.TSIZ); XNT2 = MAKLIT(CLITVALUE(.NT)^.RPOS) End Else Begin If (.TPOS-.GOAL)*(.NT[gt_pos]-.GOAL) Lss 0 Then RPOS = .GOAL Else If Abs(.TPOS-.GOAL) Lss Abs(.NT[gt_pos]-.GOAL) Then RPOS = .TPOS Else RPOS = .NT[gt_pos]; RSIZ = Min(.GOAL,Max(.TSIZ,.NT[gt_len])); If .TPOS Neq .RPOS Then SHIFT(.NODE[gt_reg],.TPOS,.RPOS,Min(.TSIZ,.RSIZ)); If .TSIZ Lss .RSIZ Then ISOLATE(.NODE[gt_reg],.RPOS,.TSIZ); If .NT[gt_pos] Neq .RPOS Then Begin XNT2 = MAKEDESTROYABLE(.XNT2); SHIFT(.XNT2,.NT[gt_pos],.RPOS,Min(.NT[gt_len],.RSIZ)) End; If Not .NODE[rc_mov_target] Then If (.RPOS Or (.RSIZ Mod 8)) Neq 0 Then Begin XNT2 = MAKEDESTROYABLE(.XNT2); ISOLATE(.XNT2,.RPOS,.RSIZ) End; If .NT[gt_len] Lss .RSIZ Then Begin XNT2 = MAKEDESTROYABLE(.XNT2); ISOLATE(.XNT2,.RPOS,.NT[gt_len]) End End; X = 0; Incr I From 0 To .OPS[-1]-1 Do Case .OPS[.I] From 0 To 9 Of Set [XNT]: Begin X = VERYTEMP(0); GENMOVE(.XNT2,.X) End; [CN]: If ISLIT(.XNT2) Then XNT2 = MAKLIT(Not CLITVALUE(.XNT2)) Else Begin XNT2 = MAKEDESTROYABLE(.XNT2); EMIT(PCOM,GMA(.XNT2),0) End; [CT]: EMIT(PICK8(PCOM,.RPOS,.RSIZ),GMA(.NODE[gt_reg]),0); [CX]: EMIT(PCOM,GMA(.X),0); [BISNT]: EMIT(PICK8(PBIS,.RPOS,.RSIZ),GMA(.XNT2),GMA(.NODE[gt_reg])); [BISXT]: EMIT(PBIS,GMA(.X),GMA(.NODE[gt_reg])); [BISTX]: EMIT(PBIS,GMA(.NODE[gt_reg]),GMA(.X)); [BICNT]: EMIT(PICK8(PBIC,.RPOS,.RSIZ),GMA(.XNT2),GMA(.NODE[gt_reg])); [BICXT]: EMIT(PBIC,GMA(.X),GMA(.NODE[gt_reg])); [BICTX]: EMIT(PBIC,GMA(.NODE[gt_reg]),GMA(.X)) Tes; SHIFT(.NODE[gt_reg],.RPOS,.GOAL,.RSIZ); If .GOAL Gtr .RSIZ Then Begin RPOS = .GOAL+.RSIZ; RSIZ = .GOAL-.RSIZ; If .FILL Then EMIT(PICK8(PBIS,.RPOS,.RSIZ), GMA(MAKLIT(MASK(.RPOS,.RSIZ,0))), GMA(.NODE[gt_reg])) Else CLEARFIELD(.NODE[gt_reg],.RPOS,.RSIZ) End; CHECKFORFLOW; Return SETNEWPS(.NODE,.GOAL,.GOAL) End; Macro PICKCASE= (If .NODE[gt_v_tpath] Then .O1*2+.O2 Else .O2*2+.O1) %; Routine GAND(NODE : Ref GT,GOAL : GOALWD) = Begin Bind O1=NODE[gt_arg1] : Ref GT, O2=NODE[gt_arg2] : Ref GT; Bind OPS = Plit( Plit(CN,BICNT), Plit(CN,BISNT,CT), Plit(BICNT), Plit(BISNT,CT)) : Vector; Return GBOOL(.NODE,.GOAL,.OPS[PICKCASE],0) End; Routine GOR(NODE : Ref GT,GOAL : GOALWD) = Begin Bind O1=NODE[gt_arg1] : Ref GT, O2=NODE[gt_arg2] : Ref GT; Bind OPS=Plit( Plit(BISNT), Plit(CT,BISNT), Plit(CN,BISNT), Plit(CN,BICNT,CT) ) : Vector; Return GBOOL(.NODE,.GOAL,.OPS[PICKCASE],0) End; Routine XEFLOW(LOP : Ref GT,ROP : Ref GT,TLAB,FLAB) : Novalue = Begin Local VT : Ref GT, RPOS : Integer; SETNOPUSHVT; RPOS = .ROP[gt_pos]; If (.RPOS+.ROP[gt_len] Leq 8) And (Not ISREG(.ROP)) Then Begin VT = VERYTEMP(.ROP[gt_reg]); SIMPLEMOVE(.ROP,.VT); ROP = .VT End; VT = POSITIONIT(.LOP,.LOP[gt_pos],.RPOS,1); CLEARFIELD(.VT,0,.RPOS); EMIT(PADD,GMA(.ROP),GMA(.VT)); GENBITTEST(.VT,.RPOS,NODELABEL(.FLAB)); EMIT(PBR,NODELABEL(.TLAB),0); RESETPUSHVT End; Routine GXOR(NODE : Ref GT,GOAL : GOALWD) = Begin Bind O1=NODE[gt_arg1] : Ref GT, O2=NODE[gt_arg2] : Ref GT; Bind OPS=Plit( Plit(XNT,BICTX,BICNT,BISXT), Plit(XNT,BICTX,BICNT,BISXT,CT), Plit(XNT,BICTX,BICNT,BISXT,CT), Plit(XNT,BICTX,BICNT,BISXT) ) : Vector; If .NODE[rw_real_flow] Neq RFFLOW Then Return GBOOL(.NODE,.GOAL,.OPS[PICKCASE],0) Else Begin CODE(O1,FULLWD); CODE(O2,FULLWD); ADJUSTSTACK; XEFLOW(.O1,.O2,.NODE[gt_lab_t],.NODE[gt_lab_f]); Return .NODE End End; Routine GEQV(NODE : Ref GT,GOAL : GOALWD) = Begin Bind O1=NODE[gt_arg1] : Ref GT, O2=NODE[gt_arg2] : Ref GT; Bind OPS=Plit( Plit(XNT,BICTX,BICNT,BISXT,CT), Plit(XNT,BICTX,BICNT,BISXT), Plit(XNT,BICTX,BICNT,BISXT), Plit(XNT,BICTX,BICNT,BISXT,CT)) : Vector; If .NODE[rw_real_flow] Neq RFFLOW Then Return GBOOL(.NODE,.GOAL,.OPS[PICKCASE],1) Else Begin CODE(O1,FULLWD); CODE(O2,FULLWD); ADJUSTSTACK; XEFLOW(.O1,.O2,.NODE[gt_lab_f],.NODE[gt_lab_t]); Return .NODE End End; Routine GSHIFT(NODE : Ref GT,GOAL : GOALWD) = Begin Local T : Ref ST, LAB : Ref CELL, NT : Ref GT, S : Integer, AS : Integer, OP : Integer, T1 : Ref GT, GT1 : ADRWD, CHP : Boolean, GMD : Boolean, MSK : Integer; CODE(NODE[gt_arg1],FULLWD); CODE(NODE[gt_arg2],FULLWD); If .NODE[rw_real_flow] Eql RFNONE Then Return .NODE; PICKTARGET(T,NT); If Not ISLIT(.NT) Then PUNT(777); GMD = FALSE; S = CLITVALUE(.NT); If .T Leq PF016 Then MSK = 0 Else Begin S = Min(16,.S-.T[gt_pos]); MSK = (Not MASK(.T[gt_pos],.T[gt_len],0)) ^ .S End; OP = (If .S Lss 0 Then PASR Else PASL); AS = Abs(.S); CHP = FALSE; If .AS Leq 2 Or ISCHEAP(.NODE[gt_reg]) Then Begin T1 = .NODE[gt_reg]; CHP = TRUE End Else Begin T1 = VERYTMPREG(); If .T1 Eql 0 Then T1 = .NODE[gt_reg] Else CHP = TRUE End; If .S Geq 13 Then Begin AS = 17-.S; SIMPLEMOVE(.T,.T1); GT1 = GMA(.T1); While (AS = .AS-1) Geq 0 Do EMIT(PROR,.GT1,0); CLEARMASK(.T1,.MASKS[.S] Or .MSK); GENMOVE(.T1,.NODE[gt_reg]); CHECKFORFLOW; Return .NODE End; If .S Eql 7 Then Begin SIMPLEMOVE(.T,.T1); GT1 = GMA(.T1); EMIT(PSWAB,.GT1,0); EMIT(PRORB,.GT1,0); EMIT(PROR,.GT1,0); CLEARMASK(.T1,127 Or .MSK); GENMOVE(.T1,.NODE[gt_reg]); CHECKFORFLOW; Return .NODE End; If .S Geq 8 Then Begin SIMPLEMOVE(.T,.T1); GT1 = GMA(.T1); GMD = TRUE; EMIT(PSWAB,.GT1,0); AS = .AS-8; If (.MSK And Not (255^.AS)) Eql 0 Then EMIT(PCLRB,.GT1,0) Else MSK = .MSK Or 255^.AS End; If (.S Leq -7) Or (Not .CHP) Then If ISREG(.T1) And .S Leq -8 Then Begin SIMPLEMOVE(.T,.T1); GT1 = GMA(.T1); GMD = TRUE; EMIT(PSWAB,.GT1,0); If .MSK Eql 0 Then EMIT(PMOVB,.GT1,.GT1); AS = .AS-8 End Else If .AS Geq 4 Then Begin If .T1 Eql .NODE[gt_reg] Then T1 = VERYTEMP(0); SIMPLEMOVE(.T,.NODE[gt_reg]); EMIT(PMOV,GMA(MAKLIT(.AS)),GMA(.T1)); LAB = GENLABEL(); PLACELABEL(.LAB); EMIT(.OP,GMA(.NODE[gt_reg]),0); EMIT(PDEC,GMA(.T1),0); EMIT(PBNE,.LAB,0); CLEARMASK(.NODE[gt_reg],.MSK); CHECKFORFLOW; Return .NODE End; If Not .GMD Then Begin SIMPLEMOVE(.T,.T1); GT1 = GMA(.T1) End; While (AS = .AS-1) Geq 0 Do EMIT(.OP,.GT1,0); CLEARMASK(.T1,.MSK); ! FOR DISTRIBUTED MULTIPLICATION THAT DIDN'T MAKE IT. If .NODE[rc_add_offset] Then EMIT(PADD,GMOFF(.NODE),GMA(.T1)); GENMOVE(.T1,.NODE[gt_reg]); CHECKFORFLOW; Return .NODE End; Routine GROT(NODE : Ref GT,GOAL : GOALWD) = Begin Local S : Integer, NT : Ref GT, T : Ref GT, OP : Integer; CODE(NODE[gt_arg1],FULLWD); PICKTARGET(T,NT); GENMOVE(.T,.NODE[gt_reg]); If ISLIT(.NT) Then Begin S = CLITVALUE(.NT); If .S<15,1> Then S = (.S+17) And %x'ffff'; If .S Leq 8 Then OP = PROL Else Begin OP = PROR; S = 17-.S End; While (S = .S-1) Geq 0 Do EMIT(.OP,GMA(.NODE[gt_reg]),0); CHECKFORFLOW End Else PUNT(777); Return .NODE End; Routine GMAXMIN(NODE : Ref GT,GOAL : GOALWD) = Begin Local T : Ref GT, N : Ref GT, L : Ref CELL, RELOP : Integer; CODE(NODE[gt_arg1],FULLWD); CODE(NODE[gt_arg2],FULLWD); If .NODE[rw_real_flow] Eql RFNONE Then Return .NODE; PICKTARGET(T,N); RELOP = (If .NODE[gt_code] Eql OP_MIN Then OP_GTR Else OP_LSS); GENMOVE(.T,.NODE[gt_reg]); L = GENLABEL(); GENCOMPARE(.NODE[gt_reg],.N,.RELOP,0,.L,0); GENMOVE(.N,.NODE[gt_reg]); PLACELABEL(.L); CHECKFORFLOW; Return .NODE End; Routine GSWAB(NODE : Ref GT,GOAL : GOALWD) = Begin CODE(NODE[gt_arg1],FULLWD); GENMOVE(.NODE[gt_arg1],.NODE[gt_reg]); EMIT(PSWAB,GMA(.NODE[gt_reg]),0); CHECKFORFLOW; Return .NODE End; Routine GCASE(NODE : Ref GT,GOAL : GOALWD) = Begin Local SDTD : Integer, T : Ref GT, L : Ref Vector, LX : Ref CELL, LE : Ref CELL, LSG : Ref CELL, CC : Ref CELL; STOPFREE(.NODE[gt_arg1],.NODE[LASTOPERAND]); CODELST(.NODE[gt_arg1]); CODE(NODE[gt_arg2],FULLWD); SDTD = .DYTEMPS; T = .NODE[gt_arg2]; LE = GENLABEL(); LX = GENLABEL(); If .swit_i_d Then LSG = GENLABEL(); CC = NEWCODECELL(); If ISREG(.T) Then PUTCODE(.CC,UNUSED,PADD, INDEXEDBY(.T,REFLABEL(.LE,.CC,UNUSED),OPND_LABEL),PROGCTR) Else Begin PUTCODE(.CC,UNUSED,PADD,IMMLAB(.LE,.CC,UNUSED),GMA(.T)); EMIT(PADD,DEFER(GMA(.T)),PROGCTR) End; If .swit_i_d Then Begin PLACELABEL(.LSG); EMIT(PWORD,GMA(MAKLIT(0)),0) End; PLACELABEL(.LE); If .swit_i_d Then LE = .LSG; L = GETSPACE(.NODE[gt_argc]); Incr I From 2 To .NODE[gt_argc]-2 Do Begin L[.I] = GENLABEL(); EMIT(PCASE,.L[.I],.LE) End; Incr I From 2 To .NODE[gt_argc]-2 Do Begin PLACELABEL(.L[.I]); DYTEMPS = .SDTD; CODE(NODE[gt_argv(.I)],FULLWD); If .NODE[rw_real] Then Begin SETNOPUSHVT; GENMOVE(.NODE[gt_argv(.I)],.NODE[gt_reg]); RESETPUSHVT End; EMIT(PBR,.LX,0) End; PLACELABEL(.LX); CODELST(.NODE[LASTOPERAND]); RELEASESPACE(.L,.NODE[gt_argc]); STARTFREE(.NODE[gt_arg1],.NODE[LASTOPERAND]); CHECKFORFLOW; Return .NODE End; Macro POPENABLE=(If Not .swit_hydra Then EMIT(PMOV,ALOCAL(.K),GMA(.LXSIGR)) Else EMIT(PMOV,ALOCAL(.K+2),GMA(.LXSIGR))) %; ! GET RID OF ELSE PART AFTER HYDRA PEOPLE RECOMPILE Routine GCOMPOUND(NODE : Ref GT,GOAL : GOALWD) = Begin Incr I From 0 To .NODE[gt_argc]-1 Do CODE(NODE[gt_argv(.I)],FULLWD); If .NODE[gt_v_enable] Then If Not .swit_hydra Then EMIT(PMOV,DEFER(GMA(.LXSIGR)),GMA(.LXSIGR)) Else Begin ! TEMPORARY UNTIL HYDRA PEOPLE RECOMPILE Local V; V = VERYTEMP(0); GENMOVE(.LXSIGR,.V); If ISREG(.V) Then EMIT(PMOV,INDEXEDBY(.V,2,OPND_NORMAL),GMA(.LXSIGR)) Else Begin EMIT(PADD,GMA(MAKLIT(2)),GMA(.V)); EMIT(PMOV,DEFER(GMA(.V)),GMA(.LXSIGR)) End End; CHECKFORFLOW; Return .NODE End; Routine GCALL(NODE : Ref GT,GOAL : GOALWD) = Begin Local LNK : Ref GT, S : Ref GT; SETNODYNVT; SETNOPUSHVT; Incr I From 1 To .NODE[gt_argc]-1 Do CODE(NODE[gt_argv(.I)],FULLWD); LNK = .NODE[gt_arg1]; Case .LNK[st_lnk_type] From LO_LNK_TYPE To HI_LNK_TYPE Of Set [LNK_SPECIAL]: Begin S = .NODE[gt_arg2]; Selectone .S Of Set [.LXHALT]: EMIT(PHALT,0,0); [.LXRESET]: EMIT(PRESETX,0,0); [.LXWAIT]: EMIT(PWAIT,0,0); [.LXNOP]: EMIT(PNOP,0,0); [.LEXEXCHJ]: Begin LEXEXCHJ[st_v_listed_external] = TRUE; EMIT(PJSR,PROGCTR,GMA(.LEXEXCHJ)) End Tes End; [LNK_BLISS]: Begin EMIT(PJSR,PROGCTR,GMA(.NODE[gt_arg2])); If .NODE[gt_disp_16] Neq 0 Then ! FOR DIST MULTIPLICATION. EMIT(PADD,GMOFF(.NODE),GMA(.NODE)) End; [LNK_EMT]: EMIT(PEMT,BUILDOPD(OPND_TRAP,UNUSED,UNUSED,CLITVALUE(.NODE[gt_arg2])),0); [LNK_FORTRAN]: 0; ! Not CODED YET [LNK_INTERRUPT]: 0; [LNK_TRAP]: EMIT(PTRAP,BUILDOPD(OPND_TRAP,UNUSED,UNUSED,CLITVALUE(.NODE[gt_arg2])),0); [LNK_IOT]: EMIT(PIOT,0,0); [LNK_HYDRA]: Begin LXHLNK[st_v_listed_external] = TRUE; LXHLTB[st_v_listed_external] = TRUE; EMIT(PJSR,XREG(5),GMA(.LXHLNK)); EMIT(PWORD,GMA(.NODE[gt_arg2]),1); EMIT(PWORD,GMA(.LXHLTB),1) End; [LNK_IHYDRA]: Begin LXIHLNK[st_v_listed_external] = TRUE; GENMOVE(.NODE[gt_arg2],.RR0); EMIT(PJSR,PROGCTR,GMA(.LXIHLNK)) End Tes; CHECKFORFLOW; RESETPUSHVT; RESETDYNVT; Return .NODE End; Routine GIF(NODE : Ref GT,GOAL : GOALWD) = Begin Macro GENTHEN=.T<0,1> %, GENELSE=.T<1,1> %; Local SDTD : Integer, L : Ref CELL, T : Integer; Bind THENPART=NODE[gt_arg3] : Ref GT, ELSEPART=NODE[gt_arg4] : Ref GT; STOPFREE(.NODE[gt_arg1],.NODE[gt_arg5]); CODELST(.NODE[gt_arg1]); CODE(NODE[gt_arg2],FULLWD); If ISLIT(.NODE[gt_arg2]) Then If CLITVALUE(.NODE[gt_arg2]) Then T = 1 Else T = 2 Else T = 3; If GENTHEN Then Begin SDTD = .DYTEMPS; CODE(THENPART,FULLWD); If .NODE[rw_real] Then Begin SETNOPUSHVT; GENMOVE(.THENPART,.NODE[gt_reg]); RESETPUSHVT End; L = GENLABEL(); EMIT(PBR,.L,0); DYTEMPS = .SDTD; End Else PLACELABEL(NODELABEL(.THENPART)); If GENELSE Then Begin CODE(ELSEPART,FULLWD); If .NODE[rw_real] Then Begin SETNOPUSHVT; GENMOVE(.ELSEPART,.NODE[gt_reg]); RESETPUSHVT End; End Else PLACELABEL(NODELABEL(.ELSEPART)); If GENTHEN Then PLACELABEL(.L); CODELST(.NODE[gt_arg5]); STARTFREE(.NODE[gt_arg1],.NODE[gt_arg5]); CHECKFORFLOW; Return .NODE End; Routine GSELECT(NODE : Ref GT,GOAL : GOALWD) = Begin Local TN : Ref GT, FO : Integer, L : Ref CELL, SVLON : Integer, SVFON : Integer; Label aaa; Macro THISOP=NODE[gt_argv(.I)] %; TN = .NODE[gt_argv(.NODE[gt_argc]-2)] And %x'7fffffff'; FO = CLITVALUE(.NODE[LASTOPERAND]); CODE(NODE[gt_arg1],FULLWD); If .NODE[rw_real_flow] Neq RFNONE Then If Not .NODE[rc_otherwise] Then EMIT(PMOV,GMA(MAKLIT(-1)),GMA(.NODE[gt_reg])); If .FO Neq 0 Then EMIT(PCLR,GMA(.TN),0); Incr I From 1 To .NODE[gt_argc]-4 By 2 Do aaa: Begin L = GENLABEL(); If .THISOP Eql LEXOTHERWISE Then Begin If .I Gtr .FO Then Leave aaa; EMIT(PTST,GMA(.TN),0); EMIT(PBGT,.L,0); End Else If .THISOP Neq LEXALWAYS Then Begin CODE(THISOP,FULLWD); SVLON = .LON; SVFON = .FON; If .(THISOP) Eql T_NODE Then Begin LON = .GT[.THISOP,gt_lon]; FON = .GT[.THISOP,gt_fon] End; GENCOMPARE(.NODE[gt_arg1],.THISOP,OP_EQL,0,.L,0); LON = .SVLON; FON = .SVFON End; CODE(NODE[gt_argv(.I+1)],FULLWD); If .NODE[rw_real_flow] Neq RFNONE Then Begin SETNOPUSHVT; GENMOVE(.NODE[gt_argv(.I+1)],.NODE[gt_reg]); RESETPUSHVT End; If .I Lss .FO Then EMIT(PADD,GMA(MAKLIT(1)),GMA(.TN)); PLACELABEL(.L) End; CHECKFORFLOW; Return .NODE End; Routine GMOVP(NODE : Ref GT,GOAL : GOALWD) = Begin Local L : Ref GT; CODE(NODE[gt_arg1],FULLWD); L = .NODE[gt_arg2]; EMIT(PMFPI+.L,GMA(.NODE[gt_arg1]),0); CHECKFORFLOW; Return .NODE End; Routine GSIGNAL(NODE : Ref GT,GOAL : GOALWD ) = Begin CODE(NODE[gt_arg1],FULLWD); GENMOVE(.NODE[gt_arg1],.NODE[gt_reg]); If .SIGLAB Eql 0 Then Begin SIGLAB = GENLABEL(); PLACELABEL(.SIGLAB); EMIT(PJMP,GMA(.LXSIGL),0) End Else EMIT(PBR,.SIGLAB,0); Return .NODE End; Routine GENABLE(NODE : Ref GT,GOAL : GOALWD) = Begin Local N : Ref GT, K : Ref GT, L : Ref CELL, CC : Ref CELL, LEXIT : Ref CELL; Label aaa; N = .NODE[gt_arg1]; K = .NODE[gt_arg2]; EMIT(PMOV,GMA(MAKLIT(XLO(.K)+6)),.NODE[gt_reg]); EMIT(PJSR,PROGCTR,GMA(.LXENAB)); L = GENLABEL(); LEXIT = GENLABEL(); If Not .swit_i_d Then EMIT(PCASE,.LEXIT,.L) Else Begin CC = NEWCODECELL(); PUTCODE(.CC,UNUSED,PJMP,REFLABEL(.LEXIT,.CC,UNUSED),0); REFLABEL(.L,.BRAK1,UNUSED) End; PLACELABEL(.L); If .swit_debug Then Begin LXY612[st_v_listed_external] = TRUE; EMIT(PJSR,PROGCTR,GMA(.LXY612)) End; aaa: Begin Incr I From 1 To .N[gt_argc]-4 By 2 Do Begin If .N[gt_argv(.I)] Eql LEXALWAYS Then Begin CODE(N[gt_argv(.I+1)],FULLWD); Leave aaa End; CODE(N[gt_argv(.I)],FULLWD); L = GENLABEL(); GENCOMPARE(.N[gt_argv(.I)],.LXSIGV,OP_EQL,0,.L,0); CODE(N[gt_argv(.I+1)],FULLWD); PLACELABEL(.L) End; EMIT(PJMP,GMA(.LXSIG1),0) End; PLACELABEL(.LEXIT); Return .NODE End; Routine GLABEL(NODE : Ref GT,GOAL : GOALWD) = Begin Local LAB : Ref ST; LAB = .NODE[gt_arg2]; LAB[st_lab_cell] = 0; CODE(NODE[gt_arg1],FULLWD); If .NODE[rw_real_flow] Neq RFNONE Then GENMOVE(.NODE[gt_arg1],.NODE[gt_reg]); ADJUSTSTACK; PLACELABEL(USERLABEL(.LAB)); CHECKFORFLOW; Return .NODE End; Routine GLOOP(NODE : Ref GT,XBR : Integer) = Begin Local L : Ref CELL; Bind tbl = Uplit Byte (4,7,7,7,4,7,6,7,6,7,6,6) : Vector[,Byte]; STOPFREE(.NODE[gt_arg1],.NODE[gt_arg2]); XBR = .tbl[.XBR]; CODELST(.NODE[gt_arg1]); CODELST(.NODE[gt_arg2]); If .XBR<0,1> Then Begin L = GENLABEL(); PLACELABEL(.L) End; If .XBR<2,1> Then CODE(NODE[gt_arg3],FULLWD); If .XBR<1,1> Then CODE(NODE[gt_arg4],FULLWD); If .XBR<0,1> Then EMIT(PBR,.L,0); CODE(NODE[gt_arg5],FULLWD); If .NODE[rw_real_flow] Neq RFNONE Then EMIT(PMOV,GMA(MAKLIT(-1)),GMA(.NODE[gt_reg])); STARTFREE(.NODE[gt_arg1],.NODE[gt_arg2]); CHECKFORFLOW; Return .NODE End; Macro DLC(X)= (If ISLIT(X) Then (CLITVALUE(X) And 1) Else 2) %; Routine GWD(NODE : Ref GT,GOAL : GOALWD) = Begin Return GLOOP(.NODE,0+DLC(.NODE[gt_arg3])) End; Routine GUD(NODE : Ref GT,GOAL : GOALWD) = Begin Return GLOOP(.NODE,3+DLC(.NODE[gt_arg3])) End; Routine GDW(NODE : Ref GT,GOAL : GOALWD) = Begin Return GLOOP(.NODE,6+DLC(.NODE[gt_arg4])) End; Routine GDU(NODE : Ref GT,GOAL : GOALWD) = Begin Return GLOOP(.NODE,9+DLC(.NODE[gt_arg4])) End; Routine GID(NODE : Ref GT,WHICH : Boolean) = Begin Macro STDTST= Begin EMIT(PCMP,GMA(.NODE[gt_arg1]),GMA(.NODE[gt_arg3])); EMIT(If .WHICH Then PBGE Else PBLE,.L1,0); End %; Local L : Integer, L1 : Ref CELL, L2 : Ref CELL, T : Boolean, T2 : Integer, T3 : Integer; STOPFREE(.NODE[gt_arg5],.NODE[gt_arg6]); L1 = GENLABEL(); L2 = GENLABEL(); T = 1; CODE(NODE[gt_arg2],FULLWD); CODE(NODE[gt_arg3],FULLWD); CODE(NODE[gt_arg4],FULLWD); CODELST(.NODE[gt_arg5]); CODELST(.NODE[gt_arg6]); GENMOVE(.NODE[gt_arg2],.NODE[gt_arg1]); If CLITVALUE(.NODE[gt_arg3]) Eql 0 Then EMIT(PTST,GMA(.NODE[gt_arg1]),0); If ISLIT(.NODE[gt_arg2]) Then If ISLIT(.NODE[gt_arg3]) Then Begin T2 = CLITVALUE(.NODE[gt_arg2]); T3 = CLITVALUE(.NODE[gt_arg3]); If .WHICH Then (If .T2 Geq .T3 Then T = 0) Else (If .T2 Leq .T3 Then T = 0) End; If .T Then EMIT(PBR,.L2,0); PLACELABEL(.L1); CODE(NODE[gt_arg7],FULLWD); EMIT(If .WHICH Then PSUB Else PADD,GMA(.NODE[gt_arg4]),GMA(.NODE[gt_arg1])); PLACELABEL(.L2); If ISLIT(.NODE[gt_arg3]) Then Begin L = CLITVALUE(.NODE[gt_arg3]); If Abs(.L)-.WHICH Eql %x'7fff' Then EMIT(PBR,.L1,0) Else If .L Eql 0 Then EMIT(If .WHICH Then PBPL Else PBLE,.L1,0) Else If .WHICH And .L Eql 1 Then EMIT(PBGT,.L1,0) Else If Not .WHICH And .L Eql -1 Then EMIT(PBMI,.L1,0) Else STDTST End Else STDTST; If .NODE[rw_real_flow] Neq RFNONE Then EMIT(PMOV,GMA(MAKLIT(-1)),GMA(.NODE[gt_reg])); STARTFREE(.NODE[gt_arg5],.NODE[gt_arg6]); CHECKFORFLOW; Return .NODE End; Routine GINCR(NODE : Ref GT,GOAL : GOALWD) = Begin Return GID(.NODE,FALSE) End; Routine GDECR(NODE : Ref GT,GOAL : GOALWD) = Begin Return GID(.NODE,TRUE) End; Routine NOTEREGS(RNAME : Ref GT) : Novalue = Begin RNAME[st_var_reg_save] = (.REGSCHNGD And Not .RESERVED) And ((1^6)-1) End; Routine FIXFORMALS(N : Integer,CURS : Ref CELL,E : Ref CELL) = Begin Routine FF(A : Ref ST,N : Integer) : Novalue = Begin If .A[adr_name_type] Eql NAME_FORMAL Then Begin A[adr_name_type] = NAME_NORMAL; A[adr_disp] = .A[adr_disp]+.N End End; While (CURS = NXTCC(.CURS)) Neq .E Do Case .OPERTYPE[.CURS[cel_code]] From LO_OPTYPE To HI_OPTYPE Of Set [Inrange]: 0; [OPTYPE_ONE]: FF(CURS[cel_src],.N); [OPTYPE_TWO]: Begin FF(CURS[cel_src],.N); FF(CURS[cel_dst],.N) End; [OPTYPE_BR]: FF(CURS[cel_src],.N); [OPTYPE_JSR]: FF(CURS[cel_dst],.N) Tes End; Routine GBODY(NODE : Ref GT,GOAL : GOALWD) = Begin Local RNAME : Ref GT, LNKAGE : Ref GT, BNCELL : Ref CELL, ENCELL : Ref CELL, BLOC : Integer, ELOC : Integer, LB : Integer, NR : Integer, LX : Ref CELL, L : Ref LSTHDR, I : Ref ITEM, A : ADRWD, B : ADRWD, LNKTYPE : Integer, HR : Integer, LEX : Ref GT; Own INLINSAVPLIT : Vector[9] Initial(0,0,1,1,1,1,1,0,0), SAVN : Vector[4] Initial(LXSAV2,LXSAV3,LXSAV4,LXSAV5); Macro POF2(X) =(((X) And -(X)) Eql (X)) %, INLINSAV =(.swit_debug Or .swit_zip Or POF2(.RNAME[st_var_reg_save])) %; LOC = 100; BNCELL = .NCELL; NR = 0; RNAME = .NODE[gt_arg2]; LNKAGE = .RNAME[st_var_linkage]; LNKTYPE = .LNKAGE[st_lnk_type]; NODE[gt_label] = LX = GENLABEL(); If .RNAME[st_v_unique] Then Begin CODENAME[3] = .RNAME[st_unique]; CODENAME[2] = (If .RNAME[gt_type] Eql S_ROUTINE Then .CODENAME[3] Else -.CODENAME[3]) End; CODENAME[0] = NT[.RNAME[st_name],nt_data]; CODENAME[4] = .RNAME; ! load up register parameters I = L = .RNAME[st_var_reg_list]; Until (I = .I[itm_rlink]) Eqla .L Do Begin A = XREG(.I[itm_ldata(1)]); B = GMA(.I[itm_rdata(1)]); If .A Neq .B Then EMIT(PMOV,.A,.B) End; ! code the body of the routine CODE(NODE[gt_arg1],FULLWD); LB = .MAXLOCALS+.STATICSIZE+(.VTEMPS[stk_max]+1)*2; NOTEREGS(.RNAME); ! if this routine produces a result If .LNKTYPE Neq LNK_INTERRUPT Then Begin RNAME[st_var_reg_save] = .RNAME[st_var_reg_save] And (Not(1)); GENMOVE(.NODE[gt_arg1],.NODE[gt_reg]) End; ! place the label If .DYTEMPS Neq 0 Then EMIT(PADD,GMA(MAKLIT(.DYTEMPS)),STACKPTR); PLACELABEL(.LX); ! release locals If .LB Neq 0 Then EMIT(PADD,GMA(MAKLIT(.LB)),STACKPTR); NODE[gt_dtdelete] = .DYTEMPS; ! pop registers If .INLINSAVPLIT[.LNKTYPE] Or INLINSAV Then Begin Decr I From 5 To 0 Do If (.RNAME[st_var_reg_save] And 1^(.I)) Neq 0 Then EMIT(PMOV,POPPED,XREG(.I)) End; ! generate return Case .LNKTYPE From LO_LNK_TYPE To HI_LNK_TYPE Of Set [LNK_SPECIAL]: 0; [LNK_BLISS,LNK_HYDRA,LNK_IHYDRA]: If Not .swit_debug Then EMIT(PRTS,PROGCTR,0) Else Begin LXX612[st_v_listed_external] = TRUE; EMIT(PJMP,GMA(.LXX612),0) End; [LNK_EMT,LNK_INTERRUPT,LNK_TRAP,LNK_IOT]: Begin If .swit_debug Then EMIT(PJSR,PROGCTR,GMA(.LXX612)); EMIT(PRTI,0,0) End; [LNK_FORTRAN]: EMIT(PRTS,XREG(5),0) Tes; ENCELL = .NCELL; ELOC = .LOC; NCELL = .BNCELL; LOC = 0; ! if debug, generate a call to the debugger If .swit_debug Then Begin LXE612[st_v_listed_external] = TRUE; EMIT(PJSR,PROGCTR,GMA(.LXE612)) End; ! if registers saved in-line, generate pushes of the registers If .INLINSAVPLIT[.LNKTYPE] Or INLINSAV Then Begin Incr I From 0 To 5 Do If (.RNAME[st_var_reg_save] And 1^(.I)) Neq 0 Then Begin NR = .NR+1; EMIT(PMOV,XREG(.I),PUSHED) End End Else ! not saved in-line. generate a call to the register save routine Begin HR = FIRSTONE(.RNAME[st_var_reg_save]); NR = .HR+1; LEX = .SAVN[.HR-2]; LEX[st_v_listed_external] = TRUE; EMIT(PJSR,XREG(1),GMA(.LEX)); End; ! allocate locals If .LB Neq 0 Then EMIT(PSUB,GMA(MAKLIT(.LB)),STACKPTR); NODE[gt_label] = 0; NCELL = .ENCELL; LOC = .ELOC; NR = (.NR+.VTEMPS[stk_max]+1)*2; FIXFORMALS(.NR,.BRAK1,.NCELL); Return .NODE End; Routine GLEAVE(NODE : Ref GT,GOAL : GOALWD) = Begin Local LAB : Ref GT, LABNODE : Ref GT, K : Integer, L : Ref GT; LAB = .NODE[gt_arg2]; LABNODE = .LAB[st_lab_node]; CODE(NODE[gt_arg1],FULLWD); If .LABNODE[rw_real_flow] Neq RFNONE Then GENMOVE(.NODE[gt_arg1],.LABNODE[gt_reg]); If .DYTEMPS Neq .LABNODE[gt_dtdelete] Then EMIT(PADD,GMA(MAKLIT(.DYTEMPS-.LABNODE[gt_dtdelete])),STACKPTR); L = .NODE[gt_arg3]; K = .L; If .K Neq 0 Then POPENABLE; EMIT(PBR,USERLABEL(.LAB),0); Return .NODE End; Routine GRETURN(NODE : Ref GT,GOAL : GOALWD) = Begin Local R : Ref GT, K : Integer, L : Ref GT; R = .NODE[gt_arg2]; R = .R[st_retlab]; CODE(NODE[gt_arg1],FULLWD); If .R[gt_reg] Neq 0 Then GENMOVE(.NODE[gt_arg1],.R[gt_reg]); If .DYTEMPS Neq 0 Then EMIT(PADD,GMA(MAKLIT(.DYTEMPS)),STACKPTR); L = .NODE[gt_arg3]; K = .L; If .K Neq 0 Then POPENABLE; EMIT(PBR,.R[gt_label],0); Return .NODE End; Routine GINLINE(NODE : Ref GT,GOAL : GOALWD) = Begin Bind ILO=BUILDOPD(OPND_INLINE,0,0,0); PUTCODE(NEWCODECELL(),INST_INLINE,0,.NODE[gt_arg1],ILO); NCELL[cel_inl_comment] = .NODE[gt_v_inlinecom]; Return .NODE End; !!! THE FOLLOWING ARE THE DRIVERS FOR THE NODE-SPECIFIC GENERATORS !!! ---------------------------------------------------------------- Bind GENPLIT = Uplit Long ( GADD, ! + GSWAB, ! SWAB GBNULL, ! / GDOT, ! . GSUB, ! - (BINARY) GBNULL, ! MOD GBNULL, ! * GDOT, ! - (UNARY) GLOADNODE, ! + (UNARY) GSHIFT, ! ^ GBIT, ! BIT GREL, ! GTR GREL, ! LEQ GREL, ! LSS GREL, ! GEQ GREL, ! EQL GREL, ! NEQ GDOT, ! NOT, GEQV, ! EQV GAND, ! AND GOR, ! OR GXOR, ! XOR GREL, ! GTRU GREL, ! LEQU GREL, ! LSSU GREL, ! GEQU GREL, ! EQLU GREL, ! NEQU GROT, ! ROT GMAXMIN, ! MAX GMAXMIN, ! MIN PUNT, ! CARRY PUNT, ! OVERFLOW GSTORE, ! = 0, ! ERROR OPERATOR GCASE, ! CASE GNULL, ! CALL-STORE GNULL, ! CALL-PARM GWD, ! WHILE-DO GUD, ! UNTIL-DO GBODY, ! ROUTINE DEFN GCOMPOUND, ! COMPOUND GINCR, ! INCR GDECR, ! DECR GIF, ! IF GDW, ! DO-WHILE GDU, ! DO-UNTIL 0, ! CREATE 0, ! EXCHJ GSELECT, ! SELECT 0, ! EXITLOOP GLABEL, ! LABEL PLACEMENT 0, ! MODULE 0, ! PLIT GCALL, ! CALL GDOT, ! POINTER 0, ! [ GLEAVE, ! LEAVE GRETURN, ! RETURN GXNULL, ! NULL GINLINE, ! INLINE GENABLE, ! ENABLE GSIGNAL, ! SIGNAL GMOVP, ! MFPI, ETC. 0,0,0,0,0,0) : Vector[,Long]; Routine FREEUNDER(NODE : Ref GT,XLON) = Begin Local L : Ref GT, B : Boolean, A : Ref GT; Label aaa; If .PLSTCNT Gtr 0 Then Return 0; If .NODE Neq T_NODE Then Return 0; Decr I From .NODE[gt_argc]-1 To 0 Do aaa: Begin L = .NODE[gt_argv(.I)]; If .L Neq 0 Then If .L Eql T_NODE Then Begin A = 0; B = 0; If .L[gt_code] Eql OP_STORE Then Begin A = .L[gt_reg]; B = (.A Neq 0) End; If .L[gt_code] Eql OP_LOAD_NODE Then Begin A = .L[gt_reg]; If .A Geq 8 Then If .A[tn_request] Eql MEMREQDB And Not .A[tn_v_lit] Then If .A[gt_reg] Geq 8 Then B = (.GT[.A[gt_reg],gt_type] Eql S_NODE) End; If .B And .A[tn_lon_lu] Gequ .XLON Then Return 0; If FREEUNDER(.L,.XLON) Eql 0 Then Leave aaa Else RELEASESPACE(.L,.L[gt_argc]+SZ_NODE) End Else If .L Geq LOWFLOLSTTYPE Then RELLST(.L); NODE[gt_argv(.I)] = 0 End End; Routine CODEWALK(NODE : Ref GT) : Novalue = Begin Local N : Ref GT; If Not .NODE[gt_v_coded] Then Begin N = FASTLEXOUT(T_NODE,.NODE[gt_csparent]); If .N Eql .NODE Then Return; If .N[gt_v_coded] Then Return; If Not .N[gt_v_delayed] Then ! N IS A BOGUS NODE UNBOGUS(N); PULSECODE(.N,0) End End; Routine CODE(PNODE : Ref Vector,GOAL : GOALWD) : Novalue = Begin Local NODE : Ref GT, SLON : Integer, SFON : Integer, SVTN : Ref GT, NODE1 : Ref GT; Label aaa; NODE = .PNODE[0]; If .NODE Neq T_NODE Then Return; If .NODE[gt_label] Neqa 0 Then PLACELABEL(.NODE[gt_label]) Else If .NODE[gt_v_lab_req] Then PLACELABEL(NODELABEL(.NODE)); If .NODE[gt_v_mustgencode] Then If Not .NODE[gt_v_coded] Then Begin SLON = .LON; SFON = .FON; SVTN = .VTN; LON = .NODE[gt_lon]; FON = .NODE[gt_fon]; VTN = .NODE; PNODE[0] = NODE = Bliss(.GENPLIT[.NODE[gt_code]],.NODE,.GOAL); ADJUSTSTACK; LON = .SLON; FON = .SFON; VTN = .SVTN; aaa: Begin ! if we are not the parent and the parent has been coded... NODE1 = .NODE[gt_csparent]; If .NODE1 Neqa .NODE And .NODE1[gt_v_coded] Then Leave aaa; If Not ISCSECREATION(NODE1) Then Leave aaa; ! mark all CSE uses as coded Do Begin If Not (.NODE1[gt_v_delayed] And .NODE1[gt_v_mustgencode]) Then NODE1[gt_v_coded] = TRUE End Until (NODE1 = .NODE1[gt_csthread]) Eqla 0 End; NODE[gt_v_coded] = TRUE End Else CHECKFORFLOW Else Begin CODEWALK(.NODE); CHECKFORFLOW End; Selectone .NODE[gt_code] Of Set [OP_STORE]: If .NODE[gt_reg] Eqla 0 Then FREEUNDER(.NODE,.NODE[gt_lon]); [OP_LOAD_NODE,OP_DOT,OP_COMPOUND]: 0; [Otherwise]: FREEUNDER(.NODE,.NODE[gt_lon]) Tes End; Global Routine CODEDRIVER(LEX : Ref GT) : Novalue = Begin Local ENCELL : Ref CELL, T : Integer; CODENAME[0] = .MODNAME; CODENAME[2] = 0; CODENAME[3] = 0; CODENAME[4] = 0; DYTEMPS = 0; LOC = 0; SAMETOG = FALSE; SIGLAB = 0; flg_stack_addr = FALSE; VTEMPS = GETSPACE(10); VTEMPS[stk_idx] = -1; VTEMPS[stk_max] = -1; BRAK1 = NEWCODECELL(); BRAK1[cel_class] = INST_INLINE; NCELL = .BRAK1; NLHEAD = NEWLABCELL(0,0); PLSTCNT = 0; NODVT = 0; NOVTCNT = 0; REGSCHNGD = (If .flg_enable Then %o'77' Else 0); CODE(LEX,FULLWD); PLSTCNT = 0; If .LEX Eql T_NODE Then FREEUNDER(.LEX,.LEX[gt_lon]); VTN = .VTEMPS[stk_max]+1; If .LEX Eql T_NODE Then RELEASESPACE(.LEX,.LEX[gt_argc]+SZ_NODE); If .swit_debug Then LXHLTB[st_v_listed_external] = TRUE; If .MODDONE Then Begin ENCELL = .NCELL; NCELL = .BRAK1; T = .MAXLOCALS+.STATICSIZE+.VTN*2; If .T Neq 0 Then EMIT(PSUB,GMA(MAKLIT(.T)),STACKPTR); If .MAINDECL And .swit_debug Then Begin LXINT612[st_v_listed_external] = TRUE; EMIT(PJSR,PROGCTR,GMA(.LXINT612)) End; NCELL = .ENCELL End; RELEASESPACE(.VTEMPS,10); If .MODDONE And (.BRAK1 Neqa .NCELL Or .MAINDECL) Then EMIT(PHALT,0,0); BRAK2 = PUTCODE(NEWCODECELL(),INST_INLINE,0,0,0); RELALLTNS() ! RELEASE ALL TNS End; End Eludom