forth-V1.s 86 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908
  1. ;;; forth.s
  2. ;;; based on the public domain eforth implementations
  3. ;;; found in the files eforth.4th and eforth.S
  4. ;;; These original implementations are in the Public Domain
  5. ;;; This is exactly the same as eforth and is not ANSI Forth,
  6. ;;; although my additions try to follow the ANSI standard
  7. ;;; This file is placed under a two clause BSD-style license
  8. ;;; as follows:
  9. ;;; Copyright 2009 Christopher Hall <hsw@openmoko.com>
  10. ;;;
  11. ;;; Redistribution and use in source and binary forms, with or without
  12. ;;; modification, are permitted provided that the following conditions are
  13. ;;; met:
  14. ;;;
  15. ;;; 1. Redistributions of source code must retain the above copyright
  16. ;;; notice, this list of conditions and the following disclaimer.
  17. ;;;
  18. ;;; 2. Redistributions in binary form must reproduce the above copyright
  19. ;;; notice, this list of conditions and the following disclaimer in
  20. ;;; the documentation and/or other materials provided with the
  21. ;;; distribution.
  22. ;;;
  23. ;;; THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY
  24. ;;; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25. ;;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  26. ;;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
  27. ;;; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  28. ;;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  29. ;;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  30. ;;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  31. ;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  32. ;;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  33. ;;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34. ;;; symbols used in the ( -- ) comments
  35. ;;;
  36. ;;; a aligned address (to 4 byte boundary)
  37. ;;; b byte address
  38. ;;; c character
  39. ;;; ca code address
  40. ;;; cy carry
  41. ;;; d signed double integer (2 cells)
  42. ;;; dirid directory handle (1..n)
  43. ;;; F logical false (zero)
  44. ;;; f flag 0 or non-zero
  45. ;;; fam file access mode
  46. ;;; fileid file handle (1..n)
  47. ;;; h half-word address (to 2 byte boundary)
  48. ;;; ior system dependent error code (zero => no error)
  49. ;;; la link address
  50. ;;; n signed integer
  51. ;;; na name address
  52. ;;; pa param address
  53. ;;; T logical true (non-zero)
  54. ;;; t flag T or F
  55. ;;; u unsigned integer
  56. ;;; ud unsigned double integer (2 cells)
  57. ;;; va vocabulary address
  58. ;;; w unspecified word value
  59. ;;;
  60. ;;; if characters are taken from the input buffer then
  61. ;;; this form is used
  62. ;;; ( -- \ <string> ) \ string is terminated by space
  63. ;;; ( -- \ <string>% ) \ string terminated by %
  64. ;;; \ % could be any char
  65. ;;; ( c -- \ <string><char c> )
  66. ;;; \ string terminated by value of c
  67. ;;; \ where the character is passed on the stack
  68. ;;; Version (no minor values, just increment)
  69. BUILD_NUMBER = 2
  70. ;;; set this to 1 to diable assembler optimisations
  71. PREFER_FORTH_CODE = 0
  72. ;;; some character constants
  73. backspace = 0x08
  74. line_feed = 0x0a
  75. carriage_return = 0x0d
  76. delete = 0x7f
  77. ;;; some special constants
  78. BYTES_PER_CELL = 4
  79. BITS_PER_BYTE = 8
  80. BITS_PER_CELL = (BITS_PER_BYTE * BYTES_PER_CELL)
  81. FALSE = 0
  82. TRUE = -1
  83. ;;; header flags
  84. FLAG_IMMEDIATE = 0x80
  85. FLAG_COMPILE_ONLY = 0x40
  86. FLAG_NORMAL = 0
  87. ;;; registers (C preserves r0..r3)
  88. ;;; r0 forth ip
  89. ;;; r1 forth sp
  90. ;;; r2 forth pp
  91. ;;; r3 forth w
  92. ;;; r4 C result low
  93. ;;; r5 C result high
  94. ;;; r6 C argument 1
  95. ;;; r7 C argument 2
  96. ;;; r8 C argument 3
  97. ;;; r9 C argument 4
  98. ;;; r10..r14 used by C and/or extended asm instructions
  99. ;;; r15 __dp for C
  100. .macro NEXT ; inner interpreter
  101. ld.w %r2, [%r0]+ ; incr IP (%r0)
  102. ld.w %r3, [%r2]+ ; %r2 -> param address
  103. jp %r3 ; execute the code
  104. .endm
  105. ;;; inline forth counted strings
  106. .macro FSTRING, text
  107. .byte str_\@_finish - str_\@_start
  108. str_\@_start:
  109. .ascii "\text"
  110. str_\@_finish:
  111. .balign 4
  112. .endm
  113. ;;; macro to create offsets in bytes and cells
  114. .macro MAKE_OFFSET, label, value
  115. .ifnotdef \label\()_BYTE
  116. \label\()_BYTES = \value
  117. \label\()_CELLS = \value
  118. .endif
  119. .endm
  120. ;;; the header
  121. ;;; 0: code address
  122. ;;; 4: param address
  123. ;;; 8: flags
  124. ;;; 12: link address
  125. ;;; 16: count (byte) (name adress points here)
  126. ;;; 17: name string (count bytes)
  127. ;;; 17+count: (zeros as required to .balign 4)
  128. .section .forth_dict, "wa"
  129. .balign 4
  130. .section .forth_param, "wax"
  131. .balign 4
  132. __last_name = 0 ; to link the list
  133. .macro HEADER, label, name, flags, code
  134. .section .forth_dict
  135. .balign 4
  136. .global \label
  137. \label\():
  138. .long \code ; code
  139. l_param_\@:
  140. .long param_\label ; param
  141. l_flags_\@:
  142. .long \flags ; flags
  143. prev_\label = __last_name
  144. l_link_\@:
  145. .long prev_\label ; link
  146. .global name_\label
  147. name_\label\():
  148. __last_name = .
  149. FSTRING "\name"
  150. MAKE_OFFSET DICTIONARY_HEADER, "( name_\label - \label )"
  151. MAKE_OFFSET DICTIONARY_CODE_OFFSET, "( name_\label - \label )"
  152. MAKE_OFFSET DICTIONARY_PARAM_OFFSET, "( name_\label - l_param_\@ )"
  153. MAKE_OFFSET DICTIONARY_FLAGS_OFFSET, "( name_\label - l_flags_\@ )"
  154. MAKE_OFFSET DICTIONARY_LINK_OFFSET, "( name_\label - l_link_\@ )"
  155. .section .forth_param
  156. .balign 4
  157. .global param_\label
  158. param_\label\():
  159. .endm
  160. ;;; code definitions
  161. .macro CODE, label, name, flags
  162. HEADER \label, "\name", \flags, param_\label
  163. .endm
  164. .macro END_CODE
  165. .endm
  166. ;;; colon definitions
  167. .macro COLON, label, name, flags
  168. HEADER \label, "\name", \flags, param_docolon
  169. .endm
  170. ;;; variable definitions
  171. .macro VARIABLE, label, name, flags
  172. HEADER \label, "\name", \flags, param_dovar
  173. .endm
  174. ;;; constant definitions
  175. .macro CONSTANT, label, name, flags
  176. HEADER \label, "\name", \flags, param_doconst
  177. .endm
  178. ;;; user variables sections
  179. .section .user_variables, "wa"
  180. .balign 4
  181. user_variables:
  182. ;;; define user variables
  183. .macro USER, label, name, flags, defaults
  184. .section .user_variables
  185. .global \label\()_variable
  186. \label\()_variable:
  187. .long \defaults
  188. HEADER \label, "\name", \flags, param_douser
  189. .long \label\()_variable
  190. .endm
  191. ;;; miscellaneous variables
  192. .section .bss
  193. .balign 4
  194. terminal_buffer:
  195. .space 65536
  196. .global initial_stack_pointer
  197. initial_stack_pointer: ; NOTE: stack underflows over return space!
  198. .space 65536
  199. .global initial_return_pointer
  200. initial_return_pointer:
  201. ;;; Program Code
  202. .section .text
  203. .global main
  204. main:
  205. xld.w %r15, __dp
  206. xld.w %r1, initial_stack_pointer
  207. xld.w %r4, initial_return_pointer
  208. ld.w %sp, %r4
  209. xld.w %r0, cold_start ; initial ip value
  210. NEXT
  211. .balign 4 ; forth byte code must be aligned
  212. cold_start:
  213. .long cold, branch, cold_start ; just run cold in a loop
  214. ;;; .( Special interpreters )
  215. CODE dolit, "(dolit)", FLAG_COMPILE_ONLY ; ( -- w ) COMPILE-ONLY
  216. ld.w %r3, [%r0]+
  217. sub %r1, BYTES_PER_CELL
  218. ld.w [%r1], %r3
  219. NEXT
  220. END_CODE
  221. CODE docolon, "(docolon)", FLAG_COMPILE_ONLY ; ( -- )
  222. pushn %r0 ; save previous ip
  223. ld.w %r0, [%r2] ; ip = param address
  224. NEXT
  225. END_CODE
  226. CODE execute, "execute", FLAG_NORMAL ; ( a -- )
  227. ld.w %r2, [%r1]+ ; point to code ptr
  228. ld.w %r3, [%r2]+ ; code / param address
  229. jp %r3 ; execute the code
  230. END_CODE
  231. CODE exit, "exit", FLAG_NORMAL ; ( -- )
  232. popn %r0 ; restore ip
  233. NEXT
  234. END_CODE
  235. ;;; .( Loop & Branch - absolute address )
  236. ;;; : (next) ( -- ) \ hiLevel model 16bit absolute branch
  237. ;;; r> r> dup if 1- >r @ >r exit then drop cell+ >r ;
  238. CODE donext, "(next)", FLAG_COMPILE_ONLY
  239. ld.w %r4, [%sp]
  240. or %r4, %r4
  241. jreq donext_l1
  242. xsub %r4, 1
  243. ld.w [%sp], %r4
  244. ld.w %r0, [%r0]
  245. NEXT
  246. donext_l1:
  247. add %sp, 1
  248. no_branch:
  249. add %r0, BYTES_PER_CELL
  250. NEXT
  251. END_CODE
  252. CODE qbranch, "?branch", FLAG_COMPILE_ONLY ; ( f -- ) COMPILE-ONLY
  253. ld.w %r4, [%r1]+
  254. or %r4, %r4
  255. jrne no_branch
  256. ld.w %r0, [%r0]
  257. NEXT
  258. END_CODE
  259. CODE branch, "branch", FLAG_COMPILE_ONLY ; ( -- ) COMPILE-ONLY
  260. ld.w %r0, [%r0]
  261. NEXT
  262. END_CODE
  263. ;;; .( Memory fetch & store )
  264. CODE store, "!", FLAG_NORMAL ; ( w a -- )
  265. ld.w %r4, [%r1]+
  266. ld.w %r5, [%r1]+
  267. ld.w [%r4], %r5
  268. NEXT
  269. END_CODE
  270. CODE fetch, "@", FLAG_NORMAL ; ( a -- w )
  271. ld.w %r4, [%r1]
  272. ld.w %r4, [%r4]
  273. ld.w [%r1], %r4
  274. NEXT
  275. END_CODE
  276. CODE hstore, "h!", FLAG_NORMAL ; ( c h -- )
  277. ld.w %r4, [%r1]+
  278. ld.w %r5, [%r1]+
  279. ld.h [%r4], %r5
  280. NEXT
  281. END_CODE
  282. CODE hfetch, "h@", FLAG_NORMAL ; ( h -- c )
  283. ld.w %r4, [%r1]
  284. ld.uh %r4, [%r4]
  285. ld.w [%r1], %r4
  286. NEXT
  287. END_CODE
  288. CODE cstore, "c!", FLAG_NORMAL ; ( c b -- )
  289. ld.w %r4, [%r1]+
  290. ld.w %r5, [%r1]+
  291. ld.b [%r4], %r5
  292. NEXT
  293. END_CODE
  294. CODE cfetch, "c@", FLAG_NORMAL ; ( b -- c )
  295. ld.w %r4, [%r1]
  296. ld.ub %r4, [%r4]
  297. ld.w [%r1], %r4
  298. NEXT
  299. END_CODE
  300. ;;; .( Return Stack )
  301. CODE rp_fetch, "rp@", FLAG_NORMAL ; ( -- a )
  302. ld.w %r4, %sp
  303. sub %r1, BYTES_PER_CELL
  304. ld.w [%r1], %r4
  305. NEXT
  306. END_CODE
  307. CODE rp_store, "rp!", FLAG_COMPILE_ONLY ; ( a -- ) COMPILE-ONLY
  308. ld.w %r4, [%r1]+
  309. ld.w %sp, %r4
  310. NEXT
  311. END_CODE
  312. CODE r_from, "r>", FLAG_COMPILE_ONLY ; ( -- w ) COMPILE-ONLY
  313. ld.w %r4, [%sp]
  314. add %sp, 1
  315. sub %r1, BYTES_PER_CELL
  316. ld.w [%r1], %r4
  317. NEXT
  318. END_CODE
  319. CODE r_fetch, "r@", FLAG_NORMAL ; ( -- w )
  320. ld.w %r4, [%sp]
  321. xsub %r1, BYTES_PER_CELL
  322. ld.w [%r1], %r4
  323. NEXT
  324. END_CODE
  325. CODE to_r, ">r", FLAG_COMPILE_ONLY ; ( w -- ) COMPILE-ONLY
  326. ld.w %r4, [%r1]+
  327. sub %sp, 1
  328. ld.w [%sp], %r4
  329. NEXT
  330. END_CODE
  331. ;;; .( Data Stack )
  332. CODE sp_fetch, "sp@", FLAG_NORMAL ; ( -- a )
  333. ld.w %r4, %r1
  334. sub %r1, BYTES_PER_CELL
  335. ld.w [%r1], %r4
  336. NEXT
  337. END_CODE
  338. CODE sp_store, "sp!", FLAG_NORMAL ; ( a -- )
  339. ld.w %r1, [%r1]
  340. NEXT
  341. END_CODE
  342. CODE drop, "drop", FLAG_NORMAL ; ( w -- )
  343. ld.w %r4, [%r1]+
  344. NEXT
  345. END_CODE
  346. CODE dup, "dup", FLAG_NORMAL ; ( w -- w w )
  347. ld.w %r4, [%r1]
  348. sub %r1, BYTES_PER_CELL
  349. ld.w [%r1], %r4
  350. NEXT
  351. END_CODE
  352. CODE swap, "swap", FLAG_NORMAL ; ( w1 w2 -- w2 w1 )
  353. ld.w %r4, [%r1]+
  354. ld.w %r5, [%r1]+
  355. sub %r1, BYTES_PER_CELL
  356. ld.w [%r1], %r4
  357. sub %r1, BYTES_PER_CELL
  358. ld.w [%r1], %r5
  359. NEXT
  360. END_CODE
  361. CODE over, "over", FLAG_NORMAL ; ( w1 w2 -- w1 w2 w1 )
  362. xld.w %r4, [%r1 + 4]
  363. sub %r1, BYTES_PER_CELL
  364. ld.w [%r1], %r4
  365. NEXT
  366. END_CODE
  367. ;;; : ?DUP ( w -- w w, 0 ) DUP IF DUP THEN ;
  368. COLON qdup, "?dup", FLAG_NORMAL
  369. .long dup, qbranch, qdup_l1
  370. .long dup
  371. qdup_l1:
  372. .long exit
  373. ;;; : NIP ( w1 w2 -- w2 ) SWAP DROP ;
  374. COLON nip, "nip", FLAG_NORMAL
  375. .long swap, drop, exit
  376. ;;; : ROT ( w1 w2 w3 -- w2 w3 w1 ) >R SWAP R> SWAP ;
  377. COLON rot, "rot", FLAG_NORMAL
  378. .long to_r, swap, r_from, swap, exit
  379. ;;; : -ROT ( w1 w2 w3 -- w3 w1 w2 ) ROT ROT ;
  380. COLON minus_rot, "-rot", FLAG_NORMAL
  381. .long rot, rot, exit
  382. ;;; : 2DROP ( w w -- ) DROP DROP ;
  383. COLON twodrop, "2drop", FLAG_NORMAL
  384. .long drop, drop, exit
  385. ;;; : 2DUP ( w1 w2 -- w1 w2 w1 w2 ) OVER OVER ;
  386. COLON twodup, "2dup", FLAG_NORMAL
  387. .long over, over, exit
  388. ;;; .( Logic )
  389. CODE zero_less, "0<", FLAG_NORMAL ; ( n -- t )
  390. ld.w %r4, [%r1]
  391. or %r4, %r4
  392. jrlt zero_less_l1
  393. ld.w %r4, FALSE
  394. ld.w [%r1], %r4
  395. NEXT
  396. zero_less_l1:
  397. ld.w %r4, TRUE
  398. ld.w [%r1], %r4
  399. NEXT
  400. END_CODE
  401. CODE _and, "and", FLAG_NORMAL ; ( w w -- w )
  402. ld.w %r4, [%r1]+
  403. ld.w %r5, [%r1]
  404. and %r4, %r5
  405. ld.w [%r1], %r4
  406. NEXT
  407. END_CODE
  408. CODE _or, "or", FLAG_NORMAL ; ( w w -- w )
  409. ld.w %r4, [%r1]+
  410. ld.w %r5, [%r1]
  411. or %r4, %r5
  412. ld.w [%r1], %r4
  413. NEXT
  414. END_CODE
  415. CODE _xor, "xor", FLAG_NORMAL ; ( w w -- w )
  416. ld.w %r4, [%r1]+
  417. ld.w %r5, [%r1]
  418. xor %r4, %r5
  419. ld.w [%r1], %r4
  420. NEXT
  421. END_CODE
  422. ;;; : INVERT ( w -- w ) -1 XOR ;
  423. COLON invert, "invert", FLAG_NORMAL
  424. .long dolit, -1, _xor, exit
  425. ;;; .( Arithmetic )
  426. CODE umplus, "um+", FLAG_NORMAL ; ( u u -- u cy ) \ or ( u u -- ud )
  427. ld.w %r4, [%r1]+
  428. ld.w %r5, [%r1]
  429. add %r4, %r5
  430. ld.w [%r1], %r4
  431. ld.w %r4, 0
  432. adc %r4, %r4
  433. sub %r1, BYTES_PER_CELL
  434. ld.w [%r1], %r4
  435. NEXT
  436. END_CODE
  437. ;;; : + ( u u -- u ) UM+ DROP ;
  438. CODE plus, "+", FLAG_NORMAL ; ( w w -- w )
  439. ld.w %r4, [%r1]+
  440. ld.w %r5, [%r1]
  441. add %r4, %r5
  442. ld.w [%r1], %r4
  443. NEXT
  444. END_CODE
  445. ;;; : 1+ ( w -- w+1 ) 1 + ;
  446. CODE increment, "1+", FLAG_NORMAL
  447. ld.w %r4, [%r1]
  448. xadd %r4, 1
  449. ld.w [%r1], %r4
  450. NEXT
  451. END_CODE
  452. ;;; : 1- ( w -- w-1 ) 1 - ;
  453. CODE decrement, "1-", FLAG_NORMAL
  454. ld.w %r4, [%r1]
  455. xsub %r4, 1
  456. ld.w [%r1], %r4
  457. NEXT
  458. END_CODE
  459. ;;; : NEGATE ( n -- -n ) INVERT 1+ ;
  460. COLON negate "negate",0
  461. .long invert, increment, exit
  462. ;;; : DNEGATE ( d -- -d ) INVERT >R INVERT 1 UM+ R> + ;
  463. COLON dnegate, "dnegate", FLAG_NORMAL
  464. .long invert, to_r, invert
  465. .long dolit, 1, umplus
  466. .long r_from, plus, exit
  467. ;;; : - ( w w -- w ) NEGATE + ;
  468. CODE minus, "-", FLAG_NORMAL ; ( w w -- w )
  469. ld.w %r5, [%r1]+
  470. ld.w %r4, [%r1]
  471. sub %r4, %r5
  472. ld.w [%r1], %r4
  473. NEXT
  474. END_CODE
  475. ;;; : ABS ( n -- +n ) DUP 0< IF NEGATE THEN ;
  476. COLON abs, "abs", FLAG_NORMAL
  477. .long dup, zero_less, qbranch, abs_l1
  478. .long negate
  479. abs_l1:
  480. .long exit
  481. ;;; .( User variables )
  482. ;;; : (douser) ( -- a ) R> @ UP @ + ; COMPILE-ONLY ( address passed via %r2 not stack )
  483. CODE douser, "(douser)", FLAG_COMPILE_ONLY
  484. ld.w %r4, [%r2]
  485. ld.w %r4, [%r4] ; user is another pointer!
  486. sub %r1, BYTES_PER_CELL
  487. ld.w [%r1], %r4
  488. NEXT
  489. END_CODE
  490. ;;; : (dovar) ( -- a ) R> ; COMPILE-ONLY ( address passed via %r2 not stack )
  491. CODE dovar, "(dovar)", FLAG_COMPILE_ONLY
  492. ld.w %r4, [%r2] ; %r4 = parameter address
  493. sub %r1, BYTES_PER_CELL
  494. ld.w [%r1], %r4
  495. NEXT
  496. END_CODE
  497. ;;; : (doconst) ( -- a ) R> @ ; COMPILE-ONLY ( address passed via %r2 not stack )
  498. CODE doconst, "(doconst)", FLAG_COMPILE_ONLY
  499. ld.w %r4, [%r2] ; %r4 = parameter address
  500. ld.w %r4, [%r4] ; read the constant value
  501. sub %r1, BYTES_PER_CELL
  502. ld.w [%r1], %r4
  503. NEXT
  504. END_CODE
  505. ;;; 8 \ start offset
  506. USER user_reserved, "(ureserved)", FLAG_NORMAL, "0,0,0,0"
  507. ;;; DUP USER SP0 1 CELL+ \ initial data stack pointer
  508. USER sp0, "sp0", FLAG_NORMAL, initial_stack_pointer
  509. ;;; DUP USER RP0 1 CELL+ \ initial return stack pointer
  510. USER rp0, "rp0", FLAG_NORMAL, initial_return_pointer
  511. ;;; DUP USER 'KEY? 1 CELL+ \ character input ready vector
  512. USER tkey_query, "\047key?", FLAG_NORMAL, rx_query
  513. ;;; DUP USER 'EMIT 1 CELL+ \ character output vector
  514. USER temit, "\047emit", FLAG_NORMAL, tx_store
  515. ;;; DUP USER 'EXPECT 1 CELL+ \ line input vector
  516. USER texpect, "\047expect", FLAG_NORMAL, accept
  517. ;;; DUP USER 'TAP 1 CELL+ \ input case vector
  518. USER ttap, "\047tap", FLAG_NORMAL, ktap
  519. ;;; DUP USER 'ECHO 1 CELL+ \ input echo vector
  520. USER techo, "\047echo", FLAG_NORMAL, tx_store
  521. ;;; DUP USER 'PROMPT 1 CELL+ \ operator prompt vector
  522. USER tprompt, "\047prompt", FLAG_NORMAL, dot_ok
  523. ;;; DUP USER BASE 1 CELL+ \ number base
  524. USER base, "base", FLAG_NORMAL, 10
  525. ;;; DUP USER temp 1 CELL+ \ scratch
  526. USER temp, "temp", FLAG_COMPILE_ONLY, 0
  527. ;;; DUP USER SPAN 1 CELL+ \ #chars input by EXPECT
  528. USER span, "span", FLAG_NORMAL, 0
  529. ;;; DUP USER >IN 1 CELL+ \ input buffer offset
  530. USER to_in, ">in", FLAG_NORMAL, 0
  531. ;;; DUP USER #TIB 1 CELL+ \ #chars in the input buffer
  532. ;;; 1 CELLS ALLOT \ address of input buffer
  533. USER hash_tib, "#tib", FLAG_NORMAL, "0,terminal_buffer"
  534. ;;; DUP USER UP 1 CELL+ \ user base pointer
  535. ;; not needed
  536. ;;; DUP USER CSP 1 CELL+ \ save stack pointers
  537. ;; not needed
  538. ;;; DUP USER 'EVAL 1 CELL+ \ interpret/compile vector
  539. USER teval, "\047eval", FLAG_NORMAL, dollar_interpret
  540. ;;; DUP USER 'NUMBER 1 CELL+ \ numeric input vector
  541. USER tnumber, "\047number", FLAG_NORMAL, numberq
  542. ;;; DUP USER HLD 1 CELL+ \ formated numeric string
  543. USER hld, "hld", FLAG_NORMAL, 0
  544. ;;; DUP USER HANDLER 1 CELL+ \ error frame pointer
  545. USER handler, "handler", FLAG_NORMAL, 0
  546. ;;; DUP USER CONTEXT 1 CELL+ \ first search vocabulary
  547. ;;; =VOCS CELL+ \ vocabulary stack
  548. USER context, "context", FLAG_NORMAL, "0, 0,0,0,0, 0,0,0,0"
  549. ;;; DUP USER CURRENT 1 CELL+ \ definitions vocabulary
  550. ;;; 1 CELL+ \ newest vocabulary
  551. USER current, "current", FLAG_NORMAL, "0,0"
  552. ;;; DUP USER CP 1 CELL+ \ dictionary code pointer
  553. ;;; 1 CELL+ \ dictionary name pointer
  554. ;;; 1 CELL+ \ last name compiled
  555. USER cp, "cp", FLAG_NORMAL, "end_of_code, end_of_dictionary, last_name"
  556. ;;; .( Comparison )
  557. ;;; : 0= ( w -- t ) IF FALSE EXIT THEN TRUE ;
  558. COLON zero_equal, "0=", FLAG_NORMAL
  559. .long qbranch, zero_equal_l1
  560. .long dolit, FALSE, exit
  561. zero_equal_l1:
  562. .long dolit, TRUE, exit
  563. ;;; \ convert any non-zero to a preper TRUE
  564. ;;; : 0<> ( w -- t ) IF TRUE EXIT THEN FALSE ;
  565. COLON zero_not_equal, "0<>", FLAG_NORMAL
  566. .long qbranch, zero_not_equal_l1
  567. .long dolit, TRUE, exit
  568. zero_not_equal_l1:
  569. .long dolit, FALSE, exit
  570. ;;; : = ( w w -- t ) XOR 0= ;
  571. COLON equal, "=", FLAG_NORMAL
  572. .long _xor, zero_equal, exit
  573. ;;; : U< ( u u -- t ) 2DUP XOR 0< IF NIP 0< EXIT THEN - 0< ;
  574. COLON uless, "u<", FLAG_NORMAL
  575. .long twodup, _xor, zero_less, qbranch, uless_l1
  576. .long nip, zero_less, exit
  577. uless_l1:
  578. .long minus, zero_less, exit
  579. ;;; : U> ( n n -- t ) SWAP U< ;
  580. COLON ugreater, "u>", FLAG_NORMAL
  581. .long swap, uless, exit
  582. ;;; : < ( n n -- t ) 2DUP XOR 0< IF DROP 0< EXIT THEN - 0< ;
  583. COLON less, "<", FLAG_NORMAL
  584. .long twodup, _xor, zero_less, qbranch, less_l1
  585. .long drop, zero_less, exit
  586. less_l1:
  587. .long minus, zero_less, exit
  588. ;;; : > ( n n -- t ) SWAP < ;
  589. COLON greater, ">", FLAG_NORMAL
  590. .long swap, less, exit
  591. ;;; : MAX ( n n -- n ) 2DUP < IF SWAP THEN DROP ;
  592. COLON max, "max", FLAG_NORMAL
  593. .long twodup, less, qbranch, max_l1
  594. .long swap
  595. max_l1:
  596. .long drop, exit
  597. ;;; : MIN ( n n -- n ) 2DUP SWAP < IF SWAP THEN DROP ;
  598. COLON min, "min", FLAG_NORMAL
  599. .long twodup, swap, less, qbranch, min_l1
  600. .long swap
  601. min_l1:
  602. .long drop, exit
  603. ;;; : WITHIN ( u ul uh -- t ) OVER - >R - R> U< ;
  604. COLON within, "within", FLAG_NORMAL
  605. .long over, minus, to_r, minus, r_from, uless, exit
  606. ;;; .( Divide )
  607. ;;; : UM/MOD ( udl udh un -- ur uq )
  608. ;;; 2DUP U<
  609. ;;; IF NEGATE 15
  610. ;;; FOR >R DUP UM+ >R >R DUP UM+ R> + DUP
  611. ;;; R> R@ SWAP >R UM+ R> OR
  612. ;;; IF >R DROP 1+ R> ELSE DROP THEN R>
  613. ;;; NEXT DROP SWAP EXIT
  614. ;;; THEN DROP 2DROP -1 DUP ;
  615. COLON um_slash_mod, "um/mod", FLAG_NORMAL
  616. .long twodup, uless
  617. .long qbranch, um_slash_mod_l4
  618. .long negate, dolit, BITS_PER_CELL - 1, to_r
  619. um_slash_mod_l1:
  620. .long to_r, dup, umplus
  621. .long to_r, to_r, dup, umplus
  622. .long r_from, plus, dup
  623. .long r_from, r_fetch, swap, to_r
  624. .long umplus, r_from, _or
  625. .long qbranch, um_slash_mod_l2
  626. .long to_r, drop, dolit, 1, plus, r_from
  627. .long branch, um_slash_mod_l3
  628. um_slash_mod_l2:
  629. .long drop
  630. um_slash_mod_l3:
  631. .long r_from
  632. .long donext, um_slash_mod_l1
  633. .long drop, swap, exit
  634. um_slash_mod_l4:
  635. .long drop, twodrop
  636. .long dolit, -1, dup, exit
  637. ;;; : M/MOD ( d n -- r q ) \ floored
  638. ;;; DUP 0< DUP >R
  639. ;;; IF NEGATE >R DNEGATE R>
  640. ;;; THEN >R DUP 0< IF R@ + THEN R> UM/MOD R>
  641. ;;; IF SWAP NEGATE SWAP THEN ;
  642. COLON m_slash_mod, "m/mod", 0
  643. .long dup, zero_less, dup, to_r
  644. .long qbranch, m_slash_mod_l1
  645. .long negate, to_r, dnegate, r_from
  646. m_slash_mod_l1:
  647. .long to_r, dup, zero_less
  648. .long qbranch, m_slash_mod_l2
  649. .long r_fetch, plus
  650. m_slash_mod_l2:
  651. .long r_from, um_slash_mod, r_from
  652. .long qbranch, m_slash_mod_l3
  653. .long swap, negate, swap
  654. m_slash_mod_l3:
  655. .long exit
  656. ;;; : /MOD ( n n -- r q ) OVER 0< SWAP M/MOD ;
  657. COLON slash_mod, "/mod", FLAG_NORMAL
  658. .long over, zero_less, swap, m_slash_mod, exit
  659. ;;; : MOD ( n n -- r ) /MOD DROP ;
  660. COLON mod, "mod", FLAG_NORMAL
  661. .long slash_mod, drop, exit
  662. ;;; : / ( n n -- q ) /MOD NIP ;
  663. COLON divide, "/", FLAG_NORMAL
  664. .long slash_mod, nip, exit
  665. ;;; .( Multiply )
  666. ;;; : UM* ( u1 u2 -- ud )
  667. ;;; 0 SWAP ( u1 0 u2 ) 15
  668. ;;; FOR DUP UM+ >R >R DUP UM+ R> + R>
  669. ;;; IF >R OVER UM+ R> + THEN
  670. ;;; NEXT ROT DROP ;
  671. CODE umult, "um*", FLAG_NORMAL
  672. ld.w %r4, [%r1]+
  673. ld.w %r5, [%r1]
  674. mltu.w %r4, %r5
  675. ld.w %r4, %alr
  676. ld.w [%r1], %r4
  677. sub %r1, BYTES_PER_CELL
  678. ld.w %r4, %ahr
  679. ld.w [%r1], %r4
  680. NEXT
  681. END_CODE
  682. ;;; : * ( n n -- n ) UM* DROP ;
  683. CODE times, "*", FLAG_NORMAL
  684. ld.w %r4, [%r1]+
  685. ld.w %r5, [%r1]
  686. mlt.w %r4, %r5
  687. ld.w %r4, %alr
  688. ld.w [%r1], %r4
  689. NEXT
  690. END_CODE
  691. ;;; : M* ( n n -- d )
  692. ;;; 2DUP XOR 0< >R ABS SWAP ABS UM* R> IF DNEGATE THEN ;
  693. CODE multd, "m*", FLAG_NORMAL
  694. ld.w %r4, [%r1]+
  695. ld.w %r5, [%r1]
  696. mlt.w %r4, %r5
  697. ld.w %r4, %alr
  698. ld.w [%r1], %r4
  699. ld.w %r4, %ahr
  700. sub %r1, BYTES_PER_CELL
  701. ld.w [%r1], %r4
  702. NEXT
  703. END_CODE
  704. ;;; : */MOD ( n n n -- r q ) >R M* R> M/MOD ;
  705. ;;; : */ ( n n n -- q ) */MOD NIP ;
  706. ;;; .( bit shifts )
  707. ;;; : 2* 2 * ;
  708. CODE _shl, "2*", FLAG_NORMAL
  709. ld.w %r4, [%r1]
  710. sla %r4, 1
  711. ld.w [%r1], %r4
  712. NEXT
  713. END_CODE
  714. ;;; : 2/ 2 / ;
  715. CODE _shra, "2/", FLAG_NORMAL
  716. ld.w %r4, [%r1]
  717. sra %r4, 1
  718. ld.w [%r1], %r4
  719. NEXT
  720. END_CODE
  721. ;;; : LSHIFT ( u u -- u ) UM+ DROP ;
  722. CODE lshift, "lshift", FLAG_NORMAL ; ( w u -- w )
  723. ld.w %r4, [%r1]+ ; shift
  724. ld.w %r5, [%r1] ; value
  725. sla %r5, %r4
  726. ld.w [%r1], %r5
  727. NEXT
  728. END_CODE
  729. ;;; : RSHIFT ( u u -- u ) UM+ DROP ;
  730. CODE rshift, "rshift", FLAG_NORMAL ; ( w u -- w )
  731. ld.w %r4, [%r1]+ ; shift
  732. ld.w %r5, [%r1] ; value
  733. srl %r5, %r4
  734. ld.w [%r1], %r5
  735. NEXT
  736. END_CODE
  737. ;;; .( Bits & Bytes )
  738. ;;; : CHAR+ ( b -- b ) [ =BYTE ] LITERAL + ;
  739. COLON char_plus, "char+", FLAG_NORMAL
  740. .long increment, exit
  741. ;;; : CHAR- ( b -- b ) [ =BYTE ] LITERAL - ;
  742. COLON char_minus, "char-", FLAG_NORMAL
  743. .long decrement, exit
  744. ;;; : BYTE+ ( b -- b ) [ =BYTE ] LITERAL + ;
  745. COLON byte_plus, "byte+", FLAG_NORMAL
  746. .long increment, exit
  747. ;;; : BYTE- ( b -- b ) [ =BYTE ] LITERAL - ;
  748. COLON byte_minus, "byte-", FLAG_NORMAL
  749. .long decrement, exit
  750. ;;; : CELL+ ( a -- a ) [ =CELL ] LITERAL + ;
  751. COLON cell_plus, "cell+", FLAG_NORMAL
  752. .long dolit, BYTES_PER_CELL, plus, exit
  753. ;;; : CELL- ( a -- a ) [ =CELL ] LITERAL - ;
  754. COLON cell_minus, "cell-", FLAG_NORMAL
  755. .long dolit, BYTES_PER_CELL, minus, exit
  756. ;;; : CELLS ( n -- n ) [ =CELL ] LITERAL * ;
  757. COLON cells, "cells", FLAG_NORMAL
  758. .long dolit, BYTES_PER_CELL, times, exit
  759. ;;; : BL ( -- 32 ) 32 ;
  760. COLON blank, "bl", FLAG_NORMAL
  761. .long dolit, 32, exit
  762. ;;; \ subsitute unprintable character with '.'
  763. ;;; : >CHAR ( c -- c )
  764. ;;; 127 AND DUP 127 BL WITHIN IF DROP [CHAR] . THEN ;
  765. COLON to_char, ">char", FLAG_NORMAL
  766. .long dolit, 0x7f, _and, dup
  767. .long dolit, 0x7f, blank, within
  768. .long qbranch, to_char_l1
  769. .long drop, dolit, '.'
  770. to_char_l1:
  771. .long exit
  772. ;;; : CHAR>LOWER ( c -- c )
  773. ;;; DUP [CHAR] A [ CHAR Z 1+ ] LITERAL WITHIN
  774. ;;; IF [ CHAR a CHAR A - ] LITERAL + THEN ;
  775. COLON char_to_lower, "char>lower", FLAG_NORMAL
  776. .long dup, dolit, 'A', dolit, 'Z' + 1, within
  777. .long qbranch, char_to_lower_l1
  778. .long dolit, 'a' - 'A', plus
  779. char_to_lower_l1:
  780. .long exit
  781. ;;; : CHAR>UPPER ( c -- c )
  782. ;;; DUP [CHAR] a [ CHAR z 1+ ] LITERAL WITHIN
  783. ;;; IF [ CHAR A CHAR a - ] LITERAL + THEN ;
  784. COLON char_to_upper, "char>upper", FLAG_NORMAL
  785. .long dup, dolit, 'a', dolit, 'z' + 1, within
  786. .long qbranch, char_to_upper_l1
  787. .long dolit, 'A' - 'a', plus
  788. char_to_upper_l1:
  789. .long exit
  790. ;;; : DEPTH ( -- n ) SP@ SP0 @ SWAP - 1 CELLS / ;
  791. COLON depth, "depth", FLAG_NORMAL
  792. .long sp_fetch, sp0, fetch, swap, minus
  793. .long dolit, 1, cells, divide, exit
  794. ;;; : PICK ( +n -- w ) 1+ CELLS SP@ + @ ;
  795. COLON pick, "pick", FLAG_NORMAL
  796. .long increment, cells, sp_fetch, plus, fetch, exit
  797. ;;; align to a CELL boundary
  798. ;;; : ALIGNED ( b -- a ) ; IMMEDIATE
  799. COLON aligned, "aligned", FLAG_IMMEDIATE
  800. .long dolit, BYTES_PER_CELL - 1, plus
  801. .long dolit, -BYTES_PER_CELL, _and, exit
  802. ;;; .( Memory access )
  803. ;;; : +! ( n a -- ) SWAP OVER @ + SWAP ! ;
  804. COLON plus_store, "+!", FLAG_NORMAL
  805. .long swap, over, fetch, plus, swap, store, exit
  806. ;;; : 2! ( d a -- ) SWAP OVER ! CELL+ ! ;
  807. COLON dstore, "2!", FLAG_NORMAL
  808. .long swap, over, store, cell_plus, store, exit
  809. ;;; : 2@ ( a -- d ) DUP CELL+ @ SWAP @ ;
  810. COLON dfetch, "2@", FLAG_NORMAL
  811. .long dup, cell_plus, fetch, swap, fetch, exit
  812. ;;; : COUNT ( b -- b +n ) DUP BYTE+ SWAP C@ ;
  813. COLON count, "count", FLAG_NORMAL
  814. .long dup, byte_plus, swap, cfetch, exit
  815. ;;; : HERE ( -- a ) CP @ ;
  816. COLON here, "here", FLAG_NORMAL
  817. .long cp, fetch, exit
  818. ;;; : PAD ( -- a ) HERE 80 + ;
  819. COLON pad, "pad", FLAG_NORMAL
  820. .long here, dolit, 80, plus, exit
  821. ;;; : TIB ( -- a ) #TIB CELL+ @ ;
  822. COLON tib, "tib", FLAG_NORMAL
  823. .long hash_tib, cell_plus, fetch, exit
  824. ;;; : NP ( -- a ) CP CELL+ ;
  825. COLON np, "np", FLAG_NORMAL
  826. .long cp, cell_plus, exit
  827. ;;; : LAST ( -- a ) NP CELL+ ;
  828. COLON last, "last", FLAG_NORMAL
  829. .long np, cell_plus, exit
  830. ;;; : (dovoc) ( -- ) R> CONTEXT ! ; COMPILE-ONLY
  831. COLON dovoc, "(dovoc)", FLAG_COMPILE_ONLY
  832. .long r_from, context, store, exit
  833. ;;; \ Make FORTH the context vocabulary
  834. ;;; : FORTH ( -- ) COMPILE (dovoc) [ =HEAD ] , [ =LINK ] , ;
  835. COLON forth, "forth", FLAG_NORMAL
  836. .long dovoc
  837. .long last_name ; vocabulary head pointer
  838. .long last_name ; vocabulary link pointer
  839. ;;; : @EXECUTE ( a -- ) @ ?DUP IF EXECUTE THEN ;
  840. COLON atexecute, "@execute", FLAG_NORMAL
  841. .long fetch, qdup, qbranch, atexecute_l1
  842. .long execute
  843. atexecute_l1:
  844. .long exit
  845. ;;; : CMOVE ( b b u -- )
  846. ;;; FOR AFT >R COUNT R@ C! R> 1+ THEN NEXT 2DROP ;
  847. CODE cmove, "cmove", FLAG_NORMAL
  848. ld.w %r4, [%r1]+ ; count
  849. ld.w %r5, [%r1]+ ; dst
  850. ld.w %r6, [%r1]+ ; src
  851. or %r4, %r4
  852. jreq cmove_done
  853. cmove_loop:
  854. ld.ub %r7, [%r6]+
  855. ld.b [%r5]+, %r7
  856. xsub %r4, 1
  857. jrne cmove_loop
  858. cmove_done:
  859. NEXT
  860. END_CODE
  861. ;;; \ compile to memory blocks
  862. ;;; : MEM= ( b b u -- f )
  863. CODE mem_equal, "mem=", FLAG_NORMAL
  864. ld.w %r4, [%r1]+ ; count
  865. ld.w %r5, [%r1]+ ; addr 2
  866. ld.w %r6, [%r1] ; addr 1
  867. or %r4, %r4
  868. jreq mem_equal_true
  869. mem_equal_loop:
  870. ld.ub %r7, [%r6]+
  871. ld.ub %r8, [%r5]+
  872. cmp %r7, %r8
  873. jrne mem_equal_false
  874. xsub %r4, 1
  875. jrne mem_equal_loop
  876. mem_equal_true:
  877. ld.w %r4, TRUE
  878. ld.w [%r1], %r4
  879. NEXT
  880. END_CODE
  881. mem_equal_false:
  882. ld.w %r4, FALSE
  883. ld.w [%r1], %r4
  884. NEXT
  885. END_CODE
  886. ;;; : -TRAILING ( b u -- b u )
  887. ;;; FOR AFT DUP R@ + C@ BL XOR
  888. ;;; IF R> BYTE+ EXIT THEN THEN
  889. ;;; NEXT 0 ;
  890. COLON minus_trailing, "-trailing", FLAG_NORMAL
  891. .long to_r
  892. minus_trailing_l1:
  893. .long dup, r_fetch, plus, cfetch, blank, _xor
  894. .long qbranch, minus_trailing_l2
  895. .long r_from, byte_plus, exit
  896. minus_trailing_l2:
  897. .long donext, minus_trailing_l1
  898. .long dolit, 0, exit
  899. ;;; : FILL ( b u c -- )
  900. ;;; SWAP FOR SWAP AFT 2DUP C! BYTE+ THEN NEXT 2DROP ;
  901. COLON fill, "fill", FLAG_NORMAL
  902. .long swap, to_r, swap
  903. fill_l1:
  904. .long twodup, cstore, byte_plus
  905. .long donext, fill_l1
  906. .long twodrop, exit
  907. ;;; : ERASE ( b u -- ) 0 FILL ;
  908. COLON erase, "erase", FLAG_NORMAL
  909. .long dolit, 0, fill, exit
  910. ;;; : PACK$ ( b u a -- a ) \ null terminated
  911. ;;; DUP >R 2DUP C! BYTE+ SWAP CMOVE R> ;
  912. COLON pack_dollar, "pack$", FLAG_NORMAL
  913. .long aligned, dup, to_r
  914. .long twodup, cstore, byte_plus
  915. .long swap, cmove, r_from, exit
  916. ;;; .( stack handling )
  917. ;;; \ usage example:
  918. ;;; \ 25 ( stack-size-in-cells )
  919. ;;; \ dup create my-stack 2 + cells allot
  920. ;;; \ mystack !
  921. ;;; \ stack = {size(N), ptr, value1, value2, ..., valueN}
  922. ;;; : stack-clear ( a -- )
  923. ;;; cell+ 0 swap ! ;
  924. COLON stack_clear, "stack-clear", FLAG_NORMAL
  925. .long cell_plus, dolit, 0, swap, store, exit
  926. ;;; : STACK-PUSH ( w a -- )
  927. ;;; DUP \ w a a
  928. ;;; @ \ w a size
  929. ;;; SWAP CELL+ \ w size ptr
  930. ;;; >R R@ @ 1+ \ w size index
  931. ;;; SWAP OVER \ w index size index
  932. ;;; < ABORT" stack overflow"
  933. ;;; \ w index
  934. ;;; DUP R@ ! \ w index
  935. ;;; CELLS R> + !
  936. ;;; ;
  937. COLON stack_push, "stack-push", FLAG_NORMAL
  938. .long dup, fetch, swap, cell_plus
  939. .long to_r, r_fetch, fetch, increment
  940. .long swap, over, less
  941. .long do_abort_quote
  942. FSTRING "stack overflow"
  943. .long dup, r_fetch, store
  944. .long cells, r_from, plus, store
  945. .long exit
  946. ;;; : STACK-POP ( a -- w )
  947. ;;; CELL+ >R R@ @ 1- DUP 0< abort" stack underflow"
  948. ;;; DUP R@ ! 1+ CELLS R> + @
  949. ;;; ;
  950. COLON stack_pop, "stack-pop", FLAG_NORMAL
  951. .long cell_plus, to_r, r_fetch, fetch
  952. .long decrement, dup, zero_less
  953. .long do_abort_quote
  954. FSTRING "stack underflow"
  955. .long dup, r_fetch, store, increment
  956. .long cells, r_from, plus, fetch
  957. .long exit
  958. ;;; .( Numeric Output ) \ single precision
  959. ;;; : DIGIT ( u -- c ) 9 OVER < 7 AND + [CHAR] 0 + ;
  960. COLON digit, "digit", FLAG_NORMAL
  961. .long dolit, 9, over, less, dolit, 7, _and, plus, dolit, '0', plus, exit
  962. ;;; : EXTRACT ( n base -- n c ) 0 SWAP UM/MOD SWAP DIGIT ;
  963. COLON extract, "extract", FLAG_NORMAL
  964. .long dolit, 0, swap, um_slash_mod, swap, digit, exit
  965. ;;; : <# ( -- ) PAD HLD ! ;
  966. COLON less_hash, "<#", FLAG_NORMAL
  967. .long pad, hld, store, exit
  968. ;;; : HOLD ( c -- ) HLD @ BYTE- DUP HLD ! C! ;
  969. COLON hold, "hold", FLAG_NORMAL
  970. .long hld, fetch, byte_minus, dup, hld, store, cstore, exit
  971. ;;; : # ( u -- u ) BASE @ EXTRACT HOLD ;
  972. COLON hash, "#", FLAG_NORMAL
  973. .long base, fetch, extract, hold, exit
  974. ;;; : #S ( u -- 0 ) BEGIN # DUP WHILE REPEAT ;
  975. COLON hash_s, "#s", FLAG_NORMAL
  976. hash_s_l1:
  977. .long hash, dup
  978. .long qbranch, hash_s_l2
  979. .long branch, hash_s_l1
  980. hash_s_l2:
  981. .long exit
  982. ;;; : SIGN ( n -- ) 0< IF [CHAR] - HOLD THEN ;
  983. COLON sign, "sign", FLAG_NORMAL
  984. .long zero_less, qbranch, sign_l1
  985. .long dolit, '-', hold
  986. sign_l1:
  987. .long exit
  988. ;;; : #> ( w -- b u ) DROP HLD @ PAD OVER - ;
  989. COLON hash_greater, "#>", FLAG_NORMAL
  990. .long drop, hld, fetch, pad, over, minus, exit
  991. ;;; : (str) ( w -- b u ) DUP >R ABS <# #S R> SIGN #> ;
  992. COLON paren_str, "(str)"
  993. .long dup, to_r, abs, less_hash, hash_s, r_from, sign, hash_greater, exit
  994. ;;; : HEX ( -- ) 16 BASE ! ;
  995. COLON hex, "hex", FLAG_NORMAL
  996. .long dolit, 16, base, store, exit
  997. ;;; : DECIMAL ( -- ) 10 BASE ! ;
  998. COLON decimal, "decimal", FLAG_NORMAL
  999. .long dolit, 10, base, store, exit
  1000. ;;; .( Numeric Input ) \ single precision
  1001. ;;; : DIGIT? ( c base -- u t )
  1002. ;;; >R CHAR>UPPER [CHAR] 0 - 9 OVER <
  1003. ;;; IF 7 - DUP 10 < OR THEN DUP R> U< ;
  1004. COLON digitq, "digit?", FLAG_NORMAL
  1005. .long to_r, char_to_lower, dolit, '0', minus
  1006. .long dolit, 9, over, less
  1007. .long qbranch, digitq_l1
  1008. .long dolit, 'a' - '0' - 10, minus ;*lower case*
  1009. .long dup, dolit, 10, less, _or
  1010. digitq_l1:
  1011. .long dup, r_from, uless, exit
  1012. ;;; : NUMBER? ( a -- n T, a F )
  1013. ;;; BASE @ >R 0 OVER COUNT ( a 0 b n)
  1014. ;;; OVER C@ [CHAR] $ =
  1015. ;;; IF HEX SWAP BYTE+ SWAP 1- THEN ( a 0 b' n')
  1016. ;;; OVER C@ [CHAR] - = >R ( a 0 b n)
  1017. ;;; SWAP R@ - SWAP R@ + ( a 0 b" n") ?DUP
  1018. ;;; IF 1- ( a 0 b n)
  1019. ;;; FOR DUP >R C@ BASE @ DIGIT?
  1020. ;;; WHILE SWAP BASE @ * + R> BYTE+
  1021. ;;; NEXT R@ ( ?sign) NIP ( b) IF NEGATE THEN SWAP
  1022. ;;; ELSE R> R> ( b index) 2DROP ( digit number) 2DROP 0
  1023. ;;; THEN DUP
  1024. ;;; THEN R> ( n ?sign) 2DROP R> BASE ! ;
  1025. COLON numberq, "number?", FLAG_NORMAL
  1026. .long base, fetch, to_r, dolit, 0, over, count
  1027. .long over, cfetch, dolit, '$', equal
  1028. .long qbranch, numberq_l1
  1029. .long hex, swap, byte_plus
  1030. .long swap, decrement
  1031. numberq_l1:
  1032. .long over, cfetch, dolit, '-', equal, to_r
  1033. .long swap, r_fetch, minus, swap, r_fetch, plus, qdup
  1034. .long qbranch, numberq_l6
  1035. .long decrement, to_r
  1036. numberq_l2:
  1037. .long dup, to_r, cfetch, base, fetch, digitq
  1038. .long qbranch, numberq_l4
  1039. .long swap, base, fetch, times, plus, r_from
  1040. .long byte_plus
  1041. .long donext, numberq_l2
  1042. .long r_fetch, swap, drop
  1043. .long qbranch, numberq_l3
  1044. .long negate
  1045. numberq_l3:
  1046. .long swap
  1047. .long branch, numberq_l5
  1048. numberq_l4:
  1049. .long r_from, r_from, twodrop, twodrop, dolit, 0
  1050. numberq_l5:
  1051. .long dup
  1052. numberq_l6:
  1053. .long r_from, twodrop
  1054. .long r_from, base, store, exit
  1055. ;;; .( Basic I/O )
  1056. ;;; : KEY? ( -- c T | F ) 'KEY? @EXECUTE ;
  1057. COLON key_query, "key?", FLAG_NORMAL
  1058. .long tkey_query, atexecute, exit
  1059. ;;; : KEY ( -- c ) BEGIN KEY? UNTIL ;
  1060. COLON key, "key", FLAG_NORMAL
  1061. key_l1:
  1062. .long key_query, qbranch, key_l1, exit
  1063. ;;; : EMIT ( c -- ) 'EMIT @EXECUTE ;
  1064. COLON emit, "emit", FLAG_NORMAL
  1065. .long temit, atexecute, exit
  1066. ;;; if key is pressed, wait for second key press
  1067. ;;; return true if the second key is enter
  1068. ;;; : ENOUGH? ( -- f ) KEY? DUP IF 2DROP KEY 13 = THEN ;
  1069. COLON enoughq, "enough?", FLAG_NORMAL
  1070. .long key_query, dup
  1071. .long qbranch, enoughq_l1
  1072. .long twodrop, key, dolit, 13, equal
  1073. enoughq_l1:
  1074. .long exit
  1075. ;;; : SPACE ( -- ) BL EMIT ;
  1076. COLON space, "space", FLAG_NORMAL
  1077. .long blank, emit, exit
  1078. ;;; : CHARS ( +n c -- ) SWAP 0 MAX FOR AFT DUP EMIT THEN NEXT DROP ;
  1079. COLON chars, "chars", FLAG_NORMAL
  1080. .long swap, dolit, 0, max
  1081. .long to_r, branch, chars_l2
  1082. chars_l1:
  1083. .long dup, emit
  1084. chars_l2:
  1085. .long donext, chars_l1
  1086. .long drop, exit
  1087. ;;; : SPACES ( +n -- ) BL CHARS ;
  1088. COLON spaces, "spaces", FLAG_NORMAL
  1089. .long blank, chars, exit
  1090. ;;; : do$ ( -- a )
  1091. ;;; R> R@ R> COUNT + ALIGNED >R SWAP >R ; COMPILE-ONLY
  1092. COLON do_dollar, "do$", FLAG_COMPILE_ONLY
  1093. .long r_from, r_fetch, r_from, count, plus
  1094. .long aligned, to_r, swap, to_r, exit
  1095. ;;; : ($") ( -- a ) do$ ; COMPILE-ONLY
  1096. COLON do_dollar_quote, "($\042)", FLAG_COMPILE_ONLY
  1097. .long do_dollar, exit
  1098. ;;; : TYPE ( b u -- ) FOR AFT COUNT EMIT THEN NEXT DROP ;
  1099. COLON type, "type", FLAG_NORMAL
  1100. .long to_r
  1101. .long branch, type_l2
  1102. type_l1:
  1103. .long dup, cfetch, emit, increment
  1104. type_l2:
  1105. .long donext, type_l1
  1106. .long drop, exit
  1107. ;;; : .$ ( a -- ) COUNT TYPE ;
  1108. COLON dot_dollar, ".$", FLAG_NORMAL
  1109. .long count, type, exit
  1110. ;;; : (.") ( -- ) do$ .$ ; COMPILE-ONLY
  1111. COLON do_dot_quote, "(.\042)", FLAG_COMPILE_ONLY
  1112. .long do_dollar, dot_dollar, exit
  1113. ;;; : CR ( -- ) 13 EMIT 10 EMIT ;
  1114. COLON cr, "cr", FLAG_NORMAL
  1115. .long dolit, carriage_return, emit
  1116. .long dolit, line_feed, emit, exit
  1117. ;;; : .R ( n +n -- ) >R (str) R> OVER - SPACES TYPE ;
  1118. COLON dot_r, ".r", FLAG_NORMAL
  1119. .long to_r, paren_str, r_from, over, minus, spaces, type, exit
  1120. ;;; : U.R ( u +n -- ) >R <# #S #> R> OVER - SPACES TYPE ;
  1121. COLON u_dot_r, "u.r", FLAG_NORMAL
  1122. .long to_r, less_hash, hash_s, hash_greater, r_from, over, minus, spaces, type, exit
  1123. ;;; : U. ( u -- ) <# #S #> SPACE TYPE ;
  1124. COLON u_dot, "u.", FLAG_NORMAL
  1125. .long less_hash, hash_s, hash_greater, space, type, exit
  1126. ;;; : . ( w -- ) BASE @ 10 XOR IF U. EXIT THEN (str) SPACE TYPE ;
  1127. COLON dot, ".", FLAG_NORMAL
  1128. .long base, fetch, dolit, 10, _xor
  1129. .long qbranch, dot_l1
  1130. .long u_dot, exit
  1131. dot_l1:
  1132. .long paren_str, space, type, exit
  1133. ;;; : DEC. ( w -- ) \ decimal display
  1134. ;;; BASE @ DECIMAL SWAP . BASE ! ;
  1135. COLON dec_dot, "dec.", FLAG_NORMAL
  1136. .long base, fetch, decimal, swap, dot, base, store, exit
  1137. ;;; : HEX. ( w -- ) \ hexadecimal display
  1138. ;;; BASE @ HEX SWAP . BASE ! ;
  1139. COLON hex_dot, "hex.", FLAG_NORMAL
  1140. .long base, fetch, hex, swap, dot, base, store, exit
  1141. ;;; : ? ( a -- ) @ . ;
  1142. COLON question, "?", FLAG_NORMAL
  1143. .long fetch, dot, exit
  1144. ;;; : H? ( h -- ) H@ . ;
  1145. COLON hquestion, "h?", FLAG_NORMAL
  1146. .long hfetch, dot, exit
  1147. ;;; : C? ( b -- ) C@ . ;
  1148. COLON cquestion, "c?", FLAG_NORMAL
  1149. .long cfetch, dot, exit
  1150. ;;; .( Parsing )
  1151. ;;; : (parse) ( b u c -- b u delta \ <string><char c> )
  1152. ;;; temp ! OVER >R DUP \ b u u
  1153. ;;; IF 1- temp @ BL =
  1154. ;;; IF \ b u' \ 'skip'
  1155. ;;; FOR COUNT temp @ SWAP - 0< INVERT WHILE
  1156. ;;; NEXT ( b) R> DROP 0 DUP EXIT \ all delim
  1157. ;;; THEN 1- R>
  1158. ;;; THEN OVER SWAP \ b' b' u' \ 'scan'
  1159. ;;; FOR COUNT temp @ SWAP - temp @ BL =
  1160. ;;; IF 0< THEN WHILE
  1161. ;;; NEXT DUP >R ELSE R> DROP DUP >R 1-
  1162. ;;; THEN OVER - R> R> - EXIT
  1163. ;;; THEN ( b u) OVER R> - ;
  1164. COLON paren_parse, "(parse)", FLAG_NORMAL
  1165. .long temp, store, over, to_r, dup
  1166. .long qbranch, paren_parse_l8
  1167. .long decrement, temp, fetch, blank, equal
  1168. .long qbranch, paren_parse_l3
  1169. .long to_r
  1170. paren_parse_l1:
  1171. .long blank, over, cfetch
  1172. .long minus, zero_less, invert
  1173. .long qbranch, paren_parse_l2
  1174. .long increment
  1175. .long donext, paren_parse_l1
  1176. .long r_from, drop, dolit, 0, dup, exit
  1177. paren_parse_l2:
  1178. .long r_from
  1179. paren_parse_l3:
  1180. .long over, swap
  1181. .long to_r
  1182. paren_parse_l4:
  1183. .long temp, fetch, over, cfetch, minus
  1184. .long temp, fetch, blank, equal
  1185. .long qbranch, paren_parse_l5
  1186. .long zero_less
  1187. paren_parse_l5:
  1188. .long qbranch, paren_parse_l6
  1189. .long increment
  1190. .long donext, paren_parse_l4
  1191. .long dup, to_r
  1192. .long branch, paren_parse_l7
  1193. paren_parse_l6:
  1194. .long r_from, drop, dup
  1195. .long increment, to_r
  1196. paren_parse_l7:
  1197. .long over, minus
  1198. .long r_from, r_from, minus, exit
  1199. paren_parse_l8:
  1200. .long over, r_from, minus, exit
  1201. ;;; : PARSE ( c -- b u \ <string> )
  1202. ;;; >R TIB >IN @ + #TIB @ >IN @ - R> (parse) >IN +! ;
  1203. COLON parse, "parse", FLAG_NORMAL
  1204. .long to_r, tib, to_in, fetch, plus
  1205. .long hash_tib, fetch, to_in, fetch, minus
  1206. .long r_from, paren_parse
  1207. .long to_in, plus_store, exit
  1208. ;;; : .( ( -- ) [CHAR] ) PARSE CR TYPE ; IMMEDIATE
  1209. COLON dot_paren, ".(", FLAG_IMMEDIATE
  1210. .long dolit, ')', parse, cr, type, exit
  1211. ;;; : ( ( -- ) [CHAR] ) PARSE 2DROP ; IMMEDIATE
  1212. COLON paren, "(", FLAG_IMMEDIATE
  1213. .long dolit, ')', parse, twodrop, exit
  1214. ;;; : \ ( -- ) #TIB @ >IN ! ; IMMEDIATE
  1215. COLON backslash, "\\", FLAG_IMMEDIATE
  1216. .long hash_tib, fetch, to_in, store, exit
  1217. ;;; : CHAR ( -- c ) BL PARSE DROP C@ ;
  1218. COLON char, "char", FLAG_NORMAL
  1219. .long blank, parse, drop, cfetch, exit
  1220. ;;; : [CHAR] ( -- c ) CHAR LITERAL ; FLAG_IMMEDIATE FLAG_COMPILE_ONLY
  1221. COLON bracket_char, "[char]", FLAG_IMMEDIATE + FLAG_COMPILE_ONLY
  1222. .long char, literal, exit
  1223. ;;; : CTRL ( -- c ) CHAR $001F AND ;
  1224. COLON ctrl, "ctrl", FLAG_NORMAL
  1225. .long char, dolit, 0x1f, _and, exit
  1226. ;;; : [CTRL] ( -- c ) CTRL LITERAL ; FLAG_IMMEDIATE FLAG_COMPILE_ONLY
  1227. COLON bracket_ctrl, "[ctrl]", FLAG_IMMEDIATE + FLAG_COMPILE_ONLY
  1228. .long ctrl, literal, exit
  1229. ;;; this puts the name in the right place for being the next defined item
  1230. ;;; : TOKEN ( -- a \ <string> ) \ and reserve space for dictionary header
  1231. ;;; BL PARSE 31 MIN NP @ [ =DICTIONARY-HEADER-CELLS ] CELLS + PACK$ ;
  1232. COLON token, "token", FLAG_NORMAL
  1233. .long blank, parse
  1234. .long dolit, 31, min
  1235. .long np, fetch, dolit, DICTIONARY_HEADER_CELLS, cells, plus, pack_dollar
  1236. .long exit
  1237. ;;; : WORD ( c -- a \ <string> ) PARSE HERE PACK$ ;
  1238. COLON word, "word", FLAG_NORMAL
  1239. .long parse, here, pack_dollar, exit
  1240. ;;; .( Dictionary Search )
  1241. ;;; : NAME>CODE ( na -- ca ) [ =DICTIONARY-CODE-OFFSET ] LITERAL CELLS - ;
  1242. COLON name_to_code, "name>code", FLAG_NORMAL
  1243. .long dolit, DICTIONARY_CODE_OFFSET_BYTES, minus, exit
  1244. ;;; : NAME>PARAM ( na -- pa ) [ =DICTIONARY-PARAM-OFFSET ] LITERAL CELLS - ;
  1245. COLON name_to_param, "name>param", FLAG_NORMAL
  1246. .long dolit, DICTIONARY_PARAM_OFFSET_BYTES, minus, exit
  1247. ;;; : NAME>FLAGS ( na -- fa ) [ =DICTIONARY-FLAGS-OFFSET ] LITERAL CELLS - ;
  1248. COLON name_to_flags, "name>flags", FLAG_NORMAL
  1249. .long dolit, DICTIONARY_FLAGS_OFFSET_BYTES, minus, exit
  1250. ;;; : NAME>LINK ( na -- la ) [ =DICTIONARY-LINK-OFFSET ] LITERAL CELLS - ;
  1251. COLON name_to_link, "name>link", FLAG_NORMAL
  1252. .long dolit, DICTIONARY_LINK_OFFSET_BYTES, minus, exit
  1253. ;;; : CODE>NAME ( ca -- na ) [ =DICTIONARY-CODE-OFFSET ] LITERAL CELLS + ;
  1254. COLON code_to_name, "code>name", FLAG_NORMAL
  1255. .long dolit, DICTIONARY_CODE_OFFSET_BYTES, plus, exit
  1256. ;;; return TRUE if counted strings are equal
  1257. ;;; : SAME? ( a a -- a a f )
  1258. ;;; 2DUP COUNT NIP SWAP COUNT NIP 2DUP =
  1259. ;;; IF DROP \ a a u
  1260. ;;; FOR AFT OVER R@ + BYTE+ C@
  1261. ;;; OVER R@ + BYTE+ C@ XOR
  1262. ;;; IF R> DROP FALSE EXIT THEN THEN
  1263. ;;; NEXT TRUE
  1264. ;;; ELSE 2DROP FALSE
  1265. ;;; THEN ;
  1266. .if PREFER_FORTH_CODE
  1267. COLON sameq, "same?", FLAG_NORMAL
  1268. .long twodup, count, nip, swap, count, nip, twodup, equal
  1269. .long qbranch, same_l3
  1270. .long drop, to_r
  1271. .long branch, same_l2
  1272. same_l1:
  1273. .long over, r_fetch, plus, byte_plus, cfetch
  1274. .long over, r_fetch, plus, byte_plus, cfetch
  1275. .long _xor
  1276. .long qbranch, same_l2
  1277. .long r_from, drop, dolit, FALSE, exit
  1278. same_l2:
  1279. .long donext, same_l1
  1280. .long dolit, TRUE, exit
  1281. same_l3:
  1282. .long twodrop, dolit, FALSE, exit
  1283. .else
  1284. CODE sameq, "same?", FLAG_NORMAL
  1285. ld.w %r4, [%r1] ; address 1
  1286. xld.w %r5, [%r1 + 4] ; address 2
  1287. ld.ub %r6, [%r4]+ ; count 1
  1288. ld.ub %r7, [%r5]+ ; count 2
  1289. cmp %r6, %r7 ; counts must be equal
  1290. jrne sameq_false ; ...no
  1291. sameq_loop:
  1292. ld.ub %r7,[%r4]+ ; get byte from string 1
  1293. ld.ub %r8,[%r5]+ ; get byte from string 2
  1294. cmp %r7, %r8 ; check if equal
  1295. jrne sameq_false ; ..not equal => false result
  1296. sub %r6, 1 ; decrement counter
  1297. jrne sameq_loop ; go back for more
  1298. sub %r1, BYTES_PER_CELL
  1299. ld.w %r4, TRUE ; matched
  1300. ld.w [%r1], %r4 ; ..
  1301. NEXT
  1302. sameq_false:
  1303. sub %r1, BYTES_PER_CELL
  1304. ld.w %r4, FALSE ; match failed
  1305. xld.w [%r1], %r4 ; ..
  1306. NEXT
  1307. END_CODE
  1308. .endif
  1309. ;;; : find ( a va -- ca na, a F )
  1310. ;;; BEGIN @ DUP \ a na na
  1311. ;;; IF \ a na
  1312. ;;; SAME? 0= \ a na f
  1313. ;;; ELSE \ a na
  1314. ;;; DROP FALSE EXIT \ a F
  1315. ;;; THEN
  1316. ;;; WHILE NAME>LINK \ a la
  1317. ;;; REPEAT
  1318. ;;; \ a na
  1319. ;;; NIP DUP NAME>CODE SWAP ;
  1320. .if PREFER_FORTH_CODE
  1321. COLON find, "find", FLAG_NORMAL
  1322. find_l1:
  1323. .long fetch, dup, qbranch, find_l2
  1324. .long sameq, zero_equal
  1325. .long branch, find_l3
  1326. find_l2:
  1327. .long drop, dolit, FALSE
  1328. .long exit
  1329. find_l3:
  1330. .long qbranch, find_l4
  1331. .long name_to_link, branch, find_l1
  1332. find_l4:
  1333. .long nip, dup, name_to_code, swap
  1334. .long exit
  1335. .else
  1336. CODE find, "find", FLAG_NORMAL
  1337. ld.w %r4, [%r1] ; va
  1338. find_loop:
  1339. ld.w %r4, [%r4]
  1340. or %r4, %r4
  1341. jreq find_not_found
  1342. ;; comparison of counted strings is inlined for speed
  1343. xld.w %r5, [%r1 + 4] ; a
  1344. ld.w %r6, %r4
  1345. ld.ub %r7, [%r5]+ ; count 1
  1346. ld.ub %r8, [%r6]+ ; count 2
  1347. cmp %r7, %r8 ; counts must be equal
  1348. jrne find_next ; ...no
  1349. find_cmp_loop:
  1350. ld.ub %r8,[%r5]+ ; get 1 byte from string 1
  1351. ld.ub %r9,[%r6]+ ; get 1 byte from string 2
  1352. cmp %r8, %r9 ; check if equal
  1353. jrne find_next ; ..not equal => false result
  1354. sub %r7, 1 ; decrement counter
  1355. jrne find_cmp_loop ; go back for more bytes
  1356. find_found:
  1357. ld.w [%r1], %r4 ; na
  1358. xld.w %r5, DICTIONARY_CODE_OFFSET_BYTES
  1359. sub %r4, %r5 ; NAME>CODE
  1360. xld.w [%r1 + 4], %r4 ; ca
  1361. NEXT
  1362. find_next:
  1363. xld.w %r5, DICTIONARY_LINK_OFFSET_BYTES
  1364. jp.d find_loop ; try next word (delayed)
  1365. sub %r4, %r5 ; NAME>LINK
  1366. find_not_found:
  1367. ld.w %r4, FALSE
  1368. ld.w [%r1], %r4 ; F
  1369. NEXT
  1370. END_CODE
  1371. .endif
  1372. ;;; : NAME? ( a -- ca na, a F )
  1373. ;;; CONTEXT DUP 2@ XOR IF CELL- THEN >R \ context<>also
  1374. ;;; BEGIN R> CELL+ DUP >R @ ?DUP
  1375. ;;; WHILE find ?DUP
  1376. ;;; UNTIL R> DROP EXIT THEN R> DROP 0 ;
  1377. COLON nameq, "name?", FLAG_NORMAL
  1378. .long context, dup, dfetch, _xor
  1379. .long qbranch, nameq_l1
  1380. .long cell_minus
  1381. nameq_l1:
  1382. .long to_r
  1383. nameq_l2:
  1384. .long r_from, cell_plus, dup, to_r
  1385. .long fetch, qdup
  1386. .long qbranch, nameq_l3
  1387. .long find, qdup
  1388. .long qbranch, nameq_l2
  1389. .long r_from, drop, exit
  1390. nameq_l3:
  1391. .long r_from, drop
  1392. .long dolit, 0, exit
  1393. ;;; .( Terminal )
  1394. ;;; : ^H ( b b b -- b b b ) \ backspace
  1395. ;;; >R OVER R@ < DUP
  1396. ;;; IF [ CTRL H ] LITERAL 'ECHO @EXECUTE THEN R> + ;
  1397. COLON bksp, "^h", FLAG_NORMAL
  1398. .long to_r, over, r_from, swap, over, _xor
  1399. .long qbranch, bksp_l1
  1400. .long dolit, backspace, techo, atexecute, dolit, 1, minus
  1401. .long blank, techo, atexecute
  1402. .long dolit, backspace, techo, atexecute
  1403. bksp_l1:
  1404. .long exit
  1405. ;;; : TAP ( bot eot cur key -- bot eot cur )
  1406. ;;; DUP 'ECHO @EXECUTE OVER C! 1+ ;
  1407. COLON tap, "tap", FLAG_NORMAL
  1408. .long dup, techo, atexecute, over, cstore, increment, exit
  1409. ;;; : kTAP ( bot eot cur key -- bot eot cur )
  1410. ;;; DUP 13 XOR
  1411. ;;; IF [ CTRL H ] LITERAL XOR IF BL TAP ELSE ^H THEN EXIT
  1412. ;;; THEN DROP NIP DUP ;
  1413. COLON ktap, "ktap", FLAG_NORMAL
  1414. .long dup, dolit, carriage_return, _xor
  1415. .long qbranch, ktap_l2
  1416. .long dolit, delete, _xor
  1417. .long qbranch, ktap_l1
  1418. .long blank, tap, exit
  1419. ktap_l1:
  1420. .long bksp, exit
  1421. ktap_l2:
  1422. .long drop, swap, drop, dup, exit
  1423. ;;; : accept ( b u -- b u2 )
  1424. ;;; OVER + OVER
  1425. ;;; BEGIN 2DUP XOR
  1426. ;;; WHILE KEY DUP BL - 95 U<
  1427. ;;; IF TAP ELSE 'TAP @EXECUTE THEN
  1428. ;;; REPEAT DROP OVER - ;
  1429. COLON accept, "accept", FLAG_NORMAL
  1430. .long over, plus, over
  1431. accept_l1:
  1432. .long twodup, _xor, qbranch, accept_l4
  1433. .long key, dup, blank, minus, dolit, 95, uless
  1434. .long qbranch, accept_l2
  1435. .long tap, branch, accept_l3
  1436. accept_l2:
  1437. .long ttap, atexecute
  1438. accept_l3:
  1439. .long branch, accept_l1
  1440. accept_l4:
  1441. .long drop, over, minus, exit
  1442. ;;; : EXPECT ( b u -- ) 'EXPECT @EXECUTE SPAN ! DROP ;
  1443. colon expect, "expect", FLAG_NORMAL
  1444. .long texpect, atexecute, span, store, drop, exit
  1445. ;;; : QUERY ( -- )
  1446. ;;; TIB 256 'EXPECT @EXECUTE #TIB ! 0 NIP >IN ! ;
  1447. COLON query, "query", FLAG_NORMAL
  1448. .long tib, dolit, 256, texpect, atexecute, hash_tib, store
  1449. .long drop, dolit, 0, to_in, store, exit
  1450. ;;; .( File input - substitutes for accept above )
  1451. ;;; CREATE SOURCE-ID 0 ,
  1452. VARIABLE source_id, "source-id", FLAG_NORMAL
  1453. .long 0
  1454. ;;; : FILE-READER ( b u -- b u2 )
  1455. ;;; OVER SWAP SOURCE-ID @ READ-LINE \ b u2 f ior
  1456. ;;; ?DUP IF CR ." read error = " . CR \ b u2
  1457. ;;; SOURCE-ID @ CLOSE-FILE DROP
  1458. ;;; 2DROP HAND
  1459. ;;; TRUE ABORT" file error"
  1460. ;;; THEN
  1461. ;;; IF EXIT
  1462. ;;; ELSE SOURCE-ID @ CLOSE-FILE DROP
  1463. ;;; FILEID-STACK STACK-POP DUP SOURCE-ID !
  1464. ;;; 0= IF HAND THEN
  1465. ;;; THEN
  1466. ;;; ;
  1467. COLON file_reader, "file-reader", FLAG_NORMAL
  1468. .long over, swap, source_id, fetch, read_line
  1469. .long qdup, qbranch, file_reader_l1
  1470. .long cr, do_dot_quote
  1471. FSTRING "read error = "
  1472. .long dot, cr
  1473. .long source_id, fetch, close_file, drop
  1474. .long twodrop, hand
  1475. .long dolit, TRUE, do_abort_quote
  1476. FSTRING "file error"
  1477. file_reader_l1:
  1478. .long qbranch, file_reader_l2
  1479. .long exit
  1480. file_reader_l2:
  1481. .long source_id, fetch, close_file, drop
  1482. .long fileid_stack, stack_pop, dup, source_id, store
  1483. .long zero_equal, qbranch, file_reader_l3
  1484. .long hand
  1485. file_reader_l3:
  1486. .long exit
  1487. ;;; .( Error handling )
  1488. ;;; : CATCH ( ca -- err#/0 )
  1489. ;;; SP@ >R HANDLER @ >R RP@ HANDLER !
  1490. ;;; EXECUTE
  1491. ;;; R> HANDLER ! R> DROP 0 ;
  1492. COLON catch, "catch", FLAG_NORMAL
  1493. .long sp_fetch
  1494. .long to_r, handler, fetch, to_r
  1495. .long rp_fetch, handler, store, execute
  1496. .long r_from, handler, store
  1497. .long r_from, drop, dolit, 0, exit
  1498. ;;; : THROW ( err# -- err# )
  1499. ;;; HANDLER @ RP! R> HANDLER ! R> SWAP >R SP! DROP R> ;
  1500. COLON throw, "throw", FLAG_NORMAL
  1501. .long handler, fetch, rp_store
  1502. .long r_from, handler, store
  1503. .long r_from, swap, to_r, sp_store
  1504. .long drop, r_from, exit
  1505. ;;; VARIABLE NULL$
  1506. VARIABLE null_dollar, "null$", FLAG_NORMAL
  1507. .long 0
  1508. ;;; : ABORT ( -- ) NULL$ THROW ;
  1509. COLON abort, "abort", FLAG_NORMAL
  1510. .long null_dollar, throw, exit
  1511. ;;; : (abort") ( f -- ) IF do$ THROW THEN do$ DROP ; COMPILE-ONLY
  1512. COLON do_abort_quote, "(abort\042)", FLAG_COMPILE_ONLY
  1513. .long qbranch, do_abort_quote_l1
  1514. .long do_dollar, throw
  1515. do_abort_quote_l1:
  1516. .long do_dollar, drop, exit
  1517. ;;; .( Interpret )
  1518. ;;; : $INTERPRET ( a -- )
  1519. ;;; NAME? ?DUP
  1520. ;;; IF @ [ =COMP ] LITERAL AND
  1521. ;;; ABORT" compile ONLY" EXECUTE EXIT
  1522. ;;; THEN
  1523. ;;; 'NUMBER @EXECUTE
  1524. ;;; IF EXIT THEN THROW ;
  1525. COLON dollar_interpret, "$interpret", FLAG_NORMAL
  1526. .long nameq, qdup
  1527. .long qbranch, dollar_interpret_l1
  1528. .long name_to_flags, fetch, dolit, FLAG_COMPILE_ONLY, _and
  1529. .long do_abort_quote
  1530. FSTRING " compile only "
  1531. .long execute
  1532. .long exit
  1533. dollar_interpret_l1:
  1534. .long tnumber, atexecute
  1535. .long qbranch, dollar_interpret_l2
  1536. .long exit
  1537. dollar_interpret_l2:
  1538. .long throw
  1539. ;;; : [ ( -- ) ['] $INTERPRET 'EVAL ! ; IMMEDIATE
  1540. COLON left_bracket, "[", FLAG_IMMEDIATE
  1541. .long dolit, dollar_interpret, teval, store, exit
  1542. ;;; : .OK ( -- ) ['] $INTERPRET 'EVAL @ = IF ." ok" THEN CR ;
  1543. COLON dot_ok, ".ok", FLAG_NORMAL
  1544. .long dolit, dollar_interpret, teval, fetch, equal
  1545. .long qbranch, dot_ok_l1
  1546. .long do_dot_quote
  1547. FSTRING " Ok"
  1548. dot_ok_l1:
  1549. .long cr, exit
  1550. ;;; : ?STACK ( -- ) DEPTH 0< IF $" underflow" THROW THEN ;
  1551. COLON qstack, "?stack", FLAG_NORMAL
  1552. .long depth, zero_less
  1553. .long do_abort_quote
  1554. FSTRING " underflow"
  1555. .long exit
  1556. ;;; : EVAL ( -- )
  1557. ;;; BEGIN TOKEN DUP C@
  1558. ;;; WHILE 'EVAL @EXECUTE ?STACK
  1559. ;;; REPEAT DROP 'PROMPT @EXECUTE ;
  1560. COLON eval, "eval", FLAG_NORMAL
  1561. eval_l1:
  1562. .long token, dup, cfetch
  1563. .long qbranch, eval_l2
  1564. .long teval, atexecute, qstack
  1565. .long branch, eval_l1
  1566. eval_l2:
  1567. .long drop, tprompt, atexecute, exit
  1568. ;;; .( Device I/O )
  1569. ;;; CODE IO? ( -- f ) \ FFFF is an impossible character
  1570. ;;; XOR BX, BX
  1571. ;;; MOV DL, # $0FF \ input
  1572. ;;; MOV AH, # 6 \ MS-DOS Direct Console I/O
  1573. ;;; INT $021
  1574. ;;; 0<> IF \ ?key ready
  1575. ;;; OR AL, AL
  1576. ;;; 0= IF \ ?extended ascii code
  1577. ;;; INT $021
  1578. ;;; MOV BH, AL \ extended code in msb
  1579. ;;; ELSE MOV BL, AL
  1580. ;;; THEN
  1581. ;;; PUSH BX
  1582. ;;; MOVE BX, # -1
  1583. ;;; THEN
  1584. ;;; PUSH BX
  1585. ;;; NEXT
  1586. ;;; END-CODE
  1587. ;;; input character
  1588. CODE rx_query, "rx?", FLAG_NORMAL ; ( -- c T | F )
  1589. xcall Serial_InputAvailable
  1590. or %r4, %r4
  1591. jreq rx_query_no_character
  1592. xcall Serial_GetChar
  1593. sub %r1, BYTES_PER_CELL
  1594. ld.w [%r1], %r4
  1595. ld.w %r4, TRUE
  1596. rx_query_no_character:
  1597. sub %r1, BYTES_PER_CELL
  1598. ld.w [%r1], %r4
  1599. NEXT
  1600. END_CODE
  1601. ;;; output a character
  1602. CODE tx_store, "tx!", FLAG_NORMAL ; ( c -- )
  1603. ld.w %r6, [%r1]+
  1604. xcall Serial_PutChar
  1605. NEXT
  1606. END_CODE
  1607. ;;; : !IO ( -- ) ; IMMEDIATE \ initialize I/O device
  1608. ;;; *missing*
  1609. ;;; .( Shell )
  1610. ;;; : PRESET ( -- ) SP0 @ SP! [ =TIB ] LITERAL #TIB CELL+ !
  1611. ;;; FILESYSTEM-CLOSE-ALL FILEID-STACK STACK-CLEAR
  1612. ;;; 0 SOURCE-ID ! ;
  1613. COLON preset, "preset", FLAG_NORMAL
  1614. .long sp0, fetch, sp_store
  1615. .long dolit, terminal_buffer, hash_tib, cell_plus, store
  1616. .long filesystem_close_all
  1617. .long fileid_stack, stack_clear
  1618. .long dolit, 0, source_id, store
  1619. .long exit
  1620. ;;; : XIO ( a a a a -- ) \ reset 'TAP 'ECHO 'PROMPT 'EXPECT
  1621. ;;; ['] accept 'EXPECT ! 'TAP ! 'ECHO ! 'PROMPT ! ;
  1622. COLON xio, "xio", FLAG_NORMAL
  1623. .long ttap, store
  1624. .long techo, store
  1625. .long tprompt, store
  1626. .long texpect, store
  1627. .long exit
  1628. ;;; \ first cell stack size
  1629. ;;; \ second cell is the index
  1630. ;;; 20 DUP CREATE FILEID-STACK 2 + CELLS ALLOT
  1631. ;;; FILEID-STACK !
  1632. fileid_stack_length = 20
  1633. VARIABLE fileid_stack, "fileid-stack", FLAG_NORMAL
  1634. .long fileid_stack_length ; size
  1635. .long 0 ; index
  1636. ;; there must be the 'size' field above
  1637. .rept fileid_stack_length
  1638. .long 0
  1639. .endr
  1640. ;;; : INCLUDE-FILE ( fileid -- )
  1641. ;;; SOURCE-ID @ FILEID-STACK STACK-PUSH
  1642. ;;; SOURCE-ID !
  1643. ;;; ['] FILE-READER ['] PACE ['] DROP ['] kTAP XIO ;
  1644. COLON include_file, "include-file", FLAG_NORMAL
  1645. .long source_id, fetch, fileid_stack, stack_push
  1646. .long source_id, store
  1647. .long dolit, file_reader, dolit, 0, dolit, drop, dolit, ktap, xio, exit
  1648. ;;; : INCLUDED ( b u -- )
  1649. ;;; R/O OPEN-FILE \ fileid ior
  1650. ;;; ?DUP IF CR ." open error = " . DROP
  1651. ;;; ELSE CR INCLUDE-FILE
  1652. ;;; THEN ;
  1653. COLON included, "included", FLAG_NORMAL
  1654. .long readonly, open_file
  1655. .long qdup, qbranch, include_quote_l1
  1656. .long cr, do_dot_quote
  1657. FSTRING "open error = "
  1658. .long dot, drop, exit
  1659. include_quote_l1:
  1660. .long hash_tib, fetch, to_in, store ; empty the buffer
  1661. .long cr, include_file, exit
  1662. ;;; : INCLUDE" ( -- \ <string>" )
  1663. ;;; [CHAR] " PARSE INCLUDED ;
  1664. COLON include_quote, "include\042", FLAG_NORMAL
  1665. .long dolit, '\"', parse, included, exit
  1666. ;;; : INCLUDE ( -- \ <string> )
  1667. ;;; BL PARSE INCLUDED ;
  1668. COLON include, "include", FLAG_NORMAL
  1669. .long blank, parse, included, exit
  1670. ;;; : HAND ( -- )
  1671. ;;; ['] accept ['] .OK 'EMIT @ ['] kTAP XIO ;
  1672. COLON hand, "hand", FLAG_NORMAL
  1673. .long dolit, accept, dolit, dot_ok, temit, fetch, dolit, ktap, xio
  1674. .long hash_tib, fetch, to_in, store ; empty the buffer
  1675. .long exit
  1676. ;;; CREATE I/O ' ?RX , ' TX! , \ defaults
  1677. ;;; ** Missing **
  1678. ;;; : CONSOLE ( -- ) I/O 2@ 'KEY? 2! HAND ;
  1679. COLON console, "console", FLAG_NORMAL
  1680. .long dolit, rx_query, tkey_query, store
  1681. .long dolit, tx_store, temit, store
  1682. .long hand, exit
  1683. ;;; : que ( -- ) QUERY EVAL ;
  1684. ; COLON que, "que", FLAG_NORMAL
  1685. ; .long query, eval, exit
  1686. ;;; : QUIT ( -- ) \ clear return stack ONLY
  1687. ;;; RP0 @ RP!
  1688. ;;; BEGIN [COMPILE] [
  1689. ;;; BEGIN ['] que CATCH ?DUP
  1690. ;;; UNTIL ( a)
  1691. ;;; CONSOLE NULL$ OVER XOR
  1692. ;;; IF CR TIB #TIB @ TYPE
  1693. ;;; CR >IN @ [CHAR] ^ CHARS
  1694. ;;; CR .$ ." ? "
  1695. ;;; THEN PRESET
  1696. ;;; AGAIN ;
  1697. COLON quit, "quit", FLAG_NORMAL
  1698. .long rp0, fetch, rp_store
  1699. quit_l1:
  1700. .long left_bracket
  1701. quit_l2:
  1702. .long query
  1703. .long dolit, eval, catch
  1704. .long qdup
  1705. .long qbranch, quit_l2
  1706. .long tprompt, fetch, to_r
  1707. .long console, null_dollar, over, _xor
  1708. .long qbranch, quit_l3
  1709. .long space, count, type
  1710. .long do_dot_quote
  1711. FSTRING " ? "
  1712. quit_l3:
  1713. .long r_from, dolit, dot_ok, _xor
  1714. .long qbranch, quit_l4
  1715. .long dolit, '?', emit
  1716. quit_l4:
  1717. .long preset
  1718. .long branch, quit_l1
  1719. ;;; .( Compiler Primitives )
  1720. ;;; : ' ( -- ca \ <string> ) TOKEN NAME? IF EXIT THEN THROW ;
  1721. COLON tick, "'", FLAG_NORMAL
  1722. .long token, nameq
  1723. .long qbranch, tick_l1
  1724. .long exit
  1725. tick_l1:
  1726. .long throw, exit
  1727. ;;; : ['] ( -- \ <string> ) ' LITERAL ; IMMEDIATE COMPILE_ONLY
  1728. ;;; \ runtime ( -- ca )
  1729. COLON bracket_tick, "[']", FLAG_IMMEDIATE + FLAG_COMPILE_ONLY
  1730. .long tick, literal, exit
  1731. ;;; : ALLOT ( n -- ) CP +! ;
  1732. COLON allot, "allot", FLAG_NORMAL
  1733. .long cp, plus_store, exit
  1734. ;;; : , ( w -- ) HERE ALIGNED DUP CELL+ CP ! ! ;
  1735. COLON comma, ",", FLAG_NORMAL
  1736. .long here, aligned, dup, cell_plus, cp
  1737. .long store, store, exit
  1738. ;;; : c, ( w -- ) HERE DUP CHAR+ CP ! C! ;
  1739. COLON c_comma, "c,", FLAG_NORMAL
  1740. .long here, dup, char_plus, cp
  1741. .long store, cstore, exit
  1742. ;;; : [COMPILE] ( -- \ <string> ) ' , ; IMMEDIATE
  1743. COLON bracket_compile, "[compile]", FLAG_IMMEDIATE
  1744. .long tick, comma, exit
  1745. ;;; : COMPILE ( -- ) R> DUP @ , CELL+ >R ; COMPILE-ONLY
  1746. COLON compile, "compile", FLAG_COMPILE_ONLY
  1747. .long r_from, dup, fetch, comma, cell_plus, to_r, exit
  1748. ;;; : LITERAL ( w -- ) COMPILE (dolit) , ; IMMEDIATE
  1749. COLON literal, "literal", FLAG_IMMEDIATE
  1750. .long compile, dolit, comma, exit
  1751. ;;; : $," ( -- \ <string>" ) [CHAR] " PARSE HERE PACK$ C@ 1+ ALLOT ;
  1752. COLON dollar_comma_quote, "$,\042", FLAG_NORMAL
  1753. .long dolit, '\"', parse, here, pack_dollar, cfetch, increment, allot, exit
  1754. ;;; : RECURSE ( -- ) LAST @ CURRENT @ ! ; IMMEDIATE
  1755. COLON recurse, "recurse", FLAG_IMMEDIATE
  1756. .long last, fetch, current, fetch, store, exit
  1757. ;;; .( Structures )
  1758. ;;; : FOR ( -- a ) COMPILE >R HERE ; IMMEDIATE
  1759. COLON for, "for", FLAG_IMMEDIATE
  1760. .long compile, to_r, here, exit
  1761. ;;; : BEGIN ( -- a ) HERE ; IMMEDIATE
  1762. COLON begin, "begin", FLAG_IMMEDIATE
  1763. .long here, exit
  1764. ;;; : NEXT ( a -- ) COMPILE (next) , ; IMMEDIATE
  1765. COLON next, "next", FLAG_IMMEDIATE
  1766. .long compile, donext, comma, exit
  1767. ;;; : UNTIL ( a -- ) COMPILE ?branch , ; IMMEDIATE
  1768. COLON until, "until", FLAG_IMMEDIATE
  1769. .long compile, qbranch, comma, exit
  1770. ;;; : AGAIN ( a -- ) COMPILE branch , ; IMMEDIATE
  1771. COLON again, "again", FLAG_IMMEDIATE
  1772. .long compile, branch, comma, exit
  1773. ;;; : IF ( -- A ) COMPILE ?branch HERE 0 , ; IMMEDIATE
  1774. COLON if, "if", FLAG_IMMEDIATE
  1775. .long compile, qbranch, here, dolit, 0, comma, exit
  1776. ;;; : AHEAD ( -- A ) COMPILE branch HERE 0 , ; IMMEDIATE
  1777. COLON ahead, "ahead", FLAG_IMMEDIATE
  1778. .long compile, branch, here, dolit, 0, comma, exit
  1779. ;;; : REPEAT ( A a -- ) [COMPILE] AGAIN HERE SWAP ! ; IMMEDIATE
  1780. COLON repeat, "repeat", FLAG_IMMEDIATE
  1781. .long again, here, swap, store, exit
  1782. ;;; : THEN ( A -- ) HERE SWAP ! ; IMMEDIATE
  1783. COLON then, "then", FLAG_IMMEDIATE
  1784. .long here, swap, store, exit
  1785. ;;; : AFT ( a -- a A ) DROP [COMPILE] AHEAD [COMPILE] BEGIN SWAP ; IMMEDIATE
  1786. COLON aft, "aft", FLAG_IMMEDIATE
  1787. .long drop, ahead, begin, swap, exit
  1788. ;;; : ELSE ( A -- A ) [COMPILE] AHEAD SWAP [COMPILE] THEN ; IMMEDIATE
  1789. COLON else, "else", FLAG_IMMEDIATE
  1790. .long ahead, swap, then, exit
  1791. ;;; : WHILE ( a -- A a ) [COMPILE] IF SWAP ; IMMEDIATE
  1792. COLON while, "while", FLAG_IMMEDIATE,
  1793. .long if, swap, exit
  1794. ;;; : ABORT" ( -- \ <string> ) COMPILE (abort") $," ; IMMEDIATE
  1795. COLON abortquote, "abort\042", FLAG_IMMEDIATE
  1796. .long compile, do_abort_quote, dollar_comma_quote, exit
  1797. ;;; : $" ( -- \ <string>" ) COMPILE ($") $," ; IMMEDIATE
  1798. COLON dollar_quote, "$\042", FLAG_IMMEDIATE
  1799. .long compile, do_dollar_quote, dollar_comma_quote, exit
  1800. ;;; : ." ( -- \ <string>" ) COMPILE ."| $," ; IMMEDIATE
  1801. COLON dot_quote, ".\042", FLAG_IMMEDIATE
  1802. .long compile, do_dot_quote, dollar_comma_quote, exit
  1803. ;;; .( Name Compiler )
  1804. ;;; : ?UNIQUE ( a -- a )
  1805. ;;; DUP NAME? IF ." redefined " OVER .$ THEN DROP ;
  1806. COLON qunique, "?unique", FLAG_NORMAL
  1807. .long dup, nameq
  1808. .long qbranch, qunique_l1
  1809. .long do_dot_quote
  1810. FSTRING " redefined "
  1811. .long over, dot_dollar
  1812. qunique_l1:
  1813. .long drop, exit
  1814. ;;; \ assumes the name is in the right place and the header
  1815. ;;; \ has already be reserved (TOKEN does this)
  1816. ;;; : $,n ( na -- )
  1817. ;;; DUP C@
  1818. ;;; IF ?UNIQUE
  1819. ;;; ( na ) DUP LAST ! \ for OVERT
  1820. ;;; ( na ) HERE ALIGNED SWAP
  1821. ;;; ( cp na ) DUP NAME>LINK
  1822. ;;; ( cp na la) CURRENT @ @ \ previous name
  1823. ;;; ( cp na la na') SWAP !
  1824. ;;; ( cp na ) DUP COUNT + ALIGNED NP !
  1825. ;;; ( cp na ) NAME>PARAM ! EXIT
  1826. ;;; THEN $" name" THROW ;
  1827. COLON dollar_comma_n, "$,n", FLAG_NORMAL
  1828. .long dup, cfetch ; cfetch for string count (strlen ??)
  1829. .long qbranch, dollar_comma_n_l1
  1830. .long qunique
  1831. .long dup, last, store
  1832. .long here, aligned, swap
  1833. .long dup, name_to_link
  1834. .long current, fetch, fetch
  1835. .long swap, store
  1836. .long dup
  1837. .long count, plus, aligned ; skip over the name
  1838. .long np, store
  1839. .long name_to_param
  1840. .long store
  1841. .long exit
  1842. dollar_comma_n_l1:
  1843. .long do_dollar_quote
  1844. FSTRING "name"
  1845. .long throw
  1846. ;;; .( FORTH Compiler )
  1847. ;;; : $COMPILE ( a -- )
  1848. ;;; NAME? ?DUP
  1849. ;;; IF NAME>FLAGS @ [ =FLAG-IMMEDIATE ] LITERAL AND
  1850. ;;; IF EXECUTE ELSE , THEN EXIT
  1851. ;;; THEN
  1852. ;;; 'NUMBER @EXECUTE
  1853. ;;; IF [COMPILE] LITERAL EXIT
  1854. ;;; THEN THROW ;
  1855. colon dollar_compile, "$compile", FLAG_NORMAL
  1856. .long nameq, qdup
  1857. .long qbranch, dollar_compile_l2
  1858. .long name_to_flags, fetch, dolit, FLAG_IMMEDIATE, _and
  1859. .long qbranch, dollar_compile_l1
  1860. .long execute, exit
  1861. dollar_compile_l1:
  1862. .long comma, exit
  1863. dollar_compile_l2:
  1864. .long tnumber, atexecute
  1865. .long qbranch, dollar_compile_l3
  1866. .long literal, exit
  1867. dollar_compile_l3:
  1868. .long throw
  1869. ;;; : OVERT ( -- ) LAST @ CURRENT @ ! ;
  1870. COLON overt, "overt", FLAG_NORMAL
  1871. .long last, fetch, current, fetch, store, exit
  1872. ;;; : ; ( -- )
  1873. ;;; COMPILE EXIT [COMPILE] [ OVERT ; COMPILE-ONLY IMMEDIATE
  1874. COLON semicolon, "\073", FLAG_COMPILE_ONLY + FLAG_IMMEDIATE
  1875. .long compile, exit
  1876. .long left_bracket, overt, exit
  1877. ;;; : ] ( -- ) ['] $COMPILE 'EVAL ! ;
  1878. COLON right_bracket, "]", FLAG_NORMAL
  1879. .long dolit, dollar_compile, teval, store, exit
  1880. ;;; \ basic defining word call like: ' (doXXX) (DEFINE) THING
  1881. ;;; \ and it will place the address of the actual code for (doXXX)
  1882. ;;; \ into the code pointer for thing
  1883. ;;; : (DEFINE) ( code -- \ <string> ) TOKEN DUP $,n
  1884. ;;; SWAP OVER NAME>CODE !
  1885. ;;; [ =FLAG-NORMAL ] LITERAL SWAP NAME>FLAGS ! ;
  1886. COLON paren_define, "(define)", FLAG_NORMAL
  1887. .long token, dup, dollar_comma_n
  1888. .long swap, over, name_to_code, store
  1889. .long dolit, FLAG_NORMAL, swap, name_to_flags, store
  1890. .long exit
  1891. ;;; : : ( -- \ <string> ) [ ' (docolon) @ ] (DEFINE) ] ;
  1892. COLON colon, ":", FLAG_NORMAL
  1893. .long dolit, param_docolon, paren_define
  1894. .long right_bracket, exit
  1895. ;;; : IMMEDIATE ( -- )
  1896. ;;; LAST @ NAME>FLAGS DUP @
  1897. ;;; [ =FLAG-IMMEDIATE ] LITERAL OR SWAP ! ;
  1898. COLON _immediate, "immediate", FLAG_NORMAL
  1899. .long last, fetch, name_to_flags, dup, fetch
  1900. .long dolit, FLAG_IMMEDIATE, _or, swap, store, exit
  1901. ;;; : COMPILE-ONLY ( -- )
  1902. ;;; LAST @ NAME>FLAGS DUP @
  1903. ;;; [ =FLAG-COMPILE-ONLY ] LITERAL OR SWAP ! ;
  1904. COLON _compile_only, "compile-only", FLAG_NORMAL
  1905. .long last, fetch, name_to_flags, dup, fetch
  1906. .long dolit, FLAG_COMPILE_ONLY, _or, swap, store, exit
  1907. ;;; .( Defining Words )
  1908. ;;; : USER ( -- \ <string> ) [ ' (douser) @ ] LITERAL (DEFINE) OVERT ;
  1909. COLON user, "user", FLAG_NORMAL
  1910. .long dolit, param_douser, paren_define, overt, exit
  1911. ;;; : CREATE ( -- \ <string> ) [ ' (dovar) @ ] LITERAL (DEFINE) OVERT ;
  1912. COLON create, "create", FLAG_NORMAL
  1913. .long dolit, param_dovar, paren_define, overt, exit
  1914. ;;; : VARIABLE ( -- \ <string> ) CREATE 0 , ;
  1915. COLON variable, "variable", FLAG_NORMAL
  1916. .long create, dolit, 0, comma, exit
  1917. ;;; : CONSTANT ( u -- \ <string> ) [ ' (doconst) @ ] LITERAL (DEFINE) OVERT ;
  1918. COLON constant, "constant", FLAG_NORMAL
  1919. .long dolit, param_doconst, paren_define, comma, overt, exit
  1920. ;;; .( special constants )
  1921. CONSTANT true, "true", FLAG_NORMAL
  1922. .long TRUE
  1923. CONSTANT false, "false", FLAG_NORMAL
  1924. .long FALSE
  1925. ;;; .( Tools )
  1926. ;;; : (dump_ascii) ( b u -- ) FOR AFT COUNT >CHAR EMIT THEN NEXT DROP ;
  1927. COLON dump_ascii,"(dump_ascii)", FLAG_NORMAL
  1928. .long to_r
  1929. .long branch, dump_ascii_l2
  1930. dump_ascii_l1:
  1931. .long count, to_char, emit
  1932. dump_ascii_l2:
  1933. .long donext, dump_ascii_l1
  1934. .long drop, exit
  1935. ;;; : (dump) ( b u -- b )
  1936. ;;; OVER 4 U.R SPACE FOR AFT COUNT 3 U.R THEN NEXT ;
  1937. COLON paren_dump, "(dump)", FLAG_NORMAL
  1938. .long over, dolit, 8, u_dot_r, space
  1939. .long to_r
  1940. .long branch, paren_dump_l2
  1941. paren_dump_l1:
  1942. .long count, dolit, 3, u_dot_r
  1943. paren_dump_l2:
  1944. .long donext, paren_dump_l1
  1945. .long exit
  1946. ;;; : DUMP ( b u -- )
  1947. ;;; BASE @ >R HEX 16 /
  1948. ;;; FOR CR 16 2DUP (dump) -ROT 2 SPACES _TYPE ENOUGH? 0= WHILE
  1949. ;;; NEXT ELSE R> DROP THEN DROP R> BASE ! ;
  1950. COLON dump, "dump", FLAG_NORMAL
  1951. .long base, fetch, to_r, hex, dolit, 16, divide
  1952. .long to_r
  1953. dump_l1:
  1954. .long cr, dolit, 16, twodup, paren_dump, minus_rot, dolit, 2, spaces, dump_ascii
  1955. .long enoughq, zero_equal, qbranch, dump_l2
  1956. .long donext, dump_l1
  1957. .long branch, dump_l3
  1958. dump_l2:
  1959. .long r_from, drop
  1960. dump_l3:
  1961. .long drop, r_from, base, store, exit
  1962. ;;; : .S ( -- ) CR DEPTH FOR AFT R@ PICK . THEN NEXT ." <tos" ;
  1963. COLON dot_s, ".s", FLAG_NORMAL
  1964. .long cr, depth, to_r
  1965. .long branch, dot_s_l2
  1966. dot_s_l1:
  1967. .long r_fetch, pick, dot
  1968. dot_s_l2:
  1969. .long donext, dot_s_l1
  1970. .long do_dot_quote
  1971. FSTRING " <tos"
  1972. .long exit
  1973. ;;; : !CSP ( -- ) SP@ CSP ! ;
  1974. ;;; ** Missing **
  1975. ;;; : ?CSP ( -- ) SP@ CSP @ XOR ABORT" stack depth" ;
  1976. ;;; ** Missing **
  1977. ;;; \ search to see if an unknown address is really forth code
  1978. ;;; : CODE? ( ca -- na | F )
  1979. ;;; CURRENT
  1980. ;;; BEGIN CELL+ @ ?DUP WHILE 2DUP
  1981. ;;; BEGIN @ DUP WHILE 2DUP NAME>CODE XOR
  1982. ;;; WHILE NAME>LINK
  1983. ;;; REPEAT THEN NIP ?DUP
  1984. ;;; UNTIL NIP NIP EXIT THEN DROP FALSE ;
  1985. ;;; hacked version - the vocabulary structure is not workable yet
  1986. COLON code_query, "code?", FLAG_NORMAL
  1987. .long current
  1988. ;code_query_l1:
  1989. .long cell_plus, fetch, qdup
  1990. .long qbranch, code_query_l4
  1991. .long twodup
  1992. code_query_l2:
  1993. .long fetch, dup
  1994. .long qbranch, code_query_l3
  1995. .long twodup, name_to_code, _xor
  1996. .long qbranch, code_query_l3
  1997. .long name_to_link
  1998. .long branch, code_query_l2
  1999. code_query_l3:
  2000. .long nip, qdup
  2001. ;.long qbranch, code_query_l1
  2002. .long qbranch, code_query_l5
  2003. .long nip, nip, exit
  2004. code_query_l4:
  2005. .long drop, dolit, FALSE, exit
  2006. code_query_l5:
  2007. .long twodrop, dolit, FALSE, exit
  2008. ;;; disassembler for colon definitions
  2009. ;;; does no know how to stop - press enter twice to stop
  2010. ;;; SEE ( -- ) \ token
  2011. ;;; BASE @
  2012. ;;; ' CODE>NAME NAME>PARAM DUP
  2013. ;;; CR [CHAR] $ EMIT HEX 1 U.R [ CHAR : ] EMIT
  2014. ;;; @ CR ALIGNED CELL-
  2015. ;;; BEGIN
  2016. ;;; CELL+ DUP @ DUP IF CODE? THEN
  2017. ;;; ?DUP
  2018. ;;; IF SPACE .ID
  2019. ;;; ELSE DUP @ DUP DECIMAL U.
  2020. ;;; [CHAR] / EMIT
  2021. ;;; [CHAR] $ EMIT
  2022. ;;; HEX 1 U.R \ number
  2023. ;;; THEN
  2024. ;;; ENOUGH? UNTIL DROP BASE !;
  2025. COLON see, "see", FLAG_NORMAL
  2026. .long base, fetch
  2027. .long tick, code_to_name, name_to_param, dup
  2028. .long cr
  2029. .long dolit, '$', emit
  2030. .long hex, dolit, 1, u_dot_r
  2031. .long dolit, ':', emit
  2032. .long fetch
  2033. .long cr, aligned, cell_minus
  2034. see_l1:
  2035. .long cell_plus, dup, fetch, dup
  2036. .long qbranch, see_l2
  2037. .long code_query
  2038. see_l2:
  2039. .long qdup
  2040. .long qbranch, see_l3
  2041. .long space, dot_id
  2042. .long branch, see_l4
  2043. see_l3:
  2044. .long dup, fetch, dup, decimal, u_dot
  2045. .long dolit, '/', emit, dolit, '$', emit
  2046. .long hex, dolit, 1, u_dot_r, cr
  2047. see_l4:
  2048. .long enoughq, qbranch, see_l1
  2049. .long drop, base, store, exit
  2050. ;;; : .ID ( na -- )
  2051. ;;; ?DUP IF COUNT $001F AND TYPE EXIT THEN ." {noName}" ;
  2052. COLON dot_id, ".id", FLAG_NORMAL
  2053. .long qdup, qbranch, dot_id_l1
  2054. .long count, type, exit
  2055. dot_id_l1:
  2056. .long do_dot_quote
  2057. FSTRING "{no-name}"
  2058. .long exit
  2059. ;;; : WORDS ( -- )
  2060. ;;; CR CONTEXT @
  2061. ;;; BEGIN @ ?DUP
  2062. ;;; WHILE DUP SPACE .ID NAME>LINK ENOUGH?
  2063. ;;; UNTIL DROP THEN ;
  2064. COLON words, "words", FLAG_NORMAL
  2065. .long cr, context, fetch
  2066. words_l1:
  2067. .long fetch, qdup
  2068. .long qbranch, words_l2
  2069. .long dup, space, dot_id, name_to_link
  2070. .long enoughq, qbranch, words_l1
  2071. .long drop
  2072. words_l2:
  2073. .long exit
  2074. ;;; .( File I/O )
  2075. ;;; : R/O ( -- fam )
  2076. CODE readonly, "r/o", FLAG_NORMAL
  2077. xcall FileSystem_ReadOnly
  2078. sub %r1, BYTES_PER_CELL
  2079. ld.w [%r1], %r4
  2080. NEXT
  2081. END_CODE
  2082. ;;; : W/O ( -- fam )
  2083. CODE writeonly, "w/o", FLAG_NORMAL
  2084. xcall FileSystem_WriteOnly
  2085. sub %r1, BYTES_PER_CELL
  2086. ld.w [%r1], %r4
  2087. NEXT
  2088. END_CODE
  2089. ;;; : R/W ( -- fam )
  2090. CODE readwrite, "r/w", FLAG_NORMAL
  2091. xcall FileSystem_ReadWrite
  2092. sub %r1, BYTES_PER_CELL
  2093. ld.w [%r1], %r4
  2094. NEXT
  2095. END_CODE
  2096. ;;; : BIN ( fam -- fam2 )
  2097. CODE bin, "bin", FLAG_NORMAL
  2098. ld.w %r6, [%r1] ; fam
  2099. xcall FileSystem_bin
  2100. ld.w [%r1], %r4 ; fam2
  2101. NEXT
  2102. END_CODE
  2103. ;;; : S" ( -- \ <string> ) [COMPILE] $" COMPILE COUNT ; IMMEDIATE
  2104. ;;; \ runtime ( -- b u )
  2105. COLON s_quote, "s\042", FLAG_IMMEDIATE
  2106. .long dollar_quote, compile, count, exit
  2107. ;;; : DELETE-FILE ( b u -- ior )
  2108. CODE delete_file, "delete-file", FLAG_NORMAL
  2109. ld.w %r7, [%r1]+ ; count
  2110. ld.w %r6, [%r1] ; string
  2111. xcall FileSystem_delete
  2112. ld.w [%r1], %r5 ; ior
  2113. NEXT
  2114. END_CODE
  2115. ;;; : RENAME-FILE ( b1 u1 b2 u2 -- ior )
  2116. CODE rename_file, "rename-file", FLAG_NORMAL
  2117. ld.w %r9, [%r1]+ ; count2
  2118. ld.w %r8, [%r1]+ ; name2
  2119. ld.w %r7, [%r1]+ ; count1
  2120. ld.w %r6, [%r1] ; name1
  2121. xcall FileSystem_rename
  2122. ld.w [%r1], %r5 ; ior
  2123. NEXT
  2124. END_CODE
  2125. ;;; : CREATE-FILE ( b u fam -- fileid ior )
  2126. CODE create_file, "create-file", FLAG_NORMAL
  2127. ld.w %r8, [%r1]+ ; fam
  2128. ld.w %r7, [%r1] ; count
  2129. xld.w %r6, [%r1 + 4] ; string
  2130. xcall FileSystem_create
  2131. ld.w [%r1], %r5 ; ior
  2132. xld.w [%r1 + 4], %r4 ; fd
  2133. NEXT
  2134. END_CODE
  2135. ;;; : OPEN-FILE ( b u fam -- fileid ior )
  2136. CODE open_file, "open-file", FLAG_NORMAL
  2137. ld.w %r8, [%r1]+ ; fam
  2138. ld.w %r7, [%r1] ; count
  2139. xld.w %r6, [%r1 + 4] ; string
  2140. xcall FileSystem_open
  2141. ld.w [%r1], %r5 ; ior
  2142. xld.w [%r1 + 4], %r4 ; fd
  2143. NEXT
  2144. END_CODE
  2145. ;;; : CLOSE-FILE ( fileid -- ior )
  2146. CODE close_file, "close-file", FLAG_NORMAL
  2147. ld.w %r6, [%r1] ; fileid
  2148. xcall FileSystem_close
  2149. ld.w [%r1], %r5 ; ior
  2150. NEXT
  2151. END_CODE
  2152. ;;; : READ-FILE ( b u fileid -- u2 ior )
  2153. CODE read_file, "read-file", FLAG_NORMAL
  2154. ld.w %r6, [%r1]+ ; fileid
  2155. ld.w %r8, [%r1] ; count
  2156. xld.w %r7, [%r1 + 4] ; buffer
  2157. xcall FileSystem_read
  2158. ld.w [%r1], %r5 ; ior
  2159. xld.w [%r1 + 4], %r4 ; count2
  2160. NEXT
  2161. END_CODE
  2162. ;;; : READ-LINE ( b u fileid -- u2 f ior )
  2163. ;;; \ EOF: 0 T 0
  2164. ;;; >R >R DUP R> R> SWAP \ b0 b fileid u
  2165. ;;; FOR AFT \ b0 b fileid
  2166. ;;; BEGIN
  2167. ;;; 2DUP 1 SWAP READ-FILE \ b0 b fileid 0/1 ior
  2168. ;;; ?DUP IF >R 2DROP SWAP - R> R> DROP EXIT THEN
  2169. ;;; 0= IF DROP SWAP - DUP 0 R> DROP EXIT THEN \ u2 f 0
  2170. ;;; \ b0 b fileid
  2171. ;;; OVER C@ [CTRL] M XOR \ b0 b fileid f
  2172. ;;; UNTIL
  2173. ;;; \ here have a non CR character
  2174. ;;; OVER C@ [CTRL] J = IF DROP SWAP - TRUE 0 R> DROP EXIT THEN
  2175. ;;; >R 1+ R> \ b0 b+1 fileid
  2176. ;;; THEN NEXT
  2177. ;;; \ filled buffer without CR/LF \ b0 b' fileid
  2178. ;;; DROP SWAP - TRUE 0 \ u2 T 0
  2179. ;;; ;
  2180. COLON read_line, "read-line", FLAG_NORMAL
  2181. .long to_r, to_r, dup, r_from, r_from, swap
  2182. .long to_r
  2183. .long branch, read_line_l5
  2184. read_line_l1:
  2185. .long twodup, dolit, 1, swap, read_file
  2186. .long qdup, qbranch, read_line_l2
  2187. .long to_r, twodrop, swap, minus, true, r_from, r_from, drop, exit
  2188. read_line_l2:
  2189. .long zero_equal, qbranch, read_line_l3
  2190. .long drop, swap, minus, dup, dolit, 0, r_from, drop, exit
  2191. read_line_l3:
  2192. .long over, cfetch, dolit, 13, _xor, qbranch, read_line_l1
  2193. .long over, cfetch, dolit, 10, equal, qbranch, read_line_l4
  2194. .long drop, swap, minus, true, dolit, 0, r_from, drop, exit
  2195. read_line_l4:
  2196. .long to_r, increment, r_from
  2197. read_line_l5:
  2198. .long donext, read_line_l1
  2199. .long drop, swap, minus, true, dolit, 0, exit
  2200. ;;; : WRITE-FILE ( b u fileid -- u2 ior )
  2201. CODE write_file, "write-file", FLAG_NORMAL
  2202. ld.w %r6, [%r1]+ ; fileid
  2203. ld.w %r8, [%r1] ; count
  2204. xld.w %r7, [%r1 + 4] ; buffer
  2205. xcall FileSystem_write
  2206. ld.w [%r1], %r5 ; ior
  2207. xld.w [%r1 + 4], %r4 ; count2
  2208. NEXT
  2209. END_CODE
  2210. ;;; : FLUSH-FILE ( fileid -- ior )
  2211. CODE flush_file, "flush-file", FLAG_NORMAL
  2212. ld.w %r6, [%r1] ; fileid
  2213. xcall FileSystem_sync
  2214. ld.w [%r1], %r5 ; ior
  2215. NEXT
  2216. END_CODE
  2217. ;;; : FILE-SIZE ( fileid -- u ior )
  2218. CODE file_size, "file-size", FLAG_NORMAL
  2219. ld.w %r6, [%r1] ; fileid
  2220. xcall FileSystem_lsize
  2221. ld.w [%r1], %r4 ; size
  2222. sub %r1, BYTES_PER_CELL
  2223. ld.w [%r1], %r5 ; ior
  2224. NEXT
  2225. END_CODE
  2226. ;;; : FILE-POSITION ( fileid -- u ior )
  2227. CODE file_position, "file-position", FLAG_NORMAL
  2228. ld.w %r6, [%r1] ; fileid
  2229. xcall FileSystem_ltell
  2230. ld.w [%r1], %r4 ; pos
  2231. sub %r1, BYTES_PER_CELL
  2232. ld.w [%r1], %r5 ; ior
  2233. NEXT
  2234. END_CODE
  2235. ;;; : REPOSITION-FILE ( u fileid -- ior )
  2236. CODE reposition_file, "reposition-file", FLAG_NORMAL
  2237. ld.w %r6, [%r1]+ ; fileid
  2238. ld.w %r7, [%r1] ; pos
  2239. xcall FileSystem_lseek
  2240. ld.w [%r1], %r5 ; ior
  2241. NEXT
  2242. END_CODE
  2243. ;;; : FILESYSTEM-INIT ( -- )
  2244. CODE filesystem_init, "filesystem-init", FLAG_NORMAL
  2245. xcall FileSystem_initialise
  2246. NEXT
  2247. END_CODE
  2248. ;;; : FILESYSTEM-CLOSE-ALL ( -- )
  2249. CODE filesystem_close_all, "filesystem-close-all", FLAG_NORMAL
  2250. xcall FileSystem_CloseAll
  2251. NEXT
  2252. END_CODE
  2253. ;;; : OPEN-DIRECTORY ( b u -- dirid ior )
  2254. CODE open_directory, "open-directory", FLAG_NORMAL
  2255. ld.w %r7, [%r1] ; count
  2256. xld.w %r6, [%r1 + 4] ; buffer
  2257. xcall FileSystem_OpenDirectory
  2258. ld.w [%r1], %r5 ; ior
  2259. xld.w [%r1 + 4], %r4 ; count2
  2260. NEXT
  2261. END_CODE
  2262. ;;; : CLOSE-DIRECTORY ( dirid -- ior )
  2263. CODE close_directory, "close-directory", FLAG_NORMAL
  2264. ld.w %r6, [%r1] ; dirid
  2265. xcall FileSystem_CloseDirectory
  2266. ld.w [%r1], %r5 ; ior
  2267. NEXT
  2268. END_CODE
  2269. ;;; : READ-DIRECTORY ( b u dirid -- u2 ior )
  2270. CODE read_directory, "read-directory", FLAG_NORMAL
  2271. ld.w %r6, [%r1]+ ; dirid
  2272. ld.w %r8, [%r1] ; count
  2273. xld.w %r7, [%r1 + 4] ; buffer
  2274. xcall FileSystem_ReadDirectory
  2275. ld.w [%r1], %r5 ; ior
  2276. xld.w [%r1 + 4], %r4 ; count2
  2277. NEXT
  2278. END_CODE
  2279. ;;; .( Access to low level sectors on disk )
  2280. ;;; \ buffer size = count * 512 bytes
  2281. ;;; : READ-SECTORS ( b count sector -- ior )
  2282. CODE read_sectors, "read-sectors", FLAG_NORMAL
  2283. ld.w %r6, [%r1]+ ; sector
  2284. ld.w %r8, [%r1]+ ; count
  2285. xld.w %r7, [%r1] ; buffer
  2286. xcall FileSystem_AbsoluteRead
  2287. ld.w [%r1], %r5 ; ior
  2288. NEXT
  2289. END_CODE
  2290. ;;; \ buffer size = count * 512 bytes
  2291. ;;; : WRITE-SECTORS ( b count sector -- ior )
  2292. CODE write_sectors, "write-sectors", FLAG_NORMAL
  2293. ld.w %r6, [%r1]+ ; sector
  2294. ld.w %r8, [%r1]+ ; count
  2295. xld.w %r7, [%r1] ; buffer
  2296. xcall FileSystem_AbsoluteWrite
  2297. ld.w [%r1], %r5 ; ior
  2298. NEXT
  2299. END_CODE
  2300. ;;; .( Hardware reset )
  2301. ;;; \ version
  2302. ;;; =BUILD-NUMBER CONSTANT BUILD ( -- u )
  2303. CONSTANT build, "build", FLAG_NORMAL
  2304. .long BUILD_NUMBER
  2305. ;;; BANNER ( -- ) CR <message> CR
  2306. COLON banner, "banner", FLAG_NORMAL
  2307. .long cr
  2308. .long do_dot_quote
  2309. FSTRING "S33 forth interpreter (build:"
  2310. .long build, u_dot, do_dot_quote
  2311. FSTRING ")"
  2312. .long cr, exit
  2313. ;;; CREATE 'BOOT ' BANNER , \ application vector
  2314. VARIABLE tboot, "'boot", FLAG_NORMAL
  2315. .long banner
  2316. ;;; MACRO INIT-USER-VARIABLES
  2317. .macro INIT_USER_VARIABLES
  2318. .long dolit, initial_stack_pointer, sp0, store
  2319. .long dolit, initial_return_pointer, rp0, store
  2320. .long dolit, rx_query, tkey_query, store
  2321. .long dolit, tx_store, temit, store
  2322. .long dolit, accept, texpect, store
  2323. .long dolit, ktap, ttap, store
  2324. .long dolit, tx_store, techo, store
  2325. .long dolit, dot_ok, tprompt, store
  2326. .long dolit, 10, base, store
  2327. .long dolit, 0, temp, store
  2328. .long dolit, 0, span, store
  2329. .long dolit, 0, to_in, store
  2330. .long dolit, 0, hash_tib, store
  2331. .long dolit, terminal_buffer, hash_tib, cell_plus, store
  2332. .long dolit, dollar_interpret, teval, store
  2333. .long dolit, numberq, tnumber, store
  2334. .long dolit, 0, hld, store
  2335. .long dolit, 0, handler, store
  2336. .long dolit, 0, context, store
  2337. .long dolit, 0, context, dolit, 1, cells, plus, store
  2338. .long dolit, 0, context, dolit, 2, cells, plus, store
  2339. .long dolit, 0, context, dolit, 3, cells, plus, store
  2340. .long dolit, 0, context, dolit, 4, cells, plus, store
  2341. .long dolit, 0, context, dolit, 5, cells, plus, store
  2342. .long dolit, 0, context, dolit, 6, cells, plus, store
  2343. .long dolit, 0, context, dolit, 7, cells, plus, store
  2344. .long dolit, 0, context, dolit, 8, cells, plus, store
  2345. .long dolit, 0, current, store
  2346. .long dolit, 0, current, cell_plus, store
  2347. .long dolit, end_of_code, cp, store
  2348. .long dolit, end_of_dictionary, cp, cell_plus, store
  2349. .long dolit, last_name, cp, cell_plus, cell_plus, store
  2350. .endm
  2351. ;;; : COLD ( -- )
  2352. ;;; \ init CPU
  2353. ;;; \ init stacks
  2354. ;;; \ init user area
  2355. ;;; \ init IP
  2356. ;;; PRESET
  2357. ;;; FORTH CONTEXT @ DUP CURRENT D! OVERT
  2358. ;;; 'BOOT @EXECUTE
  2359. ;;; QUIT ;
  2360. COLON cold, "cold", FLAG_NORMAL
  2361. INIT_USER_VARIABLES
  2362. .long preset, filesystem_init
  2363. .long forth, context, fetch, dup, current, dstore, overt
  2364. .long tboot, atexecute
  2365. .long do_dollar_quote
  2366. FSTRING "forth.4th"
  2367. .long count, included
  2368. .long do_dollar_quote
  2369. FSTRING "auto.4th"
  2370. .long count, readonly, open_file
  2371. .long qbranch, have_auto
  2372. .long drop, branch, run_quit
  2373. have_auto:
  2374. .long include_file
  2375. run_quit:
  2376. .long quit
  2377. COLON nop, "nop", FLAG_NORMAL ;debug
  2378. .long exit
  2379. CODE BREAKPOINT, "(brk)", FLAG_NORMAL ;debug
  2380. xcall xdebug ;debug
  2381. xld.w %r6, bpt
  2382. xcall Serial_PutString
  2383. s1: jp s1 ;debug
  2384. bpt: .asciz "STOPPED\r\n"
  2385. .balign 4
  2386. CODE DEBUG, "(debug)", FLAG_NORMAL ;debug
  2387. xcall xdebug ;debug
  2388. NEXT ;debug
  2389. END_CODE ;debug
  2390. ;;; delay in micro seconds
  2391. CODE delay_micro_seconds, "delay-us", FLAG_NORMAL
  2392. ld.w %r5, [%r1]+
  2393. delay_micro_seconds_outer:
  2394. ld.w %r4, 12
  2395. delay_micro_seconds_loop:
  2396. nop
  2397. sub %r4, 1
  2398. jrne delay_micro_seconds_loop
  2399. sub %r5, 1
  2400. jrne delay_micro_seconds_outer
  2401. NEXT
  2402. END_CODE
  2403. ;;; finish off the dictionary
  2404. .section .forth_dict
  2405. .balign 4
  2406. end_of_dictionary:
  2407. .long 0,0
  2408. .space 65536 ; space for more names
  2409. end_of_dictionary_memory:
  2410. last_name = __last_name ; should be the final name
  2411. ;;; finish off the code
  2412. .section .forth_param
  2413. .balign 4
  2414. end_of_code:
  2415. ; .space 65536 ; space for more code
  2416. ;end_of_code_memory: