-
Notifications
You must be signed in to change notification settings - Fork 4
/
X80.B2S
921 lines (865 loc) · 26.7 KB
/
X80.B2S
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
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
1000 REM &
REM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! &
REM !! !! &
REM !! 8080/8085 Cross Assembler !! &
REM !! !!
1010 REM !! A.G. Nicholson, Newcastle Uni . !! &
REM !! !! &
REM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! &
1020 REM &
REM ! Version of 12-May-80 &
1030 EXTEND
1040 CCL.ENTRY%=0%
1050 DIM SYMBOLS$(767%), &
VALUES%(767%), &
FLAGS%(767%), &
SYMBOL.CHARS%(6%), &
DELIMITER.TABLE%(3%)
1060 ! -- Set up error trap routine --
1070 ON ERROR GOTO 31020 &
\ X$=SYS(CHR$(6%)+CHR$(-7%))
1080 ! -- Initialise --
1090 NUMBER.OF.SYMBOLS%=0% &
\ SYMBOL.TABLE.SIZE%=768% &
\ START.CPU.TIME%=TIME(1%) &
\ LISTING.FILE$="KB:"
1100 FOR I%=1% TO 97% &
\ READ SYMBOL$,VALUE%,FLAG.WORD% &
\ GOSUB 2310 &
\ NEXT I% &
! Read in opcodes
1110 FLAG.WORD%=0% &
\ FOR I%=1% TO 13% &
\ READ SYMBOL$,VALUE% &
\ GOSUB 2310 &
\ NEXT I% &
! Read in register definitions
1120 ! -- Print header --
1130 OPEN LISTING.FILE$ AS FILE 1% &
\ GOTO 1180 IF CCL.ENTRY% &
\ PRINT #1%,"8080/8085 Cross assembler" &
\ PRINT #1%,"#";
1140 ! &
1150 ! -- Get listing, source filenames --
1160 INPUT LINE #1%, SOURCE.FILE$ &
\ SOURCE.FILE$=CVT$$(SOURCE.FILE$,-1%)
1170 ! -- Check for errors only switch --
1180 ERRORS.ONLY.SWITCH%=-1% &
\ I%=INSTR(1%,SOURCE.FILE$,"/E") &
\ IF I% THEN SOURCE.FILE$=LEFT(SOURCE.FILE$,I%-1%)+ &
RIGHT(SOURCE.FILE$,I%+2%) &
\ ERRORS.ONLY.SWITCH%=0%
1190 ! -- Check for symbol table listing switch --
1200 SYMBOL.TABLE.LIST.FLAG%=INSTR(1%,SOURCE.FILE$,"/S") &
\ IF SYMBOL.TABLE.LIST.FLAG% THEN SOURCE.FILE$= &
LEFT(SOURCE.FILE$,SYMBOL.TABLE.LIST.FLAG%-1%)+ &
RIGHT(SOURCE.FILE$,SYMBOL.TABLE.LIST.FLAG%+2%)
1210 ! -- Check for object module output switch --
1220 OBJECT.OUT.FLAG%=0% &
\ I%=INSTR(1%,SOURCE.FILE$,"/O") &
\ IF I% THEN SOURCE.FILE$=LEFT(SOURCE.FILE$,I%-1%)+ &
RIGHT(SOURCE.FILE$,I%+2%) &
\ OBJECT.OUT.FLAG%=-1%
1230 ! -- Check for listing file and add default extensions --
1240 LISTING.TO.FILE.FLAG%=INSTR(1%,SOURCE.FILE$,"=") &
\ IF LISTING.TO.FILE.FLAG% THEN LISTING.FILE$= &
LEFT(SOURCE.FILE$,LISTING.TO.FILE.FLAG%-1%) &
\ LISTING.FILE$=LISTING.FILE$+".LST" UNLESS &
INSTR(1%,LISTING.FILE$,".") &
\ SOURCE.FILE$=RIGHT(SOURCE.FILE$, &
LISTING.TO.FILE.FLAG%+1%)
1250 SOURCE.FILE$=SOURCE.FILE$+".SRC" UNLESS &
INSTR(1%,SOURCE.FILE$,".")
1260 PRINT #1%,"Listing sent to "+ &
LISTING.FILE$ IF LISTING.TO.FILE.FLAG%
1270 IF OBJECT.OUT.FLAG% THEN OBJECT.FILE$= &
LEFT(SOURCE.FILE$,INSTR(1%,SOURCE.FILE$,"."))+"HEX" &
\ PRINT #1%,"Object module to ";OBJECT.FILE$
1280 ! -- Get a unique workfile name --
1290 WORK.FILE$="X80X"+MID(NUM$(100%+ASCII(SYS(CHR$(6%)+ &
CHR$(9%)))/2%),3%,2%)+".TMP"
1300 ! -- Commence assembly --
1310 GOSUB 2010 &
\ GOSUB 3010 &
\ X%=1% &
\ GOSUB 3720
1320 ! -- Print symbol table --
1330 GOSUB 3750 IF SYMBOL.TABLE.LIST.FLAG% &
\ PRINT #1%
1340 ! -- Finish up and exit --
1350 CLOSE 1% &
\ IF LISTING.TO.FILE.FLAG% THEN X%=0% &
\ GOSUB 3720
1360 PRINT "Runtime was";(TIME(1%)-START.CPU.TIME%)/10;"sec" &
\ GOTO 32767
1370 !
2000 &
! -- Pass 1 Driver routine -- &
2010 ERROR.COUNT%, &
TOTAL.BYTES%, &
LOCATION.COUNTER%, &
ERROR.LINE.FLAG%, &
OPCODE.TABLE.SUBSCRIPT%=0% &
\ PASS.NUMBER%=1% &
\ OPEN SOURCE.FILE$ FOR INPUT AS FILE 2% &
\ OPEN WORK.FILE$ FOR OUTPUT AS FILE 3% &
\ PRINT #1%,"Pass 1"
2020 INPUT LINE #2%,SOURCE.LINE$ &
\ SOURCE.LINE$=CVT$$(SOURCE.LINE$,421%) &
\ LINE.LENGTH%=LEN(SOURCE.LINE$) &
\ LINE.NUMBER%=LINE.NUMBER%+1%
2030 IF LINE.LENGTH%=0% OR LEFT(SOURCE.LINE$,1%)="$" THEN &
OPCODE.TABLE.SUBSCRIPT%=-1% &
\ GOTO 2150
2040 ! -- Scan source line --
2050 GOSUB 2190 &
\ GOSUB 2240
2060 ! -- Comment line ? --
2070 IF COMMENT.DELIMITER%=1% THEN &
OPCODE.TABLE.SUBSCRIPT%=-1% &
\ GOTO 2150
2080 ! -- Get argument field --
2090 IF COMMENT.DELIMITER% THEN ARGUMENT$= &
CVT$$(MID(SOURCE.LINE$,OPCODE.DELIMITER%+1%, &
COMMENT.DELIMITER%-OPCODE.DELIMITER%-1%),258%) &
ELSE ARGUMENT$=CVT$$(RIGHT(SOURCE.LINE$,OPCODE.DELIMITER%+1%),258%)
2100 ! -- Label ? --
2110 IF LABEL.DELIMITER% THEN SYMBOL$= &
CVT$$(LEFT(SOURCE.LINE$,LABEL.DELIMITER%-1%),128%) &
\ VALUE%=LOCATION.COUNTER% &
\ FLAG.WORD%=-2% &
\ GOSUB 2310
2120 ! -- Assignment ? --
2130 IF EQU.DELIMITER% THEN GOSUB 2380 &
ELSE GOSUB 2420
2140 ! -- Write to workfile --
2150 GOSUB 2460 &
\ GOTO 2020 IF OPCODE.TABLE.SUBSCRIPT%=-1% &
\ GOTO 2020 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)<>10%
2160 CLOSE 2%,3% &
\ RETURN &
! -- End of Pass 1
2170 ! &
2180 &
! -- Scan for strings in SOURCE.LINE$ -- &
2190 DELIMITER%=-1% &
\ TEMP2%=0%
2200 TEMP1%=INSTR(TEMP2%+1%,SOURCE.LINE$,"'") &
\ RETURN UNLESS TEMP1%
2210 TEMP2%=INSTR(TEMP1%+1%,SOURCE.LINE$,"'") &
\ IF TEMP2% THEN DELIMITER%=DELIMITER%+1% &
\ IF DELIMITER%<4% THEN DELIMITER.TABLE%(DELIMITER%)= &
SWAP%(TEMP1% AND 255%) OR (TEMP2% AND 255%) &
\ GOTO 2200
2220 RETURN
2230 &
! -- Search for token delimiters -- &
! LABEL.DELIMITER% Label &
! OPCODE.DELIMITER% Opcode &
! COMMENT.DELIMITER% Comment &
! EQU.DELIMITER% Assignment &
2240 LABEL.DELIMITER%=INSTR(1%,SOURCE.LINE$,":") &
\ LABEL.DELIMITER%=0% IF FNCHECK.SYNTAX%(LABEL.DELIMITER%) &
\ COMMENT.DELIMITER%=0%
2250 COMMENT.DELIMITER%=INSTR(COMMENT.DELIMITER%+1%,SOURCE.LINE$,";") &
\ GOTO 2250 IF FNCHECK.SYNTAX%(COMMENT.DELIMITER%) &
\ LABEL.DELIMITER%=0% IF (LABEL.DELIMITER%> &
COMMENT.DELIMITER% AND COMMENT.DELIMITER%<>0%) &
\ OPCODE.DELIMITER%=LABEL.DELIMITER%
2260 OPCODE.DELIMITER%=OPCODE.DELIMITER%+1% &
\ IF OPCODE.DELIMITER%>=LINE.LENGTH% THEN 2280 &
ELSE X%=ASCII(RIGHT(SOURCE.LINE$,OPCODE.DELIMITER%)) &
\ IF X%=9% OR X%=32% THEN 2260
2270 OPCODE.DELIMITER%=OPCODE.DELIMITER%+1% &
\ IF OPCODE.DELIMITER%<LINE.LENGTH% THEN &
X%=ASCII(RIGHT(SOURCE.LINE$,OPCODE.DELIMITER%)) &
\ IF X%<>9% AND X%<>32% THEN 2270 &
ELSE OPCODE.DELIMITER%=OPCODE.DELIMITER%-1%
2280 EQU.DELIMITER%=INSTR(1%,SOURCE.LINE$,"=") &
\ EQU.DELIMITER%=0% IF FNCHECK.SYNTAX%(EQU.DELIMITER%) OR &
(EQU.DELIMITER%>COMMENT.DELIMITER% AND &
COMMENT.DELIMITER%<>0%) &
\ OPCODE.DELIMITER%=EQU.DELIMITER% IF EQU.DELIMITER%
2290 OPCODE.DELIMITER%=COMMENT.DELIMITER%-1% IF &
(OPCODE.DELIMITER%>=COMMENT.DELIMITER% AND &
COMMENT.DELIMITER%<>0%) &
\ RETURN
2300 &
! Enter symbol SYMBOL$ into symbol table &
! and its value VALUE% &
2310 IF NUMBER.OF.SYMBOLS%=SYMBOL.TABLE.SIZE% THEN &
VALUE%=FNERROR.PRINT%("?X80 - FATAL: Symbol table overflow") &
\ STOP &
! Symbol table full
2320 X%=ASCII(SYMBOL$) &
\ IF X%<>46% AND ( X%<65% OR X%>90% ) THEN &
VALUE%=FNERROR.PRINT%("Invalid symbol = "+SYMBOL$) &
\ RETURN &
! Invalid symbol
2330 TEMP2%=FNHASH.SYMBOL%(SYMBOL$,SYMBOL.TABLE.SIZE%) &
! Hash symbol
2340 IF SYMBOLS$(TEMP2%)="" THEN SYMBOLS$(TEMP2%)=SYMBOL$ &
\ VALUES%(TEMP2%)=VALUE% &
\ FLAGS%(TEMP2%)=FLAG.WORD% &
\ NUMBER.OF.SYMBOLS%=NUMBER.OF.SYMBOLS%+1% &
\ RETURN &
! If slot empty, enter symbol, value and flagword
2350 IF SYMBOLS$(TEMP2%)=SYMBOL$ AND FLAGS%(TEMP2%)<0% THEN &
VALUE%=FNERROR.PRINT%("Redefined symbol = "+SYMBOL$) &
\ RETURN &
! Multiple definition not allowed
2360 TEMP2%=FNREHASH.SYMBOL%(TEMP2%,SYMBOL.TABLE.SIZE%) &
\ GOTO 2340
2370 &
! -- Enter assignment -- &
2380 SYMBOL$=CVT$$(MID(SOURCE.LINE$,LABEL.DELIMITER%+1%, &
EQU.DELIMITER%-LABEL.DELIMITER%-1%),136%) &
\ VALUE%=FNEVALUATE.EXPR%(ARGUMENT$)
2390 IF SYMBOL$="." THEN LOCATION.COUNTER%=VALUE% &
ELSE IF SYMBOL$="" THEN VALUE%= &
FNERROR.PRINT%("Missing symbol") &
ELSE FLAG.WORD%=-1% &
\ GOSUB 2310
2400 OPCODE.TABLE.SUBSCRIPT%=-1% &
\ RETURN
2410 &
! -- Get opcode subscript -- &
2420 OPCODE$=CVT$$(MID(SOURCE.LINE$,LABEL.DELIMITER%+1%, &
OPCODE.DELIMITER%-LABEL.DELIMITER%),8%) &
\ IF OPCODE$<>"" THEN OPCODE.TABLE.SUBSCRIPT%= &
FNHASH.SYMBOL%(OPCODE$,SYMBOL.TABLE.SIZE%) &
ELSE OPCODE.TABLE.SUBSCRIPT%=-1% \ RETURN
2430 IF SYMBOLS$(OPCODE.TABLE.SUBSCRIPT%)=OPCODE$ THEN RETURN &
ELSE IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)<0% OR &
SYMBOLS$(OPCODE.TABLE.SUBSCRIPT%)="" THEN &
OPCODE.TABLE.SUBSCRIPT%= &
FNERROR.PRINT%("Invalid opcode = "+OPCODE$)-1% &
ELSE OPCODE.TABLE.SUBSCRIPT%= &
FNREHASH.SYMBOL%(OPCODE.TABLE.SUBSCRIPT%, &
SYMBOL.TABLE.SIZE%) &
\ GOTO 2430 &
! Check for opcode match in the symbol table &
! If flagword < 0 then report an error else rehash
2440 RETURN
2450 &
! -- Get byte count and output to workfile -- &
2460 IF OPCODE.TABLE.SUBSCRIPT%=-1% THEN BYTE.COUNT%=0% &
ELSE IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)>3% THEN &
GOSUB 2500 &
ELSE BYTE.COUNT%=FLAGS%(OPCODE.TABLE.SUBSCRIPT%) &
! Get byte count into BYTE.COUNT%
2470 PRINT #3%,LOCATION.COUNTER%;","; &
BYTE.COUNT%;","; &
OPCODE.TABLE.SUBSCRIPT%;","; &
ERROR.LINE.FLAG% &
\ PRINT #3%,ARGUMENT$ &
\ TOTAL.BYTES%=TOTAL.BYTES%+BYTE.COUNT% &
\ LOCATION.COUNTER%=LOCATION.COUNTER%+BYTE.COUNT% &
\ ERROR.LINE.FLAG%=0% &
\ RETURN
2480 ! &
2490 &
! -- Get byte count for pseudo-op -- &
2500 ON FLAGS%(OPCODE.TABLE.SUBSCRIPT%)-9% &
GOTO 2590, 2520, 2520, 2520, &
2540, 2540, 2540, 2590, &
2570 &
! .END .BYTE .DBYTE .WORD &
! .ASCII .ASCIP .ASCIZ .LIST &
! .BLKB
2510 ! -- .BYTE, .DBYTE, .WORD --
2520 TEMP1%=0% &
\ TEMP2%=-1% &
\ FOR BYTE.COUNT%=0% WHILE TEMP2% &
\ TEMP1%,TEMP2%=INSTR(TEMP1%+1%,ARGUMENT$,",") &
\ NEXT BYTE.COUNT% &
\ BYTE.COUNT%=BYTE.COUNT%*2% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=12% &
OR FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=13% &
\ RETURN
2530 ! -- .ASCII, .ASCIP, .ASCIZ --
2540 TEMP1%=INSTR(2%,ARGUMENT$,LEFT(ARGUMENT$,1%)) &
\ IF TEMP1%=0% THEN OPCODE.TABLE.SUBSCRIPT%= &
FNERROR.PRINT%("Missing delimiter")-1% &
ELSE BYTE.COUNT%=TEMP1%-2%
2550 BYTE.COUNT%=BYTE.COUNT%+1% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=16% &
\ RETURN
2560 ! -- .BLKB
2570 BYTE.COUNT%=FNEVALUATE.EXPR%(ARGUMENT$) &
\ RETURN
2580 ! -- .LIST, END --
2590 BYTE.COUNT%=0% &
\ RETURN
2600 ! &
3000 &
! -- Pass 2 Driver routine -- &
3010 LINE.NUMBER%, &
CHECKSUM%, &
NEW.LINE.FLAG%=0% &
\ PASS.NUMBER%=2% &
\ LIST.FLAG%=-1% &
\ PRINT #1%,"Pass 2" &
\ CLOSE 1% &
\ OPEN LISTING.FILE$ FOR OUTPUT AS FILE 1% &
\ OPEN SOURCE.FILE$ FOR INPUT AS FILE 2% &
\ OPEN WORK.FILE$ FOR INPUT AS FILE 3% &
\ KILL WORK.FILE$
3020 IF OBJECT.OUT.FLAG% THEN &
OPEN OBJECT.FILE$ FOR OUTPUT AS FILE 4% &
\ NEW.OBJ.LINE%=0%
3030 IF ERRORS.ONLY.SWITCH% THEN PRINT #1%," Line Addr B1 B2 B3" &
\ PRINT #1%
3040 INPUT #3%,LOCATION.COUNTER%, &
BYTE.COUNT%, &
OPCODE.TABLE.SUBSCRIPT%, &
ERROR.LINE.FLAG% &
\ INPUT LINE #3%, ARGUMENT$ &
\ ARGUMENT$=CVT$$(ARGUMENT$,4%) &
\ INPUT LINE #2%, SOURCE.LINE$ &
\ SOURCE.LINE$=CVT$$(SOURCE.LINE$,4%) &
\ LINE.NUMBER%=LINE.NUMBER%+1%
3050 ! -- Form object code and output to listing file --
3060 IF LEFT(SOURCE.LINE$,1%)="$" THEN &
SOURCE.LINE$=RIGHT(SOURCE.LINE$,2%)
3070 IF OPCODE.TABLE.SUBSCRIPT%=-1% THEN GOSUB 3630 &
\ GOTO 3040
3080 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=10% THEN &
GOSUB 3130 &
\ RETURN
3090 ADDRESS$=FNDEC.TO.HEX$(LOCATION.COUNTER%,0%) &
\ VALUE%=VALUES%(OPCODE.TABLE.SUBSCRIPT%) &
\ FLAG.WORD%=SWAP%(VALUE%) AND 255% &
\ VALUE%=VALUE% AND 255%
3100 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)>3% THEN GOSUB 3370 &
ELSE IF FLAG.WORD% THEN GOSUB 3170 &
ELSE GOSUB 3540 &
\ GOSUB 3630
3110 GOTO 3040
3120 &
! -- End of assembly, tidy up -- &
3130 GOSUB 3630 &
\ PRINT #4% IF OBJECT.OUT.FLAG%
3140 CLOSE 2%,3%,4% &
\ RETURN
3150 ! &
3160 &
! -- Process operands -- &
3170 FIRST.ARG.TYPE%=FLAG.WORD% AND 7% &
\ SECOND.ARG.TYPE%=(FLAG.WORD% AND 56%)/8% &
\ SHIFT.ARG.FLAG%=(FLAG.WORD% AND 192%)/64% &
\ SHIFT.ARG.FLAG%=4% IF SHIFT.ARG.FLAG%=2%
3180 ! -- If two operands evaluate the second into ARG2.VALUE%
3190 IF SECOND.ARG.TYPE%=0% THEN ARG2.VALUE%=0% &
ELSE TEMP2%=INSTR(1%,ARGUMENT$,",") &
\ IF TEMP2%=0% THEN ARG2.VALUE%= &
FNERROR.PRINT%("Missing operand") &
ELSE ARG2.VALUE%=FNEVALUATE.ARGUMENT%( &
RIGHT(ARGUMENT$,TEMP2%+1%),SECOND.ARG.TYPE%) &
\ ARGUMENT$=LEFT(ARGUMENT$,TEMP2%-1%)
3200 ! -- Evaluate the first (only) operand
3210 ARG1.VALUE%=FNEVALUATE.ARGUMENT%(ARGUMENT$,FIRST.ARG.TYPE%)
3220 ! -- If register , do appropriate shift and OR into opcode base
3230 IF FIRST.ARG.TYPE%<4% OR FIRST.ARG.TYPE%=7% THEN &
ARG1.VALUE%=ARG1.VALUE%*(2%^SHIFT.ARG.FLAG%) &
\ VALUE%=VALUE% OR ARG1.VALUE%
3240 IF SECOND.ARG.TYPE%<4% THEN VALUE%=VALUE% OR ARG2.VALUE% &
! -- Assemble the bytes for this instruction
3250 GOSUB 3540
3260 IF SHIFT.ARG.FLAG%=1% THEN GOSUB 3330 &
\ GOSUB 3560 &
\ GOSUB 3630 &
\ RETURN
3270 IF SECOND.ARG.TYPE%=4% THEN FIRST.ARG.TYPE%=4% &
\ ARG1.VALUE%=ARG2.VALUE%
3280 IF FIRST.ARG.TYPE%=4% THEN VALUE%=ARG1.VALUE% &
\ GOSUB 3560 &
\ GOSUB 3630 &
\ RETURN
3290 IF SECOND.ARG.TYPE%=5% THEN FIRST.ARG.TYPE%=6% &
\ ARG1.VALUE%=ARG2.VALUE%
3300 IF FIRST.ARG.TYPE%=6% THEN VALUE%=ARG1.VALUE% &
\ GOSUB 3560 &
\ VALUE%=SWAP%(ARG1.VALUE%) &
\ GOSUB 3580
3310 GOSUB 3630 &
\ RETURN
3320 ! -- Z80 relative branches
3330 VALUE%=ARG1.VALUE%-LOCATION.COUNTER%-2% &
\ IF VALUE%<-128% OR VALUE%>127% THEN &
VALUE%=FNERROR.PRINT%("Invalid displacement ="+NUM$(VALUE%))
3340 RETURN
3350 ! &
3360 &
! -- Pseudo-ops. -- &
3370 ON FLAGS%(OPCODE.TABLE.SUBSCRIPT%)-9% &
GOTO 3490, 3390, 3390, 3390, &
3450, 3450, 3450, 3490, &
3510 &
! .END .BYTE .DBYTE .WORD &
! .ASCII .ASCIP .ASCIZ .LIST &
! .BLKB
3380 ! -- .BYTE, .DBYTE, .WORD --
3390 ARGUMENT$=ARGUMENT$+"," &
\ TEMP3%=1% &
\ TEMP3%=2% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=12% &
OR FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=13% &
\ FOR I%=1% TO BYTE.COUNT% STEP TEMP3% &
\ ADDRESS$=FNDEC.TO.HEX$(LOCATION.COUNTER%+I%-1%,0%) &
\ TEMP1%=INSTR(1%,ARGUMENT$,",")
3400 TEMP2%=FNEVALUATE.EXPR%(LEFT(ARGUMENT$,TEMP1%-1%)) &
\ IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=12% THEN &
VALUE%=SWAP%(TEMP2%) &
\ GOSUB 3540 &
\ VALUE%=TEMP2% &
\ GOSUB 3560
3410 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=13% THEN &
VALUE%=TEMP2% &
\ GOSUB 3540 &
\ VALUE%=SWAP%(TEMP2%) &
\ GOSUB 3560
3420 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=11% THEN &
VALUE%=TEMP2% &
\ GOSUB 3540
3430 GOSUB 3630 &
\ ARGUMENT$=RIGHT(ARGUMENT$,TEMP1%+1%) &
\ NEXT I% &
\ RETURN
3440 ! -- .ASCII, .ASCIP, .ASCIZ --
3450 ARGUMENT$=MID(ARGUMENT$,2%,BYTE.COUNT%) &
\ ARGUMENT$=LEFT(ARGUMENT$,BYTE.COUNT%-1%)+CHR$(0%) &
IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=16% &
\ FOR I%=1% TO BYTE.COUNT% STEP 3% &
\ ADDRESS$=FNDEC.TO.HEX$(LOCATION.COUNTER%+I%-1%,0%) &
\ VALUE%=FNCHAR%(I%) &
\ GOSUB 3540 &
\ VALUE%=FNCHAR%(I%+1%) &
\ GOSUB 3560 IF I%+1%<=BYTE.COUNT% &
\ VALUE%=FNCHAR%(I%+2%) &
\ GOSUB 3580 IF I%+2%<=BYTE.COUNT% &
\ GOSUB 3630 &
\ NEXT I% &
\ RETURN
3460 ! -- Get character J% from ARGUMENT$
3470 DEF* FNCHAR%(J%) &
\ CHAR%=ASCII(MID(ARGUMENT$,J%,1%)) &
\ CHAR%=CHAR% OR 128% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=15% &
AND J%=BYTE.COUNT% &
\ FNCHAR%=CHAR% &
\ FNEND &
3480 ! -- .LIST --
3490 LIST.FLAG%=FNEVALUATE.EXPR%(ARGUMENT$) &
\ ADDRESS$="" &
\ RETURN
3500 ! -- .BLKB
3510 TEMP1%=FNEVALUATE.EXPR%(ARGUMENT$) &
\ IF OBJECT.OUT.FLAG% THEN VALUE%=0% &
\ FOR X%=1% TO TEMP1% &
\ GOSUB 3610 &
\ NEXT X%
3520 GOSUB 3630 &
\ RETURN
3530 &
! -- Form B1 -- &
3540 BYTE1$=FNDEC.TO.HEX$(VALUE%,3%) &
\ GOSUB 3610 &
\ RETURN
3550 &
! -- Form B2 -- &
3560 BYTE2$=FNDEC.TO.HEX$(VALUE%,3%) &
\ GOSUB 3610 &
\ RETURN
3570 &
! -- Form B3 -- &
3580 BYTE3$=FNDEC.TO.HEX$(VALUE%,3%) &
\ GOSUB 3610 &
\ RETURN
3590 ! &
3600 &
! -- Output object and update checksum -- &
3610 OBJECT.BYTE%=VALUE% AND 255% &
\ OBJECT.BYTE%=FNOBJECT.OUTPUT%(VALUE%) IF OBJECT.OUT.FLAG% &
\ CHECKSUM%=CHECKSUM%+OBJECT.BYTE% &
\ RETURN
3620 &
! -- Output assembled code to listing file -- &
3630 GOTO 3680 UNLESS ERRORS.ONLY.SWITCH% OR ERROR.LINE.FLAG%
3640 IF ERROR.LINE.FLAG% THEN PRINT #1%,"?"; ELSE PRINT #1%," ";
3650 IF NEW.LINE.FLAG%<LINE.NUMBER% THEN &
PRINT #1% USING "#### ",LINE.NUMBER%; &
ELSE PRINT #1%," ";
3660 PRINT #1% USING"\ \ \\ \\ \\",ADDRESS$,BYTE1$,BYTE2$,BYTE3$; &
\ IF LIST.FLAG% AND SOURCE.LINE$<>"" THEN &
PRINT #1%,CHR$(9%);SOURCE.LINE$ &
ELSE PRINT #1%
3670 ! -- Set a flag, clear output strings --
3680 NEW.LINE.FLAG%=LINE.NUMBER% &
\ ADDRESS$,BYTE1$,BYTE2$,BYTE3$,SOURCE.LINE$="" &
\ RETURN
3690 &
! -- Output binary byte to object file -- &
3700 DEF* FNOBJECT.OUTPUT%(X%) &
\ OBJECT.BYTE%=X% AND 255% &
\ PRINT #4%,FNDEC.TO.HEX$(OBJECT.BYTE%,3%); &
\ NEW.OBJ.LINE%=NEW.OBJ.LINE%+1% &
\ PRINT #4% IF (NEW.OBJ.LINE% AND 15%)=0% &
\ FNOBJECT.OUTPUT%=OBJECT.BYTE% &
\ FNEND
3710 &
! -- Print error count, checksum -- &
3720 PRINT #X% &
\ PRINT #X%,"Errors detected ";FNDEC.TO.HEX$(ERROR.COUNT%,0%) &
\ PRINT #X%,"Source checksum ";FNDEC.TO.HEX$(CHECKSUM%,0%) &
\ PRINT #X%,"Total hex bytes ";FNDEC.TO.HEX$(TOTAL.BYTES%,0%) &
\ PRINT #X% &
\ RETURN
3730 ! &
3740 &
! -- Print sorted symbol table -- &
3750 TEMP1%,TEMP2%=0% &
\ NUMBER.OF.SYMBOLS%=NUMBER.OF.SYMBOLS%-111% &
\ RETURN IF NUMBER.OF.SYMBOLS%<0%
3760 PRINT #1%," Symbol Table" &
\ PRINT #1%
3770 TEMP1%=TEMP1%+1% WHILE FLAGS%(TEMP1%)>=0% &
\ SYMBOLS$(TEMP2%)=SYMBOLS$(TEMP1%) &
\ VALUES%(TEMP2%)=VALUES%(TEMP1%) &
\ FLAGS%(TEMP2%)=FLAGS%(TEMP1%) &
\ TEMP2%=TEMP2%+1% &
\ TEMP1%=TEMP1%+1% &
\ GOTO 3770 UNLESS TEMP2%=NUMBER.OF.SYMBOLS%+1%
3780 ! -- Quick sort the symbol table
3790 TEMP1%=FNQUICKSORT%(0%,NUMBER.OF.SYMBOLS%,0%,NUMBER.OF.SYMBOLS%)
3800 ! -- Output to listing file --
3810 FOR I%=0% TO NUMBER.OF.SYMBOLS% &
\ IF FLAGS%(I%)=-1% THEN S$="#" ELSE S$=" "
3820 PRINT #1% USING " \ \ \ \ ", &
SYMBOLS$(I%),FNDEC.TO.HEX$(VALUES%(I%),0%)+S$; &
\ PRINT #1% IF CCPOS(1%)>63% &
\ NEXT I%
3830 PRINT #1% IF CCPOS(1%) &
\ RETURN
3840 &
! -- Check position of char X% in SOURCE.LINE$ using tables &
! -- DELIMITER%(). FNCHECK.SYNTAX%=-1% means in string &
3850 DEF* FNCHECK.SYNTAX%(X%)
3860 GOTO 3880 IF DELIMITER%=-1% OR X%=0% &
\ FOR X0%=0% TO DELIMITER% &
\ GOTO 3880 IF X%<(SWAP%(DELIMITER.TABLE%(X0%)) AND 255%) &
\ IF X%<(DELIMITER.TABLE%(X0%) AND 255%) THEN &
FNCHECK.SYNTAX%=-1% &
\ GOTO 3890
3870 NEXT X0%
3880 FNCHECK.SYNTAX%=0%
3890 FNEND
3900 ! &
4000 &
! -- Evaluate the argument expression -- &
4010 DEF* FNEVALUATE.EXPR%(X$)
4020 &
! -- Main driver routine -- &
4030 EXPR$=X$ &
\ GOSUB 4060 &
\ GOSUB 4080 &
\ EXP.VAL%=TERM%
4040 GOTO 4290 UNLESS OP% &
\ LAST.OP%=OP% &
\ GOSUB 4060 &
\ GOSUB 4080 &
\ GOSUB 4190 &
\ GOTO 4040
4050 &
REM ! -- Scan for the next operator { ! & % + * - / } -- &
4060 EXP.FLAG%=-1% &
\ FOR TOK.PTR%=1% TO LEN(EXPR$) &
\ TOK.CHR$=MID(EXPR$,TOK.PTR%,1%) &
\ EXP.FLAG%= NOT EXP.FLAG% IF TOK.CHR$="'" &
\ OP%=INSTR(1%,"!%&*+-/",TOK.CHR$) &
\ RETURN IF OP% AND EXP.FLAG% &
\ NEXT TOK.PTR% &
\ OP%=0% &
\ TOK.PTR%=TOK.PTR%+1% &
\ RETURN
4070 &
! -- Get value of term -- &
4080 TERM$=LEFT(EXPR$,TOK.PTR%-1%) &
\ EXPR$=RIGHT(EXPR$,TOK.PTR%+1%)
4090 IF TERM$="" THEN TERM%=0% &
\ RETURN
4100 ! -- H() or L() ? --
4110 TEMP1$=LEFT(TERM$,2%) &
\ IF TEMP1$="H(" THEN EXP.FLAG%=1% &
ELSE IF TEMP1$="L(" THEN EXP.FLAG%=2% &
ELSE EXP.FLAG%=0%
4120 IF EXP.FLAG% THEN IF RIGHT(TERM$,LEN(TERM$))=")" THEN &
TERM$=MID(TERM$,3%,LEN(TERM$)-3%) &
ELSE 4170
4130 TEMP1$=LEFT(TERM$,1%)
4140 IF TEMP1$>="A" AND TEMP1$<="Z" THEN TERM%=FNSYMBOL.LOOKUP%(TERM$) &
ELSE IF TEMP1$="0" THEN TERM%=FNHEX.TO.DEC%(RIGHT(TERM$,2%)) &
ELSE IF TEMP1$>="1" AND TEMP1$<="9" THEN TERM%=VAL(TERM$) &
ELSE IF TEMP1$="'" THEN TERM%=ASCII(RIGHT(TERM$,2%)) &
ELSE IF TEMP1$="^" THEN TERM%=FNOCT.TO.DEC%(RIGHT(TERM$,2%)) &
ELSE IF TERM$="." THEN TERM%=LOCATION.COUNTER% &
ELSE 4170
4150 IF EXP.FLAG%=1% THEN TERM%=SWAP%(TERM%) AND 255% &
ELSE IF EXP.FLAG%=2% THEN TERM%=TERM% AND 255%
4160 RETURN
4170 TERM%=FNERROR.PRINT%("Invalid term = "+TERM$) &
\ RETURN
4180 &
! -- Carry out the arithmetic or logical operation -- &
4190 ON LAST.OP%+1% &
GOTO 4270, 4200, 4210, 4220, &
4230, 4240, 4250, 4260 &
! or not and &
! mult add sub div
4200 EXP.VAL%=EXP.VAL% OR TERM% &
\ RETURN &
! or
4210 EXP.VAL%=EXP.VAL%+(NOT TERM%) &
\ RETURN &
! not
4220 EXP.VAL%=EXP.VAL% AND TERM% &
\ RETURN &
! and
4230 EXP.VAL%=EXP.VAL%*TERM% &
\ RETURN &
! multiply
4240 EXP.VAL%=EXP.VAL%+TERM% &
\ RETURN &
! add
4250 EXP.VAL%=EXP.VAL%-TERM% &
\ RETURN &
! subtract
4260 IF TERM%=0% THEN EXP.VAL%=FNERROR.PRINT%("Division by zero") &
ELSE EXP.VAL%=EXP.VAL%/TERM%
4270 RETURN
4280 &
! -- Exit with value of expression -- &
4290 FNEVALUATE.EXPR%=EXP.VAL%
4300 FNEND
4310 &
! -- Find value of argument of the type TYPE% &
4320 DEF* FNEVALUATE.ARGUMENT%(X$,TYPE%) &
\ EXP.VAL%=FNEVALUATE.EXPR%(X$)
4330 IF TYPE%=1% AND (EXP.VAL%<0% OR EXP.VAL%>7%) THEN &
EXP.VAL%=FNERROR.PRINT%("Invalid register id") &
ELSE IF (TYPE%=2% AND EXP.VAL% AND 4%) OR &
(TYPE%=3% AND EXP.VAL%>1%) THEN &
EXP.VAL%=FNERROR.PRINT%("Invalid register pair") &
ELSE IF TYPE%=7% AND (EXP.VAL%<0% OR EXP.VAL%>7%) &
THEN EXP.VAL%=FNERROR.PRINT%("Invalid RST vector")
4340 FNEVALUATE.ARGUMENT%=EXP.VAL% &
\ FNEND
4350 ! &
4360 &
! -- Print the given error message to the listing file &
4370 DEF* FNERROR.PRINT%(X$) &
\ PRINT #1%,"********";X$; &
\ IF PASS.NUMBER%=1% THEN PRINT #1%," at line";LINE.NUMBER% &
ELSE PRINT #1%
4380 ERROR.COUNT%=ERROR.COUNT%+1% &
\ ERROR.LINE.FLAG%=-1% &
\ FNERROR.PRINT%=0% &
\ FNEND
4390 &
! -- Look up value of symbol -- &
4400 DEF* FNSYMBOL.LOOKUP%(SYMBOL$) &
\ X%=FNHASH.SYMBOL%(SYMBOL$,SYMBOL.TABLE.SIZE%)
4410 IF SYMBOLS$(X%)=SYMBOL$ AND FLAGS%(X%)<=0% THEN &
FNSYMBOL.LOOKUP%=VALUES%(X%) &
ELSE IF SYMBOLS$(X%)="" THEN FNSYMBOL.LOOKUP%= &
FNERROR.PRINT%("Undefined symbol = "+SYMBOL$) &
ELSE X%=FNREHASH.SYMBOL%(X%,SYMBOL.TABLE.SIZE%) &
\ GOTO 4410
4420 FNEND
4430 &
! -- Dec to Hex conversion -- &
4440 DEF* FNDEC.TO.HEX$(X%,D%)
4450 X$="" &
\ FOR X1%=0% TO 3% &
\ X0%=(X% AND (16%^(X1%+1%)-1%*(16%^X1%)))/(16%^X1%) &
\ X0%=X0%+16% IF X0%<0% &
\ X$=CHR$(48%+X0%)+X$ IF X0%<10% &
\ X$=CHR$(55%+X0%)+X$ IF X0%>9% &
\ NEXT X1% &
\ IF D% THEN X$=MID(X$,D%,2%)
4460 FNDEC.TO.HEX$=X$
4470 FNEND
4480 &
! -- Hex to Dec conversion -- &
4490 DEF* FNHEX.TO.DEC%(X$) &
\ X0%=0% &
\ FOR X1%=1% TO LEN(X$) &
\ X2%=ASCII(MID(X$,X1%,1%)) &
\ IF X2%<48% OR (X2%>57% AND X2%<65%) OR X2%>70% THEN &
FNHEX.TO.DEC%=FNERROR.PRINT%("Invalid HEX constant = "+X$) &
\ GOTO 4510
4500 X2%=X2%-48% &
\ X2%=X2%-7% IF X2%>9% &
\ X0%=X2%+X0%*16% &
\ NEXT X1% &
\ FNHEX.TO.DEC%=X0%
4510 FNEND
4520 &
! -- Octal to Dec conversion -- &
4530 DEF* FNOCT.TO.DEC%(X$) &
\ X0%=0% &
\ FOR X1%=1% TO LEN(X$) &
\ X2%=ASCII(MID(X$,X1%,1%))-48% &
\ IF X2%<0% OR X2%>7% THEN &
FNOCT.TO.DEC%=FNERROR.PRINT%("Invalid OCTAL constant = "+X$) &
\ GOTO 4550
4540 X0%=X0%*8% + X2% &
\ NEXT X1% &
\ FNOCT.TO.DEC%=X0%
4550 FNEND
4560 &
! -- Calculate X1% modulo X2% -- &
4570 DEF* FNMOD%(X1%,X2%) &
\ X1%=X1%-(X1%/X2%)*X2% &
\ X1%=X1%+X2% IF X1%<0% &
\ FNMOD%=X1% &
\ FNEND
4580 &
! -- Hash symbol X$, modulo SYMBOL.TABLE.SIZE% -- &
4590 DEF* FNHASH.SYMBOL%(SYMBOL$,M%) &
\ SYMBOL$=LEFT(SYMBOL$+" ",6%) &
\ CHANGE SYMBOL$ TO SYMBOL.CHARS% &
\ SYMBOL.CHARS%(X%)=SYMBOL.CHARS%(X%)-48% FOR X%=1% TO 6% &
\ FNHASH.SYMBOL%=FNMOD%(SYMBOL.CHARS%(1%)*23%+ &
SYMBOL.CHARS%(2%)*19%+SYMBOL.CHARS%(3%)*17%+ &
SYMBOL.CHARS%(4%)*13%+SYMBOL.CHARS%(5%)*11%+ &
SYMBOL.CHARS%(6%)*7%,M%) &
\ FNEND
4600 &
! -- Rehash function, modulo X2% &
4610 DEF* FNREHASH.SYMBOL%(X1%,X2%)=FNMOD%(X1%+23%,X2%)
4620 &
! -- Quick sort symbol table &
4630 DEF* FNQUICKSORT%(LOW%,HIGH%,I%,J%) &
\ I%=LOW% &
\ J%=HIGH% &
\ X$=SYMBOLS$((HIGH%+LOW%)/2%)
4640 I%=I%+1% WHILE SYMBOLS$(I%)<X$
4650 J%=J%-1% WHILE X$<SYMBOLS$(J%)
4660 IF I%>J% THEN 4680 &
ELSE IF I%<>J% THEN VALUE%=VALUES%(I%) &
\ FLAG.WORD%=FLAGS%(I%) &
\ SYMBOL$=SYMBOLS$(I%) &
\ VALUES%(I%)=VALUES%(J%) &
\ FLAGS%(I%)=FLAGS%(J%) &
\ SYMBOLS$(I%)=SYMBOLS$(J%) &
\ VALUES%(J%)=VALUE% &
\ FLAGS%(J%)=FLAG.WORD% &
\ SYMBOLS$(J%)=SYMBOL$
4670 I%=I%+1% &
\ J%=J%-1% &
\ IF I%<=J% THEN 4640
4680 IF LOW%<J% THEN TEMP1%=FNQUICKSORT%(LOW%,J%,LOW%,J%)
4690 IF I%<HIGH% THEN TEMP1%=FNQUICKSORT%(I%,HIGH%,I%,HIGH%)
4700 FNQUICKSORT%=-1% &
\ FNEND
4710 ! &
30000 &
! CCL Entry point &
30010 SOURCE.FILE$=CVT$$(SYS(CHR$(7%)),188%) &
\ I%=INSTR(1%,SOURCE.FILE$,"X80") &
\ IF I% THEN SOURCE.FILE$=RIGHT(SOURCE.FILE$,4%) &
ELSE PRINT "?X80 - Illegal entry" &
\ GOTO 32767
30020 IF SOURCE.FILE$<>"" THEN CCL.ENTRY%=-1% ELSE CCL.ENTRY%=0%
30030 GOTO 1070
30999 ! &
31000 &
! -- Error routine -- &
31010 ! -- No ".END" --
31020 IF ERR=11% AND ERL=2020% THEN OPCODE.TABLE.SUBSCRIPT%= &
FNERROR.PRINT%("Missing .END")+ &
FNHASH.SYMBOL%(".END",SYMBOL.TABLE.SIZE%) &
\ SOURCE.LINE$="" &
\ RESUME 2150
31030 IF ERR=11% AND ERL=3040% THEN SOURCE.LINE$="" &
\ OPCODE.TABLE.SUBSCRIPT%=FNHASH.SYMBOL%(".END", &
SYMBOL.TABLE.SIZE%) &
\ RESUME 3080
31040 ! -- ^Z at filename request --
31050 RESUME 32767 IF ERL=1160%
31060 ! -- Illegal number in FNEVALUATE.EXPR%() --
31070 IF ERR=51% AND ERL=4140% THEN X0%=VAL(TERM$)-65536 &
\ RESUME 4150
31080 RESUME 4170 IF ERR=52% AND ERL=4140%
31090 CLOSE 1%,2%,3%,4% &
\ RESUME 32767% IF ERR=28%
31100 ! -- Print any unanticipated error --
31110 ON ERROR GOTO 0
31999 ! &
32000 &
! -- Opcode data &
32010 ! Table is of the form: &
! SYMBOL,value,byte count &
! where: the low byte of value is the opcode base &
! and the high byte a flag consisting of &
! bits 15,14 a shift flag 0=none,2=four,3=three &
! bits 13-11,10-8 are arg2, arg1 types &
! 0-none, 1-register, 2-register pair, &
! 3-limited register pair, 4-data byte, &
! 5-data word, 6-address and 7-for RST
32020 DATA .END, 0, 10, .BYTE, 0, 11, &
.DBYTE, 0, 12, .WORD, 0, 13, &
.ASCII, 0, 14, .ASCIP, 0, 15, &
.ASCIZ, 0, 16, .LIST, 0, 17, &
.BLKB, 0, 18
32030 DATA CALL, 1741, 3, CC, 1756, 3, &
CM, 1788, 3, CNC, 1748, 3, &
CNZ, 1732, 3, CP, 1780, 3, &
CPE, 1772, 3, CPO, 1764, 3, &
CZ, 1740, 3
32040 DATA JC, 1754, 3, JM, 1786, 3, &
JMP, 1731, 3, JNC, 1746, 3, &
JNZ, 1730, 3, JP, 1778, 3, &
JPE, 1770, 3, JPO, 1762, 3, &
JZ, 1738, 3
32050 DATA LDA, 1594, 3, LHLD, 1578, 3, &
SHLD, 1570, 3, STA, 1586, 3, &
LXI, -22015, 3
32060 DATA ACI, 1230, 2, ADI, 1222, 2, &
ANI, 1254, 2, CPI, 1278, 2, &
ORI, 1270, 2, SBI, 1246, 2, &
SUI, 1238, 2, XRI, 1262, 2, &
IN, 1243, 2, OUT, 1235, 2, &
MVI, -7930, 2
32070 DATA DJNZ, 17936, 2, JR, 17944, 2, &
JRNZ, 17952, 2, JRZ, 17960, 2, &
JRNC, 17968, 2, JRC, 17976, 2
32080 DATA ADC, 392, 1, ADD, 384, 1, &
ANA, 416, 1, CMP, 440, 1, &
ORA, 432, 1, SBB, 408, 1, &
SUB, 400, 1, XRA, 424, 1, &
DAD, -32247, 1, DCX, -32245, 1, &
INX, -32253, 1, POP, -32063, 1, &
PUSH, -32059, 1
32090 DATA DCR, -16123, 1, INR, -16124, 1, &
LDAX, -31990, 1, STAX, -31998, 1, &
MOV, -14016, 1, RST, -14393, 1
32100 DATA CMA, 47, 1, CMC, 63, 1, &
DAA, 39, 1, EI, 251, 1, &
HLT, 118, 1, NOP, 0, 1, &
DI, 243, 1, PCHL, 233, 1, &
RAL, 23, 1, RAR, 31, 1, &
RC, 216, 1, RET, 201, 1, &
RLC, 7, 1, RM, 248, 1, &
RNC, 208, 1, RNZ, 192, 1, &
RP, 240, 1, RPE, 232, 1, &
RPO, 224, 1, RRC, 15, 1, &
RZ, 200, 1, SPHL, 249, 1, &
STC, 55, 1, XCHG, 235, 1, &
XTHL, 227, 1
32110 DATA RIM, 32, 1, SIM, 48, 1, &
EXX, 217, 1, EXAF, 8, 1
32120 !--Register symbol definitions
32130 DATA B, 0, C, 1, D, 2, &
E, 3, H, 4, L, 5, &
M, 6, A, 7, BC, 0, &
DE, 1, HL, 2, SP, 3, &
PSW, 3
32767 END