Tuned M0 for much better performance (down to 9/32 previous)

This commit is contained in:
Jeremiah Orians 2017-12-26 00:01:53 -05:00
parent deac93c6f2
commit 8396dc15df
No known key found for this signature in database
GPG Key ID: 7457821534D2ACCD
5 changed files with 338 additions and 744 deletions

View File

@ -32,6 +32,7 @@ Corrected behavior when using the web IDE and attempting to set registers that d
Fixed regression in hex.c caused by refactoring Fixed regression in hex.c caused by refactoring
Fixed output of large negative numbers in hex Fixed output of large negative numbers in hex
Updated checksums to reflect changed made in performance tuning Updated checksums to reflect changed made in performance tuning
Fixed M0 performance by a factor of 4
** 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

View File

@ -116,7 +116,7 @@ To build our line macro assembler:
Now with our new line macro assembler, which with our definition file High_level_prototypes/defs means we can write straight assembly from here on out. Now with our new line macro assembler, which with our definition file High_level_prototypes/defs means we can write straight assembly from here on out.
roms/M0 should have the sha256sum of 2b9727381aec15a504c0898189fbc2344209d8e04451e3fa5d743e08e38f64cf roms/M0 should have the sha256sum of 47bc5a29e37bbe4cac31ba612f5e452210b0c4364e529116b9a1c4976912c29d
* Step 5b Saving a bunch of duplicate work * Step 5b Saving a bunch of duplicate work
Assuming that you have been doing all of the above the hard way on physical hardware with real paper tapes, this step is for you. Assuming that you have been doing all of the above the hard way on physical hardware with real paper tapes, this step is for you.

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.
@ -16,130 +16,108 @@
:start :start
# ;; We will be using R13 for storage of Head # ;; We will be using R13 for storage of Head
# ;; We will be using R14 for our condition codes 2D2E 4000 # LOADUI R14 0x4000 ; Our malloc pointer (Initialized)
2D2F $stack # LOADUI R15 $stack ; Put stack at end of progra 2D2F $stack # LOADUI R15 $stack ; Put stack at end of program
# ;; Main program # ;; Main program
# ;; Reads contents of Tape_01 and applies all Definitions # ;; Reads contents of Tape_01 and applies all Definitions
# ;; Writes results to Tape_02 # ;; Writes results to Tape_02
# ;; Accepts no arguments and HALTS when done # ;; Accepts no arguments and HALTS when done
:main :main
# ;; Prep TAPE_01
2D201100 # LOADUI R0 0x1100
42100000 # FOPEN_READ
0D00002D # FALSE R13 ; Head is NULL
09000510 # MOVE R1 R0 ; Read Tape_01
0D00002E # FALSE R14 ; We haven't yet reached EOF
:main_0
2D0F @Tokenize_Line # CALLI R15 @Tokenize_Line ; Call Tokenize_Line 2D0F @Tokenize_Line # CALLI R15 @Tokenize_Line ; Call Tokenize_Line
2C9E @main_0 # JUMP.Z R14 @main_0 ; Until we reach EOF 2D0F @reverse_list # CALLI R15 @reverse_list ; Reverse the list of tokens
# ;; Done reading File
2D201100 # LOADUI R0 0x1100 ; Close TAPE_01
42100002 # FCLOSE
0900040D # COPY R0 R13 ; Prepare for function
2D0F @Identify_Macros # CALLI R15 @Identify_Macros ; Tag all nodes that are macros 2D0F @Identify_Macros # CALLI R15 @Identify_Macros ; Tag all nodes that are macros
2D0F @Line_Macro # CALLI R15 @Line_Macro ; Apply macros down nodes 2D0F @Line_Macro # CALLI R15 @Line_Macro ; Apply macros down nodes
2D0F @Process_String # CALLI R15 @Process_String ; Convert string values to Hex16 2D0F @Process_String # CALLI R15 @Process_String ; Convert string values to Hex16
2D0F @Eval_Immediates # CALLI R15 @Eval_Immediates ; Convert numbers to hex 2D0F @Eval_Immediates # CALLI R15 @Eval_Immediates ; Convert numbers to hex
2D0F @Preserve_Other # CALLI R15 @Preserve_Other ; Ensure labels/Pointers aren't lost 2D0F @Preserve_Other # CALLI R15 @Preserve_Other ; Ensure labels/Pointers aren't lost
# ;; Prep TAPE_02
2D201101 # LOADUI R0 0x1101
42100001 # FOPEN_WRITE
2D0F @Print_Hex # CALLI R15 @Print_Hex ; Write Nodes to Tape_02 2D0F @Print_Hex # CALLI R15 @Print_Hex ; Write Nodes to Tape_02
# ;; Done writing File
2D201101 # LOADUI R0 0x1101 ; Close TAPE_01
42100002 # FCLOSE
FFFFFFFF # HALT ; We are Done FFFFFFFF # HALT ; We are Done
# ;; Primative malloc function
# ;; Recieves number of bytes to allocate in R0
# ;; Returns pointer to block of that size in R0
# ;; Returns to whatever called it
:malloc
# ;; Preserve registers
0902001F # PUSHR R1 R15
# ;; Get current malloc pointer
2E01 @malloc_pointer # LOADR R1 @malloc_pointer
# ;; Deal with special case
A0310000 # CMPSKIPI.NE R1 0 ; If Zero set to our start of heap space
2D214000 # LOADUI R1 0x4000
# ;; update malloc pointer
09000301 # SWAP R0 R1
05000101 # ADD R1 R0 R1
2F01 @malloc_pointer # STORER R1 @malloc_pointer
# ;; Done
# ;; Restore registers
0902801F # POPR R1 R15
0D01001F # RET R15
# ;; Our static value for malloc pointer
:malloc_pointer
00000000 # NOP
# ;; Tokenize_Line function # ;; Tokenize_Line function
# ;; Recieves pointer to Head in R0 and desired input in R1 # ;; Opens tape_01 and reads into a backwards linked list in R13
# ;; Alters R14 when EOF Reached
# ;; Returns to whatever called it # ;; Returns to whatever called it
:Tokenize_Line :Tokenize_Line
# ;; Preserve registers # ;; Prep TAPE_01
0902000F # PUSHR R0 R15 2D201100 # LOADUI R0 0x1100
0902001F # PUSHR R1 R15 42100000 # FOPEN_READ
0902002F # PUSHR R2 R15 0D00002D # FALSE R13 ; Head is NULL
0902003F # PUSHR R3 R15 09000510 # MOVE R1 R0 ; Read Tape_01
0902004F # PUSHR R4 R15
# ;; Initialize
0900044D # COPY R4 R13 ; Get Head pointer out of the way
:Tokenize_Line_0 :Tokenize_Line_0
42100100 # FGETC ; Get a Char 42100100 # FGETC ; Get a Char
# ;; Deal with lines comments starting with # # ;; Deal with lines comments starting with #
A0300023 # CMPSKIPI.NE R0 35 A0300023 # CMPSKIPI.NE R0 35
3C00 @Purge_Line_Comment # JUMP @Purge_Line_Comment 3C00 @Purge_Line_Comment # JUMP @Purge_Line_Comment
# ;; Deal with Line comments starting with ; # ;; Deal with Line comments starting with ;
A030003b # CMPSKIPI.NE R0 59 A030003b # CMPSKIPI.NE R0 59
3C00 @Purge_Line_Comment # JUMP @Purge_Line_Comment 3C00 @Purge_Line_Comment # JUMP @Purge_Line_Comment
# ;; Deal with Tab # ;; Deal with Tab
A0300009 # CMPSKIPI.NE R0 9 A0300009 # CMPSKIPI.NE R0 9
3C00 @Tokenize_Line_0 # JUMP @Tokenize_Line_0 ; Throw away byte and try again 3C00 @Tokenize_Line_0 # JUMP @Tokenize_Line_0 ; Throw away byte and try again
# ;; Deal with New line # ;; Deal with New line
A030000a # CMPSKIPI.NE R0 10 A030000a # CMPSKIPI.NE R0 10
3C00 @Tokenize_Line_0 # JUMP @Tokenize_Line_0 ; Throw away byte and try again 3C00 @Tokenize_Line_0 # JUMP @Tokenize_Line_0 ; Throw away byte and try again
# ;; Deal with space characters # ;; Deal with space characters
A0300020 # CMPSKIPI.NE R0 32 A0300020 # CMPSKIPI.NE R0 32
3C00 @Tokenize_Line_0 # JUMP @Tokenize_Line_0 ; Throw away byte and try again 3C00 @Tokenize_Line_0 # JUMP @Tokenize_Line_0 ; Throw away byte and try again
# ;; Flag if reached EOF
A0100000 # CMPSKIPI.GE R0 0
0D00003E # TRUE R14
# ;; Stop if EOF # ;; Stop if EOF
A0100000 # CMPSKIPI.GE R0 0 A0100000 # CMPSKIPI.GE R0 0
3C00 @Tokenize_Line_Done # JUMP @Tokenize_Line_Done 3C00 @Tokenize_Line_Done # JUMP @Tokenize_Line_Done
# ;; Allocate a new Node # ;; Allocate a new Node
09000520 # MOVE R2 R0 ; Get Char out the way 0900042E # COPY R2 R14 ; Get address of new Node
2D200010 # LOADUI R0 16 ; Allocate 16 Bytes 0FEE0010 # ADDUI R14 R14 16 ; Allocate 16 Bytes
2D0F @malloc # CALLI R15 @malloc ; Get address of new Node 23E20008 # STORE32 R14 R2 8 ; Set Text pointer
09000320 # SWAP R2 R0 ; Store Pointer in R2
# ;; Deal with Strings wrapped in "" # ;; Deal with Strings wrapped in \"
A0300022 # CMPSKIPI.NE R0 34 A0300022 # CMPSKIPI.NE R0 34
3C00 @Store_String # JUMP @Store_String 3C00 @Store_String # JUMP @Store_String
# ;; Deal with Strings wrapped in ' # ;; Deal with Strings wrapped in '
A0300027 # CMPSKIPI.NE R0 39 A0300027 # CMPSKIPI.NE R0 39
3C00 @Store_String # JUMP @Store_String 3C00 @Store_String # JUMP @Store_String
# ;; Everything else is an atom store it # ;; Everything else is an atom store it
2D0F @Store_Atom # CALLI R15 @Store_Atom 2D0F @Store_Atom # CALLI R15 @Store_Atom
:Tokenize_Line_1
23D20000 # STORE32 R13 R2 0 ; Set p->next to head
090005D2 # MOVE R13 R2 ; Set head to p
3C00 @Tokenize_Line_0 # JUMP @Tokenize_Line_0 ; Keep getting tokens
:Tokenize_Line_Done :Tokenize_Line_Done
09000512 # MOVE R1 R2 ; Put Node pointer we are working on into R1 # ;; Done reading File
0900040D # COPY R0 R13 ; Get current HEAD 2D201100 # LOADUI R0 0x1100 ; Close TAPE_01
2D0F @Add_Token # CALLI R15 @Add_Token ; Append new token to Head 42100002 # FCLOSE
# ;; Restore registers 0D01001F # RET R15
0902804F # POPR R4 R15
0902803F # POPR R3 R15
0902802F # POPR R2 R15 # ;; reverse_list Function
0902801F # POPR R1 R15 # ;; Reverses the list given in R13
0902800F # POPR R0 R15 :reverse_list
# ;; Return since we are done # ;; Initialize
0900040D # COPY R0 R13 ; Using R0 as head
0D000021 # FALSE R1 ; Using R1 as root
# ; Using R2 as next
:reverse_list_0
2C90 @reverse_list_done # JUMP.Z R0 @reverse_list_done ; Stop if NULL == head
13200000 # LOAD R2 R0 0 ; next = head->next
20100000 # STORE R1 R0 0 ; head->next = root
09000510 # MOVE R1 R0 ; root = head
09000502 # MOVE R0 R2 ; head = next
3C00 @reverse_list_0 # JUMP @reverse_list_0 ; Keep looping
:reverse_list_done
# ;; Clean up
090005D1 # MOVE R13 R1 ; Set token_list to root
0D01001F # RET R15 0D01001F # RET R15
@ -161,33 +139,20 @@ A020000a # CMPSKIPI.E R0 10 ; Stop When LF is reached
# ;; Modifies node Text to point to string and sets # ;; Modifies node Text to point to string and sets
# ;; Type to string. # ;; Type to string.
:Store_String :Store_String
# ;; Preserve registers
0902004F # PUSHR R4 R15
0902005F # PUSHR R5 R15
0902006F # PUSHR R6 R15
# ;; Initialize # ;; Initialize
09000560 # MOVE R6 R0 ; Get R0 out of the way 09000430 # COPY R3 R0 ; Copy Char for comparison
2D0F @malloc # CALLI R15 @malloc ; Get where space is free
09000540 # MOVE R4 R0 ; Put pointer someplace safe
0D000025 # FALSE R5 ; Start at index 0
09000406 # COPY R0 R6 ; Copy Char back into R0
# ;; Primary Loop
:Store_String_0 :Store_String_0
05049045 # STOREX8 R0 R4 R5 ; Store the Byte 210E0000 # STORE8 R0 R14 0 ; Store the Byte
42100100 # FGETC ; Get next Byte 42100100 # FGETC ; Get next Byte
0F550001 # ADDUI R5 R5 1 ; Prep for next loop 0FEE0001 # ADDUI R14 R14 1 ; Prep for next loop
C306 @Store_String_0 # CMPJUMPI.NE R0 R6 @Store_String_0 ; Loop if matching not found C303 @Store_String_0 # CMPJUMPI.NE R0 R3 @Store_String_0 ; Loop if matching not found
# ;; Clean up # ;; Clean up
23420008 # STORE32 R4 R2 8 ; Set Text pointer 0FEE0004 # ADDUI R14 R14 4 ; Correct Malloc
0F050004 # ADDUI R0 R5 4 ; Correct Malloc
2D0F @malloc # CALLI R15 @malloc ; To the amount of space used
2D200002 # LOADUI R0 2 ; Using type string 2D200002 # LOADUI R0 2 ; Using type string
23020004 # STORE32 R0 R2 4 ; Set node type 23020004 # STORE32 R0 R2 4 ; Set node type
# ;; Restore Registers 3C00 @Tokenize_Line_1 # JUMP @Tokenize_Line_1
0902806F # POPR R6 R15
0902805F # POPR R5 R15
0902804F # POPR R4 R15
3C00 @Tokenize_Line_Done # JUMP @Tokenize_Line_Done
# ;; Store_Atom function # ;; Store_Atom function
@ -195,74 +160,22 @@ C306 @Store_String_0 # CMPJUMPI.NE R0 R6 @Store_String_0 ; Loop if matching not
# ;; And node pointer in R2 # ;; And node pointer in R2
# ;; Modifies node Text to point to string # ;; Modifies node Text to point to string
:Store_Atom :Store_Atom
# ;; Preserve registers 210E0000 # STORE8 R0 R14 0 ; Store the Byte
0902004F # PUSHR R4 R15
0902005F # PUSHR R5 R15
# ;; Initialize
09000550 # MOVE R5 R0 ; Get R0 out of the way
2D0F @malloc # CALLI R15 @malloc ; Get where space is free
09000540 # MOVE R4 R0 ; Put pointer someplace safe
09000505 # MOVE R0 R5 ; Copy Char back and Set index to 0
# ;; Primary Loop
:Store_Atom_0
05049045 # STOREX8 R0 R4 R5 ; Store the Byte
42100100 # FGETC ; Get next Byte 42100100 # FGETC ; Get next Byte
0F550001 # ADDUI R5 R5 1 ; Prep for next loop 0FEE0001 # ADDUI R14 R14 1 ; Prep for next loop
A0300009 # CMPSKIPI.NE R0 9 ; If char is Tab A0300009 # CMPSKIPI.NE R0 9 ; If char is Tab
3C00 @Store_Atom_Done # JUMP @Store_Atom_Done ; Be done 3C00 @Store_Atom_Done # JUMP @Store_Atom_Done ; Be done
A030000a # CMPSKIPI.NE R0 10 ; If char is LF A030000a # CMPSKIPI.NE R0 10 ; If char is LF
3C00 @Store_Atom_Done # JUMP @Store_Atom_Done ; Be done 3C00 @Store_Atom_Done # JUMP @Store_Atom_Done ; Be done
A0300020 # CMPSKIPI.NE R0 32 ; If char is Space A0300020 # CMPSKIPI.NE R0 32 ; If char is Space
3C00 @Store_Atom_Done # JUMP @Store_Atom_Done ; Be done 3C00 @Store_Atom_Done # JUMP @Store_Atom_Done ; Be done
# ;; Otherwise loop # ;; Otherwise loop
3C00 @Store_Atom_0 # JUMP @Store_Atom_0 3C00 @Store_Atom # JUMP @Store_Atom
:Store_Atom_Done :Store_Atom_Done
# ;; Cleanup # ;; Cleanup
23420008 # STORE32 R4 R2 8 ; Set Text pointer 0FEE0001 # ADDUI R14 R14 1 ; Correct Malloc
0F050001 # ADDUI R0 R5 1 ; Correct Malloc
2D0F @malloc # CALLI R15 @malloc ; To the amount of space used
# ;; Restore Registers
0902805F # POPR R5 R15
0902804F # POPR R4 R15
0D01001F # RET R15
# ;; Add_Token Function
# ;; Recieves pointers in R0 R1
# ;; Alters R13 if R) is NULL
# ;; Appends nodes together
# ;; Returns to whatever called it
:Add_Token
# ;; Preserve Registers
0902002F # PUSHR R2 R15
0902001F # PUSHR R1 R15
0902000F # PUSHR R0 R15
# ;; Handle if Head is NULL
2CA0 @Add_Token_0 # JUMP.NZ R0 @Add_Token_0
090004D1 # COPY R13 R1 ; Fix head
0902800F # POPR R0 R15 ; Clean up register
0902001F # PUSHR R1 R15 ; And act like we passed the reverse
3C00 @Add_Token_2 # JUMP @Add_Token_2
:Add_Token_0
# ;; Handle if Head->next is NULL
18200000 # LOAD32 R2 R0 0
2CA2 @Add_Token_1 # JUMP.NZ R2 @Add_Token_1
# ;; Set head->next = p
23100000 # STORE32 R1 R0 0
3C00 @Add_Token_2 # JUMP @Add_Token_2
:Add_Token_1
# ;; Handle case of Head->next not being NULL
18000000 # LOAD32 R0 R0 0 ; Move to next node
18200000 # LOAD32 R2 R0 0 ; Get node->next
A0220000 # CMPSKIPI.E R2 0 ; If it is not null
3C00 @Add_Token_1 # JUMP @Add_Token_1 ; Move to the next node and try again
3C00 @Add_Token_0 # JUMP @Add_Token_0 ; Else simply act as if we got this node
# ; in the first place
:Add_Token_2
# ;; Restore registers
0902800F # POPR R0 R15
0902801F # POPR R1 R15
0902802F # POPR R2 R15
0D01001F # RET R15 0D01001F # RET R15
@ -273,94 +186,87 @@ A0220000 # CMPSKIPI.E R2 0 ; If it is not null
# ;; Returns to whatever called it # ;; Returns to whatever called it
:strcmp :strcmp
# ;; 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 ; Put R0 in a safe place 09000520 # MOVE R2 R0 ; Put R0 in a safe place
09000531 # MOVE R3 R1 ; Put R1 in a safe place 09000531 # MOVE R3 R1 ; Put R1 in a safe place
2D240000 # LOADUI R4 0 ; Starting at index 0 0D000024 # FALSE R4 ; Starting at index 0
:cmpbyte :cmpbyte
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 05004001 # CMP R0 R0 R1 ; Compare the bytes
A0200000 # CMPSKIPI.E R0 0 ; Stop if byte is NULL A0210000 # CMPSKIPI.E R1 0 ; Stop if byte is NULL
2C51 @cmpbyte # JUMP.E R1 @cmpbyte ; Loop if bytes are equal 2C50 @cmpbyte # JUMP.E R0 @cmpbyte ; Loop if bytes are equal
# ;; Done # ;; Done
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
# ;; Identify_Macros Function # ;; Identify_Macros Function
# ;; Recieves a pointer to a node in R0
# ;; If the text stored in its Text segment matches # ;; If the text stored in its Text segment matches
# ;; DEFINE, flag it and Collapse it down to a single Node # ;; DEFINE, flag it and Collapse it down to a single Node
# ;; Loop until all nodes are checked # ;; Loop until all nodes are checked
# ;; Return to whatever called it # ;; Return to whatever called it
:Identify_Macros :Identify_Macros
# ;; Preserve Registers # ;; Initializ
0902000F # PUSHR R0 R15 2D2101d0 # LOADUI R1 $Identify_Macros_string
0902001F # PUSHR R1 R15 0900042D # COPY R2 R13 ; i = head
0902002F # PUSHR R2 R15
0902003F # PUSHR R3 R15
# ;; Main Loop # ;; Main Loop
:Identify_Macros_0 :Identify_Macros_0
09000520 # MOVE R2 R0 18020008 # LOAD32 R0 R2 8 ; Get Pointer to Text
18120008 # LOAD32 R1 R2 8 ; Get Pointer to Text
2D20 $Identify_Macros_string # LOADUI R0 $Identify_Macros_string
2D0F @strcmp # CALLI R15 @strcmp 2D0F @strcmp # CALLI R15 @strcmp
09000512 # MOVE R1 R2
2C60 @Identify_Macros_1 # JUMP.NE R0 @Identify_Macros_1 2C60 @Identify_Macros_1 # JUMP.NE R0 @Identify_Macros_1
# ;; It is a definition # ;; It is a definition
# ;; Set p->Type = macro # ;; Set i->Type = macro
2D200001 # LOADUI R0 1 ; The Enum value for macro 2D200001 # LOADUI R0 1 ; The Enum value for macro
23010004 # STORE32 R0 R1 4 ; Set node type 23020004 # STORE32 R0 R2 4 ; Set node type
# ;; Set p->Text = p->Next->Text
18210000 # LOAD32 R2 R1 0 ; Get Next # ;; Set i->Text = i->Next->Text
18020008 # LOAD32 R0 R2 8 ; Get Next->Text 18420000 # LOAD32 R4 R2 0 ; Get Next
23010008 # STORE32 R0 R1 8 ; Set Text = Next->Text 18040008 # LOAD32 R0 R4 8 ; Get Next->Text
# ;; Set p->Expression = p->next->next->Text 23020008 # STORE32 R0 R2 8 ; Set i->Text = Next->Text
18220000 # LOAD32 R2 R2 0 ; Get Next->Next
18020008 # LOAD32 R0 R2 8 ; Get Next->Next->Text # ;; Set i->Expression = i->next->next->Text
18320004 # LOAD32 R3 R2 4 ; Get Next->Next->type 18440000 # LOAD32 R4 R4 0 ; Get Next->Next
18040008 # LOAD32 R0 R4 8 ; Get Next->Next->Text
18340004 # LOAD32 R3 R4 4 ; Get Next->Next->type
A0330002 # CMPSKIPI.NE R3 2 ; If node is a string A0330002 # CMPSKIPI.NE R3 2 ; If node is a string
0F000001 # ADDUI R0 R0 1 ; Skip first char 0F000001 # ADDUI R0 R0 1 ; Skip first char
2301000c # STORE32 R0 R1 12 ; Set Expression = Next->Next->Text 2302000c # STORE32 R0 R2 12 ; Set Expression = Next->Next->Text
# ;; Set p->Next = p->Next->Next->Next
18020000 # LOAD32 R0 R2 0 ; Get Next->Next->Next # ;; Set i->Next = i->Next->Next->Next
23010000 # STORE32 R0 R1 0 ; Set Next = Next->Next->Next 18440000 # LOAD32 R4 R4 0 ; Get Next->Next->Next
23420000 # STORE32 R4 R2 0 ; Set i->Next = Next->Next->Next
:Identify_Macros_1 :Identify_Macros_1
18010000 # LOAD32 R0 R1 0 ; Get node->next 18220000 # LOAD32 R2 R2 0 ; Get node->next
A0300000 # CMPSKIPI.NE R0 0 ; If node->next is NULL 2CA2 @Identify_Macros_0 # JUMP.NZ R2 @Identify_Macros_0 ; Loop if i not NULL
3C00 @Identify_Macros_Done # JUMP @Identify_Macros_Done ; Be done
# ;; Otherwise keep looping
3C00 @Identify_Macros_0 # JUMP @Identify_Macros_0
:Identify_Macros_Done
# ;; Restore registers
0902803F # POPR R3 R15
0902802F # POPR R2 R15
0902801F # POPR R1 R15
0902800F # POPR R0 R15
0D01001F # RET R15 0D01001F # RET R15
:Identify_Macros_string :Identify_Macros_string
444546494E450000 # "DEFINE" 444546494E450000 # "DEFINE" ;; Line_Macro Function
# ;; Line_Macro Function
# ;; Recieves a node pointer in R0 # ;; Recieves a node pointer in R0
# ;; Causes macros to be applied # ;; Causes macros to be applied
# ;; Returns to whatever called it # ;; Returns to whatever called it
:Line_Macro :Line_Macro
# ;; Preserve Registers # ;; Initialize
0902000F # PUSHR R0 R15 0900040D # COPY R0 R13 ; Start with Head
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
0902003F # PUSHR R3 R15
# ;; Main loop # ;; Main loop
:Line_Macro_0 :Line_Macro_0
18300004 # LOAD32 R3 R0 4 ; Load Node type 18300004 # LOAD32 R3 R0 4 ; Load Node type
@ -369,13 +275,7 @@ A0300000 # CMPSKIPI.NE R0 0 ; If node->next is NULL
18000000 # LOAD32 R0 R0 0 ; Load Next pointer 18000000 # LOAD32 R0 R0 0 ; Load Next pointer
A0330001 # CMPSKIPI.NE R3 1 ; If a macro A0330001 # CMPSKIPI.NE R3 1 ; If a macro
2D0F @setExpression # CALLI R15 @setExpression ; Apply to other nodes 2D0F @setExpression # CALLI R15 @setExpression ; Apply to other nodes
A0200000 # CMPSKIPI.E R0 0 ; If Next is Null 2CA0 @Line_Macro_0 # JUMP.NZ R0 @Line_Macro_0 ; If Next is Null Don't loop
3C00 @Line_Macro_0 # JUMP @Line_Macro_0 ; Don't loop
# ;; Clean up
0902803F # POPR R3 R15
0902802F # POPR R2 R15
0902801F # POPR R1 R15
0902800F # POPR R0 R15
0D01001F # RET R15 0D01001F # RET R15
@ -388,29 +288,25 @@ A0200000 # CMPSKIPI.E R0 0 ; If Next is Null
:setExpression :setExpression
# ;; Preserve registers # ;; Preserve registers
0902000F # PUSHR R0 R15 0902000F # PUSHR R0 R15
0902003F # PUSHR R3 R15
0902004F # PUSHR R4 R15
0902005F # PUSHR R5 R15
# ;; Initialize # ;; Initialize
09000541 # MOVE R4 R1 ; Put Macro Text in a safe place 09000440 # COPY R4 R0 ; Use R4 for Node pointer
09000450 # COPY R5 R0 ; Use R5 for Node pointer
:setExpression_0 :setExpression_0
18350004 # LOAD32 R3 R5 4 ; Load type into R3 18340004 # LOAD32 R3 R4 4 ; Load type into R3
A0330001 # CMPSKIPI.NE R3 1 ; Check if Macro A0330001 # CMPSKIPI.NE R3 1 ; Check if Macro
3C00 @setExpression_1 # JUMP @setExpression_1 ; Move to next if Macro 3C00 @setExpression_1 # JUMP @setExpression_1 ; Move to next if Macro
18050008 # LOAD32 R0 R5 8 ; Load Text pointer into R0 for Comparision 18040008 # LOAD32 R0 R4 8 ; Load Text pointer into R0 for Comparision
09000414 # COPY R1 R4 ; Put Macro Text for comparision
2D0F @strcmp # CALLI R15 @strcmp ; compare Text and Macro Text 2D0F @strcmp # CALLI R15 @strcmp ; compare Text and Macro Text
2C60 @setExpression_1 # JUMP.NE R0 @setExpression_1 ; Move to next if not Match 2C60 @setExpression_1 # JUMP.NE R0 @setExpression_1 ; Move to next if not Match
2325000c # STORE32 R2 R5 12 ; Set node->Expression = Exp 2324000c # STORE32 R2 R4 12 ; Set node->Expression = Exp
:setExpression_1 :setExpression_1
18550000 # LOAD32 R5 R5 0 ; Load Next 18440000 # LOAD32 R4 R4 0 ; Load Next
2CA5 @setExpression_0 # JUMP.NZ R5 @setExpression_0 ; Loop if next isn't NULL 2CA4 @setExpression_0 # JUMP.NZ R4 @setExpression_0 ; Loop if next isn't NULL
:setExpression_Done :setExpression_Done
# ;; Restore registers # ;; Restore registers
0902805F # POPR R5 R15
0902804F # POPR R4 R15
0902803F # POPR R3 R15
0902800F # POPR R0 R15 0902800F # POPR R0 R15
0D01001F # RET R15 0D01001F # RET R15
@ -420,36 +316,35 @@ A0330001 # CMPSKIPI.NE R3 1 ; Check if Macro
# ;; Doesn't modify registers # ;; Doesn't modify registers
# ;; Returns back to whatever called it # ;; Returns back to whatever called it
:Process_String :Process_String
# ;; Preserve Registers # ;; Initialize
0902000F # PUSHR R0 R15 0900040D # COPY R0 R13 ; Start with Head
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
:Process_String_0 :Process_String_0
# ;; Get node type # ;; Get node type
18100004 # LOAD32 R1 R0 4 ; Load Type 18100004 # LOAD32 R1 R0 4 ; Load Type
A0210002 # CMPSKIPI.E R1 2 ; If not a string A0210002 # CMPSKIPI.E R1 2 ; If not a string
3C00 @Process_String_Done # JUMP @Process_String_Done ; Just go to next 3C00 @Process_String_Done # JUMP @Process_String_Done ; Just go to next
# ;; Its a string # ;; Its a string
18100008 # LOAD32 R1 R0 8 ; Get Text pointer 18100008 # LOAD32 R1 R0 8 ; Get Text pointer
14210000 # LOAD8 R2 R1 0 ; Get first char of Text 14210000 # LOAD8 R2 R1 0 ; Get first char of Text
# ;; Deal with ' # ;; Deal with '
A0220027 # CMPSKIPI.E R2 39 ; If char is not ' A0220027 # CMPSKIPI.E R2 39 ; If char is not '
3C00 @Process_String_1 # JUMP @Process_String_1 ; Move to next label 3C00 @Process_String_1 # JUMP @Process_String_1 ; Move to next label
# ;; Simply use Hex strings as is # ;; Simply use Hex strings as is
0F110001 # ADDUI R1 R1 1 ; Move Text pointer by 1 0F110001 # ADDUI R1 R1 1 ; Move Text pointer by 1
2310000c # STORE32 R1 R0 12 ; Set expression to Text + 1 2310000c # STORE32 R1 R0 12 ; Set expression to Text + 1
3C00 @Process_String_Done # JUMP @Process_String_Done ; And move on 3C00 @Process_String_Done # JUMP @Process_String_Done ; And move on
:Process_String_1 :Process_String_1
# ;; Deal with "" # ;; Deal with \"
2D0F @Hexify_String # CALLI R15 @Hexify_String 2D0F @Hexify_String # CALLI R15 @Hexify_String
:Process_String_Done :Process_String_Done
18000000 # LOAD32 R0 R0 0 ; Load Next 18000000 # LOAD32 R0 R0 0 ; Load Next
A0200000 # CMPSKIPI.E R0 0 ; If Next isn't NULL 2CA0 @Process_String_0 # JUMP.NZ R0 @Process_String_0 ; If Next isn't NULL Recurse down list
3C00 @Process_String_0 # JUMP @Process_String_0 ; Recurse down list
# ;; Restore registers
0902802F # POPR R2 R15
0902801F # POPR R1 R15
0902800F # POPR R0 R15
0D01001F # RET R15 0D01001F # RET R15
@ -462,43 +357,31 @@ A0200000 # CMPSKIPI.E R0 0 ; If Next isn't NULL
:Hexify_String :Hexify_String
# ;; Preserve Registers # ;; Preserve Registers
0902000F # PUSHR R0 R15 0902000F # PUSHR R0 R15
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
0902003F # PUSHR R3 R15
0902004F # PUSHR R4 R15
# ;; Initialize # ;; Initialize
09000520 # MOVE R2 R0 ; Move R0 out of the way 09000510 # MOVE R1 R0 ; Move R0 out of the way
2D0F @malloc # CALLI R15 @malloc ; Get address of new Node 23E1000c # STORE32 R14 R1 12 ; Set node expression pointer
09000510 # MOVE R1 R0 ; Prep For Hex32 18110008 # LOAD32 R1 R1 8 ; Load Text pointer into R2
2312000c # STORE32 R1 R2 12 ; Set node expression pointer 0F110001 # ADDUI R1 R1 1 ; SKip leading \"
18220008 # LOAD32 R2 R2 8 ; Load Text pointer into R2
0F220001 # ADDUI R2 R2 1 ; SKip leading ""
0D000024 # FALSE R4 ; Set counter for malloc to Zero
# ;; Main Loop # ;; Main Loop
:Hexify_String_0 :Hexify_String_0
18020000 # LOAD32 R0 R2 0 ; Load 4 bytes into R0 from Text 18010000 # LOAD32 R0 R1 0 ; Load 4 bytes into R0 from Text
B03000ff # ANDI R3 R0 0xFF ; Preserve byte to check for NULL B02000ff # ANDI R2 R0 0xFF ; Preserve byte to check for NULL
2D0F @hex32 # CALLI R15 @hex32 ; Convert to hex and store in Expression 2D0F @hex32 # CALLI R15 @hex32 ; Convert to hex and store in Expression
0F220004 # ADDUI R2 R2 4 ; Pointer Text pointer to next 4 bytes 0F110004 # ADDUI R1 R1 4 ; Pointer Text pointer to next 4 bytes
0F440008 # ADDUI R4 R4 8 ; Increment storage space required 2CA2 @Hexify_String_0 # JUMP.NZ R2 @Hexify_String_0
A0230000 # CMPSKIPI.E R3 0 ; If byte was NULL
3C00 @Hexify_String_0 # JUMP @Hexify_String_0
# ;; Done # ;; Done
0F040001 # ADDUI R0 R4 1 ; Lead space for NULL terminator 0FEE0001 # ADDUI R14 R14 1 ; Correct malloc value
2D0F @malloc # CALLI R15 @malloc ; Correct malloc value
# ;; Restore Registers
0902804F # POPR R4 R15
0902803F # POPR R3 R15
0902802F # POPR R2 R15
0902801F # POPR R1 R15
0902800F # POPR R0 R15 0902800F # POPR R0 R15
0D01001F # RET R15 0D01001F # RET R15
# ;; hex32 functionality # ;; hex32 functionality
# ;; Accepts 32bit value in R0 # ;; Accepts 32bit value in R0
# ;; Require R1 to be a pointer to place to store hex16 # ;; Require R14 to be the heap pointer
# ;; WILL ALTER R1 ! # ;; WILL ALTER R14 !
# ;; Returns to whatever called it # ;; Returns to whatever called it
:hex32 :hex32
0902000F # PUSHR R0 R15 0902000F # PUSHR R0 R15
@ -516,12 +399,12 @@ A0230000 # CMPSKIPI.E R3 0 ; If byte was NULL
2D0F @hex4 # CALLI R15 @hex4 2D0F @hex4 # CALLI R15 @hex4
0902800F # POPR R0 R15 0902800F # POPR R0 R15
:hex4 :hex4
B000000f # ANDI R0 R0 0x000F ; isolate nybble B000000f # ANDI R0 R0 0xF ; isolate nybble
0F000030 # ADDUI R0 R0 48 ; convert to ascii 0F000030 # ADDUI R0 R0 48 ; convert to ascii
A0400039 # CMPSKIPI.LE R0 57 ; If nybble was greater than '9' A0400039 # CMPSKIPI.LE R0 57 ; If nybble was greater than '9'
0F000007 # ADDUI R0 R0 7 ; Shift it into 'A' range of ascii 0F000007 # ADDUI R0 R0 7 ; Shift it into 'A' range of ascii
21010000 # STORE8 R0 R1 0 ; Store Hex Char 210E0000 # STORE8 R0 R14 0 ; Store Hex Char
0F110001 # ADDUI R1 R1 1 ; Increment address pointer 0FEE0001 # ADDUI R14 R14 1 ; Increment address pointer
0D01001F # RET R15 ; Get next nybble or return if done 0D01001F # RET R15 ; Get next nybble or return if done
@ -530,52 +413,29 @@ A0400039 # CMPSKIPI.LE R0 57 ; If nybble was greater than '9'
# ;; Converts number into Hex # ;; Converts number into Hex
# ;; And write into Memory and fix pointer # ;; And write into Memory and fix pointer
:Eval_Immediates :Eval_Immediates
# ;; Preserve Registers
0902000F # PUSHR R0 R15
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
0902003F # PUSHR R3 R15
0902004F # PUSHR R4 R15
0902005F # PUSHR R5 R15
0902006F # PUSHR R6 R15
# ;; Initialize # ;; Initialize
0900040D # COPY R0 R13 ; Start with Head 0900043D # COPY R3 R13 ; Start with Head
0D000025 # FALSE R5 ; Zero for checking return of numerate_string
# ;; Process Text # ;; Process Text
:Eval_Immediates_0 :Eval_Immediates_0
09000460 # COPY R6 R0 ; Safely preserve pointer to node 18230000 # LOAD32 R2 R3 0 ; Load Node->Next
18400000 # LOAD32 R4 R0 0 ; Load Node->Next 1803000c # LOAD32 R0 R3 12 ; Load Expression pointer
18300004 # LOAD32 R3 R0 4 ; Load Node type 2CA0 @Eval_Immediates_1 # JUMP.NZ R0 @Eval_Immediates_1 ; Don't do anything if Expression is set
1820000c # LOAD32 R2 R0 12 ; Load Expression pointer 18030004 # LOAD32 R0 R3 4 ; Load Node type
18100008 # LOAD32 R1 R0 8 ; Load Text pointer 2CA0 @Eval_Immediates_1 # JUMP.NZ R0 @Eval_Immediates_1 ; Don't do anything if Typed
2CA2 @Eval_Immediates_1 # JUMP.NZ R2 @Eval_Immediates_1 ; Don't do anything if Expression is set 18030008 # LOAD32 R0 R3 8 ; Load Text pointer
2CA3 @Eval_Immediates_1 # JUMP.NZ R3 @Eval_Immediates_1 ; Don't do anything if Typed 14100000 # LOAD8 R1 R0 0 ; Get first char of Text
09000401 # COPY R0 R1 ; Put Text pointer into R0
2D0F @numerate_string # CALLI R15 @numerate_string ; Convert to number in R0 2D0F @numerate_string # CALLI R15 @numerate_string ; Convert to number in R0
14110000 # LOAD8 R1 R1 0 ; Get first char of Text
A0210030 # CMPSKIPI.E R1 48 ; Skip next comparision if '0' A0210030 # CMPSKIPI.E R1 48 ; Skip next comparision if '0'
C205 @Eval_Immediates_1 # CMPJUMPI.E R0 R5 @Eval_Immediates_1 ; Don't do anything if string isn't a number 2C90 @Eval_Immediates_1 # JUMP.Z R0 @Eval_Immediates_1 ; Don't do anything if string isn't a number
09000510 # MOVE R1 R0 ; Preserve number 20E3000c # STORE R14 R3 12 ; Preserve pointer to expression
2D200005 # LOADUI R0 5 ; Allocate enough space for 4 hex and a null
2D0F @malloc # CALLI R15 @malloc ; Obtain the pointer the newly allocated Expression
2006000c # STORE R0 R6 12 ; Preserve pointer to expression
09000301 # SWAP R0 R1 ; Fix order for call to hex16
2D0F @hex16 # CALLI R15 @hex16 ; Shove our number into expression 2D0F @hex16 # CALLI R15 @hex16 ; Shove our number into expression
0FEE0001 # ADDUI R14 R14 1 ; Allocate enough space for a null
# ;; Handle looping # ;; Handle looping
:Eval_Immediates_1 :Eval_Immediates_1
C245 @Eval_Immediates_2 # CMPJUMPI.E R4 R5 @Eval_Immediates_2 ; If null be done 09000532 # MOVE R3 R2 ; Prepare for next loop
09000504 # MOVE R0 R4 ; Prepare for next loop 2CA3 @Eval_Immediates_0 # JUMP.NZ R3 @Eval_Immediates_0 ; And loop
3C00 @Eval_Immediates_0 # JUMP @Eval_Immediates_0 ; And loop
# ;; Clean up
:Eval_Immediates_2
# ;; Restore Registers
0902806F # POPR R6 R15
0902805F # POPR R5 R15
0902804F # POPR R4 R15
0902803F # POPR R3 R15
0902802F # POPR R2 R15
0902801F # POPR R1 R15
0902800F # POPR R0 R15
0D01001F # RET R15 0D01001F # RET R15
@ -589,6 +449,7 @@ C245 @Eval_Immediates_2 # CMPJUMPI.E R4 R5 @Eval_Immediates_2 ; If null be done
0902002F # PUSHR R2 R15 0902002F # PUSHR R2 R15
0902003F # PUSHR R3 R15 0902003F # PUSHR R3 R15
0902004F # PUSHR R4 R15 0902004F # PUSHR R4 R15
# ;; Initialize # ;; Initialize
09000510 # MOVE R1 R0 ; Get Text pointer out of the way 09000510 # MOVE R1 R0 ; Get Text pointer out of the way
0D000022 # FALSE R2 ; Set Negative flag to false 0D000022 # FALSE R2 ; Set Negative flag to false
@ -596,6 +457,7 @@ C245 @Eval_Immediates_2 # CMPJUMPI.E R4 R5 @Eval_Immediates_2 ; If null be done
14010001 # LOAD8 R0 R1 1 ; Get second byte 14010001 # LOAD8 R0 R1 1 ; Get second byte
A0300078 # CMPSKIPI.NE R0 120 ; If the second byte is x A0300078 # CMPSKIPI.NE R0 120 ; If the second byte is x
3C00 @numerate_string_hex # JUMP @numerate_string_hex ; treat string like hex 3C00 @numerate_string_hex # JUMP @numerate_string_hex ; treat string like hex
# ;; Deal with Decimal input # ;; Deal with Decimal input
2D24000a # LOADUI R4 10 ; Multiply by 10 2D24000a # LOADUI R4 10 ; Multiply by 10
14010000 # LOAD8 R0 R1 0 ; Get a byte 14010000 # LOAD8 R0 R1 0 ; Get a byte
@ -603,6 +465,7 @@ A030002d # CMPSKIPI.NE R0 45 ; If - toggle flag
0D000032 # TRUE R2 ; So that we know to negate 0D000032 # TRUE R2 ; So that we know to negate
A0220000 # CMPSKIPI.E R2 0 ; If toggled A0220000 # CMPSKIPI.E R2 0 ; If toggled
0F110001 # ADDUI R1 R1 1 ; Move to next 0F110001 # ADDUI R1 R1 1 ; Move to next
:numerate_string_dec :numerate_string_dec
14010000 # LOAD8 R0 R1 0 ; Get a byte 14010000 # LOAD8 R0 R1 0 ; Get a byte
A0300000 # CMPSKIPI.NE R0 0 ; If NULL A0300000 # CMPSKIPI.NE R0 0 ; If NULL
@ -616,16 +479,17 @@ A050000a # CMPSKIPI.L R0 10 ; If more than a number
05001330 # ADDU R3 R3 R0 ; Don't add to the count 05001330 # ADDU R3 R3 R0 ; Don't add to the count
0F110001 # ADDUI R1 R1 1 ; Move onto next byte 0F110001 # ADDUI R1 R1 1 ; Move onto next byte
3C00 @numerate_string_dec # JUMP @numerate_string_dec 3C00 @numerate_string_dec # JUMP @numerate_string_dec
# ;; Deal with Hex input # ;; Deal with Hex input
:numerate_string_hex :numerate_string_hex
14010000 # LOAD8 R0 R1 0 ; Get a byte 14010000 # LOAD8 R0 R1 0 ; Get a byte
A0200030 # CMPSKIPI.E R0 48 ; All hex strings start with 0x A0200030 # CMPSKIPI.E R0 48 ; All hex strings start with 0x
3C00 @numerate_string_done # JUMP @numerate_string_done ; Be done if not a match 3C00 @numerate_string_done # JUMP @numerate_string_done ; Be done if not a match
0F110002 # ADDUI R1 R1 2 ; Move to after leading 0x 0F110002 # ADDUI R1 R1 2 ; Move to after leading 0x
:numerate_string_hex_0 :numerate_string_hex_0
14010000 # LOAD8 R0 R1 0 ; Get a byte 14010000 # LOAD8 R0 R1 0 ; Get a byte
A0300000 # CMPSKIPI.NE R0 0 ; If NULL 2C90 @numerate_string_done # JUMP.Z R0 @numerate_string_done ; If NULL Be done
3C00 @numerate_string_done # JUMP @numerate_string_done ; Be done
2D530004 # SL0I R3 4 ; Shift counter by 16 2D530004 # SL0I R3 4 ; Shift counter by 16
10000030 # SUBI R0 R0 48 ; Convert ascii number to number 10000030 # SUBI R0 R0 48 ; Convert ascii number to number
A050000a # CMPSKIPI.L R0 10 ; If A-F A050000a # CMPSKIPI.L R0 10 ; If A-F
@ -635,11 +499,13 @@ A0500010 # CMPSKIPI.L R0 16 ; If a-f
05001330 # ADDU R3 R3 R0 ; Add to the count 05001330 # ADDU R3 R3 R0 ; Add to the count
0F110001 # ADDUI R1 R1 1 ; Get next Hex 0F110001 # ADDUI R1 R1 1 ; Get next Hex
3C00 @numerate_string_hex_0 # JUMP @numerate_string_hex_0 3C00 @numerate_string_hex_0 # JUMP @numerate_string_hex_0
# ;; Clean up # ;; Clean up
:numerate_string_done :numerate_string_done
A0220000 # CMPSKIPI.E R2 0 ; If Negate flag has been set A0220000 # CMPSKIPI.E R2 0 ; If Negate flag has been set
09000033 # NEG R3 R3 ; Make the number negative 09000033 # NEG R3 R3 ; Make the number negative
09000503 # MOVE R0 R3 ; Put number in R0 09000503 # MOVE R0 R3 ; Put number in R0
# ;; Restore Registers # ;; Restore Registers
0902804F # POPR R4 R15 0902804F # POPR R4 R15
0902803F # POPR R3 R15 0902803F # POPR R3 R15
@ -652,35 +518,23 @@ A0220000 # CMPSKIPI.E R2 0 ; If Negate flag has been set
# ;; Sets Expression pointer to Text pointer value # ;; Sets Expression pointer to Text pointer value
# ;; For all unset nodes # ;; For all unset nodes
:Preserve_Other :Preserve_Other
# ;; Preserve Registers
0902000F # PUSHR R0 R15
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
0902003F # PUSHR R3 R15
0902004F # PUSHR R4 R15
# ;; Initialize # ;; Initialize
0900040D # COPY R0 R13 ; Start with HEAD 0900040D # COPY R0 R13 ; Start with HEAD
# ;; Process Node # ;; Process Node
:Preserve_Other_0 :Preserve_Other_0
18400000 # LOAD32 R4 R0 0 ; Load Node->Next 18200000 # LOAD32 R2 R0 0 ; Load Node->Next
18300004 # LOAD32 R3 R0 4 ; Load Node type 18100004 # LOAD32 R1 R0 4 ; Load Node type
1820000c # LOAD32 R2 R0 12 ; Load Expression pointer 2CA1 @Preserve_Other_1 # JUMP.NZ R1 @Preserve_Other_1 ; Don't do anything if Typed
1810000c # LOAD32 R1 R0 12 ; Load Expression pointer
2CA1 @Preserve_Other_1 # JUMP.NZ R1 @Preserve_Other_1 ; Don't do anything if Expression is set
18100008 # LOAD32 R1 R0 8 ; Load Text pointer 18100008 # LOAD32 R1 R0 8 ; Load Text pointer
2CA2 @Preserve_Other_1 # JUMP.NZ R2 @Preserve_Other_1 ; Don't do anything if Expression is set
2CA3 @Preserve_Other_1 # JUMP.NZ R3 @Preserve_Other_1 ; Don't do anything if Typed
2310000c # STORE32 R1 R0 12 ; Set Expression pointer to Text pointer 2310000c # STORE32 R1 R0 12 ; Set Expression pointer to Text pointer
# ;; Loop through nodes # ;; Loop through nodes
:Preserve_Other_1 :Preserve_Other_1
09000504 # MOVE R0 R4 ; Prepare for next loop 09000502 # MOVE R0 R2 ; Prepare for next loop
2CA0 @Preserve_Other_0 # JUMP.NZ R0 @Preserve_Other_0 2CA0 @Preserve_Other_0 # JUMP.NZ R0 @Preserve_Other_0
# ;; Clean up
:Preserve_Other_Done
# ;; Restore Registers
0902804F # POPR R4 R15
0902803F # POPR R3 R15
0902802F # POPR R2 R15
0902801F # POPR R1 R15
0902800F # POPR R0 R15
0D01001F # RET R15 0D01001F # RET R15
@ -688,34 +542,30 @@ A0220000 # CMPSKIPI.E R2 0 ; If Negate flag has been set
# ;; Print all of the expressions # ;; Print all of the expressions
# ;; Starting with HEAD # ;; Starting with HEAD
:Print_Hex :Print_Hex
# ;; Preserve Registers # ;; Prep TAPE_02
0902000F # PUSHR R0 R15 2D201101 # LOADUI R0 0x1101
0902001F # PUSHR R1 R15 42100001 # FOPEN_WRITE
0902002F # PUSHR R2 R15
0902003F # PUSHR R3 R15
0902004F # PUSHR R4 R15
# ;; Initialize # ;; Initialize
0900040D # COPY R0 R13 ; Start with HEAD 0900040D # COPY R0 R13 ; Start with HEAD
2D211101 # LOADUI R1 0x1101 ; Write to Tape_02
:Print_Hex_0 :Print_Hex_0
18200000 # LOAD32 R2 R0 0 ; Load Node->Next 18200000 # LOAD32 R2 R0 0 ; Load Node->Next
18100004 # LOAD32 R1 R0 4 ; Load Node type 18300004 # LOAD32 R3 R0 4 ; Load Node type
1800000c # LOAD32 R0 R0 12 ; Load Expression pointer 1800000c # LOAD32 R0 R0 12 ; Load Expression pointer
10110001 # SUBI R1 R1 1 ; Check for Macros 10330001 # SUBI R3 R3 1 ; Check for Macros
2C91 @Print_Hex_1 # JUMP.Z R1 @Print_Hex_1 ; Don't print Macros 2C93 @Print_Hex_1 # JUMP.Z R3 @Print_Hex_1 ; Don't print Macros
2D211101 # LOADUI R1 0x1101 ; Write to Tape_02
2D0F @Print_Line # CALLI R15 @Print_Line ; Print the Expression 2D0F @Print_Line # CALLI R15 @Print_Line ; Print the Expression
# ;; Loop down the nodes # ;; Loop down the nodes
:Print_Hex_1 :Print_Hex_1
09000502 # MOVE R0 R2 ; Prepare for next loop 09000502 # MOVE R0 R2 ; Prepare for next loop
2CA0 @Print_Hex_0 # JUMP.NZ R0 @Print_Hex_0 ; Keep looping if not NULL 2CA0 @Print_Hex_0 # JUMP.NZ R0 @Print_Hex_0 ; Keep looping if not NULL
# ;; Clean up
:Print_Hex_Done # ;; Done writing File
# ;; Restore Registers 2D201101 # LOADUI R0 0x1101 ; Close TAPE_01
0902804F # POPR R4 R15 42100002 # FCLOSE
0902803F # POPR R3 R15
0902802F # POPR R2 R15
0902801F # POPR R1 R15
0902800F # POPR R0 R15
0D01001F # RET R15 0D01001F # RET R15
@ -725,32 +575,21 @@ A0220000 # CMPSKIPI.E R2 0 ; If Negate flag has been set
# ;; Writes all Chars in string # ;; Writes all Chars in string
# ;; Then writes a New line character to interface # ;; Then writes a New line character to interface
:Print_Line :Print_Line
# ;; Preserve Registers
0902000F # PUSHR R0 R15
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
0902003F # PUSHR R3 R15
0902004F # PUSHR R4 R15
# ;; Initialize # ;; Initialize
09000530 # MOVE R3 R0 ; Get Pointer safely out of the way 09000530 # MOVE R3 R0 ; Get Pointer safely out of the way
0D000024 # FALSE R4 ; Start index at 0
:Print_Line_0 :Print_Line_0
0503A034 # LOADXU8 R0 R3 R4 ; Get our first byte 15030000 # LOADU8 R0 R3 0 ; Get our first byte
A0300000 # CMPSKIPI.NE R0 0 ; If the loaded byte is NULL A0300000 # CMPSKIPI.NE R0 0 ; If the loaded byte is NULL
3C00 @Print_Line_Done # JUMP @Print_Line_Done ; Be done 3C00 @Print_Line_Done # JUMP @Print_Line_Done ; Be done
42100200 # FPUTC ; Otherwise print 42100200 # FPUTC ; Otherwise print
0F440001 # ADDUI R4 R4 1 ; Increment for next loop 0F330001 # ADDUI R3 R3 1 ; Increment for next loop
3C00 @Print_Line_0 # JUMP @Print_Line_0 ; And Loop 3C00 @Print_Line_0 # JUMP @Print_Line_0 ; And Loop
# ;; Clean up # ;; Clean up
:Print_Line_Done :Print_Line_Done
2D20000a # LOADUI R0 10 ; Put in Newline char 2D20000a # LOADUI R0 10 ; Put in Newline char
42100200 # FPUTC ; Write it out 42100200 # FPUTC ; Write it out
# ;; Restore Registers
0902804F # POPR R4 R15
0902803F # POPR R3 R15
0902802F # POPR R2 R15
0902801F # POPR R1 R15
0902800F # POPR R0 R15
0D01001F # RET R15 0D01001F # RET R15
# ;; Where we are putting the start of our stack # ;; Where we are putting the start of our stack

View File

@ -16,7 +16,7 @@
:start :start
;; We will be using R13 for storage of Head ;; We will be using R13 for storage of Head
;; We will be using R14 for our condition codes LOADUI R14 0x4000 ; Our malloc pointer (Initialized)
LOADUI R15 $stack ; Put stack at end of program LOADUI R15 $stack ; Put stack at end of program
;; Main program ;; Main program
@ -24,81 +24,28 @@
;; Writes results to Tape_02 ;; Writes results to Tape_02
;; Accepts no arguments and HALTS when done ;; Accepts no arguments and HALTS when done
:main :main
CALLI R15 @Tokenize_Line ; Call Tokenize_Line
CALLI R15 @reverse_list ; Reverse the list of tokens
CALLI R15 @Identify_Macros ; Tag all nodes that are macros
CALLI R15 @Line_Macro ; Apply macros down nodes
CALLI R15 @Process_String ; Convert string values to Hex16
CALLI R15 @Eval_Immediates ; Convert numbers to hex
CALLI R15 @Preserve_Other ; Ensure labels/Pointers aren't lost
CALLI R15 @Print_Hex ; Write Nodes to Tape_02
HALT ; We are Done
;; Tokenize_Line function
;; Opens tape_01 and reads into a backwards linked list in R13
;; Returns to whatever called it
:Tokenize_Line
;; Prep TAPE_01 ;; Prep TAPE_01
LOADUI R0 0x1100 LOADUI R0 0x1100
FOPEN_READ FOPEN_READ
FALSE R13 ; Head is NULL FALSE R13 ; Head is NULL
MOVE R1 R0 ; Read Tape_01 MOVE R1 R0 ; Read Tape_01
FALSE R14 ; We haven't yet reached EOF
:main_0
CALLI R15 @Tokenize_Line ; Call Tokenize_Line
JUMP.Z R14 @main_0 ; Until we reach EOF
;; Done reading File
LOADUI R0 0x1100 ; Close TAPE_01
FCLOSE
COPY R0 R13 ; Prepare for function
CALLI R15 @Identify_Macros ; Tag all nodes that are macros
CALLI R15 @Line_Macro ; Apply macros down nodes
CALLI R15 @Process_String ; Convert string values to Hex16
CALLI R15 @Eval_Immediates ; Convert numbers to hex
CALLI R15 @Preserve_Other ; Ensure labels/Pointers aren't lost
;; Prep TAPE_02
LOADUI R0 0x1101
FOPEN_WRITE
CALLI R15 @Print_Hex ; Write Nodes to Tape_02
;; Done writing File
LOADUI R0 0x1101 ; Close TAPE_01
FCLOSE
HALT ; We are Done
;; Primative malloc function
;; Recieves number of bytes to allocate in R0
;; Returns pointer to block of that size in R0
;; Returns to whatever called it
:malloc
;; Preserve registers
PUSHR R1 R15
;; Get current malloc pointer
LOADR R1 @malloc_pointer
;; Deal with special case
CMPSKIPI.NE R1 0 ; If Zero set to our start of heap space
LOADUI R1 0x4000
;; update malloc pointer
SWAP R0 R1
ADD R1 R0 R1
STORER R1 @malloc_pointer
;; Done
;; Restore registers
POPR R1 R15
RET R15
;; Our static value for malloc pointer
:malloc_pointer
NOP
;; Tokenize_Line function
;; Recieves pointer to Head in R0 and desired input in R1
;; Alters R14 when EOF Reached
;; Returns to whatever called it
:Tokenize_Line
;; Preserve registers
PUSHR R0 R15
PUSHR R1 R15
PUSHR R2 R15
PUSHR R3 R15
PUSHR R4 R15
;; Initialize
COPY R4 R13 ; Get Head pointer out of the way
:Tokenize_Line_0 :Tokenize_Line_0
FGETC ; Get a Char FGETC ; Get a Char
@ -122,19 +69,14 @@
CMPSKIPI.NE R0 32 CMPSKIPI.NE R0 32
JUMP @Tokenize_Line_0 ; Throw away byte and try again JUMP @Tokenize_Line_0 ; Throw away byte and try again
;; Flag if reached EOF
CMPSKIPI.GE R0 0
TRUE R14
;; Stop if EOF ;; Stop if EOF
CMPSKIPI.GE R0 0 CMPSKIPI.GE R0 0
JUMP @Tokenize_Line_Done JUMP @Tokenize_Line_Done
;; Allocate a new Node ;; Allocate a new Node
MOVE R2 R0 ; Get Char out the way COPY R2 R14 ; Get address of new Node
LOADUI R0 16 ; Allocate 16 Bytes ADDUI R14 R14 16 ; Allocate 16 Bytes
CALLI R15 @malloc ; Get address of new Node STORE32 R14 R2 8 ; Set Text pointer
SWAP R2 R0 ; Store Pointer in R2
;; Deal with Strings wrapped in " ;; Deal with Strings wrapped in "
CMPSKIPI.NE R0 34 CMPSKIPI.NE R0 34
@ -146,20 +88,35 @@
;; Everything else is an atom store it ;; Everything else is an atom store it
CALLI R15 @Store_Atom CALLI R15 @Store_Atom
:Tokenize_Line_1
STORE32 R13 R2 0 ; Set p->next to head
MOVE R13 R2 ; Set head to p
JUMP @Tokenize_Line_0 ; Keep getting tokens
:Tokenize_Line_Done :Tokenize_Line_Done
MOVE R1 R2 ; Put Node pointer we are working on into R1 ;; Done reading File
COPY R0 R13 ; Get current HEAD LOADUI R0 0x1100 ; Close TAPE_01
CALLI R15 @Add_Token ; Append new token to Head FCLOSE
RET R15
;; Restore registers
POPR R4 R15
POPR R3 R15
POPR R2 R15
POPR R1 R15
POPR R0 R15
;; Return since we are done ;; reverse_list Function
;; Reverses the list given in R13
:reverse_list
;; Initialize
COPY R0 R13 ; Using R0 as head
FALSE R1 ; Using R1 as root
; Using R2 as next
:reverse_list_0
JUMP.Z R0 @reverse_list_done ; Stop if NULL == head
LOAD R2 R0 0 ; next = head->next
STORE R1 R0 0 ; head->next = root
MOVE R1 R0 ; root = head
MOVE R0 R2 ; head = next
JUMP @reverse_list_0 ; Keep looping
:reverse_list_done
;; Clean up
MOVE R13 R1 ; Set token_list to root
RET R15 RET R15
@ -181,37 +138,20 @@
;; Modifies node Text to point to string and sets ;; Modifies node Text to point to string and sets
;; Type to string. ;; Type to string.
:Store_String :Store_String
;; Preserve registers
PUSHR R4 R15
PUSHR R5 R15
PUSHR R6 R15
;; Initialize ;; Initialize
MOVE R6 R0 ; Get R0 out of the way COPY R3 R0 ; Copy Char for comparison
CALLI R15 @malloc ; Get where space is free
MOVE R4 R0 ; Put pointer someplace safe
FALSE R5 ; Start at index 0
COPY R0 R6 ; Copy Char back into R0
;; Primary Loop
:Store_String_0 :Store_String_0
STOREX8 R0 R4 R5 ; Store the Byte STORE8 R0 R14 0 ; Store the Byte
FGETC ; Get next Byte FGETC ; Get next Byte
ADDUI R5 R5 1 ; Prep for next loop ADDUI R14 R14 1 ; Prep for next loop
CMPJUMPI.NE R0 R6 @Store_String_0 ; Loop if matching not found CMPJUMPI.NE R0 R3 @Store_String_0 ; Loop if matching not found
;; Clean up ;; Clean up
STORE32 R4 R2 8 ; Set Text pointer ADDUI R14 R14 4 ; Correct Malloc
ADDUI R0 R5 4 ; Correct Malloc
CALLI R15 @malloc ; To the amount of space used
LOADUI R0 2 ; Using type string LOADUI R0 2 ; Using type string
STORE32 R0 R2 4 ; Set node type STORE32 R0 R2 4 ; Set node type
JUMP @Tokenize_Line_1
;; Restore Registers
POPR R6 R15
POPR R5 R15
POPR R4 R15
JUMP @Tokenize_Line_Done
;; Store_Atom function ;; Store_Atom function
@ -219,21 +159,9 @@
;; And node pointer in R2 ;; And node pointer in R2
;; Modifies node Text to point to string ;; Modifies node Text to point to string
:Store_Atom :Store_Atom
;; Preserve registers STORE8 R0 R14 0 ; Store the Byte
PUSHR R4 R15
PUSHR R5 R15
;; Initialize
MOVE R5 R0 ; Get R0 out of the way
CALLI R15 @malloc ; Get where space is free
MOVE R4 R0 ; Put pointer someplace safe
MOVE R0 R5 ; Copy Char back and Set index to 0
;; Primary Loop
:Store_Atom_0
STOREX8 R0 R4 R5 ; Store the Byte
FGETC ; Get next Byte FGETC ; Get next Byte
ADDUI R5 R5 1 ; Prep for next loop ADDUI R14 R14 1 ; Prep for next loop
CMPSKIPI.NE R0 9 ; If char is Tab CMPSKIPI.NE R0 9 ; If char is Tab
JUMP @Store_Atom_Done ; Be done JUMP @Store_Atom_Done ; Be done
@ -245,60 +173,11 @@
JUMP @Store_Atom_Done ; Be done JUMP @Store_Atom_Done ; Be done
;; Otherwise loop ;; Otherwise loop
JUMP @Store_Atom_0 JUMP @Store_Atom
:Store_Atom_Done :Store_Atom_Done
;; Cleanup ;; Cleanup
STORE32 R4 R2 8 ; Set Text pointer ADDUI R14 R14 1 ; Correct Malloc
ADDUI R0 R5 1 ; Correct Malloc
CALLI R15 @malloc ; To the amount of space used
;; Restore Registers
POPR R5 R15
POPR R4 R15
RET R15
;; Add_Token Function
;; Recieves pointers in R0 R1
;; Alters R13 if R) is NULL
;; Appends nodes together
;; Returns to whatever called it
:Add_Token
;; Preserve Registers
PUSHR R2 R15
PUSHR R1 R15
PUSHR R0 R15
;; Handle if Head is NULL
JUMP.NZ R0 @Add_Token_0
COPY R13 R1 ; Fix head
POPR R0 R15 ; Clean up register
PUSHR R1 R15 ; And act like we passed the reverse
JUMP @Add_Token_2
:Add_Token_0
;; Handle if Head->next is NULL
LOAD32 R2 R0 0
JUMP.NZ R2 @Add_Token_1
;; Set head->next = p
STORE32 R1 R0 0
JUMP @Add_Token_2
:Add_Token_1
;; Handle case of Head->next not being NULL
LOAD32 R0 R0 0 ; Move to next node
LOAD32 R2 R0 0 ; Get node->next
CMPSKIPI.E R2 0 ; If it is not null
JUMP @Add_Token_1 ; Move to the next node and try again
JUMP @Add_Token_0 ; Else simply act as if we got this node
; in the first place
:Add_Token_2
;; Restore registers
POPR R0 R15
POPR R1 R15
POPR R2 R15
RET R15 RET R15
@ -309,87 +188,71 @@
;; 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
;; Setup registers ;; Setup registers
MOVE R2 R0 ; Put R0 in a safe place MOVE R2 R0 ; Put R0 in a safe place
MOVE R3 R1 ; Put R1 in a safe place MOVE R3 R1 ; Put R1 in a safe place
LOADUI R4 0 ; Starting at index 0 FALSE R4 ; Starting at index 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 R0 R0 R1 ; Compare the bytes
CMPSKIPI.E R0 0 ; Stop if byte is NULL CMPSKIPI.E R1 0 ; Stop if byte is NULL
JUMP.E R1 @cmpbyte ; Loop if bytes are equal JUMP.E R0 @cmpbyte ; Loop if bytes are equal
;; Done ;; Done
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
;; Identify_Macros Function ;; Identify_Macros Function
;; Recieves a pointer to a node in R0
;; If the text stored in its Text segment matches ;; If the text stored in its Text segment matches
;; DEFINE, flag it and Collapse it down to a single Node ;; DEFINE, flag it and Collapse it down to a single Node
;; Loop until all nodes are checked ;; Loop until all nodes are checked
;; Return to whatever called it ;; Return to whatever called it
:Identify_Macros :Identify_Macros
;; Preserve Registers ;; Initializ
PUSHR R0 R15 LOADUI R1 $Identify_Macros_string
PUSHR R1 R15 COPY R2 R13 ; i = head
PUSHR R2 R15
PUSHR R3 R15
;; Main Loop ;; Main Loop
:Identify_Macros_0 :Identify_Macros_0
MOVE R2 R0 LOAD32 R0 R2 8 ; Get Pointer to Text
LOAD32 R1 R2 8 ; Get Pointer to Text
LOADUI R0 $Identify_Macros_string
CALLI R15 @strcmp CALLI R15 @strcmp
MOVE R1 R2
JUMP.NE R0 @Identify_Macros_1 JUMP.NE R0 @Identify_Macros_1
;; It is a definition ;; It is a definition
;; Set p->Type = macro ;; Set i->Type = macro
LOADUI R0 1 ; The Enum value for macro LOADUI R0 1 ; The Enum value for macro
STORE32 R0 R1 4 ; Set node type STORE32 R0 R2 4 ; Set node type
;; Set p->Text = p->Next->Text ;; Set i->Text = i->Next->Text
LOAD32 R2 R1 0 ; Get Next LOAD32 R4 R2 0 ; Get Next
LOAD32 R0 R2 8 ; Get Next->Text LOAD32 R0 R4 8 ; Get Next->Text
STORE32 R0 R1 8 ; Set Text = Next->Text STORE32 R0 R2 8 ; Set i->Text = Next->Text
;; Set p->Expression = p->next->next->Text ;; Set i->Expression = i->next->next->Text
LOAD32 R2 R2 0 ; Get Next->Next LOAD32 R4 R4 0 ; Get Next->Next
LOAD32 R0 R2 8 ; Get Next->Next->Text LOAD32 R0 R4 8 ; Get Next->Next->Text
LOAD32 R3 R2 4 ; Get Next->Next->type LOAD32 R3 R4 4 ; Get Next->Next->type
CMPSKIPI.NE R3 2 ; If node is a string CMPSKIPI.NE R3 2 ; If node is a string
ADDUI R0 R0 1 ; Skip first char ADDUI R0 R0 1 ; Skip first char
STORE32 R0 R1 12 ; Set Expression = Next->Next->Text STORE32 R0 R2 12 ; Set Expression = Next->Next->Text
;; Set p->Next = p->Next->Next->Next ;; Set i->Next = i->Next->Next->Next
LOAD32 R0 R2 0 ; Get Next->Next->Next LOAD32 R4 R4 0 ; Get Next->Next->Next
STORE32 R0 R1 0 ; Set Next = Next->Next->Next STORE32 R4 R2 0 ; Set i->Next = Next->Next->Next
:Identify_Macros_1 :Identify_Macros_1
LOAD32 R0 R1 0 ; Get node->next LOAD32 R2 R2 0 ; Get node->next
CMPSKIPI.NE R0 0 ; If node->next is NULL JUMP.NZ R2 @Identify_Macros_0 ; Loop if i not NULL
JUMP @Identify_Macros_Done ; Be done
;; Otherwise keep looping
JUMP @Identify_Macros_0
:Identify_Macros_Done
;; Restore registers
POPR R3 R15
POPR R2 R15
POPR R1 R15
POPR R0 R15
RET R15 RET R15
:Identify_Macros_string :Identify_Macros_string
@ -401,11 +264,8 @@
;; Causes macros to be applied ;; Causes macros to be applied
;; Returns to whatever called it ;; Returns to whatever called it
:Line_Macro :Line_Macro
;; Preserve Registers ;; Initialize
PUSHR R0 R15 COPY R0 R13 ; Start with Head
PUSHR R1 R15
PUSHR R2 R15
PUSHR R3 R15
;; Main loop ;; Main loop
:Line_Macro_0 :Line_Macro_0
@ -415,14 +275,7 @@
LOAD32 R0 R0 0 ; Load Next pointer LOAD32 R0 R0 0 ; Load Next pointer
CMPSKIPI.NE R3 1 ; If a macro CMPSKIPI.NE R3 1 ; If a macro
CALLI R15 @setExpression ; Apply to other nodes CALLI R15 @setExpression ; Apply to other nodes
CMPSKIPI.E R0 0 ; If Next is Null JUMP.NZ R0 @Line_Macro_0 ; If Next is Null Don't loop
JUMP @Line_Macro_0 ; Don't loop
;; Clean up
POPR R3 R15
POPR R2 R15
POPR R1 R15
POPR R0 R15
RET R15 RET R15
@ -435,33 +288,25 @@
:setExpression :setExpression
;; Preserve registers ;; Preserve registers
PUSHR R0 R15 PUSHR R0 R15
PUSHR R3 R15
PUSHR R4 R15
PUSHR R5 R15
;; Initialize ;; Initialize
MOVE R4 R1 ; Put Macro Text in a safe place COPY R4 R0 ; Use R4 for Node pointer
COPY R5 R0 ; Use R5 for Node pointer
:setExpression_0 :setExpression_0
LOAD32 R3 R5 4 ; Load type into R3 LOAD32 R3 R4 4 ; Load type into R3
CMPSKIPI.NE R3 1 ; Check if Macro CMPSKIPI.NE R3 1 ; Check if Macro
JUMP @setExpression_1 ; Move to next if Macro JUMP @setExpression_1 ; Move to next if Macro
LOAD32 R0 R5 8 ; Load Text pointer into R0 for Comparision LOAD32 R0 R4 8 ; Load Text pointer into R0 for Comparision
COPY R1 R4 ; Put Macro Text for comparision
CALLI R15 @strcmp ; compare Text and Macro Text CALLI R15 @strcmp ; compare Text and Macro Text
JUMP.NE R0 @setExpression_1 ; Move to next if not Match JUMP.NE R0 @setExpression_1 ; Move to next if not Match
STORE32 R2 R5 12 ; Set node->Expression = Exp STORE32 R2 R4 12 ; Set node->Expression = Exp
:setExpression_1 :setExpression_1
LOAD32 R5 R5 0 ; Load Next LOAD32 R4 R4 0 ; Load Next
JUMP.NZ R5 @setExpression_0 ; Loop if next isn't NULL JUMP.NZ R4 @setExpression_0 ; Loop if next isn't NULL
:setExpression_Done :setExpression_Done
;; Restore registers ;; Restore registers
POPR R5 R15
POPR R4 R15
POPR R3 R15
POPR R0 R15 POPR R0 R15
RET R15 RET R15
@ -471,10 +316,8 @@
;; Doesn't modify registers ;; Doesn't modify registers
;; Returns back to whatever called it ;; Returns back to whatever called it
:Process_String :Process_String
;; Preserve Registers ;; Initialize
PUSHR R0 R15 COPY R0 R13 ; Start with Head
PUSHR R1 R15
PUSHR R2 R15
:Process_String_0 :Process_String_0
;; Get node type ;; Get node type
@ -501,13 +344,7 @@
:Process_String_Done :Process_String_Done
LOAD32 R0 R0 0 ; Load Next LOAD32 R0 R0 0 ; Load Next
CMPSKIPI.E R0 0 ; If Next isn't NULL JUMP.NZ R0 @Process_String_0 ; If Next isn't NULL Recurse down list
JUMP @Process_String_0 ; Recurse down list
;; Restore registers
POPR R2 R15
POPR R1 R15
POPR R0 R15
RET R15 RET R15
@ -520,47 +357,31 @@
:Hexify_String :Hexify_String
;; Preserve Registers ;; Preserve Registers
PUSHR R0 R15 PUSHR R0 R15
PUSHR R1 R15
PUSHR R2 R15
PUSHR R3 R15
PUSHR R4 R15
;; Initialize ;; Initialize
MOVE R2 R0 ; Move R0 out of the way MOVE R1 R0 ; Move R0 out of the way
CALLI R15 @malloc ; Get address of new Node STORE32 R14 R1 12 ; Set node expression pointer
MOVE R1 R0 ; Prep For Hex32 LOAD32 R1 R1 8 ; Load Text pointer into R2
STORE32 R1 R2 12 ; Set node expression pointer ADDUI R1 R1 1 ; SKip leading "
LOAD32 R2 R2 8 ; Load Text pointer into R2
ADDUI R2 R2 1 ; SKip leading "
FALSE R4 ; Set counter for malloc to Zero
;; Main Loop ;; Main Loop
:Hexify_String_0 :Hexify_String_0
LOAD32 R0 R2 0 ; Load 4 bytes into R0 from Text LOAD32 R0 R1 0 ; Load 4 bytes into R0 from Text
ANDI R3 R0 0xFF ; Preserve byte to check for NULL ANDI R2 R0 0xFF ; Preserve byte to check for NULL
CALLI R15 @hex32 ; Convert to hex and store in Expression CALLI R15 @hex32 ; Convert to hex and store in Expression
ADDUI R2 R2 4 ; Pointer Text pointer to next 4 bytes ADDUI R1 R1 4 ; Pointer Text pointer to next 4 bytes
ADDUI R4 R4 8 ; Increment storage space required JUMP.NZ R2 @Hexify_String_0
CMPSKIPI.E R3 0 ; If byte was NULL
JUMP @Hexify_String_0
;; Done ;; Done
ADDUI R0 R4 1 ; Lead space for NULL terminator ADDUI R14 R14 1 ; Correct malloc value
CALLI R15 @malloc ; Correct malloc value
;; Restore Registers
POPR R4 R15
POPR R3 R15
POPR R2 R15
POPR R1 R15
POPR R0 R15 POPR R0 R15
RET R15 RET R15
;; hex32 functionality ;; hex32 functionality
;; Accepts 32bit value in R0 ;; Accepts 32bit value in R0
;; Require R1 to be a pointer to place to store hex16 ;; Require R14 to be the heap pointer
;; WILL ALTER R1 ! ;; WILL ALTER R14 !
;; Returns to whatever called it ;; Returns to whatever called it
:hex32 :hex32
PUSHR R0 R15 PUSHR R0 R15
@ -578,12 +399,12 @@
CALLI R15 @hex4 CALLI R15 @hex4
POPR R0 R15 POPR R0 R15
:hex4 :hex4
ANDI R0 R0 0x000F ; isolate nybble ANDI R0 R0 0xF ; isolate nybble
ADDUI R0 R0 48 ; convert to ascii ADDUI R0 R0 48 ; convert to ascii
CMPSKIPI.LE R0 57 ; If nybble was greater than '9' CMPSKIPI.LE R0 57 ; If nybble was greater than '9'
ADDUI R0 R0 7 ; Shift it into 'A' range of ascii ADDUI R0 R0 7 ; Shift it into 'A' range of ascii
STORE8 R0 R1 0 ; Store Hex Char STORE8 R0 R14 0 ; Store Hex Char
ADDUI R1 R1 1 ; Increment address pointer ADDUI R14 R14 1 ; Increment address pointer
RET R15 ; Get next nybble or return if done RET R15 ; Get next nybble or return if done
@ -592,56 +413,29 @@
;; Converts number into Hex ;; Converts number into Hex
;; And write into Memory and fix pointer ;; And write into Memory and fix pointer
:Eval_Immediates :Eval_Immediates
;; Preserve Registers
PUSHR R0 R15
PUSHR R1 R15
PUSHR R2 R15
PUSHR R3 R15
PUSHR R4 R15
PUSHR R5 R15
PUSHR R6 R15
;; Initialize ;; Initialize
COPY R0 R13 ; Start with Head COPY R3 R13 ; Start with Head
FALSE R5 ; Zero for checking return of numerate_string
;; Process Text ;; Process Text
:Eval_Immediates_0 :Eval_Immediates_0
COPY R6 R0 ; Safely preserve pointer to node LOAD32 R2 R3 0 ; Load Node->Next
LOAD32 R4 R0 0 ; Load Node->Next LOAD32 R0 R3 12 ; Load Expression pointer
LOAD32 R3 R0 4 ; Load Node type JUMP.NZ R0 @Eval_Immediates_1 ; Don't do anything if Expression is set
LOAD32 R2 R0 12 ; Load Expression pointer LOAD32 R0 R3 4 ; Load Node type
LOAD32 R1 R0 8 ; Load Text pointer JUMP.NZ R0 @Eval_Immediates_1 ; Don't do anything if Typed
JUMP.NZ R2 @Eval_Immediates_1 ; Don't do anything if Expression is set LOAD32 R0 R3 8 ; Load Text pointer
JUMP.NZ R3 @Eval_Immediates_1 ; Don't do anything if Typed LOAD8 R1 R0 0 ; Get first char of Text
COPY R0 R1 ; Put Text pointer into R0
CALLI R15 @numerate_string ; Convert to number in R0 CALLI R15 @numerate_string ; Convert to number in R0
LOAD8 R1 R1 0 ; Get first char of Text
CMPSKIPI.E R1 48 ; Skip next comparision if '0' CMPSKIPI.E R1 48 ; Skip next comparision if '0'
CMPJUMPI.E R0 R5 @Eval_Immediates_1 ; Don't do anything if string isn't a number JUMP.Z R0 @Eval_Immediates_1 ; Don't do anything if string isn't a number
MOVE R1 R0 ; Preserve number STORE R14 R3 12 ; Preserve pointer to expression
LOADUI R0 5 ; Allocate enough space for 4 hex and a null
CALLI R15 @malloc ; Obtain the pointer the newly allocated Expression
STORE R0 R6 12 ; Preserve pointer to expression
SWAP R0 R1 ; Fix order for call to hex16
CALLI R15 @hex16 ; Shove our number into expression CALLI R15 @hex16 ; Shove our number into expression
ADDUI R14 R14 1 ; Allocate enough space for a null
;; Handle looping ;; Handle looping
:Eval_Immediates_1 :Eval_Immediates_1
CMPJUMPI.E R4 R5 @Eval_Immediates_2 ; If null be done MOVE R3 R2 ; Prepare for next loop
MOVE R0 R4 ; Prepare for next loop JUMP.NZ R3 @Eval_Immediates_0 ; And loop
JUMP @Eval_Immediates_0 ; And loop
;; Clean up
:Eval_Immediates_2
;; Restore Registers
POPR R6 R15
POPR R5 R15
POPR R4 R15
POPR R3 R15
POPR R2 R15
POPR R1 R15
POPR R0 R15
RET R15 RET R15
@ -696,8 +490,7 @@
ADDUI R1 R1 2 ; Move to after leading 0x ADDUI R1 R1 2 ; Move to after leading 0x
:numerate_string_hex_0 :numerate_string_hex_0
LOAD8 R0 R1 0 ; Get a byte LOAD8 R0 R1 0 ; Get a byte
CMPSKIPI.NE R0 0 ; If NULL JUMP.Z R0 @numerate_string_done ; If NULL Be done
JUMP @numerate_string_done ; Be done
SL0I R3 4 ; Shift counter by 16 SL0I R3 4 ; Shift counter by 16
SUBI R0 R0 48 ; Convert ascii number to number SUBI R0 R0 48 ; Convert ascii number to number
@ -728,63 +521,44 @@
;; Sets Expression pointer to Text pointer value ;; Sets Expression pointer to Text pointer value
;; For all unset nodes ;; For all unset nodes
:Preserve_Other :Preserve_Other
;; Preserve Registers
PUSHR R0 R15
PUSHR R1 R15
PUSHR R2 R15
PUSHR R3 R15
PUSHR R4 R15
;; Initialize ;; Initialize
COPY R0 R13 ; Start with HEAD COPY R0 R13 ; Start with HEAD
;; Process Node ;; Process Node
:Preserve_Other_0 :Preserve_Other_0
LOAD32 R4 R0 0 ; Load Node->Next LOAD32 R2 R0 0 ; Load Node->Next
LOAD32 R3 R0 4 ; Load Node type LOAD32 R1 R0 4 ; Load Node type
LOAD32 R2 R0 12 ; Load Expression pointer JUMP.NZ R1 @Preserve_Other_1 ; Don't do anything if Typed
LOAD32 R1 R0 12 ; Load Expression pointer
JUMP.NZ R1 @Preserve_Other_1 ; Don't do anything if Expression is set
LOAD32 R1 R0 8 ; Load Text pointer LOAD32 R1 R0 8 ; Load Text pointer
JUMP.NZ R2 @Preserve_Other_1 ; Don't do anything if Expression is set
JUMP.NZ R3 @Preserve_Other_1 ; Don't do anything if Typed
STORE32 R1 R0 12 ; Set Expression pointer to Text pointer STORE32 R1 R0 12 ; Set Expression pointer to Text pointer
;; Loop through nodes ;; Loop through nodes
:Preserve_Other_1 :Preserve_Other_1
MOVE R0 R4 ; Prepare for next loop MOVE R0 R2 ; Prepare for next loop
JUMP.NZ R0 @Preserve_Other_0 JUMP.NZ R0 @Preserve_Other_0
;; Clean up
:Preserve_Other_Done
;; Restore Registers
POPR R4 R15
POPR R3 R15
POPR R2 R15
POPR R1 R15
POPR R0 R15
RET R15 RET R15
;; Print_Hex Function ;; Print_Hex Function
;; Print all of the expressions ;; Print all of the expressions
;; Starting with HEAD ;; Starting with HEAD
:Print_Hex :Print_Hex
;; Preserve Registers ;; Prep TAPE_02
PUSHR R0 R15 LOADUI R0 0x1101
PUSHR R1 R15 FOPEN_WRITE
PUSHR R2 R15
PUSHR R3 R15
PUSHR R4 R15
;; Initialize ;; Initialize
COPY R0 R13 ; Start with HEAD COPY R0 R13 ; Start with HEAD
LOADUI R1 0x1101 ; Write to Tape_02
:Print_Hex_0 :Print_Hex_0
LOAD32 R2 R0 0 ; Load Node->Next LOAD32 R2 R0 0 ; Load Node->Next
LOAD32 R1 R0 4 ; Load Node type LOAD32 R3 R0 4 ; Load Node type
LOAD32 R0 R0 12 ; Load Expression pointer LOAD32 R0 R0 12 ; Load Expression pointer
SUBI R1 R1 1 ; Check for Macros SUBI R3 R3 1 ; Check for Macros
JUMP.Z R1 @Print_Hex_1 ; Don't print Macros JUMP.Z R3 @Print_Hex_1 ; Don't print Macros
LOADUI R1 0x1101 ; Write to Tape_02
CALLI R15 @Print_Line ; Print the Expression CALLI R15 @Print_Line ; Print the Expression
;; Loop down the nodes ;; Loop down the nodes
@ -792,14 +566,9 @@
MOVE R0 R2 ; Prepare for next loop MOVE R0 R2 ; Prepare for next loop
JUMP.NZ R0 @Print_Hex_0 ; Keep looping if not NULL JUMP.NZ R0 @Print_Hex_0 ; Keep looping if not NULL
;; Clean up ;; Done writing File
:Print_Hex_Done LOADUI R0 0x1101 ; Close TAPE_01
;; Restore Registers FCLOSE
POPR R4 R15
POPR R3 R15
POPR R2 R15
POPR R1 R15
POPR R0 R15
RET R15 RET R15
@ -809,36 +578,21 @@
;; Writes all Chars in string ;; Writes all Chars in string
;; Then writes a New line character to interface ;; Then writes a New line character to interface
:Print_Line :Print_Line
;; Preserve Registers
PUSHR R0 R15
PUSHR R1 R15
PUSHR R2 R15
PUSHR R3 R15
PUSHR R4 R15
;; Initialize ;; Initialize
MOVE R3 R0 ; Get Pointer safely out of the way MOVE R3 R0 ; Get Pointer safely out of the way
FALSE R4 ; Start index at 0
:Print_Line_0 :Print_Line_0
LOADXU8 R0 R3 R4 ; Get our first byte LOADU8 R0 R3 0 ; Get our first byte
CMPSKIPI.NE R0 0 ; If the loaded byte is NULL CMPSKIPI.NE R0 0 ; If the loaded byte is NULL
JUMP @Print_Line_Done ; Be done JUMP @Print_Line_Done ; Be done
FPUTC ; Otherwise print FPUTC ; Otherwise print
ADDUI R4 R4 1 ; Increment for next loop ADDUI R3 R3 1 ; Increment for next loop
JUMP @Print_Line_0 ; And Loop JUMP @Print_Line_0 ; And Loop
;; Clean up ;; Clean up
:Print_Line_Done :Print_Line_Done
LOADUI R0 10 ; Put in Newline char LOADUI R0 10 ; Put in Newline char
FPUTC ; Write it out FPUTC ; Write it out
;; Restore Registers
POPR R4 R15
POPR R3 R15
POPR R2 R15
POPR R1 R15
POPR R0 R15
RET R15 RET R15

View File

@ -2,7 +2,7 @@
59f0502748af32e3096e026a95e77216179cccfe803a05803317414643e2fcec roms/DEHEX 59f0502748af32e3096e026a95e77216179cccfe803a05803317414643e2fcec roms/DEHEX
b3a910f18c6bc0ef4aa7a53cb3f0216a9f143319da67ed2a02210fe88b1e1131 roms/forth b3a910f18c6bc0ef4aa7a53cb3f0216a9f143319da67ed2a02210fe88b1e1131 roms/forth
7c3887f791999aa9c1b8415d8e5be93afcf916b505296d9da7bd7a22531a84b5 roms/lisp 7c3887f791999aa9c1b8415d8e5be93afcf916b505296d9da7bd7a22531a84b5 roms/lisp
2b9727381aec15a504c0898189fbc2344209d8e04451e3fa5d743e08e38f64cf roms/M0 47bc5a29e37bbe4cac31ba612f5e452210b0c4364e529116b9a1c4976912c29d roms/M0
24a4d74eb2eb7a82e68335643855658b27b5a6c3b13db473539f3e08d6f26ceb roms/SET 24a4d74eb2eb7a82e68335643855658b27b5a6c3b13db473539f3e08d6f26ceb roms/SET
0a427b14020354d1c785f5f900677e0059fce8f8d4456e9c19e5528cb17101eb roms/stage0_monitor 0a427b14020354d1c785f5f900677e0059fce8f8d4456e9c19e5528cb17101eb roms/stage0_monitor
3ea7fed1429400c1d6fc5b85180c4114755dfb1e6b88d69e7ecc465a40523bc8 roms/stage1_assembler-0 3ea7fed1429400c1d6fc5b85180c4114755dfb1e6b88d69e7ecc465a40523bc8 roms/stage1_assembler-0