summaryrefslogtreecommitdiff
path: root/devel/debug/1/src/trace
blob: 773b5f262530b5cefb35f79d206137aeae5aa1df (plain)
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
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
PACKET trace DEFINES trace: 
 
(**************************************************************) 
(*                                          Autor: G. Szalay  *) 
(*    E U M E L 0 - T R A C E                                 *) 
(*                                          Stand: 87-04-23   *) 
(**************************************************************) 
 
LET packet area = 0, stack area = 1, text opd maxlen = 14, 
    stdds = 0, info lines = 4, crlf = ""13""10"", 
    beep = ""7"", carriage return = ""13"", cursor up = ""3"", 
    std charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456 
    7890<>.,:;-_+*!""�$%&/()=?'äÄöÖüÜ#^", 
    blanks = "                                        ", 
    startindent = 10, indentincr = 2; 
BOOL VAR trap set := FALSE, trapped, initial call := TRUE, quit, 
         single step := FALSE, protocol := FALSE, cond br follows, 
         prot just started := FALSE, prot stopped := TRUE, 
         users error := FALSE, users stpdis, prot operands := TRUE, 
         nontraceable found, errorstop processing := FALSE, 
         std procs traceable := id (1) = 4 (* processor = 68000 *), 
         longcall to trace flag; 
INT VAR  aret hi := 0, aret lo := 0, ic hi, ic lo, ic h, ic l, i, 
         atrap hi, atrap lo, nail1 hi, nail1 lo, nail2 hi, nail2 lo, 
         no of nails := 1, saved instr, saved instr w2, 
         saved1, saved1 w2, saved2, saved2 w2, 
         call to trace, call2 to trace, length of call to trace,
         cmd, ilen, iclass, ilen1, iclass1, indentpos, 
         code addr modif, pbase, lbase, users lbase, 
         users errcode, users errline, old flags, flags, 
         module no, word, word1, word2, case, xpos, ypos, 
         cond br hi, cond br lo, maxlines:=12, lines,
         opad hiword, opad hi, opad lo, opdds, br param, brcomp index, 
         ic off, opd ptr, int opd, text opd len, text opd tr len, 
         heap link, root word 2, no of results:=0, 
         no of nontraceables := 0, no of long nontraceables := 0, 
         pproc modno, pproc call, pproc ic lo := 0; 
ROW 3 INT VAR res ds, res opadh, res opadl; 
INT CONST lo byte mask  := dec ("00ff"), 
          hi byte mask  := dec ("ff00"), 
          branch param mask := dec ("87ff"), 
          opcode mask0  := dec ("83ff"), 
          opcode mask1  := dec ("7c00"), 
          bf mask1      := dec ("0040"), 
          ln br mask1   := dec ("7800"), 
          stpdis mask0  := dec ("ffbf"), 
          stpdis mask1  := dec ("0040"), 
          aritu mask1   := dec ("0010"), 
          error mask1   := dec ("0080"), 
          flags mask1   := dec ("00fc"), 
          mask 8000     := dec ("8000"), 
          mask 7fff     := dec ("7fff"), 
          mask 7ffe     := dec ("7ffe"), 
          mask 7f00     := dec ("7f00"), 
          mask 0400     := dec ("0400"), 
          mask fbff     := dec ("fbff"), 
          mask 0007     := dec ("0007"), 
          mask fff8     := dec ("fff8"), 
          m l t start   := dec ("0200"), 
          ln opcode     := dec ("0000"), 
          br opcode     := dec ("7000"), 
          rtn opcode    := dec ("7f00"), 
          call opcode   := dec ("7800"), 
          longcall opcode  := dec ("ff78"), 
          pproc opcode  := dec ("7f1e"), 
          estop opcode  := dec ("7f4b"), 
          dstop opcode  := dec ("7f4c");
TEXT VAR buf, char, command, iname, iname1, ioplist, ioplist1, opd type, 
         opd buf, text opd, res types, users errmsg; 
 
 
(********* following OPs and PROCs may be used by TRACE only ***********) 
 
PROC put (TEXT CONST a): 
  out (a); out (" ") 
ENDPROC put; 
 
PROC putline (TEXT CONST a): 
  out (a); out (crlf) 
ENDPROC putline; 
 
 
(***********************************************************************) 
 
PROC eval br addr (INT CONST br para hi, br para lo, 
                   INT VAR br addr hi, br addr lo): 
  br param := dsgetw (stdds, br para hi, br para lo) 
           AND branch param mask; 
  br addr hi := br para hi; 
  br addr lo := (br para lo AND hi byte mask) 
             OR (br param AND lo byte mask); 
  IF NOT br within page 
  THEN rotate (br param, 8); 
       br param := br param AND lo byte mask; 
       rotate (br param, 1);
       IF br param > 255 
       THEN br param INCR 1; 
            br param := br param AND 255 
       FI; 
       rotate (br param, 8); 
       br addr lo INCR br param; 
       word := br addr lo AND hi byte mask; rotate (word, 8); 
       IF word >= code addr modif 
       THEN br addr lo DECR dec("1000")
       FI 
  FI.
 
  br within page: 
    br param = (br param AND lo byte mask). 
 
ENDPROC eval br addr; 
 
 
PROC eval opd addr (INT CONST ic offset): 
  word := dsgetw (stdds, ic hi, ic lo PLUS ic offset); 
  IF ic offset = 0 
  THEN word := word AND opcode mask0 
  FI; 
  IF global
  THEN eval global addr
  ELIF local 
  THEN eval local addr 
  ELSE eval ref addr 
  FI.
 
  global: (word AND mask 8000) = 0. 
 
  local: (word AND 1) = 0. 
 
  eval global addr: 
    opdds := stdds; 
    opad hi := packet area; 
    opad hiword := opad hi;
    opad lo := pbase PLUS word; 
    perhaps put opad. 
 
  eval local addr: 
    opdds := stdds; 
    opad hi := stack area; 
    opad hiword := opad hi;
    word := word AND mask 7ffe; rotate (word, -1); 
    opad lo := users lbase PLUS word; 
    perhaps put opad. 
 
  eval ref addr: 
    eval local addr; 
    opad hiword := dsgetw (stdds, stack area, opad lo PLUS 1); 
    opad lo := dsgetw (stdds, stack area, opad lo); 
    opdds := opad hiword AND hi byte mask; rotate (opdds, 8); 
    opad hi := opad hiword AND lo byte mask; 
    perhaps put opad. 
 
perhaps put opad: 
 (* put("opad=" CT hex(opad hiword) CT hex(opad lo)) *) . (*for tests*) 
 
ENDPROC eval opd addr; 
 
 
PROC out int opd: 
  out (txt (int opd)); 
  IF int opd < 0 OR int opd > 9 
  THEN out ("("); out (hex (int opd)); out (")") 
  FI 
ENDPROC out int opd; 
 
 
PROC fetch text opd: 
  root word 2 := dsgetw (opdds, opad hi, opad lo PLUS 1); 
  opd buf := subtext (blanks, 1, text opd maxlen + 2); 
  IF text on heap 
  THEN eval text from heap 
  ELSE eval text from root 
  FI; 
  convert nonstd chars; 
  text opd := """"; 
  text opd CAT subtext (opd buf, 1, text opd tr len); 
  text opd CAT """"; 
  IF text opd len > text opd tr len 
  THEN text opd CAT "(..."; 
       text opd CAT txt (text opd len); 
       text opd CAT "B)" 
  FI. 
 
text on heap:
  (root word 2 AND lo byte mask) = 255.
 
eval text from root: 
  text opd len := root word 2 AND lo byte mask; 
  text opd tr len := min (text opd len, text opd maxlen); 
  FOR i FROM 1 UPTO text opd tr len DIV 2 + 1 REP 
    replace (opd buf, i, dsgetw (opdds, opad hi, opad lo PLUS i)) 
  PER; 
  opd buf := subtext (opd buf, 2, text opd tr len + 1). 
 
eval text from heap: 
  rotate (root word 2, 8); 
  text opd len := root word 2 AND lo byte mask 
               OR (dsget2b (opdds, opad hi, opad lo PLUS 2) AND hi byte mask); 
  text opd tr len := min (text opd len, text opd maxlen); 
  heap link := dsgetw (opdds, opad hi, opad lo); 
  rotate (heap link, 15); 
  opad hi := heap link AND mask 0007; 
  opad lo := heap link AND mask fff8; 
  IF opdds = stdds THEN opad lo INCR 2 FI; 
  FOR i FROM 1 UPTO text opd tr len DIV 2 REP 
    replace (opd buf, i, dsgetw (opdds, opad hi, opad lo PLUS i)) 
  PER; 
  opd buf := subtext (opd buf, 1, text opd tr len). 
 
convert nonstd chars: 
  i := 1; 
  WHILE i <= LENGTH opd buf REP 
    char := opd buf SUB i; 
    IF pos (std charset, char) = 0 
    THEN buf := txt (code (char)); 
         opd buf := subtext (opd buf, 1, i-1) CT 
                    """" CT buf CT """" CT 
                    subtext (opd buf, i+1); 
         i INCR 2 + length (buf); 
    ELIF char = """" 
    THEN opd buf := subtext (opd buf, 1, i-1) CT """""" CT 
                    subtext (opd buf, i+1); 
         i INCR 2 
    ELSE i INCR 1 
    FI 
  PER; 
  text opd tr len := LENGTH opd buf. 
 
END PROC fetch text opd; 
 
 
INT OP PLUS (INT CONST a, b):
  unsigned arith;
  a + b
ENDOP PLUS;

PROC trace: 
  ROW 40 INT VAR dummy space for 20 pps; 
  get return address; 
  IF initial call 
  THEN save call to trace 
  ELSE process regular call 
  FI. 
 
get return address: 
  lbase:=local base; 
  users lbase := dsgetw (stdds, stack area, lbase); 
  aret lo := dsgetw (stdds, stack area, lbase+1); 
  word := dsgetw (stdds, stack area, lbase+2); 
  aret hi := word AND 3; 
  flags := word AND flags mask1; 
  ic hi := aret hi; ic lo := aret lo. 
 
save call to trace: 
  call to trace := dsgetw (stdds, aret hi, aret lo - 1); 
  IF (call to trace AND opcode mask1) = call opcode 
  THEN length of call to trace := 1;
       longcall to trace flag := FALSE 
  ELSE call2 to trace := call to trace; 
       call to trace := dsgetw (stdds, aret hi, aret lo - 2); 
       length of call to trace := 2;
       longcall to trace flag := TRUE; 
       putline ("WARNING: call to trace needs 2 words!!!") 
  FI; 
  initial call := FALSE. 
 
process regular call: 
  IF protocol 
  THEN pull old nails 
  ELSE indentpos := startindent; cond br follows := FALSE 
  FI; 
  get users error state and set modes for trace; 
  IF NOT errorstop processing 
  THEN normal processing of instructions 
  ELSE errorstop processing := FALSE 
  FI; 
  handle possible trace errors; 
  IF NOT protocol THEN restore users error state FI.  
 
normal processing of instructions: 
  trapped := trap set AND atrap lo = ic lo - length of call to trace
           AND atrap hi = ic hi;
  IF protocol THEN postprocess protocol FI; 
  IF trapped THEN handle trap FI; 
  IF protocol OR trapped
  THEN ic lo DECR length of call to trace;
       update icount on stack
  FI; 
  IF trapped OR NOT protocol OR single step OR incharety <> "" 
     OR lines >= maxlines
  THEN quit := FALSE; protocol := FALSE; single step := FALSE; lines := 0;
       REP ask for next action; 
           execute command 
       UNTIL quit PER 
  FI; 
  IF protocol THEN protocol instruction and set nails FI. 
 
get users error state and set modes for trace: 
  signed arith; 
  IF NOT protocol 
  THEN users error  := (flags AND error mask1) <> 0; 
       users stpdis := (flags AND stpdis mask1) <> 0; 
       IF users error 
       THEN save users error state; clear error; 
            line; putline ("trace called with user error " CT 
                            txt (users errcode) CT ": " CT users errmsg) 
       ELSE disable stop 
       FI 
  ELIF is error 
  THEN IF first occurrence 
       THEN users error := TRUE; 
            save users error state; 
            line; 
            putline ("trace detected user error " CT 
                     txt (users errcode) CT ": " CT users errmsg); 
            IF users stpdis 
            THEN out ("(stop disabled)") 
            ELSE errorstop processing := TRUE; stop op; 
                 IF protocol THEN set nail1 FI 
            FI 
       ELSE line; 
            putline ("trace detected user error " CT 
                     txt (error code) CT ": " CT error message); 
            out ("(ignored because of previous error(s)) "); 
       FI; 
       clear error 
  ELSE IF (flags AND stpdis mask1) = 0 
       THEN set stpdis flag on stack; disable stop 
       FI 
  FI. 
 
first occurrence: NOT users error. 
 
save users error state: 
  users errmsg := error message; 
  users errline := error line; 
  users errcode := error code. 
 
handle possible trace errors: 
  IF is error 
  THEN line; 
       putline ("TRACE error " CT txt (error code) 
                 CT " at line " CT txt (error line) 
                 CT ": " CT error message); 
       clear error 
  FI. 
 
restore users error state: 
  IF users error 
  THEN error stop (users errcode, users errmsg); 
       users error := FALSE 
  FI; 
  restore users stpdis flag on stack. 
 
handle trap: 
  put trap message; 
  restore instruction; 
  trap set := FALSE. 
 
put trap message: 
  putline ("trap at address " CT txt (atrap hi) CT hex (atrap lo)). 
 
restore instruction: 
  dsputw (stdds, atrap hi, atrap lo, saved instr); 
  IF longcall to trace flag 
  THEN dsputw (stdds, atrap hi, atrap lo PLUS 1, saved instr w2) 
  FI. 
 
postprocess protocol: 
  IF prot operands THEN protocol result operands FI; 
  line; lines INCR 1;
  IF cond br follows THEN protocol cond br op; cond br follows := FALSE FI. 
 
protocol cond br op: 
  outsubtext (blanks, 1, indentpos); 
  out (txt (cond br hi)); out (hex (cond br lo)); out (": "); 
  word := dsget2b (stdds, cond br hi, cond br lo); 
  IF (word AND bf mask1) <> 0 
  THEN out ("BF       ") 
  ELSE out ("BT       ") 
  FI; 
  putline (hex (word)); lines INCR 1.
 
pull old nails: 
  dsputw (stdds, nail1 hi, nail1 lo, saved1); 
  IF longcall to trace flag 
  THEN dsputw (stdds, nail1 hi, nail1 lo PLUS 1, saved1 w2) 
  FI; 
  IF no of nails = 2 
  THEN dsputw (stdds, nail2 hi, nail2 lo, saved2); 
       IF longcall to trace flag 
       THEN dsputw (stdds, nail2 hi, nail2 lo PLUS 1, saved2 w2) 
       FI; 
       no of nails := 1 
  FI. 
 
update icount on stack: 
  dsputw (stdds, 1, lbase + 1, ic lo). 
 
ask for next action: 
  putline (""15"" CT
          "TRACE: step, more, trap, regs, lines, info, disasm, or quit"14""); 
  inchar (command). 
 
execute command: 
  cmd := pos ("tidqmsrl", command); 
  SELECT cmd OF 
    CASE 1: set address trap;                        prot stopped := TRUE 
    CASE 2: info (stdds, ic hi, ic lo, info lines);  prot stopped := TRUE 
    CASE 3: disasm (ic hi, ic lo);                   prot stopped := TRUE 
    CASE 4: quit := TRUE;                            prot stopped := TRUE 
    CASE 5: initialize protocol; single step := FALSE; 
            quit := TRUE 
    CASE 6: initialize protocol; single step := TRUE; 
            quit := TRUE 
    CASE 7: show registers;                          prot stopped := TRUE 
    CASE 8: set new line count;                      prot stopped := TRUE
    OTHERWISE out(beep CT carriage return CT cursor up) 
  ENDSELECT. 
 
set new line count:
  out ("lines="); gethex (buf); maxlines := dec (buf).

set address trap: 
  IF trap set 
  THEN putline ("current trap address: " CT txt (atrap hi) CT hex (atrap lo));
       out ("type <CR> to confirm, or ")
  ELSE out ("type ")
  FI;
  out ("new trap addr ("); 
  IF std procs traceable THEN out ("2") ELSE out ("3") FI; 
  out ("0000...3ffff), or 0 for no trap:"); 
  gethex (buf); 
  IF buf <> "" 
  THEN IF trap set THEN restore instruction; trap set := FALSE FI; 
       buf:="0000" CT buf; 
       atrap hi := dec (subtext (buf, LENGTH buf-7, LENGTH buf-4)); 
       atrap lo := dec (subtext (buf, LENGTH buf-3)); 
       IF atrap hi=3 OR atrap hi=2 AND std procs traceable 
       THEN saved instr := dsgetw (stdds, atrap hi, atrap lo); 
            dsputw (stdds, atrap hi, atrap lo, call to trace); 
            IF longcall to trace flag 
            THEN saved instr w2 := dsgetw (stdds, atrap hi, atrap lo PLUS 1); 
                 dsputw (stdds, atrap hi, atrap lo PLUS 1, call2 to trace); 
            FI; 
            trap set := TRUE 
       ELIF NOT (atrap hi=0 AND atrap lo=0) 
       THEN out (beep); putline ("address not in above range") 
       FI 
  ELSE IF NOT trap set THEN out (beep); putline ("no trap specified") FI 
  FI. 
 
initialize protocol: 
  pbase := dsgetw (stdds, stack area, lbase + 2) AND hi byte mask; 
  code addr modif := dsgetw (stdds, stack area, lbase + 3) 
                  AND lo byte mask; 
  set stpdis flag on stack; 
  prot just started := TRUE; 
  protocol := TRUE. 
 
set stpdis flag on stack: 
  word := dsgetw (stdds, stack area, lbase + 2); 
  dsputw (stdds, stack area, lbase + 2, word OR stpdis mask1). 
 
restore users stpdis flag on stack: 
  word := dsgetw (stdds, stack area, lbase + 2) AND stpdis mask0; 
  IF users stpdis THEN word := word OR stpdis mask1 FI; 
  dsputw (stdds, stack area, lbase + 2, word). 
 
protocol instruction and set nails: 
  protocol instr; 
  SELECT iclass OF 
    CASE 0:  standard ops 
    CASE 1:  cond branch ops 
    CASE 2:  branch ops 
    CASE 3:  comp branch op 
    CASE 4:  call op 
    CASE 5:  exec op 
    CASE 6:  pcall op 
    CASE 7:  return ops 
    CASE 8:  penter op 
    CASE 9:  pp ops 
    CASE 10: line ops 
    CASE 11: stop ops 
    CASE 12: ke op 
    CASE 13: clrerr op
    OTHERWISE: wrong ops 
  ENDSELECT; 
  IF protocol THEN set nail1 FI. 
 
protocol instr: 
  word1 := dsgetw (stdds, ic hi, ic lo); 
  disa (ic hi, ic lo, iname, ioplist, ilen, iclass); 
  protocol this instr. 
 
protocol this instr: 
  possibly delete command line; 
  outsubtext (blanks, 1, indentpos); 
  ic h := ic hi; ic l := ic lo; 
  out (txt (ic h)); out (hex (ic l)); out (": "); 
  out (iname); out (" "); 
  IF ilen > 0 
  THEN FOR i FROM 1 UPTO ilen 
       REP out (hex (dsget2b (stdds, ic h, ic l))); out (" "); 
           ic l INCR 1 PER 
  ELSE out (hex (dsget2b (stdds, ic h, ic l))); out (" ") 
  FI; 
  IF prot operands THEN protocol operands FI. 

possibly delete command line: 
  IF prot just started 
  THEN prot just started := FALSE; 
       IF prot stopped 
       THEN prot stopped := FALSE 
       ELSE delete command line 
       FI 
  FI. 
 
delete command line: 
  get cursor (xpos, ypos); cursor (1, ypos-1); out(""4""). 
 
protocol operands: 
  out ("  "); 
  IF (word1 AND mask 7f00) = mask 7f00 
  THEN ic off := 1 
  ELSE ic off := 0 
  FI; 
  res types := ""; 
  no of results := 0; 
  FOR opd ptr FROM 1 UPTO LENGTH ioplist REP 
    opd type := ioplist SUB opd ptr; 
    IF opd type <> " " 
    THEN case := pos ("irtdpahIRTDPEH", opd type); 
         IF case > 0 
         THEN eval opd addr (ic off); 
              SELECT case OF 
                CASE 1: prot int rd opd 
                CASE 2: prot real rd opd 
                CASE 3: prot text rd opd 
                CASE 4: prot dataspace rd opd 
                CASE 5: prot task rd opd 
                CASE 6: prot virt addr 
                CASE 7: prot hex rd opd 
                OTHERWISE save res type 
              ENDSELECT 
         FI; 
         ic off INCR 1 
    FI 
  UNTIL opd type = " " PER. 
 
save res type: 
  res types CAT opd type; 
  no of results INCR 1; 
  res ds    (no of results) := opdds; 
  res opadh (no of results) := opad hi; 
  res opadl (no of results) := opad lo. 
 
protocol result operands: 
  FOR opd ptr FROM 1 UPTO no of results REP prot this result PER.
 
prot this result: 
  opdds   := res ds    (opd ptr); 
  opad hi := res opadh (opd ptr); 
  opad lo := res opadl (opd ptr); 
  opd type := res types SUB opd ptr; 
  SELECT pos ("IRTDPEH", opd type) OF 
    CASE 1: prot int result 
    CASE 2: prot real result 
    CASE 3: prot text result 
    CASE 4: prot dataspace result 
    CASE 5: prot task result 
    CASE 6: prot eva result 
    CASE 7: prot hex result 
    OTHERWISE out (opd type CT "(???) ") 
  ENDSELECT. 
 
prot int rd opd: 
  int opd := dsgetw (opdds, opad hi, opad lo); 
  out (">"); out int opd; out (" "). 
 
prot int result: 
  int opd := dsgetw (opdds, opad hi, opad lo); 
  out int opd; out ("> "). 
 
prot hex rd opd: 
  int opd := dsgetw (opdds, opad hi, opad lo); 
  out (">"); out (hex (int opd)); out (" "). 
 
prot hex result: 
  int opd := dsgetw (opdds, opad hi, opad lo); 
  out (hex (int opd)); out ("> ").
 
prot real rd opd: 
  out (">"); 
  out (hex (dsget2b (opdds, opad hi, opad lo))); 
  out (hex (dsget2b (opdds, opad hi, opad lo PLUS 1))); 
  out (hex (dsget2b (opdds, opad hi, opad lo PLUS 2))); 
  out (hex (dsget2b (opdds, opad hi, opad lo PLUS 3))); out (" "). 
 
prot real result: 
  out (hex (dsget2b (opdds, opad hi, opad lo))); 
  out (hex (dsget2b (opdds, opad hi, opad lo PLUS 1))); 
  out (hex (dsget2b (opdds, opad hi, opad lo PLUS 2))); 
  out (hex (dsget2b (opdds, opad hi, opad lo PLUS 3))); 
  out ("> "). 
 
prot text rd opd: 
  fetch text opd; 
  out (">"); out (text opd); out (" "). 
 
prot text result: 
  fetch text opd; 
  out (text opd); out ("> "). 
 
prot dataspace rd opd: 
  int opd := dsgetw (opdds, opad hi, opad lo); 
  out (">"); out (hex (int opd)); out (" "). 
 
prot dataspace result: 
  int opd := dsgetw (opdds, opad hi, opad lo); 
  out (hex (int opd)); out ("> "). 
 
prot task rd opd: 
  out (">"); out (hex (dsgetw (opdds, opad hi, opad lo))); 
  out ("/"); out (hex (dsgetw (opdds, opad hi, opad lo PLUS 1))); out (" "). 
 
prot task result: 
  out (hex (dsgetw (opdds, opad hi, opad lo))); out ("/"); 
  out (hex (dsgetw (opdds, opad hi, opad lo PLUS 1))); out ("> "). 
 
prot virt addr: 
  out (">"); out (hex (opad hiword)); out (hex (opad lo)); out (" "). 
 
prot eva result: 
  out (hex (dsgetw (opdds, opad hi, opad lo PLUS 1))); 
  out (hex (dsgetw (opdds, opad hi, opad lo))); 
  out (">").  
 
standard ops: 
  nail1 hi := ic hi; nail1 lo := ic lo PLUS ilen. 
 
set nail1: 
  saved1 := dsgetw (stdds, nail1 hi, nail1 lo); 
  dsputw (stdds, nail1 hi, nail1 lo, call to trace); 
  IF longcall to trace flag 
  THEN saved1 w2 := dsgetw (stdds, nail1 hi, nail1 lo PLUS 1); 
       dsputw (stdds, nail1 hi, nail1 lo PLUS 1, call2 to trace) 
  FI. 
 
set nail2: 
  saved2 := dsgetw (stdds, nail2 hi, nail2 lo); 
  dsputw (stdds, nail2 hi, nail2 lo, call to trace); 
  IF longcall to trace flag 
  THEN saved2 w2 := dsgetw (stdds, nail2 hi, nail2 lo PLUS 1); 
       dsputw (stdds, nail2 hi, nail2 lo PLUS 1, call2 to trace) 
  FI. 
 
cond branch ops: 
  cond br follows := TRUE; 
  cond br hi := ic hi; cond br lo := ic lo PLUS ilen; 
  nail1 hi := cond br hi; nail1 lo := cond br lo PLUS 1; 
  eval br addr (cond br hi, cond br lo, nail2 hi, nail2 lo); 
  no of nails := 2; set nail2. 
 
branch ops: 
  eval br addr (ic hi, ic lo, nail1 hi, nail1 lo). 
 
comp branch op: 
  eval opd addr (1); 
  brcomp index := dsgetw (stdds, opad hi, opad lo); 
  IF brcomp index < 0 OR brcomp index >= dsgetw (stdds, ic hi, ic lo PLUS 2) 
  THEN brcomp index := -1 
  FI; 
  nail1 hi := ic hi; 
  nail1 lo := ic lo PLUS ilen PLUS brcomp index PLUS 1. 
 
call op: 
  eval module no; 
  call or exec. 
 
call or exec: 
  IF module no < 1280 AND NOT std procs traceable 
  THEN possibly append proc head; 
       out (" (*n.t.*)"); 
       nontraceable found := TRUE 
  ELSE check for nontraceable 
  FI; 
  IF NOT nontraceable found 
  THEN restore users stpdis flag on stack; 
       get proc address via module link table; 
       possibly append proc head; 
       indentpos INCR indentincr; 
       nail1 hi := ic hi; nail1 lo := ic lo PLUS 1 (*nail behind head*) 
  ELIF call to trace found 
  THEN skip instruction 
  ELIF possibly call to bool proc 
  THEN cond branch ops 
  ELSE standard ops 
  FI. 
 
eval module no: 
  IF word1 = longcall opcode
  THEN module no := dsgetw (stdds, ic hi, ic lo PLUS 1)
  ELSE module no := word1 AND opcode mask0; 
       IF (module no AND mask 8000) <> 0 
       THEN module no := module no AND mask 7fff OR mask 0400 
       FI
  FI. 
 
check for nontraceable: 
  nontraceable found := FALSE; 
  IF word1 = longcall opcode 
  THEN word2 := dsgetw (stdds, ic hi, ic lo PLUS 1); 
       FOR j FROM 1 UPTO no of long nontraceables REP 
         IF word 2 = call2 to nontraceables (j) 
         THEN out (names of long nontraceables (j)); 
              nontraceable found := TRUE 
         FI 
       UNTIL nontraceable found PER 
  ELSE FOR j FROM 1 UPTO no of nontraceables REP 
         IF word1 = calls to nontraceables (j) 
         THEN out (names of short nontraceables (j)); 
              nontraceable found := TRUE 
         FI 
       UNTIL nontraceable found PER 
  FI. 
 
get proc address via module link table: 
  IF module no < 1280 THEN ic hi := 2 ELSE ic hi := 3 FI; 
  ic lo := dsgetw (stdds, packet area, m l t start + module no). 
 
possibly append proc head: 
  out (proc head (module no)). 
 
skip instruction: 
  ic lo INCR ilen; update icount on stack; 
  nail1 hi := ic hi; nail1 lo := ic lo. 
 
possibly call to bool proc: 
  word := dsgetw (stdds, ic hi, ic lo PLUS ilen) AND ln br mask1; 
  word = ln opcode OR word = br opcode. 
 
exec op: 
  eval opd addr (1); 
  module no := dsgetw (stdds, opad hi, opad lo); 
  call or exec. 
  
pcall op: 
  eval opd addr (1); 
  IF opad lo = 2 AND NOT std procs traceable 
  THEN out (" (*n.t.*)"); 
       nontraceable found := TRUE 
  ELSE check for nontraceable pproc 
  FI; 
  IF NOT nontraceable found 
  THEN restore users stpdis flag on stack; 
       possibly append proc head for pproc; 
       indentpos INCR indentincr; 
       nail1 hi := opad hi; nail1 lo := opad lo PLUS 1 (*nail behind head*) 
(*ELIF word1 = call to trace 
  THEN skip instruction *) 
  ELIF possibly call to bool proc 
  THEN cond branch ops 
  ELSE standard ops 
  FI. 
 
check for nontraceable pproc: 
  nontraceable found := FALSE; 
  IF opad lo = pproc ic lo 
  THEN FOR j FROM 1 UPTO no of nontraceables REP 
         IF pproc call = calls to nontraceables (j) 
         THEN out (names of nontraceables (j)); 
              nontraceable found := TRUE 
         FI 
       UNTIL nontraceable found PER 
  ELSE nontraceable found := TRUE  (*to be on the secure side*) 
  FI. 
 
possibly append proc head for pproc: 
  IF opad lo = pproc ic lo 
  THEN out (proc head (pproc modno)) 
  FI. 
 
return ops: 
  fetch eumel0 regs of caller from users stack; 
  out ("--> ");
  put users flags; 
  IF (old flags AND aritu mask1) <> 0
  THEN put ("ARITU")
  ELSE put ("ARITS")
  FI;
  IF nontraceable caller 
  THEN line; putline ("trace ended by returning to nontraceable caller"); 
       protocol := FALSE; prot stopped := TRUE 
  ELIF users error AND NOT users stpdis
  THEN stop op
  ELSE set nail for return ops 
  FI. 
 
set nail for return ops: 
  IF word1 = rtn opcode 
  THEN nail1 hi := ic hi; nail1 lo := ic lo 
  ELSE nail1 hi := ic hi; nail1 lo := ic lo PLUS 1; 
       eval br addr (ic hi, ic lo, nail2 hi, nail2 lo); 
       no of nails := 2; set nail2 
  FI. 
 
penter op: 
  pbase := word1 AND lo byte mask; rotate (pbase, 8); 
  standard ops. 
  
line ops: 
  standard ops. 
 
stop ops: 
  IF word1 = estop opcode 
  THEN users stpdis := FALSE; 
       IF users error THEN stop op ELSE standard ops FI 
  ELIF word1 = dstop opcode 
  THEN users stpdis := TRUE; standard ops 
  ELSE stop op 
  FI. 
 
clrerr op:
  users error := FALSE; standard ops.

ke op: 
  skip instruction; 
  line; putline ("INFO: ke"); 
  info (stdds, ic hi, ic lo, info lines);
  single step := TRUE.

pp ops: 
  save modno and ic lo if pproc; 
  look at next instr; 
  WHILE iclass1 = 9 REP 
    ic lo INCR ilen; iname := iname1; ioplist := ioplist1; 
    ilen := ilen1; iclass := iclass1; 
    line; lines INCR 1;
    protocol this instr; 
    save modno and ic lo if pproc; (*only the first one will be saved!!!*) 
    look at next instr 
  PER; 
  standard ops. 
 
save modno and ic lo if pproc: 
  IF word1 = pproc opcode 
  THEN pproc modno := dsgetw (stdds, ic hi, ic lo PLUS 1); 
       IF pproc modno < 256 
       THEN putline ("*** this looks like a compiler error ***"); 
            protocol := FALSE; prot stopped := TRUE; users error := TRUE; 
            users errcode := 0; users errmsg := ("maybe a compiler error"); 
            LEAVE normal processing of instructions 
       ELIF (pproc modno AND mask 0400) <> 0 
       THEN word := (pproc modno AND mask fbff) OR mask 8000 
       ELSE word := pproc modno 
       FI; 
       pproc call := word OR opcode mask1; 
       pproc ic lo := dsgetw (stdds, packet area, m l t start + pproc modno) 
  FI. 
   
look at next instr: 
    word1 := dsgetw (stdds, ic hi, ic lo PLUS ilen); 
    disa (ic hi, ic lo PLUS ilen, iname1, ioplist1, ilen1, iclass1). 
 
wrong ops: 
  putline ("**** das kann ich (noch) nicht!!! ***"); 
  info (stdds, ic hi, ic lo, info lines); 
  protocol := FALSE. 
 
show registers: 
  pbase := dsgetw (stdds, stack area, lbase + 2) AND hi byte mask; 
  code addr modif := dsgetw (stdds, stack area, lbase + 3) 
                  AND lo byte mask; 
  putline ("----------------- EUMEL0-registers: ------------------"); 
  put ("icount=" CT txt (ic hi) CT hex (ic lo) CT 
       " lbase=1" CT hex (users lbase) CT " pbase=" CT hex (pbase)); 
  put users flags;
  IF (flags AND aritu mask1) <> 0
  THEN putline ("ARITU")
  ELSE putline ("ARITS")
  FI.

put users flags:
  IF users stpdis 
  THEN put ("STPDIS") 
  ELSE put ("STOPEN") 
  FI; 
  IF users error 
  THEN put ("ERROR") 
  ELSE put ("NOERR") 
  FI. 
 
ENDPROC trace; 
 
 
PROC stop op: 
  line; 
  suppress result protocolling; 
  REP outsubtext (blanks, 1, indentpos); 
      fetch eumel0 regs of caller from users stack; 
      out ("stop/error induced return to addr "); 
      out (txt (ic hi)); out (hex (ic lo)); 
      IF users stpdis 
      THEN putline (" (STPDIS)")
      ELSE putline (" (STOPEN)") 
      FI; 
      lines INCR 1;
      IF nontraceable caller 
      THEN putline ("trace ended by returning to nontraceable caller"); 
           protocol := FALSE; prot stopped := TRUE 
      ELIF users stpdis 
      THEN copy stack of disabled caller to tracers stack 
      ELSE users lbase := dsgetw (stdds, stack area, users lbase) 
      FI 
  UNTIL users stpdis OR NOT protocol PER; 
  nail1 hi := ic hi; nail1 lo := ic lo. 
 
suppress result protocolling: 
  no of results := 0. 
 
copy stack of disabled caller to tracers stack: 
  FOR i FROM 1 UPTO 4 REP 
    word := dsgetw (stdds, stack area, users lbase + i - 1); 
    dsputw (stdds, stack area, lbase + i - 1, word) 
  PER. 
 
ENDPROC stop op; 
 
 
i n i t i a l i z e   t r a c e. 
 
nontraceable caller: 
  ic hi = 2 AND NOT std procs traceable 
   OR (old flags AND aritu mask1) <> 0 AND (flags AND aritu mask1) = 0. 
 
fetch eumel0 regs of caller from users stack: 
  indentpos DECR indentincr; 
  ic lo := dsgetw (stdds, stack area, users lbase + 1); 
  word := dsgetw (stdds, stack area, users lbase + 2); 
  ic hi := word AND 3; 
  old flags := word AND flags mask1; 
  users stpdis := (old flags AND stpdis mask1) <> 0;
  pbase := word AND hi byte mask; 
  code addr modif := dsgetw (stdds, stack area, users lbase + 3) 
                     AND lo byte mask. 
 
initialize trace: 
  LET maxno of nontraceables = 20; 
  INT VAR int, j; 
  TEXT VAR text; 
  ROW maxno of nontraceables TEXT VAR names of nontraceables; 
  ROW maxno of nontraceables TEXT VAR names of short nontraceables; 
  ROW maxno of nontraceables TEXT VAR names of long nontraceables; 
  ROW maxno of nontraceables INT VAR calls to nontraceables; 
  ROW maxno of nontraceables INT VAR call2 to nontraceables; 

  putline("initializing ""trace"" ...");
  names of nontraceables (1) := "disa (I,I,T,T,I,I) (*n.t.*)"; 
  names of nontraceables (2) := "disasm (I,I) (*n.t.*)"; 
  names of nontraceables (3) := "info (I,I,I,I) (*n.t.*)";
  names of nontraceables (4) := "dec (T) (*n.t.*)"; 
  names of nontraceables (5) := "hex (I) (*n.t.*)"; 
  names of nontraceables (6) := "dsget2b (I,I,I) (*n.t.*)"; 
  names of nontraceables (7) := "trace (*ignored*)"; 
  trace; (* initialize 'call to trace', 'ic hi' and 'ic lo' *) 
  IF FALSE THEN 
     disa (int, int, text, text, int, int); 
     disasm (int, int); 
     info (int, int, int, int); 
     int := dec (text); 
     text := hex (int); 
     int  := dsget2b (int, int, int); 
     trace   (****** must be the last one !!! *****) 
   FI; 
   FOR j FROM 1 UPTO maxno of nontraceables REP 
     REP ic lo INCR 1; 
         word1 := dsgetw (stdds, ic hi, ic lo) 
     UNTIL call opcode found PER; 
     IF word1 <> longcall opcode 
     THEN no of nontraceables INCR 1; 
          calls to nontraceables (no of nontraceables) := word1; 
          names of short nontraceables (no of nontraceables) := 
               names of nontraceables (j)
     ELSE no of long nontraceables INCR 1; 
          word2 := dsgetw (stdds, ic hi, ic lo PLUS 1); ic lo INCR 1; 
          call2 to nontraceables (no of long nontraceables) := word2;
          names of long nontraceables (no of long nontraceables) := 
               names of nontraceables (j) 
     FI 
   UNTIL call to trace found 
         OR no of nontraceables = maxno of nontraceables 
         OR no of long nontraceables = maxno of nontraceables PER; 
   putline ("""trace"" initialized:");
   putline ("        " CT txt (no of nontraceables)
                       CT " nontraceable shortcalls");
   putline ("        " CT txt (no of long nontraceables)
                       CT " nontraceable longcalls"); 
   IF no of nontraceables = maxno of nontraceables 
      OR no of long nontraceables = maxno of nontraceables 
   THEN errorstop ("too many nontraceables") 
   ELSE test trace 
   FI. 
 
call opcode found: 
  (word1 AND opcode mask1) = call opcode OR word1 = longcall opcode. 
 
call to trace found: 
  IF word1 = call to trace 
  THEN IF longcall to trace flag 
       THEN word2 = call2 to trace 
       ELSE TRUE 
       FI 
  ELSE FALSE 
  FI. 
 
test trace:.

END PACKET trace;