S-C Macro Assembler 3.0 -- ASM2/X.SYMBOL.TABLE

1000 *SAVE X.SYMBOL.TABLE
1010 *--------------------------------
1020 *      INITIALIZE SYMBOL TABLE
1030 *      1.  SET EOT TO BOT
1040 *      2.  CLEAR HASH POINTER TABLE
1050 *--------------------------------
1060 STINIT LDA LO.MEM    START OF SYMBOL TABLE
1070        STA EOT
1080        LDA LO.MEM+1
1090        STA EOT+1
1100        STA MACLBL+1 PRIVATE LABELS GO DOWN FROM THERE
1110        LDX #56      # BYTES IN HASH POINTER TABLE
1120        LDA #0
1130        STA MACLBL
1140        STA CURRENT.MAJOR.LABEL+1
1150 .1     STA HSHTBL-1,X
1160        DEX
1170        BNE .1
1180   .DO AUXMEM
1190        LDA RDRAM
1200        LDA RDRAM
1210        LDX #AUX.IMAGE.LEN-1
1220 .2     LDA AUX.IMAGE,X
1230        STA AUX.CODE,X
1240        DEX
1250        BPL .2
1260 BACK.TO.ROM
1270        PHA
1280        LDA RDROM
1290        PLA
1300   .FIN
1310        RTS          RETURN WITH X=0
1320 *--------------------------------
1330    .DO AUXMEM
1340 LDA.STPNTR
1350        BIT RDRAM
1360        JSR LDA.STPNTR.AUX
1370        JMP BACK.TO.ROM
1380 *
1390 ADC.STPNTR
1400        BIT RDRAM
1410        JSR ADC.STPNTR.AUX
1420        JMP BACK.TO.ROM
1430 *
1440 SBC.STPNTR
1450        BIT RDRAM
1460        JSR SBC.STPNTR.AUX
1470        JMP BACK.TO.ROM
1480 *
1490 LDA.PNTR
1500        BIT RDRAM
1510        JSR LDA.PNTR.AUX
1520        JMP BACK.TO.ROM
1530 *
1540 LDA.TPTR
1550        BIT RDRAM
1560        JSR LDA.TPTR.AUX
1570        JMP BACK.TO.ROM
1580 *
1590 LDA.SRCP
1600        BIT RDRAM
1610        JSR LDA.SRCP.AUX
1620        JMP BACK.TO.ROM
1630 *
1640 STA.PNTR
1650        STA WRAUX
1660        STA (PNTR),Y
1670        STA WRMAIN
1680        RTS
1690 STA.STPNTR
1700        STA WRAUX
1710        STA (STPNTR),Y
1720        STA WRMAIN
1730        RTS
1740 *--------------------------------
1750 AUX.IMAGE
1760 LDA.STPNTR.AUX .EQ *-AUX.IMAGE+AUX.CODE
1770        STA RDAUX
1780        LDA (STPNTR),Y
1790        STA RDMAIN
1800        RTS
1810 ADC.STPNTR.AUX .EQ *-AUX.IMAGE+AUX.CODE
1820        STA RDAUX
1830        ADC (STPNTR),Y
1840        STA RDMAIN
1850        RTS
1860 SBC.STPNTR.AUX .EQ *-AUX.IMAGE+AUX.CODE
1870        STA RDAUX
1880        SBC (STPNTR),Y
1890        STA RDMAIN
1900        RTS
1910 LDA.PNTR.AUX .EQ *-AUX.IMAGE+AUX.CODE
1920        STA RDAUX
1930        LDA (PNTR),Y
1940        STA RDMAIN
1950        RTS
1960 LDA.TPTR.AUX .EQ *-AUX.IMAGE+AUX.CODE
1970        STA RDAUX
1980        LDA (TPTR),Y
1990        STA RDMAIN
2000        RTS
2010 LDA.SRCP.AUX .EQ *-AUX.IMAGE+AUX.CODE
2020        STA RDAUX
2030        LDA (SRCP),Y
2040        STA RDMAIN
2050        RTS
2060 AUX.IMAGE.LEN .EQ *-AUX.IMAGE
2070    .FIN
2080 *--------------------------------
2090 *      A table of 28 pointers begins at $130, called HSHTBL.
2100 *      Each pointer points to the beginning of a chain of
2110 *      symbol entries.  The entries on a chain are kept
2120 *      in alphabetical order.  If a chain is empty, the
2130 *      pointer = $0000.
2140 *
2150 *      HSHTBL+$00:  Chain for target file entries
2160 *      HSHTBL+$02:  Chain for labels starting with "A"
2170 *      HSHTBL+$04:  Chain for labels starting with "B"
2180 *        - - -
2190 *      HSHTBL+$34:  Chain for labels starting with "Z"
2200 *      HSHTBL+$36:  Chain for Macro Names and Skeletons
2210 *
2220 *      Format of Target File Entry:
2230 *          0,1 -- Forward chain pointer (0=end of chain)
2240 *          2,3 -- Length of target file in bytes
2250 *          4   -- Length of code name = $02
2260 *          5,6 -- Target file code name:
2270 *                 5:  "@" = $40
2280 *                 6:  $40 + target file number ($00-$1F)
2290 *
2300 *      Format of Label Entry:
2310 *          0,1 -- Forward chain pointer (0=end of chain)
2320 *          2-5 -- Value of label
2330 *          6   -- Flags and length of label name:
2340 *                 Bits 5-0:  length of label name ($01-$20)
2350 *                 Bit    6:  =1 if forward reference
2360 *                 Bit    7:  =1 if has local labels
2370 *          7   -- First character of label name, and flag.
2380 *                 Bit 7 = 1 if label is .SEt label.
2390 *     thru 6+n -- The rest of the label name, with bit 7 = 0
2400 *
2410 *          If the label has local labels, they follow.
2420 *          Each local label occupies two bytes:
2430 *          1   -- Label number (0-99) +128
2440 *          2   -- Label value (distance from value of
2450 *                   named label)
2460 *          The local label list is terminated with a $00
2470 *                   in the label number position.
2480 *
2490 *      Format of Macro Definition Entry:
2500 *          0,1 -- Chain to next macro name
2510 *          2,3 -- $0000
2520 *          4   -- Length of macro name
2530 *          5   -- "[" + $5B
2540 *          6-n -- Rest of Macro name
2550 *          etc.-- The packed skeleton lines, each
2560 *                   terminated by $00.  A final $00
2570 *                   terminates the skeleton.
2580 *
2590 *      Private Labels are kept in a separate table.
2600 *      Each label takes 7 bytes.  Bytes 0-3 are the
2610 *      value, byte 4 is the colon number + $80,
2620 *      and bytes 5 and 6 are the macro call number.
2630 *      The Private Label table grows downward from
2640 *      MACLBL toward $0800.
2650 *
2660 *--------------------------------
2670 *      PACK SYMBOL FROM INPUT LINE
2680 *      UP TO 32 CHARACTERS PACKED AT SYMBOL+7
2690 *      AND FOLLOWING.
2700 *      # CHARS STORED IN SYMBOL+6
2710 *      RETURN CARRY CLEAR IF NO SYMBOL
2720 *      RETURN CARRY SET IF GOOD SYMBOL
2730 *--------------------------------
2740 PACK   LDX #0       POINT AT 1ST CHAR IN NAME
2750        CMP #CHR.PERIOD LOCAL SYMBOL?
2760        BEQ .1       YES
2770        CMP #':      COLON MEANS MACRO PRIVATE LABEL
2780        BNE .3       NO, NORMAL SYMBOL
2790 .1     STA SYMBOL+7 SAVE PERIOD OR COLON
2800        JSR GNC.UC   GET NEXT CHAR
2810        JSR CHECK.DIGIT
2820        BCC .4       NO, BAD SYMBOL
2830        JSR DECN     CONVERT TO BINARY
2840        LDX #0       IN CASE BAD SYMBOL...
2850        LDA DGTCNT         VALUE MUST BE < 100
2860        CMP #3            SO MUST BE 1 OR 2 DIGITS
2870        BCS .4       ...TOO MANY DIGITS, BAD SYMBOL
2880        LDA SYM.VALUE
2890        ORA #$80     BE SURE NOT 00
2900        STA SYMBOL+8 SAVE VALUE
2910        LDA CALL.NUM JUST IN CASE IT'S A
2920        STA SYMBOL+9 MACRO PRIVATE LABEL
2930        LDA CALL.NUM+1
2940        STA SYMBOL+10
2950        INX          SIGNAL GOOD SYMBOL
2960        BNE .4       ...ALWAYS
2970 *--------------------------------
2980 .3     JSR PACK.NAME
2990 .4     JSR BACKUP.CHAR.PNTR
3000        STX SYMBOL+6 SAVE LENGTH
3010        CPX #1       CARRY SET IF AT LEAST ONE CHAR
3020        LDX #0       CLEAR X AGAIN
3030        RTS
3040 *--------------------------------
3050 *      PACK A NAME INTO SYMBOL
3060 *--------------------------------
3070 PACK.NAME
3080        JSR CHECK.LETTER
3090        BCC .4       NOT A LETTER
3100 .1     CPX #32      SEE IF ALREADY 32 CHARACTERS
3110        BEQ .2       YES, IGNORE
3120        STA SYMBOL+7,X PUT CHAR IN ENTRY
3130        INX          POINT AT NEXT SLOT
3140 .2     JSR GNC.UC   GET NEXT CHAR FROM LINE
3150        JSR CHECK.DOT.DIGIT.OR.LETTER
3160        BCS .1       VALID CHAR
3170 .4     RTS          END OF NAME
3180 *--------------------------------
3190 *      SEARCH SYMBOL TABLE
3200 *      # OF CHARS STORED AT SYMBOL+6
3210 *      SYMBOL ITSELF AT SYMBOL+7 AND FOLLOWING
3220 *      JSR STSRCH
3230 *      IF FOUND: CARRY CLEAR
3240 *                (STPNTR)=ADDRESS OF ENTRY
3250 *      IF NOT FOUND: CARRY SET
3260 *                    (STPNTR)=ADDRESS OF
3270 *                    POINTER CELL WHICH
3280 *                    SHOULD POINT AT ENTRY
3290 *--------------------------------
3300 STSRCH SEC          CONVERT FIRST CHARACTER
3310        LDA SYMBOL+7 OF SYMBOL TO HASH TABLE INDEX
3320        CMP #CHR.PERIOD SEE IF LOCAL SYMBOL
3330        BEQ .8       YES
3340        CMP #':      COLON, THEN PRIVATE LABEL
3350        BNE .12      NO, NORMAL LABEL
3360        JMP SEARCH.PRIVATE.LABELS
3370 .12    SBC #$40     AT-SIGN
3380        ASL          DOUBLE INDEX, CLEAR CARRY
3390        ADC #HSHTBL
3400        STA STPNTR
3410        LDA /HSHTBL
3420        ADC #0
3430        STA STPNTR+1
3440 .1     LDY #0
3450        >SYM LDA,STPNTR GET POINTER FROM ENTRY
3460        STA TPTR
3470        INY
3480        >SYM LDA,STPNTR
3490        BEQ .4       END OF CHAIN, NOT IN TABLE
3500        STA TPTR+1
3510        LDX SYMBOL+6 # CHARS IN SYMBOL
3520        LDY #6       POINT AT LENGTH
3530        >SYM LDA,TPTR USE MINIMUM LENGTH
3540        AND #$3F     ISOLATE LENGTH
3550        CMP SYMBOL,Y
3560        INY
3570        BCS .2
3580        TAX
3590 .2     >SYM LDA,TPTR COMPARE BYTES FROM BOTH
3600        AND #$7F     ALLOW FLAG BITS IN SYMBOL
3610        CMP SYMBOL,Y
3620        BCC .3       NOT THIS ONE, BUT KEEP LOOKING
3630        BNE .4       NOT IN THIS CHAIN
3640        DEX
3650        BEQ .5       THE NAME IS THE SAME OR A SUBSET
3660        INY          NEXT BYTE PAIR
3670        BNE .2       ...ALWAYS
3680 .3     JSR .7       UPDATE POINTER, CLEAR CARRY
3690        BCC .1       ...ALWAYS
3700 .4     SEC          DID NOT FIND
3710        LDX #0       RESTORE X=0
3720        RTS
3730 .5     LDY #6       TEST LENGTHS
3740        >SYM LDA,TPTR
3750        AND #$3F     ISOLATE LENGTH
3760        CMP SYMBOL+6 # CHARS IN SYMBOL IN TABLE
3770        BEQ .6       SAME EXACTLY
3780        BCS .4       NEW SYMBOL IS SHORTER
3790        BCC .3       NEW SYMBOL IS LONGER
3800 .6     LDY #2       POINT AT VALUE
3810 .65    >SYM LDA,TPTR SET UP VALUE FOR EXPR SCAN
3820        STA SYM.VALUE-2,Y
3830        INY
3840        CPY #6
3850        BCC .65
3860 .7     LDA TPTR
3870        STA STPNTR
3880        LDA TPTR+1
3890        STA STPNTR+1
3900        CLC          SIGNAL DID FIND IT
3910        RTS
3920 *--------------------------------
3930 .8     LDA CURRENT.MAJOR.LABEL
3940        STA STPNTR
3950        LDA CURRENT.MAJOR.LABEL+1
3960        BEQ .11
3970        STA STPNTR+1
3980        CLC
3990        LDY #6       POINT AT LENGTH
4000        >SYM LDA,STPNTR GET LENGTH OF MAJOR SYMBOL
4010        BPL .4       NO LOCAL SYMBOLS YET
4020        AND #$3F     MASK TO REAL LENGTH
4030        ADC #7       POINT AT LOCALS
4040        TAY
4050 .9     >SYM LDA,STPNTR
4060        BEQ .4       END OF LOCALS, NOT FOUND
4070        CMP SYMBOL+8 COMPARE TO NAME OF LOCAL
4080        BEQ .10      FOUND IT!
4090        INY          SKIP TO NEXT LOCAL
4100        INY
4110        BNE .9       ...ALWAYS
4120 .10    INY          POINT AT VALUE OFFSET
4130        >SYM LDA,STPNTR
4140        CLC
4150        LDY #2       POINT AT MAJOR VALUE
4160        >SYM ADC,STPNTR
4170        STA SYM.VALUE
4180        INY
4190        >SYM LDA,STPNTR
4200        ADC #0
4210        STA SYM.VALUE+1
4220        INY
4230        >SYM LDA,STPNTR
4240        ADC #0
4250        STA SYM.VALUE+2
4260        INY
4270        >SYM LDA,STPNTR
4280        ADC #0
4290        STA SYM.VALUE+3
4300        CLC
4310        RTS
4320 .11    LDY #QER9     NO NORMAL LABEL YET
4330        JMP SOFT.ERROR
4340 *--------------------------------
4350 *      SEARCH PRIVATE LABEL TABLE
4360 *--------------------------------
4370 SEARCH.PRIVATE.LABELS
4380        LDA MACLBL
4390        STA STPNTR
4400        LDA MACLBL+1
4410 .1     STA STPNTR+1
4420        CMP LO.MEM+1       END OF TABLE YET?
4430        BCS .3            ...YES, NO MORE LABELS
4440        LDY #6
4450        >SYM LDA,STPNTR
4460        AND #$3F     ISOLATE FROM FLAG BITS
4470        CMP SYMBOL+10
4480        BNE .2       NO
4490        DEY
4500        >SYM LDA,STPNTR
4510        CMP SYMBOL+9
4520        BNE .2       NO
4530        DEY
4540        >SYM LDA,STPNTR
4550        CMP SYMBOL+8
4560        BEQ .4       YES, FOUND IT!
4570 .2     CLC          BUMP PNTR TO NEXT LABEL
4580        LDA STPNTR
4590        ADC #7
4600        STA STPNTR
4610        LDA STPNTR+1
4620        ADC #0
4630        BNE .1       ...ALWAYS
4640 *--------------------------------
4650 .3     SEC          SIGNAL NOT FOUND
4660        RTS
4670 *--------------------------------
4680 .4     DEY
4690 .5     >SYM LDA,STPNTR
4700        STA SYM.VALUE,Y
4710        DEY
4720        BPL .5
4730        CLC
4740        RTS
4750 *--------------------------------
4760 *      ADD SYMBOL TO TABLE
4770 *--------------------------------
4780 STADD  LDA SYMBOL+7 SEE IF LOCAL SYMBOL
4790        CMP #CHR.PERIOD
4800        BEQ .5       YES
4810        CMP #':      COLON, PRIVATE LABEL
4820        BNE .11      NO, NORMAL LABEL
4830        JMP ADD.PRIVATE.LABEL
4840 .11    LDY #1       POINT AT POINTER
4850 .1     >SYM LDA,STPNTR GET CURRENT POINTER
4860        STA SYMBOL,Y
4870        LDA EOT,Y
4880        >SYM STA,STPNTR
4890        STA PNTR,Y
4900        STA CURRENT.MAJOR.LABEL,Y
4910        LDA ORGN,Y   VALUE
4920        STA SYMBOL+2,Y
4930        LDA ORGN+2,Y
4940        STA SYMBOL+4,Y
4950        DEY
4960        BPL .1
4970        CLC          COMPUTE ENTRY SIZE
4980        LDA SYMBOL+6 FROM SYMBOL SIZE
4990        ADC #7
5000 .2     PHA          SAVE SIZE
5010        LDY EOT+1
5020        CLC
5030        ADC EOT      SEE IF ROOM FOR NEW ENTRY
5040        BCC .10
5050        INY
5060   .DO AUXMEM
5070 .10    CPY /$C000
5080        BCS .4       MEM FULL ERR
5090        STA EOT
5100   .ELSE
5110 .10    CMP MACSTK
5120        TAX          SAVE LOW BYTE
5130        TYA          GET HIGH BYTE
5140        SBC MACSTK+1
5150        BCS .4       MEM FULL ERR
5160        STX EOT
5170   .FIN
5180        STY EOT+1
5190        PLA          GET SIZE
5200        TAY
5210        DEY          CORRECT FOR INDEXING
5220 .3     LDA SYMBOL,Y
5230        >SYM STA,PNTR
5240        DEY
5250        BPL .3
5260        RTS
5270 .4     JMP MFER     MEM FULL ERR
5280 *--------------------------------
5290 .5     LDY #6       LENGTH BYTE
5300        >SYM LDA,STPNTR
5310        BMI .6       ALREADY HAVE SOME LOCAL LABELS
5320        ORA #$80     SET LOCAL FLAG
5330        >SYM STA,STPNTR
5340        BNE .8       ...ALWAYS
5350 .6     LDA EOT      BACK UP EOT
5360        BNE .7       OVER 00 TERMINATOR
5370        DEC EOT+1    OF LOCALS
5380 .7     DEC EOT
5390 .8     LDA SYMBOL+8 NAME OF LOCAL
5400        STA SYMBOL   SET UP TO ADD TO SYMBOL TABLE
5410        SEC
5420        LDY #1
5430        JSR CALC.OFFSET.BYTE
5440        JSR CALC.OFFSET.BYTE
5450        BNE .9       ERROR > 255
5460        JSR CALC.OFFSET.BYTE
5470        BNE .9       ERROR > 255
5480        JSR CALC.OFFSET.BYTE
5490        BNE .9       ERROR > 255
5500        LDA EOT
5510        STA PNTR
5520        LDA EOT+1
5530        STA PNTR+1
5540        LDA #3       SIZE IS 3 BYTES
5550        BNE .2       ...ALWAYS
5560 .9     JMP GT255ERR  VALUE > 255
5570 *--------------------------------
5580 CALC.OFFSET.BYTE
5590        INY
5600        LDA ORGN-2,Y
5610        >SYM SBC,STPNTR
5620        STA SYMBOL-1,Y
5630        RTS
5640 *--------------------------------
5650 *      ADD A PRIVATE LABEL
5660 *--------------------------------
5670 ADD.PRIVATE.LABEL
5680        SEC
5690        LDA MACLBL
5700        SBC #7
5710        STA MACLBL
5720        STA STPNTR
5730        LDA MACLBL+1
5740        SBC #0
5750        STA MACLBL+1
5760        STA STPNTR+1
5770        CMP #8       BELOW $0800?
5780        BCC .3       YES, NO MORE ROOM
5790        LDY #6       POINT AT LAST BYTE
5800 .1     LDA SYMBOL+4,Y
5810        CPY #4
5820        BCS .2
5830        LDA ORGN,Y
5840 .2     >SYM STA,STPNTR
5850        DEY
5860        BPL .1
5870        RTS
5880 .3     JMP MFER
5890 *--------------------------------