diff --git a/CHANGELOG.org b/CHANGELOG.org index cd9c61d..3f9bde9 100644 --- a/CHANGELOG.org +++ b/CHANGELOG.org @@ -23,6 +23,7 @@ Added program to search for unusual characters that are not human detectable Expanded stage0 web IDE to include the PC and instruction counter Performance tuned hex1 to reduce both size and instruction count Performance tuned hex0 to reduce both size and instruction count +Performance tuned hex2 to reduce both size and isntruction count ** Fixed Fixed behavior of R@ thanks to reepca @@ -35,6 +36,8 @@ Updated checksums to reflect changed made in performance tuning ** 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 +Removed stage1_assembler-2's hex0 and hex2 implementation as it ended up being useless in bootstrapping +Removed Checksums.org as it didn't really end up as useful at this time. * 0.0.9 - 2017-08-17 ** Added diff --git a/Checksums.org b/Checksums.org deleted file mode 100644 index 46d5c5a..0000000 --- a/Checksums.org +++ /dev/null @@ -1,50 +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 . - -* x86 -** stage0 -| Filename | compiled binary sha256sum | compiled binary sha1sum | compiled binary md5sum | -|--------------------+------------------------------------------------------------------+------------------------------------------+----------------------------------| -| stage0_monitor.hex | 045ef96e1c8fb011cba89f268f823c06b21f91270fb9afb0af42a1ac8c3ee44b | b26c72762d2f77d8634cb532d581c1e76adceb3f | 9e29544f0220636437741cb5092cc411 | - -** stage1 -| Filename | compiled binary sha256sum | compiled binary sha1sum | compiled binary md5sum | -|-------------------+------------------------------------------------------------------+------------------------------------------+----------------------------------| -| stage1_loader.hex | 047a40efd79a2e1ce06124b9973c0db840cbb39b618dd4cc77036b0ddd54d0d5 | 0f5a2e0ff85cd7bca251e02a44bb5cca6453007a | e095a7a28c7e50c89b0c3edb0d4d97ae | - -* Knight -** stage0 -| Filename | compiled binary sha256sum | compiled binary sha1sum | compiled binary md5sum | -|---------------------+------------------------------------------------------------------+------------------------------------------+----------------------------------| -| stage0_monitor.hex0 | 0a427b14020354d1c785f5f900677e0059fce8f8d4456e9c19e5528cb17101eb | 1365da633f268f551424c621535bd94cfc6bf85b | f0890d7a69ed38f1fc5aa79d6f35c095 | - -** stage1 -| Filename | compiled binary sha256sum | compiled binary sha1sum | compiled binary md5sum | -|-------------------------+------------------------------------------------------------------+------------------------------------------+----------------------------------| -| stage1_assembler-0.hex0 | f8289dfa9dd92e8a1a48f9a624d5d19e4f312b91bc3d1e0796474b46157ec47a | 10b1490182ba3122cd80b1afe9ca11dfa71f2ce4 | a6e0f5348dbb9b049c65b467cf6033e4 | -| stage1_assembler-1.hex0 | e4f0ed6e78ae79bb5e4a4fbde36f085dd0469cd6ae036dce5953b3d1c89801ce | 358a22c6996808ef44a9596ce714970837b53379 | 5c26294c7c59b250fd00d5c3559e68d8 | -| stage1_assembler-1.hex1 | e4f0ed6e78ae79bb5e4a4fbde36f085dd0469cd6ae036dce5953b3d1c89801ce | 358a22c6996808ef44a9596ce714970837b53379 | 5c26294c7c59b250fd00d5c3559e68d8 | -| stage1_assembler-2.hex1 | 61c1b0f2f628847d9491bd678ac7a23231527cc36493b321612f191674ff3c99 | 5d43563ee2297cea95a2117817c5e68b8a9c60d6 | c608fbb896b9931b90e86fe32996ccd8 | -| stage1_assembler-2.hex2 | 61c1b0f2f628847d9491bd678ac7a23231527cc36493b321612f191674ff3c99 | 5d43563ee2297cea95a2117817c5e68b8a9c60d6 | c608fbb896b9931b90e86fe32996ccd8 | - -| Filename | Compiled by | Number of instructions Executed | -| stage1_assembler-0.hex0 | stage1_assembler-0 | 28430 | -| stage1_assembler-1.hex0 | stage1_assembler-0 | 62292 | -| stage1_assembler-1.hex0 | stage1_assembler-1 | 125636 | -| stage1_assembler-1.hex1 | stage1_assembler-1 | 122210 | -| stage1_assembler-2.hex0 | stage1_assembler-0 | 144173 | -| stage1_assembler-2.hex1 | stage1_assembler-1 | 283432 | -| stage1_assembler-2.hex2 | stage1_assembler-2 | 278186 | diff --git a/bootstrapping Steps.org b/bootstrapping Steps.org index 50a22dd..e11447f 100644 --- a/bootstrapping Steps.org +++ b/bootstrapping Steps.org @@ -104,7 +104,7 @@ To build our last and greatest Hex assembler: ./bin/vm --rom roms/stage1_assembler-1 --tape_01 stage1/stage1_assembler-2.hex1 --tape_02 roms/stage1_assembler-2 Now tape_02 contains the last hex assembler we will need -roms/stage1_assembler-2 should have the sha256sum of 61c1b0f2f628847d9491bd678ac7a23231527cc36493b321612f191674ff3c99 +roms/stage1_assembler-2 should have the sha256sum of 7b02babee42a3c05b001fb44fb0917383d8f185e2817d57ad2349a4b36dfa4ed * Step 5 Lets get us a line macro assembler I don't know about you but at this point, I don't wanna convert another instruction into HEX by hand, so to save myself the pain we are going to write the most often ignored but important development in computer programming. The LINE MACRO ASSEMBLER. diff --git a/stage1/stage1_assembler-2.hex0 b/stage1/stage1_assembler-2.hex0 deleted file mode 100644 index 3edc548..0000000 --- a/stage1/stage1_assembler-2.hex0 +++ /dev/null @@ -1,512 +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 -2D2D040c # LOADUI R13 @table ; Where we are putting our table -# ;; We will be using R14 for our condition codes -2D2F7fff # LOADUI R15 0x7FFF ; We will be using R15 for our stack - -# ;; Main program functionality -# ;; Reads in Tape_01 and writes out results onto Tape_02 -# ;; Accepts no arguments and HALTS when done -# :main -# ;; Prep TAPE_01 -2D201100 # LOADUI R0 0x1100 -42100000 # FOPEN_READ -# ;; Intialize environment -0D00002C # FALSE R12 ; Set holder to zero -0D00002B # FALSE R11 ; Set PC counter to zero -2D2A0001 # LOADUI R10 1 ; Our toggle -# ;; Perform first pass -2D0F0040 # CALLI R15 @first_pass -# ;; We need to rewind tape_01 to perform our second pass -2D201100 # LOADUI R0 0x1100 -42100003 # REWIND -# ;; Reintialize environment -0D00002C # FALSE R12 ; Set holder to zero -0D00002B # FALSE R11 ; Set PC counter to zero -2D2A0001 # LOADUI R10 1 ; Our toggle -2D2900ff # LOADUI R9 0xFF ; Byte mask -2D28000f # LOADUI R8 0x0F ; nybble mask -# ;; Prep TAPE_02 -2D201101 # LOADUI R0 0x1101 -42100001 # FOPEN_WRITE -2D0F006c # CALLI R15 @second_pass -# ;; Close up as we are done -2D201100 # LOADUI R0 0x1100 ; Close TAPE_01 -42100002 # FCLOSE -2D201101 # LOADUI R0 0x1101 ; Close TAPE_02 -42100002 # FCLOSE -FFFFFFFF # HALT - - -# ;; First pass function -# ;; Reads Tape_01 and creates our label table -# ;; Will Overwrite R0 R10 R11 -# ;; Returns to Main function when done -# :first_pass -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 -42100100 # FGETC ; Read a Char -# ;; Check for EOF -A0100000 # CMPSKIPI.GE R0 0 -0D01001F # RET R15 -# ;; Check for and deal with label (:) -A030003a # CMPSKIPI.NE R0 58 -3C0000ac # JUMP @storeLabel -# ;; Check for and deal with pointers to labels -# ;; Starting with (@) -A0300040 # CMPSKIPI.NE R0 64 -3C000298 # JUMP @ThrowAwayPointer -# ;; Then dealing with ($) -A0300024 # CMPSKIPI.NE R0 36 -3C000290 # JUMP @ThrowAwayPointer -# ;; Now check for absolute addresses (&) -A0300026 # CMPSKIPI.NE R0 38 -3C000294 # JUMP @ThrowAwayAddress -# ;; Otherwise attempt to process -2D0F02c8 # CALLI R15 @hex ; Convert it -A0100000 # CMPSKIPI.GE R0 0 ; Don't record, nonhex values -3C00ffc8 # JUMP @first_pass ; Move onto Next char -# ;; Determine if we got a full byte -2C9A000c # JUMP.Z R10 @first_pass_0 ; Jump if toggled -# ;; Deal with case of first half of byte -0D00002A # FALSE R10 ; Flip the toggle -3C00ffbc # JUMP @first_pass -# :first_pass_0 -# ;; Deal with case of second half of byte -0D00003A # TRUE R10 ; Flip the toggle -0FBB0001 # ADDUI R11 R11 1 ; increment PC now that that we have a full byte -3C00ffb0 # JUMP @first_pass - - -# ;; Second pass function -# ;; Reads from Tape_01 and uses the values in the table -# ;; To write desired contents onto Tape_02 -# ;; Will Overwrite R0 R10 R11 -# ;; Returns to Main function when done -# :second_pass -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 -42100100 # FGETC ; Read a Char -# ;; Check for EOF -A0100000 # CMPSKIPI.GE R0 0 -0D01001F # RET R15 -# ;; Check for and deal with label -A030003a # CMPSKIPI.NE R0 58 -3C000264 # JUMP @ThrowAwayLabel -# ;; Check for and deal with Pointers to labels -A0300040 # CMPSKIPI.NE R0 64 ; @ for relative -3C000078 # JUMP @StoreRelativePointer -A0300024 # CMPSKIPI.NE R0 36 ; $ for absolute -3C000098 # JUMP @StoreAbsolutePointer -A0300026 # CMPSKIPI.NE R0 38 ; & for address -3C0000b0 # JUMP @StoreAbsoluteAddress -# ;; Process everything else -2D0F0274 # CALLI R15 @hex ; Attempt to Convert it -A0100000 # CMPSKIPI.GE R0 0 ; Don't record, nonhex values -3C00ffc8 # JUMP @second_pass ; Move onto Next char -# ;; Determine if we got a full byte -2C9A0010 # JUMP.Z R10 @second_pass_0 ; Jump if toggled -# ;; Deal with case of first half of byte -05020C08 # AND R12 R0 R8 ; Store our first nibble -0D00002A # FALSE R10 ; Flip the toggle -3C00ffb8 # JUMP @second_pass -# :second_pass_0 -# ;; Deal with case of second half of byte -2D5C0004 # SL0I R12 4 ; Shift our first nybble -05020008 # AND R0 R0 R8 ; Mask out top -0500000C # ADD R0 R0 R12 ; Combine nybbles -0D00003A # TRUE R10 ; Flip the toggle -2D211101 # LOADUI R1 0x1101 ; Write the combined byte -42100200 # FPUTC ; To TAPE_02 -0FBB0001 # ADDUI R11 R11 1 ; increment PC now that that we have a full byte -3C00ff98 # JUMP @second_pass - - -# ;; Store Label function -# ;; Writes out the token and the current PC value -# ;; Its static variable for storing the next index to be used -# ;; Will overwrite R0 -# ;; Returns to first pass when done -# :storeLabel -2E000024 # LOADR R0 @current_index ; Get address of first open index -A0300000 # CMPSKIPI.NE R0 0 ; If zero intialize from R13 -0900040D # COPY R0 R13 -# ;; Store the PC of the label -23B00000 # STORE32 R11 R0 0 -# ;; Store the name of the Label -0F000004 # ADDUI R0 R0 4 ; Increment the offset of the index -2D0F0098 # CALLI R15 @writeout_token -# ;; Update our index -0F00003c # ADDUI R0 R0 60 ; Hopefully our tokens are less than 60 bytes long -2F000008 # STORER R0 @current_index -# ;; And be done -3C00ff20 # JUMP @first_pass -# ;; Where we are storing the location of the next free table entry -# :current_index -00000000 # NOP - - -# ;; StoreRelativepointer function -# ;; Deals with the special case of relative pointers -# ;; Clears Temp -# ;; Stores string in Temp -# ;; Finds match in Table -# ;; Writes out the offset -# ;; Modifies R0 R11 -# ;; Jumps back into Pass2 -# :StoreRelativePointer -# ;; Correct the PC to reflect the size of the pointer -0FBB0002 # ADDUI R11 R11 2 ; Exactly 2 bytes -2D2003cc # LOADUI R0 $Temp ; Set where we want to shove our string -2D0F00c8 # CALLI R15 @Clear_string ; Clear it -2D0F0078 # CALLI R15 @writeout_token ; Write it -2D0F0100 # CALLI R15 @Match_string ; Find the Match -1800fffc # LOAD32 R0 R0 -4 ; Get the value we care about -0500200B # SUB R0 R0 R11 ; Determine the difference -0F000004 # ADDUI R0 R0 4 ; Adjust for relative positioning -2D0F0170 # CALLI R15 @ProcessImmediate ; Write out the value -3C00ff48 # JUMP @second_pass - - -# ;; StoreAbsolutepointer function -# ;; Deals with the special case of absolute pointers -# ;; Clears Temp -# ;; Stores string in Temp -# ;; Finds match in Table -# ;; Writes out the absolute address of match -# ;; Modifies R0 R11 -# ;; Jumps back into Pass2 -# :StoreAbsolutePointer -# ;; Correct the PC to reflect the size of the pointer -0FBB0002 # ADDUI R11 R11 2 ; Exactly 2 bytes -2D2003cc # LOADUI R0 $Temp ; Set where we want to shove our string -2D0F00a0 # CALLI R15 @Clear_string ; Clear it -2D0F0050 # CALLI R15 @writeout_token ; Write it -2D0F00d8 # CALLI R15 @Match_string ; Find the Match -1800fffc # LOAD32 R0 R0 -4 ; Get the value we care about -2D0F0150 # CALLI R15 @ProcessImmediate ; Write out the value -3C00ff28 # JUMP @second_pass - - -# ;; StoreAbsoluteAddress function -# ;; Deal with the special case of absolute Addresses -# ;; Clear Temp -# ;; Stores string in Temp -# ;; Finds match in Table -# ;; Writes out the full absolute address [32 bit machine] -# ;; Modifies R0 R11 -# ;; Jumpbacs back into Pass2 -# :StoreAbsoluteAddress -# ;; COrrect the PC to reflect the size of the address -0FBB0004 # ADDUI R11 R11 4 ; 4 Bytes on 32bit machines -2D2003cc # LOADUI R0 $Temp ; Set where we ant to shove our string -2D0F0080 # CALLI R15 @Clear_string ; Clear it -2D0F0030 # CALLI R15 @writeout_token ; Write it -2D0F00b8 # CALLI R15 @Match_string ; Find the Match -090200EF # PUSHR R14 R15 ; Get a temp storage place -18E0fffc # LOAD32 R14 R0 -4 ; Get the value we care about -0900040E # COPY R0 R14 ; We need to print the top 2 bytes first -2D400010 # SARI R0 16 ; Drop bottom 16 bits -2D0F0124 # CALLI R15 @ProcessImmediate ; Write out top 2 bytes -2D20ffff # LOADUI R0 0xFFFF ; Provide mask to keep bottom 2 bytes -0502000E # AND R0 R0 R14 ; Drop top 16 bits -090280EF # POPR R14 R15 ; Restore R14 -2D0F0114 # CALLI R15 @ProcessImmediate ; Write out bottom 2 bytes -3C00feec # JUMP @second_pass - - -# ;; Writeout Token Function -# ;; Writes the Token [minus first char] to the address -# ;; It recieves in R0 until it reaches a delimiter -# ;; All register values are preserved -# ;; Returns to whatever called it -# :writeout_token -# ;; Preserve registers -0902000F # PUSHR R0 R15 -0902001F # PUSHR R1 R15 -0902002F # PUSHR R2 R15 -# ;; Initialize -09000520 # MOVE R2 R0 ; Set R2 as our index -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 -# ;; Our core loop -# :writeout_token_0 -42100100 # FGETC ; Get another byte -# ;; Deal with termination cases -A0300020 # CMPSKIPI.NE R0 32 ; Finished if space -3C000020 # JUMP @writeout_token_done -A0300009 # CMPSKIPI.NE R0 9 ; Finished if tab -3C000018 # JUMP @writeout_token_done -A030000a # CMPSKIPI.NE R0 10 ; Finished if newline -3C000010 # JUMP @writeout_token_done -# ;; Deal with valid input -21020000 # STORE8 R0 R2 0 ; Write out the byte -0F220001 # ADDUI R2 R2 1 ; Increment -3C00ffdc # JUMP @writeout_token_0 ; Keep looping -# ;; Clean up now that we are done -# :writeout_token_done -# ;; Restore registers -0902802F # POPR R2 R15 -0902801F # POPR R1 R15 -0902800F # POPR R0 R15 -# ;; And be done -0D01001F # RET R15 - - -# ;; Clear string function -# ;; Clears string pointed at by the value of R0 -# ;; Until a null character is reached -# ;; Doesn't alter any registers -# ;; Returns to the function that calls it -# :Clear_string -# ;; Preserve registers -0902000F # PUSHR R0 R15 -0902001F # PUSHR R1 R15 -0902002F # PUSHR R2 R15 -0902003F # PUSHR R3 R15 -# ;; Setup registers -09000510 # MOVE R1 R0 -2D220000 # LOADUI R2 0 -2D230000 # LOADUI R3 0 -# :clear_byte -0503A012 # LOADXU8 R0 R1 R2 ; Get the byte -05049312 # STOREX8 R3 R1 R2 ; Overwrite with a Zero -0F220001 # ADDUI R2 R2 1 ; Prep for next loop -2CA0fff4 # JUMP.NZ R0 @clear_byte ; Stop if byte is NULL -# ;; Done -# ;; Restore registers -0902803F # POPR R3 R15 -0902802F # POPR R2 R15 -0902801F # POPR R1 R15 -0902800F # POPR R0 R15 -0D01001F # RET R15 - - -# ;; Match string function -# ;; Walks down table until match is found -# ;; Then returns address of matching string in R0 -# ;; Returns to whatever called it -# :Match_string -# ;; Preserve registers -0902001F # PUSHR R1 R15 -0902002F # PUSHR R2 R15 -# ;; Initialize for Loop -2D2103cc # LOADUI R1 $Temp ; We always compare against Temp -2D22040c # LOADUI R2 $table ; Begin at start of table -0F220004 # ADDUI R2 R2 4 ; Where the string is located -# ;; Loop until we find a match -# :Match_string_0 -09000402 # COPY R0 R2 ; Set R0 to our current string -2D0F0024 # CALLI R15 @strcmp -2C500010 # JUMP.E R0 @Match_string_1 ; It is a match! -# ;; Prepare for next loop -2D2103cc # LOADUI R1 $Temp ; That function clears R1 -0F220040 # ADDUI R2 R2 64 ; Each Index is 64 bytes -3C00ffec # JUMP @Match_string_0 ; Keep looping -# :Match_string_1 -# ;; Store the correct answer -09000502 # MOVE R0 R2 -# ;; Restore registers -0902802F # POPR R2 R15 -0902801F # POPR R1 R15 -0D01001F # RET R15 - - -# ;; Our simple string compare function -# ;; Recieves two pointers in R0 and R1 -# ;; Returns the difference between the strings in R0 -# ;; Clears R1 -# ;; Returns to whatever called it -# :strcmp -# ;; Preserve registers -0902002F # PUSHR R2 R15 -0902003F # PUSHR R3 R15 -0902004F # PUSHR R4 R15 -# ;; Setup registers -09000520 # MOVE R2 R0 -09000531 # MOVE R3 R1 -2D240000 # LOADUI R4 0 -# :cmpbyte -0503A024 # LOADXU8 R0 R2 R4 ; Get a byte of our first string -0503A134 # LOADXU8 R1 R3 R4 ; Get a byte of our second string -0F440001 # ADDUI R4 R4 1 ; Prep for next loop -05004101 # CMP R1 R0 R1 ; Compare the bytes -A0200000 # CMPSKIPI.E R0 0 ; Stop if byte is NULL -2C51ffec # JUMP.E R1 @cmpbyte ; Loop if bytes are equal -# ;; Done -09000501 # MOVE R0 R1 ; Prepare for return -# ;; Restore registers -0902804F # POPR R4 R15 -0902803F # POPR R3 R15 -0902802F # POPR R2 R15 -0D01001F # RET R15 - - -# ;; Processimmediate Function -# ;; Recieves an integer value in R0 -# ;; Writes out the values to Tape_02 -# ;; Doesn't modify registers -# ;; Returns to whatever called it -# :ProcessImmediate -# ;; Preserve registers -0902000F # PUSHR R0 R15 -0902001F # PUSHR R1 R15 -0902002F # PUSHR R2 R15 -# ;; Break up Immediate -05020209 # AND R2 R0 R9 ; Put lower byte in R2 -2D400008 # SARI R0 8 ; Drop Bottom byte from R0 -05020009 # AND R0 R0 R9 ; Maskout everything outside of top byte -# ;; Write out Top Byte -2D211101 # LOADUI R1 0x1101 ; Write the byte -42100200 # FPUTC ; To TAPE_02 -# ;; Write out bottom Byte -09000502 # MOVE R0 R2 ; Put Lower byte in R0 -2D211101 # LOADUI R1 0x1101 ; Write the byte -42100200 # FPUTC ; To TAPE_02 -# ;; Restore registers -0902802F # POPR R2 R15 -0902801F # POPR R1 R15 -0902800F # POPR R0 R15 -# ;; Be Done -0D01001F # RET R15 - - -# ;; ThrowAwaypointer function -# ;; Handle the special case of a generic problem -# ;; for Pass1, Will update R11 and modify R0 -# ;; Will return to the start of first_pass -# ;; Never call this function, only jump to it -# :ThrowAwayPointer -0FBB0002 # ADDUI R11 R11 2 ; Pointers always take up 2 bytes -2D0F001c # CALLI R15 @throwAwayToken ; Get rid of rest of token -3C00fd44 # JUMP @first_pass ; Then return to the proper place -# ;; ThrowAwayAddress function -# ;; Handle the case of a 32bit absolute address storage -# ;; for Pass1, Will update R11 and modify R0 -# ;; Will return to the start of first_pass -# ;; Never call this function, conly jump to it -# :ThrowAwayAddress -0FBB0004 # ADDUI R11 R11 4 ; Addresses on 32bit systems take up 4 bytes -2D0F0010 # CALLI R15 @throwAwayToken ; Get rid of rest of token -3C00fd38 # JUMP @first_pass ; Then return to the proper place - - -# ;; ThrowAwaylabel function -# ;; Handle the special case of a generic problem -# ;; for Pass2, Will update R11 and modify R0 -# ;; Will return to the start of second_pass -# ;; Never call this function, only jump to it -# :ThrowAwayLabel -2D0F0008 # CALLI R15 @throwAwayToken ; Get rid of rest of token -3C00fd84 # JUMP @second_pass - - -# ;; Throw away token function -# ;; Deals with the general case of not wanting -# ;; The rest of the characters in a token -# ;; This Will alter the values of R0 R1 -# ;; Returns back to whatever called it -# :throwAwayToken -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 -42100100 # FGETC ; Read a Char -# ;; Stop looping if space -A0300020 # CMPSKIPI.NE R0 32 -0D01001F # RET R15 -# ;; Stop looping if tab -A0300009 # CMPSKIPI.NE R0 9 -0D01001F # RET R15 -# ;; Stop looping if newline -A030000a # CMPSKIPI.NE R0 10 -0D01001F # RET R15 -# ;; Otherwise keep looping -3C00ffe0 # JUMP @throwAwayToken - - -# ;; Hex function -# ;; This function is serving three purposes: -# ;; Identifying hex characters -# ;; Purging line comments -# ;; Returning the converted value of a hex character -# ;; This function will alter the values of R0 R14 -# ;; Returns back to whatever called it -# :hex -# ;; Deal with line comments starting with # -1FE00023 # CMPUI R14 R0 35 -2C5E0060 # JUMP.E R14 @ascii_comment -# ;; Deal with line comments starting with ; -1FE0003b # CMPUI R14 R0 59 -2C5E0058 # JUMP.E R14 @ascii_comment -# ;; Deal with all ascii less than '0' -1FE00030 # CMPUI R14 R0 48 -2C8E0048 # JUMP.L R14 @ascii_other -# ;; Deal with '0'-'9' -1FE00039 # CMPUI R14 R0 57 -2C7E0028 # JUMP.LE R14 @ascii_num -# ;; Deal with all ascii less than 'A' -1FE00041 # CMPUI R14 R0 65 -2C8E0038 # JUMP.L R14 @ascii_other -# ;; Deal with 'A'-'F' -1FE00046 # CMPUI R14 R0 70 -2C7E0028 # JUMP.LE R14 @ascii_high -# ;; Deal with all ascii less than 'a' -1FE00061 # CMPUI R14 R0 97 -2C8E0028 # JUMP.L R14 @ascii_other -# ;; Deal with 'a'-'f' -1FE00066 # CMPUI R14 R0 102 -2C7E0010 # JUMP.LE R14 @ascii_low -# ;; Ignore the rest -3C00001c # JUMP @ascii_other -# :ascii_num -11000030 # SUBUI R0 R0 48 -0D01001F # RET R15 -# :ascii_low -11000057 # SUBUI R0 R0 87 -0D01001F # RET R15 -# :ascii_high -11000037 # SUBUI R0 R0 55 -0D01001F # RET R15 -# :ascii_other -0D000030 # TRUE R0 -0D01001F # RET R15 -# :ascii_comment -2D211100 # LOADUI R1 0x1100 ; Read from TAPE_01 -42100100 # FGETC ; Read another char -1FE0000a # CMPUI R14 R0 10 ; Stop at the end of line -2C6Efff4 # JUMP.NE R14 @ascii_comment ; Otherwise keep looping -3C00ffe8 # JUMP @ascii_other - - -# ;; Where we are storing our Temp -# :Temp -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP - - -# ;; Where we will putting our Table -# :table diff --git a/stage1/stage1_assembler-2.hex1 b/stage1/stage1_assembler-2.hex1 index 4286561..841c0b8 100644 --- a/stage1/stage1_assembler-2.hex1 +++ b/stage1/stage1_assembler-2.hex1 @@ -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,40 +14,65 @@ ## You should have received a copy of the GNU General Public License ## along with stage0. If not, see . -# :start -:0 -2D2D @1 # LOADUI R13 @table ; Where we are putting our table -# ;; We will be using R14 for our condition codes -2D2F7fff # LOADUI R15 0x7FFF ; We will be using R15 for our stack +;; Node format: +;; PREV->pointer (register size) +;; Address (register size) +;; NULL terminated string (strln + 1) +# :start 0 +:0 +# ;; R1 is reserved for reading/writing bytes (don't touch) +# ;; We will be using R8 for our malloc pointer +# ;; We will be using R9 for our header size in bytes +# ;; We will be using R10 for our toggle +# ;; We will be using R11 for our PC counter +# ;; We will be using R12 for holding our nybble +# ;; We will be using R13 for our register size in bytes +# ;; We will be using R14 for our head-node + +2D2F @1 # LOADUI R15 $stack ; We will be using R15 for our stack # ;; Main program functionality # ;; Reads in Tape_01 and writes out results onto Tape_02 # ;; Accepts no arguments and HALTS when done -# :main -:3 +# :main 4 +:2 +# ;; Initialize header info +0D000010 # READSCID R0 ; Get process capabilities +B010000f # ANDI R1 R0 0xF ; We only care about size nybble +2D200001 # LOADUI R0 1 ; Assume we are 8bit +05032D01 # SL0 R13 R0 R1 ; Let size nybble correct answer +0900049D # COPY R9 R13 ; Prepare Header size +2D590001 # SL0I R9 1 ; Double to make proper size + # ;; Prep TAPE_01 2D201100 # LOADUI R0 0x1100 42100000 # FOPEN_READ + # ;; Intialize environment +2D211100 # LOADUI R1 0x1100 ; Read from tape_01 0D00002C # FALSE R12 ; Set holder to zero 0D00002B # FALSE R11 ; Set PC counter to zero -2D2A0001 # LOADUI R10 1 ; Our toggle +0D00002A # FALSE R10 ; Our toggle +2D280500 # LOADUI R8 0x500 ; Where we want our heap to start + # ;; Perform first pass -2D0F @2 # CALLI R15 @first_pass +2D0F @3 # CALLI R15 @first_pass + # ;; We need to rewind tape_01 to perform our second pass 2D201100 # LOADUI R0 0x1100 42100003 # REWIND + # ;; Reintialize environment 0D00002C # FALSE R12 ; Set holder to zero 0D00002B # FALSE R11 ; Set PC counter to zero -2D2A0001 # LOADUI R10 1 ; Our toggle -2D2900ff # LOADUI R9 0xFF ; Byte mask -2D28000f # LOADUI R8 0x0F ; nybble mask +0D00002A # FALSE R10 ; Our toggle + # ;; Prep TAPE_02 2D201101 # LOADUI R0 0x1101 42100001 # FOPEN_WRITE 2D0F @4 # CALLI R15 @second_pass + # ;; Close up as we are done 2D201100 # LOADUI R0 0x1100 ; Close TAPE_01 42100002 # FCLOSE @@ -60,41 +85,42 @@ FFFFFFFF # HALT # ;; Reads Tape_01 and creates our label table # ;; Will Overwrite R0 R10 R11 # ;; Returns to Main function when done -# :first_pass -:2 -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 +# :first_pass 70 +:3 42100100 # FGETC ; Read a Char + # ;; Check for EOF A0100000 # CMPSKIPI.GE R0 0 0D01001F # RET R15 + # ;; Check for and deal with label (:) A030003a # CMPSKIPI.NE R0 58 3C00 @5 # JUMP @storeLabel + # ;; Check for and deal with pointers to labels # ;; Starting with (@) A0300040 # CMPSKIPI.NE R0 64 3C00 @6 # JUMP @ThrowAwayPointer + # ;; Then dealing with ($) A0300024 # CMPSKIPI.NE R0 36 3C00 @6 # JUMP @ThrowAwayPointer + # ;; Now check for absolute addresses (&) A0300026 # CMPSKIPI.NE R0 38 -3C00 @v # JUMP @ThrowAwayAddress +3C00 @7 # JUMP @ThrowAwayAddress + # ;; Otherwise attempt to process -2D0F @7 # CALLI R15 @hex ; Convert it -A0100000 # CMPSKIPI.GE R0 0 ; Don't record, nonhex values -3C00 @2 # JUMP @first_pass ; Move onto Next char -# ;; Determine if we got a full byte -2C9A @8 # JUMP.Z R10 @first_pass_0 ; Jump if toggled -# ;; Deal with case of first half of byte -0D00002A # FALSE R10 ; Flip the toggle -3C00 @2 # JUMP @first_pass -# :first_pass_0 -:8 +2D0F @8 # CALLI R15 @hex ; Convert it +2CC0 @3 # JUMP.NP R0 @first_pass ; Don't record, nonhex values + +# ;; Flip the toggle +090006AA # NOT R10 R10 +2C9A @3 # JUMP.Z R10 @first_pass ; Jump if toggled + # ;; Deal with case of second half of byte -0D00003A # TRUE R10 ; Flip the toggle 0FBB0001 # ADDUI R11 R11 1 ; increment PC now that that we have a full byte -3C00 @2 # JUMP @first_pass +3C00 @3 # JUMP @first_pass # ;; Second pass function @@ -102,42 +128,48 @@ A0100000 # CMPSKIPI.GE R0 0 ; Don't record, nonhex values # ;; To write desired contents onto Tape_02 # ;; Will Overwrite R0 R10 R11 # ;; Returns to Main function when done -#:second_pass +# :second_pass b4 :4 -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 42100100 # FGETC ; Read a Char + # ;; Check for EOF A0100000 # CMPSKIPI.GE R0 0 0D01001F # RET R15 + # ;; Check for and deal with label A030003a # CMPSKIPI.NE R0 58 3C00 @9 # JUMP @ThrowAwayLabel + # ;; Check for and deal with Pointers to labels A0300040 # CMPSKIPI.NE R0 64 ; @ for relative 3C00 @a # JUMP @StoreRelativePointer A0300024 # CMPSKIPI.NE R0 36 ; $ for absolute 3C00 @b # JUMP @StoreAbsolutePointer A0300026 # CMPSKIPI.NE R0 38 ; & for address -3C00 @w # JUMP @StoreAbsoluteAddress +3C00 @c # JUMP @StoreAbsoluteAddress + # ;; Process everything else -2D0F @7 # CALLI R15 @hex ; Attempt to Convert it +2D0F @8 # CALLI R15 @hex ; Attempt to Convert it A0100000 # CMPSKIPI.GE R0 0 ; Don't record, nonhex values 3C00 @4 # JUMP @second_pass ; Move onto Next char + # ;; Determine if we got a full byte -2C9A @c # JUMP.Z R10 @second_pass_0 ; Jump if toggled +090006AA # NOT R10 R10 +2C9A @d # JUMP.Z R10 @second_pass_0 ; Jump if toggled + # ;; Deal with case of first half of byte -05020C08 # AND R12 R0 R8 ; Store our first nibble -0D00002A # FALSE R10 ; Flip the toggle +B0C0000f # ANDI R12 R0 0x0F ; Store our first nibble 3C00 @4 # JUMP @second_pass -# :second_pass_0 -:c + +# :second_pass_0 fc +:d # ;; Deal with case of second half of byte 2D5C0004 # SL0I R12 4 ; Shift our first nybble -05020008 # AND R0 R0 R8 ; Mask out top +B000000f # ANDI R0 R0 0x0F ; Mask out top 0500000C # ADD R0 R0 R12 ; Combine nybbles -0D00003A # TRUE R10 ; Flip the toggle 2D211101 # LOADUI R1 0x1101 ; Write the combined byte 42100200 # FPUTC ; To TAPE_02 +2D211100 # LOADUI R1 0x1100 ; Read from tape_01 0FBB0001 # ADDUI R11 R11 1 ; increment PC now that that we have a full byte 3C00 @4 # JUMP @second_pass @@ -147,197 +179,161 @@ A0100000 # CMPSKIPI.GE R0 0 ; Don't record, nonhex values # ;; Its static variable for storing the next index to be used # ;; Will overwrite R0 # ;; Returns to first pass when done -#:storeLabel +# :storeLabel 11c :5 -2E00 @d # LOADR R0 @current_index ; Get address of first open index -A0300000 # CMPSKIPI.NE R0 0 ; If zero intialize from R13 -0900040D # COPY R0 R13 -# ;; Store the PC of the label -23B00000 # STORE32 R11 R0 0 +09000408 # COPY R0 R8 ; get current malloc +05000889 # ADD R8 R8 R9 ; update malloc + +# ;; Add node info +05048B0D # STOREX R11 R0 R13 ; Store the PC of the label +20E00000 # STORE R14 R0 0 ; Store the Previous Head +090005E0 # MOVE R14 R0 ; Update Head + # ;; Store the name of the Label -0F000004 # ADDUI R0 R0 4 ; Increment the offset of the index 2D0F @e # CALLI R15 @writeout_token -# ;; Update our index -0F00003c # ADDUI R0 R0 60 ; Hopefully our tokens are less than 60 bytes long -2F00 @d # STORER R0 @current_index + # ;; And be done -3C00 @2 # JUMP @first_pass -# ;; Where we are storing the location of the next free table entry -# :current_index -:d -00000000 # NOP +3C00 @3 # JUMP @first_pass # ;; StoreRelativepointer function # ;; Deals with the special case of relative pointers -# ;; Clears Temp -# ;; Stores string in Temp +# ;; Stores string # ;; Finds match in Table # ;; Writes out the offset # ;; Modifies R0 R11 # ;; Jumps back into Pass2 -# :StoreRelativePointer +# :StoreRelativePointer 138 :a # ;; Correct the PC to reflect the size of the pointer 0FBB0002 # ADDUI R11 R11 2 ; Exactly 2 bytes -2D2003cc # LOADUI R0 $Temp ; Set where we want to shove our string -2D0F @f # CALLI R15 @Clear_string ; Clear it -2D0F @e # CALLI R15 @writeout_token ; Write it -2D0F @g # CALLI R15 @Match_string ; Find the Match -1800fffc # LOAD32 R0 R0 -4 ; Get the value we care about +2D0F @o # CALLI R15 @Match_string ; Find the Match 0500200B # SUB R0 R0 R11 ; Determine the difference 0F000004 # ADDUI R0 R0 4 ; Adjust for relative positioning -2D0F @h # CALLI R15 @ProcessImmediate ; Write out the value +2D0F @p # CALLI R15 @ProcessImmediate ; Write out the value 3C00 @4 # JUMP @second_pass # ;; StoreAbsolutepointer function # ;; Deals with the special case of absolute pointers -# ;; Clears Temp -# ;; Stores string in Temp +# ;; Stores string # ;; Finds match in Table # ;; Writes out the absolute address of match # ;; Modifies R0 R11 # ;; Jumps back into Pass2 -# :StoreAbsolutePointer +# :StoreAbsolutePointer 150 :b # ;; Correct the PC to reflect the size of the pointer 0FBB0002 # ADDUI R11 R11 2 ; Exactly 2 bytes -2D2003cc # LOADUI R0 $Temp ; Set where we want to shove our string -2D0F @f # CALLI R15 @Clear_string ; Clear it -2D0F @e # CALLI R15 @writeout_token ; Write it -2D0F @g # CALLI R15 @Match_string ; Find the Match -1800fffc # LOAD32 R0 R0 -4 ; Get the value we care about -2D0F @h # CALLI R15 @ProcessImmediate ; Write out the value +2D0F @o # CALLI R15 @Match_string ; Find the Match +2D0F @p # CALLI R15 @ProcessImmediate ; Write out the value 3C00 @4 # JUMP @second_pass # ;; StoreAbsoluteAddress function # ;; Deal with the special case of absolute Addresses -# ;; Clear Temp -# ;; Stores string in Temp +# ;; Stores string # ;; Finds match in Table # ;; Writes out the full absolute address [32 bit machine] # ;; Modifies R0 R11 # ;; Jumpbacs back into Pass2 -# :StoreAbsoluteAddress +# :StoreAbsoluteAddress 160 +:c # ;; COrrect the PC to reflect the size of the address -:w 0FBB0004 # ADDUI R11 R11 4 ; 4 Bytes on 32bit machines -2D2003cc # LOADUI R0 $Temp ; Set where we ant to shove our string -2D0F @f # CALLI R15 @Clear_string ; Clear it -2D0F @e # CALLI R15 @writeout_token ; Write it -2D0F @g # CALLI R15 @Match_string ; Find the Match -090200EF # PUSHR R14 R15 ; Get a temp storage place -18E0fffc # LOAD32 R14 R0 -4 ; Get the value we care about -0900040E # COPY R0 R14 ; We need to print the top 2 bytes first +2D0F @o # CALLI R15 @Match_string ; Find the Match +B020ffff # ANDI R2 R0 0xFFFF ; Save bottom half for next function 2D400010 # SARI R0 16 ; Drop bottom 16 bits -2D0F @h # CALLI R15 @ProcessImmediate ; Write out top 2 bytes -2D20ffff # LOADUI R0 0xFFFF ; Provide mask to keep bottom 2 bytes -0502000E # AND R0 R0 R14 ; Drop top 16 bits -090280EF # POPR R14 R15 ; Restore R14 -2D0F @h # CALLI R15 @ProcessImmediate ; Write out bottom 2 bytes +2D0F @p # CALLI R15 @ProcessImmediate ; Write out top 2 bytes +09000502 # MOVE R0 R2 ; Use the saved 16bits +2D0F @p # CALLI R15 @ProcessImmediate ; Write out bottom 2 bytes 3C00 @4 # JUMP @second_pass # ;; Writeout Token Function # ;; Writes the Token [minus first char] to the address -# ;; It recieves in R0 until it reaches a delimiter -# ;; All register values are preserved -# ;; Returns to whatever called it -# :writeout_token +# ;; given by malloc and updates malloc pointer +# ;; Returns starting address of string +# :writeout_token 180 :e # ;; Preserve registers -0902000F # PUSHR R0 R15 0902001F # PUSHR R1 R15 0902002F # PUSHR R2 R15 + # ;; Initialize -09000520 # MOVE R2 R0 ; Set R2 as our index -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 +09000428 # COPY R2 R8 ; Get current malloc pointer + # ;; Our core loop -# :writeout_token_0 -:j +# :writeout_token_0 18c +:r 42100100 # FGETC ; Get another byte + # ;; Deal with termination cases A0300020 # CMPSKIPI.NE R0 32 ; Finished if space -3C00 @i # JUMP @writeout_token_done +3C00 @q # JUMP @writeout_token_done A0300009 # CMPSKIPI.NE R0 9 ; Finished if tab -3C00 @i # JUMP @writeout_token_done +3C00 @q # JUMP @writeout_token_done A030000a # CMPSKIPI.NE R0 10 ; Finished if newline -3C00 @i # JUMP @writeout_token_done +3C00 @q # JUMP @writeout_token_done +A030ffff # CMPSKIPI.NE R0 -1 ; Finished if EOF +3C00 @q # JUMP @writeout_token_done + # ;; Deal with valid input -21020000 # STORE8 R0 R2 0 ; Write out the byte -0F220001 # ADDUI R2 R2 1 ; Increment -3C00 @j # JUMP @writeout_token_0 ; Keep looping +21080000 # STORE8 R0 R8 0 ; Write out the byte +0F880001 # ADDUI R8 R8 1 ; Increment +3C00 @r # JUMP @writeout_token_0 ; Keep looping + # ;; Clean up now that we are done -# :writeout_token_done -:i +# :writeout_token_done 1bc +:q +# ;; Fix malloc +0F880001 # ADDUI R8 R8 1 + +# ;; Prepare for return +09000502 # MOVE R0 R2 + # ;; Restore registers 0902802F # POPR R2 R15 0902801F # POPR R1 R15 -0902800F # POPR R0 R15 + # ;; And be done 0D01001F # RET R15 -# ;; Clear string function -# ;; Clears string pointed at by the value of R0 -# ;; Until a null character is reached -# ;; Doesn't alter any registers -# ;; Returns to the function that calls it -# :Clear_string -:f -# ;; Preserve registers -0902000F # PUSHR R0 R15 -0902001F # PUSHR R1 R15 -0902002F # PUSHR R2 R15 -0902003F # PUSHR R3 R15 -# ;; Setup registers -09000510 # MOVE R1 R0 -2D220000 # LOADUI R2 0 -2D230000 # LOADUI R3 0 -# :clear_byte -:k -0503A012 # LOADXU8 R0 R1 R2 ; Get the byte -05049312 # STOREX8 R3 R1 R2 ; Overwrite with a Zero -0F220001 # ADDUI R2 R2 1 ; Prep for next loop -2CA0 @k # JUMP.NZ R0 @clear_byte ; Stop if byte is NULL -# ;; Done -# ;; Restore registers -0902803F # POPR R3 R15 -0902802F # POPR R2 R15 -0902801F # POPR R1 R15 -0902800F # POPR R0 R15 -0D01001F # RET R15 - - # ;; Match string function -# ;; Walks down table until match is found -# ;; Then returns address of matching string in R0 +# ;; Walks down list until match is found or returns -1 +# ;; Reads a token +# ;; Then returns address of match in R0 # ;; Returns to whatever called it -# :Match_string -:g +# :Match_string 1d0 +:o # ;; Preserve registers 0902001F # PUSHR R1 R15 0902002F # PUSHR R2 R15 + # ;; Initialize for Loop -2D2103cc # LOADUI R1 $Temp ; We always compare against Temp -2D22040c # LOADUI R2 $table ; Begin at start of table -0F220004 # ADDUI R2 R2 4 ; Where the string is located +2D0F @e # CALLI R15 @writeout_token ; Get our desired string +09000510 # MOVE R1 R0 ; Position our desired string +0900042E # COPY R2 R14 ; Begin at our head node + # ;; Loop until we find a match -# :Match_string_0 -:n -09000402 # COPY R0 R2 ; Set R0 to our current string -2D0F @l # CALLI R15 @strcmp -2C50 @m # JUMP.E R0 @Match_string_1 ; It is a match! +# :Match_string_0 1e4 +:h +05000029 # ADD R0 R2 R9 ; Where the string is located +2D0F @f # CALLI R15 @strcmp +2C50 @g # JUMP.E R0 @Match_string_1 ; It is a match! + # ;; Prepare for next loop -2D2103cc # LOADUI R1 $Temp ; That function clears R1 -0F220040 # ADDUI R2 R2 64 ; Each Index is 64 bytes -3C00 @n # JUMP @Match_string_0 ; Keep looping -# :Match_string_1 -:m +13220000 # LOAD R2 R2 0 ; Move to next node +2CA2 @h # JUMP.NZ R2 @Match_string_0 ; Keep looping +0D000032 # TRUE R2 ; Set result to -1 if not found + +# :Match_string_1 1fc +:g # ;; Store the correct answer -09000502 # MOVE R0 R2 +A022ffff # CMPSKIPI.E R2 -1 ; Otherwise get the value +0503802D # LOADX R0 R2 R13 ; Get the value we care about + # ;; Restore registers 0902802F # POPR R2 R15 0902801F # POPR R1 R15 @@ -347,32 +343,37 @@ A030000a # CMPSKIPI.NE R0 10 ; Finished if newline # ;; Our simple string compare function # ;; Recieves two pointers in R0 and R1 # ;; Returns the difference between the strings in R0 -# ;; Clears R1 # ;; Returns to whatever called it -# :strcmp -:l +# :strcmp 210 +:f # ;; Preserve registers +0902001F # PUSHR R1 R15 0902002F # PUSHR R2 R15 0902003F # PUSHR R3 R15 0902004F # PUSHR R4 R15 + # ;; Setup registers 09000520 # MOVE R2 R0 09000531 # MOVE R3 R1 2D240000 # LOADUI R4 0 -# :cmpbyte -:o + +# :cmpbyte 22c +:i 0503A024 # LOADXU8 R0 R2 R4 ; Get a byte of our first string 0503A134 # LOADXU8 R1 R3 R4 ; Get a byte of our second string 0F440001 # ADDUI R4 R4 1 ; Prep for next loop 05004101 # CMP R1 R0 R1 ; Compare the bytes A0200000 # CMPSKIPI.E R0 0 ; Stop if byte is NULL -2C51 @o # JUMP.E R1 @cmpbyte ; Loop if bytes are equal +2C51 @i # JUMP.E R1 @cmpbyte ; Loop if bytes are equal + # ;; Done 09000501 # MOVE R0 R1 ; Prepare for return + # ;; Restore registers 0902804F # POPR R4 R15 0902803F # POPR R3 R15 0902802F # POPR R2 R15 +0902801F # POPR R1 R15 0D01001F # RET R15 @@ -381,27 +382,31 @@ A0200000 # CMPSKIPI.E R0 0 ; Stop if byte is NULL # ;; Writes out the values to Tape_02 # ;; Doesn't modify registers # ;; Returns to whatever called it -# :ProcessImmediate -:h +# :ProcessImmediate 25c +:p # ;; Preserve registers 0902000F # PUSHR R0 R15 0902001F # PUSHR R1 R15 0902002F # PUSHR R2 R15 + # ;; Break up Immediate -05020209 # AND R2 R0 R9 ; Put lower byte in R2 +B02000ff # ANDI R2 R0 0xFF ; Put lower byte in R2 2D400008 # SARI R0 8 ; Drop Bottom byte from R0 -05020009 # AND R0 R0 R9 ; Maskout everything outside of top byte +B00000ff # ANDI R0 R0 0xFF ; Maskout everything outside of top byte + # ;; Write out Top Byte 2D211101 # LOADUI R1 0x1101 ; Write the byte 42100200 # FPUTC ; To TAPE_02 + # ;; Write out bottom Byte 09000502 # MOVE R0 R2 ; Put Lower byte in R0 -2D211101 # LOADUI R1 0x1101 ; Write the byte 42100200 # FPUTC ; To TAPE_02 + # ;; Restore registers 0902802F # POPR R2 R15 0902801F # POPR R1 R15 0902800F # POPR R0 R15 + # ;; Be Done 0D01001F # RET R15 @@ -411,11 +416,11 @@ A0200000 # CMPSKIPI.E R0 0 ; Stop if byte is NULL # ;; for Pass1, Will update R11 and modify R0 # ;; Will return to the start of first_pass # ;; Never call this function, only jump to it -# :ThrowAwayPointer +# :ThrowAwayPointer 294 :6 0FBB0002 # ADDUI R11 R11 2 ; Pointers always take up 2 bytes -2D0F @p # CALLI R15 @throwAwayToken ; Get rid of rest of token -3C00 @2 # JUMP @first_pass ; Then return to the proper place +2D0F @j # CALLI R15 @throwAwayToken ; Get rid of rest of token +3C00 @3 # JUMP @first_pass ; Then return to the proper place # ;; ThrowAwayAddress function @@ -423,11 +428,11 @@ A0200000 # CMPSKIPI.E R0 0 ; Stop if byte is NULL # ;; for Pass1, Will update R11 and modify R0 # ;; Will return to the start of first_pass # ;; Never call this function, conly jump to it -# :ThrowAwayAddress -:v +# :ThrowAwayAddress 2a0 +:7 0FBB0004 # ADDUI R11 R11 4 ; Addresses on 32bit systems take up 4 bytes -2D0F @p # CALLI R15 @throwAwayToken ; Get rid of rest of token -3C00 @2 # JUMP @first_pass ; Then return to the proper place +2D0F @j # CALLI R15 @throwAwayToken ; Get rid of rest of token +3C00 @3 # JUMP @first_pass ; Then return to the proper place # ;; ThrowAwaylabel function @@ -435,31 +440,39 @@ A0200000 # CMPSKIPI.E R0 0 ; Stop if byte is NULL # ;; for Pass2, Will update R11 and modify R0 # ;; Will return to the start of second_pass # ;; Never call this function, only jump to it -# :ThrowAwayLabel +# :ThrowAwayLabel 2ac :9 -2D0F @p # CALLI R15 @throwAwayToken ; Get rid of rest of token +2D0F @j # CALLI R15 @throwAwayToken ; Get rid of rest of token 3C00 @4 # JUMP @second_pass + # ;; Throw away token function # ;; Deals with the general case of not wanting # ;; The rest of the characters in a token # ;; This Will alter the values of R0 R1 # ;; Returns back to whatever called it -# :throwAwayToken -:p -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 +# :throwAwayToken 2b4 +:j 42100100 # FGETC ; Read a Char + # ;; Stop looping if space A0300020 # CMPSKIPI.NE R0 32 0D01001F # RET R15 + # ;; Stop looping if tab A0300009 # CMPSKIPI.NE R0 9 0D01001F # RET R15 + # ;; Stop looping if newline A030000a # CMPSKIPI.NE R0 10 0D01001F # RET R15 + +# ;; Stop looping if EOF +A030ffff # CMPSKIPI.NE R0 -1 +0D01001F # RET R15 + # ;; Otherwise keep looping -3C00 @p # JUMP @throwAwayToken +3C00 @j # JUMP @throwAwayToken # ;; Hex function @@ -467,82 +480,60 @@ A030000a # CMPSKIPI.NE R0 10 # ;; Identifying hex characters # ;; Purging line comments # ;; Returning the converted value of a hex character -# ;; This function will alter the values of R0 R14 +# ;; This function will alter the values of R0 # ;; Returns back to whatever called it -# :hex -:7 +# :hex 2dc +:8 # ;; Deal with line comments starting with # -1FE00023 # CMPUI R14 R0 35 -2C5E @q # JUMP.E R14 @ascii_comment +A0300023 # CMPSKIPI.NE R0 35 +3C00 @k # JUMP @ascii_comment + # ;; Deal with line comments starting with ; -1FE0003b # CMPUI R14 R0 59 -2C5E @q # JUMP.E R14 @ascii_comment +A030003b # CMPSKIPI.NE R0 59 +3C00 @k # JUMP @ascii_comment + # ;; Deal with all ascii less than '0' -1FE00030 # CMPUI R14 R0 48 -2C8E @r # JUMP.L R14 @ascii_other +A0100030 # CMPSKIPI.GE R0 48 +3C00 @l # JUMP @ascii_other + # ;; Deal with '0'-'9' -1FE00039 # CMPUI R14 R0 57 -2C7E @s # JUMP.LE R14 @ascii_num +A0000039 # CMPSKIPI.G R0 57 +3C00 @m # JUMP @ascii_num + # ;; Deal with all ascii less than 'A' -1FE00041 # CMPUI R14 R0 65 -2C8E @r # JUMP.L R14 @ascii_other +A0100041 # CMPSKIPI.GE R0 65 +3C00 @l # JUMP @ascii_other + +# ;; Unset high bit to set everything into uppercase +B00000df # ANDI R0 R0 0xDF + # ;; Deal with 'A'-'F' -1FE00046 # CMPUI R14 R0 70 -2C7E @t # JUMP.LE R14 @ascii_high -# ;; Deal with all ascii less than 'a' -1FE00061 # CMPUI R14 R0 97 -2C8E @r # JUMP.L R14 @ascii_other -# ;; Deal with 'a'-'f' -1FE00066 # CMPUI R14 R0 102 -2C7E @u # JUMP.LE R14 @ascii_low +A0000046 # CMPSKIPI.G R0 70 +3C00 @n # JUMP @ascii_high + # ;; Ignore the rest -3C00 @r # JUMP @ascii_other -# :ascii_num -:s +3C00 @l # JUMP @ascii_other + + +# :ascii_num 314 +:m 11000030 # SUBUI R0 R0 48 0D01001F # RET R15 -# :ascii_low -:u -11000057 # SUBUI R0 R0 87 -0D01001F # RET R15 -# :ascii_high -:t +# :ascii_high 31c +:n 11000037 # SUBUI R0 R0 55 0D01001F # RET R15 -# :ascii_other -:r +# :ascii_comment 324 +:k +42100100 # FGETC ; Read another char +2CC0 @l # JUMP.NP R0 @ascii_other ; Stop with EOF +A020000a # CMPSKIPI.E R0 10 ; Stop at the end of line +3C00 @k # JUMP @ascii_comment ; Otherwise keep looping +# :ascii_other 334 +:l 0D000030 # TRUE R0 0D01001F # RET R15 -# :ascii_comment -:q -2D211100 # LOADUI R1 0x1100 ; Read from TAPE_01 -42100100 # FGETC ; Read another char -1FE0000a # CMPUI R14 R0 10 ; Stop at the end of line -2C6E @q # JUMP.NE R14 @ascii_comment ; Otherwise keep looping -3C00 @r # JUMP @ascii_other +# ;; Where we will putting our stack - -# ;; Where we are storing our Temp -# :Temp -:z -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP - - -# ;; Where we will putting our Table -# :table +# :stack 33c :1 diff --git a/stage1/stage1_assembler-2.hex2 b/stage1/stage1_assembler-2.hex2 deleted file mode 100644 index 183dee9..0000000 --- a/stage1/stage1_assembler-2.hex2 +++ /dev/null @@ -1,513 +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 -2D2D @table # LOADUI R13 @table ; Where we are putting our table -# ;; We will be using R14 for our condition codes -2D2F7fff # LOADUI R15 0x7FFF ; We will be using R15 for our stack - - -# ;; Main program functionality -# ;; Reads in Tape_01 and writes out results onto Tape_02 -# ;; Accepts no arguments and HALTS when done -:main -# ;; Prep TAPE_01 -2D201100 # LOADUI R0 0x1100 -42100000 # FOPEN_READ -# ;; Intialize environment -0D00002C # FALSE R12 ; Set holder to zero -0D00002B # FALSE R11 ; Set PC counter to zero -2D2A0001 # LOADUI R10 1 ; Our toggle -# ;; Perform first pass -2D0F @first_pass # CALLI R15 @first_pass -# ;; We need to rewind tape_01 to perform our second pass -2D201100 # LOADUI R0 0x1100 -42100003 # REWIND -# ;; Reintialize environment -0D00002C # FALSE R12 ; Set holder to zero -0D00002B # FALSE R11 ; Set PC counter to zero -2D2A0001 # LOADUI R10 1 ; Our toggle -2D2900ff # LOADUI R9 0xFF ; Byte mask -2D28000f # LOADUI R8 0x0F ; nybble mask -# ;; Prep TAPE_02 -2D201101 # LOADUI R0 0x1101 -42100001 # FOPEN_WRITE -2D0F @second_pass # CALLI R15 @second_pass -# ;; Close up as we are done -2D201100 # LOADUI R0 0x1100 ; Close TAPE_01 -42100002 # FCLOSE -2D201101 # LOADUI R0 0x1101 ; Close TAPE_02 -42100002 # FCLOSE -FFFFFFFF # HALT - - -# ;; First pass function -# ;; Reads Tape_01 and creates our label table -# ;; Will Overwrite R0 R10 R11 -# ;; Returns to Main function when done -:first_pass -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 -42100100 # FGETC ; Read a Char -# ;; Check for EOF -A0100000 # CMPSKIPI.GE R0 0 -0D01001F # RET R15 -# ;; Check for and deal with label (:) -A030003a # CMPSKIPI.NE R0 58 -3C00 @storeLabel # JUMP @storeLabel -# ;; Check for and deal with pointers to labels -# ;; Starting with (@) -A0300040 # CMPSKIPI.NE R0 64 -3C00 @ThrowAwayPointer # JUMP @ThrowAwayPointer -# ;; Then dealing with ($) -A0300024 # CMPSKIPI.NE R0 36 -3C00 @ThrowAwayPointer # JUMP @ThrowAwayPointer -# ;; Now check for absolute addresses (&) -A0300026 # CMPSKIPI.NE R0 38 -3C00 @ThrowAwayAddress # JUMP @ThrowAwayAddress -# ;; Otherwise attempt to process -2D0F @hex # CALLI R15 @hex ; Convert it -A0100000 # CMPSKIPI.GE R0 0 ; Don't record, nonhex values -3C00 @first_pass # JUMP @first_pass ; Move onto Next char -# ;; Determine if we got a full byte -2C9A @first_pass_0 # JUMP.Z R10 @first_pass_0 ; Jump if toggled -# ;; Deal with case of first half of byte -0D00002A # FALSE R10 ; Flip the toggle -3C00 @first_pass # JUMP @first_pass -:first_pass_0 -# ;; Deal with case of second half of byte -0D00003A # TRUE R10 ; Flip the toggle -0FBB0001 # ADDUI R11 R11 1 ; increment PC now that that we have a full byte -3C00 @first_pass # JUMP @first_pass - - -# ;; Second pass function -# ;; Reads from Tape_01 and uses the values in the table -# ;; To write desired contents onto Tape_02 -# ;; Will Overwrite R0 R10 R11 -# ;; Returns to Main function when done -:second_pass -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 -42100100 # FGETC ; Read a Char -# ;; Check for EOF -A0100000 # CMPSKIPI.GE R0 0 -0D01001F # RET R15 -# ;; Check for and deal with label -A030003a # CMPSKIPI.NE R0 58 -3C00 @ThrowAwayLabel # JUMP @ThrowAwayLabel -# ;; Check for and deal with Pointers to labels -A0300040 # CMPSKIPI.NE R0 64 ; @ for relative -3C00 @StoreRelativePointer # JUMP @StoreRelativePointer -A0300024 # CMPSKIPI.NE R0 36 ; $ for absolute -3C00 @StoreAbsolutePointer # JUMP @StoreAbsolutePointer -A0300026 # CMPSKIPI.NE R0 38 ; & for address -3C00 @StoreAbsoluteAddress # JUMP @StoreAbsoluteAddress -# ;; Process everything else -2D0F @hex # CALLI R15 @hex ; Attempt to Convert it -A0100000 # CMPSKIPI.GE R0 0 ; Don't record, nonhex values -3C00 @second_pass # JUMP @second_pass ; Move onto Next char -# ;; Determine if we got a full byte -2C9A @second_pass_0 # JUMP.Z R10 @second_pass_0 ; Jump if toggled -# ;; Deal with case of first half of byte -05020C08 # AND R12 R0 R8 ; Store our first nibble -0D00002A # FALSE R10 ; Flip the toggle -3C00 @second_pass # JUMP @second_pass -:second_pass_0 -# ;; Deal with case of second half of byte -2D5C0004 # SL0I R12 4 ; Shift our first nybble -05020008 # AND R0 R0 R8 ; Mask out top -0500000C # ADD R0 R0 R12 ; Combine nybbles -0D00003A # TRUE R10 ; Flip the toggle -2D211101 # LOADUI R1 0x1101 ; Write the combined byte -42100200 # FPUTC ; To TAPE_02 -0FBB0001 # ADDUI R11 R11 1 ; increment PC now that that we have a full byte -3C00 @second_pass # JUMP @second_pass - - -# ;; Store Label function -# ;; Writes out the token and the current PC value -# ;; Its static variable for storing the next index to be used -# ;; Will overwrite R0 -# ;; Returns to first pass when done -:storeLabel -2E00 @current_index # LOADR R0 @current_index ; Get address of first open index -A0300000 # CMPSKIPI.NE R0 0 ; If zero intialize from R13 -0900040D # COPY R0 R13 -# ;; Store the PC of the label -23B00000 # STORE32 R11 R0 0 -# ;; Store the name of the Label -0F000004 # ADDUI R0 R0 4 ; Increment the offset of the index -2D0F @writeout_token # CALLI R15 @writeout_token -# ;; Update our index -0F00003c # ADDUI R0 R0 60 ; Hopefully our tokens are less than 60 bytes long -2F00 @current_index # STORER R0 @current_index -# ;; And be done -3C00 @first_pass # JUMP @first_pass -# ;; Where we are storing the location of the next free table entry -:current_index -00000000 # NOP - - -# ;; StoreRelativepointer function -# ;; Deals with the special case of relative pointers -# ;; Clears Temp -# ;; Stores string in Temp -# ;; Finds match in Table -# ;; Writes out the offset -# ;; Modifies R0 R11 -# ;; Jumps back into Pass2 -:StoreRelativePointer -# ;; Correct the PC to reflect the size of the pointer -0FBB0002 # ADDUI R11 R11 2 ; Exactly 2 bytes -2D20 $Temp # LOADUI R0 $Temp ; Set where we want to shove our string -2D0F @Clear_string # CALLI R15 @Clear_string ; Clear it -2D0F @writeout_token # CALLI R15 @writeout_token ; Write it -2D0F @Match_string # CALLI R15 @Match_string ; Find the Match -1800fffc # LOAD32 R0 R0 -4 ; Get the value we care about -0500200B # SUB R0 R0 R11 ; Determine the difference -0F000004 # ADDUI R0 R0 4 ; Adjust for relative positioning -2D0F @ProcessImmediate # CALLI R15 @ProcessImmediate ; Write out the value -3C00 @second_pass # JUMP @second_pass - - -# ;; StoreAbsolutepointer function -# ;; Deals with the special case of absolute pointers -# ;; Clears Temp -# ;; Stores string in Temp -# ;; Finds match in Table -# ;; Writes out the absolute address of match -# ;; Modifies R0 R11 -# ;; Jumps back into Pass2 -:StoreAbsolutePointer -# ;; Correct the PC to reflect the size of the pointer -0FBB0002 # ADDUI R11 R11 2 ; Exactly 2 bytes -2D20 $Temp # LOADUI R0 $Temp ; Set where we want to shove our string -2D0F @Clear_string # CALLI R15 @Clear_string ; Clear it -2D0F @writeout_token # CALLI R15 @writeout_token ; Write it -2D0F @Match_string # CALLI R15 @Match_string ; Find the Match -1800fffc # LOAD32 R0 R0 -4 ; Get the value we care about -2D0F @ProcessImmediate # CALLI R15 @ProcessImmediate ; Write out the value -3C00 @second_pass # JUMP @second_pass - - -# ;; StoreAbsoluteAddress function -# ;; Deal with the special case of absolute Addresses -# ;; Clear Temp -# ;; Stores string in Temp -# ;; Finds match in Table -# ;; Writes out the full absolute address [32 bit machine] -# ;; Modifies R0 R11 -# ;; Jumpbacs back into Pass2 -:StoreAbsoluteAddress -# ;; COrrect the PC to reflect the size of the address -0FBB0004 # ADDUI R11 R11 4 ; 4 Bytes on 32bit machines -2D20 $Temp # LOADUI R0 $Temp ; Set where we ant to shove our string -2D0F @Clear_string # CALLI R15 @Clear_string ; Clear it -2D0F @writeout_token # CALLI R15 @writeout_token ; Write it -2D0F @Match_string # CALLI R15 @Match_string ; Find the Match -090200EF # PUSHR R14 R15 ; Get a temp storage place -18E0fffc # LOAD32 R14 R0 -4 ; Get the value we care about -0900040E # COPY R0 R14 ; We need to print the top 2 bytes first -2D400010 # SARI R0 16 ; Drop bottom 16 bits -2D0F @ProcessImmediate # CALLI R15 @ProcessImmediate ; Write out top 2 bytes -2D20ffff # LOADUI R0 0xFFFF ; Provide mask to keep bottom 2 bytes -0502000E # AND R0 R0 R14 ; Drop top 16 bits -090280EF # POPR R14 R15 ; Restore R14 -2D0F @ProcessImmediate # CALLI R15 @ProcessImmediate ; Write out bottom 2 bytes -3C00 @second_pass # JUMP @second_pass - - -# ;; Writeout Token Function -# ;; Writes the Token [minus first char] to the address -# ;; It recieves in R0 until it reaches a delimiter -# ;; All register values are preserved -# ;; Returns to whatever called it -:writeout_token -# ;; Preserve registers -0902000F # PUSHR R0 R15 -0902001F # PUSHR R1 R15 -0902002F # PUSHR R2 R15 -# ;; Initialize -09000520 # MOVE R2 R0 ; Set R2 as our index -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 -# ;; Our core loop -:writeout_token_0 -42100100 # FGETC ; Get another byte -# ;; Deal with termination cases -A0300020 # CMPSKIPI.NE R0 32 ; Finished if space -3C00 @writeout_token_done # JUMP @writeout_token_done -A0300009 # CMPSKIPI.NE R0 9 ; Finished if tab -3C00 @writeout_token_done # JUMP @writeout_token_done -A030000a # CMPSKIPI.NE R0 10 ; Finished if newline -3C00 @writeout_token_done # JUMP @writeout_token_done -# ;; Deal with valid input -21020000 # STORE8 R0 R2 0 ; Write out the byte -0F220001 # ADDUI R2 R2 1 ; Increment -3C00 @writeout_token_0 # JUMP @writeout_token_0 ; Keep looping -# ;; Clean up now that we are done -:writeout_token_done -# ;; Restore registers -0902802F # POPR R2 R15 -0902801F # POPR R1 R15 -0902800F # POPR R0 R15 -# ;; And be done -0D01001F # RET R15 - - -# ;; Clear string function -# ;; Clears string pointed at by the value of R0 -# ;; Until a null character is reached -# ;; Doesn't alter any registers -# ;; Returns to the function that calls it -:Clear_string -# ;; Preserve registers -0902000F # PUSHR R0 R15 -0902001F # PUSHR R1 R15 -0902002F # PUSHR R2 R15 -0902003F # PUSHR R3 R15 -# ;; Setup registers -09000510 # MOVE R1 R0 -2D220000 # LOADUI R2 0 -2D230000 # LOADUI R3 0 -:clear_byte -0503A012 # LOADXU8 R0 R1 R2 ; Get the byte -05049312 # STOREX8 R3 R1 R2 ; Overwrite with a Zero -0F220001 # ADDUI R2 R2 1 ; Prep for next loop -2CA0 @clear_byte # JUMP.NZ R0 @clear_byte ; Stop if byte is NULL -# ;; Done -# ;; Restore registers -0902803F # POPR R3 R15 -0902802F # POPR R2 R15 -0902801F # POPR R1 R15 -0902800F # POPR R0 R15 -0D01001F # RET R15 - - -# ;; Match string function -# ;; Walks down table until match is found -# ;; Then returns address of matching string in R0 -# ;; Returns to whatever called it -:Match_string -# ;; Preserve registers -0902001F # PUSHR R1 R15 -0902002F # PUSHR R2 R15 -# ;; Initialize for Loop -2D21 $Temp # LOADUI R1 $Temp ; We always compare against Temp -2D22 $table # LOADUI R2 $table ; Begin at start of table -0F220004 # ADDUI R2 R2 4 ; Where the string is located -# ;; Loop until we find a match -:Match_string_0 -09000402 # COPY R0 R2 ; Set R0 to our current string -2D0F @strcmp # CALLI R15 @strcmp -2C50 @Match_string_1 # JUMP.E R0 @Match_string_1 ; It is a match! -# ;; Prepare for next loop -2D21 $Temp # LOADUI R1 $Temp ; That function clears R1 -0F220040 # ADDUI R2 R2 64 ; Each Index is 64 bytes -3C00 @Match_string_0 # JUMP @Match_string_0 ; Keep looping -:Match_string_1 -# ;; Store the correct answer -09000502 # MOVE R0 R2 -# ;; Restore registers -0902802F # POPR R2 R15 -0902801F # POPR R1 R15 -0D01001F # RET R15 - - -# ;; Our simple string compare function -# ;; Recieves two pointers in R0 and R1 -# ;; Returns the difference between the strings in R0 -# ;; Clears R1 -# ;; Returns to whatever called it -:strcmp -# ;; Preserve registers -0902002F # PUSHR R2 R15 -0902003F # PUSHR R3 R15 -0902004F # PUSHR R4 R15 -# ;; Setup registers -09000520 # MOVE R2 R0 -09000531 # MOVE R3 R1 -2D240000 # LOADUI R4 0 -:cmpbyte -0503A024 # LOADXU8 R0 R2 R4 ; Get a byte of our first string -0503A134 # LOADXU8 R1 R3 R4 ; Get a byte of our second string -0F440001 # ADDUI R4 R4 1 ; Prep for next loop -05004101 # CMP R1 R0 R1 ; Compare the bytes -A0200000 # CMPSKIPI.E R0 0 ; Stop if byte is NULL -2C51 @cmpbyte # JUMP.E R1 @cmpbyte ; Loop if bytes are equal -# ;; Done -09000501 # MOVE R0 R1 ; Prepare for return -# ;; Restore registers -0902804F # POPR R4 R15 -0902803F # POPR R3 R15 -0902802F # POPR R2 R15 -0D01001F # RET R15 - - -# ;; Processimmediate Function -# ;; Recieves an integer value in R0 -# ;; Writes out the values to Tape_02 -# ;; Doesn't modify registers -# ;; Returns to whatever called it -:ProcessImmediate -# ;; Preserve registers -0902000F # PUSHR R0 R15 -0902001F # PUSHR R1 R15 -0902002F # PUSHR R2 R15 -# ;; Break up Immediate -05020209 # AND R2 R0 R9 ; Put lower byte in R2 -2D400008 # SARI R0 8 ; Drop Bottom byte from R0 -05020009 # AND R0 R0 R9 ; Maskout everything outside of top byte -# ;; Write out Top Byte -2D211101 # LOADUI R1 0x1101 ; Write the byte -42100200 # FPUTC ; To TAPE_02 -# ;; Write out bottom Byte -09000502 # MOVE R0 R2 ; Put Lower byte in R0 -2D211101 # LOADUI R1 0x1101 ; Write the byte -42100200 # FPUTC ; To TAPE_02 -# ;; Restore registers -0902802F # POPR R2 R15 -0902801F # POPR R1 R15 -0902800F # POPR R0 R15 -# ;; Be Done -0D01001F # RET R15 - - -# ;; ThrowAwaypointer function -# ;; Handle the special case of a generic problem -# ;; for Pass1, Will update R11 and modify R0 -# ;; Will return to the start of first_pass -# ;; Never call this function, only jump to it -:ThrowAwayPointer -0FBB0002 # ADDUI R11 R11 2 ; Pointers always take up 2 bytes -2D0F @throwAwayToken # CALLI R15 @throwAwayToken ; Get rid of rest of token -3C00 @first_pass # JUMP @first_pass ; Then return to the proper place - - -# ;; ThrowAwayAddress function -# ;; Handle the case of a 32bit absolute address storage -# ;; for Pass1, Will update R11 and modify R0 -# ;; Will return to the start of first_pass -# ;; Never call this function, conly jump to it -:ThrowAwayAddress -0FBB0004 # ADDUI R11 R11 4 ; Addresses on 32bit systems take up 4 bytes -2D0F @throwAwayToken # CALLI R15 @throwAwayToken ; Get rid of rest of token -3C00 @first_pass # JUMP @first_pass ; Then return to the proper place - - -# ;; ThrowAwaylabel function -# ;; Handle the special case of a generic problem -# ;; for Pass2, Will update R11 and modify R0 -# ;; Will return to the start of second_pass -# ;; Never call this function, only jump to it -:ThrowAwayLabel -2D0F @throwAwayToken # CALLI R15 @throwAwayToken ; Get rid of rest of token -3C00 @second_pass # JUMP @second_pass - -# ;; Throw away token function -# ;; Deals with the general case of not wanting -# ;; The rest of the characters in a token -# ;; This Will alter the values of R0 R1 -# ;; Returns back to whatever called it -:throwAwayToken -2D211100 # LOADUI R1 0x1100 ; Read from tape_01 -42100100 # FGETC ; Read a Char -# ;; Stop looping if space -A0300020 # CMPSKIPI.NE R0 32 -0D01001F # RET R15 -# ;; Stop looping if tab -A0300009 # CMPSKIPI.NE R0 9 -0D01001F # RET R15 -# ;; Stop looping if newline -A030000a # CMPSKIPI.NE R0 10 -0D01001F # RET R15 -# ;; Otherwise keep looping -3C00 @throwAwayToken # JUMP @throwAwayToken - -# ;; Hex function -# ;; This function is serving three purposes: -# ;; Identifying hex characters -# ;; Purging line comments -# ;; Returning the converted value of a hex character -# ;; This function will alter the values of R0 R14 -# ;; Returns back to whatever called it -:hex -# ;; Deal with line comments starting with # -1FE00023 # CMPUI R14 R0 35 -2C5E @ascii_comment # JUMP.E R14 @ascii_comment -# ;; Deal with line comments starting with ; -1FE0003b # CMPUI R14 R0 59 -2C5E @ascii_comment # JUMP.E R14 @ascii_comment -# ;; Deal with all ascii less than '0' -1FE00030 # CMPUI R14 R0 48 -2C8E @ascii_other # JUMP.L R14 @ascii_other -# ;; Deal with '0'-'9' -1FE00039 # CMPUI R14 R0 57 -2C7E @ascii_num # JUMP.LE R14 @ascii_num -# ;; Deal with all ascii less than 'A' -1FE00041 # CMPUI R14 R0 65 -2C8E @ascii_other # JUMP.L R14 @ascii_other -# ;; Deal with 'A'-'F' -1FE00046 # CMPUI R14 R0 70 -2C7E @ascii_high # JUMP.LE R14 @ascii_high -# ;; Deal with all ascii less than 'a' -1FE00061 # CMPUI R14 R0 97 -2C8E @ascii_other # JUMP.L R14 @ascii_other -# ;; Deal with 'a'-'f' -1FE00066 # CMPUI R14 R0 102 -2C7E @ascii_low # JUMP.LE R14 @ascii_low -# ;; Ignore the rest -3C00 @ascii_other # JUMP @ascii_other -:ascii_num -11000030 # SUBUI R0 R0 48 -0D01001F # RET R15 -:ascii_low -11000057 # SUBUI R0 R0 87 -0D01001F # RET R15 -:ascii_high -11000037 # SUBUI R0 R0 55 -0D01001F # RET R15 -:ascii_other -0D000030 # TRUE R0 -0D01001F # RET R15 -:ascii_comment -2D211100 # LOADUI R1 0x1100 ; Read from TAPE_01 -42100100 # FGETC ; Read another char -1FE0000a # CMPUI R14 R0 10 ; Stop at the end of line -2C6E @ascii_comment # JUMP.NE R14 @ascii_comment ; Otherwise keep looping -3C00 @ascii_other # JUMP @ascii_other - - -# ;; Where we are storing our Temp -:Temp -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP -00000000 # NOP - - -# ;; Where we will putting our Table -:table diff --git a/stage1/stage1_assembler-2.s b/stage1/stage1_assembler-2.s index 649e885..d9a833c 100644 --- a/stage1/stage1_assembler-2.s +++ b/stage1/stage1_assembler-2.s @@ -14,24 +14,45 @@ ; You should have received a copy of the GNU General Public License ; along with stage0. If not, see . +;; Node format: +;; PREV->pointer (register size) +;; Address (register size) +;; NULL terminated string (strln + 1) + :start - LOADUI R13 @table ; Where we are putting our table - ;; We will be using R14 for our condition codes - LOADUI R15 0x7FFF ; We will be using R15 for our stack + ;; R1 is reserved for reading/writing bytes (don't touch) + ;; We will be using R8 for our malloc pointer + ;; We will be using R9 for our header size in bytes + ;; We will be using R10 for our toggle + ;; We will be using R11 for our PC counter + ;; We will be using R12 for holding our nybble + ;; We will be using R13 for our register size in bytes + ;; We will be using R14 for our head-node + LOADUI R15 $stack ; We will be using R15 for our stack ;; Main program functionality ;; Reads in Tape_01 and writes out results onto Tape_02 ;; Accepts no arguments and HALTS when done :main + ;; Initialize header info + READSCID R0 ; Get process capabilities + ANDI R1 R0 0xF ; We only care about size nybble + LOADUI R0 1 ; Assume we are 8bit + SL0 R13 R0 R1 ; Let size nybble correct answer + COPY R9 R13 ; Prepare Header size + SL0I R9 1 ; Double to make proper size + ;; Prep TAPE_01 LOADUI R0 0x1100 FOPEN_READ ;; Intialize environment + LOADUI R1 0x1100 ; Read from tape_01 FALSE R12 ; Set holder to zero FALSE R11 ; Set PC counter to zero - LOADUI R10 1 ; Our toggle + FALSE R10 ; Our toggle + LOADUI R8 0x500 ; Where we want our heap to start ;; Perform first pass CALLI R15 @first_pass @@ -43,9 +64,7 @@ ;; Reintialize environment FALSE R12 ; Set holder to zero FALSE R11 ; Set PC counter to zero - LOADUI R10 1 ; Our toggle - LOADUI R9 0xFF ; Byte mask - LOADUI R8 0x0F ; nybble mask + FALSE R10 ; Our toggle ;; Prep TAPE_02 LOADUI R0 0x1101 @@ -66,7 +85,6 @@ ;; Will Overwrite R0 R10 R11 ;; Returns to Main function when done :first_pass - LOADUI R1 0x1100 ; Read from tape_01 FGETC ; Read a Char ;; Check for EOF @@ -92,19 +110,13 @@ ;; Otherwise attempt to process CALLI R15 @hex ; Convert it - CMPSKIPI.GE R0 0 ; Don't record, nonhex values - JUMP @first_pass ; Move onto Next char + JUMP.NP R0 @first_pass ; Don't record, nonhex values - ;; Determine if we got a full byte - JUMP.Z R10 @first_pass_0 ; Jump if toggled + ;; Flip the toggle + NOT R10 R10 + JUMP.Z R10 @first_pass ; Jump if toggled - ;; Deal with case of first half of byte - FALSE R10 ; Flip the toggle - JUMP @first_pass - -:first_pass_0 ;; Deal with case of second half of byte - TRUE R10 ; Flip the toggle ADDUI R11 R11 1 ; increment PC now that that we have a full byte JUMP @first_pass @@ -115,7 +127,6 @@ ;; Will Overwrite R0 R10 R11 ;; Returns to Main function when done :second_pass - LOADUI R1 0x1100 ; Read from tape_01 FGETC ; Read a Char ;; Check for EOF @@ -142,21 +153,21 @@ JUMP @second_pass ; Move onto Next char ;; Determine if we got a full byte + NOT R10 R10 JUMP.Z R10 @second_pass_0 ; Jump if toggled ;; Deal with case of first half of byte - AND R12 R0 R8 ; Store our first nibble - FALSE R10 ; Flip the toggle + ANDI R12 R0 0x0F ; Store our first nibble JUMP @second_pass :second_pass_0 ;; Deal with case of second half of byte SL0I R12 4 ; Shift our first nybble - AND R0 R0 R8 ; Mask out top + ANDI R0 R0 0x0F ; Mask out top ADD R0 R0 R12 ; Combine nybbles - TRUE R10 ; Flip the toggle LOADUI R1 0x1101 ; Write the combined byte FPUTC ; To TAPE_02 + LOADUI R1 0x1100 ; Read from tape_01 ADDUI R11 R11 1 ; increment PC now that that we have a full byte JUMP @second_pass @@ -167,32 +178,24 @@ ;; Will overwrite R0 ;; Returns to first pass when done :storeLabel - LOADR R0 @current_index ; Get address of first open index - CMPSKIPI.NE R0 0 ; If zero intialize from R13 - COPY R0 R13 + COPY R0 R8 ; get current malloc + ADD R8 R8 R9 ; update malloc - ;; Store the PC of the label - STORE32 R11 R0 0 + ;; Add node info + STOREX R11 R0 R13 ; Store the PC of the label + STORE R14 R0 0 ; Store the Previous Head + MOVE R14 R0 ; Update Head ;; Store the name of the Label - ADDUI R0 R0 4 ; Increment the offset of the index CALLI R15 @writeout_token - ;; Update our index - ADDUI R0 R0 60 ; Hopefully our tokens are less than 60 bytes long - STORER R0 @current_index ;; And be done JUMP @first_pass -;; Where we are storing the location of the next free table entry -:current_index - NOP - ;; StoreRelativepointer function ;; Deals with the special case of relative pointers -;; Clears Temp -;; Stores string in Temp +;; Stores string ;; Finds match in Table ;; Writes out the offset ;; Modifies R0 R11 @@ -200,11 +203,7 @@ :StoreRelativePointer ;; Correct the PC to reflect the size of the pointer ADDUI R11 R11 2 ; Exactly 2 bytes - LOADUI R0 $Temp ; Set where we want to shove our string - CALLI R15 @Clear_string ; Clear it - CALLI R15 @writeout_token ; Write it CALLI R15 @Match_string ; Find the Match - LOAD32 R0 R0 -4 ; Get the value we care about SUB R0 R0 R11 ; Determine the difference ADDUI R0 R0 4 ; Adjust for relative positioning CALLI R15 @ProcessImmediate ; Write out the value @@ -213,8 +212,7 @@ ;; StoreAbsolutepointer function ;; Deals with the special case of absolute pointers -;; Clears Temp -;; Stores string in Temp +;; Stores string ;; Finds match in Table ;; Writes out the absolute address of match ;; Modifies R0 R11 @@ -222,19 +220,14 @@ :StoreAbsolutePointer ;; Correct the PC to reflect the size of the pointer ADDUI R11 R11 2 ; Exactly 2 bytes - LOADUI R0 $Temp ; Set where we want to shove our string - CALLI R15 @Clear_string ; Clear it - CALLI R15 @writeout_token ; Write it CALLI R15 @Match_string ; Find the Match - LOAD32 R0 R0 -4 ; Get the value we care about CALLI R15 @ProcessImmediate ; Write out the value JUMP @second_pass ;; StoreAbsoluteAddress function ;; Deal with the special case of absolute Addresses -;; Clear Temp -;; Stores string in Temp +;; Stores string ;; Finds match in Table ;; Writes out the full absolute address [32 bit machine] ;; Modifies R0 R11 @@ -242,36 +235,26 @@ :StoreAbsoluteAddress ;; COrrect the PC to reflect the size of the address ADDUI R11 R11 4 ; 4 Bytes on 32bit machines - LOADUI R0 $Temp ; Set where we ant to shove our string - CALLI R15 @Clear_string ; Clear it - CALLI R15 @writeout_token ; Write it CALLI R15 @Match_string ; Find the Match - PUSHR R14 R15 ; Get a temp storage place - LOAD32 R14 R0 -4 ; Get the value we care about - COPY R0 R14 ; We need to print the top 2 bytes first + ANDI R2 R0 0xFFFF ; Save bottom half for next function SARI R0 16 ; Drop bottom 16 bits CALLI R15 @ProcessImmediate ; Write out top 2 bytes - LOADUI R0 0xFFFF ; Provide mask to keep bottom 2 bytes - AND R0 R0 R14 ; Drop top 16 bits - POPR R14 R15 ; Restore R14 + MOVE R0 R2 ; Use the saved 16bits CALLI R15 @ProcessImmediate ; Write out bottom 2 bytes JUMP @second_pass ;; Writeout Token Function ;; Writes the Token [minus first char] to the address -;; It recieves in R0 until it reaches a delimiter -;; All register values are preserved -;; Returns to whatever called it +;; given by malloc and updates malloc pointer +;; Returns starting address of string :writeout_token ;; Preserve registers - PUSHR R0 R15 PUSHR R1 R15 PUSHR R2 R15 ;; Initialize - MOVE R2 R0 ; Set R2 as our index - LOADUI R1 0x1100 ; Read from tape_01 + COPY R2 R8 ; Get current malloc pointer ;; Our core loop :writeout_token_0 @@ -284,54 +267,31 @@ JUMP @writeout_token_done CMPSKIPI.NE R0 10 ; Finished if newline JUMP @writeout_token_done + CMPSKIPI.NE R0 -1 ; Finished if EOF + JUMP @writeout_token_done ;; Deal with valid input - STORE8 R0 R2 0 ; Write out the byte - ADDUI R2 R2 1 ; Increment + STORE8 R0 R8 0 ; Write out the byte + ADDUI R8 R8 1 ; Increment JUMP @writeout_token_0 ; Keep looping ;; Clean up now that we are done :writeout_token_done + ;; Fix malloc + ADDUI R8 R8 1 + ;; Prepare for return + MOVE R0 R2 ;; Restore registers POPR R2 R15 POPR R1 R15 - POPR R0 R15 ;; And be done RET R15 -;; Clear string function -;; Clears string pointed at by the value of R0 -;; Until a null character is reached -;; Doesn't alter any registers -;; Returns to the function that calls it -:Clear_string - ;; Preserve registers - PUSHR R0 R15 - PUSHR R1 R15 - PUSHR R2 R15 - PUSHR R3 R15 - ;; Setup registers - MOVE R1 R0 - LOADUI R2 0 - LOADUI R3 0 -:clear_byte - LOADXU8 R0 R1 R2 ; Get the byte - STOREX8 R3 R1 R2 ; Overwrite with a Zero - ADDUI R2 R2 1 ; Prep for next loop - JUMP.NZ R0 @clear_byte ; Stop if byte is NULL -;; Done - ;; Restore registers - POPR R3 R15 - POPR R2 R15 - POPR R1 R15 - POPR R0 R15 - RET R15 - - ;; Match string function -;; Walks down table until match is found -;; Then returns address of matching string in R0 +;; Walks down list until match is found or returns -1 +;; Reads a token +;; Then returns address of match in R0 ;; Returns to whatever called it :Match_string ;; Preserve registers @@ -339,23 +299,24 @@ PUSHR R2 R15 ;; Initialize for Loop - LOADUI R1 $Temp ; We always compare against Temp - LOADUI R2 $table ; Begin at start of table - ADDUI R2 R2 4 ; Where the string is located + CALLI R15 @writeout_token ; Get our desired string + MOVE R1 R0 ; Position our desired string + COPY R2 R14 ; Begin at our head node ;; Loop until we find a match :Match_string_0 - COPY R0 R2 ; Set R0 to our current string + ADD R0 R2 R9 ; Where the string is located CALLI R15 @strcmp JUMP.E R0 @Match_string_1 ; It is a match! ;; Prepare for next loop - LOADUI R1 $Temp ; That function clears R1 - ADDUI R2 R2 64 ; Each Index is 64 bytes - JUMP @Match_string_0 ; Keep looping + LOAD R2 R2 0 ; Move to next node + JUMP.NZ R2 @Match_string_0 ; Keep looping + TRUE R2 ; Set result to -1 if not found :Match_string_1 ;; Store the correct answer - MOVE R0 R2 + CMPSKIPI.E R2 -1 ; Otherwise get the value + LOADX R0 R2 R13 ; Get the value we care about ;; Restore registers POPR R2 R15 POPR R1 R15 @@ -365,10 +326,10 @@ ;; Our simple string compare function ;; Recieves two pointers in R0 and R1 ;; Returns the difference between the strings in R0 -;; Clears R1 ;; Returns to whatever called it :strcmp ;; Preserve registers + PUSHR R1 R15 PUSHR R2 R15 PUSHR R3 R15 PUSHR R4 R15 @@ -377,18 +338,19 @@ MOVE R3 R1 LOADUI R4 0 :cmpbyte - LOADXU8 R0 R2 R4 ; Get a byte of our first string - LOADXU8 R1 R3 R4 ; Get a byte of our second string - ADDUI R4 R4 1 ; Prep for next loop - CMP R1 R0 R1 ; Compare the bytes - CMPSKIPI.E R0 0 ; Stop if byte is NULL - JUMP.E R1 @cmpbyte ; Loop if bytes are equal + LOADXU8 R0 R2 R4 ; Get a byte of our first string + LOADXU8 R1 R3 R4 ; Get a byte of our second string + ADDUI R4 R4 1 ; Prep for next loop + CMP R1 R0 R1 ; Compare the bytes + CMPSKIPI.E R0 0 ; Stop if byte is NULL + JUMP.E R1 @cmpbyte ; Loop if bytes are equal ;; Done - MOVE R0 R1 ; Prepare for return + MOVE R0 R1 ; Prepare for return ;; Restore registers POPR R4 R15 POPR R3 R15 POPR R2 R15 + POPR R1 R15 RET R15 @@ -403,16 +365,15 @@ PUSHR R1 R15 PUSHR R2 R15 ;; Break up Immediate - AND R2 R0 R9 ; Put lower byte in R2 - SARI R0 8 ; Drop Bottom byte from R0 - AND R0 R0 R9 ; Maskout everything outside of top byte + ANDI R2 R0 0xFF ; Put lower byte in R2 + SARI R0 8 ; Drop Bottom byte from R0 + ANDI R0 R0 0xFF ; Maskout everything outside of top byte ;; Write out Top Byte LOADUI R1 0x1101 ; Write the byte FPUTC ; To TAPE_02 ;; Write out bottom Byte MOVE R0 R2 ; Put Lower byte in R0 - LOADUI R1 0x1101 ; Write the byte FPUTC ; To TAPE_02 ;; Restore registers @@ -460,7 +421,6 @@ ;; This Will alter the values of R0 R1 ;; Returns back to whatever called it :throwAwayToken - LOADUI R1 0x1100 ; Read from tape_01 FGETC ; Read a Char ;; Stop looping if space @@ -475,6 +435,10 @@ CMPSKIPI.NE R0 10 RET R15 + ;; Stop looping if EOF + CMPSKIPI.NE R0 -1 + RET R15 + ;; Otherwise keep looping JUMP @throwAwayToken @@ -484,75 +448,47 @@ ;; Identifying hex characters ;; Purging line comments ;; Returning the converted value of a hex character -;; This function will alter the values of R0 R14 +;; This function will alter the values of R0 ;; Returns back to whatever called it :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 + ;; Unset high bit to set everything into uppercase + ANDI R0 R0 0xDF ;; Deal with 'A'-'F' - CMPUI R14 R0 70 - JUMP.LE R14 @ascii_high - ;; Deal with all ascii less than 'a' - CMPUI R14 R0 97 - JUMP.L R14 @ascii_other - ;; Deal with 'a'-'f' - CMPUI R14 R0 102 - JUMP.LE R14 @ascii_low + CMPSKIPI.G R0 70 + JUMP @ascii_high ;; Ignore the rest JUMP @ascii_other :ascii_num SUBUI R0 R0 48 RET R15 -:ascii_low - SUBUI R0 R0 87 - RET R15 :ascii_high SUBUI R0 R0 55 RET R15 +:ascii_comment + FGETC ; Read another char + JUMP.NP R0 @ascii_other ; Stop with EOF + CMPSKIPI.E R0 10 ; Stop at the end of line + JUMP @ascii_comment ; Otherwise keep looping :ascii_other TRUE R0 RET R15 -:ascii_comment - LOADUI R1 0x1100 ; Read from TAPE_01 - FGETC ; Read another char - CMPUI R14 R0 10 ; Stop at the end of line - JUMP.NE R14 @ascii_comment ; Otherwise keep looping - JUMP @ascii_other -;; Where we are storing our Temp -:Temp - NOP - NOP - NOP - NOP - NOP - NOP - NOP - NOP - NOP - NOP - NOP - NOP - NOP - NOP - NOP - NOP - - -;; Where we will putting our Table -:table +;; Where we will putting our stack +:stack diff --git a/test/SHA256SUMS b/test/SHA256SUMS index 6385583..b404af3 100644 --- a/test/SHA256SUMS +++ b/test/SHA256SUMS @@ -7,4 +7,4 @@ b3a910f18c6bc0ef4aa7a53cb3f0216a9f143319da67ed2a02210fe88b1e1131 roms/forth 0a427b14020354d1c785f5f900677e0059fce8f8d4456e9c19e5528cb17101eb roms/stage0_monitor 3ea7fed1429400c1d6fc5b85180c4114755dfb1e6b88d69e7ecc465a40523bc8 roms/stage1_assembler-0 b6aabcc3418a0a28f4ed32ace43b20103d9d21dffae03e7936cb14fa0e044013 roms/stage1_assembler-1 -61c1b0f2f628847d9491bd678ac7a23231527cc36493b321612f191674ff3c99 roms/stage1_assembler-2 +7b02babee42a3c05b001fb44fb0917383d8f185e2817d57ad2349a4b36dfa4ed roms/stage1_assembler-2