/* THIS IS THE BCPL CODE GENERATOR FOR THE INTEL 8086 MICROPROCESSOR, (FOR THE 1M (MAX) VERSION OF TRIPOS). IT HAS BEEN ADAPTED FROM THAT FOR THE PDP11 ( COPYRIGHT TRIPOS RESEARCH GROUP, CAMBRIDGE ). THIS VERSION ASSUMES ES=DS=SS. EACH SECTION STARTS IN A NEW CODE SEGMENT SETTING. THE 8086 REGISTERS ARE USED AS FOLLOWS:- . ES, DS AND SS ARE NOT CHANGED, CS CHANGES WITH SECTION . IP IS THE INSTRUCTION POINTER WHICH IS CHANGED ONLY IMPLICITLY BY NORMAL EXECUTION OF INSTRUCTIONS . SP IS THE MACHINE STACK POINTER USED BY CALL,RET,PUSH,POP ETC . BP IS THE BCPL STACK FRAME BASE POINTER . DI HOLDS THE ADDRESS OF THE GLOBAL VECTOR . THE OTHER 5 REGISTERS ARE USED FOR TEMPORARY STORAGE OF DATA ITEMS. FOR MANY OPERATIONS ANY OF THESE REGISTERS MAY BE USED, BUT FOR OTHERS OPERANDS ARE RESTRICTED TO ONE OR TWO POSSIBLE REGISTERS. . R0 = R.BX = REGISTER BX GENERAL, INDEX, FUNCTION AND VALOF RESULT, ARG1 R1 = R.AX = REGISTER AX GENERAL, MULTIPLICAND, LS PRODUCT, LS DIVIDEND, ARG2 R2 = R.CX = REGISTER CX GENERAL, SHIFT COUNTER, ARG3 R3 = R.DX = REGISTER DX GENERAL, REMAINDER, MS DIVIDEND, SIZE OF CALLING ROUTINE'S FRAME R4 = R.SI = REGISTER SI GENERAL, INDEX, ADDRESS OF CALLED ROUTINE'S DESCRIPTOR R5 = R.BP = REGISTER BP R6 = R.SP = REGISTER SP R7 = R.DI = REGISTER DI */ /* THE FOLLOWING STREAMS ARE USED FOR THE CROSS-COMPILER VERSION SYSPRINT (OUT) HEADING, DEBUGGING AND ERROR INFO OCODE (IN) OCODE FROM PHASE 1 CODE (OUT) A REPRESENTATION OF THE COMPILED M/C CODE */ /* THE CROSS VERSION CROSS-COMPILES ON 360/370/303X IBM MACHINES */ /* (UNDER K. MOODY'S IMPLEMENTATION OF BCPL) */ SECTION "CG1" GET "CGHDR" LET START(PARMS) BE $(1 LET V = 0 //*<3032 LET SYSP = FINDOUTPUT("SYSPRINT") LET VDA = DATE() OCODEFILE := "OCODE" CODEFILE := "CODE" CGWORKSIZE := 5000 DATVEC := GETVEC(14) FOR I = 1 TO 9 DO PUTBYTE(DATVEC,I,ASKII(GETBYTE(VDA,I+2))) PUTBYTE(DATVEC,3,ASKII('-')) PUTBYTE(DATVEC,7,ASKII('-')) PUTBYTE(DATVEC,5,GETBYTE(DATVEC,5) | #X20) PUTBYTE(DATVEC,6,GETBYTE(DATVEC,6) | #X20) // TO LOWER CASE PROFILING := FALSE STKCHKING := FALSE CALLCOUNTING := FALSE NAMING := TRUE DEBUGGING := FALSE CGLISTING := FALSE IF SYSP=0 THEN $( WRITETOLOG("NO PRINT STREAM SELECTED - CG ABORTED") STOP(16) $) SELECTOUTPUT(SYSP) VERSTREAM := SYSP FOR I = 1 TO GETBYTE(PARMS, 0) DO SWITCHON GETBYTE(PARMS, I) INTO $(2 DEFAULT: LOOP CASE 'P': PROFILING := TRUE CASE 'K': CALLCOUNTING := TRUE; LOOP CASE 'N': NAMING := FALSE; LOOP CASE 'C': STKCHKING := TRUE; LOOP CASE 'D': DEBUGGING := TRUE; LOOP CASE 'L': CGLISTING := TRUE; LOOP CASE 'W': CGWORKSIZE := 0 $( LET CH = ? UNLESS I+1<=GETBYTE(PARMS, 0) DO BREAK CH := GETBYTE(PARMS, I+1) UNLESS '0'<=CH<='9' DO BREAK CGWORKSIZE := CGWORKSIZE*10 + CH - '0' I := I+1 $) REPEAT $)2 /*3032>*/ ERR.P, ERR.L := LEVEL(), FAIL WRITES("RAL 8086 cg*N") //*<3032 CODESTREAM := FINDOUTPUT(CODEFILE) IF CODESTREAM=0 DO CGERROR("CAN'T OPEN %S", TRUE, CODEFILE) /*3032>*/ OCODESTREAM := FINDINPUT(OCODEFILE) IF OCODESTREAM=0 DO CGERROR("CAN'T OPEN %S", TRUE, OCODEFILE) SELECTINPUT(OCODESTREAM) V := GETVEC(CGWORKSIZE) IF V=0 DO CGERROR("CAN'T GET WORKSPACE OF %N", TRUE, CGWORKSIZE) IF CGWORKSIZE<500 DO CGERROR("GIVE MORE WORKSPACE TO CG", TRUE) PROGSIZE := 0 //*<3032 WRITEWCOUNT := 0 LISTCHAN := TRUE IF CGLISTING DO $( ORDCH := RDCH RDCH := MYRDCH $) /*3032>*/ L: OP := RDN() IF OP=0 GOTO X FOR I = 0 TO CGWORKSIZE DO V!I := 0 TEMPV, TEMPT := V, V+150 BREFV, BREFP := TEMPT, TEMPT PROCSTK, PROCSTKP := BREFV+129, 0 REG.K := PROCSTK+20 REG.N := REG.K+5 LABV := REG.N+5 DP := V+CGWORKSIZE PARAMNUMBER := (DP-LABV)/10 + 10 STV := LABV+PARAMNUMBER FOR P = LABV TO STV-1 DO !P := -1 FORGETALL() // INIT. REGISTERS STVP := 0 INITDATALISTS() INCODE := FALSE MAXGN := 0 MAXLAB := 0 MAXSSP := 0 RETURN.SET := 0 INITSTACK(SAVESPACESIZE) CODE(0, 0) // FIRST WORD WILL HOLD NO. OF WORDS OF CODE COMPILED TEST OP=S.SECTION THEN $( CGNAME(S.SECTION, RDN()) OP := RDN() $) OR CGNAME(S.SECTION, 0) SCAN() EVEN() UNLESS MAXGN=0 DO OUTPUTSECTION() PROGSIZE := PROGSIZE + STVP GOTO L X: WRITEF("PROGRAM SIZE %N BYTES*N", PROGSIZE) FAIL: UNLESS V=0 DO FREEVEC(V) UNLESS OCODESTREAM=0 DO ENDREAD() OCODESTREAM := 0 //*<3032 UNLESS RC=0 DO STOP(RC) /*3032>*/ $)1 //*<3032 AND MYRDCH() = VALOF $( LET CH = ORDCH() IF LISTCHAN DO $( WRITES("*N** ") LISTCNT := 0 LISTCHAN := FALSE $) IF CH=ENDSTREAMCH RESULTIS 0 WRCH(CH='*N'->'*S',CH) LISTCNT := LISTCNT + 1 IF LISTCNT>60 DO LISTCHAN := TRUE RESULTIS CH $) /*3032>*/ AND RDN() = VALOF $( LET A, SIGN = 0, FALSE LET CH = ? CH := RDCH() REPEATWHILE CH='*S' | CH='*N' | CH='L' IF CH=ENDSTREAMCH RESULTIS 0 IF CH='-' DO $( SIGN := TRUE CH := RDCH() $) WHILE '0'<=CH<='9' DO $( A := 10*A + CH - '0' CH := RDCH() $) IF SIGN DO A := -A RESULTIS A $) // READ IN AN OCODE LABEL AND RDL() = VALOF $( LET L = RDN() IF MAXLAB=PARAMNUMBER DO $( CGERROR("TOO MANY LABELS -* * INCREASE WORKSPACE", TRUE) $) AND CGERROR(N,F,A) BE $( WRITES("*NERROR. ") WRITEF(N,A) NEWLINE() RC := 10 IF F DO $( RC := 20 LONGJUMP(ERR.P, ERR.L) $) $) .