home *** CD-ROM | disk | FTP | other *** search
Text File | 2019-04-13 | 89.7 KB | 4,758 lines |
- ;*** as v1.00 program: one-pass assembler - by Craig Bruce - 15-Oct-1994
-
- ; This is the ACE-assembler version of the program
-
- ;todo: -implement storage classes: $00=internal, $01=rel.label, $80=exported
- ; -implement all var types: 0=value, 1=address, 2=addr.high, 3=addr.low
- ; -implement source column, make line:col point to start of cur token
- ; -make it so you can use a "\<CR>" to continue a line
- ; -add more operators: * / & | ~ full precedence?
- ; -cache current symbol
-
- ;--> include acehead.s
- ;===ace system interface declarations===
-
- zp = $f8 ;(2)
- zw = $fa ;(2)
- mp = $fc ;(4)
- syswork = $80 ;(16)
-
- aceStatB = $f00
- errno = aceStatB+0 ;(1)
- aceID = aceStatB+2 ;(2)
- aceArgc = aceStatB+4 ;(2)
- aceArgv = aceStatB+6 ;(2)
- aceMemTop = aceStatB+8 ;(2)
- aceShellPath = $c00 ;(256)
- aceShellAlias = $d00 ;(256)
- aceCurDirName = aceStatB+$80 ;(128)
- aceExitData = $e00 ;(256)
- aceDirentBuffer = aceStatB+10 ;(aceDirentLength)
- aceDirentBytes = aceDirentBuffer+0 ;(4)
- aceDirentDate = aceDirentBuffer+4 ;(8) = YY:YY:MM:DD:HH:MM:SS:TW
- aceDirentType = aceDirentBuffer+12 ;(4)
- aceDirentFlags = aceDirentBuffer+16 ;(1) = drwx*e-t
- aceDirentUsage = aceDirentBuffer+17 ;(1) = ulshb---
- aceDirentNameLen = aceDirentBuffer+18 ;(1)
- aceDirentName = aceDirentBuffer+19 ;(17)
- aceDirentLength = 36
-
- aceCallB = $2803
- open = aceCallB+0 ;( (zp)=Name, .A=Mode ) : .A=fd
- close = aceCallB+3 ;( .A=fd )
- read = aceCallB+6 ;( .X=fd, (zp)=Buf, .AY=Len ) : .AY=(zw)=Len, .Z
- write = aceCallB+9 ;( .X=fd, (zp)=Buf, .AY=Len )
- fastopen = aceCallB+12 ;( (zp)=Name, .A=Mode ) : .A=fd
- fastclose = aceCallB+15 ;( .A=fd )
- fastread = aceCallB+18 ;( .X=fd, (zp)=Buf, .AY=Len ) : .AY=(zw)=Len, .Z
- bload = aceCallB+21 ;( (zp)=Name, .AY=LoadAddr, (zw)=Limit+1 ) : .AY=End+1
- remove = aceCallB+24 ;( (zp)=Name )
- rename = aceCallB+27 ;( (zp)=OldName, (zw)=NewName )
- devinfo = aceCallB+30 ;( .X=fd ) : .A=DevType, .X=Cols, .Y=Rows
- fdswap = aceCallB+33 ;( .X=fd1, .Y=fd2 )
-
- diropen = aceCallB+36 ;( (zp)=DirName ) : .A=fd
- dirclose = aceCallB+39 ;( .A=fd )
- dirread = aceCallB+42 ;( .X=fd ) : direntBuffer, .Z=eof
- isdir = aceCallB+45 ;( (zp)=Name ) : .A=Dev, .X=isDisk, .Y=isDir
- chdir = aceCallB+48 ;( (zp)=DirName )
- cdhome = aceCallB+51 ;( )
- mkdir = aceCallB+54 ;( (zp)=NewDirName )
- rmdir = aceCallB+57 ;( (zp)=DirName )
-
- zpload = aceCallB+60 ;( [mp]=Source, .X=ZpDest, .Y=Length )
- zpstore = aceCallB+63 ;( .X=ZpSource, [mp]=Dest, .Y=Length )
- fetch = aceCallB+66 ;( [mp]=FarSource, (zp)=Ram0Dest, .AY=Length )
- stash = aceCallB+69 ;( (zp)=Ram0Source, [mp]=FarDest, .AY=length )
- pagealloc = aceCallB+72 ;( .A=PageCount, .X=StartTyp, .Y=EndTyp ) : [mp]=FarPtr
- pagefree = aceCallB+75 ;( [mp]=FarPointer, .A=PageCount )
-
- winmax = aceCallB+78 ;( )
- wincls = aceCallB+81 ;( .A=char/color/attrFlags, .X=char, .Y=color )
- winset = aceCallB+84 ;( .A=rows, .X=cols, sw+0=scrRow, sw+1=scrCol )
- winsize = aceCallB+87 ;( ) : <above>+ ,(sw+2)=addr,(sw+4)=rowinc
- winput = aceCallB+90 ;( (sw+0)=addr,(sw+2)=charPtr,.A=attr,.Y=color,.X=len
- ; sw+4=fillChar, sw+5=fieldLen )
- wincolor = aceCallB+93 ;( .X=screen, .Y=border, .A=which ) : .X=scr, .Y=bor
- winpos = aceCallB+96 ;( .A=row, .X=col ) : (sw+0)=addr
- wincursor = aceCallB+99 ;( (sw+0)=addr, .Y=color, .A=$ff:on/$00:off)
- winscroll = aceCallB+102 ;( .A=attr+$08:up+$04:down,.X=rows,sw+4=char,.Y=color)
-
- conread = aceCallB+105 ;( (zp)=Buf, .AY=Len ) : .AY=(zw)=Len, .Z
- conwrite = aceCallB+108 ;( (zp)=Buf, .AY=Len )
- conputchar = aceCallB+111 ;( .A=char )
- conputlit = aceCallB+114 ;( .A=char )
- stopkey = aceCallB+117 ;( ) : .CC=notPressed
- getkey = aceCallB+120 ;( ) : .A=key
- concolor = aceCallB+123 ;( .A=which, .X=char, .Y=cursor ) : .X=char,.Y=cursr
- conpalette = aceCallB+126 ;( ) : sw+0...sw+7=palette [8 colors]
- conscreen = aceCallB+129 ;( .A=MinRows, .X=MinCols )
- conpos = aceCallB+132 ;( .A=row, .X=col )
-
- exec = aceCallB+135 ;( (zp)=execName, (zw)=argv, .AY=argCnt, [mp]=saveArea)
- ; : .A=exitCode, .X=exitDataLen, [mp]=saveArea
- execsub = aceCallB+138 ;( (zp)=execAddr, (zw)=argv, .AY=argCnt, [mp]=saveArea)
- ; : .A=exitCode, .X=exitDataLen, [mp]=saveArea
- exit = aceCallB+141 ;( .A=exitCode, .X=exitBufDataLen, exitData )
- memstat = aceCallB+144 ;( ) : .A=procID, [sw+0]=total, [sw+4]=free
-
- utoa = aceCallB+147 ;( $0+X=value32, (sw+0)=buf, .A=minLen ) :buf, .Y=len
- getdate = aceCallB+150 ;( (.AY)=dateString ) : dateString
- setdate = aceCallB+153 ;( (.AY)=dateString )
- cmdopen = aceCallB+156 ;( (zp)=DevName ) : .A=fd
- cmdclose = aceCallB+159 ;( .A=fd )
- cmdsend = aceCallB+162 ;( .X=fd, (.AY)=CmdString )
- cmdstatus = aceCallB+165 ;( .X=fd, (.AY)=StatBufPtr ) : StatBuf, .A=statusCode
- grscreen = aceCallB+168 ;(...)...
- grexit = aceCallB+171 ;(...)...
- grfill = aceCallB+174 ;(...)...
- grload = aceCallB+177 ;(...)...
- conkeyavail = aceCallB+180 ;( ) : .CC=keyIsAvailable
-
- aceAppAddress = $7000
- aceID1 = $cb
- aceID2 = $06
- aceID3 = 11
-
- aceMemNull = $00
- aceMemREU = $01
- aceMemInternal = $02
- aceMemRLREU = $06
- aceMemRL = $07
-
- aceErrStopped = 0
- aceErrTooManyFiles = 1
- aceErrFileOpen = 2
- aceErrFileNotOpen = 3
- aceErrFileNotFound = 4
- aceErrDeviceNotPresent = 5
- aceErrFileNotInput = 6
- aceErrFileNotOutput = 7
- aceErrMissingFilename = 8
- aceErrIllegalDevice = 9
- aceErrWriteProtect = 26
- aceErrFileExists = 63
- aceErrFileTypeMismatch = 64
- aceErrNoChannel = 70
- aceErrDiskFull = 72
- aceErrInsufficientMemory = 128
- aceErrOpenDirectory = 129
- aceErrDiskOnlyOperation = 131
- aceErrNullPointer = 132
- aceErrInvalidFreeParms = 133
- aceErrFreeNotOwned = 134
- aceErrInvalidWindowParms = 135
- aceErrInvalidConParms = 136
- aceErrInvalidFileMode = 137
- aceErrNotImplemented = 138
- aceErrBloadTruncated = 139
- aceErrPermissionDenied = 140
- aceErrNoGraphicsSpace = 141
-
- stdin = 0
- stdout = 1
- stderr = 2
- ;===end of ace interface declarations===
-
- org aceAppAddress
-
- jmp main
- db aceID1,aceID2,aceID3
- db 64,0 ;** stack,reserved
-
- ;======== global declarations ========
-
- sourceFcb = 2 ;(1) ;file control block of current input file
- bufptr = 3 ;(1) ;byte offset inside of source buffer
- sourceLine = 4 ;(4) ;source file current line
- number = 8 ;(4) ;token: 32-bit number value
- stringLen = 12 ;(1) ;length of string in string buffer
- prevChar = 13 ;(1) ;previous character scanned, next read (1-too-far)
- tokenType = 14 ;(1) ;token: type
- tokenNextChar = 15 ;(1) ;token: next char after token
- tokenNumBytes = 16 ;(1) ;token: number length (1-4 bytes)
- tokenChar = 17 ;(1) ;token: character
- name = 18 ;(2) ;pointer to source filename
- sourceCol = 20 ;(1) ;source file column within line
- nextPlusLab = 22 ;(4) ;number for next "+" label
- prevMinusLab = 26 ;(4) ;number for previous "-" label
- address = 30 ;(4) ;current memory address for code assembly
- hashVal = 34 ;(2) ;16-bit hash value result
- hashPtr = 36 ;(2) ;pointer to selected entry in identifier hash table
- idPtr = 38 ;(4) ;pointer to current identifier descriptor
- idVal = 42 ;(4) ;value of current identifier
- varPtr = 46 ;(4) ;pointer to current identifier to be defined
- filePtr = 50 ;(4) ;pointer to current file info descriptor
- idType = 54 ;(1) ;type of current identifier (value,address,unres)
- originSet = 55 ;(1) ;flag indicating whether origin has been set
- expPlusCount = 56 ;(1) ;number of plus monadic operators of an operand
- expMinusCount = 57 ;(1) ;number of minus monadic operators of an operand
- expLessCount = 58 ;(1) ;number of low-byte monadic operators of an operand
- expGreaterCount = 59 ;(1) ;number of high-byte monadic operators of an operand
- expOffset = 60 ;(1) ;offset of cur operand in an expression descriptor
- expPtr = 62 ;(4) ;pointer to expression descriptor in far memory
- addressOrigin = 66 ;(4) ;origin as set by org directive
- holeCount = 70 ;(4) ;number of holes (unresolved references)
- relHoleCount = 74 ;(4) ;number of holes for relative (internal) references
- instrNum = 78 ;(1) ;assem instr: instruction number (1-56)
- instrAddrMode = 79 ;(1) ;assem instr: addressing mode for instr (1-12)
- instrValue = 80 ;(2) ;assem instr: operand value for instr (8/16 bit)
- instrValueType = 82 ;(1) ;assem instr: operand value type
- instrOpcode = 83 ;(1) ;assem instr: opcode of instr/addrmode
- instrLen = 84 ;(1) ;assem instr: length of instruction
- memBufPage = 85 ;(1) ;mem put: page of buffer
- memBufPtr = 86 ;(4) ;mem put: pointer to 1K memory-buffer block
- memPutVals = 90 ;(4) ;mem put: values to put into memory
- memPutCount = 94 ;(1) ;mem put: number of values to put into memory
- memPutPage = 95 ;(1) ;mem put: current page for values
- newLine = 96 ;(4) ;current input line
- newCol = 100 ;(1) ;current input column
- arg = 102 ;(2) ;current command line argument
- reserved = 104
- memWork = 112 ;(16) ;work area for the memory routines/low-level work
- strDelimit = 112 ;(1) ;string tokenize: delimiter--overlap
- numBase = 113 ;(1) ;number tokenize: base--overlap
- numSave = 114 ;(4) ;number tokenize: save--overlap
- work = 112 ;(16) ;miscellaneous work--low-level--overlap
-
- hashTablePages = 16
- hashTableEntriesHigh = 4
- hashTableMask = $03
- symNew = $81
- symUnresolved = $80
- symFound = 0
-
- tokenIdentifier = 0
- tokenNumber = 1
- tokenString = 2
- tokenSpecial = 3
- tokenEOF = 4
-
- chrCR = $0d
- chrQuote = $22
- chrTab = $09
- chrEOF = $00
-
- errOk = 0 ;ok
- errIdentTooLong = 1 ;an identifier token exceeds 240 chars in length
- errStringTooLong = 2 ;a string literal exceeds 255 chars in length
- errNoCloseQuote = 3 ;ran into a CR before end of string literal
- errBadNumber = 4 ;invalid numeric literal
- errNumOverflow = 5 ;numeric literal value overflows 32-bits
- errSyntax = 6 ;syntax error
- errInvalStrOpers = 7 ;attempt to perform numeric operators on a string
- errTooManyOperands = 8 ;expression has more than 17 operands
- errInsufficientMemory = 9 ;ran out of memory during compilation process
- errRedefinedSymbol = 10 ;attempt to redefine a symbol
- errOriginNotSet = 11 ;attempt to assemble code with code origin not set
- errInternAssign = 12 ;internal error: attempt to assign to unexpected id
- errNonNumIdExpr = 13 ;non-numeric symbol in a numeric expression
- errExpectOperator = 14 ;expecting an operator
- errExpectOperand = 15 ;expecting an operand
- errExpectCommand = 16 ;expecting a command
- errValueTooLarge = 17 ;value is too large for operation (or is negative)
- errBranchTooFar = 18 ;branch out of range
- errNotImplemented = 19 ;feature is not (yet) implemented
- errWrongAdmode = 20 ;instruction does not support given address mode
- errAddressWrap = 21 ;address wraped around 64K code address space
- errObjectFile = 22 ;error trying to write output object file
- errNotResolvedExpr = 23 ;directive requires resolved expression
- errOriginAlreadySet = 24 ;code origin already set; you can't set it twice
- errUnresdReferences = 25 ;unresolved reference
- errDotCommand = 26 ;this assembler doesn't accept dot commands
-
- debug : buf 1 ;display debug information: $ff=yes, $00=no
- symDump : buf 1 ;display symbol table dump: $ff=yes, $00=no
- outputType : buf 1 ;type of output module: $00=binary, $01=reloc, $80=link
-
- ;======== main routine ========
-
- main = *
- ;** check for large enough TPA
- sec
- lda #<bssEnd
- cmp aceMemTop+0
- lda #>bssEnd
- sbc aceMemTop+1
- bcs +
- jmp mainCont
- + lda #<tpaMsg
- ldy #>tpaMsg
- jsr eputs
- die = *
- lda #1
- ldx #0
- jmp exit
-
- tpaMsg = *
- db "as: Insufficient program space to run in"
- db chrCR,0
-
- usage = *
- lda #<usageMsg
- ldy #>usageMsg
- jsr eputs
- jmp die
-
- usageMsg = *
- db "usage: as [-help] [-s] [-d] [file ...]"
- db chrCR,chrCR
- db " -help : produce this information, don't run"
- db chrCR
- db " -s : produce symbol table dump at end"
- db chrCR
- db " -d : provide debugging information (lots)"
- db chrCR,0
-
- defaultInput = *
- db "-stdin-"
- db 0
-
- filenameUsed : buf 1
-
- mainCont = *
- ;** init globals
- lda #$00
- sta debug ;default off
- sta symDump ;default none
- sta outputType ;default binary
- lda #$00
- sta filenameUsed
- lda #0
- sta arg+0
- sta arg+1
- jsr asInit
- ldx #7
- - lda writeDefaultName,x
- sta writeName,x
- dex
- bpl -
-
- mainNext = *
- jsr checkStop
- inc arg+0
- bne +
- inc arg+1
- + lda arg+0
- ldy arg+1
- jsr getarg
- lda zp+0
- ora zp+1
- beq mainExit
- lda zp+0
- ldy zp+1
- sta name+0
- sty name+1
- ldy #0
- lda (zp),y
- cmp #"-"
- bne +
- jsr handleFlags
- jmp mainNext
- + jsr echo
- jsr mainFile
- jmp mainNext
-
- mainExit = *
- bit filenameUsed
- bmi +
- lda #<defaultInput
- ldy #>defaultInput
- sta name+0
- sty name+1
- jsr echo
- jsr mainStdin
- + lda #$00
- ldx #3
- - ora holeCount
- dex
- bpl -
- cmp #$00
- beq +
- jsr findUnresSymbol
- lda #errUnresdReferences
- jmp errorRef
- + jsr writeObjectFile
- jsr dumpSymbolTable
- rts
-
- handleFlags = *
- iny
- lda (zp),y
- bne +
- rts
- + cmp #"s"
- beq flagS
- cmp #"d"
- beq flagD
- jmp usage
-
- flagS = *
- lda #$ff
- sta symDump
- jmp handleFlags
-
- flagD = *
- lda #$ff
- sta debug
- jmp handleFlags
-
- echo = *
- lda #<echoMsg1
- ldy #>echoMsg1
- jsr eputs
- jsr echoName
- lda #<echoMsg2
- ldy #>echoMsg2
- jmp eputs
- echoName = *
- lda name+0
- ldy name+1
- jmp eputs
-
- echoMsg1 = *
- db "assembling source file "
- db chrQuote,0
- echoMsg2 = *
- db chrQuote,chrCR,0
-
- mainFile = *
- bit filenameUsed
- bmi +
- jsr mainExtractObj
- + lda name+0
- ldy name+1
- sta zp+0
- sty zp+1
- lda #"r"
- jsr open
- bcc +
- jsr echoName
- lda #<mainFileErr
- ldy #>mainFileErr
- jsr eputs
- jmp die
- + sta sourceFcb
- jsr asDriver
- lda sourceFcb
- jsr close
- lda #$ff
- sta filenameUsed
- rts
- mainFileErr = *
- db ": Cannot open file"
- db chrCR,0
-
- mainStdin = *
- lda #stdin
- sta sourceFcb
- jsr asDriver
- rts
-
- mainExtractObj = *
- ldx #0 ;copy-start
- ldy #0
- - lda (name),y
- beq +++
- cmp #":"
- beq +
- cmp #"/"
- bne ++
- + tya
- tax
- inx
- + iny
- bne -
- + txa
- tay
- ldx #0
- - lda (name),y
- sta stringBuf,x
- beq +
- iny
- inx
- bne -
- + nop
- - cpx #3
- bcs +
- rts
- + lda stringBuf-2,x
- cmp #","
- bne +
- lda #0
- dex
- dex
- sta stringBuf,x
- jmp -
- + cmp #"."
- beq +
- rts
- + lda stringBuf-1,x
- cmp #"s"
- beq +
- rts
- + cpx #18
- bcc +
- ldx #18
- + lda #","
- sta stringBuf-2,x
- lda #"p"
- sta stringBuf-1,x
- lda #0
- sta stringBuf,x
- - lda stringBuf,x
- sta writeName,x
- dex
- bpl -
- rts
-
- asInit = * ;initialize variables for assembly
- ldx #3
- lda #0
- - sta newLine,x
- sta nextPlusLab,x
- sta prevMinusLab,x
- sta address,x
- sta holeCount,x
- sta relHoleCount,x
- dex
- bpl -
- sta newCol
- lda #1
- sta newLine+0
- sta nextPlusLab+0
- lda #$00
- sta originSet
- lda #<$1300
- ldy #>$1300
- sta address+0
- sty address+1
- sta addressOrigin+0
- sty addressOrigin+1
- jsr mallocInit
- jsr initSymbolTable
- jsr memInit
- rts
-
- ;======== driver ========
-
- asDriver = *
- lda #$ff
- sta bufptr
- lda #" "
- sta prevChar
- - jsr parse
- bcc -
- rts
-
- writeObTry : buf 1
- writeObFd : buf 1
-
- writeObjectFile = *
- lda #<writeMsg
- ldy #>writeMsg
- jsr eputs
- lda #<writeName
- ldy #>writeName
- jsr eputs
- lda #chrQuote
- ldx #stderr
- jsr putc
- ldx #stderr
- lda #chrCR
- jsr putc
- lda #2
- sta writeObTry
- lda #<writeName
- ldy #>writeName
- sta zp+0
- sty zp+1
-
- ;** open object for writing
- - lda #"w"
- jsr open
- bcc ++
- lda errno
- cmp #aceErrFileExists
- beq +
- - lda #errObjectFile
- jmp error
- + dec writeObTry
- beq -
- jsr remove
- bcs -
- jmp --
- + sta writeObFd
-
- ;** write object data
- lda addressOrigin+0
- ldx writeObFd
- jsr putc
- lda addressOrigin+1
- ldx writeObFd
- jsr putc
- lda writeObFd
- ldx addressOrigin+0
- ldy addressOrigin+1
- jsr memSave
-
- ;** close object
- lda writeObFd
- jsr close
- bcc +
- lda #errObjectFile
- jmp error
- + lda #<writeRangeMsg1
- ldy #>writeRangeMsg1
- jsr eputs
- lda addressOrigin+1
- ldx #stderr
- jsr fputhex
- lda addressOrigin+0
- ldx #stderr
- jsr fputhex
- lda #<writeRangeMsg2
- ldy #>writeRangeMsg2
- jsr eputs
- sec
- lda address+0
- sbc #1
- pha
- lda address+1
- sbc #0
- ldx #stderr
- jsr fputhex
- pla
- ldx #stderr
- jsr fputhex
- lda #<writeRangeMsg3
- ldy #>writeRangeMsg3
- jsr eputs
- sec
- lda address+0
- sbc addressOrigin+0
- sta work+0
- lda address+1
- sbc addressOrigin+1
- sta work+1
- lda #0
- sta work+2
- sta work+3
- ldx #work
- jsr eputnum
- lda #<writeRangeMsg4
- ldy #>writeRangeMsg4
- jsr eputs
- rts
-
- writeDefaultName = *
- db "a.out,p"
- db 0
- writeMsg = *
- db "writing object file "
- db chrQuote,0
- writeRangeMsg1 = *
- db "code range: $"
- db 0
- writeRangeMsg2 = *
- db "--$"
- db 0
- writeRangeMsg3 = *
- db " ("
- db 0
- writeRangeMsg4 = *
- db " bytes)"
- db chrCR,0
-
- ;======== parser ========
-
- parse = *
- ;** at beginning of command
- jsr checkStop
- jsr getToken
- lda tokenType
- cmp #tokenEOF
- bne +
- sec
- rts
- + cmp #tokenIdentifier
- bne parseNotId
- lda tokenNextChar
- cmp #"="
- bne +
- jmp parseEquate
- + cmp #":"
- bne +
- jmp parseAddress
- + jmp parseIdentifier
-
- parseNotId = *
- cmp #tokenSpecial
- beq +
- syntaxError = *
- lda #errSyntax
- jmp error
- + lda tokenChar
- cmp #chrCR
- bne +
- jmp parseEnd
- + cmp #"+"
- bne +
- jmp parsePlus
- + cmp #"-"
- bne +
- jmp parseMinus
- + cmp #"#"
- bne +
- jmp parseEnd
- + cmp #"."
- bne +
- jmp parseDotCommand
- + jmp syntaxError
-
- ;ret: .X=tokenIdentifier, .A=nextChar, .Y=strlen, stringLen, stringBuf
- ; .X=tokenNumber, .Y=numlen, number
- ; .X=tokenString, .A=firstChar,.Y=strlen, stringLen, stringBuf
- ; .X=tokenSpecial, .A=char
-
- parseEquate = *
- jsr parseDefineVar
- jsr getToken
- cpx #tokenSpecial
- beq +
- - jmp syntaxError
- + cmp #"="
- bne -
- lda #0
- jsr parseExpression
- cmp #chrCR
- bne -
- jsr evaluateExpression
- bcs +
- jsr assignVariable
- jmp ++
- + jsr addVariableHole
- + bit debug
- bpl +
- lda #<parseEquateMsg
- ldy #>parseEquateMsg
- jsr puts
- + jmp parseEnd
- parseEquateMsg = *
- db "parseEquate: assign parsed expression to variable."
- db chrCR,0
-
- parseAddress = *
- jsr parseDefineVar
- jsr getToken
- cpx #tokenSpecial
- beq +
- - jmp syntaxError
- + cmp #":"
- beq +
- jmp syntaxError
- + jsr parseAssignAddress
- bit debug
- bpl +
- lda #<parseAddressMsg
- ldy #>parseAddressMsg
- jsr puts
- + jmp parseEnd
- parseAddressMsg = *
- db "parseAddress: assign current address to variable."
- db chrCR,0
-
- parseAssignAddress = *
- bit originSet
- bmi +
- lda #errOriginNotSet
- jmp error
- + ldx #3
- - lda address,x
- sta idVal,x
- dex
- bpl -
- lda #$01
- sta idType
- jmp assignVariable
-
- parsePlus = *
- lda #"+"
- ldy #0
- jsr genRelLabel
- jsr parseDefineVar
- jsr parseAssignAddress
- bit debug
- bpl +
- lda #<parsePlusMsg
- ldy #>parsePlusMsg
- jsr puts
- ldx #nextPlusLab
- jsr putnum
- lda #chrCR
- jsr putchar
- + inc nextPlusLab+0
- bne +
- inc nextPlusLab+1
- bne +
- inc nextPlusLab+2
- bne +
- inc nextPlusLab+3
- + jmp parseEnd
- parsePlusMsg = *
- db "parsePlus: assign current address to a syntheic '+' variable:"
- db 0
-
- parseMinus = *
- inc prevMinusLab+0
- bne +
- inc prevMinusLab+1
- bne +
- inc prevMinusLab+2
- bne +
- inc prevMinusLab+3
- + lda #"-"
- ldy #0
- jsr genRelLabel
- jsr parseDefineVar
- jsr parseAssignAddress
- bit debug
- bpl +
- lda #<parseMinusMsg
- ldy #>parseMinusMsg
- jsr puts
- ldx #prevMinusLab
- jsr putnum
- lda #chrCR
- jsr putchar
- + jmp parseEnd
- parseMinusMsg = *
- db "parseMinus: assign current address to a synthetic '-' variable:"
- db 0
-
- genRelLabel = * ;( .A=type, .Y=relative )
- sta stringBuf+1
- cmp #"+"
- bne +
- clc
- tya
- adc nextPlusLab
- sta number+0
- ldy #3
- ldx #1
- - lda nextPlusLab,x
- adc #0
- sta number,x
- inx
- dey
- bne -
- jmp ++
- + sec
- sty number+0
- lda prevMinusLab+0
- sbc number+0
- sta number+0
- ldy #3
- ldx #1
- - lda prevMinusLab,x
- sbc #0
- sta number,x
- inx
- dey
- bne -
- + lda #"L"
- sta stringBuf+0
- lda #<stringBuf+2
- ldy #>stringBuf+2
- sta zp+0
- sty zp+1
- ldx #number
- lda #1
- jsr utoa
- iny
- iny
- lda #"c"
- sta stringBuf,y
- iny
- lda #0
- sta stringBuf,y
- sty stringLen
- rts
-
- parseEnd = *
- bit debug
- bpl +
- lda #<parseEndMsg
- ldy #>parseEndMsg
- jsr puts
- + clc
- rts
- parseEndMsg = *
- db "-----=-----"
- db chrCR,chrCR,0
-
- parseIdentifier = * ;line starting with an identifier
- jsr hash
- ;** check if identifier is a processor instruction
- lda stringLen
- cmp #3
- bne parseIdNotInstr
- lda hashVal+0
- and #63
- tax
- lda instrHashPtrs,x
- cmp #100
- bcs +
- jsr parseIdCheckInstr
- bcs parseIdNotInstr
- jmp instr
- + sec
- sbc #100
- tax
- - lda instrHashIndirects,x
- beq parseIdNotInstr
- jsr parseIdCheckInstr
- bcs +
- jmp instr
- + inx
- bne -
-
- ;** check if identifier is a directive
- parseIdNotInstr = *
- jsr checkIfDirective
- bcs parseIdNotDirective
- jmp directive
-
- ;** check if identifier is a macro
- parseIdNotDirective = *
- lda #errExpectCommand
- jmp error
-
- parseDotCommand = *
- lda #errDotCommand
- jmp error
-
- ;======== handle assembler directives ========
-
- direcNum : buf 1
-
- checkIfDirective = * ;( stringBuf, stringLen ) : .CS=no, .A=dirNum
- lda #0
- sta direcNum
-
- direcCheckNext = *
- ldx direcNum
- ldy direcOffsets,x
- ldx #0
- - lda stringBuf,x
- cmp direcNames,y
- bne direcCheckCont
- cmp #$00
- bne +
- lda direcNum
- clc
- rts
- + iny
- inx
- bne -
-
- direcCheckCont = *
- inc direcNum
- lda direcNum
- cmp #16
- bcc direcCheckNext
- lda #0
- sec
- rts
-
- direcOffsets = *
- db 00,03,07,10,13,16,20,28,31,37,42,48,54,63,70
-
- direcNames = *
- db "db" ;dn=01. off=00
- db 0
- db "buf" ;dn=02. off=03
- db 0
- db "dw" ;dn=03. off=07
- db 0
- db "dt" ;dn=04. off=10
- db 0
- db "dl" ;dn=05. off=13
- db 0
- db "org" ;dn=06. off=16
- db 0
- db "include" ;dn=07. off=20
- db 0
- db "if" ;dn=08. off=28
- db 0
- db "elsif" ;dn=09. off=31
- db 0
- db "else" ;dn=10. off=37
- db 0
- db "endif" ;dn=11. off=42
- db 0
- db "macro" ;dn=12. off=48
- db 0
- db "endmacro" ;dn=13. off=54
- db 0
- db "export" ;dn=14. off=63
- db 0
- db "bss" ;dn=15. off=70
- db 0
-
- direcVectors = *
- dw direcDb,direcBuf,direcDw,direcDt,direcDl,direcOrg,direcInclude
- dw direcIf,direcElsif,direcElse,direcEndif,direcMacro,direcEndmacro
- dw direcExport,direcBss
-
- directive = * ;( .A=dirNum )
- bit debug
- bpl +
- pha
- lda #<direcMsg
- ldy #>direcMsg
- jsr puts
- pla
- + asl
- tay
- lda direcVectors+0,y
- sta work+14
- lda direcVectors+1,y
- sta work+15
- jsr +
- jmp parseEnd
- + jmp (work+14)
- direcMsg = *
- db "must parse a directive"
- db chrCR,0
-
- direcOrg = *
- bit originSet
- bpl +
- lda #errOriginAlreadySet
- jmp error
- + lda #0
- jsr parseExpression
- cmp #chrCR
- beq +
- jmp syntaxError
- + jsr evaluateExpression
- bcc +
- lda #errNotResolvedExpr
- jmp error
- + lda idVal+2
- ora idVal+3
- beq +
- lda #errValueTooLarge
- jmp error
- + lda idVal+0
- ldy idVal+1
- sta address+0
- sty address+1
- sta addressOrigin+0
- sty addressOrigin+1
- lda #$ff
- sta originSet
- bit debug
- bpl +
- lda #<direcOrgMsg
- ldy #>direcOrgMsg
- jsr puts
- lda idVal+1
- jsr puthex
- lda idVal+0
- jsr puthex
- lda #chrCR
- jsr putchar
- + rts
- direcOrgMsg = *
- db "setting code origin to $"
- db 0
-
- direcDfSize : buf 1
- direcDfChar : buf 1
-
- direcDb = *
- lda #1
- bne direcDlIn
- direcDw = *
- lda #2
- bne direcDlIn
- direcDt = *
- lda #3
- bne direcDlIn
- direcDl = *
- lda #4
- direcDlIn = *
- sta direcDfSize
- bit originSet
- bmi direcDfNext
- lda #errOriginNotSet
- jmp error
-
- direcDfNext = *
- lda #1
- jsr parseExpression
- sta direcDfChar
- cpx #0
- beq +
- jsr direcDfString
- jmp direcDfCont
- + jsr evaluateExpression
- bcs ++
- ldx direcDfSize
- - cpx #4
- bcs ++
- lda idVal,x
- bne +
- inx
- bne -
- + lda #errValueTooLarge
- jmp error
- + lda #1
- ldy #0
- sta direcDfCount+0
- sty direcDfCount+1
- jsr direcDfPut
-
- direcDfCont = *
- lda direcDfChar
- cmp #","
- beq direcDfNext
- cmp #chrCR
- beq +
- jmp syntaxError
- + rts
-
- direcDfStrPos : buf 1
-
- direcDfString = *
- lda #0
- sta direcDfStrPos
- sta idType
- sta idVal+1
- sta idVal+2
- sta idVal+3
- - ldx direcDfStrPos
- cpx stringLen
- bcc +
- rts
- + lda stringBuf,x
- sta idVal+0
- lda #1
- ldy #0
- sta direcDfCount+0
- sty direcDfCount+1
- jsr direcDfPut
- inc direcDfStrPos
- jmp -
-
- direcDfCount : buf 2
-
- direcDfPut = * ;(address++, idVal, idType, direcDfSize, direcDfCount--, expBuf)
- lda direcDfCount+0
- ora direcDfCount+1
- bne +
- rts
-
- ;** debug information
- + bit debug
- bpl +++
- lda #<direcDfPutMsg1
- ldy #>direcDfPutMsg1
- jsr puts
- lda address+1
- jsr puthex
- lda address+0
- jsr puthex
- lda #<direcDfPutMsg2
- ldy #>direcDfPutMsg2
- jsr puts
- bit idType
- bpl +
- lda #"?"
- jsr putchar
- jmp ++
- + ldx #idVal
- jsr putnum
- + lda #chrCR
- jsr putchar
-
- ;** handle unresolved reference
- + bit idType
- bpl +
- ldx direcDfSize
- lda #0
- jsr addMemoryHole
-
- ;** handle resolved reference
- + ldx #3
- - lda idVal,x
- sta memPutVals,x
- dex
- bpl -
- lda direcDfSize
- ldx address+0
- ldy address+1
- jsr memPut
- ;** add relocatable reference
- lda idType
- beq +
- cmp #$04
- bcs +
- ldx address+0
- ldy address+1
- jsr recordRelocRef
-
- ;** go onto next put
- + clc
- lda address+0
- adc direcDfSize
- sta address+0
- bcc +
- inc address+1
- bne +
- lda #errAddressWrap
- jmp error
- + lda direcDfCount+0
- bne +
- dec direcDfCount+1
- + dec direcDfCount+0
- jmp direcDfPut
-
- direcDfPutMsg1 = *
- db "define-put: address=$"
- db 0
- direcDfPutMsg2 = *
- db ", value="
- db 0
-
- direcBuf = *
- bit originSet
- bmi +
- lda #errOriginNotSet
- jmp error
- + lda #0
- jsr parseExpression
- cmp #chrCR
- beq +
- jmp syntaxError
- + jsr evaluateExpression
- bcc +
- lda #errNotResolvedExpr
- jmp error
- + lda idVal+2
- ora idVal+3
- beq +
- lda #errValueTooLarge
- jmp error
- + lda idVal+0
- ldy idVal+1
- sta direcDfCount+0
- sty direcDfCount+1
- + lda #0
- sta idType
- sta idVal+0
- sta idVal+1
- sta idVal+2
- sta idVal+3
- lda #1
- sta direcDfSize
- jsr direcDfPut
- rts
-
- direcInclude = *
- direcIf = *
- direcElsif = *
- direcElse = *
- direcEndif = *
- direcMacro = *
- direcEndmacro = *
- direcExport = *
- lda #errNotImplemented
- jmp error
- direcBss = *
- bit originSet
- bpl +
- lda #errOriginNotSet
- jmp error
- + nop
- lda #errNotImplemented
- jmp error
-
- ;======== error handler ========
-
- errorCode : buf 1
- errorPos : buf 1
- errorExitCode = aceExitData+0 ;$fc8a09cb:editor-repos
- errorExitLine = aceExitData+4
- errorExitCol = aceExitData+8
- errorExitRepos = aceExitData+12
- errorExitFilep = aceExitData+13
- errorExitReser = aceExitData+14
- errorBuf = aceExitData+15
-
- errorRef = *
- jsr errorPreramble
- lda #<errorMsg2
- ldy #>errorMsg2
- jsr errorCat
- ldx #3
- - lda expSrcLine,x
- sta work+0,x
- lda expSrcFile,x
- sta work+4,x
- dex
- bpl -
- lda expSrcCol
- ldx #work+0
- ldy #work+4
- jsr errorDispFile
- jmp errorIn
-
- errorPreramble = *
- sta errorCode
- ldx #14
- - lda errorExitHead,x
- sta errorExitCode,x
- dex
- bpl -
- lda #0
- sta errorPos
- lda #<errorMsg1
- ldy #>errorMsg1
- jsr errorCat
- ldx #sourceLine
- ldy #filePtr
- lda sourceCol
- jmp errorDispFile
-
- error = *
- jsr errorPreramble
- errorIn = *
- ldx errorPos
- lda #" "
- sta errorBuf,x
- inc errorPos
- lda errorCode
- asl
- tax
- lda errDesc+1,x
- tay
- lda errDesc+0,x
- jsr errorCat
- lda errorCode
- cmp #errUnresdReferences
- bne +
- lda #<symName
- ldy #>symName
- jsr errorCat
- + lda #<errorBuf
- ldy #>errorBuf
- jsr eputs
- lda #chrCR
- ldx #stderr
- jsr putc
- lda #1
- ldx #0
- jmp exit
-
- errDispFiFp : buf 1
- errDispFiCol : buf 1
- errDispFiLin : buf 1
-
- errorDispFile = * ;( .X=zpLineOff, .A=col, .Y=zpFilePtr, errorPos ) : errorPos
- ;** uses name instead of filePtr for now
- ;** produces output of the form: ("filename":1234:12)
- sta errDispFiCol
- stx errDispFiLin
- sty errDispFiFp
- ldx errorPos
- lda #"("
- sta errorBuf,x
- inx
- lda #chrQuote
- sta errorBuf,x
- inx
- stx errorPos
- lda name+0
- ldy name+1
- jsr errorCat
- lda #chrQuote
- sta errorBuf,x
- inx
- lda #":"
- sta errorBuf,x
- inx
- stx errorPos
- ldx errDispFiLin
- jsr errorDispFileApnum
- lda #":"
- sta errorBuf,x
- inx
- stx errorPos
- lda errDispFiCol
- sta number+0
- lda #0
- sta number+1
- sta number+2
- sta number+3
- ldx #number
- jsr errorDispFileApnum
- lda #")"
- sta errorBuf,x
- inx
- stx errorPos
- rts
-
- errorDispFileApnum = * ;( .X=zpoff, errorPos ) : .X=errorPos
- lda #<putnumNum
- ldy #>putnumNum
- sta zp+0
- sty zp+1
- lda #1
- jsr utoa
- lda #<putnumNum
- ldy #>putnumNum
- ;** fall through
-
- errorCat = * ;( .AY=str, errorPos ) : .X=errorPos
- sta work+14
- sty work+15
- ldx errorPos
- ldy #0
- - lda (work+14),y
- sta errorBuf,x
- beq +
- inx
- iny
- bne -
- + stx errorPos
- rts
-
- errorExitHead = *
- db $fc,$8a,$09,$cb,$00,$00,$00,$00,$00,$00,$00,$00,$ff,$06,$00
- errorMsg1 = *
- db "err "
- db 0
- errorMsg2 = *
- db ", ref"
- db 0
-
- errDesc: dw err00,err01,err02,err03,err04,err05,err06,err07,err08,err09
- dw err10,err11,err12,err13,err14,err15,err16,err17,err18,err19
- dw err20,err21,err22,err23,err24,err25,err26
-
- err00: db "Ok--no error"
- db 0
- err01: db "An identifier token exceeds 240 chars in length"
- db 0
- err02: db "A string literal exceeds 240 chars in length"
- db 0
- err03: db "Ran into a CR before end of string literal"
- db 0
- err04: db "Invalid numeric literal"
- db 0
- err05: db "Numeric literal value overflows 32-bits"
- db 0
- err06: db "Syntax error"
- db 0
- err07: db "Attempt to perform numeric operators on a string"
- db 0
- err08: db "Expression has more than 17 operands"
- db 0
- err09: db "Ran out of memory during compilation process"
- db 0
- err10: db "Attempt to redefine a symbol"
- db 0
- err11: db "Attempt to assemble code with code origin not set"
- db 0
- err12: db "Internal error: attempt to assign to unexpected id"
- db 0
- err13: db "Non-numeric symbol in a numeric expression"
- db 0
- err14: db "Expecting an operator"
- db 0
- err15: db "Expecting an operand"
- db 0
- err16: db "Expecting a command"
- db 0
- err17: db "Value is too large or negative"
- db 0
- err18: db "Branch out of range"
- db 0
- err19: db "Feature is not (yet) implemented"
- db 0
- err20: db "Instruction does not support given address mode"
- db 0
- err21: db "Address wraped around 64K code address space"
- db 0
- err22: db "Error trying to write output object file"
- db 0
- err23: db "Directive requires resolved expression"
- db 0
- err24: db "Code origin already set; you can't set it twice"
- db 0
- err25: db "Unresolved symbol: "
- db 0
- err26: db "Thus assembler doesn't accept .dot commands, Buddy!"
- db 0
-
- wputnum = *
- lda #stdout
- sta putnumFd
- jmp putnumIn
- eputnum = *
- lda #stderr
- jmp fputnum
- putnum = *
- lda #stdout
- fputnum = *
- sta putnumFd
- ldy #1
- putnumIn = *
- lda #<putnumNum
- sta zp+0
- lda #>putnumNum
- sta zp+1
- tya
- jsr utoa
- ldx putnumFd
- jmp fputsZp
-
- putnumFd : buf 1
- putnumNum : buf 11
-
- puthex = * ;( .A=value )
- ldx #stdout
- fputhex = * ;( .A=value, .X=fd )
- stx putnumFd
- pha
- lsr
- lsr
- lsr
- lsr
- tax
- lda puthexChars,x
- ldx putnumFd
- jsr putc
- pla
- and #$0f
- tax
- lda puthexChars,x
- ldx putnumFd
- jsr putc
- rts
- puthexChars = *
- db "0123456789abcdef"
-
- checkStop = *
- jsr stopkey
- bcs +
- rts
- + lda #<stoppedMsg
- ldy #>stoppedMsg
- jsr eputs
- lda #1
- ldx #0
- jmp exit
-
- stoppedMsg = *
- db "<Stopped>"
- db chrCR,0
-
- ;======== utility functions ========
-
- incLong = * ;( .X=zpOffset )
- inc 0,x
- bne +
- inc 1,x
- bne +
- inc 2,x
- bne +
- inc 3,x
- + rts
-
- decLong = * ;( .X=zpOffset )
- sec
- lda 0,x
- sbc #1
- sta 0,x
- inx
- ldy #3
- - lda 0,x
- sbc #0
- sta 0,x
- inx
- dey
- bne -
- rts
-
- ;======== included files ========
-
- ;--> include ashelp.s
- ;** assembler program utility file - by Craig Bruce - 26-Sep-1994
-
- ;======== assemble processor instruction ========
-
- ; num bkt ins num bkt ins num bkt ins num bkt ins num bkt ins
- ; 00. xx. xxx 12. 63. bvc 24. 22. eor 36. 20. pha 48. 27. sta
- ; 01. 12. adc 13. 15. bvs 25. 05. inc 37. 35. php 49. 50. stx
- ; 02. 63. and 14. 38. clc 26. 26. inx 38. 40. pla 50. 51. sty
- ; 03. 00. asl 15. 39. cld 27. 27. iny 39. 55. plp 51. 12. tax
- ; 04. 00. bcc 16. 44. cli 28. 06. jmp 40. 20. rol 52. 13. tay
- ; 05. 16. bcs 17. 57. clv 29. 38. jsr 41. 26. ror 53. 38. tsx
- ; 06. 24. beq 18. 24. cmp 30. 28. lda 42. 10. rti 54. 08. txa
- ; 07. 47. bit 19. 15. cpx 31. 51. ldx 43. 20. rts 55. 26. txs
- ; 08. 56. bmi 20. 16. cpy 32. 52. ldy 44. 03. sbc 56. 45. tya
- ; 09. 25. bne 21. 60. dec 33. 24. lsr 45. 50. sec
- ; 10. 42. bpl 22. 17. dex 34. 52. nop 46. 51. sed
- ; 11. 51. brk 23. 18. dey 35. 45. ora 47. 56. sei
-
- instrNames = * ;names of instruction, 3 chars each
- db "xxxadcandaslbccbcsbeqbitbmibnebplbrkbvcbvsclccldcliclvcmpcpxcpy"
- db "decdexdeyeorincinxinyjmpjsrldaldxldylsrnoporaphaphpplaplprolror"
- db "rtirtssbcsecsedseistastxstytaxtaytsxtxatxstya"
-
- instrHashPtrs = * ;pointers to instruction numbers or >=100=indirects
- ;bucketx0..x1..x2..x3..x4..x5..x6..x7..x8..x9
- db 100,000,000,044,000,025,028,000,054,000 ;buckets 00-09
- db 042,000,103,052,000,106,109,022,023,000 ;buckets 10-19
- db 112,000,024,000,116,009,120,124,030,000 ;buckets 20-29
- db 000,000,000,000,000,037,000,000,127,015 ;buckets 30-39
- db 038,000,010,000,016,131,000,007,000,000 ;buckets 40-49
- db 134,137,142,000,000,039,145,017,000,000 ;buckets 50-59
- db 021,000,000,148 ;buckets 60-63
-
- instrHashIndirects = *
- db 004,003,000 ;off=100, bucket=00, instrs=bcc,asl
- db 001,051,000 ;off=103, bucket=12, instrs=adc,tax
- db 019,013,000 ;off=106, bucket=15, instrs=cpx,bvs
- db 005,020,000 ;off=109, bucket=16, instrs=bcs,cpy
- db 043,036,040,000 ;off=112, bucket=20, instrs=rts,pha,rol
- db 006,018,033,000 ;off=116, bucket=24, instrs=beq,cmp,lsr
- db 026,041,055,000 ;off=120, bucket=26, instrs=inx,ror,txs
- db 048,027,000 ;off=124, bucket=27, instrs=sta,iny
- db 029,014,053,000 ;off=127, bucket=38, instrs=jsr,clc,tsx
- db 035,056,000 ;off=131, bucket=45, instrs=ora,tya
- db 049,045,000 ;off=134, bucket=50, instrs=stx,sec
- db 031,050,011,046,000;off=137,buck=51, instrs=ldx,sty,brk,sed
- db 032,034,000 ;off=142, bucket=52, instrs=ldy,nop
- db 008,047,000 ;off=145, bucket=56, instrs=bmi,sei
- db 002,012,000 ;off=148, bucket=63, instrs=and,bvc
-
- parseIdCheckInstr = * ;( .A=instrNumToCheck ) : .CS=notInstr, .A+.X:unch
- sta work
- asl
- adc work
- tay
- lda stringBuf+0
- cmp instrNames+0,y
- bne +
- lda stringBuf+1
- cmp instrNames+1,y
- bne +
- lda stringBuf+2
- cmp instrNames+2,y
- bne +
- clc
- lda work
- rts
- + sec
- rts
-
- instr = * ;( .A=instrNum )
- ;** got instruction number
- sta instrNum
- bit originSet
- bmi +
- lda #errOriginNotSet
- jmp error
- + bit debug
- bpl +
- sta number+0
- lda #0
- sta number+1
- sta number+2
- sta number+3
- lda #<instrMsg
- ldy #>instrMsg
- jsr puts
- ldx #number
- jsr putnum
- lda #chrCR
- jsr putchar
-
- ;** get addressing mode and value
- + jsr instrGetAddrMode
- bit debug
- bpl +++
- lda instrAddrMode
- sta number+0
- lda #0
- sta number+1
- sta number+2
- sta number+3
- lda #<instrAddrMsg1
- ldy #>instrAddrMsg1
- jsr puts
- ldx #number
- jsr putnum
- lda #<instrAddrMsg2
- ldy #>instrAddrMsg2
- jsr puts
- lda instrValue+0
- ldy instrValue+1
- sta number+0
- sty number+1
- lda instrValueType
- bmi +
- ldx #number
- jsr putnum
- jmp ++
- + lda #"?"
- jsr putchar
- + lda #chrCR
- jsr putchar
-
- ;** get opcode for instr/addrmode
- + nop
- - lda instrNum
- ldx instrAddrMode
- jsr instrGetOpcode
- bcc +
- ldx instrAddrMode
- lda instrAdmodePromote,x
- sta instrAddrMode
- bne -
- lda #errWrongAdmode
- jmp error
- + bit debug
- bpl ++
- lda #<instrCodeMsg
- ldy #>instrCodeMsg
- jsr puts
- lda address+1
- jsr puthex
- lda address+0
- jsr puthex
- lda #":"
- jsr putchar
- lda #" "
- jsr putchar
- lda instrOpcode
- jsr puthex
- lda instrLen
- cmp #1
- beq +
- lda #" "
- jsr putchar
- lda instrValue+0
- jsr puthex
- lda instrLen
- cmp #2
- beq +
- lda #" "
- jsr putchar
- lda instrValue+1
- jsr puthex
- + lda #chrCR
- jsr putchar
-
- ;** store the instruction into memory
- + lda instrOpcode
- sta memPutVals+0
- lda instrValue+0
- ldy instrValue+1
- sta memPutVals+1
- sty memPutVals+2
- ldx address+0
- ldy address+1
- lda instrLen
- jsr memPut
-
- ;** add relocatable reference
- lda instrValueType
- beq ++
- cmp #$04
- bcs ++
- ldx address+0
- ldy address+1
- inx
- bne +
- iny
- + jsr recordRelocRef
-
- ;** increment address and finish
- + clc
- lda address+0
- adc instrLen
- sta address+0
- bcc +
- inc address+1
- bne +
- lda #errAddressWrap
- jmp error
- + jmp parseEnd
-
- instrMsg = *
- db "got processor instruction="
- db 0
- instrAddrMsg1 = *
- db "got address mode="
- db 0
- instrAddrMsg2 = *
- db ", value="
- db 0
- instrCodeMsg = *
- db "code = "
- db 0
- instrAdmodePromote = *
- db $00,$00,$00,$00,$07,$08,$09,$00,$00,$00,$00,$00,$00
-
- ; num name gen byt tokens
- ; --- --------- --- --- -------
- ; 00. <none> 00. 0 <none>
- ; 01. implied 00. 1 CR
- ; 02. immediate 00. 2 # / exp8 / CR
- ; 03. relative 00. 2 exp16 / CR
- ; 04. zeropage 07. 2 exp8 / CR
- ; 05. zp,x 08. 2 exp8 / , / x / CR
- ; 06. zp,y 09. 2 exp8 / , / y / CR
- ; 07. absolute 00. 3 exp16 / CR
- ; 08. abs,x 00. 3 exp16 / , / x / CR
- ; 09. abs,y 00. 3 exp16 / , / y / CR
- ; 10. indirect 00. 3 ( / exp16 / ) / CR
- ; 11. (ind,x) 00. 2 ( / exp8 / , / x / ) / CR
- ; 12. (ind),y 00. 2 ( / exp8 / ) / , / y / CR
- ;
- ; All zp modes can be promoted to abs except for zp,y for stx and zp,x for sty.
- ; Indy mode causes some special problems--I'll have to patch the hole.
-
- instrGetAddrMode = * ;( address, instrNum ) : instrAddrMode, instrValue,
- lda #$00 ; instrValueType
- sta instrValue+0
- sta instrValue+1
- sta instrValueType
- lda tokenNextChar
- cmp #"#"
- beq admodeImmediate
- cmp #"("
- beq admodeIndirect
- cmp #chrCR
- bne +
- jsr getToken ;get the CR
- lda #01 ;implied
- sta instrAddrMode
- rts
- + lda instrNum
- cmp #14
- bcs +
- cmp #4
- bcc +
- cmp #7
- beq +
- cmp #11
- beq +
- jmp admodeRelative
- ;** zp or abs, straight or indexed
- + lda #0
- jsr admodeHandleExpr
- ldy #04 ;zeropage mode
- cpx #1
- beq +
- ldy #07 ;absolute mode
- + sty instrAddrMode
- cmp #chrCR
- bne +
- rts
- + cmp #","
- beq +
- - jmp syntaxError
- + jsr admodeGetXY
- inc instrAddrMode
- cpx #0
- beq +
- inc instrAddrMode
- + cmp #chrCR
- bne -
- rts
-
- admodeImmediate = *
- jsr getToken ;get the "#"
- lda #1
- jsr admodeHandleExpr
- cmp #chrCR
- beq +
- jmp syntaxError
- + lda #02
- sta instrAddrMode
- rts
-
- admodeRelative = *
- lda #2
- jsr admodeHandleExpr
- cmp #chrCR
- beq +
- jmp syntaxError
- + lda #03
- sta instrAddrMode
- rts
-
- admodeIndirect = *
- jsr getToken ;get the "("
- lda #0
- jsr parseExpression
- cmp #","
- beq admodeIndX
- cmp #")"
- beq +
- - jmp syntaxError
- + jsr getToken
- ldx tokenType
- cpx #tokenSpecial
- bne -
- lda tokenChar
- cmp #","
- beq admodeIndY
- cmp #chrCR
- bne -
- lda #0
- sta admodeMustBe
- jsr admodeHandleExprIn
- lda #10
- sta instrAddrMode
- rts
-
- admodeIndX = *
- lda #1
- sta admodeMustBe
- jsr admodeHandleExprIn
- jsr admodeGetXY
- cpx #0
- beq +
- - jmp syntaxError
- + cmp #")"
- bne -
- jsr getToken
- cpx #tokenSpecial
- bne -
- cmp #chrCR
- bne -
- lda #11
- sta instrAddrMode
- rts
-
- admodeIndY = *
- lda #1
- sta admodeMustBe
- jsr admodeHandleExprIn
- jsr admodeGetXY
- cpx #1
- beq +
- - jmp syntaxError
- + cmp #chrCR
- bne -
- lda #12
- sta instrAddrMode
- rts
-
- admodeGetXY = * ;( .X=tokenType, token ) : .A=specialChar, .X=0:x/1:y
- jsr getToken
- ldx tokenType
- cpx #tokenIdentifier
- beq +
- - jmp syntaxError
- + lda stringLen
- cmp #1
- bne -
- lda stringBuf+0
- ldy #0
- cmp #"x"
- beq +
- iny
- cmp #"y"
- bne -
- + tya
- pha
- jsr getToken
- ldx tokenType
- cpx #tokenSpecial
- bne -
- pla
- tax
- lda tokenChar
- rts
-
- admodeMustBe : buf 1
- admodeChar : buf 1
- admodeHole : buf 1
-
- admodeHandleExpr = * ;( .A=1:byte+2:rel, address ) : .A=nextChar, .X=valBytes,
- sta admodeMustBe ; instrValue, instrValueType
- lda #0
- jsr parseExpression
- sta admodeChar
-
- admodeHandleExprIn = *
- jsr evaluateExpression
- lda idVal+0
- ldy idVal+1
- sta instrValue+0
- sty instrValue+1
- lda idType
- sta instrValueType
- bcs admodeExprHole
- lda idVal+2
- ora idVal+3
- beq +
- - lda #errValueTooLarge
- jmp error
- + lda admodeMustBe
- bne ++
- ldx #2
- lda instrValue+1
- bne +
- - ldx #1
- + lda admodeChar
- rts
- + cmp #1 ;must be byte
- bne +
- lda instrValue+1
- bne --
- beq -
- + clc ;must be relative
- lda address+0
- adc #2
- sta work+14
- lda address+1
- adc #0
- sta work+15
- sec
- lda instrValue+0
- sbc work+14
- sta instrValue+0
- tax
- lda instrValue+1
- sbc work+15
- sta instrValue+1
- cmp #0
- bne +
- cpx #128
- bcc ++
- - lda #errBranchTooFar
- jmp error
- + cmp #$ff
- bne -
- cpx #128
- bcc -
- + lda #0
- sta instrValue+1
- ldx #1
- lda admodeChar
- rts
-
- admodeExprHole = *
- ;** get presumed hole type
- lda #$02 ;holeType=word
- ldx admodeMustBe
- beq +
- lda #$01 ;holeType=byte
- cpx #1
- beq +
- lda #$40 ;holeType=branch
- ;** check for special cases of "stx zp,y" and "sty zp,x" which must be zp
- + cmp #$02
- bne +
- ldx instrNum
- cpx #49 ;instr.49==stx
- bcc +
- cpx #50+1 ;instr.50==sty
- bcs +
- ldx admodeChar
- cpx #","
- bne +
- lda #$01 ;is one of specials, so hole must be 8-bits
- ;** record the hole
- + pha
- tax
- lda #1
- jsr addMemoryHole
- ;** get the return values
- pla
- cmp #$40
- bne +
- lda #1
- + tax
- ldy #$80
- sty instrValueType
- ldy #$00
- sty instrValue+0
- sty instrValue+1
- lda admodeChar
- rts
-
- ;taken from Mighty Mon 4.0: instr# + addrMode -> opcode conversion + length
-
- opcodeBase = work+14
- opcodeAdmodeNum = work+15
-
- instrGetOpcode = * ;( .A=instr#, .X=addrMode ) : instrOpcode, instrLen, .CS=inv
- tay ;.$da4b [a8 ] tay
- lda opcodeBaseTab,y ;.$da4c [b9 55 c2] lda $c255,y
- sta opcodeBase ;.$da4f [85 48 ] sta $48
- stx opcodeAdmodeNum ;.$da51 [86 49 ] stx $49
- lda opcodeAdmodeTab,y ;.$da53 [b9 8d c2] lda $c28d,y
- bmi ++ ;.$da56 [30 0e ] bmi $da66
- cmp opcodeAdmodeNum ;.$da58 [c5 49 ] cmp $49
- bne + ;.$da5a [d0 08 ] bne $da64
- lda opcodeLenTab,x ;.$da5c [bd 6c c3] lda $c36c,x
- tax ;.$da5f [aa ] tax
- lda opcodeBase ;.$da60 [a5 48 ] lda $48
- sta instrOpcode ;
- stx instrLen ;
- clc ;.$da62 [18 ] clc
- rts ;.$da63 [60 ] rts
- + nop ;
- - sec ;.$da64 [38 ] sec
- rts ;.$da65 [60 ] rts
- ;
- + and #$7f ;.$da66 [29 7f ] and #$7f
- tay ;.$da68 [a8 ] tay
- lda opcodeOrOffTab,y ;.$da69 [b9 60 c3] lda $c360,y
- clc ;.$da6c [18 ] clc
- adc opcodeAdmodeNum ;.$da6d [65 49 ] adc $49
- tay ;.$da6f [a8 ] tay
- dey ; <the ad modes start from 1 not 0 like in mm4>
- lda opcodeOrMaskTab,y ;.$da70 [b9 d2 c2] lda $c2d2,y
- bmi - ;.$da73 [30 ef ] bmi $da64
- ora opcodeBase ;.$da75 [05 48 ] ora $48
- tay ;.$da77 [a8 ] tay
- lda opcodeLenTab,x ;.$da78 [bd 6c c3] lda $c36c,x
- tax ;.$da7b [aa ] tax
- tya ;.$da7c [98 ] tya
- sta instrOpcode ;
- stx instrLen ;
- clc ;.$da7d [18 ] clc
- rts ;.$da7e [60 ] rts
-
- opcodeBaseTab = *
- db $00,$61,$21,$02,$90,$b0,$f0,$24,$30,$d0,$10,$00,$50,$70,$18,$d8
- db $58,$b8,$c1,$e0,$c0,$c6,$ca,$88,$41,$e6,$e8,$c8,$4c,$20,$a1,$a2
- db $a0,$42,$ea,$01,$48,$08,$68,$28,$22,$62,$40,$60,$e1,$38,$f8,$78
- db $81,$86,$84,$aa,$a8,$ba,$8a,$9a,$98
-
- opcodeAdmodeTab = *
- db $00,$81,$81,$82,$03,$03,$03,$83,$03,$03,$03,$01,$03,$03,$01,$01
- db $01,$01,$81,$84,$84,$85,$01,$01,$81,$85,$01,$01,$86,$07,$81,$87
- db $88,$82,$01,$81,$01,$01,$01,$01,$82,$82,$01,$01,$81,$01,$01,$01
- db $89,$8a,$8b,$01,$01,$01,$01,$01,$01
-
- opcodeLenTab = *
- db $00,$01,$02,$02,$02,$02,$02,$03,$03,$03,$03,$02,$02
-
- opcodeOrOffTab = *
- db 0,0,12,24,36,48,60,72,84,96,108,120
-
- opcodeOrMaskTab = *
- ; 01 02 03 04 05 06 07 08 09 10 11 12 : addrMode
- ; -- -- -- -- -- -- -- -- -- -- -- -- <if compressed>
- db $80,$08,$80,$04,$14,$80,$0c,$1c,$18,$80,$00,$10 ;[trim:1+0=1] [add=2]
- db $08,$80,$80,$04,$14,$80,$0c,$1c,$80,$80,$80,$80 ;[trim:0+4=4] [add=2]
- db $80,$80,$80,$04,$80,$80,$0c,$80,$80,$80,$80,$80 ;[trim:3+5=8] [add=2]
- db $80,$00,$80,$04,$80,$80,$0c,$80,$80,$80,$80,$80 ;[trim:1+5=6] [add=2]
- db $80,$80,$80,$04,$14,$80,$0c,$1c,$80,$80,$80,$80 ;[trim:3+4=7] [add=2]
- db $80,$80,$80,$80,$80,$80,$00,$80,$80,$20,$80,$80 ;[trim:6+2=8] [add=2]
- db $80,$00,$80,$04,$80,$14,$0c,$80,$1c,$80,$80,$80 ;[trim:1+3=4] [add=2]
- db $80,$00,$80,$04,$14,$80,$0c,$1c,$80,$80,$80,$80 ;[trim:1+4=5] [add=2]
- db $80,$80,$80,$04,$14,$80,$0c,$1c,$18,$80,$00,$10 ;[trim:3+0=3] [add=2]
- db $80,$80,$80,$04,$80,$14,$0c,$80,$80,$80,$80,$80 ;[trim:3+5=8] [add=2]
- db $80,$80,$80,$04,$14,$80,$0c,$80,$80,$80,$80,$80 ;[trim:3+5=8] [add=2]
-
- ;======== expression handling ========
-
- parseExprType : buf 1
-
- parseExpression = * ;( .A=type(0=num,1=either) ) : .A=nextSpecialChar,.X=type
- sta parseExprType
- ldx #16
- stx expOffset
- lda #"+"
- sta expOp+0,x
- ldx #3
- - lda #0
- sta expHoleType,x
- lda #aceMemNull
- sta expHoleAddr,x
- lda sourceLine,x
- sta expSrcLine,x
- lda filePtr,x
- sta expSrcFile,x
- dex
- bpl -
- lda sourceCol
- sta expSrcCol
- bit debug
- bpl expGetOperand
- lda #<parseExprMsg
- ldy #>parseExprMsg
- jsr puts
-
- ;** expecting operand
- expGetOperand = *
- lda #0
- sta expPlusCount
- sta expMinusCount
- sta expLessCount
- sta expGreaterCount
- expGetOperandCont = *
- ldx expOffset
- lda #0
- sta expReserved,x
- jsr getToken
- cpx #tokenSpecial
- bne expNotSpecial
- lda tokenChar
- cmp #"+"
- bne +
- inc expPlusCount
- jmp expGetOperandCont
- + cmp #"-"
- bne +
- inc expMinusCount
- jmp expGetOperandCont
- + cmp #">"
- bne +
- inc expGreaterCount
- jmp expGetOperandCont
- + cmp #"<"
- bne +
- inc expLessCount
- jmp expGetOperandCont
- + cmp #"*"
- bne +
- jmp expOpnStar
- + jmp expOpnRelative
-
- expNotSpecial = *
- ldx expOffset
- lda expMinusCount
- and #$01
- lsr
- ror
- sta expSign,x
- jsr expFigureHiLo
- sta expHiLo,x
- lda #$00
- sta expType,x
- ldx tokenType
- cpx #tokenIdentifier
- bne +
- lda #0
- jmp expOpnIdentifier
- + cpx #tokenNumber
- bne +
- jmp expOpnNumber
- + cpx #tokenString
- bne +
- jmp expOpnString
- + jmp syntaxError
- parseExprMsg = *
- db "...must parse an expression..."
- db chrCR,0
-
- ;"Asteroids do not concern me, Admiral. I want that ship, not excuses!"
- ;"Mudhole!? Slimy!!? My home, this is!"
-
- expFigureHiLoWork : buf 1
-
- expFigureHiLo = * ; ( ) : .A=HiLo_value ;.X:unchanged
- lda expGreaterCount
- cmp #16
- bcc +
- lda #15
- + asl
- asl
- asl
- asl
- sta expFigureHiLoWork
- lda expLessCount
- cmp #2
- bcc +
- lda #1
- + ora expFigureHiLoWork
- rts
-
- expOpnRelExit : buf 1 ;whether to exit exp after relative ref.
-
- expOpnRelative = *
- ldx #0
- cmp #":"
- beq +
- ldx #$ff
- + stx expOpnRelExit
- lda expPlusCount ;there must be some pluses or minuses
- ora expMinusCount
- bne +
- jmp syntaxError
- + jsr expFigureHiLo
- ldx expOffset
- sta expHiLo,x
- lda #0
- sta expSign,x
- lda #"+"
- ldy expPlusCount
- beq +
- ldx expMinusCount
- beq ++
- jmp syntaxError
- + lda #"-"
- ldy expMinusCount
- bne +
- jmp syntaxError
- + dey
- jsr genRelLabel
- lda expOpnRelExit
- ;** fall through
-
- expOpnIdentifier = *
- pha
- jsr findSymbol
- ldx expOffset
- lda idType
- cmp #$81
- bcc +
- cmp #$ff
- beq +
- lda #errNonNumIdExpr
- jmp error
- + sta expType,x
- ldy #0
- cmp #$80
- bcs +
- - lda idVal,y
- sta expValue,x
- inx
- iny
- cpy #4
- bcc -
- pla
- jmp expGetOperator
- + inc expUnresCnt
- - lda idPtr,y
- sta expValue,x
- inx
- iny
- cpy #4
- bcc -
- pla
- jmp expGetOperator
-
- expOpnStar = *
- bit originSet
- bmi +
- lda #errOriginNotSet
- jmp error
- + ldx expOffset
- lda expMinusCount
- and #$01
- lsr
- ror
- sta expSign,x
- jsr expFigureHiLo
- sta expHiLo,x
- lda #$01
- sta expType,x
- lda address+0
- sta expValue+0,x
- lda address+1
- sta expValue+1,x
- lda #0
- sta expValue+2,x
- sta expValue+3,x
- lda #0
- jmp expGetOperator
-
- expOpnNumber = *
- ldx expOffset
- lda #$00
- sta expType,x
- ldy #0
- - lda number,y
- sta expValue,x
- inx
- iny
- cpy #4
- bcc -
- lda #0
- jmp expGetOperator
-
- expOpnString = *
- lda stringLen
- cmp #1
- bne +
- ;** interpret string as number
- ldx expOffset
- lda #$00
- sta expType,x
- lda stringBuf+0
- sta expValue+0,x
- lda #0
- sta expValue+1,x
- sta expValue+2,x
- sta expValue+3,x
- lda #0
- jmp expGetOperator
-
- ;** interpret string as actual string
- + lda expPlusCount
- ora expMinusCount
- ora expLessCount
- ora expGreaterCount
- beq +
- - lda #errInvalStrOpers
- jmp error
- + lda expOffset
- cmp #16
- bne -
- lda parseExprType
- bne +
- - jmp syntaxError
- + jsr getToken
- cpx #tokenSpecial
- bne -
- + ldx #$80
- rts
-
- expGetOperator = * ;(.A=exitFlag)
- pha
- clc
- lda expOffset
- adc #14
- sta expOffset
- bcc +
- lda #errTooManyOperands
- jmp error
- + pla
- cmp #0
- beq +
- - ldx expOffset
- txa
- sta expLength
- lda sourceCol
- sta expSrcCol
- lda tokenChar
- ldx #0
- rts
- + jsr getToken
- ldx tokenType
- cpx #tokenSpecial
- beq +
- jmp syntaxError
- + lda tokenChar
- cmp #"+"
- beq +
- cmp #"-"
- bne -
- + ldx expOffset
- sta expOp,x
- jmp expGetOperand
-
- evaluateExpression = * ;( expTable ) : .CS=unresolved, idVal, idType
- ldx #3
- lda #0
- - sta idVal,x
- dex
- bpl -
- sta idType
- lda expUnresCnt
- beq +
- lda #$80
- sta idType
- sec
- rts
- + ldx #16
- stx expOffset
-
- evalNext = *
- ldx expOffset
- lda expType,x
- eor idType ;(+-:val+val=val,adr+val=adr,val+adr=adr,adr+adr=val)
- sta idType
- ldy #$00
- - lda expValue,x
- sta number,y
- inx
- iny
- cpy #4
- bcc -
- ldx expOffset
- lda expSign,x
- bpl +
- jsr evalNegate
- + ldx expOffset
- cpx #16
- beq +
- lda expHiLo,x
- beq +
- jsr evalHiLo
- + ldx expOffset
- lda expOp,x
- cmp #"+"
- beq +
- jsr evalNegate
- ;** perform addition
- + clc
- ldy #4
- ldx #0
- - lda idVal,x
- adc number,x
- sta idVal,x
- inx
- dey
- bne -
- ;** go onto next operation
- clc
- lda expOffset
- adc #14
- sta expOffset
- cmp expLength
- bcc evalNext
- ;** check global hi-lo
- lda expHiLo+16
- beq +
- ldx #3
- - lda idVal,x
- sta number,x
- dex
- bpl -
- lda expHiLo+16
- jsr evalHiLo
- ldx #3
- - lda number,x
- sta idVal,x
- dex
- bpl -
- + clc
- bit debug
- bmi +
- rts
- + lda #<evalMsg
- ldy #>evalMsg
- jsr puts
- ldx #idVal
- jsr putnum
- lda #","
- jsr putchar
- lda #" "
- jsr putchar
- lda #"v"
- ldx idType
- beq +
- lda #"a"
- + jsr putchar
- lda #chrCR
- jsr putchar
- clc
- rts
- evalMsg = *
- db "evaluate: result="
- db 0
-
- evalNegate = * ;( number ) : -number
- sec
- ldy #4
- ldx #0
- - lda #0
- sbc number,x
- sta number,x
- inx
- dey
- bne -
- rts
-
- evalHiLoCnt : buf 1
-
- evalHiLo = *
- ;value $10 will extract high byte of addr, $01 will extract low byte
- pha
- lsr
- lsr
- lsr
- lsr
- tax
- beq +
- - lda number+1
- sta number+0
- lda number+2
- sta number+1
- lda number+3
- sta number+2
- lda #$00
- sta number+3
- dex
- bne -
- + pla
- and #$0f
- beq +
- ldx #0
- stx number+3
- stx number+2
- stx number+1
- + rts
-
- ;======== symbol table management ========
-
- findSymbol = * ;( stringBuf, stringLen ) : .A=code,idPtr,idVal
- ;** ret: code .A=(symFound,symUnresolved,symNew)
- jsr hash
- ldy #3
- - lda (hashPtr),y
- sta mp,y
- dey
- bpl -
- findSymNext = *
- lda mp+3
- cmp #aceMemNull
- bne +
- jmp findSymCreate
- + lda #<symBuf
- ldy #>symBuf
- sta zp+0
- sty zp+1
- lda #12+8+1
- ldy #0
- jsr fetch
- lda symNameLen
- cmp stringLen
- bne findSymCont
- cmp #8+1
- bcc +
- clc
- adc #12+1
- ldy #0
- jsr fetch
- + ldx #0
- - lda stringBuf,x
- beq +
- cmp symName,x
- bne findSymCont
- inx
- bne -
- + ldx #3
- - lda mp,x
- sta idPtr,x
- lda symValue,x
- sta idVal,x
- dex
- bpl -
- lda symType
- sta idType
- lda #symFound
- bit symType
- bpl +
- lda #symUnresolved
- + rts
-
- findSymCont = *
- ldx #3
- - lda symNext,x
- sta mp,x
- dex
- bpl -
- jmp findSymNext
-
- findSymCreate = *
- lda #$80
- sta symType
- sta idType
- lda #$00
- sta symClass
- sta symUnresOpnd
- lda stringLen
- sta symNameLen
- ldx #0
- - lda stringBuf,x
- sta symName,x
- beq +
- inx
- bne -
- + clc
- lda #12+1
- adc symNameLen
- ldy #0
- jsr malloc
- bcc +
- lda #errInsufficientMemory
- jmp error
- + ldy #3
- - lda #aceMemNull
- sta symValue,y
- lda #0
- sta idVal,y
- lda (hashPtr),y
- sta symNext,y
- lda mp,y
- sta idPtr,y
- sta (hashPtr),y
- dey
- bpl -
- jsr stashSymbol
- lda #symNew
- rts
-
- fetchSymbol = * ;( [mp] ) : symBuf
- lda #<symBuf
- ldy #>symBuf
- sta zp+0
- sty zp+1
- lda #12+8+1
- ldy #0
- jsr fetch
- lda symNameLen
- cmp #8+1
- bcc +
- clc
- adc #12+1
- ldy #0
- jsr fetch
- + rts
-
- fetchSymbolHeader = * ;( [mp] ) : symBuf (header)
- lda #<symBuf
- ldy #>symBuf
- sta zp+0
- sty zp+1
- lda #12
- ldy #0
- jsr fetch
- rts
-
- stashSymbol = * ;( symBuf, [mp] )
- lda #<symBuf
- ldy #>symBuf
- sta zp+0
- sty zp+1
- clc
- lda #12+1
- adc symNameLen
- ldy #0
- jsr stash
- rts
-
- stashSymbolHeader = * ;( symBuf(header), [mp] )
- lda #<symBuf
- ldy #>symBuf
- sta zp+0
- sty zp+1
- lda #12
- ldy #0
- jsr stash
- rts
-
- initSymbolTable = *
- lda #<identHashTable
- ldy #>identHashTable
- ldx #hashTablePages
- ;** fall through
-
- fillNull = *
- sta work+0
- sty work+1
- ldy #0
- lda #aceMemNull
- - sta (work),y
- iny
- bne -
- inc work+1
- dex
- bne -
- rts
-
- findUnresSymbol = *
- ;** fetches symbol and reference
- lda #$80
- sta dumpSymOpt
- jmp dumpSymbolTableIn
- foundUnresSymbol = *
- ldx #3
- - lda symValue,x
- sta expPtr,x
- dex
- bpl -
- jsr fetchExp
- rts
-
- dumpSymEntries : buf 2
- dumpSymOpt : buf 1
- dumpCount = idVal
-
- dumpSymbolTable = *
- lda #$00
- sta dumpSymOpt
- ldx #3
- - sta dumpCount,x
- dex
- bpl -
- bit symDump
- bmi +
- rts
- + lda #<dumpSymMsg1
- ldy #>dumpSymMsg1
- jsr puts
- dumpSymbolTableIn = *
- lda #<identHashTable
- ldy #>identHashTable
- sta hashPtr+0
- sty hashPtr+1
- lda #0
- ldy #hashTableEntriesHigh
- sta dumpSymEntries+0
- sty dumpSymEntries+1
- - jsr dumpSymBucket
- clc
- lda hashPtr+0
- adc #4
- sta hashPtr+0
- bcc +
- inc hashPtr+1
- + inc dumpSymEntries+0
- bne -
- dec dumpSymEntries+1
- bne -
- lda #<dumpSymMsg2
- ldy #>dumpSymMsg2
- jsr puts
- ldx #dumpCount
- jsr putnum
- lda #chrCR
- jsr putchar
- rts
-
- dumpSymBucket = *
- ldy #3
- - lda (hashPtr),y
- sta mp,y
- dey
- bpl -
- - lda mp+3
- cmp #aceMemNull
- bne +
- rts
- + jsr fetchSymbol
- jsr dumpSymbol
- ldx #3
- - lda symNext,x
- sta mp,x
- dex
- bpl -
- jmp --
-
- dumpSymbol = *
- bit dumpSymOpt
- bpl ++
- lda symType
- cmp #$80
- beq +
- cmp #$ff
- bne ++
- + pla ;** pop call from dumpSymBucket
- pla
- pla ;** pop call from dumpSymbolTable
- pla
- jmp foundUnresSymbol
- + ldx #dumpCount
- jsr incLong
- lda #0
- sta number+2
- sta number+3
- sec
- lda hashPtr+0
- sbc #<identHashTable
- sta number+0
- lda hashPtr+1
- sbc #>identHashTable
- sta number+1
- lsr number+1
- ror number+0
- lsr number+1
- ror number+0
- ldx #number
- ldy #4
- jsr wputnum
- lda #2
- jsr space
- ldx #3
- - lda symValue,x
- sta number,x
- dex
- bpl -
- lda number+3
- jsr puthex
- lda number+2
- jsr puthex
- lda number+1
- jsr puthex
- lda number+0
- jsr puthex
- lda #1
- jsr space
- ldx #number
- ldy #10
- jsr wputnum
- lda #2
- jsr space
- lda #"v"
- ldx symType
- beq +
- lda #"a"
- bit symType
- bpl +
- lda #"?"
- + jsr putchar
- lda #2
- jsr space
- lda #<symName
- ldy #>symName
- jsr puts
- lda #chrCR
- jsr putchar
- jsr checkStop
- rts
-
- spaceCount : buf 1
-
- space = *
- sta spaceCount
- - lda #" "
- jsr putchar
- dec spaceCount
- bne -
- rts
-
- dumpSymMsg1 = *
- db "HASH HEXVALUE DECIMAL T NAME"
- db chrCR
- db "---- -------- ---------- - -----"
- db chrCR,0
- dumpSymMsg2 = *
- db "--"
- db chrCR
- db "Number of symbols: "
- db 0
- ;1234567890123456789012345678901234567890
-
- hashWork : buf 2
-
- hash = *
- lda #$aa
- sta hashVal+0
- sta hashVal+1
- ldx #0
- - lda stringBuf,x
- bne +
- lda hashVal+0
- sta hashPtr+0
- lda hashVal+1
- and #hashTableMask
- asl hashPtr+0
- rol
- asl hashPtr+0
- rol
- sta hashPtr+1
- clc
- lda hashPtr+0
- adc #<identHashTable
- sta hashPtr+0
- lda hashPtr+1
- adc #>identHashTable
- sta hashPtr+1
- rts
- ;** hashVal := hashVal * 37;
- + lda hashVal+0
- ldy hashVal+1
- sta hashWork+0
- sty hashWork+1
- asl ;times 2
- rol hashVal+1
- asl ;times 4
- rol hashVal+1
- asl ;times 8
- rol hashVal+1
- jsr hashAddWork ;times 9
- asl ;times 18
- rol hashVal+1
- asl ;times 36
- rol hashVal+1
- jsr hashAddWork ;times 37
- adc stringBuf,x
- sta hashVal+0
- bcc +
- inc hashVal+1
- + inx
- bne -
-
- hashAddWork = *
- clc
- adc hashWork+0
- sta hashVal+0
- lda hashVal+1
- adc hashWork+1
- sta hashVal+1
- lda hashVal+0
- rts
-
- ;======== symbols, expressions, and holes: symbol definition support ========
-
- parseDefineVar = *
- jsr findSymbol
- cmp #symNew
- beq +
- lda symType
- cmp #$80
- beq +
- lda #errRedefinedSymbol
- jmp error
- + lda #$ff
- sta symType
- jsr stashSymbol
- ldx #3
- - lda idPtr,x
- sta varPtr,x
- dex
- bpl -
- rts
-
- addMemoryHole = * ;( .X=holeType, address+.A )
- ;** put in hole information
- stx expHoleType
- clc
- adc address+0
- sta expHoleAddr+0
- lda address+1
- adc #0
- sta expHoleAddr+1
- lda #0
- sta expHoleAddr+2
- sta expHoleAddr+3
- jmp addHoleIn
-
- addVariableHole = * ;( varPtr, expTable ) : ...
- ;** put in hole information
- lda #$80
- sta expHoleType
- ldx #3
- - lda varPtr,x
- sta expHoleAddr,x
- dex
- bpl -
-
- addHoleIn = *
- ;** keep a count of the global number of unresolved references
- ldx #holeCount
- jsr incLong
- ;** keep a separate count of the unresolved relative labels:they must be resd
- lda stringLen
- cmp #2
- bcc +
- lda stringBuf+1
- cmp #"+"
- beq +
- cmp #"-"
- bne ++
- + ldx #relHoleCount
- jsr incLong
- ;** allocate storage for expression descriptor
- + lda expLength
- ldy #0
- jsr malloc
- bcc +
- lda #errInsufficientMemory
- jmp error
- + ldx #3
- - lda mp,x
- sta expPtr,x
- dex
- bpl -
- ;** scan for pointers to unresolved labels, refs into corresp.reference lists
- ldx #16
- stx expOffset
-
- addHoleNext = *
- ldx expOffset
- lda expType,x
- bpl addHoleCont
- ldy #0
- - lda expValue,x
- sta mp,y
- inx
- iny
- cpy #4
- bcc -
- jsr fetchSymbolHeader
- ldx expOffset
- ldy #0
- - lda symValue,y
- sta expNextUnres,x
- lda expPtr,y
- sta symValue,y
- inx
- iny
- cpy #4
- bcc -
- ldx expOffset
- lda symUnresOpnd
- sta expNextOpnd,x
- stx symUnresOpnd
- jsr stashSymbolHeader
-
- addHoleCont = *
- clc
- lda expOffset
- adc #14
- sta expOffset
- cmp expLength
- bcc addHoleNext
-
- ;** store expression descriptor
- jmp stashExp
-
- plugStackHead : buf 4
- plugRecBuf = *
- plugRecNext : buf 4
- plugRecVarPtr : buf 4
- plugRecIdVal : buf 4
- plugRecIdType : buf 1
-
- plugStackInit = *
- lda #aceMemNull
- sta plugStackHead+3
- rts
-
- plugStackPush = * ;( varPtr, idVal, idType )
- lda #13
- ldy #0
- jsr malloc
- bcc +
- lda #errInsufficientMemory
- jsr error
- + ldx #3
- - lda plugStackHead,x
- sta plugRecNext,x
- lda mp,x
- sta plugStackHead,x
- lda varPtr,x
- sta plugRecVarPtr,x
- lda idVal,x
- sta plugRecIdVal,x
- dex
- bpl -
- lda idType
- sta plugRecIdType
- lda #<plugRecBuf
- ldy #>plugRecBuf
- sta zp+0
- sty zp+1
- lda #13
- ldy #0
- jsr stash
- rts
-
- plugStackPop = * ;( ) : varPtr, idVal, idType, .CS=empty
- ldx #3
- - lda plugStackHead,x
- sta mp,x
- dex
- bpl -
- lda mp+3
- cmp #aceMemNull
- bne +
- sec
- rts
- + lda #<plugRecBuf
- ldy #>plugRecBuf
- sta zp+0
- sty zp+1
- lda #13
- ldy #0
- jsr fetch
- lda #13
- ldy #0
- jsr free
- ldx #3
- - lda plugRecNext,x
- sta plugStackHead,x
- lda plugRecVarPtr,x
- sta varPtr,x
- lda plugRecIdVal,x
- sta idVal,x
- dex
- bpl -
- lda plugRecIdType
- sta idType
- rts
-
- assignVarSave : buf 10
-
- assignVariable = * ;( varPtr, idVal, idType ) : ... ;changes idPtr,varPtr,etc.
- jsr plugStackInit
- ;** assign value to variable
- assignVarBody = *
- ldx #3
- - lda varPtr,x
- sta mp,x
- dex
- bpl -
- jsr fetchSymbolHeader
- lda symType
- cmp #$ff
- beq +
- lda #errInternAssign
- jmp error
- + ldx #3
- - lda symValue,x
- sta expPtr,x
- lda idVal,x
- sta symValue,x
- dex
- bpl -
- lda symUnresOpnd
- sta expOffset
- lda idType
- sta symType
- jsr stashSymbolHeader
-
- ;** cascade changes if necessary
- ;Run through reference list, filling in value of id, unlinking from this id.
- ;If we resolve an expression, evaluate it, and if the hole is in memory, fill
- ;it. If the filled hole is another variable, push the <varPtr,idVal,idType>
- ;values onto the plug stack and continue with reference list for the current
- ;variable. When we are done with the current label, pop a variable off the
- ;plug stack and continue with it. Otherwise, exit.
- assignVarCascade = *
- lda expPtr+3
- cmp #aceMemNull
- bne +
- jsr plugStackPop
- bcc assignVarBody
- rts
- ;** fetch unresolved expression
- + jsr fetchExp
- ;** fill in value
- ldx expOffset
- lda idType
- sta expType,x
- ldy #0
- - lda idVal,y
- sta expValue,x
- inx
- iny
- cpy #4
- bcc -
- dec expUnresCnt
- bne assignVarUnresolved
- jmp assignVarResolved
-
- ;** still unresolved--stash modified expression
- assignVarUnresolved = *
- jsr stashExp
- jmp assignVarCascadeCont
-
- ;** resolved--evaluate expression, fill in hole
- assignVarResolved = *
- ldx #3
- - lda expPtr,x
- sta mp,x
- dex
- bpl -
- lda expLength
- ldy #0
- jsr free
- ;** save varPtr,idVal,idType,expOffset
- ldx #3
- - lda varPtr,x
- sta assignVarSave+0,x
- lda expHoleAddr,x
- sta varPtr,x
- lda idVal,x
- sta assignVarSave+4,x
- dex
- bpl -
- lda idType
- sta assignVarSave+8
- lda expOffset
- sta assignVarSave+9
- ldx #holeCount
- jsr decLong
- lda symClass
- cmp #$01
- beq +
- ldx #relHoleCount
- jsr decLong
- ;** evaluate new expression
- + jsr evaluateExpression
- ;** fill hole--id hole: push hole plug--do something else for memory hole
- lda expHoleType
- cmp #$80
- beq +
- jsr fillMemoryHole
- jmp ++
- + jsr plugStackPush
- ;** restore varPtr,idVal,idType,expOffset
- + ldx #3
- - lda assignVarSave+0,x
- sta varPtr,x
- lda assignVarSave+4,x
- sta idVal,x
- dex
- bpl -
- lda assignVarSave+8
- sta idType
- lda assignVarSave+9
- sta expOffset
-
- ;** go onto next unresolved expression
- assignVarCascadeCont = *
- ldx expOffset
- lda expNextOpnd,x
- sta expOffset
- ldy #0
- - lda expNextUnres,x
- sta expPtr,y
- inx
- iny
- cpy #4
- bcc -
- jmp assignVarCascade
-
- fetchExp = * ;( [expPtr] ) : expTable, mp=expPtr
- ldx #3
- - lda expPtr,x
- sta mp,x
- dex
- bpl -
- lda #<expTable
- ldy #>expTable
- sta zp+0
- sty zp+1
- lda #16+14
- ldy #0
- jsr fetch
- lda expLength
- cmp #16+14+1
- bcc +
- lda expLength
- ldy #0
- jsr fetch
- + rts
-
- stashExp = * ;( [expPtr], expTable ) : mp=expPtr
- ldx #3
- - lda expPtr,x
- sta mp,x
- dex
- bpl -
- lda #<expTable
- ldy #>expTable
- sta zp+0
- sty zp+1
- lda expLength
- ldy #0
- jsr stash
- rts
-
- fillMhType : buf 1
-
- fillMemoryHole = * ;( .A=holeType, varPtr, idVal, idType )
- sta fillMhType
- bit debug
- bpl fillMhCont
- lda #<fillMhMsg1
- ldy #>fillMhMsg1
- jsr puts
- lda varPtr+1
- jsr puthex
- lda varPtr+0
- jsr puthex
- lda #<fillMhMsg2
- ldy #>fillMhMsg2
- jsr puts
- ldx #idVal
- jsr putnum
- lda #" "
- jsr putchar
- lda #"("
- jsr putchar
- lda #"v"
- ldx idType
- beq +
- lda #"a"
- + jsr putchar
- lda #<fillMhMsg3
- ldy #>fillMhMsg3
- jsr puts
- lda fillMhType
- jsr puthex
- lda #chrCR
- jsr putchar
- ;%%%
-
- fillMhCont = *
- lda fillMhType
- cmp #$40
- beq fillMhBranch
- tax
- dex
- - lda idVal,x
- sta memPutVals,x
- dex
- bpl -
- ldx fillMhType
- dex
- - inx
- cpx #4
- bcs +
- lda idVal,x
- beq -
- lda #errValueTooLarge
- jmp errorRef
- + lda fillMhType
- ldx varPtr+0
- ldy varPtr+1
- jsr memPut
- ;** add relocatable reference
- lda idType
- beq +
- cmp #$04
- bcs +
- ldx varPtr+0
- ldy varPtr+1
- jsr recordRelocRef
- + rts
-
- fillMhBranch = *
- lda idVal+2
- ora idVal+3
- beq +
- lda #errValueTooLarge
- jmp errorRef
- + clc
- lda varPtr+0
- adc #1
- sta memPutVals+0
- lda varPtr+1
- adc #0
- sta memPutVals+1
- sec
- lda idVal+0
- sbc memPutVals+0
- sta memPutVals+0
- tax
- lda idVal+1
- sbc memPutVals+1
- sta memPutVals+1
- cmp #0
- bne +
- cpx #128
- bcc ++
- - lda #errBranchTooFar
- jmp error
- + cmp #$ff
- bne -
- cpx #128
- bcc -
- + lda #1
- ldx varPtr+0
- ldy varPtr+1
- jsr memPut
- rts
-
- fillMhMsg1 = *
- db "fill memory hole: address=$"
- db 0
- fillMhMsg2 = *
- db ", value="
- db 0
- fillMhMsg3 = *
- db "), holeType=$"
- db 0
-
- ;======== program memory storage ========
-
- memInit = * ;( )
- lda #aceMemNull
- sta memBufPtr+3
- ldx #0
- lda #aceMemNull
- - sta memPtrTable,x
- inx
- bne -
- rts
-
- memPutSave : buf 2
-
- memPut = * ;( .XY=addr,.A=byteCount, memPutVals )
- sta memPutCount
- sty memPutPage
- ldy #0
-
- memPutNext = *
- lda memBufPtr+3
- cmp #aceMemNull
- beq memPutMiss
- lda memPutPage
- cmp memBufPage
- bne memPutMiss
- lda memPutVals,y
- sta memBuf,x
- inx
- bne +
- inc memPutPage
- + iny
- cpy memPutCount
- bcc memPutNext
- rts
-
- memPutMiss = *
- stx memPutSave+0
- sty memPutSave+1
- jsr memFlushBuf
- jsr memFetchBuf
- ldx memPutSave+0
- ldy memPutSave+1
- jmp memPutNext
-
- memFlushBuf = *
- lda #<memBuf
- ldy #>memBuf
- sta zp+0
- sty zp+1
- ;** flush old page
- ldx #3
- - lda memBufPtr,x
- sta mp,x
- dex
- bpl -
- lda mp+3
- cmp #aceMemNull
- beq +
- lda memBufPage
- and #$03
- clc
- adc mp+1
- sta mp+1
- lda #0
- ldy #1
- jsr stash
- + rts
-
- memFetchBuf = * ;( memPutPage )
- lda #<memBuf
- ldy #>memBuf
- sta zp+0
- sty zp+1
- lda memPutPage
- sta memBufPage
- and #%11111100
- tay
- ldx #0
- - lda memPtrTable,y
- sta memBufPtr,x
- sta mp,x
- iny
- inx
- cpx #4
- bcc -
- lda mp+3
- cmp #aceMemNull
- beq memFetchBufNew
- lda memPutPage
- and #$03
- clc
- adc mp+1
- sta mp+1
- lda #0
- ldy #1
- jsr fetch
- rts
-
- memFetchBufNew = *
- lda #0
- ldy #4
- jsr malloc
- lda memBufPage
- and #%11111100
- tay
- ldx #0
- - lda mp,x
- sta memPtrTable,y
- sta memBufPtr,x
- iny
- inx
- cpx #4
- bcc -
- rts
-
- memSaveAddr : buf 2
- memSaveFd : buf 1
- memSaveLen : buf 1 ;0==256
-
- memSave = * ;( .A=fd, .XY=from, address=to)
- sta memSaveFd
- stx memSaveAddr+0
- sty memSaveAddr+1
- jsr memFlushBuf
-
- memSaveNext = *
- lda memSaveAddr+0
- cmp address+0
- lda memSaveAddr+1
- sbc address+1
- bcc +
- rts
- + lda memSaveAddr+1
- sta memPutPage
- jsr memFetchBuf ;sets (zp)
- lda #0
- sta memSaveLen
- ;** set bottom
- lda memSaveAddr+0
- beq ++
- clc
- lda zp+0
- adc memSaveAddr+0
- sta zp+0
- bcc +
- inc zp+1
- + sec
- lda memSaveLen
- sbc memSaveAddr+0
- sta memSaveLen
- ;** set top
- + lda memSaveAddr+1
- cmp address+1
- bcc +
- sec
- lda #0
- sbc address+0
- tax
- lda memSaveLen
- stx memSaveLen
- sec
- sbc memSaveLen
- sta memSaveLen
- ;** save the page
- + ldy #0
- lda memSaveLen
- bne +
- iny
- + ldx memSaveFd
- jsr write
- lda memSaveLen
- beq +
- clc
- adc memSaveAddr+0
- sta memSaveAddr+0
- bcc ++
- + inc memSaveAddr+1
- + jmp memSaveNext
-
- recordRelocRef = * ;( .XY=refAddress, .A=valueType )
- rts
-
- ;======== tokenizer ========
-
- ;* fill entire buffer, pad with spaces; .CS=eof
- fillbuf = *
- lda #<sourceBuf
- ldy #>sourceBuf
- sta zp
- sty zp+1
- lda #0
- ldy #1
- sta bufptr
- ldx sourceFcb
- jsr read
- bne +
- sec
- rts
- + cpy #1
- bcc +
- clc
- rts
- + tay
- lda #" "
- - sta sourceBuf,y
- iny
- bne -
- clc
- rts
-
- getNextChar = *
- inc bufptr
- beq +
- - ldy bufptr
- lda sourceBuf,y
- rts
- + jsr fillbuf
- bcc -
- lda #chrEOF
- rts
-
- eatWhitespace = * ;() : .A=NextChar
- lda prevChar
- cmp #" "
- beq +
- cmp #chrTab
- beq +
- rts
- + ldy bufptr
- - iny
- beq +
- eatWhCont = *
- lda sourceBuf,y
- cmp #" "
- beq -
- cmp #chrTab
- beq -
- sty bufptr
- rts
- + jsr fillbuf
- bcs +
- ldy #0
- jmp eatWhCont
- + lda #chrEOF
- rts
-
- ;*** token dispatch ***
- ;ret: .X=tokenIdentifier, .A=nextChar, .Y=strlen, stringLen, stringBuf
- ; .X=tokenNumber, .Y=numlen, number
- ; .X=tokenString, .A=firstChar,.Y=strlen, stringLen, stringBuf
- ; .X=tokenSpecial, .A=char
-
- tokDebugSave : buf 3
-
- getToken = *
- lda newCol
- sta sourceCol
- lda newLine+0
- sta sourceLine+0
- lda newLine+1
- sta sourceLine+1
- lda newLine+2
- sta sourceLine+2
- lda newLine+3
- sta sourceLine+3
- bit debug
- bpl getTokenReal
- jsr getTokenReal
- sta tokDebugSave+0
- stx tokDebugSave+1
- sty tokDebugSave+2
- jsr dispToken
- lda tokDebugSave+0
- ldx tokDebugSave+1
- ldy tokDebugSave+2
- rts
-
- getTokenReal = *
- lda prevChar
- cmp #" "
- bne +
- - jsr eatWhitespace
- + cmp #chrTab
- beq -
- cmp #"@"
- bcc +
- jmp getIdentifier
- + cmp #"'"
- bcc cmpMore1
- bne +
- jmp getString
- + cmp #"0"
- bcc tokSpecial
- cmp #":"
- bcs +
-
- tokNum = *
- jmp getNumber
-
- + cmp #";"
- bne +
- jmp eatComment
-
- tokSpecial = *
- jmp getSpecialToken
-
- cmpMore1 = *
- cmp #"$"
- bcc +
- beq tokNum
- cmp #"%"
- beq tokNum
- jmp getSpecialToken
-
- + cmp #chrQuote
- bne tokSpecial
- jmp getString
-
- ;*** comment ***
-
- eatComment = *
- ldy bufptr
- - iny
- beq +
-
- commentChar = *
- lda sourceBuf,y
- cmp #chrCR
- bne -
- sty bufptr
- jmp getSpecialToken
- + jsr fillbuf
- bcs +
- ldy #0
- beq commentChar
- + lda #chrEOF
- jmp getSpecialToken
-
- ;*** special ***
-
- getSpecialToken = *
- cmp #chrCR
- bne +
- inc newLine+0
- bne +
- inc newLine+1
- bne +
- inc newLine+2
- bne +
- inc newLine+3
- + cmp #chrEOF
- bne +
- sta prevChar
- sta tokenChar
- ldx #tokenEOF
- stx tokenType
- rts
- + pha
- jsr getNextChar
- sta prevChar
- sta tokenNextChar
- pla
- ldx #tokenSpecial
- stx tokenType
- sta tokenChar
- rts
-
- ;*** identifier ***
-
- getIdentifier = *
- sta stringBuf
- ldy #1
- sty stringLen
- - jsr getNextChar
- cmp #"@"
- bcc identExit
-
- identGoodChar = *
- ldy stringLen
- sta stringBuf,y
- inc stringLen
- cpy #240
- bcc -
- sta prevChar
- lda #errIdentTooLong
- jmp error
-
- identExit = *
- cmp #"."
- beq identGoodChar
- cmp #"_"
- beq identGoodChar
- cmp #"0"
- bcc +
- cmp #":"
- bcc identGoodChar
- + cmp #" "
- bne +
- - sta prevChar
- jsr eatWhitespace
- + cmp #chrTab
- beq -
- sta prevChar
- lda #0
- ldy stringLen
- sta stringBuf,y
- lda prevChar
- ldy stringLen
- ldx #tokenIdentifier
- stx tokenType
- cmp #";"
- bne +
- lda #chrCR
- + sta tokenNextChar
- rts
-
- ;*** string ***
-
- getString = *
- sta strDelimit
- lda #0
- sta stringLen
- - jsr getNextChar
- sta prevChar
- cmp #chrEOF
- beq strEof
- cmp strDelimit
- beq strExit
- cmp #chrCR
- beq strEof
- cmp #"\\"
- beq strEsc
- getStrPut = *
- ldy stringLen
- sta stringBuf,y
- inc stringLen
- lda stringLen
- cmp #241
- bcc -
- sta prevChar
- lda #errStringTooLong
- jmp error
-
- strEsc = *
- jsr getNextChar
- cmp #chrCR
- beq strEof
- cmp #chrEOF
- beq strEof
- ldx #strEscCharEnd-strEscChar-1
- - cmp strEscChar,x
- beq +
- dex
- bpl -
- jmp getStrPut
- + lda strEscTrans,x
- jmp getStrPut
-
- strEscChar = *
- db "\\nbtraz'e0q"
- db chrQuote
- strEscCharEnd = *
- strEscTrans = *
- db 92,13,20,9,10,7,0,39,27,0,34,34
-
- strEof = *
- lda #errNoCloseQuote
- jmp error
-
- strExit = *
- jsr getNextChar
- sta prevChar
- lda #0 ;but may contain \0
- ldy stringLen
- sta stringBuf,y
- lda stringBuf+0
- ldx #tokenString
- stx tokenType
- sta tokenChar
- rts
-
- getNumber = *
- pha
- ldx #3
- lda #0
- - sta number,x
- dex
- bpl -
- pla
- ldx #16
- cmp #"$"
- beq +
- ldx #2
- cmp #"%"
- beq +
- ldx #10
- stx numBase
- bne gotNextDigit
- + stx numBase
- jsr getNextChar
- sta prevChar
- jsr checkDigit
- bcc +
- lda #errBadNumber
- jmp error
- + txa
- jmp gotNextDigit
-
- nextDigit = *
- jsr getNextChar
- sta prevChar
- cmp #"_"
- beq nextDigit
- gotNextDigit = *
- jsr checkDigit
- bcs getNumExit
- pha
- jsr shiftNumber
- bcs overflowExitPla
- pla
- clc
- adc number
- sta number
- bcc +
- inc number+1
- bne +
- inc number+2
- bne +
- inc number+3
- beq overflowExit
- + jmp nextDigit
-
- overflowExitPla = *
- pla
- overflowExit = *
- lda #errNumOverflow
- jmp error
-
- getNumExit = *
- ldy #3
- - lda number,y
- beq +
- dey
- bpl -
- iny
- + iny
- sty tokenNumBytes
- ldx #tokenNumber
- stx tokenType
- rts
-
- checkDigit = * ;( .A=asciiDigit ) : .A=binDigit, .X=asciiDigit, .CC=ok
- tax
- cmp #"0"
- bcc checkBad
- cmp #"9"+1
- bcc checkAnd
- cmp #"a"
- bcc checkBad
- cmp #"f"+1
- bcc +
- cmp #"A"
- bcc checkBad
- cmp #"F"+1
- bcs checkBad
- + sec
- sbc #7
- checkAnd = *
- and #$0f
- cmp numBase
- rts
- checkBad = *
- sec
- rts
-
- shiftNumber = *
- lda numBase
- cmp #10
- bne +
- ldx #3
- - lda number,x
- sta numSave,x
- dex
- bpl -
- ldx #2
- jsr rollNumber
- jsr addNumber
- ldx #1
- jsr rollNumber
- rts
- + ldx #1
- cmp #16
- bne +
- ldx #4
- + jsr rollNumber
- rts
-
- rollNumber = * ;( .X=times )
- asl number
- rol number+1
- rol number+2
- rol number+3
- bcs +
- dex
- bne rollNumber
- rts
- + pla
- pla
- sec
- rts
-
- addNumber = *
- ldx #0
- clc
- - lda number,x
- adc numSave,x
- sta number,x
- inx
- txa
- and #$03
- bne -
- bcs +
- rts
- + pla
- pla
- sec
- rts
-
- ;======== debugging token display routines ========
-
- dispToken = * ;( .tokenType )
- ldx tokenType
- cpx #tokenIdentifier
- beq dispIdentifier
- cpx #tokenString
- beq dispString
- cpx #tokenSpecial
- bne +
- jmp dispSpecial
- + cpx #tokenNumber
- bne +
- jmp dispNumber
- + rts
-
- dispIdentifier = *
- lda #"i"
- jsr putchar
- lda #":"
- jsr putchar
- jsr showStr
- lda #","
- jsr putchar
- jsr hash
- lda #0
- sta number+2
- sta number+3
- lda hashVal+0
- ldy hashVal+1
- sta number+0
- sty number+1
- ldx #number
- jsr putnum
- lda #","
- jsr putchar
- sec
- lda hashPtr+0
- sbc #<identHashTable
- sta number+0
- lda hashPtr+1
- sbc #>identHashTable
- sta number+1
- lsr number+1
- ror number+0
- lsr number+1
- ror number+0
- ldx #number
- jsr putnum
- lda #","
- jsr putchar
- lda tokenNextChar
- showChar = *
- cmp #chrCR
- bne +
- lda #"\\"
- jsr putchar
- lda #"n"
- + jsr putchar
- showCR = *
- lda #chrCR
- jsr putchar
- rts
-
- dispString = *
- lda #"s"
- jsr putchar
- lda #":"
- jsr putchar
- jsr showStr
- jmp showCR
-
- showStr = *
- lda #<stringBuf
- ldy #>stringBuf
- sta zp+0
- sty zp+1
- lda stringLen
- ldy #0
- ldx #stdout
- jsr write
- rts
-
- dispSpecial = *
- lda #"c"
- jsr putchar
- lda #":"
- jsr putchar
- lda tokenChar
- jmp showChar
-
- dispNumber = *
- lda #"n"
- jsr putchar
- lda #":"
- jsr putchar
- lda #<stringBuf
- ldy #>stringBuf
- sta zp+0
- sty zp+1
- ldx #number
- lda #1
- jsr utoa
- sty stringLen
- jsr showStr
- jmp showCR
-
- ;=== dynamic memory routines ===
-
- mallocWork = memWork ;(16) ;required work area; defined earlier
-
- mallocHead : buf 4
- tpaFreeFirst : buf 1
- tpaFreeMin : buf 1
- tpaFreePages : buf 1
- tpaAreaStart : buf 1
- tpaAreaEnd : buf 1
-
- ;*** mallocInit()
-
- mallocInit = *
- lda #aceMemNull
- sta mallocHead+3
- ldx #0
- lda #$ff
- - sta tpaFreemap,x
- inx
- bne -
- ldx #>bssEnd
- lda #<bssEnd
- beq +
- inx
- + stx tpaFreeFirst
- stx tpaAreaStart
- ldx aceMemTop+1
- stx mallocWork
- stx tpaAreaEnd
- txa
- sec
- sbc tpaFreeFirst
- bcs +
- lda #0
- + sta tpaFreePages
- clc
- adc #1
- sta tpaFreeMin
- ldx tpaFreeFirst
- cpx mallocWork
- bcs +
- lda #$00
- - sta tpaFreemap,x
- inx
- cpx mallocWork
- bcc -
- + rts
-
- libPages : buf 1
-
- libPageAlloc = * ;( .A=pages ) : [mp]
- sta libPages
- ldx #$00
- ldy #aceMemInternal-1
- jsr pagealloc
- bcs +
- rts
- + jsr tpaPageAlloc
- bcs +
- rts
- + lda libPages
- ldx #aceMemInternal
- ldy #$ff
- jsr pagealloc
- bcs +
- rts
- + sec
- ;rts
- ;lda #<nomemMsg
- ;ldy #>nomemMsg
- ;jsr eputs
- lda #errInsufficientMemory
- jmp error
-
- ;nomemMsg = *
- ;db chrCR
- ;db "Insufficient memory, aborting."
- ;db chrCR,0
-
- newmax : buf 1
-
- tpaPageAlloc = * ;( libPages ) : [mp]
- lda libPages
- cmp tpaFreeMin
- bcs tpaFreemapFull
- ;** first free
- ldx tpaFreeFirst
- lda tpaFreemap,x
- beq ++
- - inx
- beq tpaFreemapFull
- lda tpaFreemap,x
- bne -
- stx tpaFreeFirst
- jmp ++
- tpaFreemapFull = *
- lda libPages
- cmp tpaFreeMin
- bcs +
- sta tpaFreeMin
- + sec
- rts
-
- ;** search
- + dex
- - ldy libPages
- - inx
- beq tpaFreemapFull
- lda tpaFreemap,x
- bne --
- dey
- bne -
-
- ;** allocate
- stx newmax
- ldy libPages
- lda #$41
- - sta tpaFreemap,x
- dex
- dey
- bne -
- inx
- cpx tpaFreeFirst
- bne +
- ldy newmax
- iny
- sty tpaFreeFirst
- + sec
- lda tpaFreePages
- sbc libPages
- sta tpaFreePages
- lda #0
- ldy #aceMemInternal
- sta mp+0
- stx mp+1
- sta mp+2
- sty mp+3
- clc
- rts
-
- mallocLenSave : buf 3
-
- malloc = *
- quickMalloc = *
- sta mallocLenSave+0
- sty mallocLenSave+1
- jsr libMalloc
- bcs +
- rts
- + ldx mallocLenSave+1
- lda mallocLenSave+0
- beq +
- inx
- + txa
- cpx #>1024
- bcs +
- ldx #>1024
- + txa
- sta mallocLenSave+2
- jsr libPageAlloc
- bcc +
- rts
- + lda #0
- ldy mallocLenSave+2
- jsr free
- lda mallocLenSave+0
- ldy mallocLenSave+1
- jmp malloc
-
- ;*** malloc( .AY=Bytes ) : [mp]=FarPointer
-
- mallocMemNextPtr = mallocWork+0 ;(4)
- mallocMemLength = mallocWork+4 ;(2)
- mallocLength = mallocWork+6 ;(2)
- mallocQ = mallocWork+8 ;(4)
-
- libMalloc = *
- clc
- adc #7
- bcc +
- iny
- + and #$f8
- sta mallocLength
- sty mallocLength+1
- ldx #3
- - lda mallocHead,x
- sta mp,x
- lda #aceMemNull
- sta mallocQ,x
- dex
- bpl -
-
- mallocLook = *
- lda mp+3
- cmp #aceMemNull
- bne +
-
- mallocErrorExit = *
- lda #aceMemNull
- sta mp+3
- lda #aceErrInsufficientMemory
- sta errno
- sec
- rts
-
- + ldx #mallocMemNextPtr
- ldy #6
- jsr zpload
- lda mallocMemLength
- cmp mallocLength
- lda mallocMemLength+1
- sbc mallocLength+1
- bcs mallocGotBlock
- ldx #3
- - lda mp,x
- sta mallocQ,x
- lda mallocMemNextPtr,x
- sta mp,x
- dex
- bpl -
- jmp mallocLook
-
- mallocGotBlock = *
- lda mallocMemLength
- cmp mallocLength
- bne +
- lda mallocMemLength+1
- sbc mallocLength+1
- beq mallocTakeWholeBlock
- + sec
- lda mallocMemLength
- sbc mallocLength
- sta mallocMemLength
- lda mallocMemLength+1
- sbc mallocLength+1
- sta mallocMemLength+1
- ldx #mallocMemNextPtr
- ldy #6
- jsr zpstore
- clc
- lda mp+0
- adc mallocMemLength
- sta mp+0
- lda mp+1
- adc mallocMemLength+1
- sta mp+1
- clc
- rts
-
- mallocTakeWholeBlock = *
- lda mallocQ+3
- cmp #aceMemNull
- bne +
- ldx #3
- - lda mallocMemNextPtr,x
- sta mallocHead,x
- dex
- bpl -
- clc
- rts
- + ldx #3
- - lda mp,x
- ldy mallocQ,x
- sta mallocQ,x
- sty mp,x
- dex
- bpl -
- ldx #mallocMemNextPtr
- ldy #4
- jsr zpstore
- ldx #3
- - lda mallocQ,x
- sta mp,x
- dex
- bpl -
- clc
- rts
-
- ;*** free( [mp]=FarPointer, .AY=Length ) {alters [mp]}
-
- freeMemNextPtr = mallocWork+0 ;(4)
- freeMemLength = mallocWork+4 ;(2)
- freeLength = mallocWork+6 ;(2)
- freeNewPtr = mallocWork+8 ;(4)
- freeQ = mallocWork+12 ;(4)
-
- free = *
- clc
- adc #7
- bcc +
- iny
- + and #$f8
- sta freeLength+0
- sty freeLength+1
- ldx #3
- - lda mp,x
- sta freeNewPtr,x
- lda mallocHead,x
- sta mp,x
- lda #aceMemNull
- sta freeQ,x
- dex
- bpl -
-
- freeSearchLoop = *
- lda mp+3
- cmp #aceMemNull
- beq freeCoalesceQandNew
- lda mp+0
- cmp freeNewPtr+0
- lda mp+1
- sbc freeNewPtr+1
- lda mp+2
- sbc freeNewPtr+2
- lda mp+3
- sbc freeNewPtr+3
- bcs freeCoalesceQandNew
- + ldx #freeMemNextPtr
- ldy #4
- jsr zpload
- ldx #3
- - lda mp,x
- sta freeQ,x
- lda freeMemNextPtr,x
- sta mp,x
- dex
- bpl -
- bmi freeSearchLoop
-
- freeCoalesceQandNew = *
- ldx #3
- - lda freeQ,x
- sta mp,x
- dex
- bpl -
- lda mp+3
- cmp #aceMemNull
- bne +
- ;** prev is head
- ldx #3
- - lda mallocHead,x
- sta freeMemNextPtr,x
- lda freeNewPtr,x
- sta mallocHead,x
- dex
- bpl -
- lda freeLength+0
- ldy freeLength+1
- sta freeMemLength+0
- sty freeMemLength+1
- jmp freeCoalesceNewAndP
-
- ;** prev is real
- + ldx #freeMemNextPtr
- ldy #6
- jsr zpload
- lda mp+3
- cmp freeNewPtr+3
- bne +
- lda mp+2
- cmp freeNewPtr+2
- bne +
- clc
- lda mp+0
- adc freeMemLength
- tax
- lda mp+1
- adc freeMemLength+1
- cmp freeNewPtr+1
- bne +
- cpx freeNewPtr
- bne +
- ;** prev does coalesce
- clc
- lda freeMemLength
- adc freeLength
- sta freeMemLength
- lda freeMemLength+1
- adc freeLength+1
- sta freeMemLength+1
- ldx #3
- - lda freeQ,x
- sta freeNewPtr,x
- dex
- bpl -
- bmi freeCoalesceNewAndP
-
- ;** prev does not coalesce
- + ldx #freeNewPtr
- ldy #4
- jsr zpstore
- lda freeLength+0
- ldy freeLength+1
- sta freeMemLength+0
- sty freeMemLength+1
-
- freeCoalesceNewAndP = *
- lda freeNewPtr+3
- cmp freeMemNextPtr+3
- bne +
- lda freeNewPtr+2
- cmp freeMemNextPtr+2
- bne +
- clc
- lda freeNewPtr
- adc freeMemLength
- tax
- lda freeNewPtr+1
- adc freeMemLength+1
- cmp freeMemNextPtr+1
- bne +
- cpx freeMemNextPtr
- bne +
-
- ;** new and next coalesce
- ldx #3
- - lda freeMemNextPtr,x
- sta mp,x
- dex
- bpl -
- lda freeMemLength+1
- pha
- lda freeMemLength+0
- pha
- ldx #freeMemNextPtr
- ldy #6
- jsr zpload
- clc
- pla
- adc freeMemLength+0
- sta freeMemLength+0
- pla
- adc freeMemLength+1
- sta freeMemLength+1
-
- + ldx #3
- - lda freeNewPtr,x
- sta mp,x
- dex
- bpl -
- ldx #freeMemNextPtr
- ldy #6
- jsr zpstore
- clc
- rts
-
- ;======== standard library ========
-
- eputs = *
- ldx #stderr
- jmp fputs
- puts = *
- ldx #stdout
- fputs = *
- sta zp+0
- sty zp+1
- fputsZp = *
- ldy #$ff
- - iny
- lda (zp),y
- bne -
- tya
- ldy #0
- jmp write
-
- putchar = *
- ldx #stdout
- putc = *
- sta putcBuffer
- lda #<putcBuffer
- ldy #>putcBuffer
- sta zp+0
- sty zp+1
- lda #1
- ldy #0
- jmp write
- putcBuffer : buf 1
-
- getarg = *
- sty zp+1
- asl
- sta zp+0
- rol zp+1
- clc
- lda aceArgv
- adc zp+0
- sta zp+0
- lda aceArgv+1
- adc zp+1
- sta zp+1
- ldy #0
- lda (zp),y
- tax
- iny
- lda (zp),y
- stx zp+0
- sta zp+1
- lda zp+0
- ldy zp+1
- rts
-
- ;end of file + blank line
-
-
- ;======== bss ========
-
- bss = *
- sourceBuf = bss+0 ;( 256 bytes)
- stringBuf = sourceBuf+256 ;( 256 bytes)
- symBuf = stringBuf+256 ;( 256 bytes)
- symNext = symBuf+0
- symValue = symBuf+4
- symUnresOpnd = symBuf+8
- symType = symBuf+9
- symClass = symBuf+10
- symNameLen = symBuf+11
- symName = symBuf+12
- symHash = symBuf+254
- expTable = symBuf+256 ;( 256 bytes == 15 entries)
- expHoleType = expTable+0
- expLength = expTable+1
- expUnresCnt = expTable+2
- expSrcCol = expTable+3
- expHoleAddr = expTable+4
- expSrcLine = expTable+8
- expSrcFile = expTable+12
- expField = expTable+0
- expOp = expField+0
- expType = expField+1
- expSign = expField+2
- expHiLo = expField+3
- expValue = expField+4
- expNextUnres = expField+8
- expNextOpnd = expField+12
- expReserved = expField+13
- identHashTable = expTable+256 ;(4096 bytes == 1024 entries (ref:hTabPag)
- memPtrTable = identHashTable+4096 ;( 256 bytes == 64 entries)
- memBuf = memPtrTable+256 ;( 256 bytes)
- writeName = memBuf+256 ;( 20 bytes)
- tpaFreemap = writeName+20 ;( 256 bytes)
- bssEnd = tpaFreemap+256