forth.s 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506
  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. ;; Memory Space
  17. ;; 0 -> 512KB code -> Heap space [Heap pointer with malloc function]
  18. ;; 512KB -> 576KB Stack space 1 (Return Stack) [Pointed at by R15]
  19. ;; 576KB -> 640KB Stack space 2 (Value Stack) [Pointed at by R14]
  20. ;; 640KB+ String Space
  21. ;;
  22. ;; DICTIONARY ENTRY (HEADER)
  23. ;; 0 -> Link (pointer to previous)
  24. ;; 4 -> Text (pointer to name string)
  25. ;; 8 -> Flags (Entry's flags)
  26. ;; 12+ -> Definition
  27. ;;
  28. ;; Other allocated registers
  29. ;; Next pointer [R13]
  30. ;; Current pointer [R12]
  31. ;; Address of NEXT [R11]
  32. ;; Forth STATE [R10]
  33. ;; Forth LATEST (Pointer to last defined function) [R9]
  34. ;; Forth HERE (Pointer to next free byte in HEAP) [R8]
  35. ;; IO source [R7]
  36. ;;
  37. ;; Constants to make note of:
  38. ;; F_IMMED 0x2
  39. ;; F_HIDDEN 0x1
  40. ;;
  41. ;; Modes to make note of:
  42. ;; COMPILING 0x1
  43. ;; INTERPRETING 0x0
  44. ;; Start function
  45. ;; Loads contents of tape_01
  46. ;; Starts interface until Halted
  47. :start
  48. HAL_MEM ; Get total amount of Memory
  49. LOADR R1 @MINIMAL_MEMORY ; Get our Minimal Value
  50. CMPSKIP.GE R0 R1 ; Check if we have enough
  51. JUMP @FAILED_INITIALIZATION ; If not fail gracefully
  52. LOADR R15 @RETURN_BASE ; Load Base of Return Stack
  53. LOADR R14 @PARAMETER_BASE ; Load Base of Parameter Stack
  54. LOADUI R11 $NEXT ; Get Address of Next
  55. FALSE R10 ; Current state is Interpreting
  56. LOADUI R9 $Interpret_Entry ; Get Address of last defined function
  57. LOADUI R8 $HEAP ; Get Address of HEAP
  58. LOADUI R0 0x1101 ; Need number to engage tape_02
  59. FOPEN_WRITE ; Load Tape_01 for Writing
  60. LOADUI R0 0x1100 ; Need number to engage tape_01
  61. FOPEN_READ ; Load Tape_01 for Reading
  62. MOVE R7 R0 ; Make Tape_01 Default IO
  63. LOADUI R13 $Cold_Start ; Intialize via QUIT
  64. JSR_COROUTINE R11 ; NEXT
  65. HALT ; If anything ever returns to here HALT
  66. :Cold_Start
  67. &Quit_Code
  68. :MINIMAL_MEMORY
  69. '00100000'
  70. :RETURN_BASE
  71. '00080000'
  72. :PARAMETER_BASE
  73. '00090000'
  74. :STRING_BASE
  75. '000A0000'
  76. ;; FAILED_INITIALIZATION
  77. :FAILED_INITIALIZATION
  78. FALSE R1 ; Set output to TTY
  79. LOADUI R2 $FAILED_STRING ; Prepare our Message
  80. CALLI R15 @PRINT_Direct ; Print it
  81. HALT ; Be done
  82. :FAILED_STRING
  83. "Please provide 1MB or More of Memory for this FORTH to run
  84. "
  85. ;; The last function you'll ever need to run
  86. ;; HALT
  87. :HALT_Text
  88. "HALT"
  89. :HALT_Entry
  90. NOP ; No previous link elements
  91. &HALT_Text ; Pointer to name
  92. NOP ; Flags
  93. &final_Cleanup ; Where the assembly is
  94. ;; EXIT function
  95. ;; Pops Return stack
  96. ;; And jumps to NEXT
  97. :EXIT_Text
  98. "EXIT"
  99. :EXIT_Entry
  100. &HALT_Entry ; Pointer to HALT
  101. &EXIT_Text ; Pointer to name
  102. NOP ; Flags
  103. &EXIT_Code ; Where the assembly is
  104. :EXIT_Code
  105. POPR R13 R15
  106. ;; NEXT function
  107. ;; increments to next instruction
  108. ;; Jumps to updated current
  109. ;; Affects only Next and current
  110. :NEXT
  111. COPY R12 R13 ; Preserve pointer
  112. ADDUI R13 R13 4 ; Increment Next
  113. LOAD R12 R12 0 ; Get contents pointed at by R12
  114. LOAD R0 R12 0 ; Get Code word target
  115. JSR_COROUTINE R0 ; Jump to Code word
  116. :DODOES
  117. ADDI R1 R12 4 ; Get Parameter Field Address
  118. PUSHR R1 R14 ; Put it on data stack
  119. LOAD R12 R12 0 ; Get location of the jump to this
  120. JUMP @DOCOL ; Go to the high-level forth
  121. ;; 'DODOES - gives the address of the
  122. ;; assembly for DODOES. We need that particular bit
  123. ;; of assembly to implement DOES>.
  124. :DODOES_ADDR_Text
  125. "'DODOES"
  126. :DODOES_ADDR_Entry
  127. &EXIT_Entry ; Pointer to EXIT
  128. &DODOES_ADDR_Text ; Pointer to name
  129. NOP ; Flags
  130. &DODOES_ADDR_Code ; Where assembly is stored
  131. :DODOES_ADDR_Code
  132. LOADUI R0 $DODOES ; Get address of DODOES
  133. PUSHR R0 R14 ; Put it on data stack
  134. JSR_COROUTINE R11 ; NEXT
  135. ;; DOCOL Function
  136. ;; The Interpreter for DO COLON
  137. ;; Jumps to NEXT
  138. :DOCOL
  139. PUSHR R13 R15 ; Push NEXT onto Return Stack
  140. ADDUI R13 R12 4 ; Update NEXT to point to the instruction after itself
  141. JUMP @NEXT ; Use NEXT
  142. ;; Some Forth primatives
  143. ;; Drop
  144. :Drop_Text
  145. "DROP"
  146. :Drop_Entry
  147. &DODOES_ADDR_Entry ; Pointer to 'DODOES
  148. &Drop_Text ; Pointer to Name
  149. NOP ; Flags
  150. &Drop_Code ; Where assembly is Stored
  151. :Drop_Code
  152. POPR R0 R14 ; Drop Top of stack
  153. JSR_COROUTINE R11 ; NEXT
  154. ;; SWAP
  155. :Swap_Text
  156. "SWAP"
  157. :Swap_Entry
  158. &Drop_Entry ; Pointer to Drop
  159. &Swap_Text ; Pointer to Name
  160. NOP ; Flags
  161. &Swap_Code ; Where assembly is Stored
  162. :Swap_Code
  163. POPR R0 R14
  164. POPR R1 R14
  165. PUSHR R0 R14
  166. PUSHR R1 R14
  167. JSR_COROUTINE R11 ; NEXT
  168. ;; DUP
  169. :Dup_Text
  170. "DUP"
  171. :Dup_Entry
  172. &Swap_Entry ; Pointer to Swap
  173. &Dup_Text ; Pointer to Name
  174. NOP ; Flags
  175. &Dup_Code ; Where assembly is Stored
  176. :Dup_Code
  177. LOAD R0 R14 -4 ; Get top of stack
  178. PUSHR R0 R14 ; Push copy onto it
  179. JSR_COROUTINE R11 ; NEXT
  180. ;; OVER
  181. :Over_Text
  182. "OVER"
  183. :Over_Entry
  184. &Dup_Entry ; Pointer to DUP
  185. &Over_Text ; Pointer to Name
  186. NOP ; Flags
  187. &Over_Code ; Where assembly is Stored
  188. :Over_Code
  189. LOAD R0 R14 -8 ; Get second from Top of stack
  190. PUSHR R0 R14 ; Push it onto top of stack
  191. JSR_COROUTINE R11 ; NEXT
  192. ;; ROT
  193. :Rot_Text
  194. "ROT"
  195. :Rot_Entry
  196. &Over_Entry ; Pointer to Over
  197. &Rot_Text ; Pointer to Name
  198. NOP ; Flags
  199. &Rot_Code ; Where assembly is Stored
  200. :Rot_Code
  201. POPR R0 R14
  202. POPR R1 R14
  203. POPR R2 R14
  204. PUSHR R1 R14
  205. PUSHR R0 R14
  206. PUSHR R2 R14
  207. JSR_COROUTINE R11 ; NEXT
  208. ;; -ROT
  209. :-Rot_Text
  210. "-ROT"
  211. :-Rot_Entry
  212. &Rot_Entry ; Pointer to ROT
  213. &-Rot_Text ; Pointer to Name
  214. NOP ; Flags
  215. &-Rot_Code ; Where assembly is Stored
  216. :-Rot_Code
  217. POPR R0 R14
  218. POPR R1 R14
  219. POPR R2 R14
  220. PUSHR R0 R14
  221. PUSHR R2 R14
  222. PUSHR R1 R14
  223. JSR_COROUTINE R11 ; NEXT
  224. ;; 2DROP
  225. :2Drop_Text
  226. "2DROP"
  227. :2Drop_Entry
  228. &-Rot_Entry ; Pointer to -ROT
  229. &2Drop_Text ; Pointer to Name
  230. NOP ; Flags
  231. &2Drop_Code ; Where assembly is Stored
  232. :2Drop_Code
  233. POPR R0 R14
  234. POPR R0 R14
  235. JSR_COROUTINE R11 ; NEXT
  236. ;; 2DUP
  237. :2Dup_Text
  238. "2DUP"
  239. :2Dup_Entry
  240. &2Drop_Entry ; Pointer to 2Drop
  241. &2Dup_Text ; Pointer to Name
  242. NOP ; Flags
  243. &2Dup_Code ; Where assembly is Stored
  244. :2Dup_Code
  245. LOAD R0 R14 -4 ; Get top of stack
  246. LOAD R1 R14 -8 ; Get second on stack
  247. PUSHR R1 R14
  248. PUSHR R0 R14
  249. JSR_COROUTINE R11 ; NEXT
  250. ;; 2SWAP
  251. :2Swap_Text
  252. "2Swap"
  253. :2Swap_Entry
  254. &2Dup_Entry ; Pointer to 2Dup
  255. &2Swap_Text ; Pointer to Name
  256. NOP ; Flags
  257. &2Swap_Code ; Where assembly is Stored
  258. :2Swap_Code
  259. POPR R0 R14
  260. POPR R1 R14
  261. POPR R2 R14
  262. POPR R3 R14
  263. PUSHR R1 R14
  264. PUSHR R0 R14
  265. PUSHR R3 R14
  266. PUSHR R2 R14
  267. JSR_COROUTINE R11 ; NEXT
  268. ;; ?DUP
  269. :QDup_Text
  270. "?DUP"
  271. :QDup_Entry
  272. &2Swap_Entry ; Pointer to 2Swap
  273. &QDup_Text ; Pointer to Name
  274. NOP ; Flags
  275. &QDup_Code ; Where assembly is Stored
  276. :QDup_Code
  277. LOAD R0 R14 -4 ; Get Top of stack
  278. CMPSKIPI.E R0 0 ; Skip if Zero
  279. PUSHR R0 R14 ; Duplicate value
  280. JSR_COROUTINE R11 ; NEXT
  281. ;; +
  282. :Add_Text
  283. "+"
  284. :Add_Entry
  285. &QDup_Entry ; Pointer to ?Dup
  286. &Add_Text ; Pointer to Name
  287. NOP ; Flags
  288. &Add_Code ; Where assembly is Stored
  289. :Add_Code
  290. POPR R0 R14 ; Get top of stack
  291. POPR R1 R14 ; Get second item on Stack
  292. ADD R0 R0 R1 ; Perform the addition
  293. PUSHR R0 R14 ; Store the result
  294. JSR_COROUTINE R11 ; NEXT
  295. ;; -
  296. :Sub_Text
  297. "-"
  298. :Sub_Entry
  299. &Add_Entry ; Pointer to +
  300. &Sub_Text ; Pointer to Name
  301. NOP ; Flags
  302. &Sub_Code ; Where assembly is Stored
  303. :Sub_Code
  304. POPR R0 R14 ; Get top of stack
  305. POPR R1 R14 ; Get second item on Stack
  306. SUB R0 R1 R0 ; Perform the subtraction
  307. PUSHR R0 R14 ; Store the result
  308. JSR_COROUTINE R11 ; NEXT
  309. ;; MUL
  310. :MUL_Text
  311. "*"
  312. :MUL_Entry
  313. &Sub_Entry ; Pointer to -
  314. &MUL_Text ; Pointer to Name
  315. NOP ; Flags
  316. &MUL_Code ; Where assembly is Stored
  317. :MUL_Code
  318. POPR R0 R14 ; Get top of stack
  319. POPR R1 R14 ; Get second item on Stack
  320. MUL R0 R0 R1 ; Perform the multiplication and keep bottom half
  321. PUSHR R0 R14 ; Store the result
  322. JSR_COROUTINE R11 ; NEXT
  323. ;; MULH
  324. :MULH_Text
  325. "MULH"
  326. :MULH_Entry
  327. &MUL_Entry ; Pointer to *
  328. &MULH_Text ; Pointer to Name
  329. NOP ; Flags
  330. &MULH_Code ; Where assembly is Stored
  331. :MULH_Code
  332. POPR R0 R14 ; Get top of stack
  333. POPR R1 R14 ; Get second item on Stack
  334. MULH R0 R0 R1 ; Perform multiplcation and keep top half
  335. PUSHR R0 R14 ; Store the result
  336. JSR_COROUTINE R11 ; NEXT
  337. ;; /
  338. :DIV_Text
  339. "/"
  340. :DIV_Entry
  341. &MULH_Entry ; Pointer to MULH
  342. &DIV_Text ; Pointer to Name
  343. NOP ; Flags
  344. &DIV_Code ; Where assembly is Stored
  345. :DIV_Code
  346. POPR R0 R14 ; Get top of stack
  347. POPR R1 R14 ; Get second item on Stack
  348. DIV R0 R1 R0 ; Perform division and keep top half
  349. PUSHR R0 R14 ; Store the result
  350. JSR_COROUTINE R11 ; NEXT
  351. ;; %
  352. :MOD_Text
  353. "%"
  354. :MOD_Entry
  355. &DIV_Entry ; Pointer to /
  356. &MOD_Text ; Pointer to Name
  357. NOP ; Flags
  358. &MOD_Code ; Where assembly is Stored
  359. :MOD_Code
  360. POPR R0 R14 ; Get top of stack
  361. POPR R1 R14 ; Get second item on Stack
  362. MOD R0 R1 R0 ; Perform division and keep remainder
  363. PUSHR R0 R14 ; Store the result
  364. JSR_COROUTINE R11 ; NEXT
  365. :LSHIFT_Text
  366. "LSHIFT"
  367. :LSHIFT_Entry
  368. &MOD_Entry ; Pointer to %
  369. &LSHIFT_Text ; Pointer to Name
  370. NOP ; Flags
  371. &LSHIFT_Code ; Where assembly is Stored
  372. :LSHIFT_Code
  373. POPR R0 R14 ; Get top of stack
  374. POPR R1 R14 ; Get second item on Stack
  375. SAL R0 R1 R0 ; Left Shift
  376. PUSHR R0 R14 ; Store the result
  377. JSR_COROUTINE R11 ; NEXT
  378. :RSHIFT_Text
  379. "RSHIFT"
  380. :RSHIFT_Entry
  381. &LSHIFT_Entry ; Pointer to LSHIFT
  382. &RSHIFT_Text ; Pointer to Name
  383. NOP ; Flags
  384. &RSHIFT_Code ; Where assembly is Stored
  385. :RSHIFT_Code
  386. POPR R0 R14 ; Get top of stack
  387. POPR R1 R14 ; Get second item on Stack
  388. SAR R0 R1 R0 ; Left Shift
  389. PUSHR R0 R14 ; Store the result
  390. JSR_COROUTINE R11 ; NEXT
  391. ;; =
  392. :Equal_Text
  393. "="
  394. :Equal_Entry
  395. &RSHIFT_Entry ; Pointer to RSHIFT
  396. &Equal_Text ; Pointer to Name
  397. NOP ; Flags
  398. &Equal_Code ; Where assembly is Stored
  399. :Equal_Code
  400. POPR R2 R14 ; Get top of stack
  401. POPR R1 R14 ; Get second item on Stack
  402. TRUE R0 ; Assume comparision is True
  403. CMPSKIP.E R1 R2 ; Check if they are equal and skip if they are
  404. FALSE R0 ; Looks like our assumption was wrong
  405. PUSHR R0 R14 ; Store the result
  406. JSR_COROUTINE R11 ; NEXT
  407. ;; !=
  408. :NEqual_Text
  409. "!="
  410. :NEqual_Entry
  411. &Equal_Entry ; Pointer to =
  412. &NEqual_Text ; Pointer to Name
  413. NOP ; Flags
  414. &NEqual_Code ; Where assembly is Stored
  415. :NEqual_Code
  416. POPR R2 R14 ; Get top of stack
  417. POPR R1 R14 ; Get second item on Stack
  418. TRUE R0 ; Assume comparision is True
  419. CMPSKIP.NE R1 R2 ; Check if they are not equal and skip if they are
  420. FALSE R0 ; Looks like our assumption was wrong
  421. PUSHR R0 R14 ; Store the result
  422. JSR_COROUTINE R11 ; NEXT
  423. ;; <
  424. :Less_Text
  425. "<"
  426. :Less_Entry
  427. &NEqual_Entry ; Pointer to !=
  428. &Less_Text ; Pointer to Name
  429. NOP ; Flags
  430. &Less_Code ; Where assembly is Stored
  431. :Less_Code
  432. POPR R2 R14 ; Get top of stack
  433. POPR R1 R14 ; Get second item on Stack
  434. TRUE R0 ; Assume comparision is True
  435. CMPSKIP.L R1 R2 ; Check if less than and skip if they are
  436. FALSE R0 ; Looks like our assumption was wrong
  437. PUSHR R0 R14 ; Store the result
  438. JSR_COROUTINE R11 ; NEXT
  439. ;; <=
  440. :LEqual_Text
  441. "<="
  442. :LEqual_Entry
  443. &Less_Entry ; Pointer to <
  444. &LEqual_Text ; Pointer to Name
  445. NOP ; Flags
  446. &LEqual_Code ; Where assembly is Stored
  447. :LEqual_Code
  448. POPR R2 R14 ; Get top of stack
  449. POPR R1 R14 ; Get second item on Stack
  450. TRUE R0 ; Assume comparision is True
  451. CMPSKIP.LE R1 R2 ; Check if they are less than or equal and skip if they are
  452. FALSE R0 ; Looks like our assumption was wrong
  453. PUSHR R0 R14 ; Store the result
  454. JSR_COROUTINE R11 ; NEXT
  455. ;; >
  456. :Greater_Text
  457. ">"
  458. :Greater_Entry
  459. &LEqual_Entry ; Pointer to <=
  460. &Greater_Text ; Pointer to Name
  461. NOP ; Flags
  462. &Greater_Code ; Where assembly is Stored
  463. :Greater_Code
  464. POPR R2 R14 ; Get top of stack
  465. POPR R1 R14 ; Get second item on Stack
  466. TRUE R0 ; Assume comparision is True
  467. CMPSKIP.G R1 R2 ; Check if greater and skip if they are
  468. FALSE R0 ; Looks like our assumption was wrong
  469. PUSHR R0 R14 ; Store the result
  470. JSR_COROUTINE R11 ; NEXT
  471. ;; >=
  472. :GEqual_Text
  473. ">="
  474. :GEqual_Entry
  475. &Greater_Entry ; Pointer to >
  476. &GEqual_Text ; Pointer to Name
  477. NOP ; Flags
  478. &GEqual_Code ; Where assembly is Stored
  479. :GEqual_Code
  480. POPR R2 R14 ; Get top of stack
  481. POPR R1 R14 ; Get second item on Stack
  482. TRUE R0 ; Assume comparision is True
  483. CMPSKIP.GE R1 R2 ; Check if they are equal and skip if they are
  484. FALSE R0 ; Looks like our assumption was wrong
  485. PUSHR R0 R14 ; Store the result
  486. JSR_COROUTINE R11 ; NEXT
  487. ;; AND
  488. :AND_Text
  489. "AND"
  490. :AND_Entry
  491. &GEqual_Entry ; Pointer to >=
  492. &AND_Text ; Pointer to Name
  493. NOP ; Flags
  494. &AND_Code ; Where assembly is Stored
  495. :AND_Code
  496. POPR R0 R14 ; Get top of stack
  497. POPR R1 R14 ; Get second item on Stack
  498. AND R0 R0 R1 ; Perform AND
  499. PUSHR R0 R14 ; Store the result
  500. JSR_COROUTINE R11 ; NEXT
  501. ;; OR
  502. :OR_Text
  503. "OR"
  504. :OR_Entry
  505. &AND_Entry ; Pointer to AND
  506. &OR_Text ; Pointer to Name
  507. NOP ; Flags
  508. &OR_Code ; Where assembly is Stored
  509. :OR_Code
  510. POPR R0 R14 ; Get top of stack
  511. POPR R1 R14 ; Get second item on Stack
  512. OR R0 R0 R1 ; Perform OR
  513. PUSHR R0 R14 ; Store the result
  514. JSR_COROUTINE R11 ; NEXT
  515. ;; XOR
  516. :XOR_Text
  517. "XOR"
  518. :XOR_Entry
  519. &OR_Entry ; Pointer to OR
  520. &XOR_Text ; Pointer to Name
  521. NOP ; Flags
  522. &XOR_Code ; Where assembly is Stored
  523. :XOR_Code
  524. POPR R0 R14 ; Get top of stack
  525. POPR R1 R14 ; Get second item on Stack
  526. XOR R0 R0 R1 ; Perform XOR
  527. PUSHR R0 R14 ; Store the result
  528. JSR_COROUTINE R11 ; NEXT
  529. ;; NOT
  530. :NOT_Text
  531. "NOT"
  532. :NOT_Entry
  533. &XOR_Entry ; Pointer to XOR
  534. &NOT_Text ; Pointer to Name
  535. NOP ; Flags
  536. &NOT_Code ; Where assembly is Stored
  537. :NOT_Code
  538. POPR R0 R14 ; Get top of stack
  539. NOT R0 R0 ; Bit flip it
  540. PUSHR R0 R14 ; Store it back onto stack
  541. JSR_COROUTINE R11 ; NEXT
  542. ;; LIT
  543. :LIT_Text
  544. "LIT"
  545. :LIT_Entry
  546. &NOT_Entry ; Pointer to NOT
  547. &LIT_Text ; Pointer to Name
  548. NOP ; Flags
  549. &LIT_Code ; Where assembly is Stored
  550. :LIT_Code
  551. LOAD R0 R13 0 ; Get contents of NEXT
  552. ADDUI R13 R13 4 ; Increment NEXT
  553. PUSHR R0 R14 ; Put immediate onto stack
  554. JSR_COROUTINE R11 ; NEXT
  555. ;; Memory manipulation instructions
  556. ;; STORE
  557. :Store_Text
  558. "!"
  559. :Store_Entry
  560. &LIT_Entry ; Pointer to LIT
  561. &Store_Text ; Pointer to Name
  562. NOP ; Flags
  563. &Store_Code ; Where assembly is Stored
  564. :Store_Code
  565. POPR R0 R14 ; Destination
  566. POPR R1 R14 ; Contents
  567. STORE R1 R0 0 ; Write out
  568. JSR_COROUTINE R11 ; NEXT
  569. ;; FETCH
  570. :Fetch_Text
  571. "@"
  572. :Fetch_Entry
  573. &Store_Entry ; Pointer to Store
  574. &Fetch_Text ; Pointer to Name
  575. NOP ; Flags
  576. &Fetch_Code ; Where assembly is Stored
  577. :Fetch_Code
  578. POPR R0 R14 ; Source address
  579. LOAD R0 R0 0 ; Get Contents
  580. PUSHR R0 R14 ; Push Contents
  581. JSR_COROUTINE R11 ; NEXT
  582. ;; ADDSTORE
  583. :AStore_Text
  584. "+!"
  585. :AStore_Entry
  586. &Fetch_Entry ; Pointer to Fetch
  587. &AStore_Text ; Pointer to Name
  588. NOP ; Flags
  589. &AStore_Code ; Where assembly is Stored
  590. :AStore_Code
  591. POPR R0 R14 ; Destination
  592. POPR R1 R14 ; How much to add
  593. LOAD R2 R0 0 ; Get contents of address
  594. ADD R1 R1 R2 ; Combine
  595. STORE R1 R0 0 ; Write out
  596. JSR_COROUTINE R11 ; NEXT
  597. ;; SUBSTORE
  598. :SStore_Text
  599. "-!"
  600. :SStore_Entry
  601. &AStore_Entry ; Pointer to ADDSTORE
  602. &SStore_Text ; Pointer to Name
  603. NOP ; Flags
  604. &SStore_Code ; Where assembly is Stored
  605. :SStore_Code
  606. POPR R0 R14 ; Destination
  607. POPR R1 R14 ; How much to sub
  608. LOAD R2 R0 0 ; Get contents of address
  609. SUB R1 R2 R1 ; Subtract
  610. STORE R1 R0 0 ; Write out
  611. JSR_COROUTINE R11 ; NEXT
  612. ;; STOREBYTE
  613. :SByte_Text
  614. "C!"
  615. :SByte_Entry
  616. &SStore_Entry ; Pointer to SUBSTORE
  617. &SByte_Text ; Pointer to Name
  618. NOP ; Flags
  619. &SByte_Code ; Where assembly is Stored
  620. :SByte_Code
  621. POPR R0 R14 ; Destination
  622. POPR R1 R14 ; Contents
  623. STORE8 R1 R0 0 ; Write out
  624. JSR_COROUTINE R11 ; NEXT
  625. ;; FETCHBYTE
  626. :FByte_Text
  627. "C@"
  628. :FByte_Entry
  629. &SByte_Entry ; Pointer to STOREBYTE
  630. &FByte_Text ; Pointer to Name
  631. NOP ; Flags
  632. &FByte_Code ; Where assembly is Stored
  633. :FByte_Code
  634. POPR R0 R14 ; Source address
  635. LOADU8 R0 R0 0 ; Get Contents
  636. PUSHR R0 R14 ; Push Contents
  637. JSR_COROUTINE R11 ; NEXT
  638. ;; CMOVE
  639. :CMove_Text
  640. "CMOVE"
  641. :CMove_Entry
  642. &FByte_Entry ; Pointer to FETCHBYTE
  643. &CMove_Text ; Pointer to Name
  644. NOP ; Flags
  645. &CMove_Code ; Where assembly is Stored
  646. :CMove_Code
  647. POPR R0 R14 ; Get number of bytes to Move
  648. POPR R1 R14 ; Where to put the result
  649. POPR R2 R14 ; Where it is coming from
  650. :Cmove_Main
  651. CMPSKIPI.GE R0 4 ; Loop if we have 4 or more bytes to move
  652. JUMP @Cmove_Slow ; Otherwise slowly move bytes
  653. LOAD R3 R2 0 ; Get 4 Bytes
  654. STORE R3 R1 0 ; Store them at the destination
  655. ADDUI R1 R1 4 ; Increment Source by 4
  656. ADDUI R2 R2 4 ; Increment Destination by 4
  657. SUBI R0 R0 4 ; Decrement number of bytes to move by 4
  658. JUMP @Cmove_Main ; Loop more
  659. :Cmove_Slow
  660. CMPSKIPI.G R0 0 ; While number of bytes is greater than 0
  661. JUMP @Cmove_Done ; Otherwise be done
  662. LOADU8 R3 R2 0 ; Get 4 Bytes
  663. STORE8 R3 R1 0 ; Store them at the destination
  664. ADDUI R1 R1 1 ; Increment Source by 1
  665. ADDUI R2 R2 1 ; Increment Destination by 1
  666. SUBI R0 R0 1 ; Decrement number of bytes to move by 1
  667. JUMP @Cmove_Slow ; Loop more
  668. :Cmove_Done
  669. JSR_COROUTINE R11 ; NEXT
  670. ;; Global variables
  671. ;; STATE
  672. :State_Text
  673. "STATE"
  674. :State_Entry
  675. &CMove_Entry ; Pointer to CMOVE
  676. &State_Text ; Pointer to Name
  677. NOP ; Flags
  678. &State_Code ; Where assembly is Stored
  679. :State_Code
  680. PUSHR R10 R14 ; Put STATE onto stack
  681. JSR_COROUTINE R11 ; NEXT
  682. ;; LATEST
  683. :Latest_Text
  684. "LATEST"
  685. :Latest_Entry
  686. &State_Entry ; Pointer to STATE
  687. &Latest_Text ; Pointer to Name
  688. NOP ; Flags
  689. &Latest_Code ; Where assembly is Stored
  690. :Latest_Code
  691. PUSHR R9 R14 ; Put LATEST onto stack
  692. JSR_COROUTINE R11 ; NEXT
  693. ;; LATEST!
  694. :SetLatest_Text
  695. "LATEST!"
  696. :SetLatest_Entry
  697. &Latest_Entry ; Pointer to LATEST
  698. &SetLatest_Text ; Pointer to Name
  699. NOP ; Flags
  700. &SetLatest_Code ; Where assembly is stored
  701. :SetLatest_Code
  702. POPR R9 R14 ; Set LATEST from stack
  703. JSR_COROUTINE R11 ; NEXT
  704. ;; HERE
  705. :Here_Text
  706. "HERE"
  707. :Here_Entry
  708. &SetLatest_Entry ; Pointer to LATEST!
  709. &Here_Text ; Pointer to Name
  710. NOP ; Flags
  711. &Here_Code ; Where assembly is Stored
  712. :Here_Code
  713. PUSHR R8 R14 ; Put HERE onto stack
  714. JSR_COROUTINE R11 ; NEXT
  715. ;; UPDATE_HERE
  716. :Update_Here_Text
  717. "DP!"
  718. :Update_Here_Entry
  719. &Here_Entry ; Pointer to HERE
  720. &Update_Here_Text ; Pointer to Name
  721. NOP ; Flags
  722. &Update_Here_Code ; Where assembly is Stored
  723. :Update_Here_Code
  724. POPR R8 R14 ; Pop STACK onto HERE
  725. JSR_COROUTINE R11 ; NEXT
  726. ;; Return Stack functions
  727. ;; >R
  728. :TOR_Text
  729. ">R"
  730. :TOR_Entry
  731. &Update_Here_Entry ; Pointer to UPDATE_HERE
  732. &TOR_Text ; Pointer to Name
  733. NOP ; Flags
  734. &TOR_Code ; Where assembly is Stored
  735. :TOR_Code
  736. POPR R0 R14 ; Get top of Parameter stack
  737. PUSHR R0 R15 ; Shove it onto return stack
  738. JSR_COROUTINE R11 ; NEXT
  739. ;; R@
  740. :COPYR_Text
  741. "R@"
  742. :COPYR_Entry
  743. &TOR_Entry ; Pointer to >R
  744. &COPYR_Text ; Pointer to Name
  745. NOP ; Flags
  746. &COPYR_Code ; Where assembly is stored
  747. :COPYR_Code
  748. LOAD R0 R15 -4 ; Get top of return stack
  749. PUSHR R0 R14 ; Put it on data stack
  750. JSR_COROUTINE R11 ; NEXT
  751. ;; R>
  752. :FROMR_Text
  753. "R>"
  754. :FROMR_Entry
  755. &COPYR_Entry ; Pointer to >R
  756. &FROMR_Text ; Pointer to Name
  757. NOP ; Flags
  758. &FROMR_Code ; Where assembly is Stored
  759. :FROMR_Code
  760. POPR R0 R15 ; Get top of Return stack
  761. PUSHR R0 R14 ; Shove it onto parameter stack
  762. JSR_COROUTINE R11 ; NEXT
  763. ;; RSP@
  764. :RSPFetch_Text
  765. "RSP@"
  766. :RSPFetch_Entry
  767. &FROMR_Entry ; Pointer to R>
  768. &RSPFetch_Text ; Pointer to Name
  769. NOP ; Flags
  770. &RSPFetch_Code ; Where assembly is Stored
  771. :RSPFetch_Code
  772. PUSHR R14 R15 ; Push Return stack pointer onto Parameter stack
  773. JSR_COROUTINE R11 ; NEXT
  774. ;; RSP!
  775. :RSPStore_Text
  776. "RSP!"
  777. :RSPStore_Entry
  778. &RSPFetch_Entry ; Pointer to RSP@
  779. &RSPStore_Text ; Pointer to Name
  780. NOP ; Flags
  781. &RSPStore_Code ; Where assembly is Stored
  782. :RSPStore_Code
  783. POPR R15 R14 ; Replace Return stack pointer from parameter stack
  784. JSR_COROUTINE R11 ; NEXT
  785. ;; Clear out the return stack
  786. :RETURN_CLEAR
  787. &RETURN_CODE
  788. :RETURN_CODE
  789. LOADR R1 @RETURN_BASE ; Get Base of Return Stack
  790. CMPJUMPI.LE R15 R1 @RETURN_Done ; If Return stack is empty skip clearing
  791. :Clear_Return
  792. POPR R0 R15 ; Remove entry from Return Stack
  793. CMPSKIP.LE R15 R1 ; While Return stack isn't empty
  794. JUMP @Clear_Return ; Keep looping to clear it out
  795. :RETURN_Done
  796. MOVE R15 R1 ; Ensure underflow is corrected
  797. JSR_COROUTINE R11 ; NEXT
  798. ;; Parameter stack operations
  799. ;; DSP@
  800. :DSPFetch_Text
  801. "DSP@"
  802. :DSPFetch_Entry
  803. &RSPStore_Entry ; Pointer to RSP!
  804. &DSPFetch_Text ; Pointer to Name
  805. NOP ; Flags
  806. &DSPFetch_Code ; Where assembly is Stored
  807. :DSPFetch_Code
  808. PUSHR R14 R14 ; Push current parameter pointer onto parameter stack
  809. JSR_COROUTINE R11 ; NEXT
  810. ;; DSP!
  811. :DSPStore_Text
  812. "DSP!"
  813. :DSPStore_Entry
  814. &DSPFetch_Entry ; Pointer to DSP@
  815. &DSPStore_Text ; Pointer to Name
  816. NOP ; Flags
  817. &DSPStore_Code ; Where assembly is Stored
  818. :DSPStore_Code
  819. POPR R14 R14 ; Replace parameter stack pointer from parameter stack
  820. JSR_COROUTINE R11 ; NEXT
  821. ;; Input and output
  822. ;; KEY
  823. :Key_Text
  824. "KEY"
  825. :Key_Entry
  826. &DSPStore_Entry ; Pointer to DSP!
  827. &Key_Text ; Pointer to Name
  828. NOP ; Flags
  829. &Key_Code ; Where assembly is Stored
  830. :Key_Code
  831. COPY R1 R7 ; Using designated IO
  832. FGETC ; Get a byte
  833. CMPSKIPI.NE R0 13 ; If Carriage return
  834. LOADUI R0 10 ; Replace with Line Feed
  835. CMPSKIPI.NE R1 0 ; If not TTY
  836. FPUTC ; Skip Echoing
  837. PUSHR R0 R14 ; And push it onto the stack
  838. JSR_COROUTINE R11 ; NEXT
  839. ;; EMIT
  840. :Emit_Text
  841. "EMIT"
  842. :Emit_Entry
  843. &Key_Entry ; Pointer to Key
  844. &Emit_Text ; Pointer to Name
  845. NOP ; Flags
  846. &Emit_Code ; Where assembly is Stored
  847. :Emit_Code
  848. POPR R0 R14 ; Get value off the parameter stack
  849. ANDI R0 R0 0xFF ; Ensure only bottom Byte
  850. FALSE R1 ; Write out only to TTY
  851. FPUTC ; Write out the byte
  852. JSR_COROUTINE R11 ; NEXT
  853. ;; WRITE8
  854. :WRITE8_Text
  855. "WRITE8"
  856. :WRITE8_Entry
  857. &Emit_Entry ; Pointer to EMIT
  858. &WRITE8_Text ; Pointer to Name
  859. NOP ; Flags
  860. &WRITE8_Code ; Where assembly is Stored
  861. :WRITE8_Code
  862. POPR R0 R14 ; Get value off the parameter stack
  863. ANDI R0 R0 0xFF ; Ensure only bottom Byte
  864. LOADUI R1 0x1101 ; Write out only to TAPE_02
  865. FPUTC ; Write out the byte
  866. JSR_COROUTINE R11 ; NEXT
  867. ;; WORD
  868. :Word_Text
  869. "WORD"
  870. :Word_Entry
  871. &WRITE8_Entry ; Pointer to WRITE8
  872. &Word_Text ; Pointer to Name
  873. NOP ; Flags
  874. &Word_Code ; Where assembly is Stored
  875. :Word_Code
  876. CALLI R15 @Word_Direct ; Trick for direct calls
  877. JSR_COROUTINE R11 ; NEXT
  878. :Word_Direct
  879. COPY R1 R7 ; Using designated IO
  880. FALSE R2 ; Starting at index 0
  881. LOADR R4 @STRING_BASE ; Use the STRING_BASE instead
  882. :Word_Start
  883. FGETC ; Read a byte
  884. CMPSKIPI.NE R0 13 ; If Carriage return
  885. LOADUI R0 10 ; Convert to linefeed
  886. CMPSKIPI.NE R1 0 ; Don't output unless TTY
  887. FPUTC ; Make it visible
  888. CMPSKIPI.NE R0 9 ; If Tab
  889. JUMP @Word_Start ; Get another byte
  890. CMPSKIPI.NE R0 32 ; If space
  891. JUMP @Word_Start ; Get another byte
  892. CMPSKIPI.NE R0 10 ; If Newline
  893. JUMP @Word_Start ; Get another byte
  894. :Word_Main
  895. CMPSKIPI.NE R0 4 ; If EOF
  896. JUMP @cold_done ; Stop processing
  897. CMPSKIPI.G R0 0 ; If ERROR
  898. JUMP @cold_done ; Stop processing
  899. CMPSKIPI.NE R0 9 ; If Tab
  900. JUMP @Word_Done ; Be done
  901. CMPSKIPI.NE R0 10 ; If LF
  902. JUMP @Word_Done ; Be done
  903. CMPSKIPI.NE R0 32 ; If space
  904. JUMP @Word_Done ; Be done
  905. CMPSKIPI.NE R0 92 ; If comment
  906. JUMP @Word_Comment ; Purge it and be done
  907. STOREX8 R0 R4 R2 ; Store byte onto HEAP
  908. ADDUI R2 R2 1 ; Increment index
  909. FGETC ; Read a byte
  910. CMPSKIPI.NE R0 13 ; IF CR
  911. LOADUI R0 10 ; Convert to LF
  912. CMPSKIPI.NE R1 0 ; Don't output unless TTY
  913. FPUTC ; Make it visible
  914. JUMP @Word_Main ; Keep looping
  915. :Word_Comment
  916. FGETC ; Get another byte
  917. CMPSKIPI.NE R0 13 ; If CR
  918. LOADUI R0 10 ; Convert to LF
  919. CMPSKIPI.NE R1 0 ; Don't output unless TTY
  920. FPUTC ; Make it visible
  921. CMPSKIPI.NE R0 4 ; IF EOF
  922. JUMP @Word_Done ; Be done
  923. CMPSKIPI.G R0 0 ; If ERROR
  924. JUMP @cold_done ; Stop processing
  925. CMPSKIPI.NE R0 10 ; IF Line Feed
  926. JUMP @Word_Done ; Be done
  927. JUMP @Word_Comment ; Otherwise keep looping
  928. :Word_Done
  929. PUSHR R4 R14 ; Push pointer to string on parameter stack
  930. PUSHR R2 R14 ; Push number of bytes in length onto stack
  931. ADDUI R2 R2 4 ; Add a null to end of string
  932. ANDI R2 R2 -4 ; Rounded up the next for or to Zero
  933. ADD R4 R4 R2 ; Update pointer
  934. STORER R4 @STRING_BASE ; Save its value
  935. RET R15
  936. ;; NUMBER
  937. :Number_Text
  938. "NUMBER"
  939. :Number_Entry
  940. &Word_Entry ; Pointer to Word
  941. &Number_Text ; Pointer to Name
  942. NOP ; Flags
  943. &Number_Code ; Where assembly is Stored
  944. :Number_Code
  945. CALLI R15 @Number_Direct ; Trick for direct access
  946. JSR_COROUTINE R11 ; NEXT
  947. :Number_Direct
  948. POPR R1 R14 ; Get pointer to string for parsing
  949. FALSE R2 ; Set Negate flag to false
  950. FALSE R3 ; Set index to Zero
  951. LOAD8 R0 R1 1 ; Get second byte
  952. CMPSKIPI.NE R0 120 ; If the second byte is x
  953. JUMP @numerate_string_hex ; treat string like hex
  954. ;; Deal with Decimal input
  955. LOADUI R4 10 ; Multiply by 10
  956. LOAD8 R0 R1 0 ; Get a byte
  957. CMPSKIPI.NE R0 45 ; If - toggle flag
  958. TRUE R2 ; So that we know to negate
  959. CMPSKIPI.E R2 0 ; If toggled
  960. ADDUI R1 R1 1 ; Move to next
  961. :numerate_string_dec
  962. LOAD8 R0 R1 0 ; Get a byte
  963. CMPSKIPI.NE R0 0 ; If NULL
  964. JUMP @numerate_string_done ; Be done
  965. MUL R3 R3 R4 ; Shift counter by 10
  966. SUBI R0 R0 48 ; Convert ascii to number
  967. CMPSKIPI.GE R0 0 ; If less than a number
  968. JUMP @ABORT_Code ; Dealing with an undefined symbol
  969. CMPSKIPI.L R0 10 ; If more than a number
  970. JUMP @ABORT_Code ; Dealing with an undefined symbol
  971. ADDU R3 R3 R0 ; Don't add to the count
  972. ADDUI R1 R1 1 ; Move onto next byte
  973. JUMP @numerate_string_dec
  974. ;; Deal with Hex input
  975. :numerate_string_hex
  976. LOADU8 R0 R1 0 ; Get a byte
  977. CMPSKIPI.E R0 48 ; All hex strings start with 0x
  978. JUMP @numerate_string_done ; Be done if not a match
  979. ADDUI R1 R1 2 ; Move to after leading 0x
  980. :numerate_string_hex_0
  981. LOAD8 R0 R1 0 ; Get a byte
  982. CMPSKIPI.NE R0 0 ; If NULL
  983. JUMP @numerate_string_done ; Be done
  984. SL0I R3 4 ; Shift counter by 16
  985. SUBI R0 R0 48 ; Convert ascii number to number
  986. CMPSKIPI.L R0 10 ; If A-F
  987. SUBI R0 R0 7 ; Shove into Range
  988. CMPSKIPI.L R0 16 ; If a-f
  989. SUBI R0 R0 32 ; Shove into Range
  990. ADDU R3 R3 R0 ; Add to the count
  991. ADDUI R1 R1 1 ; Get next Hex
  992. JUMP @numerate_string_hex_0
  993. :numerate_string_done
  994. CMPSKIPI.E R2 0 ; If Negate flag has been set
  995. NEG R3 R3 ; Make the number negative
  996. PUSHR R3 R14 ; Store result
  997. RET R15 ; Return to whoever called it
  998. ;; ABORT
  999. :ABORT_Text
  1000. "ABORT"
  1001. :ABORT_Entry
  1002. &Number_Entry ; Pointer to NUMBER
  1003. &ABORT_Text ; Pointer to Name
  1004. NOP ; Flags
  1005. &ABORT_Code ; Where assembly is Stored
  1006. :ABORT_Code
  1007. MOVE R2 R1 ; Protect the string pointer and set output to TTY
  1008. CALLI R15 @PRINT_Direct ; Print our unknown
  1009. LOADUI R2 $ABORT_String ; Get our string
  1010. CALLI R15 @PRINT_Direct ; Print it
  1011. LOADUI R0 10 ; NEWLINE
  1012. FPUTC ; Printed
  1013. LOADR R15 @RETURN_BASE ; Load Base of Return Stack
  1014. LOADR R14 @PARAMETER_BASE ; Load Base of Parameter Stack
  1015. LOADUI R13 $Cold_Start ; Intialize via QUIT
  1016. JSR_COROUTINE R11 ; NEXT
  1017. :ABORT_String
  1018. " was not defined nor a valid number"
  1019. ;; PRINT
  1020. :PRINT_Text
  1021. "PRINT"
  1022. :PRINT_Entry
  1023. &ABORT_Entry ; Pointer to ABORT
  1024. &PRINT_Text ; Pointer to Name
  1025. NOP ; Flags
  1026. &PRINT_Code ; Where assembly is Stored
  1027. :PRINT_Code
  1028. POPR R2 R14 ; Load pointer to string
  1029. COPY R1 R7 ; Write to standard out
  1030. CALLI R15 @PRINT_Direct ; Trick to allow direct calls
  1031. JSR_COROUTINE R11 ; NEXT
  1032. :PRINT_Direct
  1033. LOAD8 R0 R2 0 ; Get a byte
  1034. ADDUI R2 R2 1 ; Increment to next byte
  1035. CMPSKIPI.NE R0 0 ; If NULL
  1036. RET R15 ; Return to caller
  1037. FPUTC ; Write the CHAR
  1038. JUMP @PRINT_Direct ; Loop until NULL
  1039. ;; strcmp
  1040. :Strcmp_Text
  1041. "STRCMP"
  1042. :Strcmp_Entry
  1043. &PRINT_Entry ; Pointer to PRINT
  1044. &Strcmp_Text ; Pointer to Name
  1045. NOP ; Flags
  1046. &Strcmp_Code ; Where assembly is Stored
  1047. :Strcmp_Code
  1048. CALLI R15 @Strcmp_Direct ; Trick to allow direct calls
  1049. JSR_COROUTINE R11 ; NEXT
  1050. :Strcmp_Direct
  1051. POPR R2 R14 ; Load pointer to string1
  1052. POPR R3 R14 ; Load pointer to string2
  1053. LOADUI R4 0 ; Starting at index 0
  1054. :cmpbyte
  1055. LOADXU8 R0 R2 R4 ; Get a byte of our first string
  1056. LOADXU8 R1 R3 R4 ; Get a byte of our second string
  1057. ADDUI R4 R4 1 ; Prep for next loop
  1058. CMP R1 R0 R1 ; Compare the bytes
  1059. CMPSKIPI.E R0 0 ; Stop if byte is NULL
  1060. JUMP.E R1 @cmpbyte ; Loop if bytes are equal
  1061. PUSHR R1 R14 ; Store the comparision result
  1062. RET R15 ; Return to whoever called it
  1063. ;; FIND
  1064. :Find_Text
  1065. "FIND"
  1066. :Find_Entry
  1067. &Strcmp_Entry ; Pointer to STRCMP
  1068. &Find_Text ; Pointer to Name
  1069. NOP ; Flags
  1070. &Find_Code ; Where assembly is Stored
  1071. :Find_Code
  1072. CALLI R15 @Find_Direct ; Allow Direct access
  1073. JSR_COROUTINE R11 ; NEXT
  1074. :Find_Direct
  1075. POPR R0 R14 ; Get pointer to String to find
  1076. COPY R3 R9 ; Copy LATEST
  1077. :Find_Loop
  1078. LOAD R1 R3 4 ; Get Pointer to string
  1079. PUSHR R3 R14 ; Protect Node pointer
  1080. PUSHR R0 R14 ; Protect FIND string
  1081. PUSHR R0 R14 ; Prepare for CALL
  1082. PUSHR R1 R14 ; Prepare for CALL
  1083. CALLI R15 @Strcmp_Direct ; Perform direct call
  1084. POPR R1 R14 ; Get return value
  1085. POPR R0 R14 ; Restore FIND string pointer
  1086. POPR R3 R14 ; Restore Node pointer
  1087. LOAD R4 R3 8 ; Get Flags for Node
  1088. ANDI R4 R4 0x1 ; Mask all but HIDDEN
  1089. CMPSKIPI.NE R4 0 ; Ignore result if HIDDEN
  1090. JUMP.E R1 @Find_Done ; If find was successful
  1091. LOAD R3 R3 0 ; Otherwise get next pointer
  1092. JUMP.NZ R3 @Find_Loop ; If Not NULL keep looping
  1093. :Find_Done
  1094. PUSHR R3 R14 ; Push pointer or Zero onto parameter stack
  1095. RET R15 ; Return to whoever called you
  1096. ;; >CFA
  1097. :TCFA_Text
  1098. ">CFA"
  1099. :TCFA_Entry
  1100. &Find_Entry ; Pointer to Find
  1101. &TCFA_Text ; Pointer to Name
  1102. NOP ; Flags
  1103. &TCFA_Code ; Where assembly is Stored
  1104. :TCFA_Code
  1105. POPR R0 R14 ; Get Node pointer
  1106. ADDUI R0 R0 12 ; Move to CFA
  1107. PUSHR R0 R14 ; Push the result
  1108. JSR_COROUTINE R11 ; NEXT
  1109. ;; >DFA
  1110. :TDFA_Text
  1111. ">DFA"
  1112. :TDFA_Entry
  1113. &TCFA_Entry ; Pointer to >CFA
  1114. &TDFA_Text ; Pointer to Name
  1115. NOP ; Flags
  1116. &TDFA_Code ; Where assembly is Stored
  1117. :TDFA_Code
  1118. POPR R0 R14 ; Get Node pointer
  1119. ADDUI R0 R0 16 ; Move to DFA
  1120. PUSHR R0 R14 ; Push the result
  1121. JSR_COROUTINE R11 ; NEXT
  1122. :DOVAR
  1123. ADDUI R0 R12 4 ; Locate Parameter Field Address
  1124. PUSHR R0 R14 ; Push on stack
  1125. JSR_COROUTINE R11 ; NEXT
  1126. ;; CREATE
  1127. :Create_Text
  1128. "CREATE"
  1129. :Create_Entry
  1130. &TDFA_Entry ; Pointer to >DFA
  1131. &Create_Text ; Pointer to Name
  1132. NOP ; Flags
  1133. &Create_Code ; Where assembly is Stored
  1134. :Create_Code
  1135. CALLI R15 @Word_Direct ; Get Word
  1136. POPR R0 R14 ; Get Length
  1137. POPR R1 R14 ; Get Pointer
  1138. FALSE R2 ; Set to Zero
  1139. CMPJUMPI.LE R0 R2 @Create_Code_1 ; Prevent size below 1
  1140. COPY R3 R8 ; Remember HERE for header
  1141. :Create_Code_0
  1142. LOAD8 R2 R1 0 ; Read Byte
  1143. STORE8 R2 R8 0 ; Write at HERE
  1144. ADDUI R8 R8 1 ; Increment HERE
  1145. SUBUI R0 R0 1 ; Decrement Length
  1146. ADDUI R1 R1 1 ; Increment string pointer
  1147. JUMP.NZ R0 @Create_Code_0 ; Keep Looping
  1148. FALSE R2 ; Set to Zero
  1149. STORE8 R2 R8 0 ; Write null terminator
  1150. ADDUI R8 R8 1 ; Increment HERE
  1151. COPY R0 R8 ; Remember HERE to set LATEST
  1152. ; R9 has latest
  1153. PUSHR R9 R8 ; Push pointer to current LATEST
  1154. COPY R9 R0 ; Set LATEST to this header
  1155. PUSHR R3 R8 ; Push location of name
  1156. PUSHR R2 R8 ; Push empty flags
  1157. LOADUI R0 $DOVAR ; Load address of DOVAR
  1158. PUSHR R0 R8 ; Push address of DOVAR
  1159. :Create_Code_1
  1160. JSR_COROUTINE R11 ; NEXT
  1161. ;; DEFINE
  1162. :Define_Text
  1163. ":"
  1164. :Define_Entry
  1165. &Create_Entry ; Pointer to Create
  1166. &Define_Text ; Pointer to Name
  1167. NOP ; Flags
  1168. &Define_Code ; Where assembly is Stored
  1169. :Define_Code
  1170. CALLI R15 @Word_Direct ; Get Word
  1171. COPY R0 R8 ; Preserve HERE for next LATEST
  1172. PUSHR R9 R8 ; Store LATEST onto HEAP
  1173. POPR R1 R14 ; Get rid of string length
  1174. POPR R1 R14 ; Get pointer to string
  1175. PUSHR R1 R8 ; Store string pointer onto HEAP
  1176. LOADUI R1 1 ; Prepare HIDDEN for Flag
  1177. PUSHR R1 R8 ; Push HIDDEN Flag
  1178. LOADUI R1 $DOCOL ; Get address of DOCOL
  1179. PUSHR R1 R8 ; Push DOCOL Address onto HEAP
  1180. MOVE R9 R0 ; Set LATEST
  1181. LOADUI R10 1 ; Set STATE to Compile Mode
  1182. JSR_COROUTINE R11 ; NEXT
  1183. ;; COMA
  1184. :Comma_Text
  1185. ","
  1186. :Comma_Entry
  1187. &Define_Entry ; Pointer to DEFINE
  1188. &Comma_Text ; Pointer to Name
  1189. NOP ; Flags
  1190. &Comma_Code ; Where assembly is Stored
  1191. :Comma_Code
  1192. POPR R0 R14 ; Get top of parameter stack
  1193. PUSHR R0 R8 ; Push onto HEAP and increment HEAP pointer
  1194. JSR_COROUTINE R11 ; NEXT
  1195. ;; [
  1196. :LBRAC_Text
  1197. "["
  1198. :LBRAC_Entry
  1199. &Comma_Entry ; Pointer to Comma
  1200. &LBRAC_Text ; Pointer to Name
  1201. '00000002' ; Flags [F_IMMED]
  1202. &LBRAC_Code ; Where assembly is Stored
  1203. :LBRAC_Code
  1204. FALSE R10 ; Set STATE to Interpret Mode
  1205. JSR_COROUTINE R11 ; NEXT
  1206. ;; ]
  1207. :RBRAC_Text
  1208. "]"
  1209. :RBRACK_Entry
  1210. &LBRAC_Entry ; Pointer to LBRAC
  1211. &RBRAC_Text ; Pointer to Name
  1212. NOP ; Flags
  1213. &RBRACK_Code ; Where assembly is Stored
  1214. :RBRACK_Code
  1215. LOADUI R10 1 ; Set State to Compile Mode
  1216. JSR_COROUTINE R11 ; NEXT
  1217. ;; ;
  1218. :SEMICOLON_Text
  1219. ";"
  1220. :SEMICOLON_Entry
  1221. &RBRACK_Entry ; Pointer to RBRAC
  1222. &SEMICOLON_Text ; Pointer to Name
  1223. '00000002' ; Flags [F_IMMED]
  1224. &SEMICOLON_Code ; Where assembly is Stored
  1225. :SEMICOLON_Code
  1226. LOADUI R0 $EXIT_Entry ; Get EXIT Pointer
  1227. ADDUI R0 R0 12 ; Adjust pointer
  1228. PUSHR R0 R8 ; Push EXIT onto HEAP and increment HEAP pointer
  1229. FALSE R0 ; Prep NULL for Flag
  1230. STORE R0 R9 8 ; Set Flag
  1231. FALSE R10 ; Set State to Interpret Mode
  1232. JSR_COROUTINE R11 ; NEXT
  1233. ;; Branching
  1234. ;; BRANCH
  1235. :Branch_Text
  1236. "BRANCH"
  1237. :Branch_Entry
  1238. &SEMICOLON_Entry ; Pointer to Semicolon
  1239. &Branch_Text ; Pointer to Name
  1240. NOP ; Flags
  1241. :Branch
  1242. &Branch_Code ; Where assembly is Stored
  1243. :Branch_Code
  1244. LOAD R0 R13 0 ; Get Contents of NEXT
  1245. ADD R13 R13 R0 ; Update NEXT with offset
  1246. JSR_COROUTINE R11 ; NEXT
  1247. ;; 0BRANCH
  1248. :0Branch_Text
  1249. "0BRANCH"
  1250. :0Branch_Entry
  1251. &Branch_Entry ; Pointer to Branch
  1252. &0Branch_Text ; Pointer to Name
  1253. NOP ; Flags
  1254. &0Branch_Code ; Where assembly is Stored
  1255. :0Branch_Code
  1256. POPR R1 R14 ; Get value off parameter stack
  1257. LOADUI R0 4 ; Default offset of 4
  1258. CMPSKIPI.NE R1 0 ; If not Zero use default offset
  1259. LOAD R0 R13 0 ; Otherwise use Contents of NEXT
  1260. ADD R13 R13 R0 ; Set NEXT to NEXT plus the offset
  1261. JSR_COROUTINE R11 ; NEXT
  1262. ;; EXECUTE
  1263. :Execute_Text
  1264. "EXECUTE"
  1265. :Execute_Entry
  1266. &0Branch_Entry ; Pointer to 0Branch
  1267. &Execute_Text ; Pointer to Name
  1268. NOP ; Flags
  1269. &Execute_Code ; Where assembly is Stored
  1270. :Execute_Code
  1271. POPR R12 R14 ; Get address pointer off parameter stack
  1272. LOAD R0 R12 0 ; Get address from pointer
  1273. JSR_COROUTINE R0 ; Jump to that address
  1274. ;; Interaction Commands
  1275. ;; QUIT
  1276. :Quit_Text
  1277. "QUIT"
  1278. :Quit_Entry
  1279. &Execute_Entry ; Pointer to Execute
  1280. &Quit_Text ; Pointer to Name
  1281. NOP ; Flags
  1282. :Quit_Code
  1283. &DOCOL ; Use DOCOL
  1284. &RETURN_CLEAR ; Clear the return stack
  1285. &Interpret_Loop ; INTERPRET
  1286. &Branch ; Loop forever
  1287. 'FFFFFFF4' ; -12
  1288. ;; INTERPRET
  1289. :Interpret_Text
  1290. "INTERPRET"
  1291. :Interpret_Entry
  1292. &Quit_Entry ; Pointer to QUIT
  1293. &Interpret_Text ; Pointer to Name
  1294. NOP ; Flags
  1295. :Interpret_Loop
  1296. &Interpret_Code ; Where assembly is Stored
  1297. :Interpret_Code
  1298. CALLI R15 @Word_Direct ; Get the Word
  1299. POPR R0 R14 ; Remove Length
  1300. CMPSKIPI.NE R0 0 ; If Nothing read
  1301. JUMP @Interpret_Cleanup ; Cleanup
  1302. POPR R0 R14 ; Remove Pointer
  1303. PUSHR R0 R14 ; Protect Pointer
  1304. PUSHR R0 R14 ; Put Pointer
  1305. CALLI R15 @Find_Direct ; Try to Find it
  1306. POPR R0 R14 ; Get result of Search
  1307. JUMP.Z R0 @Interpret_Literal ; Since it wasn't found assume it is a literal
  1308. ;; Found Node
  1309. POPR R1 R14 ; Clean up unneed stack
  1310. LOAD R1 R0 8 ; Get Flags of found node
  1311. ANDI R1 R1 0x2 ; Check if F_IMMED is set
  1312. JUMP.Z R1 @Interpret_Compile ; Its not immediate so I might have to compile
  1313. :Interpret_Execute
  1314. ADDUI R12 R0 12 ; Point to codeword
  1315. LOAD R1 R0 12 ; Get where to jump
  1316. JSR_COROUTINE R1 ; EXECUTE Directly
  1317. :Interpret_Compile
  1318. ANDI R1 R10 1 ; Check if we are in compile mode
  1319. JUMP.Z R1 @Interpret_Execute ; If not execute the node
  1320. ADDUI R0 R0 12 ; Adjust pointer to body of Node
  1321. PUSHR R0 R8 ; Append to HEAP
  1322. JSR_COROUTINE R11 ; NEXT
  1323. :Interpret_Literal
  1324. CALLI R15 @Number_Direct ; Attempt to process string as number
  1325. ANDI R0 R10 1 ; Check if we are in compile mode
  1326. CMPSKIPI.NE R0 0 ; If not compiling
  1327. JSR_COROUTINE R11 ; Simply leave on stack and NEXT
  1328. LOADUI R0 $LIT_Entry ; Get address of LIT
  1329. ADDUI R0 R0 12 ; Adjust to point to direct code
  1330. PUSHR R0 R8 ; Append pointer to HEAP
  1331. POPR R0 R14 ; Get Immediate value
  1332. PUSHR R0 R8 ; Append Immediate to HEAP
  1333. JSR_COROUTINE R11 ; NEXT
  1334. :Interpret_Cleanup
  1335. POPR R0 R14 ; Remove Pointer
  1336. JSR_COROUTINE R11 ; NEXT
  1337. ;; Cold done function
  1338. ;; Reads Tape_01 until EOF
  1339. ;; Then switches into TTY Mode
  1340. :cold_done
  1341. ;; IF TTY Receives EOF call it quits
  1342. CMPSKIPI.NE R7 0 ; Check if TTY
  1343. JUMP @final_Cleanup ; Clean up and call it a day
  1344. ;; Prep TTY
  1345. FALSE R7 ; Set TTY ID
  1346. LOADUI R13 $Cold_Start ; Prepare to return to QUIT LOOP
  1347. JSR_COROUTINE R11 ; NEXT
  1348. ;; Clean up
  1349. ;; Cleans up everything before HALTING
  1350. ;; Don't try to make it a forth primative
  1351. ;; It only has 1 use
  1352. :final_Cleanup
  1353. LOADUI R0 0x1101 ; Need number to disengage tape_02
  1354. FCLOSE ; unload Tape_01
  1355. LOADUI R0 0x1100 ; Need number to disengage tape_01
  1356. FCLOSE ; unload Tape_01
  1357. HALT ; User is done
  1358. ;; Where our HEAP Starts
  1359. :HEAP