## This file is part of stage0. ## ## stage0 is free software: you an redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 3 of the License, or ## (at your option) any later version. ## ## stage0 is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with stage0. If not, see . # :start 2D2F0394 # LOADUI R15 $stack ; Put stack at end of program # ;; We will be using R14 for our condition codes # ;; We will be using R13 for storage of Head # ;; Main program # ;; Reads contents of Tape_01 and writes desired contents onto Tape_02 # ;; Accepts no arguments and HALTS when done # :main # ;; Prep TAPE_01 2D201100 # LOADUI R0 0x1100 42100000 # FOPEN_READ # ;; Prepare to Read File 0D00002E # FALSE R14 0D000021 # FALSE R1 2D0F0018 # CALLI R15 @ReadFile # ;; Done reading File 2D201100 # LOADUI R0 0x1100 ; Close TAPE_01 42100002 # FCLOSE # ;; Enter Editor Loop 090005D1 # MOVE R13 R1 ; Set R13 to Head 2D0F0134 # CALLI R15 @EditorLoop # ;; And We are Done FFFFFFFF # HALT # ;; Readfile function # ;; Recieves pointer to head in R1 # ;; Creates Nodes and imports text until EOF # ;; Alters R0 R1 R14 # ;; Returns to whatever called it # :ReadFile # ;; Allocate another Node 2D20000c # LOADUI R0 12 2D0F0100 # CALLI R15 @malloc # ;; Get another line into list 0902001F # PUSHR R1 R15 2D211100 # LOADUI R1 0x1100 ; Read from tape_01 2D0F001c # CALLI R15 @Readline 0902801F # POPR R1 R15 09000301 # SWAP R0 R1 2D0F00a0 # CALLI R15 @addline 09000301 # SWAP R0 R1 # ;; Loop if not reached EOF 2C9Effdc # JUMP.Z R14 @ReadFile 0D01001F # RET R15 # ;; Readline function # ;; Recieves Pointer to node in R0 # ;; And Input in R1 # ;; Allocates Text segment on Heap # ;; Sets node's pointer to Text segment # ;; Sets R14 to True if EOF reached # ;; Returns to whatever called it # :Readline # ;; Preserve registers 0902000F # PUSHR R0 R15 0902001F # PUSHR R1 R15 0902002F # PUSHR R2 R15 0902003F # PUSHR R3 R15 0902004F # PUSHR R4 R15 # ;; Initialize 09000540 # MOVE R4 R0 2D200100 # LOADUI R0 256 2D0F00bc # CALLI R15 @malloc 09000520 # MOVE R2 R0 0D000023 # FALSE R3 # :Readline_0 42100100 # FGETC ; Read a Char # ;; Flag if reached EOF A0100000 # CMPSKIPI.GE R0 0 0D00003E # TRUE R14 # ;; Stop if EOF A0100000 # CMPSKIPI.GE R0 0 3C00003c # JUMP @Readline_2 # ;; Handle Backspace A020007f # CMPSKIPI.E R0 127 3C000010 # JUMP @Readline_1 # ;; Move back 1 character if R3 > 0 A0430000 # CMPSKIPI.LE R3 0 11330001 # SUBUI R3 R3 1 # ;; Hopefully they keep typing 3C00ffdc # JUMP @Readline_0 # :Readline_1 # ;; Replace all CR with LF A030000d # CMPSKIPI.NE R0 13 2D20000a # LOADUI R0 10 # ;; Store the Byte 05049023 # STOREX8 R0 R2 R3 # ;; Check for EOL A030000a # CMPSKIPI.NE R0 10 3C000014 # JUMP @Readline_2 # ;; Prevent lines from exceeding 255 chars A04300ff # CMPSKIPI.LE R3 255 3C00000c # JUMP @Readline_2 # ;; Prep for next loop 0F330001 # ADDUI R3 R3 1 3C00ffb8 # JUMP @Readline_0 # :Readline_2 # ;; Set Text pointer 23240008 # STORE32 R2 R4 8 # ;; 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 # ;; addline Function # ;; Recieves pointers in R0 R1 # ;; Alters R0 if NULL # ;; Appends nodes together # ;; Returns to whatever called it # :addline # ;; Preserve Registers 0902002F # PUSHR R2 R15 0902001F # PUSHR R1 R15 0902000F # PUSHR R0 R15 # ;; Handle if Head is NULL 2CA00010 # JUMP.NZ R0 @addline_0 0902800F # POPR R0 R15 0902001F # PUSHR R1 R15 3C000020 # JUMP @addline_2 # :addline_0 # ;; Handle if Head->next is NULL 18200000 # LOAD32 R2 R0 0 2CA20010 # JUMP.NZ R2 @addline_1 # ;; Set head->next = p 23100000 # STORE32 R1 R0 0 # ;; Set p->prev = head 23010004 # STORE32 R0 R1 4 3C00000c # JUMP @addline_2 # :addline_1 # ;; Handle case of Head->next not being NULL 18000000 # LOAD32 R0 R0 0 2D0Fffcc # CALLI R15 @addline # :addline_2 # ;; Restore registers 0902800F # POPR R0 R15 0902801F # POPR R1 R15 0902802F # POPR R2 R15 0D01001F # RET R15 # ;; 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 2E010020 # 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 2F01000c # STORER R1 @malloc_pointer # ;; Done # ;; Restore registers 0902801F # POPR R1 R15 0D01001F # RET R15 # ;; Our static value for malloc pointer # :malloc_pointer 00000000 # NOP # ;; Editor Loop # ;; Provides user interaction # ;; Requires R13 to be pointer to Head # ;; Internally loops # ;; Returns nothing # :EditorLoop 0D000021 # FALSE R1 ; Read from tty 42100100 # FGETC ; Read a Char # ;; Quit if q A0300071 # CMPSKIPI.NE R0 113 0D01001F # RET R15 # ;; Print if p 1FE00070 # CMPUI R14 R0 112 2C6E0014 # JUMP.NE R14 @EditorLoop_0 180D0008 # LOAD32 R0 R13 8 0D000021 # FALSE R1 2D0F0118 # CALLI R15 @PrintLine 3C00ffdc # JUMP @EditorLoop # :EditorLoop_0 # ;; Move forward if f 1FE00066 # CMPUI R14 R0 102 2C6E0014 # JUMP.NE R14 @EditorLoop_1 180D0000 # LOAD32 R0 R13 0 ; Load head->next # ;; If head->next isn't null make it the new head A0200000 # CMPSKIPI.E R0 0 090005D0 # MOVE R13 R0 3C00ffc4 # JUMP @EditorLoop # :EditorLoop_1 # ;; Move backward if b 1FE00062 # CMPUI R14 R0 98 2C6E0014 # JUMP.NE R14 @EditorLoop_2 180D0004 # LOAD32 R0 R13 4 ; Load head->prev # ;; If head->prev isn't null make it the new head A0200000 # CMPSKIPI.E R0 0 090005D0 # MOVE R13 R0 3C00ffac # JUMP @EditorLoop # :EditorLoop_2 # ;; Edit Line if e 1FE00065 # CMPUI R14 R0 101 2C6E0014 # JUMP.NE R14 @EditorLoop_3 # ;; Change Head's Text 0900040D # COPY R0 R13 0D000021 # FALSE R1 ; Read from tty 2D0Ffe98 # CALLI R15 @Readline 3C00ff94 # JUMP @EditorLoop # :EditorLoop_3 # ;; Writeout to tape_02 if w 1FE00077 # CMPUI R14 R0 119 2C6E0028 # JUMP.NE R14 @EditorLoop_4 # ;; Prep TAPE_02 2D201101 # LOADUI R0 0x1101 42100001 # FOPEN_WRITE 0900040D # COPY R0 R13 2D211101 # LOADUI R1 0x1101 2D0F0058 # CALLI R15 @GetRoot 2D0F0074 # CALLI R15 @PrintAll 2D201101 # LOADUI R0 0x1101 ; Close TAPE_02 42100002 # FCLOSE 3C00ff68 # JUMP @EditorLoop # :EditorLoop_4 # ;; Append node if a 1FE00061 # CMPUI R14 R0 97 2C6E0010 # JUMP.NE R14 @EditorLoop_5 0900040D # COPY R0 R13 2D0F00dc # CALLI R15 @AppendLine 3C00ff54 # JUMP @EditorLoop # :EditorLoop_5 # ;; Insert node if i 1FE00069 # CMPUI R14 R0 105 2C6E0010 # JUMP.NE R14 @EditorLoop_6 0900040D # COPY R0 R13 2D0F0108 # CALLI R15 @InsertLine 3C00ff40 # JUMP @EditorLoop # :EditorLoop_6 # ;; Delete node if d 1FE00064 # CMPUI R14 R0 100 2C6E0014 # JUMP.NE R14 @EditorLoop_7 0900040D # COPY R0 R13 2D0F0134 # CALLI R15 @RemoveLine 090005D0 # MOVE R13 R0 3C00ff28 # JUMP @EditorLoop # :EditorLoop_7 3C00ff24 # JUMP @EditorLoop # ;; GetRoot function # ;; Walks backwards through nodes until beginning # ;; Recieves node pointer in R0 and Returns result in R0 # ;; Returns to whatever called it # :GetRoot # ;; Preserve registers 0902001F # PUSHR R1 R15 # :GetRoot_0 # ;; Get Head->Prev 18100004 # LOAD32 R1 R0 4 A0310000 # CMPSKIPI.NE R1 0 3C00000c # JUMP @GetRoot_1 09000501 # MOVE R0 R1 3C00fff0 # JUMP @GetRoot_0 # :GetRoot_1 # ;; Restore registers 0902801F # POPR R1 R15 0D01001F # RET R15 # ;; Printall Function # ;; Prints all lines to Interface in R1 # ;; Starting at node in R0 # ;; Does not alter registers # ;; Returns to whatever called it # :PrintAll # ;; Preserve registers 0902000F # PUSHR R0 R15 0902001F # PUSHR R1 R15 0902002F # PUSHR R2 R15 # :PrintAll_0 18200000 # LOAD32 R2 R0 0 ; Store Head->Next in R2 18000008 # LOAD32 R0 R0 8 ; Set R0 to Head->Text 2D0F0024 # CALLI R15 @PrintLine ; Prints Head->Text A0320000 # CMPSKIPI.NE R2 0 ; If Head->Next is NULL 3C00000c # JUMP @PrintAll_1 ; Stop Looping 09000502 # MOVE R0 R2 ; Otherwise Move to Next Node 3C00ffe8 # JUMP @PrintAll_0 ; And Loop # :PrintAll_1 # ;; Restore registers 0902802F # POPR R2 R15 0902801F # POPR R1 R15 0902800F # POPR R0 R15 0D01001F # RET R15 # ;; Printline function # ;; Recieves a string pointer in R0 # ;; Prints string interface specified in R1 # ;; Does not alter registers # ;; Returns to whatever called it # :PrintLine # ;; Preserve registers 0902000F # PUSHR R0 R15 0902001F # PUSHR R1 R15 0902002F # PUSHR R2 R15 0902003F # PUSHR R3 R15 # ;; Initialize 09000520 # MOVE R2 R0 0D000023 # FALSE R3 # ;; Deal with NULL Pointer A0320000 # CMPSKIPI.NE R2 0 3C00001c # JUMP @PrintLine_1 # :PrintLine_0 0503A023 # LOADXU8 R0 R2 R3 ; Load char from string # ;; Don't print NULLs A0300000 # CMPSKIPI.NE R0 0 3C000010 # JUMP @PrintLine_1 42100200 # FPUTC # ; Print the char 0F330001 # ADDUI R3 R3 1 ; Prep for next loop 3C00ffec # JUMP @PrintLine_0 # :PrintLine_1 # ;; Restore registers 0902803F # POPR R3 R15 0902802F # POPR R2 R15 0902801F # POPR R1 R15 0902800F # POPR R0 R15 0D01001F # RET R15 # ;; AppendLine Function # ;; Recieves a Node in R0 # ;; Creates a new Node and appends it # ;; Does not alter registers # ;; Returns to whatever calls it # :AppendLine # ;; Preserve registers 0902000F # PUSHR R0 R15 0902001F # PUSHR R1 R15 0902002F # PUSHR R2 R15 # ;; Initialize 09000510 # MOVE R1 R0 # ;; Allocate another Node 2D20000c # LOADUI R0 12 2D0Ffe40 # CALLI R15 @malloc # ;; Check if head->Next is null 18210000 # LOAD32 R2 R1 0 A0220000 # CMPSKIPI.E R2 0 ; If head->Next is something 23020004 # STORE32 R0 R2 4 ; Set head->next->prev to p # ;; Setup p and head 23200000 # STORE32 R2 R0 0 ; p->next = head->next 23100004 # STORE32 R1 R0 4 ; p->prev = head 23010000 # STORE32 R0 R1 0 ; head->next = p # ;; Restore Registers 0902802F # POPR R2 R15 0902801F # POPR R1 R15 0902800F # POPR R0 R15 0D01001F # RET R15 # ;; InsertLine Function # ;; Recieves a Node in R0 # ;; Creates a new Node and prepends it # ;; Does not alter registers # ;; Returns to whatever called it # :InsertLine # ;; Preserve Registers 0902000F # PUSHR R0 R15 0902001F # PUSHR R1 R15 0902002F # PUSHR R2 R15 # ;; Initialize 09000510 # MOVE R1 R0 # ;; Allocate another Node 2D20000c # LOADUI R0 12 2D0Ffe00 # CALLI R15 @malloc # ;; Check if Head->Prev is Null 18210004 # LOAD32 R2 R1 4 A0220000 # CMPSKIPI.E R2 0 ; If head->prev is something 23020000 # STORE32 R0 R2 0 ; Set head->prev->next to p # ;; Setup p and head 23200004 # STORE32 R2 R0 4 ; p->prev = head->prev 23100000 # STORE32 R1 R0 0 ; p->next = head 23010004 # STORE32 R0 R1 4 ; head->prev = p # ;; Restore Registers 0902802F # POPR R2 R15 0902801F # POPR R1 R15 0902800F # POPR R0 R15 0D01001F # RET R15 # ;; RemoveLine Function # ;; Recieves Node in R0 # ;; Returns replacement node in R0 # ;; Returns to whatever called it # :RemoveLine # ;; Preserve Registers 0902001F # PUSHR R1 R15 0902002F # PUSHR R2 R15 # ;; Initialize 09000510 # MOVE R1 R0 18010004 # LOAD32 R0 R1 4 ; put p->prev in R0 18210000 # LOAD32 R2 R1 0 ; put p->next in R2 # ;; Keep links A0200000 # CMPSKIPI.E R0 0 ; If p->prev is not null 23200000 # STORE32 R2 R0 0 ; p->prev->next = p->next A0220000 # CMPSKIPI.E R2 0 ; If p->next is not null 23020004 # STORE32 R0 R2 4 ; p->next->prev = p->prev # ;; Attempt to save what is left of the list A0300000 # CMPSKIPI.NE R0 0 ; If p->prev is null 09000502 # MOVE R0 R2 ; return p->next # ;; Restore Registers 0902802F # POPR R2 R15 0902801F # POPR R1 R15 0D01001F # RET R15 # ;; Where our stack begins # :stack