Updated hex2 to improve performance and reduce size

This commit is contained in:
Jeremiah Orians 2017-12-24 17:17:37 -05:00
parent 21239523bd
commit deac93c6f2
No known key found for this signature in database
GPG Key ID: 7457821534D2ACCD
8 changed files with 345 additions and 1490 deletions

View File

@ -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 Expanded stage0 web IDE to include the PC and instruction counter
Performance tuned hex1 to reduce both size and instruction count Performance tuned hex1 to reduce both size and instruction count
Performance tuned hex0 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
Fixed behavior of R@ thanks to reepca Fixed behavior of R@ thanks to reepca
@ -35,6 +36,8 @@ Updated checksums to reflect changed made in performance tuning
** Removed ** Removed
Removed stage1_assembler-0's need for Memory and reduced size of program while at it 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-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 * 0.0.9 - 2017-08-17
** Added ** Added

View File

@ -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 <http://www.gnu.org/licenses/>.
* 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 |

View File

@ -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 ./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 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 * 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. 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.

View File

@ -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 <http://www.gnu.org/licenses/>.
# :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

View File

@ -1,7 +1,7 @@
## Copyright (C) 2016 Jeremiah Orians ## Copyright (C) 2016 Jeremiah Orians
## This file is part of stage0. ## 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 ## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or ## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version. ## (at your option) any later version.
@ -14,40 +14,65 @@
## You should have received a copy of the GNU General Public License ## You should have received a copy of the GNU General Public License
## along with stage0. If not, see <http://www.gnu.org/licenses/>. ## along with stage0. If not, see <http://www.gnu.org/licenses/>.
# :start ;; Node format:
:0 ;; PREV->pointer (register size)
2D2D @1 # LOADUI R13 @table ; Where we are putting our table ;; Address (register size)
# ;; We will be using R14 for our condition codes ;; NULL terminated string (strln + 1)
2D2F7fff # LOADUI R15 0x7FFF ; We will be using R15 for our stack
# :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 # ;; Main program functionality
# ;; Reads in Tape_01 and writes out results onto Tape_02 # ;; Reads in Tape_01 and writes out results onto Tape_02
# ;; Accepts no arguments and HALTS when done # ;; Accepts no arguments and HALTS when done
# :main # :main 4
:3 :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 # ;; Prep TAPE_01
2D201100 # LOADUI R0 0x1100 2D201100 # LOADUI R0 0x1100
42100000 # FOPEN_READ 42100000 # FOPEN_READ
# ;; Intialize environment # ;; Intialize environment
2D211100 # LOADUI R1 0x1100 ; Read from tape_01
0D00002C # FALSE R12 ; Set holder to zero 0D00002C # FALSE R12 ; Set holder to zero
0D00002B # FALSE R11 ; Set PC counter 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 # ;; 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 # ;; We need to rewind tape_01 to perform our second pass
2D201100 # LOADUI R0 0x1100 2D201100 # LOADUI R0 0x1100
42100003 # REWIND 42100003 # REWIND
# ;; Reintialize environment # ;; Reintialize environment
0D00002C # FALSE R12 ; Set holder to zero 0D00002C # FALSE R12 ; Set holder to zero
0D00002B # FALSE R11 ; Set PC counter to zero 0D00002B # FALSE R11 ; Set PC counter to zero
2D2A0001 # LOADUI R10 1 ; Our toggle 0D00002A # FALSE R10 ; Our toggle
2D2900ff # LOADUI R9 0xFF ; Byte mask
2D28000f # LOADUI R8 0x0F ; nybble mask
# ;; Prep TAPE_02 # ;; Prep TAPE_02
2D201101 # LOADUI R0 0x1101 2D201101 # LOADUI R0 0x1101
42100001 # FOPEN_WRITE 42100001 # FOPEN_WRITE
2D0F @4 # CALLI R15 @second_pass 2D0F @4 # CALLI R15 @second_pass
# ;; Close up as we are done # ;; Close up as we are done
2D201100 # LOADUI R0 0x1100 ; Close TAPE_01 2D201100 # LOADUI R0 0x1100 ; Close TAPE_01
42100002 # FCLOSE 42100002 # FCLOSE
@ -60,41 +85,42 @@ FFFFFFFF # HALT
# ;; Reads Tape_01 and creates our label table # ;; Reads Tape_01 and creates our label table
# ;; Will Overwrite R0 R10 R11 # ;; Will Overwrite R0 R10 R11
# ;; Returns to Main function when done # ;; Returns to Main function when done
# :first_pass # :first_pass 70
:2 :3
2D211100 # LOADUI R1 0x1100 ; Read from tape_01
42100100 # FGETC ; Read a Char 42100100 # FGETC ; Read a Char
# ;; Check for EOF # ;; Check for EOF
A0100000 # CMPSKIPI.GE R0 0 A0100000 # CMPSKIPI.GE R0 0
0D01001F # RET R15 0D01001F # RET R15
# ;; Check for and deal with label (:) # ;; Check for and deal with label (:)
A030003a # CMPSKIPI.NE R0 58 A030003a # CMPSKIPI.NE R0 58
3C00 @5 # JUMP @storeLabel 3C00 @5 # JUMP @storeLabel
# ;; Check for and deal with pointers to labels # ;; Check for and deal with pointers to labels
# ;; Starting with (@) # ;; Starting with (@)
A0300040 # CMPSKIPI.NE R0 64 A0300040 # CMPSKIPI.NE R0 64
3C00 @6 # JUMP @ThrowAwayPointer 3C00 @6 # JUMP @ThrowAwayPointer
# ;; Then dealing with ($) # ;; Then dealing with ($)
A0300024 # CMPSKIPI.NE R0 36 A0300024 # CMPSKIPI.NE R0 36
3C00 @6 # JUMP @ThrowAwayPointer 3C00 @6 # JUMP @ThrowAwayPointer
# ;; Now check for absolute addresses (&) # ;; Now check for absolute addresses (&)
A0300026 # CMPSKIPI.NE R0 38 A0300026 # CMPSKIPI.NE R0 38
3C00 @v # JUMP @ThrowAwayAddress 3C00 @7 # JUMP @ThrowAwayAddress
# ;; Otherwise attempt to process # ;; Otherwise attempt to process
2D0F @7 # CALLI R15 @hex ; Convert it 2D0F @8 # CALLI R15 @hex ; Convert it
A0100000 # CMPSKIPI.GE R0 0 ; Don't record, nonhex values 2CC0 @3 # JUMP.NP R0 @first_pass ; Don't record, nonhex values
3C00 @2 # JUMP @first_pass ; Move onto Next char
# ;; Determine if we got a full byte # ;; Flip the toggle
2C9A @8 # JUMP.Z R10 @first_pass_0 ; Jump if toggled 090006AA # NOT R10 R10
# ;; Deal with case of first half of byte 2C9A @3 # JUMP.Z R10 @first_pass ; Jump if toggled
0D00002A # FALSE R10 ; Flip the toggle
3C00 @2 # JUMP @first_pass
# :first_pass_0
:8
# ;; Deal with case of second half of byte # ;; 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 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 # ;; Second pass function
@ -102,42 +128,48 @@ A0100000 # CMPSKIPI.GE R0 0 ; Don't record, nonhex values
# ;; To write desired contents onto Tape_02 # ;; To write desired contents onto Tape_02
# ;; Will Overwrite R0 R10 R11 # ;; Will Overwrite R0 R10 R11
# ;; Returns to Main function when done # ;; Returns to Main function when done
#:second_pass # :second_pass b4
:4 :4
2D211100 # LOADUI R1 0x1100 ; Read from tape_01
42100100 # FGETC ; Read a Char 42100100 # FGETC ; Read a Char
# ;; Check for EOF # ;; Check for EOF
A0100000 # CMPSKIPI.GE R0 0 A0100000 # CMPSKIPI.GE R0 0
0D01001F # RET R15 0D01001F # RET R15
# ;; Check for and deal with label # ;; Check for and deal with label
A030003a # CMPSKIPI.NE R0 58 A030003a # CMPSKIPI.NE R0 58
3C00 @9 # JUMP @ThrowAwayLabel 3C00 @9 # JUMP @ThrowAwayLabel
# ;; Check for and deal with Pointers to labels # ;; Check for and deal with Pointers to labels
A0300040 # CMPSKIPI.NE R0 64 ; @ for relative A0300040 # CMPSKIPI.NE R0 64 ; @ for relative
3C00 @a # JUMP @StoreRelativePointer 3C00 @a # JUMP @StoreRelativePointer
A0300024 # CMPSKIPI.NE R0 36 ; $ for absolute A0300024 # CMPSKIPI.NE R0 36 ; $ for absolute
3C00 @b # JUMP @StoreAbsolutePointer 3C00 @b # JUMP @StoreAbsolutePointer
A0300026 # CMPSKIPI.NE R0 38 ; & for address A0300026 # CMPSKIPI.NE R0 38 ; & for address
3C00 @w # JUMP @StoreAbsoluteAddress 3C00 @c # JUMP @StoreAbsoluteAddress
# ;; Process everything else # ;; 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 A0100000 # CMPSKIPI.GE R0 0 ; Don't record, nonhex values
3C00 @4 # JUMP @second_pass ; Move onto Next char 3C00 @4 # JUMP @second_pass ; Move onto Next char
# ;; Determine if we got a full byte # ;; 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 # ;; Deal with case of first half of byte
05020C08 # AND R12 R0 R8 ; Store our first nibble B0C0000f # ANDI R12 R0 0x0F ; Store our first nibble
0D00002A # FALSE R10 ; Flip the toggle
3C00 @4 # JUMP @second_pass 3C00 @4 # JUMP @second_pass
# :second_pass_0
:c # :second_pass_0 fc
:d
# ;; Deal with case of second half of byte # ;; Deal with case of second half of byte
2D5C0004 # SL0I R12 4 ; Shift our first nybble 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 0500000C # ADD R0 R0 R12 ; Combine nybbles
0D00003A # TRUE R10 ; Flip the toggle
2D211101 # LOADUI R1 0x1101 ; Write the combined byte 2D211101 # LOADUI R1 0x1101 ; Write the combined byte
42100200 # FPUTC ; To TAPE_02 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 0FBB0001 # ADDUI R11 R11 1 ; increment PC now that that we have a full byte
3C00 @4 # JUMP @second_pass 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 # ;; Its static variable for storing the next index to be used
# ;; Will overwrite R0 # ;; Will overwrite R0
# ;; Returns to first pass when done # ;; Returns to first pass when done
#:storeLabel # :storeLabel 11c
:5 :5
2E00 @d # LOADR R0 @current_index ; Get address of first open index 09000408 # COPY R0 R8 ; get current malloc
A0300000 # CMPSKIPI.NE R0 0 ; If zero intialize from R13 05000889 # ADD R8 R8 R9 ; update malloc
0900040D # COPY R0 R13
# ;; Store the PC of the label # ;; Add node info
23B00000 # STORE32 R11 R0 0 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 # ;; Store the name of the Label
0F000004 # ADDUI R0 R0 4 ; Increment the offset of the index
2D0F @e # CALLI R15 @writeout_token 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 # ;; And be done
3C00 @2 # JUMP @first_pass 3C00 @3 # JUMP @first_pass
# ;; Where we are storing the location of the next free table entry
# :current_index
:d
00000000 # NOP
# ;; StoreRelativepointer function # ;; StoreRelativepointer function
# ;; Deals with the special case of relative pointers # ;; Deals with the special case of relative pointers
# ;; Clears Temp # ;; Stores string
# ;; Stores string in Temp
# ;; Finds match in Table # ;; Finds match in Table
# ;; Writes out the offset # ;; Writes out the offset
# ;; Modifies R0 R11 # ;; Modifies R0 R11
# ;; Jumps back into Pass2 # ;; Jumps back into Pass2
# :StoreRelativePointer # :StoreRelativePointer 138
:a :a
# ;; Correct the PC to reflect the size of the pointer # ;; Correct the PC to reflect the size of the pointer
0FBB0002 # ADDUI R11 R11 2 ; Exactly 2 bytes 0FBB0002 # ADDUI R11 R11 2 ; Exactly 2 bytes
2D2003cc # LOADUI R0 $Temp ; Set where we want to shove our string 2D0F @o # CALLI R15 @Match_string ; Find the Match
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
0500200B # SUB R0 R0 R11 ; Determine the difference 0500200B # SUB R0 R0 R11 ; Determine the difference
0F000004 # ADDUI R0 R0 4 ; Adjust for relative positioning 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 3C00 @4 # JUMP @second_pass
# ;; StoreAbsolutepointer function # ;; StoreAbsolutepointer function
# ;; Deals with the special case of absolute pointers # ;; Deals with the special case of absolute pointers
# ;; Clears Temp # ;; Stores string
# ;; Stores string in Temp
# ;; Finds match in Table # ;; Finds match in Table
# ;; Writes out the absolute address of match # ;; Writes out the absolute address of match
# ;; Modifies R0 R11 # ;; Modifies R0 R11
# ;; Jumps back into Pass2 # ;; Jumps back into Pass2
# :StoreAbsolutePointer # :StoreAbsolutePointer 150
:b :b
# ;; Correct the PC to reflect the size of the pointer # ;; Correct the PC to reflect the size of the pointer
0FBB0002 # ADDUI R11 R11 2 ; Exactly 2 bytes 0FBB0002 # ADDUI R11 R11 2 ; Exactly 2 bytes
2D2003cc # LOADUI R0 $Temp ; Set where we want to shove our string 2D0F @o # CALLI R15 @Match_string ; Find the Match
2D0F @f # CALLI R15 @Clear_string ; Clear it 2D0F @p # CALLI R15 @ProcessImmediate ; Write out the value
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
3C00 @4 # JUMP @second_pass 3C00 @4 # JUMP @second_pass
# ;; StoreAbsoluteAddress function # ;; StoreAbsoluteAddress function
# ;; Deal with the special case of absolute Addresses # ;; Deal with the special case of absolute Addresses
# ;; Clear Temp # ;; Stores string
# ;; Stores string in Temp
# ;; Finds match in Table # ;; Finds match in Table
# ;; Writes out the full absolute address [32 bit machine] # ;; Writes out the full absolute address [32 bit machine]
# ;; Modifies R0 R11 # ;; Modifies R0 R11
# ;; Jumpbacs back into Pass2 # ;; Jumpbacs back into Pass2
# :StoreAbsoluteAddress # :StoreAbsoluteAddress 160
:c
# ;; COrrect the PC to reflect the size of the address # ;; COrrect the PC to reflect the size of the address
:w
0FBB0004 # ADDUI R11 R11 4 ; 4 Bytes on 32bit machines 0FBB0004 # ADDUI R11 R11 4 ; 4 Bytes on 32bit machines
2D2003cc # LOADUI R0 $Temp ; Set where we ant to shove our string 2D0F @o # CALLI R15 @Match_string ; Find the Match
2D0F @f # CALLI R15 @Clear_string ; Clear it B020ffff # ANDI R2 R0 0xFFFF ; Save bottom half for next function
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
2D400010 # SARI R0 16 ; Drop bottom 16 bits 2D400010 # SARI R0 16 ; Drop bottom 16 bits
2D0F @h # CALLI R15 @ProcessImmediate ; Write out top 2 bytes 2D0F @p # CALLI R15 @ProcessImmediate ; Write out top 2 bytes
2D20ffff # LOADUI R0 0xFFFF ; Provide mask to keep bottom 2 bytes 09000502 # MOVE R0 R2 ; Use the saved 16bits
0502000E # AND R0 R0 R14 ; Drop top 16 bits 2D0F @p # CALLI R15 @ProcessImmediate ; Write out bottom 2 bytes
090280EF # POPR R14 R15 ; Restore R14
2D0F @h # CALLI R15 @ProcessImmediate ; Write out bottom 2 bytes
3C00 @4 # JUMP @second_pass 3C00 @4 # JUMP @second_pass
# ;; Writeout Token Function # ;; Writeout Token Function
# ;; Writes the Token [minus first char] to the address # ;; Writes the Token [minus first char] to the address
# ;; It recieves in R0 until it reaches a delimiter # ;; given by malloc and updates malloc pointer
# ;; All register values are preserved # ;; Returns starting address of string
# ;; Returns to whatever called it # :writeout_token 180
# :writeout_token
:e :e
# ;; Preserve registers # ;; Preserve registers
0902000F # PUSHR R0 R15
0902001F # PUSHR R1 R15 0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15 0902002F # PUSHR R2 R15
# ;; Initialize # ;; Initialize
09000520 # MOVE R2 R0 ; Set R2 as our index 09000428 # COPY R2 R8 ; Get current malloc pointer
2D211100 # LOADUI R1 0x1100 ; Read from tape_01
# ;; Our core loop # ;; Our core loop
# :writeout_token_0 # :writeout_token_0 18c
:j :r
42100100 # FGETC ; Get another byte 42100100 # FGETC ; Get another byte
# ;; Deal with termination cases # ;; Deal with termination cases
A0300020 # CMPSKIPI.NE R0 32 ; Finished if space 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 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 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 # ;; Deal with valid input
21020000 # STORE8 R0 R2 0 ; Write out the byte 21080000 # STORE8 R0 R8 0 ; Write out the byte
0F220001 # ADDUI R2 R2 1 ; Increment 0F880001 # ADDUI R8 R8 1 ; Increment
3C00 @j # JUMP @writeout_token_0 ; Keep looping 3C00 @r # JUMP @writeout_token_0 ; Keep looping
# ;; Clean up now that we are done # ;; Clean up now that we are done
# :writeout_token_done # :writeout_token_done 1bc
:i :q
# ;; Fix malloc
0F880001 # ADDUI R8 R8 1
# ;; Prepare for return
09000502 # MOVE R0 R2
# ;; Restore registers # ;; Restore registers
0902802F # POPR R2 R15 0902802F # POPR R2 R15
0902801F # POPR R1 R15 0902801F # POPR R1 R15
0902800F # POPR R0 R15
# ;; And be done # ;; And be done
0D01001F # RET R15 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 # ;; Match string function
# ;; Walks down table until match is found # ;; Walks down list until match is found or returns -1
# ;; Then returns address of matching string in R0 # ;; Reads a token
# ;; Then returns address of match in R0
# ;; Returns to whatever called it # ;; Returns to whatever called it
# :Match_string # :Match_string 1d0
:g :o
# ;; Preserve registers # ;; Preserve registers
0902001F # PUSHR R1 R15 0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15 0902002F # PUSHR R2 R15
# ;; Initialize for Loop # ;; Initialize for Loop
2D2103cc # LOADUI R1 $Temp ; We always compare against Temp 2D0F @e # CALLI R15 @writeout_token ; Get our desired string
2D22040c # LOADUI R2 $table ; Begin at start of table 09000510 # MOVE R1 R0 ; Position our desired string
0F220004 # ADDUI R2 R2 4 ; Where the string is located 0900042E # COPY R2 R14 ; Begin at our head node
# ;; Loop until we find a match # ;; Loop until we find a match
# :Match_string_0 # :Match_string_0 1e4
:n :h
09000402 # COPY R0 R2 ; Set R0 to our current string 05000029 # ADD R0 R2 R9 ; Where the string is located
2D0F @l # CALLI R15 @strcmp 2D0F @f # CALLI R15 @strcmp
2C50 @m # JUMP.E R0 @Match_string_1 ; It is a match! 2C50 @g # JUMP.E R0 @Match_string_1 ; It is a match!
# ;; Prepare for next loop # ;; Prepare for next loop
2D2103cc # LOADUI R1 $Temp ; That function clears R1 13220000 # LOAD R2 R2 0 ; Move to next node
0F220040 # ADDUI R2 R2 64 ; Each Index is 64 bytes 2CA2 @h # JUMP.NZ R2 @Match_string_0 ; Keep looping
3C00 @n # JUMP @Match_string_0 ; Keep looping 0D000032 # TRUE R2 ; Set result to -1 if not found
# :Match_string_1
:m # :Match_string_1 1fc
:g
# ;; Store the correct answer # ;; 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 # ;; Restore registers
0902802F # POPR R2 R15 0902802F # POPR R2 R15
0902801F # POPR R1 R15 0902801F # POPR R1 R15
@ -347,32 +343,37 @@ A030000a # CMPSKIPI.NE R0 10 ; Finished if newline
# ;; Our simple string compare function # ;; Our simple string compare function
# ;; Recieves two pointers in R0 and R1 # ;; Recieves two pointers in R0 and R1
# ;; Returns the difference between the strings in R0 # ;; Returns the difference between the strings in R0
# ;; Clears R1
# ;; Returns to whatever called it # ;; Returns to whatever called it
# :strcmp # :strcmp 210
:l :f
# ;; Preserve registers # ;; Preserve registers
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15 0902002F # PUSHR R2 R15
0902003F # PUSHR R3 R15 0902003F # PUSHR R3 R15
0902004F # PUSHR R4 R15 0902004F # PUSHR R4 R15
# ;; Setup registers # ;; Setup registers
09000520 # MOVE R2 R0 09000520 # MOVE R2 R0
09000531 # MOVE R3 R1 09000531 # MOVE R3 R1
2D240000 # LOADUI R4 0 2D240000 # LOADUI R4 0
# :cmpbyte
:o # :cmpbyte 22c
:i
0503A024 # LOADXU8 R0 R2 R4 ; Get a byte of our first string 0503A024 # LOADXU8 R0 R2 R4 ; Get a byte of our first string
0503A134 # LOADXU8 R1 R3 R4 ; Get a byte of our second string 0503A134 # LOADXU8 R1 R3 R4 ; Get a byte of our second string
0F440001 # ADDUI R4 R4 1 ; Prep for next loop 0F440001 # ADDUI R4 R4 1 ; Prep for next loop
05004101 # CMP R1 R0 R1 ; Compare the bytes 05004101 # CMP R1 R0 R1 ; Compare the bytes
A0200000 # CMPSKIPI.E R0 0 ; Stop if byte is NULL 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 # ;; Done
09000501 # MOVE R0 R1 ; Prepare for return 09000501 # MOVE R0 R1 ; Prepare for return
# ;; Restore registers # ;; Restore registers
0902804F # POPR R4 R15 0902804F # POPR R4 R15
0902803F # POPR R3 R15 0902803F # POPR R3 R15
0902802F # POPR R2 R15 0902802F # POPR R2 R15
0902801F # POPR R1 R15
0D01001F # RET 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 # ;; Writes out the values to Tape_02
# ;; Doesn't modify registers # ;; Doesn't modify registers
# ;; Returns to whatever called it # ;; Returns to whatever called it
# :ProcessImmediate # :ProcessImmediate 25c
:h :p
# ;; Preserve registers # ;; Preserve registers
0902000F # PUSHR R0 R15 0902000F # PUSHR R0 R15
0902001F # PUSHR R1 R15 0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15 0902002F # PUSHR R2 R15
# ;; Break up Immediate # ;; 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 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 # ;; Write out Top Byte
2D211101 # LOADUI R1 0x1101 ; Write the byte 2D211101 # LOADUI R1 0x1101 ; Write the byte
42100200 # FPUTC ; To TAPE_02 42100200 # FPUTC ; To TAPE_02
# ;; Write out bottom Byte # ;; Write out bottom Byte
09000502 # MOVE R0 R2 ; Put Lower byte in R0 09000502 # MOVE R0 R2 ; Put Lower byte in R0
2D211101 # LOADUI R1 0x1101 ; Write the byte
42100200 # FPUTC ; To TAPE_02 42100200 # FPUTC ; To TAPE_02
# ;; Restore registers # ;; Restore registers
0902802F # POPR R2 R15 0902802F # POPR R2 R15
0902801F # POPR R1 R15 0902801F # POPR R1 R15
0902800F # POPR R0 R15 0902800F # POPR R0 R15
# ;; Be Done # ;; Be Done
0D01001F # RET R15 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 # ;; for Pass1, Will update R11 and modify R0
# ;; Will return to the start of first_pass # ;; Will return to the start of first_pass
# ;; Never call this function, only jump to it # ;; Never call this function, only jump to it
# :ThrowAwayPointer # :ThrowAwayPointer 294
:6 :6
0FBB0002 # ADDUI R11 R11 2 ; Pointers always take up 2 bytes 0FBB0002 # ADDUI R11 R11 2 ; Pointers always take up 2 bytes
2D0F @p # CALLI R15 @throwAwayToken ; Get rid of rest of token 2D0F @j # CALLI R15 @throwAwayToken ; Get rid of rest of token
3C00 @2 # JUMP @first_pass ; Then return to the proper place 3C00 @3 # JUMP @first_pass ; Then return to the proper place
# ;; ThrowAwayAddress function # ;; ThrowAwayAddress function
@ -423,11 +428,11 @@ A0200000 # CMPSKIPI.E R0 0 ; Stop if byte is NULL
# ;; for Pass1, Will update R11 and modify R0 # ;; for Pass1, Will update R11 and modify R0
# ;; Will return to the start of first_pass # ;; Will return to the start of first_pass
# ;; Never call this function, conly jump to it # ;; Never call this function, conly jump to it
# :ThrowAwayAddress # :ThrowAwayAddress 2a0
:v :7
0FBB0004 # ADDUI R11 R11 4 ; Addresses on 32bit systems take up 4 bytes 0FBB0004 # ADDUI R11 R11 4 ; Addresses on 32bit systems take up 4 bytes
2D0F @p # CALLI R15 @throwAwayToken ; Get rid of rest of token 2D0F @j # CALLI R15 @throwAwayToken ; Get rid of rest of token
3C00 @2 # JUMP @first_pass ; Then return to the proper place 3C00 @3 # JUMP @first_pass ; Then return to the proper place
# ;; ThrowAwaylabel function # ;; ThrowAwaylabel function
@ -435,31 +440,39 @@ A0200000 # CMPSKIPI.E R0 0 ; Stop if byte is NULL
# ;; for Pass2, Will update R11 and modify R0 # ;; for Pass2, Will update R11 and modify R0
# ;; Will return to the start of second_pass # ;; Will return to the start of second_pass
# ;; Never call this function, only jump to it # ;; Never call this function, only jump to it
# :ThrowAwayLabel # :ThrowAwayLabel 2ac
:9 :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 3C00 @4 # JUMP @second_pass
# ;; Throw away token function # ;; Throw away token function
# ;; Deals with the general case of not wanting # ;; Deals with the general case of not wanting
# ;; The rest of the characters in a token # ;; The rest of the characters in a token
# ;; This Will alter the values of R0 R1 # ;; This Will alter the values of R0 R1
# ;; Returns back to whatever called it # ;; Returns back to whatever called it
# :throwAwayToken # :throwAwayToken 2b4
:p :j
2D211100 # LOADUI R1 0x1100 ; Read from tape_01
42100100 # FGETC ; Read a Char 42100100 # FGETC ; Read a Char
# ;; Stop looping if space # ;; Stop looping if space
A0300020 # CMPSKIPI.NE R0 32 A0300020 # CMPSKIPI.NE R0 32
0D01001F # RET R15 0D01001F # RET R15
# ;; Stop looping if tab # ;; Stop looping if tab
A0300009 # CMPSKIPI.NE R0 9 A0300009 # CMPSKIPI.NE R0 9
0D01001F # RET R15 0D01001F # RET R15
# ;; Stop looping if newline # ;; Stop looping if newline
A030000a # CMPSKIPI.NE R0 10 A030000a # CMPSKIPI.NE R0 10
0D01001F # RET R15 0D01001F # RET R15
# ;; Stop looping if EOF
A030ffff # CMPSKIPI.NE R0 -1
0D01001F # RET R15
# ;; Otherwise keep looping # ;; Otherwise keep looping
3C00 @p # JUMP @throwAwayToken 3C00 @j # JUMP @throwAwayToken
# ;; Hex function # ;; Hex function
@ -467,82 +480,60 @@ A030000a # CMPSKIPI.NE R0 10
# ;; Identifying hex characters # ;; Identifying hex characters
# ;; Purging line comments # ;; Purging line comments
# ;; Returning the converted value of a hex character # ;; 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 # ;; Returns back to whatever called it
# :hex # :hex 2dc
:7 :8
# ;; Deal with line comments starting with # # ;; Deal with line comments starting with #
1FE00023 # CMPUI R14 R0 35 A0300023 # CMPSKIPI.NE R0 35
2C5E @q # JUMP.E R14 @ascii_comment 3C00 @k # JUMP @ascii_comment
# ;; Deal with line comments starting with ; # ;; Deal with line comments starting with ;
1FE0003b # CMPUI R14 R0 59 A030003b # CMPSKIPI.NE R0 59
2C5E @q # JUMP.E R14 @ascii_comment 3C00 @k # JUMP @ascii_comment
# ;; Deal with all ascii less than '0' # ;; Deal with all ascii less than '0'
1FE00030 # CMPUI R14 R0 48 A0100030 # CMPSKIPI.GE R0 48
2C8E @r # JUMP.L R14 @ascii_other 3C00 @l # JUMP @ascii_other
# ;; Deal with '0'-'9' # ;; Deal with '0'-'9'
1FE00039 # CMPUI R14 R0 57 A0000039 # CMPSKIPI.G R0 57
2C7E @s # JUMP.LE R14 @ascii_num 3C00 @m # JUMP @ascii_num
# ;; Deal with all ascii less than 'A' # ;; Deal with all ascii less than 'A'
1FE00041 # CMPUI R14 R0 65 A0100041 # CMPSKIPI.GE R0 65
2C8E @r # JUMP.L R14 @ascii_other 3C00 @l # JUMP @ascii_other
# ;; Unset high bit to set everything into uppercase
B00000df # ANDI R0 R0 0xDF
# ;; Deal with 'A'-'F' # ;; Deal with 'A'-'F'
1FE00046 # CMPUI R14 R0 70 A0000046 # CMPSKIPI.G R0 70
2C7E @t # JUMP.LE R14 @ascii_high 3C00 @n # JUMP @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
# ;; Ignore the rest # ;; Ignore the rest
3C00 @r # JUMP @ascii_other 3C00 @l # JUMP @ascii_other
# :ascii_num
:s
# :ascii_num 314
:m
11000030 # SUBUI R0 R0 48 11000030 # SUBUI R0 R0 48
0D01001F # RET R15 0D01001F # RET R15
# :ascii_low # :ascii_high 31c
:u :n
11000057 # SUBUI R0 R0 87
0D01001F # RET R15
# :ascii_high
:t
11000037 # SUBUI R0 R0 55 11000037 # SUBUI R0 R0 55
0D01001F # RET R15 0D01001F # RET R15
# :ascii_other # :ascii_comment 324
:r :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 0D000030 # TRUE R0
0D01001F # RET R15 0D01001F # RET R15
# :ascii_comment # ;; Where we will putting our stack
: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
# :stack 33c
# ;; 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
:1 :1

View File

@ -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 <http://www.gnu.org/licenses/>.
: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

View File

@ -14,24 +14,45 @@
; You should have received a copy of the GNU General Public License ; You should have received a copy of the GNU General Public License
; along with stage0. If not, see <http://www.gnu.org/licenses/>. ; along with stage0. If not, see <http://www.gnu.org/licenses/>.
;; Node format:
;; PREV->pointer (register size)
;; Address (register size)
;; NULL terminated string (strln + 1)
:start :start
LOADUI R13 @table ; Where we are putting our table ;; R1 is reserved for reading/writing bytes (don't touch)
;; We will be using R14 for our condition codes ;; We will be using R8 for our malloc pointer
LOADUI R15 0x7FFF ; We will be using R15 for our stack ;; 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 ;; Main program functionality
;; Reads in Tape_01 and writes out results onto Tape_02 ;; Reads in Tape_01 and writes out results onto Tape_02
;; Accepts no arguments and HALTS when done ;; Accepts no arguments and HALTS when done
:main :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 ;; Prep TAPE_01
LOADUI R0 0x1100 LOADUI R0 0x1100
FOPEN_READ FOPEN_READ
;; Intialize environment ;; Intialize environment
LOADUI R1 0x1100 ; Read from tape_01
FALSE R12 ; Set holder to zero FALSE R12 ; Set holder to zero
FALSE R11 ; Set PC counter 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 ;; Perform first pass
CALLI R15 @first_pass CALLI R15 @first_pass
@ -43,9 +64,7 @@
;; Reintialize environment ;; Reintialize environment
FALSE R12 ; Set holder to zero FALSE R12 ; Set holder to zero
FALSE R11 ; Set PC counter to zero FALSE R11 ; Set PC counter to zero
LOADUI R10 1 ; Our toggle FALSE R10 ; Our toggle
LOADUI R9 0xFF ; Byte mask
LOADUI R8 0x0F ; nybble mask
;; Prep TAPE_02 ;; Prep TAPE_02
LOADUI R0 0x1101 LOADUI R0 0x1101
@ -66,7 +85,6 @@
;; Will Overwrite R0 R10 R11 ;; Will Overwrite R0 R10 R11
;; Returns to Main function when done ;; Returns to Main function when done
:first_pass :first_pass
LOADUI R1 0x1100 ; Read from tape_01
FGETC ; Read a Char FGETC ; Read a Char
;; Check for EOF ;; Check for EOF
@ -92,19 +110,13 @@
;; Otherwise attempt to process ;; Otherwise attempt to process
CALLI R15 @hex ; Convert it CALLI R15 @hex ; Convert it
CMPSKIPI.GE R0 0 ; Don't record, nonhex values JUMP.NP R0 @first_pass ; Don't record, nonhex values
JUMP @first_pass ; Move onto Next char
;; Determine if we got a full byte ;; Flip the toggle
JUMP.Z R10 @first_pass_0 ; Jump if toggled 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 ;; 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 ADDUI R11 R11 1 ; increment PC now that that we have a full byte
JUMP @first_pass JUMP @first_pass
@ -115,7 +127,6 @@
;; Will Overwrite R0 R10 R11 ;; Will Overwrite R0 R10 R11
;; Returns to Main function when done ;; Returns to Main function when done
:second_pass :second_pass
LOADUI R1 0x1100 ; Read from tape_01
FGETC ; Read a Char FGETC ; Read a Char
;; Check for EOF ;; Check for EOF
@ -142,21 +153,21 @@
JUMP @second_pass ; Move onto Next char JUMP @second_pass ; Move onto Next char
;; Determine if we got a full byte ;; Determine if we got a full byte
NOT R10 R10
JUMP.Z R10 @second_pass_0 ; Jump if toggled JUMP.Z R10 @second_pass_0 ; Jump if toggled
;; Deal with case of first half of byte ;; Deal with case of first half of byte
AND R12 R0 R8 ; Store our first nibble ANDI R12 R0 0x0F ; Store our first nibble
FALSE R10 ; Flip the toggle
JUMP @second_pass JUMP @second_pass
:second_pass_0 :second_pass_0
;; Deal with case of second half of byte ;; Deal with case of second half of byte
SL0I R12 4 ; Shift our first nybble 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 ADD R0 R0 R12 ; Combine nybbles
TRUE R10 ; Flip the toggle
LOADUI R1 0x1101 ; Write the combined byte LOADUI R1 0x1101 ; Write the combined byte
FPUTC ; To TAPE_02 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 ADDUI R11 R11 1 ; increment PC now that that we have a full byte
JUMP @second_pass JUMP @second_pass
@ -167,32 +178,24 @@
;; Will overwrite R0 ;; Will overwrite R0
;; Returns to first pass when done ;; Returns to first pass when done
:storeLabel :storeLabel
LOADR R0 @current_index ; Get address of first open index COPY R0 R8 ; get current malloc
CMPSKIPI.NE R0 0 ; If zero intialize from R13 ADD R8 R8 R9 ; update malloc
COPY R0 R13
;; Store the PC of the label ;; Add node info
STORE32 R11 R0 0 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 ;; Store the name of the Label
ADDUI R0 R0 4 ; Increment the offset of the index
CALLI R15 @writeout_token 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 ;; And be done
JUMP @first_pass JUMP @first_pass
;; Where we are storing the location of the next free table entry
:current_index
NOP
;; StoreRelativepointer function ;; StoreRelativepointer function
;; Deals with the special case of relative pointers ;; Deals with the special case of relative pointers
;; Clears Temp ;; Stores string
;; Stores string in Temp
;; Finds match in Table ;; Finds match in Table
;; Writes out the offset ;; Writes out the offset
;; Modifies R0 R11 ;; Modifies R0 R11
@ -200,11 +203,7 @@
:StoreRelativePointer :StoreRelativePointer
;; Correct the PC to reflect the size of the pointer ;; Correct the PC to reflect the size of the pointer
ADDUI R11 R11 2 ; Exactly 2 bytes 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 CALLI R15 @Match_string ; Find the Match
LOAD32 R0 R0 -4 ; Get the value we care about
SUB R0 R0 R11 ; Determine the difference SUB R0 R0 R11 ; Determine the difference
ADDUI R0 R0 4 ; Adjust for relative positioning ADDUI R0 R0 4 ; Adjust for relative positioning
CALLI R15 @ProcessImmediate ; Write out the value CALLI R15 @ProcessImmediate ; Write out the value
@ -213,8 +212,7 @@
;; StoreAbsolutepointer function ;; StoreAbsolutepointer function
;; Deals with the special case of absolute pointers ;; Deals with the special case of absolute pointers
;; Clears Temp ;; Stores string
;; Stores string in Temp
;; Finds match in Table ;; Finds match in Table
;; Writes out the absolute address of match ;; Writes out the absolute address of match
;; Modifies R0 R11 ;; Modifies R0 R11
@ -222,19 +220,14 @@
:StoreAbsolutePointer :StoreAbsolutePointer
;; Correct the PC to reflect the size of the pointer ;; Correct the PC to reflect the size of the pointer
ADDUI R11 R11 2 ; Exactly 2 bytes 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 CALLI R15 @Match_string ; Find the Match
LOAD32 R0 R0 -4 ; Get the value we care about
CALLI R15 @ProcessImmediate ; Write out the value CALLI R15 @ProcessImmediate ; Write out the value
JUMP @second_pass JUMP @second_pass
;; StoreAbsoluteAddress function ;; StoreAbsoluteAddress function
;; Deal with the special case of absolute Addresses ;; Deal with the special case of absolute Addresses
;; Clear Temp ;; Stores string
;; Stores string in Temp
;; Finds match in Table ;; Finds match in Table
;; Writes out the full absolute address [32 bit machine] ;; Writes out the full absolute address [32 bit machine]
;; Modifies R0 R11 ;; Modifies R0 R11
@ -242,36 +235,26 @@
:StoreAbsoluteAddress :StoreAbsoluteAddress
;; COrrect the PC to reflect the size of the address ;; COrrect the PC to reflect the size of the address
ADDUI R11 R11 4 ; 4 Bytes on 32bit machines 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 CALLI R15 @Match_string ; Find the Match
PUSHR R14 R15 ; Get a temp storage place ANDI R2 R0 0xFFFF ; Save bottom half for next function
LOAD32 R14 R0 -4 ; Get the value we care about
COPY R0 R14 ; We need to print the top 2 bytes first
SARI R0 16 ; Drop bottom 16 bits SARI R0 16 ; Drop bottom 16 bits
CALLI R15 @ProcessImmediate ; Write out top 2 bytes CALLI R15 @ProcessImmediate ; Write out top 2 bytes
LOADUI R0 0xFFFF ; Provide mask to keep bottom 2 bytes MOVE R0 R2 ; Use the saved 16bits
AND R0 R0 R14 ; Drop top 16 bits
POPR R14 R15 ; Restore R14
CALLI R15 @ProcessImmediate ; Write out bottom 2 bytes CALLI R15 @ProcessImmediate ; Write out bottom 2 bytes
JUMP @second_pass JUMP @second_pass
;; Writeout Token Function ;; Writeout Token Function
;; Writes the Token [minus first char] to the address ;; Writes the Token [minus first char] to the address
;; It recieves in R0 until it reaches a delimiter ;; given by malloc and updates malloc pointer
;; All register values are preserved ;; Returns starting address of string
;; Returns to whatever called it
:writeout_token :writeout_token
;; Preserve registers ;; Preserve registers
PUSHR R0 R15
PUSHR R1 R15 PUSHR R1 R15
PUSHR R2 R15 PUSHR R2 R15
;; Initialize ;; Initialize
MOVE R2 R0 ; Set R2 as our index COPY R2 R8 ; Get current malloc pointer
LOADUI R1 0x1100 ; Read from tape_01
;; Our core loop ;; Our core loop
:writeout_token_0 :writeout_token_0
@ -284,54 +267,31 @@
JUMP @writeout_token_done JUMP @writeout_token_done
CMPSKIPI.NE R0 10 ; Finished if newline CMPSKIPI.NE R0 10 ; Finished if newline
JUMP @writeout_token_done JUMP @writeout_token_done
CMPSKIPI.NE R0 -1 ; Finished if EOF
JUMP @writeout_token_done
;; Deal with valid input ;; Deal with valid input
STORE8 R0 R2 0 ; Write out the byte STORE8 R0 R8 0 ; Write out the byte
ADDUI R2 R2 1 ; Increment ADDUI R8 R8 1 ; Increment
JUMP @writeout_token_0 ; Keep looping JUMP @writeout_token_0 ; Keep looping
;; Clean up now that we are done ;; Clean up now that we are done
:writeout_token_done :writeout_token_done
;; Fix malloc
ADDUI R8 R8 1
;; Prepare for return
MOVE R0 R2
;; Restore registers ;; Restore registers
POPR R2 R15 POPR R2 R15
POPR R1 R15 POPR R1 R15
POPR R0 R15
;; And be done ;; And be done
RET R15 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 ;; Match string function
;; Walks down table until match is found ;; Walks down list until match is found or returns -1
;; Then returns address of matching string in R0 ;; Reads a token
;; Then returns address of match in R0
;; Returns to whatever called it ;; Returns to whatever called it
:Match_string :Match_string
;; Preserve registers ;; Preserve registers
@ -339,23 +299,24 @@
PUSHR R2 R15 PUSHR R2 R15
;; Initialize for Loop ;; Initialize for Loop
LOADUI R1 $Temp ; We always compare against Temp CALLI R15 @writeout_token ; Get our desired string
LOADUI R2 $table ; Begin at start of table MOVE R1 R0 ; Position our desired string
ADDUI R2 R2 4 ; Where the string is located COPY R2 R14 ; Begin at our head node
;; Loop until we find a match ;; Loop until we find a match
:Match_string_0 :Match_string_0
COPY R0 R2 ; Set R0 to our current string ADD R0 R2 R9 ; Where the string is located
CALLI R15 @strcmp CALLI R15 @strcmp
JUMP.E R0 @Match_string_1 ; It is a match! JUMP.E R0 @Match_string_1 ; It is a match!
;; Prepare for next loop ;; Prepare for next loop
LOADUI R1 $Temp ; That function clears R1 LOAD R2 R2 0 ; Move to next node
ADDUI R2 R2 64 ; Each Index is 64 bytes JUMP.NZ R2 @Match_string_0 ; Keep looping
JUMP @Match_string_0 ; Keep looping TRUE R2 ; Set result to -1 if not found
:Match_string_1 :Match_string_1
;; Store the correct answer ;; 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 ;; Restore registers
POPR R2 R15 POPR R2 R15
POPR R1 R15 POPR R1 R15
@ -365,10 +326,10 @@
;; Our simple string compare function ;; Our simple string compare function
;; Recieves two pointers in R0 and R1 ;; Recieves two pointers in R0 and R1
;; Returns the difference between the strings in R0 ;; Returns the difference between the strings in R0
;; Clears R1
;; Returns to whatever called it ;; Returns to whatever called it
:strcmp :strcmp
;; Preserve registers ;; Preserve registers
PUSHR R1 R15
PUSHR R2 R15 PUSHR R2 R15
PUSHR R3 R15 PUSHR R3 R15
PUSHR R4 R15 PUSHR R4 R15
@ -377,18 +338,19 @@
MOVE R3 R1 MOVE R3 R1
LOADUI R4 0 LOADUI R4 0
:cmpbyte :cmpbyte
LOADXU8 R0 R2 R4 ; Get a byte of our first string LOADXU8 R0 R2 R4 ; Get a byte of our first string
LOADXU8 R1 R3 R4 ; Get a byte of our second string LOADXU8 R1 R3 R4 ; Get a byte of our second string
ADDUI R4 R4 1 ; Prep for next loop ADDUI R4 R4 1 ; Prep for next loop
CMP R1 R0 R1 ; Compare the bytes CMP R1 R0 R1 ; Compare the bytes
CMPSKIPI.E R0 0 ; Stop if byte is NULL CMPSKIPI.E R0 0 ; Stop if byte is NULL
JUMP.E R1 @cmpbyte ; Loop if bytes are equal JUMP.E R1 @cmpbyte ; Loop if bytes are equal
;; Done ;; Done
MOVE R0 R1 ; Prepare for return MOVE R0 R1 ; Prepare for return
;; Restore registers ;; Restore registers
POPR R4 R15 POPR R4 R15
POPR R3 R15 POPR R3 R15
POPR R2 R15 POPR R2 R15
POPR R1 R15
RET R15 RET R15
@ -403,16 +365,15 @@
PUSHR R1 R15 PUSHR R1 R15
PUSHR R2 R15 PUSHR R2 R15
;; Break up Immediate ;; Break up Immediate
AND R2 R0 R9 ; Put lower byte in R2 ANDI R2 R0 0xFF ; Put lower byte in R2
SARI R0 8 ; Drop Bottom byte from R0 SARI R0 8 ; Drop Bottom byte from R0
AND R0 R0 R9 ; Maskout everything outside of top byte ANDI R0 R0 0xFF ; Maskout everything outside of top byte
;; Write out Top Byte ;; Write out Top Byte
LOADUI R1 0x1101 ; Write the byte LOADUI R1 0x1101 ; Write the byte
FPUTC ; To TAPE_02 FPUTC ; To TAPE_02
;; Write out bottom Byte ;; Write out bottom Byte
MOVE R0 R2 ; Put Lower byte in R0 MOVE R0 R2 ; Put Lower byte in R0
LOADUI R1 0x1101 ; Write the byte
FPUTC ; To TAPE_02 FPUTC ; To TAPE_02
;; Restore registers ;; Restore registers
@ -460,7 +421,6 @@
;; This Will alter the values of R0 R1 ;; This Will alter the values of R0 R1
;; Returns back to whatever called it ;; Returns back to whatever called it
:throwAwayToken :throwAwayToken
LOADUI R1 0x1100 ; Read from tape_01
FGETC ; Read a Char FGETC ; Read a Char
;; Stop looping if space ;; Stop looping if space
@ -475,6 +435,10 @@
CMPSKIPI.NE R0 10 CMPSKIPI.NE R0 10
RET R15 RET R15
;; Stop looping if EOF
CMPSKIPI.NE R0 -1
RET R15
;; Otherwise keep looping ;; Otherwise keep looping
JUMP @throwAwayToken JUMP @throwAwayToken
@ -484,75 +448,47 @@
;; Identifying hex characters ;; Identifying hex characters
;; Purging line comments ;; Purging line comments
;; Returning the converted value of a hex character ;; 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 ;; Returns back to whatever called it
:hex :hex
;; Deal with line comments starting with # ;; Deal with line comments starting with #
CMPUI R14 R0 35 CMPSKIPI.NE R0 35
JUMP.E R14 @ascii_comment JUMP @ascii_comment
;; Deal with line comments starting with ; ;; Deal with line comments starting with ;
CMPUI R14 R0 59 CMPSKIPI.NE R0 59
JUMP.E R14 @ascii_comment JUMP @ascii_comment
;; Deal with all ascii less than '0' ;; Deal with all ascii less than '0'
CMPUI R14 R0 48 CMPSKIPI.GE R0 48
JUMP.L R14 @ascii_other JUMP @ascii_other
;; Deal with '0'-'9' ;; Deal with '0'-'9'
CMPUI R14 R0 57 CMPSKIPI.G R0 57
JUMP.LE R14 @ascii_num JUMP @ascii_num
;; Deal with all ascii less than 'A' ;; Deal with all ascii less than 'A'
CMPUI R14 R0 65 CMPSKIPI.GE R0 65
JUMP.L R14 @ascii_other JUMP @ascii_other
;; Unset high bit to set everything into uppercase
ANDI R0 R0 0xDF
;; Deal with 'A'-'F' ;; Deal with 'A'-'F'
CMPUI R14 R0 70 CMPSKIPI.G R0 70
JUMP.LE R14 @ascii_high JUMP @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
;; Ignore the rest ;; Ignore the rest
JUMP @ascii_other JUMP @ascii_other
:ascii_num :ascii_num
SUBUI R0 R0 48 SUBUI R0 R0 48
RET R15 RET R15
:ascii_low
SUBUI R0 R0 87
RET R15
:ascii_high :ascii_high
SUBUI R0 R0 55 SUBUI R0 R0 55
RET R15 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 :ascii_other
TRUE R0 TRUE R0
RET R15 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 ;; Where we will putting our stack
:Temp :stack
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
;; Where we will putting our Table
:table

View File

@ -7,4 +7,4 @@ b3a910f18c6bc0ef4aa7a53cb3f0216a9f143319da67ed2a02210fe88b1e1131 roms/forth
0a427b14020354d1c785f5f900677e0059fce8f8d4456e9c19e5528cb17101eb roms/stage0_monitor 0a427b14020354d1c785f5f900677e0059fce8f8d4456e9c19e5528cb17101eb roms/stage0_monitor
3ea7fed1429400c1d6fc5b85180c4114755dfb1e6b88d69e7ecc465a40523bc8 roms/stage1_assembler-0 3ea7fed1429400c1d6fc5b85180c4114755dfb1e6b88d69e7ecc465a40523bc8 roms/stage1_assembler-0
b6aabcc3418a0a28f4ed32ace43b20103d9d21dffae03e7936cb14fa0e044013 roms/stage1_assembler-1 b6aabcc3418a0a28f4ed32ace43b20103d9d21dffae03e7936cb14fa0e044013 roms/stage1_assembler-1
61c1b0f2f628847d9491bd678ac7a23231527cc36493b321612f191674ff3c99 roms/stage1_assembler-2 7b02babee42a3c05b001fb44fb0917383d8f185e2817d57ad2349a4b36dfa4ed roms/stage1_assembler-2