OpenCores
URL https://opencores.org/ocsvn/bitserial/bitserial/trunk

Subversion Repositories bitserial

[/] [bitserial/] [trunk/] [bit.fth] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 howe.r.j.8
\
2
\ Cross Compiler and eForth interpreter for the bit-serial CPU available at:
3
\
4
\   
5
\
6
\ This implements a Direct Threaded Code virtual machine on which we can
7
\ build a Forth interpreter.
8
\
9
\ References:
10
\
11
\ - 
12
\ - 
13
\ - 
14
\ - 
15
\ - 
16
\ - 8086 eForth 1.0 by Bill Muench and C. H. Ting, 1990
17
\
18
\ The cross compiler has been tested and works with gforth versions 0.7.0 and
19
\ 0.7.3. An already compiled image (called 'bit.hex') should be available if
20
\ you do not have gforth installed.
21
\
22
 
23
only forth also definitions hex
24
 
25
wordlist constant meta.1
26
wordlist constant target.1
27
wordlist constant assembler.1
28
wordlist constant target.only.1
29
 
30
: (order) ( u wid*n n -- wid*n u n )
31
   dup if
32
    1- swap >r recurse over r@ xor if
33
     1+ r> -rot exit then r> drop then ;
34
: -order ( wid -- ) get-order (order) nip set-order ;
35
: +order ( wid -- ) dup >r -order get-order r> swap 1+ set-order ;
36
 
37
meta.1 +order also definitions
38
 
39
   2 constant =cell
40
4000 constant size ( 16384 bytes, 8192 cells )
41
2000 constant =end ( 8192  bytes, leaving 4096 for Dual Port Block RAM )
42
  40 constant =stksz
43
  60 constant =buf
44
0008 constant =bksp
45
000A constant =lf
46
000D constant =cr
47
007F constant =del
48
 
49
create tflash size cells here over erase allot
50
 
51
variable tdp
52
variable tep
53
variable tlast
54
size =cell - tep !
55
 
56
 
57
: :m meta.1 +order also definitions : ;
58
: ;m postpone ; ; immediate
59
:m there tdp @ ;m
60
:m tc! tflash + c! ;m
61
:m tc@ tflash + c@ ;m
62
:m t! over ff and over tc! swap 8 rshift swap 1+ tc! ;m
63
:m t@ dup tc@ swap 1+ tc@ 8 lshift or ;m
64
:m talign there 1 and tdp +! ;m
65
:m tc, there tc! 1 tdp +! ;m
66
:m t, there t! 2 tdp +! ;m
67
:m $literal [char] " word count dup tc, 0 ?do count tc, loop drop talign ;m
68
:m tallot tdp +! ;m
69
:m thead
70
  talign
71
  there tlast @ t, tlast !
72
  parse-word dup tc, 0 ?do count tc, loop drop talign ;m
73
:m hex# ( u -- addr len )  0 <# base @ >r hex =lf hold # # # # r> base ! #> ;m
74
:m save-hex (  -- )
75
  parse-word w/o create-file throw
76
  there 0 do i t@  over >r hex# r> write-file throw =cell +loop
77
   close-file throw ;m
78
:m save-target (  -- )
79
  parse-word w/o create-file throw >r
80
   tflash there r@ write-file throw r> close-file ;m
81
:m .h base @ >r hex     u. r> base ! ;m
82
:m .d base @ >r decimal u. r> base ! ;m
83
:m twords
84
   cr tlast @
85
   begin
86
      dup tflash + =cell + count 1f and type space t@
87
   ?dup 0= until ;m
88
:m .stat
89
 
90
    ." target: "      target.1      +order words cr cr
91
    ." target-only: " target.only.1 +order words cr cr
92
    ." assembler: "   assembler.1   +order words cr cr
93
    ." meta: "        meta.1        +order words cr cr
94
  then
95
  ." used> " there dup ." 0x" .h ." / " .d cr ;m
96
:m .end only forth also definitions decimal ;m
97
:m atlast tlast @ ;m
98
:m tvar   get-current >r meta.1 set-current create r> set-current there , t, does> @ ;m
99
:m label: get-current >r meta.1 set-current create r> set-current there ,    does> @ ;m
100
:m tdown =cell negate and ;m
101
:m tnfa =cell + ;m ( pwd -- nfa : move to name field address)
102
:m tcfa tnfa dup c@ $1F and + =cell + tdown ;m ( pwd -- cfa )
103
:m compile-only tlast @ tnfa t@ $20 or tlast @ tnfa t! ;m ( -- )
104
:m immediate    tlast @ tnfa t@ $40 or tlast @ tnfa t! ;m ( -- )
105
:m t' ' >body @ ;m
106
:m call 2/ C000 or ;m
107
:m t2/ 2/ ;m
108
 
109
: iOR      0000 or t, ;
110
: iAND     1000 or t, ;
111
: iXOR     2000 or t, ;
112
: iADD     3000 or t, ;
113
: iLSHIFT  4000 or t, ;
114
: iRSHIFT  5000 or t, ;
115
: iLOAD    2/ 6000 or t, ;
116
: iSTORE   2/ 7000 or t, ;
117
 
118
: iLOAD-C  2/ 8000 or t, ;
119
: iSTORE-C 2/ 9000 or t, ;
120
: iLITERAL A000 or t, ;
121
: iUNUSED  B000 or t, ;
122
: iJUMP    C000 or t, ;
123
: iJUMPZ   D000 or t, ;
124
: iSET     E000 or t, ;
125
: iGET     F000 or t, ;
126
 
127
 1 constant flgCy
128
 2 constant flgZ
129
 4 constant flgNg
130
 8 constant flgR
131
10 constant flgHlt
132
 
133
: flags? 1 iGET ;
134
: flags! 1 iSET ;
135
: halt!  flgHlt iLITERAL flags! ;
136
: branch  2/ iJUMP ;
137
: ?branch 2/ iJUMPZ ;
138
: zero? flags? 2 iAND ;
139
:m postpone t' branch ;m
140
 
141
assembler.1 +order also definitions
142
: begin there ;
143
: until ?branch ;
144
: again branch ;
145
: if there 0 ?branch ;
146
: mark there 0 branch ;
147
: then begin 2/ over t@ or swap t! ;
148
: else mark swap then ;
149
: while if swap ;
150
: repeat branch then ;
151
assembler.1 -order
152
meta.1 +order also definitions
153
 
154
\ ---- ---- ---- ---- ---- image generation   ---- ---- ---- ---- ---- ----
155
 
156
 
157
1 t,  \ must be 1 ('1 iADD' works in either indirect or direct mode )
158
2 t,  \ must be 2 ('2 iADD' works in either indirect or direct mode )
159
label: entry
160
 
161
 
162
FFFF tvar set       \ all bits set, -1
163
  FF tvar low       \ lowest bytes set
164
 
165
 
166
 
167
 
168
 
169
 
170
 
171
 
172
 
173
 
174
 
175
 
176
 
177
 
178
 
179
 
180
 
181
 =end                       dup tvar {sp0} tvar {sp} \ grows downwards
182
 =end =stksz 2* -           dup tvar {rp0} tvar {rp} \ grows upwards
183
 =end =stksz 2* - =buf - constant TERMBUF \ pad buffer space
184
 
185
TERMBUF =buf + constant =tbufend
186
 
187
: vcell 1 ( cell '1' should contain '1' ) ;
188
: -vcell set 2/ ;
189
: --sp {sp} iLOAD-C  vcell iADD {sp} iSTORE-C ;
190
: ++sp {sp} iLOAD-C -vcell iADD {sp} iSTORE-C ;
191
: --rp {rp} iLOAD-C -vcell iADD {rp} iSTORE-C ;
192
: ++rp {rp} iLOAD-C  vcell iADD {rp} iSTORE-C ;
193
 
194
\ ---- ---- ---- ---- ---- Forth VM ---- ---- ---- ---- ---- ---- ---- ----
195
 
196
label: start
197
  start call entry t!
198
  {sp0} iLOAD-C {sp} iSTORE-C
199
  {rp0} iLOAD-C {rp} iSTORE-C
200
   iLOAD-C
201
  ip iSTORE-C
202
  \ -- fall-through --
203
label: vm ( The Forth virtual machine )
204
  ip iLOAD-C
205
  w iSTORE-C
206
  ip iLOAD-C 1 iADD ip iSTORE-C
207
  w iLOAD-C
208
 
209
 
210
label: {nest} ( function call: accumulator must contain '0 iGET' prior to call )
211
  w iSTORE-C ( store '0 iGET' into working pointer )
212
  ++rp
213
  ip iLOAD-C
214
  {rp} iSTORE
215
  w iLOAD-C
216
  2 iADD
217
  ip iSTORE-C
218
  vm branch
219
 
220
label: {unnest} ( return from function call )
221
  {rp} iLOAD
222
  t iSTORE-C
223
  --rp
224
  t iLOAD-C
225
  ip iSTORE-C
226
  vm branch
227
 
228
:m nest 0 iGET {nest} branch ;m
229
:m unnest {unnest} branch ;m
230
:m =nest {nest} call ;m
231
:m =unnest {unnest} call ;m
232
:m =0iGET F000 ;m
233
 
234
:m :ht ( "name" -- : forth only routine )
235
  get-current >r target.1 set-current create
236
  r> set-current CAFEBABE talign there ,
237
  nest
238
  does> @ branch ( really a call ) ;m
239
 
240
:m :t ( "name" -- : forth only routine )
241
  >in @ thead >in !
242
  get-current >r target.1 set-current create
243
  r> set-current CAFEBABE talign there ,
244
  nest
245
  does> @ branch ( really a call ) ;m
246
 
247
:m :to ( "name" -- : forth only, target only routine )
248
  >in @ thead >in !
249
  get-current >r target.only.1 set-current create r> set-current
250
  there ,
251
  nest CAFEBABE
252
  does> @ branch ;m
253
 
254
:m ;t CAFEBABE <> if abort" unstructured" then talign unnest target.only.1 -order ;
255
 
256
:m a: ( "name" -- : assembly only routine, no header )
257
  CAFED00D
258
  target.1 +order also definitions
259
  create talign there ,
260
  assembler.1 +order
261
  does> @ branch ;m
262
:m (a); CAFED00D <> if abort" unstructured" then assembler.1 -order ;m
263
:m a; (a); vm branch ;m
264
 
265
label: IncIp ip iLOAD-C 1 iADD ip iSTORE-C vm branch
266
label: decSp tos iSTORE-C --sp vm branch
267
 
268
a: opPush ( pushes the next value in instruction stream on to the stack )
269
  ++sp
270
  tos iLOAD-C
271
  {sp} iSTORE
272
  ip iLOAD-C
273
  t iSTORE-C
274
  t iLOAD
275
  tos iSTORE-C
276
  IncIp branch
277
  (a);
278
 
279
a: opJump ( jump to next value in instruction stream )
280
label: Jump
281
  ip iLOAD
282
  ip iSTORE-C
283
  a;
284
 
285
a: opJumpZ
286
  tos iLOAD-C
287
  t iSTORE-C
288
  {sp} iLOAD
289
  tos iSTORE-C
290
  --sp
291
  t iLOAD-C
292
  if
293
    IncIp branch
294
  then
295
  Jump branch
296
  (a);
297
 
298
a: opNext
299
  {rp} iLOAD
300
  if
301
    set 2/ iADD
302
    {rp} iSTORE
303
    Jump branch
304
  then
305
  --rp
306
  IncIp branch
307
  (a);
308
 
309
:m lit         opPush t, ;m
310
:m [char] char opPush t, ;m
311
:m char   char opPush t, ;m
312
:m =push  [ t' opPush  ] literal call  ;m
313
:m =jump  [ t' opJump  ] literal call  ;m
314
:m =jumpz [ t' opJumpZ ] literal call  ;m
315
:m begin talign there ;m
316
:m until talign opJumpZ 2/ t, ;m
317
:m again talign opJump  2/ t, ;m
318
:m if opJumpZ there 0 t, ;m
319
:m mark opJump there 0 t, ;m
320
:m then there 2/ swap t! ;m
321
:m else mark swap then ;m
322
:m while if ;m
323
:m repeat swap again then ;m
324
:m aft drop mark begin swap ;m
325
:m next talign opNext 2/ t, ;m
326
 
327
a: bye halt! a;   ( -- : bye bye! )
328
a: exit unnest a; ( -- : exit from current function )
329
 
330
a: lls ( u shift -- u : shift left by number of bits set )
331
  {sp} iLOAD
332
  tos 2/ iLSHIFT
333
  decSp branch
334
  (a);
335
 
336
a: lrs ( u shift -- u : shift right by number of bits set )
337
  {sp} iLOAD
338
  tos 2/ iRSHIFT
339
  decSp branch
340
  (a);
341
 
342
a: and ( u u -- u : bit wise AND )
343
  {sp} iLOAD
344
  tos 2/ iAND
345
  decSp branch
346
  (a);
347
 
348
a: or ( u u -- u : bit wise OR )
349
  {sp} iLOAD
350
  tos 2/ iOR
351
  decSp branch
352
  (a);
353
 
354
a: xor ( u u -- u : bit wise XOR )
355
  {sp} iLOAD
356
  tos 2/ iXOR
357
  decSp branch
358
  (a);
359
 
360
a: + ( u u -- u : Plain old addition )
361
  {sp} iLOAD
362
  tos 2/ iADD
363
  decSp branch
364
  (a);
365
 
366
a: um+ ( u u -- u f : Add with carry )
367
  {sp} iLOAD
368
  tos 2/ iADD
369
  {sp} iSTORE
370
  flags?
371
  flgCy iAND
372
  tos iSTORE-C
373
  a;
374
 
375
a: @ ( a -- u : load a memory address )
376
  tos iLOAD-C
377
  1 iRSHIFT
378
  tos iSTORE-C
379
  tos iLOAD
380
  tos iSTORE-C
381
  a;
382
 
383
a: ! ( u a -- store a cell at a memory address )
384
  tos iLOAD-C
385
  1 iRSHIFT
386
  t iSTORE-C
387
  {sp} iLOAD
388
  t iSTORE
389
  --sp
390
  {sp} iLOAD
391
  decSp branch
392
  (a);
393
 
394
a: c@ ( b -- c )
395
  tos iLOAD-C
396
  1 iRSHIFT
397
  t iSTORE-C
398
  t iLOAD
399
  t iSTORE-C
400
  tos iLOAD-C
401
  1 iAND if
402
    t iLOAD-C
403
    low 2/ iRSHIFT
404
  else
405
    t iLOAD-C
406
    low 2/ iAND
407
  then
408
  tos iSTORE-C
409
  a;
410
 
411
a: dup ( u -- u u : duplicate item on top of stack )
412
  ++sp
413
  tos iLOAD-C
414
  {sp} iSTORE
415
  a;
416
 
417
a: drop ( u -- : drop it like it's hot )
418
  {sp} iLOAD
419
  decSp branch
420
  (a);
421
 
422
a: swap ( u1 u2 -- u2 u1 : swap top two stack items )
423
  {sp} iLOAD
424
  t iSTORE-C
425
  tos iLOAD-C
426
  {sp} iSTORE
427
  t iLOAD-C
428
  tos iSTORE-C
429
  a;
430
 
431
a: over ( u1 u2 -- u1 u2 u1 : reach over top of stack and copy next on stack )
432
  {sp} iLOAD
433
  t iSTORE-C
434
  ++sp
435
  tos iLOAD-C
436
  {sp} iSTORE
437
  t iLOAD-C
438
  tos iSTORE-C
439
  a;
440
 
441
a: 1- ( u -- u : decrement top of stack by one )
442
  tos iLOAD-C
443
  set 2/ iADD
444
  tos iSTORE-C
445
  a;
446
 
447
a: >r ( u -- , R: -- u : move variable from data to return stack )
448
  ++rp
449
  tos iLOAD-C
450
  {rp} iSTORE
451
  {sp} iLOAD
452
  decSp branch
453
  (a);
454
 
455
:m for talign >r begin ;m
456
:m =>r [ t' >r ] literal call ;m
457
:m =next [ t' opNext ] literal call ;m
458
 
459
a: r>  ( -- u , R: u -- : move variable from return to data stack )
460
  {rp} iLOAD
461
  t iSTORE-C
462
  --rp
463
  ++sp
464
  tos iLOAD-C
465
  {sp} iSTORE
466
  t iLOAD-C
467
  tos iSTORE-C
468
  a;
469
 
470
a: r@ ( -- u, R: u -- u : copy top of return stack to data stack )
471
  ++sp
472
  tos iLOAD-C
473
  {sp} iSTORE
474
  {rp} iLOAD
475
  tos iSTORE-C
476
  a;
477
 
478
a: rdrop ( --, R: u -- : drop top item on return stack )
479
  --rp
480
  a;
481
 
482
a: execute ( xt -- : execute an execution token! )
483
  tos iLOAD-C
484
  t iSTORE-C
485
  {sp} iLOAD
486
  tos iSTORE-C
487
  --sp
488
  t iLOAD-C
489
  1 iRSHIFT
490
  {nest} branch
491
  (a);
492
 
493
a: sp! ( ??? u -- ??? : set stack depth )
494
  tos iLOAD-C
495
  {sp} iSTORE-C
496
  {sp} iLOAD
497
  tos iSTORE-C
498
  a;
499
 
500
a: rp! ( u -- , R: ??? --- ??? : set return stack depth )
501
  tos iLOAD-C
502
  {rp} iSTORE-C
503
  {sp} iLOAD
504
  decSp branch
505
  (a);
506
 
507
a: sp@ ( -- u : get variable stack depth )
508
  {sp} iLOAD-C
509
  t iSTORE-C
510
  ++sp
511
  tos iLOAD-C
512
  {sp} iSTORE
513
  t iLOAD-C
514
  tos iSTORE-C
515
  a;
516
 
517
a: rp@ ( -- u : get return stack depth )
518
  ++sp
519
  tos iLOAD-C
520
  {sp} iSTORE
521
  {rp} iLOAD-C
522
  tos iSTORE-C
523
  a;
524
 
525
\ ---- ---- ---- ---- ---- no more direct assembly ---- ---- ---- ---- ----
526
 
527
assembler.1 -order
528
 
529
:ht #0   0 lit ;t ( --  0 : space saving measure, push  0 onto variable stack )
530
:ht #1   1 lit ;t ( --  1 : space saving measure, push  1 onto variable stack )
531
:ht #-1 -1 lit ;t ( -- -1 : space saving measure, push -1 onto variable stack )
532
 
533
\ Add words written in assembly into dictionary, you will need an understanding
534
\ of wordlists to understand this.
535
 
536
:to bye bye ;t
537
:to and and ;t
538
:to or or ;t
539
:to xor xor ;t
540
:to + + ;t
541
:to um+ um+ ;t
542
:to @ @ ;t
543
:to ! ! ;t
544
:to c@ c@ ;t
545
:to dup dup ;t
546
:to drop drop ;t
547
:to swap swap ;t
548
:to over over ;t
549
:to 1- 1- ;t
550
:to >r r> swap >r >r ;t compile-only
551
:to r> r> r> swap >r ;t compile-only
552
:to r@ r> r@ swap >r ;t compile-only
553
:to execute execute ;t
554
 
555
:t 0= if #0 exit then #-1 ;t
556
:t invert #-1 xor ;t
557
:t 1+ #1 + ;t
558
:t emit ( ch -- :  )
559
   begin 8002 lit @ 1000 lit and 0= until
560
   FF lit and 2000 lit or 8002 lit ! ;t
561
:t key? ( -- ch -1 | 0 )
562
   8002 lit @ 100 lit and if #0 exit then
563
   400 lit 8002 lit ! 8002 lit @ FF lit and #-1 ;t
564
:t here h lit @ ;t
565
:t base {base} lit ;t  ( -- a : base variable controls input/output radix )
566
:t dpl {dpl} lit ;t    ( -- a : push address of 'dpl' onto the variable stack )
567
:t hld {hld} lit ;t    ( -- a : push address of 'hld' onto the variable stack )
568
:t bl 20 lit ;t        ( -- space : push a space onto the stack )
569
:t >in {in} lit ;t     ( -- b : push pointer to terminal input position )
570
:t hex  $10 lit base ! ;t ( -- : switch to hexadecimal input/output radix )
571
:t source TERMBUF lit #tib lit @ ;t ( -- b u )
572
:t last {last} lit @ ;t      ( -- : last defined word )
573
:t state {state} lit ;t      ( -- a : compilation state variable )
574
:t ] #-1 state ! ;t          ( -- : turn compile mode on )
575
:t [ #0 state ! ;t immediate ( -- : turn compile mode off )
576
:t nip swap drop ;t          ( u1 u2 -- u2 : remove next stack value )
577
:t tuck swap over ;t         ( u1 u2 -- u2 u1 u2 : save top stack value )
578
:t ?dup dup if dup then ;t   ( u -- u u | 0 : duplicate if not zero )
579
:t rot >r swap r> swap ;t    ( u1 u2 u3 -- u2 u3 u1 : rotate three numbers )
580
:t 2drop drop drop ;t        ( u u -- : drop two numbers )
581
:t 2dup  over over ;t        ( u1 u2 -- u1 u2 u1 u2 : duplicate set of values )
582
:t +! tuck @ + swap ! ;t     ( n a -- : increment value at address by 'n' )
583
:t = xor 0= ;t               ( u u -- f : equality )
584
:t <> = 0= ;t                ( u u -- f : inequality )
585
:t 0>= 8000 lit and 0= ;t    ( n -- f : greater or equal to zero )
586
:t 0< 0>= 0= ;t              ( n -- f : less than zero )
587
:t negate 1- invert ;t       ( n -- n : negate [twos compliment] )
588
:t - negate + ;t             ( u u -- u : subtract )
589
:t < - 0< ;t                 ( n n -- f : signed less than )
590
:t > swap < ;t               ( n n -- f : signed greater than )
591
:t 0> #0 > ;t                ( n -- f : greater than zero )
592
:t 2* #1 lls ;t              ( u -- u : multiply by two )
593
:t 2/ #1 lrs ;t              ( u -- u : divide by two )
594
:t cell 2 lit ;t             ( -- u : size of memory cell )
595
:t cell+ cell + ;t           ( a -- a : increment address to next cell )
596
:t pick sp@ + 2* @ ;t        ( ??? u -- ??? u u : )
597
:t u< 2dup 0>= swap 0>= xor >r < r> xor ;t ( u u -- f : )
598
:t aligned dup #1 and + ;t       ( b -- u : align a pointer )
599
:t align here aligned h lit ! ;t ( -- : align dictionary pointer )
600
:t depth {sp0} lit @ sp@ - 1- ;t ( -- u : variable stack depth )
601
:t c! ( c b -- : store character at address )
602
  dup dup >r #1 and if
603
    @ 00FF lit and swap FF lit lls
604
  else
605
    @ FF00 lit and swap FF lit and
606
  then or r> ! ;t
607
:t count dup 1+ swap c@ ;t ( b -- b c : advance string, get next char )
608
:t allot aligned h lit +! ;t            ( u -- : allocate space in dictionary )
609
:t , align here ! cell allot ;t         ( u -- : write a value into the dictionary )
610
:t abs dup 0< if negate then ;t         ( n -- u : absolute value of a number )
611
:t mux dup >r and swap r> invert and or ;t ( u1 u2 f -- )
612
:t max 2dup < mux ;t  ( n n -- n : maximum of two numbers )
613
:t min 2dup > mux ;t  ( n n -- n : minimum of two numbers )
614
:t +string #1 over min rot over + rot rot - ;t ( b u -- b u : increment str )
615
:t catch ( xt -- exception# | 0 \ return addr on stack )
616
   sp@ >r              ( xt )   \ save data stack pointer
617
   {handler} lit @ >r  ( xt )   \ and previous handler
618
   rp@ {handler} lit ! ( xt )   \ set current handler
619
   execute             ( )      \ execute returns if no throw
620
   r> {handler} lit !  ( )      \ restore previous handler
621
   rdrop               ( )      \ discard saved stack ptr
622
   #0 ;t               ( 0 )    \ normal completion
623
:t throw ( ??? exception# -- ??? exception# )
624
    ?dup if              ( exc# )     \ 0 throw is no-op
625
      {handler} lit @ rp!   ( exc# )     \ restore prev return stack
626
      r> {handler} lit !    ( exc# )     \ restore prev handler
627
      r> swap >r            ( saved-sp ) \ exc# on return stack
628
      sp! drop r>           ( exc# )     \ restore stack
629
    then ;t
630
:t um* ( u u -- ud : double cell width multiply )
631
  #0 swap ( u1 0 u2 ) $F lit
632
  for dup um+ >r >r dup um+ r> + r>
633
    if >r over um+ r> + then
634
  next rot drop ;t
635
:t um/mod ( ud u -- ur uq : unsigned double cell width divide/modulo )
636
  ?dup 0= if -A lit throw then
637
  2dup u<
638
  if negate $F lit
639
    for >r dup um+ >r >r dup um+ r> + dup
640
      r> r@ swap >r um+ r> or
641
      if >r drop 1+ r> else drop then r>
642
    next
643
    drop swap exit
644
  then 2drop drop #-1 dup ;t
645
:t key begin key? until ;t     ( c -- : get a character from UART )
646
:t type begin dup while swap count emit swap 1- repeat 2drop ;t ( b u -- )
647
:t cmove for aft >r dup c@ r@ c! 1+ r> 1+ then next 2drop ;t ( b1 b2 u -- )
648
:t do$ r> r> 2* dup count + aligned 2/ >r swap >r ;t ( -- a : )
649
:t ($) do$ ;t            ( -- a : do string NB. )
650
:t .$ do$ count type ;t  ( -- : print string, next cells contain string )
651
:m ." .$ $literal ;m
652
:m $" ($) $literal ;m
653
:t space bl emit ;t               ( -- : print space )
654
:t cr .$ 2 tc, =cr tc, =lf tc, ;t ( -- : print new line )
655
:t ktap ( bot eot cur c -- bot eot cur )
656
  dup dup =cr lit <> >r  =lf lit <> r> and if \ Not End of Line?
657
    dup =bksp lit <> >r =del lit <> r> and if \ Not Delete Char?
658
      bl ( tap -> ) dup emit over c! 1+ ( bot eot cur c -- bot eot cur )
659
      exit
660
    then
661
    >r over r@ < dup if
662
      =bksp lit dup emit space emit
663
    then
664
    r> +
665
    exit
666
  then drop nip dup ;t
667
:t accept ( b u -- b u : read in a line of user input )
668
  over + over
669
  begin
670
    2dup xor
671
  while
672
    key dup bl - $5F lit u< if ( tap -> ) dup emit over c! 1+ else ktap then
673
  repeat drop over - ;t
674
:t query TERMBUF lit =buf lit accept #tib lit ! drop #0 >in ! ;t ( -- : get line)
675
:t ?depth depth > if -4 lit throw then ;t ( u -- : check stack depth )
676
:t -trailing ( b u -- b u : remove trailing spaces )
677
  for
678
    aft bl over r@ + c@ <
679
      if r> 1+ exit then
680
    then
681
  next #0 ;t
682
:ht look ( b u c xt -- b u : skip until *xt* test succeeds )
683
  swap >r rot rot
684
  begin
685
    dup
686
  while
687
    over c@ r@ - r@ bl = 4 lit pick execute
688
    if rdrop rot drop exit then
689
    +string
690
  repeat rdrop rot drop ;t
691
:ht no-match if 0> exit then 0= 0= ;t ( c1 c2 -- t )
692
:ht match no-match invert ;t          ( c1 c2 -- t )
693
:t parse ( c -- b u ;  )
694
    >r source drop >in @ + #tib lit @ >in @ - r@
695
    >r over r> swap >r >r
696
    r@ t' no-match lit look 2dup
697
    r> t' match    lit look swap r> - >r - r> 1+  ( b u c -- b u delta )
698
    >in +!
699
    r> bl = if -trailing then #0 max ;t
700
:t spaces begin dup 0> while space 1- repeat drop ;t ( +n -- )
701
:t hold #-1 hld +! hld @ c! ;t ( c -- : save a character in hold space )
702
:t #> 2drop hld @ =tbufend lit over - ;t  ( u -- b u )
703
:t #  ( d -- d : add next character in number to hold space )
704
   2 lit ?depth
705
   #0 base @
706
   ( extract ->) dup >r um/mod r> swap >r um/mod r> rot ( ud ud -- ud u )
707
   ( digit -> ) 9 lit over < 7 lit and + [char] 0 + ( u -- c )
708
   hold ;t
709
:t #s begin # 2dup ( d0= -> ) or 0= until ;t       ( d -- 0 )
710
:t <# =tbufend lit hld ! ;t                        ( -- )
711
:t sign 0< if [char] - hold then ;t                ( n -- )
712
:t u.r >r #0 <# #s #>  r> over - spaces type ;t    ( u +n -- : print u right justified by +n )
713
:t u.  #0 <# #s #> space type ;t                   ( u -- : print unsigned number )
714
:t . dup >r abs #0 <# #s r> sign #> space type ;t  ( n -- print number )
715
:t >number ( ud b u -- ud b u : convert string to number )
716
  begin
717
    2dup >r >r drop c@ base @        ( get next character )
718
    ( digit? -> ) >r [char] 0 - 9 lit over <
719
    if 7 lit - dup $A lit < or then dup r> u< ( c base -- u f )
720
    0= if                            ( d char )
721
      drop                           ( d char -- d )
722
      r> r>                          ( restore string )
723
      exit                           ( ..exit )
724
    then                             ( d char )
725
    swap base @ um* drop rot base @ um* ( d+ -> ) >r swap >r um+ r> + r> + ( accumulate digit )
726
    r> r>                            ( restore string )
727
    +string dup 0=                   ( advance string and test for end )
728
  until ;t
729
:t number? ( a u -- d -1 | a u 0 : string to a number [easier to use] )
730
  #-1 dpl !
731
  base @ >r
732
  over c@ [char] - = dup >r if     +string then
733
  over c@ [char] $ =        if hex +string then
734
  >r >r #0 dup r> r>
735
  begin
736
    >number dup
737
  while over c@ [char] . xor
738
    if rot drop rot r> 2drop #0 r> base ! exit then
739
    1- dpl ! 1+ dpl @
740
  repeat
741
  2drop r> if
742
    ( dnegate -> ) invert >r invert #1 um+ r> +
743
  then r> base ! #-1 ;t
744
:t compare ( a1 u1 a2 u2 -- n : string equality )
745
  rot
746
  over - ?dup if >r 2drop r> nip exit then
747
  for ( a1 a2 )
748
    aft
749
      count rot count rot - ?dup
750
      if rdrop nip nip exit then
751
    then
752
  next 2drop #0 ;t
753
:to .s depth  for aft r@ pick . then next ;t ( -- : print variable stack )
754
:t nfa cell+ ;t ( pwd -- nfa : move word pointer to name field )
755
:t cfa nfa dup c@ $1F lit and + cell+ cell negate and ;t ( pwd -- cfa )
756
:t (find) ( a wid -- PWD PWD 1|PWD PWD -1|0 a 0: find word in WID )
757
  swap >r dup
758
  begin
759
    dup
760
  while
761
    dup nfa count $9F lit ( $1F:word-length + $80:hidden ) and r@ count compare 0=
762
    if ( found! )
763
      rdrop
764
      dup ( immediate? -> ) nfa $40 lit swap @ and 0= 0=
765
      #1 or negate exit
766
    then
767
    nip dup @
768
  repeat
769
  2drop #0 r> #0 ;t
770
:t find last (find) rot drop ;t  ( "name" -- b )
771
:t literal state @ if =push lit , , then ;t immediate ( u -- )
772
:t compile, 2/ align C000 lit or , ;t                 ( xt -- )
773
:t ?found if exit then space count type [char] ? emit cr -D lit throw ;t ( u f -- )
774
:t interpret                                          ( b -- )
775
  find ?dup if
776
    state @
777
    if
778
      0> if cfa execute exit then \ <- immediate word are executed
779
      cfa compile, exit           \ <- compiling word are...compiled.
780
    then
781
    drop
782
    dup nfa c@ 20 lit and if -E lit throw then ( <- ?compile )
783
    cfa execute exit  \ <- if its not, execute it, then exit *interpreter*
784
  then
785
  \ not a word
786
  dup >r count number? if rdrop \ it is a number!
787
    dpl @ 0< if \ <- dpl will be -1 if it is a single cell number
788
       drop     \ drop high cell from 'number?' for single cell output
789
    else        \ <- dpl is not -1, it is a double cell number
790
       state @ if swap then
791
       postpone literal \ literal is executed twice if it's a double
792
    then
793
    postpone literal exit
794
  then
795
  r> #0 ?found \ Could vector ?found here, to handle arbitrary words
796
  ;t
797
:t word parse here dup >r 2dup ! 1+ swap cmove r> ;t ( c -- b )
798
:to words last begin dup nfa count 1f lit and space type @ ?dup 0= until ;t
799
:to see bl word find ?found
800
    cr begin dup @ =unnest lit <> while dup @ u. cell+ repeat @ u. ;t
801
:to : align here last , {last} lit ! ( "name" -- : define a new word )
802
    bl word
803
    dup c@ 0= if -A lit throw then
804
    count + h lit ! align
805
    =0iGET lit , =nest lit , ] BABE lit ;t
806
:to ; postpone [ BABE lit <> if -16 lit throw then  =unnest lit , ;t immediate compile-only
807
:to begin align here ;t immediate compile-only
808
:to until =jumpz lit , 2/ , ;t immediate compile-only
809
:to again =jump  lit , 2/ , ;t immediate compile-only
810
:to if =jumpz lit , here #0 , ;t immediate compile-only
811
:to then here 2/ swap ! ;t immediate compile-only
812
:to for =>r lit , here ;t immediate compile-only
813
:to next =next lit , 2/ , ;t immediate compile-only
814
:to ' bl word find ?found cfa literal ;t immediate
815
:t compile r> dup 2* @ , 1+ >r ;t compile-only ( -- : compile next compiled into dictionary )
816
:to exit compile exit ;t immediate compile-only
817
:to ." compile .$  [char] " word count + h lit ! align ;t immediate compile-only
818
:to $" compile ($) [char] " word count + h lit ! align ;t immediate compile-only  \ "
819
:to ( [char] ) parse 2drop ;t immediate ( "comment" -- discard until parenthesis )
820
:to \ source drop @ >in ! ;t immediate  ( "comment" -- discard until end of line )
821
:to immediate last nfa @ $40 lit or last nfa ! ;t ( -- : turn previously defined word into an immediate one )
822
:to dump begin over c@ u. +string ?dup 0= until drop ;t
823
:t eval begin bl word dup c@ while interpret #1 ?depth repeat drop ."  ok" cr ;t ( "word" -- )
824
:t ini hex postpone [ #0 >in ! #-1 dpl ! ;t ( -- )
825
:t quit ( -- : interpreter loop [and more, does more than most QUITs] )
826
   there t2/  t! \ program entry point set here
827
   ." eForth 3.2" cr
828
   ini
829
   begin
830
     query t' eval lit catch
831
     ( ?error -> ) ?dup if
832
       space . [char] ? emit cr ini
833
     then again ;t
834
 
835
\ ---- ---- ---- ---- ---- implementation finished ---- ---- ---- ---- ----
836
 
837
there h t!
838
atlast {last} t!
839
save-hex bit.hex
840
save-target bit.bin
841
.stat
842
.end
843
.( DONE ) cr
844
bye
845
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.