diff --git a/CHANGELOG.org b/CHANGELOG.org index 3f9bde9..e553053 100644 --- a/CHANGELOG.org +++ b/CHANGELOG.org @@ -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 diff --git a/bootstrapping Steps.org b/bootstrapping Steps.org index e11447f..51c5723 100644 --- a/bootstrapping Steps.org +++ b/bootstrapping Steps.org @@ -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. diff --git a/stage1/M0-macro.hex2 b/stage1/M0-macro.hex2 index 4d48e95..d7a9d86 100644 --- a/stage1/M0-macro.hex2 +++ b/stage1/M0-macro.hex2 @@ -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 diff --git a/stage1/M0-macro.s b/stage1/M0-macro.s index d788667..f243e31 100644 --- a/stage1/M0-macro.s +++ b/stage1/M0-macro.s @@ -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 diff --git a/test/SHA256SUMS b/test/SHA256SUMS index b404af3..b2c1e54 100644 --- a/test/SHA256SUMS +++ b/test/SHA256SUMS @@ -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