diff --git a/gidubba.asm b/gidubba.asm index 46e3cfc..c761511 100644 --- a/gidubba.asm +++ b/gidubba.asm @@ -1,1476 +1,1477 @@ - ;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: + ;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: + \ No newline at end of file diff --git a/license.md b/license.md index fabda6a..21283d6 100644 --- a/license.md +++ b/license.md @@ -1,23 +1,24 @@ -MIT License -=========== - -Copyright (c) 2022 - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +MIT License +=========== + +Copyright (c) 2022 + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + \ No newline at end of file diff --git a/readme.md b/readme.md index 5259205..3a58e0d 100644 --- a/readme.md +++ b/readme.md @@ -1,43 +1,44 @@ -Gidubba -======== - -Gidubba (Sumerian for 'stylus') is a simple line editor for the -Thingamajig computer architecture. Its git repository can be found at -https://ahti.space/git/crazyettin/Gidubba and that of Thingamajig at -https://ahti.space/git/crazyettin/Thingamajig. - -System requirements -------------------- - -Gidubba requires a terminal with local echo at address FFFF and -optionally a line printer at address FFFE and a punched tape reader and -punch at FFFD. If your setup differs from this you may have to modify -the code yourself. - -Usage ------ - -The commands are individual letters that can be followed by one or two -arguments separated by a comma. The first argument is a target line -number between 0 and FFFF and the second the range of lines between 0 -and FF the command affects. Inserting lines to a target that does not -exist or the shortcut hash (#) appends them to the text; otherwise -targets or parts of ranges that do not exist are ignored. - -Commands with a single argument: - * I: Insert a line or lines - -Commands with two arguments: - * D: Delete a line - * L: List a line - -Commands with no argument: - * P: Print (requires a printer) - * W: Writes to tape (requires a tape punch) - * R: Reads from tape (requires a tape reader) - * H: Halt - -Both commands and arguments are case-insensitive. In both the command -prompt as well as when inserting lines sending an escape (^[) will allow -retyping the line in question. To finish inserting lines send a -substitute (^Z): the line on which this is done is not saved. +Gidubba +======== + +Gidubba (Sumerian for 'stylus') is a simple line editor for the +Thingamajig computer architecture. Its git repository can be found at +https://ahti.space/git/crazyettin/Gidubba and that of Thingamajig at +https://ahti.space/git/crazyettin/Thingamajig. + +System requirements +------------------- + +Gidubba requires a terminal with local echo at address FFFF and +optionally a line printer at address FFFE and a punched tape reader and +punch at FFFD. If your setup differs from this you may have to modify +the code yourself. + +Usage +----- + +The commands are individual letters that can be followed by one or two +arguments separated by a comma. The first argument is a target line +number between 0 and FFFF and the second the range of lines between 0 +and FF the command affects. Inserting lines to a target that does not +exist or the shortcut hash (#) appends them to the text; otherwise +targets or parts of ranges that do not exist are ignored. + +Commands with a single argument: + * I: Insert a line or lines + +Commands with two arguments: + * D: Delete a line + * L: List a line + +Commands with no argument: + * P: Print + * R: Read from the tape reader + * W: Write to the tape punch + * H: Halt + +Both commands and arguments are case-insensitive. In both the command +prompt as well as when inserting lines sending an escape (^[) will allow +retyping the line in question. To finish inserting lines send a +substitute (^Z): the line on which this is done is not saved. + \ No newline at end of file