-
Notifications
You must be signed in to change notification settings - Fork 85
/
directive.src
782 lines (631 loc) · 12.5 KB
/
directive.src
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
.page
.subttl directive
; equate and orgin processing
h102 lda #$ff ;-1
sta jorg
inc icolp
stx ilsst ;save start of string
jsr nfndnb ;if rest field blank
bcs 20$ ;non-blank found
10$ jmp h99
20$ lda icrd,x ;equate or org
cmp #'='
bne 10$
h121 inc icolp ;look for operand after '='
jsr nfndnb
bcs 20$ ;...got something
jmp h99 ;...EOL: report error
20$ jsr eval ;eval operand field
dec return
bmi 40$
bne 30$
lda #$11
ldy #3
jmp lts1
30$ lda #$13
ldy #3
jmp lts1
40$ lda jorg ;equ or org
beq 60$
lda #1 ;org, expression ok
and overflow
beq 50$ ;expression is >=0
ldx #0 ;reset PC & wrap flag
stx ipc
stx ipc+1
stx wrap
ldx icsb ;bad expr - flag
lda #$21 ;PC overflow error
ldy #$ff
jsr ltins
jmp endln
50$ ldx #0
txa
tay
sta wrap
jsr ltins
lda iexp ;ipc = iexp
sta ipc+1
lda iexp+1
sta ipc
jmp endln
; is equate
60$ pla ;restore label portion
sta icsl ;restore length
ldx #5
70$ pla
sta isym,x
dex
bpl 70$
jsr nfind
bcc 90$
lda knval ;see if value is the same
cmp iexp
bne 80$
lda knval+1
cmp iexp+1
beq 100$ ;ok
80$ ldx ilsst ;already defined
lda #2
ldy #0
jmp lts1
90$ lda iexp
sta knval
lda iexp+1
sta knval+1
jsr nsert
100$ jmp h990
.page
; assembler directives *****
; find what directive to process
directive
lda #$14 ;asm error code
sta ierr
ldx icsb ;start of directive
inx ;skip period
lda #<asmdir
sta tblptr
lda #>asmdir
sta tblptr+1
lda #3 ;get length
sta klen
jsr consym ;build directive
dex
10$ inx
lda icrd,x ;look for end of directive
beq 30$ ;...EOL
cmp #space
bne 10$ ;...loop until blank or EOL
30$ stx icolp ;pntr to char after direct
lda #0 ;init column to zero
sta j ;...fall thru to look for match
.page
; search table of directives for match:
;
; if a match --> indirect JMP made to process
; if no match --> pointer points to next valid directive in table.
;
; search is done from back to front of table.
; .x (numasm) --> number of directives to check
; (tblptr) --> pointer to current directive in table
ldx #numasm
h9938 ldy #2 ;# characters-1 per directive
10$ lda isym,y ;do compare
cmp (tblptr),y
bne 20$ ;...until no match
dey
bpl 10$ ;...until end of directive (match)
; a match- .X is index to directive dispatch table
txa
asl a ;*2 for addr table index
tax
lda asmjmp,x ;low byte addr
sta tblptr
lda asmjmp+1,x ;high byte addr
sta tblptr+1
jmp (tblptr) ;======> go process directive
; no match- point to next table entry & start again. quit if done (error).
20$ lda tblptr ;low addr
clc
adc #3 ;offset to next directive
sta tblptr
bcc 30$
inc tblptr+1
30$ dex
bpl h9938 ;...loop while more directives
; invalid directive - error
jmp h900 ;put in length table
.page
; .MESSAGE processing **
dimes lda pass
beq 30$ ;...only during pass 2
jsr nfndnb ;.MES- look for 'string' to print to console
bcc 30$ ;...nothing- treat like a comment
jsr is_quote
bne 30$ ;...not a quote
ldy #0
10$ inx ;copy string into error buffer
lda icrd,x
beq 20$ ;...until EOL
jsr is_quote
beq 20$ ;...until end quote
sta doserr,y
iny
cpy #48-2
bcc 10$ ;...until error buffer full
20$ lda #cr
sta doserr,y ;append <cr>
lda #0
sta doserr+1,y ;terminate with a null
lda #>doserr
ldy #<doserr
jsr wscrn ;print the message to console
30$ jmp h990 ;print the source line to listing
; .BYTE, .WORD, .DBYTE processing ***
h111 lda #1 ;.BYTE
.byte $2c
h506 lda #3 ;.DBYTE
.byte $2c
h113 lda #2 ;.WORD
sta jbywor
ldy #0
sty j ;memmap index for byte gen
tay
cpy #3 ;.dbyte?
bne 10$ ;...no
dey
10$ sty char ;length of each param.
jsr nfndnb ;next non-blank
bcs h18 ;non-blank found
ldx icse ;ran off eol
lda #7
jmp lts1
h18 ldx icsb
jsr eval
dec return
bmi 40$ ;return =0
beq 30$ ;return =1
jmp h29 ;return =2
30$ lda #1 ;undef'd sym
sta ierr
lda char
clc
adc j
tay
lda ierr
ldx icsb
jsr ltins
ldy #0
sty j
jmp h15
40$ lda #4 ;good return
sta ierr
ldx jbywor
cpx #1
beq 70$ ;...if .byte
cpx #3
bne 50$ ;...if .word
lda iexp ;is .dbyte
ldy j
jsr objout
inc j
50$ lda iexp+1 ;is .word
ldy j
jsr objout
inc j
ldx jbywor
cpx #2
bne 60$ ;...if .dbyte
lda iexp
ldy j
jsr objout ;iexp in memory map
inc j
60$ lda #0
tax
ldy char
sta j
jsr ltins
jmp h15
70$ lda iexp+1 ;is .byte
ldy j
jsr objout
inc j
bne h15
80$ jsr nfncmp ;more parms?
lda iexp+1
bcs 90$ ;more parms
eor #$80
90$ ldy j
jsr objout
inc j
; find next parameter
h15 jsr nfncmp ;look for comma
bcs 10$ ;...found it (maybe)
jmp byte15 ;...no more parms
10$ lda icrd,x ;get the character
beq 20$ ;...EOL
inx ;point to next character
stx icolp
cmp #comma
bne h15 ;...not comma, maybe paren
jsr nfndnb ;look for something after comma
bcc 20$
jmp h18 ;...found chr: evaluate
20$ jmp h99 ;...found EOL: report error
; expression handler bombed
h29 lda j
beq 10$
txa ;output line (remain)
pha
ldy j
lda #0
tax
sta j
jsr ltins
pla
tax
10$ lda icrd,x
jsr is_quote ;ascii?
beq 30$
20$ lda #$13 ;bad expression
ldy temp
jsr ltins
ldy #0
sty j
jmp h15
; looks like ascii
30$ sta delm ;save delimiter
cpx icsb ;first in string
bne 20$
ldy jbywor ;after a .byt
cpy #2
bcs 20$
stx icolp ;count bytes generated
ldy #0
40$ inc icolp
ldx icolp
50$ lda icrd,x
beq 80$ ;...EOL (error)
cmp delm ;compare delimiter
bne 70$ ;...no
inc icolp ;imbedded quote
ldx icolp
60$ lda icrd,x
beq 130$ ;...EOL (logical end of string)
cmp delm
bne 90$ ;...no
70$ ldy j ;convert to ascii
sta objmap,y ;byte to memory map
inc j ;count of ascii chars
bne 40$ ;*** bra
80$ ldy j ;EOL: report error
lda #7
jmp lts1
; **********************
; * .BYTE expression *
; **********************
90$ sta kop
jsr endtst
bcs 130$
ldy #0
sty ysave
stx xsave
100$ cpy j
beq 130$
lda #0
sta iexp
lda objmap,y
sta iexp+1
ldx xsave ;restore x
stx icolp ;restore x
jsr d71 ;eval follows
dec return
beq 110$ ;undefined symbol
bpl 120$ ;bad expression
lda iexp+1 ;expression ok
ldy ysave
sta objmap,y
iny
inc ysave
bne 100$ ;*** bra
110$ lda #1 ;undefined symbol
.byte $2c
120$ lda #$18 ;bad expression
sta ierr ;undefed symbol
130$ ldy #0 ;done with ascii string
sty ysave
140$ iny
cpy j
beq 150$ ;last character
dey
lda objmap,y
jsr objout ;output object
inc ysave
ldy ysave
bne 140$ ;*** bra
150$ dey
lda objmap,y
jsr objout
inc ysave
ldy ysave
lda #0
sta j
tax
jsr ltins
jmp h15
byte15 lda j
bne 10$
jmp endln
10$ ldy j
lda #0
tax
jmp lts1
.page
; .OPT assembler directive
;
; > look for parms until none left.
; > when done, treat line as a comment.
; > use search from asmb directives.
h301 jsr nfndnb ;find beginning of option string
bcs 10$ ;...ok
jmp h990 ;...EOL: treat like comment
10$ ldx icsb ;get start of parm
lda #3 ;3 is length of parm
sta klen ;store for consym
jsr consym ;construct the parm
bcs 20$ ;...ok
jmp h900 ;...bad parm - error
; search. NOTE: must restore .X and the adr where the search left off.
20$ lda #<optdir ;set (tblptr) to include .OPTIONS
sta tblptr
lda #>optdir
sta tblptr+1
ldx #numsav ;# of directives to search
jmp h9938 ;go do the search, will JMP() to process if found.
;continue .OPT processing when done.
.page
nhash lda #0 ;disable long labels
.byte $2c
hash lda #$ff ;enable long labels
sta fhash
jmp h391
h311 lda optsav ;enable listing option (restore runtime spec)
and #opt_lst
.byte $2c
h323 lda #opt_gen ;enable string generation
.byte $2c
h303 lda #opt_sym ;enable symbol table
.byte $2c
h307 lda #opt_err ;enable error messages
.byte $2c
h309 lda #opt_mac ;enable object generation
.byte $2c
h331 lda #opt_mac ;enable macro expansion
ora options
bne opt_set ;...bra
h312 lda #$ff-opt_lst ;disable listing option
.byte $2c
h302 lda #$ff-opt_gen ;disable string generation
.byte $2c
h304 lda #$ff-opt_sym ;disable symbol table
.byte $2c
h308 lda #$ff-opt_err ;disable error messages
.byte $2c
h310 lda #$ff-opt_obj ;disable object generation
.byte $2c
h330 lda #$ff-opt_mac ;disable macro expansion
and options
opt_set sta options ;update assembler options
.page
h391 jsr nfncmp ;continue processing .OPT: look for comma
bcs 10$ ;...comma or right paren
jmp h990 ;...none found
10$ lda icrd,x ;something follows
cmp #comma
beq 20$ ;...comma
jmp endln ;...no
20$ inx
stx icolp
jmp h301
; skip ***
h26 jsr nfndnb ;next non-blank
bcs 10$ ;non-blank found
ldx j
10$ lda #204
ldy #0
jmp lts1
; page ***
; has a title with it?
h12 jsr nfndnb ;next nonblank
bcc 10$ ;only blanks found
lda icrd,x ;next title char
jsr is_quote ;a quote?
beq 20$ ;yes
10$ ldx #0
20$ lda #203
ldy #0
jmp lts1
; end ***
h10 bit sfile ;what is done?
bvs 20$ ;...include file
ldx stack_ptr ;...pass
txs
ldx pass ;which pass?
beq 10$ ;...pass 1
lda #2 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> end pass 2
jsr close ;close source file (#2)
ldx #0
ldy #0
lda #205
jsr ltins ;print the .END
jmp pass3 ;sort & print symbol table & xref
10$ inc pass ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> end pass 1
lda #2
jsr close ;close source file (#2)
jmp pass2 ;start pass 2
20$ lda #3 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> end include file
jsr close ;close 'included' source file (#3)
lda sfile
and #$bf ;switch control
sta sfile
endr ldx #0
stx chan
ldy #0
lda #205
inc lboth
jsr ltins
dec lboth
lda #$0d
sta lchar
jmp endln
; file ***
hfil bit sfile
bvc 10$ ;not in .LIB
lda #3 ;close .LIB file
jsr close
jmp dlib1 ;reopen .LIB as .FIL
10$ lda #2 ;close old file
jsr close
jsr nfile ;parse new file
lda #2 ;logical file #2
tay
ldx sunit
jsr setlfs
jsr open
jsr ftest
jmp endr
; common parse routine
nfile jsr nfndnb ;find beginning of name
bcc 20$ ;...EOL: no name
ldy #0
10$ lda icrd,x ;extract filename
beq 30$ ;...until EOL
cmp #space
beq 30$ ;...until blank
sta isym,y
inx
iny
cpy #16
bcc 10$ ;...until too long
20$ jsr clear_io
jsr primm
.byte cr,rvs,bell,'FILE NAME ERROR',cr,0
jmp done ;...abort assembly
30$ lda #$0d ;flag fresh start
sta lchar
lda #comma ;append ',S' file type
sta isym,y
iny
lda #'S'
sta isym,y
iny
tya ;filename length
ldy #>isym ;filename address
ldx #<isym
jsr setnam ;set up file name for open
ldx #0
jmp setbnk ;set bank for name & rts
; lib ***
hlib bit sfile ;cannot nest .LIB's
bvc dlib1 ;...ok
jsr clear_io
jsr primm
.byte cr,rvs,bell,'.LIB ERROR',cr,0
jmp done ;...abort assembly
dlib1 jsr nfile ;parse filename
lda #3 ;la
tay ;sa
ldx sunit ;fa
jsr setlfs
jsr open ;open .LIB source file (#3)
jsr ftest
lda #$40
ora sfile
sta sfile ;flag .LIB
jmp endr
.page
; .IFN and .IFE ***
;
; syntax for conditional assembly is as follows:
;
; .IFE expr <
; code
; >
;
; where: .IFE (or .IFN) is the directive meaning IF EQUAL (or IF NOT EQUAL)
; expr is a valid expression (no forward references).
; < is the start of an IF range (on same card).
;
; the end of IF range is marked by > character in the first column of a card in
; the same FILE as the IF statement.
hifn lda #$ff ;not equal flag
.byte $2c
hife lda #$00 ;equal flag
sta ifflag
jsr nfndnb ;find next non-blank
bcc ranoff ;ran off end of card
sty char
ldx icsb ;index into card
jsr eval ;evaluate expression
dec return ;simpler testing
bmi 10$ ;good return
beq hundef ;undefined something
jmp noeval ;could not eval...
; look for '<', test expression, execute result
10$ stx icolp ;new pntr in line
jsr nfndnb ;skip blanks
bcc ranoff ;not there
cmp #'<' ;check for right char.
beq 20$ ;found it
jmp ranoff ;bad directive
20$ ldy #$ff ;set y to inverse
lda iexp ;get value of expr
ora iexp+1
beq 30$
iny ;$00
30$ tya
eor ifflag ;tack in the flag
bne 60$ ;false condition- assemble
; eat source until '>' is found
40$ jsr newchr ;get a char
cmp #cr ;return char?
bne 40$ ;no- loop until end of card
jsr newchr ;if next card starts with > then stop
cmp #'>'
bne 40$ ;no- keep eating
lda #0
tax
tay
jsr ltins
inc icrdno+1
bne 50$
inc icrdno
50$ lda #0
sta lcdpt ;clear multiple lines flag
lda #'>'
sta icrd
ldx #1 ;card column pointer
jsr card1
jmp card0
60$ jmp h990 ;finished...
;
; errors and subroutines for IF's
;
hundef lda pass ;which pass?
bne notdef ;...pass 2
lda #11 ;foward ref error
.byte $2c
notdef lda #1 ;not defined
.byte $2c
ranoff lda #7 ;ran off card
.byte $2c
noeval lda #13 ;can't eval expr...
ldx icse ;pointer into card
ldy #0 ;num of bytes generated
jmp lts1
newchr jsr getchr ;read next character from source file
cmp #0
beq 10$ ;...EOF
rts
10$ jmp h10 ;...missing .END
;.end