|
|
;Gidubba: A simple line editor |
|
|
|
|
|
;*** |
|
|
|
|
|
;Check the RAM size |
|
|
|
|
|
;Initialise the comparison value |
|
|
load r0, #1b |
|
|
|
|
|
;Check a memory location |
|
|
mchks: store ffef, r0 |
|
|
mchkl: load r1, ffef |
|
|
breq r0, r1, svlmit |
|
|
|
|
|
;Decrement the pointer |
|
|
load r0, mchks + 1 |
|
|
load r2, #fc |
|
|
cleq r0, r0, sum |
|
|
store mchks + 1, r0 |
|
|
store mchkl + 1, r0 |
|
|
|
|
|
;Check the next location |
|
|
breq r0, r0, mchks |
|
|
|
|
|
;Save the RAM limit |
|
|
svlmit: load r0, mchks + 1 |
|
|
store limit, r0 |
|
|
|
|
|
;*** |
|
|
|
|
|
;Save an end-of-file at the start address |
|
|
load r0, #1a |
|
|
store buffer + 100, r0 |
|
|
|
|
|
;*** |
|
|
|
|
|
;Command prompt |
|
|
cmdp: load r0, #3e |
|
|
store ffff, r0 |
|
|
load r0, #20 |
|
|
store ffff, r0 |
|
|
|
|
|
;Input the command |
|
|
cmdin: cleq r0, r0, input |
|
|
|
|
|
;Check for control characters |
|
|
;Escape |
|
|
load r0, #1b |
|
|
breq r0, r2, cmdesc |
|
|
;End-of-file |
|
|
load r0, #1a |
|
|
breq r0, r2, end |
|
|
|
|
|
;Initialise the command and argument |
|
|
xor r0, r0 |
|
|
store cmd, r0 |
|
|
store argf1, r0 |
|
|
store argf2, r0 |
|
|
load r0, #30 |
|
|
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, #d |
|
|
load r2, #23 |
|
|
;Check for no command |
|
|
breq r0, r1, cmdp |
|
|
;First digit |
|
|
load r0, buffer + 1 |
|
|
breq r0, r1, chkcmd |
|
|
load r3, #1 |
|
|
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, #2c |
|
|
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, #2c |
|
|
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, #2c |
|
|
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, #2c |
|
|
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, #d |
|
|
arg1d5: load r0, buffer + 5 |
|
|
breq r0, r1, getarg |
|
|
load r3, #2c |
|
|
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, #d |
|
|
;First digit |
|
|
arg2d1: load r0, 0 |
|
|
breq r0, r1, chkcmd |
|
|
load r3, #1 |
|
|
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, #3f |
|
|
breq r0, r1, cmderr |
|
|
xor r2, r2 |
|
|
xor r2, r0 |
|
|
shl r2, 4 |
|
|
;Second digit |
|
|
load r0, arg1 + 1 |
|
|
cleq r0, r0, hex2n |
|
|
load r1, #3f |
|
|
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, #3f |
|
|
breq r0, r1, cmderr |
|
|
xor r2, r2 |
|
|
xor r2, r0 |
|
|
shl r2, 4 |
|
|
;Fourth digit |
|
|
load r0, arg1 + 3 |
|
|
cleq r0, r0, hex2n |
|
|
load r1, #3f |
|
|
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, #3f |
|
|
breq r0, r1, cmderr |
|
|
xor r2, r2 |
|
|
xor r2, r0 |
|
|
shl r2, 4 |
|
|
;Second digit |
|
|
load r0, arg2 + 1 |
|
|
cleq r0, r0, hex2n |
|
|
load r1, #3f |
|
|
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, #43 |
|
|
breq r0, r1, copy |
|
|
load r1, #63 |
|
|
breq r0, r1, copy |
|
|
;Delete |
|
|
load r1, #44 |
|
|
breq r0, r1, delete |
|
|
load r1, #64 |
|
|
breq r0, r1, delete |
|
|
;List |
|
|
load r1, #4c |
|
|
breq r0, r1, list |
|
|
load r1, #6c |
|
|
breq r0, r1, list |
|
|
;Branch to error |
|
|
breq r0, r0, cmderr |
|
|
;Insert |
|
|
onearg: load r1, #49 |
|
|
breq r0, r1, insln |
|
|
load r1, #69 |
|
|
breq r0, r1, insln |
|
|
;Set a mark |
|
|
load r1, #4d |
|
|
breq r0, r1, setmrk |
|
|
load r1, #6d |
|
|
breq r0, r1, setmrk |
|
|
;Branch to error |
|
|
breq r0, r0, cmderr |
|
|
;Print |
|
|
cnarg: load r1, #50 |
|
|
breq r0, r1, print |
|
|
load r1, #70 |
|
|
breq r0, r1, print |
|
|
;Write to tape |
|
|
load r1, #57 |
|
|
breq r0, r1, write |
|
|
load r1, #77 |
|
|
breq r0, r1, write |
|
|
;Read from tape |
|
|
load r1, #52 |
|
|
breq r0, r1, read |
|
|
load r1, #72 |
|
|
breq r0, r1, read |
|
|
|
|
|
;Print an error and return to the command prompt |
|
|
cmderr: load r0, #3f |
|
|
store ffff, r0 |
|
|
cleq r0, r0, newln |
|
|
breq r0, r0, cmdp |
|
|
|
|
|
cmdesc: load r0, #20 |
|
|
store ffff, r0 |
|
|
store ffff, r0 |
|
|
breq r0, r0, cmdin |
|
|
|
|
|
;*** |
|
|
|
|
|
;Insert a line |
|
|
|
|
|
;Reset the line number |
|
|
insln: xor r0, r0 |
|
|
store lnnum, r0 |
|
|
store lnnum + 1, r0 |
|
|
|
|
|
;Get the save start address |
|
|
;High byte |
|
|
load r0, svstrt |
|
|
store eoflod + 1, r0 |
|
|
;Low byte |
|
|
load r0, svstrt + 1 |
|
|
store eoflod + 2, r0 |
|
|
|
|
|
;Find the argument line in the save and store its number |
|
|
nextln: cleq r0, r0, fend |
|
|
|
|
|
;Print a line number prompt |
|
|
instrt: cleq r0, r0, prnln |
|
|
|
|
|
;Input the line |
|
|
inline: cleq r0, r0, input |
|
|
|
|
|
;Check for control characters |
|
|
;Escape |
|
|
load r0, #1b |
|
|
breq r0, r2, inesc |
|
|
;End-of-file |
|
|
load r0, #1a |
|
|
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, eoflod + 1 |
|
|
store eofchk + 1, r3 |
|
|
store cmpadr, r3 |
|
|
;Low byte |
|
|
load r0, eoflod + 2 |
|
|
store eofchk + 2, r0 |
|
|
store cmpadr + 1, r0 |
|
|
|
|
|
;Make room for the line |
|
|
cleq r0, r0, eofchk |
|
|
xor r0, r0 |
|
|
brneq r0, r1, cmdp |
|
|
|
|
|
;Restore the buffer start address |
|
|
;High byte |
|
|
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, eoflod + 1 |
|
|
store chsave + 1, r0 |
|
|
;Low byte |
|
|
load r0, eoflod + 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, #a |
|
|
breq r1, r2, nextln |
|
|
|
|
|
;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 |
|
|
|
|
|
inesc: load r0, #20 |
|
|
store ffff, r0 |
|
|
store ffff, r0 |
|
|
store ffff, r0 |
|
|
store ffff, r0 |
|
|
store ffff, r0 |
|
|
store ffff, r0 |
|
|
breq r0, r0, inline |
|
|
|
|
|
;*** |
|
|
|
|
|
;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 |
|
|
|
|
|
;Check for an empty counter |
|
|
copy: xor r0, r0 |
|
|
load r1, count |
|
|
breq r0, r1, cmdp |
|
|
|
|
|
;Reset the line number |
|
|
xor r0, r0 |
|
|
store lnnum, r0 |
|
|
store lnnum + 1, r0 |
|
|
|
|
|
;Get the save start address |
|
|
;High byte |
|
|
load r0, svstrt |
|
|
store eoflod + 1, r0 |
|
|
;Low byte |
|
|
load r0, svstrt + 1 |
|
|
store eoflod + 2, r0 |
|
|
|
|
|
;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, eoflod + 1 |
|
|
store strsz, r0 |
|
|
store chsend + 1, r0 |
|
|
;Low byte |
|
|
load r0, eoflod + 2 |
|
|
store strsz + 1, r0 |
|
|
store chsend + 2, r0 |
|
|
|
|
|
;Check for the save end |
|
|
chsend: load r0, 0 |
|
|
load r1, #1a |
|
|
breq r0, r1, cmdp |
|
|
|
|
|
;Save the buffer address to tmp1 and increment it |
|
|
;Low byte |
|
|
load r0, target + 1 |
|
|
store tmp1 + 1, r0 |
|
|
load r2, count |
|
|
cleq r0, r0, sum |
|
|
store target + 1, r0 |
|
|
;Add the overflow to the high byte |
|
|
load r0, target |
|
|
store tmp1, r0 |
|
|
xor r2, r2 |
|
|
xor r2, r1 |
|
|
cleq r0, r0, sum |
|
|
store target, r0 |
|
|
|
|
|
;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, eoflod + 1 |
|
|
store tmp2, r0 |
|
|
;Low byte |
|
|
load r0, eoflod + 2 |
|
|
store tmp2 + 1, r0 |
|
|
|
|
|
;Negate the first address |
|
|
;Low byte |
|
|
load r0, strsz + 1 |
|
|
nand r0, r0 |
|
|
load r2, #1 |
|
|
cleq r0, r0, sum |
|
|
store strsz + 1, r0 |
|
|
;Reverse and add the overflow to the high byte |
|
|
load r0, strsz |
|
|
nand r0, r0 |
|
|
xor r2, r2 |
|
|
xor r2, r1 |
|
|
cleq r0, r0, sum |
|
|
store strsz, r0 |
|
|
|
|
|
;Get the copy length |
|
|
;High byte |
|
|
load r0, tmp2 |
|
|
load r2, strsz |
|
|
cleq r0, r0, sum |
|
|
store strsz, r0 |
|
|
;Low byte |
|
|
load r0, tmp2 + 1 |
|
|
load r2, strsz + 1 |
|
|
cleq r0, r0, sum |
|
|
store strsz + 1, r0 |
|
|
;Reverse and add the overflow to the high byte |
|
|
load r0, strsz |
|
|
xor r2, r2 |
|
|
xor r2, r1 |
|
|
cleq r0, r0, sum |
|
|
store strsz, r0 |
|
|
|
|
|
;Load the mark to target |
|
|
load r0, mark |
|
|
store target, r0 |
|
|
load r0, mark + 1 |
|
|
store target + 1, r0 |
|
|
|
|
|
;Reset the line number |
|
|
xor r0, r0 |
|
|
store lnnum, r0 |
|
|
store lnnum + 1, r0 |
|
|
|
|
|
;Get the save start address |
|
|
;High byte |
|
|
load r0, svstrt |
|
|
store eoflod + 1, r0 |
|
|
;Low byte |
|
|
load r0, svstrt + 1 |
|
|
store eoflod + 2, r0 |
|
|
|
|
|
;Find the marked line in the save and store its number |
|
|
cleq r0, r0, fend |
|
|
|
|
|
;Store the save address |
|
|
;High byte |
|
|
load r3, eoflod + 1 |
|
|
store eofchk + 1, r3 |
|
|
store cmpadr, r3 |
|
|
store cstor + 1, r3 |
|
|
store cinit + 1, r3 |
|
|
;Low byte |
|
|
load r0, eoflod + 2 |
|
|
store eofchk + 2, r0 |
|
|
store cmpadr + 1, r0 |
|
|
store cstor + 2, r0 |
|
|
store cinit + 2, r0 |
|
|
|
|
|
;Make room for the copy |
|
|
cleq r0, r0, eofchk |
|
|
xor r0, r0 |
|
|
brneq r0, r1, cmdp |
|
|
|
|
|
;Check for the end of the space |
|
|
cendsp: load r0, movsto + 1 |
|
|
load r1, cinit + 1 |
|
|
brneq r0, r1, cinist |
|
|
load r0, movsto + 2 |
|
|
load r1, cinit + 2 |
|
|
brneq r0, r1, cinist |
|
|
breq r0, r1, relodt |
|
|
|
|
|
;Initialise a character |
|
|
cinist: load r0, #0 |
|
|
cinit: store 0, r0 |
|
|
|
|
|
;Increment the source address |
|
|
;Load the address |
|
|
incini: load r0, cinit + 1 |
|
|
load r1, cinit + 2 |
|
|
;Increment |
|
|
cleq r0, r0, incdw |
|
|
;Store the address |
|
|
store cinit + 1, r0 |
|
|
store cinit + 2, r1 |
|
|
|
|
|
;Initialise the next character |
|
|
breq r0, r0, cendsp |
|
|
|
|
|
;Reload the target from tmp1 |
|
|
relodt: load r0, tmp1 |
|
|
store target, r0 |
|
|
load r0, tmp1 + 1 |
|
|
store target + 1, r0 |
|
|
|
|
|
;Reset the line number |
|
|
xor r0, r0 |
|
|
store lnnum, r0 |
|
|
store lnnum + 1, r0 |
|
|
|
|
|
;Get the save start address |
|
|
;High byte |
|
|
load r0, svstrt |
|
|
store eoflod + 1, r0 |
|
|
;Low byte |
|
|
load r0, svstrt + 1 |
|
|
store eoflod + 2, r0 |
|
|
|
|
|
;Find the marked line in the save and store its number |
|
|
cleq r0, r0, fend |
|
|
|
|
|
;Store the save address |
|
|
;High byte |
|
|
load r3, eoflod + 1 |
|
|
store cload + 1, r3 |
|
|
;Low byte |
|
|
load r0, eoflod + 2 |
|
|
store cload + 2, r0 |
|
|
|
|
|
;Copy a character |
|
|
;Load |
|
|
cload: load r1, 0 |
|
|
;Check for a null |
|
|
xor r2, r2 |
|
|
breq r1, r2, skip0 |
|
|
;Check for save end |
|
|
load r2, #1a |
|
|
breq r1, r2, cmdp |
|
|
;Save |
|
|
cstor: store 0, r1 |
|
|
|
|
|
;Check for line end |
|
|
load r2, #a |
|
|
brneq r1, r2, cincs |
|
|
|
|
|
;Decrement the counter |
|
|
load r0, count |
|
|
load r2, #ff |
|
|
cleq r0, r0, sum |
|
|
store count, r0 |
|
|
|
|
|
;Check the counter |
|
|
xor r0, r0 |
|
|
load r1, count |
|
|
breq r0, r1, cmdp |
|
|
|
|
|
;Increment the source address |
|
|
;Load the address |
|
|
cincs: load r0, cload + 1 |
|
|
load r1, cload + 2 |
|
|
;Increment |
|
|
cleq r0, r0, incdw |
|
|
;Store the address |
|
|
store cload + 1, r0 |
|
|
store cload + 2, r1 |
|
|
|
|
|
;Increment the copy address |
|
|
;Load the address |
|
|
load r0, cstor + 1 |
|
|
load r1, cstor + 2 |
|
|
;Increment |
|
|
cleq r0, r0, incdw |
|
|
;Store the address |
|
|
store cstor + 1, r0 |
|
|
store cstor + 2, r1 |
|
|
|
|
|
;Load and save the next character |
|
|
breq r0, r0, cload |
|
|
|
|
|
;Increment the source address |
|
|
;Load the address |
|
|
skip0: load r0, cload + 1 |
|
|
load r1, cload + 2 |
|
|
;Increment |
|
|
cleq r0, r0, incdw |
|
|
;Store the address |
|
|
store cload + 1, r0 |
|
|
store cload + 2, r1 |
|
|
|
|
|
;Load the next character |
|
|
breq r0, r0, cload |
|
|
|
|
|
;*** |
|
|
|
|
|
;Delete a line |
|
|
|
|
|
;Check for an empty counter |
|
|
delete: xor r0, r0 |
|
|
load r1, count |
|
|
breq r0, r1, cmdp |
|
|
|
|
|
;Reset the line number |
|
|
xor r0, r0 |
|
|
store lnnum, r0 |
|
|
store lnnum + 1, r0 |
|
|
|
|
|
;Get the save start address |
|
|
;High byte |
|
|
load r0, svstrt |
|
|
store eoflod + 1, r0 |
|
|
;Low byte |
|
|
load r0, svstrt + 1 |
|
|
store eoflod + 2, r0 |
|
|
|
|
|
;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, eoflod + 1 |
|
|
store stomov + 1, r0 |
|
|
store dchend + 1, r0 |
|
|
;Low byte |
|
|
load r0, eoflod + 2 |
|
|
store stomov + 2, r0 |
|
|
store dchend + 2, r0 |
|
|
|
|
|
;Check for the save end |
|
|
dchend: load r0, 0 |
|
|
load r1, #1a |
|
|
breq r0, r1, cmdp |
|
|
|
|
|
;Increment the buffer address |
|
|
;Low byte |
|
|
load r0, target + 1 |
|
|
load r2, count |
|
|
cleq r0, r0, sum |
|
|
store target + 1, r0 |
|
|
;Add the overflow to the high byte |
|
|
load r0, target |
|
|
xor r2, r2 |
|
|
xor r2, r1 |
|
|
cleq r0, r0, sum |
|
|
store target, r0 |
|
|
|
|
|
;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, eoflod + 1 |
|
|
store lodmov + 1, r0 |
|
|
;Low byte |
|
|
load r0, eoflod + 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, #1a |
|
|
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 |
|
|
|
|
|
;Return to the command prompt |
|
|
delend: breq r0, r0, cmdp |
|
|
|
|
|
;*** |
|
|
|
|
|
;List a line |
|
|
|
|
|
;Reset the line number |
|
|
list: xor r0, r0 |
|
|
store lnnum, r0 |
|
|
store lnnum + 1, r0 |
|
|
|
|
|
;Get the save start address |
|
|
;High byte |
|
|
load r0, svstrt |
|
|
store eoflod + 1, r0 |
|
|
;Low byte |
|
|
load r0, svstrt + 1 |
|
|
store eoflod + 2, r0 |
|
|
|
|
|
;Check the counter |
|
|
lcount: 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, eoflod + 1 |
|
|
store chlist + 1, r0 |
|
|
store lchend + 1, r0 |
|
|
;Low byte |
|
|
load r0, eoflod + 2 |
|
|
store chlist + 2, r0 |
|
|
store lchend + 2, r0 |
|
|
|
|
|
;Check for the save end |
|
|
lchend: load r0, 0 |
|
|
load r1, #1a |
|
|
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, #1a |
|
|
breq r1, r2, prnwln |
|
|
|
|
|
;Print the character |
|
|
store ffff, r1 |
|
|
|
|
|
;Check for the line end |
|
|
load r2, #a |
|
|
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, #ff |
|
|
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, lcount |
|
|
|
|
|
;*** |
|
|
|
|
|
;Print the text |
|
|
|
|
|
;Get the printer address |
|
|
;High byte |
|
|
print: load r0, #ff |
|
|
store prwrch + 1, r0 |
|
|
;Low byte |
|
|
load r0, #fe |
|
|
store prwrch + 2, r0 |
|
|
|
|
|
;Print |
|
|
cleq r0, r0, prwr |
|
|
|
|
|
;Return to the command prompt |
|
|
breq r0, r0, cmdp |
|
|
|
|
|
;*** |
|
|
|
|
|
;Write the text to the tape punch |
|
|
|
|
|
;Get the tape punch address |
|
|
;High byte |
|
|
write: load r0, #ff |
|
|
store prwrch + 1, r0 |
|
|
;Low byte |
|
|
load r0, #fd |
|
|
store prwrch + 2, r0 |
|
|
|
|
|
;Write |
|
|
cleq r0, r0, prwr |
|
|
|
|
|
;Return to the command prompt |
|
|
breq r0, r0, cmdp |
|
|
|
|
|
;*** |
|
|
|
|
|
;Read the text from the tape reader |
|
|
|
|
|
;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 |
|
|
|
|
|
;Ignore the leader |
|
|
iglead: load r1, fffd |
|
|
xor r2, r2 |
|
|
breq r1, r2, iglead |
|
|
breq r0, r0, chkend |
|
|
|
|
|
;Check for the RAM limit |
|
|
load r0, chrsto + 1 |
|
|
load r1, chrsto + 2 |
|
|
chkram: cleq r0, r0, ramchk |
|
|
xor r2, r2 |
|
|
brneq r1, r2, cmdp |
|
|
|
|
|
;Read a character |
|
|
chread: load r1, fffd |
|
|
|
|
|
;Check for trailer or empty tape reader |
|
|
;Trailer |
|
|
chkend: xor r2, r2 |
|
|
brneq r1, r2, chkntp |
|
|
load r1, #1a |
|
|
breq r0, r0, chrsto |
|
|
;Empty tape reader |
|
|
chkntp: nand r2, r2 |
|
|
brneq r1, r2, chklf |
|
|
load r1, #1a |
|
|
breq r0, r0, chrsto |
|
|
|
|
|
;Check for a line feed |
|
|
chklf: load r2, #a |
|
|
load r3, #0 |
|
|
brneq r1, r2, chrsto |
|
|
load r1, #d |
|
|
load r3, #a |
|
|
|
|
|
;Store a character |
|
|
chrsto: store buffer + 100, r1 |
|
|
|
|
|
;Check for a newline |
|
|
;Line feed |
|
|
load r2, #a |
|
|
breq r2, r3, readlf |
|
|
;Carriage return |
|
|
load r2, #d |
|
|
breq r1, r2, readcr |
|
|
|
|
|
;Check for the save end |
|
|
load r2, #1a |
|
|
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, chkram |
|
|
|
|
|
;Read a newline beginning with a carriage return |
|
|
readcr: cleq r0, r0, readnl |
|
|
|
|
|
;Check for a line feed |
|
|
load r2, #a |
|
|
breq r1, r2, chread |
|
|
breq r0, r0, chkend |
|
|
|
|
|
;Read a newline beginning with a line feed |
|
|
readlf: cleq r0, r0, readnl |
|
|
|
|
|
;Check for a carriage return |
|
|
load r2, #d |
|
|
breq r1, r2, chread |
|
|
breq r0, r0, chkend |
|
|
|
|
|
;Return to the command prompt |
|
|
redend: breq r0, r0, cmdp |
|
|
|
|
|
;*** |
|
|
|
|
|
;Halt |
|
|
end: halt |
|
|
|
|
|
;*** |
|
|
|
|
|
;Print a newline |
|
|
newln: load r0, #d |
|
|
store ffff, r0 |
|
|
load r0, #a |
|
|
store ffff, r0 |
|
|
ret |
|
|
|
|
|
;*** |
|
|
|
|
|
;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, 1 |
|
|
|
|
|
;Check for and store overflow if any |
|
|
;Check |
|
|
rol r1, 1 |
|
|
breq r1, r2, nvrflw |
|
|
;Store |
|
|
load r1, #1 |
|
|
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, #1 |
|
|
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, #ff |
|
|
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, #ff |
|
|
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, #f |
|
|
and r0, r1 |
|
|
|
|
|
;Get the nibble value |
|
|
load r1, #0 |
|
|
breq r0, r1, dgt0 |
|
|
load r1, #1 |
|
|
breq r0, r1, dgt1 |
|
|
load r1, #2 |
|
|
breq r0, r1, dgt2 |
|
|
load r1, #3 |
|
|
breq r0, r1, dgt3 |
|
|
load r1, #4 |
|
|
breq r0, r1, dgt4 |
|
|
load r1, #5 |
|
|
breq r0, r1, dgt5 |
|
|
load r1, #6 |
|
|
breq r0, r1, dgt6 |
|
|
load r1, #7 |
|
|
breq r0, r1, dgt7 |
|
|
load r1, #8 |
|
|
breq r0, r1, dgt8 |
|
|
load r1, #9 |
|
|
breq r0, r1, dgt9 |
|
|
load r1, #a |
|
|
breq r0, r1, dgta |
|
|
load r1, #b |
|
|
breq r0, r1, dgtb |
|
|
load r1, #c |
|
|
breq r0, r1, dgtc |
|
|
load r1, #d |
|
|
breq r0, r1, dgtd |
|
|
load r1, #e |
|
|
breq r0, r1, dgte |
|
|
load r1, #f |
|
|
breq r0, r1, dgtf |
|
|
|
|
|
;Load the hexadecimal digit of the nibble |
|
|
dgt0: load r0, #30 |
|
|
breq r0, r0, n2hend |
|
|
dgt1: load r0, #31 |
|
|
breq r0, r0, n2hend |
|
|
dgt2: load r0, #32 |
|
|
breq r0, r0, n2hend |
|
|
dgt3: load r0, #33 |
|
|
breq r0, r0, n2hend |
|
|
dgt4: load r0, #34 |
|
|
breq r0, r0, n2hend |
|
|
dgt5: load r0, #35 |
|
|
breq r0, r0, n2hend |
|
|
dgt6: load r0, #36 |
|
|
breq r0, r0, n2hend |
|
|
dgt7: load r0, #37 |
|
|
breq r0, r0, n2hend |
|
|
dgt8: load r0, #38 |
|
|
breq r0, r0, n2hend |
|
|
dgt9: load r0, #39 |
|
|
breq r0, r0, n2hend |
|
|
dgta: load r0, #41 |
|
|
breq r0, r0, n2hend |
|
|
dgtb: load r0, #42 |
|
|
breq r0, r0, n2hend |
|
|
dgtc: load r0, #43 |
|
|
breq r0, r0, n2hend |
|
|
dgtd: load r0, #44 |
|
|
breq r0, r0, n2hend |
|
|
dgte: load r0, #45 |
|
|
breq r0, r0, n2hend |
|
|
dgtf: load r0, #46 |
|
|
breq r0, r0, n2hend |
|
|
|
|
|
;Return |
|
|
n2hend: ret |
|
|
|
|
|
;*** |
|
|
|
|
|
;Get the nibble of a hexadecimal digit |
|
|
|
|
|
;Get the nibble value |
|
|
;Numeric digits |
|
|
hex2n: load r1, #30 |
|
|
breq r0, r1, nbl0 |
|
|
load r1, #31 |
|
|
breq r0, r1, nbl1 |
|
|
load r1, #32 |
|
|
breq r0, r1, nbl2 |
|
|
load r1, #33 |
|
|
breq r0, r1, nbl3 |
|
|
load r1, #34 |
|
|
breq r0, r1, nbl4 |
|
|
load r1, #35 |
|
|
breq r0, r1, nbl5 |
|
|
load r1, #36 |
|
|
breq r0, r1, nbl6 |
|
|
load r1, #37 |
|
|
breq r0, r1, nbl7 |
|
|
load r1, #38 |
|
|
breq r0, r1, nbl8 |
|
|
load r1, #39 |
|
|
breq r0, r1, nbl9 |
|
|
;Uppercase letter digits |
|
|
load r1, #41 |
|
|
breq r0, r1, nbla |
|
|
load r1, #42 |
|
|
breq r0, r1, nblb |
|
|
load r1, #43 |
|
|
breq r0, r1, nblc |
|
|
load r1, #44 |
|
|
breq r0, r1, nbld |
|
|
load r1, #45 |
|
|
breq r0, r1, nble |
|
|
load r1, #46 |
|
|
breq r0, r1, nblf |
|
|
;Lowercase letter digits |
|
|
load r1, #61 |
|
|
breq r0, r1, nbla |
|
|
load r1, #62 |
|
|
breq r0, r1, nblb |
|
|
load r1, #63 |
|
|
breq r0, r1, nblc |
|
|
load r1, #64 |
|
|
breq r0, r1, nbld |
|
|
load r1, #65 |
|
|
breq r0, r1, nble |
|
|
load r1, #66 |
|
|
breq r0, r1, nblf |
|
|
;Load a question mark if the character is not a digit |
|
|
load r0, #3f |
|
|
breq r0, r0, h2nend |
|
|
|
|
|
;Load the hexadecimal digit of the nibble |
|
|
nbl0: load r0, #0 |
|
|
breq r0, r0, h2nend |
|
|
nbl1: load r0, #1 |
|
|
breq r0, r0, h2nend |
|
|
nbl2: load r0, #2 |
|
|
breq r0, r0, h2nend |
|
|
nbl3: load r0, #3 |
|
|
breq r0, r0, h2nend |
|
|
nbl4: load r0, #4 |
|
|
breq r0, r0, h2nend |
|
|
nbl5: load r0, #5 |
|
|
breq r0, r0, h2nend |
|
|
nbl6: load r0, #6 |
|
|
breq r0, r0, h2nend |
|
|
nbl7: load r0, #7 |
|
|
breq r0, r0, h2nend |
|
|
nbl8: load r0, #8 |
|
|
breq r0, r0, h2nend |
|
|
nbl9: load r0, #9 |
|
|
breq r0, r0, h2nend |
|
|
nbla: load r0, #a |
|
|
breq r0, r0, h2nend |
|
|
nblb: load r0, #b |
|
|
breq r0, r0, h2nend |
|
|
nblc: load r0, #c |
|
|
breq r0, r0, h2nend |
|
|
nbld: load r0, #d |
|
|
breq r0, r0, h2nend |
|
|
nble: load r0, #e |
|
|
breq r0, r0, h2nend |
|
|
nblf: load r0, #f |
|
|
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, 4 |
|
|
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 |
|
|
;Null |
|
|
load r2, #0 |
|
|
breq r1, r2, inloop |
|
|
;FF |
|
|
load r2, #ff |
|
|
breq r1, r2, inloop |
|
|
;Delete |
|
|
load r2, #7f |
|
|
breq r1, r2, delbr |
|
|
;Escape |
|
|
load r2, #1b |
|
|
breq r1, r2, escbr |
|
|
;End-of-file |
|
|
load r2, #1a |
|
|
breq r1, r2, eofbr |
|
|
;Carriage return |
|
|
load r2, #d |
|
|
breq r1, r2, crbr |
|
|
;Line feed |
|
|
load r2, #a |
|
|
breq r1, r2, lfbr |
|
|
;Buffer end |
|
|
load r2, bfsize |
|
|
brneq r0, r2, chstor |
|
|
|
|
|
;Ignore the input and print an underscore if at the buffer end |
|
|
load r2, #5f |
|
|
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, #1 |
|
|
cleq r0, r0, sum |
|
|
;Store |
|
|
xor r3, r3 |
|
|
xor r3, r0 |
|
|
|
|
|
;Increment the buffer address |
|
|
;Low byte |
|
|
load r0, chstor + 2 |
|
|
load r2, #1 |
|
|
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 an underscore |
|
|
delbr: load r2, #5f |
|
|
store ffff, r2 |
|
|
|
|
|
;Check for buffer start |
|
|
xor r2, r2 |
|
|
breq r0, r2, inloop |
|
|
|
|
|
;Decrement the character counter and store it in r3 |
|
|
;Decrement |
|
|
load r2, #ff |
|
|
cleq r0, r0, sum |
|
|
;Store |
|
|
xor r3, r3 |
|
|
xor r3, r0 |
|
|
|
|
|
;Decrement the buffer address |
|
|
;High byte |
|
|
load r0, chstor + 1 |
|
|
load r2, #ff |
|
|
cleq r0, r0, sum |
|
|
store chstor + 1, r0 |
|
|
;Low byte |
|
|
load r0, chstor + 2 |
|
|
load r2, #ff |
|
|
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, #20 |
|
|
store ffff, r0 |
|
|
load r0, #5c |
|
|
store ffff, r0 |
|
|
;Newline |
|
|
cleq r0, r0, newln |
|
|
|
|
|
;Return with escape in r2 |
|
|
ret |
|
|
|
|
|
;Print a newline |
|
|
eofbr: cleq r0, r0, newln |
|
|
|
|
|
;Return with End-of-file at r2 |
|
|
ret |
|
|
|
|
|
;Print a line feed |
|
|
crbr: load r1, #a |
|
|
store ffff, r1 |
|
|
breq r0, r0, endnl |
|
|
|
|
|
;Print a carriage return and a null |
|
|
lfbr: load r1, #d |
|
|
store ffff, r1 |
|
|
load r1, #0 |
|
|
store ffff, r1 |
|
|
|
|
|
;Increment and store the string size |
|
|
endnl: load r2, #2 |
|
|
cleq r0, r0, sum |
|
|
store strsz + 1, r0 |
|
|
load r0, #0 |
|
|
store strsz, r0 |
|
|
|
|
|
;Get the buffer address |
|
|
load r1, chstor + 1 |
|
|
store endcr + 1, r1 |
|
|
load r1, chstor + 2 |
|
|
store endcr + 2, r1 |
|
|
|
|
|
;Store the CR of a newline in the buffer |
|
|
load r0, #d |
|
|
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 |
|
|
|
|
|
;Store the LF of a newline in the buffer |
|
|
load r0, #a |
|
|
endlf: store 0, r0 |
|
|
|
|
|
;Return |
|
|
ret |
|
|
|
|
|
;*** |
|
|
|
|
|
;Make room for the line |
|
|
|
|
|
;Find the end of the save address |
|
|
;Check for an end-of-file |
|
|
eofchk: load r0, 0 |
|
|
load r1, #1a |
|
|
breq r0, r1, endfnd |
|
|
;Load the address |
|
|
load r0, eofchk + 1 |
|
|
load r1, eofchk + 2 |
|
|
;Increment |
|
|
cleq r0, r0, incdw |
|
|
;Store the address |
|
|
store eofchk + 1, r0 |
|
|
store eofchk + 2, r1 |
|
|
;Check the next character |
|
|
breq r0, r0, eofchk |
|
|
|
|
|
;Store the end of the save address |
|
|
;High byte |
|
|
endfnd: load r0, eofchk + 1 |
|
|
store movlod + 1, r0 |
|
|
;Low byte |
|
|
load r3, eofchk + 2 |
|
|
store movlod + 2, r3 |
|
|
|
|
|
;Calculate the new end of the save |
|
|
;High byte |
|
|
load r2, strsz |
|
|
cleq r0, r0, sum |
|
|
store strsz, r0 |
|
|
;Check for overflow from the high byte |
|
|
xor r0, r0 |
|
|
brneq r0, r1, lmterr |
|
|
;Low byte |
|
|
xor r0, r0 |
|
|
xor r0, r3 |
|
|
load r2, strsz + 1 |
|
|
cleq r0, r0, sum |
|
|
store strsz + 1, r0 |
|
|
;Add the overflow to the high byte |
|
|
load r0, strsz |
|
|
xor r2, r2 |
|
|
xor r2, r1 |
|
|
cleq r0, r0, sum |
|
|
;Store the new end of the save |
|
|
store movsto + 1, r0 |
|
|
load r3, strsz + 1 |
|
|
store movsto + 2, r3 |
|
|
;Check for overflow from the high byte |
|
|
xor r0, r0 |
|
|
brneq r0, r1, lmterr |
|
|
|
|
|
;Negate the RAM limit |
|
|
;Low byte |
|
|
load r0, limit + 1 |
|
|
nand r0, r0 |
|
|
load r2, #1 |
|
|
cleq r0, r0, sum |
|
|
store tmp2 + 1, r0 |
|
|
;Reverse and add the overflow to the high byte |
|
|
load r0, limit |
|
|
nand r0, r0 |
|
|
xor r2, r2 |
|
|
xor r2, r1 |
|
|
cleq r0, r0, sum |
|
|
store tmp2, r0 |
|
|
|
|
|
;Subtract the RAM limit from the new end of the save |
|
|
;High byte |
|
|
load r0, movsto + 1 |
|
|
load r2, tmp2 |
|
|
cleq r0, r0, sum |
|
|
store tmp2, r0 |
|
|
;Check for overflow from the high byte |
|
|
xor r0, r0 |
|
|
brneq r0, r1, lmterr |
|
|
;Low byte |
|
|
load r0, movsto + 2 |
|
|
load r2, tmp2 + 1 |
|
|
cleq r0, r0, sum |
|
|
store tmp2 + 1, r0 |
|
|
;Add the overflow to the high byte |
|
|
load r0, tmp2 |
|
|
xor r2, r2 |
|
|
xor r2, r1 |
|
|
cleq r0, r0, sum |
|
|
store tmp2, r0 |
|
|
;Check for overflow from the high byte |
|
|
xor r0, r0 |
|
|
brneq r0, r1, lmterr |
|
|
|
|
|
;Move the End-of-file |
|
|
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, roomnd |
|
|
|
|
|
;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 |
|
|
|
|
|
;Return with a null at r1 |
|
|
roomnd: xor r1, r1 |
|
|
ret |
|
|
|
|
|
;Print an error and return with an exclamation mark at r1 |
|
|
lmterr: load r0, #21 |
|
|
store ffff, r0 |
|
|
cleq r0, r0, newln |
|
|
load r1, #21 |
|
|
ret |
|
|
|
|
|
;*** |
|
|
|
|
|
;Find the argument line in the save and store its number |
|
|
|
|
|
;Check for the argument |
|
|
fend: load r0, target |
|
|
load r1, lnnum |
|
|
brneq r0, r1, feof |
|
|
load r0, target + 1 |
|
|
load r1, lnnum + 1 |
|
|
breq r0, r1, fendnd |
|
|
|
|
|
;Check for control characters |
|
|
;End-of-file |
|
|
feof: load r0, #1a |
|
|
eoflod: load r1, 0 |
|
|
breq r0, r1, fendnd |
|
|
;Line feed |
|
|
load r2, #a |
|
|
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, eoflod + 1 |
|
|
load r1, eoflod + 2 |
|
|
;Increment |
|
|
cleq r0, r0, incdw |
|
|
;Store the address |
|
|
store eoflod + 1, r0 |
|
|
store eoflod + 2, r1 |
|
|
|
|
|
;Check the next character |
|
|
breq r0, r0, fend |
|
|
|
|
|
;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, #30 |
|
|
breq r0, r2, lead0 |
|
|
store ffff, r0 |
|
|
nlead0: store ffff, r1 |
|
|
load r3, #1 |
|
|
breq r0, r0, lbtln |
|
|
lead0: load r0, #20 |
|
|
store ffff, r0 |
|
|
brneq r1, r2, nlead0 |
|
|
load r1, #20 |
|
|
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, #30 |
|
|
brneq r0, r2, nled0s |
|
|
load r0, #20 |
|
|
store ffff, r0 |
|
|
store ffff, r1 |
|
|
breq r0, r0, prcln |
|
|
nled0s: store ffff, r0 |
|
|
store ffff, r1 |
|
|
|
|
|
;Print a colon |
|
|
prcln: load r0, #3a |
|
|
store ffff, r0 |
|
|
load r0, #20 |
|
|
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 |
|
|
|
|
|
;Print the character |
|
|
prwrch: store fffe, r1 |
|
|
|
|
|
;Check for the save end |
|
|
load r2, #1a |
|
|
breq r1, r2, pwend |
|
|
|
|
|
;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 |
|
|
|
|
|
;*** |
|
|
|
|
|
;Check for the RAM limit |
|
|
|
|
|
;Check |
|
|
ramchk: load r2, limit |
|
|
load r3, limit + 1 |
|
|
brneq r0, r2, ramend |
|
|
brneq r1, r3, ramend |
|
|
|
|
|
;Save an end-of-file at the start address |
|
|
load r0, #1a |
|
|
store buffer + 100, r0 |
|
|
|
|
|
;Print an error |
|
|
load r0, #21 |
|
|
store ffff, r0 |
|
|
cleq r0, r0, newln |
|
|
|
|
|
;Return with an exclamation mark at r1 |
|
|
load r1, #21 |
|
|
ret |
|
|
|
|
|
;Return with a null at r1 |
|
|
ramend: load r1, #0 |
|
|
ret |
|
|
|
|
|
;*** |
|
|
|
|
|
;Read a newline |
|
|
|
|
|
;Increment the save address |
|
|
;Load the address |
|
|
readnl: load r0, chrsto + 1 |
|
|
load r1, chrsto + 2 |
|
|
;Increment |
|
|
cleq r0, r0, incdw |
|
|
;Store the address |
|
|
store chrsto + 1, r0 |
|
|
store lfstor + 1, r0 |
|
|
store chrsto + 2, r1 |
|
|
store lfstor + 2, r1 |
|
|
|
|
|
;Check for the RAM limit |
|
|
cleq r0, r0, ramchk |
|
|
xor r2, r2 |
|
|
brneq r1, r2, cmdp |
|
|
|
|
|
;Store a line feed |
|
|
load r1, #a |
|
|
lfstor: store 0, r1 |
|
|
|
|
|
;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 |
|
|
|
|
|
;Check for the RAM limit |
|
|
cleq r0, r0, ramchk |
|
|
xor r2, r2 |
|
|
brneq r1, r2, cmdp |
|
|
|
|
|
;Read a character |
|
|
load r1, fffd |
|
|
|
|
|
;Return |
|
|
ret |
|
|
|
|
|
;*** |
|
|
|
|
|
;Data |
|
|
|
|
|
;Variables |
|
|
ovrflw: data 0 |
|
|
lnnum: data 0 |
|
|
data 0 |
|
|
strsz: data 0 |
|
|
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 |
|
|
tmp1: data 0 |
|
|
data 0 |
|
|
tmp2: data 0 |
|
|
data 0 |
|
|
|
|
|
;Buffer and save |
|
|
bfstrt: addr buffer |
|
|
bfsize: data fe |
|
|
svstrt: addr buffer + 100 |
|
|
limit: data 0 |
|
|
data 0 |
|
|
|
|
|
buffer: |
|
|
|