1: .title expr - expression evaluator 2: 3: .ident /16jan4/ 4: 5: .mcall (at)always,st.flg,ch.mne,xmit,genedt 6: .mcall (at)sdebug 7: .mcall (at)jne,jeq 8: always 9: st.flg 10: ch.mne 11: .mcall (at)setnz,error,search 12: 13: .globl abserr, absexp, abstrm, abstst, expr 14: .globl exprg, relexp, reltst 15: 16: 17: .if df rsx11d 18: .globl ed.gbl, edmask, cpopj 19: .endc 20: 21: .globl chrpnt, clcnam, clcsec, cradix, mode 22: .globl cvtnum, dmprld, expflg, flags, lsrch 23: .globl getchr, getnb, getsym, insert 24: .globl pass, rellvl, rolndx, r50dot, savreg 25: .globl setnb, setrld, setsec, setsym, setxpr 26: .globl symbeg, symbol, symrol, pstrol, value 27: .globl secrol, objsec 28: 29: .globl crfref 30: .if ndf oldcod 31: cc.opr= 040 32: cc.nam= 020 33: cc.sec= 010 34: cc.val= 004 35: cc.dsp= 002 36: .endc 37: 38: 39: .macro chscan table ;character scan 40: mov #table,r0 41: call chscan 42: .endm 43: 44: .macro gchtbl char, addr ;gen char scan table 45: .word addr, char 46: .endm 47: xitsec ;start in default sector 48: 49: exprg: ;external expression 50: .if ndf oldcod 51: decb oprflg+1 ;flag "ok for external expression" 52: call expr ;process 53: incb oprflg+1 ;restore 54: tst r0 ;reset r0 flags 55: return 56: .endc 57: 58: expr: ;expression evaluation 59: call savreg ;save registers 60: call term ;try for a term 61: beq 5$ ;exit if null 62: clr -(sp) ;non-null, set register flag storage 63: 1$: call setxpr ;set expression registers 64: bis (r3),(sp) ;save register flag 65: chscan boptbl ;scan the binary operator table 66: beq 2$ ; branch if not found 67: call 10$ ;found, call handler 68: br 1$ ;test for more 69: 70: 2$: bic #-1-regflg,(sp) ;mask all but register flag 71: beq 6$ ;branch if not register 72: bit #177770,(r4) ;in bounds? 73: beq 6$ 74: error 70,r,<pdp-11 only has 8 registers> 75: br 77$ 76: 6$: asr rellvl ;test relocaton level 77: bne 3$ ;branch if not 0 or 1 78: bcc 4$ ;branch if 0 79: tst (sp) ;relocatable, test register flag 80: beq 4$ ;branch if not set 81: 7$: error 1,r,<cannot relocate a register> 82: 77$: clr (sp) ;clear register bit 83: br 4$ 84: 85: 3$: error 2,a,<improper relocation> 86: 4$: bis (sp)+,(r3) ;merge register bit 87: setnz r0 ;set true 88: 5$: return 89: 10$: 90: mov r0,-(sp) ;stack operator address 91: mov r1,r3 ;leave pointer to "symbol" in r3 92: mov (r1)+,-(sp) ;stack symbol 93: mov (r1)+,-(sp) 94: mov (r1)+,-(sp) ; mode, 95: mov (r1)+,-(sp) ; value, 96: mov (r1)+,-(sp) ; and rel level 97: call glbtrm ;evaluate next tern 98: mov #expbak+^d10,r1 ;set to unstack previous 99: mov (sp)+,-(r1) ;rel level 100: mov (sp)+,-(r1) ;value 101: mov r1,r2 ;r2 points to previous value 102: mov (sp)+,-(r1) ;mode 103: mov (sp)+,-(r1) 104: mov (sp)+,-(r1) ;r1 points to previous symbol 105: .if ndf oldcod 106: tst oprflg 107: bpl 11$ 108: tst pass 109: beq 11$ 110: bit #glbflg!relflg,mode 111: bne expxxx 112: bit #glbflg!relflg,expbak+4 113: bne expxxx 114: 11$: 115: .endc 116: mov @(sp)+,-(sp) 117: asr (sp) ;absolute only? 118: bcs 12$ ; no 119: bis -(r2),-(r4) ;yes, merge flags 120: call abstst ;test for absolute 121: cmp (r2)+,(r4)+ ;restore registers 122: 12$: asl (sp) ;even out address 123: jmp @(sp)+ ;exit through handler 124: .if ndf oldcod 125: expxxx: inc oprflg 126: mov #200,r0 127: mov #expbak,r1 128: call expyyy 129: mov (sp)+,r0 130: sub #boptbl,r0 131: asr r0 132: asr r0 133: add #201,r0 134: mov #symbol,r1 135: call expyyy 136: mov #symbol,r1 137: clr (r1)+ 138: movb oprflg,(r1)+ 139: clrb (r1)+ 140: mov #glbflg,(r1)+ 141: clr (r1)+ 142: return 143: 144: expyyy: mov r0,-(sp) 145: call setrld 146: mov r2,-(sp) 147: movb #cc.opr,(r2)+ 148: clr -(sp) 149: bit #glbflg!relflg,4(r1) 150: beq 2$ 151: bit #glbflg,4(r1) 152: bne 1$ 153: mov #cc.sec,(sp) 154: cmpb 5(r1),objsec 155: beq 2$ 156: 1$: bis #cc.nam,(sp) 157: .rept 4 158: movb (r1)+,(r2)+ 159: .endm 160: cmp -(r1),-(r1) 161: 2$: add #6,r1 162: tst (r1) 163: beq 3$ 164: bis #cc.val,(sp) 165: movb (r1)+,(r2)+ 166: movb (r1)+,(r2)+ 167: 3$: bisb (sp)+,@(sp)+ 168: movb (sp)+,(r2)+ 169: movb oprflg,(r2)+ 170: jmp dmprld 171: 172: entsec implin 173: oprflg: .blkw 174: xitsec 175: .endc 176: 177: entsec impure 178: expbak: .blkw 5 ;previous term storage 179: xitsec 180: entsec dpure 181: boptbl: ;binary op table 182: gchtbl ch.add, bopadd+1 ; "+" 183: gchtbl ch.sub, bopsub+1 ; "-" 184: gchtbl ch.mul, bopmul ; "*" 185: gchtbl ch.div, bopdiv ; "/" 186: gchtbl ch.and, bopand ; "&" 187: gchtbl ch.ior, bopior ; "!" 188: .word 0 189: xitsec 190: 191: bopsub: call reltst ;make sure no globals 192: neg (r4) ; -, negate value 193: neg rellvl ; and rellvl 194: 195: bopadd: add (r2)+,(r4)+ ; +, add values 196: add (r2),(r4) ; and relocation levels 197: cmp -(r2),-(r4) ;point back to values 198: bit #glbflg!relflg,-(r2) ;abs * xxx? 199: beq 3$ ; yes, all set 200: bit #glbflg!relflg,-(r4) ;xxx * abs? 201: beq 4$ ; yes, old flags 202: bitb #glbflg,(r2)+ ;error if either global 203: bne 5$ 204: bitb #glbflg,(r4)+ 205: bne 5$ 206: cmpb (r4),(r2) ;rel +- rel, same sector? 207: bne 5$ ; no, error 208: bisb #relflg,-(r4) 209: tst rellvl 210: bne 3$ 211: bic #177400!relflg,(r4) 212: 3$: return 213: 214: 4$: mov (r1)+,(r3)+ 215: mov (r1)+,(r3)+ 216: bis (r1)+,(r3)+ 217: return 218: 219: 5$: jmp abserr 220: 221: 222: bopand: com (r2) 223: bic (r2),(r4) 224: return 225: 226: bopior: bis (r2),(r4) 227: return 228: bopmul: ; * 229: mov (r2),r0 ;fetch first arg 230: mov r0,-(sp) ;save a copy 231: bpl 1$ ;positive? 232: neg r0 ; no, make it so 233: 1$: mov (r4),r3 ;set second arg 234: bpl 2$ ;branch if positive 235: neg r3 ;negative, make it + 236: com (sp) ;toggle result sign 237: 2$: mul r3,r0 ;multiply 238: mov r1,r0 ;set for exit 239: br bopdvx ;exit through divide 240: 241: bopdiv: ; / 242: mov (r4),r3 ;set divisor 243: mov r3,-(sp) ;save a copy 244: bpl 1$ ;branch if plus 245: neg r3 ;make it thus 246: 1$: mov (r2),r1 ;set quotient 247: bpl 2$ ;again!!! 248: neg r1 249: com (sp) 250: 2$: clr r0 ;operate 251: div r3,r0 252: 253: bopdvx: tst (sp)+ ;test result 254: bpl 1$ ; ok as is 255: neg r0 ;no, negate it 256: 1$: mov r0,(r4) ;set result 257: return 258: 259: ;special entry point to expr 260: ;null field causes error 261: ;r0 set to value 262: 263: glbtrm: call term 264: beq abserr 265: br abserx 266: 267: glbexp: ;non-null expression 268: call expr 269: beq abserr 270: br abserx 271: 272: reltrm: call glbtrm 273: br reltst 274: 275: relexp: 276: call glbexp 277: reltst: bit #glbflg,flags 278: beq abserx 279: br abserr 280: 281: abstrm: call glbtrm 282: br abstst 283: 284: absexp: 285: call glbexp 286: abstst: bit #glbflg!relflg,flags 287: beq abserx 288: abserr: clr mode 289: clr rellvl 290: abserf: error 3,a,<bad expression> 291: abserx: mov value,r0 ;return with value in r0 292: return 293: .sbttl term evaluator 294: 295: term: ;term evaluator 296: call savreg ;save registers 297: call setxpr ; and set "expression" type 298: clr (r3) ;clear mode 299: clr (r4) ; and value 300: call term10 ;process 301: bic #defflg!lblflg!mdfflg,(r3) ;clear extraneous 302: clr rellvl ;assume absolute 303: bit #relflg,(r3) ;true? 304: beq 1$ 305: inc rellvl ; no, relocatable 306: 1$: inc expflg ;mark as expression 307: jmp setnb ;exit with non-blank and r0 set 308: 309: term10: call getsym ;try for a symbol 310: jeq term20 ;branch if not a symbol 311: .if ndf xcref 312: mov #symrol,rolndx 313: call crfref 314: .endc 315: cmp symbol,r50dot ;location counter? 316: beq 14$ ; yes, treat special 317: search symrol ;search the symbol table 318: beq 16$ ;branch if not found 319: bit #mdfflg,(r3) ;multiply defined? 320: beq 11$ ; no 321: error 5,m,<multiply defined> 322: 11$: bit #defflg,(r3) ;defined? 323: beq 13$ ; no 324: call setsec ;refer by sector name 325: br 12$ 326: 327: 13$: bit #glbflg,(r3) ;no, global? 328: jne term28 ; yes 329: error 4,u,<undefined symbol> 330: sdebug <undef 1> 331: 12$: bic #glbflg,(r3) ;clear internal global flag 332: jmp term28 333: 334: 14$: mov #clcnam,r1 ;dot, move to working area 335: mov #symbol,r2 336: xmit 4 337: bicb #^c<relflg>,(r3) ;clear all but rel flag 338: jmp term28 339: 340: 16$: search pstrol ;not user defined, perhaps an op-code? 341: tst (r3) ;op code? 342: bmi 17$ ;yes 343: search symrol ;set search pointers 344: .if df rsx11d 345: bis #dfgflg!glbflg,(r3) 346: bit #ed.gbl,edmask 347: beq 20$ 348: bic #dfgflg!glbflg,(r3) 349: .endc 350: error 4,u,<undefined symbol> 351: sdebug <undef 2> 352: 20$: call insert ;not in table, insert as undefined 353: 17$: clr (r3) ;be sure mode is zero 354: jmp term28 355: 356: .iif df rsx11d, genedt gbl 357: 358: term20: 359: mov cradix,r2 ;assume number, current radix 360: 21$: mov chrpnt,symbeg ;in case of re-scan 361: call cvtnum ;convert 362: beq term30 ; nope, missed again 363: bpl 22$ ;number, any overflow? 364: error 7,t,<number too big> 365: 22$: cmp r5,#ch.dot ;number, decimal? 366: beq 24$ ; yes 367: .if ndf xedlsb 368: cmp r5,#ch.dol ;no, local symbol? 369: beq 24$ ; yes 370: .endc 371: tstb r0 ;no, any numbers out of range? 372: jeq term28 ; no 373: error 6,n,<digit illegal in current radix> 374: br 23$ 375: 376: 24$: cmp r2,#10. ;"." or "$", were we decimal? 377: beq 25$ ; yes 378: 23$: call setsym ;no, 379: mov #10.,r2 ; try again with decimal radix 380: br 21$ 381: 382: 25$: cmp r5,#ch.dot ;decimal? 383: beq term27 ; yes 384: .if ndf xedlsb 385: call lsrch ;no, local symbol 386: bne term27 ;branch if found 387: .endc 388: term26: error 8,u,<local symbol not defined> ; no, flag as undefined 389: term27: call getchr ;bypass dot or dollar 390: term28: call setnb ;return pointing to non-blank 391: setnz r0 ;flag as found 392: term29: return 393: term30: 394: chscan uoptbl ;scan unary operator table 395: beq term29 ; not there 396: clr r2 ;clear for future use 397: call @(r0)+ ;found, go and process 398: jmp term28 ;exit true 399: 400: 401: entsec dpure 402: uoptbl: 403: gchtbl ch.add, glbtrm ; "+" 404: gchtbl ch.sub, term42 ; "-" 405: gchtbl ch.qtm, term44 ; """ 406: gchtbl ch.xcl, term45 ; "'" 407: gchtbl ch.pct, term46 ; "%" 408: gchtbl ch.lab, term47 ; "<" 409: gchtbl ch.uar, term50 ; "^" 410: .word 0 411: xitsec 412: 413: term42: call abstrm ;evaluate absolute 414: neg (r4) ;negate value 415: return 416: 417: term44: inc r2 ; """, mark it 418: term45: mov r4,r1 ; "'", set temp store register 419: call setsym ;point back to operator 420: 1$: call getchr ;get the next character 421: beq term48 ;error if eol 422: .if ndf xedlc 423: movb @chrpnt,(r1) ;store absolute char 424: bicb #200,(r1)+ ;clear possible sign bit and index 425: .iff 426: movb r5,(r1)+ 427: .endc 428: dec r2 ;another character 429: beq 1$ ; yes 430: br term27 ;bypass last char 431: 432: term46: call abstrm ;register expression 433: bis #regflg,(r3) ;flag it 434: return 435: 436: term47: ; "<" 437: call glbexp ;process non-null expression 438: cmp r5,#ch.rab ;">"? 439: beq term27 ; yes, bypass and exit 440: term48: jmp abserf ;error, flag it 441: term50: ; "^" 442: chscan uartbl ;scan on next character 443: beq term48 ; invalid, error 444: jmp @(r0)+ ;call routine 445: 446: entsec dpure 447: uartbl: ;up arrow table 448: gchtbl let.c, term51 ; ^c 449: gchtbl let.d, term52 ; ^d 450: gchtbl let.o, term53 ; ^o 451: gchtbl let.b term54 ; ^b 452: gchtbl let.r, trmr50 ; ^r 453: .if ndf xfltg 454: gchtbl let.f, term55 ; ^f 455: .endc 456: .if ndf oldcod 457: gchtbl let.p, term56 ; ^p 458: .endc 459: .word 0 460: xitsec 461: 462: term51: call abstrm ;process absolute 463: com (r4) ;complement value 464: return 465: 466: term52: add #2.,r2 467: term53: add #6.,r2 468: term54: add #2.,r2 469: mov cradix,-(sp) ;stack current radix 470: mov r2,cradix ;replace with local 471: call glbtrm ;evaluate term 472: mov (sp)+,cradix ;restore radix 473: return 474: 475: .globl setr50,mulr50 476: r50gch: call getchr ;get next character 477: cmp r2,#3 ;filled word? 478: beq r50xit ; yes 479: trmr50: call setr50 ;test radix 50 480: call r50prc ;process the character 481: bcc r50gch ;if cc no terminator seen 482: 483: 1$: cmp r2,#3 ;filled word? 484: beq r50xit ; yes 485: clr r0 ; no - pad with blanks 486: call r50prc 487: br 1$ 488: 489: r50xit: return ;done with argument 490: 491: r50prc: cmp r0,#50 ;rad50? 492: bhis 1$ ; no 493: mov r0,-(sp) ;save current char 494: mov (r4),r0 ;get partial 495: call mulr50 ;multiply 496: add (sp)+,r0 ;add in current 497: mov r0,(r4) ;save 498: inc r2 ;bump count 499: clc ;no terminator seen 500: return 501: 502: 1$: sec ;terminator seen 503: return 504: 505: .if ndf xfltg 506: .globl fltg1w 507: term55: call fltg1w ;process one word floating 508: beq term48 ;error if null 509: return 510: .endc 511: .if ndf oldcod 512: term56: ; ^p 513: call mk.upp ;make upper case 514: cmp r5,#'l&^c40 ;low limit? 515: beq 1$ ; yes 516: cmp r5,#'h&^c40 ; high? 517: bne term48 ; no, error 518: inc r2 ;yes, reflect high 519: 1$: add #3,r2 ;make 3 or 4 520: mov r2,-(sp) ;save operator 521: call setrld ;set up rld 522: movb #cc.opr,(r2)+ ;flag operator 523: movb (sp)+,(r2)+ ;unary type 524: call getnb ;bypass char 525: call getsym ;get the argument 526: mov #secrol,rolndx 527: call crfref ;cref into proper roll 528: mov #symbol,r1 529: .rept 4 ;move into code buffer 530: movb (r1)+,(r2)+ 531: .endm 532: inc oprflg ;get unique number 533: movb oprflg,(r2)+ ;stuff it 534: call dmprld ;dump it 535: mov #symbol,r1 536: clr (r1)+ ;symbol is zero 537: movb oprflg,(r1)+ ; followed by unique numbwr 538: clrb (r1)+ 539: mov #glbflg,(r1)+ 540: clr (r1)+ 541: return 542: 543: .endc 544: chscan: ;character scan routine 545: call mk.upp ;make char. upper-case 546: 1$: tst (r0)+ ;end (zero)? 547: beq 2$ ; yes 548: cmp (r0)+,r5 ;this the one? 549: bne 1$ ; no 550: tst -(r0) ;yes, move pointer back 551: mov chrpnt,symbeg ;save current pointer 552: call getnb ;get next non-blank 553: tst -(r0) ;move addr or zero into r0 554: return 555: 556: 2$: clr r0 557: return 558: 559: 560: mk.upp: cmp r5,#141 ; between a - z ? 561: blt 1$ ;no 562: cmp r5,#172 563: bgt 1$ ;no 564: sub #40,r5 ;yes, make it upper-case 565: 1$: return 566: 567: .end