diff --git a/CHANGELOG.org b/CHANGELOG.org index d44eda5..ee8f43e 100644 --- a/CHANGELOG.org +++ b/CHANGELOG.org @@ -21,6 +21,7 @@ Added program to search for unusual characters that are not human detectable ** Changed Expanded stage0 web IDE to include the PC and instruction counter +Performance tuned hex1 to reduce both size and instruction count ** Fixed Fixed behavior of R@ thanks to reepca @@ -31,6 +32,7 @@ Fixed output of large negative numbers in hex ** Removed Removed stage1_assembler-0's need for Memory and reduced size of program while at it +Removed stage1_assembler-1's hex1 implementation as it ended up being useless in bootstrapping * 0.0.9 - 2017-08-17 ** Added diff --git a/bootstrapping Steps.org b/bootstrapping Steps.org index 2b0c2b5..0be43d9 100644 --- a/bootstrapping Steps.org +++ b/bootstrapping Steps.org @@ -93,7 +93,7 @@ So we are going to limit ourselves to single character labels and pointers (:a a To build our improved hex assembler: ./bin/vm --rom roms/stage1_assembler-0 --tape_01 stage1/stage1_assembler-1.hex0 --tape_02 roms/stage1_assembler-1 -roms/stage1_assembler-1 should have the sha256sum of e4f0ed6e78ae79bb5e4a4fbde36f085dd0469cd6ae036dce5953b3d1c89801ce +roms/stage1_assembler-1 should have the sha256sum of e59338381ca3ab01a14fa0fc85d0fa1c6e4d59a06ac2d9d75668d878ab469769 * Step 4 get even long label support Now that we have labels and pointers, I want the ability to have labels like :main_function and :stack_start and be able to reference the absolute address of things in my code like $stack_start and complex objects that have 32bit pointers like &foo_bar. diff --git a/stage1/stage1_assembler-1.hex0 b/stage1/stage1_assembler-1.hex0 index e2f2bc5..2d4354d 100644 --- a/stage1/stage1_assembler-1.hex0 +++ b/stage1/stage1_assembler-1.hex0 @@ -1,7 +1,7 @@ ## Copyright (C) 2016 Jeremiah Orians ## This file is part of stage0. ## -## stage0 is free software: you an redistribute it and/or modify +## stage0 is free software: you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 3 of the License, or ## (at your option) any later version. @@ -14,14 +14,11 @@ ## You should have received a copy of the GNU General Public License ## along with stage0. If not, see . -# start -2D2801e8 # LOADUI R8 @table ; Where we are putting our address pointers -2D2900ff # LOADUI R9 0xFF ; Byte mask -2D2A000f # LOADUI R10 0x0F ; nybble mask -2D2B0001 # LOADUI R11 1 ; Our toggle -0D00002C # FALSE R12 ; Our PC counter -2D2D0600 # LOADUI R13 0x600 ; Where we are starting our Stack -# ;; We will be using R14 for our condition codes +#:start 0 +2D2B019C # LOADUI R11 $table ; Where we are putting our address pointers +0D00003C # TRUE R12 ; Our toggle +0D00002D # FALSE R13 ; Our PC counter +2D2E0040 # LOADUI R14 $getLables_2 ; our first iterator # ;; We will be using R15 for holding our processed nybbles # ;; Prep TAPE_01 @@ -32,211 +29,194 @@ 2D201101 # LOADUI R0 0x1101 42100001 # FOPEN_WRITE -# ;; Function for collecting the address of all labels -# getLables 2D211100 # LOADUI R1 0x1100 ; Read from tape_01 -42100100 # FGETC ; Read a Char -# ;; Check for EOF -A0100000 # CMPSKIPI.GE R0 0 -3C00005c # JUMP @stage2 +# ;; Function for collecting the address of all labels +#:getLables 24 +42100100 # FGETC ; Read a Char +2CC00048 # JUMP.NP R0 @stage2 ; Check for EOF # ;; Check for Label -A030003a # CMPSKIPI.NE R0 58 ; If the Char is : the next char is the label -2D0D0040 # CALLI R13 @storeLabel +A030003A # CMPSKIPI.NE R0 58 ; If the Char is : the next char is the label +3C000030 # JUMP @storeLabel # ;; Check for pointer to label -1FE00040 # CMPUI R14 R0 64 ; If the Char is @ the next char is the pointer to a label -2C6E0014 # JUMP.NE R14 @.L0 +A0300040 # CMPSKIPI.NE R0 64 ; If the Char is @ the next char is the pointer to a label +3C00001C # JUMP @ignorePointer -# ;; Ignore the pointer for now -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 -42100100 # FGETC ; Read a Char -0FCC0002 # ADDUI R12 R12 2 ; The pointer will end up taking 2 bytes -3C00ffd4 # JUMP @getLables - -# .L0 # ;; Otherwise attempt to process -2D0D00fc # CALLI R13 @hex ; Convert it -A0100000 # CMPSKIPI.GE R0 0 ; Don't record, nonhex values -3C00ffc8 # JUMP @getLables ; Move onto Next char +3C0000DC # JUMP @hex ; Convert it -# ;; Determine if we got a full byte -2C9B000c # JUMP.Z R11 @.L1 ; Jump if toggled +#:getLables_2 40 +2CC0FFE4 # JUMP.NP R0 @getLables ; Don't record, nonhex values +090006CC # NOT R12 R12 ; Flip the toggle +2C9CFFDC # JUMP.Z R12 @getLables ; First half doesn't need anything -# ;; Deal with case of first half of byte -0D00002B # FALSE R11 ; Flip the toggle -3C00ffbc # JUMP @getLables - -# .L1 # ;; Deal with case of second half of byte -0D00003B # TRUE R11 ; Flip the toggle -0FCC0001 # ADDUI R12 R12 1 ; increment PC now that we have a full byte -3C00ffb0 # JUMP @getLables +0FDD0001 # ADDUI R13 R13 1 ; increment PC now that we have a full byte +3C00FFD4 # JUMP @getLables + +#:ignorePointer 54 +# ;; Ignore the pointer for now +42100100 # FGETC ; Read a Char +0FDD0002 # ADDUI R13 R13 2 ; The pointer will end up taking 2 bytes +3C00FFC8 # JUMP @getLables # ;; Function for storing the address of the label -# storeLabel +#:storeLabel 60 # ;; Get the char of the Label -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 42100100 # FGETC ; Read a Char -# ;; We require 4 bytes to store the pointer values -2D500002 # SL0I R0 2 ; Thus we multiply our label by 4 +# ;; We require 2 bytes to store the pointer values +2D500001 # SL0I R0 1 ; Thus we multiply our label by 2 # ;; Store the current Program counter -05048C80 # STOREX R12 R8 R0 +0504ADB0 # STOREX16 R13 R11 R0 # ;; Label is safely stored, return -0D01001D # RET R13 +3C00FFB8 # JUMP @getLables -# ;; Main Functionality -# stage2 + +# ;; Now that we have all of the label addresses, +# ;; We can process input to produce our output +#:stage2 70 # ;; We first need to rewind tape_01 to perform our second pass 2D201100 # LOADUI R0 0x1100 42100003 # REWIND -# ;; Reset our toggle and counter, just in case -2D2B0001 # LOADUI R11 1 ; Our toggle -0D00002C # FALSE R12 ; Our PC counter +# ;; Reset our toggle and counter +2D291101 # LOADUI R9 0x1101 ; Where to write the combined byte +0D00003C # TRUE R12 ; Our toggle +0D00002D # FALSE R13 ; Our PC counter +2D2E00A4 # LOADUI R14 $loop_hex ; The hex return target -# loop -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 +#:loop 88 42100100 # FGETC ; Read a Char - -# ;; Check for EOF -A0100000 # CMPSKIPI.GE R0 0 -3C000128 # JUMP @finish +2CC000FC # JUMP.NP R0 @finish ; Check for EOF # ;; Check for Label -1FE0003a # CMPUI R14 R0 58 ; Make sure we jump over the label -2C6E0010 # JUMP.NE R14 @.L97 +A030003A # CMPSKIPI.NE R0 58 ; Make sure we jump over the label +3C000044 # JUMP @ignoreLabel -# ;; Consume next char -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 -42100100 # FGETC ; Read a Char -3C00ffe0 # JUMP @loop - -# .L97 # ;; Check for Pointer -1FE00040 # CMPUI R14 R0 64 ; If it is a pointer Deal with it -2C6E000c # JUMP.NE R14 @.L98 ; Otherwise attempt to process it -2D0D004c # CALLI R13 @storePointer -3C00ffd0 # JUMP @loop +A0300040 # CMPSKIPI.NE R0 64 ; If it is a pointer Deal with it +3C000044 # JUMP @storePointer -# .L98 # ;; Process Char -2D210000 # LOADUI R1 0 ; Write to Char to TTY -42100200 # FPUTC ; Print the Char -2D0D0078 # CALLI R13 @hex ; Convert it -12E00000 # CMPI R14 R0 0 ; Check if it is hex -2C8Effbc # JUMP.L R14 @loop ; Don't use nonhex chars -2C9B0010 # JUMP.Z R11 @.L99 ; Jump if toggled +3C000078 # JUMP @hex ; Convert it + +#:loop_hex a4 +2CC0FFE4 # JUMP.NP R0 @loop ; Don't use nonhex chars +090006CC # NOT R12 R12 ; Flip the toggle +2CAC000C # JUMP.NZ R12 @loop_second_nybble ; Jump if toggled # ;; Process first byte of pair -05020F0A # AND R15 R0 R10 ; Store First nibble -0D00002B # FALSE R11 ; Flip the toggle -3C00ffac # JUMP @loop +B0F0000F # ANDI R15 R0 0xF ; Store First nibble +3C00FFD4 # JUMP @loop -# .L99 +#:loop_second_nybble b8 2D5F0004 # SL0I R15 4 ; Shift our first nibble -0502000A # AND R0 R0 R10 ; Mask out top +B000000F # ANDI R0 R0 0xF ; Mask out top 0500000F # ADD R0 R0 R15 ; Combine nibbles -0D00003B # TRUE R11 ; Flip the toggle -2D211101 # LOADUI R1 0x1101 ; Write the combined byte +09000319 # SWAP R1 R9 ; Set to write to tape_2 42100200 # FPUTC ; To TAPE_02 -0FCC0001 # ADDUI R12 R12 1 ; increment PC now that we have a full byte -3C00ff8c # JUMP @loop ; Try to get more bytes +09000319 # SWAP R1 R9 ; Restore from tape_1 +0FDD0001 # ADDUI R13 R13 1 ; increment PC now that we have a full byte +3C00FFB4 # JUMP @loop ; Try to get more bytes -# storePointer +#:ignoreLabel d8 +# ;; Consume next char +42100100 # FGETC ; Read a Char +3C00FFAC # JUMP @loop + +#:storePointer e0 # ;; Correct the PC to reflect the size of the pointer -0FCC0002 # ADDUI R12 R12 2 ; Exactly 2 bytes +0FDD0002 # ADDUI R13 R13 2 ; Exactly 2 bytes # ;; Get the char of the Label -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 42100100 # FGETC ; Read a Char -# ;; Since we stored a full pointer taking up 4 bytes -2D500002 # SL0I R0 2 ; Thus we multiply our label by 4 to get where it is stored -05038280 # LOADX R2 R8 R0 ; Load the address of the label +# ;; Since we stored a short pointer taking up 2 bytes +2D500001 # SL0I R0 1 ; Thus we multiply our label by 2 to get where it is stored +0503C3B0 # LOADXU16 R3 R11 R0 ; Load the address of the label # ;; We now have to calculate the distance and store the 2 bytes -0500222C # SUB R2 R2 R12 ; First determine the difference between the current PC and the stored PC of the label -0F220004 # ADDUI R2 R2 4 ; Adjust for relative positioning +0500233D # SUB R3 R3 R13 ; First determine the difference between the current PC and the stored PC of the label +0F330004 # ADDUI R3 R3 4 ; Adjust for relative positioning # ;; Store Upper byte -09000402 # COPY R0 R2 +B003FF00 # ANDI R0 R3 0xFF00 ; Mask out everything but top byte 2D400008 # SARI R0 8 ; Drop the bottom 8 bits -05020009 # AND R0 R0 R9 ; Mask out everything but bottom bits -2D211101 # LOADUI R1 0x1101 ; Write the byte +09000319 # SWAP R1 R9 ; Write the byte 42100200 # FPUTC ; To TAPE_02 # ;; Store Lower byte -05020029 # AND R0 R2 R9 ; Drop everything but the bottom 8 bits +B00300FF # ANDI R0 R3 0xFF ; Preserve bottom half for later 42100200 # FPUTC ; Write the byte to TAPE_02 -0D01001D # RET R13 +09000319 # SWAP R1 R9 ; Restore Read +3C00FF74 # JUMP @loop -# hex +# ;; Hex function +# ;; Returns hex value of ascii char +# ;; Or -1 if not a hex char +#:hex 118 # ;; Deal with line comments starting with # -1FE00023 # CMPUI R14 R0 35 -2C5E0060 # JUMP.E R14 @ascii_comment +A0300023 # CMPSKIPI.NE R0 35 +3C000058 # JUMP @ascii_comment # ;; Deal with line comments starting with ; -1FE0003b # CMPUI R14 R0 59 -2C5E0058 # JUMP.E R14 @ascii_comment +A030003B # CMPSKIPI.NE R0 59 +3C000050 # JUMP @ascii_comment # ;; Deal with all ascii less than '0' -1FE00030 # CMPUI R14 R0 48 -2C8E0048 # JUMP.L R14 @ascii_other +A0100030 # CMPSKIPI.GE R0 48 +3C000054 # JUMP @ascii_other # ;; Deal with '0'-'9' -1FE00039 # CMPUI R14 R0 57 -2C7E0028 # JUMP.LE R14 @ascii_num +A0000039 # CMPSKIPI.G R0 57 +3C000028 # JUMP @ascii_num # ;; Deal with all ascii less than 'A' -1FE00041 # CMPUI R14 R0 65 -2C8E0038 # JUMP.L R14 @ascii_other +A0100041 # CMPSKIPI.GE R0 65 +3C000044 # JUMP @ascii_other # ;; Deal with 'A'-'F' -1FE00046 # CMPUI R14 R0 70 -2C7E0028 # JUMP.LE R14 @ascii_high +A0000046 # CMPSKIPI.G R0 70 +3C000028 # JUMP @ascii_high # ;; Deal with all ascii less than 'a' -1FE00061 # CMPUI R14 R0 97 -2C8E0028 # JUMP.L R14 @ascii_other +A0100061 # CMPSKIPI.GE R0 97 +3C000034 # JUMP @ascii_other # ;; Deal with 'a'-'f' -1FE00066 # CMPUI R14 R0 102 -2C7E0010 # JUMP.LE R14 @ascii_low +A0000066 # CMPSKIPI.G R0 102 +3C000010 # JUMP @ascii_low # ;; Ignore the rest -3C00001c # JUMP @ascii_other +3C000028 # JUMP @ascii_other -# ascii_num +#:ascii_num 15c 11000030 # SUBUI R0 R0 48 -0D01001D # RET R13 +0D01000E # JSR_COROUTINE R14 -# ascii_low +#:ascii_low 164 11000057 # SUBUI R0 R0 87 -0D01001D # RET R13 +0D01000E # JSR_COROUTINE R14 -# ascii_high +#:ascii_high 16c 11000037 # SUBUI R0 R0 55 -0D01001D # RET R13 +0D01000E # JSR_COROUTINE R14 -# ascii_other -0D000030 # TRUE R0 -0D01001D # RET R13 - -# ascii_comment -2D211100 # LOADUI R1 0x1100 ; Read from TAPE_01 +#:ascii_comment 174 42100100 # FGETC ; Read another char -1FE0000a # CMPUI R14 R0 10 ; Stop at the end of line -2D210000 # LOADUI R1 0 ; Write to TTY -42100200 # FPUTC ; The char we just read -2C6Effec # JUMP.NE R14 @ascii_comment ; Otherwise keep looping -3C00ffe0 # JUMP @ascii_other +A020000A # CMPSKIPI.E R0 10 ; Stop at the end of line +3C00FFF8 # JUMP @ascii_comment ; Otherwise keep looping -# finish +#:ascii_other 180 +0D000030 # TRUE R0 +0D01000E # JSR_COROUTINE R14 + +#:finish 188 2D201100 # LOADUI R0 0x1100 ; Close TAPE_01 42100002 # FCLOSE 2D201101 # LOADUI R0 0x1101 ; Close TAPE_02 @@ -244,4 +224,4 @@ A0100000 # CMPSKIPI.GE R0 0 FFFFFFFF # HALT # ;; Where all of our pointers will be stored for our locations -# table +#:table 19c diff --git a/stage1/stage1_assembler-1.hex1 b/stage1/stage1_assembler-1.hex1 deleted file mode 100644 index 65b542d..0000000 --- a/stage1/stage1_assembler-1.hex1 +++ /dev/null @@ -1,265 +0,0 @@ -## Copyright (C) 2016 Jeremiah Orians -## This file is part of stage0. -## -## stage0 is free software: you an redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation, either version 3 of the License, or -## (at your option) any later version. -## -## stage0 is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with stage0. If not, see . - -# start -2D28 @z # LOADUI R8 @table ; Where we are putting our address pointers -2D2900ff # LOADUI R9 0xFF ; Byte mask -2D2A000f # LOADUI R10 0x0F ; nybble mask -2D2B0001 # LOADUI R11 1 ; Our toggle -0D00002C # FALSE R12 ; Our PC counter -2D2D0600 # LOADUI R13 0x600 ; Where we are starting our Stack -# ;; We will be using R14 for our condition codes -# ;; We will be using R15 for holding our processed nybbles - -# ;; Prep TAPE_01 -2D201100 # LOADUI R0 0x1100 -42100000 # FOPEN_READ - -# ;; Prep TAPE_02 -2D201101 # LOADUI R0 0x1101 -42100001 # FOPEN_WRITE - -# ;; Function for collecting the address of all labels -# getLables -:a -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 -42100100 # FGETC ; Read a Char - -# ;; Check for EOF -A0100000 # CMPSKIPI.GE R0 0 -3C00 @e # JUMP @stage2 - -# ;; Check for Label -A030003a # CMPSKIPI.NE R0 58 ; If the Char is : the next char is the label -2D0D @d # CALLI R13 @storeLabel - -# ;; Check for pointer to label -1FE00040 # CMPUI R14 R0 64 ; If the Char is @ the next char is the pointer to a label -2C6E @b # JUMP.NE R14 @.L0 - -# ;; Ignore the pointer for now -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 -42100100 # FGETC ; Read a Char -0FCC0002 # ADDUI R12 R12 2 ; The pointer will end up taking 2 bytes -3C00 @a # JUMP @getLables - -# .L0 -:b -# ;; Otherwise attempt to process -2D0D @k # CALLI R13 @hex ; Convert it -A0100000 # CMPSKIPI.GE R0 0 ; Don't record, nonhex values -3C00 @a # JUMP @getLables ; Move onto Next char - -# ;; Determine if we got a full byte -2C9B @c # JUMP.Z R11 @.L1 ; Jump if toggled - -# ;; Deal with case of first half of byte -0D00002B # FALSE R11 ; Flip the toggle -3C00 @a # JUMP @getLables - -# .L1 -:c -# ;; Deal with case of second half of byte -0D00003B # TRUE R11 ; Flip the toggle -0FCC0001 # ADDUI R12 R12 1 ; increment PC now that we have a full byte -3C00 @a # JUMP @getLables - -# ;; Function for storing the address of the label -# storeLabel -:d -# ;; Get the char of the Label -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 -42100100 # FGETC ; Read a Char - -# ;; We require 4 bytes to store the pointer values -2D500002 # SL0I R0 2 ; Thus we multiply our label by 4 - -# ;; Store the current Program counter -05048C80 # STOREX R12 R8 R0 - -# ;; Label is safely stored, return -0D01001D # RET R13 - -# ;; Main Functionality -# stage2 -:e -# ;; We first need to rewind tape_01 to perform our second pass -2D201100 # LOADUI R0 0x1100 -42100003 # REWIND - -# ;; Reset our toggle and counter, just in case -2D2B0001 # LOADUI R11 1 ; Our toggle -0D00002C # FALSE R12 ; Our PC counter - -# loop -:f -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 -42100100 # FGETC ; Read a Char - -# ;; Check for EOF -A0100000 # CMPSKIPI.GE R0 0 -3C00 @q # JUMP @finish - -# ;; Check for Label -1FE0003a # CMPUI R14 R0 58 ; Make sure we jump over the label -2C6E @g # JUMP.NE R14 @.L97 - -# ;; Consume next char -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 -42100100 # FGETC ; Read a Char -3C00 @f # JUMP @loop - -# .L97 -:g -# ;; Check for Pointer -1FE00040 # CMPUI R14 R0 64 ; If it is a pointer Deal with it -2C6E @h # JUMP.NE R14 @.L98 ; Otherwise attempt to process it -2D0D @j # CALLI R13 @storePointer -3C00 @f # JUMP @loop - -# .L98 -:h -# ;; Process Char -2D210000 # LOADUI R1 0 ; Write to Char to TTY -42100200 # FPUTC ; Print the Char -2D0D @k # CALLI R13 @hex ; Convert it -12E00000 # CMPI R14 R0 0 ; Check if it is hex -2C8E @f # JUMP.L R14 @loop ; Don't use nonhex chars -2C9B @i # JUMP.Z R11 @.L99 ; Jump if toggled - -# ;; Process first byte of pair -05020F0A # AND R15 R0 R10 ; Store First nibble -0D00002B # FALSE R11 ; Flip the toggle -3C00 @f # JUMP @loop - -# .L99 -:i -2D5F0004 # SL0I R15 4 ; Shift our first nibble -0502000A # AND R0 R0 R10 ; Mask out top -0500000F # ADD R0 R0 R15 ; Combine nibbles -0D00003B # TRUE R11 ; Flip the toggle -2D211101 # LOADUI R1 0x1101 ; Write the combined byte -42100200 # FPUTC ; To TAPE_02 -0FCC0001 # ADDUI R12 R12 1 ; increment PC now that we have a full byte -3C00 @f # JUMP @loop ; Try to get more bytes - -# storePointer -:j -# ;; Correct the PC to reflect the size of the pointer -0FCC0002 # ADDUI R12 R12 2 ; Exactly 2 bytes - -# ;; Get the char of the Label -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 -42100100 # FGETC ; Read a Char - -# ;; Since we stored a full pointer taking up 4 bytes -2D500002 # SL0I R0 2 ; Thus we multiply our label by 4 to get where it is stored -05038280 # LOADX R2 R8 R0 ; Load the address of the label - -# ;; We now have to calculate the distance and store the 2 bytes -0500222C # SUB R2 R2 R12 ; First determine the difference between the current PC and the stored PC of the label -0F220004 # ADDUI R2 R2 4 ; Adjust for relative positioning - -# ;; Store Upper byte -09000402 # COPY R0 R2 -2D400008 # SARI R0 8 ; Drop the bottom 8 bits -05020009 # AND R0 R0 R9 ; Mask out everything but bottom bits -2D211101 # LOADUI R1 0x1101 ; Write the byte -42100200 # FPUTC ; To TAPE_02 - -# ;; Store Lower byte -05020029 # AND R0 R2 R9 ; Drop everything but the bottom 8 bits -42100200 # FPUTC ; Write the byte to TAPE_02 -0D01001D # RET R13 - -# hex -:k -# ;; Deal with line comments starting with # -1FE00023 # CMPUI R14 R0 35 -2C5E @p # JUMP.E R14 @ascii_comment - -# ;; Deal with line comments starting with ; -1FE0003b # CMPUI R14 R0 59 -2C5E @p # JUMP.E R14 @ascii_comment - -# ;; Deal with all ascii less than '0' -1FE00030 # CMPUI R14 R0 48 -2C8E @o # JUMP.L R14 @ascii_other - -# ;; Deal with '0'-'9' -1FE00039 # CMPUI R14 R0 57 -2C7E @l # JUMP.LE R14 @ascii_num - -# ;; Deal with all ascii less than 'A' -1FE00041 # CMPUI R14 R0 65 -2C8E @o # JUMP.L R14 @ascii_other - -# ;; Deal with 'A'-'F' -1FE00046 # CMPUI R14 R0 70 -2C7E @n # JUMP.LE R14 @ascii_high - -# ;; Deal with all ascii less than 'a' -1FE00061 # CMPUI R14 R0 97 -2C8E @o # JUMP.L R14 @ascii_other - -# ;; Deal with 'a'-'f' -1FE00066 # CMPUI R14 R0 102 -2C7E @m # JUMP.LE R14 @ascii_low - -# ;; Ignore the rest -3C00 @o # JUMP @ascii_other - -# ascii_num -:l -11000030 # SUBUI R0 R0 48 -0D01001D # RET R13 - -# ascii_low -:m -11000057 # SUBUI R0 R0 87 -0D01001D # RET R13 - -# ascii_high -:n -11000037 # SUBUI R0 R0 55 -0D01001D # RET R13 - -# ascii_other -:o -0D000030 # TRUE R0 -0D01001D # RET R13 - -# ascii_comment -:p -2D211100 # LOADUI R1 0x1100 ; Read from TAPE_01 -42100100 # FGETC ; Read another char -1FE0000a # CMPUI R14 R0 10 ; Stop at the end of line -2D210000 # LOADUI R1 0 ; Write to TTY -42100200 # FPUTC ; The char we just read -2C6E @p # JUMP.NE R14 @ascii_comment ; Otherwise keep looping -3C00 @o # JUMP @ascii_other - -# finish -:q -2D201100 # LOADUI R0 0x1100 ; Close TAPE_01 -42100002 # FCLOSE -2D201101 # LOADUI R0 0x1101 ; Close TAPE_02 -42100002 # FCLOSE -FFFFFFFF # HALT - -# ;; Where all of our pointers will be stored for our locations -# table -:z diff --git a/stage1/stage1_assembler-1.s b/stage1/stage1_assembler-1.s index 199b2dc..3bb5d31 100644 --- a/stage1/stage1_assembler-1.s +++ b/stage1/stage1_assembler-1.s @@ -15,13 +15,10 @@ ; along with stage0. If not, see . :start - LOADUI R8 @table ; Where we are putting our address pointers - LOADUI R9 0xFF ; Byte mask - LOADUI R10 0x0F ; nybble mask - LOADUI R11 1 ; Our toggle - FALSE R12 ; Our PC counter - LOADUI R13 0x600 ; Where we are starting our Stack - ;; We will be using R14 for our condition codes + LOADUI R11 $table ; Where we are putting our address pointers + TRUE R12 ; Our toggle + FALSE R13 ; Our PC counter + LOADUI R14 $getLables_2 ; our first iterator ;; We will be using R15 for holding our processed nybbles ;; Prep TAPE_01 @@ -32,150 +29,135 @@ LOADUI R0 0x1101 FOPEN_WRITE + LOADUI R1 0x1100 ; Read from tape_01 ;; Function for collecting the address of all labels :getLables - LOADUI R1 0x1100 ; Read from tape_01 FGETC ; Read a Char ;; Check for EOF - CMPSKIPI.GE R0 0 - JUMP @stage2 + JUMP.NP R0 @stage2 ;; Check for Label CMPSKIPI.NE R0 58 ; If the Char is : the next char is the label - CALLI R13 @storeLabel + JUMP @storeLabel ;; Check for pointer to label - CMPUI R14 R0 64 ; If the Char is @ the next char is the pointer to a label - JUMP.NE R14 @.L0 + CMPSKIPI.NE R0 64 ; If the Char is @ the next char is the pointer to a label + JUMP @ignorePointer - ;; Ignore the pointer for now - LOADUI R1 0x1100 ; Read from tape_01 - FGETC ; Read a Char - - ADDUI R12 R12 2 ; The pointer will end up taking 2 bytes - JUMP @getLables - -:.L0 ;; Otherwise attempt to process - CALLI R13 @hex ; Convert it - CMPSKIPI.GE R0 0 ; Don't record, nonhex values - JUMP @getLables ; Move onto Next char + JUMP @hex ; Convert it +:getLables_2 + JUMP.NP R0 @getLables ; Don't record, nonhex values + NOT R12 R12 ; Flip the toggle + JUMP.Z R12 @getLables ; First half doesn't need anything - ;; Determine if we got a full byte - JUMP.Z R11 @.L1 ; Jump if toggled - - ;; Deal with case of first half of byte - FALSE R11 ; Flip the toggle + ;; Deal with case of second half of byte + ADDUI R13 R13 1 ; increment PC now that we have a full byte JUMP @getLables -:.L1 - ;; Deal with case of second half of byte - TRUE R11 ; Flip the toggle - ADDUI R12 R12 1 ; increment PC now that we have a full byte +:ignorePointer + ;; Ignore the pointer for now + FGETC ; Read a Char + ADDUI R13 R13 2 ; The pointer will end up taking 2 bytes JUMP @getLables ;; Function for storing the address of the label :storeLabel ;; Get the char of the Label - LOADUI R1 0x1100 ; Read from tape_01 FGETC ; Read a Char - ;; We require 4 bytes to store the pointer values - SL0I R0 2 ; Thus we multiply our label by 4 + ;; We require 2 bytes to store the pointer values + SL0I R0 1 ; Thus we multiply our label by 2 ;; Store the current Program counter - STOREX R12 R8 R0 + STOREX16 R13 R11 R0 ;; Label is safely stored, return - RET R13 + JUMP @getLables -;; Main Functionality + +;; Now that we have all of the label addresses, +;; We can process input to produce our output :stage2 ;; We first need to rewind tape_01 to perform our second pass LOADUI R0 0x1100 REWIND - ;; Reset our toggle and counter, just in case - LOADUI R11 1 ; Our toggle - FALSE R12 ; Our PC counter + ;; Reset our toggle and counter + LOADUI R9 0x1101 ; Where to write the combined byte + TRUE R12 ; Our toggle + FALSE R13 ; Our PC counter + LOADUI R14 $loop_hex ; The hex return target :loop - LOADUI R1 0x1100 ; Read from tape_01 FGETC ; Read a Char ;; Check for EOF - CMPSKIPI.GE R0 0 - JUMP @finish + JUMP.NP R0 @finish ;; Check for Label - CMPUI R14 R0 58 ; Make sure we jump over the label - JUMP.NE R14 @.L97 + CMPSKIPI.NE R0 58 ; Make sure we jump over the label + JUMP @ignoreLabel - ;; Consume next char - LOADUI R1 0x1100 ; Read from tape_01 - FGETC ; Read a Char - JUMP @loop - -:.L97 ;; Check for Pointer - CMPUI R14 R0 64 ; If it is a pointer Deal with it - JUMP.NE R14 @.L98 ; Otherwise attempt to process it - CALLI R13 @storePointer - JUMP @loop + CMPSKIPI.NE R0 64 ; If it is a pointer Deal with it + JUMP @storePointer -:.L98 ;; Process Char - LOADUI R1 0 ; Write to Char to TTY - FPUTC ; Print the Char - CALLI R13 @hex ; Convert it - CMPI R14 R0 0 ; Check if it is hex - JUMP.L R14 @loop ; Don't use nonhex chars - JUMP.Z R11 @.L99 ; Jump if toggled + JUMP @hex ; Convert it + +:loop_hex + JUMP.NP R0 @loop ; Don't use nonhex chars + NOT R12 R12 ; Flip the toggle + JUMP.NZ R12 @loop_second_nybble ; Jump if toggled ;; Process first byte of pair - AND R15 R0 R10 ; Store First nibble - FALSE R11 ; Flip the toggle + ANDI R15 R0 0xF ; Store First nibble JUMP @loop -:.L99 +:loop_second_nybble SL0I R15 4 ; Shift our first nibble - AND R0 R0 R10 ; Mask out top + ANDI R0 R0 0xF ; Mask out top ADD R0 R0 R15 ; Combine nibbles - TRUE R11 ; Flip the toggle - LOADUI R1 0x1101 ; Write the combined byte + SWAP R1 R9 ; Set to write to tape_2 FPUTC ; To TAPE_02 - ADDUI R12 R12 1 ; increment PC now that we have a full byte + SWAP R1 R9 ; Restore from tape_1 + ADDUI R13 R13 1 ; increment PC now that we have a full byte JUMP @loop ; Try to get more bytes +:ignoreLabel + ;; Consume next char + FGETC ; Read a Char + JUMP @loop + :storePointer ;; Correct the PC to reflect the size of the pointer - ADDUI R12 R12 2 ; Exactly 2 bytes + ADDUI R13 R13 2 ; Exactly 2 bytes ;; Get the char of the Label - LOADUI R1 0x1100 ; Read from tape_01 FGETC ; Read a Char - ;; Since we stored a full pointer taking up 4 bytes - SL0I R0 2 ; Thus we multiply our label by 4 to get where it is stored - LOADX R2 R8 R0 ; Load the address of the label + ;; Since we stored a short pointer taking up 2 bytes + SL0I R0 1 ; Thus we multiply our label by 2 to get where it is stored + LOADXU16 R3 R11 R0 ; Load the address of the label ;; We now have to calculate the distance and store the 2 bytes - SUB R2 R2 R12 ; First determine the difference between the current PC and the stored PC of the label - ADDUI R2 R2 4 ; Adjust for relative positioning + SUB R3 R3 R13 ; First determine the difference between the current PC and the stored PC of the label + ADDUI R3 R3 4 ; Adjust for relative positioning ;; Store Upper byte - COPY R0 R2 + ANDI R0 R3 0xFF00 ; Mask out everything but top byte SARI R0 8 ; Drop the bottom 8 bits - AND R0 R0 R9 ; Mask out everything but bottom bits - LOADUI R1 0x1101 ; Write the byte + SWAP R1 R9 ; Write the byte FPUTC ; To TAPE_02 ;; Store Lower byte - AND R0 R2 R9 ; Drop everything but the bottom 8 bits + ANDI R0 R3 0xFF ; Preserve bottom half for later FPUTC ; Write the byte to TAPE_02 - RET R13 + SWAP R1 R9 ; Restore Read + JUMP @loop ;; Hex function @@ -183,52 +165,48 @@ ;; Or -1 if not a hex char :hex ;; Deal with line comments starting with # - CMPUI R14 R0 35 - JUMP.E R14 @ascii_comment + CMPSKIPI.NE R0 35 + JUMP @ascii_comment ;; Deal with line comments starting with ; - CMPUI R14 R0 59 - JUMP.E R14 @ascii_comment + CMPSKIPI.NE R0 59 + JUMP @ascii_comment ;; Deal with all ascii less than '0' - CMPUI R14 R0 48 - JUMP.L R14 @ascii_other + CMPSKIPI.GE R0 48 + JUMP @ascii_other ;; Deal with '0'-'9' - CMPUI R14 R0 57 - JUMP.LE R14 @ascii_num + CMPSKIPI.G R0 57 + JUMP @ascii_num ;; Deal with all ascii less than 'A' - CMPUI R14 R0 65 - JUMP.L R14 @ascii_other + CMPSKIPI.GE R0 65 + JUMP @ascii_other ;; Deal with 'A'-'F' - CMPUI R14 R0 70 - JUMP.LE R14 @ascii_high + CMPSKIPI.G R0 70 + JUMP @ascii_high ;; Deal with all ascii less than 'a' - CMPUI R14 R0 97 - JUMP.L R14 @ascii_other + CMPSKIPI.GE R0 97 + JUMP @ascii_other ;; Deal with 'a'-'f' - CMPUI R14 R0 102 - JUMP.LE R14 @ascii_low + CMPSKIPI.G R0 102 + JUMP @ascii_low ;; Ignore the rest JUMP @ascii_other :ascii_num SUBUI R0 R0 48 - RET R13 + JSR_COROUTINE R14 :ascii_low SUBUI R0 R0 87 - RET R13 + JSR_COROUTINE R14 :ascii_high SUBUI R0 R0 55 - RET R13 + JSR_COROUTINE R14 +:ascii_comment + FGETC ; Read another char + CMPSKIPI.E R0 10 ; Stop at the end of line + JUMP @ascii_comment ; Otherwise keep looping :ascii_other TRUE R0 - RET R13 -:ascii_comment - LOADUI R1 0x1100 ; Read from TAPE_01 - FGETC ; Read another char - CMPUI R14 R0 10 ; Stop at the end of line - LOADUI R1 0 ; Write to TTY - FPUTC ; The char we just read - JUMP.NE R14 @ascii_comment ; Otherwise keep looping - JUMP @ascii_other + JSR_COROUTINE R14 :finish LOADUI R0 0x1100 ; Close TAPE_01 @@ -237,6 +215,5 @@ FCLOSE HALT - ;; Where all of our pointers will be stored for our locations :table diff --git a/test/SHA256SUMS b/test/SHA256SUMS index 6c64ef9..51c6401 100644 --- a/test/SHA256SUMS +++ b/test/SHA256SUMS @@ -6,5 +6,5 @@ b3a910f18c6bc0ef4aa7a53cb3f0216a9f143319da67ed2a02210fe88b1e1131 roms/forth 24a4d74eb2eb7a82e68335643855658b27b5a6c3b13db473539f3e08d6f26ceb roms/SET 0a427b14020354d1c785f5f900677e0059fce8f8d4456e9c19e5528cb17101eb roms/stage0_monitor 85e5c06ac07f2b97d01dfb5454f5a698b3ec6c21fe53bf3fa57b386aac7b9601 roms/stage1_assembler-0 -e4f0ed6e78ae79bb5e4a4fbde36f085dd0469cd6ae036dce5953b3d1c89801ce roms/stage1_assembler-1 +e59338381ca3ab01a14fa0fc85d0fa1c6e4d59a06ac2d9d75668d878ab469769 roms/stage1_assembler-1 61c1b0f2f628847d9491bd678ac7a23231527cc36493b321612f191674ff3c99 roms/stage1_assembler-2