123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427 |
- ## Copyright (C) 2016 Jeremiah Orians
- ## This file is part of stage0.
- ##
- ## 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.
- ##
- ## stage0 is distributed in the hope that it will be useful,
- ## but WITHOUT ANY WARRANTY; without even the implied warranty of
- ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ## GNU General Public License for more details.
- ##
- ## You should have received a copy of the GNU General Public License
- ## along with stage0. If not, see <http://www.gnu.org/licenses/>.
- :start
- E0002D2F $stack # 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
- E0002D2C4000 # LOADUI R12 0x4000 ; We will be using R12 for the HEAP
- # ;; 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
- E0002D201100 # LOADUI R0 0x1100
- 42100000 # FOPEN_READ
- # ;; Prepare to Read File
- 0D00002E # FALSE R14
- 0D000021 # FALSE R1
- E0002D0F @ReadFile # CALLI R15 @ReadFile
- # ;; Done reading File
- E0002D201100 # LOADUI R0 0x1100 ; Close TAPE_01
- 42100002 # FCLOSE
- # ;; Enter Editor Loop
- 090005D1 # MOVE R13 R1 ; Set R13 to Head
- E0002D0F @EditorLoop # CALLI R15 @EditorLoop
- # ;; And We are Done
- FFFFFFFF # HALT
- # ;; Readfile function
- # ;; Receives 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
- 0900040C # COPY R0 R12 ; Copy Current free into R0
- E1000FCC000c # ADDUI R12 R12 12 ; Allocate Node
- # ;; Get another line into list
- 0902001F # PUSHR R1 R15
- E0002D211100 # LOADUI R1 0x1100 ; Read from tape_01
- E0002D0F @Readline # CALLI R15 @Readline
- 0902801F # POPR R1 R15
- 09000301 # SWAP R0 R1
- E0002D0F @addline # CALLI R15 @addline
- 09000301 # SWAP R0 R1
- # ;; Loop if not reached EOF
- E0002C9E @ReadFile # JUMP.Z R14 @ReadFile
- 0D01001F # RET R15
- # ;; Readline function
- # ;; Receives 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
- 0900040C # COPY R0 R12 ; Get where space is free
- 09000520 # MOVE R2 R0
- 0D000023 # FALSE R3
- :Readline_0
- 42100100 # FGETC ; Read a Char
- # ;; Flag if reached EOF
- E000A0100000 # CMPSKIPI.GE R0 0
- 0D00003E # TRUE R14
- # ;; Stop if EOF
- E000A0100000 # CMPSKIPI.GE R0 0
- 3C00 @Readline_2 # JUMP @Readline_2
- # ;; Handle Backspace
- E000A020007f # CMPSKIPI.E R0 127
- 3C00 @Readline_1 # JUMP @Readline_1
- # ;; Move back 1 character if R3 > 0
- E000A0430000 # CMPSKIPI.LE R3 0
- E10011330001 # SUBUI R3 R3 1
- # ;; Hopefully they keep typing
- 3C00 @Readline_0 # JUMP @Readline_0
- :Readline_1
- # ;; Replace all CR with LF
- E000A030000d # CMPSKIPI.NE R0 13
- E0002D20000a # LOADUI R0 10
- # ;; Store the Byte
- 05049023 # STOREX8 R0 R2 R3
- # ;; Prep for next loop
- E1000F330001 # ADDUI R3 R3 1
- # ;; Check for EOL
- E000A030000a # CMPSKIPI.NE R0 10
- 3C00 @Readline_2 # JUMP @Readline_2
- # ;; Otherwise loop
- 3C00 @Readline_0 # JUMP @Readline_0
- :Readline_2
- # ;; Set Text pointer
- E000A0230000 # CMPSKIPI.E R3 0 ; Don't bother for Empty strings
- E10023240008 # STORE32 R2 R4 8
- # ;; Correct Malloc
- 05000CC3 # ADD R12 R12 R3 ; Ensure actually allocates exactly the amount of space required
- # ;; 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
- # ;; Receives 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
- E0002CA0 @addline_0 # JUMP.NZ R0 @addline_0
- 0902800F # POPR R0 R15
- 0902001F # PUSHR R1 R15
- 3C00 @addline_2 # JUMP @addline_2
- :addline_0
- # ;; Handle if Head->next is NULL
- E10018200000 # LOAD32 R2 R0 0
- E0002CA2 @addline_1 # JUMP.NZ R2 @addline_1
- # ;; Set head->next = p
- E10023100000 # STORE32 R1 R0 0
- # ;; Set p->prev = head
- E10023010004 # STORE32 R0 R1 4
- 3C00 @addline_2 # JUMP @addline_2
- :addline_1
- # ;; Handle case of Head->next not being NULL
- E10018000000 # LOAD32 R0 R0 0 ; Move to next node
- E10018200000 # LOAD32 R2 R0 0 ; Get node->next
- E000A0220000 # CMPSKIPI.E R2 0 ; If it is not null
- 3C00 @addline_1 # JUMP @addline_1 ; Move to the next node and try again
- 3C00 @addline_0 # JUMP @addline_0 ; Else simply act as if we got this node in the first place
- :addline_2
- # ;; Restore registers
- 0902800F # POPR R0 R15
- 0902801F # POPR R1 R15
- 0902802F # POPR R2 R15
- 0D01001F # RET R15
- # ;; 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
- E000A0300071 # CMPSKIPI.NE R0 113
- 0D01001F # RET R15
- # ;; Print if p
- E1001FE00070 # CMPUI R14 R0 112
- E0002C6E @EditorLoop_0 # JUMP.NE R14 @EditorLoop_0
- E100180D0008 # LOAD32 R0 R13 8
- 0D000021 # FALSE R1
- E0002D0F @PrintLine # CALLI R15 @PrintLine
- 3C00 @EditorLoop # JUMP @EditorLoop
- :EditorLoop_0
- # ;; Move forward if f
- E1001FE00066 # CMPUI R14 R0 102
- E0002C6E @EditorLoop_1 # JUMP.NE R14 @EditorLoop_1
- E100180D0000 # LOAD32 R0 R13 0 ; Load head->next
- # ;; If head->next isn't null make it the new head
- E000A0200000 # CMPSKIPI.E R0 0
- 090005D0 # MOVE R13 R0
- 3C00 @EditorLoop # JUMP @EditorLoop
- :EditorLoop_1
- # ;; Move backward if b
- E1001FE00062 # CMPUI R14 R0 98
- E0002C6E @EditorLoop_2 # JUMP.NE R14 @EditorLoop_2
- E100180D0004 # LOAD32 R0 R13 4 ; Load head->prev
- # ;; If head->prev isn't null make it the new head
- E000A0200000 # CMPSKIPI.E R0 0
- 090005D0 # MOVE R13 R0
- 3C00 @EditorLoop # JUMP @EditorLoop
- :EditorLoop_2
- # ;; Edit Line if e
- E1001FE00065 # CMPUI R14 R0 101
- E0002C6E @EditorLoop_3 # JUMP.NE R14 @EditorLoop_3
- # ;; Change Head's Text
- 0900040D # COPY R0 R13
- 0D000021 # FALSE R1 ; Read from tty
- E0002D0F @Readline # CALLI R15 @Readline
- 3C00 @EditorLoop # JUMP @EditorLoop
- :EditorLoop_3
- # ;; Writeout to tape_02 if w
- E1001FE00077 # CMPUI R14 R0 119
- E0002C6E @EditorLoop_4 # JUMP.NE R14 @EditorLoop_4
- # ;; Prep TAPE_02
- E0002D201101 # LOADUI R0 0x1101
- 42100001 # FOPEN_WRITE
- 0900040D # COPY R0 R13
- E0002D211101 # LOADUI R1 0x1101
- E0002D0F @GetRoot # CALLI R15 @GetRoot
- E0002D0F @PrintAll # CALLI R15 @PrintAll
- E0002D201101 # LOADUI R0 0x1101 ; Close TAPE_02
- 42100002 # FCLOSE
- 3C00 @EditorLoop # JUMP @EditorLoop
- :EditorLoop_4
- # ;; Append node if a
- E1001FE00061 # CMPUI R14 R0 97
- E0002C6E @EditorLoop_5 # JUMP.NE R14 @EditorLoop_5
- 0900040D # COPY R0 R13
- E0002D0F @AppendLine # CALLI R15 @AppendLine
- 3C00 @EditorLoop # JUMP @EditorLoop
- :EditorLoop_5
- # ;; Insert node if i
- E1001FE00069 # CMPUI R14 R0 105
- E0002C6E @EditorLoop_6 # JUMP.NE R14 @EditorLoop_6
- 0900040D # COPY R0 R13
- E0002D0F @InsertLine # CALLI R15 @InsertLine
- 3C00 @EditorLoop # JUMP @EditorLoop
- :EditorLoop_6
- # ;; Delete node if d
- E1001FE00064 # CMPUI R14 R0 100
- E0002C6E @EditorLoop_7 # JUMP.NE R14 @EditorLoop_7
- 0900040D # COPY R0 R13
- E0002D0F @RemoveLine # CALLI R15 @RemoveLine
- 090005D0 # MOVE R13 R0
- 3C00 @EditorLoop # JUMP @EditorLoop
- :EditorLoop_7
- 3C00 @EditorLoop # JUMP @EditorLoop
- # ;; GetRoot function
- # ;; Walks backwards through nodes until beginning
- # ;; Receives 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
- E10018100004 # LOAD32 R1 R0 4
- E000A0310000 # CMPSKIPI.NE R1 0
- 3C00 @GetRoot_1 # JUMP @GetRoot_1
- 09000501 # MOVE R0 R1
- 3C00 @GetRoot_0 # 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
- E10018200000 # LOAD32 R2 R0 0 ; Store Head->Next in R2
- E10018000008 # LOAD32 R0 R0 8 ; Set R0 to Head->Text
- E0002D0F @PrintLine # CALLI R15 @PrintLine ; Prints Head->Text
- E000A0320000 # CMPSKIPI.NE R2 0 ; If Head->Next is NULL
- 3C00 @PrintAll_1 # JUMP @PrintAll_1 ; Stop Looping
- 09000502 # MOVE R0 R2 ; Otherwise Move to Next Node
- 3C00 @PrintAll_0 # 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
- # ;; Receives 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
- E000A0320000 # CMPSKIPI.NE R2 0
- 3C00 @PrintLine_1 # JUMP @PrintLine_1
- :PrintLine_0
- 0503A023 # LOADXU8 R0 R2 R3 ; Load char from string
- # ;; Don't print NULLs
- E000A0300000 # CMPSKIPI.NE R0 0
- 3C00 @PrintLine_1 # JUMP @PrintLine_1
- 42100200 # FPUTC
- # ; Print the char
- E1000F330001 # ADDUI R3 R3 1 ; Prep for next loop
- 3C00 @PrintLine_0 # 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
- # ;; Receives 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
- 0900040C # COPY R0 R12
- E1000FCC000c # ADDUI R12 R12 12
- # ;; Check if head->Next is null
- E10018210000 # LOAD32 R2 R1 0
- E000A0220000 # CMPSKIPI.E R2 0 ; If head->Next is something
- E10023020004 # STORE32 R0 R2 4 ; Set head->next->prev to p
- # ;; Setup p and head
- E10023200000 # STORE32 R2 R0 0 ; p->next = head->next
- E10023100004 # STORE32 R1 R0 4 ; p->prev = head
- E10023010000 # 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
- # ;; Receives 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
- 0900040C # COPY R0 R12
- E1000FCC000c # ADDUI R12 R12 12
- # ;; Check if Head->Prev is Null
- E10018210004 # LOAD32 R2 R1 4
- E000A0220000 # CMPSKIPI.E R2 0 ; If head->prev is something
- E10023020000 # STORE32 R0 R2 0 ; Set head->prev->next to p
- # ;; Setup p and head
- E10023200004 # STORE32 R2 R0 4 ; p->prev = head->prev
- E10023100000 # STORE32 R1 R0 0 ; p->next = head
- E10023010004 # 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
- # ;; Receives 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
- E10018010004 # LOAD32 R0 R1 4 ; put p->prev in R0
- E10018210000 # LOAD32 R2 R1 0 ; put p->next in R2
- # ;; Keep links
- E000A0200000 # CMPSKIPI.E R0 0 ; If p->prev is not null
- E10023200000 # STORE32 R2 R0 0 ; p->prev->next = p->next
- E000A0220000 # CMPSKIPI.E R2 0 ; If p->next is not null
- E10023020004 # STORE32 R0 R2 4 ; p->next->prev = p->prev
- # ;; Attempt to save what is left of the list
- E000A0300000 # 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
|