SET.hex2 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. ## Copyright (C) 2016 Jeremiah Orians
  2. ## This file is part of stage0.
  3. ##
  4. ## stage0 is free software: you can redistribute it and/or modify
  5. ## it under the terms of the GNU General Public License as published by
  6. ## the Free Software Foundation, either version 3 of the License, or
  7. ## (at your option) any later version.
  8. ##
  9. ## stage0 is distributed in the hope that it will be useful,
  10. ## but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ## GNU General Public License for more details.
  13. ##
  14. ## You should have received a copy of the GNU General Public License
  15. ## along with stage0. If not, see <http://www.gnu.org/licenses/>.
  16. :start
  17. E0002D2F $stack # LOADUI R15 $stack ; Put stack at end of program
  18. # ;; We will be using R14 for our condition codes
  19. # ;; We will be using R13 for storage of Head
  20. E0002D2C4000 # LOADUI R12 0x4000 ; We will be using R12 for the HEAP
  21. # ;; Main program
  22. # ;; Reads contents of Tape_01 and writes desired contents onto Tape_02
  23. # ;; Accepts no arguments and HALTS when done
  24. :main
  25. # ;; Prep TAPE_01
  26. E0002D201100 # LOADUI R0 0x1100
  27. 42100000 # FOPEN_READ
  28. # ;; Prepare to Read File
  29. 0D00002E # FALSE R14
  30. 0D000021 # FALSE R1
  31. E0002D0F @ReadFile # CALLI R15 @ReadFile
  32. # ;; Done reading File
  33. E0002D201100 # LOADUI R0 0x1100 ; Close TAPE_01
  34. 42100002 # FCLOSE
  35. # ;; Enter Editor Loop
  36. 090005D1 # MOVE R13 R1 ; Set R13 to Head
  37. E0002D0F @EditorLoop # CALLI R15 @EditorLoop
  38. # ;; And We are Done
  39. FFFFFFFF # HALT
  40. # ;; Readfile function
  41. # ;; Receives pointer to head in R1
  42. # ;; Creates Nodes and imports text until EOF
  43. # ;; Alters R0 R1 R14
  44. # ;; Returns to whatever called it
  45. :ReadFile
  46. # ;; Allocate another Node
  47. 0900040C # COPY R0 R12 ; Copy Current free into R0
  48. E1000FCC000c # ADDUI R12 R12 12 ; Allocate Node
  49. # ;; Get another line into list
  50. 0902001F # PUSHR R1 R15
  51. E0002D211100 # LOADUI R1 0x1100 ; Read from tape_01
  52. E0002D0F @Readline # CALLI R15 @Readline
  53. 0902801F # POPR R1 R15
  54. 09000301 # SWAP R0 R1
  55. E0002D0F @addline # CALLI R15 @addline
  56. 09000301 # SWAP R0 R1
  57. # ;; Loop if not reached EOF
  58. E0002C9E @ReadFile # JUMP.Z R14 @ReadFile
  59. 0D01001F # RET R15
  60. # ;; Readline function
  61. # ;; Receives Pointer to node in R0
  62. # ;; And Input in R1
  63. # ;; Allocates Text segment on Heap
  64. # ;; Sets node's pointer to Text segment
  65. # ;; Sets R14 to True if EOF reached
  66. # ;; Returns to whatever called it
  67. :Readline
  68. # ;; Preserve registers
  69. 0902000F # PUSHR R0 R15
  70. 0902001F # PUSHR R1 R15
  71. 0902002F # PUSHR R2 R15
  72. 0902003F # PUSHR R3 R15
  73. 0902004F # PUSHR R4 R15
  74. # ;; Initialize
  75. 09000540 # MOVE R4 R0
  76. 0900040C # COPY R0 R12 ; Get where space is free
  77. 09000520 # MOVE R2 R0
  78. 0D000023 # FALSE R3
  79. :Readline_0
  80. 42100100 # FGETC ; Read a Char
  81. # ;; Flag if reached EOF
  82. E000A0100000 # CMPSKIPI.GE R0 0
  83. 0D00003E # TRUE R14
  84. # ;; Stop if EOF
  85. E000A0100000 # CMPSKIPI.GE R0 0
  86. 3C00 @Readline_2 # JUMP @Readline_2
  87. # ;; Handle Backspace
  88. E000A020007f # CMPSKIPI.E R0 127
  89. 3C00 @Readline_1 # JUMP @Readline_1
  90. # ;; Move back 1 character if R3 > 0
  91. E000A0430000 # CMPSKIPI.LE R3 0
  92. E10011330001 # SUBUI R3 R3 1
  93. # ;; Hopefully they keep typing
  94. 3C00 @Readline_0 # JUMP @Readline_0
  95. :Readline_1
  96. # ;; Replace all CR with LF
  97. E000A030000d # CMPSKIPI.NE R0 13
  98. E0002D20000a # LOADUI R0 10
  99. # ;; Store the Byte
  100. 05049023 # STOREX8 R0 R2 R3
  101. # ;; Prep for next loop
  102. E1000F330001 # ADDUI R3 R3 1
  103. # ;; Check for EOL
  104. E000A030000a # CMPSKIPI.NE R0 10
  105. 3C00 @Readline_2 # JUMP @Readline_2
  106. # ;; Otherwise loop
  107. 3C00 @Readline_0 # JUMP @Readline_0
  108. :Readline_2
  109. # ;; Set Text pointer
  110. E000A0230000 # CMPSKIPI.E R3 0 ; Don't bother for Empty strings
  111. E10023240008 # STORE32 R2 R4 8
  112. # ;; Correct Malloc
  113. 05000CC3 # ADD R12 R12 R3 ; Ensure actually allocates exactly the amount of space required
  114. # ;; Restore Registers
  115. 0902804F # POPR R4 R15
  116. 0902803F # POPR R3 R15
  117. 0902802F # POPR R2 R15
  118. 0902801F # POPR R1 R15
  119. 0902800F # POPR R0 R15
  120. 0D01001F # RET R15
  121. # ;; addline Function
  122. # ;; Receives pointers in R0 R1
  123. # ;; Alters R0 if NULL
  124. # ;; Appends nodes together
  125. # ;; Returns to whatever called it
  126. :addline
  127. # ;; Preserve Registers
  128. 0902002F # PUSHR R2 R15
  129. 0902001F # PUSHR R1 R15
  130. 0902000F # PUSHR R0 R15
  131. # ;; Handle if Head is NULL
  132. E0002CA0 @addline_0 # JUMP.NZ R0 @addline_0
  133. 0902800F # POPR R0 R15
  134. 0902001F # PUSHR R1 R15
  135. 3C00 @addline_2 # JUMP @addline_2
  136. :addline_0
  137. # ;; Handle if Head->next is NULL
  138. E10018200000 # LOAD32 R2 R0 0
  139. E0002CA2 @addline_1 # JUMP.NZ R2 @addline_1
  140. # ;; Set head->next = p
  141. E10023100000 # STORE32 R1 R0 0
  142. # ;; Set p->prev = head
  143. E10023010004 # STORE32 R0 R1 4
  144. 3C00 @addline_2 # JUMP @addline_2
  145. :addline_1
  146. # ;; Handle case of Head->next not being NULL
  147. E10018000000 # LOAD32 R0 R0 0 ; Move to next node
  148. E10018200000 # LOAD32 R2 R0 0 ; Get node->next
  149. E000A0220000 # CMPSKIPI.E R2 0 ; If it is not null
  150. 3C00 @addline_1 # JUMP @addline_1 ; Move to the next node and try again
  151. 3C00 @addline_0 # JUMP @addline_0 ; Else simply act as if we got this node in the first place
  152. :addline_2
  153. # ;; Restore registers
  154. 0902800F # POPR R0 R15
  155. 0902801F # POPR R1 R15
  156. 0902802F # POPR R2 R15
  157. 0D01001F # RET R15
  158. # ;; Editor Loop
  159. # ;; Provides user interaction
  160. # ;; Requires R13 to be pointer to Head
  161. # ;; Internally loops
  162. # ;; Returns nothing
  163. :EditorLoop
  164. 0D000021 # FALSE R1 ; Read from tty
  165. 42100100 # FGETC ; Read a Char
  166. # ;; Quit if q
  167. E000A0300071 # CMPSKIPI.NE R0 113
  168. 0D01001F # RET R15
  169. # ;; Print if p
  170. E1001FE00070 # CMPUI R14 R0 112
  171. E0002C6E @EditorLoop_0 # JUMP.NE R14 @EditorLoop_0
  172. E100180D0008 # LOAD32 R0 R13 8
  173. 0D000021 # FALSE R1
  174. E0002D0F @PrintLine # CALLI R15 @PrintLine
  175. 3C00 @EditorLoop # JUMP @EditorLoop
  176. :EditorLoop_0
  177. # ;; Move forward if f
  178. E1001FE00066 # CMPUI R14 R0 102
  179. E0002C6E @EditorLoop_1 # JUMP.NE R14 @EditorLoop_1
  180. E100180D0000 # LOAD32 R0 R13 0 ; Load head->next
  181. # ;; If head->next isn't null make it the new head
  182. E000A0200000 # CMPSKIPI.E R0 0
  183. 090005D0 # MOVE R13 R0
  184. 3C00 @EditorLoop # JUMP @EditorLoop
  185. :EditorLoop_1
  186. # ;; Move backward if b
  187. E1001FE00062 # CMPUI R14 R0 98
  188. E0002C6E @EditorLoop_2 # JUMP.NE R14 @EditorLoop_2
  189. E100180D0004 # LOAD32 R0 R13 4 ; Load head->prev
  190. # ;; If head->prev isn't null make it the new head
  191. E000A0200000 # CMPSKIPI.E R0 0
  192. 090005D0 # MOVE R13 R0
  193. 3C00 @EditorLoop # JUMP @EditorLoop
  194. :EditorLoop_2
  195. # ;; Edit Line if e
  196. E1001FE00065 # CMPUI R14 R0 101
  197. E0002C6E @EditorLoop_3 # JUMP.NE R14 @EditorLoop_3
  198. # ;; Change Head's Text
  199. 0900040D # COPY R0 R13
  200. 0D000021 # FALSE R1 ; Read from tty
  201. E0002D0F @Readline # CALLI R15 @Readline
  202. 3C00 @EditorLoop # JUMP @EditorLoop
  203. :EditorLoop_3
  204. # ;; Writeout to tape_02 if w
  205. E1001FE00077 # CMPUI R14 R0 119
  206. E0002C6E @EditorLoop_4 # JUMP.NE R14 @EditorLoop_4
  207. # ;; Prep TAPE_02
  208. E0002D201101 # LOADUI R0 0x1101
  209. 42100001 # FOPEN_WRITE
  210. 0900040D # COPY R0 R13
  211. E0002D211101 # LOADUI R1 0x1101
  212. E0002D0F @GetRoot # CALLI R15 @GetRoot
  213. E0002D0F @PrintAll # CALLI R15 @PrintAll
  214. E0002D201101 # LOADUI R0 0x1101 ; Close TAPE_02
  215. 42100002 # FCLOSE
  216. 3C00 @EditorLoop # JUMP @EditorLoop
  217. :EditorLoop_4
  218. # ;; Append node if a
  219. E1001FE00061 # CMPUI R14 R0 97
  220. E0002C6E @EditorLoop_5 # JUMP.NE R14 @EditorLoop_5
  221. 0900040D # COPY R0 R13
  222. E0002D0F @AppendLine # CALLI R15 @AppendLine
  223. 3C00 @EditorLoop # JUMP @EditorLoop
  224. :EditorLoop_5
  225. # ;; Insert node if i
  226. E1001FE00069 # CMPUI R14 R0 105
  227. E0002C6E @EditorLoop_6 # JUMP.NE R14 @EditorLoop_6
  228. 0900040D # COPY R0 R13
  229. E0002D0F @InsertLine # CALLI R15 @InsertLine
  230. 3C00 @EditorLoop # JUMP @EditorLoop
  231. :EditorLoop_6
  232. # ;; Delete node if d
  233. E1001FE00064 # CMPUI R14 R0 100
  234. E0002C6E @EditorLoop_7 # JUMP.NE R14 @EditorLoop_7
  235. 0900040D # COPY R0 R13
  236. E0002D0F @RemoveLine # CALLI R15 @RemoveLine
  237. 090005D0 # MOVE R13 R0
  238. 3C00 @EditorLoop # JUMP @EditorLoop
  239. :EditorLoop_7
  240. 3C00 @EditorLoop # JUMP @EditorLoop
  241. # ;; GetRoot function
  242. # ;; Walks backwards through nodes until beginning
  243. # ;; Receives node pointer in R0 and Returns result in R0
  244. # ;; Returns to whatever called it
  245. :GetRoot
  246. # ;; Preserve registers
  247. 0902001F # PUSHR R1 R15
  248. :GetRoot_0
  249. # ;; Get Head->Prev
  250. E10018100004 # LOAD32 R1 R0 4
  251. E000A0310000 # CMPSKIPI.NE R1 0
  252. 3C00 @GetRoot_1 # JUMP @GetRoot_1
  253. 09000501 # MOVE R0 R1
  254. 3C00 @GetRoot_0 # JUMP @GetRoot_0
  255. :GetRoot_1
  256. # ;; Restore registers
  257. 0902801F # POPR R1 R15
  258. 0D01001F # RET R15
  259. # ;; Printall Function
  260. # ;; Prints all lines to Interface in R1
  261. # ;; Starting at node in R0
  262. # ;; Does not alter registers
  263. # ;; Returns to whatever called it
  264. :PrintAll
  265. # ;; Preserve registers
  266. 0902000F # PUSHR R0 R15
  267. 0902001F # PUSHR R1 R15
  268. 0902002F # PUSHR R2 R15
  269. :PrintAll_0
  270. E10018200000 # LOAD32 R2 R0 0 ; Store Head->Next in R2
  271. E10018000008 # LOAD32 R0 R0 8 ; Set R0 to Head->Text
  272. E0002D0F @PrintLine # CALLI R15 @PrintLine ; Prints Head->Text
  273. E000A0320000 # CMPSKIPI.NE R2 0 ; If Head->Next is NULL
  274. 3C00 @PrintAll_1 # JUMP @PrintAll_1 ; Stop Looping
  275. 09000502 # MOVE R0 R2 ; Otherwise Move to Next Node
  276. 3C00 @PrintAll_0 # JUMP @PrintAll_0 ; And Loop
  277. :PrintAll_1
  278. # ;; Restore registers
  279. 0902802F # POPR R2 R15
  280. 0902801F # POPR R1 R15
  281. 0902800F # POPR R0 R15
  282. 0D01001F # RET R15
  283. # ;; Printline function
  284. # ;; Receives a string pointer in R0
  285. # ;; Prints string interface specified in R1
  286. # ;; Does not alter registers
  287. # ;; Returns to whatever called it
  288. :PrintLine
  289. # ;; Preserve registers
  290. 0902000F # PUSHR R0 R15
  291. 0902001F # PUSHR R1 R15
  292. 0902002F # PUSHR R2 R15
  293. 0902003F # PUSHR R3 R15
  294. # ;; Initialize
  295. 09000520 # MOVE R2 R0
  296. 0D000023 # FALSE R3
  297. # ;; Deal with NULL Pointer
  298. E000A0320000 # CMPSKIPI.NE R2 0
  299. 3C00 @PrintLine_1 # JUMP @PrintLine_1
  300. :PrintLine_0
  301. 0503A023 # LOADXU8 R0 R2 R3 ; Load char from string
  302. # ;; Don't print NULLs
  303. E000A0300000 # CMPSKIPI.NE R0 0
  304. 3C00 @PrintLine_1 # JUMP @PrintLine_1
  305. 42100200 # FPUTC
  306. # ; Print the char
  307. E1000F330001 # ADDUI R3 R3 1 ; Prep for next loop
  308. 3C00 @PrintLine_0 # JUMP @PrintLine_0
  309. :PrintLine_1
  310. # ;; Restore registers
  311. 0902803F # POPR R3 R15
  312. 0902802F # POPR R2 R15
  313. 0902801F # POPR R1 R15
  314. 0902800F # POPR R0 R15
  315. 0D01001F # RET R15
  316. # ;; AppendLine Function
  317. # ;; Receives a Node in R0
  318. # ;; Creates a new Node and appends it
  319. # ;; Does not alter registers
  320. # ;; Returns to whatever calls it
  321. :AppendLine
  322. # ;; Preserve registers
  323. 0902000F # PUSHR R0 R15
  324. 0902001F # PUSHR R1 R15
  325. 0902002F # PUSHR R2 R15
  326. # ;; Initialize
  327. 09000510 # MOVE R1 R0
  328. # ;; Allocate another Node
  329. 0900040C # COPY R0 R12
  330. E1000FCC000c # ADDUI R12 R12 12
  331. # ;; Check if head->Next is null
  332. E10018210000 # LOAD32 R2 R1 0
  333. E000A0220000 # CMPSKIPI.E R2 0 ; If head->Next is something
  334. E10023020004 # STORE32 R0 R2 4 ; Set head->next->prev to p
  335. # ;; Setup p and head
  336. E10023200000 # STORE32 R2 R0 0 ; p->next = head->next
  337. E10023100004 # STORE32 R1 R0 4 ; p->prev = head
  338. E10023010000 # STORE32 R0 R1 0 ; head->next = p
  339. # ;; Restore Registers
  340. 0902802F # POPR R2 R15
  341. 0902801F # POPR R1 R15
  342. 0902800F # POPR R0 R15
  343. 0D01001F # RET R15
  344. # ;; InsertLine Function
  345. # ;; Receives a Node in R0
  346. # ;; Creates a new Node and prepends it
  347. # ;; Does not alter registers
  348. # ;; Returns to whatever called it
  349. :InsertLine
  350. # ;; Preserve Registers
  351. 0902000F # PUSHR R0 R15
  352. 0902001F # PUSHR R1 R15
  353. 0902002F # PUSHR R2 R15
  354. # ;; Initialize
  355. 09000510 # MOVE R1 R0
  356. # ;; Allocate another Node
  357. 0900040C # COPY R0 R12
  358. E1000FCC000c # ADDUI R12 R12 12
  359. # ;; Check if Head->Prev is Null
  360. E10018210004 # LOAD32 R2 R1 4
  361. E000A0220000 # CMPSKIPI.E R2 0 ; If head->prev is something
  362. E10023020000 # STORE32 R0 R2 0 ; Set head->prev->next to p
  363. # ;; Setup p and head
  364. E10023200004 # STORE32 R2 R0 4 ; p->prev = head->prev
  365. E10023100000 # STORE32 R1 R0 0 ; p->next = head
  366. E10023010004 # STORE32 R0 R1 4 ; head->prev = p
  367. # ;; Restore Registers
  368. 0902802F # POPR R2 R15
  369. 0902801F # POPR R1 R15
  370. 0902800F # POPR R0 R15
  371. 0D01001F # RET R15
  372. # ;; RemoveLine Function
  373. # ;; Receives Node in R0
  374. # ;; Returns replacement node in R0
  375. # ;; Returns to whatever called it
  376. :RemoveLine
  377. # ;; Preserve Registers
  378. 0902001F # PUSHR R1 R15
  379. 0902002F # PUSHR R2 R15
  380. # ;; Initialize
  381. 09000510 # MOVE R1 R0
  382. E10018010004 # LOAD32 R0 R1 4 ; put p->prev in R0
  383. E10018210000 # LOAD32 R2 R1 0 ; put p->next in R2
  384. # ;; Keep links
  385. E000A0200000 # CMPSKIPI.E R0 0 ; If p->prev is not null
  386. E10023200000 # STORE32 R2 R0 0 ; p->prev->next = p->next
  387. E000A0220000 # CMPSKIPI.E R2 0 ; If p->next is not null
  388. E10023020004 # STORE32 R0 R2 4 ; p->next->prev = p->prev
  389. # ;; Attempt to save what is left of the list
  390. E000A0300000 # CMPSKIPI.NE R0 0 ; If p->prev is null
  391. 09000502 # MOVE R0 R2 ; return p->next
  392. # ;; Restore Registers
  393. 0902802F # POPR R2 R15
  394. 0902801F # POPR R1 R15
  395. 0D01001F # RET R15
  396. # ;; Where our stack begins
  397. :stack