File: tkisem

package info (click to toggle)
tkisem 4.5.12-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 964 kB
  • ctags: 1,372
  • sloc: cpp: 4,844; tcl: 3,047; asm: 1,991; makefile: 335; ansic: 269; sh: 155
file content (2785 lines) | stat: -rwxr-xr-x 90,309 bytes parent folder | download
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
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
#!/usr/bin/wish -f
###############################################################################
## CONFIGURING this script:
##
##  As of tkisem version 4.5.8 on Linux systems, this file SHOULD NOT REQUIRE
##  ANY CUSTOMIZATION (unless you've got wish elsewhere than above).
##
## 1. If you're on a Unix system, replace the first line with the full
##    pathname of your wish interpreter (be certain to leave the "-f" after
##    the pathname).  This wish interpreter must be at least 7.5 (for file 
##    split/join commands, 8.0 or higher preferred).
##    
## 2. Set the library directory to the full pathname of where you installed
##    the library and help file.
##
## 3. Set the library extension: for Unix systems, this is 'so'.
##
###############################################################################

set libdir /usr/lib/tkisem
set lib_ext so

# $Format: "set release $ProjectVersion$"$
set release 4.5.12


###############################################################################
# Other configurable options -- 
###############################################################################

set library "$libdir/tkisem.$lib_ext"
set rom "$libdir/isem_rom"
set tkhfile "$libdir/isemhelp.txt"

if {[info exists env(TKISEM_ROM)]} {
    set rom $env(TKISEM_ROM)
}

load $library

# how to display registers
# the default is  regular  which uses the names %r0 through %r31
# the alternative is  window  which uses the names %g0-%g7, %o0-%o7, etc
set reg_view regular


#--------------------------fonts-----------------------------------------------
# configuration related to the help window
set help_fore black		;# basic help text
set help_back white
set help_font variable

set help_xref_fore black	;# cross reference text
set help_xref_back yellow
set help_xref_font variable

set help_label_fore black	;# label text
set help_label_back white
set help_label_font variable

set help_example_fore black	;# example text
set help_example_back white
set help_example_font fixed

set gpreg_font fixed
set text_font fixed		;# font used in the text (code) display windows
set data_font fixed		;# font used in the date display windows
set sym_font fixed
set console_font fixed

#--------------------------isem devices----------------------------------------
#
# the address is the memory address for the device
# the mode specifies which address spaces the device appears in -- it always
#   mapped into supervisor space, if mode is set to user, it is also mapped
#   into user space

set gx_address 0x100000
set gx_mode user

set console_address 0x110000
set console_mode user

set halt_address 0x120000
set halt_mode user

set timer_int_level 1
set timer_address 0x130000
set timer_mode user

set uart_int_level 1
set uart_address 0x140000
set uart_status_address 0x140000
set uart_creg_address 0x140004
set uart_txreg_address 0x140008
set uart_rxreg_address 0x14000c
set uart_mode user

###############################################################################
# end of configuration
###############################################################################

###############################################################################
# The debug panel
###############################################################################
toplevel .isem_debug
wm title .isem_debug "Debugging Messages for the tkISEM Script"
wm withdraw .isem_debug

label .isem_debug.lab -text "tkISEM DEBUG" -relief groove
frame .isem_debug.text
pack .isem_debug.lab .isem_debug.text -side top -fill x -expand 1

text .isem_debug.text.text -height 20 -width 80 \
    -relief sunken -bd 2 -font fixed \
    -yscrollcommand ".isem_debug.text.scroll set"
scrollbar .isem_debug.text.scroll -command ".isem_debug.text.text yview"
pack .isem_debug.text.scroll -side right -fill y
pack .isem_debug.text.text -side left

button .isem_debug.dismiss -text "Dismiss" -command "wm withdraw .isem_debug" -bg yellow
pack .isem_debug.dismiss

proc isem_debug {mes} {
    .isem_debug.text.text insert end [format "%s\n" $mes]
    .isem_debug.text.text yview -pickplace end
}

#------------------------------------------------------------------------------
# globals
set super_breaks {}
set user_breaks {}
set last_shown_pc_user 0
set last_shown_pc_super 0

set instr_annul ""

wm title . "tkisem Release: $release"

set file_super $rom
set file_user "a.out"
set proc_state "execute"

#####################
# AckleyHacks(tm) ON
# 
# a routine to keep the wm from killing our windows

proc make_delete_withdraw {win} {
    wm protocol $win WM_DELETE_WINDOW "wm withdraw $win"
}

#
# AckleyHacks(tm) OFF
#####################

proc set_status_message {msg} {
    global status_message
    set status_message $msg
}

proc updateprocmodecolor {vname velt op} {
    upvar $vname x
    if {$x=="super"} {
	catch {.pstate.mode.mode config -bg yellow}
    } elseif {$x=="user"} {
	catch {.pstate.mode.mode config -bg lightblue}
    }
}

proc updateprocstatecolor {vname velt op} {
    upvar $vname x
    if {$x=="execute"} {
	catch {.pstate.state.state config -bg lightgreen}
    } else {
	catch {.pstate.state.state config -bg red}
    }
}

###############################################################################
# a widget for the GX device
###############################################################################
toplevel .gx
wm withdraw .gx
wm title .gx "ISEM GX device"
make_delete_withdraw {.gx}

frame .gx.buttons
button .gx.buttons.dismiss -text "Dismiss" -command "wm withdraw .gx" \
    -bg yellow
button .gx.buttons.help -text "Help" -bg red \
    -command "goto_help_label {The GX device} 1"
pack .gx.buttons.dismiss -side left
pack .gx.buttons.help -side right


isem_gx .gx.display
pack .gx.display .gx.buttons -side top -fill x -expand on

###############################################################################
# a widget for the timer device
###############################################################################
toplevel .timer
wm withdraw .timer
wm title .timer "ISEM timer device"
make_delete_withdraw {.timer}

set timer_edit 0x00000000

frame .timer.bdy
frame .timer.buttons

pack .timer.bdy .timer.buttons -side top -expand 1 -fill x

label .timer.bdy.periodlab -text "Period" -bg grey75 -relief groove
label .timer.bdy.periodval -textvariable timer_period -relief sunken -bd 2
grid .timer.bdy.periodlab .timer.bdy.periodval -row 0 -sticky ew

label .timer.bdy.countlab -text "Count" -bg grey75 -relief groove
label .timer.bdy.countval -textvariable timer_count -relief sunken -bd 2
grid .timer.bdy.countlab .timer.bdy.countval -row 1 -sticky ew

label .timer.bdy.interrlab -text "Interrupt" -bg grey75 -relief groove
label .timer.bdy.interrval -textvariable timer_interrupt -relief sunken -bd 2
grid .timer.bdy.interrlab .timer.bdy.interrval -row 2 -sticky ew

button .timer.bdy.edlab -text "Set period" -command timer_edit_button \
    -bg grey75
entry .timer.bdy.edval -width 11 -textvariable timer_edit -relief sunken -bd 2
grid .timer.bdy.edlab .timer.bdy.edval -row 3 -sticky ew
bind .timer.bdy.edval <Return> {timer_edit_button}

proc timer_edit_button {} {
    global timer_edit timer_period

    set_timer_period $timer_edit
    set timer_edit $timer_period
}


button .timer.buttons.dismiss -text "Dismiss" -command "wm withdraw .timer" \
    -bg yellow
button .timer.buttons.help -text "Help" -bg red \
    -command "goto_help_label {The interval timer} 1"
pack .timer.buttons.dismiss -side left
pack .timer.buttons.help -side right

#############################################################################
##  UART device for tkisem
##############################################################################

toplevel .uart
wm withdraw .uart
wm title .uart "ISEM UART device"
make_delete_withdraw {.uart}
wm minsize .uart 30 20

# variable initialization
set UART_interrupt 0

set UART_RXscale 4			;# scale for UART clock ticks
set UART_TXscale 4			;# scale for UART clock ticks

set UART_sending "****"			;# current value being sent
set UART_TXReg "****"			;# vaule in the transmit register

set UART_receiving "****"		;# current value being sent
set UART_RXReg "****"			;# vaule in the transmit register

set UART_Tx_count 0			;# ticks until value transmitted
set UART_Rx_count 0			;# ticks until next value received
set UART_running 0			;# only set when interesting things
					;# are happening

set UART_stat 0x21
set UART_ctrl 0xfc

set UART_src none
set UART_src_file uart_src
set UART_srate 256
set UART_src_count 0
set UART_inchar 0

set UartTxInput program
set UartRxInput program
set UartTxOutput program
set UartRxOutput program
set UartTxInFile {}
set UartRxInFile {}
set UartTxOutFile {}
set UartRxOutFile {}
set UartTXReg 0x0
set UartRxIndex 1.0
set UartRxIndexCount -1
set UartTxIndex 1.0
set UartTxIndexCount -1

# register displays
frame .uart.reg 
pack .uart.reg -side top -fill x -expand true

# create status register
frame .uart.reg.stat -borderwidth 5 -relief ridge
grid .uart.reg.stat -row 0 -column 0 -rowspan 3 -sticky ns

# status register label
label .uart.reg.stat.reg -text "Status Reg" -bg grey75
grid .uart.reg.stat.reg -row 0 -columnspan 2 -sticky ew

# status register bit labels
label .uart.reg.stat.id0 -text  "tx reg emty"
label .uart.reg.stat.id1 -text  "rx reg full"
label .uart.reg.stat.id2 -text  "overrun err"
label .uart.reg.stat.id3 -text  "framing err"
label .uart.reg.stat.id4 -text  "parity err"
label .uart.reg.stat.id5 -text  "dsr"
label .uart.reg.stat.id6 -text  "unused"
label .uart.reg.stat.id7 -text  "unused"
foreach uarti {0 1 2 3 4 5 6 7}  {
    grid .uart.reg.stat.id$uarti -column 1 -row [expr $uarti + 1] -sticky w
}

# status register bit values
set temp $UART_stat
foreach uarti {0 1 2 3 4 5 6 7}  {
    set bit [expr $temp & 1]
    message .uart.reg.stat.bit$uarti -justify center -text $bit -relief sunken
    grid .uart.reg.stat.bit$uarti -column 0 -row [expr $uarti + 1]
    set temp [expr $temp >> 1]
}

# create control register
frame .uart.reg.creg -borderwidth 5 -relief ridge
grid .uart.reg.creg -row 0 -column 1 -rowspan 3 -sticky ns

# control register label
label .uart.reg.creg.reg -text "Control Reg" -bg grey75
grid .uart.reg.creg.reg -row 0 -columnspan 2 -sticky ew

# control register bit labels
frame .uart.reg.creg.id -borderwidth 5
label .uart.reg.creg.id0 -text  "tx intrrpt enbl"
label .uart.reg.creg.id1 -text  "rx intrrpt enbl"
label .uart.reg.creg.id2 -text  "tx/rx rate x1"
label .uart.reg.creg.id3 -text  "\"            \" x2"
label .uart.reg.creg.id4 -text  "\"            \" x4"
label .uart.reg.creg.id5 -text  "\"            \" x8"
label .uart.reg.creg.id6 -text  "\"            \" x16"
label .uart.reg.creg.id7 -text  "\"            \" x32"
foreach uarti {0 1 2 3 4 5 6 7}  {
    grid .uart.reg.creg.id$uarti -column 1 -row [expr $uarti + 1] -sticky w
}

# control register bit values
set temp $UART_ctrl
foreach uarti {0 1 2 3 4 5 6 7} {
    set bit [expr $temp & 1]
    message .uart.reg.creg.bit$uarti -justify center -relief sunken -text $bit
    grid .uart.reg.creg.bit$uarti -column 0 -row [expr $uarti + 1]
    set temp [expr $temp >> 1]
}

proc uart_disp_reg {reg reg_val} {
    set temp $reg_val
    foreach uarti {0 1 2 3 4 5 6 7} {
	set bit [expr $temp & 1]
	.uart.reg.$reg.bit$uarti configure -text $bit
	set temp [expr $temp >> 1]
    }
}

# the uart data registers
frame .uart.reg.data -borderwidth 5 -relief ridge
grid .uart.reg.data -row 0 -column 2 -sticky ns -rowspan 3

label .uart.reg.data.lab -bg grey75 -text "Data Regs"
grid .uart.reg.data.lab -row 0 -columnspan 2 -sticky ew

label .uart.reg.data.send_lab -text Sending
label .uart.reg.data.send_val -relief sunken -textvariable UART_sending \
    -width 8
grid .uart.reg.data.send_lab .uart.reg.data.send_val -row 1 -sticky e

label .uart.reg.data.tx_lab -text "TX reg"
label .uart.reg.data.tx_val -relief sunken -textvariable UART_TXReg -width 8
grid .uart.reg.data.tx_lab .uart.reg.data.tx_val -row 2 -sticky e

label .uart.reg.data.recv_lab -text Receiving
label .uart.reg.data.recv_val -relief sunken -textvariable UART_receiving \
    -width 8
grid .uart.reg.data.recv_lab .uart.reg.data.recv_val -row 3 -sticky e

label .uart.reg.data.rx_lab -text "RX reg"
label .uart.reg.data.rx_val -relief sunken -textvariable UART_RXReg -width 8
grid .uart.reg.data.rx_lab .uart.reg.data.rx_val -row 4 -sticky e

label .uart.reg.data.interr_lab -text Interrupt
label .uart.reg.data.interr_val -relief sunken -textvariable UART_interrupt \
    -width 8
grid .uart.reg.data.interr_lab .uart.reg.data.interr_val -row 5 -sticky e

label .uart.reg.data.txcnt_lab -text "TX count"
label .uart.reg.data.txcnt_val -relief sunken -textvariable UART_Tx_count \
    -width 8
grid .uart.reg.data.txcnt_lab .uart.reg.data.txcnt_val -row 6 -sticky e

label .uart.reg.data.rxcnt_lab -text "RX count"
label .uart.reg.data.rxcnt_val -relief sunken -textvariable UART_Rx_count \
    -width 8
grid .uart.reg.data.rxcnt_lab .uart.reg.data.rxcnt_val -row 7 -sticky e

entry .uart.reg.data.scale_entr -textvariable UART_RXscale -width 7
label .uart.reg.data.scale_lab -text "RX Scale" -bg grey75
grid .uart.reg.data.scale_lab .uart.reg.data.scale_entr -row 8 -sticky e

entry .uart.reg.data.txscale_entr -textvariable UART_TXscale -width 7
label .uart.reg.data.txscale_lab -text "TX Scale" -bg grey75
grid .uart.reg.data.txscale_lab .uart.reg.data.txscale_entr -row 9 -sticky e

# uart source
frame .uart.reg.source -borderwidth 5 -relief ridge
grid .uart.reg.source -row 1 -column 3

label .uart.reg.source.lab -text "UART Source" -bg grey75
pack .uart.reg.source.lab -side top -fill x -expand on

frame .uart.reg.source.radio
pack .uart.reg.source.radio -side top
radiobutton .uart.reg.source.radio.none -text none -value none \
    -variable UART_src -command uart_source_disabled
radiobutton .uart.reg.source.radio.key -text keybd -value key \
    -variable UART_src -command uart_source_key
radiobutton .uart.reg.source.radio.file -text file -value file \
    -variable UART_src -command uart_source_file
radiobutton .uart.reg.source.radio.rfile -text "rand file" -value rand_file \
    -variable UART_src -command uart_source_file
grid .uart.reg.source.radio.none .uart.reg.source.radio.key -row 0
grid .uart.reg.source.radio.file .uart.reg.source.radio.rfile -row 1

entry .uart.reg.source.entr -textvariable UART_src_file -width 18
pack .uart.reg.source.entr -side top

frame .uart.reg.srate -borderwidth 5 -relief ridge
grid .uart.reg.srate -row 2 -column 3 -sticky ew

label .uart.reg.srate.label -text "Source Rate" -bg grey75
grid .uart.reg.srate.label -columnspan 2 -row 0 -sticky ew
entry .uart.reg.srate.entr -textvariable UART_srate -width 10
label .uart.reg.srate.lab -text "rate"
grid .uart.reg.srate.lab .uart.reg.srate.entr -row 1

label .uart.reg.srate.scnt -textvariable UART_src_count -width 10
label .uart.reg.srate.scntlab -text "count"
grid .uart.reg.srate.scntlab .uart.reg.srate.scnt -row 2

proc uart_source_file {} {
    global UART_src_file UART_src UART_file
    global UART_running

    if {[file readable $UART_src_file]==0} {
	set_status_message "UART_file: Cannot read $UART_src_file"
	set UART_src none
	return
    }

    set UART_file [open $UART_src_file RDONLY]

    uart_getch
    if { $UART_running == 0 } {
	set UART_running 1
	add_run uart_timer
    }
}

proc uart_source_key {} {
    global UART_running
    uart_getch
    if { $UART_running == 0 } {
	set UART_running 1
	add_run uart_timer
    }
}

proc uart_source_disabled {} {
    set UART_src_count 0
}

# the buttons
frame .uart.buttons
pack .uart.buttons -side bottom -fill x -expand on

button .uart.buttons.help -text "Help" -bg red \
    -command "goto_help_label {The UART} 1"
button .uart.buttons.dismiss -text "Dismiss" -command "wm withdraw .uart" \
     -bg yellow
pack .uart.buttons.help -side right
pack .uart.buttons.dismiss -side left

##########################################################################
#  uart input/output selection - PLV
##########################################################################

set uart_test {}
set uart_filename {}

proc UartGetFileName {}  {
    global uart_test uart_filename
    toplevel .uart_get -borderwidth 10
    message .uart_get.msg -text "Please enter filename."  
    entry .uart_get.entry -textvariable uart_filename -bg white \
	-relief ridge
    frame .uart_get.buttons -borderwidth 10
    pack .uart_get.msg .uart_get.entry .uart_get.buttons -side top -fill x
    button .uart_get.buttons.ok -text "OK" -command {set uart_test 1}
    button .uart_get.buttons.can -text "Cancel" -command {set uart_test 0}
    pack .uart_get.buttons.ok -side left
    pack .uart_get.buttons.can -side right
    
    bind .uart_get.buttons.ok <Alt-o> "focus .uart_get.buttons.ok ; break"
    bind .uart_get.buttons.can <Alt-c>\
	"focus .uart_get.buttons.cancel ; break"
    bind .uart_get.entry <Return> {set uart_test 1}
    bind .uart_get <Alt-Key> break
    bind .uart_get <Control-c> {set uart_test 0}
    focus .uart_get.entry
    grab .uart_get
    tkwait variable uart_test
    #grab release .uart_get
    destroy .uart_get
    if {$uart_test}  {
	return $uart_filename
    } else {
	return {}
    }
}

# tx output window
frame .uart.keybd
pack .uart.keybd -side bottom -anchor sw 

frame .uart.keybd.txout
pack .uart.keybd.txout -side top
label .uart.keybd.txout.id -text "Transmitted Values" -bg grey75 -relief groove
pack .uart.keybd.txout.id -side top -fill x -expand true
text .uart.keybd.txout.text -setgrid true -wrap word -width 80 -height 5 \
    -yscrollcommand ".uart.keybd.txout.yscroll set" \
    -relief sunken -state disabled -font fixed
scrollbar .uart.keybd.txout.yscroll -command ".uart.keybd.txout.text yview"
pack .uart.keybd.txout.yscroll -side right -fill y
pack .uart.keybd.txout.text -side left -fill x -expand true

frame .uart.keybd.rxin
pack .uart.keybd.rxin -side top
label .uart.keybd.rxin.id -text "Source Values" -bg grey75  -relief groove
pack .uart.keybd.rxin.id -side top -fill x -expand true
text .uart.keybd.rxin.text -setgrid true -wrap word -width 80 -height 5 \
    -yscrollcommand {.uart.keybd.rxin.yscroll set} -font fixed
scrollbar .uart.keybd.rxin.yscroll -command {.uart.keybd.rxin.text yview}
pack .uart.keybd.rxin.yscroll -side right -fill y
pack .uart.keybd.rxin.text -side left -fill x -expand true

###############################################################################
# The state registers, pc, npc, z, psr, and tbr, are displayed in the
#   register display window along with the general purpose registers
###############################################################################
proc set_state_regs {} {
    global reg_view
    global pc npc y wim
    global psr_cwp psr_et psr_ps psr_s psr_pil psr_ef psr_ec
    global psr_c psr_v psr_z psr_n
    global tbr_tba tbr_tt
    global instr_annul instr_op instr_lab instr_opnds proc_mode

    set pc [isem_reg get pc]
    set npc [isem_reg get npc]
    set instr [isem_mem_rd $proc_mode text $pc]
    set ninstr [isem_mem_rd $proc_mode text $npc]
    set instr [isem_disasm $pc $proc_mode $reg_view]
    set instr_lab [lindex $instr 0]
    set instr_op [lindex $instr 1]
    set instr_opnds [lindex $instr 2]

    # get annul
    set instr_annul [isem_annul]
    
    set y [isem_reg get y]
    set wim [isem_reg get wim]

    set psr [isem_reg get psr]
    set psr_cwp [expr $psr & 1]
    set psr_cwp [expr $psr>>1 & 1]$psr_cwp
    set psr_cwp [expr $psr>>2 & 1]$psr_cwp
    set psr_cwp [expr $psr>>3 & 1]$psr_cwp
    set psr_cwp [expr $psr>>4 & 1]$psr_cwp

    set psr_et [expr $psr>>5 & 1]
    set psr_ps [expr $psr>>6 & 1]
    set psr_s [expr $psr>>7 & 1]

    set psr_pil [expr $psr>>8 & 1]
    set psr_pil [expr $psr>>9 & 1]$psr_pil
    set psr_pil [expr $psr>>10 & 1]$psr_pil
    set psr_pil [expr $psr>>11 & 1]$psr_pil

    set psr_ef [expr $psr>>12 &1]
    set psr_ec [expr $psr>>13 &1]

    set psr_c [expr $psr>>20 &1]
    set psr_v [expr $psr>>21 &1]
    set psr_z [expr $psr>>22 &1]
    set psr_n [expr $psr>>23 &1]

    set tbr [isem_reg get tbr]
    set tbr_tt [format {%.2x} [expr $tbr>>4 & 0xff] ]
    set tbr_tba [format {%.5x} [expr $tbr>>12] ]
}

proc set_gp_regs {} {
    for {set i 0} {$i < 32} {incr i} {
	global r$i
	set r$i [isem_reg get r$i]
    }
}

proc set_memrange {range mode}  {
    upvar \#0 $range range_var
    set temp [convert_val $range_var $mode "unknown"]
    if { $temp != "unknown" } {
	set range_var $temp
    }
}

proc scroll_data_super {args} {
    eval .super_data.mem.lab yview $args
    eval .super_data.mem.mem yview $args
    eval .super_data.mem.char yview $args
}

proc scroll_data_user {args} {
    eval .user_data.mem.lab yview $args
    eval .user_data.mem.mem yview $args
    eval .user_data.mem.char yview $args
}

proc scroll_super {args} {
    eval .super_syms.syms.syms.syms yview $args
    eval .super_syms.syms.value.vals yview $args
}

proc scroll_user {args} {
    eval .user_syms.syms.syms.syms yview $args
    eval .user_syms.syms.value.vals yview $args
}

proc show_syms {mode} {
    # clear out the symbol and value displays
    set syms_list [format {.%s_syms.syms.syms.syms} $mode]
    set vals_list [format {.%s_syms.syms.value.vals} $mode]
    $syms_list delete 0 end
    $vals_list delete 0 end

    upvar \#0 [format {%s_sort} $mode] sort
    if {$sort == "name"} {
	upvar \#0 [format {%s_syms} $mode] syms
	foreach s [lsort [array names syms]] {
	    $syms_list insert end $s
	    $vals_list insert end $syms($s)
	}
    } else {
	foreach sect {abs bss data text} {
	    upvar \#0 [format {%s_%s} $mode $sect] vals
	    foreach s [lsort [array names vals]] {
		$vals_list insert end "$s $sect"
		$syms_list insert end $vals($s)
	    }
	}
    }
}

proc toggle_breakpoint_addr {window addr} {
    regexp {(user|super)} $window mode
    set bv ${mode}_break_var
    global $bv
    set $bv $addr
    if {[is_breakp $mode $addr]} {
	rmv_break $bv $mode
    } else {
	set_bpoint $bv $mode
    }                
}

proc clear_breaks {mode} {
    set base [format {.%s_break.bp} $mode]
    $base.vals delete 0 end
    $base.labs delete 0 end

    set brks [format {.%s_text.mem.breakp} $mode]
    upvar \#0 [format {text_start_%s} $mode] start

    upvar \#0 [format "last_shown_pc_%s" $mode] last_pc
    upvar \#0 [format {%s_breaks} $mode] break_list
    foreach bkpt $break_list {
	set index [expr ($bkpt-$start) / 4]
	$brks delete $index
	if {$bkpt == $last_pc} {
	    $brks insert $index " >"
	} else {
	    $brks insert $index "  "
	}
    }
    set break_list {}

    # clear the last shown pc
    set index [expr ($last_pc-$start) / 4]
    $brks delete $index
    $brks insert $index "  "

    # show the pc
    set last_pc [isem_reg get pc]
    set index [expr ($last_pc-$start) / 4]
    $brks delete $index
    $brks insert $index " >"
}

proc set_bpoint {val_var mode} {
    upvar \#0 $val_var break
    set temp [convert_val $break $mode "unknown"]
    if {$temp != "unknown"} {

	# see if we have a label
	upvar \#0 [format {%s_syms} $mode] syms
	if { [info exists syms($break)] } {
	    set label $break
	} else {
	    set label ""
	}

	# add to the break list
	upvar \#0 [format {%s_breaks} $mode] breaks
	if { [lsearch -exact $breaks $temp] == -1 } {
	    lappend breaks $temp
	    set base [format {.%s_break.bp} $mode]
	    $base.labs insert end $label
	    $base.vals insert end $temp
	} 

	# show the breakpoint
	upvar \#0 [format "last_shown_pc_%s" $mode] last_pc
	set brks [format {.%s_text.mem.breakp} $mode]
	upvar \#0 [format {text_start_%s} $mode] start
	set index [expr ($temp-$start) / 4]
	$brks delete $index
	if {$temp == $last_pc} {
	    $brks insert $index "B>"
	} else {
	    $brks insert $index "B "
	}
    }
}

proc rmv_break {val_var mode} {
    upvar \#0 $val_var break
    set temp [convert_val $break $mode "unknown"]
    if {$temp != "unknown"} {
	upvar \#0  [format {%s_breaks} $mode] breaks
	set index [lsearch -exact $breaks $temp]
	if { $index != -1 } {
	    set breaks [lreplace $breaks $index $index]
	    set base [format {.%s_break.bp} $mode]
	    $base.labs delete $index
	    $base.vals delete $index
	} 

	# clear the breakpoint
	upvar \#0 [format "last_shown_pc_%s" $mode] last_pc
	set brks [format {.%s_text.mem.breakp} $mode]
	upvar \#0 [format {text_start_%s} $mode] start
	set index [expr ($temp-$start) / 4]
	$brks delete $index
	if {$temp == $last_pc} {
	    $brks insert $index " >"
	} else {
	    $brks insert $index "  "
	}
    }
}

###############################################################################
# support functions
###############################################################################
#..............................................................................
# show_data -- 
#------------------------------------------------------------------------------
proc show_data {mode} {
    upvar \#0 [format {data_start_%s} $mode] start
    upvar \#0 [format {data_end_%s} $mode] end

    set start [format {0x%.8x} [expr ($start>>2)<<2]]
    set end [format {0x%.8x} [expr ($end>>2)<<2]]

    set labs [format {.%s_data.mem.lab} $mode]
    $labs delete 0 end
    set mem [format {.%s_data.mem.mem} $mode]
    $mem delete 0 end
    set char [format {.%s_data.mem.char} $mode]
    $char delete 0 end

    upvar \#0 [format {%s_data} $mode] val

    set update [format {.%s_text.range.update} $mode]
    $update configure -text ""
    update

    set values [isem_mem_rd $mode data $start $end]
    set addr $start
    foreach v $values {
	set addr [format {0x%.8x} $addr]
	if {[info exists val($addr)]} {
	    $labs insert end "$val($addr):"
	} else {
	    $labs insert end $addr
	}
	$mem insert end $v
	$char insert end [format {%c%c%c%c} [expr ($v>>24)&0xff] \
			      [expr ($v>>16)&0xff] [expr ($v>>8)&0xff] \
			      [expr $v&0xff] ]
	incr addr 4
    }
    $update configure -text "Update" -bg lightgreen
    update
}

proc show_text {mode} {
    global reg_view
    set scrollw [format {.%s_text.mem.scroll} $mode]
    set wasy [lindex [$scrollw get] 0]
    
    set pc [format {0x%.8x} [isem_reg get pc]]
    
    upvar \#0 [format {text_start_%s} $mode] start
    upvar \#0 [format {text_end_%s} $mode] end
    
    set start [format {0x%.8x} [expr ($start>>2)<<2]]
    set end [format {0x%.8x} [expr ($end>>2)<<2]]
    
    set update [format {.%s_text.range.update} $mode]
    $update configure -text ""
    update
    
    set addrs [format {.%s_text.mem.addr} $mode]
    $addrs delete 0 end
    set labs [format {.%s_text.mem.lab} $mode]
    $labs delete 0 end
    set opr [format {.%s_text.mem.opr} $mode]
    $opr delete 0 end
    set opnds [format {.%s_text.mem.opnds} $mode]
    $opnds delete 0 end
    set brks [format {.%s_text.mem.breakp} $mode]
    $brks delete 0 end
    
    for {set adr $start} {$adr <= $end} {incr adr 4} {
	set addr [format {0x%.8x} $adr]
	
        set pcflag " "
        if {$addr==$pc} {
	    set pcflag ">"
	    upvar \#0 [format "last_shown_pc_%s" $mode] last_pc
	    set last_pc $pc
        }
        set brkflag " "
	if {[is_breakp $mode $addr] } {
	    set brkflag "B"
	}
	$brks insert end "$brkflag$pcflag" 
	$addrs insert end $addr
	
	set instr [isem_disasm $addr $mode $reg_view]
	$labs insert end [lindex $instr 0]
	$opr insert end [lindex $instr 1]
	$opnds insert end [lindex $instr 2]
    }
    
    set pc_indx [expr ($pc-$start)/4]
    $addrs see $pc_indx
    $labs see $pc_indx
    $opr see $pc_indx
    $opnds see $pc_indx
    $brks see $pc_indx

    $update configure -text "Update" -bg lightgreen
    update
}

#------------------------------------------------------------------------------
# loading files
#------------------------------------------------------------------------------
proc load_super name {
    global load_mode

    set load_mode super
    load_file $name
}

proc load_user name {
    global load_mode

    set load_mode user
    load_file $name
}

proc load_file name {

    # make sure we can read the file we're trying to read
    if {[file readable $name]==0} {
	set_status_message "load_file: Cannot read $name"
	isem_debug "load_file: Cannot read $name"
	return "error"
    }

    global load_mode
    if {[catch {isem_load $name $load_mode} symbols] != 0} {
	set_status_message $symbols
	isem_debug "load_file: $symbols"
	return "error"
    }

    global proc_mode proc_state
    global file_$load_mode

    #set file_$load_mode [file tail $name]

    set proc_mode $load_mode
    set file_name [format {%s_file} $load_mode]
    global $file_name
    set $file_name $name

    upvar \#0 [format {%s_syms} $load_mode] syms
    set syms(x) y
    foreach i [array names syms] {
	unset syms($i)
    }

    foreach sect {abs bss data text} {
	upvar \#0 [format {%s_%s} $load_mode $sect] arr
	set arr(x) y
	foreach i [array names arr] {
	    unset arr($i)
	}
    }

    global text_start_$load_mode text_end_$load_mode
    global data_start_$load_mode data_end_$load_mode

    set text_start_$load_mode [lindex $symbols 0]
    upvar \#0 [format {%s_text} $load_mode] val
    set text_end_$load_mode [lindex $symbols 1]
    set data_start_$load_mode [lindex $symbols 2]
    set data_end_$load_mode [lindex $symbols 3]

    set symbols [lrange $symbols 4 end]

    foreach s $symbols {
	set nam [lindex $s 0]
	if { ![regexp {.*\.o$} $nam] } {
	    set syms($nam) [list [lindex $s 1] [lindex $s 2]]
	    upvar \#0 [format {%s_%s} $load_mode [lindex $s 2]] val
	    set val([lindex $s 1]) $nam
	}
    }

    set xxx $syms(_etext)
    set text_end_$load_mode [lindex $xxx 0]

    set xxx $syms(_edata)
    set data_end_$load_mode [lindex $xxx 0]
    
    show_syms $load_mode
    clear_breaks $load_mode

    set_state_regs
    set_gp_regs

    .run_stop configure -text Run -command run_button
    set proc_state "execute"

    set_status_message "$name loaded into $load_mode memory"

    return "ok"
}

proc is_breakp {mode addr} {
   global user_breaks super_breaks
   if { [lsearch -exact [set ${mode}_breaks] $addr] != -1} {
	return 1
    } else {
   	return 0
    }
}

#------------------------------------------------------------------------------
# running programs
#------------------------------------------------------------------------------

#..............................................................................
# driver -- run until stop_run is set
proc driver {} {
    global total_cycles stop_run proc_state
    global user_breaks super_breaks proc_mode step_super step_user
    
    set_status_message ""
    set stop_run 0
    while {!$stop_run} {
	set proc_mode [isem_step]
	run_devices
	incr total_cycles

	if {$proc_mode=="error"} {
	    set stop_run 1
	} else {
	    if { [set step_${proc_mode}] } {
		set stop_run 1
	    } elseif { $total_cycles%[.uprate get] == 0 } {
		update_display 0
	    }
	    
	    if {[llength ${proc_mode}_breaks]} { ;# see if worth checking..
		set pc [isem_reg get pc]
		if { [lsearch -exact [set ${proc_mode}_breaks] $pc] != -1 } {
		    set_status_message [format {Breakpoint at %s} $pc]
		    set stop_run 1
		}
	    }
	}
    }
    
    update_display 1
    .run_stop configure -text Run -command run_button
    .loadfile.user.load configure -state normal
    .loadfile.super.load configure -state normal
}

#..............................................................................
# run and stop buttons
proc do_nothing {} {
}

proc run_button {} {
    .loadfile.user.load configure -state disabled
    .loadfile.super.load configure -state disabled
    .run_stop configure -text Stop -command stop_button
    driver
}

proc stop_button {} {
    global stop_run
    .run_stop configure -text Run -command run_button
    set stop_run 1
}

#..............................................................................
# update_display -- updates the main window and register displays.  Called
# whenever execution is halted or when enough instructions have been executed
proc update_display { force } {
    global proc_mode proc_state update_user update_super
    global user_cycles user_mems super_cycles super_mems
    global super_breaks user_breaks

    if {$proc_mode=="error"} {
	set proc_state "error"
	set psr [isem_reg get psr]
	if { [expr $psr>>7 & 1] == 1 } {
	    set proc_mode super
	} else {
	    set proc_mode user
	}
    }

    set mode_is_updated [set update_${proc_mode}]
    if {$mode_is_updated || $force} {
	if {[wm state .gpregs] == "normal"} {
	    set_state_regs
	    set_gp_regs
	}
	if {[wm state .${proc_mode}_text] == "normal" } {
	    # clear the last shown pc
	    set brks [format {.%s_text.mem.breakp} $proc_mode]
	    upvar \#0 [format {text_start_%s} $proc_mode] start
	    upvar \#0 [format "last_shown_pc_%s" $proc_mode] last_pc
	    set index [expr ($last_pc-$start) / 4]
	    $brks delete $index
	    if { [lsearch -exact [set ${proc_mode}_breaks] $last_pc] != -1 } {
		$brks insert $index "B "
	    } else {
		$brks insert $index "  "
	    }
	    
	    # show the pc
	    set last_pc [isem_reg get pc]
	    set index [expr ($last_pc-$start) / 4]
	    $brks delete $index
	    if { [lsearch -exact [set ${proc_mode}_breaks] $last_pc] != -1 } {
		$brks insert $index "B>"
	    } else {
		$brks insert $index " >"
	    }

	    set addrs [format {.%s_text.mem.addr} $proc_mode]
	    set labs [format {.%s_text.mem.lab} $proc_mode]
	    set opr [format {.%s_text.mem.opr} $proc_mode]
	    set opnds [format {.%s_text.mem.opnds} $proc_mode]

	    $addrs see $index
	    $labs see $index
	    $opr see $index
	    $opnds see $index
	    $brks see $index
	}
    }

    # get processor state
    scan [isem_counts] %d%d%d%d user_cycles user_mems super_cycles super_mems
    update
}

###############################################################################
# The control panel
###############################################################################

#------------------------------------------------------------------------------
# the menu bar entries
#------------------------------------------------------------------------------
frame .mbar -relief raised -bd 2
menubutton .mbar.file -text File -underline 0 -menu .mbar.file.menu
menubutton .mbar.regs -text Registers -underline 0 -menu .mbar.regs.menu
menubutton .mbar.symb -text Symbols -underline 0 -menu .mbar.symb.menu
menubutton .mbar.break -text Breakpoints -underline 0 -menu .mbar.break.menu
menubutton .mbar.mem -text Memory -underline 0 -menu .mbar.mem.menu
menubutton .mbar.opt -text Options -underline 0 -menu .mbar.opt.menu
menubutton .mbar.dev -text Devices -underline 0 -menu .mbar.dev.menu
menubutton .mbar.help -text "Help" -underline 0 -menu .mbar.help.menu -bg red

menu .mbar.file.menu
.mbar.file.menu add command -label Quit -command exit
.mbar.file.menu add command -label "Debug" -command "wm deiconify .isem_debug"

menu .mbar.regs.menu
.mbar.regs.menu add command -label "Display" -command "wm deiconify .gpregs;raise .gpregs"

menu .mbar.break.menu
.mbar.break.menu add command -label "User Breakpoints" \
    -command "wm deiconify .user_break;raise .user_break"
.mbar.break.menu add command -label "Supervisor Breakpoints"  \
    -command "wm deiconify .super_break;raise .super_break"

menu .mbar.mem.menu
.mbar.mem.menu add command -label "User Data" \
    -command "wm deiconify .user_data;raise .user_data"
.mbar.mem.menu add command -label "User Text" \
    -command "wm deiconify .user_text;raise .user_text"
.mbar.mem.menu add command -label "Supervisor Data" \
    -command "wm deiconify .super_data;raise .super_data"
.mbar.mem.menu add command -label "Supervisor Text" \
    -command "wm deiconify .super_text;raise .super_text"

menu .mbar.symb.menu
.mbar.symb.menu add command -label "User Symbols" \
    -command "wm deiconify .user_syms;raise .user_syms"
.mbar.symb.menu add command -label "Supervisor Symbols" \
    -command "wm deiconify .super_syms;raise .super_syms"

menu .mbar.dev.menu
.mbar.dev.menu add command -label "Timer" -command "wm deiconify .timer;raise .timer"
.mbar.dev.menu add command -label "UART" -command "wm deiconify .uart;raise .uart"
.mbar.dev.menu add command -label "GX" -command "wm deiconify .gx;raise .gx"

menu .mbar.opt.menu

.mbar.opt.menu add command -label "Regular Regs" -command set_reg_view_regular
.mbar.opt.menu add command -label "Window Regs" -command set_reg_view_window

menu .mbar.help.menu
.mbar.help.menu add command -label "Table of contents" \
    -command "goto_help_label {Table of contents} 1"
.mbar.help.menu add command -label "Overview" \
    -command "goto_help_label {Overview} 1"
.mbar.help.menu add command -label "Using Help" \
    -command "goto_help_label {Using help} 1"
.mbar.help.menu add command -label "About Tcl Errors" \
    -command "goto_help_label {About Tcl errors} 1"
.mbar.help.menu add command -label "The Main Window" \
    -command "goto_help_label {Main window} 1"
.mbar.help.menu add command -label "The Register Window" \
    -command "goto_help_label {Register window} 1"
.mbar.help.menu add command -label "The Symbol Window" \
    -command "goto_help_label {Symbol window} 1"
.mbar.help.menu add command -label "The Breakpoint Window" \
    -command "goto_help_label {Breakpoint window} 1"
.mbar.help.menu add command -label "The Text Display Window" \
    -command "goto_help_label {Text display window} 1"
.mbar.help.menu add command -label "The Data Display Window" \
    -command "goto_help_label {Data display window} 1"
.mbar.help.menu add command -label "Breakpoints" \
    -command "goto_help_label {Breakpoints} 1"
.mbar.help.menu add command -label "The Devices" \
    -command "goto_help_label {The devices} 1"
.mbar.help.menu add command -label "The ROM Code" \
    -command "goto_help_label {The rom code} 1"

#------------------------------------------------------------------------------
# the help window
#------------------------------------------------------------------------------
toplevel .tkhelp
wm withdraw .tkhelp
wm title .tkhelp "ISEM: Help"
make_delete_withdraw .tkhelp

frame .tkhelp.statusline

label .tkhelp.statusline.stat -text "Message: " -bg grey75
label .tkhelp.statusline.msg -anchor w -textvariable status_message -width 50 \
    -relief sunken -bg white
pack .tkhelp.statusline.stat -side left -ipadx 2m -fill x
pack .tkhelp.statusline.msg -side left -expand 1 -fill x 
pack .tkhelp.statusline -side bottom

frame .tkhelp.buttons
pack .tkhelp.buttons -side bottom -fill x
text .tkhelp.text -yscrollcommand ".tkhelp.scroll set" -wrap word
scrollbar .tkhelp.scroll -command ".tkhelp.text yview"
pack .tkhelp.scroll -side right -fill y
pack .tkhelp.text -side left
button .tkhelp.buttons.dismiss -text "Dismiss" -command "wm withdraw .tkhelp" \
     -bg yellow
set help_previous_topics {}
set help_current_topic {}

button .tkhelp.buttons.back -text "Back" -command "help_go_back" \
    -state disabled
button .tkhelp.buttons.last -text Previous -command "help_go_prev" \
    -state disabled
pack .tkhelp.buttons.dismiss -side left
pack .tkhelp.buttons.back -side right

.tkhelp.text configure -foreground $help_fore
.tkhelp.text configure -bg $help_back
.tkhelp.text configure -font $help_font

.tkhelp.text tag configure xref -foreground $help_xref_fore
.tkhelp.text tag configure xref -background $help_xref_back
.tkhelp.text tag configure xref -font $help_xref_font

.tkhelp.text tag configure label -background $help_label_back
.tkhelp.text tag configure label -foreground $help_label_fore
.tkhelp.text tag configure label -font $help_label_font

.tkhelp.text tag configure example -foreground $help_example_fore
.tkhelp.text tag configure example -background $help_example_back
.tkhelp.text tag configure example -font $help_example_font

.tkhelp.text tag bind xref <Any-Button> {
    infojumpfocus [.tkhelp.text index @%x,%y] 1
}

##########################################
# Sun Jan 22 12:26:13 1995 dha Barfing out something, anything, to add a
# little help functionality to tkisem21 before the students have actually
# to *use* the damn thing

# Basic scheme: A single help file for everything, that will get
# inhaled in its entirety the first time any help is requested, and a
# single help window to display the file.  We're going to parse the help
# text just slightly on the way in, to find two things: 
# (1) Beginning-of-section labels, indicating that the immediately
# following text should be scrolled to the top of the help window if
# help on the given label is requested, and 
# (2) Inline xrefs to other sections, mentioning them by labels.
#
# For disgustimento nroff-oid ease of parsing, we'll require that all
# such commands appear alone on a line, and use blank lines to separate
# paragraphs, and flow everything else together.
#
# The implementation strategy is to tag all xrefs as XREF or something,
# and tag all labels as, say, LABEL, and then go from there.
#
# Sun Jan 22 12:35:46 1995 Here we go.
#
# Sun Jan 22 13:45:09 1995 OK, well, regrouping...  Frigging text
# widgets can't be trusted to wrap text as far as I can barf them, so
# we're tossing the nroff-oid mode and going with arbitrary position
# trip characters instead.  This isn't so awful to do since we're using
# regexp already.  So now we're going to believe the line breaks in the
# help file.  Going again.
#
# Sun Jan 22 15:20:49 1995 OK, it works.  God I hate Tcl.  Now to drop by
# the escape pod to see if I can use these fonts or not, on the way outta here
#
# Thu Jan 26 10:30:10 1995 Well, since it's office hours and nobody's here,
# I'm going to hack help a little more.  Going back to tcl-wrap/paragraph
# mode, but keeping the trip-character style

set tkhloadedp 0

proc help_go_back {} {
    global help_previous_topics
    set l [expr [llength $help_previous_topics]-1]
    if { $l >= 0 } {
	set b [lindex $help_previous_topics $l]
	set help_previous_topics [lreplace $help_previous_topics $l $l]
	goto_help_label $b 0
    }
    if {$help_previous_topics=={}} {
	.tkhelp.buttons.back config -state disabled -text "Back"
    } else {
	set b [lindex $help_previous_topics \
		   [expr [llength $help_previous_topics]-1]]
	.tkhelp.buttons.back config -state normal -text "Back to '$b'"
    }
}

proc find_prev_label {indx} {
    set w .tkhelp.text
    $w mark set finger 1.0
    set nr ""
    while {1} {
	set last $nr
	set nr [$w tag nextrange label [$w index finger] "$indx+1 char"]
	if {$nr==""} {
	    if {$last==""} return
	    set ats [lindex $last 0]
	    set ate [lindex $last 1]
	    set lab [$w get $ats $ate]
	    return $lab
	} else { 
	    $w mark set finger [lindex $nr 1] 
	}
    }
}

proc infojumpfocus {jndex additp} {
    set w .tkhelp.text
    $w mark set finger 1.0
    set nr ""
    while {1} {
	set last $nr
	set nr [$w tag nextrange xref [$w index finger] "$jndex+1 char"]
	if {$nr==""} {
	    if {$last==""} return
	    set ats [lindex $last 0]
	    set ate [lindex $last 1]
	    set lab [$w get $ats $ate]
	    global help_current_topic
	    set cur_label [find_prev_label $jndex]
	    if {$cur_label != $help_current_topic} {
		global help_previous_topics
		lappend help_previous_topics $help_current_topic
		set help_current_topic $cur_label
	    }
	    goto_help_label $lab $additp
	    return
	} else { 
	    $w mark set finger [lindex $nr 1] 
	}
    }
}

proc goto_help_label {label additp} {
    tkhcheckload
    wm deiconify .tkhelp
    raise .tkhelp
    set_status_message ""
    if {[catch {set kndex [lindex [.tkhelp.text tag ranges $label] 0]} \
	                          errorstring]==0} {
	if {$kndex!=""} {
	    .tkhelp.text yview $kndex
	    global help_current_topic
	    if { $additp && $help_current_topic != {} } {
		global help_previous_topics
		lappend help_previous_topics $help_current_topic
		.tkhelp.buttons.back config -state normal \
		    -text "Back to '$help_current_topic'"
	    }
	    set help_current_topic $label
	    return
	}
    }
    set_status_message "Can't find help label '$label'"
}

proc tkhcheckload {} {
    global tkhloadedp tkhfile
    if {$tkhloadedp==0} {
	tkhloadparse $tkhfile .tkhelp
	set tkhloadedp 1
    }
}

set lvl1_cnt 0
set lvl2_cnt 0
set lvl3_cnt 0

proc tkhloadparse {name w} {

    set evalstr ""
    $w.text delete 1.0 end
    if {[file readable $name]==0} {
	$w.text insert end "Can't read help file $name"
	return
    }

    set f [open $name r]
    while {[gets $f line] >= 0} {	;# til eof

	# look for blank lines
	set first 1
	set notlast 1
	while {$notlast && [regexp {^[ 	]*$} $line]} {
	    if {$first} {
		$w.text insert end "\n\n"
		set first 0
	    }
	    if {[gets $f line] < 0} {
		set notlast 0
	    }
	}

	global lvl1_cnt lvl2_cnt lvl3_cnt
	while {[regexp -nocase \
		    {^([^~]*)~(br|lb|lb1|lb2|lb3|xr|eg|var)\[([^~]*)\](.*)$} \
		    $line all pre cmd arg post]!=0} {

	    # ship off the leading non-cmd stuff
	    $w.text insert end $pre 

	    if {$cmd == "lb1"} {
		incr lvl1_cnt
		set lvl2_cnt 0
		set lvl3_cnt 0
		$w.text insert end "$lvl1_cnt.  "
		set cmd "lb"
	    } elseif {$cmd=="lb2"} {
		incr lvl2_cnt
		set lvl3_cnt 0
		$w.text insert end "$lvl1_cnt.$lvl2_cnt.  "
		set cmd "lb"
	    } elseif {$cmd=="lb3"} {
		incr lvl3_cnt
		$w.text insert end "$lvl1_cnt.$lvl2_cnt.$lvl3_cnt  "
		set cmd "lb"
	    }

	    # replace the variable for a ~var command
	    if {$cmd=="var"} {
		upvar \#0 $arg xxx
		set arg $xxx
		set cmd "eg"
	    }

	    # record the start and end of the text for this command
	    set start [$w.text index "end - 1 chars"]
	    $w.text insert end $arg
	    set end [$w.text index "end - 1 chars"]

	    #puts "tkhlp cmd $cmd start $start end $end arg $arg"

	    # process the command
	    if {$cmd=="lb"} {
		append evalstr "$w.text mark set {$arg} $start\n"
		append evalstr "$w.text tag add label $start $end\n"
		append evalstr "$w.text tag add {$arg} $start $end\n"
	    } elseif {$cmd=="xr"} {
		append evalstr "$w.text tag add xref $start $end\n"
	    } elseif {$cmd=="eg"} {
		append evalstr "$w.text tag add example $start $end\n"
	    } elseif {$cmd=="br"} {
		$w.text insert end "\n"
	    }
	    
	    # process the rest of the line
	    set line $post
	}

	# add the rest (non command part) of the line
	$w.text insert end "$line "
    }

    #puts "$evalstr"
    eval $evalstr
    close $f
    $w.text configure -state disabled
}

# End of tkisem_help.tcl
##########################################

pack .mbar.file .mbar.regs .mbar.symb .mbar.break .mbar.mem .mbar.dev \
    .mbar.opt -side left
pack .mbar.help -side right

#------------------------------------------------------------------------------
# the status line
#------------------------------------------------------------------------------
frame .statusline

label .statusline.stat -text "Message: " -background grey75
label .statusline.msg -anchor w -textvariable status_message -width 50 \
    -relief sunken -bg white
pack .statusline.stat -side left -ipadx 2m -fill x
pack .statusline.msg -side left -expand 1 -fill x 

#------------------------------------------------------------------------------
# the processor state line
#------------------------------------------------------------------------------
frame .pstate -relief raised -bd 2
frame .pstate.state
label .pstate.state.lab -text "Proc State" -anchor w
label .pstate.state.state -width 8 -textvariable proc_state \
    -relief groove -bd 4 -anchor w
pack .pstate.state.lab .pstate.state.state -side top -expand 1 -fill x

frame .pstate.mode
label .pstate.mode.lab -text "Proc Mode" -anchor w
label .pstate.mode.mode -width 7 -textvariable proc_mode -relief groove \
    -bd 4 -anchor w

#####################
# AckleyHacks(tm) ON
# 
# make it a bit more obvious what the processor mode is

trace variable proc_mode w updateprocmodecolor
trace variable proc_state w updateprocstatecolor

#
# AckleyHacks(tm) OFF
#####################

pack .pstate.mode.lab .pstate.mode.mode -side top -expand 1 -fill x
pack .pstate.state .pstate.mode -side left -padx 2m

frame .pstate.step
frame .pstate.step.super
label .pstate.step.super.lab -text "Super" -width 6
checkbutton .pstate.step.super.step -text "Step" -variable step_super \
    -command set_super_step -anchor w
checkbutton .pstate.step.super.update -text "Display" -variable update_super \
    -command set_super_update -anchor w
label .pstate.step.super.cyclecount -textvariable super_cycles -width 8 \
    -anchor e
label .pstate.step.super.memcount -textvariable super_mems -width 8 -anchor e
pack .pstate.step.super.lab .pstate.step.super.step .pstate.step.super.update \
    .pstate.step.super.cyclecount .pstate.step.super.memcount -side left

frame .pstate.step.user
label .pstate.step.user.lab -text "User" -width 6
checkbutton .pstate.step.user.step -text "Step" -variable step_user \
    -command set_user_step -anchor w
checkbutton .pstate.step.user.update -text "Display" -variable update_user \
    -command set_user_update -anchor w
label .pstate.step.user.cyclecount -textvariable user_cycles -width 8 \
    -anchor e
label .pstate.step.user.memcount -textvariable user_mems -width 8 -anchor e
pack .pstate.step.user.lab .pstate.step.user.step .pstate.step.user.update \
    .pstate.step.user.cyclecount .pstate.step.user.memcount -side left

pack .pstate.step.super .pstate.step.user -side top -expand 1 -fill x -padx 2m

pack .pstate.step -side left -expand 1 -fill x -padx 2m

proc set_super_step {} {
    global step_super update_super

    if { $step_super } {
	set update_super 1
    }
}

proc set_super_update {} {
    global step_super update_super

    if { $update_super==0 } {
	set step_super 0
    }
}

proc set_user_step {} {
    global step_user update_user

    if { $step_user } {
	set update_user 1
    }
}

proc set_user_update {} {
    global step_user update_user

    if { $update_user==0 } {
	set step_user 0
    }
}

#------------------------------------------------------------------------------
# the load line  -- now including update rate and also run?
#------------------------------------------------------------------------------
set ld_fname a.out
frame .loadfile

frame .loadfile.user
button .loadfile.user.load -text "Load User" -command {load_user $file_user} \
    -state disabled
entry .loadfile.user.name -relief sunken -textvariable file_user
bind .loadfile.user.name <Return> {load_user $file_user}
pack .loadfile.user.load .loadfile.user.name -side top -fill x -expand 1

frame .loadfile.super
button .loadfile.super.load -text "Load Super" \
    -command {load_super $file_super} -state disabled
entry .loadfile.super.name -relief sunken -textvariable file_super
bind .loadfile.super.name <Return> {load_super $file_super}
pack .loadfile.super.load .loadfile.super.name -side top -fill x -expand 1

pack .loadfile.user .loadfile.super -side left

scale .uprate -label "Display Frequency" -from 1 -to 1024 \
    -orient horizontal 
.uprate set 256
pack .uprate -in .loadfile -side right -fill x -expand 1 -padx 1m
button .run_stop -width 5
pack .run_stop -in .loadfile -side right -padx 1m -fill y

#------------------------------------------------------------------------------
# the console output
#------------------------------------------------------------------------------
set conout_height 6
set conout_width 80
frame .conout
label .conout.lab -text "Console Output" -relief groove -background grey75
frame .conout.text
pack .conout.lab -side top -fill x -expand 0
pack .conout.text -side top -fill both -expand 1

text .conout.text.text \
        -height $conout_height -width $conout_width \
        -relief sunken -bd 2 -state disabled -font $console_font \
        -yscrollcommand ".conout.text.scroll set"
scrollbar .conout.text.scroll -command ".conout.text.text yview"
pack .conout.text.scroll -side right -fill y 
pack .conout.text.text -side left -fill both -expand 1

#------------------------------------------------------------------------------
# the console input
#------------------------------------------------------------------------------
set conin_height 2
set conin_width 80
frame .conin
label .conin.lab -text "Console Input" -relief groove -background grey75
frame .conin.text
pack .conin.lab -side top -fill x -expand 0
pack .conin.text -side top -fill both -expand 1

text .conin.text.text \
        -height $conin_height -width $conin_width \
        -relief sunken -bd 2 -font $console_font \
        -yscrollcommand ".conin.text.scroll set"
scrollbar .conin.text.scroll -command ".conin.text.text yview"
pack .conin.text.scroll -side right -fill y
pack .conin.text.text -side left -fill both -expand 1

#------------------------------------------------------------------------------
# put the pieces together for the main window
pack .mbar .pstate .loadfile .statusline -side top -fill x
pack .conout .conin -side top -fill both -expand 1

###############################################################################
# toplevel widgets to display supervisor and user text
###############################################################################
foreach mode {super user} {
    set top [format {.%s_text} $mode]

    toplevel $top
    wm withdraw $top

    frame $top.mem
    pack $top.mem -side top -fill both -expand yes

    frame $top.range
    pack $top.range -side top -fill x

    frame $top.range.start
    frame $top.range.end
    button $top.range.update -width 6 -text "Update" -bg lightgreen \
	-command "show_text $mode"
    pack $top.range.update -side left
    pack $top.range.start -side left -fill x
    pack $top.range.end -side left -fill x

    global text_start_$mode text_end_$mode

    label $top.range.start.lab -text Start
    entry $top.range.start.val -width 11 -font $text_font -relief sunken \
	-textvariable text_start_$mode
    bind $top.range.start.val <Return> "set_memrange text_start_$mode $mode"
    pack $top.range.start.lab -side left
    pack $top.range.start.val -side left -fill x

    label $top.range.end.lab -text End
    entry $top.range.end.val -width 11 -font $text_font -relief sunken \
	-textvariable text_end_$mode
    bind $top.range.end.val <Return> "set_memrange text_end_$mode $mode"
    pack $top.range.end.lab -side left
    pack $top.range.end.val -side left -fill x

    frame $top.buttons
    pack $top.buttons -side bottom -fill x

    listbox $top.mem.addr -font $text_font -width 11 -height 20 \
	-relief sunken -yscrollcommand "$top.mem.scroll set"

    bind $top.mem.addr <Double-Button-1> \
	{toggle_breakpoint_addr %W [selection get]}
    
    listbox $top.mem.breakp -font $text_font -width 2 -height 20 \
	-relief sunken -yscrollcommand "$top.mem.scroll set"

    listbox $top.mem.lab -font $text_font -width 11 -height 20 -relief sunken \
	-yscrollcommand "$top.mem.scroll set"
    listbox $top.mem.opr -font $text_font -width 11 -height 20 -relief sunken \
	-yscrollcommand "$top.mem.scroll set"
    listbox $top.mem.opnds -font $text_font -width 25 -height 20 \
	-relief sunken -yscrollcommand "$top.mem.scroll set"
    pack $top.mem.breakp $top.mem.addr $top.mem.lab $top.mem.opr \
	$top.mem.opnds -side left -fill both -expand yes

    scrollbar $top.mem.scroll -command scroll_text_$mode -relief ridge
    pack $top.mem.scroll -side left -fill y

    button $top.buttons.dismiss -text "Dismiss" -command "wm withdraw $top" \
	 -bg yellow
    button $top.buttons.help -text "Help" -bg red \
	-command "goto_help_label {Text display window} 1"
    pack $top.buttons.dismiss -side left
    pack $top.buttons.help -side right
}

proc scroll_text_super {args} {
    eval .super_text.mem.breakp yview $args
    eval .super_text.mem.addr yview $args
    eval .super_text.mem.lab yview $args
    eval .super_text.mem.opr yview $args
    eval .super_text.mem.opnds yview $args
}

proc scroll_text_user {args} {
    eval .user_text.mem.breakp yview $args
    eval .user_text.mem.addr yview $args
    eval .user_text.mem.lab yview $args
    eval .user_text.mem.opr yview $args
    eval .user_text.mem.opnds yview $args
}

wm title .super_text "ISEM: Supervisor Text"
make_delete_withdraw .super_text
wm title .user_text "ISEM: User Text"
make_delete_withdraw .user_text

###############################################################################
# toplevel widgets to display supervisor and user data
###############################################################################
foreach mode {super user} {
    set top [format {.%s_data} $mode]

    toplevel $top
    wm withdraw $top

    frame $top.mem
    pack $top.mem -side top -fill both -expand 1

    frame $top.range
    pack $top.range -side top

    frame $top.range.start
    frame $top.range.end
    button $top.range.update -width 6 -text "Update" -bg lightgreen\
	-command "show_data $mode"
    pack $top.range.update $top.range.start $top.range.end -side left

    global data_start_$mode data_end_$mode

    label $top.range.start.lab -text Start
    entry $top.range.start.val -width 11 -font $data_font -relief sunken \
	-textvariable data_start_$mode
    bind $top.range.start.val <Return> "set_memrange data_start_$mode $mode"
    pack $top.range.start.lab -side left
    pack $top.range.start.val -side left -fill x

    label $top.range.end.lab -text End
    entry $top.range.end.val -width 11 -font $data_font -relief sunken \
	-textvariable data_end_$mode
    bind $top.range.end.val <Return> "set_memrange data_end_$mode $mode"
    pack $top.range.end.lab $top.range.end.val -side left

    frame $top.buttons
    pack $top.buttons -side bottom -fill x

    listbox $top.mem.lab -font $data_font -width 11 -height 20 -relief sunken \
	-yscrollcommand "$top.mem.scroll set"
    listbox $top.mem.mem -font $data_font -width 11 -height 20 -relief sunken \
	-yscrollcommand "$top.mem.scroll set"
    listbox $top.mem.char -font $data_font -width 5 -height 20 -relief sunken \
	-yscrollcommand "$top.mem.scroll set"
    pack $top.mem.lab $top.mem.mem $top.mem.char -side left \
	-fill both -expand 1

    scrollbar $top.mem.scroll -command scroll_data_$mode -relief ridge
    pack $top.mem.scroll -side left -fill y

    button $top.buttons.dismiss -text "Dismiss" -command "wm withdraw $top" \
	 -bg yellow
    button $top.buttons.help -text "Help" -bg red \
	-command "goto_help_label {Data display window} 1"
    pack $top.buttons.dismiss -side left
    pack $top.buttons.help -side right
}

wm title .super_data "ISEM: Supervisor Data"
make_delete_withdraw .super_data
wm title .user_data "ISEM: User Data"
make_delete_withdraw .user_data


###############################################################################
# a simple view of the registers
###############################################################################

toplevel .gpregs
#bind .gpregs <Map> update_display
wm withdraw .gpregs
wm title .gpregs "ISEM: Registers"
make_delete_withdraw .gpregs

#------------------------------------------------------------------------------
# The dismiss and help buttons
#------------------------------------------------------------------------------
frame .gpregs.buttons
pack .gpregs.buttons -side bottom -fill x

button .gpregs.buttons.dismiss -text "Dismiss" -command "wm withdraw .gpregs" \
     -bg yellow
button .gpregs.buttons.update -text "Update" -bg lightgreen \
    -command "update_display 1"
pack .gpregs.buttons.dismiss .gpregs.buttons.update -side left
button .gpregs.buttons.help -text "Help" -bg red \
    -command "goto_help_label {Register window} 1"
pack .gpregs.buttons.help -side right

#------------------------------------------------------------------------------
# display the processor state registers
#------------------------------------------------------------------------------
frame .gpregs.pstate
pack .gpregs.pstate -side top -expand 1 -fill x

frame .gpregs.pstate.y
frame .gpregs.pstate.psr
frame .gpregs.pstate.wim
frame .gpregs.pstate.tbr

pack .gpregs.pstate.y -side left -anchor sw
pack .gpregs.pstate.psr -side left -expand 1
pack .gpregs.pstate.wim -side left -anchor s -expand 1
pack .gpregs.pstate.tbr -side left

label .gpregs.pstate.y.lab -font $gpreg_font -text Y -bg grey75
pack .gpregs.pstate.y.lab -side left
button .gpregs.pstate.y.val -font $gpreg_font -textvariable y -relief groove \
    -width 7 -command "edit_reg y" -bg lightblue
pack .gpregs.pstate.y.val -side left

label .gpregs.pstate.wim.lab -font $gpreg_font -text WIM
pack .gpregs.pstate.wim.lab -side left
button .gpregs.pstate.wim.val -font $gpreg_font -textvariable wim \
    -relief sunken
pack .gpregs.pstate.wim.val -side left

frame .gpregs.pstate.psr.labs
frame .gpregs.pstate.psr.vals
pack .gpregs.pstate.psr.labs .gpregs.pstate.psr.vals -side top

frame .gpregs.pstate.tbr.labs
frame .gpregs.pstate.tbr.vals
pack .gpregs.pstate.tbr.labs .gpregs.pstate.tbr.vals -side top

label .gpregs.pstate.psr.labs.blank -width 3 -font $gpreg_font -text " "
label .gpregs.pstate.psr.labs.impl -width 4 -font $gpreg_font -text impl
label .gpregs.pstate.psr.labs.ver -width 3 -font $gpreg_font -text ver
label .gpregs.pstate.psr.labs.n -width 1 -font $gpreg_font -text n
label .gpregs.pstate.psr.labs.z -width 1 -font $gpreg_font -text z
label .gpregs.pstate.psr.labs.v -width 1 -font $gpreg_font -text v
label .gpregs.pstate.psr.labs.c -width 1 -font $gpreg_font -text c
label .gpregs.pstate.psr.labs.res -width 3 -font $gpreg_font -text res
label .gpregs.pstate.psr.labs.ec -width 2 -font $gpreg_font -text EC
label .gpregs.pstate.psr.labs.ef -width 2 -font $gpreg_font -text EF
label .gpregs.pstate.psr.labs.pil -width 4 -font $gpreg_font -text PIL
label .gpregs.pstate.psr.labs.s -width 1 -font $gpreg_font -text S
label .gpregs.pstate.psr.labs.ps -width 2 -font $gpreg_font -text PS
label .gpregs.pstate.psr.labs.et -width 2 -font $gpreg_font -text ET
label .gpregs.pstate.psr.labs.cwp -width 5 -font $gpreg_font -text CWP
pack .gpregs.pstate.psr.labs.blank .gpregs.pstate.psr.labs.impl \
    .gpregs.pstate.psr.labs.ver .gpregs.pstate.psr.labs.n \
    .gpregs.pstate.psr.labs.z .gpregs.pstate.psr.labs.v \
    .gpregs.pstate.psr.labs.c .gpregs.pstate.psr.labs.res \
    .gpregs.pstate.psr.labs.ec .gpregs.pstate.psr.labs.ef \
    .gpregs.pstate.psr.labs.pil .gpregs.pstate.psr.labs.s \
    .gpregs.pstate.psr.labs.ps .gpregs.pstate.psr.labs.et \
    .gpregs.pstate.psr.labs.cwp -side left

label .gpregs.pstate.psr.vals.lab -width 3 -font $gpreg_font -text PSR
label .gpregs.pstate.psr.vals.impl -width 4 -font $gpreg_font -relief sunken
label .gpregs.pstate.psr.vals.ver -width 3 -font $gpreg_font -relief sunken
label .gpregs.pstate.psr.vals.n -width 1 -font $gpreg_font \
    -textvariable psr_n -relief sunken
label .gpregs.pstate.psr.vals.z -width 1 -font $gpreg_font \
    -textvariable psr_z -relief sunken
label .gpregs.pstate.psr.vals.v -width 1 -font $gpreg_font \
    -textvariable psr_v -relief sunken
label .gpregs.pstate.psr.vals.c -width 1 -font $gpreg_font \
    -textvariable psr_c -relief sunken
label .gpregs.pstate.psr.vals.res -width 3 -font $gpreg_font -relief sunken
label .gpregs.pstate.psr.vals.ec -width 2 -font $gpreg_font \
    -textvariable psr_ec -relief sunken
label .gpregs.pstate.psr.vals.ef -width 2 -font $gpreg_font \
    -textvariable psr_ef -relief sunken
label .gpregs.pstate.psr.vals.pil -width 4 -font $gpreg_font \
    -textvariable psr_pil -relief sunken
label .gpregs.pstate.psr.vals.s -width 1 -font $gpreg_font \
    -textvariable psr_s -relief sunken
label .gpregs.pstate.psr.vals.ps -width 2 -font $gpreg_font \
    -textvariable psr_ps -relief sunken
label .gpregs.pstate.psr.vals.et -width 2 -font $gpreg_font \
    -textvariable psr_et -relief sunken
label .gpregs.pstate.psr.vals.cwp -width 5 -font $gpreg_font \
    -textvariable psr_cwp -relief sunken
pack .gpregs.pstate.psr.vals.lab .gpregs.pstate.psr.vals.impl \
    .gpregs.pstate.psr.vals.ver .gpregs.pstate.psr.vals.n \
    .gpregs.pstate.psr.vals.z .gpregs.pstate.psr.vals.v \
    .gpregs.pstate.psr.vals.c .gpregs.pstate.psr.vals.res \
    .gpregs.pstate.psr.vals.ec .gpregs.pstate.psr.vals.ef \
    .gpregs.pstate.psr.vals.pil .gpregs.pstate.psr.vals.s \
    .gpregs.pstate.psr.vals.ps .gpregs.pstate.psr.vals.et \
    .gpregs.pstate.psr.vals.cwp -side left

label .gpregs.pstate.tbr.labs.blank -font $gpreg_font -text " " -width 3
label .gpregs.pstate.tbr.labs.tba -font $gpreg_font -text TBA -width 5
label .gpregs.pstate.tbr.labs.tt -font $gpreg_font -text TT -width 2
label .gpregs.pstate.tbr.labs.blank3 -font $gpreg_font -text " " -width 1
pack .gpregs.pstate.tbr.labs.blank .gpregs.pstate.tbr.labs.tba \
    .gpregs.pstate.tbr.labs.tt .gpregs.pstate.tbr.labs.blank3 -side left

set tbr_tba 00000
set tbr_tt 00
label .gpregs.pstate.tbr.vals.lab -font $gpreg_font -text TBR
label .gpregs.pstate.tbr.vals.tba -font $gpreg_font -textvariable tbr_tba \
    -relief sunken
label .gpregs.pstate.tbr.vals.tt -font $gpreg_font -textvariable tbr_tt \
    -relief sunken
label .gpregs.pstate.tbr.vals.blank3 -font $gpreg_font -text 0 -relief sunken
pack .gpregs.pstate.tbr.vals.lab .gpregs.pstate.tbr.vals.tba \
    .gpregs.pstate.tbr.vals.tt .gpregs.pstate.tbr.vals.blank3 -side left

#------------------------------------------------------------------------------
# display the program counter, next program counter and instruction
#------------------------------------------------------------------------------
frame .gpregs.instr
pack .gpregs.instr -side top -fill x

frame .gpregs.instr.pc
frame .gpregs.instr.npc
pack .gpregs.instr.pc -side left
pack .gpregs.instr.npc -side left -expand 1

label .gpregs.instr.pc.lab -font $gpreg_font -text PC -bg grey75
pack .gpregs.instr.pc.lab -side left
button .gpregs.instr.pc.val -font $gpreg_font -textvariable pc -relief groove \
    -width 7 -command "edit_reg pc"  -bg lightblue
pack .gpregs.instr.pc.val -side left

label .gpregs.instr.npc.lab -font $gpreg_font -text nPC -bg grey75
pack .gpregs.instr.npc.lab -side left
label .gpregs.instr.npc.val -font $gpreg_font -textvariable npc \
    -relief sunken -width 11
pack .gpregs.instr.npc.val -side left

frame .gpregs.instr.val
pack .gpregs.instr.val -side left

label .gpregs.instr.val.label -font $gpreg_font -text "Next Instr." -bg grey75
label .gpregs.instr.val.annul -font $gpreg_font -width 7 -bg grey75 \
    -textvariable instr_annul
frame .gpregs.instr.val.instr -relief sunken -bd 2
label .gpregs.instr.val.instr.lab -anchor w -font $gpreg_font \
    -textvariable instr_lab -width 9
label .gpregs.instr.val.instr.op -anchor w -font $gpreg_font \
    -textvariable instr_op -width 9
label .gpregs.instr.val.instr.opnds -anchor w -font $gpreg_font \
    -textvariable instr_opnds -width 20

pack .gpregs.instr.val.label .gpregs.instr.val.annul .gpregs.instr.val.instr \
    .gpregs.instr.val.instr.lab .gpregs.instr.val.instr.op \
    .gpregs.instr.val.instr.opnds -side left

# register names

#------------------------------------------------------------------------------
# build the register display
#------------------------------------------------------------------------------
set reg 0
frame .gpregs.regs
pack .gpregs.regs -side top

for {set row 0} {$row < 4} {incr row 1} {
    label .gpregs.regs.lab$row -font $gpreg_font -width 9 -anchor e -bg grey75
    grid .gpregs.regs.lab$row -row $row -column 0
    for {set col 1} {$col < 9} {incr col 1} {
	set r$reg 0x00000000
	button .gpregs.regs.$reg -font $gpreg_font -relief groove \
	    -width 7 -textvariable r$reg -command "edit_reg r$reg" \
	    -bg lightblue
	grid .gpregs.regs.$reg -row $row -column $col
	incr reg 1
    }
}

proc set_reg_view_window {} {
    global reg_view rname
    set reg_view window

    set rname(0) "%g0";  set rname(1) "%g1";  set rname(2) "%g2"
    set rname(3) "%g3";  set rname(4) "%g4";  set rname(5) "%g5"
    set rname(6) "%g6";  set rname(7) "%g7"
    set rname(8) "%o0";  set rname(9) "%o1";  set rname(10) "%o2"
    set rname(11) "%o3"; set rname(12) "%o4"; set rname(13) "%o5"
    set rname(14) "%sp"; set rname(15) "%o7"
    set rname(16) "%l0"; set rname(17) "%l1"; set rname(18) "%l2"
    set rname(19) "%l3"; set rname(20) "%l4"; set rname(21) "%l5"
    set rname(22) "%l6"; set rname(23) "%l7"
    set rname(24) "%i0"; set rname(25) "%i1"; set rname(26) "%i2"
    set rname(27) "%i3"; set rname(28) "%i4"; set rname(29) "%i5"
    set rname(30) "%fp"; set rname(31) "%i7"

    for {set row 0} {$row < 4} {incr row 1} {
	.gpregs.regs.lab$row configure \
	    -text [format "%s-%s" $rname([expr $row*8]) \
		       $rname([expr $row*8 + 7])]
    }
}

proc set_reg_view_regular {} {
    global reg_view rname
    set reg_view regular

    for {set i 0} {$i < 32} {incr i 1} {
	set rname($i) [format "%%r%d" $i]
    }

    for {set row 0} {$row < 4} {incr row 1} {
	.gpregs.regs.lab$row configure \
	    -text [format "%s-%s" $rname([expr $row*8]) \
		       $rname([expr $row*8 + 7])]
    }
}

set_reg_view_regular

#------------------------------------------------------------------------------
# build the register edit area
#  the register edit area uses two global variables -- ed_reg and ed_val -- 
#  to keep track of which register is being edited and what it's new value
#  is supposed to be.
#------------------------------------------------------------------------------
frame .gpregs.edit
pack .gpregs.edit -side top

label .gpregs.edit.lab -font $gpreg_font -text "Edit "
label .gpregs.edit.reg -width 10 -textvariable ed_reg_labels -anchor w
entry .gpregs.edit.val -font $gpreg_font -width 20 -textvariable ed_val \
    -relief sunken -width 11
bind .gpregs.edit.val <Return> set_edreg
button .gpregs.edit.set -text Set -command set_edreg
pack .gpregs.edit.lab .gpregs.edit.reg .gpregs.edit.val .gpregs.edit.set \
    -side left

proc edit_reg {reg} {
    upvar \#0 $reg r
    global ed_reg ed_val ed_reg_labels
    global rname

    if { $reg != "pc" && $reg != "npc" && $reg != "y"  } {
        set ed_reg_labels [format {%s} \
	    $rname([string range $reg 1 end])]
    } else {
	set ed_reg_labels [format {%%%s} $reg]
    }
    set ed_reg $reg
    set ed_val $r
}

proc set_edreg {} {
    global ed_reg ed_val proc_mode
    upvar \#0 $ed_reg r

    if { $ed_reg != "r0" } {
	set r [convert_val $ed_val $proc_mode $r]
	isem_reg set $ed_reg $r
    } else {
	set ed_val 0x00000000
    }
}

# Tue Feb 13 17:41:04 2001 Ackley: use 'scan' just for number format
# checking, not for its results.  On Linux anyway, scan %i (now)
# follows the strtol semantics (rather than strtoul), and produces
# 0x7fffffff when given 0xffffffff.  Tcl's native number interpreter,
# though, apparently (still) does not, so just use $val.

proc convert_val {val mode default} {
    if {[scan $val %i ignore] == 1} {    
	set value [format {0x%.8x} $val] 
    } else {
	upvar \#0 [format {%s_syms} $mode] syms
	if { [info exists syms($val)] } {
	    set value [lindex $syms($val) 0]
	} else {
	    set value $default
	}
    }
    return $value
}

set ed_reg r0
set ed_val 0x00000000

###############################################################################
# supervisor and user symbols
###############################################################################
set super_sort name
set user_sort name

foreach mode {super user} {
    set top [format {.%s_syms} $mode]

    toplevel $top
    wm withdraw $top

    frame $top.file -relief groove -bd 4
    frame $top.syms
    frame $top.sort
    frame $top.buttons
    pack $top.file -fill x
    pack $top.syms $top.sort -side top
    pack $top.buttons -side top -fill x

    label $top.file.label -text "File:"
    set file_var [format {%s_file} $mode]
    label $top.file.name -textvariable $file_var -anchor w
    pack $top.file.label -side left
    pack $top.file.name -side left -fill x -expand 1

    frame $top.syms.syms
    label $top.syms.syms.lab -text Symbol
    listbox $top.syms.syms.syms -font $sym_font -relief sunken \
	-yscrollcommand "$top.syms.scroll.bar set"
    pack $top.syms.syms.lab $top.syms.syms.syms -side top

    frame $top.syms.value
    label $top.syms.value.lab -text Value
    listbox $top.syms.value.vals -font $sym_font -relief sunken
    pack $top.syms.value.lab $top.syms.value.vals -side top
    frame $top.syms.scroll
    label $top.syms.scroll.text -text ""
    scrollbar $top.syms.scroll.bar -command scroll_$mode -relief ridge
    pack $top.syms.scroll.text -side top
    pack $top.syms.scroll.bar -side top -expand 1 -fill y

    pack $top.syms.syms $top.syms.value -side left
    pack $top.syms.scroll -side left -fill y

    label $top.sort.label -text "Sort by"
    set sort_var [format {%s_sort} $mode]
    radiobutton $top.sort.name -text Name -value name \
	-variable $sort_var -command "show_syms $mode"
    radiobutton $top.sort.value -text Value -value value \
	-variable $sort_var -command "show_syms $mode"
    pack $top.sort.label $top.sort.name $top.sort.value -side left

    button $top.buttons.dismiss -text "Dismiss" -command "wm withdraw $top" \
	 -bg yellow
    button $top.buttons.help -text "Help" -bg red \
	-command "goto_help_label {Symbol window} 1"
    pack $top.buttons.dismiss -side left
    pack $top.buttons.help -side right
}

wm title .super_syms "ISEM: Supervisor Symbols"
make_delete_withdraw .super_syms
wm title .user_syms "ISEM: User Symbols"
make_delete_withdraw .user_syms

###############################################################################
# supervisor and user breakpoints
###############################################################################

foreach mode {user super} {
    set top [format {.%s_break} $mode]
    toplevel $top
    wm withdraw $top

    frame $top.bp
    listbox $top.bp.labs -relief sunken -yscrollcommand "$top.bp.scroll set"
    listbox $top.bp.vals -relief sunken -yscrollcommand "$top.bp.scroll set"
    scrollbar $top.bp.scroll -command "scroll_bps $mode"
    pack $top.bp.labs -side left -fill x -expand 1
    pack $top.bp.vals -side left -fill x -expand 1
    pack $top.bp.scroll -side left -fill y

    set break_var [format {%s_break_var} $mode]
    global $break_var

    frame $top.edit
    button $top.edit.clear -text "Clear All" -command "clear_breaks $mode"
    button $top.edit.del -text Delete -command "rmv_break $break_var $mode"
    button $top.edit.add -text Add -command "set_bpoint $break_var $mode"
    entry $top.edit.val -width 20 -textvariable $break_var -relief sunken
    bind $top.edit.val <Return> "set_bpoint $break_var $mode"
    pack $top.edit.clear $top.edit.del -side left
    pack $top.edit.val $top.edit.add -side right

    frame $top.buttons
    button $top.buttons.dismiss -text "Dismiss" -command "wm withdraw $top" \
	 -bg yellow
    button $top.buttons.help -text "Help" -bg red \
	-command "goto_help_label {Breakpoint window} 1"
    pack $top.buttons.dismiss -side left
    pack $top.buttons.help -side right

    pack $top.bp -side top -fill x -expand 1
    pack $top.edit -side top
    pack $top.buttons -side top -fill x -expand 1
}

proc scroll_bps {mode top} {
    set base [format {.%s_break.bp} $mode]
    $base.vals yview $top
    $base.labs yview $top
}

wm title .user_break "User Breakpoints"
make_delete_withdraw .user_break
wm title .super_break "Supervisor Breakpoints"
make_delete_withdraw .super_break

###############################################################################
# ---- devices -----
###############################################################################

#------------------------------------------------------------------------------
# the device run list
#------------------------------------------------------------------------------
set dev_run_list {}
proc run_devices {} {
    global dev_run_list

    foreach dev_proc $dev_run_list {
	$dev_proc
    }
}

proc add_run {dev_proc} {
    global dev_run_list

    lappend dev_run_list $dev_proc
}

proc rmv_run {dev_proc} {
    global dev_run_list

    set index [lsearch -exact $dev_run_list $dev_proc]
    if { $index != -1 } {
	set dev_run_list [lreplace $dev_run_list $index $index]
    }    
}

#------------------------------------------------------------------------------
# the gx device
#------------------------------------------------------------------------------
proc gx {op addr bytemask value} {

    if {$op == "read"} {
	return [.gx.display read]
    } else {
	.gx.display write $value $addr
    }
}

isem_device gx $gx_address $gx_mode

#------------------------------------------------------------------------------
# the console device
#------------------------------------------------------------------------------
set in_count 0

proc console {op addr bytemask value} {
    global in_count

    if {$op == "write"} {
	.conout.text.text configure -state normal
	.conout.text.text insert end [format "%c" $value]
	.conout.text.text yview -pickplace end
	.conout.text.text configure -state disabled
    } else {
	set cur_index [.conin.text.text index "1.0 + $in_count chars"]
	scan $cur_index %i cur_line 
	
	set end_index [.conin.text.text index end]
	scan $end_index "%i.%i" last_line last_char
	
	if {$last_char == "0"} {
	    incr last_line -1
	}
	if {$last_line == $cur_line} {
	    return 0xffffffff
	} else {
	    incr in_count 1
	    scan [.conin.text.text get $cur_index] %c res
	    return $res
	}
    }
}

isem_device console $console_address $console_mode

#------------------------------------------------------------------------------
# the halt device
#------------------------------------------------------------------------------
proc halt {op addr bytemask value} {
    global stop_run proc_state

    set stop_run 1
}

isem_device halt $halt_address $halt_mode

#------------------------------------------------------------------------------
# the timer device
#------------------------------------------------------------------------------
set timer_period 0x00000000
set timer_count 0x00000000
set timer_interrupt 0

proc timer_tick {} {
    global timer_period timer_count
     if {$timer_period != 0} {
	set timer_count [format {0x%.8x} [expr $timer_count+1]]
	if {$timer_count == $timer_period} {
	    timer_interrupt 1
	    set timer_count 0x00000000
	}
    }
}

proc timer_interrupt {state} {
    global timer_interrupt timer_int_level

    set timer_interrupt $state
    isem_interrupt $timer_int_level $state
}

proc timer {op addr bytemask value} {
    global timer_period

    #puts [format "uartcall %s %d %d %d" $op $addr $bytemask $value]
    timer_interrupt 0
    if {$op == "write"} {
	set_timer_period $value
    } else {
        scan $timer_count 0x%x woof
        return $woof
    }
}

proc set_timer_period {period} {
    global timer_period timer_count

    set old_period $timer_period
    set timer_period [format {0x%.8x} $period]
    set timer_count 0x00000000
    if {$timer_period != 0 && $old_period == 0} {
	add_run timer_tick
    }
    if {$timer_period == 0 && $old_period != 0} {
	rmv_run timer_tick
    }
}

isem_device timer $timer_address $timer_mode

#-----------------------------------------------------------------------------
# the UART device
#-----------------------------------------------------------------------------
#.uart.keybd.txout.text tag configure uart_curr_tx -background blue\
#    -foreground white
#.uart.keybd.rxin.text tag configure uart_curr_rx -background blue\
#    -foreground white

proc uart_interrupt {state} {
    global UART_interrupt uart_int_level
    set UART_interrupt $state
    isem_interrupt $uart_int_level $state
}

proc uart_tx_tick {} {
    global UART_Tx_count UART_TXscale
    global UART_stat UART_ctrl
    global UART_sending UART_TXReg

    incr UART_Tx_count -1
    if { $UART_Tx_count == 0 } {
	.uart.keybd.txout.text configure -state normal
	if { $UART_sending > 126 } {
	    .uart.keybd.txout.text insert end [format "\\x%.2x" $UART_sending]
	} else {
	    .uart.keybd.txout.text insert end [format "%c" $UART_sending]
	}
	.uart.keybd.txout.text yview -pickplace end
	.uart.keybd.txout.text configure -state disabled
	
	if { [string compare $UART_TXReg "****"] != 0 } {
	    set UART_sending $UART_TXReg
	    set UART_TXReg "****"
	    set UART_stat [format 0x%.2x [expr $UART_stat | 1]]
	    .uart.reg.stat.bit0 configure -text "1"
	    if { $UART_ctrl & 1 } {
		uart_interrupt 1
	    }
	    set UART_Tx_count [expr ($UART_ctrl >> 2) * $UART_TXscale]
	} else {
	    set UART_sending "****"
	}
    }
}

proc uart_rx_tick {} {
    global UART_Rx_count UART_src_count UART_src
    global UART_RXReg UART_receiving
    global UART_stat UART_ctrl

    incr UART_Rx_count -1
    if { $UART_Rx_count == 0 } {
	if { [string compare $UART_RXReg "****"] == 0 } {
	    if { $UART_ctrl & 2 } {
		uart_interrupt 1
	    }
	} else {
	    # overrun error
	    set UART_stat [format 0x%.2x [expr $UART_stat | 4]]
	    .uart.reg.stat.bit2 configure -text "1"
	}
	.uart.reg.stat.bit1 configure -text "1"
	set UART_stat [format 0x%.2x [expr $UART_stat | 2]]
	set UART_RXReg $UART_receiving
	set UART_receiving "****"
	if { ($UART_src_count == 0) && ($UART_src != "none") } {
	    uart_getch
	}
    }
}

proc uart_src_tick {} {
    global UART_src_count UART_src UART_receiving

    incr UART_src_count -1
    if { ($UART_src_count == 0) && ($UART_src != "none") && ($UART_receiving == "****") } {
	uart_getch
    }
}

proc uart_getch {} {
    global UART_src UART_src_count
    global UART_srate
    global UART_ctrl
    global UART_RXscale UART_Rx_count
    global UART_receiving
    global UART_inchar

    if { $UART_src == "key" } {
	set cur_index [.uart.keybd.rxin.text index "1.0 + $UART_inchar chars"]
	scan $cur_index %i cur_line 
	
	set end_index [.uart.keybd.rxin.text index end]

	if { [string compare $cur_index $end_index] == 0 } {
	    # out of characters
	    set UART_src none
	} else {
	    incr UART_inchar
	    scan [.uart.keybd.rxin.text get $cur_index] %c res
	    set UART_src_count $UART_srate
	    set UART_receiving [format "0x%.2x" $res]
	    set UART_Rx_count [expr ($UART_ctrl>>2) * $UART_RXscale]
	}
    } elseif { $UART_src == "file" } {
	global UART_file
	set ch [read $UART_file 1]
	if { [string compare $ch ""] == 0 } {
	    # out of characters
	    set UART_src none
	} else {
	    scan $ch %c res
	    set UART_src_count $UART_srate
	    set UART_receiving [format "0x%.2x" $res]
	    set UART_Rx_count [expr ($UART_ctrl>>2) * $UART_RXscale]
	}
    } elseif { $UART_src == "rand_file" } {
	global UART_file
	gets $UART_file line
	set stat [scan $line "%d.%1s" count ch]
	if { $stat == 0 } {
	    # out of characters
	    set UART_src none
	} else {
	    if { $stat == 1 } {
		if { [string index $line [expr [string length $line] - 1]] == " " } {
		    set res 32
		} else {
		    set res 10
		}
	    } else {
		scan $ch %c res
	    }
	    puts "uart returning $res"
	    set UART_src_count $count
	    set UART_receiving [format "0x%.2x" $res]
	    set UART_Rx_count [expr ($UART_ctrl>>2) * $UART_RXscale]
	}
    }
}
    
proc uart_timer {}  {
    global UART_Tx_count UART_Rx_count UART_src_count
    global UART_running

    if { $UART_Tx_count != 0 } {
	uart_tx_tick
    } 
    if { $UART_Rx_count != 0 } {
	uart_rx_tick
    } 
    if { $UART_src_count != 0 } {
	uart_src_tick
    }
    if { ($UART_src_count==0) && ($UART_Tx_count==0) && ($UART_Rx_count==0) } {
	set UART_running 0
	rmv_run uart_timer
    }
}

proc uart {op addr bytemask value} {
    global UART_TXReg UART_sending UART_RXReg
    global UART_stat UART_ctrl
    global UART_Tx_count UART_TXscale
    global UART_running

    set uart_reg_addr [expr $addr & 0xf]
    switch -exact -- $uart_reg_addr {
	0 {
	    if {[string compare $op write] == 0} {
		set UART_ctrl $value
		uart_disp_reg creg $UART_ctrl
	    } else {
		scan $UART_stat 0x%x uart_byte
		uart_interrupt 0
		# clear the overrun bit if it's set
		if { $UART_stat & 4 } {
		    set UART_stat [format 0x%.2x [expr $UART_stat & 0xfb]]
		    .Uart.reg.stat.bit2 configure -text "0"
		}
		return $uart_byte
	    }
	}	
	4 {
	    if { [string compare $op write] == 0 } {
		if { [string compare $UART_sending "****"] == 0 } {
		    set UART_sending [format 0x%.2x $value]
		    set UART_Tx_count [expr ($UART_ctrl >> 2) * $UART_TXscale]
		    if { $UART_running == 0 } {
			set UART_running 1
			add_run uart_timer
		    }
		} else {
		    set UART_TXReg [format 0x%.2x $value]
		    set UART_stat [format 0x%.2x [expr $UART_stat & 0xfe]]
		    .uart.reg.stat.bit0 configure -text "0"
		}
	    } else {
		if { [string compare $UART_RXReg "****"] != 0 } {
		    scan $UART_RXReg 0x%x uart_byte
		    set UART_RXReg "****"
		    set UART_stat [format 0x%.2x [expr $UART_stat & 0xfd]]
		    .uart.reg.stat.bit1 configure -text "0"
		    return $uart_byte
		} else {
		    return 0
		}
	    }
	}	
    }
}
##################################################################

proc uart_tx_and_rx {}  {
    global UartRxInput UartTxOutput 
    global UartRxInFileID UartTxOutFileID 
    global UartTXReg UART_RXReg
    global UartRxIndex UartRxIndexCount
    global UART_stat UartMask
    
    set uartbitmask0 $UartMask
    set uartbitmask1 [expr $UartMask << 1]
    set uartbitmask2 [expr $UartMask << 2]
    
    #  if something in TX register, then
    #  if txout = file, write it to file and set status bit
    #  elseif txout = discard, set status bit
    #  else do nothing
    #  
    #  if nothing in RX register, then
    #  if rxin = file || keyboard, read it from textwindow, put in RXwindow, 
    #  and set status bit
    #  else do nothing
    
    if {[expr $UART_stat & $uartbitmask0] == 0}  {
	if {[string compare $UartTxOutput file] == 0}  {
	    set uart_char [format "%c" $UartTXReg]
	    puts -nonewline $UartTxOutFileID $uart_char 
	    set UART_stat [expr $UART_stat ^ $uartbitmask0]
	} elseif {[string compare $UartTxOutput discard] == 0}  {
	    set UART_stat [expr $UART_stat ^ $uartbitmask0]
	}
    }
    
    if {[expr $UART_stat & $uartbitmask1] == 0}  {
	if {[string compare $UartRxInput file] == 0 || \
		[string compare $UartRxInput keyboard] == 0} {
	    .uart.keybd.rxin.text tag remove uart_curr_rx \
		"$UartRxIndex + $UartRxIndexCount chars"
	    #set UartRxIndex {[$UartRxIndex + 1 chars]}
	    set UartRxIndexCount [expr $UartRxIndexCount + 1]
	    set uart_char [.uart.keybd.rxin.text get \
			       "$UartRxIndex + $UartRxIndexCount chars"]
	    .uart.keybd.rxin.text tag add uart_curr_rx \
		"$UartRxIndex + $UartRxIndexCount chars"
	    scan $uart_char "%c" uart_temp
	    .uart.line1.regRX.value config -text [format "%#x" $uart_temp]
	    set UART_RXReg [format "%#x" $uart_temp]
	    set UART_stat [expr $UART_stat ^ $uartbitmask1]
	}
    }
}

proc uart_clear {} {
    global UartTxInput UartRxInput UartTxOutput UartRxOutput 
    global UartTxInFileID UartRxInFileID UartTxOutFileID UartRxOutFileID
    global UartTXReg UART_RXReg
    global UART_stat UART_ctrl UartMask
    global UartTxIndex UartTxIndexCount
    
    set uartbitmask0 $UartMask
    set uartbitmask1 [expr $UartMask << 1]
    set uartbitmask2 [expr $UartMask << 2]
    set uartbitmask3 [expr $UartMask << 3]
    set uartbitmask4 [expr $UartMask << 4]
    set uartbitmask5 [expr $UartMask << 5]
    
    #  if nothing in TX register && TX interrupt enabled, then
    #  if txin = file || keyboard, read it from textwindow, put in TXwindow,
    #      and set status bit
    #  else do nothing
    #  
    #  if something in RX register && RX interrupt enabled, then
    #  if rxout = file, write it to file and set status bit
    #elseif rxout = discard, set status bit
    #  else do nothing
    
    # was it a tx interrupt ?
    if {[expr $UART_stat & $uartbitmask0] && [expr $UART_ctrl & $uartbitmask0]} {
	if {[string compare $UartTxInput file] == 0 || \
		[string compare $UartTxInput keyboard] == 0}  {
	    .uart.keybd.txout.text tag remove uart_curr_tx \
		"$UartTxIndex + $UartTxIndexCount chars"
	    set UartTxIndexCount [expr $UartTxIndexCount + 1]
	    set uart_char [.uart.keybd.txout.text get \
			       "$UartTxIndex + $UartTxIndexCount chars"]
	    .uart.keybd.txout.text tag add uart_curr_tx \
		"$UartTxIndex + $UartTxIndexCount chars"
	    scan $uart_char "%c" uart_temp
	    .uart.line1.regTX.value config -text [format "%#x" $uart_temp]
	    set UartTXReg [format "%#x" $uart_temp]
	    set UART_stat [expr $UART_stat ^ $uartbitmask0]
	}
    }
    
    # was it a rx interrupt?
    if {[expr $UART_stat & $uartbitmask1] > 0 && \
	    [expr $UART_ctrl & $uartbitmask1] > 0} {
	if {[string compare $UartRxOutput file] == 0}  {
	    set uart_char [format "%c" $UART_RXReg]
	    puts -nonewline $UartRxOutFileID $uart_char 
	    set UART_stat [expr $UART_stat ^ $uartbitmask1]
	} elseif {[string compare $UartRxOutput discard] == 0}  {
	    set UART_stat [expr $UART_stat ^ $uartbitmask1]
	} else {}
    }
}

proc uart_ovr_check {}  {
    global UartTxInput UartRxInput UartTxOutput UartRxOutput 
    global UartTxInFileID UartRxInFileID UartTxOutFileID UartRxOutFileID
    global UartTXReg UART_RXReg
    global UART_stat UART_ctrl UartMask
    global UartRxIndex UartRxIndexCount
    
    set uartbitmask1 [expr $UartMask << 1]
    
    if {[expr $UART_stat & $uartbitmask1] > 0}  {
	if {[string compare $UartRxInput file] == 0 || \
		[string compare $UartRxInput keyboard] == 0} {
	    .uart.keybd.rxin.text tag remove uart_curr_rx \
		"$UartRxIndex + $UartRxIndexCount chars"
	    set UartRxIndexCount [expr $UartRxIndexCount + 1]
	    set uart_char [.uart.keybd.rxin.text get \
			       "$UartRxIndex + $UartRxIndexCount chars"]
	    .uart.keybd.rxin.text tag add uart_curr_rx \
		"$UartRxIndex + $UartRxIndexCount chars"
	    scan $uart_char "%c" uart_temp
	    .uart.line1.regRX.value config -text [format "%#x" $uart_temp]
	    set UART_RXReg [format "%#x" $uart_temp]
	    set UART_stat [expr $UART_stat ^ $uartbitmask1]
	}
    }
}

isem_device uart $uart_address $uart_mode


###############################################################################
# this is where it starts!
###############################################################################

set total_cycles 0

isem_debug "Booting supervisor from $rom"
set load_mode super

set stop_run 0
set step_super 0
set update_super 0
set step_user 1
set update_user 1
update

if { "ok" == [load_file $rom] } {
    set_status_message "Running supervisor initialization..."
    driver
    set_state_regs
    set_gp_regs
    set_status_message "tk ISEM version Release $release ready"
} else {
    update
}

.conout.text.text yview -pickplace 0

set load_mode user
.loadfile.user.load configure -state normal
.loadfile.super.load configure -state normal
.run_stop configure -text Run -command run_button

.uprate set 1