Trailing-Edge
-
PDP-10 Archives
-
ap-c800d-sb
-
expgen.mac
There are 21 other files named expgen.mac in the archive. Click here to see a list.
; UPD ID= 1898 on 5/15/79 at 4:21 PM by N:<NIXON>
TITLE EXPGEN FOR COBOL V12A
SUBTTL CODE GENERATORS FOR ARITHMETIC EXPRESSIONS AL BLACKINGTON/CAM
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1974, 1979 BY DIGITAL EQUIPMENT CORPORATION
SEARCH P
%%P==:%%P
;EDITS
;V12A RELEASED
;NAME DATE COMMENTS
;DMN 27-FEB-79 ;[641] FIX INCORRECT TEST FOR OPERAND IS ACC AT LASTOP
;DAW 23-FEB-79 ;[637] FIX COMPUTE WITH COMP-1 RESULT
;EHM 14-APR-78 ;[534] FIX COMPUTE GETS ANSWER FROM WRONG AC
;V12 RELEASE
;EHM 28-DEC-76 ;[456] WARN IF ROUNDING IN WRONG PLACE
;V11 RELEASE
;JC 16-SEP-76 ;[443] FIX 'COMPUTE A = - (25)'
;ACK 28-MAY-75 COMP-3/EBCDIC CODE.
;V10 RELEASE
; EDIT 370 FIX RETURN FATAL ERROR IN EXPRESSION
; EDIT 360 FIX EDIT 320 FOR SIMPLE COMPUTE X = -A OR (-A)
; EDIT 350 TURN OFF ZERO BIT AFTER COMPUTE
; EDIT 321 FIX RECOVERY IN A COMPUTE STATEMENT IF DATA IS NOT QUALIFIED.
; EIDT 320 FIX COMPUTE X = - (EXP) (MINUS SIGN)
;EDIT 314 FIX RECOVERY IF COMPUTE STATEMENT HAS UNDEFINED VARIBLE
TWOSEG
SALL
RELOC 400000
EXPGEN: INTERNAL EXPGEN
ENTRY EXPRGN ;START OF AN EXPRESSION
ENTRY COMPGN ;"COMPUTE" GENERATOR
ENTRY CENDGN ;"CEND" GENERATOR
EXTERNAL PUTASY,PUTASN,FATAL,WARN,GETEMP,GETGEN,SETOPN,LNKSET
EXTERNAL BMPEOP,GETTAG,PUTTAG,ADJDP.,COMEBK,PUSEOP,PUSH12
EXTERNAL ADDX.,SUBX.,MULX.,DIVX.,EXPX.,MACX.,MXAC.,MNXAC.,SWAPAB
EXTERNAL PUT.XA,PUT.XB,PUT.EX
EXTERNAL ROUND,SIZERA,NOTNUM,BADEOP
EXTERNAL NEGCMP ; [360]
EXTERNAL OPNWRN ;[456]
DEFINE SUBGEN (X),<
XLIST
IRP X,<
ENTRY X'GN
X'GN=NOTOPR
>
LIST>
NOTOPR: MOVEM PP,SAVEPP
MOVEI DW,E.215
W1ERA: LDB LN,W1LN
LDB CP,W1CP
;PUT OUT A DIAGNOSTIC, THEN SCAN GENFIL FOR ENDEXP OR ENDIT OPERATOR.
GOBACK: PUSHJ PP,FATAL
JRST GOBAK3
GOBAK1: MOVE PP,SAVEPP
GOBAK2: PUSHJ PP,GETGEN
GOBAK3: JUMPL W1,GOBAK2
HRRZ TE,W2
CAIL TE,CADD. ; [321] GO PAST PARTS OF COMPUTE
CAILE TE,CEXP. ; [321] STMNT ADD,SUB,MULPY,DIV,EXPEN
SKIPA ; [321] OKAY SO FAR
JRST GOBAK2 ; [321] ONE OF THE ABOVE- GO ON
CAIL TE,LPAR. ; [321] ALSO GO PAST LEFT AND RIGHT
CAILE TE,EXP. ; [321] PARENS AND EXPRESSIONS
;[360] POPJ PP, ; [321] OKAY EXIT NOW
; [V10] JRST [SETZM NEGCMP ; /360/ TURN OFF NEGATE SWITCH
; [V10] POPJ PP,] ; [360] OK EXIT NOW
CAIN TE,YECCH. ; [V10] SKIP OVER THE YECCH ALSO.
JRST GOBAK2 ; [321] ONE OF THE ABOVE- GO ON
SETZM NEGCMP ; [V10]
POPJ PP, ; [V10]
;THE FOLLOWING ROUTINES SHOULD NEVER BE ENTERED FROM THE OUTSIDE
SUBGEN <CADD,CSUB,CMUL,CDIV,CEXP,LPAR,RPAR,ENDX>
;"COMPUTE" GENERATOR
COMPGN: SETZM NEGCMP ; [360] TURN OFF NEGATE SWITCH
SETZM ECARRY## ;[534] RESET ECARRY
SETZM FLTDIV## ;[637] CLEAR "RESULT IS FLOATING POINT"
SWOFF FEOFF1 ;TURN OFF MOST FLAGS
MOVEM W1,OPLINE ;SAVE LN&CP OF OPERATOR
SWON FBIGCV ;TURN ON "CONVERT TO FL.PT. IF TOO BIG"
HRRZ TC,EOPLOC ;GET FIRST OPERAND
IFN ANS68,<
ADDI TC,1
>
IFN ANS74,<
MOVE CH,CMPLVL
IMULI CH,4 ;4 WORDS EACH
ADDI TC,1(CH)
>
CAIL TC,(EACA)
JRST BADEOP ;THERE ISN'T ONE--ERROR
MOVEM EACA,EOPNXT
MOVE W2,1(TC) ;GET OPERAND'S SECOND WORD
LDB CH,W2SUBC ;GET SUBSCRIPT COUNT
ADDI CH,1
LSH CH,1
HRLS CH
PUSHJ PP,PUSEOP ;STASH IT IN EOPTAB
MOVEI CH,0 ; FOLLOWED BY
PUSHJ PP,PUSEOP ; ZERO
MOVE TA,W2 ;IF ITEM IS
LDB TE,LNKCOD ; NOT
CAIN TE,TB.DAT ; DATA-NAME,
JRST COMPG1 ; USE
MOVEI TA,0 ; ZERO
JRST COMPG2 ; DECIMAL PLACES
COMPG1: PUSHJ PP,LNKSET ;IT'S DATA-NAME--GET DATAB ENTRY ADDRESS
LDB TE,DA.NDP ;GET DECIMAL PLACES
LDB TD,DA.DPR ;IF DECIMAL POINT IS TO
SKIPE TD ; THE RIGHT OF THE WORD BOUNDARY,
MOVNS TE ; NEGATE
LDB TD,DA.USG## ;[637] GET USAGE OF TARGET
CAIN TD,%US.C1 ;[637] IF IT IS COMP-1
SETOM FLTDIV ;[637] SET FLAG
COMPG2: TLNE W2,GNROUN ;IS RESULT TO BE ROUNDED?
ADDI TE,1 ;YES--ADD 1 TO DECIMAL PLACES
IFN ANS74,<
SKIPN CMPLVL## ;NOT FIRST?
JRST .+3 ;IT IS
CAMGE TE,ERESDP ;FIND LARGEST IN SERIES
MOVE TE,ERESDP ;USE PREVIOUS
>
MOVEM TE,ERESDP
MOVE EACA,EOPNXT
IFN ANS74,<
AOS CH,CMPLVL ;BUMP COUNT
SOJN CH,COMEBK ;ONLY OUTPUT FIRST TIME
>
MOVE CH,[XWD SETZM.,OVFLO.]
PUSHJ PP,PUT.EX
SETOM OVFLFL## ;SIGNAL WE MIGHT NEED OVERFLOW CHECKING
JRST COMEBK
;"CEND" GENERATOR
CENDGN: SETZM ERESDP
SETZM FLTDIV## ;[637] CLEAR "FLOATING POINT RESULT"
SWOFF <FBIGCV!FEOFF1>-FALWY0; TURN OFF SOME FLAGS
MOVEM EACA,EOPNXT
HRRZ TC,EOPLOC
ADDI TC,1
CAIL TC,(EACA) ;ANY OPERANDS?
POPJ PP, ;NO--MUST HAVE HAD A YECCH
MOVEM TC,OPERND
MOVEM TC,CUREOP
IFN ANS74,<
SETZM CMPTMP## ;
SOSG CMPLVL ;MORE THAN 1 IN SERIES?
JRST CEND00 ;NO
MOVE TC,CMPLVL ;GET COUNT
PUSHJ PP,BMPEOP ;BYPASS OPERAND
POPJ PP, ;ERROR
PUSHJ PP,BMPEOP ;BYPASS "PSEUDO = OP"
POPJ PP,
SOJGE TC,.-4 ;LOOP
MOVE TC,CUREOP ;POINT TO VALUE OF COMP
HRRZM TC,CMPEOP## ;STORE FOR LATER
HRRZ TC,EOPLOC
ADDI TC,1
MOVEM TC,OPERND ;RESET
MOVEM TC,CUREOP
HRROS CMPLVL ;SIGNAL FIRST TIME
CEND0L: PUSHJ PP,CEND00 ;YES, LOOP BACK
SKIPN CMPTMP ;NEED TO RESTORE VALUE?
JRST CEND0N ;NO
IFN BIS,<
HLRZ CH,CMPTMP
SOJE CH,.+3 ;1 WORD ONLY
PUSHJ PP,PUTASA
SKIPA CH,[DMOVE.##+ASINC,,AS.MSC]
>
MOVE CH,[MOV##+ASINC,,AS.MSC]
PUSHJ PP,PUTASY
HRRZ CH,CMPTMP
PUSHJ PP,PUTASN
IFE BIS,<
HLRZ CH,CMPTMP
SOJE CH,CEND0N
MOVE CH,[MOV+AC1+ASINC,,AS.MSC]
PUSHJ PP,PUTASY
HRRZ CH,CMPTMP
ADDI CH,1
PUSHJ PP,PUTASN
>
CEND0N: HRRZ TC,EOPLOC
MOVEI TC,1(TC)
MOVEM TC,OPERND
MOVEM TC,CUREOP
PUSHJ PP,BMPEOP ;BYPASS THIS
POPJ PP, ;CAN'T HAPPEN
AOS TC,CUREOP ;BYPASS "PSEUDO = OP"
HRRM TC,EOPLOC ;SET TO TOP OF NEW OPERAND
MOVEI TC,1(TC)
MOVEM TC,OPERND
MOVEM TC,CUREOP
SOSE CMPLVL ;COUNT DOWN
JRST CEND0L ;NOT DONE YET
CEND00:
>;END OF IFN ANS74
MOVEI LN,EBASEB
PUSHJ PP,SETOPN
TSWT FBNUM;
JRST CEND2
CEND0: PUSHJ PP,BMPEOP
POPJ PP, ;ONLY 1 OP--MUST HAVE BEEN A YECCH.
HRRZ TC,EOPLOC ;GET
ADDI TC,1 ; CUREOP, AND RESET IT TO
EXCH TC,CUREOP ; TOP OF EOPTAB
ADDI TC,2 ;SKIP PAST COUNT WORD AND "PSEUDO =" OPERATOR
IFN ANS74,<
SKIPE CMPLVL ;LAST ONE (OR ONLY ONE)?
MOVE TC,CMPEOP ;YES, POINT TO IT
>
HRLM TC,OPERND
MOVE TA,1(TC) ; [314] GET DATA NAME ADDRESS
CAIN TA,100001 ; [314] IF DUMMY VARIABLE
POPJ PP, ; [314] WHICH REPLACED UNDEFINED ONE-QUIT
MOVEI LN,EBASEA
PUSHJ PP,SETOPN
IFN ANS74,<
SKIPE CMPTMP ;VALUE IN TEMP?
SETZM EBASEA ;ACTUALLY IN ACC 0 & 1
SKIPL CMPLVL ;FIRST TIME?
JRST CEND0B ;NO
HRRZS CMPLVL ;ONLY ONCE
HRRZ TE,EBASEA ;IS IT IN THE ACCS
CAILE TE,17
JRST CEND0B ;NO?
MOVEI TE,2
MOVE TD,EMODEA
CAIE TD,D2MODE
MOVEI TE,1 ;1 WORD ONLY
HRLZM TE,CMPTMP ;LHS = NO. OF WORDS
PUSHJ PP,GETEMP
IFN BIS,<
CAIN TD,D2MODE
PUSHJ PP,PUTASA ;NEED DMOVE
>
MOVE CH,EBASEA ;GET ACC
LSH CH,^D18+5
IFE BIS,<
ADD CH,[MOVEM.+ASINC,,AS.MSC]
>
IFN BIS,<
ADD CH,[ASINC,,AS.MSC]
CAIN TD,D2MODE ;NEED DMOVEM
TLOA CH,DMOVM.##
TLO CH,MOVEM.
>
PUSHJ PP,PUTASY
HRRZ CH,EACC
HRRM CH,CMPTMP ;RHS = TEMP ADDRESS
PUSHJ PP,PUTASN
IFE BIS,<
CAIE TD,D2MODE
JRST CEND0B
MOVE CH,EBASEA
LSH CH,^D18+5
ADD CH,[MOVEM.+AC1+ASINC,,AS.MSC]
PUSHJ PP,PUTASY
MOVEI CH,1(EACC)
PUSHJ PP,PUTASN
>
CEND0B:>
TSWT FANUM ;IS "A" NUMERIC?
PUSHJ PP,CEND3
HRRZ TE,EMODEA ;IS "A" A LITERAL?
CAIN TE,LTMODE
JRST CEND0A
HRRZ TE,EBASEA ;NO--IS IT THE AC'S?
CAIG TE,17
JRST CEND1 ;YES
CEND0A: SETZM EAC ;NO--GET IT INTO AC'S 0&1
PUSHJ PP,INTOAC ;GET "A" INTO THE AC'S
SETZM NEGEOP ;[443]
CEND1: HLRZ TC,OPERND ; [320] GET AC OPERND ADDRESS
MOVE TC,1(TC) ; [320] GET 2ND WORD OF OPERND
TLNE TC,NEGEOP ; [320] NEGATE THE RESULT IN THE AC?
PUSHJ PP,CENDN ; [320] YES
SETZM NEGCMP ; [360] TURN OFF NEGATE SWITCH
MOVE TC,OPERND
MOVE TC,1(TC)
TLNE TC,GNROUN
PUSHJ PP,ROUND
SETZM EMULSZ ;SET "SINGLE RESULT" INDICATOR
;[350] TLNN W1,GNSERA
;[350] JRST MACX.
;[350] PUSHJ PP,GETTAG ;GET A TAG NUMBER
;[350] MOVEM CH,ESZERA ;SAVE IT FOR "SPIF"
;[350] JRST SIZERA ;GENERATE "SIZE ERROR" CODE
TLNE W1,GNSERA ;[350] ON SIZE SPECIFIED?
JRST CEND1A ;[350] YES
PUSHJ PP,MACX. ;[350] GENERATE MOVE
JRST CEND1B ;[350] FINISH UP AND RETURN.
CEND1A: PUSHJ PP,GETTAG ;[350] GET A TAG NUMBER.
MOVEM CH,ESZERA ;[350] SAVE IT FOR "SPIF"
PUSHJ PP,SIZERA ;[350] GENERATE "SIZE ERROR" CODE
CEND1B: SWOFF FALWY0 ;[350] TURN OFF ZERO INDICATOR
POPJ PP, ;[350] RETURN
; NEGATE THE RESULT IN THE AC'S
; ONLY NEGATE FINAL RESULT IF COMPUTE STATEMENT HAS
; LEADING MINUS SIGN AND LEFT PAREN
CENDN: MOVE TC,NEGCMP ; [360] SEE IF WE SHOULD NEGATE THE FINAL OUTPUT.
CAIGE TC,2 ; [360] YES IF CORRECT COUNT
POPJ PP, ; [360] DO DON'T DO IT.
HRRZ TC,EMODEA ; [320] GET MODE OF AC
MOVSI CH,MOVN. ; [320] ASSUME 1-WORD RESULT
CAIE TC,D2MODE ; [320] IS IT 2-WORD RESULT?
JRST PUTASY ; [320] NO, PUT IN CODE AND RETURN
IFE BIS,<
MOVSI CH,NEG.## ; [320] FOR 2-WORD RESULT USE NEG UUO
>
IFN BIS,<
PUSHJ PP,PUTASA##
MOVSI CH,DMOVN.##
>
JRST PUTASY ; [320] PUT IN CODE AND RETURN
;"B" ISN'T NUMERIC. SEE IF IT IS NUMERIC EDITED.
CEND2: TLNN TB,GNOPNM
JRST NOTNUM ;IT ISN'T--TOUGH
MOVE TA,ETABLB ;IT IS--
PUSHJ PP,LNKSET ; GET
LDB TE,DA.INS ; INTERNAL SIZE
MOVEM TE,ESIZEB
MOVEI TE,EDMODE ;RESET MODE
MOVEM TE,EMODEB
SWON FBNUM;
JRST CEND0
;"A" ISN'T NUMERIC. SEE IF IT IS "ZERO".
CEND3: HRRZ TE,EMODEA
MOVE TD,EFLAGA
CAIN TE,FCMODE
CAIE TD,ZERO
JRST NOTNUM
JRST INTOAC ;IT IS "ZERO"--SET AC'S TO ZERO
;GENERATE CODE FOR EXPRESSION
EXPRGN: MOVEM W1,OPLINE
MOVEM PP,SAVEPP ;SAVE PP IN CASE OF ERROR
MOVE EACA,EOPNXT
MOVE TE,EACA
SUB TE,EOPLOC
MOVEM TE,EXPBEG
;[360] PUSHJ PP,EXPR1 ;EVALUATE EXPRESSION
PUSHJ PP,EXPRGA ; [360] CHECK SEQUENCE OF TERMS AND EVALUATE EXPRESSION.
EXPRA: MOVEI TA,COMEBK
PUSH PP,TA
MOVE TA,EOPLOC
ADD TA,EXPBEG
CAMN TA,EOPNXT
JRST EXPR0
HRRZ TD,W2
CAIE TD,YECCH.
POPJ PP,
PUSHJ PP,GOBAK2
;TROUBLE--PUT DUMMY DATAB OPERAND ON EOPTAB
EXPR0: MOVE EACA,TA
MOVEM EACA,EOPNXT
MOVE CH,OPLINE
TLZ CH,777774
TLO CH,(1B0)
PUSHJ PP,PUSEOP
HRRZI CH,100001
PUSHJ PP,PUSEOP
MOVE CH,[XWD 2,2]
JRST PUSEOP
; [360] CHECK TERM SEQUENCE IN AN EXPRESSION.
EXPRGA: PUSHJ PP,GETGEN ; [360] GET NEXT GENFIL INPUT
SETZM NEGCMP ; [360] RESET NEGATE SWITCH
JUMPL W1,EXPR1A ; [360] IT IS AN OPERAND, NO NEGATION
CAIN W2,CSUB. ; [360] LEADING MINUS SIGN
AOS NEGCMP ; [360] YES, FINAL NEGATION POSSIBLE
JRST EXPR11 ; [360] GO ON TO EVALUATE EXPRESSION
EXPR1: PUSHJ PP,GETGEN
JUMPL W1,EXPR1A
EXPR11: HRRZ TE,W2 ; [360] GET OPERATOR CODE
CAIN TE,ENDXP.
POPJ PP,
PUSHJ PP,NXTOPR
JRST EXPR1B
EXPR1A: PUSHJ PP,GTOPN1
EXPR1B: PUSHJ PP,GETOPR
EXPR2: SWOFF FEOFF1-FBIGCV-FALWY0;
HRRZ TE,W2
CAIG TE,CEXP. ;IS IT ONE OF THE ALGEBRAIC OPERATORS?
CAIGE TE,CADD.
JRST EXPR3 ;NO
PUSHJ PP,@EXPR5-CADD.(TE) ;YES--DISPATCH TO A ROUTINE
JRST EXPR2 ;LOOP
EXPR3: CAIN TE,RPAR.
POPJ PP,
CAIN TE,ENDXP.
JRST EXPR4
CAIE TE,YECCH.
JRST CONFUZ
EXPR4: SETZM ERESDP
POPJ PP,
EXPR5: EXP CADD
EXP CSUB
EXP CMUL
EXP CDIV
EXP CEXP
;GENERATE CODE FOR A+B
CADD: PUSHJ PP,ADDSUB ;INSURE THAT WE CAN ADD NOW
PUSHJ PP,BOPRND ;GET "B" OPERAND
JRST CADD4 ;IT IS IN AC'S
PUSHJ PP,AOPRND ;GET "A" OPERAND
JRST CADD3 ;IT IS IN AC'S
HRRZ TE,EMODEA ;IS "A" A LITERAL?
CAIN TE,LTMODE
JRST CADD6 ;YES--MAYBE WE'LL SWAP
CADD2: PUSHJ PP,INTOAC ;GET "A" INTO THE AC'S
CADD3: MOVE TE,OPERND
MOVE TE,1(TE)
TLNE TE,NEGEOP
JRST CSUB3A
CADD3A: PUSHJ PP,ADDX. ;GENERATE THE ADD
JRST SETAC ;SET OPERAND TO BE AC'S, AND RETURN
CADD4: PUSHJ PP,SWAPAB
CADD5: PUSHJ PP,BOPRN1 ;GET OTHER OPERAND
JRST CONFUZ ;IT CAN'T BE IN AC'S
JRST CADD3
CADD6: HRRZ TE,EMODEB ;IS "B" A LITERAL?
CAIN TE,LTMODE
JRST CADD2 ;YES--NO SENSE IN SWAPPING
PUSHJ PP,SWAPAB ;NO--SWAP SO LITERAL IS "B"
JRST CADD2
;GENERATE CODE FOR A-B
CSUB: PUSHJ PP,ADDSUB ;INSURE THAT WE CAN SUBTRACT NOW
PUSHJ PP,BOPRND ;GET "B" OPERAND
JRST CSUB4 ;IT IS IN AC'S
PUSHJ PP,AOPRND ;GET "A" OPERAND
JRST CSUB3 ;IT IS IN AC'S
PUSHJ PP,INTOAC ;GET "A" INTO AC'S
CSUB3: MOVE TE,OPERND
MOVE TE,1(TE)
TLNE TE,NEGEOP
JRST CADD3A
CSUB3A: PUSHJ PP,SUBX.
JRST SETAC
CSUB4: PUSHJ PP,SWAPAB
HRRZ TE,EMODEA ;NEGATE THE AC'S
CAIN TE,D2MODE
JRST CSUB5
MOVSI CH,MOVN. ;GENERATE <MOVN AC,AC>
JRST CSUB6
CSUB5:
IFE BIS,<
MOVSI CH,NEG. ;GENERATE <NEG. AC,AC>
>
IFN BIS,<
PUSHJ PP,PUTASA
MOVSI CH,DMOVN.
>
CSUB6: HRR CH,EAC
DPB CH,CHAC
PUSHJ PP,PUTASY
JRST CADD5
;GENERATE CODE FOR A*B
CMUL: PUSHJ PP,MULDIV ;INSURE THAT WE CAN MULTIPLY NOW
PUSHJ PP,BOPRND ;GET "B" OPERAND
JRST CMUL5 ;IT IS AC'S
PUSHJ PP,AOPRND ;GET "A" OPERAND
JRST CMUL3 ;IT IS AC'S
HRRZ TE,EMODEA
CAIE TE,FCMODE
CAIN TE,LTMODE
PUSHJ PP,SWAPAB
CMUL2: PUSHJ PP,INTOAC ;GET OPERAND INTO AC'S
CMUL3: PUSHJ PP,MULX. ;GENERATE THE MULTIPLY
CMUL4: PUSHJ PP,SETAC ;SET OPERAND TO BE AC'S
HRRZ TE,W2 ;IS NEXT OPERATOR ANOTHER "*"?
CAIN TE,CMUL.
JRST CMUL ;YES--LOOP
CAIN TE,CDIV. ;NO--IS IT "/"?
JRST CDIV ;YES
POPJ PP, ;NO--RETURN
CMUL5: MOVE TE,[XWD EBASEB,EBASEA] ;MOVE "B" TO "A"
BLT TE,EBASAX
MOVSS OPERND
PUSHJ PP,BOPRN1 ;GET OTHER OPERAND
JRST CONFUZ ;IT CAN'T BE IN AC'S
JRST CMUL3
;GENERATE CODE FOR A/B
CDIV: PUSHJ PP,MULDIV
PUSHJ PP,BOPRND ;GET "B" OPERAND
JRST CDIV5 ;IT'S IN AC'S
PUSHJ PP,AOPRND ;GET "A" OPERAND
JRST CDIV3
CDIV2:
IFN BISCMP,<
SETOM FLTDIV ;FORCE FLOATING POINT ON DIVIDE
>
PUSHJ PP,INTOAC ;GET "A" INTO AC'S
IFN ANS74&0,<
MOVE TE,ESIZEA
CAIL TE,^D18 ;MAX. SIZE
JRST CDIV3 ;YES, CAN NOT DO ANY BETTER
MOVE TE,[EBASEB,,ESAVEB##]
BLT TE,ESAVBX## ;SAVE CURRENT "B"
MOVE TE,[EBASEA,,EBASEB]
BLT TE,EBASBX ;COPY "A" TO "B"
MOVEI TE,D2MODE
MOVEM TE,EMODEB ;SET MODE TO 2-WORDS
MOVEI TE,^D18
MOVEM TE,ESIZEB ;MAKE "B" MAX. SIZE
SUB TE,ESIZEA
ADDM TE,EDPLB ;ADD EXTRA AS DECIMAL PLACES
PUSHJ PP,ADJDP.## ;ADJUST ACCS
MOVE TE,[EBASEB,,EBASEA]
BLT TE,EBASAX ;NEW "A"
MOVE TE,[ESAVEB,,EBASEB]
BLT TE,EBASBX ;RESTORE "B"
>
CDIV3: PUSHJ PP,DIVX.
JRST CMUL4
CDIV5: HRRZ TE,EMODEB ;ARE AC'S 2-WORD COMP
CAIN TE,D2MODE
JRST CDIV7 ;YES
MOVEI TE,1 ;NO--GET A 1-WORD TEMP
PUSHJ PP,GETEMP
CDIV6: MOVE CH,[XWD MOVEM.+ASINC,AS.MSC]
CDIV8: PUSHJ PP,PUT.XA
IORI EACC,AS.TMP
HRRZ CH,EACC
PUSHJ PP,PUTASN
MOVEM EACC,EINCRB
MOVEI TE,AS.MSC
MOVEM TE,EBASEB
PUSHJ PP,AOPRND
JRST CONFUZ
MOVEI TE,1(EACA)
HRLM TE,OPERND
JRST CDIV2
CDIV7: MOVEI TE,2
PUSHJ PP,GETEMP
IFE BIS,<
IORI EACC,AS.TMP
MOVE CH,[XWD MOVEM.+ASINC,AS.MSC]
PUSHJ PP,PUT.XB
MOVEI CH,1(EACC)
PUSHJ PP,PUTASN
JRST CDIV6
>
IFN BIS,<
PUSHJ PP,PUTASA
MOVE CH,[DMOVM.##+ASINC,,AS.MSC]
JRST CDIV8
>
;EXPONENTIATE.
CEXP: MOVE CH,W1 ;SAVE
PUSHJ PP,PUSEOP ; OPERATOR
PUSHJ PP,GETOPN ;GET NEXT OPERAND
PUSHJ PP,BOPRND ;GET "B" OPERAND
JRST CEXP5
CEXP1A: PUSHJ PP,AOPRND ;GET "A" OPERAND
JRST CEXP2
PUSHJ PP,INTOAC ;PUT IT INTO AC'S
CEXP2: PUSHJ PP,EXPX.
PUSHJ PP,SETAC
PUSHJ PP,GETOPR
HRRZ TE,W2
CAIN TE,CEXP.
JRST CEXP
POPJ PP,
CEXP5: MOVEI TE,1
HRRZ TD,EMODEA
CAIN TD,D2MODE
MOVEI TE,2
PUSHJ PP,GETEMP
HRRZM EACC,EINCRA
MOVEI TD,AS.MSC
MOVEM TD,EBASEA
MOVE TE,[XWD EBASEA,EBASEB]
BLT TE,EBASBX
PUSHJ PP,MACX.
MOVE TE,[XWD EBASEA,EBASEB]
BLT TE,EBASBX
JRST CEXP1A
;LOOK AHEAD TO SEE IF WE CAN ADD OR SUBTRACT.
;IF WE CANNOT, FIX IT SUCH THAT WE CAN.
ADDSUB: PUSHJ PP,ADSB6 ;GET OPERAND & OPERATOR
CAIN TE,CEXP. ;EXPONENTIATION?
JRST ADSB3 ;YES
ADSB2: CAIN TE,CMUL. ;MULTIPLICATION?
JRST ADSB4 ;YES
CAIN TE,CDIV. ;DIVISION?
JRST ADSB5 ;YES
POPJ PP, ;NO--RETURN
;NEXT OPERATOR IS "**"
ADSB3: PUSHJ PP,STASH ;STASH CURRENT AC'S
PUSHJ PP,CEXP ;GENERATE EXPONENTIATION CALLS
HRRZ TE,W2 ;GO BACK TO CHECK FOR
JRST ADSB2 ; MULTIPLY AND DIVIDE
;NEXT OPERATOR IS "*"
ADSB4: PUSHJ PP,STASH ;STASH CURRENT AC'S
JRST CMUL ;GENERATE MULTIPLY AND RETURN
;NEXT OPERATOR IS "/"
ADSB5: PUSHJ PP,STASH ;STASH CURRENT AC'S
JRST CDIV ;GENERATE DIVIDE AND RETURN
;GET NEXT OPERAND AND OPERATOR
ADSB6: MOVE CH,W1 ;SAVE
PUSHJ PP,PUSEOP ; THIS OPERATOR
PUSHJ PP,GETOPN ;GET OPERAND
PUSHJ PP,GETOPR ;GET OPERATOR
HRRZ TE,W2 ;EXTRACT OPERATOR CODE
POPJ PP,
;LOOK AHEAD TO SEE IF WE CAN MULTIPLY OR DIVIDE NOW.
;IF WE CANNOT, FIX IT SO THAT WE CAN.
MULDIV: PUSHJ PP,ADSB6 ;GET OPERAND AND OPERATOR
CAIE TE,CEXP. ;IS IT EXPONENTIATION?
POPJ PP, ;NO--RETURN
PUSHJ PP,STASH ;YES--SAVE CURRENT AC'S
JRST CEXP ;EXPONENTIATE, THEN RETURN
;GENERATE CODE TO GET "A" INTO THE AC'S
INTOAC: CAMN EACA,EOPLOC ;ANYTHING IN EOPTAB?
JRST INTOA0 ;NO
MOVE TD,[XWD EBASEB,ESAVER] ;YES--IF AC'S, STASH
BLT TD,ESAVRX
MOVEI TD,-2(EACA)
PUSHJ PP,STASHA
MOVE TD,[XWD ESAVER,EBASEB]
BLT TD,EBASBX
INTOA0: SETZM EAC
HRRZ TE,EMODEA
CAIN TE,FCMODE
JRST INTOA2
INTOA1: MOVS TA,OPERND
MOVE TA,1(TA)
SKIPE FLTDIV## ;[637] IS RESULT FLOATING?
JRST INTOF1 ;[637] YES, FLOAT "A"
TLNE TA,NEGEOP
JRST MNXAC.
JRST MXAC.
;[637] "FLTDIV" HAS BEEN SET TO -1 BY "COMPGN". THIS HAPPENS WHEN
;[637] THE COBOL STATEMENT IS "COMPUTE COMP-1 = EXPRESSION"
;[637] OR A DIVIDE OPARAND HAS BEEN SEEN IN EXPRESSION.
;[637] THE FIRST OPERAND IS BROUGHT INTO THE ACS AS COMP-1 OR COMP-2,
;[637] THUS FORCING COBOL TO EVALUATE THE EXPRESSION
;[637] ENTIRELY WITH FLOATING-POINT OPERATIONS
INTOF1:
IFE BISCMP,<
TLNN TA,NEGEOP ;[637] NEGATE "A" ALSO?
JRST MXFPA.## ;[637] NO, JUST FLOAT IT
PUSHJ PP,MNXAC. ;[637] YES, GET -A IN ACS
JRST CCXFP.## ;[637] AND FLOAT IT
>
IFN BISCMP,<
TLNN TA,NEGEOP ;[637] NEGATE "A" ALSO?
JRST MXF2A.## ;[637] NO, JUST FLOAT IT
PUSHJ PP,MNXAC. ;[637] YES, GET -A IN ACS
JRST CCXF2.## ;[637] AND FLOAT IT
>
INTOA2: HRRZ TD,EMODEB
CAIE TD,FCMODE
CAIN TD,LTMODE
MOVEI TD,D1MODE
CAILE TE,DSMODE ;IS IT DISPLAY OR
CAIN TD,C3MODE## ; OR COMP-3.
TRNA ;YES, CHANGE THE MODE.
JRST INTOA3
MOVE TE,ESIZEB
MOVEI TD,D1MODE
CAILE TE,^D10
MOVEI TD,D2MODE
INTOA3: SWON FALWY0 ;SET "AC'S CONTAIN ZERO"
POPJ PP,
;GET "B" OPERAND FROM EOPTAB
BOPRND: MOVEI LN,EBASEB
PUSHJ PP,LASTOP
AOS (PP)
POP EACA,EOPHLD
MOVEM EACA,EOPNXT
MOVEI TE,EOPHLD
MOVEM TE,CUREOP
BOPA: HRRM TC,OPERND
TSWF FBNUM ;IS "B" NUMERIC?
POPJ PP, ;YES
HRRZ TE,EMODEB ;NO--IT BEST BE "ZERO"
MOVE TD,EFLAGB
BOPB: CAIN TE,FCMODE ;IS IT A FIG. CONST.?
CAIE TD,ZERO ;YES--ZERO?
JRST NOTNMA ;NO--YOU LOSE
POPJ PP,
;GET "B" OPERAND AS SECOND OPERAND
BOPRN1: MOVEI LN,EBASEB
PUSHJ PP,LASTOP
AOS (PP)
JRST BOPA
;GET "A" OPERAND FROM EOPTAB
AOPRND: MOVEI LN,EBASEA
AOPRN1: PUSHJ PP,LASTOP
AOS (PP)
HRLM TC,OPERND
TSWF FANUM ;IS "A" NUMERIC?
POPJ PP,
HRRZ TE,EMODEA
MOVE TD,EFLAGA
JRST BOPB
;GET THE LAST OPERAND FROM EOPTAB
LASTOP: MOVE EACA,EOPNXT
POP EACA,TC ;GET DECREMENT COUNT
SUB EACA,TC ;BACK UP EOPTAB POINTER
MOVS TE,1(EACA) ;[641] IS IT THE AC'S?
CAIN TE,GNOPNM ;[641] TEST FOR OPERAND SET AT SETAC
AOS (PP) ;YES--RETURN TO CALL+2
MOVEI TC,1(EACA)
MOVEM EACA,EOPNXT
PUSHJ PP,SETOPN
MOVE EACA,EOPNXT
MOVE TB,EBASEX(LN) ; [321] GETOPERAND LOCATION
CAIE TB,<CD.DAT>B20+1 ; [321] IF DUMMY QUIT NOW
POPJ PP, ; [321] OKAY- RETURN
JRST GOHOME ; [321] ABANDON EXPRESSION CODE GENERATION
;SET "LAST OPERAND IS AC".
SETAC: MOVSI CH,GNOPNM ;STASH FIRST PART OF
PUSHJ PP,PUSEOP ; OPERAND
MOVSI TD,GNOPNM
MOVE TE,EMODEA
DPB TE,ACMODE
MOVE TE,ESIZEA
DPB TE,ACSIZE
HRR TD,EDPLA
TLO TD,GNNOTD
MOVE CH,TD ;STASH SECOND PART OF
PUSHJ PP,PUSEOP ; OPERAND
MOVE CH,[XWD 2,2] ;STASH
JRST PUSEOP ; COUNT WORD AND RETURN
;IF ANYTHING IN AC'S--SAVE IT IN A TEMP
;LAST THING IN EOPTAB IS AN OPERAND.
STASH: MOVE TD,EOPNXT
SUB TD,(TD)
MOVEI TD,-4(TD)
STASHA: MOVE TE,1(TD)
HRRZ TC,0(TD)
TLNE TE,GNNOTD
CAILE TC,17
POPJ PP,
MOVE TE,[XWD EBASEA,ESAVEA] ;SAVE CURRENT "A"
BLT TE,ESAVAX
MOVE TC,TD
MOVE TD,1(TD)
HRRE TE,TD
MOVEM TE,EDPLA
LDB TE,ACMODE
MOVEM TE,EMODEA
LDB TE,ACSIZE
MOVEM TE,ESIZEA
PUSH PP,SW ;SAVE CURRENT SWITCHES
SWON FASIGN!FANUM!FBSIGN!FBNUM;
SWOFF FASUB!FBSUB;
MOVEI TE,1
HRRZ TD,EMODEA
CAIN TD,D2MODE
MOVEI TE,2
CAIN TD,D4MODE
MOVEI TE,4
PUSHJ PP,GETEMP
HRRM EACC,0(TC)
MOVE TE,[XWD EBASEA+1,EBASEB+1]
BLT TE,EBASBX
HRRZM EACC,EINCRB
HRRZI TE,AS.MSC
MOVEM TE,EBASEB
PUSHJ PP,MACX.
MOVE TE,[XWD ESAVEA,EBASEA] ;RESTORE "A"
BLT TE,EBASAX
POP PP,SW ;RESTORE SWITCHES
SETZM EAC
POPJ PP,
;SAVE ANYTHING IN AC'S (CONT'D).
;LAST THING IN EOPTAB IS OPERATOR, COUNT WORD, OR NOTHING
STASHB: MOVE EACA,EOPNXT
CAMN EACA,EOPLOC ;ANYTHING IN EOPTAB?
POPJ PP, ;NO--NOTHING TO STASH
MOVE TD,(EACA) ;IS LAST THING AN OPERATOR?
TLNN TD,777000
POPJ PP, ;NO--FORGET IT
MOVEI TD,-1(EACA)
SUB TD,0(TD)
JRST STASHA
;GET NEXT OPERAND.
GETOPN: PUSHJ PP,GETGEN
JUMPGE W1,NXTOPR ;IT IS AN OPERATOR
GTOPN1: PUSHJ PP,PUSH12 ;STASH W1&W2 IN EOPTAB
MOVEI TE,-1(EACA) ;SAVE
MOVEM TE,CUREOP ; THAT ENTRY LOCATION
TLNE W2,GNROUN ;[456] IS IT ROUNDED?
PUSHJ PP,ROUNER ;[456] YES, ERROR
TLNE W1,GNLIT
TDCA TE,TE
LDB TE,W2SUBC
MOVE TD,TE
JUMPE TE,GTOPN3
GTOPN2: PUSHJ PP,GETGEN
PUSHJ PP,PUSH12 ;STASH W1&W2
SOJG TE,GTOPN2
GTOPN3: LSH TD,1
ADDI TD,2
HRLS TD
MOVE CH,TD ;STASH COUNT WORD
JRST PUSEOP ; AND RETURN
;GET NEXT OPERATOR
GETOPR: PUSHJ PP,GETGEN
JUMPL W1,CONFUZ
HRRZ TE,W2
CAIE TE,YECCH.
POPJ PP,
;NEXT OPERATOR WAS YECCH--GO AWAY
GOHOME: MOVE PP,SAVEPP
PUSHJ PP,GOBAK3 ; [370] GET READY TO RETURN
MOVE TA,EXPBEG
ADD TA,EOPLOC
MOVEM TA,EOPNXT
JRST EXPRA
;WE WENT LOOKING FOR AN OPERAND, BUT FOUND AN OPERATOR.
NXTOPR: HRRZ TE,W2 ;LEFT PAREN?
CAIE TE,LPAR.
JRST NXTOP1 ;NO
PUSHJ PP,STASHB ;YES--STASH AC'S
SKIPLE NEGCMP ; [360] IF > 0 MEANS WE HAD A LEADING SIGN.
AOS NEGCMP ; [360] LEADING MINUS SIGN - COUNT LEFT PAREN
JRST EXPR1 ;EVALUATE EXPRESSION AND RETURN
NXTOP1: CAIE TE,CSUB. ;WAS IT A UNARY MINUS?
JRST NXTOP3 ;NO--WE'RE CONFUSED
PUSH PP,EACA
PUSHJ PP,GETOPN ;YES--GET NEXT OPERAND
POP PP,TD
MOVSI TE,NEGEOP ;SET "NEGATE OPERAND"
XORM TE,2(TD)
POPJ PP,
NXTOP3: CAIE TE,YECCH.
JRST CONFUZ
JRST GOHOME
;ERROR ROUTINES
;OPERAND WAS NOT NUMERIC (INSIDE EXPRESSION)
NOTNMA: MOVEI DW,E.211
SWON FERROR;
MOVE TC,(TC)
LDB CP,TCCP
LDB LN,TCLN
JRST FATAL
;WRONG NUMBER OF OPERANDS (INSIDE EXPRESSION)
BADOPA: MOVEI DW,E.214
JRST W1ERA
CONFUZ: MOVE TC,CUREOP
MOVE TC,(TC)
LDB LN,TCLN
LDB CP,TCCP
MOVEI DW,E.216
JRST GOBACK
;[456] USER HAS TRIED TO ROUND IN WRONG PLACE, WARN HIM
ROUNER: MOVEI DW,E.591 ;[456] GET DIAGNOSTIC
PUSH PP,TE ;[456] SAVE
PUSH PP,LN ;[456] SOME
PUSH PP,TC ;[456] REGISTERS
PUSHJ PP,OPNWRN ;[456] GIVE WARNING
POP PP,TC ;[456] GET
POP PP,LN ;[456] REGISTERS
POP PP,TE ;[456] BACK
POPJ PP, ;[456] AND CONTINUE
NEGEOP==1B<^D18+6>
EXTERNAL TCLN,TCCP,W1LN,W1CP,W2SUBC,EAC,SAVEPP
EXTERNAL EBASEA,EINCRA,ERESA,EDPLA,ESIZEA,EMODEA,EFLAGA,EBYTEA
EXTERNAL EBASEB,EINCRB,ERESB,EDPLB,ESIZEB,EMODEB,EFLAGB,EBYTEB,ETABLB
EXTERNAL EBASEX,EINCRX,ERESX,EDPLX,ESIZEX,EMODEX,EFLAGX,EBYTEX
EXTERNAL ESAVEA,ESAVEB,EBASAX,EBASBX,ESAVAX,ESAVBX
EXTERNAL ESAVER,ESAVRX
EXTERNAL EOPLOC,EOPNXT,CUREOP,OPLINE,OPERND,EXPBEG
EXTERNAL DA.NDP,DA.DPR,DA.INS
EXTERNAL LNKCOD,TB.DAT
EXTERNAL D1MODE,D2MODE,D4MODE,D6MODE,D7MODE,EDMODE,LTMODE,FCMODE,DSMODE,ZERO
EXTERNAL ACMODE,ACSIZE,TESUBC
EXTERNAL OVFLO.
EXTERNAL MOVN.,MOVEM.,JRST.,CAML.,COMP.D
EXTERNAL SKIPL.,SKIPA.,SETZM.,SETZB.,HRRZI.
EXTERNAL CHAC,ESAVAC,ESZERA,POWR10,ELITPC,EOPHLD,ERESDP
EXTERNAL AS.MSC,AS.TMP,D1LIT,D2LIT,AS.DOT,AS.%X,EMULSZ
EXTERNAL EBASEX ; [321]
CADD.==51
CSUB.==52
CMUL.==53
CDIV.==54
CEXP.==55
LPAR.==70
RPAR.==71
EXP.==72 ; [321] EXPRESSION START CODE
ENDXP.==73
YECCH.==105
ENDIT.==377
END