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 output of large negative numbers in hex
Updated checksums to reflect changed made in performance tuning
Fixed M0 performance by a factor of 4
** Removed
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.
roms/M0 should have the sha256sum of 2b9727381aec15a504c0898189fbc2344209d8e04451e3fa5d743e08e38f64cf
roms/M0 should have the sha256sum of 47bc5a29e37bbe4cac31ba612f5e452210b0c4364e529116b9a1c4976912c29d
* 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.

View File

@ -1,7 +1,7 @@
## Copyright (C) 2016 Jeremiah Orians
## This file is part of stage0.
##
## stage0 is free software: you an redistribute it and/or modify
## stage0 is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
@ -16,130 +16,108 @@
:start
# ;; We will be using R13 for storage of Head
# ;; We will be using R14 for our condition codes
2D2F $stack # LOADUI R15 $stack ; Put stack at end of progra
2D2E 4000 # LOADUI R14 0x4000 ; Our malloc pointer (Initialized)
2D2F $stack # LOADUI R15 $stack ; Put stack at end of program
# ;; Main program
# ;; Reads contents of Tape_01 and applies all Definitions
# ;; Writes results to Tape_02
# ;; Accepts no arguments and HALTS when done
: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
2C9E @main_0 # JUMP.Z R14 @main_0 ; Until we reach EOF
# ;; Done reading File
2D201100 # LOADUI R0 0x1100 ; Close TAPE_01
42100002 # FCLOSE
0900040D # COPY R0 R13 ; Prepare for function
2D0F @reverse_list # CALLI R15 @reverse_list ; Reverse the list of tokens
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 @Process_String # CALLI R15 @Process_String ; Convert string values to Hex16
2D0F @Eval_Immediates # CALLI R15 @Eval_Immediates ; Convert numbers to hex
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
# ;; Done writing File
2D201101 # LOADUI R0 0x1101 ; Close TAPE_01
42100002 # FCLOSE
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
# ;; Recieves pointer to Head in R0 and desired input in R1
# ;; Alters R14 when EOF Reached
# ;; Opens tape_01 and reads into a backwards linked list in R13
# ;; Returns to whatever called it
:Tokenize_Line
# ;; Preserve registers
0902000F # PUSHR R0 R15
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
0902003F # PUSHR R3 R15
0902004F # PUSHR R4 R15
# ;; Initialize
0900044D # COPY R4 R13 ; Get Head pointer out of the way
# ;; Prep TAPE_01
2D201100 # LOADUI R0 0x1100
42100000 # FOPEN_READ
0D00002D # FALSE R13 ; Head is NULL
09000510 # MOVE R1 R0 ; Read Tape_01
:Tokenize_Line_0
42100100 # FGETC ; Get a Char
# ;; Deal with lines comments starting with #
A0300023 # CMPSKIPI.NE R0 35
3C00 @Purge_Line_Comment # JUMP @Purge_Line_Comment
# ;; Deal with Line comments starting with ;
A030003b # CMPSKIPI.NE R0 59
3C00 @Purge_Line_Comment # JUMP @Purge_Line_Comment
# ;; Deal with Tab
A0300009 # CMPSKIPI.NE R0 9
3C00 @Tokenize_Line_0 # JUMP @Tokenize_Line_0 ; Throw away byte and try again
# ;; Deal with New line
A030000a # CMPSKIPI.NE R0 10
3C00 @Tokenize_Line_0 # JUMP @Tokenize_Line_0 ; Throw away byte and try again
# ;; Deal with space characters
A0300020 # CMPSKIPI.NE R0 32
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
A0100000 # CMPSKIPI.GE R0 0
3C00 @Tokenize_Line_Done # JUMP @Tokenize_Line_Done
# ;; Allocate a new Node
09000520 # MOVE R2 R0 ; Get Char out the way
2D200010 # LOADUI R0 16 ; Allocate 16 Bytes
2D0F @malloc # CALLI R15 @malloc ; Get address of new Node
09000320 # SWAP R2 R0 ; Store Pointer in R2
# ;; Deal with Strings wrapped in ""
0900042E # COPY R2 R14 ; Get address of new Node
0FEE0010 # ADDUI R14 R14 16 ; Allocate 16 Bytes
23E20008 # STORE32 R14 R2 8 ; Set Text pointer
# ;; Deal with Strings wrapped in \"
A0300022 # CMPSKIPI.NE R0 34
3C00 @Store_String # JUMP @Store_String
# ;; Deal with Strings wrapped in '
A0300027 # CMPSKIPI.NE R0 39
3C00 @Store_String # JUMP @Store_String
# ;; Everything else is an atom store it
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
09000512 # MOVE R1 R2 ; Put Node pointer we are working on into R1
0900040D # COPY R0 R13 ; Get current HEAD
2D0F @Add_Token # CALLI R15 @Add_Token ; Append new token to Head
# ;; Restore registers
0902804F # POPR R4 R15
0902803F # POPR R3 R15
0902802F # POPR R2 R15
0902801F # POPR R1 R15
0902800F # POPR R0 R15
# ;; Return since we are done
# ;; Done reading File
2D201100 # LOADUI R0 0x1100 ; Close TAPE_01
42100002 # FCLOSE
0D01001F # RET R15
# ;; reverse_list Function
# ;; Reverses the list given in R13
:reverse_list
# ;; 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
@ -161,33 +139,20 @@ A020000a # CMPSKIPI.E R0 10 ; Stop When LF is reached
# ;; Modifies node Text to point to string and sets
# ;; Type to string.
:Store_String
# ;; Preserve registers
0902004F # PUSHR R4 R15
0902005F # PUSHR R5 R15
0902006F # PUSHR R6 R15
# ;; Initialize
09000560 # MOVE R6 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
0D000025 # FALSE R5 ; Start at index 0
09000406 # COPY R0 R6 ; Copy Char back into R0
# ;; Primary Loop
09000430 # COPY R3 R0 ; Copy Char for comparison
:Store_String_0
05049045 # STOREX8 R0 R4 R5 ; Store the Byte
210E0000 # STORE8 R0 R14 0 ; Store the Byte
42100100 # FGETC ; Get next Byte
0F550001 # ADDUI R5 R5 1 ; Prep for next loop
C306 @Store_String_0 # CMPJUMPI.NE R0 R6 @Store_String_0 ; Loop if matching not found
0FEE0001 # ADDUI R14 R14 1 ; Prep for next loop
C303 @Store_String_0 # CMPJUMPI.NE R0 R3 @Store_String_0 ; Loop if matching not found
# ;; Clean up
23420008 # STORE32 R4 R2 8 ; Set Text pointer
0F050004 # ADDUI R0 R5 4 ; Correct Malloc
2D0F @malloc # CALLI R15 @malloc ; To the amount of space used
0FEE0004 # ADDUI R14 R14 4 ; Correct Malloc
2D200002 # LOADUI R0 2 ; Using type string
23020004 # STORE32 R0 R2 4 ; Set node type
# ;; Restore Registers
0902806F # POPR R6 R15
0902805F # POPR R5 R15
0902804F # POPR R4 R15
3C00 @Tokenize_Line_Done # JUMP @Tokenize_Line_Done
3C00 @Tokenize_Line_1 # JUMP @Tokenize_Line_1
# ;; 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
# ;; Modifies node Text to point to string
:Store_Atom
# ;; Preserve registers
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
210E0000 # STORE8 R0 R14 0 ; Store the 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
3C00 @Store_Atom_Done # JUMP @Store_Atom_Done ; Be done
A030000a # CMPSKIPI.NE R0 10 ; If char is LF
3C00 @Store_Atom_Done # JUMP @Store_Atom_Done ; Be done
A0300020 # CMPSKIPI.NE R0 32 ; If char is Space
3C00 @Store_Atom_Done # JUMP @Store_Atom_Done ; Be done
# ;; Otherwise loop
3C00 @Store_Atom_0 # JUMP @Store_Atom_0
3C00 @Store_Atom # JUMP @Store_Atom
:Store_Atom_Done
# ;; Cleanup
23420008 # STORE32 R4 R2 8 ; Set Text pointer
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
0FEE0001 # ADDUI R14 R14 1 ; Correct Malloc
0D01001F # RET R15
@ -273,94 +186,87 @@ A0220000 # CMPSKIPI.E R2 0 ; If it is not null
# ;; Returns to whatever called it
:strcmp
# ;; Preserve registers
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
0902003F # PUSHR R3 R15
0902004F # PUSHR R4 R15
# ;; Setup registers
09000520 # MOVE R2 R0 ; Put R0 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
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
05004001 # CMP R0 R0 R1 ; Compare the bytes
A0210000 # CMPSKIPI.E R1 0 ; Stop if byte is NULL
2C50 @cmpbyte # JUMP.E R0 @cmpbyte ; Loop if bytes are equal
# ;; Done
09000501 # MOVE R0 R1 ; Prepare for return
# ;; Restore registers
0902804F # POPR R4 R15
0902803F # POPR R3 R15
0902802F # POPR R2 R15
0902801F # POPR R1 R15
0D01001F # RET R15
# ;; Identify_Macros Function
# ;; Recieves a pointer to a node in R0
# ;; If the text stored in its Text segment matches
# ;; DEFINE, flag it and Collapse it down to a single Node
# ;; Loop until all nodes are checked
# ;; Return to whatever called it
:Identify_Macros
# ;; Preserve Registers
0902000F # PUSHR R0 R15
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
0902003F # PUSHR R3 R15
# ;; Initializ
2D2101d0 # LOADUI R1 $Identify_Macros_string
0900042D # COPY R2 R13 ; i = head
# ;; Main Loop
:Identify_Macros_0
09000520 # MOVE R2 R0
18120008 # LOAD32 R1 R2 8 ; Get Pointer to Text
2D20 $Identify_Macros_string # LOADUI R0 $Identify_Macros_string
18020008 # LOAD32 R0 R2 8 ; Get Pointer to Text
2D0F @strcmp # CALLI R15 @strcmp
09000512 # MOVE R1 R2
2C60 @Identify_Macros_1 # JUMP.NE R0 @Identify_Macros_1
# ;; It is a definition
# ;; Set p->Type = macro
# ;; Set i->Type = macro
2D200001 # LOADUI R0 1 ; The Enum value for macro
23010004 # STORE32 R0 R1 4 ; Set node type
# ;; Set p->Text = p->Next->Text
18210000 # LOAD32 R2 R1 0 ; Get Next
18020008 # LOAD32 R0 R2 8 ; Get Next->Text
23010008 # STORE32 R0 R1 8 ; Set Text = Next->Text
# ;; Set p->Expression = p->next->next->Text
18220000 # LOAD32 R2 R2 0 ; Get Next->Next
18020008 # LOAD32 R0 R2 8 ; Get Next->Next->Text
18320004 # LOAD32 R3 R2 4 ; Get Next->Next->type
23020004 # STORE32 R0 R2 4 ; Set node type
# ;; Set i->Text = i->Next->Text
18420000 # LOAD32 R4 R2 0 ; Get Next
18040008 # LOAD32 R0 R4 8 ; Get Next->Text
23020008 # STORE32 R0 R2 8 ; Set i->Text = Next->Text
# ;; Set i->Expression = i->next->next->Text
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
0F000001 # ADDUI R0 R0 1 ; Skip first char
2301000c # STORE32 R0 R1 12 ; Set Expression = Next->Next->Text
# ;; Set p->Next = p->Next->Next->Next
18020000 # LOAD32 R0 R2 0 ; Get Next->Next->Next
23010000 # STORE32 R0 R1 0 ; Set Next = Next->Next->Next
2302000c # STORE32 R0 R2 12 ; Set Expression = Next->Next->Text
# ;; Set i->Next = i->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
18010000 # LOAD32 R0 R1 0 ; Get node->next
A0300000 # CMPSKIPI.NE R0 0 ; If node->next is 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
18220000 # LOAD32 R2 R2 0 ; Get node->next
2CA2 @Identify_Macros_0 # JUMP.NZ R2 @Identify_Macros_0 ; Loop if i not NULL
0D01001F # RET R15
:Identify_Macros_string
444546494E450000 # "DEFINE"
444546494E450000 # "DEFINE" ;; Line_Macro Function
# ;; Line_Macro Function
# ;; Recieves a node pointer in R0
# ;; Causes macros to be applied
# ;; Returns to whatever called it
:Line_Macro
# ;; Preserve Registers
0902000F # PUSHR R0 R15
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
0902003F # PUSHR R3 R15
# ;; Initialize
0900040D # COPY R0 R13 ; Start with Head
# ;; Main loop
:Line_Macro_0
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
A0330001 # CMPSKIPI.NE R3 1 ; If a macro
2D0F @setExpression # CALLI R15 @setExpression ; Apply to other nodes
A0200000 # CMPSKIPI.E R0 0 ; If Next is Null
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
2CA0 @Line_Macro_0 # JUMP.NZ R0 @Line_Macro_0 ; If Next is Null Don't loop
0D01001F # RET R15
@ -388,29 +288,25 @@ A0200000 # CMPSKIPI.E R0 0 ; If Next is Null
:setExpression
# ;; Preserve registers
0902000F # PUSHR R0 R15
0902003F # PUSHR R3 R15
0902004F # PUSHR R4 R15
0902005F # PUSHR R5 R15
# ;; Initialize
09000541 # MOVE R4 R1 ; Put Macro Text in a safe place
09000450 # COPY R5 R0 ; Use R5 for Node pointer
09000440 # COPY R4 R0 ; Use R4 for Node pointer
: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
3C00 @setExpression_1 # JUMP @setExpression_1 ; Move to next if Macro
18050008 # LOAD32 R0 R5 8 ; Load Text pointer into R0 for Comparision
09000414 # COPY R1 R4 ; Put Macro Text for comparision
18040008 # LOAD32 R0 R4 8 ; Load Text pointer into R0 for Comparision
2D0F @strcmp # CALLI R15 @strcmp ; compare Text and Macro Text
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
18550000 # LOAD32 R5 R5 0 ; Load Next
2CA5 @setExpression_0 # JUMP.NZ R5 @setExpression_0 ; Loop if next isn't NULL
18440000 # LOAD32 R4 R4 0 ; Load Next
2CA4 @setExpression_0 # JUMP.NZ R4 @setExpression_0 ; Loop if next isn't NULL
:setExpression_Done
# ;; Restore registers
0902805F # POPR R5 R15
0902804F # POPR R4 R15
0902803F # POPR R3 R15
0902800F # POPR R0 R15
0D01001F # RET R15
@ -420,36 +316,35 @@ A0330001 # CMPSKIPI.NE R3 1 ; Check if Macro
# ;; Doesn't modify registers
# ;; Returns back to whatever called it
:Process_String
# ;; Preserve Registers
0902000F # PUSHR R0 R15
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
# ;; Initialize
0900040D # COPY R0 R13 ; Start with Head
:Process_String_0
# ;; Get node type
18100004 # LOAD32 R1 R0 4 ; Load Type
A0210002 # CMPSKIPI.E R1 2 ; If not a string
3C00 @Process_String_Done # JUMP @Process_String_Done ; Just go to next
# ;; Its a string
18100008 # LOAD32 R1 R0 8 ; Get Text pointer
14210000 # LOAD8 R2 R1 0 ; Get first char of Text
# ;; Deal with '
A0220027 # CMPSKIPI.E R2 39 ; If char is not '
3C00 @Process_String_1 # JUMP @Process_String_1 ; Move to next label
# ;; Simply use Hex strings as is
0F110001 # ADDUI R1 R1 1 ; Move Text pointer by 1
2310000c # STORE32 R1 R0 12 ; Set expression to Text + 1
3C00 @Process_String_Done # JUMP @Process_String_Done ; And move on
:Process_String_1
# ;; Deal with ""
# ;; Deal with \"
2D0F @Hexify_String # CALLI R15 @Hexify_String
:Process_String_Done
18000000 # LOAD32 R0 R0 0 ; Load Next
A0200000 # CMPSKIPI.E R0 0 ; If Next isn't NULL
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
2CA0 @Process_String_0 # JUMP.NZ R0 @Process_String_0 ; If Next isn't NULL Recurse down list
0D01001F # RET R15
@ -462,43 +357,31 @@ A0200000 # CMPSKIPI.E R0 0 ; If Next isn't NULL
:Hexify_String
# ;; Preserve Registers
0902000F # PUSHR R0 R15
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
0902003F # PUSHR R3 R15
0902004F # PUSHR R4 R15
# ;; Initialize
09000520 # MOVE R2 R0 ; Move R0 out of the way
2D0F @malloc # CALLI R15 @malloc ; Get address of new Node
09000510 # MOVE R1 R0 ; Prep For Hex32
2312000c # STORE32 R1 R2 12 ; Set node expression pointer
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
09000510 # MOVE R1 R0 ; Move R0 out of the way
23E1000c # STORE32 R14 R1 12 ; Set node expression pointer
18110008 # LOAD32 R1 R1 8 ; Load Text pointer into R2
0F110001 # ADDUI R1 R1 1 ; SKip leading \"
# ;; Main Loop
:Hexify_String_0
18020000 # LOAD32 R0 R2 0 ; Load 4 bytes into R0 from Text
B03000ff # ANDI R3 R0 0xFF ; Preserve byte to check for NULL
18010000 # LOAD32 R0 R1 0 ; Load 4 bytes into R0 from Text
B02000ff # ANDI R2 R0 0xFF ; Preserve byte to check for NULL
2D0F @hex32 # CALLI R15 @hex32 ; Convert to hex and store in Expression
0F220004 # ADDUI R2 R2 4 ; Pointer Text pointer to next 4 bytes
0F440008 # ADDUI R4 R4 8 ; Increment storage space required
A0230000 # CMPSKIPI.E R3 0 ; If byte was NULL
3C00 @Hexify_String_0 # JUMP @Hexify_String_0
0F110004 # ADDUI R1 R1 4 ; Pointer Text pointer to next 4 bytes
2CA2 @Hexify_String_0 # JUMP.NZ R2 @Hexify_String_0
# ;; Done
0F040001 # ADDUI R0 R4 1 ; Lead space for NULL terminator
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
0FEE0001 # ADDUI R14 R14 1 ; Correct malloc value
0902800F # POPR R0 R15
0D01001F # RET R15
# ;; hex32 functionality
# ;; Accepts 32bit value in R0
# ;; Require R1 to be a pointer to place to store hex16
# ;; WILL ALTER R1 !
# ;; Require R14 to be the heap pointer
# ;; WILL ALTER R14 !
# ;; Returns to whatever called it
:hex32
0902000F # PUSHR R0 R15
@ -516,12 +399,12 @@ A0230000 # CMPSKIPI.E R3 0 ; If byte was NULL
2D0F @hex4 # CALLI R15 @hex4
0902800F # POPR R0 R15
:hex4
B000000f # ANDI R0 R0 0x000F ; isolate nybble
B000000f # ANDI R0 R0 0xF ; isolate nybble
0F000030 # ADDUI R0 R0 48 ; convert to ascii
A0400039 # CMPSKIPI.LE R0 57 ; If nybble was greater than '9'
0F000007 # ADDUI R0 R0 7 ; Shift it into 'A' range of ascii
21010000 # STORE8 R0 R1 0 ; Store Hex Char
0F110001 # ADDUI R1 R1 1 ; Increment address pointer
210E0000 # STORE8 R0 R14 0 ; Store Hex Char
0FEE0001 # ADDUI R14 R14 1 ; Increment address pointer
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
# ;; And write into Memory and fix pointer
: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
0900040D # COPY R0 R13 ; Start with Head
0D000025 # FALSE R5 ; Zero for checking return of numerate_string
0900043D # COPY R3 R13 ; Start with Head
# ;; Process Text
:Eval_Immediates_0
09000460 # COPY R6 R0 ; Safely preserve pointer to node
18400000 # LOAD32 R4 R0 0 ; Load Node->Next
18300004 # LOAD32 R3 R0 4 ; Load Node type
1820000c # LOAD32 R2 R0 12 ; Load Expression pointer
18100008 # LOAD32 R1 R0 8 ; Load Text pointer
2CA2 @Eval_Immediates_1 # JUMP.NZ R2 @Eval_Immediates_1 ; Don't do anything if Expression is set
2CA3 @Eval_Immediates_1 # JUMP.NZ R3 @Eval_Immediates_1 ; Don't do anything if Typed
09000401 # COPY R0 R1 ; Put Text pointer into R0
18230000 # LOAD32 R2 R3 0 ; Load Node->Next
1803000c # LOAD32 R0 R3 12 ; Load Expression pointer
2CA0 @Eval_Immediates_1 # JUMP.NZ R0 @Eval_Immediates_1 ; Don't do anything if Expression is set
18030004 # LOAD32 R0 R3 4 ; Load Node type
2CA0 @Eval_Immediates_1 # JUMP.NZ R0 @Eval_Immediates_1 ; Don't do anything if Typed
18030008 # LOAD32 R0 R3 8 ; Load Text pointer
14100000 # LOAD8 R1 R0 0 ; Get first char of Text
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'
C205 @Eval_Immediates_1 # CMPJUMPI.E R0 R5 @Eval_Immediates_1 ; Don't do anything if string isn't a number
09000510 # MOVE R1 R0 ; Preserve number
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
2C90 @Eval_Immediates_1 # JUMP.Z R0 @Eval_Immediates_1 ; Don't do anything if string isn't a number
20E3000c # STORE R14 R3 12 ; Preserve pointer to expression
2D0F @hex16 # CALLI R15 @hex16 ; Shove our number into expression
0FEE0001 # ADDUI R14 R14 1 ; Allocate enough space for a null
# ;; Handle looping
:Eval_Immediates_1
C245 @Eval_Immediates_2 # CMPJUMPI.E R4 R5 @Eval_Immediates_2 ; If null be done
09000504 # MOVE R0 R4 ; Prepare for next 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
09000532 # MOVE R3 R2 ; Prepare for next loop
2CA3 @Eval_Immediates_0 # JUMP.NZ R3 @Eval_Immediates_0 ; And loop
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
0902003F # PUSHR R3 R15
0902004F # PUSHR R4 R15
# ;; Initialize
09000510 # MOVE R1 R0 ; Get Text pointer out of the way
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
A0300078 # CMPSKIPI.NE R0 120 ; If the second byte is x
3C00 @numerate_string_hex # JUMP @numerate_string_hex ; treat string like hex
# ;; Deal with Decimal input
2D24000a # LOADUI R4 10 ; Multiply by 10
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
A0220000 # CMPSKIPI.E R2 0 ; If toggled
0F110001 # ADDUI R1 R1 1 ; Move to next
:numerate_string_dec
14010000 # LOAD8 R0 R1 0 ; Get a byte
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
0F110001 # ADDUI R1 R1 1 ; Move onto next byte
3C00 @numerate_string_dec # JUMP @numerate_string_dec
# ;; Deal with Hex input
:numerate_string_hex
14010000 # LOAD8 R0 R1 0 ; Get a byte
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
0F110002 # ADDUI R1 R1 2 ; Move to after leading 0x
:numerate_string_hex_0
14010000 # LOAD8 R0 R1 0 ; Get a byte
A0300000 # CMPSKIPI.NE R0 0 ; If NULL
3C00 @numerate_string_done # JUMP @numerate_string_done ; Be done
2C90 @numerate_string_done # JUMP.Z R0 @numerate_string_done ; If NULL Be done
2D530004 # SL0I R3 4 ; Shift counter by 16
10000030 # SUBI R0 R0 48 ; Convert ascii number to number
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
0F110001 # ADDUI R1 R1 1 ; Get next Hex
3C00 @numerate_string_hex_0 # JUMP @numerate_string_hex_0
# ;; Clean up
:numerate_string_done
A0220000 # CMPSKIPI.E R2 0 ; If Negate flag has been set
09000033 # NEG R3 R3 ; Make the number negative
09000503 # MOVE R0 R3 ; Put number in R0
# ;; Restore Registers
0902804F # POPR R4 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
# ;; For all unset nodes
: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
0900040D # COPY R0 R13 ; Start with HEAD
# ;; Process Node
:Preserve_Other_0
18400000 # LOAD32 R4 R0 0 ; Load Node->Next
18300004 # LOAD32 R3 R0 4 ; Load Node type
1820000c # LOAD32 R2 R0 12 ; Load Expression pointer
18200000 # LOAD32 R2 R0 0 ; Load Node->Next
18100004 # LOAD32 R1 R0 4 ; Load Node type
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
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
# ;; Loop through nodes
: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
# ;; 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
@ -688,34 +542,30 @@ A0220000 # CMPSKIPI.E R2 0 ; If Negate flag has been set
# ;; Print all of the expressions
# ;; Starting with HEAD
:Print_Hex
# ;; Preserve Registers
0902000F # PUSHR R0 R15
0902001F # PUSHR R1 R15
0902002F # PUSHR R2 R15
0902003F # PUSHR R3 R15
0902004F # PUSHR R4 R15
# ;; Prep TAPE_02
2D201101 # LOADUI R0 0x1101
42100001 # FOPEN_WRITE
# ;; Initialize
0900040D # COPY R0 R13 ; Start with HEAD
2D211101 # LOADUI R1 0x1101 ; Write to Tape_02
:Print_Hex_0
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
10110001 # SUBI R1 R1 1 ; Check for Macros
2C91 @Print_Hex_1 # JUMP.Z R1 @Print_Hex_1 ; Don't print Macros
2D211101 # LOADUI R1 0x1101 ; Write to Tape_02
10330001 # SUBI R3 R3 1 ; Check for Macros
2C93 @Print_Hex_1 # JUMP.Z R3 @Print_Hex_1 ; Don't print Macros
2D0F @Print_Line # CALLI R15 @Print_Line ; Print the Expression
# ;; Loop down the nodes
:Print_Hex_1
09000502 # MOVE R0 R2 ; Prepare for next loop
2CA0 @Print_Hex_0 # JUMP.NZ R0 @Print_Hex_0 ; Keep looping if not NULL
# ;; Clean up
:Print_Hex_Done
# ;; Restore Registers
0902804F # POPR R4 R15
0902803F # POPR R3 R15
0902802F # POPR R2 R15
0902801F # POPR R1 R15
0902800F # POPR R0 R15
# ;; Done writing File
2D201101 # LOADUI R0 0x1101 ; Close TAPE_01
42100002 # FCLOSE
0D01001F # RET R15
@ -725,32 +575,21 @@ A0220000 # CMPSKIPI.E R2 0 ; If Negate flag has been set
# ;; Writes all Chars in string
# ;; Then writes a New line character to interface
: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
09000530 # MOVE R3 R0 ; Get Pointer safely out of the way
0D000024 # FALSE R4 ; Start index at 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
3C00 @Print_Line_Done # JUMP @Print_Line_Done ; Be done
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
# ;; Clean up
:Print_Line_Done
2D20000a # LOADUI R0 10 ; Put in Newline char
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
# ;; Where we are putting the start of our stack

View File

@ -16,7 +16,7 @@
:start
;; 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
;; Main program
@ -24,81 +24,28 @@
;; Writes results to Tape_02
;; Accepts no arguments and HALTS when done
: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
LOADUI R0 0x1100
FOPEN_READ
FALSE R13 ; Head is NULL
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
FGETC ; Get a Char
@ -122,19 +69,14 @@
CMPSKIPI.NE R0 32
JUMP @Tokenize_Line_0 ; Throw away byte and try again
;; Flag if reached EOF
CMPSKIPI.GE R0 0
TRUE R14
;; Stop if EOF
CMPSKIPI.GE R0 0
JUMP @Tokenize_Line_Done
;; Allocate a new Node
MOVE R2 R0 ; Get Char out the way
LOADUI R0 16 ; Allocate 16 Bytes
CALLI R15 @malloc ; Get address of new Node
SWAP R2 R0 ; Store Pointer in R2
COPY R2 R14 ; Get address of new Node
ADDUI R14 R14 16 ; Allocate 16 Bytes
STORE32 R14 R2 8 ; Set Text pointer
;; Deal with Strings wrapped in "
CMPSKIPI.NE R0 34
@ -146,20 +88,35 @@
;; Everything else is an atom store it
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
MOVE R1 R2 ; Put Node pointer we are working on into R1
COPY R0 R13 ; Get current HEAD
CALLI R15 @Add_Token ; Append new token to Head
;; Done reading File
LOADUI R0 0x1100 ; Close TAPE_01
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
@ -181,37 +138,20 @@
;; Modifies node Text to point to string and sets
;; Type to string.
:Store_String
;; Preserve registers
PUSHR R4 R15
PUSHR R5 R15
PUSHR R6 R15
;; Initialize
MOVE R6 R0 ; Get R0 out of the way
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
COPY R3 R0 ; Copy Char for comparison
;; Primary Loop
:Store_String_0
STOREX8 R0 R4 R5 ; Store the Byte
STORE8 R0 R14 0 ; Store the Byte
FGETC ; Get next Byte
ADDUI R5 R5 1 ; Prep for next loop
CMPJUMPI.NE R0 R6 @Store_String_0 ; Loop if matching not found
ADDUI R14 R14 1 ; Prep for next loop
CMPJUMPI.NE R0 R3 @Store_String_0 ; Loop if matching not found
;; Clean up
STORE32 R4 R2 8 ; Set Text pointer
ADDUI R0 R5 4 ; Correct Malloc
CALLI R15 @malloc ; To the amount of space used
ADDUI R14 R14 4 ; Correct Malloc
LOADUI R0 2 ; Using type string
STORE32 R0 R2 4 ; Set node type
;; Restore Registers
POPR R6 R15
POPR R5 R15
POPR R4 R15
JUMP @Tokenize_Line_Done
JUMP @Tokenize_Line_1
;; Store_Atom function
@ -219,21 +159,9 @@
;; And node pointer in R2
;; Modifies node Text to point to string
:Store_Atom
;; Preserve registers
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
STORE8 R0 R14 0 ; Store the 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
JUMP @Store_Atom_Done ; Be done
@ -245,60 +173,11 @@
JUMP @Store_Atom_Done ; Be done
;; Otherwise loop
JUMP @Store_Atom_0
JUMP @Store_Atom
:Store_Atom_Done
;; Cleanup
STORE32 R4 R2 8 ; Set Text pointer
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
ADDUI R14 R14 1 ; Correct Malloc
RET R15
@ -309,87 +188,71 @@
;; Returns to whatever called it
:strcmp
;; Preserve registers
PUSHR R1 R15
PUSHR R2 R15
PUSHR R3 R15
PUSHR R4 R15
;; Setup registers
MOVE R2 R0 ; Put R0 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
LOADXU8 R0 R2 R4 ; Get a byte of our first string
LOADXU8 R1 R3 R4 ; Get a byte of our second string
ADDUI R4 R4 1 ; Prep for next loop
CMP R1 R0 R1 ; Compare the bytes
CMPSKIPI.E R0 0 ; Stop if byte is NULL
JUMP.E R1 @cmpbyte ; Loop if bytes are equal
CMP R0 R0 R1 ; Compare the bytes
CMPSKIPI.E R1 0 ; Stop if byte is NULL
JUMP.E R0 @cmpbyte ; Loop if bytes are equal
;; Done
MOVE R0 R1 ; Prepare for return
;; Restore registers
POPR R4 R15
POPR R3 R15
POPR R2 R15
POPR R1 R15
RET R15
;; Identify_Macros Function
;; Recieves a pointer to a node in R0
;; If the text stored in its Text segment matches
;; DEFINE, flag it and Collapse it down to a single Node
;; Loop until all nodes are checked
;; Return to whatever called it
:Identify_Macros
;; Preserve Registers
PUSHR R0 R15
PUSHR R1 R15
PUSHR R2 R15
PUSHR R3 R15
;; Initializ
LOADUI R1 $Identify_Macros_string
COPY R2 R13 ; i = head
;; Main Loop
:Identify_Macros_0
MOVE R2 R0
LOAD32 R1 R2 8 ; Get Pointer to Text
LOADUI R0 $Identify_Macros_string
LOAD32 R0 R2 8 ; Get Pointer to Text
CALLI R15 @strcmp
MOVE R1 R2
JUMP.NE R0 @Identify_Macros_1
;; It is a definition
;; Set p->Type = macro
;; Set i->Type = 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
LOAD32 R2 R1 0 ; Get Next
LOAD32 R0 R2 8 ; Get Next->Text
STORE32 R0 R1 8 ; Set Text = Next->Text
;; Set i->Text = i->Next->Text
LOAD32 R4 R2 0 ; Get Next
LOAD32 R0 R4 8 ; Get Next->Text
STORE32 R0 R2 8 ; Set i->Text = Next->Text
;; Set p->Expression = p->next->next->Text
LOAD32 R2 R2 0 ; Get Next->Next
LOAD32 R0 R2 8 ; Get Next->Next->Text
LOAD32 R3 R2 4 ; Get Next->Next->type
;; Set i->Expression = i->next->next->Text
LOAD32 R4 R4 0 ; Get Next->Next
LOAD32 R0 R4 8 ; Get Next->Next->Text
LOAD32 R3 R4 4 ; Get Next->Next->type
CMPSKIPI.NE R3 2 ; If node is a string
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
LOAD32 R0 R2 0 ; Get Next->Next->Next
STORE32 R0 R1 0 ; Set Next = Next->Next->Next
;; Set i->Next = i->Next->Next->Next
LOAD32 R4 R4 0 ; Get Next->Next->Next
STORE32 R4 R2 0 ; Set i->Next = Next->Next->Next
:Identify_Macros_1
LOAD32 R0 R1 0 ; Get node->next
CMPSKIPI.NE R0 0 ; If node->next is 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
LOAD32 R2 R2 0 ; Get node->next
JUMP.NZ R2 @Identify_Macros_0 ; Loop if i not NULL
RET R15
:Identify_Macros_string
@ -401,11 +264,8 @@
;; Causes macros to be applied
;; Returns to whatever called it
:Line_Macro
;; Preserve Registers
PUSHR R0 R15
PUSHR R1 R15
PUSHR R2 R15
PUSHR R3 R15
;; Initialize
COPY R0 R13 ; Start with Head
;; Main loop
:Line_Macro_0
@ -415,14 +275,7 @@
LOAD32 R0 R0 0 ; Load Next pointer
CMPSKIPI.NE R3 1 ; If a macro
CALLI R15 @setExpression ; Apply to other nodes
CMPSKIPI.E R0 0 ; If Next is Null
JUMP @Line_Macro_0 ; Don't loop
;; Clean up
POPR R3 R15
POPR R2 R15
POPR R1 R15
POPR R0 R15
JUMP.NZ R0 @Line_Macro_0 ; If Next is Null Don't loop
RET R15
@ -435,33 +288,25 @@
:setExpression
;; Preserve registers
PUSHR R0 R15
PUSHR R3 R15
PUSHR R4 R15
PUSHR R5 R15
;; Initialize
MOVE R4 R1 ; Put Macro Text in a safe place
COPY R5 R0 ; Use R5 for Node pointer
COPY R4 R0 ; Use R4 for Node pointer
: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
JUMP @setExpression_1 ; Move to next if Macro
LOAD32 R0 R5 8 ; Load Text pointer into R0 for Comparision
COPY R1 R4 ; Put Macro Text for comparision
LOAD32 R0 R4 8 ; Load Text pointer into R0 for Comparision
CALLI R15 @strcmp ; compare Text and Macro Text
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
LOAD32 R5 R5 0 ; Load Next
JUMP.NZ R5 @setExpression_0 ; Loop if next isn't NULL
LOAD32 R4 R4 0 ; Load Next
JUMP.NZ R4 @setExpression_0 ; Loop if next isn't NULL
:setExpression_Done
;; Restore registers
POPR R5 R15
POPR R4 R15
POPR R3 R15
POPR R0 R15
RET R15
@ -471,10 +316,8 @@
;; Doesn't modify registers
;; Returns back to whatever called it
:Process_String
;; Preserve Registers
PUSHR R0 R15
PUSHR R1 R15
PUSHR R2 R15
;; Initialize
COPY R0 R13 ; Start with Head
:Process_String_0
;; Get node type
@ -501,13 +344,7 @@
:Process_String_Done
LOAD32 R0 R0 0 ; Load Next
CMPSKIPI.E R0 0 ; If Next isn't NULL
JUMP @Process_String_0 ; Recurse down list
;; Restore registers
POPR R2 R15
POPR R1 R15
POPR R0 R15
JUMP.NZ R0 @Process_String_0 ; If Next isn't NULL Recurse down list
RET R15
@ -520,47 +357,31 @@
:Hexify_String
;; Preserve Registers
PUSHR R0 R15
PUSHR R1 R15
PUSHR R2 R15
PUSHR R3 R15
PUSHR R4 R15
;; Initialize
MOVE R2 R0 ; Move R0 out of the way
CALLI R15 @malloc ; Get address of new Node
MOVE R1 R0 ; Prep For Hex32
STORE32 R1 R2 12 ; Set node expression pointer
LOAD32 R2 R2 8 ; Load Text pointer into R2
ADDUI R2 R2 1 ; SKip leading "
FALSE R4 ; Set counter for malloc to Zero
MOVE R1 R0 ; Move R0 out of the way
STORE32 R14 R1 12 ; Set node expression pointer
LOAD32 R1 R1 8 ; Load Text pointer into R2
ADDUI R1 R1 1 ; SKip leading "
;; Main Loop
:Hexify_String_0
LOAD32 R0 R2 0 ; Load 4 bytes into R0 from Text
ANDI R3 R0 0xFF ; Preserve byte to check for NULL
LOAD32 R0 R1 0 ; Load 4 bytes into R0 from Text
ANDI R2 R0 0xFF ; Preserve byte to check for NULL
CALLI R15 @hex32 ; Convert to hex and store in Expression
ADDUI R2 R2 4 ; Pointer Text pointer to next 4 bytes
ADDUI R4 R4 8 ; Increment storage space required
CMPSKIPI.E R3 0 ; If byte was NULL
JUMP @Hexify_String_0
ADDUI R1 R1 4 ; Pointer Text pointer to next 4 bytes
JUMP.NZ R2 @Hexify_String_0
;; Done
ADDUI R0 R4 1 ; Lead space for NULL terminator
CALLI R15 @malloc ; Correct malloc value
;; Restore Registers
POPR R4 R15
POPR R3 R15
POPR R2 R15
POPR R1 R15
ADDUI R14 R14 1 ; Correct malloc value
POPR R0 R15
RET R15
;; hex32 functionality
;; Accepts 32bit value in R0
;; Require R1 to be a pointer to place to store hex16
;; WILL ALTER R1 !
;; Require R14 to be the heap pointer
;; WILL ALTER R14 !
;; Returns to whatever called it
:hex32
PUSHR R0 R15
@ -578,12 +399,12 @@
CALLI R15 @hex4
POPR R0 R15
:hex4
ANDI R0 R0 0x000F ; isolate nybble
ANDI R0 R0 0xF ; isolate nybble
ADDUI R0 R0 48 ; convert to ascii
CMPSKIPI.LE R0 57 ; If nybble was greater than '9'
ADDUI R0 R0 7 ; Shift it into 'A' range of ascii
STORE8 R0 R1 0 ; Store Hex Char
ADDUI R1 R1 1 ; Increment address pointer
STORE8 R0 R14 0 ; Store Hex Char
ADDUI R14 R14 1 ; Increment address pointer
RET R15 ; Get next nybble or return if done
@ -592,56 +413,29 @@
;; Converts number into Hex
;; And write into Memory and fix pointer
: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
COPY R0 R13 ; Start with Head
FALSE R5 ; Zero for checking return of numerate_string
COPY R3 R13 ; Start with Head
;; Process Text
:Eval_Immediates_0
COPY R6 R0 ; Safely preserve pointer to node
LOAD32 R4 R0 0 ; Load Node->Next
LOAD32 R3 R0 4 ; Load Node type
LOAD32 R2 R0 12 ; Load Expression pointer
LOAD32 R1 R0 8 ; Load Text pointer
JUMP.NZ R2 @Eval_Immediates_1 ; Don't do anything if Expression is set
JUMP.NZ R3 @Eval_Immediates_1 ; Don't do anything if Typed
COPY R0 R1 ; Put Text pointer into R0
LOAD32 R2 R3 0 ; Load Node->Next
LOAD32 R0 R3 12 ; Load Expression pointer
JUMP.NZ R0 @Eval_Immediates_1 ; Don't do anything if Expression is set
LOAD32 R0 R3 4 ; Load Node type
JUMP.NZ R0 @Eval_Immediates_1 ; Don't do anything if Typed
LOAD32 R0 R3 8 ; Load Text pointer
LOAD8 R1 R0 0 ; Get first char of Text
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'
CMPJUMPI.E R0 R5 @Eval_Immediates_1 ; Don't do anything if string isn't a number
MOVE R1 R0 ; Preserve number
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
JUMP.Z R0 @Eval_Immediates_1 ; Don't do anything if string isn't a number
STORE R14 R3 12 ; Preserve pointer to expression
CALLI R15 @hex16 ; Shove our number into expression
ADDUI R14 R14 1 ; Allocate enough space for a null
;; Handle looping
:Eval_Immediates_1
CMPJUMPI.E R4 R5 @Eval_Immediates_2 ; If null be done
MOVE R0 R4 ; Prepare for next 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
MOVE R3 R2 ; Prepare for next loop
JUMP.NZ R3 @Eval_Immediates_0 ; And loop
RET R15
@ -696,8 +490,7 @@
ADDUI R1 R1 2 ; Move to after leading 0x
:numerate_string_hex_0
LOAD8 R0 R1 0 ; Get a byte
CMPSKIPI.NE R0 0 ; If NULL
JUMP @numerate_string_done ; Be done
JUMP.Z R0 @numerate_string_done ; If NULL Be done
SL0I R3 4 ; Shift counter by 16
SUBI R0 R0 48 ; Convert ascii number to number
@ -728,63 +521,44 @@
;; Sets Expression pointer to Text pointer value
;; For all unset nodes
:Preserve_Other
;; Preserve Registers
PUSHR R0 R15
PUSHR R1 R15
PUSHR R2 R15
PUSHR R3 R15
PUSHR R4 R15
;; Initialize
COPY R0 R13 ; Start with HEAD
;; Process Node
:Preserve_Other_0
LOAD32 R4 R0 0 ; Load Node->Next
LOAD32 R3 R0 4 ; Load Node type
LOAD32 R2 R0 12 ; Load Expression pointer
LOAD32 R2 R0 0 ; Load Node->Next
LOAD32 R1 R0 4 ; Load Node type
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
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
;; Loop through nodes
:Preserve_Other_1
MOVE R0 R4 ; Prepare for next loop
MOVE R0 R2 ; Prepare for next loop
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
;; Print_Hex Function
;; Print all of the expressions
;; Starting with HEAD
:Print_Hex
;; Preserve Registers
PUSHR R0 R15
PUSHR R1 R15
PUSHR R2 R15
PUSHR R3 R15
PUSHR R4 R15
;; Prep TAPE_02
LOADUI R0 0x1101
FOPEN_WRITE
;; Initialize
COPY R0 R13 ; Start with HEAD
LOADUI R1 0x1101 ; Write to Tape_02
:Print_Hex_0
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
SUBI R1 R1 1 ; Check for Macros
JUMP.Z R1 @Print_Hex_1 ; Don't print Macros
LOADUI R1 0x1101 ; Write to Tape_02
SUBI R3 R3 1 ; Check for Macros
JUMP.Z R3 @Print_Hex_1 ; Don't print Macros
CALLI R15 @Print_Line ; Print the Expression
;; Loop down the nodes
@ -792,14 +566,9 @@
MOVE R0 R2 ; Prepare for next loop
JUMP.NZ R0 @Print_Hex_0 ; Keep looping if not NULL
;; Clean up
:Print_Hex_Done
;; Restore Registers
POPR R4 R15
POPR R3 R15
POPR R2 R15
POPR R1 R15
POPR R0 R15
;; Done writing File
LOADUI R0 0x1101 ; Close TAPE_01
FCLOSE
RET R15
@ -809,36 +578,21 @@
;; Writes all Chars in string
;; Then writes a New line character to interface
:Print_Line
;; Preserve Registers
PUSHR R0 R15
PUSHR R1 R15
PUSHR R2 R15
PUSHR R3 R15
PUSHR R4 R15
;; Initialize
MOVE R3 R0 ; Get Pointer safely out of the way
FALSE R4 ; Start index at 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
JUMP @Print_Line_Done ; Be done
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
;; Clean up
:Print_Line_Done
LOADUI R0 10 ; Put in Newline char
FPUTC ; Write it out
;; Restore Registers
POPR R4 R15
POPR R3 R15
POPR R2 R15
POPR R1 R15
POPR R0 R15
RET R15

View File

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