1477 lines
35 KiB
NASM
1477 lines
35 KiB
NASM
;Gidubba: A simple line editor
|
||
|
||
;***
|
||
|
||
;Save a substitute at the start address
|
||
load r0, sub
|
||
store buffer + 100, r0
|
||
|
||
;***
|
||
|
||
;Command prompt
|
||
cmdp: load r0, prompt
|
||
store ffff, r0
|
||
load r0, space
|
||
store ffff, r0
|
||
|
||
;Input the command
|
||
cleq r0, r0, input
|
||
|
||
;Check for escape
|
||
load r0, esc
|
||
breq r0, r2, cmdp
|
||
|
||
;Initialise the command and argument
|
||
xor r0, r0
|
||
store cmd, r0
|
||
store argf1, r0
|
||
store argf2, r0
|
||
load r0, zero
|
||
store arg1, r0
|
||
store arg1 + 1, r0
|
||
store arg1 + 2, r0
|
||
store arg1 + 3, r0
|
||
store arg2, r0
|
||
store arg2 + 1, r0
|
||
|
||
;Parse the command and its first argument
|
||
;Command
|
||
load r0, buffer
|
||
store cmd, r0
|
||
;Load carriage return and hash
|
||
load r1, cr
|
||
load r2, hash
|
||
;Check for no command
|
||
breq r0, r1, cmdp
|
||
;First digit
|
||
load r0, buffer + 1
|
||
breq r0, r1, chkcmd
|
||
load r3, const1
|
||
store argf1, r3
|
||
breq r0, r2, hsharg
|
||
load r3, arg1d2 + 1
|
||
store arg2d1 + 1, r3
|
||
load r3, arg1d2 + 2
|
||
store arg2d1 + 2, r3
|
||
load r3, comma
|
||
breq r0, r3, 2ndarg
|
||
store arg1 + 3, r0
|
||
;Second digit
|
||
arg1d2: load r0, buffer + 2
|
||
breq r0, r1, getarg
|
||
load r3, arg1d3 + 1
|
||
store arg2d1 + 1, r3
|
||
load r3, arg1d3 + 2
|
||
store arg2d1 + 2, r3
|
||
load r3, comma
|
||
breq r0, r3, 2ndarg
|
||
load r2, arg1 + 3
|
||
store arg1 + 2, r2
|
||
store arg1 + 3, r0
|
||
;Third digit
|
||
arg1d3: load r0, buffer + 3
|
||
breq r0, r1, getarg
|
||
load r3, arg1d4 + 1
|
||
store arg2d1 + 1, r3
|
||
load r3, arg1d4 + 2
|
||
store arg2d1 + 2, r3
|
||
load r3, comma
|
||
breq r0, r3, 2ndarg
|
||
load r2, arg1 + 2
|
||
store arg1 + 1, r2
|
||
load r2, arg1 + 3
|
||
store arg1 + 2, r2
|
||
store arg1 + 3, r0
|
||
;Fourth digit
|
||
arg1d4: load r0, buffer + 4
|
||
breq r0, r1, getarg
|
||
load r3, arg1d5 + 1
|
||
store arg2d1 + 1, r3
|
||
load r3, arg1d5 + 2
|
||
store arg2d1 + 2, r3
|
||
load r3, comma
|
||
breq r0, r3, 2ndarg
|
||
load r2, arg1 + 1
|
||
store arg1, r2
|
||
load r2, arg1 + 2
|
||
store arg1 + 1, r2
|
||
load r2, arg1 + 3
|
||
store arg1 + 2, r2
|
||
store arg1 + 3, r0
|
||
;Check for command end
|
||
load r0, arg1d5 + 1
|
||
load r1, arg1d5 + 2
|
||
cleq r0, r0, incdw
|
||
store arg2d1 + 1, r0
|
||
store arg2d1 + 2, r1
|
||
load r1, cr
|
||
arg1d5: load r0, buffer + 5
|
||
breq r0, r1, getarg
|
||
load r3, comma
|
||
breq r0, r3, 2ndarg
|
||
breq r0, r0, cmderr
|
||
|
||
;Parse the second argument
|
||
;Set the addresses
|
||
2ndarg: load r0, arg2d1 + 1
|
||
load r1, arg2d1 + 2
|
||
cleq r0, r0, incdw
|
||
store arg2d2 + 1, r0
|
||
store arg2d2 + 2, r1
|
||
cleq r0, r0, incdw
|
||
store arg2d3 + 1, r0
|
||
store arg2d3 + 2, r1
|
||
;Load carriage return
|
||
load r1, cr
|
||
;First digit
|
||
arg2d1: load r0, 0
|
||
breq r0, r1, chkcmd
|
||
load r3, const1
|
||
store argf2, r3
|
||
store arg2 + 1, r0
|
||
;Second digit
|
||
arg2d2: load r0, 0
|
||
breq r0, r1, getarg
|
||
load r2, arg2 + 1
|
||
store arg2, r2
|
||
store arg2 + 1, r0
|
||
;Check for command end
|
||
arg2d3: load r0, 0
|
||
breq r0, r1, getarg
|
||
breq r0, r0, cmderr
|
||
|
||
;Hash is a shortcut for FFFF
|
||
;Check for command end
|
||
hsharg: load r0, buffer + 2
|
||
brneq r0, r1, cmderr
|
||
;Save FFFF
|
||
xor r0, r0
|
||
nand r0, r0
|
||
store target, r0
|
||
store target + 1, r0
|
||
breq r0, r0, chkcmd
|
||
|
||
;Get the value of the first argument
|
||
;First digit
|
||
getarg: load r0, arg1
|
||
cleq r0, r0, hex2n
|
||
load r1, qmark
|
||
breq r0, r1, cmderr
|
||
xor r2, r2
|
||
xor r2, r0
|
||
shl r2
|
||
shl r2
|
||
shl r2
|
||
shl r2
|
||
;Second digit
|
||
load r0, arg1 + 1
|
||
cleq r0, r0, hex2n
|
||
load r1, qmark
|
||
breq r0, r1, cmderr
|
||
;Combine and store the first and second digits
|
||
or r0, r2
|
||
store target, r0
|
||
;Third digit
|
||
load r0, arg1 + 2
|
||
cleq r0, r0, hex2n
|
||
load r1, qmark
|
||
breq r0, r1, cmderr
|
||
xor r2, r2
|
||
xor r2, r0
|
||
shl r2
|
||
shl r2
|
||
shl r2
|
||
shl r2
|
||
;Fourth digit
|
||
load r0, arg1 + 3
|
||
cleq r0, r0, hex2n
|
||
load r1, qmark
|
||
breq r0, r1, cmderr
|
||
;Combine and store the third and fourth digits
|
||
or r0, r2
|
||
store target + 1, r0
|
||
|
||
;Get the value of the second argument
|
||
;First digit
|
||
load r0, arg2
|
||
cleq r0, r0, hex2n
|
||
load r1, qmark
|
||
breq r0, r1, cmderr
|
||
xor r2, r2
|
||
xor r2, r0
|
||
shl r2
|
||
shl r2
|
||
shl r2
|
||
shl r2
|
||
;Second digit
|
||
load r0, arg2 + 1
|
||
cleq r0, r0, hex2n
|
||
load r1, qmark
|
||
breq r0, r1, cmderr
|
||
;Combine and store the first and second digits
|
||
or r0, r2
|
||
store count, r0
|
||
|
||
;Check for commands
|
||
;Load the command
|
||
chkcmd: load r0, cmd
|
||
;Check for no argument
|
||
load r2, argf1
|
||
xor r3, r3
|
||
breq r2, r3, cnarg
|
||
;Check for single argument
|
||
load r2, argf2
|
||
xor r3, r3
|
||
breq r2, r3, onearg
|
||
;Copy to mark
|
||
load r1, ucc
|
||
breq r0, r1, copy
|
||
load r1, lcc
|
||
breq r0, r1, copy
|
||
;Delete
|
||
load r1, ucd
|
||
breq r0, r1, delete
|
||
load r1, lcd
|
||
breq r0, r1, delete
|
||
;List
|
||
load r1, ucl
|
||
breq r0, r1, list
|
||
load r1, lcl
|
||
breq r0, r1, list
|
||
;Branch to error
|
||
breq r0, r0, cmderr
|
||
;Insert
|
||
onearg: load r1, uci
|
||
breq r0, r1, insln
|
||
load r1, lci
|
||
breq r0, r1, insln
|
||
;Set a mark
|
||
load r1, ucs
|
||
breq r0, r1, setmrk
|
||
load r1, lcs
|
||
breq r0, r1, setmrk
|
||
;Branch to error
|
||
breq r0, r0, cmderr
|
||
;Print
|
||
cnarg: load r1, ucp
|
||
breq r0, r1, print
|
||
load r1, lcp
|
||
breq r0, r1, print
|
||
;Write to tape
|
||
load r1, ucw
|
||
breq r0, r1, write
|
||
load r1, lcw
|
||
breq r0, r1, write
|
||
;Read from tape
|
||
load r1, ucr
|
||
breq r0, r1, read
|
||
load r1, lcr
|
||
breq r0, r1, read
|
||
;Halt
|
||
load r1, uch
|
||
breq r0, r1, end
|
||
load r1, lch
|
||
breq r0, r1, end
|
||
|
||
;Print an error and return to the command prompt
|
||
cmderr: cleq r0, r0, error
|
||
breq r0, r0, cmdp
|
||
|
||
;***
|
||
|
||
;Insert a line
|
||
|
||
;Find the argument line in the save and store its number
|
||
insln: cleq r0, r0, fend
|
||
|
||
;Print a line number prompt
|
||
instrt: cleq r0, r0, prnln
|
||
|
||
;Input the line
|
||
cleq r0, r0, input
|
||
|
||
;Check for control characters
|
||
;Escape
|
||
load r0, esc
|
||
breq r0, r2, instrt
|
||
;Substitute
|
||
load r0, sub
|
||
breq r0, r2, cmdp
|
||
|
||
;Increment the line number
|
||
;Load the number
|
||
load r0, lnnum
|
||
load r1, lnnum + 1
|
||
;Increment
|
||
cleq r0, r0, incdw
|
||
;Store the number
|
||
store target, r0
|
||
store target + 1, r1
|
||
|
||
;Store the save address
|
||
;High byte
|
||
load r3, sublod + 1
|
||
store subchk + 1, r3
|
||
store cmpadr, r3
|
||
;Low byte
|
||
load r0, sublod + 2
|
||
store subchk + 2, r0
|
||
store cmpadr + 1, r0
|
||
|
||
;Save the line
|
||
cleq r0, r0, subchk
|
||
|
||
;Insert the next line
|
||
breq r0, r0, insln
|
||
|
||
;***
|
||
|
||
;Set a mark for copying
|
||
setmrk: load r0, target
|
||
store mark, r0
|
||
load r0, target + 1
|
||
store mark + 1, r0
|
||
breq r0, r0, cmdp
|
||
|
||
;***
|
||
|
||
;Copy to mark
|
||
|
||
;Placeholder
|
||
copy: breq r0, r0, cmdp
|
||
|
||
;***
|
||
|
||
;Delete a line
|
||
|
||
;Check the counter
|
||
delete: xor r0, r0
|
||
load r1, count
|
||
breq r0, r1, cmdp
|
||
|
||
;Find the argument line in the save and store its number
|
||
cleq r0, r0, fend
|
||
|
||
;Get the save address of the line
|
||
;High byte
|
||
load r0, sublod + 1
|
||
store stomov + 1, r0
|
||
store dchend + 1, r0
|
||
;Low byte
|
||
load r0, sublod + 2
|
||
store stomov + 2, r0
|
||
store dchend + 2, r0
|
||
|
||
;Check for the save end
|
||
dchend: load r0, 0
|
||
load r1, sub
|
||
breq r0, r1, cmdp
|
||
|
||
;Increment the line number
|
||
;Load the number
|
||
load r0, target
|
||
load r1, target + 1
|
||
;Increment
|
||
cleq r0, r0, incdw
|
||
;Store the number
|
||
store target, r0
|
||
store target + 1, r1
|
||
|
||
;Find the next line in the save and store its number
|
||
cleq r0, r0, fend
|
||
|
||
;Get the save address of the line
|
||
;High byte
|
||
load r0, sublod + 1
|
||
store lodmov + 1, r0
|
||
;Low byte
|
||
load r0, sublod + 2
|
||
store lodmov + 2, r0
|
||
|
||
;Move the remainder of the text back
|
||
lodmov: load r0, 0
|
||
stomov: store 0, r0
|
||
|
||
;Check for the save end
|
||
load r1, sub
|
||
breq r0, r1, delend
|
||
|
||
;Increment the first save address
|
||
;Load the address
|
||
load r0, stomov + 1
|
||
load r1, stomov + 2
|
||
;Increment
|
||
cleq r0, r0, incdw
|
||
;Store the address
|
||
store stomov + 1, r0
|
||
store stomov + 2, r1
|
||
|
||
;Increment the second save address
|
||
;Load the address
|
||
load r0, lodmov + 1
|
||
load r1, lodmov + 2
|
||
;Increment
|
||
cleq r0, r0, incdw
|
||
;Store the address
|
||
store lodmov + 1, r0
|
||
store lodmov + 2, r1
|
||
|
||
;Move the next character
|
||
breq r0, r0, lodmov
|
||
|
||
;Loop
|
||
;Decrement the counter
|
||
delend: load r0, count
|
||
load r2, cstff
|
||
cleq r0, r0, sum
|
||
store count, r0
|
||
;Decrement the line number
|
||
load r0, target
|
||
load r1, target + 1
|
||
cleq r0, r0, decdw
|
||
store target, r0
|
||
store target + 1, r1
|
||
;Loop
|
||
breq r0, r0, delete
|
||
|
||
;***
|
||
|
||
;List a line
|
||
|
||
;Check the counter
|
||
list: xor r0, r0
|
||
load r1, count
|
||
breq r0, r1, cmdp
|
||
|
||
;Find the argument line in the save and store its number
|
||
cleq r0, r0, fend
|
||
|
||
;Get the save address of the line
|
||
;High byte
|
||
load r0, sublod + 1
|
||
store chlist + 1, r0
|
||
store lchend + 1, r0
|
||
;Low byte
|
||
load r0, sublod + 2
|
||
store chlist + 2, r0
|
||
store lchend + 2, r0
|
||
|
||
;Check for the save end
|
||
lchend: load r0, 0
|
||
load r1, sub
|
||
breq r0, r1, cmdp
|
||
|
||
;Print a line number prompt
|
||
cleq r0, r0, prnln
|
||
|
||
;Load a character from the save
|
||
chlist: load r1, 0
|
||
|
||
;Check for the save end
|
||
load r2, sub
|
||
breq r1, r2, prnwln
|
||
|
||
;Print the character
|
||
store ffff, r1
|
||
|
||
;Check for the line end
|
||
load r2, lf
|
||
breq r1, r2, lstend
|
||
|
||
;Increment the save address
|
||
;Load the address
|
||
load r0, chlist + 1
|
||
load r1, chlist + 2
|
||
;Increment
|
||
cleq r0, r0, incdw
|
||
;Store the address
|
||
store chlist + 1, r0
|
||
store chlist + 2, r1
|
||
|
||
;Print the next character
|
||
breq r0, r0, chlist
|
||
|
||
;Print a newline
|
||
prnwln: cleq r0, r0, newln
|
||
|
||
;Loop
|
||
;Decrement the counter
|
||
lstend: load r0, count
|
||
load r2, cstff
|
||
cleq r0, r0, sum
|
||
store count, r0
|
||
;Increment the line number
|
||
load r0, target
|
||
load r1, target + 1
|
||
cleq r0, r0, incdw
|
||
store target, r0
|
||
store target + 1, r1
|
||
;Loop
|
||
breq r0, r0, list
|
||
|
||
;***
|
||
|
||
;Print the text
|
||
|
||
;Get the printer address
|
||
;High byte
|
||
print: load r0, cstff
|
||
store prwrch + 1, r0
|
||
;Low byte
|
||
load r0, cstfe
|
||
store prwrch + 2, r0
|
||
|
||
;Print
|
||
cleq r0, r0, prwr
|
||
|
||
;Return to the command prompt
|
||
breq r0, r0, cmdp
|
||
|
||
;***
|
||
|
||
;Write the text to tape
|
||
|
||
;Get the tape punch address
|
||
;High byte
|
||
write: load r0, cstff
|
||
store prwrch + 1, r0
|
||
;Low byte
|
||
load r0, cstfd
|
||
store prwrch + 2, r0
|
||
|
||
;Write
|
||
cleq r0, r0, prwr
|
||
|
||
;Write a substitute
|
||
load r0, sub
|
||
store fffd, r0
|
||
|
||
;Return to the command prompt
|
||
breq r0, r0, cmdp
|
||
|
||
;***
|
||
|
||
;Read the text from tape
|
||
|
||
;Get the save start address
|
||
;High byte
|
||
read: load r0, svstrt
|
||
store chrsto + 1, r0
|
||
;Low byte
|
||
load r0, svstrt + 1
|
||
store chrsto + 2, r0
|
||
|
||
;Read a character
|
||
chread: load r1, fffd
|
||
|
||
;Check for empty tape reader
|
||
xor r2, r2
|
||
brneq r1, r2, chrsto
|
||
load r1, sub
|
||
|
||
;Store a character
|
||
chrsto: store buffer + 100, r1
|
||
|
||
;Check for the save end
|
||
load r2, sub
|
||
breq r1, r2, redend
|
||
|
||
;Increment the save address
|
||
;Load the address
|
||
load r0, chrsto + 1
|
||
load r1, chrsto + 2
|
||
;Increment
|
||
cleq r0, r0, incdw
|
||
;Store the address
|
||
store chrsto + 1, r0
|
||
store chrsto + 2, r1
|
||
|
||
;Read the next character
|
||
breq r0, r0, chread
|
||
|
||
;Return to the command prompt
|
||
redend: breq r0, r0, cmdp
|
||
|
||
;***
|
||
|
||
;Halt
|
||
end: halt
|
||
|
||
;***
|
||
|
||
;Print a newline
|
||
newln: load r0, cr
|
||
store ffff, r0
|
||
load r0, lf
|
||
store ffff, r0
|
||
ret
|
||
|
||
;***
|
||
|
||
;Print an error
|
||
error: load r0, space
|
||
store ffff, r0
|
||
store ffff, r0
|
||
load r0, qmark
|
||
store ffff, r0
|
||
cleq r0, r0, newln
|
||
|
||
;***
|
||
|
||
;Add r2 to r0 with the overflow stored in r1
|
||
|
||
;Reset overflow
|
||
sum: xor r1, r1
|
||
store ovrflw, r1
|
||
|
||
;Copy the first argument to r1
|
||
sumlop: xor r1, r1
|
||
xor r1, r0
|
||
|
||
;Calculate the sum and carry and copy the pre-shift carry to r1
|
||
;Sum
|
||
xor r0, r2
|
||
;Carry
|
||
and r2, r1
|
||
;Copy the pre-shift carry
|
||
xor r1, r1
|
||
xor r1, r2
|
||
;Shift the carry
|
||
shl r2
|
||
|
||
;Check for and store overflow if any
|
||
;Check
|
||
rol r1
|
||
breq r1, r2, nvrflw
|
||
;Store
|
||
load r1, const1
|
||
store ovrflw, r1
|
||
|
||
;Check for no carry
|
||
nvrflw: xor r1, r1
|
||
breq r1, r2, sumend
|
||
|
||
;Loop
|
||
breq r0, r0, sumlop
|
||
|
||
;Load overflow and return
|
||
sumend: load r1, ovrflw
|
||
ret
|
||
|
||
;***
|
||
|
||
;Increment a value stored in r0 and r1
|
||
|
||
;Store the high byte in r3
|
||
incdw: xor r3, r3
|
||
xor r3, r0
|
||
|
||
;Load the low byte to r0
|
||
xor r0, r0
|
||
xor r0, r1
|
||
|
||
;Increment the low byte
|
||
load r2, const1
|
||
cleq r0, r0, sum
|
||
|
||
;Load the high byte to r0 and store the low byte in r3
|
||
;Move the high byte to r2
|
||
xor r2, r2
|
||
xor r2, r3
|
||
;Store the low byte to r3
|
||
xor r3, r3
|
||
xor r3, r0
|
||
;Load the high byte to r0
|
||
xor r0, r0
|
||
xor r0, r2
|
||
|
||
;Add the overflow to the high byte
|
||
xor r2, r2
|
||
xor r2, r1
|
||
cleq r0, r0, sum
|
||
|
||
;Load the low byte in r1
|
||
xor r1, r1
|
||
xor r1, r3
|
||
|
||
;Return
|
||
ret
|
||
|
||
;***
|
||
|
||
;Decrement a value stored in r0 and r1
|
||
|
||
;Store the low byte in r3
|
||
decdw: xor r3, r3
|
||
xor r3, r1
|
||
|
||
;Decrement the high byte
|
||
load r2, cstff
|
||
cleq r0, r0, sum
|
||
|
||
;Load the low byte to r0 and store the high byte in r3
|
||
;Move the low byte to r2
|
||
xor r2, r2
|
||
xor r2, r3
|
||
;Store the high byte to r3
|
||
xor r3, r3
|
||
xor r3, r0
|
||
;Load the low byte to r0
|
||
xor r0, r0
|
||
xor r0, r2
|
||
|
||
;Decrement the low byte
|
||
load r2, cstff
|
||
cleq r0, r0, sum
|
||
|
||
;Load the high byte to r0 and store the low byte in r3
|
||
;Move the high byte to r2
|
||
xor r2, r2
|
||
xor r2, r3
|
||
;Store the low byte to r3
|
||
xor r3, r3
|
||
xor r3, r0
|
||
;Load the high byte to r0
|
||
xor r0, r0
|
||
xor r0, r2
|
||
|
||
;Add the overflow to the high byte
|
||
xor r2, r2
|
||
xor r2, r1
|
||
cleq r0, r0, sum
|
||
|
||
;Load the low byte in r1
|
||
xor r1, r1
|
||
xor r1, r3
|
||
|
||
;Return
|
||
ret
|
||
|
||
;***
|
||
|
||
;Get the hexadecimal digit of a nibble
|
||
|
||
;Extract the low nibble
|
||
n2hex: load r1, constf
|
||
and r0, r1
|
||
|
||
;Get the nibble value
|
||
load r1, const0
|
||
breq r0, r1, dgt0
|
||
load r1, const1
|
||
breq r0, r1, dgt1
|
||
load r1, const2
|
||
breq r0, r1, dgt2
|
||
load r1, const3
|
||
breq r0, r1, dgt3
|
||
load r1, const4
|
||
breq r0, r1, dgt4
|
||
load r1, const5
|
||
breq r0, r1, dgt5
|
||
load r1, const6
|
||
breq r0, r1, dgt6
|
||
load r1, const7
|
||
breq r0, r1, dgt7
|
||
load r1, const8
|
||
breq r0, r1, dgt8
|
||
load r1, const9
|
||
breq r0, r1, dgt9
|
||
load r1, consta
|
||
breq r0, r1, dgta
|
||
load r1, constb
|
||
breq r0, r1, dgtb
|
||
load r1, constc
|
||
breq r0, r1, dgtc
|
||
load r1, constd
|
||
breq r0, r1, dgtd
|
||
load r1, conste
|
||
breq r0, r1, dgte
|
||
load r1, constf
|
||
breq r0, r1, dgtf
|
||
|
||
;Load the hexadecimal digit of the nibble
|
||
dgt0: load r0, zero
|
||
breq r0, r0, n2hend
|
||
dgt1: load r0, one
|
||
breq r0, r0, n2hend
|
||
dgt2: load r0, two
|
||
breq r0, r0, n2hend
|
||
dgt3: load r0, three
|
||
breq r0, r0, n2hend
|
||
dgt4: load r0, four
|
||
breq r0, r0, n2hend
|
||
dgt5: load r0, five
|
||
breq r0, r0, n2hend
|
||
dgt6: load r0, six
|
||
breq r0, r0, n2hend
|
||
dgt7: load r0, seven
|
||
breq r0, r0, n2hend
|
||
dgt8: load r0, eight
|
||
breq r0, r0, n2hend
|
||
dgt9: load r0, nine
|
||
breq r0, r0, n2hend
|
||
dgta: load r0, uca
|
||
breq r0, r0, n2hend
|
||
dgtb: load r0, ucb
|
||
breq r0, r0, n2hend
|
||
dgtc: load r0, ucc
|
||
breq r0, r0, n2hend
|
||
dgtd: load r0, ucd
|
||
breq r0, r0, n2hend
|
||
dgte: load r0, uce
|
||
breq r0, r0, n2hend
|
||
dgtf: load r0, ucf
|
||
breq r0, r0, n2hend
|
||
|
||
;Return
|
||
n2hend: ret
|
||
|
||
;***
|
||
|
||
;Get the nibble of a hexadecimal digit
|
||
|
||
;Get the nibble value
|
||
;Numeric digits
|
||
hex2n: load r1, zero
|
||
breq r0, r1, nbl0
|
||
load r1, one
|
||
breq r0, r1, nbl1
|
||
load r1, two
|
||
breq r0, r1, nbl2
|
||
load r1, three
|
||
breq r0, r1, nbl3
|
||
load r1, four
|
||
breq r0, r1, nbl4
|
||
load r1, five
|
||
breq r0, r1, nbl5
|
||
load r1, six
|
||
breq r0, r1, nbl6
|
||
load r1, seven
|
||
breq r0, r1, nbl7
|
||
load r1, eight
|
||
breq r0, r1, nbl8
|
||
load r1, nine
|
||
breq r0, r1, nbl9
|
||
;Uppercase letter digits
|
||
load r1, uca
|
||
breq r0, r1, nbla
|
||
load r1, ucb
|
||
breq r0, r1, nblb
|
||
load r1, ucc
|
||
breq r0, r1, nblc
|
||
load r1, ucd
|
||
breq r0, r1, nbld
|
||
load r1, uce
|
||
breq r0, r1, nble
|
||
load r1, ucf
|
||
breq r0, r1, nblf
|
||
;Lowercase letter digits
|
||
load r1, lca
|
||
breq r0, r1, nbla
|
||
load r1, lcb
|
||
breq r0, r1, nblb
|
||
load r1, lcc
|
||
breq r0, r1, nblc
|
||
load r1, lcd
|
||
breq r0, r1, nbld
|
||
load r1, lce
|
||
breq r0, r1, nble
|
||
load r1, lcf
|
||
breq r0, r1, nblf
|
||
;Load a question mark if the character is not a digit
|
||
load r0, qmark
|
||
breq r0, r0, h2nend
|
||
|
||
;Load the hexadecimal digit of the nibble
|
||
nbl0: load r0, const0
|
||
breq r0, r0, h2nend
|
||
nbl1: load r0, const1
|
||
breq r0, r0, h2nend
|
||
nbl2: load r0, const2
|
||
breq r0, r0, h2nend
|
||
nbl3: load r0, const3
|
||
breq r0, r0, h2nend
|
||
nbl4: load r0, const4
|
||
breq r0, r0, h2nend
|
||
nbl5: load r0, const5
|
||
breq r0, r0, h2nend
|
||
nbl6: load r0, const6
|
||
breq r0, r0, h2nend
|
||
nbl7: load r0, const7
|
||
breq r0, r0, h2nend
|
||
nbl8: load r0, const8
|
||
breq r0, r0, h2nend
|
||
nbl9: load r0, const9
|
||
breq r0, r0, h2nend
|
||
nbla: load r0, consta
|
||
breq r0, r0, h2nend
|
||
nblb: load r0, constb
|
||
breq r0, r0, h2nend
|
||
nblc: load r0, constc
|
||
breq r0, r0, h2nend
|
||
nbld: load r0, constd
|
||
breq r0, r0, h2nend
|
||
nble: load r0, conste
|
||
breq r0, r0, h2nend
|
||
nblf: load r0, constf
|
||
breq r0, r0, h2nend
|
||
|
||
;Return
|
||
h2nend: ret
|
||
|
||
;***
|
||
|
||
;Get the hexadecimal digits of a byte
|
||
|
||
;Load the byte to to r2
|
||
bt2hex: xor r2, r2
|
||
xor r2, r0
|
||
|
||
;Convert the low nibble to a digit and store it in r2
|
||
;Convert
|
||
cleq r0, r0, n2hex
|
||
;Store
|
||
xor r1, r1
|
||
xor r1, r0
|
||
|
||
;Re-load the byte to r0
|
||
xor r0, r0
|
||
xor r0, r2
|
||
|
||
;Store the low nibble in r2
|
||
xor r2, r2
|
||
xor r2, r1
|
||
|
||
;Convert the high nibble to a digit
|
||
ror r0
|
||
ror r0
|
||
ror r0
|
||
ror r0
|
||
cleq r0, r0, n2hex
|
||
|
||
;Load the digit of the low nibble to r1
|
||
xor r1, r1
|
||
xor r1, r2
|
||
|
||
;Return
|
||
ret
|
||
|
||
;***
|
||
|
||
;Input a character
|
||
|
||
;Restore the buffer start address
|
||
;High byte
|
||
input: load r0, bfstrt
|
||
store chstor + 1, r0
|
||
;Low byte
|
||
load r0, bfstrt + 1
|
||
store chstor + 2, r0
|
||
|
||
;Initialise the character counter
|
||
xor r0, r0
|
||
|
||
;Read a character
|
||
inloop: load r1, ffff
|
||
|
||
;Check for control characters and the buffer end
|
||
;Escape
|
||
load r2, esc
|
||
breq r1, r2, escbr
|
||
;Substitute
|
||
load r2, sub
|
||
breq r1, r2, subbr
|
||
;Carriage return
|
||
load r2, cr
|
||
breq r1, r2, crbr
|
||
;Buffer end
|
||
load r2, bfsize
|
||
brneq r0, r2, chstor
|
||
|
||
;Backtrack if at the buffer end
|
||
load r2, bs
|
||
store ffff, r2
|
||
breq r0, r0, inloop
|
||
|
||
;Store the character in the buffer
|
||
chstor: store buffer, r1
|
||
|
||
;Increment the character counter and store it in r3
|
||
;Increment
|
||
load r2, const1
|
||
cleq r0, r0, sum
|
||
;Store
|
||
xor r3, r3
|
||
xor r3, r0
|
||
|
||
;Increment the buffer address
|
||
;Low byte
|
||
load r0, chstor + 2
|
||
load r2, const1
|
||
cleq r0, r0, sum
|
||
store chstor + 2, r0
|
||
;Add the overflow to the high byte
|
||
load r0, chstor + 1
|
||
xor r2, r2
|
||
xor r2, r1
|
||
cleq r0, r0, sum
|
||
store chstor + 1, r0
|
||
|
||
;Reload the character counter to r0
|
||
xor r0, r0
|
||
xor r0, r3
|
||
|
||
;Read the next character
|
||
breq r0, r0, inloop
|
||
|
||
;Print a backslash and a newline
|
||
;Backslash
|
||
escbr: load r0, space
|
||
store ffff, r0
|
||
load r0, bslash
|
||
store ffff, r0
|
||
;Newline
|
||
cleq r0, r0, newln
|
||
|
||
;Return with escape in r2
|
||
breq r0, r0, inend
|
||
|
||
;Print a newline
|
||
subbr: cleq r0, r0, newln
|
||
|
||
;Return with substitute at r2
|
||
breq r0, r0, inend
|
||
|
||
;Increment and store the string size
|
||
crbr: load r2, const2
|
||
cleq r0, r0, sum
|
||
store strsz, r0
|
||
|
||
;Store the CR of a newline in the buffer
|
||
;Get the buffer address
|
||
load r1, chstor + 1
|
||
store endcr + 1, r1
|
||
load r1, chstor + 2
|
||
store endcr + 2, r1
|
||
;Store
|
||
load r0, cr
|
||
endcr: store 0, r0
|
||
|
||
;Increment the buffer address
|
||
;Load the address
|
||
load r0, chstor + 1
|
||
load r1, chstor + 2
|
||
;Increment
|
||
cleq r0, r0, incdw
|
||
;Store the address
|
||
store endlf + 1, r0
|
||
store endlf + 2, r1
|
||
|
||
;Print and store the LF of a newline in the buffer
|
||
load r0, lf
|
||
store ffff, r0
|
||
endlf: store 0, r0
|
||
|
||
;Return
|
||
inend: ret
|
||
|
||
;***
|
||
|
||
;Make room for the line
|
||
|
||
;Find the end of the save address
|
||
;Check for a substitute
|
||
subchk: load r0, 0
|
||
load r1, sub
|
||
breq r0, r1, endfnd
|
||
;Load the address
|
||
load r0, subchk + 1
|
||
load r1, subchk + 2
|
||
;Increment
|
||
cleq r0, r0, incdw
|
||
;Store the address
|
||
store subchk + 1, r0
|
||
store subchk + 2, r1
|
||
;Check the next character
|
||
breq r0, r0, subchk
|
||
|
||
;Store the end of the save address
|
||
;High byte
|
||
endfnd: load r3, subchk + 1
|
||
store movlod + 1, r3
|
||
;Low byte
|
||
load r0, subchk + 2
|
||
store movlod + 2, r0
|
||
|
||
;Calculate the new end of the save
|
||
;Increment the low byte
|
||
load r2, strsz
|
||
cleq r0, r0, sum
|
||
;Move the high byte to r2
|
||
xor r2, r2
|
||
xor r2, r3
|
||
;Store the low byte to r3
|
||
xor r3, r3
|
||
xor r3, r0
|
||
;Load the high byte to r0
|
||
xor r0, r0
|
||
xor r0, r2
|
||
;Add the overflow to the high byte
|
||
xor r2, r2
|
||
xor r2, r1
|
||
cleq r0, r0, sum
|
||
;Store the new end of the save
|
||
store movsto + 1, r0
|
||
store movsto + 2, r3
|
||
|
||
;Move the substitute
|
||
movlod: load r0, 0
|
||
movsto: store 0, r0
|
||
|
||
;Check for the address of the new line
|
||
load r0, cmpadr
|
||
load r1, movlod + 1
|
||
brneq r0, r1, decsav
|
||
load r0, cmpadr + 1
|
||
load r1, movlod + 2
|
||
brneq r0, r1, decsav
|
||
breq r0, r1, save
|
||
|
||
;Decrement the old save address
|
||
;load the address
|
||
decsav: load r0, movlod + 1
|
||
load r1, movlod + 2
|
||
;Decrement
|
||
cleq r0, r0, decdw
|
||
;Store the address
|
||
store movlod + 1, r0
|
||
store movlod + 2, r1
|
||
|
||
;Decrement the new save address
|
||
;load the address
|
||
load r0, movsto + 1
|
||
load r1, movsto + 2
|
||
;Decrement
|
||
cleq r0, r0, decdw
|
||
;Store the address
|
||
store movsto + 1, r0
|
||
store movsto + 2, r1
|
||
|
||
;Move the next character
|
||
breq r0, r0, movlod
|
||
|
||
;***
|
||
|
||
;Save the line
|
||
|
||
;Restore the buffer start address
|
||
;High byte
|
||
save: load r0, bfstrt
|
||
store chload + 1, r0
|
||
;Low byte
|
||
load r0, bfstrt + 1
|
||
store chload + 2, r0
|
||
|
||
;Store the save address
|
||
;High byte
|
||
load r0, sublod + 1
|
||
store chsave + 1, r0
|
||
;Low byte
|
||
load r0, sublod + 2
|
||
store chsave + 2, r0
|
||
|
||
;Load and save a character from the buffer
|
||
;Load
|
||
chload: load r1, buffer
|
||
;Save
|
||
chsave: store buffer + 100, r1
|
||
|
||
;Check for line end
|
||
load r2, lf
|
||
breq r1, r2, savend
|
||
|
||
;Increment the buffer address
|
||
;Load the address
|
||
load r0, chload + 1
|
||
load r1, chload + 2
|
||
;Increment
|
||
cleq r0, r0, incdw
|
||
;Store the address
|
||
store chload + 1, r0
|
||
store chload + 2, r1
|
||
|
||
;Increment the save address
|
||
;Load the address
|
||
load r0, chsave + 1
|
||
load r1, chsave + 2
|
||
;Increment
|
||
cleq r0, r0, incdw
|
||
;Store the address
|
||
store chsave + 1, r0
|
||
store chsave + 2, r1
|
||
|
||
;Load and save the next character
|
||
breq r0, r0, chload
|
||
|
||
;Return
|
||
savend: ret
|
||
|
||
;***
|
||
|
||
;Find the argument line in the save and store its number
|
||
|
||
;Reset the line number
|
||
fend: xor r0, r0
|
||
store lnnum, r0
|
||
store lnnum + 1, r0
|
||
|
||
;Get the save start address
|
||
;High byte
|
||
load r0, svstrt
|
||
store sublod + 1, r0
|
||
;Low byte
|
||
load r0, svstrt + 1
|
||
store sublod + 2, r0
|
||
|
||
;Check for the argument
|
||
charg: load r0, target
|
||
load r1, lnnum
|
||
brneq r0, r1, fsub
|
||
load r0, target + 1
|
||
load r1, lnnum + 1
|
||
breq r0, r1, fendnd
|
||
|
||
;Check for control characters
|
||
;Substitute
|
||
fsub: load r0, sub
|
||
sublod: load r1, 0
|
||
breq r0, r1, fendnd
|
||
;Line feed
|
||
load r2, lf
|
||
brneq r1, r2, incsav
|
||
|
||
;Increment the line number
|
||
;Load the number
|
||
load r0, lnnum
|
||
load r1, lnnum + 1
|
||
;Increment
|
||
cleq r0, r0, incdw
|
||
;Store the number
|
||
store lnnum, r0
|
||
store lnnum + 1, r1
|
||
|
||
;Increment the save address
|
||
;Load the address
|
||
incsav: load r0, sublod + 1
|
||
load r1, sublod + 2
|
||
;Increment
|
||
cleq r0, r0, incdw
|
||
;Store the address
|
||
store sublod + 1, r0
|
||
store sublod + 2, r1
|
||
|
||
;Check the next character
|
||
breq r0, r0, charg
|
||
|
||
;Return
|
||
fendnd: ret
|
||
|
||
;***
|
||
|
||
;Print a line number prompt
|
||
|
||
;Print the high byte
|
||
;Get the byte
|
||
prnln: load r0, lnnum
|
||
;Convert
|
||
cleq r0, r0, bt2hex
|
||
;Print
|
||
load r2, zero
|
||
breq r0, r2, lead0
|
||
store ffff, r0
|
||
nlead0: store ffff, r1
|
||
load r3, const1
|
||
breq r0, r0, lbtln
|
||
lead0: load r0, space
|
||
store ffff, r0
|
||
brneq r1, r2, nlead0
|
||
load r1, space
|
||
store ffff, r1
|
||
xor r3, r3
|
||
|
||
;Print the low byte
|
||
;Get the byte
|
||
lbtln: load r0, lnnum + 1
|
||
;Convert
|
||
cleq r0, r0, bt2hex
|
||
;Check for preceding leading zeroes
|
||
xor r2, r2
|
||
brneq r2, r3, nled0s
|
||
;Print
|
||
load r2, zero
|
||
brneq r0, r2, nled0s
|
||
load r0, space
|
||
store ffff, r0
|
||
store ffff, r1
|
||
breq r0, r0, prcln
|
||
nled0s: store ffff, r0
|
||
store ffff, r1
|
||
|
||
;Print a colon
|
||
prcln: load r0, colon
|
||
store ffff, r0
|
||
load r0, space
|
||
store ffff, r0
|
||
|
||
;Return
|
||
ret
|
||
|
||
;***
|
||
|
||
;Print or write to tape
|
||
|
||
;Get the save start address
|
||
;High byte
|
||
prwr: load r0, svstrt
|
||
store chprwr + 1, r0
|
||
;Low byte
|
||
load r0, svstrt + 1
|
||
store chprwr + 2, r0
|
||
|
||
;Load a character from the save
|
||
chprwr: load r1, buffer + 100
|
||
|
||
;Check for the save end
|
||
load r2, sub
|
||
breq r1, r2, pwend
|
||
|
||
;Print the character
|
||
prwrch: store fffe, r1
|
||
|
||
;Increment the save address
|
||
;Load the address
|
||
load r0, chprwr + 1
|
||
load r1, chprwr + 2
|
||
;Increment
|
||
cleq r0, r0, incdw
|
||
;Store the address
|
||
store chprwr + 1, r0
|
||
store chprwr + 2, r1
|
||
|
||
;Print the next character
|
||
breq r0, r0, chprwr
|
||
|
||
;Return
|
||
pwend: ret
|
||
|
||
;***
|
||
|
||
;Data
|
||
|
||
;Constants
|
||
const0: data 0
|
||
const1: data 1
|
||
const2: data 2
|
||
const3: data 3
|
||
const4: data 4
|
||
const5: data 5
|
||
const6: data 6
|
||
const7: data 7
|
||
const8: data 8
|
||
const9: data 9
|
||
consta: data a
|
||
constb: data b
|
||
constc: data c
|
||
constd: data d
|
||
conste: data e
|
||
constf: data f
|
||
constf: data f
|
||
cstfd: data fd
|
||
cstfe: data fe
|
||
cstff: data ff
|
||
|
||
;Characters
|
||
bs: data 8
|
||
lf: data a
|
||
cr: data d
|
||
sub: data 1a
|
||
esc: data 1b
|
||
space: data 20
|
||
hash: data 23
|
||
comma: data 2c
|
||
zero: data 30
|
||
one: data 31
|
||
two: data 32
|
||
three: data 33
|
||
four: data 34
|
||
five: data 35
|
||
six: data 36
|
||
seven: data 37
|
||
eight: data 38
|
||
nine: data 39
|
||
colon: data 3a
|
||
prompt: data 3e
|
||
qmark: data 3f
|
||
uca: data 41
|
||
ucb: data 42
|
||
ucc: data 43
|
||
ucd: data 44
|
||
uce: data 45
|
||
ucf: data 46
|
||
uch: data 48
|
||
uci: data 49
|
||
ucl: data 4c
|
||
ucp: data 50
|
||
ucr: data 52
|
||
ucs: data 53
|
||
ucw: data 57
|
||
bslash: data 5c
|
||
lca: data 61
|
||
lcb: data 62
|
||
lcc: data 63
|
||
lcd: data 64
|
||
lce: data 65
|
||
lcf: data 66
|
||
lch: data 68
|
||
lci: data 69
|
||
lcl: data 6c
|
||
lcp: data 70
|
||
lcr: data 72
|
||
lcs: data 73
|
||
lcw: data 77
|
||
|
||
;Variables
|
||
ovrflw: data 0
|
||
lnnum: data 0
|
||
data 0
|
||
strsz: data 0
|
||
dgtcnt: data 0
|
||
dgtadr: addr buffer + 2
|
||
cmd: data 0
|
||
arg1: data 30
|
||
data 30
|
||
data 30
|
||
data 30
|
||
argf1: data 0
|
||
arg2: data 30
|
||
data 30
|
||
argf2: data 0
|
||
target: data 0
|
||
data 0
|
||
count: data 0
|
||
mark: data 0
|
||
data 0
|
||
mrkadr: data 0
|
||
data 0
|
||
cmpadr: data 0
|
||
data 0
|
||
tmp: data 0
|
||
data 0
|
||
|
||
;Buffer and save
|
||
bfstrt: addr buffer
|
||
bfsize: data fe
|
||
svstrt: addr buffer + 100
|
||
|
||
buffer:
|
||
|