From 0ad673fed3b0008e71506797e6cd89d851aeff4c Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Wed, 20 Apr 2011 12:23:06 -0700 Subject: [PATCH] Separated Pcap-VMS from the rest of the simh source tree. This is being done since the plan going forward (in the primary descrip.mms and the Visual Studio Projects) is to local pcap components (VMS and Windows) one level up from the simh directory. The PCAP-VMS components are presumed (by this procedure) to be located in a directory at the same level as the directory containing the simh source files. For example, if these exist here: []descrip.mms []scp.c etc. Then the following should exist: [-.PCAP-VMS]BUILD_ALL.COM [-.PCAP-VMS.PCAP-VCI] [-.PCAP-VMS.PCAPVCM] etc. --- .gitignore | 1 + 0readme_30.txt | 166 - 0readme_ethernet.txt | 162 - ALTAIR/altair.txt | 211 -- ALTAIR/altair_cpu.c | 1189 ------- ALTAIR/altair_defs.h | 42 - ALTAIR/altair_dsk.c | 366 --- ALTAIR/altair_sio.c | 258 -- ALTAIR/altair_sys.c | 302 -- AltairZ80/altairZ80.txt | 895 ----- AltairZ80/altairZ80_cpu.c | 5605 -------------------------------- AltairZ80/altairZ80_defs.h | 90 - AltairZ80/altairZ80_dsk.c | 569 ---- AltairZ80/altairZ80_sio.c | 1105 ------- AltairZ80/altairZ80_sys.c | 782 ----- AltairZ80/altairz80_hdsk.c | 386 --- GRI/gri_cpu.c | 890 ----- GRI/gri_defs.h | 221 -- GRI/gri_doc.txt | 321 -- GRI/gri_stddev.c | 394 --- GRI/gri_sys.c | 582 ---- H316/h316_cpu.c | 1088 ------- H316/h316_defs.h | 144 - H316/h316_doc.txt | 320 -- H316/h316_lp.c | 261 -- H316/h316_stddev.c | 539 --- H316/h316_sys.c | 346 -- HP2100/hp2100_cpu.c | 2602 --------------- HP2100/hp2100_defs.h | 269 -- HP2100/hp2100_diag.txt | 171 - HP2100/hp2100_doc.txt | 945 ------ HP2100/hp2100_dp.c | 796 ----- HP2100/hp2100_dq.c | 720 ---- HP2100/hp2100_dr.c | 422 --- HP2100/hp2100_fp.c | 312 -- HP2100/hp2100_ipl.c | 476 --- HP2100/hp2100_lps.c | 176 - HP2100/hp2100_lpt.c | 194 -- HP2100/hp2100_ms.c | 672 ---- HP2100/hp2100_mt.c | 478 --- HP2100/hp2100_mux.c | 704 ---- HP2100/hp2100_stddev.c | 704 ---- HP2100/hp2100_sys.c | 580 ---- I1401/i1401_cd.c | 282 -- I1401/i1401_cpu.c | 1563 --------- I1401/i1401_dat.h | 57 - I1401/i1401_defs.h | 278 -- I1401/i1401_doc.txt | 503 --- I1401/i1401_dp.c | 555 ---- I1401/i1401_iq.c | 155 - I1401/i1401_lp.c | 233 -- I1401/i1401_mt.c | 329 -- I1401/i1401_sys.c | 339 -- I1620/i1620_cd.c | 405 --- I1620/i1620_cpu.c | 1884 ----------- I1620/i1620_defs.h | 221 -- I1620/i1620_doc.txt | 518 --- I1620/i1620_dp.c | 463 --- I1620/i1620_fp.c | 388 --- I1620/i1620_lp.c | 316 -- I1620/i1620_pt.c | 436 --- I1620/i1620_sys.c | 491 --- I1620/i1620_tty.c | 347 -- Ibm1130/1130consoleblank.bmp | Bin 887934 -> 0 bytes Ibm1130/HAND.CUR | Bin 326 -> 0 bytes Ibm1130/dmsr2v12phases.h | 171 - Ibm1130/dmsr2v12slet.h | 129 - Ibm1130/ibm1130.mak | 372 --- Ibm1130/ibm1130.rc | 61 - Ibm1130/ibm1130_conin.h | 41 - Ibm1130/ibm1130_conout.h | 58 - Ibm1130/ibm1130_cpu.c | 1872 ----------- Ibm1130/ibm1130_cr.c | 2079 ------------ Ibm1130/ibm1130_defs.h | 294 -- Ibm1130/ibm1130_disk.c | 875 ----- Ibm1130/ibm1130_fmt.c | 303 -- Ibm1130/ibm1130_fmt.h | 17 - Ibm1130/ibm1130_gdu.c | 1118 ------- Ibm1130/ibm1130_gui.c | 1269 -------- Ibm1130/ibm1130_prt.c | 773 ----- Ibm1130/ibm1130_prtwheel.h | 126 - Ibm1130/ibm1130_stddev.c | 1274 -------- Ibm1130/ibm1130_sys.c | 495 --- Ibm1130/ibm1130res.h | 18 - Ibm1130/makefile | 74 - Ibm1130/readme1130.txt | 189 -- Ibm1130/readme_update.txt | 48 - Ibm1130/utils/asm1130.c | 4499 ------------------------- Ibm1130/utils/asm1130.mak | 161 - Ibm1130/utils/bindump.c | 752 ----- Ibm1130/utils/bindump.mak | 161 - Ibm1130/utils/checkdisk.c | 264 -- Ibm1130/utils/checkdisk.mak | 177 - Ibm1130/utils/diskview.c | 614 ---- Ibm1130/utils/diskview.mak | 175 - Ibm1130/utils/mkboot.c | 705 ---- Ibm1130/utils/mkboot.mak | 161 - Ibm1130/utils/viewdeck.c | 242 -- Ibm1130/utils/viewdeck.mak | 161 - Interdata/id16_cpu.c | 1720 ---------- Interdata/id16_dboot.c | 352 -- Interdata/id16_sys.c | 570 ---- Interdata/id32_cpu.c | 2028 ------------ Interdata/id32_dboot.c | 317 -- Interdata/id32_sys.c | 699 ---- Interdata/id_defs.h | 487 --- Interdata/id_diag.txt | 907 ------ Interdata/id_doc.txt | 974 ------ Interdata/id_dp.c | 564 ---- Interdata/id_fd.c | 479 --- Interdata/id_fp.c | 471 --- Interdata/id_idc.c | 693 ---- Interdata/id_io.c | 567 ---- Interdata/id_lp.c | 290 -- Interdata/id_mt.c | 482 --- Interdata/id_pas.c | 548 ---- Interdata/id_pt.c | 352 -- Interdata/id_tt.c | 260 -- Interdata/id_ttp.c | 265 -- Interdata/id_uvc.c | 350 -- NOVA/eclipse.txt | 24 - NOVA/eclipse_cpu.c | 3382 ------------------- NOVA/eclipse_tt.c | 395 --- NOVA/nova_clk.c | 163 - NOVA/nova_cpu.c | 900 ----- NOVA/nova_defs.h | 271 -- NOVA/nova_dkp.c | 723 ---- NOVA/nova_doc.txt | 594 ---- NOVA/nova_dsk.c | 298 -- NOVA/nova_lp.c | 124 - NOVA/nova_mta.c | 589 ---- NOVA/nova_plt.c | 125 - NOVA/nova_pt.c | 215 -- NOVA/nova_sys.c | 957 ------ NOVA/nova_tt.c | 220 -- NOVA/nova_tt1.c | 323 -- PDP1/pdp1_cpu.c | 853 ----- PDP1/pdp1_defs.h | 125 - PDP1/pdp1_doc.txt | 516 --- PDP1/pdp1_drm.c | 169 - PDP1/pdp1_dt.c | 983 ------ PDP1/pdp1_lp.c | 184 -- PDP1/pdp1_stddev.c | 455 --- PDP1/pdp1_sys.c | 513 --- PDP10/pdp10_cpu.c | 2102 ------------ PDP10/pdp10_defs.h | 749 ----- PDP10/pdp10_diag.txt | 25 - PDP10/pdp10_doc.txt | 623 ---- PDP10/pdp10_fe.c | 168 - PDP10/pdp10_ksio.c | 797 ----- PDP10/pdp10_lp20.c | 599 ---- PDP10/pdp10_mdfp.c | 688 ---- PDP10/pdp10_pag.c | 801 ----- PDP10/pdp10_rp.c | 1138 ------- PDP10/pdp10_sys.c | 798 ----- PDP10/pdp10_tim.c | 201 -- PDP10/pdp10_tu.c | 1058 ------ PDP10/pdp10_xtnd.c | 642 ---- PDP11/pdp11_cis.c | 1265 ------- PDP11/pdp11_cpu.c | 2506 -------------- PDP11/pdp11_defs.h | 593 ---- PDP11/pdp11_doc.txt | 1330 -------- PDP11/pdp11_dz.c | 633 ---- PDP11/pdp11_fp.c | 1008 ------ PDP11/pdp11_hk.c | 1134 ------- PDP11/pdp11_io.c | 603 ---- PDP11/pdp11_lp.c | 184 -- PDP11/pdp11_mscp.h | 514 --- PDP11/pdp11_pclk.c | 293 -- PDP11/pdp11_pt.c | 324 -- PDP11/pdp11_rk.c | 615 ---- PDP11/pdp11_rl.c | 653 ---- PDP11/pdp11_rp.c | 1182 ------- PDP11/pdp11_rq.c | 2316 ------------- PDP11/pdp11_rx.c | 483 --- PDP11/pdp11_ry.c | 632 ---- PDP11/pdp11_stddev.c | 409 --- PDP11/pdp11_sys.c | 902 ----- PDP11/pdp11_tc.c | 1182 ------- PDP11/pdp11_tm.c | 656 ---- PDP11/pdp11_tq.c | 2010 ------------ PDP11/pdp11_ts.c | 1011 ------ PDP11/pdp11_uqssp.h | 169 - PDP11/pdp11_xq.c | 2240 ------------- PDP11/pdp11_xq.h | 230 -- PDP11/pdp11_xq_bootrom.h | 312 -- PDP11/pdp11_xu.c | 63 - PDP18B/pdp18b_cpu.c | 2006 ------------ PDP18B/pdp18b_defs.h | 488 --- PDP18B/pdp18b_doc.txt | 993 ------ PDP18B/pdp18b_drm.c | 230 -- PDP18B/pdp18b_dt.c | 1338 -------- PDP18B/pdp18b_fpp.c | 781 ----- PDP18B/pdp18b_lp.c | 783 ----- PDP18B/pdp18b_mt.c | 476 --- PDP18B/pdp18b_rb.c | 273 -- PDP18B/pdp18b_rf.c | 332 -- PDP18B/pdp18b_rp.c | 461 --- PDP18B/pdp18b_stddev.c | 975 ------ PDP18B/pdp18b_sys.c | 1119 ------- PDP18B/pdp18b_tt1.c | 312 -- PDP8/pdp8_clk.c | 166 - PDP8/pdp8_cpu.c | 1145 ------- PDP8/pdp8_defs.h | 188 -- PDP8/pdp8_df.c | 347 -- PDP8/pdp8_doc.txt | 758 ----- PDP8/pdp8_dt.c | 1174 ------- PDP8/pdp8_lp.c | 165 - PDP8/pdp8_mt.c | 582 ---- PDP8/pdp8_pt.c | 266 -- PDP8/pdp8_rf.c | 400 --- PDP8/pdp8_rk.c | 410 --- PDP8/pdp8_rl.c | 629 ---- PDP8/pdp8_rx.c | 659 ---- PDP8/pdp8_sys.c | 515 --- PDP8/pdp8_tt.c | 264 -- PDP8/pdp8_ttx.c | 383 --- Pcap-VMS/pcap-vci/VMS_PCAP.COM | 2 +- S3/haltguide.txt | 950 ------ S3/readme_s3.txt | 78 - S3/s3_cd.c | 442 --- S3/s3_cpu.c | 1832 ----------- S3/s3_defs.h | 94 - S3/s3_disk.c | 788 ----- S3/s3_lp.c | 353 -- S3/s3_pkb.c | 312 -- S3/s3_sys.c | 942 ------ S3/system3.txt | 472 --- SDS/sds_cpu.c | 1282 -------- SDS/sds_defs.h | 403 --- SDS/sds_diag.txt | 113 - SDS/sds_doc.txt | 536 --- SDS/sds_drm.c | 270 -- SDS/sds_dsk.c | 357 -- SDS/sds_io.c | 886 ----- SDS/sds_lp.c | 285 -- SDS/sds_mt.c | 443 --- SDS/sds_mux.c | 506 --- SDS/sds_rad.c | 290 -- SDS/sds_stddev.c | 557 ---- SDS/sds_sys.c | 576 ---- VAX/ka655.bin | Bin 131072 -> 0 bytes VAX/vax_cpu.c | 2505 -------------- VAX/vax_cpu1.c | 1492 --------- VAX/vax_defs.h | 575 ---- VAX/vax_doc.txt | 923 ------ VAX/vax_fpa.c | 1395 -------- VAX/vax_io.c | 950 ------ VAX/vax_mmu.c | 538 --- VAX/vax_stddev.c | 385 --- VAX/vax_sys.c | 1373 -------- VAX/vax_sysdev.c | 1293 -------- VAX/vaxmod_defs.h | 410 --- build_mingw.bat | 14 - build_mingw_ether.bat | 15 - descrip.mms | 1023 ------ makefile | 340 -- scp.c | 3773 --------------------- scp_tty.c | 884 ----- sim_defs.h | 482 --- sim_ether.c | 631 ---- sim_ether.h | 122 - sim_rev.h | 832 ----- sim_sock.c | 296 -- sim_sock.h | 75 - sim_tape.c | 548 ---- sim_tape.h | 101 - sim_tmxr.c | 496 --- sim_tmxr.h | 95 - simh_doc.txt | 1267 -------- simh_faq.txt | 606 ---- simh_swre.txt | 703 ---- 272 files changed, 2 insertions(+), 174791 deletions(-) delete mode 100644 0readme_30.txt delete mode 100644 0readme_ethernet.txt delete mode 100644 ALTAIR/altair.txt delete mode 100644 ALTAIR/altair_cpu.c delete mode 100644 ALTAIR/altair_defs.h delete mode 100644 ALTAIR/altair_dsk.c delete mode 100644 ALTAIR/altair_sio.c delete mode 100644 ALTAIR/altair_sys.c delete mode 100644 AltairZ80/altairZ80.txt delete mode 100644 AltairZ80/altairZ80_cpu.c delete mode 100644 AltairZ80/altairZ80_defs.h delete mode 100644 AltairZ80/altairZ80_dsk.c delete mode 100644 AltairZ80/altairZ80_sio.c delete mode 100644 AltairZ80/altairZ80_sys.c delete mode 100644 AltairZ80/altairz80_hdsk.c delete mode 100644 GRI/gri_cpu.c delete mode 100644 GRI/gri_defs.h delete mode 100644 GRI/gri_doc.txt delete mode 100644 GRI/gri_stddev.c delete mode 100644 GRI/gri_sys.c delete mode 100644 H316/h316_cpu.c delete mode 100644 H316/h316_defs.h delete mode 100644 H316/h316_doc.txt delete mode 100644 H316/h316_lp.c delete mode 100644 H316/h316_stddev.c delete mode 100644 H316/h316_sys.c delete mode 100644 HP2100/hp2100_cpu.c delete mode 100644 HP2100/hp2100_defs.h delete mode 100644 HP2100/hp2100_diag.txt delete mode 100644 HP2100/hp2100_doc.txt delete mode 100644 HP2100/hp2100_dp.c delete mode 100644 HP2100/hp2100_dq.c delete mode 100644 HP2100/hp2100_dr.c delete mode 100644 HP2100/hp2100_fp.c delete mode 100644 HP2100/hp2100_ipl.c delete mode 100644 HP2100/hp2100_lps.c delete mode 100644 HP2100/hp2100_lpt.c delete mode 100644 HP2100/hp2100_ms.c delete mode 100644 HP2100/hp2100_mt.c delete mode 100644 HP2100/hp2100_mux.c delete mode 100644 HP2100/hp2100_stddev.c delete mode 100644 HP2100/hp2100_sys.c delete mode 100644 I1401/i1401_cd.c delete mode 100644 I1401/i1401_cpu.c delete mode 100644 I1401/i1401_dat.h delete mode 100644 I1401/i1401_defs.h delete mode 100644 I1401/i1401_doc.txt delete mode 100644 I1401/i1401_dp.c delete mode 100644 I1401/i1401_iq.c delete mode 100644 I1401/i1401_lp.c delete mode 100644 I1401/i1401_mt.c delete mode 100644 I1401/i1401_sys.c delete mode 100644 I1620/i1620_cd.c delete mode 100644 I1620/i1620_cpu.c delete mode 100644 I1620/i1620_defs.h delete mode 100644 I1620/i1620_doc.txt delete mode 100644 I1620/i1620_dp.c delete mode 100644 I1620/i1620_fp.c delete mode 100644 I1620/i1620_lp.c delete mode 100644 I1620/i1620_pt.c delete mode 100644 I1620/i1620_sys.c delete mode 100644 I1620/i1620_tty.c delete mode 100644 Ibm1130/1130consoleblank.bmp delete mode 100644 Ibm1130/HAND.CUR delete mode 100644 Ibm1130/dmsr2v12phases.h delete mode 100644 Ibm1130/dmsr2v12slet.h delete mode 100644 Ibm1130/ibm1130.mak delete mode 100644 Ibm1130/ibm1130.rc delete mode 100644 Ibm1130/ibm1130_conin.h delete mode 100644 Ibm1130/ibm1130_conout.h delete mode 100644 Ibm1130/ibm1130_cpu.c delete mode 100644 Ibm1130/ibm1130_cr.c delete mode 100644 Ibm1130/ibm1130_defs.h delete mode 100644 Ibm1130/ibm1130_disk.c delete mode 100644 Ibm1130/ibm1130_fmt.c delete mode 100644 Ibm1130/ibm1130_fmt.h delete mode 100644 Ibm1130/ibm1130_gdu.c delete mode 100644 Ibm1130/ibm1130_gui.c delete mode 100644 Ibm1130/ibm1130_prt.c delete mode 100644 Ibm1130/ibm1130_prtwheel.h delete mode 100644 Ibm1130/ibm1130_stddev.c delete mode 100644 Ibm1130/ibm1130_sys.c delete mode 100644 Ibm1130/ibm1130res.h delete mode 100644 Ibm1130/makefile delete mode 100644 Ibm1130/readme1130.txt delete mode 100644 Ibm1130/readme_update.txt delete mode 100644 Ibm1130/utils/asm1130.c delete mode 100644 Ibm1130/utils/asm1130.mak delete mode 100644 Ibm1130/utils/bindump.c delete mode 100644 Ibm1130/utils/bindump.mak delete mode 100644 Ibm1130/utils/checkdisk.c delete mode 100644 Ibm1130/utils/checkdisk.mak delete mode 100644 Ibm1130/utils/diskview.c delete mode 100644 Ibm1130/utils/diskview.mak delete mode 100644 Ibm1130/utils/mkboot.c delete mode 100644 Ibm1130/utils/mkboot.mak delete mode 100644 Ibm1130/utils/viewdeck.c delete mode 100644 Ibm1130/utils/viewdeck.mak delete mode 100644 Interdata/id16_cpu.c delete mode 100644 Interdata/id16_dboot.c delete mode 100644 Interdata/id16_sys.c delete mode 100644 Interdata/id32_cpu.c delete mode 100644 Interdata/id32_dboot.c delete mode 100644 Interdata/id32_sys.c delete mode 100644 Interdata/id_defs.h delete mode 100644 Interdata/id_diag.txt delete mode 100644 Interdata/id_doc.txt delete mode 100644 Interdata/id_dp.c delete mode 100644 Interdata/id_fd.c delete mode 100644 Interdata/id_fp.c delete mode 100644 Interdata/id_idc.c delete mode 100644 Interdata/id_io.c delete mode 100644 Interdata/id_lp.c delete mode 100644 Interdata/id_mt.c delete mode 100644 Interdata/id_pas.c delete mode 100644 Interdata/id_pt.c delete mode 100644 Interdata/id_tt.c delete mode 100644 Interdata/id_ttp.c delete mode 100644 Interdata/id_uvc.c delete mode 100644 NOVA/eclipse.txt delete mode 100644 NOVA/eclipse_cpu.c delete mode 100644 NOVA/eclipse_tt.c delete mode 100644 NOVA/nova_clk.c delete mode 100644 NOVA/nova_cpu.c delete mode 100644 NOVA/nova_defs.h delete mode 100644 NOVA/nova_dkp.c delete mode 100644 NOVA/nova_doc.txt delete mode 100644 NOVA/nova_dsk.c delete mode 100644 NOVA/nova_lp.c delete mode 100644 NOVA/nova_mta.c delete mode 100644 NOVA/nova_plt.c delete mode 100644 NOVA/nova_pt.c delete mode 100644 NOVA/nova_sys.c delete mode 100644 NOVA/nova_tt.c delete mode 100644 NOVA/nova_tt1.c delete mode 100644 PDP1/pdp1_cpu.c delete mode 100644 PDP1/pdp1_defs.h delete mode 100644 PDP1/pdp1_doc.txt delete mode 100644 PDP1/pdp1_drm.c delete mode 100644 PDP1/pdp1_dt.c delete mode 100644 PDP1/pdp1_lp.c delete mode 100644 PDP1/pdp1_stddev.c delete mode 100644 PDP1/pdp1_sys.c delete mode 100644 PDP10/pdp10_cpu.c delete mode 100644 PDP10/pdp10_defs.h delete mode 100644 PDP10/pdp10_diag.txt delete mode 100644 PDP10/pdp10_doc.txt delete mode 100644 PDP10/pdp10_fe.c delete mode 100644 PDP10/pdp10_ksio.c delete mode 100644 PDP10/pdp10_lp20.c delete mode 100644 PDP10/pdp10_mdfp.c delete mode 100644 PDP10/pdp10_pag.c delete mode 100644 PDP10/pdp10_rp.c delete mode 100644 PDP10/pdp10_sys.c delete mode 100644 PDP10/pdp10_tim.c delete mode 100644 PDP10/pdp10_tu.c delete mode 100644 PDP10/pdp10_xtnd.c delete mode 100644 PDP11/pdp11_cis.c delete mode 100644 PDP11/pdp11_cpu.c delete mode 100644 PDP11/pdp11_defs.h delete mode 100644 PDP11/pdp11_doc.txt delete mode 100644 PDP11/pdp11_dz.c delete mode 100644 PDP11/pdp11_fp.c delete mode 100644 PDP11/pdp11_hk.c delete mode 100644 PDP11/pdp11_io.c delete mode 100644 PDP11/pdp11_lp.c delete mode 100644 PDP11/pdp11_mscp.h delete mode 100644 PDP11/pdp11_pclk.c delete mode 100644 PDP11/pdp11_pt.c delete mode 100644 PDP11/pdp11_rk.c delete mode 100644 PDP11/pdp11_rl.c delete mode 100644 PDP11/pdp11_rp.c delete mode 100644 PDP11/pdp11_rq.c delete mode 100644 PDP11/pdp11_rx.c delete mode 100644 PDP11/pdp11_ry.c delete mode 100644 PDP11/pdp11_stddev.c delete mode 100644 PDP11/pdp11_sys.c delete mode 100644 PDP11/pdp11_tc.c delete mode 100644 PDP11/pdp11_tm.c delete mode 100644 PDP11/pdp11_tq.c delete mode 100644 PDP11/pdp11_ts.c delete mode 100644 PDP11/pdp11_uqssp.h delete mode 100644 PDP11/pdp11_xq.c delete mode 100644 PDP11/pdp11_xq.h delete mode 100644 PDP11/pdp11_xq_bootrom.h delete mode 100644 PDP11/pdp11_xu.c delete mode 100644 PDP18B/pdp18b_cpu.c delete mode 100644 PDP18B/pdp18b_defs.h delete mode 100644 PDP18B/pdp18b_doc.txt delete mode 100644 PDP18B/pdp18b_drm.c delete mode 100644 PDP18B/pdp18b_dt.c delete mode 100644 PDP18B/pdp18b_fpp.c delete mode 100644 PDP18B/pdp18b_lp.c delete mode 100644 PDP18B/pdp18b_mt.c delete mode 100644 PDP18B/pdp18b_rb.c delete mode 100644 PDP18B/pdp18b_rf.c delete mode 100644 PDP18B/pdp18b_rp.c delete mode 100644 PDP18B/pdp18b_stddev.c delete mode 100644 PDP18B/pdp18b_sys.c delete mode 100644 PDP18B/pdp18b_tt1.c delete mode 100644 PDP8/pdp8_clk.c delete mode 100644 PDP8/pdp8_cpu.c delete mode 100644 PDP8/pdp8_defs.h delete mode 100644 PDP8/pdp8_df.c delete mode 100644 PDP8/pdp8_doc.txt delete mode 100644 PDP8/pdp8_dt.c delete mode 100644 PDP8/pdp8_lp.c delete mode 100644 PDP8/pdp8_mt.c delete mode 100644 PDP8/pdp8_pt.c delete mode 100644 PDP8/pdp8_rf.c delete mode 100644 PDP8/pdp8_rk.c delete mode 100644 PDP8/pdp8_rl.c delete mode 100644 PDP8/pdp8_rx.c delete mode 100644 PDP8/pdp8_sys.c delete mode 100644 PDP8/pdp8_tt.c delete mode 100644 PDP8/pdp8_ttx.c delete mode 100644 S3/haltguide.txt delete mode 100644 S3/readme_s3.txt delete mode 100644 S3/s3_cd.c delete mode 100644 S3/s3_cpu.c delete mode 100644 S3/s3_defs.h delete mode 100644 S3/s3_disk.c delete mode 100644 S3/s3_lp.c delete mode 100644 S3/s3_pkb.c delete mode 100644 S3/s3_sys.c delete mode 100644 S3/system3.txt delete mode 100644 SDS/sds_cpu.c delete mode 100644 SDS/sds_defs.h delete mode 100644 SDS/sds_diag.txt delete mode 100644 SDS/sds_doc.txt delete mode 100644 SDS/sds_drm.c delete mode 100644 SDS/sds_dsk.c delete mode 100644 SDS/sds_io.c delete mode 100644 SDS/sds_lp.c delete mode 100644 SDS/sds_mt.c delete mode 100644 SDS/sds_mux.c delete mode 100644 SDS/sds_rad.c delete mode 100644 SDS/sds_stddev.c delete mode 100644 SDS/sds_sys.c delete mode 100644 VAX/ka655.bin delete mode 100644 VAX/vax_cpu.c delete mode 100644 VAX/vax_cpu1.c delete mode 100644 VAX/vax_defs.h delete mode 100644 VAX/vax_doc.txt delete mode 100644 VAX/vax_fpa.c delete mode 100644 VAX/vax_io.c delete mode 100644 VAX/vax_mmu.c delete mode 100644 VAX/vax_stddev.c delete mode 100644 VAX/vax_sys.c delete mode 100644 VAX/vax_sysdev.c delete mode 100644 VAX/vaxmod_defs.h delete mode 100644 build_mingw.bat delete mode 100644 build_mingw_ether.bat delete mode 100644 descrip.mms delete mode 100644 makefile delete mode 100644 scp.c delete mode 100644 scp_tty.c delete mode 100644 sim_defs.h delete mode 100644 sim_ether.c delete mode 100644 sim_ether.h delete mode 100644 sim_rev.h delete mode 100644 sim_sock.c delete mode 100644 sim_sock.h delete mode 100644 sim_tape.c delete mode 100644 sim_tape.h delete mode 100644 sim_tmxr.c delete mode 100644 sim_tmxr.h delete mode 100644 simh_doc.txt delete mode 100644 simh_faq.txt delete mode 100644 simh_swre.txt diff --git a/.gitignore b/.gitignore index f20c730c..6115e13d 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ _ReSharper*/ *.o BIN/ ipch/ +*.map diff --git a/0readme_30.txt b/0readme_30.txt deleted file mode 100644 index e1a623cf..00000000 --- a/0readme_30.txt +++ /dev/null @@ -1,166 +0,0 @@ -Notes For V3.0-2 - -RESTRICTION: The FP15 and XVM features of the PDP-15 are only partially -debugged. Do NOT enable these features for normal operations. - -1. New Features in 3.0-2 - -1.1 PDP-1 - -- The LOAD command takes an optional argument specifying the memory field - to be loaded. -- The PTR BOOT command takes its starting memory field from the TA (address - switch) register. - -2. Bugs Fixed in 3.0-2 - -2.1 SCP and libraries - -- Fixed end of file problem in dep, idep. -- Fixed handling of trailing spaces in dep, idep. - -2.2 PDP-1 - -- Fixed system hang if continue after PTR error. -- Fixed PTR to start/stop on successive rpa instructions. - -2.3 PDP 18b family - -- Fixed priorities in PDP-15 API (differs from PDP-9). -- Fixed sign handling in PDP-15 EAE unsigned mul/div (differs from PDP-9). -- Fixed bug in CAF, clears API subsystem. - -2.4 1401 - -- Fixed tape read end-of-record handling based on real 1401. -- Added diagnostic read (space forward). - -2.5 1620 - -- Fixed bug in immediate index add (found by Michael Short). - -3. New Features in 3.0 vs prior releases - -3.1 SCP and Libraries - -- Added ASSIGN/DEASSIGN (logical name) commands. -- Changed RESTORE to unconditionally detach files. -- Added E11 and TPC format support to magtape library. -- Fixed bug in SHOW CONNECTIONS. -- Added USE_ADDR64 support - -3.2 All magtapes - -- Magtapes support SIMH format, E11 format, and TPC format (read only). -- SET FORMAT=format sets the specified tape unit's format. -- SHOW FORMAT displays the specified tape unit's format. -- Tape format can also be set as part of the ATTACH command, using - the -F switch. - -3.3 VAX - -- VAX can be compiled without USE_INT64. -- If compiled with USE_INT64 and USE_ADDR64, RQ and TQ controllers support - files > 2GB. -- VAX ROM has speed control (SET ROM DELAY/NODELAY). - -3.4 PDP-1 - -- Added block loader format support to LOAD. -- Changed BOOT PTR to allow loading of all of the first bank of memory. - -3.5 PDP-18b Family - -- Added PDP-4 EAE support. -- Added PDP-15 FP15 support. -- Added PDP-15 XVM support. -- Added PDP-15 "re-entrancy ECO". -- Added PDP-7, PDP-9, PDP-15 hardware RIM loader support in BOOT PTR. - -4. Bugs Fixed in 3.0 vs prior releases - -4.1 VAX - -- Fixed CVTfi bug: integer overflow not set if exponent out of range -- Fixed EMODx bugs: - o First and second operands reversed - o Separated fraction received wrong exponent - o Overflow calculation on separated integer incorrect - o Fraction not set to zero if exponent out of range -- Fixed interval timer and ROM access to pass power-up self-test even on very - fast host processors (fixes from Mark Pizzolato). -- Fixed bug in user disk size (found by Chaskiel M Grundman). - -4.2 1401 - -- Fixed mnemonic, instruction lengths, and reverse scan length check bug for MCS. -- Fixed MCE bug, BS off by 1 if zero suppress. -- Fixed chaining bug, D lost if return to SCP. -- Fixed H branch, branch occurs after continue. -- Added check for invalid 8 character MCW, LCA. -- Fixed magtape load-mode end of record response. -- Revised fetch to model hardware more closely. - -4.3 Nova - -- Fixed DSK variable size interaction with restore. -- Fixed bug in DSK set size routine. - -4.4 PDP-1 - -- Fixed DT variable size interaction with restore. -- Updated CPU, line printer, standard devices to detect indefinite I/O wait. -- Fixed incorrect logical, missing activate, break in drum simulator. -- Fixed bugs in instruction decoding, overprinting for line printer. - -4.5 PDP-11 - -- Fixed DT variable size interaction with restore. -- Fixed bug in MMR1 update (found by Tim Stark). -- Added XQ features and fixed bugs: - o Corrected XQ interrupts on IE state transition (code by Tom Evans). - o Added XQ interrupt clear on soft reset. - o Removed XQ interrupt when setting XL or RL (multiple people). - o Added SET/SHOW XQ STATS. - o Added SHOW XQ FILTERS. - o Added ability to split received packet into multiple buffers. - o Added explicit runt and giant packet processing. -- Fixed bug in user disk size (found by Chaskiel M Grundman). - -4.6 PDP-18B - -- Fixed DT, RF variable size interaction with restore. -- Fixed MT bug in MTTR. -- Fixed bug in PDP-4 line printer overprinting. -- Fixed bug in PDP-15 memory protect/skip interaction. -- Fixed bug in RF set size routine. -- Increased PTP TIME for PDP-15 operating systems. - -4.7 PDP-8 - -- Fixed DT, DF, RF, RX variable size interaction with restore. -- Fixed MT bug in SKTR. -- Fixed bug in DF, RF set size routine. - -4.8 HP2100 - -- Fixed bug in DP (13210A controller only), DQ read status. -- Fixed bug in DP, DQ seek complete. -- Fixed DR drum sizes. -- Fixed DR variable capacity interaction with SAVE/RESTORE. - -4.9 GRI - -- Fixed bug in SC queue pointer management. - -4.10 PDP-10 - -- Fixed bug in RP read header. - -4.11 Ibm1130 - -- Fixed bugs found by APL 1130. - -4.12 Altairz80 - -- Fixed bug in real-time clock on Windows host. diff --git a/0readme_ethernet.txt b/0readme_ethernet.txt deleted file mode 100644 index 938fcf71..00000000 --- a/0readme_ethernet.txt +++ /dev/null @@ -1,162 +0,0 @@ -This file contains information about the XQ/SIM_ETHER package. - -------------------------------------------------------------------------------- - -The XQ emulator is a host-independant software emulation of Digital's -DELQA (M7516) and DEQNA (M7504) Q-bus ethernet cards for the SIMH emulator. - -The XQ emulator uses the Sim_Ether module to execute host-specific ethernet -packet reads and writes, since all operating systems talk to real ethernet -cards/controllers differently. The host-dependant Sim_Ether module currently -supports Windows, Linux, NetBSD, and OpenBSD. - -Currently, the Sim_Ether module sets the selected ethernet card into -promiscuous mode to gather all packets, then filters out the packets that it -doesn't want. In Windows, packets having the same source MAC address as the -controller are ignored for WinPCAP compatibility (see Windows notes below). - -If your ethernet card is plugged into a switch, the promiscuous mode setting -should not cause much of a problem, since the switch will still filter out -most of the undesirable traffic. You will only see "excessive" traffic if you -are on a direct or hub(repeater) segment. - -------------------------------------------------------------------------------- - -Windows notes: - 1. The Windows-specific code uses the WinPCAP 3.0 package from - http://winpcap.polito.it. This package for windows simulates the libpcap - package that is freely available for unix systems. - 2. You must *install* the WinPCAP runtime package. - 3. The first time the WinPCAP driver is used, it will be dynamically loaded, - and the user must be an Administrator on the machine to do so. If you need - to run as an unprivileged user, you must set the service to autostart. See - the WinPCAP documentation for details on the static load workaround. - 4. WinPCAP loops packet writes back into the read queue. This causes problems - since the XQ controller is not expecting to read it's own packet. A fix - to the packet read filter was added to reject packets from the current MAC, - but this defeats DECNET's duplicate node number detection scheme. A more - correct fix for WinPCAP will be explored as time allows. - -Building on Windows: - 1. Install WinPCAP 3.0. - 2. Put the required .h files (bittypes,devioctl,ip6_misc,packet32,pcap, - pcap-stdinc).h from the WinPCAP 3.0 developer's kit in the compiler's path - 3. Put the required .lib files (packet,wpcap).lib from the WinPCAP 3.0 - developer's kit in the linker's path - 4. If you're using Borland C++, use COFF2OMF to convert the .lib files into - a format that can be used by the compiler. - 5. Define USE_NETWORK if you want the network functionality. - 6. Build it! - -------------------------------------------------------------------------------- - -Linux, NetBSD, and OpenBSD notes: - 1. You must run SIMH(scp) as root so that the ethernet card can be set into - promiscuous mode by the driver. Alternative methods for avoiding the - 'run as root' requirement will be welcomed. - -Building on Linux, NetBSD, and OpenBSD: - 1. Get/install the libpcap package for your unix version. http://rpmfind.net - might be a useful site for finding the linux variants. - 2. Use Make USE_NETWORK=1 if you want the network functionality. - 3. Build it! - -------------------------------------------------------------------------------- - -VAX simulator support: - -An OpenVMS VAX v7.2 system with DECNET Phase IV, MultiNet 4.4a, and LAT 5.3 has -been successfully run. Other testers have reported success booting NetBSD also. - - -PDP11 simulator support: - -An RT-11 v5.3 system with a freeware TCP/IP stack has been successfully run. -Other testers have reported that RSX with DECNET and the NetBSD operating -systems also work. RSTS/E v10.1 has preliminary support - RSTS/E boots and -enables the XH (XQ) device - DECNET and LAT software have not been tested. - -------------------------------------------------------------------------------- - -Things planned for future releases: - 1. PDP-11 bootstrap/bootrom - 2. Full MOP implementation - 3. DESQA support (if someone can get me the user manuals) - 4. DETQA support [DELQA-Turbo] (I have the manual) - 5. DEUNA/DELUA support - -------------------------------------------------------------------------------- - -Things which I need help with: - 1. Porting Sim_Ether packet driver to other host platforms, especially VMS. - 2. Information about Remote MOP processing - 3. VAX/PDP-11 hardware diagnotics image files and docs, to test XQ thoroughly. - 4. Feedback on operation with other VAX/PDP-11 OS's. - -------------------------------------------------------------------------------- - -Please send all patches, questions, feedback, clarifications, and help to: - dhittner AT northropgrumman DOT com - -Thanks, and Enjoy!! -Dave - - -=============================================================================== - Change Log -=============================================================================== - -05-Jun-03 Release: - 1. Added SET/SHOW XQ STATS - 2. Added SHOW XQ FILTERS - 3. Added ability to split received packet into multiple buffers - 4. Added explicit runt & giant packet processing - -------------------------------------------------------------------------------- - -30-May-03 Release: - 1. Corrected bug in xq_setmac introduced in v3.0 (multiple people) - 2. Made XQ receive buffer allocation dynamic to reduce scp executable size - 3. Optimized some structs, removed legacy variables (Mark Pizzolato) - 4. Changed #ifdef WIN32 to _WIN32 for consistancy - -------------------------------------------------------------------------------- - -06-May-03 Release: - 1. Added second XQ controller - 2. Added SIMH v3.0 compatibility - 3. Removed SET ADDRESS functionality - -------------------------------------------------------------------------------- - -10-Apr-03 Release: - 1. Added preliminary support for RSTS/E - 2. Added PDP-11 bootrom load via CSR flags - 3. Support for SPARC linux (thanks to Mark Pizzolato) - -------------------------------------------------------------------------------- - -11-Mar-03 Release: - 1. Added support for RT-11 TCP/IP - 2. Corrected interrupts (thanks to Tom Evans and Bob Supnik) - 3. Moved change log to the bottom of the readme file, cleaned up document - -------------------------------------------------------------------------------- - -16-Jan-03 Release: - 1. Added VMScluster support (thanks to Mark Pizzolato) - 2. Verified VAX remote boot functionality (>>>B XQA0) - 3. Added major performance enhancements (thanks to Mark Pizzolato again) - 4. Changed _DEBUG tracers to XQ_DEBUG and ETH_DEBUG - 5. Added local packet processing - 6. Added system id broadcast - -------------------------------------------------------------------------------- - -08-Nov-02 Release: - 1. Added USE_NETWORK conditional to Sim_Ether - 2. Fixed behaviour of SHOW XQ ETH if no devices exist - 3. Added OpenBSD support to Sim_Ether (courtesy of Federico Schwindt) - 4. Added ethX detection simplification (from Megan Gentry) - -=============================================================================== diff --git a/ALTAIR/altair.txt b/ALTAIR/altair.txt deleted file mode 100644 index 13f0c361..00000000 --- a/ALTAIR/altair.txt +++ /dev/null @@ -1,211 +0,0 @@ -Altair 8800 Simulator -===================== - -1. Background. - - The MITS (Micro Instrumentation and Telemetry Systems) Altair 8800 -was announced on the January 1975 cover of Popular Electronics, which -boasted you could buy and build this powerful computer kit for only $397. -The kit consisted at that time of only the parts to build a case, power -supply, card cage (18 slots), CPU card, and memory card with 256 *bytes* of -memory. Still, thousands were ordered within the first few months after the -announcement, starting the personal computer revolution as we know it today. - - Many laugh at the small size of the that first kit, noting there -were no peripherals and the 256 byte memory size. But the computer was an -open system, and by 1977 MITS and many other small startups had added many -expansion cards to make the Altair quite a respectable little computer. The -"Altair Bus" that made this possible was soon called the S-100 Bus, later -adopted as an industry standard, and eventually became the IEE-696 Bus. - -2. Hardware - - We are simulating a fairly "loaded" Altair 8800 from about 1977, -with the following configuration: - - device simulates - name(s) - - CPU Altair 8800 with Intel 8080 CPU board, 62KB - of RAM, 2K of EPROM with start boot ROM. - 2SIO MITS 88-2SIO Dual Serial Interface Board. Port 1 - is assumed to be connected to a serial "glass - TTY" that is your terminal running the Simulator. - PTR Paper Tape Reader attached to port 2 of the - 2SIO board. - PTP Paper Tape Punch attached to port 2 of the - 2SIO board. This also doubles as a printer - port. - DSK MITS 88-DISK Floppy Disk controller with up - to eight drives. - -2.1 CPU - - We have 2 CPU options that were not present on the original -machine but are useful in the simulator. We also allow you to select -memory sizes, but be aware that some sample software requires the full -64K (i.e. CP/M) and the MITS Disk Basic and Altair DOS require about -a minimum of 24K. - - SET CPU 8080 Simulates the 8080 CPU (normal) - SET CPU Z80 Simulates the later Z80 CPU [At the present time - this is not fully implemented and is not to be - trusted with real Z80 software] - SET CPU ITRAP Causes the simulator to halt if an invalid 8080 - Opcode is detected. - SET CPU NOITRAP Does not stop on an invalid Opcode. This is - how the real 8080 works. - SET CPU 4K - SET CPU 8K - SET CPU 12K - SET CPU 16K - ...... - SET CPU 64K All these set various CPU memory configurations. - The 2K EPROM at the high end of memory is always - present and will always boot. - -The BOOT EPROM card starts at address 177400. Jumping to this address -will always boot drive 0 of the floppy controller. If no valid bootable -software is present there the machine crashes. This is historically -accurate behavior. - -The real 8080, on receiving a HLT (Halt) instruction, freezes the processor -and only an interrupt or CPU hardware reset will restore it. The simulator -is alot nicer, it will halt but send you back to the simulator command line. - -CPU Registers include the following: - - name size comments - - PC 16 The Program Counter - A 8 The accumulator - BC 16 The BC register pair. Register B is the high - 8 bits, C is the lower 8 bits - DE 16 The DE register pair. D is the top 8 bits, E is - the bottom. - HL 16 The HL register pair. H is top, L is bottom. - C 1 Carry flag. - Z 1 Zero Flag. - AC 1 Auxillary Carry flag. - P 1 Parity flag. - S 1 Sign flag. - SR 16 The front panel switches. - BREAK 16 Breakpoint address (377777 to disable). - WRU 8 The interrupt character. This starts as 005 - (ctrl-E) but some Altair software uses this - keystroke so best to change this to something - exotic such as 035 (which is Ctl-]). - - -2.2 The Serial I/O Card (2SIO) - - This simple programmed I/O device provides 2 serial ports to the -outside world, which could be hardware jumpered to support RS-232 plugs or a -TTY current loop interface. The standard I/O addresses assigned by MITS -was 20-21 (octal) for the first port, and 22-23 (octal) for the second. -We follow this standard in the Simulator. - - The simulator directs I/O to/from the first port to the screen. The -second port reads from an attachable "tape reader" file on input, and writes -to an attachable "punch file" on output. These files are considered a -simple stream of 8-bit bytes. - -2.3 The 88-DISK controller. - - The MITS 88-DISK is a simple programmed I/O interface to the MITS -8-inch floppy drive, which was basically a Pertec FD-400 with a power -supply and buffer board builtin. The controller supports neither interrupts -nor DMA, so floppy access required the sustained attention of the CPU. -The standard I/O addresses were 10, 11, and 12 (octal), and we follow the -standard. Details on controlling this hardware are in the altair_dsk.c -source file. - - -3. Sample Software - - Running an Altair in 1977 you would be running either MITS Disk -Extended BASIC, or the brand new and sexy CP/M Operating System from Digital -Research. Or possibly, you ordered Altair DOS back when it was promised in -1975, and are still waiting for it to be delivered in early 1977. - - We have samples of all three for you to check out. We can't go into -the details of how they work, but we'll give you a few hints. - - -3.1 CP/M Version 2.2 - - This version is my own port of the standard CP/M to the Altair. -There were some "official" versions but I don't have them. None were -endorsed or sold by MITS to my knowledge, however. - To boot CP/M: - - sim> attach dsk0 altcpm.dsk - sim> go 177400 - 62K CP/M VERSION 2.2 (ALTAIR 8800) - A>DIR - - CP/M feels like DOS, sort of. DIR will work. I have included all -the standard CP/M utilities, plus a few common public-domain ones. I also -include the sources to the customized BIOS and some other small programs. -TYPE will print an ASCII file. DUMP will dump a binary one. LS is a better -DIR than DIR. ASM will assemble .ASM files to Hex, LOAD will "load" them to -binary format (.COM). ED is a simple editor, #A command will bring the -source file to the buffer, T command will "type" lines, L will move lines, -E exits the editor. 20L20T will move down 20 lines, and type 20. Very -DECish. DDT is the debugger, SUBMIT is a batch-type command processor. -A sample batch file that will assemble and write out the bootable CP/M -image (on drive A) is "SYSGEN.SUB". To run it, type "SUBMIT SYSGEN". - - -3.2 MITS Disk Extended BASIC Version 4.1 - - This was the commonly used software for serious users of the Altair -computer. It is a powerful (but slow) BASIC with some extended commands to -allow it to access and manage the disk. There was no operating system it -ran under. To boot: - - sim> attach dsk0 mbasic.dsk - sim> go 177400 - - MEMORY SIZE? [return] - LINEPRINTER? C [return] - HIGHEST DISK NUMBER? 0 [return] (3 here = 4 drive system) - NUMBER OF FILES? 3 [return] - NUMBER OF RANDOM FILES? 2 [return] - - 44297 BYTES FREE - ALTAIR BASIC REV. 4.1 - [DISK EXTENDED VERSION] - COPYRIGHT 1977 BY MITS INC. - OK - mount 0 - OK - files - - -3.3 Altair DOS Version 1.0 - - This was long promised but not delivered until it was almost -irrelevant. A short attempted tour will reveal it to be a dog, far inferior -to CP/M. To boot: - - sim> attach dsk0 altdos.dsk - sim> go 177400 - - MEMORY SIZE? 64 [return] - INTERRUPTS? N [return] - HIGHEST DISK NUMBER? 0 [return] (3 here = 4 drive system) - HOW MANY DISK FILES? 3 [return] - HOW MANY RANDOM FILES? 2 [return] - - 056769 BYTES AVAILABLE - DOS MONITOR VER 1.0 - COPYRIGHT 1977 BY MITS INC - .mnt 0 - - .dir 0 - - - - - diff --git a/ALTAIR/altair_cpu.c b/ALTAIR/altair_cpu.c deleted file mode 100644 index 1977d0e2..00000000 --- a/ALTAIR/altair_cpu.c +++ /dev/null @@ -1,1189 +0,0 @@ -/* altair_cpu.c: MITS Altair Intel 8080 CPU simulator - - Copyright (c) 1997-2003, Charles E. Owen - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. - - cpu 8080 CPU - - 08-Oct-02 RMS Tied off spurious compiler warnings - - The register state for the 8080 CPU is: - - A<0:7> Accumulator - BC<0:15> BC Register Pair - DE<0:15> DE Register Pair - HL<0:15> HL Register Pair - C carry flag - Z zero flag - S Sign bit - AC Aux carry - P Parity bit - PC<0:15> program counter - SP<0:15> Stack Pointer - - The 8080 is an 8-bit CPU, which uses 16-bit registers to address - up to 64KB of memory. - - The 78 basic instructions come in 1, 2, and 3-byte flavors. -*/ - -/* This routine is the instruction decode routine for the 8080. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - I/O error in I/O simulator - Invalid OP code (if ITRAP is set on CPU) - - 2. Interrupts. - There are 8 possible levels of interrupt, and in effect they - do a hardware CALL instruction to one of 8 possible low - memory addresses. - - 3. Non-existent memory. On the 8080, reads to non-existent memory - return 0377, and writes are ignored. In the simulator, the - largest possible memory is instantiated and initialized to zero. - Thus, only writes need be checked against actual memory size. - - 4. Adding I/O devices. These modules must be modified: - - altair_cpu.c add I/O service routines to dev_table - altair_sys.c add pointer to data structures in sim_devices -*/ - - -#include - -#include "altair_defs.h" - -#define UNIT_V_OPSTOP (UNIT_V_UF) /* Stop on Invalid OP? */ -#define UNIT_OPSTOP (1 << UNIT_V_OPSTOP) -#define UNIT_V_CHIP (UNIT_V_UF+1) /* 8080 or Z80 */ -#define UNIT_CHIP (1 << UNIT_V_CHIP) -#define UNIT_V_MSIZE (UNIT_V_UF+2) /* Memory Size */ -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -unsigned char M[MAXMEMSIZE]; /* memory */ -int32 A = 0; /* accumulator */ -int32 BC = 0; /* BC register pair */ -int32 DE = 0; /* DE register pair */ -int32 HL = 0; /* HL register pair */ -int32 SP = 0; /* Stack pointer */ -int32 C = 0; /* carry flag */ -int32 Z = 0; /* Zero flag */ -int32 AC = 0; /* Aux carry */ -int32 S = 0; /* sign flag */ -int32 P = 0; /* parity flag */ -int32 saved_PC = 0; /* program counter */ -int32 SR = 0; /* switch register */ -int32 INTE = 0; /* Interrupt Enable */ -int32 int_req = 0; /* Interrupt request */ -int32 chip = 0; /* 0 = 8080 chip, 1 = z80 chip */ - -int32 PCX; /* External view of PC */ - -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ - -/* function prototypes */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -void setarith(int32 reg); -void setlogical(int32 reg); -void setinc(int32 reg); -int32 getreg(int32 reg); -void putreg(int32 reg, int32 val); -int32 getpair(int32 reg); -int32 getpush(int32 reg); -void putpush(int32 reg, int32 data); -void putpair(int32 reg, int32 val); -void parity(int32 reg); -int32 cond(int32 con); - -extern int32 sio0s(int32 io, int32 data); -extern int32 sio0d(int32 io, int32 data); -extern int32 sio1s(int32 io, int32 data); -extern int32 sio1d(int32 io, int32 data); -extern int32 dsk10(int32 io, int32 data); -extern int32 dsk11(int32 io, int32 data); -extern int32 dsk12(int32 io, int32 data); -int32 nulldev(int32 io, int32 data); - -/* This is the I/O configuration table. There are 255 possible -device addresses, if a device is plugged to a port it's routine -address is here, 'nulldev' means no device is available -*/ -struct idev { - int32 (*routine)(); -}; -struct idev dev_table[256] = { -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 000 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 004 */ -{&dsk10}, {&dsk11}, {&dsk12}, {&nulldev}, /* 010 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 014 */ -{&sio0s}, {&sio0d}, {&sio1s}, {&sio1d}, /* 020 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 024 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 030 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 034 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 040 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 044 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 050 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 054 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 060 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 064 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 070 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 074 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 100 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 104 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 110 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 114 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 120 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 124 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 130 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 134 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 140 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 144 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 150 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 154 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 160 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 164 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 170 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 174 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 200 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 204 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 210 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 214 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 220 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 224 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 230 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 234 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 240 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 244 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 250 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 254 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 260 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 264 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 270 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 274 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 300 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 304 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 310 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 314 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 320 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 324 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 330 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 334 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 340 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 344 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 350 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 354 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 360 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 364 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 370 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} }; /* 374 */ - -/* Altair MITS standard BOOT EPROM, fits in upper 256K of memory */ - -int32 bootrom[256] = { - 0041, 0000, 0114, 0021, 0030, 0377, 0016, 0346, - 0032, 0167, 0023, 0043, 0015, 0302, 0010, 0377, - 0303, 0000, 0114, 0000, 0000, 0000, 0000, 0000, - 0363, 0061, 0142, 0115, 0257, 0323, 0010, 0076, /* 46000 */ - 0004, 0323, 0011, 0303, 0031, 0114, 0333, 0010, /* 46010 */ - 0346, 0002, 0302, 0016, 0114, 0076, 0002, 0323, /* 46020 */ - 0011, 0333, 0010, 0346, 0100, 0302, 0016, 0114, - 0021, 0000, 0000, 0006, 0000, 0333, 0010, 0346, - 0004, 0302, 0045, 0114, 0076, 0020, 0365, 0325, - 0305, 0325, 0021, 0206, 0200, 0041, 0324, 0114, - 0333, 0011, 0037, 0332, 0070, 0114, 0346, 0037, - 0270, 0302, 0070, 0114, 0333, 0010, 0267, 0372, - 0104, 0114, 0333, 0012, 0167, 0043, 0035, 0312, - 0132, 0114, 0035, 0333, 0012, 0167, 0043, 0302, - 0104, 0114, 0341, 0021, 0327, 0114, 0001, 0200, - 0000, 0032, 0167, 0276, 0302, 0301, 0114, 0200, - 0107, 0023, 0043, 0015, 0302, 0141, 0114, 0032, - 0376, 0377, 0302, 0170, 0114, 0023, 0032, 0270, - 0301, 0353, 0302, 0265, 0114, 0361, 0361, 0052, - 0325, 0114, 0325, 0021, 0000, 0377, 0315, 0316, - 0114, 0321, 0332, 0276, 0114, 0315, 0316, 0114, - 0322, 0256, 0114, 0004, 0004, 0170, 0376, 0040, - 0332, 0054, 0114, 0006, 0001, 0312, 0054, 0114, - 0333, 0010, 0346, 0002, 0302, 0240, 0114, 0076, - 0001, 0323, 0011, 0303, 0043, 0114, 0076, 0200, - 0323, 0010, 0303, 0000, 0000, 0321, 0361, 0075, - 0302, 0056, 0114, 0076, 0103, 0001, 0076, 0117, - 0001, 0076, 0115, 0107, 0076, 0200, 0323, 0010, - 0170, 0323, 0001, 0303, 0311, 0114, 0172, 0274, - 0300, 0173, 0275, 0311, 0204, 0000, 0114, 0044, - 0026, 0126, 0026, 0000, 0000, 0000, 0000, 0000 -}; - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifiers list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, - MAXMEMSIZE) }; - -REG cpu_reg[] = { - { ORDATA (PC, saved_PC, 16) }, - { ORDATA (A, A, 8) }, - { ORDATA (BC, BC, 16) }, - { ORDATA (DE, DE, 16) }, - { ORDATA (HL, HL, 16) }, - { ORDATA (SP, SP, 16) }, - { FLDATA (C, C, 16) }, - { FLDATA (Z, Z, 16) }, - { FLDATA (AC, AC, 16) }, - { FLDATA (S, S, 16) }, - { FLDATA (P, P, 16) }, - { FLDATA (INTE, INTE, 16) }, - { ORDATA (SR, SR, 16) }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_CHIP, UNIT_CHIP, "Z80", "Z80", NULL }, - { UNIT_CHIP, 0, "8080", "8080", NULL }, - { UNIT_OPSTOP, UNIT_OPSTOP, "ITRAP", "ITRAP", NULL }, - { UNIT_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL }, - { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, - { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, - { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size }, - { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, - { UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size }, - { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size }, - { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size }, - { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, - { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size }, - { UNIT_MSIZE, 65535, NULL, "64K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, 16, 1, 8, 8, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -int32 sim_instr (void) -{ - extern int32 sim_interval; - int32 PC, IR, OP, DAR, reason, hi, lo, carry, i; - - PC = saved_PC & ADDRMASK; /* load local PC */ - C = C & 0200000; - reason = 0; - - /* Main instruction fetch/decode loop */ - - while (reason == 0) { /* loop until halted */ - if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; - } - - if (int_req > 0) { /* interrupt? */ - - /* 8080 interrupts not implemented yet. None were used, - on a standard Altair 8800. All I/O is programmed. */ - - } /* end interrupt */ - - if (sim_brk_summ && - sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; - } - - if (PC == 0177400) { /* BOOT PROM address */ - for (i = 0; i < 250; i++) { - M[i + 0177400] = bootrom[i] & 0xFF; - } - } - - PCX = PC; - - IR = OP = M[PC]; /* fetch instruction */ - - PC = (PC + 1) & ADDRMASK; /* increment PC */ - - sim_interval--; - - if (OP == 0166) { /* HLT Instruction*/ - reason = STOP_HALT; - PC--; - continue; - } - - /* Handle below all operations which refer to registers or - register pairs. After that, a large switch statement - takes care of all other opcodes */ - - if ((OP & 0xC0) == 0x40) { /* MOV */ - DAR = getreg(OP & 0x07); - putreg((OP >> 3) & 0x07, DAR); - continue; - } - if ((OP & 0xC7) == 0x06) { /* MVI */ - putreg((OP >> 3) & 0x07, M[PC]); - PC++; - continue; - } - if ((OP & 0xCF) == 0x01) { /* LXI */ - DAR = M[PC] & 0x00ff; - PC++; - DAR = DAR | (M[PC] <<8) & 0xFF00;; - putpair((OP >> 4) & 0x03, DAR); - PC++; - continue; - } - if ((OP & 0xEF) == 0x0A) { /* LDAX */ - DAR = getpair((OP >> 4) & 0x03); - putreg(7, M[DAR]); - continue; - } - if ((OP & 0xEF) == 0x02) { /* STAX */ - DAR = getpair((OP >> 4) & 0x03); - M[DAR] = getreg(7); - continue; - } - - if ((OP & 0xF8) == 0xB8) { /* CMP */ - DAR = A & 0xFF; - DAR -= getreg(OP & 0x07); - setarith(DAR); - continue; - } - if ((OP & 0xC7) == 0xC2) { /* JMP */ - if (cond((OP >> 3) & 0x07) == 1) { - lo = M[PC]; - PC++; - hi = M[PC]; - PC++; - PC = (hi << 8) + lo; - } else { - PC += 2; - } - continue; - } - if ((OP & 0xC7) == 0xC4) { /* CALL */ - if (cond((OP >> 3) & 0x07) == 1) { - lo = M[PC]; - PC++; - hi = M[PC]; - PC++; - SP--; - M[SP] = (PC >> 8) & 0xff; - SP--; - M[SP] = PC & 0xff; - PC = (hi << 8) + lo; - } else { - PC += 2; - } - continue; - } - if ((OP & 0xC7) == 0xC0) { /* RET */ - if (cond((OP >> 3) & 0x07) == 1) { - PC = M[SP]; - SP++; - PC |= (M[SP] << 8) & 0xff00; - SP++; - } - continue; - } - if ((OP & 0xC7) == 0xC7) { /* RST */ - SP--; - M[SP] = (PC >> 8) & 0xff; - SP--; - M[SP] = PC & 0xff; - PC = OP & 0x38; - continue; - } - - if ((OP & 0xCF) == 0xC5) { /* PUSH */ - DAR = getpush((OP >> 4) & 0x03); - SP--; - M[SP] = (DAR >> 8) & 0xff; - SP--; - M[SP] = DAR & 0xff; - continue; - } - if ((OP & 0xCF) == 0xC1) { /*POP */ - DAR = M[SP]; - SP++; - DAR |= M[SP] << 8; - SP++; - putpush((OP >> 4) & 0x03, DAR); - continue; - } - if ((OP & 0xF8) == 0x80) { /* ADD */ - A += getreg(OP & 0x07); - setarith(A); - A = A & 0xFF; - continue; - } - if ((OP & 0xF8) == 0x88) { /* ADC */ - carry = 0; - if (C) carry = 1; - A += getreg(OP & 0x07); - A += carry; - setarith(A); - A = A & 0xFF; - continue; - } - if ((OP & 0xF8) == 0x90) { /* SUB */ - A -= getreg(OP & 0x07); - setarith(A); - A = A & 0xFF; - continue; - } - if ((OP & 0xF8) == 0x98) { /* SBB */ - carry = 0; - if (C) carry = 1; - A -= (getreg(OP & 0x07)) + carry ; - setarith(A); - A = A & 0xFF; - continue; - } - if ((OP & 0xC7) == 0x04) { /* INR */ - DAR = getreg((OP >> 3) & 0x07); - DAR++; - setinc(DAR); - DAR = DAR & 0xFF; - putreg((OP >> 3) & 0x07, DAR); - continue; - } - if ((OP & 0xC7) == 0x05) { /* DCR */ - DAR = getreg((OP >> 3) & 0x07); - DAR--; - setinc(DAR); - DAR = DAR & 0xFF; - putreg((OP >> 3) & 0x07, DAR); - continue; - } - if ((OP & 0xCF) == 0x03) { /* INX */ - DAR = getpair((OP >> 4) & 0x03); - DAR++; - DAR = DAR & 0xFFFF; - putpair((OP >> 4) & 0x03, DAR); - continue; - } - if ((OP & 0xCF) == 0x0B) { /* DCX */ - DAR = getpair((OP >> 4) & 0x03); - DAR--; - DAR = DAR & 0xFFFF; - putpair((OP >> 4) & 0x03, DAR); - continue; - } - if ((OP & 0xCF) == 0x09) { /* DAD */ - HL += getpair((OP >> 4) & 0x03); - C = 0; - if (HL & 0x10000) - C = 0200000; - HL = HL & 0xFFFF; - continue; - } - if ((OP & 0xF8) == 0xA0) { /* ANA */ - A &= getreg(OP & 0x07); - C = 0; - setlogical(A); - A &= 0xFF; - continue; - } - if ((OP & 0xF8) == 0xA8) { /* XRA */ - A ^= getreg(OP & 0x07); - C = 0; - setlogical(A); - A &= 0xFF; - continue; - } - if ((OP & 0xF8) == 0xB0) { /* ORA */ - A |= getreg(OP & 0x07); - C = 0; - setlogical(A); - A &= 0xFF; - continue; - } - - - - /* The Big Instruction Decode Switch */ - - switch (IR) { - - /* Logical instructions */ - - case 0376: { /* CPI */ - DAR = A & 0xFF; - DAR -= M[PC]; - PC++; - setarith(DAR); - break; - } - case 0346: { /* ANI */ - A &= M[PC]; - PC++; - C = AC = 0; - setlogical(A); - A &= 0xFF; - break; - } - case 0356: { /* XRI */ - A ^= M[PC]; - PC++; - C = AC = 0; - setlogical(A); - A &= 0xFF; - break; - } - case 0366: { /* ORI */ - A |= M[PC]; - PC++; - C = AC = 0; - setlogical(A); - A &= 0xFF; - break; - } - - /* Jump instructions */ - - case 0303: { /* JMP */ - lo = M[PC]; - PC++; - hi = M[PC]; - PC++; - PC = (hi << 8) + lo; - break; - } - case 0351: { /* PCHL */ - PC = HL; - break; - } - case 0315: { /* CALL */ - lo = M[PC]; - PC++; - hi = M[PC]; - PC++; - SP--; - M[SP] = (PC >> 8) & 0xff; - SP--; - M[SP] = PC & 0xff; - PC = (hi << 8) + lo; - break; - } - case 0311: { /* RET */ - PC = M[SP]; - SP++; - PC |= (M[SP] << 8) & 0xff00; - SP++; - break; - } - - /* Data Transfer Group */ - - case 062: { /* STA */ - lo = M[PC]; - PC++; - hi = M[PC]; - PC++; - DAR = (hi << 8) + lo; - M[DAR] = A; - break; - } - case 072: { /* LDA */ - lo = M[PC]; - PC++; - hi = M[PC]; - PC++; - DAR = (hi << 8) + lo; - A = M[DAR]; - break; - } - case 042: { /* SHLD */ - lo = M[PC]; - PC++; - hi = M[PC]; - PC++; - DAR = (hi << 8) + lo; - M[DAR] = HL; - DAR++; - M[DAR] = (HL >>8) & 0x00ff; - break; - } - case 052: { /* LHLD */ - lo = M[PC]; - PC++; - hi = M[PC]; - PC++; - DAR = (hi << 8) + lo; - HL = M[DAR]; - DAR++; - HL = HL | (M[DAR] <<8); - break; - } - case 0353: { /* XCHG */ - DAR = HL; - HL = DE; - DE = DAR; - break; - } - - /* Arithmetic Group */ - - case 0306: { /* ADI */ - A += M[PC]; - PC++; - setarith(A); - A = A & 0xFF; - break; - } - case 0316: { /* ACI */ - carry = 0; - if (C) carry = 1; - A += M[PC]; - A += carry; - PC++; - setarith(A); - A = A & 0xFF; - break; - } - case 0326: { /* SUI */ - A -= M[PC]; - PC++; - setarith(A); - A = A & 0xFF; - break; - } - case 0336: { /* SBI */ - carry = 0; - if (C) carry = 1; - A -= (M[PC] + carry); - PC++; - setarith(A); - A = A & 0xFF; - break; - } - case 047: { /* DAA */ - DAR = A & 0x0F; - if (DAR > 9 || AC > 0) { - DAR += 6; - A &= 0xF0; - A |= DAR & 0x0F; - if (DAR & 0x10) - AC = 0200000; - else - AC = 0; - } - DAR = (A >> 4) & 0x0F; - if (DAR > 9 || AC > 0) { - DAR += 6; - if (AC) DAR++; - A &= 0x0F; - A |= (DAR << 4); - } - if ((DAR << 4) & 0x100) - C = 0200000; - else - C = 0; - if (A & 0x80) { - S = 0200000; - } else { - S = 0; - } - if ((A & 0xff) == 0) - Z = 0200000; - else - Z = 0; - parity(A); - A = A & 0xFF; - break; - } - case 07: { /* RLC */ - C = 0; - C = (A << 9) & 0200000; - A = (A << 1) & 0xFF; - if (C) - A |= 0x01; - break; - } - case 017: { /* RRC */ - C = 0; - if ((A & 0x01) == 1) - C |= 0200000; - A = (A >> 1) & 0xFF; - if (C) - A |= 0x80; - break; - } - case 027: { /* RAL */ - DAR = C; - C = 0; - C = (A << 9) & 0200000; - A = (A << 1) & 0xFF; - if (DAR) - A |= 1; - else - A &= 0xFE; - break; - } - case 037: { /* RAR */ - DAR = C; - C = 0; - if ((A & 0x01) == 1) - C |= 0200000; - A = (A >> 1) & 0xFF; - if (DAR) - A |= 0x80; - else - A &= 0x7F; - break; - } - case 057: { /* CMA */ - A = ~ A; - A &= 0xFF; - break; - } - case 077: { /* CMC */ - C = ~ C; - C &= 0200000; - break; - } - case 067: { /* STC */ - C = 0200000; - break; - } - - /* Stack, I/O & Machine Control Group */ - - case 0: { /* NOP */ - break; - } - case 0343: { /* XTHL */ - lo = M[SP]; - hi = M[SP + 1]; - M[SP] = HL & 0xFF; - M[SP + 1] = (HL >> 8) & 0xFF; - HL = (hi << 8) + lo; - break; - } - case 0371: { /* SPHL */ - SP = HL; - break; - } - case 0373: { /* EI */ - INTE = 0200000; - break; - } - case 0363: { /* DI */ - INTE = 0; - break; - } - case 0333: { /* IN */ - DAR = M[PC] & 0xFF; - PC++; - if (DAR == 0xFF) { - A = (SR >> 8) & 0xFF; - } else { - A = dev_table[DAR].routine(0, 0); - } - break; - } - case 0323: { /* OUT */ - DAR = M[PC] & 0xFF; - PC++; - dev_table[DAR].routine(1, A); - break; - } - - default: { - if (cpu_unit.flags & UNIT_OPSTOP) { - reason = STOP_OPCODE; - PC--; - } - break; - } - } -} - -/* Simulation halted */ - -saved_PC = PC; -return reason; -} - -/* Test an 8080 flag condition and return 1 if true, 0 if false */ -int32 cond(int32 con) -{ - int32 r = 0; - - switch (con) { - case 0: - if (Z == 0) return (1); - break; - case 1: - if (Z != 0) return (1); - break; - case 2: - if (C == 0) return (1); - break; - case 3: - if (C != 0) return (1); - break; - case 4: - if (P == 0) return (1); - break; - case 5: - if (P != 0) return (1); - break; - case 6: - if (S == 0) return (1); - break; - case 7: - if (S != 0) return (1); - break; - default: - break; - } - return (0); -} - -/* Set the arry, ign, ero and

arity flags following - an arithmetic operation on 'reg'. -*/ - -void setarith(int32 reg) -{ - int32 bc = 0; - - if (reg & 0x100) - C = 0200000; - else - C = 0; - if (reg & 0x80) { - bc++; - S = 0200000; - } else { - S = 0; - } - if ((reg & 0xff) == 0) - Z = 0200000; - else - Z = 0; - AC = 0; - if (cpu_unit.flags & UNIT_CHIP) { - P = 0; /* parity is zero for *all* arith ops on Z80 */ - } else { - parity(reg); - } -} - -/* Set the arry, ign, ero amd

arity flags following - a logical (bitwise) operation on 'reg'. -*/ - -void setlogical(int32 reg) -{ - C = 0; - if (reg & 0x80) { - S = 0200000; - } else { - S = 0; - } - if ((reg & 0xff) == 0) - Z = 0200000; - else - Z = 0; - AC = 0; - parity(reg); -} - -/* Set the Parity (P) flag based on parity of 'reg', i.e., number - of bits on even: P=0200000, else P=0 -*/ - -void parity(int32 reg) -{ - int32 bc = 0; - - if (reg & 0x01) bc++; - if (reg & 0x02) bc++; - if (reg & 0x04) bc++; - if (reg & 0x08) bc++; - if (reg & 0x10) bc++; - if (reg & 0x20) bc++; - if (reg & 0x40) bc++; - if (reg & 0x80) bc++; - P = ~(bc << 16); - P &= 0200000; -} - -/* Set the ign, ero amd

arity flags following - an INR/DCR operation on 'reg'. -*/ - -void setinc(int32 reg) -{ - int32 bc = 0; - - if (reg & 0x80) { - bc++; - S = 0200000; - } else { - S = 0; - } - if ((reg & 0xff) == 0) - Z = 0200000; - else - Z = 0; - if (cpu_unit.flags & UNIT_CHIP) { - P = 0; /* parity is zero for *all* arith ops on Z80 */ - } else { - parity(reg); - } -} - -/* Get an 8080 register and return it */ -int32 getreg(int32 reg) -{ - switch (reg) { - case 0: - return ((BC >>8) & 0x00ff); - case 1: - return (BC & 0x00FF); - case 2: - return ((DE >>8) & 0x00ff); - case 3: - return (DE & 0x00ff); - case 4: - return ((HL >>8) & 0x00ff); - case 5: - return (HL & 0x00ff); - case 6: - return (M[HL]); - case 7: - return (A); - default: - break; - } - return 0; -} - -/* Put a value into an 8080 register from memory */ -void putreg(int32 reg, int32 val) -{ - switch (reg) { - case 0: - BC = BC & 0x00FF; - BC = BC | (val <<8); - break; - case 1: - BC = BC & 0xFF00; - BC = BC | val; - break; - case 2: - DE = DE & 0x00FF; - DE = DE | (val <<8); - break; - case 3: - DE = DE & 0xFF00; - DE = DE | val; - break; - case 4: - HL = HL & 0x00FF; - HL = HL | (val <<8); - break; - case 5: - HL = HL & 0xFF00; - HL = HL | val; - break; - case 6: - M[HL] = val & 0xff; - break; - case 7: - A = val & 0xff; - default: - break; - } -} - -/* Return the value of a selected register pair */ -int32 getpair(int32 reg) -{ - switch (reg) { - case 0: - return (BC); - case 1: - return (DE); - case 2: - return (HL); - case 3: - return (SP); - default: - break; - } - return 0; -} - -/* Return the value of a selected register pair, in PUSH - format where 3 means A& flags, not SP */ -int32 getpush(int32 reg) -{ - int32 stat; - - switch (reg) { - case 0: - return (BC); - case 1: - return (DE); - case 2: - return (HL); - case 3: - stat = A << 8; - if (S) stat |= 0x80; - if (Z) stat |= 0x40; - if (AC) stat |= 0x10; - if (P) stat |= 0x04; - stat |= 0x02; - if (C) stat |= 0x01; - return (stat); - default: - break; - } - return 0; -} - - -/* Place data into the indicated register pair, in PUSH - format where 3 means A& flags, not SP */ -void putpush(int32 reg, int32 data) -{ - switch (reg) { - case 0: - BC = data; - break; - case 1: - DE = data; - break; - case 2: - HL = data; - break; - case 3: - A = (data >> 8) & 0xff; - S = Z = AC = P = C = 0; - if (data & 0x80) S = 0200000; - if (data & 0x40) Z = 0200000; - if (data & 0x10) AC = 0200000; - if (data & 0x04) P = 0200000; - if (data & 0x01) C = 0200000; - break; - default: - break; - } -} - - -/* Put a value into an 8080 register pair */ -void putpair(int32 reg, int32 val) -{ - switch (reg) { - case 0: - BC = val; - break; - case 1: - DE = val; - break; - case 2: - HL = val; - break; - case 3: - SP = val; - break; - default: - break; - } -} - - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -C = 0; -Z = 0; -saved_PC = 0; -int_req = 0; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & 0377; -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ - if (addr >= MEMSIZE) return SCPE_NXM; - M[addr] = val & 0377; - return SCPE_OK; -} - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; -if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_OK; -MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; -return SCPE_OK; -} - -int32 nulldev(int32 flag, int32 data) -{ - if (flag == 0) - return (0377); - return 0; -} - diff --git a/ALTAIR/altair_defs.h b/ALTAIR/altair_defs.h deleted file mode 100644 index 5786247e..00000000 --- a/ALTAIR/altair_defs.h +++ /dev/null @@ -1,42 +0,0 @@ -/* altair_defs.h: MITS Altair simulator definitions - - Copyright (c) 1997-2003, Charles E. Owen - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Memory */ - -#define MAXMEMSIZE 65536 /* max memory size */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define ADDRMASK (MAXMEMSIZE - 1) /* address mask */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_OPCODE 4 - diff --git a/ALTAIR/altair_dsk.c b/ALTAIR/altair_dsk.c deleted file mode 100644 index 5ae54cf5..00000000 --- a/ALTAIR/altair_dsk.c +++ /dev/null @@ -1,366 +0,0 @@ -/* altair_dsk.c: MITS Altair 88-DISK Simulator - - Copyright (c) 1997-2003, Charles E. Owen - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. - - The 88_DISK is a 8-inch floppy controller which can control up - to 16 daisy-chained Pertec FD-400 hard-sectored floppy drives. - Each diskette has physically 77 tracks of 32 137-byte sectors - each. - - The controller is interfaced to the CPU by use of 3 I/O addreses, - standardly, these are device numbers 10, 11, and 12 (octal). - - Address Mode Function - ------- ---- -------- - - 10 Out Selects and enables Controller and Drive - 10 In Indicates status of Drive and Controller - 11 Out Controls Disk Function - 11 In Indicates current sector position of disk - 12 Out Write data - 12 In Read data - - Drive Select Out (Device 10 OUT): - - +---+---+---+---+---+---+---+---+ - | C | X | X | X | Device | - +---+---+---+---+---+---+---+---+ - - C = If this bit is 1, the disk controller selected by 'device' is - cleared. If the bit is zero, 'device' is selected as the - device being controlled by subsequent I/O operations. - X = not used - Device = value zero thru 15, selects drive to be controlled. - - Drive Status In (Device 10 IN): - - +---+---+---+---+---+---+---+---+ - | R | Z | I | X | X | H | M | W | - +---+---+---+---+---+---+---+---+ - - W - When 0, write circuit ready to write another byte. - M - When 0, head movement is allowed - H - When 0, indicates head is loaded for read/write - X - not used (will be 0) - I - When 0, indicates interrupts enabled (not used this simulator) - Z - When 0, indicates head is on track 0 - R - When 0, indicates that read circuit has new byte to read - - Drive Control (Device 11 OUT): - - +---+---+---+---+---+---+---+---+ - | W | C | D | E | U | H | O | I | - +---+---+---+---+---+---+---+---+ - - I - When 1, steps head IN one track - O - When 1, steps head OUT out track - H - When 1, loads head to drive surface - U - When 1, unloads head - E - Enables interrupts (ignored this simulator) - D - Disables interrupts (ignored this simulator) - C - When 1 lowers head current (ignored this simulator) - W - When 1, starts Write Enable sequence: W bit on device 10 - (see above) will go 1 and data will be read from port 12 - until 137 bytes have been read by the controller from - that port. The W bit will go off then, and the sector data - will be written to disk. Before you do this, you must have - stepped the track to the desired number, and waited until - the right sector number is presented on device 11 IN, then - set this bit. - - Sector Position (Device 11 IN): - - As the sectors pass by the read head, they are counted and the - number of the current one is available in this register. - - +---+---+---+---+---+---+---+---+ - | X | X | Sector Number | T | - +---+---+---+---+---+---+---+---+ - - X = Not used - Sector number = binary of the sector number currently under the - head, 0-31. - T = Sector True, is a 1 when the sector is positioned to read or - write. - -*/ - -#include - -#include "altair_defs.h" - -#define UNIT_V_ENABLE (UNIT_V_UF + 0) /* Write Enable */ -#define UNIT_ENABLE (1 << UNIT_V_ENABLE) - -#define DSK_SECTSIZE 137 -#define DSK_SECT 32 -#define DSK_TRACSIZE 4384 -#define DSK_SURF 1 -#define DSK_CYL 77 -#define DSK_SIZE (DSK_SECT * DSK_SURF * DSK_CYL * DSK_SECTSIZE) - -t_stat dsk_svc (UNIT *uptr); -t_stat dsk_reset (DEVICE *dptr); -void writebuf(); - -extern int32 PCX; - -/* Global data on status */ - -int32 cur_disk = 8; /* Currently selected drive */ -int32 cur_track[9] = {0, 0, 0, 0, 0, 0, 0, 0, 377}; -int32 cur_sect[9] = {0, 0, 0, 0, 0, 0, 0, 0, 377}; -int32 cur_byte[9] = {0, 0, 0, 0, 0, 0, 0, 0, 377}; -int32 cur_flags[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; - -char dskbuf[137]; /* Data Buffer */ -int32 dirty = 0; /* 1 when buffer has unwritten data in it */ -UNIT *dptr; /* fileref to write dirty buffer to */ - -int32 dsk_rwait = 100; /* rotate latency */ - - -/* 88DSK Standard I/O Data Structures */ - -UNIT dsk_unit[] = { - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) } - }; - -REG dsk_reg[] = { - { ORDATA (DISK, cur_disk, 4) }, - { NULL } }; - -DEVICE dsk_dev = { - "DSK", dsk_unit, dsk_reg, NULL, - 8, 10, 31, 1, 8, 8, - NULL, NULL, &dsk_reset, - NULL, NULL, NULL }; - -/* Service routines to handle simlulator functions */ - -/* service routine - actually gets char & places in buffer */ - -t_stat dsk_svc (UNIT *uptr) -{ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat dsk_reset (DEVICE *dptr) -{ -cur_disk = 0; -return SCPE_OK; -} - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. - - Each function is passed an 'io' flag, where 0 means a read from - the port, and 1 means a write to the port. On input, the actual - input is passed as the return value, on output, 'data' is written - to the device. -*/ - -/* Disk Controller Status/Select */ - -/* IMPORTANT: The status flags read by port 8 IN instruction are - INVERTED, that is, 0 is true and 1 is false. To handle this, the - simulator keeps it's own status flags as 0=false, 1=true; and - returns the COMPLEMENT of the status flags when read. This makes - setting/testing of the flag bits more logical, yet meets the - simulation requirement that they are reversed in hardware. -*/ - -int32 dsk10(int32 io, int32 data) -{ - - if (io == 0) { /* IN: return flags */ - return ((~cur_flags[cur_disk]) & 0xFF); /* Return the COMPLEMENT! */ - } - - /* OUT: Controller set/reset/enable/disable */ - - if (dirty == 1) - writebuf(); - - /*printf("\n[%o] OUT 10: %x", PCX, data);*/ - cur_disk = data & 0x0F; - if (data & 0x80) { - cur_flags[cur_disk] = 0; /* Disable drive */ - cur_sect[cur_disk = 0377]; - cur_byte[cur_disk = 0377]; - return (0); - } - cur_flags[cur_disk] = 0x1A; /* Enable: head move true */ - cur_sect[cur_disk] = 0377; /* reset internal counters */ - cur_byte[cur_disk] = 0377; - if (cur_track[cur_disk] == 0) - cur_flags[cur_disk] |= 0x40; /* track 0 if there */ - return (0); -} - -/* Disk Drive Status/Functions */ - -int32 dsk11(int32 io, int32 data) -{ - int32 stat; - - if (io == 0) { /* Read sector position */ - /*printf("\n[%o] IN 11", PCX);*/ - if (dirty == 1) - writebuf(); - if (cur_flags[cur_disk] & 0x04) { /* head loaded? */ - cur_sect[cur_disk]++; - if (cur_sect[cur_disk] > 31) - cur_sect[cur_disk] = 0; - cur_byte[cur_disk] = 0377; - stat = cur_sect[cur_disk] << 1; - stat &= 0x3E; /* return 'sector true' bit = 0 (true) */ - stat |= 0xC0; /* set on 'unused' bits */ - return (stat); - } else { - return (0); /* head not loaded - return 0 */ - } - } - - /* Drive functions */ - - if (cur_disk > 7) - return (0); /* no drive selected - can do nothin */ - - /*printf("\n[%o] OUT 11: %x", PCX, data);*/ - if (data & 0x01) { /* Step head in */ - cur_track[cur_disk]++; - if (cur_track[cur_disk] > 76 ) - cur_track[cur_disk] = 76; - if (dirty == 1) - writebuf(); - cur_sect[cur_disk] = 0377; - cur_byte[cur_disk] = 0377; - } - - if (data & 0x02) { /* Step head out */ - cur_track[cur_disk]--; - if (cur_track[cur_disk] < 0) { - cur_track[cur_disk] = 0; - cur_flags[cur_disk] |= 0x40; /* track 0 if there */ - } - if (dirty == 1) - writebuf(); - cur_sect[cur_disk] = 0377; - cur_byte[cur_disk] = 0377; - } - - if (dirty == 1) - writebuf(); - - if (data & 0x04) { /* Head load */ - cur_flags[cur_disk] |= 0x04; /* turn on head loaded bit */ - cur_flags[cur_disk] |= 0x80; /* turn on 'read data available */ - } - - if (data & 0x08) { /* Head Unload */ - cur_flags[cur_disk] &= 0xFB; /* off on 'head loaded' */ - cur_flags[cur_disk] &= 0x7F; /* off on 'read data avail */ - cur_sect[cur_disk] = 0377; - cur_byte[cur_disk] = 0377; - } - - /* Interrupts & head current are ignored */ - - if (data & 0x80) { /* write sequence start */ - cur_byte[cur_disk] = 0; - cur_flags[cur_disk] |= 0x01; /* enter new write data on */ - } - return 0; -} - -/* Disk Data In/Out*/ - -int32 dsk12(int32 io, int32 data) -{ - static int32 rtn, i; - static long pos; - UNIT *uptr; - - uptr = dsk_dev.units + cur_disk; - if (io == 0) { - if ((i = cur_byte[cur_disk]) < 138) { /* just get from buffer */ - cur_byte[cur_disk]++; - return (dskbuf[i] & 0xFF); - } - /* physically read the sector */ - /*printf("\n[%o] IN 12 (READ) T%d S%d", PCX, cur_track[cur_disk], - cur_sect[cur_disk]);*/ - pos = DSK_TRACSIZE * cur_track[cur_disk]; - pos += DSK_SECTSIZE * cur_sect[cur_disk]; - rtn = fseek(uptr -> fileref, pos, 0); - rtn = fread(dskbuf, 137, 1, uptr -> fileref); - cur_byte[cur_disk] = 1; - return (dskbuf[0] & 0xFF); - } else { - if (cur_byte[cur_disk] > 136) { - i = cur_byte[cur_disk]; - dskbuf[i] = data & 0xFF; - writebuf(); - return (0); - } - i = cur_byte[cur_disk]; - dirty = 1; - dptr = uptr; - dskbuf[i] = data & 0xFF; - cur_byte[cur_disk]++; - return (0); - } -} - -void writebuf() -{ - long pos; - int32 rtn, i; - - i = cur_byte[cur_disk]; /* null-fill rest of sector if any */ - while (i < 138) { - dskbuf[i] = 0; - i++; - } - /*printf("\n[%o] OUT 12 (WRITE) T%d S%d", PCX, cur_track[cur_disk], - cur_sect[cur_disk]); i = getch(); */ - pos = DSK_TRACSIZE * cur_track[cur_disk]; /* calc file pos */ - pos += DSK_SECTSIZE * cur_sect[cur_disk]; - rtn = fseek(dptr -> fileref, pos, 0); - rtn = fwrite(dskbuf, 137, 1, dptr -> fileref); - cur_flags[cur_disk] &= 0xFE; /* ENWD off */ - cur_byte[cur_disk] = 0377; - dirty = 0; - return; -} diff --git a/ALTAIR/altair_sio.c b/ALTAIR/altair_sio.c deleted file mode 100644 index 9c212160..00000000 --- a/ALTAIR/altair_sio.c +++ /dev/null @@ -1,258 +0,0 @@ -/* altair_sio: MITS Altair serial I/O card - - Copyright (c) 1997-2003, Charles E. Owen - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. - - These functions support a simulated MITS 2SIO interface card. - The card had two physical I/O ports which could be connected - to any serial I/O device that would connect to a current loop, - RS232, or TTY interface. Available baud rates were jumper - selectable for each port from 110 to 9600. - - All I/O is via programmed I/O. Each each has a status port - and a data port. A write to the status port can select - some options for the device (0x03 will reset the port). - A read of the status port gets the port status: - - +---+---+---+---+---+---+---+---+ - | X X X X X X O I | - +---+---+---+---+---+---+---+---+ - - I - A 1 in this bit position means a character has been received - on the data port and is ready to be read. - O - A 1 in this bit means the port is ready to receive a character - on the data port and transmit it out over the serial line. - - A read to the data port gets the buffered character, a write - to the data port writes the character to the device. -*/ - -#include - -#include "altair_defs.h" - -#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */ -#define UNIT_ANSI (1 << UNIT_V_ANSI) - -t_stat sio_svc (UNIT *uptr); -t_stat sio_reset (DEVICE *dptr); -t_stat ptr_svc (UNIT *uptr); -t_stat ptr_reset (DEVICE *dptr); -t_stat ptp_svc (UNIT *uptr); -t_stat ptp_reset (DEVICE *dptr); - -int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */ - -/* 2SIO Standard I/O Data Structures */ - -UNIT sio_unit = { UDATA (&sio_svc, 0, 0), - KBD_POLL_WAIT }; - -REG sio_reg[] = { - { ORDATA (DATA, sio_unit.buf, 8) }, - { ORDATA (STAT, sio_unit.u3, 8) }, - { NULL } }; - -MTAB sio_mod[] = { - { UNIT_ANSI, 0, "TTY", "TTY", NULL }, - { UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL }, - { 0 } }; - -DEVICE sio_dev = { - "2SIO", &sio_unit, sio_reg, sio_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &sio_reset, - NULL, NULL, NULL }; - -UNIT ptr_unit = { UDATA (&ptr_svc, UNIT_SEQ + UNIT_ATTABLE, 0), - KBD_POLL_WAIT }; - -REG ptr_reg[] = { - { ORDATA (DATA, ptr_unit.buf, 8) }, - { ORDATA (STAT, ptr_unit.u3, 8) }, - { ORDATA (POS, ptr_unit.pos, T_ADDR_W) }, - { NULL } }; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - NULL, NULL, NULL }; - -UNIT ptp_unit = { UDATA (&ptp_svc, UNIT_SEQ + UNIT_ATTABLE, 0), - KBD_POLL_WAIT }; - -REG ptp_reg[] = { - { ORDATA (DATA, ptp_unit.buf, 8) }, - { ORDATA (STAT, ptp_unit.u3, 8) }, - { ORDATA (POS, ptp_unit.pos, T_ADDR_W) }, - { NULL } }; - -DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptp_reset, - NULL, NULL, NULL }; - -/* Service routines to handle simulator functions */ - -/* service routine - actually gets char & places in buffer */ - -int32 sio_svc (UNIT *uptr) -{ - int32 temp; - - sim_activate (&sio_unit, sio_unit.wait); /* continue poll */ - if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) - return temp; /* no char or error? */ - sio_unit.buf = temp & 0377; /* Save char */ - sio_unit.u3 |= 0x01; /* Set status */ - - /* Do any special character handling here */ - - sio_unit.pos++; - return SCPE_OK; -} - - -int32 ptr_svc (UNIT *uptr) -{ - return SCPE_OK; -} - -int32 ptp_svc (UNIT *uptr) -{ - return SCPE_OK; -} - - -/* Reset routine */ - -int32 sio_reset (DEVICE *dptr) -{ - sio_unit.buf = 0; /* Data */ - sio_unit.u3 = 0x02; /* Status */ - sim_activate (&sio_unit, sio_unit.wait); /* activate unit */ - return SCPE_OK; -} - - -int32 ptr_reset (DEVICE *dptr) -{ - ptr_unit.buf = 0; - ptr_unit.u3 = 0x02; - sim_cancel (&ptr_unit); /* deactivate unit */ - return SCPE_OK; -} - -int32 ptp_reset (DEVICE *dptr) -{ - ptp_unit.buf = 0; - ptp_unit.u3 = 0x02; - sim_cancel (&ptp_unit); /* deactivate unit */ - return SCPE_OK; -} - - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. - - Each function is passed an 'io' flag, where 0 means a read from - the port, and 1 means a write to the port. On input, the actual - input is passed as the return value, on output, 'data' is written - to the device. -*/ - -int32 sio0s(int32 io, int32 data) -{ - if (io == 0) { - return (sio_unit.u3); - } else { - if (data == 0x03) { /* reset port! */ - sio_unit.u3 = 0x02; - sio_unit.buf = 0; - sio_unit.pos = 0; - } - return (0); - } -} - -int32 sio0d(int32 io, int32 data) -{ - if (io == 0) { - sio_unit.u3 = sio_unit.u3 & 0xFE; - return (sio_unit.buf); - } else { - sim_putchar(data); - } - return 0; -} - -/* Port 2 controls the PTR/PTP devices */ - -int32 sio1s(int32 io, int32 data) -{ - if (io == 0) { - if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ - return 0x02; - if (ptr_unit.u3 != 0) /* No more data? */ - return 0x02; - return (0x03); /* ready to read/write */ - } else { - if (data == 0x03) { - ptr_unit.u3 = 0; - ptr_unit.buf = 0; - ptr_unit.pos = 0; - ptp_unit.u3 = 0; - ptp_unit.buf = 0; - ptp_unit.pos = 0; - } - return (0); - } -} - -int32 sio1d(int32 io, int32 data) -{ - int32 temp; - UNIT *uptr; - - if (io == 0) { - if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ - return 0; - if (ptr_unit.u3 != 0) - return 0; - uptr = ptr_dev.units; - if ((temp = getc(uptr -> fileref)) == EOF) { /* end of file? */ - ptr_unit.u3 = 0x01; - return 0; - } - ptr_unit.pos++; - return (temp & 0xFF); - } else { - uptr = ptp_dev.units; - putc(data, uptr -> fileref); - ptp_unit.pos++; - } - return 0; -} - diff --git a/ALTAIR/altair_sys.c b/ALTAIR/altair_sys.c deleted file mode 100644 index cf558d41..00000000 --- a/ALTAIR/altair_sys.c +++ /dev/null @@ -1,302 +0,0 @@ -/* altair_sys.c: MITS Altair system interface - - Copyright (c) 1997-2003, Charles E. Owen - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. -*/ - -#include -#include "altair_defs.h" - -extern DEVICE cpu_dev; -extern DEVICE dsk_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern DEVICE sio_dev; -extern DEVICE ptr_dev; -extern DEVICE ptp_dev; -extern DEVICE lpt_dev; -extern unsigned char M[]; -extern int32 saved_PC; - -/* SCP data structures - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words needed for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "Altair 8800"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { &cpu_dev, &sio_dev, &ptr_dev, - &ptp_dev, &dsk_dev, NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unknown I/O Instruction", - "HALT instruction", - "Breakpoint", - "Invalid Opcode" }; - -static const char *opcode[] = { -"NOP", "LXI B", "STAX B", "INX B", /* 000-003 */ -"INR B", "DCR B", "MVI B", "RLC", /* 004-007 */ -"???", "DAD B", "LDAX B", "DCX B", /* 010-013 */ -"INR C", "DCR C", "MVI C", "RRC", /* 014-017 */ -"???", "LXI D", "STAX D", "INX D", /* 020-023 */ -"INR D", "DCR D", "MVI D", "RAL", /* 024-027 */ -"???", "DAD D", "LDAX D", "DCX D", /* 030-033 */ -"INR E", "DCR E", "MVI E", "RAR", /* 034-037 */ -"???", "LXI H", "SHLD", "INX H", /* 040-043 */ -"INR H", "DCR H", "MVI H", "DAA", /* 044-047 */ -"???", "DAD H", "LHLD", "DCX H", /* 050-053 */ -"INR L", "DCR L", "MVI L", "CMA", /* 054-057 */ -"???", "LXI SP", "STA", "INX SP", /* 060-063 */ -"INR M", "DCR M", "MVI M", "STC", /* 064-067 */ -"???", "DAD SP", "LDA", "DCX SP", /* 070-073 */ -"INR A", "DCR A", "MVI A", "CMC", /* 074-077 */ -"MOV B,B", "MOV B,C", "MOV B,D", "MOV B,E", /* 100-103 */ -"MOV B,H", "MOV B,L", "MOV B,M", "MOV B,A", /* 104-107 */ -"MOV C,B", "MOV C,C", "MOV C,D", "MOV C,E", /* 110-113 */ -"MOV C,H", "MOV C,L", "MOV C,M", "MOV C,A", /* 114-117 */ -"MOV D,B", "MOV D,C", "MOV D,D", "MOV D,E", /* 120-123 */ -"MOV D,H", "MOV D,L", "MOV D,M", "MOV D,A", /* 124-127 */ -"MOV E,B", "MOV E,C", "MOV E,D", "MOV E,E", /* 130-133 */ -"MOV E,H", "MOV E,L", "MOV E,M", "MOV E,A", /* 134-137 */ -"MOV H,B", "MOV H,C", "MOV H,D", "MOV H,E", /* 140-143 */ -"MOV H,H", "MOV H,L", "MOV H,M", "MOV H,A", /* 144-147 */ -"MOV L,B", "MOV L,C", "MOV L,D", "MOV L,E", /* 150-153 */ -"MOV L,H", "MOV L,L", "MOV L,M", "MOV L,A", /* 154-157 */ -"MOV M,B", "MOV M,C", "MOV M,D", "MOV M,E", /* 160-163 */ -"MOV M,H", "MOV M,L", "HLT", "MOV M,A", /* 164-167 */ -"MOV A,B", "MOV A,C", "MOV A,D", "MOV A,E", /* 170-173 */ -"MOV A,H", "MOV A,L", "MOV A,M", "MOV A,A", /* 174-177 */ -"ADD B", "ADD C", "ADD D", "ADD E", /* 200-203 */ -"ADD H", "ADD L", "ADD M", "ADD A", /* 204-207 */ -"ADC B", "ADC C", "ADC D", "ADC E", /* 210-213 */ -"ADC H", "ADC L", "ADC M", "ADC A", /* 214-217 */ -"SUB B", "SUB C", "SUB D", "SUB E", /* 220-223 */ -"SUB H", "SUB L", "SUB M", "SUB A", /* 224-227 */ -"SBB B", "SBB C", "SBB D", "SBB E", /* 230-233 */ -"SBB H", "SBB L", "SBB M", "SBB A", /* 234-237 */ -"ANA B", "ANA C", "ANA D", "ANA E", /* 240-243 */ -"ANA H", "ANA L", "ANA M", "ANA A", /* 244-247 */ -"XRA B", "XRA C", "XRA D", "XRA E", /* 250-253 */ -"XRA H", "XRA L", "XRA M", "XRA A", /* 254-257 */ -"ORA B", "ORA C", "ORA D", "ORA E", /* 260-263 */ -"ORA H", "ORA L", "ORA M", "ORA A", /* 264-267 */ -"CMP B", "CMP C", "CMP D", "CMP E", /* 270-273 */ -"CMP H", "CMP L", "CMP M", "CMP A", /* 274-277 */ -"RNZ", "POP B", "JNZ", "JMP", /* 300-303 */ -"CNZ", "PUSH B", "ADI", "RST 0", /* 304-307 */ -"RZ", "RET", "JZ", "???", /* 310-313 */ -"CZ", "CALL", "ACI", "RST 1", /* 314-317 */ -"RNC", "POP D", "JNC", "OUT", /* 320-323 */ -"CNC", "PUSH D", "SUI", "RST 2", /* 324-327 */ -"RC", "???", "JC", "IN", /* 330-333 */ -"CC", "???", "SBI", "RST 3", /* 334-337 */ -"RPO", "POP H", "JPO", "XTHL", /* 340-343 */ -"CPO", "PUSH H", "ANI", "RST 4", /* 344-347 */ -"RPE", "PCHL", "JPE", "XCHG", /* 350-353 */ -"CPE", "???", "XRI", "RST 5", /* 354-357 */ -"RP", "POP PSW", "JP", "DI", /* 360-363 */ -"CP", "PUSH PSW", "ORI", "RST 6", /* 364-367 */ -"RM", "SPHL", "JM", "EI", /* 370-373 */ -"CM", "???", "CPI", "RST 7", /* 374-377 */ - }; - -int32 oplen[256] = { -1,3,1,1,1,1,2,1,0,1,1,1,1,1,2,1,0,3,1,1,1,1,2,1,0,1,1,1,1,1,2,1, -0,3,3,1,1,1,2,1,0,1,3,1,1,1,2,1,0,3,3,1,1,1,2,1,0,1,3,1,1,1,2,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,3,3,3,1,2,1,1,1,3,0,3,3,2,1,1,1,3,2,3,1,2,1,1,0,3,2,3,0,2,1, -1,1,3,1,3,1,2,1,1,1,3,1,3,0,2,1,1,1,3,1,3,1,2,1,1,1,3,1,3,0,2,1 }; - -/* This is the binary loader. The input file is considered to be - a string of literal bytes with no format special format. The - load starts at the current value of the PC. -*/ - -int32 sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 i, addr = 0, cnt = 0; - -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; -addr = saved_PC; -while ((i = getc (fileref)) != EOF) { - M[addr] = i; - addr++; - cnt++; - } /* end while */ -printf ("%d Bytes loaded.\n", cnt); -return (SCPE_OK); -} - -/* Symbolic output - - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - status = error code -*/ - -int32 fprint_sym (FILE *of, int32 addr, unsigned int32 *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, c1, c2, inst, adr; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -c1 = (val[0] >> 8) & 0177; -c2 = val[0] & 0177; -if (sw & SWMASK ('A')) { - fprintf (of, (c2 < 040)? "<%03o>": "%c", c2); - return SCPE_OK; } -if (sw & SWMASK ('C')) { - fprintf (of, (c1 < 040)? "<%03o>": "%c", c1); - fprintf (of, (c2 < 040)? "<%03o>": "%c", c2); - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; -inst = val[0]; -fprintf (of, "%s", opcode[inst]); -if (oplen[inst] == 2) { - if (strchr(opcode[inst], ' ') != NULL) - fprintf (of, ","); - else fprintf (of, " "); - fprintf (of, "%o", val[1]); -} -if (oplen[inst] == 3) { - adr = val[1] & 0xFF; - adr |= (val[2] << 8) & 0xff00; - if (strchr(opcode[inst], ' ') != NULL) - fprintf (of, ","); - else fprintf (of, " "); - fprintf (of, "%o", adr); -} -return -(oplen[inst] - 1); -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = error status -*/ - -int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, unsigned int32 *val, int32 sw) -{ -int32 cflag, i = 0, j, r; -char gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ -if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (unsigned int) cptr[0]; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = ((unsigned int) cptr[0] << 8) + (unsigned int) cptr[1]; - return SCPE_OK; } - -/* An instruction: get opcode (all characters until null, comma, - or numeric (including spaces). -*/ - -while (1) { - if (*cptr == ',' || *cptr == '\0' || - isdigit(*cptr)) - break; - gbuf[i] = toupper(*cptr); - cptr++; - i++; -} - -/* Allow for RST which has numeric as part of opcode */ - -if (toupper(gbuf[0]) == 'R' && - toupper(gbuf[1]) == 'S' && - toupper(gbuf[2]) == 'T') { - gbuf[i] = toupper(*cptr); - cptr++; - i++; -} - -/* Allow for 'MOV' which is only opcode that has comma in it. */ - -if (toupper(gbuf[0]) == 'M' && - toupper(gbuf[1]) == 'O' && - toupper(gbuf[2]) == 'V') { - gbuf[i] = toupper(*cptr); - cptr++; - i++; - gbuf[i] = toupper(*cptr); - cptr++; - i++; -} - -/* kill trailing spaces if any */ -gbuf[i] = '\0'; -for (j = i - 1; gbuf[j] == ' '; j--) { - gbuf[j] = '\0'; -} - -/* find opcode in table */ -for (j = 0; j < 256; j++) { - if (strcmp(gbuf, opcode[j]) == 0) - break; -} -if (j > 255) /* not found */ - return SCPE_ARG; - -val[0] = j; /* store opcode */ -if (oplen[j] < 2) /* if 1-byter we are done */ - return SCPE_OK; -if (*cptr == ',') cptr++; -cptr = get_glyph(cptr, gbuf, 0); /* get address */ -sscanf(gbuf, "%o", &r); -if (oplen[j] == 2) { - val[1] = r & 0xFF; - return (-1); -} -val[1] = r & 0xFF; -val[2] = (r >> 8) & 0xFF; -return (-2); -} diff --git a/AltairZ80/altairZ80.txt b/AltairZ80/altairZ80.txt deleted file mode 100644 index 48f83a1e..00000000 --- a/AltairZ80/altairZ80.txt +++ /dev/null @@ -1,895 +0,0 @@ -Altair 8800 Simulator with Z80 support -====================================== - -0. Revision History - -- 25-Feb-2003, Peter Schorn (added support for real time simulation) -- 9-Oct-2002, Peter Schorn (added support for simulated hard disk) -- 28-Sep-2002, Peter Schorn (number of tracks per disk can be configured) -- 19-Sep-2002, Peter Schorn (added WARNROM feature) -- 31-Aug-2002, Peter Schorn (added extended ROM features suggested - by Scott LaBombard) -- 4-May-2002, Peter Schorn (added description of MP/M II sample software) -- 28-Apr-2002, Peter Schorn (added periodic timer interrupts and three - additional consoles) -- 15-Apr-2002, Peter Schorn (added memory breakpoint) -- 7-Apr-2002, Peter Schorn (added ROM / NOROM switch) -Original version of this document written by Charles E Owen - - -1. Background. - - The MITS (Micro Instrumentation and Telemetry Systems) Altair 8800 was -announced on the January 1975 cover of Popular Electronics, which boasted -you could buy and build this powerful computer kit for only $397. The kit -consisted at that time of only the parts to build a case, power supply, -card cage (18 slots), CPU card, and memory card with 256 *bytes* of memory. -Still, thousands were ordered within the first few months after the -announcement, starting the personal computer revolution as we know it -today. - - Many laugh at the small size of the that first kit, noting there were no -peripherals and the 256 byte memory size. But the computer was an open -system, and by 1977 MITS and many other small startups had added many -expansion cards to make the Altair quite a respectable little computer. The -"Altair Bus" that made this possible was soon called the S-100 Bus, later -adopted as an industry standard, and eventually became the IEE-696 Bus. - - -2. Hardware - - We are simulating a fairly "loaded" Altair 8800 from about 1977, with the -following configuration: - - device simulates - name(s) - - CPU Altair 8800 with Intel 8080 CPU board, 62KB - of RAM, 2K of EPROM with start boot ROM. - SIO MITS 88-2SIO Dual Serial Interface Board. Port 1 - is assumed to be connected to a serial "glass - TTY" that is your terminal running the Simulator. - PTR Paper Tape Reader attached to port 2 of the 2SIO board. - PTP Paper Tape Punch attached to port 2 of the - 2SIO board. This also doubles as a printer port. - DSK MITS 88-DISK Floppy Disk controller with up - to eight drives. - - -2.1 CPU - - We have 2 CPU options that were not present on the original machine but -are useful in the simulator. We also allow you to select memory sizes, but -be aware that some sample software requires the full 64K (i.e. CP/M) and -the MITS Disk Basic and Altair DOS require about a minimum of 24K. - - SET CPU 8080 Simulates the 8080 CPU (normal) - SET CPU Z80 Simulates the Z80 CPU. Note that some software (e.g. most - original Altair software such as 4K Basic) requires an 8080 CPU and - will not or not properly run on a Z80. This is mainly due to the use - of the parity flag on the 8080 which has not always the same - semantics on the Z80. - - SET CPU ITRAP Causes the simulator to halt if an invalid opcode - is detected (depending on the chosen CPU). - SET CPU NOITRAP Does not stop on an invalid Opcode. This is - how the real 8080 works. - - SET CPU 4K - SET CPU 8K - SET CPU 12K - SET CPU 16K - ...... (in 4K steps) - SET CPU 64K All these set various CPU memory configurations. - - SET CPU BANKED Enables the banked memory support. The simulated memory - has eight banks with address range 0..'common' (see registers below) - and a common area from 'common' to 0xfff which is common to all - banks. The currently active bank is determined by register 'bank' - (see below). You can only switch to banked memory if the memory - is set to 64K. The banked memory is used by CP/M 3. - - SET CPU NONBANKED Disables banked memory support. - - SET CPU ROM Enables the ROM from address 'ROMLOW' to 'ROMHIGH' - (see below under CPU Registers) and prevents write access - to these locations. This is the default setting. - - SET CPU NOROM Disables the ROM. - - SET CPU ALTAIRROM Enables the slightly modified but downwards compatible - Altair boot ROM at addresses 0FF00 to 0FFFF. This is the default. - - SET CPU NOALTAIRROM Disables standard Altair ROM behavior. - - SET CPU WARNROM Enables warning messages to be printed when the CPU - attempts to write into ROM or into non-existing memory. Also prints - a warning message if the CPU attempts to read from non-existing - memory. - - SET CPU NOWARNROM Suppreses all warning message of "WARNROM". Note that - some software tries on purpose to write to ROM in order to detect - the available RAM. - - The BOOT EPROM card starts at address 0FF00 if it has been enabled by -'SET CPU ALTAIRROM'. Jumping to this address will boot drive 0 of the -floppy controller (CPU must be set to ROM or equivalent code must be -present). If no valid bootable software is present there the machine -crashes. This is historically accurate behavior. - - The real 8080, on receiving a HLT (Halt) instruction, freezes the -processor and only an interrupt or CPU hardware reset will restore it. The -simulator is alot nicer, it will halt but send you back to the simulator -command line. - -CPU Registers include the following: - - Name Size Comment - - PC 16 The Program Counter - AF 16 The accumulator and the flag register - F = S Z - AC - P/V N C - S = Sign flag. - Z = Zero Flag. - AC = Auxillary Carry flag. - P/V = Parity flag on 8080 - Parity / Overflow flag on Z80 - - = not used (undefined) - N = Internal sign flag - C = Carry flag. - BC 16 The BC register pair. - Register B is the high 8 bits, C is the lower 8 bits - DE 16 The DE register pair. - Register D is the high 8 bits, E is the lower 8 bits. - HL 16 The HL register pair. - Register H is the high 8 bits, L is the lower 8 bits. - AF1 16 The alternate AF register (on Z80 only) - BC1 16 The alternate BC register (on Z80 only) - DE1 16 The alternate DE register (on Z80 only) - HL1 16 The alternate HL register (on Z80 only) - IX 16 The IX index register (on Z80 only) - IY 16 The IY index register (on Z80 only) - IFF 8 Interrupt flag (on Z80 only) - INT 8 Interrupt register (on Z80 only) - - SR 16 The front panel switches (use D SR 8 for 4k Basic). - WRU 8 The interrupt character. This starts as 5 - (ctrl-E) but some Altair software uses this - keystroke so best to change this to something - exotic such as 035 (which is Ctl-]). - - BANK 3 The currently active memory bank (if banked memory - is activated - see memory options above) - COMMON 16 The starting address of common memory. Originally set - to 0xc000 (note this setting must agree with the - value supplied to GENCPM for CP/M 3 system generation) - ROMLOW 16 The starting address of the ROM. Default is 0FF00. - ROMHIGH 16 The final address of the ROM. Default is 0FFFF. - CLOCK 32 The clock speed of the simulated CPU in kHz or 0 to run - at maximum speed. To set the clock speed for a typical - 4 MHz Z80 CPU, use D CLOCK 4000. The CP/M utility SPEED - measures the clock speed of the simulated CPU. - - -2.2 The Serial I/O Card (2SIO) - - This simple programmed I/O device provides 2 serial ports to the outside -world, which could be hardware jumpered to support RS-232 plugs or a TTY -current loop interface. The standard I/O addresses assigned by MITS was -10-11 (hex) for the first port, and 12-13 (hex) for the second. We follow -this standard in the Simulator. - - The simulator directs I/O to/from the first port to the screen. The -second port reads from an attachable "tape reader" file on input, and -writes to an attachable "punch file" on output. These files are considered -a simple stream of 8-bit bytes. - - The SIO can be configured in SIMH with the following commands: - - SET SIO TTY Bit 8 is set to zero on console output - SET SIO ANSI Bit 8 is not touched on console output - - SET SIO ALL Console input support lower- and upper case - SET SIO UPPER Console input is transformed to upper case characters only - (This feature is useful for most Altair software) - - SET SIO BS Map the delete character to backspace - SET SIO DEL Map the backspace character to delete - - SET SIO QUIET Do not print warning messages - SET SIO VERBOSE Print warning messages (useful for debugging) - The register SIOWL determines how often the same warning - is displayed. The default is 3. - - You can also attach the SIO to a port: - - ATTACH SIO 23 Console IO goes via a Telnet connection on port 23 - DETACH SIO Console IO goes via the regular SIMH console - - -2.3 The SIMH pseudo device - - The SIMH pseudo device facilitates the communication between the -simulated ALTAIR and the simulator environment. This device defines a -number of (most R/O) registers (see source code) which are primarily useful -for debugging purposes. - - The SIMH pseudo device can be configured with - - SET SIMH QUIET Do not print warning messages - SET SIMH VERBOSE Print warning messages (useful for debugging) - - SET SIMH TIMERON Start periodic timer interrupts - SET SIMH TIMEROFF Stop the periodic timer interrupts - - The following variables determine the behavior of the timer: - - TIMD This is the delay between consecutive interrupts in milliseconds. - Use D TIMD 20 for a 50 Hz clock. - TIMH This is the address of the interrupt handler to call for a - timer interrupt. - - -2.4 The 88-DISK controller. - - The MITS 88-DISK is a simple programmed I/O interface to the MITS 8-inch -floppy drive, which was basically a Pertec FD-400 with a power supply and -buffer board builtin. The controller supports neither interrupts nor DMA, -so floppy access required the sustained attention of the CPU. The standard -I/O addresses were 8, 9, and 0A (hex), and we follow the standard. Details -on controlling this hardware are in the altair_dsk.c source file. - - The only difference is that the simulated disks may be larger than the -original ones: The original disk had 77 tracks while the simulated disks -support up to 254 tracks (only relevant for CP/M). You can change the -number of tracks per disk by setting the appropriate value in TRACKS[..]. -For example "D TRACKS[0] 77" sets the number of tracks for disk 0 to the -original number of 77. The command "D TRACKS[0-7] 77" changes the highest -track number for all disks to 77. - - For debugging purposes you can set the trace level of some disk I/O -functions. To do so the following bits in TRACE (a register of the disk) -have been defined with the following meaning: - - 1 Trace all IN and OUT instructions on the disk ports 8 and 9 - 2 Trace all read and writes to full sectors on the disk - 4 Print a message whenever an unnecessary step-in or step out of the - disk head occurs (often an indication of an infinite loop) - 8 Print a message whenever the disk head appears to be waiting for a - sector which does not show up (often an indication of an infinite - loop) - -For example the command "D TRACE 10" will trace options 2+8 from above. - - The DSK device can be configured with - - SET DSK QUIET Do not print warning messages for disk - SET DSK VERBOSE Print warning messages for disk - (useful for debugging) - The register DSKWL determines how often the - same warning is displayed. The default is 3. - - SET DSK WRITEENABLED Allow write operations for disk - SET DSK LOCKED Disk is locked, i.e. no write operations - will be allowed. - - -2.5 The simulated hard disk - - In order to increase the available storage capacity, the simulator -features 8 simulated hard disks with a capacity of 8MB (HDSK0 to HDSK7). -Currently only CP/M supports two hard disks as devices I: and J:. - - For debugging purposes one can set the trace flag by executing the -command "D HDTRACE 1". The default for "HDTRACE" is 0 (no trace). - - The HDSK device can be configured with - - SET HDSK QUIET Do not print warning messages for hard disk - SET HDSK VERBOSE Print warning messages for hard disk - (useful for debugging) - - SET HDSK WRITEENABLED Allow write operations for hard disk - SET HDSK LOCKED Hard disk is locked, i.e. no - write operations will be allowed. - - -3. Sample Software - - Running an Altair in 1977 you would be running either MITS Disk Extended -BASIC, or the brand new and sexy CP/M Operating System from Digital -Research. Or possibly, you ordered Altair DOS back when it was promised in -1975, and are still waiting for it to be delivered in early 1977. - - We have samples of all three for you to check out. We can't go into the -details of how they work, but we'll give you a few hints. - - -3.1 CP/M Version 2.2 - - This version is my own port of the standard CP/M to the Altair. There -were some "official" versions but I don't have them. None were endorsed or -sold by MITS to my knowledge, however. - - To boot CP/M: - - sim> attach dsk cpm2.dsk - sim> boot dsk - - CP/M feels like DOS, sort of. DIR will work. I have included all the -standard CP/M utilities, plus a few common public-domain ones. I also -include the sources to the customized BIOS and some other small programs. -TYPE will print an ASCII file. DUMP will dump a binary one. LS is a -better DIR than DIR. ASM will assemble .ASM files to Hex, LOAD will "load" -them to binary format (.COM). ED is a simple editor, #A command will bring -the source file to the buffer, T command will "type" lines, L will move -lines, E exits the editor. 20L20T will move down 20 lines, and type 20. -Very DECish. DDT is the debugger, DO is a batch-type command processor. A -sample batch file that will assemble and write out the bootable CP/M image -(on drive A) is "SYSCPM2.SUB". To run it, type "DO SYSCPM2". - - In order to efficiently transfer files into the CP/M environment use the -included program R . If you have a file named foo.ext in the -current directory (i.e. the directory where SIMH is), executing R FOO.EXT -under CP/M will transfer the file onto the CP/M disk. Transferring a file -from the CP/M environment to the SIMH environment is accomplished by -W for text files or by W B for binary files. -The simplest way for transferring multiple files is to create a ".SUB" -batch file which contains the necessary R resp. W commands. - - If you need more storage space you can use a simulated hard disk on -drives I: and J:. To use do "attach HDSK0 hdi.dsk" and issue the -"XFORMAT I:" resp. "XFORMAT J:" command from CP/M do initialize the disk -to an empty state. - -The disk "cpm2.dsk" contains the following files: -Name Ext Size Comment -ASM .COM 8K ; CP/M assembler -BDOS .MAC 68K ; Basic Disk Operating System assembler source code -BOOT .COM 1K ; transfer control to boot ROM -BOOT .MAC 2K ; source for BOOT.COM -BOOTGEN .COM 2K ; put a program on the boot sectors -CBIOSX .MAC 48K ; CP/M 2 BIOS source for Altair -CCP .MAC 26K ; Console Command Processor assembler source code -COPY .COM 2K ; copy disks -CPMBOOT .COM 12K ; CP/M operating system -CPU .COM 2K ; get and set the CPU type (8080 or Z80) -CPU .MAC 2K ; source for CPU.COM -CREF80 .COM 4K ; cross reference utility -DDT .COM 6K ; 8080 debugger -DDTZ .COM 10K ; Z80 debugger -DIF .COM 4K ; determine differences between two files -DO .COM 2K ; batch processing -DSKBOOT .MAC 8K ; source for boot ROM -DUMP .COM 2K ; hex dump a file -ED .COM 8K ; line editor -ELIZA .BAS 10K ; Eliza game in Basic -EX8080 .COM 12K ; exercise 8080 instruction set -EXZ80N .COM 12K ; exercise Z80 instruction set, No undefined status bits -EXZ80U .COM 12K ; exercise Z80 instruction set, Undefined status bits -EXZ80 .MAC 54K ; source for EX8080.COM, EXZ80N.COM, EXZ80U.COM -EX .SUB 2K ; benchmark execution of EX8080.COM, EXZ80N.COM, EXZ80U.COM -FORMAT .COM 2K ; format disks -GO .COM 0K ; start the currently loaded program at 100H -HDSKBOOT.MAC 6K ; boot code for hard disk -L80 .COM 12K ; Microsoft linker -LADDER .COM 40K ; game -LADDER .DAT 2K ; high score file for LADDER.COM -LIB80 .COM 6K ; library utility -LOAD .COM 2K ; load hex files -LS .COM 4K ; directory utility -LU .COM 20K ; library utility -M80 .COM 20K ; Microsoft macro assembler -MBASIC .COM 24K ; Microsoft Basic interpreter -MC .SUB 2K ; assemble and link an assembler program -MCC .SUB 2K ; read, assemble and link an assembler program -MCCL .SUB 2K ; assemble, link and produce listing -MEMCFG .LIB 2K ; defines the memory configuration -MOVER .MAC 2K ; moves operating system in place -OTHELLO .COM 12K ; Othello (Reversi) game -PIP .COM 8K ; Peripheral Interchange Program -PRELIM .COM 2K ; preliminary CPU tests -PRELIM .MAC 6K ; source code for PRELIM.COM -R .COM 4K ; read files from SIMH environment -RSETSIMH.COM 2K ; reset SIMH interface -RSETSIMH.MAC 2K ; assembler source for RSETSIMH.COM -SHOWSEC .COM 3K ; show sectors on a disk -SID .COM 8K ; debugger for 8080 -SPEED .COM 2K ; utility to measure the clock speed of the simulated CPU -STAT .COM 6K ; provide information about currently logged disks -SURVEY .COM 2K ; system survey -SURVEY .MAC 16K ; assembler source for SURVEY.COM -SYSCOPY .COM 2K ; copy system tracks between disks -SYSCPM2 .SUB 2K ; create CP/M 2 on drive A: -TIMER .COM 2K ; perform various timer operations -TIMER .MAC 2K ; source code for TIMER.COM -UNCR .COM 8K ; un-crunch utility -UNERA .COM 2K ; un-erase a file -UNERA .MAC 16K ; source for UNERA.COM -USQ .COM 2K ; un-squeeze utility -W .COM 4K ; write files to SIMH environment -WM .COM 12K ; word master screen editor -WM .HLP 3K ; help file for WM.COM -WORM .COM 4K ; worm game for VT100 terminal -XFORMAT .COM 2K ; initialise a drive (floppy or hard disk) -XSUB .COM 2K ; support for DO.COM -ZAP .COM 10K ; SuperZap 5.2 disk editor configured for VT100 -ZSID .COM 10K ; debugger for Z80 -ZTRAN4 .COM 4K ; translate 8080 mnemonics into Z80 equivalents - - -3.2 CP/M Version 3 with banked memory - - CP/M 3 is the successor to CP/M 2.2. A customised BIOS (BIOS3.MAC) is -included to facilitate modification if so desired. The defaults supplied in -GENCPM.DAT for system generation can be used. BOOTGEN.COM is used to place -the CP/M loader (LDR.COM) on the boot tracks of a disk. - - Running CP/M 3 with banked memory: - sim> attach dsk cpm3.dsk - sim> reset cpu - sim> set cpu banked - sim> set cpu itrap - sim> boot dsk - - Executing "DO SYSCPM3" will re-generate the banked version of CP/M 3. You -can boot CP/M 3 with or without a Z80 CPU. The Z80 CPU is needed for both -sysgens due to the use of BOOTGEN.COM which requires it. - -The disk "cpm3.dsk" contains the following files: -ASM .COM 8K ; CP/M assembler -ASSIGN .SYS 2K -BDOS3 .SPR 10K -BIOS3 .MAC 28K ; CP/M 3 BIOS source for Altair SIMH -BIOS3 .SPR 4K -BNKBDOS3.SPR 14K -BNKBIOS3.SPR 4K -BOOT .COM 2K ; transfer control to boot ROM -BOOTGEN .COM 2K ; put a program on the boot sectors -CCP .COM 4K -COPYSYS .COM 2K -CPM3 .SYS 18K -CPMLDR .MAC 38K ; CP/M 3 loader assembler source -DATE .COM 4K ; date utility -DDT .COM 6K ; 8080 debugger -DDTZ .COM 10K ; Z80 debugger -DEFS .LIB 2K ; include file for BIOS3.MAC to create banked CP/M 3 -DEVICE .COM 8K -DIF .COM 4K ; determine differences between two files -DIR .COM 16K ; directory utility -DO .COM 6K ; batch processing -DUMP .COM 2K -ED .COM 10K -ERASE .COM 4K -GENCOM .COM 16K -GENCPM .COM 22K -GENCPM .DAT 4K ; CP/M generation information for banked version -GENCPMNB.DAT 4K ; CP/M generation information for non-banked version -GET .COM 8K -HELP .COM 8K ; help utility -HELP .HLP 62K ; help files -HEXCOM .CPM 2K -HIST .UTL 2K -INITDIR .COM 32K -L80 .COM 12K ; Microsoft linker -LDR .COM 4K ; CP/M loader with optimised loader BIOS -LDRBIOS3.MAC 14K ; optimised (for space) loader BIOS -LIB .COM 8K ; Digital Research librarian -LINK .COM 16K ; Digital Research linker -LOAD .COM 2K -M80 .COM 20K ; Microsoft macro assembler -MC .SUB 2K ; assemble and link an assmbler program -MCC .SUB 2K ; read, assemble and link an assembler program -PATCH .COM 4K -PIP .COM 10K ; Peripheral Interchange Program -PROFILE .SUB 2K ; commands to be executed at start up -PUT .COM 8K -R .COM 4K ; read files from SIMH environment -RENAME .COM 4K -RESBDOS3.SPR 2K -RMAC .COM 14K ; Digital Research macro assembler -RSETSIMH.COM 2K ; reset SIMH interface -SAVE .COM 2K -SCB .MAC 2K -SET .COM 12K -SETDEF .COM 6K -SHOW .COM 10K -SHOWSEC .COM 4K ; show sectors on a disk -SID .COM 8K ; 8080 debugger -SYSCOPY .COM 2K ; copy system tracks between disks -SYSCPM3 .SUB 2K ; create banked CP/M 3 system -TRACE .UTL 2K -TSHOW .COM 2K ; show split time -TSTART .COM 2K ; create timer and start it -TSTOP .COM 2K ; show final time and stop timer -TYPE .COM 4K -UNERA .COM 2K ; un-erase a file -W .COM 4K ; write files to SIMH environment -XREF .COM 16K ; cross reference utility -ZSID .COM 10K ; Z80 debugger - - -3.3 MP/M II with banked memory - - MP/M II is an acronym for MultiProgramming Monitor Control Program for -Microprocessors. It is a multiuser operating system for an eight bit -microcomputer. MP/M II supports multiprogramming at each terminal. This -version supports four terminals available via Telnet. To boot: - - sim> attach dsk mpm.dsk - sim> set cpu itrap - sim> set cpu z80 - sim> set cpu rom - sim> set cpu banked - sim> attach sio 23 - sim> d common b000 - sim> boot dsk - - Now connect a Telnet session to the simulator and type "MPM" at the "A>" -prompt. Now you can connect up to three additional terminals via Telnet to -the Altair running MP/M II. To re-generate the system perform "DO SYSMPM" -in the CP/M environment (not possible under MP/M since XSUB is needed). - -The disk "mpm.dsk" contains the following files: -Name Ext Size Comment -ABORT .PRL 2K ; abort a process -ABORT .RSP 2K -ASM .PRL 10K ; MP/M assembler -BNKBDOS .SPR 12K ; banked BDOS -BNKXDOS .SPR 2K ; banked XDOS -BNKXIOS .SPR 4K ; banked XIOS -BOOTGEN .COM 2K ; copy an executable to the boot section -CONSOLE .PRL 2K ; print console number -CPM .COM 2K ; return to CP/M -CPM .MAC 2K ; source for CPM.COM -DDT .COM 6K ; MP/M DDT -DDT2 .COM 6K ; CP/M DDT -DDTZ .COM 10K ; CP/M DDT with Z80 support -DIF .COM 4K ; difference between two files -DIR .PRL 2K ; directory command -DO .COM 2K ; CP/M submit -DSKRESET.PRL 2K ; disk reset command -DUMP .MAC 6K ; source for DUMP.PRL -DUMP .PRL 2K ; dump command -ED .PRL 10K ; MP/M line editor -ERA .PRL 2K ; erase command -ERAQ .PRL 4K ; erase comand (verbose) -GENHEX .COM 2K -GENMOD .COM 2K -GENSYS .COM 10K -L80 .COM 12K ; Microsoft linker -LDRBIOS .MAC 14K ; loader BIOS -LIB .COM 8K ; library utility -LINK .COM 16K ; linker -LOAD .COM 2K ; loader -M80 .COM 20K ; Microsoft macro assembler -MC .SUB 2K ; assemble and link an assmbler program -MCC .SUB 2K ; read, assemble and link an assembler program -MPM .COM 8K ; start MP/M II -MPM .SYS 26K ; MP/M system file -MPMD .LIB 2K ; define a banked system -MPMLDR .COM 6K ; MP/M loader without LDRBIOS -MPMSTAT .BRS 6K ; status of MP/M system -MPMSTAT .PRL 6K -MPMSTAT .RSP 2K -MPMXIOS .MAC 26K ; XIOS for MP/M -PIP .PRL 10K ; MP/M peripheral interchange program -PIP2 .COM 8K ; CP/M peripheral interchange program -PRINTER .PRL 2K -PRLCOM .PRL 4K -R .COM 4K ; read a file from the SIMH environment -RDT .PRL 8K ; debugger for page relocatable programs -REN .PRL 4K ; rename a file -RESBDOS .SPR 4K ; non-banked BDOS -RMAC .COM 14K ; Digital Research macro assembler -RSETSIMH.COM 2K ; reset SIMH interface -SCHED .BRS 2K ; schedule a job -SCHED .PRL 4K -SCHED .RSP 2K -SDIR .PRL 18K ; fancy directory command -SET .PRL 8K ; set parameters -SHOW .PRL 8K ; show status of disks -SPOOL .BRS 4K ; spool utility -SPOOL .PRL 4K -SPOOL .RSP 2K -STAT .COM 6K ; CP/M stat command -STAT .PRL 10K ; MP/M stat command -STOPSPLR.PRL 2K ; stop spooler -SUBMIT .PRL 6K ; MP/M submit -SYSCOPY .COM 2K ; copy system tracks -SYSMPM .SUB 2K ; do a system generation -SYSTEM .DAT 2K ; default values for system generation -TMP .SPR 2K -TOD .PRL 4K ; time of day -TSHOW .COM 2K ; show split time -TSTART .COM 2K ; create timer and start it -TSTOP .COM 2K ; show final time and stop timer -TYPE .PRL 2K ; type a file on the screen -USER .PRL 2K ; set user area -W .COM 4K ; write a file to SIMH environment -XDOS .SPR 10K ; XDOS -XREF .COM 16K ; cross reference utility -XSUB .COM 2K ; for CP/M DO - - -3.4 CP/M application software - - There is also a small collection of sample application software -containing the following items: - -- SPL: a Small Programming Language with a suite of sample programs -- PROLOGZ: a Prolog interpreter written in SPL with sources -- PASCFORM: a Pascal pretty printer written in Pascal -- Pascal MT+: Pascal language system needed to compile PASCFORM - -The sample software comes on "app.dsk" and to use it do - - sim> attach dsk1 app.dsk - -before booting CP/M. - -The disk "app.dsk" contains the following files: -Name Ext Size Comment -BOOTGEN .COM 2K -BOOTGEN .SPL 6K ; SPL source for BOOTGEN.COM -C .SUB 2K ; batch file for compiling an SPL source file -CALC .PRO 4K ; Prolog demo program: Calculator -CC .SUB 2K ; compile an SPL source which is on the underlying - file system -DECLARAT. 12K ; common include file, SPL source -DIF .COM 4K -DIF .SPL 10K ; SPL source for DIF.COM -EDIT .SPL 10K ; screen editor for PROLOGZ, SPL source -FAMILY .PRO 4K ; Prolog demo program: Family relations -INTEGER .PRO 2K ; Prolog demo program: Integer arithmetic -KNAKE .PRO 2K ; Prolog demo program: Logic puzzle -LINKMT .COM 12K ; Pascal MT+ 5.5 linker -MAIN .SPL 14K ; main module for PROLOGZ, SPL source -MOVE .MAC 4K ; helper functions for PROLOGZ in assembler -MTERRS .TXT 6K ; Pascal MT+ error messages -MTPLUS .000 14K ; Pascal MT+ 5.5 compiler file -MTPLUS .001 12K ; Pascal MT+ 5.5 compiler file -MTPLUS .002 8K ; Pascal MT+ 5.5 compiler file -MTPLUS .003 8K ; Pascal MT+ 5.5 compiler file -MTPLUS .004 18K ; Pascal MT+ 5.5 compiler file -MTPLUS .005 8K ; Pascal MT+ 5.5 compiler file -MTPLUS .006 6K ; Pascal MT+ 5.5 compiler file -MTPLUS .COM 36K ; Pascal MT+ 5.5 compiler -PASCFORM.COM 36K ; Pascal formatter -PASCFORM.PAS 54K ; Pascal formatter source code -PASCFORM.SUB 2K ; create Pascal formatter -PASLIB .ERL 24K ; Pascal MT+ 5.5 run time library -PINST .COM 4K ; terminal installation program for PROLOGZ -PINST .SPL 16K ; terminal installation program for PROLOGZ, - SPL source -PROLOGZ .COM 18K ; PROLOGZ interpreter and screen editor -PROLOGZ .SPL 2K ; PROLOGZ main program, SPL source -PROLOGZ .TXT 40K ; PROLOGZ documentation in German -PROVE .SPL 16K ; backtrack theorem prover for PROLOGZ, SPL source -PZCLEAN .SUB 2K ; PROLOGZ: remove all created ".rel" and ".lst" files -PZLINK .SUB 2K ; PROLOGZ: create PINST, PROLOGZ and personalise the - serial number -PZMAKE .SUB 2K ; PROLOGZ: compiles the sources (you can ignore - any compiler errors) -QUEEN .PRO 2K ; Prolog demo program: N-queens problem -READ .COM 4K -READ .SPL 10K ; SPL source for R.COM -SHOWSEC .COM 4K -SHOWSEC .SPL 6K ; SPL source for SHOWSEC.COM -SPEED .COM 2K ; utility to measure the clock speed of the simulated CPU -SPEED .SPL 2K ; SPL source for SPEED.COM, requires SWLIB.MAC -SPL .COM 38K ; the SPL compiler itself -SPL .TXT 56K ; SPL language and compiler documentation in German -SPLERROR.DAT 12K ; error messages of the compiler (in German) -SPLIB .REL 6K ; SPL runtime library -STDIO . 2K ; include file for SPL programs -SWLIB .MAC 2K ; assembler utility routines needed by SPEED.SPL -SYSCOPY .COM 2K -SYSCOPY .SPL 6K ; SPL source for SYSCOPY.COM -TERMBDOS.SPL 2K ; terminal interface to CP/M for PROLOGZ, SPL source -UTIL .SPL 18K ; utility functions for PROLOGZ, SPL source -WRITE .COM 4K -WRITE .SPL 8K ; SPL source for W.COM -XFORMAT .COM 2K -XFORMAT .SPL 6K ; SPL source for XFORMAT.COM - - -3.5 MITS Disk Extended BASIC Version 4.1 - - This was the commonly used software for serious users of the Altair -computer. It is a powerful (but slow) BASIC with some extended commands to -allow it to access and manage the disk. There was no operating system it -ran under. To boot: - - sim> set cpu 8080 ;Z80 will not work - sim> attach dsk mbasic.dsk - sim> set sio upper - sim> go ff00 - - MEMORY SIZE? [return] - LINEPRINTER? [C return] - HIGHEST DISK NUMBER? [0 return] (0 here = 1 drive system) - NUMBER OF FILES? [3 return] - NUMBER OF RANDOM FILES? [2 return] - - 44041 BYTES FREE - ALTAIR BASIC REV. 4.1 - [DISK EXTENDED VERSION] - COPYRIGHT 1977 BY MITS INC. - OK - [MOUNT 0] - OK - [FILES] - - -3.6 Altair DOS Version 1.0 - - This was long promised but not delivered until it was almost irrelevant. -A short attempted tour will reveal it to be a dog, far inferior to CP/M. To -boot: - - sim> d tracks[0-7] 77 ;set to Altair settings - sim> set cpu altairrom - sim> attach dsk altdos.dsk - sim> set sio upper - sim> go ff00 - - MEMORY SIZE? [return] - INTERRUPTS? N [return] - HIGHEST DISK NUMBER? [0 return] (3 here = 4 drive system) - HOW MANY DISK FILES? [3 return] - HOW MANY RANDOM FILES? [2 return] - - 056449 BYTES AVAILABLE - DOS MONITOR VER 1.0 - COPYRIGHT 1977 BY MITS INC - .[MNT 0] - - .[DIR 0] - - -3.7 Altair Basic 3.2 (4k) - - In order to run the famous 4k Basic, use the following commands (the -trick is to get the Switch Register right). - - sim> set cpu 8080 ;note 4k Basic will not run on a Z80 CPU - sim> set sio upper ;4k Basic does not like lower case letters as input - sim> set sio ansi ;4k Basic produces 8-bit output, strip to seven bits - sim> d sr 8 ;good setting for the Switch Register - sim> load 4kbas.bin 0 ;load it at 0 - sim> go 0 ;and start it - MEMORY SIZE? [return] - TERMINAL WIDTH? [return] - WANT SIN? [Y] - - 61911 BYTES FREE - - BASIC VERSION 3.2 - [4K VERSION] - - OK - - -3.8 Altair 8k Basic - Running 8k Basic follows the procedure for 4k Basic. - - sim> set cpu 8080 ;note 8k Basic will not run on a Z80 CPU - sim> set sio upper ;8k Basic does not like lower case letters as input - sim> set sio ansi ;8k Basic produces 8-bit output, strip to seven bits - sim> d sr 8 ;good setting for the Switch Register - sim> load 8kbas.bin 0 ;load it at 0 - sim> go 0 ;and start it - MEMORY SIZE? [A] - - WRITTEN FOR ROYALTIES BY MICRO-SOFT - - MEMORY SIZE? [return] - TERMINAL WIDTH? [return] - WANT SIN-COS-TAN-ATN? [Y] - - 58756 BYTES FREE - ALTAIR BASIC REV. 4.0 - [EIGHT-K VERSION] - COPYRIGHT 1976 BY MITS INC. - OK - - -3.9 Altair Basic 4.0 - - Execute the following commands to run Altair Extended Basic: - - sim> set sio upper ;Extended Basic does not like lower case letters as input - sim> set sio ansi ;Extended Basic produces 8-bit output, strip to seven bits - sim> d sr 8 ;good setting for the Switch Register - sim> load exbas.bin 0 ;load it at 0 - sim> go 0 ;and start it - 16384 Bytes loaded at 0. - - MEMORY SIZE? [return] - WANT SIN-COS-TAN-ATN? [Y] - - 50606 BYTES FREE - ALTAIR BASIC REV. 4.0 - [EXTENDED VERSION] - COPYRIGHT 1977 BY MITS INC. - OK - - -3.10 Altair Disk Extended Basic Version 300-5-C - - This version of Basic was provided by Scott LaBombard. To execute use the -following commands: - - sim> d tracks[0-7] 77 ;set to Altair settings - sim> at dsk extbas5.dsk - sim> g 0 - - MEMORY SIZE? [return] - LINEPRINTER? [C] - HIGHEST DISK NUMBER? [0] - HOW MANY FILES? [3] - HOW MANY RANDOM FILES? [3] - - 42082 BYTES FREE - - ALTAIR DISK EXTENDED BASIC - VERSION 300-5-C [01NOV78] - COPYRIGHT 1978 BY MITS INC. - - OK - - -4. Special simulator features - - In addition to the regular SIMH features such as PC queue, breakpoints -etc., this simulator supports memory access breakpoints. A memory access -breakpoint is triggered when a pre-defined memory location is accessed -(read, write or update). To set a memory location breakpoint enter - -sim> break -m - - Execution will stop whenever an operation accesses . Note that -a memory access breakpoint is not triggered by fetching code from memory -(this is the job of regular breakpoints). This feature has been implemented -by using the typing facility of the SIMH breakpoints. - - -5. Brief summary of all major changes to the original Altair simulator -- Full support for Z80. CP/M software requiring a Z80 CPU now runs - properly. DDTZ and PROLOGZ are included for demonstration purposes. -- Added banked memory support. -- PC queue implemented. -- Full assembler and dis-assembler support for Z80 and 8080 mnemonics. - Depending on the current setting of the CPU, the appropriate mnemonics - are used. -- The BOOT ROM was changed to fully load the software from disk. The - original code basically loaded a copy of itself from the disk and - executed it. -- ROM and memory size settings are now fully honored. This means that you - cannot write into the ROM or outside the defined RAM (e.g. when the RAM size - was truncated with the SET CPU commands). This feature allows programs which - check for the size of available RAM to run properly (e.g. 4k Basic). In - addition one can enable and disable the ROM which is useful in special cases - (e.g. when testing a new version of the ROM). -- The console can also be used via Telnet. This is useful when a terminal is - needed which supports cursor control such as a VT100. PROLOGZ for example - has a built-in screen editor which works under Telnet. -- Simplified file exchange for CP/M. Using the READ program under CP/M one - can easily import files into CP/M from the regular file system. Note that PIP - does not work properly on non-text files on PTR. -- The WRITE program can be used to transfer files from the CP/M environment to - the regular environment (binary or ASCII transfer). -- The last character read from PTR is always Control-Z (the EOF character for - CP/M). This makes sure that PIP (Peripheral Interchange Program on CP/M) will - terminate properly. -- Fixed a bug in the BIOS warm boot routine which caused CP/M to crash. -- Modified the BIOS for CP/M to support 8 disks. -- Added CP/M 3 banked version as sample software -- Changed from octal to hex -- Made the DSK and SIO device more robust (previously malicious code could - crash the simulator) -- Added memory access break points -- Added periodic timer interrupts (useful for MP/M) -- Added additional consoles (useful for MP/M) -- Added MP/M II banked version as sample software diff --git a/AltairZ80/altairZ80_cpu.c b/AltairZ80/altairZ80_cpu.c deleted file mode 100644 index 0b119432..00000000 --- a/AltairZ80/altairZ80_cpu.c +++ /dev/null @@ -1,5605 +0,0 @@ -/* altairz80_cpu.c: MITS Altair CPU (8080 and Z80) - - Copyright (c) 2002-2003, Peter Schorn - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - PETER SCHORN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 - Code for Z80 CPU from Frank D. Cringle ((c) 1995 under GNU license) -*/ - -#include "altairz80_defs.h" - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_SIZE_LOG2 6 /* log2 of PCQ_SIZE */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY(PC) pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC - -/* simulator stop codes */ -#define STOP_HALT 0 /* HALT */ -#define STOP_IBKPT 1 /* breakpoint (program counter) */ -#define STOP_MEM 2 /* breakpoint (memory access) */ -#define STOP_OPCODE 3 /* unknown 8080 or Z80 instruction */ - -/*-------------------------------- definitions for memory space --------------------*/ - -static uint8 M[MAXMEMSIZE][MAXBANKS]; /* RAM which is present */ - -/* two sets of accumulator / flags */ -static uint16 af[2]; -static int af_sel; - -/* two sets of 16-bit registers */ -static struct ddregs { - uint16 bc; - uint16 de; - uint16 hl; -} regs[2]; -static int regs_sel; - -static uint16 ir; -static uint16 ix; -static uint16 iy; -static uint16 sp; -static uint16 pc; -static uint16 IFF; - -#define FLAG_C 1 -#define FLAG_N 2 -#define FLAG_P 4 -#define FLAG_H 16 -#define FLAG_Z 64 -#define FLAG_S 128 - -#define SETFLAG(f,c) AF = (c) ? AF | FLAG_ ## f : AF & ~FLAG_ ## f -#define TSTFLAG(f) ((AF & FLAG_ ## f) != 0) - -#define ldig(x) ((x) & 0xf) -#define hdig(x) (((x) >> 4) & 0xf) -#define lreg(x) ((x) & 0xff) -#define hreg(x) (((x) >> 8) & 0xff) - -#define Setlreg(x, v) x = (((x) & 0xff00) | ((v) & 0xff)) -#define Sethreg(x, v) x = (((x) & 0xff) | (((v) & 0xff) << 8)) - -#define parity(x) parityTable[(x) & 0xff] -/* SetPV and SetPV2 are used to provide correct parity flag semantics for the 8080 in cases - where the Z80 uses the overflow flag -*/ -#define SetPVS(s) ((cpu_unit.flags & UNIT_CHIP) ? (((cbits >> 6) ^ (cbits >> 5)) & 4) : (parity(s))) -#define SetPV (SetPVS(sum)) -#define SetPV2(x) ((cpu_unit.flags & UNIT_CHIP) ? (((temp == (x)) << 2)) : (parity(temp))) - -/* checkCPU8080 must be invoked whenever a Z80 only instruction is executed */ -#define checkCPU8080 \ - if (((cpu_unit.flags & UNIT_CHIP) == 0) && (cpu_unit.flags & UNIT_OPSTOP)) {\ - reason = STOP_OPCODE; \ - goto end_decode; \ - } - -/* checkCPUZ80 must be invoked whenever a non Z80 instruction is executed */ -#define checkCPUZ80 \ - if (cpu_unit.flags & UNIT_OPSTOP) { \ - reason = STOP_OPCODE; \ - goto end_decode; \ - } - -#define POP(x) do { \ - register uint32 y = RAM_pp(SP); \ - x = y + (RAM_pp(SP) << 8); \ -} while (0) - -#define JPC(cond) { \ - tStates += 10; \ - if (cond) { \ - PCQ_ENTRY(PC - 1); \ - PC = GetWORD(PC); \ - } \ - else { \ - PC += 2; \ - } \ -} - -#define CALLC(cond) { \ - if (cond) { \ - register uint32 adrr = GetWORD(PC); \ - CheckBreakWord(SP - 2); \ - PUSH(PC + 2); \ - PCQ_ENTRY(PC - 1); \ - PC = adrr; \ - tStates += 17; \ - } \ - else { \ - sim_brk_pend = FALSE; \ - PC += 2; \ - tStates += 10; \ - } \ -} - -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern int32 sio0s (const int32 port, const int32 io, const int32 data); -extern int32 sio0d (const int32 port, const int32 io, const int32 data); -extern int32 sio1s (const int32 port, const int32 io, const int32 data); -extern int32 sio1d (const int32 port, const int32 io, const int32 data); -extern int32 dsk10 (const int32 port, const int32 io, const int32 data); -extern int32 dsk11 (const int32 port, const int32 io, const int32 data); -extern int32 dsk12 (const int32 port, const int32 io, const int32 data); -extern int32 nulldev (const int32 port, const int32 io, const int32 data); -extern int32 hdsk_io (const int32 port, const int32 io, const int32 data); -extern int32 simh_dev (const int32 port, const int32 io, const int32 data); -extern int32 sr_dev (const int32 port, const int32 io, const int32 data); -extern int32 bootrom[bootrom_size]; -extern char memoryAccessMessage[]; -extern char messageBuffer[]; -extern void printMessage(void); - -/* function prototypes */ -t_stat cpu_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset(DEVICE *dptr); -static t_stat cpu_set_rom (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_norom (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_altairrom (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_warnrom (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_size (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_banked (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_nonbanked (UNIT *uptr, int32 value, char *cptr, void *desc); -static void prepareMemoryAccessMessage(t_addr loc); -static void checkROMBoundaries(void); -static void warnUnsuccessfulWriteAttempt(const uint32 Addr); -static uint8 warnUnsuccessfulReadAttempt(const uint32 Addr); -static void reset_memory(void); -static uint32 in(const uint32 Port); -static void out(const uint32 Port, const uint32 Value); -uint8 GetBYTE(register uint32 Addr); -void PutBYTEBasic(const uint32 Addr, const uint32 Bank, const uint32 Value); -void PutBYTE(register uint32 Addr, register uint32 Value); -void PutBYTEForced(register uint32 Addr, register uint32 Value); -int32 addressIsInROM(const uint32 Addr); -int32 addressExists(const uint32 Addr); -static uint16 GetWORD(register uint32 a); -static void PutWORD(register uint32 a, register uint32 v); -int32 sim_instr(void); -int32 install_bootrom(void); -static t_bool sim_brk_lookup (const t_addr bloc, const int32 btyp); -void protect(const int32 l, const int32 h); -static void resetCell(const int32 address, const int32 bank); -void printROMMessage(const uint32 cntROM); - -#ifndef NO_INLINE -/* in case of using inline we need to ensure that the GetBYTE and PutBYTE - are accessible externally */ -uint8 GetBYTEWrapper(register uint32 Addr); -void PutBYTEWrapper(register uint32 Addr, register uint32 Value); -#endif - -/* CPU data structures - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifiers list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK + UNIT_ROM + UNIT_ALTAIRROM, MAXMEMSIZE) }; - - int32 PCX; /* external view of PC */ - int32 saved_PC = 0; /* program counter */ -static int32 AF_S; /* AF register */ -static int32 BC_S; /* BC register */ -static int32 DE_S; /* DE register */ -static int32 HL_S; /* HL register */ -static int32 IX_S; /* IX register */ -static int32 IY_S; /* IY register */ -static int32 SP_S; /* SP register */ -static int32 AF1_S; /* alternate AF register */ -static int32 BC1_S; /* alternate BC register */ -static int32 DE1_S; /* alternate DE register */ -static int32 HL1_S; /* alternate HL register */ -static int32 IFF_S; /* interrupt Flip Flop */ -static int32 IR_S; /* interrupt (upper)/refresh (lower) register */ - int32 SR = 0; /* switch register */ - int32 bankSelect = 0; /* determines selected memory bank */ - uint32 common = 0xc000; /* addresses >= 'common' are in common memory */ -static uint32 ROMLow = defaultROMLow; /* lowest address of ROM */ -static uint32 ROMHigh = defaultROMHigh; /* highest address of ROM */ -static uint32 previousCapacity= 0; /* safe for previous memory capacity */ -static uint32 clockFrequency = 0; /* in kHz, 0 means as fast as possible */ -static uint32 sliceLength = 10; /* length of time-slice for CPU speed */ - /* adjustment in milliseonds */ -static uint32 executedTStates = 0; /* executed t-states */ -static uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -static int32 pcq_p = 0; /* PC queue ptr */ -static REG *pcq_r = NULL; /* PC queue reg ptr */ - - -REG cpu_reg[] = { - { HRDATA (PC, saved_PC, 16) }, - { HRDATA (AF, AF_S, 16) }, - { HRDATA (BC, BC_S, 16) }, - { HRDATA (DE, DE_S, 16) }, - { HRDATA (HL, HL_S, 16) }, - { HRDATA (IX, IX_S, 16) }, - { HRDATA (IY, IY_S, 16) }, - { HRDATA (SP, SP_S, 16) }, - { HRDATA (AF1, AF1_S, 16) }, - { HRDATA (BC1, BC1_S, 16) }, - { HRDATA (DE1, DE1_S, 16) }, - { HRDATA (HL1, HL1_S, 16) }, - { GRDATA (IFF, IFF_S, 2, 2, 0) }, - { FLDATA (IR, IR_S, 8) }, - { FLDATA (Z80, cpu_unit.flags, UNIT_V_CHIP), REG_HRO }, - { FLDATA (OPSTOP, cpu_unit.flags, UNIT_V_OPSTOP), REG_HRO }, - { HRDATA (SR, SR, 8) }, - { HRDATA (BANK, bankSelect, MAXBANKSLOG2) }, - { HRDATA (COMMON, common, 16) }, - { HRDATA (ROMLOW, ROMLow, 16) }, - { HRDATA (ROMHIGH, ROMHigh, 16) }, - { DRDATA (CLOCK, clockFrequency, 32) }, - { DRDATA (SLICE, sliceLength, 16) }, - { DRDATA (TSTATES, executedTStates, 32), REG_RO }, - { HRDATA (CAPACITY, cpu_unit.capac, 32), REG_RO }, - { HRDATA (PREVCAP, previousCapacity, 32), REG_RO }, - { BRDATA (PCQ, pcq, 16, 16, PCQ_SIZE), REG_RO + REG_CIRC }, - { DRDATA (PCQP, pcq_p, PCQ_SIZE_LOG2), REG_HRO }, - { HRDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -static MTAB cpu_mod[] = { - { UNIT_CHIP, UNIT_CHIP, "Z80", "Z80", NULL }, - { UNIT_CHIP, 0, "8080", "8080", NULL }, - { UNIT_OPSTOP, UNIT_OPSTOP, "ITRAP", "ITRAP", NULL }, - { UNIT_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL }, - { UNIT_BANKED, UNIT_BANKED, "BANKED", "BANKED", &cpu_set_banked }, - { UNIT_BANKED, 0, "NONBANKED", "NONBANKED", &cpu_set_nonbanked }, - { UNIT_ROM, UNIT_ROM, "ROM", "ROM", &cpu_set_rom }, - { UNIT_ROM, 0, "NOROM", "NOROM", &cpu_set_norom }, - { UNIT_ALTAIRROM, UNIT_ALTAIRROM, "ALTAIRROM", "ALTAIRROM", &cpu_set_altairrom }, - { UNIT_ALTAIRROM, 0, "NOALTAIRROM", "NOALTAIRROM", NULL }, - { UNIT_WARNROM, UNIT_WARNROM, "WARNROM", "WARNROM", &cpu_set_warnrom }, - { UNIT_WARNROM, 0, "NOWARNROM", "NOWARNROM", NULL }, - { UNIT_MSIZE, 4 * KB, NULL, "4K", &cpu_set_size }, - { UNIT_MSIZE, 8 * KB, NULL, "8K", &cpu_set_size }, - { UNIT_MSIZE, 12 * KB, NULL, "12K", &cpu_set_size }, - { UNIT_MSIZE, 16 * KB, NULL, "16K", &cpu_set_size }, - { UNIT_MSIZE, 20 * KB, NULL, "20K", &cpu_set_size }, - { UNIT_MSIZE, 24 * KB, NULL, "24K", &cpu_set_size }, - { UNIT_MSIZE, 28 * KB, NULL, "28K", &cpu_set_size }, - { UNIT_MSIZE, 32 * KB, NULL, "32K", &cpu_set_size }, - { UNIT_MSIZE, 36 * KB, NULL, "36K", &cpu_set_size }, - { UNIT_MSIZE, 40 * KB, NULL, "40K", &cpu_set_size }, - { UNIT_MSIZE, 44 * KB, NULL, "44K", &cpu_set_size }, - { UNIT_MSIZE, 48 * KB, NULL, "48K", &cpu_set_size }, - { UNIT_MSIZE, 52 * KB, NULL, "52K", &cpu_set_size }, - { UNIT_MSIZE, 56 * KB, NULL, "56K", &cpu_set_size }, - { UNIT_MSIZE, 60 * KB, NULL, "60K", &cpu_set_size }, - { UNIT_MSIZE, 64 * KB, NULL, "64K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 16, 16, 1, 16, 8, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL, NULL, 0, NULL, NULL }; - -/* data structure for IN/OUT instructions */ -struct idev { - int32 (*routine)(const int32, const int32, const int32); -}; - -/* This is the I/O configuration table. There are 255 possible - device addresses, if a device is plugged to a port it's routine - address is here, 'nulldev' means no device is available -*/ -static const struct idev dev_table[256] = { - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 00 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 04 */ - {&dsk10}, {&dsk11}, {&dsk12}, {&nulldev}, /* 08 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C */ - {&sio0s}, {&sio0d}, {&sio1s}, {&sio1d}, /* 10 */ - {&sio0s}, {&sio0d}, {&sio0s}, {&sio0d}, /* 14 */ - {&sio0s}, {&sio0d}, {&nulldev}, {&nulldev}, /* 18 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 20 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 24 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 28 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 30 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 34 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 38 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 40 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 44 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 48 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 4C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 50 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 54 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 58 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 5C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 60 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 64 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 68 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 6C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 70 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 74 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 78 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 7C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 80 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 84 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 88 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 8C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 90 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 94 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 98 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 9C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* A0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* A4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* A8 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* AC */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* B0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* B4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* B8 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* BC */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* C0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* C4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* C8 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* CC */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D8 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* DC */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* E4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* E8 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* EC */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* F0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* F4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* F8 */ - {&nulldev}, {&hdsk_io}, {&simh_dev}, {&sr_dev} /* FC */ -}; - -static INLINE void out(const uint32 Port, const uint32 Value) { - dev_table[Port].routine(Port, 1, Value); -} - -static INLINE uint32 in(const uint32 Port) { - return dev_table[Port].routine(Port, 0, 0); -} - -/* the following tables precompute some common subexpressions - parityTable[i] 0..255 (number of 1's in i is odd) ? 0 : 4 - incTable[i] 0..256! (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0) << 4) - decTable[i] 0..255 (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0xf) << 4) | 2 - cbitsTable[i] 0..511 (i & 0x10) | ((i >> 8) & 1) - cbitsDup8Table[i] 0..511 (i & 0x10) | ((i >> 8) & 1) | ((i & 0xff) << 8) | (i & 0xa8) | - (((i & 0xff) == 0) << 6) - cbitsDup16Table[i] 0..511 (i & 0x10) | ((i >> 8) & 1) | (i & 0x28) - cbits2Table[i] 0..511 (i & 0x10) | ((i >> 8) & 1) | 2 - rrcaTable[i] 0..255 ((i & 1) << 15) | ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1) - rraTable[i] 0..255 ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1) - addTable[i] 0..511 ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) - subTable[i] 0..255 ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | 2 - andTable[i] 0..255 (i << 8) | (i & 0xa8) | ((i == 0) << 6) | 0x10 | parityTable[i] - xororTable[i] 0..255 (i << 8) | (i & 0xa8) | ((i == 0) << 6) | parityTable[i] - rotateShiftTable[i] 0..255 (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i & 0xff] - incZ80Table[i] 0..256! (i & 0xa8) | (((i & 0xff) == 0) << 6) | - (((i & 0xf) == 0) << 4) | ((i == 0x80) << 2) - decZ80Table[i] 0..255 (i & 0xa8) | (((i & 0xff) == 0) << 6) | - (((i & 0xf) == 0xf) << 4) | ((i == 0x7f) << 2) | 2 - cbitsZ80Table[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) - cbitsZ80DupTable[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | - ((i >> 8) & 1) | (i & 0xa8) - cbits2Z80Table[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2 - cbits2Z80DupTable[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2 | - (i & 0xa8) - negTable[i] 0..255 (((i & 0x0f) != 0) << 4) | ((i == 0x80) << 2) | 2 | (i != 0) - rrdrldTable[i] 0..255 (i << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i] - cpTable[i] 0..255 (i & 0x80) | (((i & 0xff) == 0) << 6) -*/ - -/* parityTable[i] = (number of 1's in i is odd) ? 0 : 4, i = 0..255 */ -static const uint8 parityTable[256] = { - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, -}; - -/* incTable[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0) << 4), i = 0..256 */ -static const uint8 incTable[257] = { - 80, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, 80 -}; - -/* decTable[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0xf) << 4) | 2, i = 0..255 */ -static const uint8 decTable[256] = { - 66, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, -}; - -/* cbitsTable[i] = (i & 0x10) | ((i >> 8) & 1), i = 0..511 */ -static const uint8 cbitsTable[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, -}; - -/* cbitsDup8Table[i] = (i & 0x10) | ((i >> 8) & 1) | ((i & 0xff) << 8) | (i & 0xa8) | - (((i & 0xff) == 0) << 6), i = 0..511 */ -static const uint16 cbitsDup8Table[512] = { - 0x0040,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700, - 0x0808,0x0908,0x0a08,0x0b08,0x0c08,0x0d08,0x0e08,0x0f08, - 0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,0x1610,0x1710, - 0x1818,0x1918,0x1a18,0x1b18,0x1c18,0x1d18,0x1e18,0x1f18, - 0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,0x2620,0x2720, - 0x2828,0x2928,0x2a28,0x2b28,0x2c28,0x2d28,0x2e28,0x2f28, - 0x3030,0x3130,0x3230,0x3330,0x3430,0x3530,0x3630,0x3730, - 0x3838,0x3938,0x3a38,0x3b38,0x3c38,0x3d38,0x3e38,0x3f38, - 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700, - 0x4808,0x4908,0x4a08,0x4b08,0x4c08,0x4d08,0x4e08,0x4f08, - 0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,0x5610,0x5710, - 0x5818,0x5918,0x5a18,0x5b18,0x5c18,0x5d18,0x5e18,0x5f18, - 0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,0x6620,0x6720, - 0x6828,0x6928,0x6a28,0x6b28,0x6c28,0x6d28,0x6e28,0x6f28, - 0x7030,0x7130,0x7230,0x7330,0x7430,0x7530,0x7630,0x7730, - 0x7838,0x7938,0x7a38,0x7b38,0x7c38,0x7d38,0x7e38,0x7f38, - 0x8080,0x8180,0x8280,0x8380,0x8480,0x8580,0x8680,0x8780, - 0x8888,0x8988,0x8a88,0x8b88,0x8c88,0x8d88,0x8e88,0x8f88, - 0x9090,0x9190,0x9290,0x9390,0x9490,0x9590,0x9690,0x9790, - 0x9898,0x9998,0x9a98,0x9b98,0x9c98,0x9d98,0x9e98,0x9f98, - 0xa0a0,0xa1a0,0xa2a0,0xa3a0,0xa4a0,0xa5a0,0xa6a0,0xa7a0, - 0xa8a8,0xa9a8,0xaaa8,0xaba8,0xaca8,0xada8,0xaea8,0xafa8, - 0xb0b0,0xb1b0,0xb2b0,0xb3b0,0xb4b0,0xb5b0,0xb6b0,0xb7b0, - 0xb8b8,0xb9b8,0xbab8,0xbbb8,0xbcb8,0xbdb8,0xbeb8,0xbfb8, - 0xc080,0xc180,0xc280,0xc380,0xc480,0xc580,0xc680,0xc780, - 0xc888,0xc988,0xca88,0xcb88,0xcc88,0xcd88,0xce88,0xcf88, - 0xd090,0xd190,0xd290,0xd390,0xd490,0xd590,0xd690,0xd790, - 0xd898,0xd998,0xda98,0xdb98,0xdc98,0xdd98,0xde98,0xdf98, - 0xe0a0,0xe1a0,0xe2a0,0xe3a0,0xe4a0,0xe5a0,0xe6a0,0xe7a0, - 0xe8a8,0xe9a8,0xeaa8,0xeba8,0xeca8,0xeda8,0xeea8,0xefa8, - 0xf0b0,0xf1b0,0xf2b0,0xf3b0,0xf4b0,0xf5b0,0xf6b0,0xf7b0, - 0xf8b8,0xf9b8,0xfab8,0xfbb8,0xfcb8,0xfdb8,0xfeb8,0xffb8, - 0x0041,0x0101,0x0201,0x0301,0x0401,0x0501,0x0601,0x0701, - 0x0809,0x0909,0x0a09,0x0b09,0x0c09,0x0d09,0x0e09,0x0f09, - 0x1011,0x1111,0x1211,0x1311,0x1411,0x1511,0x1611,0x1711, - 0x1819,0x1919,0x1a19,0x1b19,0x1c19,0x1d19,0x1e19,0x1f19, - 0x2021,0x2121,0x2221,0x2321,0x2421,0x2521,0x2621,0x2721, - 0x2829,0x2929,0x2a29,0x2b29,0x2c29,0x2d29,0x2e29,0x2f29, - 0x3031,0x3131,0x3231,0x3331,0x3431,0x3531,0x3631,0x3731, - 0x3839,0x3939,0x3a39,0x3b39,0x3c39,0x3d39,0x3e39,0x3f39, - 0x4001,0x4101,0x4201,0x4301,0x4401,0x4501,0x4601,0x4701, - 0x4809,0x4909,0x4a09,0x4b09,0x4c09,0x4d09,0x4e09,0x4f09, - 0x5011,0x5111,0x5211,0x5311,0x5411,0x5511,0x5611,0x5711, - 0x5819,0x5919,0x5a19,0x5b19,0x5c19,0x5d19,0x5e19,0x5f19, - 0x6021,0x6121,0x6221,0x6321,0x6421,0x6521,0x6621,0x6721, - 0x6829,0x6929,0x6a29,0x6b29,0x6c29,0x6d29,0x6e29,0x6f29, - 0x7031,0x7131,0x7231,0x7331,0x7431,0x7531,0x7631,0x7731, - 0x7839,0x7939,0x7a39,0x7b39,0x7c39,0x7d39,0x7e39,0x7f39, - 0x8081,0x8181,0x8281,0x8381,0x8481,0x8581,0x8681,0x8781, - 0x8889,0x8989,0x8a89,0x8b89,0x8c89,0x8d89,0x8e89,0x8f89, - 0x9091,0x9191,0x9291,0x9391,0x9491,0x9591,0x9691,0x9791, - 0x9899,0x9999,0x9a99,0x9b99,0x9c99,0x9d99,0x9e99,0x9f99, - 0xa0a1,0xa1a1,0xa2a1,0xa3a1,0xa4a1,0xa5a1,0xa6a1,0xa7a1, - 0xa8a9,0xa9a9,0xaaa9,0xaba9,0xaca9,0xada9,0xaea9,0xafa9, - 0xb0b1,0xb1b1,0xb2b1,0xb3b1,0xb4b1,0xb5b1,0xb6b1,0xb7b1, - 0xb8b9,0xb9b9,0xbab9,0xbbb9,0xbcb9,0xbdb9,0xbeb9,0xbfb9, - 0xc081,0xc181,0xc281,0xc381,0xc481,0xc581,0xc681,0xc781, - 0xc889,0xc989,0xca89,0xcb89,0xcc89,0xcd89,0xce89,0xcf89, - 0xd091,0xd191,0xd291,0xd391,0xd491,0xd591,0xd691,0xd791, - 0xd899,0xd999,0xda99,0xdb99,0xdc99,0xdd99,0xde99,0xdf99, - 0xe0a1,0xe1a1,0xe2a1,0xe3a1,0xe4a1,0xe5a1,0xe6a1,0xe7a1, - 0xe8a9,0xe9a9,0xeaa9,0xeba9,0xeca9,0xeda9,0xeea9,0xefa9, - 0xf0b1,0xf1b1,0xf2b1,0xf3b1,0xf4b1,0xf5b1,0xf6b1,0xf7b1, - 0xf8b9,0xf9b9,0xfab9,0xfbb9,0xfcb9,0xfdb9,0xfeb9,0xffb9, -}; - -/* cbitsDup16Table[i] = (i & 0x10) | ((i >> 8) & 1) | (i & 0x28), i = 0..511 */ -static const uint8 cbitsDup16Table[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24, - 32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40, - 48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24, - 32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40, - 48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24, - 32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40, - 48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24, - 32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40, - 48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56, - 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, - 17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25, - 33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41, - 49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57, - 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, - 17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25, - 33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41, - 49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57, - 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, - 17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25, - 33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41, - 49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57, - 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, - 17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25, - 33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41, - 49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57, -}; - -/* cbits2Table[i] = (i & 0x10) | ((i >> 8) & 1) | 2, i = 0..511 */ -static const uint8 cbits2Table[512] = { - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, -}; - -/* rrcaTable[i] = ((i & 1) << 15) | ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1), i = 0..255 */ -static const uint16 rrcaTable[256] = { - 0x0000,0x8001,0x0100,0x8101,0x0200,0x8201,0x0300,0x8301, - 0x0400,0x8401,0x0500,0x8501,0x0600,0x8601,0x0700,0x8701, - 0x0808,0x8809,0x0908,0x8909,0x0a08,0x8a09,0x0b08,0x8b09, - 0x0c08,0x8c09,0x0d08,0x8d09,0x0e08,0x8e09,0x0f08,0x8f09, - 0x1000,0x9001,0x1100,0x9101,0x1200,0x9201,0x1300,0x9301, - 0x1400,0x9401,0x1500,0x9501,0x1600,0x9601,0x1700,0x9701, - 0x1808,0x9809,0x1908,0x9909,0x1a08,0x9a09,0x1b08,0x9b09, - 0x1c08,0x9c09,0x1d08,0x9d09,0x1e08,0x9e09,0x1f08,0x9f09, - 0x2020,0xa021,0x2120,0xa121,0x2220,0xa221,0x2320,0xa321, - 0x2420,0xa421,0x2520,0xa521,0x2620,0xa621,0x2720,0xa721, - 0x2828,0xa829,0x2928,0xa929,0x2a28,0xaa29,0x2b28,0xab29, - 0x2c28,0xac29,0x2d28,0xad29,0x2e28,0xae29,0x2f28,0xaf29, - 0x3020,0xb021,0x3120,0xb121,0x3220,0xb221,0x3320,0xb321, - 0x3420,0xb421,0x3520,0xb521,0x3620,0xb621,0x3720,0xb721, - 0x3828,0xb829,0x3928,0xb929,0x3a28,0xba29,0x3b28,0xbb29, - 0x3c28,0xbc29,0x3d28,0xbd29,0x3e28,0xbe29,0x3f28,0xbf29, - 0x4000,0xc001,0x4100,0xc101,0x4200,0xc201,0x4300,0xc301, - 0x4400,0xc401,0x4500,0xc501,0x4600,0xc601,0x4700,0xc701, - 0x4808,0xc809,0x4908,0xc909,0x4a08,0xca09,0x4b08,0xcb09, - 0x4c08,0xcc09,0x4d08,0xcd09,0x4e08,0xce09,0x4f08,0xcf09, - 0x5000,0xd001,0x5100,0xd101,0x5200,0xd201,0x5300,0xd301, - 0x5400,0xd401,0x5500,0xd501,0x5600,0xd601,0x5700,0xd701, - 0x5808,0xd809,0x5908,0xd909,0x5a08,0xda09,0x5b08,0xdb09, - 0x5c08,0xdc09,0x5d08,0xdd09,0x5e08,0xde09,0x5f08,0xdf09, - 0x6020,0xe021,0x6120,0xe121,0x6220,0xe221,0x6320,0xe321, - 0x6420,0xe421,0x6520,0xe521,0x6620,0xe621,0x6720,0xe721, - 0x6828,0xe829,0x6928,0xe929,0x6a28,0xea29,0x6b28,0xeb29, - 0x6c28,0xec29,0x6d28,0xed29,0x6e28,0xee29,0x6f28,0xef29, - 0x7020,0xf021,0x7120,0xf121,0x7220,0xf221,0x7320,0xf321, - 0x7420,0xf421,0x7520,0xf521,0x7620,0xf621,0x7720,0xf721, - 0x7828,0xf829,0x7928,0xf929,0x7a28,0xfa29,0x7b28,0xfb29, - 0x7c28,0xfc29,0x7d28,0xfd29,0x7e28,0xfe29,0x7f28,0xff29, -}; - -/* rraTable[i] = ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1), i = 0..255 */ -static const uint16 rraTable[256] = { - 0x0000,0x0001,0x0100,0x0101,0x0200,0x0201,0x0300,0x0301, - 0x0400,0x0401,0x0500,0x0501,0x0600,0x0601,0x0700,0x0701, - 0x0808,0x0809,0x0908,0x0909,0x0a08,0x0a09,0x0b08,0x0b09, - 0x0c08,0x0c09,0x0d08,0x0d09,0x0e08,0x0e09,0x0f08,0x0f09, - 0x1000,0x1001,0x1100,0x1101,0x1200,0x1201,0x1300,0x1301, - 0x1400,0x1401,0x1500,0x1501,0x1600,0x1601,0x1700,0x1701, - 0x1808,0x1809,0x1908,0x1909,0x1a08,0x1a09,0x1b08,0x1b09, - 0x1c08,0x1c09,0x1d08,0x1d09,0x1e08,0x1e09,0x1f08,0x1f09, - 0x2020,0x2021,0x2120,0x2121,0x2220,0x2221,0x2320,0x2321, - 0x2420,0x2421,0x2520,0x2521,0x2620,0x2621,0x2720,0x2721, - 0x2828,0x2829,0x2928,0x2929,0x2a28,0x2a29,0x2b28,0x2b29, - 0x2c28,0x2c29,0x2d28,0x2d29,0x2e28,0x2e29,0x2f28,0x2f29, - 0x3020,0x3021,0x3120,0x3121,0x3220,0x3221,0x3320,0x3321, - 0x3420,0x3421,0x3520,0x3521,0x3620,0x3621,0x3720,0x3721, - 0x3828,0x3829,0x3928,0x3929,0x3a28,0x3a29,0x3b28,0x3b29, - 0x3c28,0x3c29,0x3d28,0x3d29,0x3e28,0x3e29,0x3f28,0x3f29, - 0x4000,0x4001,0x4100,0x4101,0x4200,0x4201,0x4300,0x4301, - 0x4400,0x4401,0x4500,0x4501,0x4600,0x4601,0x4700,0x4701, - 0x4808,0x4809,0x4908,0x4909,0x4a08,0x4a09,0x4b08,0x4b09, - 0x4c08,0x4c09,0x4d08,0x4d09,0x4e08,0x4e09,0x4f08,0x4f09, - 0x5000,0x5001,0x5100,0x5101,0x5200,0x5201,0x5300,0x5301, - 0x5400,0x5401,0x5500,0x5501,0x5600,0x5601,0x5700,0x5701, - 0x5808,0x5809,0x5908,0x5909,0x5a08,0x5a09,0x5b08,0x5b09, - 0x5c08,0x5c09,0x5d08,0x5d09,0x5e08,0x5e09,0x5f08,0x5f09, - 0x6020,0x6021,0x6120,0x6121,0x6220,0x6221,0x6320,0x6321, - 0x6420,0x6421,0x6520,0x6521,0x6620,0x6621,0x6720,0x6721, - 0x6828,0x6829,0x6928,0x6929,0x6a28,0x6a29,0x6b28,0x6b29, - 0x6c28,0x6c29,0x6d28,0x6d29,0x6e28,0x6e29,0x6f28,0x6f29, - 0x7020,0x7021,0x7120,0x7121,0x7220,0x7221,0x7320,0x7321, - 0x7420,0x7421,0x7520,0x7521,0x7620,0x7621,0x7720,0x7721, - 0x7828,0x7829,0x7928,0x7929,0x7a28,0x7a29,0x7b28,0x7b29, - 0x7c28,0x7c29,0x7d28,0x7d29,0x7e28,0x7e29,0x7f28,0x7f29, -}; - -/* addTable[i] = ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6), i = 0..511 */ -static const uint16 addTable[512] = { - 0x0040,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700, - 0x0808,0x0908,0x0a08,0x0b08,0x0c08,0x0d08,0x0e08,0x0f08, - 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, - 0x1808,0x1908,0x1a08,0x1b08,0x1c08,0x1d08,0x1e08,0x1f08, - 0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,0x2620,0x2720, - 0x2828,0x2928,0x2a28,0x2b28,0x2c28,0x2d28,0x2e28,0x2f28, - 0x3020,0x3120,0x3220,0x3320,0x3420,0x3520,0x3620,0x3720, - 0x3828,0x3928,0x3a28,0x3b28,0x3c28,0x3d28,0x3e28,0x3f28, - 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700, - 0x4808,0x4908,0x4a08,0x4b08,0x4c08,0x4d08,0x4e08,0x4f08, - 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x5700, - 0x5808,0x5908,0x5a08,0x5b08,0x5c08,0x5d08,0x5e08,0x5f08, - 0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,0x6620,0x6720, - 0x6828,0x6928,0x6a28,0x6b28,0x6c28,0x6d28,0x6e28,0x6f28, - 0x7020,0x7120,0x7220,0x7320,0x7420,0x7520,0x7620,0x7720, - 0x7828,0x7928,0x7a28,0x7b28,0x7c28,0x7d28,0x7e28,0x7f28, - 0x8080,0x8180,0x8280,0x8380,0x8480,0x8580,0x8680,0x8780, - 0x8888,0x8988,0x8a88,0x8b88,0x8c88,0x8d88,0x8e88,0x8f88, - 0x9080,0x9180,0x9280,0x9380,0x9480,0x9580,0x9680,0x9780, - 0x9888,0x9988,0x9a88,0x9b88,0x9c88,0x9d88,0x9e88,0x9f88, - 0xa0a0,0xa1a0,0xa2a0,0xa3a0,0xa4a0,0xa5a0,0xa6a0,0xa7a0, - 0xa8a8,0xa9a8,0xaaa8,0xaba8,0xaca8,0xada8,0xaea8,0xafa8, - 0xb0a0,0xb1a0,0xb2a0,0xb3a0,0xb4a0,0xb5a0,0xb6a0,0xb7a0, - 0xb8a8,0xb9a8,0xbaa8,0xbba8,0xbca8,0xbda8,0xbea8,0xbfa8, - 0xc080,0xc180,0xc280,0xc380,0xc480,0xc580,0xc680,0xc780, - 0xc888,0xc988,0xca88,0xcb88,0xcc88,0xcd88,0xce88,0xcf88, - 0xd080,0xd180,0xd280,0xd380,0xd480,0xd580,0xd680,0xd780, - 0xd888,0xd988,0xda88,0xdb88,0xdc88,0xdd88,0xde88,0xdf88, - 0xe0a0,0xe1a0,0xe2a0,0xe3a0,0xe4a0,0xe5a0,0xe6a0,0xe7a0, - 0xe8a8,0xe9a8,0xeaa8,0xeba8,0xeca8,0xeda8,0xeea8,0xefa8, - 0xf0a0,0xf1a0,0xf2a0,0xf3a0,0xf4a0,0xf5a0,0xf6a0,0xf7a0, - 0xf8a8,0xf9a8,0xfaa8,0xfba8,0xfca8,0xfda8,0xfea8,0xffa8, - 0x0040,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700, - 0x0808,0x0908,0x0a08,0x0b08,0x0c08,0x0d08,0x0e08,0x0f08, - 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, - 0x1808,0x1908,0x1a08,0x1b08,0x1c08,0x1d08,0x1e08,0x1f08, - 0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,0x2620,0x2720, - 0x2828,0x2928,0x2a28,0x2b28,0x2c28,0x2d28,0x2e28,0x2f28, - 0x3020,0x3120,0x3220,0x3320,0x3420,0x3520,0x3620,0x3720, - 0x3828,0x3928,0x3a28,0x3b28,0x3c28,0x3d28,0x3e28,0x3f28, - 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700, - 0x4808,0x4908,0x4a08,0x4b08,0x4c08,0x4d08,0x4e08,0x4f08, - 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x5700, - 0x5808,0x5908,0x5a08,0x5b08,0x5c08,0x5d08,0x5e08,0x5f08, - 0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,0x6620,0x6720, - 0x6828,0x6928,0x6a28,0x6b28,0x6c28,0x6d28,0x6e28,0x6f28, - 0x7020,0x7120,0x7220,0x7320,0x7420,0x7520,0x7620,0x7720, - 0x7828,0x7928,0x7a28,0x7b28,0x7c28,0x7d28,0x7e28,0x7f28, - 0x8080,0x8180,0x8280,0x8380,0x8480,0x8580,0x8680,0x8780, - 0x8888,0x8988,0x8a88,0x8b88,0x8c88,0x8d88,0x8e88,0x8f88, - 0x9080,0x9180,0x9280,0x9380,0x9480,0x9580,0x9680,0x9780, - 0x9888,0x9988,0x9a88,0x9b88,0x9c88,0x9d88,0x9e88,0x9f88, - 0xa0a0,0xa1a0,0xa2a0,0xa3a0,0xa4a0,0xa5a0,0xa6a0,0xa7a0, - 0xa8a8,0xa9a8,0xaaa8,0xaba8,0xaca8,0xada8,0xaea8,0xafa8, - 0xb0a0,0xb1a0,0xb2a0,0xb3a0,0xb4a0,0xb5a0,0xb6a0,0xb7a0, - 0xb8a8,0xb9a8,0xbaa8,0xbba8,0xbca8,0xbda8,0xbea8,0xbfa8, - 0xc080,0xc180,0xc280,0xc380,0xc480,0xc580,0xc680,0xc780, - 0xc888,0xc988,0xca88,0xcb88,0xcc88,0xcd88,0xce88,0xcf88, - 0xd080,0xd180,0xd280,0xd380,0xd480,0xd580,0xd680,0xd780, - 0xd888,0xd988,0xda88,0xdb88,0xdc88,0xdd88,0xde88,0xdf88, - 0xe0a0,0xe1a0,0xe2a0,0xe3a0,0xe4a0,0xe5a0,0xe6a0,0xe7a0, - 0xe8a8,0xe9a8,0xeaa8,0xeba8,0xeca8,0xeda8,0xeea8,0xefa8, - 0xf0a0,0xf1a0,0xf2a0,0xf3a0,0xf4a0,0xf5a0,0xf6a0,0xf7a0, - 0xf8a8,0xf9a8,0xfaa8,0xfba8,0xfca8,0xfda8,0xfea8,0xffa8, -}; - -/* subTable[i] = ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | 2, i = 0..255 */ -static const uint16 subTable[256] = { - 0x0042,0x0102,0x0202,0x0302,0x0402,0x0502,0x0602,0x0702, - 0x080a,0x090a,0x0a0a,0x0b0a,0x0c0a,0x0d0a,0x0e0a,0x0f0a, - 0x1002,0x1102,0x1202,0x1302,0x1402,0x1502,0x1602,0x1702, - 0x180a,0x190a,0x1a0a,0x1b0a,0x1c0a,0x1d0a,0x1e0a,0x1f0a, - 0x2022,0x2122,0x2222,0x2322,0x2422,0x2522,0x2622,0x2722, - 0x282a,0x292a,0x2a2a,0x2b2a,0x2c2a,0x2d2a,0x2e2a,0x2f2a, - 0x3022,0x3122,0x3222,0x3322,0x3422,0x3522,0x3622,0x3722, - 0x382a,0x392a,0x3a2a,0x3b2a,0x3c2a,0x3d2a,0x3e2a,0x3f2a, - 0x4002,0x4102,0x4202,0x4302,0x4402,0x4502,0x4602,0x4702, - 0x480a,0x490a,0x4a0a,0x4b0a,0x4c0a,0x4d0a,0x4e0a,0x4f0a, - 0x5002,0x5102,0x5202,0x5302,0x5402,0x5502,0x5602,0x5702, - 0x580a,0x590a,0x5a0a,0x5b0a,0x5c0a,0x5d0a,0x5e0a,0x5f0a, - 0x6022,0x6122,0x6222,0x6322,0x6422,0x6522,0x6622,0x6722, - 0x682a,0x692a,0x6a2a,0x6b2a,0x6c2a,0x6d2a,0x6e2a,0x6f2a, - 0x7022,0x7122,0x7222,0x7322,0x7422,0x7522,0x7622,0x7722, - 0x782a,0x792a,0x7a2a,0x7b2a,0x7c2a,0x7d2a,0x7e2a,0x7f2a, - 0x8082,0x8182,0x8282,0x8382,0x8482,0x8582,0x8682,0x8782, - 0x888a,0x898a,0x8a8a,0x8b8a,0x8c8a,0x8d8a,0x8e8a,0x8f8a, - 0x9082,0x9182,0x9282,0x9382,0x9482,0x9582,0x9682,0x9782, - 0x988a,0x998a,0x9a8a,0x9b8a,0x9c8a,0x9d8a,0x9e8a,0x9f8a, - 0xa0a2,0xa1a2,0xa2a2,0xa3a2,0xa4a2,0xa5a2,0xa6a2,0xa7a2, - 0xa8aa,0xa9aa,0xaaaa,0xabaa,0xacaa,0xadaa,0xaeaa,0xafaa, - 0xb0a2,0xb1a2,0xb2a2,0xb3a2,0xb4a2,0xb5a2,0xb6a2,0xb7a2, - 0xb8aa,0xb9aa,0xbaaa,0xbbaa,0xbcaa,0xbdaa,0xbeaa,0xbfaa, - 0xc082,0xc182,0xc282,0xc382,0xc482,0xc582,0xc682,0xc782, - 0xc88a,0xc98a,0xca8a,0xcb8a,0xcc8a,0xcd8a,0xce8a,0xcf8a, - 0xd082,0xd182,0xd282,0xd382,0xd482,0xd582,0xd682,0xd782, - 0xd88a,0xd98a,0xda8a,0xdb8a,0xdc8a,0xdd8a,0xde8a,0xdf8a, - 0xe0a2,0xe1a2,0xe2a2,0xe3a2,0xe4a2,0xe5a2,0xe6a2,0xe7a2, - 0xe8aa,0xe9aa,0xeaaa,0xebaa,0xecaa,0xedaa,0xeeaa,0xefaa, - 0xf0a2,0xf1a2,0xf2a2,0xf3a2,0xf4a2,0xf5a2,0xf6a2,0xf7a2, - 0xf8aa,0xf9aa,0xfaaa,0xfbaa,0xfcaa,0xfdaa,0xfeaa,0xffaa, -}; - -/* andTable[i] = (i << 8) | (i & 0xa8) | ((i == 0) << 6) | 0x10 | parityTable[i], i = 0..255 */ -static const uint16 andTable[256] = { - 0x0054,0x0110,0x0210,0x0314,0x0410,0x0514,0x0614,0x0710, - 0x0818,0x091c,0x0a1c,0x0b18,0x0c1c,0x0d18,0x0e18,0x0f1c, - 0x1010,0x1114,0x1214,0x1310,0x1414,0x1510,0x1610,0x1714, - 0x181c,0x1918,0x1a18,0x1b1c,0x1c18,0x1d1c,0x1e1c,0x1f18, - 0x2030,0x2134,0x2234,0x2330,0x2434,0x2530,0x2630,0x2734, - 0x283c,0x2938,0x2a38,0x2b3c,0x2c38,0x2d3c,0x2e3c,0x2f38, - 0x3034,0x3130,0x3230,0x3334,0x3430,0x3534,0x3634,0x3730, - 0x3838,0x393c,0x3a3c,0x3b38,0x3c3c,0x3d38,0x3e38,0x3f3c, - 0x4010,0x4114,0x4214,0x4310,0x4414,0x4510,0x4610,0x4714, - 0x481c,0x4918,0x4a18,0x4b1c,0x4c18,0x4d1c,0x4e1c,0x4f18, - 0x5014,0x5110,0x5210,0x5314,0x5410,0x5514,0x5614,0x5710, - 0x5818,0x591c,0x5a1c,0x5b18,0x5c1c,0x5d18,0x5e18,0x5f1c, - 0x6034,0x6130,0x6230,0x6334,0x6430,0x6534,0x6634,0x6730, - 0x6838,0x693c,0x6a3c,0x6b38,0x6c3c,0x6d38,0x6e38,0x6f3c, - 0x7030,0x7134,0x7234,0x7330,0x7434,0x7530,0x7630,0x7734, - 0x783c,0x7938,0x7a38,0x7b3c,0x7c38,0x7d3c,0x7e3c,0x7f38, - 0x8090,0x8194,0x8294,0x8390,0x8494,0x8590,0x8690,0x8794, - 0x889c,0x8998,0x8a98,0x8b9c,0x8c98,0x8d9c,0x8e9c,0x8f98, - 0x9094,0x9190,0x9290,0x9394,0x9490,0x9594,0x9694,0x9790, - 0x9898,0x999c,0x9a9c,0x9b98,0x9c9c,0x9d98,0x9e98,0x9f9c, - 0xa0b4,0xa1b0,0xa2b0,0xa3b4,0xa4b0,0xa5b4,0xa6b4,0xa7b0, - 0xa8b8,0xa9bc,0xaabc,0xabb8,0xacbc,0xadb8,0xaeb8,0xafbc, - 0xb0b0,0xb1b4,0xb2b4,0xb3b0,0xb4b4,0xb5b0,0xb6b0,0xb7b4, - 0xb8bc,0xb9b8,0xbab8,0xbbbc,0xbcb8,0xbdbc,0xbebc,0xbfb8, - 0xc094,0xc190,0xc290,0xc394,0xc490,0xc594,0xc694,0xc790, - 0xc898,0xc99c,0xca9c,0xcb98,0xcc9c,0xcd98,0xce98,0xcf9c, - 0xd090,0xd194,0xd294,0xd390,0xd494,0xd590,0xd690,0xd794, - 0xd89c,0xd998,0xda98,0xdb9c,0xdc98,0xdd9c,0xde9c,0xdf98, - 0xe0b0,0xe1b4,0xe2b4,0xe3b0,0xe4b4,0xe5b0,0xe6b0,0xe7b4, - 0xe8bc,0xe9b8,0xeab8,0xebbc,0xecb8,0xedbc,0xeebc,0xefb8, - 0xf0b4,0xf1b0,0xf2b0,0xf3b4,0xf4b0,0xf5b4,0xf6b4,0xf7b0, - 0xf8b8,0xf9bc,0xfabc,0xfbb8,0xfcbc,0xfdb8,0xfeb8,0xffbc, -}; - -/* xororTable[i] = (i << 8) | (i & 0xa8) | ((i == 0) << 6) | parityTable[i], i = 0..255 */ -static const uint16 xororTable[256] = { - 0x0044,0x0100,0x0200,0x0304,0x0400,0x0504,0x0604,0x0700, - 0x0808,0x090c,0x0a0c,0x0b08,0x0c0c,0x0d08,0x0e08,0x0f0c, - 0x1000,0x1104,0x1204,0x1300,0x1404,0x1500,0x1600,0x1704, - 0x180c,0x1908,0x1a08,0x1b0c,0x1c08,0x1d0c,0x1e0c,0x1f08, - 0x2020,0x2124,0x2224,0x2320,0x2424,0x2520,0x2620,0x2724, - 0x282c,0x2928,0x2a28,0x2b2c,0x2c28,0x2d2c,0x2e2c,0x2f28, - 0x3024,0x3120,0x3220,0x3324,0x3420,0x3524,0x3624,0x3720, - 0x3828,0x392c,0x3a2c,0x3b28,0x3c2c,0x3d28,0x3e28,0x3f2c, - 0x4000,0x4104,0x4204,0x4300,0x4404,0x4500,0x4600,0x4704, - 0x480c,0x4908,0x4a08,0x4b0c,0x4c08,0x4d0c,0x4e0c,0x4f08, - 0x5004,0x5100,0x5200,0x5304,0x5400,0x5504,0x5604,0x5700, - 0x5808,0x590c,0x5a0c,0x5b08,0x5c0c,0x5d08,0x5e08,0x5f0c, - 0x6024,0x6120,0x6220,0x6324,0x6420,0x6524,0x6624,0x6720, - 0x6828,0x692c,0x6a2c,0x6b28,0x6c2c,0x6d28,0x6e28,0x6f2c, - 0x7020,0x7124,0x7224,0x7320,0x7424,0x7520,0x7620,0x7724, - 0x782c,0x7928,0x7a28,0x7b2c,0x7c28,0x7d2c,0x7e2c,0x7f28, - 0x8080,0x8184,0x8284,0x8380,0x8484,0x8580,0x8680,0x8784, - 0x888c,0x8988,0x8a88,0x8b8c,0x8c88,0x8d8c,0x8e8c,0x8f88, - 0x9084,0x9180,0x9280,0x9384,0x9480,0x9584,0x9684,0x9780, - 0x9888,0x998c,0x9a8c,0x9b88,0x9c8c,0x9d88,0x9e88,0x9f8c, - 0xa0a4,0xa1a0,0xa2a0,0xa3a4,0xa4a0,0xa5a4,0xa6a4,0xa7a0, - 0xa8a8,0xa9ac,0xaaac,0xaba8,0xacac,0xada8,0xaea8,0xafac, - 0xb0a0,0xb1a4,0xb2a4,0xb3a0,0xb4a4,0xb5a0,0xb6a0,0xb7a4, - 0xb8ac,0xb9a8,0xbaa8,0xbbac,0xbca8,0xbdac,0xbeac,0xbfa8, - 0xc084,0xc180,0xc280,0xc384,0xc480,0xc584,0xc684,0xc780, - 0xc888,0xc98c,0xca8c,0xcb88,0xcc8c,0xcd88,0xce88,0xcf8c, - 0xd080,0xd184,0xd284,0xd380,0xd484,0xd580,0xd680,0xd784, - 0xd88c,0xd988,0xda88,0xdb8c,0xdc88,0xdd8c,0xde8c,0xdf88, - 0xe0a0,0xe1a4,0xe2a4,0xe3a0,0xe4a4,0xe5a0,0xe6a0,0xe7a4, - 0xe8ac,0xe9a8,0xeaa8,0xebac,0xeca8,0xedac,0xeeac,0xefa8, - 0xf0a4,0xf1a0,0xf2a0,0xf3a4,0xf4a0,0xf5a4,0xf6a4,0xf7a0, - 0xf8a8,0xf9ac,0xfaac,0xfba8,0xfcac,0xfda8,0xfea8,0xffac, -}; - -/* rotateShiftTable[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i & 0xff], i = 0..255 */ -static const uint8 rotateShiftTable[256] = { - 68, 0, 0, 4, 0, 4, 4, 0, 8, 12, 12, 8, 12, 8, 8, 12, - 0, 4, 4, 0, 4, 0, 0, 4, 12, 8, 8, 12, 8, 12, 12, 8, - 32, 36, 36, 32, 36, 32, 32, 36, 44, 40, 40, 44, 40, 44, 44, 40, - 36, 32, 32, 36, 32, 36, 36, 32, 40, 44, 44, 40, 44, 40, 40, 44, - 0, 4, 4, 0, 4, 0, 0, 4, 12, 8, 8, 12, 8, 12, 12, 8, - 4, 0, 0, 4, 0, 4, 4, 0, 8, 12, 12, 8, 12, 8, 8, 12, - 36, 32, 32, 36, 32, 36, 36, 32, 40, 44, 44, 40, 44, 40, 40, 44, - 32, 36, 36, 32, 36, 32, 32, 36, 44, 40, 40, 44, 40, 44, 44, 40, - 128,132,132,128,132,128,128,132,140,136,136,140,136,140,140,136, - 132,128,128,132,128,132,132,128,136,140,140,136,140,136,136,140, - 164,160,160,164,160,164,164,160,168,172,172,168,172,168,168,172, - 160,164,164,160,164,160,160,164,172,168,168,172,168,172,172,168, - 132,128,128,132,128,132,132,128,136,140,140,136,140,136,136,140, - 128,132,132,128,132,128,128,132,140,136,136,140,136,140,140,136, - 160,164,164,160,164,160,160,164,172,168,168,172,168,172,172,168, - 164,160,160,164,160,164,164,160,168,172,172,168,172,168,168,172, -}; - -/* incZ80Table[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | - (((i & 0xf) == 0) << 4) | ((i == 0x80) << 2), i = 0..256 */ -static const uint8 incZ80Table[257] = { - 80, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 148,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, 80, -}; - -/* decZ80Table[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | - (((i & 0xf) == 0xf) << 4) | ((i == 0x7f) << 2) | 2, i = 0..255 */ -static const uint8 decZ80Table[256] = { - 66, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 62, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, -}; - -/* cbitsZ80Table[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1), i = 0..511 */ -static const uint8 cbitsZ80Table[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, -}; - -/* cbitsZ80DupTable[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | - ((i >> 8) & 1) | (i & 0xa8), i = 0..511 */ -static const uint8 cbitsZ80DupTable[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24, - 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 48, 48, 48, 48, 48, 48, 48, 56, 56, 56, 56, 56, 56, 56, 56, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24, - 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 48, 48, 48, 48, 48, 48, 48, 56, 56, 56, 56, 56, 56, 56, 56, - 132,132,132,132,132,132,132,132,140,140,140,140,140,140,140,140, - 148,148,148,148,148,148,148,148,156,156,156,156,156,156,156,156, - 164,164,164,164,164,164,164,164,172,172,172,172,172,172,172,172, - 180,180,180,180,180,180,180,180,188,188,188,188,188,188,188,188, - 132,132,132,132,132,132,132,132,140,140,140,140,140,140,140,140, - 148,148,148,148,148,148,148,148,156,156,156,156,156,156,156,156, - 164,164,164,164,164,164,164,164,172,172,172,172,172,172,172,172, - 180,180,180,180,180,180,180,180,188,188,188,188,188,188,188,188, - 5, 5, 5, 5, 5, 5, 5, 5, 13, 13, 13, 13, 13, 13, 13, 13, - 21, 21, 21, 21, 21, 21, 21, 21, 29, 29, 29, 29, 29, 29, 29, 29, - 37, 37, 37, 37, 37, 37, 37, 37, 45, 45, 45, 45, 45, 45, 45, 45, - 53, 53, 53, 53, 53, 53, 53, 53, 61, 61, 61, 61, 61, 61, 61, 61, - 5, 5, 5, 5, 5, 5, 5, 5, 13, 13, 13, 13, 13, 13, 13, 13, - 21, 21, 21, 21, 21, 21, 21, 21, 29, 29, 29, 29, 29, 29, 29, 29, - 37, 37, 37, 37, 37, 37, 37, 37, 45, 45, 45, 45, 45, 45, 45, 45, - 53, 53, 53, 53, 53, 53, 53, 53, 61, 61, 61, 61, 61, 61, 61, 61, - 129,129,129,129,129,129,129,129,137,137,137,137,137,137,137,137, - 145,145,145,145,145,145,145,145,153,153,153,153,153,153,153,153, - 161,161,161,161,161,161,161,161,169,169,169,169,169,169,169,169, - 177,177,177,177,177,177,177,177,185,185,185,185,185,185,185,185, - 129,129,129,129,129,129,129,129,137,137,137,137,137,137,137,137, - 145,145,145,145,145,145,145,145,153,153,153,153,153,153,153,153, - 161,161,161,161,161,161,161,161,169,169,169,169,169,169,169,169, - 177,177,177,177,177,177,177,177,185,185,185,185,185,185,185,185, -}; - -/* cbits2Z80Table[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2, i = 0..511 */ -static const uint8 cbits2Z80Table[512] = { - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, -}; - -/* cbits2Z80DupTable[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2 | - (i & 0xa8), i = 0..511 */ -static const uint8 cbits2Z80DupTable[512] = { - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, - 18, 18, 18, 18, 18, 18, 18, 18, 26, 26, 26, 26, 26, 26, 26, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 42, - 50, 50, 50, 50, 50, 50, 50, 50, 58, 58, 58, 58, 58, 58, 58, 58, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, - 18, 18, 18, 18, 18, 18, 18, 18, 26, 26, 26, 26, 26, 26, 26, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 42, - 50, 50, 50, 50, 50, 50, 50, 50, 58, 58, 58, 58, 58, 58, 58, 58, - 134,134,134,134,134,134,134,134,142,142,142,142,142,142,142,142, - 150,150,150,150,150,150,150,150,158,158,158,158,158,158,158,158, - 166,166,166,166,166,166,166,166,174,174,174,174,174,174,174,174, - 182,182,182,182,182,182,182,182,190,190,190,190,190,190,190,190, - 134,134,134,134,134,134,134,134,142,142,142,142,142,142,142,142, - 150,150,150,150,150,150,150,150,158,158,158,158,158,158,158,158, - 166,166,166,166,166,166,166,166,174,174,174,174,174,174,174,174, - 182,182,182,182,182,182,182,182,190,190,190,190,190,190,190,190, - 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 15, 15, - 23, 23, 23, 23, 23, 23, 23, 23, 31, 31, 31, 31, 31, 31, 31, 31, - 39, 39, 39, 39, 39, 39, 39, 39, 47, 47, 47, 47, 47, 47, 47, 47, - 55, 55, 55, 55, 55, 55, 55, 55, 63, 63, 63, 63, 63, 63, 63, 63, - 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 15, 15, - 23, 23, 23, 23, 23, 23, 23, 23, 31, 31, 31, 31, 31, 31, 31, 31, - 39, 39, 39, 39, 39, 39, 39, 39, 47, 47, 47, 47, 47, 47, 47, 47, - 55, 55, 55, 55, 55, 55, 55, 55, 63, 63, 63, 63, 63, 63, 63, 63, - 131,131,131,131,131,131,131,131,139,139,139,139,139,139,139,139, - 147,147,147,147,147,147,147,147,155,155,155,155,155,155,155,155, - 163,163,163,163,163,163,163,163,171,171,171,171,171,171,171,171, - 179,179,179,179,179,179,179,179,187,187,187,187,187,187,187,187, - 131,131,131,131,131,131,131,131,139,139,139,139,139,139,139,139, - 147,147,147,147,147,147,147,147,155,155,155,155,155,155,155,155, - 163,163,163,163,163,163,163,163,171,171,171,171,171,171,171,171, - 179,179,179,179,179,179,179,179,187,187,187,187,187,187,187,187, -}; - -/* negTable[i] = (((i & 0x0f) != 0) << 4) | ((i == 0x80) << 2) | 2 | (i != 0), i = 0..255 */ -static const uint8 negTable[256] = { - 2,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 7,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, -}; - -/* rrdrldTable[i] = (i << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i], i = 0..255 */ -static const uint16 rrdrldTable[256] = { - 0x0044,0x0100,0x0200,0x0304,0x0400,0x0504,0x0604,0x0700, - 0x0808,0x090c,0x0a0c,0x0b08,0x0c0c,0x0d08,0x0e08,0x0f0c, - 0x1000,0x1104,0x1204,0x1300,0x1404,0x1500,0x1600,0x1704, - 0x180c,0x1908,0x1a08,0x1b0c,0x1c08,0x1d0c,0x1e0c,0x1f08, - 0x2020,0x2124,0x2224,0x2320,0x2424,0x2520,0x2620,0x2724, - 0x282c,0x2928,0x2a28,0x2b2c,0x2c28,0x2d2c,0x2e2c,0x2f28, - 0x3024,0x3120,0x3220,0x3324,0x3420,0x3524,0x3624,0x3720, - 0x3828,0x392c,0x3a2c,0x3b28,0x3c2c,0x3d28,0x3e28,0x3f2c, - 0x4000,0x4104,0x4204,0x4300,0x4404,0x4500,0x4600,0x4704, - 0x480c,0x4908,0x4a08,0x4b0c,0x4c08,0x4d0c,0x4e0c,0x4f08, - 0x5004,0x5100,0x5200,0x5304,0x5400,0x5504,0x5604,0x5700, - 0x5808,0x590c,0x5a0c,0x5b08,0x5c0c,0x5d08,0x5e08,0x5f0c, - 0x6024,0x6120,0x6220,0x6324,0x6420,0x6524,0x6624,0x6720, - 0x6828,0x692c,0x6a2c,0x6b28,0x6c2c,0x6d28,0x6e28,0x6f2c, - 0x7020,0x7124,0x7224,0x7320,0x7424,0x7520,0x7620,0x7724, - 0x782c,0x7928,0x7a28,0x7b2c,0x7c28,0x7d2c,0x7e2c,0x7f28, - 0x8080,0x8184,0x8284,0x8380,0x8484,0x8580,0x8680,0x8784, - 0x888c,0x8988,0x8a88,0x8b8c,0x8c88,0x8d8c,0x8e8c,0x8f88, - 0x9084,0x9180,0x9280,0x9384,0x9480,0x9584,0x9684,0x9780, - 0x9888,0x998c,0x9a8c,0x9b88,0x9c8c,0x9d88,0x9e88,0x9f8c, - 0xa0a4,0xa1a0,0xa2a0,0xa3a4,0xa4a0,0xa5a4,0xa6a4,0xa7a0, - 0xa8a8,0xa9ac,0xaaac,0xaba8,0xacac,0xada8,0xaea8,0xafac, - 0xb0a0,0xb1a4,0xb2a4,0xb3a0,0xb4a4,0xb5a0,0xb6a0,0xb7a4, - 0xb8ac,0xb9a8,0xbaa8,0xbbac,0xbca8,0xbdac,0xbeac,0xbfa8, - 0xc084,0xc180,0xc280,0xc384,0xc480,0xc584,0xc684,0xc780, - 0xc888,0xc98c,0xca8c,0xcb88,0xcc8c,0xcd88,0xce88,0xcf8c, - 0xd080,0xd184,0xd284,0xd380,0xd484,0xd580,0xd680,0xd784, - 0xd88c,0xd988,0xda88,0xdb8c,0xdc88,0xdd8c,0xde8c,0xdf88, - 0xe0a0,0xe1a4,0xe2a4,0xe3a0,0xe4a4,0xe5a0,0xe6a0,0xe7a4, - 0xe8ac,0xe9a8,0xeaa8,0xebac,0xeca8,0xedac,0xeeac,0xefa8, - 0xf0a4,0xf1a0,0xf2a0,0xf3a4,0xf4a0,0xf5a4,0xf6a4,0xf7a0, - 0xf8a8,0xf9ac,0xfaac,0xfba8,0xfcac,0xfda8,0xfea8,0xffac, -}; - -/* cpTable[i] = (i & 0x80) | (((i & 0xff) == 0) << 6), i = 0..255 */ -static const uint8 cpTable[256] = { - 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, -}; - -/* remove comments to generate table contents -static void altairz80_init(void); -void (*sim_vm_init) (void) = &altairz80_init; -static void altairz80_init(void) { -*/ -/* parityTable */ -/* - uint32 i, v; - for (i = 0; i < 256; i++) { - v = ((i & 1) + ((i & 2) >> 1) + ((i & 4) >> 2) + ((i & 8) >> 3) + - ((i & 16) >> 4) + ((i & 32) >> 5) + ((i & 64) >> 6) + ((i & 128) >> 7)) % 2 ? 0 : 4; - printf("%1d,", v); - if ( ((i+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* incTable */ -/* - uint32 temp, v; - for (temp = 0; temp <= 256; temp++) { - v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | (((temp & 0xf) == 0) << 4); - printf("%3d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* decTable */ -/* - uint32 temp, v; - for (temp = 0; temp < 256; temp++) { - v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | (((temp & 0xf) == 0xf) << 4) | 2; - printf("%3d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbitsTable */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | ((cbits >> 8) & 1); - printf("%2d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbitsDup8Table */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | ((cbits >> 8) & 1) | ((cbits & 0xff) << 8) | (cbits & 0xa8) | (((cbits & 0xff) == 0) << 6); - printf("0x%04x,", v); - if ( ((cbits+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* cbitsDup16Table */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | ((cbits >> 8) & 1) | (cbits & 0x28); - printf("%2d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbits2Table */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | ((cbits >> 8) & 1) | 2; - printf("%2d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* rrcaTable */ -/* - uint32 temp, sum, v; - for (temp = 0; temp < 256; temp++) { - sum = temp >> 1; - v = ((temp & 1) << 15) | (sum << 8) | (sum & 0x28) | (temp & 1); - printf("0x%04x,", v); - if ( ((temp+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* rraTable */ -/* - uint32 temp, sum, v; - for (temp = 0; temp < 256; temp++) { - sum = temp >> 1; - v = (sum << 8) | (sum & 0x28) | (temp & 1); - printf("0x%04x,", v); - if ( ((temp+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* addTable */ -/* - uint32 sum, v; - for (sum = 0; sum < 512; sum++) { - v = ((sum & 0xff) << 8) | (sum & 0xa8) | (((sum & 0xff) == 0) << 6); - printf("0x%04x,", v); - if ( ((sum+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* subTable */ -/* - uint32 sum, v; - for (sum = 0; sum < 256; sum++) { - v = ((sum & 0xff) << 8) | (sum & 0xa8) | (((sum & 0xff) == 0) << 6) | 2; - printf("0x%04x,", v); - if ( ((sum+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* andTable */ -/* - uint32 sum, v; - for (sum = 0; sum < 256; sum++) { - v = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | 0x10 | parityTable[sum]; - printf("0x%04x,", v); - if ( ((sum+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* xororTable */ -/* - uint32 sum, v; - for (sum = 0; sum < 256; sum++) { - v = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | parityTable[sum]; - printf("0x%04x,", v); - if ( ((sum+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* rotateShiftTable */ -/* - uint32 temp, v; - for (temp = 0; temp < 256; temp++) { - v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | parity(temp); - printf("%3d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* incZ80Table */ -/* - uint32 temp, v; - for (temp = 0; temp < 256; temp++) { - v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | - (((temp & 0xf) == 0) << 4) | ((temp == 0x80) << 2); - printf("%3d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* decZ80Table */ -/* - uint32 temp, v; - for (temp = 0; temp < 256; temp++) { - v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | - (((temp & 0xf) == 0xf) << 4) | ((temp == 0x7f) << 2) | 2; - printf("%3d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbitsZ80Table */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | (((cbits >> 6) ^ (cbits >> 5)) & 4) | - ((cbits >> 8) & 1); - printf("%2d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbitsZ80DupTable */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | (((cbits >> 6) ^ (cbits >> 5)) & 4) | - ((cbits >> 8) & 1) | (cbits & 0xa8); - printf("%3d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbits2Z80Table */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (((cbits >> 6) ^ (cbits >> 5)) & 4) | (cbits & 0x10) | 2 | ((cbits >> 8) & 1); - printf("%2d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbits2Z80DupTable */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (((cbits >> 6) ^ (cbits >> 5)) & 4) | (cbits & 0x10) | 2 | ((cbits >> 8) & 1) | - (cbits & 0xa8); - printf("%3d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* negTable */ -/* - uint32 temp, v; - for (temp = 0; temp < 256; temp++) { - v = (((temp & 0x0f) != 0) << 4) | ((temp == 0x80) << 2) | 2 | (temp != 0); - printf("%2d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* rrdrldTable */ -/* - uint32 acu, v; - for (acu = 0; acu < 256; acu++) { - v = (acu << 8) | (acu & 0xa8) | (((acu & 0xff) == 0) << 6) | parityTable[acu]; - printf("0x%04x,", v); - if ( ((acu+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* cpTable */ -/* - uint32 sum, v; - for (sum = 0; sum < 256; sum++) { - v = (sum & 0x80) | (((sum & 0xff) == 0) << 6); - printf("%3d,", v); - if ( ((sum+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* remove comments to generate table contents -} -*/ - -static void warnUnsuccessfulWriteAttempt(const uint32 Addr) { - if (cpu_unit.flags & UNIT_WARNROM) { - if (addressIsInROM(Addr)) { - message2("Attempt to write to ROM " AddressFormat ".\n", Addr); - } - else { - message2("Attempt to write to non existing memory " AddressFormat ".\n", Addr); - } - } -} - -static uint8 warnUnsuccessfulReadAttempt(const uint32 Addr) { - if (cpu_unit.flags & UNIT_WARNROM) { - message2("Attempt to read from non existing memory " AddressFormat ".\n", Addr); - } - return 0xff; -} - -/* determine whether Addr points to Read Only Memory */ -int32 addressIsInROM(const uint32 Addr) { - uint32 addr = Addr & ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */ - return (cpu_unit.flags & UNIT_ROM) && ( /* must have ROM enabled */ - /* in banked case we have standard Altair ROM */ - ((cpu_unit.flags & UNIT_BANKED) && (defaultROMLow <= addr)) || - /* in non-banked case we check the bounds of the ROM */ - (((cpu_unit.flags & UNIT_BANKED) == 0) && (ROMLow <= addr) && (addr <= ROMHigh))); -} - -/* determine whether Addr points to a valid memory address */ -int32 addressExists(const uint32 Addr) { - uint32 addr = Addr & ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */ - return (cpu_unit.flags & UNIT_BANKED) || (addr < MEMSIZE) || - ((cpu_unit.flags & UNIT_BANKED) == 0) && (cpu_unit.flags & UNIT_ROM) - && (ROMLow <= addr) && (addr <= ROMHigh); -} - -INLINE uint8 GetBYTE(register uint32 Addr) { - Addr &= ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */ - if (cpu_unit.flags & UNIT_BANKED) { /* banked memory case */ - /* if Addr below "common" take from selected bank, otherwise from bank 0 */ - return Addr < common ? M[Addr][bankSelect] : M[Addr][0]; - } - else { /* non-banked memory case */ - return ((Addr < MEMSIZE) || - (cpu_unit.flags & UNIT_ROM) && (ROMLow <= Addr) && (Addr <= ROMHigh)) ? - M[Addr][0] : warnUnsuccessfulReadAttempt(Addr); - } -} - -INLINE void PutBYTE(register uint32 Addr, register uint32 Value) { - Addr &= ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */ - if (cpu_unit.flags & UNIT_BANKED) { - if (Addr < common) { - M[Addr][bankSelect] = Value; - } - else if ((Addr < defaultROMLow) || ((cpu_unit.flags & UNIT_ROM) == 0)) { - M[Addr][0] = Value; - } - else { - warnUnsuccessfulWriteAttempt(Addr); - } - } - else { - if ((Addr < MEMSIZE) && ((Addr < ROMLow) || (Addr > ROMHigh) || ((cpu_unit.flags & UNIT_ROM) == 0))) { - M[Addr][0] = Value; - } - else { - warnUnsuccessfulWriteAttempt(Addr); - } - } -} - -void PutBYTEBasic(const uint32 Addr, const uint32 Bank, const uint32 Value) { - M[Addr & ADDRMASK][Bank & BANKMASK] = Value; -} - -void PutBYTEForced(register uint32 Addr, register uint32 Value) { - Addr &= ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */ - if ((cpu_unit.flags & UNIT_BANKED) && (Addr < common)) { - M[Addr][bankSelect] = Value; - } - else { - M[Addr][0] = Value; - } -} - -static INLINE void PutWORD(register uint32 Addr, register uint32 Value) { - Addr &= ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */ - if (cpu_unit.flags & UNIT_BANKED) { - if (Addr < common) { - M[Addr][bankSelect] = Value; - } - else if ((Addr < defaultROMLow) || ((cpu_unit.flags & UNIT_ROM) == 0)) { - M[Addr][0] = Value; - } - else { - warnUnsuccessfulWriteAttempt(Addr); - } - Addr = (Addr + 1) & ADDRMASK; - if (Addr < common) { - M[Addr][bankSelect] = Value >> 8; - } - else if ((Addr < defaultROMLow) || ((cpu_unit.flags & UNIT_ROM) == 0)) { - M[Addr][0] = Value >> 8; - } - else { - warnUnsuccessfulWriteAttempt(Addr); - } - } - else { - if ((Addr < MEMSIZE) && ((Addr < ROMLow) || (Addr > ROMHigh) || ((cpu_unit.flags & UNIT_ROM) == 0))) { - M[Addr][0] = Value; - } - else { - warnUnsuccessfulWriteAttempt(Addr); - } - Addr = (Addr + 1) & ADDRMASK; - if ((Addr < MEMSIZE) && ((Addr < ROMLow) || (Addr > ROMHigh) || ((cpu_unit.flags & UNIT_ROM) == 0))) { - M[Addr][0] = Value >> 8; - } - else { - warnUnsuccessfulWriteAttempt(Addr); - } - } -} - -#ifndef NO_INLINE -uint8 GetBYTEWrapper(register uint32 Addr) { /* make sure that non-inlined version exists */ - return GetBYTE(Addr); -} - -void PutBYTEWrapper(register uint32 Addr, register uint32 Value) { - PutBYTE(Addr, Value); -} -#endif - -#define RAM_mm(a) GetBYTE(a--) -#define RAM_pp(a) GetBYTE(a++) - -#define PutBYTE_pp(a,v) PutBYTE(a++, v) -#define PutBYTE_mm(a,v) PutBYTE(a--, v) -#define mm_PutBYTE(a,v) PutBYTE(--a, v) - -static INLINE uint16 GetWORD(register uint32 a) { - return GetBYTE(a) | (GetBYTE(a + 1) << 8); -} - -#define MASK_BRK (TRUE + 1) - -/* this is a modified version of sim_brk_test with two differences: - 1) is does not set sim_brk_pend to FALSE (this if left to the instruction decode) - 2) it returns MASK_BRK if a breakpoint is found but should be ignored -*/ -static int32 sim_brk_lookup (const t_addr loc, const int32 btyp) { - extern t_bool sim_brk_pend; - extern t_addr sim_brk_ploc; - extern char *sim_brk_act; - BRKTAB *bp; - if ((bp = sim_brk_fnd (loc)) && /* entry in table? */ - (btyp & bp -> typ) && /* type match? */ - (!sim_brk_pend || (loc != sim_brk_ploc)) && /* new location? */ - (--(bp -> cnt) <= 0)) { /* count reach 0? */ - bp -> cnt = 0; /* reset count */ - sim_brk_ploc = loc; /* save location */ - sim_brk_act = bp -> act; /* set up actions */ - sim_brk_pend = TRUE; /* don't do twice */ - return TRUE; - } - return (sim_brk_pend && (loc == sim_brk_ploc)) ? MASK_BRK : FALSE; -} - -static void prepareMemoryAccessMessage(t_addr loc) { - sprintf(memoryAccessMessage, "Memory access breakpoint [%04xh]", loc); -} - -#define PUSH(x) do { \ - mm_PutBYTE(SP, (x) >> 8); \ - mm_PutBYTE(SP, x); \ -} while (0) - -#define CheckBreakByte(a) \ - if (sim_brk_summ && sim_brk_test(a, SWMASK('M'))) { \ - reason = STOP_MEM; \ - prepareMemoryAccessMessage(a); \ - goto end_decode; \ - } - -#define CheckBreakTwoBytesExtended(a1, a2, iCode) \ - if (sim_brk_summ) { \ - br1 = sim_brk_lookup(a1, SWMASK('M')); \ - br2 = br1 ? FALSE : sim_brk_lookup(a2, SWMASK('M')); \ - if ((br1 == MASK_BRK) || (br2 == MASK_BRK)) { \ - sim_brk_pend = FALSE; \ - } \ - else if (br1 || br2) { \ - reason = STOP_MEM; \ - if (br1) { \ - prepareMemoryAccessMessage(a1); \ - } \ - else { \ - prepareMemoryAccessMessage(a2); \ - } \ - iCode; \ - goto end_decode; \ - } \ - else { \ - sim_brk_pend = FALSE; \ - } \ - } - -#define CheckBreakTwoBytes(a1, a2) CheckBreakTwoBytesExtended(a1, a2,;) - -#define CheckBreakWord(a) CheckBreakTwoBytes(a, (a + 1)) - -int32 sim_instr (void) { - extern int32 sim_interval; - extern t_bool sim_brk_pend; - extern int32 timerInterrupt; - extern int32 timerInterruptHandler; - extern uint32 sim_os_msec(void); - extern t_bool rtc_avail; - int32 reason = 0; - register uint32 specialProcessing; - register uint32 AF; - register uint32 BC; - register uint32 DE; - register uint32 HL; - register uint32 PC; - register uint32 SP; - register uint32 IX; - register uint32 IY; - register uint32 temp, acu, sum, cbits; - register uint32 op, adr; - /* tStates contains the number of t-states executed. One t-state is executed - in one microsecond on a 1MHz CPU. tStates is used real-time simulation */ - register uint32 tStates; - uint32 tStatesInSlice; /* number of t-states in 10 mSec time-slice */ - uint32 startTime; - int32 br1, br2, tStateModifier; - - pc = saved_PC & ADDRMASK; /* load local PC */ - af[af_sel] = AF_S; - regs[regs_sel].bc = BC_S; - regs[regs_sel].de = DE_S; - regs[regs_sel].hl = HL_S; - ix = IX_S; - iy = IY_S; - sp = SP_S; - af[1 - af_sel] = AF1_S; - regs[1 - regs_sel].bc = BC1_S; - regs[1 - regs_sel].de = DE1_S; - regs[1 - regs_sel].hl = HL1_S; - IFF = IFF_S; - ir = IR_S; - - AF = af[af_sel]; - BC = regs[regs_sel].bc; - DE = regs[regs_sel].de; - HL = regs[regs_sel].hl; - PC = pc; - SP = sp; - IX = ix; - IY = iy; - specialProcessing = clockFrequency | timerInterrupt | sim_brk_summ; - tStates = 0; - if (rtc_avail) { - startTime = sim_os_msec(); - tStatesInSlice = sliceLength*clockFrequency; - } - else { /* make sure that sim_os_msec() is not called later */ - clockFrequency = startTime = tStatesInSlice = 0; - } - - /* main instruction fetch/decode loop */ - while (TRUE) { /* loop until halted */ - if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event()) { - break; - } - else { - specialProcessing = clockFrequency | timerInterrupt | sim_brk_summ; - } - } - - if (specialProcessing) { /* quick check for special processing */ - if (clockFrequency && (tStates >= tStatesInSlice)) { - /* clockFrequency != 0 implies that real time clock is available */ - startTime += sliceLength; - tStates -= tStatesInSlice; - while (sim_os_msec() <= startTime) {} /* poor man's sleep */ - } - - if (timerInterrupt && (IFF & 1)) { - timerInterrupt = FALSE; - specialProcessing = clockFrequency | sim_brk_summ; - IFF = 0; /* disable interrupts */ - CheckBreakTwoBytesExtended(SP - 2, SP - 1, (timerInterrupt = TRUE, IFF |= 1)); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = timerInterruptHandler & ADDRMASK; - } - - if (sim_brk_summ && (sim_brk_lookup(PC, SWMASK('E')) == TRUE)) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; - } - } - - PCX = PC; - sim_interval--; - - /* make sure that each instructions properly sets sim_brk_pend: - 1) Either directly to FALSE if no memory access takes place or - 2) through a call to a Check... routine - */ - switch(RAM_pp(PC)) { - case 0x00: /* NOP */ - tStates += 4; - sim_brk_pend = FALSE; - break; - case 0x01: /* LD BC,nnnn */ - tStates += 10; - sim_brk_pend = FALSE; - BC = GetWORD(PC); - PC += 2; - break; - case 0x02: /* LD (BC),A */ - tStates += 7; - CheckBreakByte(BC) - PutBYTE(BC, hreg(AF)); - break; - case 0x03: /* INC BC */ - tStates += 6; - sim_brk_pend = FALSE; - ++BC; - break; - case 0x04: /* INC B */ - tStates += 4; - sim_brk_pend = FALSE; - BC += 0x100; - temp = hreg(BC); - AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); - break; - case 0x05: /* DEC B */ - tStates += 4; - sim_brk_pend = FALSE; - BC -= 0x100; - temp = hreg(BC); - AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); - break; - case 0x06: /* LD B,nn */ - tStates += 7; - sim_brk_pend = FALSE; - Sethreg(BC, RAM_pp(PC)); - break; - case 0x07: /* RLCA */ - tStates += 4; - sim_brk_pend = FALSE; - AF = ((AF >> 7) & 0x0128) | ((AF << 1) & ~0x1ff) | - (AF & 0xc4) | ((AF >> 15) & 1); - break; - case 0x08: /* EX AF,AF' */ - tStates += 4; - sim_brk_pend = FALSE; - checkCPU8080; - af[af_sel] = AF; - af_sel = 1 - af_sel; - AF = af[af_sel]; - break; - case 0x09: /* ADD HL,BC */ - tStates += 11; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - BC &= ADDRMASK; - sum = HL + BC; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ BC ^ sum) >> 8]; - HL = sum; - break; - case 0x0a: /* LD A,(BC) */ - tStates += 7; - CheckBreakByte(BC) - Sethreg(AF, GetBYTE(BC)); - break; - case 0x0b: /* DEC BC */ - tStates += 6; - sim_brk_pend = FALSE; - --BC; - break; - case 0x0c: /* INC C */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(BC) + 1; - Setlreg(BC, temp); - AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); - break; - case 0x0d: /* DEC C */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(BC) - 1; - Setlreg(BC, temp); - AF = (AF & ~0xfe) | decTable[temp & 0xff] | SetPV2(0x7f); - break; - case 0x0e: /* LD C,nn */ - tStates += 7; - sim_brk_pend = FALSE; - Setlreg(BC, RAM_pp(PC)); - break; - case 0x0f: /* RRCA */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & 0xc4) | rrcaTable[hreg(AF)]; - break; - case 0x10: /* DJNZ dd */ - sim_brk_pend = FALSE; - checkCPU8080; - if ((BC -= 0x100) & 0xff00) { - PCQ_ENTRY(PC - 1); - PC += (signed char) GetBYTE(PC) + 1; - tStates += 13; - } - else { - PC++; - tStates += 8; - } - break; - case 0x11: /* LD DE,nnnn */ - tStates += 10; - sim_brk_pend = FALSE; - DE = GetWORD(PC); - PC += 2; - break; - case 0x12: /* LD (DE),A */ - tStates += 7; - CheckBreakByte(DE) - PutBYTE(DE, hreg(AF)); - break; - case 0x13: /* INC DE */ - tStates += 6; - sim_brk_pend = FALSE; - ++DE; - break; - case 0x14: /* INC D */ - tStates += 4; - sim_brk_pend = FALSE; - DE += 0x100; - temp = hreg(DE); - AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); - break; - case 0x15: /* DEC D */ - tStates += 4; - sim_brk_pend = FALSE; - DE -= 0x100; - temp = hreg(DE); - AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); - break; - case 0x16: /* LD D,nn */ - tStates += 7; - sim_brk_pend = FALSE; - Sethreg(DE, RAM_pp(PC)); - break; - case 0x17: /* RLA */ - tStates += 4; - sim_brk_pend = FALSE; - AF = ((AF << 8) & 0x0100) | ((AF >> 7) & 0x28) | ((AF << 1) & ~0x01ff) | - (AF & 0xc4) | ((AF >> 15) & 1); - break; - case 0x18: /* JR dd */ - tStates += 12; - sim_brk_pend = FALSE; - checkCPU8080; - PCQ_ENTRY(PC - 1); - PC += (signed char) GetBYTE(PC) + 1; - break; - case 0x19: /* ADD HL,DE */ - tStates += 11; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - DE &= ADDRMASK; - sum = HL + DE; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ DE ^ sum) >> 8]; - HL = sum; - break; - case 0x1a: /* LD A,(DE) */ - tStates += 7; - CheckBreakByte(DE) - Sethreg(AF, GetBYTE(DE)); - break; - case 0x1b: /* DEC DE */ - tStates += 6; - sim_brk_pend = FALSE; - --DE; - break; - case 0x1c: /* INC E */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(DE) + 1; - Setlreg(DE, temp); - AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); - break; - case 0x1d: /* DEC E */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(DE) - 1; - Setlreg(DE, temp); - AF = (AF & ~0xfe) | decTable[temp & 0xff] | SetPV2(0x7f); - break; - case 0x1e: /* LD E,nn */ - tStates += 7; - sim_brk_pend = FALSE; - Setlreg(DE, RAM_pp(PC)); - break; - case 0x1f: /* RRA */ - tStates += 4; - sim_brk_pend = FALSE; - AF = ((AF & 1) << 15) | (AF & 0xc4) | rraTable[hreg(AF)]; - break; - case 0x20: /* JR NZ,dd */ - sim_brk_pend = FALSE; - checkCPU8080; - if (TSTFLAG(Z)) { - PC++; - tStates += 7; - } - else { - PCQ_ENTRY(PC - 1); - PC += (signed char) GetBYTE(PC) + 1; - tStates += 12; - } - break; - case 0x21: /* LD HL,nnnn */ - tStates += 10; - sim_brk_pend = FALSE; - HL = GetWORD(PC); - PC += 2; - break; - case 0x22: /* LD (nnnn),HL */ - tStates += 16; - temp = GetWORD(PC); - CheckBreakWord(temp); - PutWORD(temp, HL); - PC += 2; - break; - case 0x23: /* INC HL */ - tStates += 6; - sim_brk_pend = FALSE; - ++HL; - break; - case 0x24: /* INC H */ - tStates += 4; - sim_brk_pend = FALSE; - HL += 0x100; - temp = hreg(HL); - AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); - break; - case 0x25: /* DEC H */ - tStates += 4; - sim_brk_pend = FALSE; - HL -= 0x100; - temp = hreg(HL); - AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); - break; - case 0x26: /* LD H,nn */ - tStates += 7; - sim_brk_pend = FALSE; - Sethreg(HL, RAM_pp(PC)); - break; - case 0x27: /* DAA */ - tStates += 4; - sim_brk_pend = FALSE; - acu = hreg(AF); - temp = ldig(acu); - cbits = TSTFLAG(C); - if (TSTFLAG(N)) { /* last operation was a subtract */ - int hd = cbits || acu > 0x99; - if (TSTFLAG(H) || (temp > 9)) { /* adjust low digit */ - if (temp > 5) { - SETFLAG(H, 0); - } - acu -= 6; - acu &= 0xff; - } - if (hd) { /* adjust high digit */ - acu -= 0x160; - } - } - else { /* last operation was an add */ - if (TSTFLAG(H) || (temp > 9)) { /* adjust low digit */ - SETFLAG(H, (temp > 9)); - acu += 6; - } - if (cbits || ((acu & 0x1f0) > 0x90)) { /* adjust high digit */ - acu += 0x60; - } - } - AF = (AF & 0x12) | rrdrldTable[acu & 0xff] | (acu >> 8) & 1 | cbits; - break; - case 0x28: /* JR Z,dd */ - sim_brk_pend = FALSE; - checkCPU8080; - if (TSTFLAG(Z)) { - PCQ_ENTRY(PC - 1); - PC += (signed char) GetBYTE(PC) + 1; - tStates += 12; - } - else { - PC++; - tStates += 7; - } - break; - case 0x29: /* ADD HL,HL */ - tStates += 11; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - sum = HL + HL; - AF = (AF & ~0x3b) | cbitsDup16Table[sum >> 8]; - HL = sum; - break; - case 0x2a: /* LD HL,(nnnn) */ - tStates += 16; - temp = GetWORD(PC); - CheckBreakWord(temp); - HL = GetWORD(temp); - PC += 2; - break; - case 0x2b: /* DEC HL */ - tStates += 6; - sim_brk_pend = FALSE; - --HL; - break; - case 0x2c: /* INC L */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(HL) + 1; - Setlreg(HL, temp); - AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); - break; - case 0x2d: /* DEC L */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(HL) - 1; - Setlreg(HL, temp); - AF = (AF & ~0xfe) | decTable[temp & 0xff] | SetPV2(0x7f); - break; - case 0x2e: /* LD L,nn */ - tStates += 7; - sim_brk_pend = FALSE; - Setlreg(HL, RAM_pp(PC)); - break; - case 0x2f: /* CPL */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (~AF & ~0xff) | (AF & 0xc5) | ((~AF >> 8) & 0x28) | 0x12; - break; - case 0x30: /* JR NC,dd */ - sim_brk_pend = FALSE; - checkCPU8080; - if (TSTFLAG(C)) { - PC++; - tStates += 7; - } - else { - PCQ_ENTRY(PC - 1); - PC += (signed char) GetBYTE(PC) + 1; - tStates += 12; - } - break; - case 0x31: /* LD SP,nnnn */ - tStates += 10; - sim_brk_pend = FALSE; - SP = GetWORD(PC); - PC += 2; - break; - case 0x32: /* LD (nnnn),A */ - tStates += 13; - temp = GetWORD(PC); - CheckBreakByte(temp); - PutBYTE(temp, hreg(AF)); - PC += 2; - break; - case 0x33: /* INC SP */ - tStates += 6; - sim_brk_pend = FALSE; - ++SP; - break; - case 0x34: /* INC (HL) */ - tStates += 11; - CheckBreakByte(HL); - temp = GetBYTE(HL) + 1; - PutBYTE(HL, temp); - AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); - break; - case 0x35: /* DEC (HL) */ - tStates += 11; - CheckBreakByte(HL); - temp = GetBYTE(HL) - 1; - PutBYTE(HL, temp); - AF = (AF & ~0xfe) | decTable[temp & 0xff] | SetPV2(0x7f); - break; - case 0x36: /* LD (HL),nn */ - tStates += 10; - CheckBreakByte(HL); - PutBYTE(HL, RAM_pp(PC)); - break; - case 0x37: /* SCF */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & ~0x3b) | ((AF >> 8) & 0x28) | 1; - break; - case 0x38: /* JR C,dd */ - sim_brk_pend = FALSE; - checkCPU8080; - if (TSTFLAG(C)) { - PCQ_ENTRY(PC - 1); - PC += (signed char) GetBYTE(PC) + 1; - tStates += 12; - } - else { - PC++; - tStates += 7; - } - break; - case 0x39: /* ADD HL,SP */ - tStates += 11; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - SP &= ADDRMASK; - sum = HL + SP; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ SP ^ sum) >> 8]; - HL = sum; - break; - case 0x3a: /* LD A,(nnnn) */ - tStates += 13; - temp = GetWORD(PC); - CheckBreakByte(temp); - Sethreg(AF, GetBYTE(temp)); - PC += 2; - break; - case 0x3b: /* DEC SP */ - tStates += 6; - sim_brk_pend = FALSE; - --SP; - break; - case 0x3c: /* INC A */ - tStates += 4; - sim_brk_pend = FALSE; - AF += 0x100; - temp = hreg(AF); - AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); - break; - case 0x3d: /* DEC A */ - tStates += 4; - sim_brk_pend = FALSE; - AF -= 0x100; - temp = hreg(AF); - AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); - break; - case 0x3e: /* LD A,nn */ - tStates += 7; - sim_brk_pend = FALSE; - Sethreg(AF, RAM_pp(PC)); - break; - case 0x3f: /* CCF */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & ~0x3b) | ((AF >> 8) & 0x28) | ((AF & 1) << 4) | (~AF & 1); - break; - case 0x40: /* LD B,B */ - tStates += 4; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x41: /* LD B,C */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & 0xff) | ((BC & 0xff) << 8); - break; - case 0x42: /* LD B,D */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & 0xff) | (DE & ~0xff); - break; - case 0x43: /* LD B,E */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & 0xff) | ((DE & 0xff) << 8); - break; - case 0x44: /* LD B,H */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & 0xff) | (HL & ~0xff); - break; - case 0x45: /* LD B,L */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & 0xff) | ((HL & 0xff) << 8); - break; - case 0x46: /* LD B,(HL) */ - tStates += 7; - CheckBreakByte(HL); - Sethreg(BC, GetBYTE(HL)); - break; - case 0x47: /* LD B,A */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & 0xff) | (AF & ~0xff); - break; - case 0x48: /* LD C,B */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & ~0xff) | ((BC >> 8) & 0xff); - break; - case 0x49: /* LD C,C */ - tStates += 4; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x4a: /* LD C,D */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & ~0xff) | ((DE >> 8) & 0xff); - break; - case 0x4b: /* LD C,E */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & ~0xff) | (DE & 0xff); - break; - case 0x4c: /* LD C,H */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & ~0xff) | ((HL >> 8) & 0xff); - break; - case 0x4d: /* LD C,L */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & ~0xff) | (HL & 0xff); - break; - case 0x4e: /* LD C,(HL) */ - tStates += 7; - CheckBreakByte(HL); - Setlreg(BC, GetBYTE(HL)); - break; - case 0x4f: /* LD C,A */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & ~0xff) | ((AF >> 8) & 0xff); - break; - case 0x50: /* LD D,B */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & 0xff) | (BC & ~0xff); - break; - case 0x51: /* LD D,C */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & 0xff) | ((BC & 0xff) << 8); - break; - case 0x52: /* LD D,D */ - tStates += 4; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x53: /* LD D,E */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & 0xff) | ((DE & 0xff) << 8); - break; - case 0x54: /* LD D,H */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & 0xff) | (HL & ~0xff); - break; - case 0x55: /* LD D,L */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & 0xff) | ((HL & 0xff) << 8); - break; - case 0x56: /* LD D,(HL) */ - tStates += 7; - CheckBreakByte(HL); - Sethreg(DE, GetBYTE(HL)); - break; - case 0x57: /* LD D,A */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & 0xff) | (AF & ~0xff); - break; - case 0x58: /* LD E,B */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & ~0xff) | ((BC >> 8) & 0xff); - break; - case 0x59: /* LD E,C */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & ~0xff) | (BC & 0xff); - break; - case 0x5a: /* LD E,D */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & ~0xff) | ((DE >> 8) & 0xff); - break; - case 0x5b: /* LD E,E */ - tStates += 4; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x5c: /* LD E,H */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & ~0xff) | ((HL >> 8) & 0xff); - break; - case 0x5d: /* LD E,L */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & ~0xff) | (HL & 0xff); - break; - case 0x5e: /* LD E,(HL) */ - tStates += 7; - CheckBreakByte(HL); - Setlreg(DE, GetBYTE(HL)); - break; - case 0x5f: /* LD E,A */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & ~0xff) | ((AF >> 8) & 0xff); - break; - case 0x60: /* LD H,B */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & 0xff) | (BC & ~0xff); - break; - case 0x61: /* LD H,C */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & 0xff) | ((BC & 0xff) << 8); - break; - case 0x62: /* LD H,D */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & 0xff) | (DE & ~0xff); - break; - case 0x63: /* LD H,E */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & 0xff) | ((DE & 0xff) << 8); - break; - case 0x64: /* LD H,H */ - tStates += 4; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x65: /* LD H,L */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & 0xff) | ((HL & 0xff) << 8); - break; - case 0x66: /* LD H,(HL) */ - tStates += 7; - CheckBreakByte(HL); - Sethreg(HL, GetBYTE(HL)); - break; - case 0x67: /* LD H,A */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & 0xff) | (AF & ~0xff); - break; - case 0x68: /* LD L,B */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & ~0xff) | ((BC >> 8) & 0xff); - break; - case 0x69: /* LD L,C */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & ~0xff) | (BC & 0xff); - break; - case 0x6a: /* LD L,D */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & ~0xff) | ((DE >> 8) & 0xff); - break; - case 0x6b: /* LD L,E */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & ~0xff) | (DE & 0xff); - break; - case 0x6c: /* LD L,H */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & ~0xff) | ((HL >> 8) & 0xff); - break; - case 0x6d: /* LD L,L */ - tStates += 4; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x6e: /* LD L,(HL) */ - tStates += 7; - CheckBreakByte(HL); - Setlreg(HL, GetBYTE(HL)); - break; - case 0x6f: /* LD L,A */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & ~0xff) | ((AF >> 8) & 0xff); - break; - case 0x70: /* LD (HL),B */ - tStates += 7; - CheckBreakByte(HL); - PutBYTE(HL, hreg(BC)); - break; - case 0x71: /* LD (HL),C */ - tStates += 7; - CheckBreakByte(HL); - PutBYTE(HL, lreg(BC)); - break; - case 0x72: /* LD (HL),D */ - tStates += 7; - CheckBreakByte(HL); - PutBYTE(HL, hreg(DE)); - break; - case 0x73: /* LD (HL),E */ - tStates += 7; - CheckBreakByte(HL); - PutBYTE(HL, lreg(DE)); - break; - case 0x74: /* LD (HL),H */ - tStates += 7; - CheckBreakByte(HL); - PutBYTE(HL, hreg(HL)); - break; - case 0x75: /* LD (HL),L */ - tStates += 7; - CheckBreakByte(HL); - PutBYTE(HL, lreg(HL)); - break; - case 0x76: /* HALT */ - tStates += 4; - sim_brk_pend = FALSE; - reason = STOP_HALT; - PC--; - goto end_decode; - case 0x77: /* LD (HL),A */ - tStates += 7; - CheckBreakByte(HL); - PutBYTE(HL, hreg(AF)); - break; - case 0x78: /* LD A,B */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & 0xff) | (BC & ~0xff); - break; - case 0x79: /* LD A,C */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & 0xff) | ((BC & 0xff) << 8); - break; - case 0x7a: /* LD A,D */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & 0xff) | (DE & ~0xff); - break; - case 0x7b: /* LD A,E */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & 0xff) | ((DE & 0xff) << 8); - break; - case 0x7c: /* LD A,H */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & 0xff) | (HL & ~0xff); - break; - case 0x7d: /* LD A,L */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & 0xff) | ((HL & 0xff) << 8); - break; - case 0x7e: /* LD A,(HL) */ - tStates += 7; - CheckBreakByte(HL); - Sethreg(AF, GetBYTE(HL)); - break; - case 0x7f: /* LD A,A */ - tStates += 4; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x80: /* ADD A,B */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(BC); - acu = hreg(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x81: /* ADD A,C */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(BC); - acu = hreg(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x82: /* ADD A,D */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(DE); - acu = hreg(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x83: /* ADD A,E */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(DE); - acu = hreg(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x84: /* ADD A,H */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(HL); - acu = hreg(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x85: /* ADD A,L */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(HL); - acu = hreg(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x86: /* ADD A,(HL) */ - tStates += 7; - CheckBreakByte(HL); - temp = GetBYTE(HL); - acu = hreg(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x87: /* ADD A,A */ - tStates += 4; - sim_brk_pend = FALSE; - cbits = 2 * hreg(AF); - AF = cbitsDup8Table[cbits] | (SetPVS(cbits)); - break; - case 0x88: /* ADC A,B */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(BC); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x89: /* ADC A,C */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(BC); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x8a: /* ADC A,D */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(DE); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x8b: /* ADC A,E */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(DE); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x8c: /* ADC A,H */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(HL); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x8d: /* ADC A,L */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(HL); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x8e: /* ADC A,(HL) */ - tStates += 7; - CheckBreakByte(HL); - temp = GetBYTE(HL); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x8f: /* ADC A,A */ - tStates += 4; - sim_brk_pend = FALSE; - cbits = 2 * hreg(AF) + TSTFLAG(C); - AF = cbitsDup8Table[cbits] | (SetPVS(cbits)); - break; - case 0x90: /* SUB B */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(BC); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x91: /* SUB C */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(BC); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x92: /* SUB D */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(DE); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x93: /* SUB E */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(DE); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x94: /* SUB H */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(HL); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x95: /* SUB L */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(HL); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x96: /* SUB (HL) */ - tStates += 7; - CheckBreakByte(HL); - temp = GetBYTE(HL); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x97: /* SUB A */ - tStates += 4; - sim_brk_pend = FALSE; - AF = cpu_unit.flags & UNIT_CHIP ? 0x42 : 0x46; - break; - case 0x98: /* SBC A,B */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(BC); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x99: /* SBC A,C */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(BC); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x9a: /* SBC A,D */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(DE); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x9b: /* SBC A,E */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(DE); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x9c: /* SBC A,H */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(HL); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x9d: /* SBC A,L */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(HL); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x9e: /* SBC A,(HL) */ - tStates += 7; - CheckBreakByte(HL); - temp = GetBYTE(HL); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x9f: /* SBC A,A */ - tStates += 4; - sim_brk_pend = FALSE; - cbits = -TSTFLAG(C); - AF = subTable[cbits & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPVS(cbits)); - break; - case 0xa0: /* AND B */ - tStates += 4; - sim_brk_pend = FALSE; - AF = andTable[((AF & BC) >> 8) & 0xff]; - break; - case 0xa1: /* AND C */ - tStates += 4; - sim_brk_pend = FALSE; - AF = andTable[((AF >> 8) & BC) & 0xff]; - break; - case 0xa2: /* AND D */ - tStates += 4; - sim_brk_pend = FALSE; - AF = andTable[((AF & DE) >> 8) & 0xff]; - break; - case 0xa3: /* AND E */ - tStates += 4; - sim_brk_pend = FALSE; - AF = andTable[((AF >> 8) & DE) & 0xff]; - break; - case 0xa4: /* AND H */ - tStates += 4; - sim_brk_pend = FALSE; - AF = andTable[((AF & HL) >> 8) & 0xff]; - break; - case 0xa5: /* AND L */ - tStates += 4; - sim_brk_pend = FALSE; - AF = andTable[((AF >> 8) & HL) & 0xff]; - break; - case 0xa6: /* AND (HL) */ - tStates += 7; - CheckBreakByte(HL); - AF = andTable[((AF >> 8) & GetBYTE(HL)) & 0xff]; - break; - case 0xa7: /* AND A */ - tStates += 4; - sim_brk_pend = FALSE; - AF = andTable[(AF >> 8) & 0xff]; - break; - case 0xa8: /* XOR B */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF ^ BC) >> 8) & 0xff]; - break; - case 0xa9: /* XOR C */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) ^ BC) & 0xff]; - break; - case 0xaa: /* XOR D */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF ^ DE) >> 8) & 0xff]; - break; - case 0xab: /* XOR E */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) ^ DE) & 0xff]; - break; - case 0xac: /* XOR H */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF ^ HL) >> 8) & 0xff]; - break; - case 0xad: /* XOR L */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) ^ HL) & 0xff]; - break; - case 0xae: /* XOR (HL) */ - tStates += 7; - CheckBreakByte(HL); - AF = xororTable[((AF >> 8) ^ GetBYTE(HL)) & 0xff]; - break; - case 0xaf: /* XOR A */ - tStates += 4; - sim_brk_pend = FALSE; - AF = 0x44; - break; - case 0xb0: /* OR B */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF | BC) >> 8) & 0xff]; - break; - case 0xb1: /* OR C */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) | BC) & 0xff]; - break; - case 0xb2: /* OR D */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF | DE) >> 8) & 0xff]; - break; - case 0xb3: /* OR E */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) | DE) & 0xff]; - break; - case 0xb4: /* OR H */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF | HL) >> 8) & 0xff]; - break; - case 0xb5: /* OR L */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) | HL) & 0xff]; - break; - case 0xb6: /* OR (HL) */ - tStates += 7; - CheckBreakByte(HL); - AF = xororTable[((AF >> 8) | GetBYTE(HL)) & 0xff]; - break; - case 0xb7: /* OR A */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[(AF >> 8) & 0xff]; - break; - case 0xb8: /* CP B */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(BC); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SetPV) | cbits2Table[cbits & 0x1ff]; - break; - case 0xb9: /* CP C */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(BC); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SetPV) | cbits2Table[cbits & 0x1ff]; - break; - case 0xba: /* CP D */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(DE); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SetPV) | cbits2Table[cbits & 0x1ff]; - break; - case 0xbb: /* CP E */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(DE); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SetPV) | cbits2Table[cbits & 0x1ff]; - break; - case 0xbc: /* CP H */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(HL); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SetPV) | cbits2Table[cbits & 0x1ff]; - break; - case 0xbd: /* CP L */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(HL); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SetPV) | cbits2Table[cbits & 0x1ff]; - break; - case 0xbe: /* CP (HL) */ - tStates += 7; - CheckBreakByte(HL); - temp = GetBYTE(HL); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SetPV) | cbits2Table[cbits & 0x1ff]; - break; - case 0xbf: /* CP A */ - tStates += 4; - sim_brk_pend = FALSE; - Setlreg(AF, (hreg(AF) & 0x28) | (cpu_unit.flags & UNIT_CHIP ? 0x42 : 0x46)); - break; - case 0xc0: /* RET NZ */ - if (TSTFLAG(Z)) { - sim_brk_pend = FALSE; - tStates += 5; - } - else { - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - tStates += 11; - } - break; - case 0xc1: /* POP BC */ - tStates += 10; - CheckBreakWord(SP); - POP(BC); - break; - case 0xc2: /* JP NZ,nnnn */ - sim_brk_pend = FALSE; - JPC(!TSTFLAG(Z)); /* also updates tStates */ - break; - case 0xc3: /* JP nnnn */ - sim_brk_pend = FALSE; - JPC(1); /* also updates tStates */ - break; - case 0xc4: /* CALL NZ,nnnn */ - CALLC(!TSTFLAG(Z)); /* also updates tStates */ - break; - case 0xc5: /* PUSH BC */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(BC); - break; - case 0xc6: /* ADD A,nn */ - tStates += 7; - sim_brk_pend = FALSE; - temp = RAM_pp(PC); - acu = hreg(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0xc7: /* RST 0 */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = 0; - break; - case 0xc8: /* RET Z */ - if (TSTFLAG(Z)) { - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - tStates += 11; - } - else { - sim_brk_pend = FALSE; - tStates += 5; - } - break; - case 0xc9: /* RET */ - tStates += 10; - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - break; - case 0xca: /* JP Z,nnnn */ - sim_brk_pend = FALSE; - JPC(TSTFLAG(Z)); /* also updates tStates */ - break; - case 0xcb: /* CB prefix */ - checkCPU8080; - adr = HL; - switch ((op = GetBYTE(PC)) & 7) { - case 0: - sim_brk_pend = tStateModifier = FALSE; - ++PC; - acu = hreg(BC); - tStates += 8; - break; - case 1: - sim_brk_pend = tStateModifier = FALSE; - ++PC; - acu = lreg(BC); - tStates += 8; - break; - case 2: - sim_brk_pend = tStateModifier = FALSE; - ++PC; - acu = hreg(DE); - tStates += 8; - break; - case 3: - sim_brk_pend = tStateModifier = FALSE; - ++PC; - acu = lreg(DE); - tStates += 8; - break; - case 4: - sim_brk_pend = tStateModifier = FALSE; - ++PC; - acu = hreg(HL); - tStates += 8; - break; - case 5: - sim_brk_pend = tStateModifier = FALSE; - ++PC; - acu = lreg(HL); - tStates += 8; - break; - case 6: - CheckBreakByte(adr); - ++PC; - acu = GetBYTE(adr); - tStateModifier = TRUE; - tStates += 15; - break; - case 7: - sim_brk_pend = tStateModifier = FALSE; - ++PC; - acu = hreg(AF); - tStates += 8; - break; - } - switch (op & 0xc0) { - case 0x00: /* shift/rotate */ - switch (op & 0x38) { - case 0x00: /* RLC */ - temp = (acu << 1) | (acu >> 7); - cbits = temp & 1; - goto cbshflg1; - case 0x08: /* RRC */ - temp = (acu >> 1) | (acu << 7); - cbits = temp & 0x80; - goto cbshflg1; - case 0x10: /* RL */ - temp = (acu << 1) | TSTFLAG(C); - cbits = acu & 0x80; - goto cbshflg1; - case 0x18: /* RR */ - temp = (acu >> 1) | (TSTFLAG(C) << 7); - cbits = acu & 1; - goto cbshflg1; - case 0x20: /* SLA */ - temp = acu << 1; - cbits = acu & 0x80; - goto cbshflg1; - case 0x28: /* SRA */ - temp = (acu >> 1) | (acu & 0x80); - cbits = acu & 1; - goto cbshflg1; - case 0x30: /* SLIA */ - temp = (acu << 1) | 1; - cbits = acu & 0x80; - goto cbshflg1; - case 0x38: /* SRL */ - temp = acu >> 1; - cbits = acu & 1; - cbshflg1: - AF = (AF & ~0xff) | rotateShiftTable[temp & 0xff] | !!cbits; - } - break; - case 0x40: /* BIT */ - if (tStateModifier) { - tStates -= 3; - } - if (acu & (1 << ((op >> 3) & 7))) { - AF = (AF & ~0xfe) | 0x10 | (((op & 0x38) == 0x38) << 7); - } - else { - AF = (AF & ~0xfe) | 0x54; - } - if ((op & 7) != 6) { - AF |= (acu & 0x28); - } - temp = acu; - break; - case 0x80: /* RES */ - temp = acu & ~(1 << ((op >> 3) & 7)); - break; - case 0xc0: /* SET */ - temp = acu | (1 << ((op >> 3) & 7)); - break; - } - switch (op & 7) { - case 0: - Sethreg(BC, temp); - break; - case 1: - Setlreg(BC, temp); - break; - case 2: - Sethreg(DE, temp); - break; - case 3: - Setlreg(DE, temp); - break; - case 4: - Sethreg(HL, temp); - break; - case 5: - Setlreg(HL, temp); - break; - case 6: - PutBYTE(adr, temp); - break; - case 7: - Sethreg(AF, temp); - break; - } - break; - case 0xcc: /* CALL Z,nnnn */ - CALLC(TSTFLAG(Z)); /* also updates tStates */ - break; - case 0xcd: /* CALL nnnn */ - CALLC(1); /* also updates tStates */ - break; - case 0xce: /* ADC A,nn */ - tStates += 7; - sim_brk_pend = FALSE; - temp = RAM_pp(PC); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0xcf: /* RST 8 */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = 8; - break; - case 0xd0: /* RET NC */ - if (TSTFLAG(C)) { - sim_brk_pend = FALSE; - tStates += 5; - } - else { - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - tStates += 11; - } - break; - case 0xd1: /* POP DE */ - tStates += 10; - CheckBreakWord(SP); - POP(DE); - break; - case 0xd2: /* JP NC,nnnn */ - sim_brk_pend = FALSE; - JPC(!TSTFLAG(C)); /* also updates tStates */ - break; - case 0xd3: /* OUT (nn),A */ - tStates += 11; - sim_brk_pend = FALSE; - out(RAM_pp(PC), hreg(AF)); - break; - case 0xd4: /* CALL NC,nnnn */ - CALLC(!TSTFLAG(C)); /* also updates tStates */ - break; - case 0xd5: /* PUSH DE */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(DE); - break; - case 0xd6: /* SUB nn */ - tStates += 7; - sim_brk_pend = FALSE; - temp = RAM_pp(PC); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0xd7: /* RST 10H */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = 0x10; - break; - case 0xd8: /* RET C */ - if (TSTFLAG(C)) { - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - tStates += 11; - } - else { - sim_brk_pend = FALSE; - tStates += 5; - } - break; - case 0xd9: /* EXX */ - tStates += 4; - sim_brk_pend = FALSE; - checkCPU8080; - regs[regs_sel].bc = BC; - regs[regs_sel].de = DE; - regs[regs_sel].hl = HL; - regs_sel = 1 - regs_sel; - BC = regs[regs_sel].bc; - DE = regs[regs_sel].de; - HL = regs[regs_sel].hl; - break; - case 0xda: /* JP C,nnnn */ - sim_brk_pend = FALSE; - JPC(TSTFLAG(C)); /* also updates tStates */ - break; - case 0xdb: /* IN A,(nn) */ - tStates += 11; - sim_brk_pend = FALSE; - Sethreg(AF, in(RAM_pp(PC))); - break; - case 0xdc: /* CALL C,nnnn */ - CALLC(TSTFLAG(C)); /* also updates tStates */ - break; - case 0xdd: /* DD prefix */ - checkCPU8080; - switch (op = RAM_pp(PC)) { - case 0x09: /* ADD IX,BC */ - tStates += 15; - sim_brk_pend = FALSE; - IX &= ADDRMASK; - BC &= ADDRMASK; - sum = IX + BC; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IX ^ BC ^ sum) >> 8]; - IX = sum; - break; - case 0x19: /* ADD IX,DE */ - tStates += 15; - sim_brk_pend = FALSE; - IX &= ADDRMASK; - DE &= ADDRMASK; - sum = IX + DE; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IX ^ DE ^ sum) >> 8]; - IX = sum; - break; - case 0x21: /* LD IX,nnnn */ - tStates += 14; - sim_brk_pend = FALSE; - IX = GetWORD(PC); - PC += 2; - break; - case 0x22: /* LD (nnnn),IX */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - PutWORD(temp, IX); - PC += 2; - break; - case 0x23: /* INC IX */ - tStates += 10; - sim_brk_pend = FALSE; - ++IX; - break; - case 0x24: /* INC IXH */ - tStates += 9; - sim_brk_pend = FALSE; - IX += 0x100; - AF = (AF & ~0xfe) | incZ80Table[hreg(IX)]; - break; - case 0x25: /* DEC IXH */ - tStates += 9; - sim_brk_pend = FALSE; - IX -= 0x100; - AF = (AF & ~0xfe) | decZ80Table[hreg(IX)]; - break; - case 0x26: /* LD IXH,nn */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IX, RAM_pp(PC)); - break; - case 0x29: /* ADD IX,IX */ - tStates += 15; - sim_brk_pend = FALSE; - IX &= ADDRMASK; - sum = IX + IX; - AF = (AF & ~0x3b) | cbitsDup16Table[sum >> 8]; - IX = sum; - break; - case 0x2a: /* LD IX,(nnnn) */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - IX = GetWORD(temp); - PC += 2; - break; - case 0x2b: /* DEC IX */ - tStates += 10; - sim_brk_pend = FALSE; - --IX; - break; - case 0x2c: /* INC IXL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IX) + 1; - Setlreg(IX, temp); - AF = (AF & ~0xfe) | incZ80Table[temp]; - break; - case 0x2d: /* DEC IXL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IX) - 1; - Setlreg(IX, temp); - AF = (AF & ~0xfe) | decZ80Table[temp & 0xff]; - break; - case 0x2e: /* LD IXL,nn */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IX, RAM_pp(PC)); - break; - case 0x34: /* INC (IX+dd) */ - tStates += 23; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr) + 1; - PutBYTE(adr, temp); - AF = (AF & ~0xfe) | incZ80Table[temp]; - break; - case 0x35: /* DEC (IX+dd) */ - tStates += 23; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr) - 1; - PutBYTE(adr, temp); - AF = (AF & ~0xfe) | decZ80Table[temp & 0xff]; - break; - case 0x36: /* LD (IX+dd),nn */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, RAM_pp(PC)); - break; - case 0x39: /* ADD IX,SP */ - tStates += 15; - sim_brk_pend = FALSE; - IX &= ADDRMASK; - SP &= ADDRMASK; - sum = IX + SP; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IX ^ SP ^ sum) >> 8]; - IX = sum; - break; - case 0x44: /* LD B,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(BC, hreg(IX)); - break; - case 0x45: /* LD B,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(BC, lreg(IX)); - break; - case 0x46: /* LD B,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Sethreg(BC, GetBYTE(adr)); - break; - case 0x4c: /* LD C,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(BC, hreg(IX)); - break; - case 0x4d: /* LD C,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(BC, lreg(IX)); - break; - case 0x4e: /* LD C,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Setlreg(BC, GetBYTE(adr)); - break; - case 0x54: /* LD D,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(DE, hreg(IX)); - break; - case 0x55: /* LD D,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(DE, lreg(IX)); - break; - case 0x56: /* LD D,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Sethreg(DE, GetBYTE(adr)); - break; - case 0x5c: /* LD E,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(DE, hreg(IX)); - break; - case 0x5d: /* LD E,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(DE, lreg(IX)); - break; - case 0x5e: /* LD E,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Setlreg(DE, GetBYTE(adr)); - break; - case 0x60: /* LD IXH,B */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IX, hreg(BC)); - break; - case 0x61: /* LD IXH,C */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IX, lreg(BC)); - break; - case 0x62: /* LD IXH,D */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IX, hreg(DE)); - break; - case 0x63: /* LD IXH,E */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IX, lreg(DE)); - break; - case 0x64: /* LD IXH,IXH */ - tStates += 9; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x65: /* LD IXH,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IX, lreg(IX)); - break; - case 0x66: /* LD H,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Sethreg(HL, GetBYTE(adr)); - break; - case 0x67: /* LD IXH,A */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IX, hreg(AF)); - break; - case 0x68: /* LD IXL,B */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IX, hreg(BC)); - break; - case 0x69: /* LD IXL,C */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IX, lreg(BC)); - break; - case 0x6a: /* LD IXL,D */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IX, hreg(DE)); - break; - case 0x6b: /* LD IXL,E */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IX, lreg(DE)); - break; - case 0x6c: /* LD IXL,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IX, hreg(IX)); - break; - case 0x6d: /* LD IXL,IXL */ - tStates += 9; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x6e: /* LD L,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Setlreg(HL, GetBYTE(adr)); - break; - case 0x6f: /* LD IXL,A */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IX, hreg(AF)); - break; - case 0x70: /* LD (IX+dd),B */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(BC)); - break; - case 0x71: /* LD (IX+dd),C */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(BC)); - break; - case 0x72: /* LD (IX+dd),D */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(DE)); - break; - case 0x73: /* LD (IX+dd),E */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(DE)); - break; - case 0x74: /* LD (IX+dd),H */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(HL)); - break; - case 0x75: /* LD (IX+dd),L */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(HL)); - break; - case 0x77: /* LD (IX+dd),A */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(AF)); - break; - case 0x7c: /* LD A,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(AF, hreg(IX)); - break; - case 0x7d: /* LD A,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(AF, lreg(IX)); - break; - case 0x7e: /* LD A,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Sethreg(AF, GetBYTE(adr)); - break; - case 0x84: /* ADD A,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - temp = hreg(IX); - acu = hreg(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x85: /* ADD A,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IX); - acu = hreg(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x86: /* ADD A,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - acu = hreg(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x8c: /* ADC A,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - temp = hreg(IX); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x8d: /* ADC A,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IX); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x8e: /* ADC A,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x96: /* SUB (IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - acu = hreg(AF); - sum = acu - temp; - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0x94: /* SUB IXH */ - SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */ - case 0x9c: /* SBC A,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - temp = hreg(IX); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0x95: /* SUB IXL */ - SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */ - case 0x9d: /* SBC A,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IX); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0x9e: /* SBC A,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0xa4: /* AND IXH */ - tStates += 9; - sim_brk_pend = FALSE; - AF = andTable[((AF & IX) >> 8) & 0xff]; - break; - case 0xa5: /* AND IXL */ - tStates += 9; - sim_brk_pend = FALSE; - AF = andTable[((AF >> 8) & IX) & 0xff]; - break; - case 0xa6: /* AND (IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - AF = andTable[((AF >> 8) & GetBYTE(adr)) & 0xff]; - break; - case 0xac: /* XOR IXH */ - tStates += 9; - sim_brk_pend = FALSE; - AF = xororTable[((AF ^ IX) >> 8) & 0xff]; - break; - case 0xad: /* XOR IXL */ - tStates += 9; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) ^ IX) & 0xff]; - break; - case 0xae: /* XOR (IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - AF = xororTable[((AF >> 8) ^ GetBYTE(adr)) & 0xff]; - break; - case 0xb4: /* OR IXH */ - tStates += 9; - sim_brk_pend = FALSE; - AF = xororTable[((AF | IX) >> 8) & 0xff]; - break; - case 0xb5: /* OR IXL */ - tStates += 9; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) | IX) & 0xff]; - break; - case 0xb6: /* OR (IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - AF = xororTable[((AF >> 8) | GetBYTE(adr)) & 0xff]; - break; - case 0xbc: /* CP IXH */ - tStates += 9; - sim_brk_pend = FALSE; - temp = hreg(IX); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0xbd: /* CP IXL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IX); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0xbe: /* CP (IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0xcb: /* CB prefix */ - adr = IX + (signed char) RAM_pp(PC); - switch ((op = GetBYTE(PC)) & 7) { - case 0: - sim_brk_pend = FALSE; - ++PC; - acu = hreg(BC); - break; - case 1: - sim_brk_pend = FALSE; - ++PC; - acu = lreg(BC); - break; - case 2: - sim_brk_pend = FALSE; - ++PC; - acu = hreg(DE); - break; - case 3: - sim_brk_pend = FALSE; - ++PC; - acu = lreg(DE); - break; - case 4: - sim_brk_pend = FALSE; - ++PC; - acu = hreg(HL); - break; - case 5: - sim_brk_pend = FALSE; - ++PC; - acu = lreg(HL); - break; - case 6: - CheckBreakByte(adr); - ++PC; - acu = GetBYTE(adr); - break; - case 7: - sim_brk_pend = FALSE; - ++PC; - acu = hreg(AF); - break; - } - switch (op & 0xc0) { - case 0x00: /* shift/rotate */ - tStates += 23; - switch (op & 0x38) { - case 0x00: /* RLC */ - temp = (acu << 1) | (acu >> 7); - cbits = temp & 1; - goto cbshflg2; - case 0x08: /* RRC */ - temp = (acu >> 1) | (acu << 7); - cbits = temp & 0x80; - goto cbshflg2; - case 0x10: /* RL */ - temp = (acu << 1) | TSTFLAG(C); - cbits = acu & 0x80; - goto cbshflg2; - case 0x18: /* RR */ - temp = (acu >> 1) | (TSTFLAG(C) << 7); - cbits = acu & 1; - goto cbshflg2; - case 0x20: /* SLA */ - temp = acu << 1; - cbits = acu & 0x80; - goto cbshflg2; - case 0x28: /* SRA */ - temp = (acu >> 1) | (acu & 0x80); - cbits = acu & 1; - goto cbshflg2; - case 0x30: /* SLIA */ - temp = (acu << 1) | 1; - cbits = acu & 0x80; - goto cbshflg2; - case 0x38: /* SRL */ - temp = acu >> 1; - cbits = acu & 1; - cbshflg2: - AF = (AF & ~0xff) | rotateShiftTable[temp & 0xff] | !!cbits; - } - break; - case 0x40: /* BIT */ - tStates += 20; - if (acu & (1 << ((op >> 3) & 7))) { - AF = (AF & ~0xfe) | 0x10 | (((op & 0x38) == 0x38) << 7); - } - else { - AF = (AF & ~0xfe) | 0x54; - } - if ((op & 7) != 6) { - AF |= (acu & 0x28); - } - temp = acu; - break; - case 0x80: /* RES */ - tStates += 23; - temp = acu & ~(1 << ((op >> 3) & 7)); - break; - case 0xc0: /* SET */ - tStates += 23; - temp = acu | (1 << ((op >> 3) & 7)); - break; - } - switch (op & 7) { - case 0: - Sethreg(BC, temp); - break; - case 1: - Setlreg(BC, temp); - break; - case 2: - Sethreg(DE, temp); - break; - case 3: - Setlreg(DE, temp); - break; - case 4: - Sethreg(HL, temp); - break; - case 5: - Setlreg(HL, temp); - break; - case 6: - PutBYTE(adr, temp); - break; - case 7: - Sethreg(AF, temp); - break; - } - break; - case 0xe1: /* POP IX */ - tStates += 14; - CheckBreakWord(SP); - POP(IX); - break; - case 0xe3: /* EX (SP),IX */ - tStates += 23; - CheckBreakWord(SP); - temp = IX; - POP(IX); - PUSH(temp); - break; - case 0xe5: /* PUSH IX */ - tStates += 15; - CheckBreakWord(SP - 2); - PUSH(IX); - break; - case 0xe9: /* JP (IX) */ - tStates += 8; - sim_brk_pend = FALSE; - PCQ_ENTRY(PC - 2); - PC = IX; - break; - case 0xf9: /* LD SP,IX */ - tStates += 10; - sim_brk_pend = FALSE; - SP = IX; - break; - default: /* ignore DD */ - sim_brk_pend = FALSE; - checkCPUZ80; - PC--; - } - break; - case 0xde: /* SBC A,nn */ - tStates += 7; - sim_brk_pend = FALSE; - temp = RAM_pp(PC); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0xdf: /* RST 18H */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = 0x18; - break; - case 0xe0: /* RET PO */ - if (TSTFLAG(P)) { - sim_brk_pend = FALSE; - tStates += 5; - } - else { - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - tStates += 11; - } - break; - case 0xe1: /* POP HL */ - tStates += 10; - CheckBreakWord(SP); - POP(HL); - break; - case 0xe2: /* JP PO,nnnn */ - sim_brk_pend = FALSE; - JPC(!TSTFLAG(P)); /* also updates tStates */ - break; - case 0xe3: /* EX (SP),HL */ - tStates += 19; - CheckBreakWord(SP); - temp = HL; - POP(HL); - PUSH(temp); - break; - case 0xe4: /* CALL PO,nnnn */ - CALLC(!TSTFLAG(P)); /* also updates tStates */ - break; - case 0xe5: /* PUSH HL */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(HL); - break; - case 0xe6: /* AND nn */ - tStates += 7; - sim_brk_pend = FALSE; - AF = andTable[((AF >> 8) & RAM_pp(PC)) & 0xff]; - break; - case 0xe7: /* RST 20H */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = 0x20; - break; - case 0xe8: /* RET PE */ - if (TSTFLAG(P)) { - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - tStates += 11; - } - else { - sim_brk_pend = FALSE; - tStates += 5; - } - break; - case 0xe9: /* JP (HL) */ - tStates += 4; - sim_brk_pend = FALSE; - PCQ_ENTRY(PC - 1); - PC = HL; - break; - case 0xea: /* JP PE,nnnn */ - sim_brk_pend = FALSE; - JPC(TSTFLAG(P)); /* also updates tStates */ - break; - case 0xeb: /* EX DE,HL */ - tStates += 4; - sim_brk_pend = FALSE; - temp = HL; - HL = DE; - DE = temp; - break; - case 0xec: /* CALL PE,nnnn */ - CALLC(TSTFLAG(P)); /* also updates tStates */ - break; - case 0xed: /* ED prefix */ - checkCPU8080; - switch (op = RAM_pp(PC)) { - case 0x40: /* IN B,(C) */ - tStates += 12; - sim_brk_pend = FALSE; - temp = in(lreg(BC)); - Sethreg(BC, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - case 0x41: /* OUT (C),B */ - tStates += 12; - sim_brk_pend = FALSE; - out(lreg(BC), hreg(BC)); - break; - case 0x42: /* SBC HL,BC */ - tStates += 15; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - BC &= ADDRMASK; - sum = HL - BC - TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbits2Z80Table[((HL ^ BC ^ sum) >> 8) & 0x1ff]; - HL = sum; - break; - case 0x43: /* LD (nnnn),BC */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - PutWORD(temp, BC); - PC += 2; - break; - case 0x44: /* NEG */ - case 0x4C: /* NEG, unofficial */ - case 0x54: /* NEG, unofficial */ - case 0x5C: /* NEG, unofficial */ - case 0x64: /* NEG, unofficial */ - case 0x6C: /* NEG, unofficial */ - case 0x74: /* NEG, unofficial */ - case 0x7C: /* NEG, unofficial */ - tStates += 8; - sim_brk_pend = FALSE; - temp = hreg(AF); - AF = ((~(AF & 0xff00) + 1) & 0xff00); /* AF = (-(AF & 0xff00) & 0xff00); */ - AF |= ((AF >> 8) & 0xa8) | (((AF & 0xff00) == 0) << 6) | negTable[temp]; - break; - case 0x45: /* RETN */ - case 0x55: /* RETN, unofficial */ - case 0x5D: /* RETN, unofficial */ - case 0x65: /* RETN, unofficial */ - case 0x6D: /* RETN, unofficial */ - case 0x75: /* RETN, unofficial */ - case 0x7D: /* RETN, unofficial */ - tStates += 14; - IFF |= IFF >> 1; - CheckBreakWord(SP); - PCQ_ENTRY(PC - 2); - POP(PC); - break; - case 0x46: /* IM 0 */ - tStates += 8; - sim_brk_pend = FALSE; - /* interrupt mode 0 */ - break; - case 0x47: /* LD I,A */ - tStates += 9; - sim_brk_pend = FALSE; - ir = (ir & 0xff) | (AF & ~0xff); - break; - case 0x48: /* IN C,(C) */ - tStates += 12; - sim_brk_pend = FALSE; - temp = in(lreg(BC)); - Setlreg(BC, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - case 0x49: /* OUT (C),C */ - tStates += 12; - sim_brk_pend = FALSE; - out(lreg(BC), lreg(BC)); - break; - case 0x4a: /* ADC HL,BC */ - tStates += 15; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - BC &= ADDRMASK; - sum = HL + BC + TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbitsZ80Table[(HL ^ BC ^ sum) >> 8]; - HL = sum; - break; - case 0x4b: /* LD BC,(nnnn) */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - BC = GetWORD(temp); - PC += 2; - break; - case 0x4d: /* RETI */ - tStates += 14; - IFF |= IFF >> 1; - CheckBreakWord(SP); - PCQ_ENTRY(PC - 2); - POP(PC); - break; - case 0x4f: /* LD R,A */ - tStates += 9; - sim_brk_pend = FALSE; - ir = (ir & ~0xff) | ((AF >> 8) & 0xff); - break; - case 0x50: /* IN D,(C) */ - tStates += 12; - sim_brk_pend = FALSE; - temp = in(lreg(BC)); - Sethreg(DE, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - case 0x51: /* OUT (C),D */ - tStates += 12; - sim_brk_pend = FALSE; - out(lreg(BC), hreg(DE)); - break; - case 0x52: /* SBC HL,DE */ - tStates += 15; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - DE &= ADDRMASK; - sum = HL - DE - TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbits2Z80Table[((HL ^ DE ^ sum) >> 8) & 0x1ff]; - HL = sum; - break; - case 0x53: /* LD (nnnn),DE */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - PutWORD(temp, DE); - PC += 2; - break; - case 0x56: /* IM 1 */ - tStates += 8; - sim_brk_pend = FALSE; - /* interrupt mode 1 */ - break; - case 0x57: /* LD A,I */ - tStates += 9; - sim_brk_pend = FALSE; - AF = (AF & 0x29) | (ir & ~0xff) | ((ir >> 8) & 0x80) | (((ir & ~0xff) == 0) << 6) | ((IFF & 2) << 1); - break; - case 0x58: /* IN E,(C) */ - tStates += 12; - sim_brk_pend = FALSE; - temp = in(lreg(BC)); - Setlreg(DE, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - case 0x59: /* OUT (C),E */ - tStates += 12; - sim_brk_pend = FALSE; - out(lreg(BC), lreg(DE)); - break; - case 0x5a: /* ADC HL,DE */ - tStates += 15; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - DE &= ADDRMASK; - sum = HL + DE + TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbitsZ80Table[(HL ^ DE ^ sum) >> 8]; - HL = sum; - break; - case 0x5b: /* LD DE,(nnnn) */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - DE = GetWORD(temp); - PC += 2; - break; - case 0x5e: /* IM 2 */ - tStates += 8; - sim_brk_pend = FALSE; - /* interrupt mode 2 */ - break; - case 0x5f: /* LD A,R */ - tStates += 9; - sim_brk_pend = FALSE; - AF = (AF & 0x29) | ((ir & 0xff) << 8) | (ir & 0x80) | - (((ir & 0xff) == 0) << 6) | ((IFF & 2) << 1); - break; - case 0x60: /* IN H,(C) */ - tStates += 12; - sim_brk_pend = FALSE; - temp = in(lreg(BC)); - Sethreg(HL, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - case 0x61: /* OUT (C),H */ - tStates += 12; - sim_brk_pend = FALSE; - out(lreg(BC), hreg(HL)); - break; - case 0x62: /* SBC HL,HL */ - tStates += 15; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - sum = HL - HL - TSTFLAG(C); - AF = (AF & ~0xff) | (((sum & ADDRMASK) == 0) << 6) | - cbits2Z80DupTable[(sum >> 8) & 0x1ff]; - HL = sum; - break; - case 0x63: /* LD (nnnn),HL */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - PutWORD(temp, HL); - PC += 2; - break; - case 0x67: /* RRD */ - tStates += 18; - sim_brk_pend = FALSE; - temp = GetBYTE(HL); - acu = hreg(AF); - PutBYTE(HL, hdig(temp) | (ldig(acu) << 4)); - AF = rrdrldTable[(acu & 0xf0) | ldig(temp)] | (AF & 1); - break; - case 0x68: /* IN L,(C) */ - tStates += 12; - sim_brk_pend = FALSE; - temp = in(lreg(BC)); - Setlreg(HL, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - case 0x69: /* OUT (C),L */ - tStates += 12; - sim_brk_pend = FALSE; - out(lreg(BC), lreg(HL)); - break; - case 0x6a: /* ADC HL,HL */ - tStates += 15; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - sum = HL + HL + TSTFLAG(C); - AF = (AF & ~0xff) | (((sum & ADDRMASK) == 0) << 6) | - cbitsZ80DupTable[sum >> 8]; - HL = sum; - break; - case 0x6b: /* LD HL,(nnnn) */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - HL = GetWORD(temp); - PC += 2; - break; - case 0x6f: /* RLD */ - tStates += 18; - sim_brk_pend = FALSE; - temp = GetBYTE(HL); - acu = hreg(AF); - PutBYTE(HL, (ldig(temp) << 4) | ldig(acu)); - AF = rrdrldTable[(acu & 0xf0) | hdig(temp)] | (AF & 1); - break; - case 0x70: /* IN (C) */ - tStates += 12; - sim_brk_pend = FALSE; - temp = in(lreg(BC)); - Setlreg(temp, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - case 0x71: /* OUT (C),0 */ - tStates += 12; - sim_brk_pend = FALSE; - out(lreg(BC), 0); - break; - case 0x72: /* SBC HL,SP */ - tStates += 15; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - SP &= ADDRMASK; - sum = HL - SP - TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbits2Z80Table[((HL ^ SP ^ sum) >> 8) & 0x1ff]; - HL = sum; - break; - case 0x73: /* LD (nnnn),SP */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - PutWORD(temp, SP); - PC += 2; - break; - case 0x78: /* IN A,(C) */ - tStates += 12; - sim_brk_pend = FALSE; - temp = in(lreg(BC)); - Sethreg(AF, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - case 0x79: /* OUT (C),A */ - tStates += 12; - sim_brk_pend = FALSE; - out(lreg(BC), hreg(AF)); - break; - case 0x7a: /* ADC HL,SP */ - tStates += 15; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - SP &= ADDRMASK; - sum = HL + SP + TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbitsZ80Table[(HL ^ SP ^ sum) >> 8]; - HL = sum; - break; - case 0x7b: /* LD SP,(nnnn) */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - SP = GetWORD(temp); - PC += 2; - break; - case 0xa0: /* LDI */ - tStates += 16; - CheckBreakTwoBytes(HL, DE); - acu = RAM_pp(HL); - PutBYTE_pp(DE, acu); - acu += hreg(AF); - AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4) | - (((--BC & ADDRMASK) != 0) << 2); - break; - case 0xa1: /* CPI */ - tStates += 16; - CheckBreakByte(HL); - acu = hreg(AF); - temp = RAM_pp(HL); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | - (((sum - ((cbits & 16) >> 4)) & 2) << 4) | (cbits & 16) | - ((sum - ((cbits >> 4) & 1)) & 8) | - ((--BC & ADDRMASK) != 0) << 2 | 2; - if ((sum & 15) == 8 && (cbits & 16) != 0) { - AF &= ~8; - } - break; - case 0xa2: /* INI */ - tStates += 16; - CheckBreakByte(HL); - PutBYTE(HL, in(lreg(BC))); - ++HL; - SETFLAG(N, 1); - SETFLAG(P, (--BC & ADDRMASK) != 0); - break; - case 0xa3: /* OUTI */ - tStates += 16; - CheckBreakByte(HL); - out(lreg(BC), GetBYTE(HL)); - ++HL; - SETFLAG(N, 1); - Sethreg(BC, lreg(BC) - 1); - SETFLAG(Z, lreg(BC) == 0); - break; - case 0xa8: /* LDD */ - tStates += 16; - CheckBreakTwoBytes(HL, DE); - acu = RAM_mm(HL); - PutBYTE_mm(DE, acu); - acu += hreg(AF); - AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4) | - (((--BC & ADDRMASK) != 0) << 2); - break; - case 0xa9: /* CPD */ - tStates += 16; - CheckBreakByte(HL); - acu = hreg(AF); - temp = RAM_mm(HL); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | - (((sum - ((cbits & 16) >> 4)) & 2) << 4) | (cbits & 16) | - ((sum - ((cbits >> 4) & 1)) & 8) | - ((--BC & ADDRMASK) != 0) << 2 | 2; - if ((sum & 15) == 8 && (cbits & 16) != 0) { - AF &= ~8; - } - break; - case 0xaa: /* IND */ - tStates += 16; - CheckBreakByte(HL); - PutBYTE(HL, in(lreg(BC))); - --HL; - SETFLAG(N, 1); - Sethreg(BC, lreg(BC) - 1); - SETFLAG(Z, lreg(BC) == 0); - break; - case 0xab: /* OUTD */ - tStates += 16; - CheckBreakByte(HL); - out(lreg(BC), GetBYTE(HL)); - --HL; - SETFLAG(N, 1); - Sethreg(BC, lreg(BC) - 1); - SETFLAG(Z, lreg(BC) == 0); - break; - case 0xb0: /* LDIR */ - tStates -= 5; - acu = hreg(AF); - BC &= ADDRMASK; - do { - tStates += 21; - CheckBreakTwoBytes(HL, DE); - acu = RAM_pp(HL); - PutBYTE_pp(DE, acu); - } while (--BC); - acu += hreg(AF); - AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4); - break; - case 0xb1: /* CPIR */ - tStates -= 5; - acu = hreg(AF); - BC &= ADDRMASK; - do { - tStates += 21; - CheckBreakByte(HL); - temp = RAM_pp(HL); - op = --BC != 0; - sum = acu - temp; - } while (op && sum != 0); - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | - (((sum - ((cbits & 16) >> 4)) & 2) << 4) | - (cbits & 16) | ((sum - ((cbits >> 4) & 1)) & 8) | - op << 2 | 2; - if ((sum & 15) == 8 && (cbits & 16) != 0) { - AF &= ~8; - } - break; - case 0xb2: /* INIR */ - tStates -= 5; - temp = hreg(BC); - do { - tStates += 21; - CheckBreakByte(HL); - PutBYTE(HL, in(lreg(BC))); - ++HL; - } while (--temp); - Sethreg(BC, 0); - SETFLAG(N, 1); - SETFLAG(Z, 1); - break; - case 0xb3: /* OTIR */ - tStates -= 5; - temp = hreg(BC); - do { - tStates += 21; - CheckBreakByte(HL); - out(lreg(BC), GetBYTE(HL)); - ++HL; - } while (--temp); - Sethreg(BC, 0); - SETFLAG(N, 1); - SETFLAG(Z, 1); - break; - case 0xb8: /* LDDR */ - tStates -= 5; - BC &= ADDRMASK; - do { - tStates += 21; - CheckBreakTwoBytes(HL, DE); - acu = RAM_mm(HL); - PutBYTE_mm(DE, acu); - } while (--BC); - acu += hreg(AF); - AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4); - break; - case 0xb9: /* CPDR */ - tStates -= 5; - acu = hreg(AF); - BC &= ADDRMASK; - do { - tStates += 21; - CheckBreakByte(HL); - temp = RAM_mm(HL); - op = --BC != 0; - sum = acu - temp; - } while (op && sum != 0); - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | - (((sum - ((cbits & 16) >> 4)) & 2) << 4) | - (cbits & 16) | ((sum - ((cbits >> 4) & 1)) & 8) | - op << 2 | 2; - if ((sum & 15) == 8 && (cbits & 16) != 0) { - AF &= ~8; - } - break; - case 0xba: /* INDR */ - tStates -= 5; - temp = hreg(BC); - do { - tStates += 21; - CheckBreakByte(HL); - PutBYTE(HL, in(lreg(BC))); - --HL; - } while (--temp); - Sethreg(BC, 0); - SETFLAG(N, 1); - SETFLAG(Z, 1); - break; - case 0xbb: /* OTDR */ - tStates -= 5; - temp = hreg(BC); - do { - tStates += 21; - CheckBreakByte(HL); - out(lreg(BC), GetBYTE(HL)); - --HL; - } while (--temp); - Sethreg(BC, 0); - SETFLAG(N, 1); - SETFLAG(Z, 1); - break; - default: /* ignore ED and following byte */ - sim_brk_pend = FALSE; - checkCPUZ80; - } - break; - case 0xee: /* XOR nn */ - tStates += 7; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) ^ RAM_pp(PC)) & 0xff]; - break; - case 0xef: /* RST 28H */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = 0x28; - break; - case 0xf0: /* RET P */ - if (TSTFLAG(S)) { - sim_brk_pend = FALSE; - tStates += 5; - } - else { - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - tStates += 11; - } - break; - case 0xf1: /* POP AF */ - tStates += 10; - CheckBreakWord(SP); - POP(AF); - break; - case 0xf2: /* JP P,nnnn */ - sim_brk_pend = FALSE; - JPC(!TSTFLAG(S)); /* also updates tStates */ - break; - case 0xf3: /* DI */ - tStates += 4; - sim_brk_pend = FALSE; - IFF = 0; - break; - case 0xf4: /* CALL P,nnnn */ - CALLC(!TSTFLAG(S)); /* also updates tStates */ - break; - case 0xf5: /* PUSH AF */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(AF); - break; - case 0xf6: /* OR nn */ - tStates += 7; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) | RAM_pp(PC)) & 0xff]; - break; - case 0xf7: /* RST 30H */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = 0x30; - break; - case 0xf8: /* RET M */ - if (TSTFLAG(S)) { - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - tStates += 11; - } - else { - sim_brk_pend = FALSE; - tStates += 5; - } - break; - case 0xf9: /* LD SP,HL */ - tStates += 6; - sim_brk_pend = FALSE; - SP = HL; - break; - case 0xfa: /* JP M,nnnn */ - sim_brk_pend = FALSE; - JPC(TSTFLAG(S)); /* also updates tStates */ - break; - case 0xfb: /* EI */ - tStates += 4; - sim_brk_pend = FALSE; - IFF = 3; - break; - case 0xfc: /* CALL M,nnnn */ - CALLC(TSTFLAG(S)); /* also updates tStates */ - break; - case 0xfd: /* FD prefix */ - checkCPU8080; - switch (op = RAM_pp(PC)) { - case 0x09: /* ADD IY,BC */ - tStates += 15; - sim_brk_pend = FALSE; - IY &= ADDRMASK; - BC &= ADDRMASK; - sum = IY + BC; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IY ^ BC ^ sum) >> 8]; - IY = sum; - break; - case 0x19: /* ADD IY,DE */ - tStates += 15; - sim_brk_pend = FALSE; - IY &= ADDRMASK; - DE &= ADDRMASK; - sum = IY + DE; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IY ^ DE ^ sum) >> 8]; - IY = sum; - break; - case 0x21: /* LD IY,nnnn */ - tStates += 14; - sim_brk_pend = FALSE; - IY = GetWORD(PC); - PC += 2; - break; - case 0x22: /* LD (nnnn),IY */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - PutWORD(temp, IY); - PC += 2; - break; - case 0x23: /* INC IY */ - tStates += 10; - sim_brk_pend = FALSE; - ++IY; - break; - case 0x24: /* INC IYH */ - tStates += 9; - sim_brk_pend = FALSE; - IY += 0x100; - AF = (AF & ~0xfe) | incZ80Table[hreg(IY)]; - break; - case 0x25: /* DEC IYH */ - tStates += 9; - sim_brk_pend = FALSE; - IY -= 0x100; - AF = (AF & ~0xfe) | decZ80Table[hreg(IY)]; - break; - case 0x26: /* LD IYH,nn */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IY, RAM_pp(PC)); - break; - case 0x29: /* ADD IY,IY */ - tStates += 15; - sim_brk_pend = FALSE; - IY &= ADDRMASK; - sum = IY + IY; - AF = (AF & ~0x3b) | cbitsDup16Table[sum >> 8]; - IY = sum; - break; - case 0x2a: /* LD IY,(nnnn) */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - IY = GetWORD(temp); - PC += 2; - break; - case 0x2b: /* DEC IY */ - tStates += 10; - sim_brk_pend = FALSE; - --IY; - break; - case 0x2c: /* INC IYL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IY) + 1; - Setlreg(IY, temp); - AF = (AF & ~0xfe) | incZ80Table[temp]; - break; - case 0x2d: /* DEC IYL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IY) - 1; - Setlreg(IY, temp); - AF = (AF & ~0xfe) | decZ80Table[temp & 0xff]; - break; - case 0x2e: /* LD IYL,nn */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IY, RAM_pp(PC)); - break; - case 0x34: /* INC (IY+dd) */ - tStates += 23; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr) + 1; - PutBYTE(adr, temp); - AF = (AF & ~0xfe) | incZ80Table[temp]; - break; - case 0x35: /* DEC (IY+dd) */ - tStates += 23; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr) - 1; - PutBYTE(adr, temp); - AF = (AF & ~0xfe) | decZ80Table[temp & 0xff]; - break; - case 0x36: /* LD (IY+dd),nn */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, RAM_pp(PC)); - break; - case 0x39: /* ADD IY,SP */ - tStates += 15; - sim_brk_pend = FALSE; - IY &= ADDRMASK; - SP &= ADDRMASK; - sum = IY + SP; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IY ^ SP ^ sum) >> 8]; - IY = sum; - break; - case 0x44: /* LD B,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(BC, hreg(IY)); - break; - case 0x45: /* LD B,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(BC, lreg(IY)); - break; - case 0x46: /* LD B,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Sethreg(BC, GetBYTE(adr)); - break; - case 0x4c: /* LD C,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(BC, hreg(IY)); - break; - case 0x4d: /* LD C,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(BC, lreg(IY)); - break; - case 0x4e: /* LD C,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Setlreg(BC, GetBYTE(adr)); - break; - case 0x54: /* LD D,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(DE, hreg(IY)); - break; - case 0x55: /* LD D,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(DE, lreg(IY)); - break; - case 0x56: /* LD D,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Sethreg(DE, GetBYTE(adr)); - break; - case 0x5c: /* LD E,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(DE, hreg(IY)); - break; - case 0x5d: /* LD E,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(DE, lreg(IY)); - break; - case 0x5e: /* LD E,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Setlreg(DE, GetBYTE(adr)); - break; - case 0x60: /* LD IYH,B */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IY, hreg(BC)); - break; - case 0x61: /* LD IYH,C */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IY, lreg(BC)); - break; - case 0x62: /* LD IYH,D */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IY, hreg(DE)); - break; - case 0x63: /* LD IYH,E */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IY, lreg(DE)); - break; - case 0x64: /* LD IYH,IYH */ - tStates += 9; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x65: /* LD IYH,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IY, lreg(IY)); - break; - case 0x66: /* LD H,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Sethreg(HL, GetBYTE(adr)); - break; - case 0x67: /* LD IYH,A */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IY, hreg(AF)); - break; - case 0x68: /* LD IYL,B */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IY, hreg(BC)); - break; - case 0x69: /* LD IYL,C */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IY, lreg(BC)); - break; - case 0x6a: /* LD IYL,D */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IY, hreg(DE)); - break; - case 0x6b: /* LD IYL,E */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IY, lreg(DE)); - break; - case 0x6c: /* LD IYL,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IY, hreg(IY)); - break; - case 0x6d: /* LD IYL,IYL */ - tStates += 9; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x6e: /* LD L,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Setlreg(HL, GetBYTE(adr)); - break; - case 0x6f: /* LD IYL,A */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IY, hreg(AF)); - break; - case 0x70: /* LD (IY+dd),B */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(BC)); - break; - case 0x71: /* LD (IY+dd),C */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(BC)); - break; - case 0x72: /* LD (IY+dd),D */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(DE)); - break; - case 0x73: /* LD (IY+dd),E */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(DE)); - break; - case 0x74: /* LD (IY+dd),H */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(HL)); - break; - case 0x75: /* LD (IY+dd),L */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(HL)); - break; - case 0x77: /* LD (IY+dd),A */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(AF)); - break; - case 0x7c: /* LD A,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(AF, hreg(IY)); - break; - case 0x7d: /* LD A,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(AF, lreg(IY)); - break; - case 0x7e: /* LD A,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Sethreg(AF, GetBYTE(adr)); - break; - case 0x84: /* ADD A,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - temp = hreg(IY); - acu = hreg(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x85: /* ADD A,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IY); - acu = hreg(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x86: /* ADD A,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - acu = hreg(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x8c: /* ADC A,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - temp = hreg(IY); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x8d: /* ADC A,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IY); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x8e: /* ADC A,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x96: /* SUB (IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - acu = hreg(AF); - sum = acu - temp; - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0x94: /* SUB IYH */ - SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */ - case 0x9c: /* SBC A,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - temp = hreg(IY); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0x95: /* SUB IYL */ - SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */ - case 0x9d: /* SBC A,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IY); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0x9e: /* SBC A,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0xa4: /* AND IYH */ - tStates += 9; - sim_brk_pend = FALSE; - AF = andTable[((AF & IY) >> 8) & 0xff]; - break; - case 0xa5: /* AND IYL */ - tStates += 9; - sim_brk_pend = FALSE; - AF = andTable[((AF >> 8) & IY) & 0xff]; - break; - case 0xa6: /* AND (IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - AF = andTable[((AF >> 8) & GetBYTE(adr)) & 0xff]; - break; - case 0xac: /* XOR IYH */ - tStates += 9; - sim_brk_pend = FALSE; - AF = xororTable[((AF ^ IY) >> 8) & 0xff]; - break; - case 0xad: /* XOR IYL */ - tStates += 9; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) ^ IY) & 0xff]; - break; - case 0xae: /* XOR (IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - AF = xororTable[((AF >> 8) ^ GetBYTE(adr)) & 0xff]; - break; - case 0xb4: /* OR IYH */ - tStates += 9; - sim_brk_pend = FALSE; - AF = xororTable[((AF | IY) >> 8) & 0xff]; - break; - case 0xb5: /* OR IYL */ - tStates += 9; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) | IY) & 0xff]; - break; - case 0xb6: /* OR (IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - AF = xororTable[((AF >> 8) | GetBYTE(adr)) & 0xff]; - break; - case 0xbc: /* CP IYH */ - tStates += 9; - sim_brk_pend = FALSE; - temp = hreg(IY); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0xbd: /* CP IYL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IY); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0xbe: /* CP (IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0xcb: /* CB prefix */ - adr = IY + (signed char) RAM_pp(PC); - switch ((op = GetBYTE(PC)) & 7) { - case 0: - sim_brk_pend = FALSE; - ++PC; - acu = hreg(BC); - break; - case 1: - sim_brk_pend = FALSE; - ++PC; - acu = lreg(BC); - break; - case 2: - sim_brk_pend = FALSE; - ++PC; - acu = hreg(DE); - break; - case 3: - sim_brk_pend = FALSE; - ++PC; - acu = lreg(DE); - break; - case 4: - sim_brk_pend = FALSE; - ++PC; - acu = hreg(HL); - break; - case 5: - sim_brk_pend = FALSE; - ++PC; - acu = lreg(HL); - break; - case 6: - CheckBreakByte(adr); - ++PC; - acu = GetBYTE(adr); - break; - case 7: - sim_brk_pend = FALSE; - ++PC; - acu = hreg(AF); - break; - } - switch (op & 0xc0) { - case 0x00: /* shift/rotate */ - tStates += 23; - switch (op & 0x38) { - case 0x00: /* RLC */ - temp = (acu << 1) | (acu >> 7); - cbits = temp & 1; - goto cbshflg3; - case 0x08: /* RRC */ - temp = (acu >> 1) | (acu << 7); - cbits = temp & 0x80; - goto cbshflg3; - case 0x10: /* RL */ - temp = (acu << 1) | TSTFLAG(C); - cbits = acu & 0x80; - goto cbshflg3; - case 0x18: /* RR */ - temp = (acu >> 1) | (TSTFLAG(C) << 7); - cbits = acu & 1; - goto cbshflg3; - case 0x20: /* SLA */ - temp = acu << 1; - cbits = acu & 0x80; - goto cbshflg3; - case 0x28: /* SRA */ - temp = (acu >> 1) | (acu & 0x80); - cbits = acu & 1; - goto cbshflg3; - case 0x30: /* SLIA */ - temp = (acu << 1) | 1; - cbits = acu & 0x80; - goto cbshflg3; - case 0x38: /* SRL */ - temp = acu >> 1; - cbits = acu & 1; - cbshflg3: - AF = (AF & ~0xff) | rotateShiftTable[temp & 0xff] | !!cbits; - } - break; - case 0x40: /* BIT */ - tStates += 20; - if (acu & (1 << ((op >> 3) & 7))) { - AF = (AF & ~0xfe) | 0x10 | (((op & 0x38) == 0x38) << 7); - } - else { - AF = (AF & ~0xfe) | 0x54; - } - if ((op & 7) != 6) { - AF |= (acu & 0x28); - } - temp = acu; - break; - case 0x80: /* RES */ - tStates += 23; - temp = acu & ~(1 << ((op >> 3) & 7)); - break; - case 0xc0: /* SET */ - tStates += 23; - temp = acu | (1 << ((op >> 3) & 7)); - break; - } - switch (op & 7) { - case 0: - Sethreg(BC, temp); - break; - case 1: - Setlreg(BC, temp); - break; - case 2: - Sethreg(DE, temp); - break; - case 3: - Setlreg(DE, temp); - break; - case 4: - Sethreg(HL, temp); - break; - case 5: - Setlreg(HL, temp); - break; - case 6: - PutBYTE(adr, temp); - break; - case 7: - Sethreg(AF, temp); - break; - } - break; - case 0xe1: /* POP IY */ - tStates += 14; - CheckBreakWord(SP); - POP(IY); - break; - case 0xe3: /* EX (SP),IY */ - tStates += 23; - CheckBreakWord(SP); - temp = IY; - POP(IY); - PUSH(temp); - break; - case 0xe5: /* PUSH IY */ - tStates += 15; - CheckBreakWord(SP - 2); - PUSH(IY); - break; - case 0xe9: /* JP (IY) */ - tStates += 8; - sim_brk_pend = FALSE; - PCQ_ENTRY(PC - 2); - PC = IY; - break; - case 0xf9: /* LD SP,IY */ - tStates += 10; - sim_brk_pend = FALSE; - SP = IY; - break; - default: /* ignore FD */ - sim_brk_pend = FALSE; - checkCPUZ80; - PC--; - } - break; - case 0xfe: /* CP nn */ - tStates += 7; - sim_brk_pend = FALSE; - temp = RAM_pp(PC); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SetPV) | cbits2Table[cbits & 0x1ff]; - break; - case 0xff: /* RST 38H */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = 0x38; - } - } - end_decode: - pc = PC; - af[af_sel] = AF; - regs[regs_sel].bc = BC; - regs[regs_sel].de = DE; - regs[regs_sel].hl = HL; - ix = IX; - iy = IY; - sp = SP; - - /* simulation halted */ - saved_PC = ((reason == STOP_OPCODE) || (reason == STOP_MEM)) ? PCX : pc; - pcq_r -> qptr = pcq_p; /* update pc q ptr */ - AF_S = af[af_sel]; - BC_S = regs[regs_sel].bc; - DE_S = regs[regs_sel].de; - HL_S = regs[regs_sel].hl; - IX_S = ix; - IY_S = iy; - SP_S = sp; - AF1_S = af[1 - af_sel]; - BC1_S = regs[1 - regs_sel].bc; - DE1_S = regs[1 - regs_sel].de; - HL1_S = regs[1 - regs_sel].hl; - IFF_S = IFF; - IR_S = ir; - executedTStates = tStates; - return reason; -} - -int32 install_bootrom(void) { - int32 i, cnt = 0; - for (i = 0; i < bootrom_size; i++) { - if (M[i + defaultROMLow][0] != (bootrom[i] & 0xff)) { - cnt++; - M[i + defaultROMLow][0] = bootrom[i] & 0xff; - } - } - return cnt; -} - -static int32 lowProtect; -static int32 highProtect; -static int32 isProtected = FALSE; - -void protect(const int32 l, const int32 h) { - isProtected = TRUE; - lowProtect = l; - highProtect = h; -} - -static void resetCell(const int32 address, const int32 bank) { - if (!(isProtected && (bank == 0) && (lowProtect <= address) && (address <= highProtect))) { - M[address][bank] = 0; - } -} - -static void reset_memory(void) { - uint32 i, j; - checkROMBoundaries(); - if (cpu_unit.flags & UNIT_BANKED) { - for (i = 0; i < MAXMEMSIZE; i++) { - for (j = 0; j < MAXBANKS; j++) { - resetCell(i, j); - } - } - } - else if (cpu_unit.flags & UNIT_ROM) { - for (i = 0; i < ROMLow; i++) { - resetCell(i, 0); - } - for (i = ROMHigh + 1; i < MAXMEMSIZE; i++) { - resetCell(i, 0); - } - } - else { - for (i = 0; i < MAXMEMSIZE; i++) { - resetCell(i, 0); - } - } - if (cpu_unit.flags & (UNIT_ALTAIRROM | UNIT_BANKED)) { - install_bootrom(); - } - isProtected = FALSE; -} - -void printROMMessage(const uint32 cntROM) { - if (cntROM) { - printf("Warning: %d bytes written to ROM [%04X - %04X].\n", cntROM, ROMLow, ROMHigh); - } -} - -/* reset routine */ - -t_stat cpu_reset(DEVICE *dptr) { - int32 i; - AF_S = AF1_S = 0; - af_sel = 0; - BC_S = DE_S = HL_S = 0; - regs_sel = 0; - BC1_S = DE1_S = HL1_S = 0; - IR_S = IX_S = IY_S = SP_S = 0; - IFF_S = 3; - bankSelect = 0; - reset_memory(); - sim_brk_types = (SWMASK('E') | SWMASK('M')); - sim_brk_dflt = SWMASK('E'); - for (i = 0; i < PCQ_SIZE; i++) { - pcq[i] = 0; - } - pcq_p = 0; - pcq_r = find_reg("PCQ", NULL, dptr); - if (pcq_r) { - pcq_r -> qptr = 0; - } - else { - return SCPE_IERR; - } - return SCPE_OK; -} - -/* memory examine */ -t_stat cpu_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { - *vptr = M[addr & ADDRMASK][(addr >> 16) & BANKMASK]; - return SCPE_OK; -} - -/* memory deposit */ -t_stat cpu_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw) { - M[addr & ADDRMASK][(addr >> 16) & BANKMASK] = val & 0xff; - return SCPE_OK; -} - -static void checkROMBoundaries(void) { - uint32 temp; - if (ROMLow > ROMHigh) { - printf("ROMLOW [%04X] must be less than or equal to ROMHIGH [%04X]. Values exchanged.\n", - ROMLow, ROMHigh); - temp = ROMLow; - ROMLow = ROMHigh; - ROMHigh = temp; - } - if (cpu_unit.flags & UNIT_ALTAIRROM) { - if (defaultROMLow < ROMLow) { - printf("ROMLOW [%04X] reset to %04X since Altair ROM was desired.\n", ROMLow, defaultROMLow); - ROMLow = defaultROMLow; - } - if (ROMHigh < defaultROMHigh) { - printf("ROMHIGH [%04X] reset to %04X since Altair ROM was desired.\n", ROMHigh, defaultROMHigh); - ROMHigh = defaultROMHigh; - } - } -} - -static t_stat cpu_set_rom(UNIT *uptr, int32 value, char *cptr, void *desc) { - checkROMBoundaries(); - return SCPE_OK; -} - -static t_stat cpu_set_norom(UNIT *uptr, int32 value, char *cptr, void *desc) { - if (cpu_unit.flags & UNIT_ALTAIRROM) { - printf("\"SET CPU NOALTAIRROM\" also executed.\n"); - cpu_unit.flags &= ~UNIT_ALTAIRROM; - } - return SCPE_OK; -} - -static t_stat cpu_set_altairrom(UNIT *uptr, int32 value, char *cptr, void *desc) { - install_bootrom(); - if (ROMLow != defaultROMLow) { - printf("\"D ROMLOW %04X\" also executed.\n", defaultROMLow); - ROMLow = defaultROMLow; - } - if (ROMHigh != defaultROMHigh) { - printf("\"D ROMHIGH %04X\" also executed.\n", defaultROMHigh); - ROMHigh = defaultROMHigh; - } - if (!(cpu_unit.flags & UNIT_ROM)) { - printf("\"SET CPU ROM\" also executed.\n"); - cpu_unit.flags |= UNIT_ROM; - } - return SCPE_OK; -} - -static t_stat cpu_set_warnrom(UNIT *uptr, int32 value, char *cptr, void *desc) { - if ((!(cpu_unit.flags & UNIT_ROM)) && (MEMSIZE >= 64*KB)) { - printf("CPU has currently no ROM - no warning to be expected.\n"); - } - return SCPE_OK; -} - -static t_stat cpu_set_banked(UNIT *uptr, int32 value, char *cptr, void *desc) { - if (common > defaultROMLow) { - printf("Warning: COMMON [%04X] must not be greater than %04X. Reset to %04X.\n", - common, defaultROMLow, defaultROMLow); - common = defaultROMLow; - } - if (MEMSIZE != (MAXBANKS * MAXMEMSIZE)) { - previousCapacity = MEMSIZE; - } - MEMSIZE = MAXBANKS * MAXMEMSIZE; - cpu_dev.awidth = 16 + MAXBANKSLOG2; - return SCPE_OK; -} - -static t_stat cpu_set_nonbanked(UNIT *uptr, int32 value, char *cptr, void *desc) { - if (MEMSIZE == (MAXBANKS * MAXMEMSIZE)) { - MEMSIZE = previousCapacity ? previousCapacity : 64*KB; - } - cpu_dev.awidth = 16; - return SCPE_OK; -} - -static t_stat cpu_set_size(UNIT *uptr, int32 value, char *cptr, void *desc) { - if (cpu_unit.flags & UNIT_BANKED) { - printf("\"SET CPU NONBANKED\" also executed.\n"); - cpu_unit.flags &= ~UNIT_BANKED; - } - MEMSIZE = value; - cpu_dev.awidth = 16; - reset_memory(); - return SCPE_OK; -} diff --git a/AltairZ80/altairZ80_defs.h b/AltairZ80/altairZ80_defs.h deleted file mode 100644 index fe5cbc83..00000000 --- a/AltairZ80/altairZ80_defs.h +++ /dev/null @@ -1,90 +0,0 @@ -/* altairz80_defs.h: MITS Altair simulator definitions - - Copyright (c) 2002-2003, Peter Schorn - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - PETER SCHORN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 -*/ - -#include "sim_defs.h" /* simulator definitions */ - -#define MAXMEMSIZE 65536 /* maximum memory size */ -#define ADDRMASK (MAXMEMSIZE - 1) /* address mask */ -#define bootrom_size 256 /* size of boot rom */ -#define MAXBANKS 8 /* max number of memory banks */ -#define MAXBANKSLOG2 3 /* log2 of MAXBANKS */ -#define BANKMASK (MAXBANKS-1) /* bank mask */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define KB 1024 /* kilo byte */ -#define defaultROMLow 0xff00 /* default for lowest addres of ROM */ -#define defaultROMHigh 0xffff /* default for highest addres of ROM */ - -#define NUM_OF_DSK 8 /* NUM_OF_DSK must be power of two */ -#define LDAInstruction 0x3e /* op-code for LD A,<8-bit value> instruction */ -#define unitNoOffset1 0x37 /* LD A, */ -#define unitNoOffset2 0xb4 /* LD a,80h | */ - -#define UNIT_V_OPSTOP (UNIT_V_UF+0) /* stop on nvalid operation */ -#define UNIT_OPSTOP (1 << UNIT_V_OPSTOP) -#define UNIT_V_CHIP (UNIT_V_UF+1) /* 8080 or Z80 CPU */ -#define UNIT_CHIP (1 << UNIT_V_CHIP) -#define UNIT_V_MSIZE (UNIT_V_UF+2) /* memory size */ -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) -#define UNIT_V_BANKED (UNIT_V_UF+3) /* banked memory is used */ -#define UNIT_BANKED (1 << UNIT_V_BANKED) -#define UNIT_V_ROM (UNIT_V_UF+4) /* ROM exists */ -#define UNIT_ROM (1 << UNIT_V_ROM) -#define UNIT_V_ALTAIRROM (UNIT_V_UF+5) /* ALTAIR ROM exists */ -#define UNIT_ALTAIRROM (1 << UNIT_V_ALTAIRROM) -#define UNIT_V_WARNROM (UNIT_V_UF+6) /* warn if ROM is written to */ -#define UNIT_WARNROM (1 << UNIT_V_WARNROM) - -#define AddressFormat "[%04xh]" -#define PCformat "\n" AddressFormat " " -#define message1(p1) \ - sprintf(messageBuffer,PCformat p1,PCX); printMessage() -#define message2(p1,p2) \ - sprintf(messageBuffer,PCformat p1,PCX,p2); printMessage() -#define message3(p1,p2,p3) \ - sprintf(messageBuffer,PCformat p1,PCX,p2,p3); printMessage() -#define message4(p1,p2,p3,p4) \ - sprintf(messageBuffer,PCformat p1,PCX,p2,p3,p4); printMessage() -#define message5(p1,p2,p3,p4,p5) \ - sprintf(messageBuffer,PCformat p1,PCX,p2,p3,p4,p5); printMessage() -#define message6(p1,p2,p3,p4,p5,p6) \ - sprintf(messageBuffer,PCformat p1,PCX,p2,p3,p4,p5,p6); printMessage() - -/* The Default is to use "inline". In this case the wrapper functions for - GetBYTE and PutBYTE need to be created. Otherwise they are not needed - and the calls map to the original functions. */ -#ifdef NO_INLINE -#define INLINE -#define GetBYTEWrapper GetBYTE -#define PutBYTEWrapper PutBYTE -#else -#if defined(__DECC) && defined(VMS) -#define INLINE __inline -#else -#define INLINE inline -#endif -#endif diff --git a/AltairZ80/altairZ80_dsk.c b/AltairZ80/altairZ80_dsk.c deleted file mode 100644 index 8856e9cd..00000000 --- a/AltairZ80/altairZ80_dsk.c +++ /dev/null @@ -1,569 +0,0 @@ -/* altairz80_dsk.c: MITS Altair 88-DISK Simulator - - Copyright (c) 2002-2003, Peter Schorn - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - PETER SCHORN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 - - The 88_DISK is a 8-inch floppy controller which can control up - to 16 daisy-chained Pertec FD-400 hard-sectored floppy drives. - Each diskette has physically 77 tracks of 32 137-byte sectors - each. - - The controller is interfaced to the CPU by use of 3 I/O addreses, - standardly, these are device numbers 10, 11, and 12 (octal). - - Address Mode Function - ------- ---- -------- - - 10 Out Selects and enables Controller and Drive - 10 In Indicates status of Drive and Controller - 11 Out Controls Disk Function - 11 In Indicates current sector position of disk - 12 Out Write data - 12 In Read data - - Drive Select Out (Device 10 OUT): - - +---+---+---+---+---+---+---+---+ - | C | X | X | X | Device | - +---+---+---+---+---+---+---+---+ - - C = If this bit is 1, the disk controller selected by 'device' is - cleared. If the bit is zero, 'device' is selected as the - device being controlled by subsequent I/O operations. - X = not used - Device = value zero thru 15, selects drive to be controlled. - - Drive Status In (Device 10 IN): - - +---+---+---+---+---+---+---+---+ - | R | Z | I | X | X | H | M | W | - +---+---+---+---+---+---+---+---+ - - W - When 0, write circuit ready to write another byte. - M - When 0, head movement is allowed - H - When 0, indicates head is loaded for read/write - X - not used (will be 0) - I - When 0, indicates interrupts enabled (not used by this simulator) - Z - When 0, indicates head is on track 0 - R - When 0, indicates that read circuit has new byte to read - - Drive Control (Device 11 OUT): - - +---+---+---+---+---+---+---+---+ - | W | C | D | E | U | H | O | I | - +---+---+---+---+---+---+---+---+ - - I - When 1, steps head IN one track - O - When 1, steps head OUT one track - H - When 1, loads head to drive surface - U - When 1, unloads head - E - Enables interrupts (ignored by this simulator) - D - Disables interrupts (ignored by this simulator) - C - When 1 lowers head current (ignored by this simulator) - W - When 1, starts Write Enable sequence: W bit on device 10 - (see above) will go 1 and data will be read from port 12 - until 137 bytes have been read by the controller from - that port. The W bit will go off then, and the sector data - will be written to disk. Before you do this, you must have - stepped the track to the desired number, and waited until - the right sector number is presented on device 11 IN, then - set this bit. - - Sector Position (Device 11 IN): - - As the sectors pass by the read head, they are counted and the - number of the current one is available in this register. - - +---+---+---+---+---+---+---+---+ - | X | X | Sector Number | T | - +---+---+---+---+---+---+---+---+ - - X = Not used - Sector number = binary of the sector number currently under the - head, 0-31. - T = Sector True, is a 1 when the sector is positioned to read or - write. - -*/ - -#include "altairz80_defs.h" - -#define UNIT_V_DSKWLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_DSKWLK (1 << UNIT_V_DSKWLK) -#define UNIT_V_DSK_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_DSK_VERBOSE (1 << UNIT_V_DSK_VERBOSE) -#define DSK_SECTSIZE 137 /* size of sector */ -#define DSK_SECT 32 /* sectors per track */ -#define MAX_TRACKS 254 /* number of tracks, - original Altair has 77 tracks only */ -#define DSK_TRACSIZE (DSK_SECTSIZE * DSK_SECT) -#define MAX_DSK_SIZE (DSK_TRACSIZE * MAX_TRACKS) -#define TRACE_IN_OUT 1 -#define TRACE_READ_WRITE 2 -#define TRACE_SECTOR_STUCK 4 -#define TRACE_TRACK_STUCK 8 -#define NUM_OF_DSK_MASK (NUM_OF_DSK - 1) - -int32 dsk10(const int32 port, const int32 io, const int32 data); -int32 dsk11(const int32 port, const int32 io, const int32 data); -int32 dsk12(const int32 port, const int32 io, const int32 data); -static int32 dskseek(const UNIT *xptr); -static t_stat dsk_boot(int32 unitno, DEVICE *dptr); -static t_stat dsk_reset(DEVICE *dptr); -static t_stat dsk_svc(UNIT *uptr); -static void writebuf(void); -static t_stat dsk_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc); -static void resetDSKWarningFlags(void); -static int32 hasVerbose(void); -static char* selectInOut(const int32 io); - -extern int32 PCX; -extern int32 saved_PC; -extern FILE *sim_log; -extern void PutBYTEWrapper(register uint32 Addr, register uint32 Value); -extern void printMessage(void); -extern char messageBuffer[]; -extern int32 install_bootrom(void); -extern UNIT cpu_unit; - -/* global data on status */ - -static int32 current_disk = NUM_OF_DSK; /* currently selected drive (values are 0 .. NUM_OF_DSK) - current_disk < NUM_OF_DSK implies that the corresponding disk is attached to a file */ -static int32 current_track [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0}; -static int32 current_sector [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0}; -static int32 current_byte [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0}; -static int32 current_flag [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0}; -static uint8 tracks [NUM_OF_DSK] = { MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, - MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS }; -static int32 trace_flag = 0; -static int32 in9_count = 0; -static int32 in9_message = FALSE; -static int32 dirty = FALSE; /* TRUE when buffer has unwritten data in it */ -static int32 warnLevelDSK = 3; -static int32 warnLock [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0}; -static int32 warnAttached [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0}; -static int32 warnDSK10 = 0; -static int32 warnDSK11 = 0; -static int32 warnDSK12 = 0; -static int8 dskbuf[DSK_SECTSIZE]; /* data Buffer */ - -/* Altair MITS modified BOOT EPROM, fits in upper 256 byte of memory */ -int32 bootrom[bootrom_size] = { - 0xf3, 0x06, 0x80, 0x3e, 0x0e, 0xd3, 0xfe, 0x05, /* ff00-ff07 */ - 0xc2, 0x05, 0xff, 0x3e, 0x16, 0xd3, 0xfe, 0x3e, /* ff08-ff0f */ - 0x12, 0xd3, 0xfe, 0xdb, 0xfe, 0xb7, 0xca, 0x20, /* ff10-ff17 */ - 0xff, 0x3e, 0x0c, 0xd3, 0xfe, 0xaf, 0xd3, 0xfe, /* ff18-ff1f */ - 0x21, 0x00, 0x5c, 0x11, 0x33, 0xff, 0x0e, 0x88, /* ff20-ff27 */ - 0x1a, 0x77, 0x13, 0x23, 0x0d, 0xc2, 0x28, 0xff, /* ff28-ff2f */ - 0xc3, 0x00, 0x5c, 0x31, 0x21, 0x5d, 0x3e, 0x00, /* ff30-ff37 */ - 0xd3, 0x08, 0x3e, 0x04, 0xd3, 0x09, 0xc3, 0x19, /* ff38-ff3f */ - 0x5c, 0xdb, 0x08, 0xe6, 0x02, 0xc2, 0x0e, 0x5c, /* ff40-ff47 */ - 0x3e, 0x02, 0xd3, 0x09, 0xdb, 0x08, 0xe6, 0x40, /* ff48-ff4f */ - 0xc2, 0x0e, 0x5c, 0x11, 0x00, 0x00, 0x06, 0x08, /* ff50-ff57 */ - 0xc5, 0xd5, 0x11, 0x86, 0x80, 0x21, 0x88, 0x5c, /* ff58-ff5f */ - 0xdb, 0x09, 0x1f, 0xda, 0x2d, 0x5c, 0xe6, 0x1f, /* ff60-ff67 */ - 0xb8, 0xc2, 0x2d, 0x5c, 0xdb, 0x08, 0xb7, 0xfa, /* ff68-ff6f */ - 0x39, 0x5c, 0xdb, 0x0a, 0x77, 0x23, 0x1d, 0xc2, /* ff70-ff77 */ - 0x39, 0x5c, 0xd1, 0x21, 0x8b, 0x5c, 0x06, 0x80, /* ff78-ff7f */ - 0x7e, 0x12, 0x23, 0x13, 0x05, 0xc2, 0x4d, 0x5c, /* ff80-ff87 */ - 0xc1, 0x21, 0x00, 0x5c, 0x7a, 0xbc, 0xc2, 0x60, /* ff88-ff8f */ - 0x5c, 0x7b, 0xbd, 0xd2, 0x80, 0x5c, 0x04, 0x04, /* ff90-ff97 */ - 0x78, 0xfe, 0x20, 0xda, 0x25, 0x5c, 0x06, 0x01, /* ff98-ff9f */ - 0xca, 0x25, 0x5c, 0xdb, 0x08, 0xe6, 0x02, 0xc2, /* ffa0-ffa7 */ - 0x70, 0x5c, 0x3e, 0x01, 0xd3, 0x09, 0x06, 0x00, /* ffa8-ffaf */ - 0xc3, 0x25, 0x5c, 0x3e, 0x80, 0xd3, 0x08, 0xfb, /* ffb0-ffb7 */ - 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffb8-ffbf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffc0-ffc7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffc8-ffcf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffd0-ffd7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffd8-ffdf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffe0-ffe7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffe8-ffef */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* fff0-fff7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* fff8-ffff */ -}; - -/* 88DSK Standard I/O Data Structures */ - -static UNIT dsk_unit[] = { - { UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) } }; - -static REG dsk_reg[] = { - { DRDATA (DISK, current_disk, 4) }, - { BRDATA (CURTRACK, current_track, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { BRDATA (CURSECTOR, current_sector, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { BRDATA (CURBYTE, current_byte, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { BRDATA (CURFLAG, current_flag, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { BRDATA (TRACKS, tracks, 10, 8, NUM_OF_DSK), REG_CIRC }, - { ORDATA (TRACE, trace_flag, 8) }, - { DRDATA (IN9COUNT, in9_count, 4), REG_RO }, - { DRDATA (IN9MESSAGE, in9_message, 4), REG_RO }, - { DRDATA (DIRTY, dirty, 4), REG_RO }, - { DRDATA (DSKWL, warnLevelDSK, 32) }, - { BRDATA (WARNLOCK, warnLock, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { BRDATA (WARNATTACHED, warnAttached, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { DRDATA (WARNDSK10, warnDSK10, 4), REG_RO }, - { DRDATA (WARNDSK11, warnDSK11, 4), REG_RO }, - { DRDATA (WARNDSK12, warnDSK12, 4), REG_RO }, - { BRDATA (DISKBUFFER, dskbuf, 10, 8, DSK_SECTSIZE), REG_CIRC + REG_RO }, - { NULL } }; - -static MTAB dsk_mod[] = { - { UNIT_DSKWLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_DSKWLK, UNIT_DSKWLK, "write locked", "LOCKED", NULL }, - /* quiet, no warning messages */ - { UNIT_DSK_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_DSK_VERBOSE, UNIT_DSK_VERBOSE, "VERBOSE", "VERBOSE", &dsk_set_verbose }, - { 0 } }; - -DEVICE dsk_dev = { - "DSK", dsk_unit, dsk_reg, dsk_mod, - 8, 10, 31, 1, 8, 8, - NULL, NULL, &dsk_reset, - &dsk_boot, NULL, NULL, NULL, 0, NULL, NULL }; - -static void resetDSKWarningFlags(void) { - int32 i; - for (i = 0; i < NUM_OF_DSK; i++) { - warnLock[i] = 0; - warnAttached[i] = 0; - } - warnDSK10 = 0; - warnDSK11 = 0; - warnDSK12 = 0; -} - -static t_stat dsk_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc) { - resetDSKWarningFlags(); - return SCPE_OK; -} - -/* returns TRUE iff there exists a disk with VERBOSE */ -static int32 hasVerbose(void) { - int32 i; - for (i = 0; i < NUM_OF_DSK; i++) { - if (((dsk_dev.units + i) -> flags) & UNIT_DSK_VERBOSE) { - return TRUE; - } - } - return FALSE; -} - -static char* selectInOut(const int32 io) { - return io == 0 ? "IN" : "OUT"; -} - -/* service routines to handle simulator functions */ - -/* service routine - actually gets char & places in buffer */ - -static t_stat dsk_svc(UNIT *uptr) { - return SCPE_OK; -} - -/* reset routine */ - -static t_stat dsk_reset(DEVICE *dptr) { - resetDSKWarningFlags(); - current_disk = NUM_OF_DSK; - trace_flag = 0; - in9_count = 0; - in9_message = FALSE; - return SCPE_OK; -} - -/* The boot routine modifies the boot ROM in such a way that subsequently - the specified disk is used for boot purposes. -*/ -static t_stat dsk_boot(int32 unitno, DEVICE *dptr) { - if (cpu_unit.flags & (UNIT_ALTAIRROM | UNIT_BANKED)) { - if (install_bootrom()) { - printf("ALTAIR boot ROM installed.\n"); - } - /* check whether we are really modifying an LD A,<> instruction */ - if ((bootrom[unitNoOffset1 - 1] == LDAInstruction) && (bootrom[unitNoOffset2 - 1] == LDAInstruction)) { - bootrom[unitNoOffset1] = unitno & 0xff; /* LD A, */ - bootrom[unitNoOffset2] = 0x80 | (unitno & 0xff); /* LD a,80h | */ - } - else { /* Attempt to modify non LD A,<> instructions is refused. */ - printf("Incorrect boot ROM offsets detected.\n"); - return SCPE_IERR; - } - } - saved_PC = defaultROMLow; - return SCPE_OK; -} - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. - - Each function is passed an 'io' flag, where 0 means a read from - the port, and 1 means a write to the port. On input, the actual - input is passed as the return value, on output, 'data' is written - to the device. -*/ - -/* Disk Controller Status/Select */ - -/* IMPORTANT: The status flags read by port 8 IN instruction are - INVERTED, that is, 0 is true and 1 is false. To handle this, the - simulator keeps it's own status flags as 0=false, 1=true; and - returns the COMPLEMENT of the status flags when read. This makes - setting/testing of the flag bits more logical, yet meets the - simulation requirement that they are reversed in hardware. -*/ - -int32 dsk10(const int32 port, const int32 io, const int32 data) { - int32 current_disk_flags; - in9_count = 0; - if (io == 0) { /* IN: return flags */ - if (current_disk >= NUM_OF_DSK) { - if (hasVerbose() && (warnDSK10 < warnLevelDSK)) { - warnDSK10++; -/*01*/ message1("Attempt of IN 0x08 on unattached disk - ignored.\n"); - } - return 0xff; /* no drive selected - can do nothing */ - } - return (~current_flag[current_disk]) & 0xff; /* return the COMPLEMENT! */ - } - - /* OUT: Controller set/reset/enable/disable */ - if (dirty) { /* implies that current_disk < NUM_OF_DSK */ - writebuf(); - } - if (trace_flag & TRACE_IN_OUT) { - message2("OUT 0x08: %x\n", data); - } - current_disk = data & NUM_OF_DSK_MASK; /* 0 <= current_disk < NUM_OF_DSK */ - current_disk_flags = (dsk_dev.units + current_disk) -> flags; - if ((current_disk_flags & UNIT_ATT) == 0) { /* nothing attached? */ - if ( (current_disk_flags & UNIT_DSK_VERBOSE) && (warnAttached[current_disk] < warnLevelDSK) ) { - warnAttached[current_disk]++; -/*02*/message2("Attempt to select unattached DSK%d - ignored.\n", current_disk); - } - current_disk = NUM_OF_DSK; - } - else { - current_sector[current_disk] = 0xff; /* reset internal counters */ - current_byte[current_disk] = 0xff; - current_flag[current_disk] = data & 0x80 ? 0 /* disable drive */ : - (current_track[current_disk] == 0 ? 0x5a /* enable: head move true, track 0 if there */ : - 0x1a);/* enable: head move true */ - } - return 0; /* ignored since OUT */ -} - -/* Disk Drive Status/Functions */ - -int32 dsk11(const int32 port, const int32 io, const int32 data) { - if (current_disk >= NUM_OF_DSK) { - if (hasVerbose() && (warnDSK11 < warnLevelDSK)) { - warnDSK11++; -/*03*/message2("Attempt of %s 0x09 on unattached disk - ignored.\n", selectInOut(io)); - } - return 0; /* no drive selected - can do nothing */ - } - - /* now current_disk < NUM_OF_DSK */ - if (io == 0) { /* read sector position */ - in9_count++; - if ((trace_flag & TRACE_SECTOR_STUCK) && (in9_count > 2 * DSK_SECT) && (!in9_message)) { - in9_message = TRUE; - message2("Looping on sector find %d.\n", current_disk); - } - if (trace_flag & TRACE_IN_OUT) { - message1("IN 0x09\n"); - } - if (dirty) {/* implies that current_disk < NUM_OF_DSK */ - writebuf(); - } - if (current_flag[current_disk] & 0x04) { /* head loaded? */ - current_sector[current_disk]++; - if (current_sector[current_disk] >= DSK_SECT) { - current_sector[current_disk] = 0; - } - current_byte[current_disk] = 0xff; - return (((current_sector[current_disk] << 1) & 0x3e) /* return 'sector true' bit = 0 (true) */ - | 0xc0); /* set on 'unused' bits */ - } else { - return 0; /* head not loaded - return 0 */ - } - } - - in9_count = 0; - /* drive functions */ - - if (trace_flag & TRACE_IN_OUT) { - message2("OUT 0x09: %x\n", data); - } - if (data & 0x01) { /* step head in */ - if (trace_flag & TRACE_TRACK_STUCK) { - if (current_track[current_disk] == (tracks[current_disk] - 1)) { - message2("Unnecessary step in for disk %d\n", current_disk); - } - } - current_track[current_disk]++; - if (current_track[current_disk] > (tracks[current_disk] - 1)) { - current_track[current_disk] = (tracks[current_disk] - 1); - } - if (dirty) { /* implies that current_disk < NUM_OF_DSK */ - writebuf(); - } - current_sector[current_disk] = 0xff; - current_byte[current_disk] = 0xff; - } - - if (data & 0x02) { /* step head out */ - if (trace_flag & TRACE_TRACK_STUCK) { - if (current_track[current_disk] == 0) { - message2("Unnecessary step out for disk %d\n", current_disk); - } - } - current_track[current_disk]--; - if (current_track[current_disk] < 0) { - current_track[current_disk] = 0; - current_flag[current_disk] |= 0x40; /* track 0 if there */ - } - if (dirty) { /* implies that current_disk < NUM_OF_DSK */ - writebuf(); - } - current_sector[current_disk] = 0xff; - current_byte[current_disk] = 0xff; - } - - if (dirty) { /* implies that current_disk < NUM_OF_DSK */ - writebuf(); - } - - if (data & 0x04) { /* head load */ - current_flag[current_disk] |= 0x04; /* turn on head loaded bit */ - current_flag[current_disk] |= 0x80; /* turn on 'read data available' */ - } - - if (data & 0x08) { /* head unload */ - current_flag[current_disk] &= 0xfb; /* turn off 'head loaded' bit */ - current_flag[current_disk] &= 0x7f; /* turn off 'read data available' */ - current_sector[current_disk] = 0xff; - current_byte[current_disk] = 0xff; - } - - /* interrupts & head current are ignored */ - - if (data & 0x80) { /* write sequence start */ - current_byte[current_disk] = 0; - current_flag[current_disk] |= 0x01; /* enter new write data on */ - } - return 0; /* ignored since OUT */ -} - -/* Disk Data In/Out */ - -static INLINE int32 dskseek(const UNIT *xptr) { - return fseek(xptr -> fileref, DSK_TRACSIZE * current_track[current_disk] + - DSK_SECTSIZE * current_sector[current_disk], SEEK_SET); -} - -int32 dsk12(const int32 port, const int32 io, const int32 data) { - int32 i; - UNIT *uptr; - - if (current_disk >= NUM_OF_DSK) { - if (hasVerbose() && (warnDSK12 < warnLevelDSK)) { - warnDSK12++; -/*04*/message2("Attempt of %s 0x0a on unattached disk - ignored.\n", selectInOut(io)); - } - return 0; - } - - /* now current_disk < NUM_OF_DSK */ - in9_count = 0; - uptr = dsk_dev.units + current_disk; - if (io == 0) { - if (current_byte[current_disk] >= DSK_SECTSIZE) { - /* physically read the sector */ - if (trace_flag & TRACE_READ_WRITE) { - message4("IN 0x0a (READ) D%d T%d S%d\n", current_disk, current_track[current_disk], current_sector[current_disk]); - } - for (i = 0; i < DSK_SECTSIZE; i++) { - dskbuf[i] = 0; - } - dskseek(uptr); - fread(dskbuf, DSK_SECTSIZE, 1, uptr -> fileref); - current_byte[current_disk] = 0; - } - return dskbuf[current_byte[current_disk]++] & 0xff; - } - else { - if (current_byte[current_disk] >= DSK_SECTSIZE) { - writebuf(); /* from above we have that current_disk < NUM_OF_DSK */ - } - else { - dirty = TRUE; /* this guarantees for the next call to writebuf that current_disk < NUM_OF_DSK */ - dskbuf[current_byte[current_disk]++] = data & 0xff; - } - return 0; /* ignored since OUT */ - } -} - -/* precondition: current_disk < NUM_OF_DSK */ -static void writebuf(void) { - int32 i, rtn; - UNIT *uptr; - i = current_byte[current_disk]; /* null-fill rest of sector if any */ - while (i < DSK_SECTSIZE) { - dskbuf[i++] = 0; - } - uptr = dsk_dev.units + current_disk; - if (((uptr -> flags) & UNIT_DSKWLK) == 0) { /* write enabled */ - if (trace_flag & TRACE_READ_WRITE) { - message4("OUT 0x0a (WRITE) D%d T%d S%d\n", current_disk, current_track[current_disk], current_sector[current_disk]); - } - if (dskseek(uptr)) { - message4("fseek failed D%d T%d S%d\n", current_disk, current_track[current_disk], current_sector[current_disk]); - } - rtn = fwrite(dskbuf, DSK_SECTSIZE, 1, uptr -> fileref); - if (rtn != 1) { - message4("fwrite failed T%d S%d Return=%d\n", current_track[current_disk], current_sector[current_disk], rtn); - } - } - else if ( ((uptr -> flags) & UNIT_DSK_VERBOSE) && (warnLock[current_disk] < warnLevelDSK) ) { - /* write locked - print warning message if required */ - warnLock[current_disk]++; -/*05*/ - message2("Attempt to write to locked DSK%d - ignored.\n", current_disk); - } - current_flag[current_disk] &= 0xfe; /* ENWD off */ - current_byte[current_disk] = 0xff; - dirty = FALSE; -} diff --git a/AltairZ80/altairZ80_sio.c b/AltairZ80/altairZ80_sio.c deleted file mode 100644 index e640e5df..00000000 --- a/AltairZ80/altairZ80_sio.c +++ /dev/null @@ -1,1105 +0,0 @@ -/* altairz80_sio: MITS Altair serial I/O card - - Copyright (c) 2002-2003, Peter Schorn - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - PETER SCHORN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 - - These functions support a simulated MITS 2SIO interface card. - The card had two physical I/O ports which could be connected - to any serial I/O device that would connect to a current loop, - RS232, or TTY interface. Available baud rates were jumper - selectable for each port from 110 to 9600. - - All I/O is via programmed I/O. Each device has a status port - and a data port. A write to the status port can select - some options for the device (0x03 will reset the port). - A read of the status port gets the port status: - - +---+---+---+---+---+---+---+---+ - | X | X | X | X | X | X | O | I | - +---+---+---+---+---+---+---+---+ - - I - A 1 in this bit position means a character has been received - on the data port and is ready to be read. - O - A 1 in this bit means the port is ready to receive a character - on the data port and transmit it out over the serial line. - - A read to the data port gets the buffered character, a write - to the data port writes the character to the device. -*/ - -#include - -#include "altairz80_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" -#include - -#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode, strip bit 8 on output */ -#define UNIT_ANSI (1 << UNIT_V_ANSI) -#define UNIT_V_UPPER (UNIT_V_UF + 1) /* uppper case mode */ -#define UNIT_UPPER (1 << UNIT_V_UPPER) -#define UNIT_V_BS (UNIT_V_UF + 2) /* map delete to backspace */ -#define UNIT_BS (1 << UNIT_V_BS) -#define UNIT_V_SIO_VERBOSE (UNIT_V_UF + 3) /* verbose mode, i.e. show error messages */ -#define UNIT_SIO_VERBOSE (1 << UNIT_V_SIO_VERBOSE) - -#define UNIT_V_SIMH_VERBOSE (UNIT_V_UF + 0) /* verbose mode for SIMH pseudo device */ -#define UNIT_SIMH_VERBOSE (1 << UNIT_V_SIMH_VERBOSE) -#define UNIT_V_SIMH_TIMERON (UNIT_V_UF + 1) /* SIMH pseudo device timer generate interrupts */ -#define UNIT_SIMH_TIMERON (1 << UNIT_V_SIMH_VERBOSE) - -#define Terminals 4 /* lines per mux */ - -#define BACKSPACE_CHAR 0x08 /* backspace character */ -#define DELETE_CHAR 0x7f /* delete character */ -#define CONTROLZ_CHAR 0x1a /* control Z character */ - -static void resetSIOWarningFlags(void); -static t_stat sio_set_verbose (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat simh_dev_set_timeron (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat simh_dev_set_timeroff (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat sio_svc(UNIT *uptr); -static t_stat sio_reset(DEVICE *dptr); -static t_stat sio_attach(UNIT *uptr, char *cptr); -static t_stat sio_detach(UNIT *uptr); -static t_stat ptr_reset(DEVICE *dptr); -static t_stat ptp_reset(DEVICE *dptr); -int32 nulldev (const int32 port, const int32 io, const int32 data); -int32 sr_dev (const int32 port, const int32 io, const int32 data); -int32 simh_dev(const int32 port, const int32 io, const int32 data); -int32 sio0d (const int32 port, const int32 io, const int32 data); -int32 sio0s (const int32 port, const int32 io, const int32 data); -int32 sio1d (const int32 port, const int32 io, const int32 data); -int32 sio1s (const int32 port, const int32 io, const int32 data); -static void reset_sio_terminals(const int32 useDefault); -static t_stat simh_dev_reset(DEVICE *dptr); -static t_stat simh_svc(UNIT *uptr); -static int32 simh_in(const int32 port); -static int32 simh_out(const int32 port, const int32 data); -static void attachCPM(UNIT *uptr); -static void setClockZSDOS(void); -static void setClockCPM3(void); -static time_t mkCPM3Origin(void); -static int32 toBCD(const int32 x); -static int32 fromBCD(const int32 x); -void printMessage(void); -static void warnNoRealTimeClock(void); - -extern t_stat sim_activate(UNIT *uptr, int32 interval); -extern t_stat sim_cancel(UNIT *uptr); -extern t_stat sim_poll_kbd(void); -extern t_stat sim_putchar(int32 out); -extern t_stat attach_unit(UNIT *uptr, char *cptr); -extern t_bool rtc_avail; -extern FILE *sim_log; -extern int32 PCX; -extern int32 sim_switches; -extern uint32 sim_os_msec(void); -extern const char *scp_error_messages[]; -extern int32 SR; -extern int32 bankSelect; -extern int32 common; -extern uint8 GetBYTEWrapper(register uint32 Addr); -extern UNIT cpu_unit; - -/* SIMH pseudo device status registers */ -/* ZSDOS clock definitions */ -static time_t ClockZSDOSDelta = 0; /* delta between real clock and Altair clock */ -static int32 setClockZSDOSPos = 0; /* determines state for receiving address of parameter block */ -static int32 setClockZSDOSAdr = 0; /* address in M of 6 byte parameter block for setting time */ -static int32 getClockZSDOSPos = 0; /* determines state for sending clock information */ - -/* CPM3 clock definitions */ -static time_t ClockCPM3Delta = 0; /* delta between real clock and Altair clock */ -static int32 setClockCPM3Pos = 0; /* determines state for receiving address of parameter block */ -static int32 setClockCPM3Adr = 0; /* address in M of 5 byte parameter block for setting time */ -static int32 getClockCPM3Pos = 0; /* determines state for sending clock information */ -static int32 daysCPM3SinceOrg = 0; /* days since 1 Jan 1978 */ - -/* interrupt related */ -static uint32 timeOfNextInterrupt; /* time when next interrupt is scheduled */ - int32 timerInterrupt = FALSE; /* timer interrupt pending */ - int32 timerInterruptHandler = 0x0fc00;/* default address of interrupt handling routine */ -static int32 setTimerInterruptAdrPos= 0; /* determines state for receiving timerInterruptHandler */ -static int32 timerDelta = 100; /* interrupt every 100 ms */ -static int32 setTimerDeltaPos = 0; /* determines state for receiving timerDelta */ - -/* stop watch and timer related */ -static uint32 stopWatchDelta = 0; /* stores elapsed time of stop watch */ -static int32 getStopWatchDeltaPos = 0; /* determines the state for receiving stopWatchDelta */ -static uint32 stopWatchNow = 0; /* stores starting time of stop watch */ -static int32 markTimeSP = 0; /* stack pointer for timer stack */ - -/* miscellaneous */ -static int32 versionPos = 0; /* determines state for sending device identifier */ -static int32 lastCPMStatus = 0; /* result of last attachCPM command */ -static int32 lastCommand = 0; /* most recent command processed on port 0xfeh */ -static int32 getCommonPos = 0; /* determines state for sending the 'common' register */ - -/* SIO status registers */ -static int32 warnLevelSIO = 3; /* display at most 'warnLevelSIO' times the same warning */ -static int32 warnUnattachedPTP = 0; /* display a warning message if < warnLevel and SIO set to - VERBOSE and output to PTP without an attached file */ -static int32 warnUnattachedPTR = 0; /* display a warning message if < warnLevel and SIO set to - VERBOSE and attempt to read from PTR without an attached file */ -static int32 warnPTREOF = 0; /* display a warning message if < warnLevel and SIO set to - VERBOSE and attempt to read from PTR past EOF */ -static int32 warnUnassignedPort = 0; /* display a warning message if < warnLevel and SIO set to - VERBOSE andattempt to perform IN or OUT on an unassigned PORT */ -struct sio_terminal { - int32 data; /* data for this terminal */ - int32 status; /* status information for this terminal */ - int32 statusPort; /* status port of this terminal */ - int32 dataPort; /* data port of this terminal */ - int32 defaultStatus; /* default status value for this terminal */ -}; - -typedef struct sio_terminal SIO_TERMINAL; - -static SIO_TERMINAL sio_terminals[Terminals] = - { {0, 0, 0x10, 0x11, 0x02}, - {0, 0, 0x14, 0x15, 0x00}, - {0, 0, 0x16, 0x17, 0x00}, - {0, 0, 0x18, 0x19, 0x00} }; -static TMLN TerminalLines[Terminals] = { {0} }; /* four terminals */ -static TMXR altairTMXR = {Terminals, 0, 0 }; /* mux descriptor */ - -static UNIT sio_unit = { UDATA (&sio_svc, UNIT_ATTABLE, 0), KBD_POLL_WAIT }; - -static REG sio_reg[] = { - { HRDATA (DATA0, sio_terminals[0].data, 8) }, - { HRDATA (STAT0, sio_terminals[0].status, 8) }, - { HRDATA (DATA1, sio_terminals[1].data, 8) }, - { HRDATA (STAT1, sio_terminals[1].status, 8) }, - { HRDATA (DATA2, sio_terminals[2].data, 8) }, - { HRDATA (STAT2, sio_terminals[2].status, 8) }, - { HRDATA (DATA3, sio_terminals[3].data, 8) }, - { HRDATA (STAT3, sio_terminals[3].status, 8) }, - { DRDATA (SIOWL, warnLevelSIO, 32) }, - { DRDATA (WUPTP, warnUnattachedPTP, 32) }, - { DRDATA (WUPTR, warnUnattachedPTR, 32) }, - { DRDATA (WPTREOF, warnPTREOF, 32) }, - { DRDATA (WUPORT, warnUnassignedPort, 32) }, - { NULL } }; - -static MTAB sio_mod[] = { - { UNIT_ANSI, 0, "TTY", "TTY", NULL }, /* keep bit 8 as is for output */ - { UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL }, /* set bit 8 to 0 before output */ - { UNIT_UPPER, 0, "ALL", "ALL", NULL }, /* do not change case of input characters */ - { UNIT_UPPER, UNIT_UPPER, "UPPER", "UPPER", NULL }, /* change input characters to upper case */ - { UNIT_BS, 0, "BS", "BS", NULL }, /* map delete to backspace */ - { UNIT_BS, UNIT_BS, "DEL", "DEL", NULL }, /* map backspace to delete */ - { UNIT_SIO_VERBOSE, 0, "QUIET", "QUIET", NULL }, /* quiet, no error messages */ - { UNIT_SIO_VERBOSE, UNIT_SIO_VERBOSE, "VERBOSE", "VERBOSE", &sio_set_verbose }, - /* verbose, display warning messages */ - { 0 } }; - -DEVICE sio_dev = { - "SIO", &sio_unit, sio_reg, sio_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &sio_reset, - NULL, &sio_attach, &sio_detach, NULL, 0, NULL, NULL }; - -static UNIT ptr_unit = { UDATA (NULL, UNIT_SEQ + UNIT_ATTABLE + UNIT_ROABLE, 0), - KBD_POLL_WAIT }; - -static REG ptr_reg[] = { - { HRDATA (DATA, ptr_unit.buf, 8) }, - { HRDATA (STAT, ptr_unit.u3, 8) }, - { DRDATA (POS, ptr_unit.pos, 32) }, - { NULL } }; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - NULL, NULL, NULL, NULL, 0, NULL, NULL }; - -static UNIT ptp_unit = { UDATA (NULL, UNIT_SEQ + UNIT_ATTABLE, 0), - KBD_POLL_WAIT }; - -static REG ptp_reg[] = { - { HRDATA (DATA, ptp_unit.buf, 8) }, - { HRDATA (STAT, ptp_unit.u3, 8) }, - { DRDATA (POS, ptp_unit.pos, 32) }, - { NULL } }; - -DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptp_reset, - NULL, NULL, NULL, NULL, 0, NULL, NULL }; - -/* Synthetic device SIMH for communication - between Altair and SIMH environment using port 0xfe */ -static UNIT simh_unit = { UDATA (&simh_svc, 0, 0), KBD_POLL_WAIT }; - -static REG simh_reg[] = { - { DRDATA (CZD, ClockZSDOSDelta, 32) }, - { DRDATA (SCZP, setClockZSDOSPos, 8), REG_RO }, - { HRDATA (SCZA, setClockZSDOSAdr, 16), REG_RO }, - { DRDATA (GCZP, getClockZSDOSPos, 8), REG_RO }, - - { DRDATA (CC3D, ClockCPM3Delta, 32) }, - { DRDATA (SC3DP, setClockCPM3Pos, 8), REG_RO }, - { HRDATA (SC3DA, setClockCPM3Adr, 16), REG_RO }, - { DRDATA (GC3DP, getClockCPM3Pos, 8), REG_RO }, - { DRDATA (D3DO, daysCPM3SinceOrg, 32), REG_RO }, - - { DRDATA (TOFNI, timeOfNextInterrupt, 32), REG_RO }, - { DRDATA (TIMI, timerInterrupt, 3) }, - { HRDATA (TIMH, timerInterruptHandler, 16) }, - { DRDATA (STIAP, setTimerInterruptAdrPos,8), REG_RO }, - { DRDATA (TIMD, timerDelta, 32) }, - { DRDATA (STDP, setTimerDeltaPos, 8), REG_RO }, - - { DRDATA (STPDT, stopWatchDelta, 32), REG_RO }, - { DRDATA (STPOS, getStopWatchDeltaPos, 8), REG_RO }, - { DRDATA (STPNW, stopWatchNow, 32), REG_RO }, - { DRDATA (MTSP, markTimeSP, 8), REG_RO }, - - { DRDATA (VPOS, versionPos, 8), REG_RO }, - { DRDATA (LCPMS, lastCPMStatus, 8), REG_RO }, - { DRDATA (LCMD, lastCommand, 8), REG_RO }, - { DRDATA (CPOS, getCommonPos, 8), REG_RO }, - { NULL } }; - -static MTAB simh_mod[] = { - /* quiet, no warning messages */ - { UNIT_SIMH_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, display warning messages */ - { UNIT_SIMH_VERBOSE, UNIT_SIMH_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - /* timer generated interrupts are off */ - { UNIT_SIMH_TIMERON, 0, "TIMEROFF", "TIMEROFF", &simh_dev_set_timeroff }, - /* timer generated interrupts are on */ - { UNIT_SIMH_TIMERON, UNIT_SIMH_TIMERON, "TIMERON", "TIMERON", &simh_dev_set_timeron }, - { 0 } }; - -DEVICE simh_device = { - "SIMH", &simh_unit, simh_reg, simh_mod, - 1, 10, 31, 1, 16, 4, - NULL, NULL, &simh_dev_reset, - NULL, NULL, NULL, NULL, 0, NULL, NULL }; - -char messageBuffer[256]; - -void printMessage(void) { - printf(messageBuffer); - if (sim_log) { - fprintf(sim_log, messageBuffer); - } -} - -static void resetSIOWarningFlags(void) { - warnUnattachedPTP = 0; - warnUnattachedPTR = 0; - warnPTREOF = 0; - warnUnassignedPort = 0; -} - -static t_stat sio_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc) { - resetSIOWarningFlags(); - return SCPE_OK; -} - -static t_stat sio_attach(UNIT *uptr, char *cptr) { - int32 i; - for (i = 0; i < Terminals; i++) { - altairTMXR.ldsc[i] = &TerminalLines[i]; - } - reset_sio_terminals(FALSE); - return tmxr_attach(&altairTMXR, uptr, cptr); /* attach mux */ -} - -static void reset_sio_terminals(const int32 useDefault) { - int32 i; - for (i = 0; i < Terminals; i++) { - sio_terminals[i].status = useDefault ? sio_terminals[i].defaultStatus : 0; /* status */ - sio_terminals[i].data = 0x00; /* data */ - } -} - -/* detach */ -static t_stat sio_detach(UNIT *uptr) { - reset_sio_terminals(TRUE); - return tmxr_detach(&altairTMXR, uptr); -} - -/* service routines to handle simulator functions */ - -/* service routine - actually gets char & places in buffer */ - -static t_stat sio_svc(UNIT *uptr) { - int32 temp; - - sim_activate(&sio_unit, sio_unit.wait); /* continue poll */ - - if (sio_unit.flags & UNIT_ATT) { - if (sim_poll_kbd() == SCPE_STOP) { /* listen for ^E */ - return SCPE_STOP; - } - temp = tmxr_poll_conn(&altairTMXR); /* poll connection */ - if (temp >= 0) { - altairTMXR.ldsc[temp] -> rcve = 1; /* enable receive */ - } - tmxr_poll_rx(&altairTMXR); /* poll input */ - tmxr_poll_tx(&altairTMXR); /* poll output */ - } - else { - if ((temp = sim_poll_kbd()) < SCPE_KFLAG) { - return temp; /* no char or error? */ - } - sio_terminals[0].data = temp & 0xff; /* save character */ - sio_terminals[0].status |= 0x01; /* set status */ - } - return SCPE_OK; -} - - -/* reset routines */ - -static t_stat sio_reset(DEVICE *dptr) { - int32 i; - resetSIOWarningFlags(); - if (sio_unit.flags & UNIT_ATT) { - for (i = 0; i < Terminals; i++) { - if (altairTMXR.ldsc[i] -> conn > 0) { - tmxr_reset_ln(altairTMXR.ldsc[i]); - } - } - reset_sio_terminals(FALSE); - } - else { - reset_sio_terminals(TRUE); - } - sim_activate(&sio_unit, sio_unit.wait); /* activate unit */ - return SCPE_OK; -} - -static t_stat ptr_reset(DEVICE *dptr) { - resetSIOWarningFlags(); - ptr_unit.buf = 0; - ptr_unit.u3 = 0; - ptr_unit.pos = 0; - if (ptr_unit.flags & UNIT_ATT) { /* attached? */ - rewind(ptr_dev.units -> fileref); - } - sim_cancel(&ptp_unit); /* deactivate unit */ - return SCPE_OK; -} - -static t_stat ptp_reset(DEVICE *dptr) { - resetSIOWarningFlags(); - ptp_unit.buf = 0; - ptp_unit.u3 = 0x02; - sim_cancel(&ptp_unit); /* deactivate unit */ - return SCPE_OK; -} - - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. - - Each function is passed an 'io' flag, where 0 means a read from - the port, and 1 means a write to the port. On input, the actual - input is passed as the return value, on output, 'data' is written - to the device. - - Port 1 controls console I/O. We distinguish two cases: - 1) SIO attached to a port (i.e. Telnet console I/O) - 2) SIO not attached to a port (i.e. "regular" console I/O) -*/ - -int32 sio0s(const int32 port, const int32 io, const int32 data) { - int32 ti; - for (ti = 0; ti < Terminals; ti++) { - if (sio_terminals[ti].statusPort == port) { - break; - } - } - if (io == 0) { /* IN */ - if (sio_unit.flags & UNIT_ATT) { - sio_terminals[ti].status = - (((tmxr_rqln(altairTMXR.ldsc[ti]) > 0 ? 0x01 : 0) | - /* read possible if character available */ - ((altairTMXR.ldsc[ti] -> conn) && (altairTMXR.ldsc[ti] -> xmte) ? 0x02 : 0x00))); - /* write possible if connected and transmit enabled */ - } - return sio_terminals[ti].status; - } - else { /* OUT */ - if (sio_unit.flags & UNIT_ATT) { - if (data == 0x03) { /* reset port! */ - sio_terminals[ti].status = 0x00; - sio_terminals[ti].data = 0; - } - } - else { - if (data == 0x03) { /* reset port! */ - sio_terminals[ti].status = sio_terminals[ti].defaultStatus; - sio_terminals[ti].data = 0; - } - } - return 0; /* ignored since OUT */ - } -} - -int32 sio0d(const int32 port, const int32 io, const int32 data) { - int32 ti; - for (ti = 0; ti < Terminals; ti++) { - if (sio_terminals[ti].dataPort == port) { - break; - } - } - if (io == 0) { /* IN */ - if (sio_unit.flags & UNIT_ATT) { - sio_terminals[ti].data = tmxr_getc_ln(altairTMXR.ldsc[ti]) & 0xff; - } - sio_terminals[ti].status &= 0xfe; - if (sio_unit.flags & UNIT_BS) { - if (sio_terminals[ti].data == BACKSPACE_CHAR) { - sio_terminals[ti].data = DELETE_CHAR; - } - } - else { - if (sio_terminals[ti].data == DELETE_CHAR) { - sio_terminals[ti].data = BACKSPACE_CHAR; - } - } - return (sio_unit.flags & UNIT_UPPER) ? toupper(sio_terminals[ti].data) : sio_terminals[ti].data; - } - else { /* OUT */ - int32 d = sio_unit.flags & UNIT_ANSI ? data & 0x7f : data; - if (sio_unit.flags & UNIT_ATT) { - tmxr_putc_ln(altairTMXR.ldsc[ti], d); - } - else { - sim_putchar(d); - } - return 0; /* ignored since OUT */ - } -} - -/* port 2 controls the PTR/PTP devices */ - -int32 sio1s(const int32 port, const int32 io, const int32 data) { - if (io == 0) { - /* reset I bit iff PTR unit not attached or no more data available. */ - /* O bit is always set since write always possible. */ - if ((ptr_unit.flags & UNIT_ATT) == 0) { - if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnattachedPTR < warnLevelSIO)) { - warnUnattachedPTR++; -/*06*/ message1("Attempt to test status of unattached PTR. 0x02 returned.\n"); - } - return 0x02; - } - return ptr_unit.u3 ? 0x02 : 0x03; - } - else { /* OUT */ - if (data == 0x03) { - ptr_unit.u3 = 0; - ptr_unit.buf = 0; - ptr_unit.pos = 0; - ptp_unit.u3 = 0; - ptp_unit.buf = 0; - ptp_unit.pos = 0; - } - return 0; /* ignored since OUT */ - } -} - -int32 sio1d(const int32 port, const int32 io, const int32 data) { - int32 temp; - if (io == 0) { /* IN */ - if (ptr_unit.u3) { /* no more data available */ - if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnPTREOF < warnLevelSIO)) { - warnPTREOF++; -/*07*/ message1("PTR attempted to read past EOF. 0x00 returned.\n"); - } - return 0; - } - if ((ptr_unit.flags & UNIT_ATT) == 0) { /* not attached */ - if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnattachedPTR < warnLevelSIO)) { - warnUnattachedPTR++; -/*08*/ message1("Attempt to read from unattached PTR. 0x00 returned.\n"); - } - return 0; - } - if ((temp = getc(ptr_dev.units -> fileref)) == EOF) { /* end of file? */ - ptr_unit.u3 = 0x01; - return CONTROLZ_CHAR; /* control Z denotes end of text file in CP/M */ - } - ptr_unit.pos++; - return temp & 0xff; - } - else { /* OUT */ - if (ptp_unit.flags & UNIT_ATT) { /* unit must be attached */ - putc(data, ptp_dev.units -> fileref); - } /* else ignore data */ - else if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnattachedPTP < warnLevelSIO)) { - warnUnattachedPTP++; -/*09*/message2("Attempt to output '0x%02x' to unattached PTP - ignored.\n", data); - } - ptp_unit.pos++; - return 0; /* ignored since OUT */ - } -} - -int32 nulldev(const int32 port, const int32 io, const int32 data) { - if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnassignedPort < warnLevelSIO)) { - warnUnassignedPort++; - if (io == 0) { - message2("Unassigned IN(%2xh) - ignored.\n", port); - } - else { - message3("Unassigned OUT(%2xh) -> %2xh - ignored.\n", port, data); - } - } - return io == 0 ? 0xff : 0; -} - -int32 sr_dev(const int32 port, const int32 io, const int32 data) { - return io == 0 ? SR : 0; -} - -static int32 toBCD(const int32 x) { - return (x / 10) * 16 + (x % 10); -} - -static int32 fromBCD(const int32 x) { - return 10 * ((0xf0 & x) >> 4) + (0x0f & x); -} - -/* Z80 or 8080 programs communicate with the SIMH pseudo device via port 0xfe. - The following principles apply: - - 1) For commands that do not require parameters and do not return results - ld a, - out (0feh),a - Special case is the reset command which needs to be send 128 times to make - sure that the internal state is properly reset. - - 2) For commands that require parameters and do not return results - ld a, - out (0feh),a - ld a, - out (0feh),a - ld a, - out (0feh),a - ... - Note: The calling program must send all parameter bytes. Otherwise - the pseudo device is left in an unexpected state. - - 3) For commands that do not require parameters and return results - ld a, - out (0feh),a - in a,(0feh) ; contains first byte of result - in a,(0feh) ; contains second byte of result - ... - Note: The calling program must request all bytes of the result. Otherwise - the pseudo device is left in an unexpected state. - - 4) Commands requiring parameters and returning results do not exist currently. - -*/ - -enum simhPseudoDeviceCommands { /* do not change order or remove commands, add only at the end */ - printTimeCmd, /* 0 print the current time in milliseconds */ - startTimerCmd, /* 1 start a new timer on the top of the timer stack */ - stopTimerCmd, /* 2 stop timer on top of timer stack and show time difference */ - resetPTRCmd, /* 3 reset the PTR device */ - attachPTRCmd, /* 4 attach the PTR device */ - detachPTRCmd, /* 5 detach the PTR device */ - getSIMHVersionCmd, /* 6 get the current version of the SIMH pseudo device */ - getClockZSDOSCmd, /* 7 get the current time in ZSDOS format */ - setClockZSDOSCmd, /* 8 set the current time in ZSDOS format */ - getClockCPM3Cmd, /* 9 get the current time in CP/M 3 format */ - setClockCPM3Cmd, /* 10 set the current time in CP/M 3 format */ - getBankSelectCmd, /* 11 get the selected bank */ - setBankSelectCmd, /* 12 set the selected bank */ - getCommonCmd, /* 13 get the base address of the common memory segment */ - resetSIMHInterfaceCmd, /* 14 reset the SIMH pseudo device */ - showTimerCmd, /* 15 show time difference to timer on top of stack */ - attachPTPCmd, /* 16 attach PTP to the file with name at beginning of CP/M command line*/ - detachPTPCmd, /* 17 detach PTP */ - hasBankedMemoryCmd, /* 18 determines whether machine has banked memory */ - setZ80CPUCmd, /* 19 set the CPU to a Z80 */ - set8080CPUCmd, /* 20 set the CPU to an 8080 */ - startTimerInterruptsCmd,/* 21 start timer interrupts */ - stopTimerInterruptsCmd, /* 22 stop timer interrupts */ - setTimerDeltaCmd, /* 23 set the timer interval in which interrupts occur */ - setTimerInterruptAdrCmd,/* 24 set the address to call by timer interrupts */ - resetStopWatchCmd, /* 25 reset the millisecond stop watch */ - readStopWatchCmd /* 26 read the millisecond stop watch */ -}; - -#define cpmCommandLineLength 128 -#define splimit 10 /* stack depth of timer stack */ -static uint32 markTime[splimit]; /* timer stack */ -static struct tm currentTime; -static int32 currentTimeValid = FALSE; -static char version[] = "SIMH002"; - -static t_stat simh_dev_reset(DEVICE *dptr) { - currentTimeValid = FALSE; - ClockZSDOSDelta = 0; - setClockZSDOSPos = 0; - getClockZSDOSPos = 0; - ClockCPM3Delta = 0; - setClockCPM3Pos = 0; - getClockCPM3Pos = 0; - getStopWatchDeltaPos = 0; - getCommonPos = 0; - setTimerDeltaPos = 0; - setTimerInterruptAdrPos = 0; - markTimeSP = 0; - versionPos = 0; - lastCommand = 0; - lastCPMStatus = SCPE_OK; - timerInterrupt = FALSE; - if (simh_unit.flags & UNIT_SIMH_TIMERON) { - simh_dev_set_timeron(NULL, 0, NULL, NULL); - } - return SCPE_OK; -} - -static void warnNoRealTimeClock(void) { - if (simh_unit.flags & UNIT_SIMH_VERBOSE) { - printf("Sorry - no real time clock available.\n"); - } -} - -static t_stat simh_dev_set_timeron(UNIT *uptr, int32 value, char *cptr, void *desc) { - if (rtc_avail) { - timeOfNextInterrupt = sim_os_msec() + timerDelta; - return sim_activate(&simh_unit, simh_unit.wait); /* activate unit */ - } - else { - warnNoRealTimeClock(); - return SCPE_ARG; - } -} - -static t_stat simh_dev_set_timeroff(UNIT *uptr, int32 value, char *cptr, void *desc) { - timerInterrupt = FALSE; - sim_cancel(&simh_unit); - return SCPE_OK; -} - -static t_stat simh_svc(UNIT *uptr) { - uint32 n = sim_os_msec(); - if (n >= timeOfNextInterrupt) { - timerInterrupt = TRUE; - timeOfNextInterrupt += timerDelta; - if (n >= timeOfNextInterrupt) { /* time of next interrupt is not in the future */ - timeOfNextInterrupt = n + timerDelta; /* make sure it is in the future! */ - } - } - if (simh_unit.flags & UNIT_SIMH_TIMERON) { - sim_activate(&simh_unit, simh_unit.wait); /* activate unit */ - } - return SCPE_OK; -} - -/* The CP/M commandline is used as the name of a file and UNIT* uptr is attached to it. */ -static void attachCPM(UNIT *uptr) { - char cpmCommandLine[cpmCommandLineLength]; - uint32 i, len = (GetBYTEWrapper(0x80) & 0x7f) - 1; /* 0x80 contains length of commandline, discard first char */ - for (i = 0; i < len; i++) { - cpmCommandLine[i] = (char)GetBYTEWrapper(0x82 + i); /* the first char, typically ' ', is discarded */ - } - cpmCommandLine[i] = 0; /* make C string */ - if (uptr == &ptr_unit) { - sim_switches = SWMASK('R'); - } - else if (uptr == &ptp_unit) { - sim_switches = SWMASK('W'); - } - lastCPMStatus = attach_unit(uptr, cpmCommandLine); - if ((lastCPMStatus != SCPE_OK) && (simh_unit.flags & UNIT_SIMH_VERBOSE)) { - message3("Cannot open '%s' (%s).\n", cpmCommandLine, scp_error_messages[lastCPMStatus - SCPE_BASE]); - } -} - -/* setClockZSDOSAdr points to 6 byte block in M: YY MM DD HH MM SS in BCD notation */ -static void setClockZSDOS(void) { - struct tm newTime; - int32 year = fromBCD(GetBYTEWrapper(setClockZSDOSAdr)); - newTime.tm_year = year < 50 ? year + 100 : year; - newTime.tm_mon = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 1)) - 1; - newTime.tm_mday = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 2)); - newTime.tm_hour = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 3)); - newTime.tm_min = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 4)); - newTime.tm_sec = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 5)); - ClockZSDOSDelta = mktime(&newTime) - time(NULL); -} - -#define secondsPerMinute 60 -#define secondsPerHour (60 * secondsPerMinute) -#define secondsPerDay (24 * secondsPerHour) -static time_t mkCPM3Origin(void) { - struct tm date; - date.tm_year = 77; - date.tm_mon = 11; - date.tm_mday = 31; - date.tm_hour = 0; - date.tm_min = 0; - date.tm_sec = 0; - return mktime(&date); -} - -/* setClockCPM3Adr points to 5 byte block in M: - 0 - 1 int16: days since 31 Dec 77 - 2 BCD byte: HH - 3 BCD byte: MM - 4 BCD byte: SS */ -static void setClockCPM3(void) { - ClockCPM3Delta = mkCPM3Origin() + - (GetBYTEWrapper(setClockCPM3Adr) + GetBYTEWrapper(setClockCPM3Adr + 1) * 256) * secondsPerDay + - fromBCD(GetBYTEWrapper(setClockCPM3Adr + 2)) * secondsPerHour + - fromBCD(GetBYTEWrapper(setClockCPM3Adr + 3)) * secondsPerMinute + - fromBCD(GetBYTEWrapper(setClockCPM3Adr + 4)) - time(NULL); -} - -static int32 simh_in(const int32 port) { - int32 result = 0; - switch(lastCommand) { - case attachPTRCmd: - case attachPTPCmd: - result = lastCPMStatus; - lastCommand = 0; - break; - case getClockZSDOSCmd: - if (currentTimeValid) { - switch(getClockZSDOSPos) { - case 0: - result = toBCD(currentTime.tm_year > 99 ? - currentTime.tm_year - 100 : currentTime.tm_year); - getClockZSDOSPos = 1; - break; - case 1: - result = toBCD(currentTime.tm_mon + 1); - getClockZSDOSPos = 2; - break; - case 2: - result = toBCD(currentTime.tm_mday); - getClockZSDOSPos = 3; - break; - case 3: - result = toBCD(currentTime.tm_hour); - getClockZSDOSPos = 4; - break; - case 4: - result = toBCD(currentTime.tm_min); - getClockZSDOSPos = 5; - break; - case 5: - result = toBCD(currentTime.tm_sec); - getClockZSDOSPos = lastCommand = 0; - break; - } - } - else { - result = getClockZSDOSPos = lastCommand = 0; - } - break; - case getClockCPM3Cmd: - if (currentTimeValid) { - switch(getClockCPM3Pos) { - case 0: - result = daysCPM3SinceOrg & 0xff; - getClockCPM3Pos = 1; - break; - case 1: - result = (daysCPM3SinceOrg >> 8) & 0xff; - getClockCPM3Pos = 2; - break; - case 2: - result = toBCD(currentTime.tm_hour); - getClockCPM3Pos = 3; - break; - case 3: - result = toBCD(currentTime.tm_min); - getClockCPM3Pos = 4; - break; - case 4: - result = toBCD(currentTime.tm_sec); - getClockCPM3Pos = lastCommand = 0; - break; - } - } - else { - result = getClockCPM3Pos = lastCommand = 0; - } - break; - case getSIMHVersionCmd: - result = version[versionPos++]; - if (result == 0) { - versionPos = lastCommand = 0; - } - break; - case getBankSelectCmd: - if (cpu_unit.flags & UNIT_BANKED) { - result = bankSelect; - } - else { - result = 0; - if (simh_unit.flags & UNIT_SIMH_VERBOSE) { - message1("Get selected bank ignored for non-banked memory."); - } - } - lastCommand = 0; - break; - case getCommonCmd: - if (getCommonPos == 0) { - result = common & 0xff; - getCommonPos = 1; - } - else { - result = (common >> 8) & 0xff; - getCommonPos = lastCommand = 0; - } - break; - case hasBankedMemoryCmd: - result = cpu_unit.flags & UNIT_BANKED ? MAXBANKS : 0; - lastCommand = 0; - break; - case readStopWatchCmd: - if (getStopWatchDeltaPos == 0) { - result = stopWatchDelta & 0xff; - getStopWatchDeltaPos = 1; - } - else { - result = (stopWatchDelta >> 8) & 0xff; - getStopWatchDeltaPos = lastCommand = 0; - } - break; - default: - if (simh_unit.flags & UNIT_SIMH_VERBOSE) { - message2("Unnecessary IN from SIMH pseudo device on port %03xh ignored.\n", - port); - } - result = lastCommand = 0; - } - return result; -} - -static int32 simh_out(const int32 port, const int32 data) { - time_t now; - switch(lastCommand) { - case setClockZSDOSCmd: - if (setClockZSDOSPos == 0) { - setClockZSDOSAdr = data; - setClockZSDOSPos = 1; - } - else { - setClockZSDOSAdr |= (data << 8); - setClockZSDOS(); - setClockZSDOSPos = lastCommand = 0; - } - break; - case setClockCPM3Cmd: - if (setClockCPM3Pos == 0) { - setClockCPM3Adr = data; - setClockCPM3Pos = 1; - } - else { - setClockCPM3Adr |= (data << 8); - setClockCPM3(); - setClockCPM3Pos = lastCommand = 0; - } - break; - case setBankSelectCmd: - if (cpu_unit.flags & UNIT_BANKED) { - bankSelect = data & BANKMASK; - } - else if (simh_unit.flags & UNIT_SIMH_VERBOSE) { - message2("Set selected bank to %i ignored for non-banked memory.", data & 3); - } - lastCommand = 0; - break; - case setTimerDeltaCmd: - if (setTimerDeltaPos == 0) { - timerDelta = data; - setTimerDeltaPos = 1; - } - else { - timerDelta |= (data << 8); - setTimerDeltaPos = lastCommand = 0; - } - break; - case setTimerInterruptAdrCmd: - if (setTimerInterruptAdrPos == 0) { - timerInterruptHandler = data; - setTimerInterruptAdrPos = 1; - } - else { - timerInterruptHandler |= (data << 8); - setTimerInterruptAdrPos = lastCommand = 0; - } - break; - default: - lastCommand = data; - switch(data) { - case printTimeCmd: /* print time */ - if (rtc_avail) { - message2("Current time in milliseconds = %d.\n", sim_os_msec()); - } - else { - warnNoRealTimeClock(); - } - break; - case startTimerCmd: /* create a new timer on top of stack */ - if (rtc_avail) { - if (markTimeSP < splimit) { - markTime[markTimeSP++] = sim_os_msec(); - } - else { - message1("Timer stack overflow.\n"); - } - } - else { - warnNoRealTimeClock(); - } - break; - case stopTimerCmd: /* stop timer on top of stack and show time difference */ - if (rtc_avail) { - if (markTimeSP > 0) { - uint32 delta = sim_os_msec() - markTime[--markTimeSP]; - message2("Timer stopped. Elapsed time in milliseconds = %d.\n", delta); - } - else { - message1("No timer active.\n"); - } - } - else { - warnNoRealTimeClock(); - } - break; - case resetPTRCmd: /* reset ptr device */ - ptr_reset(NULL); - break; - case attachPTRCmd: /* attach ptr to the file with name at beginning of CP/M command line */ - attachCPM(&ptr_unit); - break; - case detachPTRCmd: /* detach ptr */ - detach_unit(&ptr_unit); - break; - case getSIMHVersionCmd: - versionPos = 0; - break; - case getClockZSDOSCmd: - time(&now); - now += ClockZSDOSDelta; - currentTime = *localtime(&now); - currentTimeValid = TRUE; - getClockZSDOSPos = 0; - break; - case setClockZSDOSCmd: - setClockZSDOSPos = 0; - break; - case getClockCPM3Cmd: - time(&now); - now += ClockCPM3Delta; - currentTime = *localtime(&now); - currentTimeValid = TRUE; - daysCPM3SinceOrg = (now - mkCPM3Origin()) / secondsPerDay; - getClockCPM3Pos = 0; - break; - case setClockCPM3Cmd: - setClockCPM3Pos = 0; - break; - case getBankSelectCmd: - case setBankSelectCmd: - case getCommonCmd: - case hasBankedMemoryCmd: - break; - case resetSIMHInterfaceCmd: - markTimeSP = 0; - lastCommand = 0; - break; - case showTimerCmd: /* show time difference to timer on top of stack */ - if (rtc_avail) { - if (markTimeSP > 0) { - uint32 delta = sim_os_msec() - markTime[markTimeSP - 1]; - message2("Timer running. Elapsed in milliseconds = %d.\n", delta); - } - else { - message1("No timer active.\n"); - } - } - else { - warnNoRealTimeClock(); - } - break; - case attachPTPCmd: /* attach ptp to the file with name at beginning of CP/M command line */ - attachCPM(&ptp_unit); - break; - case detachPTPCmd: /* detach ptp */ - detach_unit(&ptp_unit); - break; - case setZ80CPUCmd: - cpu_unit.flags |= UNIT_CHIP; - break; - case set8080CPUCmd: - cpu_unit.flags &= ~UNIT_CHIP; - break; - case startTimerInterruptsCmd: - if (simh_dev_set_timeron(NULL, 0, NULL, NULL) == SCPE_OK) { - timerInterrupt = FALSE; - simh_unit.flags |= UNIT_SIMH_TIMERON; - } - break; - case stopTimerInterruptsCmd: - simh_unit.flags &= ~UNIT_SIMH_TIMERON; - simh_dev_set_timeroff(NULL, 0, NULL, NULL); - break; - case setTimerDeltaCmd: - setTimerDeltaPos = 0; - break; - case setTimerInterruptAdrCmd: - setTimerInterruptAdrPos = 0; - break; - case resetStopWatchCmd: - stopWatchNow = rtc_avail ? sim_os_msec() : 0; - break; - case readStopWatchCmd: - getStopWatchDeltaPos = 0; - stopWatchDelta = rtc_avail ? sim_os_msec() - stopWatchNow : 0; - break; - default: - if (simh_unit.flags & UNIT_SIMH_VERBOSE) { - message3("Unknown command (%i) to SIMH pseudo device on port %03xh ignored.\n", - data, port); - } - } - } - return 0; /* ignored, since OUT */ -} - -/* port 0xfe is a device for communication SIMH <--> Altair machine */ -int32 simh_dev(const int32 port, const int32 io, const int32 data) { - return io == 0 ? simh_in(port) : simh_out(port, data); -} diff --git a/AltairZ80/altairZ80_sys.c b/AltairZ80/altairZ80_sys.c deleted file mode 100644 index 9cc29210..00000000 --- a/AltairZ80/altairZ80_sys.c +++ /dev/null @@ -1,782 +0,0 @@ -/* altairz80_sys.c: MITS Altair system interface - - Copyright (c) 2002-2003, Peter Schorn - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - PETER SCHORN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 - Disassembler from Marat Fayzullin ((c) 1995, 1996, 1997 - Commercial use prohibited) -*/ - -#include -#include "altairz80_defs.h" - -extern DEVICE cpu_dev; -extern DEVICE dsk_dev; -extern DEVICE hdsk_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern DEVICE sio_dev; -extern DEVICE simh_device; -extern DEVICE ptr_dev; -extern DEVICE ptp_dev; -extern int32 saved_PC; -extern void PutBYTEWrapper(register uint32 Addr, register uint32 Value); -extern void PutBYTEForced(register uint32 Addr, register uint32 Value); -extern uint8 GetBYTEWrapper(register uint32 Addr); -extern int32 addressIsInROM(const uint32 Addr); -extern int32 addressExists(const uint32 Addr); -extern void printROMMessage(const uint32 cntROM); - -int32 sim_load(FILE *fileref, char *cptr, char *fnam, int32 flag); -int32 fprint_sym(FILE *of, int32 addr, uint32 *val, UNIT *uptr, int32 sw); -static int32 checkbase(char ch, const char *numString); -static int32 numok(char ch, const char **numString, const int32 minvalue, - const int32 maxvalue, const int32 requireSign, int32 *result); -static int32 match(const char *pattern, const char *input, char *xyFirst, char *xy, int32 *number, int32 *star, int32 *at, - int32 *hat, int32 *dollar); -static int32 parse_X80(const char *cptr, const int32 addr, uint32 *val, char *const Mnemonics[]); -int32 parse_sym(char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw); -static int32 DAsm(char *S, const uint32 *val, const int32 useZ80Mnemonics, const int32 addr); -static int32 checkXY(const char xy); - -/* SCP data structures - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words needed for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "Altair 8800 (Z80)"; -REG *sim_PC = &cpu_reg[0]; -int32 sim_emax = 4; -DEVICE *sim_devices[] = { &cpu_dev, &sio_dev, &simh_device, &ptr_dev, &ptp_dev, &dsk_dev, &hdsk_dev, NULL }; - -char memoryAccessMessage[80]; -const char *sim_stop_messages[] = { - "HALT instruction", - "Breakpoint", - memoryAccessMessage, - "Invalid Opcode" }; - -static char *const Mnemonics8080[] = { -/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "NOP", "LXI B,#h", "STAX B", "INX B", "INR B", "DCR B", "MVI B,*h", "RLC", /* 00-07 */ - "DB 09h", "DAD B", "LDAX B", "DCX B", "INR C", "DCR C", "MVI C,*h", "RRC", /* 08-0f */ - "DB 10h", "LXI D,#h", "STAX D", "INX D", "INR D", "DCR D", "MVI D,*h", "RAL", /* 10-17 */ - "DB 18h", "DAD D", "LDAX D", "DCX D", "INR E", "DCR E", "MVI E,*h", "RAR", /* 18-1f */ - "DB 20h", "LXI H,#h", "SHLD #h", "INX H", "INR H", "DCR H", "MVI H,*h", "DAA", /* 20-27 */ - "DB 28h", "DAD H", "LHLD #h", "DCX H", "INR L", "DCR L", "MVI L,*h", "CMA", /* 28-2f */ - "DB 30h", "LXI SP,#h", "STA #h", "INX SP", "INR M", "DCR M", "MVI M,*h", "STC", /* 30-37 */ - "DB 38h", "DAD SP", "LDA #h", "DCX SP", "INR A", "DCR A", "MVI A,*h", "CMC", /* 38-3f */ - "MOV B,B", "MOV B,C", "MOV B,D", "MOV B,E", "MOV B,H", "MOV B,L", "MOV B,M", "MOV B,A", /* 40-47 */ - "MOV C,B", "MOV C,C", "MOV C,D", "MOV C,E", "MOV C,H", "MOV C,L", "MOV C,M", "MOV C,A", /* 48-4f */ - "MOV D,B", "MOV D,C", "MOV D,D", "MOV D,E", "MOV D,H", "MOV D,L", "MOV D,M", "MOV D,A", /* 50-57 */ - "MOV E,B", "MOV E,C", "MOV E,D", "MOV E,E", "MOV E,H", "MOV E,L", "MOV E,M", "MOV E,A", /* 58-5f */ - "MOV H,B", "MOV H,C", "MOV H,D", "MOV H,E", "MOV H,H", "MOV H,L", "MOV H,M", "MOV H,A", /* 60-67 */ - "MOV L,B", "MOV L,C", "MOV L,D", "MOV L,E", "MOV L,H", "MOV L,L", "MOV L,M", "MOV L,A", /* 68-6f */ - "MOV M,B", "MOV M,C", "MOV M,D", "MOV M,E", "MOV M,H", "MOV M,L", "HLT", "MOV M,A", /* 70-77 */ - "MOV A,B", "MOV A,C", "MOV A,D", "MOV A,E", "MOV A,H", "MOV A,L", "MOV A,M", "MOV A,A", /* 78-7f */ - "ADD B", "ADD C", "ADD D", "ADD E", "ADD H", "ADD L", "ADD M", "ADD A", /* 80-87 */ - "ADC B", "ADC C", "ADC D", "ADC E", "ADC H", "ADC L", "ADC M", "ADC A", /* 88-8f */ - "SUB B", "SUB C", "SUB D", "SUB E", "SUB H", "SUB L", "SUB M", "SUB A", /* 90-97 */ - "SBB B", "SBB C", "SBB D", "SBB E", "SBB H", "SBB L", "SBB M", "SBB A", /* 98-9f */ - "ANA B", "ANA C", "ANA D", "ANA E", "ANA H", "ANA L", "ANA M", "ANA A", /* a0-a7 */ - "XRA B", "XRA C", "XRA D", "XRA E", "XRA H", "XRA L", "XRA M", "XRA A", /* a8-af */ - "ORA B", "ORA C", "ORA D", "ORA E", "ORA H", "ORA L", "ORA M", "ORA A", /* b0-b7 */ - "CMP B", "CMP C", "CMP D", "CMP E", "CMP H", "CMP L", "CMP M", "CMP A", /* b8-bf */ - "RNZ", "POP B", "JNZ #h", "JMP #h", "CNZ #h", "PUSH B", "ADI *h", "RST 0", /* c0-c7 */ - "RZ", "RET", "JZ #h", "DB CBh", "CZ #h", "CALL #h", "ACI *h", "RST 1", /* c8-cf */ - "RNC", "POP D", "JNC #h", "OUT *h", "CNC #h", "PUSH D", "SUI *h", "RST 2", /* d0-d7 */ - "RC", "DB D9h", "JC #h", "IN *h", "CC #h", "DB DDh", "SBI *h", "RST 3", /* d8-df */ - "RPO", "POP H", "JPO #h", "XTHL", "CPO #h", "PUSH H", "ANI *h", "RST 4", /* e0-e7 */ - "RPE", "PCHL", "JPE #h", "XCHG", "CPE #h", "DB EDh", "XRI *h", "RST 5", /* e8-ef */ - "RP", "POP PSW", "JP #h", "DI", "CP #h", "PUSH PSW", "ORI *h", "RST 6", /* f0-f7 */ - "RM", "SPHL", "JM #h", "EI", "CM #h", "DB FDh", "CPI *h", "RST 7" /* f8-ff */ - }; - -static char *const MnemonicsZ80[256] = { -/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "NOP", "LD BC,#h", "LD (BC),A", "INC BC", "INC B", "DEC B", "LD B,*h", "RLCA", /* 00-07 */ - "EX AF,AF'", "ADD HL,BC", "LD A,(BC)", "DEC BC", "INC C", "DEC C", "LD C,*h", "RRCA", /* 08-0f */ - "DJNZ $h", "LD DE,#h", "LD (DE),A", "INC DE", "INC D", "DEC D", "LD D,*h", "RLA", /* 10-17 */ - "JR $h", "ADD HL,DE", "LD A,(DE)", "DEC DE", "INC E", "DEC E", "LD E,*h", "RRA", /* 18-1f */ - "JR NZ,$h", "LD HL,#h", "LD (#h),HL", "INC HL", "INC H", "DEC H", "LD H,*h", "DAA", /* 20-27 */ - "JR Z,$h", "ADD HL,HL", "LD HL,(#h)", "DEC HL", "INC L", "DEC L", "LD L,*h", "CPL", /* 28-2f */ - "JR NC,$h", "LD SP,#h", "LD (#h),A", "INC SP", "INC (HL)", "DEC (HL)", "LD (HL),*h", "SCF", /* 30-37 */ - "JR C,$h", "ADD HL,SP", "LD A,(#h)", "DEC SP", "INC A", "DEC A", "LD A,*h", "CCF", /* 38-3f */ - "LD B,B", "LD B,C", "LD B,D", "LD B,E", "LD B,H", "LD B,L", "LD B,(HL)", "LD B,A", /* 40-47 */ - "LD C,B", "LD C,C", "LD C,D", "LD C,E", "LD C,H", "LD C,L", "LD C,(HL)", "LD C,A", /* 48-4f */ - "LD D,B", "LD D,C", "LD D,D", "LD D,E", "LD D,H", "LD D,L", "LD D,(HL)", "LD D,A", /* 50-57 */ - "LD E,B", "LD E,C", "LD E,D", "LD E,E", "LD E,H", "LD E,L", "LD E,(HL)", "LD E,A", /* 58-5f */ - "LD H,B", "LD H,C", "LD H,D", "LD H,E", "LD H,H", "LD H,L", "LD H,(HL)", "LD H,A", /* 60-67 */ - "LD L,B", "LD L,C", "LD L,D", "LD L,E", "LD L,H", "LD L,L", "LD L,(HL)", "LD L,A", /* 68-6f */ - "LD (HL),B", "LD (HL),C", "LD (HL),D", "LD (HL),E", "LD (HL),H", "LD (HL),L", "HALT", "LD (HL),A", /* 70-77 */ - "LD A,B", "LD A,C", "LD A,D", "LD A,E", "LD A,H", "LD A,L", "LD A,(HL)", "LD A,A", /* 78-7f */ - "ADD A,B", "ADD A,C", "ADD A,D", "ADD A,E", "ADD A,H", "ADD A,L", "ADD A,(HL)", "ADD A,A", /* 80-87 */ - "ADC A,B", "ADC A,C", "ADC A,D", "ADC A,E", "ADC A,H", "ADC A,L", "ADC A,(HL)", "ADC A,A", /* 88-8f */ - "SUB B", "SUB C", "SUB D", "SUB E", "SUB H", "SUB L", "SUB (HL)", "SUB A", /* 90-97 */ - "SBC A,B", "SBC A,C", "SBC A,D", "SBC A,E", "SBC A,H", "SBC A,L", "SBC A,(HL)", "SBC A,A", /* 98-9f */ - "AND B", "AND C", "AND D", "AND E", "AND H", "AND L", "AND (HL)", "AND A", /* a0-a7 */ - "XOR B", "XOR C", "XOR D", "XOR E", "XOR H", "XOR L", "XOR (HL)", "XOR A", /* a8-af */ - "OR B", "OR C", "OR D", "OR E", "OR H", "OR L", "OR (HL)", "OR A", /* b0-b7 */ - "CP B", "CP C", "CP D", "CP E", "CP H", "CP L", "CP (HL)", "CP A", /* b8-bf */ - "RET NZ", "POP BC", "JP NZ,#h", "JP #h", "CALL NZ,#h", "PUSH BC", "ADD A,*h", "RST 00h", /* c0-c7 */ - "RET Z", "RET", "JP Z,#h", "PFX_CB", "CALL Z,#h", "CALL #h", "ADC A,*h", "RST 08h", /* c8-cf */ - "RET NC", "POP DE", "JP NC,#h", "OUT (*h),A", "CALL NC,#h", "PUSH DE", "SUB *h", "RST 10h", /* d0-d7 */ - "RET C", "EXX", "JP C,#h", "IN A,(*h)", "CALL C,#h", "PFX_DD", "SBC A,*h", "RST 18h", /* d8-df */ - "RET PO", "POP HL", "JP PO,#h", "EX (SP),HL", "CALL PO,#h", "PUSH HL", "AND *h", "RST 20h", /* e0-e7 */ - "RET PE", "LD PC,HL", "JP PE,#h", "EX DE,HL", "CALL PE,#h", "PFX_ED", "XOR *h", "RST 28h", /* e8-ef */ - "RET P", "POP AF", "JP P,#h", "DI", "CALL P,#h", "PUSH AF", "OR *h", "RST 30h", /* f0-f7 */ - "RET M", "LD SP,HL", "JP M,#h", "EI", "CALL M,#h", "PFX_FD", "CP *h", "RST 38h" /* f8-ff */ -}; - -static char *const MnemonicsCB[256] = { -/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (HL)", "RLC A", /* 00-07 */ - "RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (HL)", "RRC A", /* 08-0f */ - "RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (HL)", "RL A", /* 10-17 */ - "RR B", "RR C", "RR D", "RR E", "RR H", "RR L", "RR (HL)", "RR A", /* 18-1f */ - "SLA B", "SLA C", "SLA D", "SLA E", "SLA H", "SLA L", "SLA (HL)", "SLA A", /* 20-27 */ - "SRA B", "SRA C", "SRA D", "SRA E", "SRA H", "SRA L", "SRA (HL)", "SRA A", /* 28-2f */ - "SLL B", "SLL C", "SLL D", "SLL E", "SLL H", "SLL L", "SLL (HL)", "SLL A", /* 30-37 */ - "SRL B", "SRL C", "SRL D", "SRL E", "SRL H", "SRL L", "SRL (HL)", "SRL A", /* 38-3f */ - "BIT 0,B", "BIT 0,C", "BIT 0,D", "BIT 0,E", "BIT 0,H", "BIT 0,L", "BIT 0,(HL)", "BIT 0,A", /* 40-47 */ - "BIT 1,B", "BIT 1,C", "BIT 1,D", "BIT 1,E", "BIT 1,H", "BIT 1,L", "BIT 1,(HL)", "BIT 1,A", /* 48-4f */ - "BIT 2,B", "BIT 2,C", "BIT 2,D", "BIT 2,E", "BIT 2,H", "BIT 2,L", "BIT 2,(HL)", "BIT 2,A", /* 50-57 */ - "BIT 3,B", "BIT 3,C", "BIT 3,D", "BIT 3,E", "BIT 3,H", "BIT 3,L", "BIT 3,(HL)", "BIT 3,A", /* 58-5f */ - "BIT 4,B", "BIT 4,C", "BIT 4,D", "BIT 4,E", "BIT 4,H", "BIT 4,L", "BIT 4,(HL)", "BIT 4,A", /* 60-67 */ - "BIT 5,B", "BIT 5,C", "BIT 5,D", "BIT 5,E", "BIT 5,H", "BIT 5,L", "BIT 5,(HL)", "BIT 5,A", /* 68-6f */ - "BIT 6,B", "BIT 6,C", "BIT 6,D", "BIT 6,E", "BIT 6,H", "BIT 6,L", "BIT 6,(HL)", "BIT 6,A", /* 70-77 */ - "BIT 7,B", "BIT 7,C", "BIT 7,D", "BIT 7,E", "BIT 7,H", "BIT 7,L", "BIT 7,(HL)", "BIT 7,A", /* 78-7f */ - "RES 0,B", "RES 0,C", "RES 0,D", "RES 0,E", "RES 0,H", "RES 0,L", "RES 0,(HL)", "RES 0,A", /* 80-87 */ - "RES 1,B", "RES 1,C", "RES 1,D", "RES 1,E", "RES 1,H", "RES 1,L", "RES 1,(HL)", "RES 1,A", /* 88-8f */ - "RES 2,B", "RES 2,C", "RES 2,D", "RES 2,E", "RES 2,H", "RES 2,L", "RES 2,(HL)", "RES 2,A", /* 90-97 */ - "RES 3,B", "RES 3,C", "RES 3,D", "RES 3,E", "RES 3,H", "RES 3,L", "RES 3,(HL)", "RES 3,A", /* 98-9f */ - "RES 4,B", "RES 4,C", "RES 4,D", "RES 4,E", "RES 4,H", "RES 4,L", "RES 4,(HL)", "RES 4,A", /* a0-a7 */ - "RES 5,B", "RES 5,C", "RES 5,D", "RES 5,E", "RES 5,H", "RES 5,L", "RES 5,(HL)", "RES 5,A", /* a8-af */ - "RES 6,B", "RES 6,C", "RES 6,D", "RES 6,E", "RES 6,H", "RES 6,L", "RES 6,(HL)", "RES 6,A", /* b0-b7 */ - "RES 7,B", "RES 7,C", "RES 7,D", "RES 7,E", "RES 7,H", "RES 7,L", "RES 7,(HL)", "RES 7,A", /* b8-bf */ - "SET 0,B", "SET 0,C", "SET 0,D", "SET 0,E", "SET 0,H", "SET 0,L", "SET 0,(HL)", "SET 0,A", /* c0-c7 */ - "SET 1,B", "SET 1,C", "SET 1,D", "SET 1,E", "SET 1,H", "SET 1,L", "SET 1,(HL)", "SET 1,A", /* c8-cf */ - "SET 2,B", "SET 2,C", "SET 2,D", "SET 2,E", "SET 2,H", "SET 2,L", "SET 2,(HL)", "SET 2,A", /* d0-d7 */ - "SET 3,B", "SET 3,C", "SET 3,D", "SET 3,E", "SET 3,H", "SET 3,L", "SET 3,(HL)", "SET 3,A", /* d8-df */ - "SET 4,B", "SET 4,C", "SET 4,D", "SET 4,E", "SET 4,H", "SET 4,L", "SET 4,(HL)", "SET 4,A", /* e0-e7 */ - "SET 5,B", "SET 5,C", "SET 5,D", "SET 5,E", "SET 5,H", "SET 5,L", "SET 5,(HL)", "SET 5,A", /* e8-ef */ - "SET 6,B", "SET 6,C", "SET 6,D", "SET 6,E", "SET 6,H", "SET 6,L", "SET 6,(HL)", "SET 6,A", /* f0-f7 */ - "SET 7,B", "SET 7,C", "SET 7,D", "SET 7,E", "SET 7,H", "SET 7,L", "SET 7,(HL)", "SET 7,A" /* f8-ff */ -}; - -static char *const MnemonicsED[256] = { -/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "DB EDh,00h", "DB EDh,01h", "DB EDh,02h", "DB EDh,03h", "DB EDh,04h", "DB EDh,05h", "DB EDh,06h", "DB EDh,07h", /* 00-07 */ - "DB EDh,08h", "DB EDh,09h", "DB EDh,0Ah", "DB EDh,0Bh", "DB EDh,0Ch", "DB EDh,0Dh", "DB EDh,0Eh", "DB EDh,0Fh", /* 08-0f */ - "DB EDh,10h", "DB EDh,11h", "DB EDh,12h", "DB EDh,13h", "DB EDh,14h", "DB EDh,15h", "DB EDh,16h", "DB EDh,17h", /* 10-17 */ - "DB EDh,18h", "DB EDh,19h", "DB EDh,1Ah", "DB EDh,1Bh", "DB EDh,1Ch", "DB EDh,1Dh", "DB EDh,1Eh", "DB EDh,1Fh", /* 18-1f */ - "DB EDh,20h", "DB EDh,21h", "DB EDh,22h", "DB EDh,23h", "DB EDh,24h", "DB EDh,25h", "DB EDh,26h", "DB EDh,27h", /* 20-27 */ - "DB EDh,28h", "DB EDh,29h", "DB EDh,2Ah", "DB EDh,2Bh", "DB EDh,2Ch", "DB EDh,2Dh", "DB EDh,2Eh", "DB EDh,2Fh", /* 28-2f */ - "DB EDh,30h", "DB EDh,31h", "DB EDh,32h", "DB EDh,33h", "DB EDh,34h", "DB EDh,35h", "DB EDh,36h", "DB EDh,37h", /* 30-37 */ - "DB EDh,38h", "DB EDh,39h", "DB EDh,3Ah", "DB EDh,3Bh", "DB EDh,3Ch", "DB EDh,3Dh", "DB EDh,3Eh", "DB EDh,3Fh", /* 38-3f */ - "IN B,(C)", "OUT (C),B", "SBC HL,BC", "LD (#h),BC", "NEG", "RETN", "IM 0", "LD I,A", /* 40-47 */ - "IN C,(C)", "OUT (C),C", "ADC HL,BC", "LD BC,(#h)", "DB EDh,4Ch", "RETI", "DB EDh,4Eh", "LD R,A", /* 48-4f */ - "IN D,(C)", "OUT (C),D", "SBC HL,DE", "LD (#h),DE", "DB EDh,54h", "DB EDh,55h", "IM 1", "LD A,I", /* 50-57 */ - "IN E,(C)", "OUT (C),E", "ADC HL,DE", "LD DE,(#h)", "DB EDh,5Ch", "DB EDh,5Dh", "IM 2", "LD A,R", /* 58-5f */ - "IN H,(C)", "OUT (C),H", "SBC HL,HL", "LD (#h),HL", "DB EDh,64h", "DB EDh,65h", "DB EDh,66h", "RRD", /* 60-67 */ - "IN L,(C)", "OUT (C),L", "ADC HL,HL", "LD HL,(#h)", "DB EDh,6Ch", "DB EDh,6Dh", "DB EDh,6Eh", "RLD", /* 68-6f */ - "IN F,(C)", "DB EDh,71h", "SBC HL,SP", "LD (#h),SP", "DB EDh,74h", "DB EDh,75h", "DB EDh,76h", "DB EDh,77h", /* 70-77 */ - "IN A,(C)", "OUT (C),A", "ADC HL,SP", "LD SP,(#h)", "DB EDh,7Ch", "DB EDh,7Dh", "DB EDh,7Eh", "DB EDh,7Fh", /* 78-7f */ - "DB EDh,80h", "DB EDh,81h", "DB EDh,82h", "DB EDh,83h", "DB EDh,84h", "DB EDh,85h", "DB EDh,86h", "DB EDh,87h", /* 80-87 */ - "DB EDh,88h", "DB EDh,89h", "DB EDh,8Ah", "DB EDh,8Bh", "DB EDh,8Ch", "DB EDh,8Dh", "DB EDh,8Eh", "DB EDh,8Fh", /* 88-8f */ - "DB EDh,90h", "DB EDh,91h", "DB EDh,92h", "DB EDh,93h", "DB EDh,94h", "DB EDh,95h", "DB EDh,96h", "DB EDh,97h", /* 90-97 */ - "DB EDh,98h", "DB EDh,99h", "DB EDh,9Ah", "DB EDh,9Bh", "DB EDh,9Ch", "DB EDh,9Dh", "DB EDh,9Eh", "DB EDh,9Fh", /* 98-9f */ - "LDI", "CPI", "INI", "OUTI", "DB EDh,A4h", "DB EDh,A5h", "DB EDh,A6h", "DB EDh,A7h", /* a0-a7 */ - "LDD", "CPD", "IND", "OUTD", "DB EDh,ACh", "DB EDh,ADh", "DB EDh,AEh", "DB EDh,AFh", /* a8-af */ - "LDIR", "CPIR", "INIR", "OTIR", "DB EDh,B4h", "DB EDh,B5h", "DB EDh,B6h", "DB EDh,B7h", /* b0-b7 */ - "LDDR", "CPDR", "INDR", "OTDR", "DB EDh,BCh", "DB EDh,BDh", "DB EDh,BEh", "DB EDh,BFh", /* b8-bf */ - "DB EDh,C0h", "DB EDh,C1h", "DB EDh,C2h", "DB EDh,C3h", "DB EDh,C4h", "DB EDh,C5h", "DB EDh,C6h", "DB EDh,C7h", /* c0-c7 */ - "DB EDh,C8h", "DB EDh,C9h", "DB EDh,CAh", "DB EDh,CBh", "DB EDh,CCh", "DB EDh,CDh", "DB EDh,CEh", "DB EDh,CFh", /* c8-cf */ - "DB EDh,D0h", "DB EDh,D1h", "DB EDh,D2h", "DB EDh,D3h", "DB EDh,D4h", "DB EDh,D5h", "DB EDh,D6h", "DB EDh,D7h", /* d0-d7 */ - "DB EDh,D8h", "DB EDh,D9h", "DB EDh,DAh", "DB EDh,DBh", "DB EDh,DCh", "DB EDh,DDh", "DB EDh,DEh", "DB EDh,DFh", /* d8-df */ - "DB EDh,E0h", "DB EDh,E1h", "DB EDh,E2h", "DB EDh,E3h", "DB EDh,E4h", "DB EDh,E5h", "DB EDh,E6h", "DB EDh,E7h", /* e0-e7 */ - "DB EDh,E8h", "DB EDh,E9h", "DB EDh,EAh", "DB EDh,EBh", "DB EDh,ECh", "DB EDh,EDh", "DB EDh,EEh", "DB EDh,EFh", /* e8-ef */ - "DB EDh,F0h", "DB EDh,F1h", "DB EDh,F2h", "DB EDh,F3h", "DB EDh,F4h", "DB EDh,F5h", "DB EDh,F6h", "DB EDh,F7h", /* f0-f7 */ - "DB EDh,F8h", "DB EDh,F9h", "DB EDh,FAh", "DB EDh,FBh", "DB EDh,FCh", "DB EDh,FDh", "DB EDh,FEh", "DB EDh,FFh" /* f8-ff */ -}; - -static char *const MnemonicsXX[256] = { -/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "NOP", "LD BC,#h", "LD (BC),A", "INC BC", "INC B", "DEC B", "LD B,*h", "RLCA", /* 00-07 */ - "EX AF,AF'", "ADD I%,BC", "LD A,(BC)", "DEC BC", "INC C", "DEC C", "LD C,*h", "RRCA", /* 08-0f */ - "DJNZ $h", "LD DE,#h", "LD (DE),A", "INC DE", "INC D", "DEC D", "LD D,*h", "RLA", /* 10-17 */ - "JR $h", "ADD I%,DE", "LD A,(DE)", "DEC DE", "INC E", "DEC E", "LD E,*h", "RRA", /* 18-1f */ - "JR NZ,$h", "LD I%,#h", "LD (#h),I%", "INC I%", "INC I%H", "DEC I%H", "LD I%H,*h", "DAA", /* 20-27 */ - "JR Z,$h", "ADD I%,I%", "LD I%,(#h)", "DEC I%", "INC I%L", "DEC I%L", "LD I%L,*h", "CPL", /* 28-2f */ - "JR NC,$h", "LD SP,#h", "LD (#h),A", "INC SP", "INC (I%+^h)", "DEC (I%+^h)", "LD (I%+^h),*h", "SCF", /* 30-37 */ - "JR C,$h", "ADD I%,SP", "LD A,(#h)", "DEC SP", "INC A", "DEC A", "LD A,*h", "CCF", /* 38-3f */ - "LD B,B", "LD B,C", "LD B,D", "LD B,E", "LD B,I%H", "LD B,I%L", "LD B,(I%+^h)", "LD B,A", /* 40-47 */ - "LD C,B", "LD C,C", "LD C,D", "LD C,E", "LD C,I%H", "LD C,I%L", "LD C,(I%+^h)", "LD C,A", /* 48-4f */ - "LD D,B", "LD D,C", "LD D,D", "LD D,E", "LD D,I%H", "LD D,I%L", "LD D,(I%+^h)", "LD D,A", /* 50-57 */ - "LD E,B", "LD E,C", "LD E,D", "LD E,E", "LD E,I%H", "LD E,I%L", "LD E,(I%+^h)", "LD E,A", /* 58-5f */ - "LD I%H,B", "LD I%H,C", "LD I%H,D", "LD I%H,E", "LD I%H,I%H", "LD I%H,I%L", "LD H,(I%+^h)", "LD I%H,A", /* 60-67 */ - "LD I%L,B", "LD I%L,C", "LD I%L,D", "LD I%L,E", "LD I%L,I%H", "LD I%L,I%L", "LD L,(I%+^h)", "LD I%L,A", /* 68-6f */ - "LD (I%+^h),B", "LD (I%+^h),C", "LD (I%+^h),D", "LD (I%+^h),E", "LD (I%+^h),H", "LD (I%+^h),L", "HALT", "LD (I%+^h),A", /* 70-77 */ - "LD A,B", "LD A,C", "LD A,D", "LD A,E", "LD A,I%H", "LD A,I%L", "LD A,(I%+^h)", "LD A,A", /* 78-7f */ - "ADD A,B", "ADD A,C", "ADD A,D", "ADD A,E", "ADD A,I%H", "ADD A,I%L", "ADD A,(I%+^h)", "ADD A,A", /* 80-87 */ - "ADC A,B", "ADC A,C", "ADC A,D", "ADC A,E", "ADC A,I%H", "ADC A,I%L", "ADC A,(I%+^h)", "ADC A,A", /* 88-8f */ - "SUB B", "SUB C", "SUB D", "SUB E", "SUB I%H", "SUB I%L", "SUB (I%+^h)", "SUB A", /* 90-97 */ - "SBC A,B", "SBC A,C", "SBC A,D", "SBC A,E", "SBC A,I%H", "SBC A,I%L", "SBC A,(I%+^h)", "SBC A,A", /* 98-9f */ - "AND B", "AND C", "AND D", "AND E", "AND I%H", "AND I%L", "AND (I%+^h)", "AND A", /* a0-a7 */ - "XOR B", "XOR C", "XOR D", "XOR E", "XOR I%H", "XOR I%L", "XOR (I%+^h)", "XOR A", /* a8-af */ - "OR B", "OR C", "OR D", "OR E", "OR I%H", "OR I%L", "OR (I%+^h)", "OR A", /* b0-b7 */ - "CP B", "CP C", "CP D", "CP E", "CP I%H", "CP I%L", "CP (I%+^h)", "CP A", /* b8-bf */ - "RET NZ", "POP BC", "JP NZ,#h", "JP #h", "CALL NZ,#h", "PUSH BC", "ADD A,*h", "RST 00h", /* c8-cf */ - "RET Z", "RET", "JP Z,#h", "PFX_CB", "CALL Z,#h", "CALL #h", "ADC A,*h", "RST 08h", /* c8-cf */ - "RET NC", "POP DE", "JP NC,#h", "OUT (*h),A", "CALL NC,#h", "PUSH DE", "SUB *h", "RST 10h", /* d0-d7 */ - "RET C", "EXX", "JP C,#h", "IN A,(*h)", "CALL C,#h", "PFX_DD", "SBC A,*h", "RST 18h", /* d8-df */ - "RET PO", "POP I%", "JP PO,#h", "EX (SP),I%", "CALL PO,#h", "PUSH I%", "AND *h", "RST 20h", /* e0-e7 */ - "RET PE", "LD PC,I%", "JP PE,#h", "EX DE,I%", "CALL PE,#h", "PFX_ED", "XOR *h", "RST 28h", /* e8-ef */ - "RET P", "POP AF", "JP P,#h", "DI", "CALL P,#h", "PUSH AF", "OR *h", "RST 30h", /* f0-f7 */ - "RET M", "LD SP,I%", "JP M,#h", "EI", "CALL M,#h", "PFX_FD", "CP *h", "RST 38h" /* f8-ff */ -}; - -static char *const MnemonicsXCB[256] = { -/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (I%@h)", "RLC A", /* 00-07 */ - "RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (I%@h)", "RRC A", /* 08-0f */ - "RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (I%@h)", "RL A", /* 10-17 */ - "RR B", "RR C", "RR D", "RR E", "RR H", "RR L", "RR (I%@h)", "RR A", /* 18-1f */ - "SLA B", "SLA C", "SLA D", "SLA E", "SLA H", "SLA L", "SLA (I%@h)", "SLA A", /* 20-27 */ - "SRA B", "SRA C", "SRA D", "SRA E", "SRA H", "SRA L", "SRA (I%@h)", "SRA A", /* 28-2f */ - "SLL B", "SLL C", "SLL D", "SLL E", "SLL H", "SLL L", "SLL (I%@h)", "SLL A", /* 30-37 */ - "SRL B", "SRL C", "SRL D", "SRL E", "SRL H", "SRL L", "SRL (I%@h)", "SRL A", /* 38-3f */ - "BIT 0,B", "BIT 0,C", "BIT 0,D", "BIT 0,E", "BIT 0,H", "BIT 0,L", "BIT 0,(I%@h)", "BIT 0,A", /* 40-47 */ - "BIT 1,B", "BIT 1,C", "BIT 1,D", "BIT 1,E", "BIT 1,H", "BIT 1,L", "BIT 1,(I%@h)", "BIT 1,A", /* 48-4f */ - "BIT 2,B", "BIT 2,C", "BIT 2,D", "BIT 2,E", "BIT 2,H", "BIT 2,L", "BIT 2,(I%@h)", "BIT 2,A", /* 50-57 */ - "BIT 3,B", "BIT 3,C", "BIT 3,D", "BIT 3,E", "BIT 3,H", "BIT 3,L", "BIT 3,(I%@h)", "BIT 3,A", /* 58-5f */ - "BIT 4,B", "BIT 4,C", "BIT 4,D", "BIT 4,E", "BIT 4,H", "BIT 4,L", "BIT 4,(I%@h)", "BIT 4,A", /* 60-67 */ - "BIT 5,B", "BIT 5,C", "BIT 5,D", "BIT 5,E", "BIT 5,H", "BIT 5,L", "BIT 5,(I%@h)", "BIT 5,A", /* 68-6f */ - "BIT 6,B", "BIT 6,C", "BIT 6,D", "BIT 6,E", "BIT 6,H", "BIT 6,L", "BIT 6,(I%@h)", "BIT 6,A", /* 70-77 */ - "BIT 7,B", "BIT 7,C", "BIT 7,D", "BIT 7,E", "BIT 7,H", "BIT 7,L", "BIT 7,(I%@h)", "BIT 7,A", /* 78-7f */ - "RES 0,B", "RES 0,C", "RES 0,D", "RES 0,E", "RES 0,H", "RES 0,L", "RES 0,(I%@h)", "RES 0,A", /* 80-87 */ - "RES 1,B", "RES 1,C", "RES 1,D", "RES 1,E", "RES 1,H", "RES 1,L", "RES 1,(I%@h)", "RES 1,A", /* 88-8f */ - "RES 2,B", "RES 2,C", "RES 2,D", "RES 2,E", "RES 2,H", "RES 2,L", "RES 2,(I%@h)", "RES 2,A", /* 90-97 */ - "RES 3,B", "RES 3,C", "RES 3,D", "RES 3,E", "RES 3,H", "RES 3,L", "RES 3,(I%@h)", "RES 3,A", /* 98-9f */ - "RES 4,B", "RES 4,C", "RES 4,D", "RES 4,E", "RES 4,H", "RES 4,L", "RES 4,(I%@h)", "RES 4,A", /* a0-a7 */ - "RES 5,B", "RES 5,C", "RES 5,D", "RES 5,E", "RES 5,H", "RES 5,L", "RES 5,(I%@h)", "RES 5,A", /* a8-af */ - "RES 6,B", "RES 6,C", "RES 6,D", "RES 6,E", "RES 6,H", "RES 6,L", "RES 6,(I%@h)", "RES 6,A", /* b0-b7 */ - "RES 7,B", "RES 7,C", "RES 7,D", "RES 7,E", "RES 7,H", "RES 7,L", "RES 7,(I%@h)", "RES 7,A", /* b8-bf */ - "SET 0,B", "SET 0,C", "SET 0,D", "SET 0,E", "SET 0,H", "SET 0,L", "SET 0,(I%@h)", "SET 0,A", /* c0-c7 */ - "SET 1,B", "SET 1,C", "SET 1,D", "SET 1,E", "SET 1,H", "SET 1,L", "SET 1,(I%@h)", "SET 1,A", /* c8-cf */ - "SET 2,B", "SET 2,C", "SET 2,D", "SET 2,E", "SET 2,H", "SET 2,L", "SET 2,(I%@h)", "SET 2,A", /* d0-d7 */ - "SET 3,B", "SET 3,C", "SET 3,D", "SET 3,E", "SET 3,H", "SET 3,L", "SET 3,(I%@h)", "SET 3,A", /* d8-df */ - "SET 4,B", "SET 4,C", "SET 4,D", "SET 4,E", "SET 4,H", "SET 4,L", "SET 4,(I%@h)", "SET 4,A", /* e0-e7 */ - "SET 5,B", "SET 5,C", "SET 5,D", "SET 5,E", "SET 5,H", "SET 5,L", "SET 5,(I%@h)", "SET 5,A", /* e8-ef */ - "SET 6,B", "SET 6,C", "SET 6,D", "SET 6,E", "SET 6,H", "SET 6,L", "SET 6,(I%@h)", "SET 6,A", /* f0-f7 */ - "SET 7,B", "SET 7,C", "SET 7,D", "SET 7,E", "SET 7,H", "SET 7,L", "SET 7,(I%@h)", "SET 7,A" /* f8-ff */ -}; - -/* symbolic disassembler - - Inputs: - *val = instructions to disassemble - useZ80Mnemonics = > 0 iff Z80 mnemonics are to be used - addr = current PC - Outputs: - *S = output text - - DAsm is Copyright (C) Marat Fayzullin 1995,1996,1997 - You are not allowed to distribute this software - commercially. - -*/ - -static int32 DAsm(char *S, const uint32 *val, const int32 useZ80Mnemonics, const int32 addr) { - char R[128], H[10], C = '\0', *T, *P; - uint8 J = 0, Offset = 0; - uint16 B = 0; - - if (useZ80Mnemonics) { - switch(val[B]) { - case 0xcb: - B++; - T = MnemonicsCB[val[B++]]; - break; - case 0xed: - B++; - T = MnemonicsED[val[B++]]; - break; - case 0xdd: - case 0xfd: - C = (val[B++] == 0xdd) ? 'X' : 'Y'; - if (val[B] == 0xcb) { - B++; - Offset = val[B++]; - J = 1; - T = MnemonicsXCB[val[B++]]; - } - else { - T = MnemonicsXX[val[B++]]; - } - break; - default: - T = MnemonicsZ80[val[B++]]; - } - } - else { - T = Mnemonics8080[val[B++]]; - } - - if (P = strchr(T, '^')) { - strncpy(R, T, P - T); - R[P - T] = '\0'; - sprintf(H, "%02X", val[B++]); - strcat(R, H); - strcat(R, P + 1); - } - else { - strcpy(R, T); - } - if (P = strchr(R, '%')) { - *P = C; - if (P = strchr(P + 1, '%')) { - *P = C; - } - } - - if(P = strchr(R, '*')) { - strncpy(S, R, P - R); - S[P - R] = '\0'; - sprintf(H, "%02X", val[B++]); - strcat(S, H); - strcat(S, P + 1); - } - else if (P = strchr(R, '@')) { - strncpy(S, R, P - R); - S[P - R] = '\0'; - if(!J) { - Offset = val[B++]; - } - strcat(S, Offset & 0x80 ? "-" : "+"); - J = Offset & 0x80 ? 256 - Offset : Offset; - sprintf(H, "%02X", J); - strcat(S, H); - strcat(S, P + 1); - } - else if (P = strchr(R, '$')) { - strncpy(S, R, P - R); - S[P - R] = '\0'; - Offset = val[B++]; - sprintf(H, "%04X", addr + 2 + (Offset & 0x80 ? (Offset - 256) : Offset)); - strcat(S, H); - strcat(S, P + 1); - } - else if (P = strchr(R, '#')) { - strncpy(S, R, P - R); - S[P - R] = '\0'; - sprintf(H, "%04X", val[B] + 256 * val[B + 1]); - strcat(S, H); - strcat(S, P + 1); - B += 2; - } - else { - strcpy(S, R); - } - return(B); -} - -/* symbolic output - - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - status = error code -*/ - -int32 fprint_sym(FILE *of, int32 addr, uint32 *val, UNIT *uptr, int32 sw) { - char disasm[128]; - int32 ch = val[0] & 0x7f; - if (sw & (SWMASK('A') | SWMASK('C'))) { - fprintf(of, ((0x20 <= ch) && (ch < 0x7f)) ? "'%c'" : "%02x", ch); - return SCPE_OK; - } - if (!(sw & SWMASK('M'))) { - return SCPE_ARG; - } - ch = DAsm(disasm, val, cpu_unit.flags & UNIT_CHIP, addr); - fprintf(of, "%s", disasm); - return 1 - ch; /* need to return additional bytes */ -} - -/* numString checks determines the base of the number (ch, *numString) - and returns FALSE if the number is bad */ -static int32 checkbase(char ch, const char *numString) { - int32 decimal = (ch <= '9'); - if (toupper(ch) == 'H') { - return FALSE; - } - while (isxdigit(ch = *numString++)) { - if (ch > '9') { - decimal = FALSE; - } - } - return toupper(ch) == 'H' ? 16 : (decimal ? 10 : FALSE); -} - -static int32 numok(char ch, const char **numString, const int32 minvalue, - const int32 maxvalue, const int32 requireSign, int32 *result) { - int32 sign = 1, value = 0, base; - if (requireSign) { - if (ch == '+') { - ch = *(*numString)++; - } - else if (ch == '-') { - sign = -1; - ch = *(*numString)++; - } - else { - return FALSE; - } - } - if (!(base = checkbase(ch, *numString))) { - return FALSE; - } - while (isxdigit(ch)) { - value = base * value + ((ch <= '9') ? (ch - '0') : (toupper(ch) - 'A' + 10)); - ch = *(*numString)++; - } - if (toupper(ch) != 'H') { - (*numString)--; - } - *result = value * sign; - return (minvalue <= value) && (value <= maxvalue); -} - -static int32 match(const char *pattern, const char *input, char *xyFirst, char *xy, int32 *number, int32 *star, - int32 *at, int32 *hat, int32 *dollar) { - char pat = *pattern++; - char inp = *input++; - while ((pat) && (inp)) { - switch(pat) { - case '_': /* patterns containting '_' should never match */ - return FALSE; - case ',': - if (inp == ' ') { - inp = *input++; - continue; - } /* otherwise fall through */ - case ' ': - if (inp != pat) { - return FALSE; - } - pat = *pattern++; - inp = *input++; - while (inp == ' ') { - inp = *input++; - } - continue; - case '%': - inp = toupper(inp); - if ((inp == 'X') || (inp == 'Y')) { - if (*xyFirst) { /* make sure that second '%' corresponds to first */ - if (*xyFirst == inp) { - *xy = inp; - } - else { - return FALSE; - } - } - else { /* take note of first '%' for later */ - *xyFirst = inp; - *xy = inp; - } - } - else { - return FALSE; - } - break; - case '#': - if (numok(inp, &input, 0, 65535, FALSE, number)) { - pattern++; /* skip h */ - } - else { - return FALSE; - } - break; - case '*': - if (numok(inp, &input, 0, 255, FALSE, star)) { - pattern++; /* skip h */ - } - else { - return FALSE; - } - break; - case '@': - if (numok(inp, &input, -128, 65535, TRUE, at)) { - pattern++; /* skip h */ - } - else { - return FALSE; - } - break; - case '$': - if (numok(inp, &input, 0, 65535, FALSE, dollar)) { - pattern++; /* skip h */ - } - else { - return FALSE; - } - break; - case '^': - if (numok(inp, &input, 0, 255, FALSE, hat)) { - pattern++; /* skip h */ - } - else { - return FALSE; - } - break; - default: - if (toupper(pat) != toupper(inp)) { - return FALSE; - } - } - pat = *pattern++; - inp = *input++; - } - while (inp == ' ') { - inp = *input++; - } - return (pat == 0) && (inp == 0); -} - -static INLINE int32 checkXY(const char xy) { - return xy == 'X' ? 0xdd : 0xfd; /* else is 'Y' */ -} - -static int32 parse_X80(const char *cptr, const int32 addr, uint32 *val, char *const Mnemonics[]) { - char xyFirst = 0, xy; - int32 op, number, star, at, hat, dollar; - for (op = 0; op < 256; op++) { - number = star = at = dollar = -129; - if (match(Mnemonics[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - val[0] = op; - if (number >= 0) { - val[1] = (0xff) & number; - val[2] = (0xff) & (number >> 8); - return -2; /* two additional bytes returned */ - } - else if (star >= 0) { - val[1] = (0xff) & star; - return -1; /* one additional byte returned */ - } - else if (at > -129) { - if ((-128 <= at) && (at <= 127)) { - val[1] = (int8)(at); - return -1; /* one additional byte returned */ - } - else { - return SCPE_ARG; - } - } - else if (dollar >= 0) { - dollar -= addr + 2; /* relative translation */ - if ((-128 <= dollar) && (dollar <= 127)) { - val[1] = (int8)(dollar); - return -1; /* one additional byte returned */ - } - else { - return SCPE_ARG; - } - } - else { - return SCPE_OK; - } - } - } - if (Mnemonics == Mnemonics8080) { - return SCPE_ARG; - } - - for (op = 0; op < 256; op++) { - if (match(MnemonicsCB[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - val[0] = 0xcb; - val[1] = op; - return -1; /* one additional byte returned */ - } - } - - for (op = 0; op < 256; op++) { - number = -1; - if (match(MnemonicsED[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - val[0] = 0xed; - val[1] = op; - if (number >= 0) { - val[2] = (0xff) & number; - val[3] = (0xff) & (number >> 8); - return -3; /* three additional bytes returned */ - } - else { - return -1; /* one additional byte returned */ - } - } - } - - for (op = 0; op < 256; op++) { - number = star = hat = -1; - xy = 0; - if (match(MnemonicsXX[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - /* all matches must have contained a '%' character */ - if (!(val[0] = checkXY(xy))) { - return SCPE_ARG; - } - val[1] = op; - if (number >= 0) { - val[2] = (0xff) & number; - val[3] = (0xff) & (number >> 8); - return -3; /* three additional bytes returned */ - } - else if ((star >= 0) && (hat >= 0)) { - val[2] = (0xff) & hat; - val[3] = (0xff) & star; - return -3; /* three additional bytes returned */ - } - else if (star >= 0) { - val[2] = (0xff) & star; - return -2; /* two additional bytes returned */ - } - else if (hat >= 0) { - val[2] = (0xff) & hat; - return -2; /* two additional bytes returned */ - } - else { - return -1; /* one additional byte returned */ - } - } - } - - for (op = 0; op < 256; op++) { - at = -129; - xy = 0; - if (match(MnemonicsXCB[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - /* all matches must have contained a '%' character */ - if (!(val[0] = checkXY(xy))) { - return SCPE_ARG; - } - val[1] = 0xcb; - if (at > -129) { - val[2] = (int8) (at); - } - else { - printf("Offset expected.\n"); - return SCPE_ARG; - } - val[3] = op; - return -3; /* three additional bytes returned */ - } - } - return SCPE_ARG; -} - - -/* symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = error status -*/ -int32 parse_sym(char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw) { - while (isspace(*cptr)) cptr++; /* absorb spaces */ - if ((sw & (SWMASK('A') | SWMASK('C'))) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) { - return SCPE_ARG; /* must have one char */ - } - val[0] = (uint32) cptr[0]; - return SCPE_OK; - } - return parse_X80(cptr, addr, val, cpu_unit.flags & UNIT_CHIP ? MnemonicsZ80 : Mnemonics8080); -} - - -/* This is the binary loader. The input file is considered to be - a string of literal bytes with no format special format. The - load starts at the current value of the PC. ROM/NOROM and - ALTAIRROM/NOALTAIRROM settings are ignored. -*/ - -int32 sim_load(FILE *fileref, char *cptr, char *fnam, int32 flag) { - int32 i, addr = 0, cnt = 0, org, cntROM = 0, cntNonExist = 0; - t_addr j, lo, hi; - char *result; - t_stat status; - if (flag) { - result = get_range(cptr, &lo, &hi, 16, ADDRMASK, 0); - if (result == NULL) { - return SCPE_ARG; - } - for (j = lo; j <= hi; j++) { - if (putc(GetBYTEWrapper(j), fileref) == EOF) { - return SCPE_IOERR; - } - } - printf("%d bytes dumped [%x - %x].\n", hi + 1 - lo, lo, hi); - } - else { - if (*cptr == 0) { - addr = saved_PC; - } - else { - addr = get_uint(cptr, 16, ADDRMASK, &status); - if (status != SCPE_OK) { - return status; - } - } - org = addr; - while ((addr < MAXMEMSIZE) && ((i = getc(fileref)) != EOF)) { - PutBYTEForced(addr, i); - if (addressIsInROM(addr)) { - cntROM++; - } - if (!addressExists(addr)) { - cntNonExist++; - } - addr++; - cnt++; - } /* end while */ - printf("%d bytes [%d page%s] loaded at %x.\n", cnt, (cnt + 255) >> 8, - ((cnt + 255) >> 8) == 1 ? "" : "s", org); - printROMMessage(cntROM); - if (cntNonExist) { - printf("Warning: %d bytes written to non-existing memory (for this configuration).\n", cntNonExist); - } - } - return SCPE_OK; -} diff --git a/AltairZ80/altairz80_hdsk.c b/AltairZ80/altairz80_hdsk.c deleted file mode 100644 index 9794098b..00000000 --- a/AltairZ80/altairz80_hdsk.c +++ /dev/null @@ -1,386 +0,0 @@ -/* altairz80_hdsk.c: simulated hard disk device to increase capacity - - Copyright (c) 2002-2003, Peter Schorn - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - PETER SCHORN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. -*/ - -#include "altairz80_defs.h" - -#define UNIT_V_HDSKWLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_HDSKWLK (1 << UNIT_V_HDSKWLK) -#define UNIT_V_HDSK_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_HDSK_VERBOSE (1 << UNIT_V_HDSK_VERBOSE) -#define HDSK_SECTOR_SIZE 128 /* size of sector */ -#define HDSK_SECTORS_PER_TRACK 32 /* sectors per track */ -#define HDS_MAX_TRACKS 2048 /* number of tracks */ -#define HDSK_TRACK_SIZE (HDSK_SECTOR_SIZE * HDSK_SECTORS_PER_TRACK) -#define HDSK_CAPACITY (HDSK_TRACK_SIZE * HDS_MAX_TRACKS) -#define HDSK_NUMBER 8 /* number of hard disks */ -#define CPM_OK 0 /* indicates to CP/M everything ok */ -#define CPM_ERROR 1 /* indicates to CP/M an error condition */ -#define CPM_EMPTY 0xe5 /* default value for non-existing bytes */ -#define hdsk_none 0 -#define hdsk_reset 1 -#define hdsk_read 2 -#define hdsk_write 3 -#define hdsk_boot_address 0x5c00 - -extern char messageBuffer[]; -extern int32 PCX; -extern UNIT cpu_unit; -extern uint8 M[MAXMEMSIZE][MAXBANKS]; -extern int32 saved_PC; - -extern int32 install_bootrom(void); -extern void printMessage(void); -extern void PutBYTEBasic(const uint32 Addr, const uint32 Bank, const uint32 Value); -extern void PutBYTEWrapper(register uint32 Addr, register uint32 Value); -extern void protect(const int32 l, const int32 h); -extern uint8 GetBYTEWrapper(register uint32 Addr); -extern int32 bootrom[bootrom_size]; - -static t_stat hdsk_svc(UNIT *uptr); -static t_stat hdsk_boot(int32 unitno, DEVICE *dptr); -static int32 hdsk_hasVerbose(void); -int32 hdsk_io(const int32 port, const int32 io, const int32 data); -static int32 hdsk_in(const int32 port); -static int32 hdsk_out(const int32 data); -static int32 checkParameters(void); -static int32 doSeek(void); -static int32 doRead(void); -static int32 doWrite(void); - -static int32 hdskLastCommand = hdsk_none; -static int32 hdskCommandPosition = 0; -static int32 selectedDisk; -static int32 selectedSector; -static int32 selectedTrack; -static int32 selectedDMA; -static int32 hdskTrace; - -static UNIT hdsk_unit[] = { - { UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) } }; - -static REG hdsk_reg[] = { - { DRDATA (HDCMD, hdskLastCommand, 32), REG_RO }, - { DRDATA (HDPOS, hdskCommandPosition, 32), REG_RO }, - { DRDATA (HDDSK, selectedDisk, 32), REG_RO }, - { DRDATA (HDSEC, selectedSector, 32), REG_RO }, - { DRDATA (HDTRK, selectedTrack, 32), REG_RO }, - { DRDATA (HDDMA, selectedDMA, 32), REG_RO }, - { DRDATA (HDTRACE, hdskTrace, 8), }, - { NULL } }; - -static MTAB hdsk_mod[] = { - { UNIT_HDSKWLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_HDSKWLK, UNIT_HDSKWLK, "write locked", "LOCKED", NULL }, - /* quiet, no warning messages */ - { UNIT_HDSK_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_HDSK_VERBOSE, UNIT_HDSK_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { 0 } }; - -DEVICE hdsk_dev = { - "HDSK", hdsk_unit, hdsk_reg, hdsk_mod, - 8, 10, 31, 1, 8, 8, - NULL, NULL, NULL, - &hdsk_boot, NULL, NULL, NULL, 0, NULL, NULL }; - -static t_stat hdsk_svc(UNIT *uptr) { - return SCPE_OK; -} - -static const int32 hdskBoot[bootrom_size] = { - 0xf3, 0x06, 0x80, 0x3e, 0x0e, 0xd3, 0xfe, 0x05, /* 5c00-5c07 */ - 0xc2, 0x05, 0x5c, 0x3e, 0x16, 0xd3, 0xfe, 0x3e, /* 5c08-5c0f */ - 0x12, 0xd3, 0xfe, 0xdb, 0xfe, 0xb7, 0xca, 0x20, /* 5c10-5c17 */ - 0x5c, 0x3e, 0x0c, 0xd3, 0xfe, 0xaf, 0xd3, 0xfe, /* 5c18-5c1f */ - 0x06, 0x20, 0x3e, 0x01, 0xd3, 0xfd, 0x05, 0xc2, /* 5c20-5c27 */ - 0x24, 0x5c, 0x11, 0x08, 0x00, 0x21, 0x00, 0x00, /* 5c28-5c2f */ - 0x0e, 0xb8, 0x3e, 0x02, 0xd3, 0xfd, 0x3a, 0x37, /* 5c30-5c37 */ - 0xff, 0xd6, 0x08, 0xd3, 0xfd, 0x7b, 0xd3, 0xfd, /* 5c38-5c3f */ - 0x7a, 0xd3, 0xfd, 0xaf, 0xd3, 0xfd, 0x7d, 0xd3, /* 5c40-5c47 */ - 0xfd, 0x7c, 0xd3, 0xfd, 0xdb, 0xfd, 0xb7, 0xca, /* 5c48-5c4f */ - 0x53, 0x5c, 0x76, 0x79, 0x0e, 0x80, 0x09, 0x4f, /* 5c50-5c57 */ - 0x0d, 0xc2, 0x60, 0x5c, 0xfb, 0xc3, 0x00, 0x00, /* 5c58-5c5f */ - 0x1c, 0x1c, 0x7b, 0xfe, 0x20, 0xca, 0x73, 0x5c, /* 5c60-5c67 */ - 0xfe, 0x21, 0xc2, 0x32, 0x5c, 0x1e, 0x00, 0x14, /* 5c68-5c6f */ - 0xc3, 0x32, 0x5c, 0x1e, 0x01, 0xc3, 0x32, 0x5c, /* 5c70-5c77 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5c78-5c7f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5c80-5c87 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5c88-5c8f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5c90-5c97 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5c98-5c9f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5ca0-5ca7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5ca8-5caf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cb0-5cb7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cb8-5cbf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cc0-5cc7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cc8-5ccf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cd0-5cd7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cd8-5cdf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5ce0-5ce7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5ce8-5cef */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cf0-5cf7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cf8-5cff */ -}; - -static t_stat hdsk_boot(int32 unitno, DEVICE *dptr) { - int32 i; - if (MEMSIZE < 24*KB) { - printf("Need at least 24KB RAM to boot from hard disk.\n"); - return SCPE_ARG; - } - if (cpu_unit.flags & (UNIT_ALTAIRROM | UNIT_BANKED)) { - if (install_bootrom()) { - printf("ALTAIR boot ROM installed.\n"); - } - /* check whether we are really modifying an LD A,<> instruction */ - if (bootrom[unitNoOffset1 - 1] == LDAInstruction) { - bootrom[unitNoOffset1] = (unitno + NUM_OF_DSK) & 0xff; /* LD A, */ - } - else { /* Attempt to modify non LD A,<> instructions is refused. */ - printf("Incorrect boot ROM offset detected.\n"); - return SCPE_IERR; - } - } - for (i = 0; i < bootrom_size; i++) { - PutBYTEBasic(i + hdsk_boot_address, 0, hdskBoot[i] & 0xff); - } - saved_PC = hdsk_boot_address; - protect(hdsk_boot_address, hdsk_boot_address + bootrom_size - 1); - return SCPE_OK; -} - -/* returns TRUE iff there exists a disk with VERBOSE */ -static int32 hdsk_hasVerbose(void) { - int32 i; - for (i = 0; i < HDSK_NUMBER; i++) { - if (((hdsk_dev.units + i) -> flags) & UNIT_HDSK_VERBOSE) { - return TRUE; - } - } - return FALSE; -} - -/* The hard disk port is 0xfd. It understands the following commands. - -1. reset - ld b,32 - ld a,hdsk_reset -l out (0fdh),a - dec b - jp nz,l - -2. read / write - ; parameter block - cmd: db hdsk_read or hdsk_write - hd: db 0 ; 0 .. 7, defines hard disk to be used - sector: db 0 ; 0 .. 31, defines sector - track: dw 0 ; 0 .. 2047, defines track - dma: dw 0 ; defines where result is placed in memory - - ; routine to execute - ld b,7 ; size of parameter block - ld hl,cmd ; start address of parameter block -l ld a,(hl) ; get byte of parameter block - out (0fdh),a ; send it to port - inc hl ; point to next byte - dec b ; decrement counter - jp nz,l ; again, if not done - in a,(0fdh) ; get result code - -*/ - -/* check the parameters and return TRUE iff parameters are correct or have been repaired */ -static int32 checkParameters(void) { - int32 currentFlag; - if ((selectedDisk < 0) || (selectedDisk >= HDSK_NUMBER)) { - if (hdsk_hasVerbose()) { - message2("HDSK%d does not exist, will use HDSK0 instead.\n", selectedDisk); - } - selectedDisk = 0; - } - currentFlag = (hdsk_dev.units + selectedDisk) -> flags; - if ((currentFlag & UNIT_ATT) == 0) { - if (currentFlag & UNIT_HDSK_VERBOSE) { - message2("HDSK%d is not attached.\n", selectedDisk); - } - return FALSE; /* cannot read or write */ - } - if ((selectedSector < 0) || (selectedSector >= HDSK_SECTORS_PER_TRACK)) { - if (currentFlag & UNIT_HDSK_VERBOSE) { - message4("HDSK%d: 0 <= Sector=%02d < %d violated, will use 0 instead.\n", - selectedDisk, selectedSector, HDSK_SECTORS_PER_TRACK); - } - selectedSector = 0; - } - if ((selectedTrack < 0) || (selectedTrack >= HDS_MAX_TRACKS)) { - if (currentFlag & UNIT_HDSK_VERBOSE) { - message4("HDSK%d: 0 <= Track=%04d < %04d violated, will use 0 instead.\n", - selectedDisk, selectedTrack, HDS_MAX_TRACKS); - } - selectedTrack = 0; - } - selectedDMA &= ADDRMASK; - if (hdskTrace) { - message6("%s HDSK%d Sector=%02d Track=%04d DMA=%04x\n", - (hdskLastCommand == hdsk_read) ? "Read" : "Write", - selectedDisk, selectedSector, selectedTrack, selectedDMA); - } - return TRUE; -} - -static int32 doSeek(void) { - UNIT *uptr = hdsk_dev.units + selectedDisk; - if (fseek(uptr -> fileref, - HDSK_TRACK_SIZE * selectedTrack + HDSK_SECTOR_SIZE * selectedSector, SEEK_SET)) { - if ((uptr -> flags) & UNIT_HDSK_VERBOSE) { - message4("Could not access HDSK%d Sector=%02d Track=%04d.\n", - selectedDisk, selectedSector, selectedTrack); - } - return CPM_ERROR; - } - else { - return CPM_OK; - } -} - -static int32 doRead(void) { - int32 i; - uint8 hdskbuf[HDSK_SECTOR_SIZE]; /* data buffer */ - UNIT *uptr = hdsk_dev.units + selectedDisk; - if (doSeek()) { - return CPM_ERROR; - } - if (fread(hdskbuf, HDSK_SECTOR_SIZE, 1, uptr -> fileref) != 1) { - for (i = 0; i < HDSK_SECTOR_SIZE; i++) { - hdskbuf[i] = CPM_EMPTY; - } - if ((uptr -> flags) & UNIT_HDSK_VERBOSE) { - message4("Could not read HDSK%d Sector=%02d Track=%04d.\n", - selectedDisk, selectedSector, selectedTrack); - } - return CPM_OK; /* allows the creation of empty hard disks */ - } - for (i = 0; i < HDSK_SECTOR_SIZE; i++) { - PutBYTEWrapper(selectedDMA + i, hdskbuf[i]); - } - return CPM_OK; -} - -static int32 doWrite(void) { - int32 i; - uint8 hdskbuf[HDSK_SECTOR_SIZE]; /* data buffer */ - UNIT *uptr = hdsk_dev.units + selectedDisk; - if (((uptr -> flags) & UNIT_HDSKWLK) == 0) { /* write enabled */ - if (doSeek()) { - return CPM_ERROR; - } - for (i = 0; i < HDSK_SECTOR_SIZE; i++) { - hdskbuf[i] = GetBYTEWrapper(selectedDMA + i); - } - if (fwrite(hdskbuf, HDSK_SECTOR_SIZE, 1, uptr -> fileref) != 1) { - if ((uptr -> flags) & UNIT_HDSK_VERBOSE) { - message4("Could not write HDSK%d Sector=%02d Track=%04d.\n", - selectedDisk, selectedSector, selectedTrack); - } - return CPM_ERROR; - } - } - else { - if ((uptr -> flags) & UNIT_HDSK_VERBOSE) { - message4("Could not write to locked HDSK%d Sector=%02d Track=%04d.\n", - selectedDisk, selectedSector, selectedTrack); - } - return CPM_ERROR; - } - return CPM_OK; -} - -static int32 hdsk_in(const int32 port) { - int32 result; - if ((hdskCommandPosition == 6) && ((hdskLastCommand == hdsk_read) || (hdskLastCommand == hdsk_write))) { - result = checkParameters() ? ((hdskLastCommand == hdsk_read) ? doRead() : doWrite()) : CPM_ERROR; - hdskLastCommand = hdsk_none; - hdskCommandPosition = 0; - return result; - } - else if (hdsk_hasVerbose()) { - message4("Illegal IN command detected (port=%03xh, cmd=%d, pos=%d).\n", - port, hdskLastCommand, hdskCommandPosition); - } - return CPM_OK; -} - -static int32 hdsk_out(const int32 data) { - switch(hdskLastCommand) { - case hdsk_read: - case hdsk_write: - switch(hdskCommandPosition) { - case 0: - selectedDisk = data; - hdskCommandPosition++; - break; - case 1: - selectedSector = data; - hdskCommandPosition++; - break; - case 2: - selectedTrack = data; - hdskCommandPosition++; - break; - case 3: - selectedTrack += (data << 8); - hdskCommandPosition++; - break; - case 4: - selectedDMA = data; - hdskCommandPosition++; - break; - case 5: - selectedDMA += (data << 8); - hdskCommandPosition++; - break; - default: - hdskLastCommand = hdsk_none; - hdskCommandPosition = 0; - } - break; - default: - hdskLastCommand = data; - hdskCommandPosition = 0; - } - return 0; /* ignored, since OUT */ -} - -int32 hdsk_io(const int32 port, const int32 io, const int32 data) { - return io == 0 ? hdsk_in(port) : hdsk_out(data); -} diff --git a/GRI/gri_cpu.c b/GRI/gri_cpu.c deleted file mode 100644 index f6166100..00000000 --- a/GRI/gri_cpu.c +++ /dev/null @@ -1,890 +0,0 @@ -/* gri_cpu.c: GRI-909 CPU simulator - - Copyright (c) 2001-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - cpu GRI-909 CPU - - 14-Mar-03 RMS Fixed bug in SC queue tracking - - The system state for the GRI-909 is: - - AX<0:15> arithmetic input - AY<0:15> arithmetic input - BSW<0:15> byte swapper - BPK<0:15> byte packer - GR[0:5]<0:15> extended general registers - MSR<0:15> machine status register - TRP<0:15> trap register (subroutine return) - SC<0:14> sequence counter - - The GRI-909 has, nominally, just one instruction format: move. - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | source | op | destination | move - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <6:9> operation - - xx1x complement - 01xx add 1 - 10xx rotate left 1 - 11xx rotate right 1 - - In fact, certain of the source and destination operators have side - effects, yielding four additional instruction formats: function out, - skip on function, memory reference, and conditional jump. -*/ - -/* The function out format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 0 0 0 1 0| pulse | destination | function out - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The skip on function format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | source | skip |rv| 0 0 0 0 1 0| skip function - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The memory reference format is (src and/or dst = 006): - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | source | op | mode| destination | memory ref - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | address or immediate | - +-----------------------------------------------+ - - <6:9> operation - - xx0x direct, ea = M[SC+1] - xx1x immediate, ea = SC+1 - xxx1 indirect, M[ea] = M[ea]+1, then ea = M[ea] - 01xx add 1 - 10xx rotate left 1 - 11xx rotate right 1 - - The conditional jump format is (src != 006): - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | source | cond|rv|df| 0 0 0 0 1 1| cond jump - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | jump address | - +-----------------------------------------------+ - - <6:9> operation - - xxx0 direct, ea = M[SC+1] - xxx1 indirect, ea = M[SC+1], M[ea] = M[ea]+1, - then ea = M[ea] - xx1x reverse conditional sense - x1xx jump if src == 0 - 1xxx jump if src < 0 -*/ - -/* This routine is the instruction decode routine for the GRI-909. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - breakpoint encountered - unknown source or destination and STOP_OPR flag set - I/O error in I/O simulator - - 2. Interrupts. The interrupt structure is kept in two parallel variables: - - dev_done device done flags - ISR interrupt status register (enables) - - In addition, there is a master interrupt enable, and a one cycle - interrupt defer, both kept in dev_done. - - 3. Non-existent memory. On the GRI-909, reads to non-existent memory - return zero, and writes are ignored. In the simulator, the - largest possible memory is instantiated and initialized to zero. - Thus, only writes need be checked against actual memory size. - - 4. Adding I/O devices. These modules must be modified: - - gri_defs.h add interrupt request definition - gri_cpu.c add dev_tab table entry - gri_sys.c add sim_devices table entry -*/ - -#include "gri_defs.h" - -#define SCQ_SIZE 64 /* must be 2**n */ -#define SCQ_MASK (SCQ_SIZE - 1) -#define SCQ_ENTRY scq[scq_p = (scq_p - 1) & SCQ_MASK] = SC -#define UNIT_V_NOEAO (UNIT_V_UF) /* EAO absent */ -#define UNIT_NOEAO (1 << UNIT_V_NOEAO) -#define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy mask */ -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -uint16 M[MAXMEMSIZE] = { 0 }; /* memory */ -uint32 SC; /* sequence cntr */ -uint32 AX, AY, AO; /* arithmetic unit */ -uint32 IR; /* instr reg */ -uint32 MA; /* memory addr */ -uint32 TRP; /* subr return */ -uint32 MSR; /* machine status */ -uint32 ISR; /* interrupt status */ -uint32 BSW, BPK; /* byte swap, pack */ -uint32 GR[6]; /* extended general regs */ -uint32 SWR; /* switch reg */ -uint32 DR; /* display register */ -uint32 thwh = 0; /* thumbwheel */ -uint32 dev_done = 0; /* device flags */ -uint32 bkp = 0; /* bkpt pending */ -uint32 stop_opr = 1; /* stop ill operator */ -int16 scq[SCQ_SIZE] = { 0 }; /* PC queue */ -int32 scq_p = 0; /* PC queue ptr */ -REG *scq_r = NULL; /* PC queue reg ptr */ - -extern int32 sim_interval; -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat bus_op (uint32 src, uint32 op, uint32 dst); - -/* Dispatch tables for source, dest, function out, skip on function */ - -uint32 no_rd (uint32 src); -t_stat no_wr (uint32 dst, uint32 val); -t_stat no_fo (uint32 op); -uint32 no_sf (uint32 op); -uint32 zero_rd (uint32 src); -t_stat zero_wr (uint32 dst, uint32 val); -t_stat zero_fo (uint32 op); -uint32 zero_sf (uint32 op); -uint32 ir_rd (uint32 op); -t_stat ir_fo (uint32 op); -uint32 trp_rd (uint32 src); -uint32 isr_rd (uint32 src); -t_stat isr_wr (uint32 dst, uint32 val); -t_stat isr_fo (uint32 op); -uint32 isr_sf (uint32 op); -uint32 ma_rd (uint32 src); -uint32 mem_rd (uint32 src); -t_stat mem_wr (uint32 dst, uint32 val); -uint32 sc_rd (uint32 src); -t_stat sc_wr (uint32 dst, uint32 val); -uint32 swr_rd (uint32 src); -uint32 ax_rd (uint32 src); -t_stat ax_wr (uint32 dst, uint32 val); -uint32 ay_rd (uint32 src); -t_stat ay_wr (uint32 dst, uint32 val); -uint32 ao_rd (uint32 src); -t_stat ao_fo (uint32 op); -uint32 ao_sf (uint32 op); -uint32 ao_update (void); -t_stat eao_fo (uint32 op); -uint32 msr_rd (uint32 src); -t_stat msr_wr (uint32 dst, uint32 val); -uint32 bsw_rd (uint32 src); -t_stat bsw_wr (uint32 dst, uint32 val); -uint32 bpk_rd (uint32 src); -t_stat bpk_wr (uint32 dst, uint32 val); -uint32 gr_rd (uint32 src); -t_stat gr_wr (uint32 dst, uint32 val); - -extern t_stat rtc_fo (uint32 op); -extern uint32 rtc_sf (uint32 op); -extern uint32 hsrp_rd (uint32 src); -extern t_stat hsrp_wr (uint32 dst, uint32 val); -extern t_stat hsrp_fo (uint32 op); -extern uint32 hsrp_sf (uint32 op); -extern uint32 tty_rd (uint32 src); -extern t_stat tty_wr (uint32 dst, uint32 val); -extern t_stat tty_fo (uint32 op); -extern uint32 tty_sf (uint32 op); - -struct gdev dev_tab[64] = { - { &zero_rd, &zero_wr, &zero_fo, &zero_sf }, /* 00: zero */ - { &ir_rd, &zero_wr, &ir_fo, &zero_sf }, /* ir */ - { &no_rd, &no_wr, &no_fo, &no_sf }, /* fo/sf */ - { &trp_rd, &no_wr, &zero_fo, &zero_sf }, /* trp */ - { &isr_rd, &isr_wr, &isr_fo, &isr_sf }, /* isr */ - { &ma_rd, &no_wr, &no_fo, &no_sf }, /* MA */ - { &mem_rd, &mem_wr, &zero_fo, &zero_sf }, /* memory */ - { &sc_rd, &sc_wr, &zero_fo, &zero_sf }, /* sc */ - { &swr_rd, &no_wr, &no_fo, &no_sf }, /* swr */ - { &ax_rd, &ax_wr, &zero_fo, &zero_sf }, /* ax */ - { &ay_rd, &ay_wr, &zero_fo, &zero_sf }, /* ay */ - { &ao_rd, &zero_wr, &ao_fo, &ao_sf }, /* ao */ - { &zero_rd, &zero_wr, &eao_fo, &zero_sf }, /* eao */ - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &msr_rd, &msr_wr, &zero_fo, &zero_sf }, /* msr */ - { &no_rd, &no_wr, &no_fo, &no_sf }, /* 20 */ - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &bsw_rd, &bsw_wr, &no_fo, &no_sf }, /* bsw */ - { &bpk_rd, &bpk_wr, &no_fo, &no_sf }, /* bpk */ - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* 30: gr1 */ - { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* gr2 */ - { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* gr3 */ - { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* gr4 */ - { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* gr5 */ - { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* gr6 */ - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, /* 40 */ - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, /* 50 */ - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, /* 60 */ - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, /* 70 */ - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &zero_rd, &zero_wr, &rtc_fo, &rtc_sf }, /* rtc */ - { &hsrp_rd, &hsrp_wr, &hsrp_fo, &hsrp_sf }, /* hsrp */ - { &tty_rd, &tty_wr, &tty_fo, &tty_sf } }; /* tty */ - -static const int32 vec_map[16] = { - VEC_TTO, VEC_TTI, VEC_HSP, VEC_HSR, - -1, -1, -1, -1, - -1, -1, -1, VEC_RTC, - -1, -1, -1, -1 }; - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifiers list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, MAXMEMSIZE) }; - -REG cpu_reg[] = { - { ORDATA (SC, SC, 15) }, - { ORDATA (AX, AX, 16) }, - { ORDATA (AY, AY, 16) }, - { ORDATA (AO, AO, 16), REG_RO }, - { ORDATA (TRP, TRP, 16) }, - { ORDATA (MSR, MSR, 16) }, - { ORDATA (ISR, ISR, 16) }, - { ORDATA (BSW, BSW, 16) }, - { ORDATA (BPK, BPK, 16) }, - { ORDATA (GR1, GR[0], 16) }, - { ORDATA (GR2, GR[1], 16) }, - { ORDATA (GR3, GR[2], 16) }, - { ORDATA (GR4, GR[3], 16) }, - { ORDATA (GR5, GR[4], 16) }, - { ORDATA (GR6, GR[5], 16) }, - { FLDATA (BOV, MSR, MSR_V_BOV) }, - { FLDATA (L, MSR, MSR_V_L) }, - { GRDATA (FOA, MSR, 8, 2, MSR_V_FOA) }, - { FLDATA (AOV, MSR, MSR_V_AOV) }, - { ORDATA (IR, IR, 16), REG_RO }, - { ORDATA (MA, MA, 16), REG_RO }, - { ORDATA (SWR, SWR, 16) }, - { ORDATA (DR, DR, 16) }, - { ORDATA (THW, thwh, 6) }, - { ORDATA (IREQ, dev_done, INT_V_NODEF) }, - { FLDATA (ION, dev_done, INT_V_ON) }, - { FLDATA (INODEF, dev_done, INT_V_NODEF) }, - { FLDATA (BKP, bkp, 0) }, - { BRDATA (SCQ, scq, 8, 15, SCQ_SIZE), REG_RO + REG_CIRC }, - { ORDATA (SCQP, scq_p, 6), REG_HRO }, - { FLDATA (STOP_OPR, stop_opr, 0) }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_NOEAO, UNIT_NOEAO, "no EAO", "NOEAO", NULL }, - { UNIT_NOEAO, 0, "EAO", "EAO", NULL }, - { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, - { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, - { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size }, - { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, - { UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size }, - { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size }, - { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size }, - { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, 15, 1, 8, 16, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -t_stat sim_instr (void) -{ -uint32 src, dst, op, t, jmp; -t_stat reason; -extern UNIT rtc_unit; - -/* Restore register state */ - -SC = SC & AMASK; /* load local PC */ -reason = 0; -AO = ao_update (); /* update AO */ -sim_rtc_init (rtc_unit.wait); /* init calibration */ - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ - -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } - -if (bkp) { /* breakpoint? */ - bkp = 0; /* clear request */ - dev_done = dev_done & ~INT_ON; /* int off */ - M[VEC_BKP] = SC; /* save SC */ - SC = VEC_BKP + 1; } /* new SC */ - -else if ((dev_done & (INT_PENDING | ISR)) > (INT_PENDING)) { /* intr? */ - int32 i, vec; - t = dev_done & ISR; /* find hi pri */ - for (i = 15; i >= 0; i--) { - if ((t >> i) & 1) break; } - if ((i < 0) || ((vec = vec_map[i]) < 0)) { /* undefined? */ - reason = STOP_ILLINT; /* stop */ - break; } - dev_done = dev_done & ~INT_ON; /* int off */ - M[vec] = SC; /* save SC */ - SC = vec + 1; /* new SC */ - continue; } - -if (sim_brk_summ && sim_brk_test (SC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - -MA = SC; /* set mem addr */ -IR = M[MA]; /* fetch instr */ -dev_done = dev_done | INT_NODEF; /* clr ion defer */ -sim_interval = sim_interval - 1; - -/* Decode instruction types */ - -src = I_GETSRC (IR); /* src unit */ -dst = I_GETDST (IR); /* dst unit */ -op = I_GETOP (IR); /* bus op */ - -if (src == U_FSK) { /* func out? */ - reason = dev_tab[dst].FO (op); /* send function */ - SC = (SC + 1) & AMASK; } /* incr SC */ - -else if (dst == U_FSK) { /* skip func? */ - t = dev_tab[src].SF (op & ~1); /* issue SF */ - reason = t >> SF_V_REASON; - if ((t ^ op) & 1) SC = SC + 2; /* skip? */ - SC = (SC + 1) & AMASK; } /* incr SC */ - -else if ((src != U_MEM) && (dst == U_TRP)) { /* cond jump */ - t = dev_tab[src].Src (src); /* get source */ - switch (op >> 1) { /* case on jump */ - case 00: /* never */ - jmp = 0; - break; - case 01: /* always */ - jmp = 1; - break; - case 02: /* src == 0 */ - jmp = (t == 0); - break; - case 03: /* src != 0 */ - jmp = (t != 0); - break; - case 04: /* src < 0 */ - jmp = (t >= SIGN); - break; - case 05: /* src >= 0 */ - jmp = (t < SIGN); - break; - case 06: /* src <= 0 */ - jmp = (t == 0) || (t & SIGN); - break; - case 07: /* src > 0 */ - jmp = (t != 0) && !(t & SIGN); - break; } - if (jmp) { /* jump taken? */ - SCQ_ENTRY; /* save SC */ - SC = (SC + 1) & AMASK; /* incr SC once */ - MA = M[SC]; /* get jump addr */ - if (op & TRP_DEF) { /* defer? */ - t = (M[MA] + 1) & DMASK; /* autoinc */ - if (MEM_ADDR_OK (MA)) M[MA] = t; - MA = t & AMASK; } /* ind addr */ - TRP = SC; /* save SC */ - SC = MA; } /* load new SC */ - else SC = (SC + 2) & AMASK; } /* incr SC twice */ - -else if ((src != U_MEM) && (dst != U_MEM)) { /* reg-reg? */ - reason = bus_op (src, op, dst); /* xmt and modify */ - SC = (SC + 1) & AMASK; } /* incr SC */ - -/* Memory reference. The second SC increment occurs after the first - execution cycle. For direct, defer, and immediate defer, this is - after the first memory read and before the bus transfer; but for - immediate, it is after the bus transfer. -*/ - -else { SC = (SC + 1) & AMASK; /* incr SC */ - switch (op & MEM_MOD) { /* case on addr mode */ - case MEM_DIR: /* direct */ - MA = M[SC] & AMASK; /* get address */ - SC = (SC + 1) & AMASK; /* incr SC again */ - reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */ - break; - case MEM_DEF: /* defer */ - MA = M[SC] & AMASK; /* get ind addr */ - SC = (SC + 1) & AMASK; /* incr SC again */ - t = (M[MA] + 1) & DMASK; /* autoinc */ - if (MEM_ADDR_OK (MA)) M[MA] = t; - MA = t & AMASK; /* ind addr */ - reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */ - break; - case MEM_IMM: /* immediate */ - MA = SC; /* eff addr */ - reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */ - SC = (SC + 1) & AMASK; /* incr SC again */ - break; - case MEM_IDF: /* immediate defer */ - MA = SC; /* get ind addr */ - t = (M[MA] + 1) & DMASK; /* autoinc */ - if (MEM_ADDR_OK (MA)) M[MA] = t; - MA = t & AMASK; /* ind addr */ - SC = (SC + 1) & AMASK; /* incr SC again */ - reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */ - break; } /* end switch */ - } /* end mem ref */ -} /* end while */ - -/* Simulation halted */ - -AO = ao_update (); /* update AO */ -scq_r->qptr = scq_p; /* update sc q ptr */ -return reason; -} - -/* Bus operations */ - -t_stat bus_op (uint32 src, uint32 op, uint32 dst) -{ -uint32 t, old_t; - -t = dev_tab[src].Src (src); /* get src */ -if (op & BUS_COM) t = t ^ DMASK; /* complement? */ -switch (op & BUS_FNC) { /* case op */ -case BUS_P1: /* plus 1 */ - t = t + 1; /* do add */ - if (t & CBIT) MSR = MSR | MSR_BOV; /* set cry out */ - else MSR = MSR & ~MSR_BOV; - break; -case BUS_L1: /* left 1 */ - t = (t << 1) | ((MSR & MSR_L)? 1: 0); /* rotate */ - if (t & CBIT) MSR = MSR | MSR_L; /* set link out */ - else MSR = MSR & ~MSR_L; - break; -case BUS_R1: /* right 1 */ - old_t = t; - t = (t >> 1) | ((MSR & MSR_L)? SIGN: 0); /* rotate */ - if (old_t & 1) MSR = MSR | MSR_L; /* set link out */ - else MSR = MSR & ~MSR_L; - break; } /* end case op */ -if (dst == thwh) DR = t & DMASK; /* display dst? */ -return dev_tab[dst].Dst (dst, t & DMASK); /* store dst */ -} - -/* Non-existent device */ - -uint32 no_rd (uint32 src) -{ -return 0; -} - -t_stat no_wr (uint32 dst, uint32 dat) -{ -return stop_opr; -} - -t_stat no_fo (uint32 fnc) -{ -return stop_opr; -} - -uint32 no_sf (uint32 fnc) -{ -return (stop_opr << SF_V_REASON); -} - -/* Zero device */ - -uint32 zero_rd (uint32 src) -{ -return 0; -} - -t_stat zero_wr (uint32 dst, uint32 val) -{ -return SCPE_OK; -} - -t_stat zero_fo (uint32 op) -{ -switch (op & 3) { /* FOM link */ -case 1: /* CLL */ - MSR = MSR & ~MSR_L; - break; -case 2: /* STL */ - MSR = MSR | MSR_L; - break; -case 3: /* CML */ - MSR = MSR ^ MSR_L; - break; } -if (op & 4) return STOP_HALT; /* HALT */ -return SCPE_OK; -} - -uint32 zero_sf (uint32 op) -{ -if ((op & 010) || /* power always ok */ - ((op & 4) && (MSR & MSR_L)) || /* link set? */ - ((op & 2) && (MSR & MSR_BOV))) return 1; /* BOV set? */ -return 0; -} - -/* Instruction register (01) */ - -uint32 ir_rd (uint32 src) -{ -return IR; -} - -t_stat ir_fo (uint32 op) -{ -if (op & 2) bkp = 1; -return SCPE_OK; -} - -/* Trap register (03) */ - -uint32 trp_rd (uint32 src) -{ -return TRP; -} - -/* Interrupt status register (04) */ - -uint32 isr_rd (uint32 src) -{ -return ISR; -} - -t_stat isr_wr (uint32 dst, uint32 dat) -{ -ISR = dat; -return SCPE_OK; -} - -t_stat isr_fo (uint32 op) -{ -if (op & ISR_ON) dev_done = (dev_done | INT_ON) & ~INT_NODEF; -if (op & ISR_OFF) dev_done = dev_done & ~INT_ON; -return SCPE_OK; -} - -uint32 isr_sf (uint32 op) -{ -return 0; -} - -/* Memory address (05) */ - -uint32 ma_rd (uint32 src) -{ -return MA; -} - -/* Memory (06) */ - -uint32 mem_rd (uint32 src) -{ -return M[MA]; -} - -t_stat mem_wr (uint32 dst, uint32 dat) -{ - -if (MEM_ADDR_OK (MA)) M[MA] = dat; -return SCPE_OK; -} - -/* Sequence counter (07) */ - -uint32 sc_rd (uint32 src) -{ -return SC; -} - -t_stat sc_wr (uint32 dst, uint32 dat) -{ -SCQ_ENTRY; -SC = dat & AMASK; -return SCPE_OK; -} - -/* Switch register (10) */ - -uint32 swr_rd (uint32 src) -{ -return SWR; -} - -/* Machine status register (17) */ - -uint32 msr_rd (uint32 src) -{ -return MSR; -} - -t_stat msr_wr (uint32 src, uint32 dat) -{ -MSR = dat; /* new MSR */ -ao_update (); /* update AOV */ -return SCPE_OK; -} - -/* Arithmetic operators (11:14) */ - -uint32 ao_update (void) -{ -int32 t; -int32 af = MSR_GET_FOA (MSR); - -switch (af) { -case AO_ADD: - t = (AX + AY) & DMASK; /* add */ - break; -case AO_AND: - t = AX & AY; /* and */ - break; -case AO_XOR: /* xor */ - t = AX ^ AY; - break; -case AO_IOR: - t = AX | AY; /* or */ - break; } -if ((AX + AY) & CBIT) MSR = MSR | MSR_AOV; /* always calc AOV */ -else MSR = MSR & ~MSR_AOV; -return t; -} - -uint32 ax_rd (uint32 src) -{ -return AX; -} - -t_stat ax_wr (uint32 dst, uint32 dat) -{ -AX = dat; -return SCPE_OK; -} - -uint32 ay_rd (uint32 src) -{ -return AY; -} - -t_stat ay_wr (uint32 dst, uint32 dat) -{ -AY = dat; -return SCPE_OK; -} - -uint32 ao_rd (uint32 src) -{ -AO = ao_update (); -return AO; -} - -t_stat ao_fo (uint32 op) -{ -uint32 t = OP_GET_FOA (op); /* get func */ -MSR = MSR_PUT_FOA (MSR, t); /* store in MSR */ -ao_update (); /* update AOV */ -return SCPE_OK; -} - -t_stat eao_fo (uint32 op) -{ -uint32 t; - -if (cpu_unit.flags & UNIT_NOEAO) return stop_opr; /* EAO installed? */ -if (op == EAO_MUL) { /* mul? */ - t = AX * AY; /* AX * AY */ - AX = (t >> 16) & DMASK; /* to AX'GR1 */ - GR[0] = t & DMASK; } -if (op == EAO_DIV) { /* div? */ - if (AY && (AX < AY)) { - t = (AX << 16) | GR[0]; /* AX'GR1 / AY */ - GR[0] = t / AY; /* quo to GR1 */ - AX = t % AY; } /* rem to AX */ - } -return SCPE_OK; -} - -uint32 ao_sf (uint32 op) -{ -if (((op & 2) && (MSR & MSR_AOV)) || /* arith carry? */ - ((op & 4) && (SIGN & /* arith overflow? */ - ((AX ^ (AX + AY)) & (~AX ^ AY))))) return 1; -return 0; -} - -/* Byte swapper (24) */ - -uint32 bsw_rd (uint32 src) -{ -return BSW; -} - -t_stat bsw_wr (uint32 dst, uint32 val) -{ -BSW = ((val >> 8) & 0377) | ((val & 0377) << 8); -return SCPE_OK; -} - -/* Byte packer (25) */ - -uint32 bpk_rd (uint32 src) -{ -return BPK; -} - -t_stat bpk_wr (uint32 dst, uint32 val) -{ -BPK = ((BPK & 0377) << 8) | (val & 0377); -return SCPE_OK; -} - -/* General registers (30:35) */ - -uint32 gr_rd (uint32 src) -{ -return GR[src - U_GR]; -} - -t_stat gr_wr (uint32 dst, uint32 dat) -{ -GR[dst - U_GR] = dat; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -int32 i; - -AX = AY = AO = 0; -TRP = 0; -ISR = 0; -MSR = 0; -MA = IR = 0; -BSW = BPK = 0; -for (i = 0; i < 6; i++) GR[i] = 0; -dev_done = dev_done & ~INT_PENDING; -scq_r = find_reg ("SCQ", NULL, dptr); -if (scq_r) scq_r->qptr = 0; -else return SCPE_IERR; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & DMASK; -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -M[addr] = val & DMASK; -return SCPE_OK; -} - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; -if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_OK; -MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; -return SCPE_OK; -} diff --git a/GRI/gri_defs.h b/GRI/gri_defs.h deleted file mode 100644 index 2888bed1..00000000 --- a/GRI/gri_defs.h +++ /dev/null @@ -1,221 +0,0 @@ -/* gri_defs.h: GRI-909 simulator definitions - - Copyright (c) 2001-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 25-Apr-03 RMS Revised for extended file support - 19-Sep-02 RMS Fixed declarations in gdev structure - - There are several discrepancies between the original GRI-909 Reference - Manual of 1969 and the only surviving code sample, the MIT Crystal Growing - System of 1972: - - 1. Ref Manual documents two GR's at codes 26-27; MITCS documents six GR's - at 30-35. - 2. Ref Manual documents only unsigned overflow (carry) for arithmetic - operator; MITCS uses both unsigned overflow (AOV) and signed overflow - (SOV). - 3. Ref Manual documents a ROM-subroutine multiply operator and mentions - but does not document a "fast multiply"; MITCS uses an extended - arithmetic operator with multiply, divide, and shifts. The behavior - of the extended arithmetic operator can only be inferred partially; - the shifts are never used, and there is no indication of how divide - overflow is handled. - - The simulator follows the code in these instances. - - Outstanding issues: - - 1. Is there any interaction between the byte swapper and the byte packer? - 2. Is SOV testable even if the FOA is not ADD? - 3. How does the EAO handle divide overflow? - 4. What are the other EAO functions beside multiply and divide? -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Simulator stop codes */ - -#define STOP_DEV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_ILLINT 4 /* illegal intr */ - -/* Memory */ - -#define MAXMEMSIZE 32768 /* max memory size */ -#define AMASK 077777 /* logical addr mask */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) - -/* Architectural constants */ - -#define SIGN 0100000 /* sign */ -#define DMASK 0177777 /* data mask */ -#define CBIT (DMASK + 1) /* carry bit */ - -/* Instruction format */ - -#define I_M_SRC 077 /* source */ -#define I_V_SRC 10 -#define I_GETSRC(x) (((x) >> I_V_SRC) & I_M_SRC) -#define I_M_OP 017 /* operator */ -#define I_V_OP 6 -#define I_GETOP(x) (((x) >> I_V_OP) & I_M_OP) -#define I_M_DST 077 /* destination */ -#define I_V_DST 0 -#define I_GETDST(x) (((x) >> I_V_DST) & I_M_DST) -#define SF_V_REASON 1 /* SF reason */ - -/* IO return */ - -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ - -/* Operators */ - -#define U_ZERO 000 /* zero */ -#define U_IR 001 /* instruction reg */ -#define U_FSK 002 /* func out/skip */ -#define U_TRP 003 /* trap */ -#define U_ISR 004 /* intr status */ -#define U_MA 005 /* mem addr */ -#define U_MEM 006 /* mem data */ -#define U_SC 007 /* seq counter */ -#define U_SWR 010 /* switch register */ -#define U_AX 011 /* arith in 1 */ -#define U_AY 012 /* arith in 2 */ -#define U_AO 013 /* arith out */ -#define U_EAO 014 /* ext arith */ -#define U_MSR 017 /* machine status */ -#define U_BSW 024 /* byte swap */ -#define U_BPK 025 /* byte pack */ -/* #define U_GR 026 /* dual general regs */ -#define U_GR 030 /* hex general regs */ -#define U_RTC 075 /* clock */ -#define U_HS 076 /* paper tape */ -#define U_TTY 077 /* console */ - -struct gdev { - uint32 (*Src)(uint32); /* source */ - t_stat (*Dst)(uint32, uint32); /* dest */ - t_stat (*FO)(uint32); /* func out */ - uint32 (*SF)(uint32); /* skip func */ -}; - -/* Trap (jump) */ - -#define TRP_DIR 00 /* direct */ -#define TRP_DEF 01 /* defer */ - -/* Interrupt status */ - -#define ISR_OFF 01 /* int off */ -#define ISR_ON 02 /* int on */ - -/* Bus modifiers */ - -#define BUS_COM 002 /* complement */ -#define BUS_FNC 014 /* function mask */ -#define BUS_P1 004 /* + 1 */ -#define BUS_L1 010 /* rotate left */ -#define BUS_R1 014 /* rotate right */ - -/* Memory address modes */ - -#define MEM_MOD 03 -#define MEM_DIR 00 /* direct */ -#define MEM_DEF 01 /* defer */ -#define MEM_IMM 02 /* immediate */ -#define MEM_IDF 03 /* immediate defer */ - -/* Arithmetic unit */ - -#define FO_V_FOA 8 /* arith func */ -#define FO_M_FOA 03 -#define OP_GET_FOA(x) (((x) >> (FO_V_FOA - I_V_OP)) & FO_M_FOA) -#define AO_ADD 00 /* add */ -#define AO_AND 01 /* and */ -#define AO_XOR 02 /* xor */ -#define AO_IOR 03 /* or */ -#define EAO_MUL 01 /* multiply */ -#define EAO_DIV 02 /* divide */ -#define EAO_ASR 03 /* arith rshft */ - -/* Machine status */ - -#define MSR_V_BOV 15 /* bus carry */ -#define MSR_BOV (1u << MSR_V_BOV) -#define MSR_V_L 14 /* bus link */ -#define MSR_L (1u << MSR_V_L) /* bus link */ -#define MSR_V_FOA 8 /* arith func */ -#define MSR_M_FOA 03 -#define MSR_V_AOV 0 /* arith carry */ -#define MSR_AOV (1u << MSR_V_AOV) -#define MSR_GET_FOA(x) (((x) >> MSR_V_FOA) & MSR_M_FOA) -#define MSR_PUT_FOA(x,n) (((x) & ~(MSR_M_FOA << MSR_V_FOA)) | \ - (((n) & MSR_M_FOA) << MSR_V_FOA)) - -/* Real time clock */ - -#define RTC_OFF 001 /* off */ -#define RTC_ON 002 /* clock on */ -#define RTC_OV 010 /* clock flag */ -#define RTC_CTR 0103 /* counter */ - -/* Terminal */ - -#define TTY_ORDY 002 /* output flag */ -#define TTY_IRDY 010 /* input flag */ - -/* Paper tape */ - -#define PT_STRT 001 /* start reader */ -#define PT_ORDY 002 /* output flag */ -#define PT_IRDY 010 /* input flag */ - -/* Interrupt masks (ISR) */ - -#define INT_V_TTO 0 /* console out */ -#define INT_V_TTI 1 /* console in */ -#define INT_V_HSP 2 /* paper tape punch */ -#define INT_V_HSR 3 /* paper tape reader */ -#define INT_V_RTC 11 /* clock */ -#define INT_V_NODEF 16 /* nodefer */ -#define INT_V_ON 17 /* enable */ -#define INT_TTO (1u << INT_V_TTO) -#define INT_TTI (1u << INT_V_TTI) -#define INT_HSP (1u << INT_V_HSP) -#define INT_HSR (1u << INT_V_HSR) -#define INT_RTC (1u << INT_V_RTC) -#define INT_NODEF (1u << INT_V_NODEF) -#define INT_ON (1u << INT_V_ON) -#define INT_PENDING (INT_ON | INT_NODEF) - -/* Vectors */ - -#define VEC_BKP 0000 /* breakpoint */ -#define VEC_TTO 0011 /* console out */ -#define VEC_TTI 0014 /* console in */ -#define VEC_HSP 0017 /* paper tape punch */ -#define VEC_HSR 0022 /* paper tape reader */ -#define VEC_RTC 0100 /* clock */ diff --git a/GRI/gri_doc.txt b/GRI/gri_doc.txt deleted file mode 100644 index aeab0072..00000000 --- a/GRI/gri_doc.txt +++ /dev/null @@ -1,321 +0,0 @@ -To: Users -From: Bob Supnik -Subj: GRI-909 Simulator Usage -Date: 20-Apr-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - Original code published in 1993-2003, written by Robert M Supnik - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - -This memorandum documents the GRI-909 simulator. - - -1. Simulator Files - -sim/ sim_defs.h - sim_rev.h - sim_sock.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tmxr.c - -sim/gri/ gri_defs.h - gri_cpu.c - gri_stddev.c - gri_sys.c - -2. GRI-909 Features - -The GRI-909 is configured as follows: - -device simulates -name(s) - -CPU GRI-909 CPU with up to 32KW of memory -HSR S42-004 high speed reader -HSP S42-004 high speed punch -TTI S42-001 Teletype input -TTO S42-002 Teletype output -RTC real-time clock - -The GRI-909 simulator implements the following unique stop conditions: - - - an unimplemented operator is referenced, and register - STOP_OPR is set - - an invalid interrupt request is made - -The LOAD commands has an optional argument to specify the load address: - - LOAD {} - -The LOAD command loads a paper-tape bootstrap format file at the specified -address. If no address is specified, loading starts at location 200. The -DUMP command is not supported. - -2.1 CPU - -The only CPU options are the presence of the extended arithmetic operator -and the size of main memory. - - SET CPU EAO enable extended arithmetic operator - SET CPU NOEAO disable extended arithmetic operator - SET CPU 4K set memory size = 4K - SET CPU 8K set memory size = 8K - SET CPU 12K set memory size = 12K - SET CPU 16K set memory size = 16K - SET CPU 20K set memory size = 20K - SET CPU 24K set memory size = 24K - SET CPU 28K set memory size = 28K - SET CPU 32K set memory size = 32K - -If memory size is being reduced, and the memory being truncated contains -non-zero data, the simulator asks for confirmation. Data in the truncated -portion of memory is lost. Initial memory size is 32K. - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - SC 15 sequence counter - AX 16 arithmetic operator input register 1 - AY 16 arithmetic operator input register 2 - AO 16 arithmetic operator output register - TRP 16 TRP register - MSR 16 machine status register - ISR 16 interrupt status register - BSW 16 byte swapper buffer - BPK 16 byte packer buffer - GR1..GR6 16 general registers 1 to 6 - BOV 1 bus overflow (MSR<15>) - L 1 link (MSR<14>) - FOA 2 arithmetic operator function (MSR<9:8>) - AOV 1 arithmetic overflow (MSR<0>) - IR 16 instruction register (read only) - MA 16 memory address register (read only) - SWR 16 switch register - DR 16 display register - THW 6 thumbwheels (selects operator displayed in DR) - IREQ 16 interrupt requests - ION 1 interrupts enabled - INODEF 1 interrupts not deferred - BKP 1 breakpoint request - SCQ[0:63] 15 SC prior to last jump or interrupt; - most recent SC change first - STOP_OPR 1 stop on undefined operator - WRU 8 interrupt character - -2.2 Programmed I/O Devices - -2.2.1 S42-004 High Speed Reader (HSR) - -The paper tape reader (HSR) reads data from or a disk file. The POS -register specifies the number of the next data item to be read. -Thus, by changing POS, the user can backspace or advance the reader. - -The paper tape reader implements these registers: - - name size comments - - BUF 8 last data item processed - IRDY 1 device ready flag - IENB 1 device interrupt enable flag - POS 32 position in the input file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - end of file 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -2.2.2 S42-006 High Speed Punch (HSP) - -The paper tape punch (HSP) writes data to a disk file. The POS -register specifies the number of the next data item to be written. -Thus, by changing POS, the user can backspace or advance the punch. - -The paper tape punch implements these registers: - - name size comments - - BUF 8 last data item processed - ORDY 1 device ready flag - IENB 1 device interrupt enable flag - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -2.2.3 S42-001 Teletype Input (TTI) - -The Teletype interfaces (TTI, TTO) can be set to one of three modes: -KSR, 7B, or 8B. In KSR mode, lower case input and output characters -are automatically converted to upper case, and the high order bit is -forced to one on input. In 7B mode, input and output characters are -masked to 7 bits. In 8B mode, characters are not modified. Changing -the mode of either interface changes both. The default mode is KSR. - -The Teletype input (TTI) polls the console keyboard for input. It -implements these registers: - - name size comments - - BUF 8 last data item processed - IRDY 1 device ready flag - IENB 1 device interrupt enable flag - POS 32 position in the output file - TIME 24 keyboard polling interval - -2.2.4 S42-002 Teletype Output (TTO) - -The Teletype output (TTO) writes to the simulator console window. It -implements these registers: - - name size comments - - BUF 8 last data item processed - ORDY 1 device ready flag - IENB 1 device interrupt enable flag - POS 32 number of characters output - TIME 24 time from I/O initiation to interrupt - -2.2.5 Real-Time Clock (RTC) - -The real-time clock (CLK) implements these registers: - - name size comments - - RDY 1 device ready flag - IENB 1 interrupt enable flag - TIME 24 clock interval - -The real-time clock autocalibrates; the clock interval is adjusted up or -down so that the clock tracks actual elapsed time. - -2.3 Symbolic Display and Input - -The GRI-909 simulator implements symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as packed ASCII characters - -m display instruction mnemonics - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or -a ASCII character - " or -c two packed ASCII characters - alphabetic instruction mnemonic - numeric octal number - -Instruction input uses modified GRI-909 basic assembler syntax. There are -thirteen different instruction formats. Operators, functions, and tests may -be octal or symbolic; jump conditions and bus operators are always symbolic. - -Function out, general - Syntax: FO function,operator - Function symbols: INP, IRDY, ORDY, STRT - Example: FO ORDY,TTO - -Function out, named - Syntax: FO{M|I|A} function - Function symbols: M: CLL, CML, STL, HLT; I: ICF, ICO; - A: ADD, AND, XOR, OR - Example: FOA XOR - -Sense function, general - Syntax: SF operator,{NOT} tests - Test symbols: IRDY, ORDY - Example: SF HSR,IRDY - -Sense function, named - Syntax: SF{M|A} {NOT} tests - Test symbols: M: POK BOV LNK; A: SOV AOV - Example: SFM NOT BOV - -Register to register - Syntax: RR{C} src,{bus op,}dst - Bus op symbols: P1, L1, R1 - Example: RRC AX,P1,AY - -Zero to register - Syntax: ZR{C} {bus op,}dst - Bus op symbols: P1, L1, R1 - Example: ZR P1,GR1 - -Register to self - Syntax: RS{C} dst{,bus op} - Bus op symbols: P1, L1, R1 - Example: RS AX,L1 - -Jump unconditional or named condition - Syntax: J{U|O|N}{D} address - Example: JUD 1400 - -Jump conditional - Syntax: JC{D} src,cond,address - Cond symbols: NEVER,ALWAYS,ETZ,NEZ,LTZ,GEZ,LEZ,GTZ - Example: JC AX,LEZ,200 - -Register to memory - syntax: RM{I|D|ID} src,{bus op,}address - Bus op symbols: P1, L1, R1 - Example: RMD AX,P1,1315 - -Zero to memory - Syntax: ZM{I|D|ID} {bus op,}address - Bus op symbols: P1, L1, R1 - Example: ZM P1,5502 - -Memory to register - Syntax: MR{I|D|ID} address,{bus op,}dst - Bus op symbols: P1, L1, R1 - Example: MRI 1405,GR6 - -Memory to self: - Syntax: MS{I|D|ID} address{,bus op} - Bus op symbols: P1, L1, R1 - Example: MS 3333,P1 diff --git a/GRI/gri_stddev.c b/GRI/gri_stddev.c deleted file mode 100644 index 425a8b7b..00000000 --- a/GRI/gri_stddev.c +++ /dev/null @@ -1,394 +0,0 @@ -/* gri_stddev.c: GRI-909 standard devices - - Copyright (c) 2001-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - tti S42-001 terminal input - tto S42-002 terminal output - hsr S42-004 high speed reader - hsp S42-006 high speed punch - rtc real time clock - - 25-Apr-03 RMS Revised for extended file support - 22-Dec-02 RMS Added break support - 01-Nov-02 RMS Added 7b/8B support to terminal -*/ - -#include "gri_defs.h" -#include - -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_KSR (1 << UNIT_V_KSR) - -uint32 hsr_stopioe = 1, hsp_stopioe = 1; - -extern uint16 M[]; -extern uint32 dev_done, ISR; - -t_stat tti_svc (UNIT *uhsr); -t_stat tto_svc (UNIT *uhsr); -t_stat tti_reset (DEVICE *dhsr); -t_stat tto_reset (DEVICE *dhsr); -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat hsr_svc (UNIT *uhsr); -t_stat hsp_svc (UNIT *uhsr); -t_stat hsr_reset (DEVICE *dhsr); -t_stat hsp_reset (DEVICE *dhsr); -t_stat rtc_svc (UNIT *uhsr); -t_stat rtc_reset (DEVICE *dhsr); -int32 rtc_tps = 1000; - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit descriptor - tti_reg TTI register list - tti_mod TTI modifiers list -*/ - -UNIT tti_unit = { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }; - -REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, 8) }, - { FLDATA (IRDY, dev_done, INT_V_TTI) }, - { FLDATA (IENB, ISR, INT_V_TTI) }, - { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (UC, tti_unit.flags, UNIT_V_KSR), REG_HRO }, - { NULL } }; - -MTAB tti_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, - { 0 } }; - -DEVICE tti_dev = { - "TTI", &tti_unit, tti_reg, tti_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tti_reset, - NULL, NULL, NULL }; - -/* TTO data structures - - tto_dev TTO device descriptor - tto_unit TTO unit descriptor - tto_reg TTO register list -*/ - -UNIT tto_unit = { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }; - -REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, 8) }, - { FLDATA (ORDY, dev_done, INT_V_TTO) }, - { FLDATA (IENB, ISR, INT_V_TTO) }, - { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -MTAB tto_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, - { 0 } }; - -DEVICE tto_dev = { - "TTO", &tto_unit, tto_reg, tto_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto_reset, - NULL, NULL, NULL }; - -/* HSR data structures - - hsr_dev HSR device descriptor - hsr_unit HSR unit descriptor - hsr_reg HSR register list - hsr_mod HSR modifiers list -*/ - -UNIT hsr_unit = { - UDATA (&hsr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), SERIAL_IN_WAIT }; - -REG hsr_reg[] = { - { ORDATA (BUF, hsr_unit.buf, 8) }, - { FLDATA (IRDY, dev_done, INT_V_HSR) }, - { FLDATA (IENB, ISR, INT_V_HSR) }, - { DRDATA (POS, hsr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, hsr_unit.wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, hsr_stopioe, 0) }, - { NULL } }; - -DEVICE hsr_dev = { - "HSR", &hsr_unit, hsr_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &hsr_reset, - NULL, NULL, NULL }; - -/* HSP data structures - - hsp_dev HSP device descriptor - hsp_unit HSP unit descriptor - hsp_reg HSP register list -*/ - -UNIT hsp_unit = { - UDATA (&hsp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG hsp_reg[] = { - { ORDATA (BUF, hsp_unit.buf, 8) }, - { FLDATA (ORDY, dev_done, INT_V_HSP) }, - { FLDATA (IENB, ISR, INT_V_HSP) }, - { DRDATA (POS, hsp_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, hsp_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, hsp_stopioe, 0) }, - { NULL } }; - -DEVICE hsp_dev = { - "HSP", &hsp_unit, hsp_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &hsp_reset, - NULL, NULL, NULL }; - -/* RTC data structures - - rtc_dev RTC device descriptor - rtc_unit RTC unit descriptor - rtc_reg RTC register list -*/ - -UNIT rtc_unit = { UDATA (&rtc_svc, 0, 0), 16000 }; - -REG rtc_reg[] = { - { FLDATA (RDY, dev_done, INT_V_RTC) }, - { FLDATA (IENB, ISR, INT_V_RTC) }, - { DRDATA (TIME, rtc_unit.wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS, rtc_tps, 8), REG_NZ + PV_LEFT + REG_HIDDEN }, - { NULL } }; - -DEVICE rtc_dev = { - "RTC", &rtc_unit, rtc_reg, NULL, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &rtc_reset, - NULL, NULL, NULL }; - -/* Console terminal function processors */ - -int32 tty_rd (int32 src, int32 ea) -{ -return tti_unit.buf; /* return data */ -} - -t_stat tty_wr (uint32 dst, uint32 val) -{ -tto_unit.buf = val & 0377; /* save char */ -dev_done = dev_done & ~INT_TTO; /* clear ready */ -sim_activate (&tto_unit, tto_unit.wait); /* activate unit */ -return SCPE_OK; -} - -t_stat tty_fo (uint32 op) -{ -if (op & TTY_IRDY) dev_done = dev_done & ~INT_TTI; -if (op & TTY_ORDY) dev_done = dev_done & ~INT_TTO; -return SCPE_OK; -} - -uint32 tty_sf (uint32 op) -{ -if (((op & TTY_IRDY) && (dev_done & INT_TTI)) || - ((op & TTY_ORDY) && (dev_done & INT_TTO))) return 1; -return 0; -} - -/* Service routines */ - -t_stat tti_svc (UNIT *uptr) -{ -int32 c; - -sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ -if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -if (c & SCPE_BREAK) tti_unit.buf = 0; /* break? */ -else if (tti_unit.flags & UNIT_KSR) { /* KSR? */ - c = c & 0177; /* force 7b */ - if (islower (c)) c = toupper (c); /* cvt to UC */ - tti_unit.buf = c | 0200; } /* add TTY bit */ -else tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177); -dev_done = dev_done | INT_TTI; /* set ready */ -tti_unit.pos = tti_unit.pos + 1; -return SCPE_OK; -} - -t_stat tto_svc (UNIT *uptr) -{ -int32 c; -t_stat r; - -dev_done = dev_done | INT_TTO; /* set ready */ -if (tto_unit.flags & UNIT_KSR) { /* KSR? */ - c = tto_unit.buf & 0177; /* force 7b */ - if (islower (c)) c = toupper (c); } /* cvt to UC */ -else c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); -if ((r = sim_putchar (c)) != SCPE_OK) return r; /* output */ -tto_unit.pos = tto_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routines */ - -t_stat tti_reset (DEVICE *dptr) -{ -tti_unit.buf = 0; /* clear buffer */ -dev_done = dev_done & ~INT_TTI; /* clear ready */ -sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ -return SCPE_OK; -} - -t_stat tto_reset (DEVICE *dptr) -{ -tto_unit.buf = 0; /* clear buffer */ -dev_done = dev_done | INT_TTO; /* set ready */ -sim_cancel (&tto_unit); /* deactivate unit */ -return SCPE_OK; -} - -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -tti_unit.flags = (tti_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; -tto_unit.flags = (tto_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; -return SCPE_OK; -} - -/* High speed paper tape function processors */ - -int32 hsrp_rd (int32 src, int32 ea) -{ -return hsr_unit.buf; /* return data */ -} - -t_stat hsrp_wr (uint32 dst, uint32 val) -{ -hsp_unit.buf = val & 0377; /* save char */ -dev_done = dev_done & ~INT_HSP; /* clear ready */ -sim_activate (&hsp_unit, hsp_unit.wait); /* activate unit */ -return SCPE_OK; -} - -t_stat hsrp_fo (uint32 op) -{ -if (op & PT_IRDY) dev_done = dev_done & ~INT_HSR; -if (op & PT_ORDY) dev_done = dev_done & ~INT_HSP; -if (op & PT_STRT) sim_activate (&hsr_unit, hsr_unit.wait); -return SCPE_OK; -} - -uint32 hsrp_sf (uint32 op) -{ -if (((op & PT_IRDY) && (dev_done & INT_HSR)) || - ((op & PT_ORDY) && (dev_done & INT_HSP))) return 1; -return 0; -} - -t_stat hsr_svc (UNIT *uptr) -{ -int32 temp; - -if ((hsr_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (hsr_stopioe, SCPE_UNATT); -if ((temp = getc (hsr_unit.fileref)) == EOF) { /* read char */ - if (feof (hsr_unit.fileref)) { /* err or eof? */ - if (hsr_stopioe) printf ("HSR end of file\n"); - else return SCPE_OK; } - else perror ("HSR I/O error"); - clearerr (hsr_unit.fileref); - return SCPE_IOERR; } -dev_done = dev_done | INT_HSR; /* set ready */ -hsr_unit.buf = temp & 0377; /* save char */ -hsr_unit.pos = hsr_unit.pos + 1; -return SCPE_OK; -} - -t_stat hsp_svc (UNIT *uptr) -{ -dev_done = dev_done | INT_HSP; /* set ready */ -if ((hsp_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (hsp_stopioe, SCPE_UNATT); -if (putc (hsp_unit.buf, hsp_unit.fileref) == EOF) { /* write char */ - perror ("HSP I/O error"); /* error? */ - clearerr (hsp_unit.fileref); - return SCPE_IOERR; } -hsp_unit.pos = hsp_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routines */ - -t_stat hsr_reset (DEVICE *dptr) -{ -hsr_unit.buf = 0; /* clear buffer */ -dev_done = dev_done & ~INT_HSR; /* clear ready */ -sim_cancel (&hsr_unit); /* deactivate unit */ -return SCPE_OK; -} - -t_stat hsp_reset (DEVICE *dptr) -{ -hsp_unit.buf = 0; /* clear buffer */ -dev_done = dev_done | INT_HSP; /* set ready */ -sim_cancel (&hsp_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Clock function processors */ - -t_stat rtc_fo (int32 op) -{ -if (op & RTC_OFF) sim_cancel (&rtc_unit); /* clock off? */ -if ((op & RTC_ON) && !sim_is_active (&rtc_unit)) /* clock on? */ - sim_activate (&rtc_unit, sim_rtc_init (rtc_unit.wait)); -if (op & RTC_OV) dev_done = dev_done & ~INT_RTC; /* clr ovflo? */ -return SCPE_OK; -} - -int32 rtc_sf (int32 op) -{ -if ((op & RTC_OV) && (dev_done & INT_RTC)) return 1; -return 0; -} - -t_stat rtc_svc (UNIT *uptr) -{ -M[RTC_CTR] = (M[RTC_CTR] + 1) & DMASK; /* incr counter */ -if (M[RTC_CTR] == 0) dev_done = dev_done | INT_RTC; /* ovflo? set ready */ -sim_activate (&rtc_unit, sim_rtc_calb (rtc_tps)); /* reactivate */ -return SCPE_OK; -} - -t_stat rtc_reset (DEVICE *dptr) -{ -dev_done = dev_done & ~INT_RTC; /* clear ready */ -sim_cancel (&rtc_unit); /* stop clock */ -return SCPE_OK; -} diff --git a/GRI/gri_sys.c b/GRI/gri_sys.c deleted file mode 100644 index 6bde9909..00000000 --- a/GRI/gri_sys.c +++ /dev/null @@ -1,582 +0,0 @@ -/* gri_sys.c: GRI-909 simulator interface - - Copyright (c) 2001-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 18-Oct-02 RMS Fixed bug in symbolic decode (found by Hans Pufal) -*/ - -#include "gri_defs.h" -#include - -extern DEVICE cpu_dev; -extern UNIT cpu_unit; -extern DEVICE tti_dev, tto_dev; -extern DEVICE hsr_dev, hsp_dev; -extern DEVICE rtc_dev; -extern REG cpu_reg[]; -extern uint16 M[]; -extern int32 sim_switches; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax maximum number of words for examine/deposit - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "GRI-909"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 2; - -DEVICE *sim_devices[] = { - &cpu_dev, - &tti_dev, - &tto_dev, - &hsr_dev, - &hsp_dev, - &rtc_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unimplemented unit", - "HALT instruction", - "Breakpoint", - "Invalid interrupt request" }; - -/* Binary loader - - Bootstrap loader format consists of blocks separated by zeroes. Each - word in the block has three frames: a control frame (ignored) and two - data frames. The user must specify the load address. Switch -c means - continue and load all blocks until end of tape. -*/ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 c; -uint32 org; -t_stat r; -char gbuf[CBUFSIZE]; - -if (*cptr != 0) { /* more input? */ - cptr = get_glyph (cptr, gbuf, 0); /* get origin */ - org = get_uint (gbuf, 8, AMASK, &r); - if (r != SCPE_OK) return r; - if (*cptr != 0) return SCPE_ARG; } /* no more */ -else org = 0200; /* default 200 */ - -for (;;) { /* until EOF */ - while ((c = getc (fileref)) == 0) ; /* skip starting 0's */ - if (c == EOF) break; /* EOF? done */ - for ( ; c != 0; ) { /* loop until ctl = 0 */ - /* ign ctrl frame */ - if ((c = getc (fileref)) == EOF) /* get high byte */ - return SCPE_FMT; /* EOF is error */ - if (!MEM_ADDR_OK (org)) return SCPE_NXM; - M[org] = ((c & 0377) << 8); /* store high */ - if ((c = getc (fileref)) == EOF) /* get low byte */ - return SCPE_FMT; /* EOF is error */ - M[org] = M[org] | (c & 0377); /* store low */ - org = org + 1; /* incr origin */ - if ((c = getc (fileref)) == EOF) /* get ctrl frame */ - return SCPE_OK; /* EOF is ok */ - } /* end block for */ - if (!(sim_switches & SWMASK ('C'))) return SCPE_OK; - } /* end tape for */ -return SCPE_OK; -} - -/* Symbol tables */ - -#define F_V_FL 16 /* class flag */ -#define F_M_FL 017 -#define F_V_FO 000 /* function out */ -#define F_V_FOI 001 /* FO, impl reg */ -#define F_V_SF 002 /* skip function */ -#define F_V_SFI 003 /* SF, impl reg */ -#define F_V_RR 004 /* reg reg */ -#define F_V_ZR 005 /* zero reg */ -#define F_V_RS 006 /* reg self */ -#define F_V_JC 010 /* jump cond */ -#define F_V_JU 011 /* jump uncond */ -#define F_V_RM 012 /* reg mem */ -#define F_V_ZM 013 /* zero mem */ -#define F_V_MR 014 /* mem reg */ -#define F_V_MS 015 /* mem self */ -#define F_2WD 010 /* 2 words */ - -#define F_FO (F_V_FO << F_V_FL) -#define F_FOI (F_V_FOI << F_V_FL) -#define F_SF (F_V_SF << F_V_FL) -#define F_SFI (F_V_SFI << F_V_FL) -#define F_RR (F_V_RR << F_V_FL) -#define F_ZR (F_V_ZR << F_V_FL) -#define F_RS (F_V_RS << F_V_FL) -#define F_JC (F_V_JC << F_V_FL) -#define F_JU (F_V_JU << F_V_FL) -#define F_RM (F_V_RM << F_V_FL) -#define F_ZM (F_V_ZM << F_V_FL) -#define F_MR (F_V_MR << F_V_FL) -#define F_MS (F_V_MS << F_V_FL) - -struct fnc_op { - uint32 inst; /* instr prot */ - uint32 imask; /* instr mask */ - uint32 oper; /* operator */ - uint32 omask; }; /* oper mask */ - -static const int32 masks[] = { - 0176000, 0176077, 0000077, 0176077, - 0000300, 0176300, 0000300, 0177777, - 0000077, 0177777, 0000377, 0176377, - 0176300, 0176377 }; - -/* Instruction mnemonics - - Order is critical, as some instructions are more precise versions of - others. For example, JU must precede JC, otherwise, JU will be decoded - as JC 0,ETZ,dst. There are some ambiguities, eg, what is 02-xxxx-06? - Priority is as follows: - - FO (02-xxxx-rr) - SF (rr-xxxx-02) - MR (06-xxxx-rr) - RM (rr-xxxx-06) - JC (rr-xxxx-03) - RR -*/ - -static const char *opcode[] = { - "FOM", "FOA", "FOI", "FO", /* FOx before FO */ - "SFM", "SFA", "SFI", "SF", /* SFx before SF */ - "ZM", "ZMD", "ZMI", "ZMID", /* ZM before RM */ - "MS", "MSD", "MSI", "MSID", - "RM", "RMD", "RMI", "RMID", - "MR", "MRD", "MRI", "MRID", - "JO", "JOD", "JN", "JND", /* JU before JC */ - "JU", "JUD", "JC", "JCD", - "ZR", "ZRC", "RR", "RRC", /* ZR before RR */ - "RS", "RSC", - NULL }; - -static const uint32 opc_val[] = { - 0004000+F_FOI, 0004013+F_FOI, 0004004+F_FOI, 0004000+F_FO, - 0000002+F_SFI, 0026002+F_SFI, 0010002+F_SFI, 0000002+F_SF, - 0000006+F_ZM, 0000106+F_ZM, 0000206+F_ZM, 0000306+F_ZM, - 0014006+F_MS, 0014106+F_MS, 0014206+F_MS, 0014306+F_MS, - 0000006+F_RM, 0000106+F_RM, 0000206+F_RM, 0000306+F_RM, - 0014000+F_MR, 0014100+F_MR, 0014200+F_MR, 0014300+F_MR, - 0037003+F_JU, 0037103+F_JU, 0037203+F_JU, 0037303+F_JU, - 0000403+F_JU, 0000503+F_JU, 0000003+F_JC, 0000103+F_JC, - 0000000+F_ZR, 0000200+F_ZR, 0000000+F_RR, 0000200+F_RR, - 0000000+F_RS, 0000200+F_RS }; - -/* Unit mnemonics. All 64 units are decoded, most just to octal integers */ - -static const char *unsrc[64] = { - "0", "IR", "2", "TRP", "ISR", "MA", "MB", "SC", /* 00 - 07 */ - "SWR", "AX", "AY", "AO", "14", "15", "16", "MSR", /* 10 - 17 */ - "20", "21", "22", "23", "BSW", "BPK", "26", "27", /* 20 - 27 */ - "GR1", "GR2", "GR3", "GR4", "GR5", "GR6", "36", "37", /* 30 - 37 */ - "40", "41", "42", "43", "44", "45", "46", "47", - "50", "51", "52", "53", "54", "55", "56", "57", - "60", "61", "62", "63", "64", "65", "66", "67", - "70", "71", "72", "73", "74", "RTC", "HSR", "TTI" }; /* 70 - 77 */ - -static const char *undst[64] = { - "0", "IR", "2", "TRP", "ISR", "5", "MB", "SC", /* 00 - 07 */ - "SWR", "AX", "AY", "13", "EAO", "15", "16", "MSR", /* 10 - 17 */ - "20", "21", "22", "23", "BSW", "BPK", "26", "27", /* 20 - 27 */ - "GR1", "GR2", "GR3", "GR4", "GR5", "GR6", "36", "37", /* 30 - 37 */ - "40", "41", "42", "43", "44", "45", "46", "47", - "50", "51", "52", "53", "54", "55", "56", "57", - "60", "61", "62", "63", "64", "65", "66", "67", - "70", "71", "72", "73", "74", "RTC", "HSP", "TTO" }; /* 70 - 77 */ - - /* Operators */ - -static const char *opname[4] = { - NULL, "P1", "L1", "R1" }; - -/* Conditions */ - -static const char *cdname[8] = { - "NEVER", "ALWAYS", "ETZ", "NEZ", "LTZ", "GEZ", "LEZ", "GTZ" }; - -/* Function out/sense function */ - -static const char *fname[] = { - "NOT", /* any SF */ - "POK", "LNK", "BOV", /* SFM */ - "SOV", "AOV", /* SFA */ - "IRDY", "ORDY", /* any SF */ - "CLL", "STL", "CML", "HLT", /* FOM */ - "ICF", "ICO", /* FOI */ - "ADD", "AND", "XOR", "OR", /* FOA */ - "INP", "IRDY", "ORDY", "STRT", /* any FO */ - NULL }; - -static const struct fnc_op fop[] = { - { 0000002, 0000077, 001, 001 }, /* NOT */ - { 0000002, 0176077, 010, 010 }, /* POK */ - { 0000002, 0176077, 004, 004 }, /* LNK */ - { 0000002, 0176077, 002, 002 }, /* BOV */ - { 0026002, 0176077, 004, 004 }, /* SOV */ - { 0026002, 0176077, 002, 002 }, /* AOV */ - { 0000002, 0000077, 010, 010 }, /* IRDY */ - { 0000002, 0000077, 002, 002 }, /* ORDY */ - { 0004000, 0176077, 001, 003 }, /* CLL */ - { 0004000, 0176077, 002, 003 }, /* STL */ - { 0004000, 0176077, 003, 003 }, /* CML */ - { 0004000, 0176077, 004, 004 }, /* HLT */ - { 0004004, 0176077, 001, 001 }, /* ICF */ - { 0004004, 0176077, 002, 002 }, /* ICO */ - { 0004013, 0176077, 000, 014 }, /* ADD */ - { 0004013, 0176077, 004, 014 }, /* AND */ - { 0004013, 0176077, 010, 014 }, /* XOR */ - { 0004013, 0176077, 014, 014 }, /* OR */ - { 0004000, 0176000, 011, 011 }, /* INP */ - { 0004000, 0176000, 010, 010 }, /* IRDY */ - { 0004000, 0176000, 002, 002 }, /* ORDY */ - { 0004000, 0176000, 001, 001 } }; /* STRT */ - -/* Print opcode field for FO, SF */ - -void fprint_op (FILE *of, uint32 inst, uint32 op) -{ -int32 i, nfirst; - -for (i = nfirst = 0; fname[i] != NULL; i++) { - if (((inst & fop[i].imask) == fop[i].inst) && - ((op & fop[i].omask) == fop[i].oper)) { - op = op & ~fop[i].omask; - if (nfirst) fputc (' ', of); - nfirst = 1; - fprintf (of, "%s", fname[i]); } - } -if (op) fprintf (of, " %o", op); -return; -} - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current PC - *val = pointer to data - *uptr = pointer to unit - sw = switches - Outputs: - return = status code -*/ - -#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 i, j; -uint32 inst, src, dst, op, bop; - -inst = val[0]; -if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; - fprintf (of, FMTASC (inst & 0177)); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* characters? */ - fprintf (of, FMTASC ((inst >> 8) & 0177)); - fprintf (of, FMTASC (inst & 0177)); - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; - -/* Instruction decode */ - -inst = val[0]; -src = I_GETSRC (inst); /* get fields */ -op = I_GETOP (inst); -dst = I_GETDST (inst); -bop = op >> 2; /* bus op */ -for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */ - j = (opc_val[i] >> F_V_FL) & F_M_FL; /* get class */ - if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */ - - switch (j) { /* case on class */ - case F_V_FO: /* func out */ - fprintf (of, "%s ", opcode[i]); - fprint_op (of, inst, op); - fprintf (of, ",%s", undst[dst]); - break; - case F_V_FOI: /* func out impl */ - fprintf (of, "%s ", opcode[i]); - fprint_op (of, inst, op); - break; - case F_V_SF: /* skip func */ - fprintf (of, "%s %s,", opcode[i], unsrc[src]); - fprint_op (of, inst, op); - break; - case F_V_SFI: /* skip func impl */ - fprintf (of, "%s ", opcode[i]); - fprint_op (of, inst, op); - break; - case F_V_RR: /* reg reg */ - if (strcmp (unsrc[src], undst[dst]) == 0) { - if (bop) fprintf (of, "%s %s,%s", opcode[i + 2], - unsrc[src], opname[bop]); - else fprintf (of, "%s %s", opcode[i + 2], unsrc[src]); } - else { - if (bop) fprintf (of, "%s %s,%s,%s", opcode[i], - unsrc[src], opname[bop], undst[dst]); - else fprintf (of, "%s %s,%s", opcode[i], - unsrc[src], undst[dst]); } - break; - case F_V_ZR: /* zero reg */ - if (bop) fprintf (of, "%s %s,%s", opcode[i], - opname[bop], undst[dst]); - else fprintf (of, "%s %s", opcode[i], undst[dst]); - break; - case F_V_JC: /* jump cond */ - fprintf (of, "%s %s,%s,%o", opcode[i], - unsrc[src], cdname[op >> 1], val[1]); - break; - case F_V_JU: /* jump uncond */ - fprintf (of, "%s %o", opcode[i], val[1]); - break; - case F_V_RM: /* reg mem */ - if (bop) fprintf (of, "%s %s,%s,%o", opcode[i], - unsrc[src], opname[bop], val[1]); - else fprintf (of, "%s %s,%o", opcode[i], unsrc[src], val[1]); - break; - case F_V_ZM: /* zero mem */ - if (bop) fprintf (of, "%s %s,%o", opcode[i], - opname[bop], val[1]); - else fprintf (of, "%s %o", opcode[i], val[1]); - break; - case F_V_MR: /* mem reg */ - if (bop) fprintf (of, "%s %o,%s,%s", opcode[i], - val[1], opname[bop], undst[dst]); - else fprintf (of, "%s %o,%s", opcode[i], val[1], undst[dst]); - break; - case F_V_MS: /* mem self */ - if (bop) fprintf (of, "%s %o,%s", opcode[i], - val[1], opname[bop]); - else fprintf (of, "%s %o", opcode[i], val[1]); - break; } /* end case */ - return (j >= F_2WD)? -1: SCPE_OK; } /* end if */ - } /* end for */ -return SCPE_ARG; -} - -/* Field parse routines - - get_fnc get function field - get_ma get memory address - get_sd get source or dest - get_op get optional bus operator -*/ - -char *get_fnc (char *cptr, t_value *val) -{ -char gbuf[CBUFSIZE]; -int32 i; -t_value d; -t_stat r; -uint32 inst = val[0]; -uint32 fncv = 0, fncm = 0; - -while (*cptr) { - cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ - d = get_uint (gbuf, 8, 017, &r); /* octal? */ - if (r == SCPE_OK) { /* ok? */ - if (d & fncm) return NULL; /* already filled? */ - fncv = fncv | d; /* save */ - fncm = fncm | d; } /* field filled */ - else { /* symbol? */ - for (i = 0; fname[i] != NULL; i++) { /* search table */ - if ((strcmp (gbuf, fname[i]) == 0) && /* match for inst? */ - ((inst & fop[i].imask) == fop[i].inst)) { - if (fop[i].oper & fncm) return NULL;/* already filled? */ - fncm = fncm | fop[i].omask; - fncv = fncv | fop[i].oper; - break; } } - if (fname[i] == NULL) return NULL; } /* end else */ - } /* end while */ -val[0] = val[0] | (fncv << I_V_OP); /* store fnc */ -return cptr; -} - -char *get_ma (char *cptr, t_value *val, char term) -{ -char gbuf[CBUFSIZE]; -t_value d; -t_stat r; - -cptr = get_glyph (cptr, gbuf, term); /* get glyph */ -d = get_uint (gbuf, 8, DMASK, &r); /* [0,177777] */ -if (r != SCPE_OK) return NULL; -val[1] = d; /* second wd */ -return cptr; -} - -char *get_sd (char *cptr, t_value *val, char term, t_bool src) -{ -char gbuf[CBUFSIZE]; -int32 d; -t_stat r; - -cptr = get_glyph (cptr, gbuf, term); /* get glyph */ -for (d = 0; d < 64; d++) { /* symbol match? */ - if ((strcmp (gbuf, unsrc[d]) == 0) || - (strcmp (gbuf, undst[d]) == 0)) break; } -if (d >= 64) { /* no, [0,63]? */ - d = get_uint (gbuf, 8, 077, &r); - if (r != SCPE_OK) return NULL; } -val[0] = val[0] | (d << (src? I_V_SRC: I_V_DST)); /* or to inst */ -return cptr; -} - -char *get_op (char *cptr, t_value *val, char term) -{ -char gbuf[CBUFSIZE], *tptr; -int32 i; - -tptr = get_glyph (cptr, gbuf, term); /* get glyph */ -for (i = 1; i < 4; i++) { /* symbol match? */ - if (strcmp (gbuf, opname[i]) == 0) { - val[0] = val[0] | (i << (I_V_OP + 2)); /* or to inst */ - return tptr; } } -return cptr; /* original ptr */ -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = error status -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 i, j, k; -char *tptr, gbuf[CBUFSIZE]; - -while (isspace (*cptr)) cptr++; /* absorb spaces */ -if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (t_value) cptr[0] & 0177; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* char string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (((t_value) cptr[0] & 0177) << 8) | - ((t_value) cptr[1] & 0177); - return SCPE_OK; } - -/* Instruction parse */ - -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; -if (opcode[i] == NULL) return SCPE_ARG; -val[0] = opc_val[i] & DMASK; /* get value */ -j = (opc_val[i] >> F_V_FL) & F_M_FL; /* get class */ - -switch (j) { /* case on class */ -case F_V_FO: /* func out */ - tptr = strchr (cptr, ','); /* find dst */ - if (!tptr) return SCPE_ARG; /* none? */ - *tptr = 0; /* split fields */ - cptr = get_fnc (cptr, val); /* fo # */ - if (!cptr) return SCPE_ARG; - cptr = get_sd (tptr + 1, val, 0, FALSE); /* dst */ - break; -case F_V_FOI: /* func out impl */ - cptr = get_fnc (cptr, val); /* fo # */ - break; -case F_V_SF: /* skip func */ - cptr = get_sd (cptr, val, ',', TRUE); /* src */ - if (!cptr) return SCPE_ARG; -case F_V_SFI: /* skip func impl */ - cptr = get_fnc (cptr, val); /* fo # */ - break; -case F_V_RR: /* reg-reg */ - cptr = get_sd (cptr, val, ',', TRUE); /* src */ - if (!cptr) return SCPE_ARG; - cptr = get_op (cptr, val, ','); /* op */ - if (!cptr) return SCPE_ARG; - cptr = get_sd (cptr, val, 0, FALSE); /* dst */ - break; -case F_V_ZR: /* zero-reg */ - cptr = get_op (cptr, val, ','); /* op */ - if (!cptr) return SCPE_ARG; - cptr = get_sd (cptr, val, 0, FALSE); /* dst */ - break; -case F_V_RS: /* reg self */ - cptr = get_sd (cptr, val, ',', TRUE); /* src */ - if (!cptr) return SCPE_ARG; - val[0] = val[0] | I_GETSRC (val[0]); /* duplicate */ - cptr = get_op (cptr, val, 0); /* op */ - break; -case F_V_JC: /* jump cond */ - cptr = get_sd (cptr, val, ',', TRUE); /* src */ - if (!cptr) return SCPE_ARG; - cptr = get_glyph (cptr, gbuf, ','); /* cond */ - for (k = 0; k < 8; k++) { /* symbol? */ - if (strcmp (gbuf, cdname[k]) == 0) break; } - if (k >= 8) return SCPE_ARG; - val[0] = val[0] | (k << (I_V_OP + 1)); /* or to inst */ -case F_V_JU: /* jump uncond */ - cptr = get_ma (cptr, val, 0); /* addr */ - break; -case F_V_RM: /* reg mem */ - cptr = get_sd (cptr, val, ',', TRUE); /* src */ - if (!cptr) return SCPE_ARG; -case F_V_ZM: /* zero mem */ - cptr = get_op (cptr, val, ','); /* op */ - if (!cptr) return SCPE_ARG; - cptr = get_ma (cptr, val, 0); /* addr */ - break; -case F_V_MR: /* mem reg */ - cptr = get_ma (cptr, val, ','); /* addr */ - if (!cptr) return SCPE_ARG; - cptr = get_op (cptr, val, ','); /* op */ - if (!cptr) return SCPE_ARG; - cptr = get_sd (cptr, val, 0, FALSE); /* dst */ - break; -case F_V_MS: /* mem self */ - cptr = get_ma (cptr, val, ','); /* addr */ - if (!cptr) return SCPE_ARG; - cptr = get_op (cptr, val, 0); /* op */ - break; } -if (!cptr || (*cptr != 0)) return SCPE_ARG; /* junk at end? */ -return (j >= F_2WD)? -1: SCPE_OK; -} diff --git a/H316/h316_cpu.c b/H316/h316_cpu.c deleted file mode 100644 index 202f126b..00000000 --- a/H316/h316_cpu.c +++ /dev/null @@ -1,1088 +0,0 @@ -/* h316_cpu.c: Honeywell 316/516 CPU simulator - - Copyright (c) 1999-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - cpu H316/H516 CPU - - 30-Dec-01 RMS Added old PC queue - 03-Nov-01 RMS Fixed NOHSA modifier - 30-Nov-01 RMS Added extended SET/SHOW support - - The register state for the Honeywell 316/516 CPU is: - - AR<1:16> A register - BR<1:16> B register - XR<1:16> X register - PC<1:16> P register (program counter) - Y<1:16> memory address register - MB<1:16> memory data register - C overflow flag - EXT extend mode flag - DP double precision mode flag - SC<1:5> shift count - SR[1:4]<0> sense switches 1-4 - - The Honeywell 316/516 has six instruction formats: memory reference, - I/O, control, shift, skip, and operate. - - The memory reference format is: - - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in|xr| op |sc| offset | memory reference - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <13:10> mnemonic action - - 0000 (other) see control, shift, skip, operate instructions - 0001 JMP P = MA - 0010 LDA A = M[MA] - 0011 ANA A = A & M[MA] - 0100 STA M[MA] = A - 0101 ERA A = A ^ M[MA] - 0110 ADD A = A + M[MA] - 0111 SUB A = A - M[MA] - 1000 JST M[MA] = P, P = MA + 1 - 1001 CAS skip if A == M[MA], double skip if A < M[MA] - 1010 IRS M[MA] = M[MA] + 1, skip if M[MA] == 0 - 1011 IMA A <=> M[MA] - 1100 (I/O) see I/O instructions - 1101 LDX/STX X = M[MA] (xr = 1), M[MA] = x (xr = 0) - 1110 MPY multiply - 1111 DIV divide - - In non-extend mode, memory reference instructions can access an address - space of 16K words. Multiple levels of indirection are supported, and - each indirect word supplies its own indirect and index bits. - - <1,2,7> mode action - - 0,0,0 sector zero direct MA = IR<8:0> - 0,0,1 current direct MA = P<13:9>'IR<8:0> - 0,1,0 sector zero indexed MA = IR<8:0> + X - 0,1,1 current direct MA = P<13:9>'IR<8:0> + X - 1,0,0 sector zero indirect MA = M[IR<8:0>] - 1,0,1 current indirect MA = M[P<13:9>'IR<8:0>] - 1,1,0 sector zero indirect indexed MA = M[IR<8:0> + X] - 1,1,1 current indirect indexed MA = M[MA = P<13:9>'IR<8:0> + X] - - In extend mode, memory reference instructions can access an address - space of 32K words. Multiple levels of indirection are supported, but - only post-indexing, based on the original instruction word index flag, - is allowed. -*/ - -/* The control format is: - - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 0 0 0 0 0| opcode | control - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The shift format is: - - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 1 0 0 0 0|dr|sz|type | shift count | shift - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | \-+-/ - | | | - | | +--------------------- type - | +------------------------- long/A only - +---------------------------- right/left - - The skip format is: - - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 0 0 0 0 0|rv|po|pe|ev|ze|s1|s2|s3|s4|cz| skip - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | | | | | | | - | | | | | | | | | +- skip if C = 0 - | | | | | | | | +---- skip if ssw 4 = 0 - | | | | | | | +------- skip if ssw 3 = 0 - | | | | | | +---------- skip if ssw 2 = 0 - | | | | | +------------- skip if ssw 1 = 0 - | | | | +---------------- skip if A == 0 - | | | +------------------- skip if A<0> == 0 - | | +---------------------- skip if mem par err - | +------------------------- skip if A<15> = 0 - +---------------------------- reverse skip sense - - The operate format is: - - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 0 0 0 0| opcode | operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The I/O format is: - - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op | 1 1 0 0| function | device | I/O transfer - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The IO transfer instruction controls the specified device. - Depending on the opcode, the instruction may set or clear - the device flag, start or stop I/O, or read or write data. -*/ - -/* This routine is the instruction decode routine for the Honeywell - 316/516. It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - breakpoint encountered - infinite indirection loop - unimplemented instruction and stop_inst flag set - unknown I/O device and stop_dev flag set - I/O error in I/O simulator - - 2. Interrupts. Interrupts are maintained by two parallel variables: - - dev_ready device ready flags - dev_enable device interrupt enable flags - - In addition, dev_ready contains the interrupt enable and interrupt no - defer flags. If interrupt enable and interrupt no defer are set, and - at least one interrupt request is pending, then an interrupt occurs. - The order of flags in these variables corresponds to the order - in the SMK instruction. - - 3. Non-existent memory. On the H316/516, reads to non-existent memory - return zero, and writes are ignored. In the simulator, the - largest possible memory is instantiated and initialized to zero. - Thus, only writes need be checked against actual memory size. - - 4. Adding I/O devices. These modules must be modified: - - h316_defs.h add interrupt request definition - h316_cpu.c add device dispatch table entry - h316_sys.c add sim_devices table entry -*/ - -#include "h316_defs.h" - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC -#define PCQ_TOP pcq[pcq_p] -#define UNIT_V_MSIZE (UNIT_V_UF) /* dummy mask */ -#define UNIT_MSIZE (1u << UNIT_V_MSIZE) -#define m7 0001000 /* for generics */ -#define m8 0000400 -#define m9 0000200 -#define m10 0000100 -#define m11 0000040 -#define m12 0000020 -#define m13 0000010 -#define m14 0000004 -#define m15 0000002 -#define m16 0000001 - -uint16 M[MAXMEMSIZE] = { 0 }; /* memory */ -int32 saved_AR = 0; /* A register */ -int32 saved_BR = 0; /* B register */ -int32 saved_XR = 0; /* X register */ -int32 PC = 0; /* P register */ -int32 C = 0; /* C register */ -int32 ext = 0; /* extend mode */ -int32 pme = 0; /* prev mode extend */ -int32 extoff_pending = 0; /* extend off pending */ -int32 dp = 0; /* double mode */ -int32 sc = 0; /* shift count */ -int32 ss[4]; /* sense switches */ -int32 dev_ready = 0; /* dev ready */ -int32 dev_enable = 0; /* dev enable */ -int32 ind_max = 8; /* iadr nest limit */ -int32 stop_inst = 1; /* stop on ill inst */ -int32 stop_dev = 2; /* stop on ill dev */ -uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -int32 dlog = 0; /* debug log */ -int32 turnoff = 0; - -extern int32 sim_int_char; -extern int32 sim_interval; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern FILE *sim_log; - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_set_noext (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifiers list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK + UNIT_EXT, - MAXMEMSIZE) }; - -REG cpu_reg[] = { - { ORDATA (P, PC, 15) }, - { ORDATA (A, saved_AR, 16) }, - { ORDATA (B, saved_BR, 16) }, - { ORDATA (X, XR, 16) }, - { ORDATA (SC, sc, 16) }, - { FLDATA (C, C, 0) }, - { FLDATA (EXT, ext, 0) }, - { FLDATA (PME, pme, 0) }, - { FLDATA (EXT_OFF, extoff_pending, 0) }, - { FLDATA (DP, dp, 0) }, - { FLDATA (SS1, ss[0], 0) }, - { FLDATA (SS2, ss[1], 0) }, - { FLDATA (SS3, ss[2], 0) }, - { FLDATA (SS4, ss[3], 0) }, - { FLDATA (ION, dev_ready, INT_V_ON) }, - { FLDATA (INODEF, dev_ready, INT_V_NODEF) }, - { ORDATA (DEVRDY, dev_ready, 16), REG_RO }, - { ORDATA (DEVENB, dev_enable, 16), REG_RO }, - { FLDATA (MPERDY, dev_ready, INT_V_MPE) }, - { FLDATA (MPEENB, dev_enable, INT_V_MPE) }, - { FLDATA (STOP_INST, stop_inst, 0) }, - { FLDATA (STOP_DEV, stop_dev, 1) }, - { DRDATA (INDMAX, ind_max, 8), REG_NZ + PV_LEFT }, - { BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_RO + REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { ORDATA (WRU, sim_int_char, 8) }, - { FLDATA (DLOG, dlog, 0), REG_HIDDEN }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_EXT, 0, "no extend", "NOEXTEND", &cpu_set_noext }, - { UNIT_EXT, UNIT_EXT, "extend", "EXTEND", NULL }, - { UNIT_HSA, 0, "no HSA", "NOHSA", NULL }, - { UNIT_HSA, UNIT_HSA, "HSA", "HSA", NULL }, - { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, - { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, - { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size }, - { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, - { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size }, - { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, 15, 1, 8, 16, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -/* I/O dispatch */ - -int32 undio (int32 op, int32 func, int32 AR); -extern int32 ptrio (int32 op, int32 func, int32 AR); -extern int32 ptpio (int32 op, int32 func, int32 AR); -extern int32 lptio (int32 op, int32 func, int32 AR); -extern int32 ttyio (int32 op, int32 func, int32 AR); -extern int32 clkio (int32 op, int32 func, int32 AR); - -int32 (*iotab[64])() = { - &undio, &ptrio, &ptpio, &lptio, &ttyio, &undio, &undio, &undio, - &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, - &clkio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, - &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, - &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, - &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, - &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, - &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio }; - - -t_stat sim_instr (void) -{ -extern UNIT clk_unit; -int32 AR, BR, MB, Y, t1, t2, t3, skip; -uint32 ut; -t_stat reason; -t_stat Ea (int32 inst, int32 *addr); -void Write (int32 val, int32 addr); -int32 Add16 (int32 val1, int32 val2); -int32 Add31 (int32 val1, int32 val2); -int32 Operate (int32 MB, int32 AR); - -#define Read(x) M[(x)] -#define GETDBL_S(h,l) (((h) << 15) | ((l) & MMASK)) -#define GETDBL_U(h,l) (((h) << 16) | (l)) -#define PUTDBL_S(x) AR = ((x) >> 15) & DMASK; \ - BR = (BR & SIGN) | ((x) & MMASK) -#define PUTDBL_U(x) AR = ((x) >> 16) & DMASK; \ - BR = (x) & DMASK -#define SEXT(x) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK)) -#define NEWA(c,n) (ext? (((c) & ~X_AMASK) | ((n) & X_AMASK)): \ - (((c) & ~NX_AMASK) | ((n) & NX_AMASK))) - -/* Restore register state */ - -AR = saved_AR & DMASK; /* restore reg */ -BR = saved_BR & DMASK; -XR = saved_XR & DMASK; -PC = PC & ((cpu_unit.flags & UNIT_EXT)? X_AMASK: NX_AMASK); /* mask PC */ -reason = 0; -turnoff = 0; -sim_rtc_init (clk_unit.wait); /* init calibration */ - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } - -if ((dev_ready & (INT_PENDING | dev_enable)) > INT_PENDING) { /* int req? */ - pme = ext; /* save extend */ - if (cpu_unit.flags & UNIT_EXT) ext = 1; /* ext opt? extend on */ - dev_ready = dev_ready & ~INT_ON; /* intr off */ - turnoff = 0; - if (dlog && sim_log) fprintf (sim_log, "Interrupt\n"); - MB = 0120000 | M_INT; } /* inst = JST* 63 */ - -else { if (sim_brk_summ && - sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - Y = PC; /* set mem addr */ - MB = Read (Y); /* fetch instr */ - PC = NEWA (Y, Y + 1); /* incr PC */ - dev_ready = dev_ready | INT_NODEF; } - -sim_interval = sim_interval - 1; -if (dlog && sim_log && !turnoff) { /* cycle log? */ - int32 op = I_GETOP (MB) & 017; /* core opcode */ - t_value val = MB; - fprintf (sim_log, "A= %06o C= %1o P= %05o (", AR, C, PC); - fprint_sym (sim_log, Y, &val, &cpu_unit, SWMASK ('M')); - fprintf (sim_log, ")"); - if ((op == 0) || (op == 014)) fprintf (sim_log, "\n"); } - -/* Memory reference instructions */ - -switch (I_GETOP (MB)) { /* case on <1:6> */ - -case 001: case 021: case 041: case 061: /* JMP */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - PCQ_ENTRY; /* save PC */ - PC = NEWA (PC, Y); /* set new PC */ - if (dlog && sim_log) { /* logging? */ - int32 op = I_GETOP (M[PC]) & 017; /* get target */ - if ((op == 014) && (PC == (PCQ_TOP - 2))) { /* jmp .-1 to IO? */ - turnoff = 1; /* yes, stop */ - fprintf (sim_log, "Idle loop detected\n"); } - else turnoff = 0; } /* no, log */ - if (extoff_pending) ext = extoff_pending = 0; /* cond ext off */ - break; - -case 002: case 022: case 042: case 062: /* LDA */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - if (dp) { /* double prec? */ - AR = Read (Y & ~1); /* get doubleword */ - BR = Read (Y | 1); - sc = 0; } - else AR = Read (Y); /* no, get word */ - break; - -case 003: case 023: case 043: case 063: /* ANA */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - AR = AR & Read (Y); - break; - -case 004: case 024: case 044: case 064: /* STA */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - if (dp) { /* double prec? */ - if ((Y & 1) == 0) Write (AR, Y); /* if even, store A */ - Write (BR, Y | 1); /* store B */ - sc = 0; } - else Write (AR, Y); /* no, store word */ - break; - -case 005: case 025: case 045: case 065: /* ERA */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - AR = AR ^ Read (Y); - break; - -case 006: case 026: case 046: case 066: /* ADD */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - if (dp) { /* double prec? */ - t1 = GETDBL_S (AR, BR); /* get A'B */ - t2 = GETDBL_S (Read (Y & ~1), Read (Y | 1)); - t1 = Add31 (t1, t2); /* 31b add */ - PUTDBL_S (t1); - sc = 0; } - else AR = Add16 (AR, Read (Y)); /* no, 16b add */ - break; - -case 007: case 027: case 047: case 067: /* SUB */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - if (dp) { /* double prec? */ - t1 = GETDBL_S (AR, BR); /* get A'B */ - t2 = GETDBL_S (Read (Y & ~1), Read (Y | 1)); - t1 = Add31 (t1, -t2); /* 31b sub */ - PUTDBL_S (t1); - sc = 0; } - else AR = Add16 (AR, (-Read (Y)) & DMASK); /* no, 16b sub */ - break; - -/* Memory reference instructions */ - -case 010: case 030: case 050: case 070: /* JST */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - MB = NEWA (Read (Y), PC); /* merge old PC */ - Write (MB, Y); - PCQ_ENTRY; - PC = NEWA (PC, Y + 1); /* set new PC */ - break; - -case 011: case 031: case 051: case 071: /* CAS */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - MB = Read (Y); - if (AR == MB) PC = NEWA (PC, PC + 1); - else if (SEXT (AR) < SEXT (MB)) PC = NEWA (PC, PC + 2); - break; - -case 012: case 032: case 052: case 072: /* IRS */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - MB = (Read (Y) + 1) & DMASK; /* incr, rewrite */ - Write (MB, Y); - if (MB == 0) PC = NEWA (PC, PC + 1); /* skip if zero */ - break; - -case 013: case 033: case 053: case 073: /* IMA */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - MB = Read (Y); - Write (AR, Y); /* A to mem */ - AR = MB; /* mem to A */ - break; - -case 015: case 055: /* STX */ - if (reason = Ea (MB & ~IDX, &Y)) break; /* eff addr */ - Write (XR, Y); /* store XR */ - break; - -case 035: case 075: /* LDX */ - if (reason = Ea (MB & ~IDX, &Y)) break; /* eff addr */ - XR = Read (Y); /* load XR */ - break; - -case 016: case 036: case 056: case 076: /* MPY */ - if (cpu_unit.flags & UNIT_HSA) { /* installed? */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - t1 = SEXT (AR) * SEXT (Read (Y)); - PUTDBL_S (t1); - sc = 0; } - else reason = stop_inst; - break; - -case 017: case 037: case 057: case 077: /* DIV */ - if (cpu_unit.flags & UNIT_HSA) { /* installed? */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - t2 = SEXT (Read (Y)); /* divr */ - if (t2) { /* divr != 0? */ - t1 = GETDBL_S (AR, BR); /* get A'B */ - BR = (t1 % t2) & DMASK; /* remainder */ - t1 = t1 / t2; /* quotient */ - AR = t1 & DMASK; - if ((t1 > MMASK) || (t1 < (-SIGN))) C = 1; - else C = 0; - sc = 0; } - else C = 1; } - else reason = stop_inst; - break; - -/* I/O instructions */ - -case 014: /* OCP */ - t2 = iotab[MB & DEVMASK] (ioOCP, I_GETFNC (MB), AR); - reason = t2 >> IOT_V_REASON; - turnoff = 0; - break; - -case 034: /* SKS */ - t2 = iotab[MB & DEVMASK] (ioSKS, I_GETFNC (MB), AR); - reason = t2 >> IOT_V_REASON; - if (t2 & IOT_SKIP) { /* skip? */ - PC = NEWA (PC, PC + 1); - turnoff = 0; } - break; - -case 054: /* INA */ - if (MB & INCLRA) AR = 0; - t2 = iotab[MB & DEVMASK] (ioINA, I_GETFNC (MB), AR); - reason = t2 >> IOT_V_REASON; - if (t2 & IOT_SKIP) { /* skip? */ - PC = NEWA (PC, PC + 1); - turnoff = 0; } - AR = t2 & DMASK; /* data */ - break; - -case 074: /* OTA */ - t2 = iotab[MB & DEVMASK] (ioOTA, I_GETFNC (MB), AR); - reason = t2 >> IOT_V_REASON; - if (t2 & IOT_SKIP) { /* skip? */ - PC = NEWA (PC, PC + 1); - turnoff = 0; } - break; - -/* Control */ - -case 000: - if ((MB & 1) == 0) { /* HLT */ - reason = STOP_HALT; - break; } - if (MB & m14) { /* SGL, DBL */ - if (cpu_unit.flags & UNIT_HSA) dp = (MB & m15)? 1: 0; - else reason = stop_inst; } - if (MB & m13) { /* DXA, EXA */ - if (!(cpu_unit.flags & UNIT_EXT)) reason = stop_inst; - else if (MB & m15) { /* EXA */ - ext = 1; - extoff_pending = 0; } /* DXA */ - else extoff_pending = 1; } - if (MB & m12) /* RMP */ - dev_ready = dev_ready & ~INT_MPE; - if (MB & m11) { /* SCA, INK */ - if (MB & m15) /* INK */ - AR = (C << 15) | (dp << 14) | (pme << 13) | (sc & 037); - else if (cpu_unit.flags & UNIT_HSA) /* SCA */ - AR = sc & 037; - else reason = stop_inst; } - else if (MB & m10) { /* NRM */ - if (cpu_unit.flags & UNIT_HSA) { - for (sc = 0; - (sc <= 32) && ((AR & SIGN) != ((AR << 1) & SIGN)); - sc++) { - AR = (AR & SIGN) | ((AR << 1) & MMASK) | - ((BR >> 14) & 1); - BR = (BR & SIGN) | ((BR << 1) & MMASK); } - sc = sc & 037; } - else reason = stop_inst; } - else if (MB & m9) { /* IAB */ - sc = BR; - BR = AR; - AR = sc; } - if (MB & m8) /* ENB */ - dev_ready = (dev_ready | INT_ON) & ~INT_NODEF; - if (MB & m7) /* INH */ - dev_ready = dev_ready & ~INT_ON; - break; - -/* Shift - - Shifts are microcoded as follows: - - op<7> = right/left - op<8> = long/short - op<9> = shift/rotate (rotate bits "or" into new position) - op<10> = logical/arithmetic - - If !op<7> && op<10> (right arithmetic), A<1> propagates rightward - If op<7> && op<10> (left arithmetic), C is set if A<1> changes state - If !op<8> && op<10> (long arithmetic), B<1> is skipped - - This microcoding "explains" how the 4 undefined opcodes actually work - 003 = long arith rotate right, skip B<1>, propagate A<1>, - bits rotated out "or" into A<1> - 007 = short arith rotate right, propagate A<1>, - bits rotated out "or" into A<1> - 013 = long arith rotate left, skip B<1>, C = overflow - 017 = short arith rotate left, C = overflow -*/ - -case 020: - C = 0; /* clear C */ - sc = 0; /* clear sc */ - if ((t1 = (-MB) & SHFMASK) == 0) break; /* shift count */ - switch (I_GETFNC (MB)) { /* case shift fnc */ - - case 000: /* LRL */ - if (t1 > 32) ut = 0; /* >32? all 0 */ - else { - ut = GETDBL_U (AR, BR); /* get A'B */ - C = (ut >> (t1 - 1)) & 1; /* C = last out */ - ut = ut >> t1; } /* log right */ - PUTDBL_U (ut); /* store A,B */ - break; - - case 001: /* LRS */ - if (t1 > 31) t1 = 31; /* limit to 31 */ - t2 = GETDBL_S (SEXT (AR), BR); /* get A'B signed */ - C = (t2 >> (t1 - 1)) & 1; /* C = last out */ - t2 = t2 >> t1; /* arith right */ - PUTDBL_S (t2); /* store A,B */ - break; - - case 002: /* LRR */ - t2 = t1 % 32; /* mod 32 */ - ut = GETDBL_U (AR, BR); /* get A'B */ - ut = (ut >> t2) | (ut << (32 - t2)); /* rot right */ - C = (ut >> 31) & 1; /* C = A<1> */ - PUTDBL_U (ut); /* store A,B */ - break; - - case 003: /* "long right arot" */ - if (reason = stop_inst) break; /* stop on undef? */ - for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ - C = BR & 1; /* C = last out */ - BR = (BR & SIGN) | ((AR & 1) << 14) | - ((BR & MMASK) >> 1); - AR = ((AR & SIGN) | (C << 15)) | (AR >> 1); } - break; - - case 004: /* LGR */ - if (t1 > 16) AR = 0; /* > 16? all 0 */ - else { - C = (AR >> (t1 - 1)) & 1; /* C = last out */ - AR = (AR >> t1) & DMASK; } /* log right */ - break; - - case 005: /* ARS */ - if (t1 > 16) t1 = 16; /* limit to 16 */ - C = ((SEXT (AR)) >> (t1 - 1)) & 1; /* C = last out */ - AR = ((SEXT (AR)) >> t1) & DMASK; /* arith right */ - break; - - case 006: /* ARR */ - t2 = t1 % 16; /* mod 16 */ - AR = ((AR >> t2) | (AR << (16 - t2))) & DMASK; - C = (AR >> 15) & 1; /* C = A<1> */ - break; - - case 007: /* "short right arot" */ - if (reason = stop_inst) break; /* stop on undef? */ - for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ - C = AR & 1; /* C = last out */ - AR = ((AR & SIGN) | (C << 15)) | (AR >> 1); } - break; - -/* Shift, continued */ - - case 010: /* LLL */ - if (t1 > 32) ut = 0; /* > 32? all 0 */ - else { - ut = GETDBL_U (AR, BR); /* get A'B */ - C = (ut >> (32 - t1)) & 1; /* C = last out */ - ut = ut << t1; } /* log left */ - PUTDBL_U (ut); /* store A,B */ - break; - - case 011: /* LLS */ - if (t1 > 31) t1 = 31; /* limit to 31 */ - t2 = GETDBL_S (SEXT (AR), BR); /* get A'B */ - t3 = t2 << t1; /* "arith" left */ - PUTDBL_S (t3); /* store A'B */ - if ((t2 >> (31 - t1)) != /* shf out = sgn? */ - ((AR & SIGN)? -1: 0)) C = 1; - break; - - case 012: /* LLR */ - t2 = t1 % 32; /* mod 32 */ - ut = GETDBL_U (AR, BR); /* get A'B */ - ut = (ut << t2) | (ut >> (32 - t2)); /* rot left */ - C = ut & 1; /* C = B<16> */ - PUTDBL_U (ut); /* store A,B */ - break; - - case 013: /* "long left arot" */ - if (reason = stop_inst) break; /* stop on undef? */ - for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ - AR = (AR << 1) | ((BR >> 14) & 1); - BR = (BR & SIGN) | ((BR << 1) & MMASK) | - ((AR >> 16) & 1); - if ((AR & SIGN) != ((AR >> 1) & SIGN)) C = 1; - AR = AR & DMASK; } - break; - - case 014: /* LGL */ - if (t1 > 16) AR = 0; /* > 16? all 0 */ - else { - C = (AR >> (16 - t1)) & 1; /* C = last out */ - AR = (AR << t1) & DMASK; } /* log left */ - break; - - case 015: /* ALS */ - if (t1 > 16) t1 = 16; /* limit to 16 */ - t2 = SEXT (AR); /* save AR */ - AR = (AR << t1) & DMASK; /* "arith" left */ - if ((t2 >> (16 - t1)) != /* shf out + sgn */ - ((AR & SIGN)? -1: 0)) C = 1; - break; - - case 016: /* ALR */ - t2 = t1 % 16; /* mod 16 */ - AR = ((AR << t2) | (AR >> (16 - t2))) & DMASK; - C = AR & 1; /* C = A<16> */ - break; - - case 017: /* "short left arot" */ - if (reason = stop_inst) break; /* stop on undef? */ - for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ - if ((AR & SIGN) != ((AR << 1) & SIGN)) C = 1; - AR = ((AR << 1) | (AR >> 15)) & DMASK; } - break; } /* end case fnc */ - break; - -/* Skip */ - -case 040: - skip = 0; - if (((MB & 000001) && C) || /* SSC */ - ((MB & 000002) && ss[3]) || /* SS4 */ - ((MB & 000004) && ss[2]) || /* SS3 */ - ((MB & 000010) && ss[1]) || /* SS2 */ - ((MB & 000020) && ss[0]) || /* SS1 */ - ((MB & 000040) && AR) || /* SNZ */ - ((MB & 000100) && (AR & 1)) || /* SLN */ - ((MB & 000200) && (TST_INTREQ (INT_MPE))) || /* SPS */ - ((MB & 000400) && (AR & SIGN))) skip = 1; /* SMI */ - if ((MB & 001000) == 0) skip = skip ^ 1; /* reverse? */ - PC = NEWA (PC, PC + skip); - break; - -/* Operate */ - -case 060: - if (MB == 0140024) AR = AR ^ SIGN; /* CHS */ - else if (MB == 0140040) AR = 0; /* CRA */ - else if (MB == 0140100) AR = AR & ~SIGN; /* SSP */ - else if (MB == 0140200) C = 0; /* RCB */ - else if (MB == 0140320) { /* CSA */ - C = (AR & SIGN) >> 15; - AR = AR & ~SIGN; } - else if (MB == 0140401) AR = AR ^ DMASK; /* CMA */ - else if (MB == 0140407) { /* TCA */ - AR = (-AR) & DMASK; - sc = 0; } - else if (MB == 0140500) AR = AR | SIGN; /* SSM */ - else if (MB == 0140600) C = 1; /* SCB */ - else if (MB == 0141044) AR = AR & 0177400; /* CAR */ - else if (MB == 0141050) AR = AR & 0377; /* CAL */ - else if (MB == 0141140) AR = AR >> 8; /* ICL */ - else if (MB == 0141206) AR = Add16 (AR, 1); /* AOA */ - else if (MB == 0141216) AR = Add16 (AR, C); /* ACA */ - else if (MB == 0141240) AR = (AR << 8) & DMASK; /* ICR */ - else if (MB == 0141340) /* ICA */ - AR = ((AR << 8) | (AR >> 8)) & DMASK; - else if (reason = stop_inst) break; - else AR = Operate (MB, AR); /* undefined */ - break; - } /* end case op */ -} /* end while */ - -saved_AR = AR & DMASK; -saved_BR = BR & DMASK; -saved_XR = XR & DMASK; -pcq_r->qptr = pcq_p; /* update pc q ptr */ -return reason; -} - -/* Effective address - - The effective address calculation consists of three phases: - - base address calculation: 0/pagenumber'displacement - - (extend): indirect address resolution - (non-extend): pre-indexing - - (extend): post-indexing - (non-extend): indirect address/post-indexing resolution - - In extend mode, address calculations are carried out to 16b - and masked to 15b at exit. In non-extend mode, address bits - <1:2> are preserved by the NEWA macro; address bit <1> is - masked at exit. -*/ - -t_stat Ea (int32 IR, int32 *addr) -{ -int32 i; -int32 Y = IR & (IA | DISP); /* ind + disp */ - -if (IR & SC) Y = ((PC - 1) & PAGENO) | Y; /* cur sec? + pageno */ -if (ext) { /* extend mode? */ - for (i = 0; (i < ind_max) && (Y & IA); i++) { /* resolve ind addr */ - Y = Read (Y & X_AMASK); } /* get ind addr */ - if (IR & IDX) Y = Y + XR; /* post-index */ - } /* end if ext */ -else { /* non-extend */ - Y = NEWA (PC, Y + ((IR & IDX)? XR: 0)); /* pre-index */ - for (i = 0; (i < ind_max) && (IR & IA); i++) { /* resolve ind addr */ - IR = Read (Y & X_AMASK); /* get ind addr */ - Y = NEWA (Y, IR + ((IR & IDX)? XR: 0)); } /* post-index */ - } /* end else */ -*addr = Y = Y & X_AMASK; /* return addr */ -if (dlog && sim_log && !turnoff) /* cycle log? */ - fprintf (sim_log, " EA= %06o [%06o]\n", Y, M[Y]); -if (i >= ind_max) return STOP_IND; /* too many ind? */ -return SCPE_OK; -} - -/* Write memory */ - -void Write (int32 val, int32 addr) -{ -if (((addr == 0) || (addr >= 020)) && MEM_ADDR_OK (addr)) - M[addr] = val; -return; -} - -/* Add */ - -int32 Add16 (int32 v1, int32 v2) -{ -int32 r = v1 + v2; - -C = 0; -if (((v1 ^ ~v2) & (v1 ^ r)) & SIGN) C = 1; -return (r & DMASK); -} - -int32 Add31 (int32 v1, int32 v2) -{ -int32 r = v1 + v2; - -C = 0; -if (((v1 ^ ~v2) & (v1 ^ r)) & (1u << 30)) C = 1; -return r; -} - -/* Unimplemented I/O device */ - -int32 undio (int32 op, int32 fnc, int32 val) -{ -return ((stop_dev << IOT_V_REASON) | val); -} - -/* Undefined operate instruction. This code is reached when the - opcode does not correspond to a standard operate instruction. - It simulates the behavior of the actual logic. - - An operate instruction executes in 4 or 6 phases. A 'normal' - instruction takes 4 phases: - - t1 t1 - t2/tlate t2/t2 extended into t3 - t3/tlate t3 - t4 t4 - - A '1.5 cycle' instruction takes 6 phases: - - t1 t1 - t2/tlate t2/t2 extended into t3 - t3/tlate t3 - t2/tlate 'special' t2/t2 extended into t3 - t3/tlate t3 - t4 t4 - - The key signals, by phase, are the following - - tlate EASTL enable A to sum leg 1 (else 0) - (((m12+m16)x!azzzz)+(m9+m11+azzzz) - EASBM enable 0 to sum leg 2 (else 177777) - (m9+m11+azzzz) - JAMKN jam carry network to 0 = force XOR - ((m12+m16)x!azzzz) - EIKI7 force carry into adder - ((m15x(C+!m13))x!JAMKN) - - t3 CLDTR set D to 177777 (always) - ESDTS enable adder sum to D (always) - SETAZ enable repeat cycle = set azzzz - (m8xm15) - - if azzzz { - t2 CLATR clear A register (due to azzzz) - EDAHS enable D high to A high register (due to azzzz) - EDALS enable D low to A low register (due to azzzz) - - tlate, t3 as above - } - - t4 CLATR clear A register - (m11+m15+m16) - CLA1R clear A1 register - (m10+m14) - EDAHS enable D high to A high register - ((m11xm14)+m15+m16) - EDALS enable D low to A low register - ((m11xm13)+m15+m16) - ETAHS enable D transposed to A high register - (m9xm11) - ETALS enable D transposed to A low register - (m10xm11) - EDA1R enable D1 to A1 register - ((m8xm10)+m14) - CBITL clear C, conditionally set C from adder output - (m9x!m11) - CBITG conditionally set C if D1 - (m10xm12xD1) - CBITE unconditionally set C - (m8xm9) -*/ - -int32 Operate (int32 MB, int32 AR) -{ -int32 D, jamkn, eiki7, easbm, eastl, setaz; -int32 clatr, cla1r, edahs, edals, etahs, etals, eda1r; -int32 cbitl, cbitg, cbite; -int32 aleg, bleg, ARx; - -/* Phase tlate */ - -ARx = AR; /* default */ -jamkn = (MB & (m12+m16)) != 0; /* m12+m16 */ -easbm = (MB & (m9+m11)) != 0; /* m9+m11 */ -eastl = jamkn || easbm; /* m9+m11+m12+m16 */ -setaz = (MB & (m8+m15)) == (m8+m15); /* m8xm15*/ -eiki7 = (MB & m15) && (C || !(MB & m13)); /* cin */ -aleg = eastl? AR: 0; /* a input */ -bleg = easbm? 0: DMASK; /* b input */ -if (jamkn) D = aleg ^ bleg; /* jammin? xor */ -else D = (aleg + bleg + eiki7) & DMASK; /* else add */ - -/* Possible repeat at end of tlate - special t2, repeat tlate */ - -if (setaz) { - ARx = D; /* forced: t2 */ - aleg = ARx; /* forced: tlate */ - bleg = 0; /* forced */ - jamkn = 0; /* forced */ - D = (aleg + bleg + eiki7) & DMASK; /* forced add */ - sc = 0; } /* ends repeat */ - -/* Phase t4 */ - -clatr = (MB & (m11+m15+m16)) != 0; /* m11+m15+m16 */ -cla1r = (MB & (m10+m14)) != 0; /* m10+m14 */ -edahs = ((MB & (m11+m14)) == (m11+m14)) || /* (m11xm14)+m15+m16 */ - (MB & (m15+m16)); -edals = ((MB & (m11+m13)) == (m11+m13)) || /* (m11xm13)+m15+m16 */ - (MB & (m15+m16)); -etahs = (MB & (m9+m11)) == (m9+m11); /* m9xm11 */ -etals = (MB & (m10+m11)) == (m10+m11); /* m10xm11 */ -eda1r = ((MB & (m8+m10)) == (m8+m10)) || (MB & m14); /* (m8xm10)+m14 */ -cbitl = (MB & (m9+m11)) == m9; /* m9x!m11 */ -cbite = (MB & (m8+m9)) == (m8+m9); /* m8xm9 */ -cbitg = (MB & (m10+m12)) == (m10+m12); /* m10xm12 */ - -if (clatr) ARx = 0; /* clear A */ -if (cla1r) ARx = ARx & ~SIGN; /* clear A1 */ -if (edahs) ARx = ARx | (D & 0177400); /* D hi to A hi */ -if (edals) ARx = ARx | (D & 0000377); /* D lo to A lo */ -if (etahs) ARx = ARx | ((D << 8) & 0177400); /* D lo to A hi */ -if (etals) ARx = ARx | ((D >> 8) & 0000377); /* D hi to A lo */ -if (eda1r) ARx = ARx | (D & SIGN); /* D1 to A1 */ -if (cbitl) { /* ovflo to C */ - -/* Overflow calculation. Cases: - - aleg bleg cin overflow - - 0 x x can't overflow - A 0 0 can't overflow - A -1 1 can't overflow - A 0 1 overflow if 77777->100000 - A -1 0 overflow if 100000->77777 -*/ - - if (!jamkn && - ((bleg && !eiki7 && (D == 0077777)) || - (!bleg && eiki7 && (D == 0100000)))) C = 1; - else C = 0; } -if (cbite || (cbitg && (D & SIGN))) C = 1; /* C = 1 */ -return ARx; -} - -/* Reset routines */ - -t_stat cpu_reset (DEVICE *dptr) -{ -saved_AR = saved_BR = saved_XR = 0; -C = 0; -dp = 0; -ext = pme = extoff_pending = 0; -dev_ready = dev_ready & ~INT_PENDING; -dev_enable = 0; -pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -int32 d; - -if (addr >= MEMSIZE) return SCPE_NXM; -if (addr == 0) d = saved_XR; -else d = M[addr]; -if (vptr != NULL) *vptr = d & DMASK; -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -if (addr == 0) saved_XR = val & DMASK; -else M[addr] = val & DMASK; -return SCPE_OK; -} - -/* Option processors */ - -t_stat cpu_set_noext (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (MEMSIZE > (NX_AMASK + 1)) return SCPE_ARG; -return SCPE_OK; -} - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0) || - (((cpu_unit.flags & UNIT_EXT) == 0) && (val > (NX_AMASK + 1)))) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; -if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_OK; -MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; -return SCPE_OK; -} diff --git a/H316/h316_defs.h b/H316/h316_defs.h deleted file mode 100644 index 240174c2..00000000 --- a/H316/h316_defs.h +++ /dev/null @@ -1,144 +0,0 @@ -/* h316_defs.h: Honeywell 316/516 simulator definitions - - Copyright (c) 1999-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 25-Apr-03 RMS Revised for extended file support -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_IODV 2 /* must be 2 */ -#define STOP_HALT 3 /* HALT */ -#define STOP_IBKPT 4 /* breakpoint */ -#define STOP_IND 5 /* indirect loop */ - -/* Memory */ - -#define MAXMEMSIZE 32768 /* max memory size */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define X_AMASK (MAXMEMSIZE - 1) /* ext address mask */ -#define NX_AMASK ((MAXMEMSIZE / 2) - 1) /* nx address mask */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) - -/* Architectural constants */ - -#define SIGN 0100000 /* sign */ -#define DMASK 0177777 /* data mask */ -#define MMASK (DMASK & ~SIGN) /* magnitude mask */ -#define XR M[0] -#define M_CLK 061 /* clock location */ -#define M_RSTINT 062 /* restrict int */ -#define M_INT 063 /* int location */ - -/* CPU options */ - -#define UNIT_V_EXT (UNIT_V_UF + 1) /* extended mem */ -#define UNIT_V_HSA (UNIT_V_UF + 2) /* high speed arith */ -#define UNIT_EXT (1u << UNIT_V_EXT) -#define UNIT_HSA (1u << UNIT_V_HSA) - -/* Instruction format */ - -#define I_M_OP 077 /* opcode */ -#define I_V_OP 10 -#define I_GETOP(x) (((x) >> I_V_OP) & I_M_OP) -#define I_M_FNC 017 /* function */ -#define I_V_FNC 6 -#define I_GETFNC(x) (((x) >> I_V_FNC) & I_M_FNC) -#define IA 0100000 /* indirect address */ -#define IDX 0040000 /* indexed */ -#define SC 0001000 /* sector */ -#define DISP 0000777 /* page displacement */ -#define PAGENO 0077000 /* page number */ -#define INCLRA (010 << I_V_FNC) /* INA clear A */ -#define DEVMASK 0000077 /* device mask */ -#define SHFMASK 0000077 /* shift mask */ - -/* I/O opcodes */ - -#define ioOCP 0 /* output control */ -#define ioSKS 1 /* skip if set */ -#define ioINA 2 /* input to A */ -#define ioOTA 3 /* output from A */ - -/* I/O devices */ - -#define PTR 001 /* paper tape reader */ -#define PTP 002 /* paper tape punch */ -#define LPT 003 /* line printer */ -#define TTY 004 /* console */ -#define CDR 005 /* card reader */ -#define MT 010 /* mag tape data */ -#define KEYS 020 /* keys (CPU) */ -#define FHD 022 /* fixed head disk */ -#define DMA 024 /* DMA control */ -#define DP 025 /* moving head disk */ -#define OPT 034 /* SKS/OCP option */ - -/* Interrupt flags, definitions correspond to SMK bits */ - -#define INT_V_CLK 0 /* clock */ -#define INT_V_MPE 1 /* parity error */ -#define INT_V_LPT 2 /* line printer */ -#define INT_V_CDR 4 /* card reader */ -#define INT_V_TTY 5 /* teletype */ -#define INT_V_PTP 6 /* paper tape punch */ -#define INT_V_PTR 7 /* paper tape reader */ -#define INT_V_FHD 8 /* fixed head disk */ -#define INT_V_DP 12 /* moving head disk */ -#define INT_V_MT 15 /* mag tape */ -#define INT_V_NODEF 16 /* int not deferred */ -#define INT_V_ON 17 /* int on */ - -/* I/O macros */ - -#define IOT_V_REASON 17 -#define IOT_V_SKIP 16 -#define IOT_SKIP (1u << IOT_V_SKIP) -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ -#define IOBADFNC(x) (((stop_inst) << IOT_V_REASON) | (x)) -#define IOSKIP(x) (IOT_SKIP | (x)) - -#define INT_CLK (1u << INT_V_CLK) -#define INT_MPE (1u << INT_V_MPE) -#define INT_LPT (1u << INT_V_LPT) -#define INT_CDR (1u << INT_V_CDR) -#define INT_TTY (1u << INT_V_TTY) -#define INT_PTP (1u << INT_V_PTP) -#define INT_PTR (1u << INT_V_PTR) -#define INT_FHD (1u << INT_V_FHD) -#define INT_DP (1u << INT_V_DP) -#define INT_MT (1u << INT_V_MT) -#define INT_NODEF (1u << INT_V_NODEF) -#define INT_ON (1u << INT_V_ON) -#define INT_PENDING (INT_ON | INT_NODEF) - -#define SET_READY(x) dev_ready = dev_ready | (x) -#define CLR_READY(x) dev_ready = dev_ready & ~(x) -#define TST_READY(x) ((dev_ready & (x)) != 0) -#define CLR_ENABLE(x) dev_enable = dev_enable & ~(x) -#define TST_INTREQ(x) ((dev_ready & dev_enable & (x)) != 0) diff --git a/H316/h316_doc.txt b/H316/h316_doc.txt deleted file mode 100644 index dc56fe0f..00000000 --- a/H316/h316_doc.txt +++ /dev/null @@ -1,320 +0,0 @@ -To: Users -From: Bob Supnik -Subj: H316 Simulator Usage -Date: 15-Jul-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - Original code published in 1993-2003, written by Robert M Supnik - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - -This memorandum documents the Honeywell 316/516 simulator. - - -1. Simulator Files - -The H316 requires the following files: - -sim/ sim_defs.h - sim_rev.h - sim_sock.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tmxr.c - -sim/h316/ h316_defs.h - h316_cpu.c - h316_lp.c - h316_stddev.c - h316_sys.c - -2. H316/H516 Features - -The Honeywell 316/516 simulator is configured as follows: - -device simulates -name(s) - -CPU H316/H516 CPU with 16/32KW memory -PTR 316/516-50 paper tape reader -PTP 316/516-52 paper tape punch -TTY 316/516-33 console terminal -CLK 316/516-12 real time clock -LPT 316/516 line printer - -The H316/H516 simulator implements several unique stop conditions: - - - decode of an undefined instruction, and STOP_INST is et - - reference to an undefined I/O device, and STOP_DEV is set - - more than INDMAX indirect references are detected during - memory reference address decoding - -The H316/H516 loader is not implemented. - -2.1 CPU - -CPU options include choice of instruction set and memory size. - - SET CPU HSA high speed arithmetic instructions - SET CPU NOHSA no high speed arithmetic instructions - SET CPU 4K set memory size = 4K - SET CPU 8K set memory size = 8K - SET CPU 12K set memory size = 12K - SET CPU 16K set memory size = 16K - SET CPU 24K set memory size = 24K - SET CPU 32K set memory size = 32K - -If memory size is being reduced, and the memory being truncated contains -non-zero data, the simulator asks for confirmation. Data in the truncated -portion of memory is lost. Initial memory size is 32K. - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - P 15 program counter - A 16 A register - B 16 B register - X 16 index register - SC 16 shift count - C 1 carry flag - EXT 1 extend flag - PME 1 previous mode extend flag - EXT_OFF 1 extend off pending flag - DP 1 double precision flag - SS1..4 1 sense switches 1..4 - ION 1 interrupts enabled - INODEF 1 interrupts not deferred - INTREQ 16 interrupt requests - DEVRDY 16 device ready flags (read only) - DEVENB 16 device interrupt enable flags (read only) - STOP_INST 1 stop on undefined instruction - STOP_DEV 1 stop on undefined device - INDMAX 1 indirect address limit - PCQ[0:63] 15 PC prior to last JMP, JSB, or interrupt; - most recent PC change first - WRU 8 interrupt character - -2.2 Programmed I/O Devices - -2.2.1 316/516-50 Paper Tape Reader (PTR) - -The paper tape reader (PTR) reads data from a disk file. The POS -register specifies the number of the next data item to be read. -Thus, by changing POS, the user can backspace or advance the reader. - -The paper tape reader supports the BOOT command. BOOT PTR copies the -absolute binary loader into memory and starts it running. - -The paper tape reader implements these registers: - - name size comments - - BUF 8 last data item processed - INTREQ 1 device interrupt request - READY 1 device ready - ENABLE 1 device interrupts enabled - POS 32 position in the input or output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - end of file 1 report error and stop - 0 out of tape or paper - - OS I/O error x report error and stop - -2.2.2 316/516-52 Paper Tape Punch (PTP) - -The paper tape punch (PTP) writes data to a disk file. The POS -register specifies the number of the next data item to be written. -Thus, by changing POS, the user can backspace or advance the punch. - -The paper tape punch implements these registers: - - name size comments - - BUF 8 last data item processed - INTREQ 1 device interrupt request - READY 1 device ready - ENABLE 1 device interrupts enabled - POWER 1 device powered up - POS 32 position in the input or output file - TIME 24 time from I/O initiation to interrupt - PWRTIME 24 time from I/O request to power up - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -2.2.3 316/516-33 Console Teletype (TTY) - -The Teletype units (TTY0, TTY1) can be set to one of three modes: -KSR, 7B, or 8B. In KSR mode, lower case input and output characters -are automatically converted to upper case, and the high order bit is -forced to one on input. In 7B mode, input and output characters are -masked to 7 bits. In 8B mode, characters are not modified. Changing -the mode of either unit changes both. The default mode is KSR. - -The Teletype reads from the console keyboard and writes to the -simulator console window. It implements these registers: - - name size comments - - BUF 8 last data item processed - MODE 1 read/write mode - INTREQ 1 device interrupt request - READY 1 device ready - ENABLE 1 device interrupts enabled - KPOS 32 number of characters input - KTIME 24 keyboard polling interval - TPOS 32 number of characters output - TTIME 24 time from I/O initiation to interrupt - -2.2.4 316/516-12 Real Time Clock (CLK) - -The real time clock (CLK) frequency can be adjusted as follows: - - SET CLK 60HZ set frequency to 60Hz - SET CLK 50HZ set frequency to 50Hz - -The default is 60Hz. - -The clock implements these registers: - - name size comments - - INTREQ 1 device interrupt request - READY 1 device ready - ENABLE 1 device interrupts enabled - TIME 24 clock interval - -The real-time clock autocalibrates; the clock interval is adjusted up or -down so that the clock tracks actual elapsed time. - -2.2.5 316/516 Line Printer (LPT) - -The line printer (LPT) writes data to a disk file. The POS register -specifies the number of the next data item to be written. Thus, -by changing POS, the user can backspace or advance the printer. - -The line printer implements these registers: - - name size comments - - WDPOS 6 word position in current scan - DRPOS 6 drum position - CRPOS 1 carriage position - XFER 1 transfer ready flag - PRDN 1 print done flag - INTREQ 1 device interrupt request - ENABLE 1 device interrupt enable - SVCST 2 service state - SVCCH 2 service channel - BUF 8 buffer - POS 32 number of characters output - XTIME 24 delay between transfers - ETIME 24 delay at end of scan - PTIME 24 delay for shuttle/line advance - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of paper - - OS I/O error x report error and stop - -2.3 Symbolic Display and Input - -The H316/H516 simulator implements symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as two character string - -m display instruction mnemonics - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or -a ASCII character - " or -c two character sixbit string - alphabetic instruction mnemonic - numeric octal number - -Instruction input uses standard H316/H516 assembler syntax. There are six -instruction classes: memory reference, I/O, control, shift, skip, and -operate. - -Memory reference instructions have the format - - memref{*} {C/Z} address{,1} - -where * signifies indirect, C a current sector reference, Z a sector zero -reference, and 1 indexed. The address is an octal number in the range 0 - -077777; if C or Z is specified, the address is a page offset in the range -0 - 0777. Normally, C is not needed; the simulator figures out from the -address what mode to use. However, when referencing memory outside the CPU, -there is no valid PC, and C must be used to specify current sector addressing. - -I/O instructions have the format - - io pulse+device - -The pulse+device is an octal number in the range 0 - 01777. - -Control and operate instructions consist of a single opcode - - opcode - -Shift instructions have the format - - shift n - -where n is an octal number in the range 0-77. - -Skip instructions have the format - - sub-op sub-op sub-op... - -The simulator checks that the combination of sub-opcodes is legal. diff --git a/H316/h316_lp.c b/H316/h316_lp.c deleted file mode 100644 index 7c17b74e..00000000 --- a/H316/h316_lp.c +++ /dev/null @@ -1,261 +0,0 @@ -/* h316_lp.c: Honeywell 316/516 line printer - - Copyright (c) 1999-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - lpt line printer - - 25-Apr-03 RMS Revised for extended file support - 30-May-02 RMS Widened POS to 32b - - The Series 16 line printer is an unbuffered Analex shuttle printer. - Because it was unbuffered, the CPU had to scan out an entire line's - worth of characters (60 words) for every character on the print drum - (64 characters). Because it was a shuttle printer, the entire - process must be repeated first for the odd columns and then for the - even columns. After scanning the odd columns, the printer carriage - shuttled right by one column; after scanning the even columns, the - carriage shuttled left. This halved the number of hammers required, - reducing cost but increasing mechanical complexity. - - The real printer is very timing dependent. If the CPU misses a - scan, then the wrong characters are printed. If the printer protocol - is violated, then results are unpredictable. The simulated printer - is much more forgiving. Rather than simulating the fixed drum and - hammer timing of the real printer, the simulator is driven by the - program's OTA instructions. If the program misses a time slot, the - simulator will still print the "correct" result. A timing based - simulation would be very hard to do in the absense of accurate - instruction timing. - - Printer state is maintained in a set of position and state variables: - - lpt_wdpos word count within a line scan (0-59) - lpt_drpos drum position (0-63) - lpt_crpos carriage position (0-1) - lpt_svcst service state (shuttle, paper advance) - lpt_svcch channel for paper advance (0 = no adv) - lpt_xfer transfer ready flag - lpt_prdn printing done flag -*/ - -#include "h316_defs.h" - -#define LPT_WIDTH 120 /* width */ -#define LPT_SCAN (LPT_WIDTH / 2) /* words/scan */ -#define LPT_DRUM 64 /* drum rows */ -#define LPT_SVCSH 01 /* shuttle */ -#define LPT_SVCPA 02 /* paper advance */ - -extern int32 dev_ready, dev_enable; -extern int32 stop_inst; - -int32 lpt_wdpos = 0; /* word position */ -int32 lpt_drpos = 0; /* drum position */ -int32 lpt_crpos = 0; /* carriage position */ -int32 lpt_svcst = 0; /* service state */ -int32 lpt_svcch = 0; /* service channel */ -int32 lpt_xfer = 0; /* transfer flag */ -int32 lpt_prdn = 1; /* printing done */ -char lpt_buf[LPT_WIDTH + 1] = { 0 }; /* line buffer */ -int32 lpt_xtime = 5; /* transfer time */ -int32 lpt_etime = 50; /* end of scan time */ -int32 lpt_ptime = 5000; /* paper adv time */ -int32 lpt_stopioe = 0; /* stop on error */ - -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_mod LPT modifiers - lpt_reg LPT register list -*/ - -UNIT lpt_unit = { UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0) }; - -REG lpt_reg[] = { - { DRDATA (WDPOS, lpt_wdpos, 6) }, - { DRDATA (DRPOS, lpt_drpos, 6) }, - { FLDATA (CRPOS, lpt_crpos, 0) }, - { FLDATA (XFER, lpt_xfer, 0) }, - { FLDATA (PRDN, lpt_prdn, 0) }, - { FLDATA (INTREQ, dev_ready, INT_V_LPT) }, - { FLDATA (ENABLE, dev_enable, INT_V_LPT) }, - { ORDATA (SVCST, lpt_svcst, 2) }, - { ORDATA (SVCCH, lpt_svcch, 2) }, - { BRDATA (BUF, lpt_buf, 8, 8, 120) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (XTIME, lpt_xtime, 24), PV_LEFT }, - { DRDATA (ETIME, lpt_etime, 24), PV_LEFT }, - { DRDATA (PTIME, lpt_ptime, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lpt_stopioe, 0) }, - { NULL } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lpt_reset, - NULL, NULL, NULL }; - -/* IO routine */ - -int32 lptio (int32 inst, int32 fnc, int32 dat) -{ -int32 chr; - -switch (inst) { /* case on opcode */ -case ioOCP: /* OCP */ - switch (fnc) { /* case on fnc */ - case 000: case 002: case 004: /* paper adv */ - lpt_svcst = lpt_svcst | LPT_SVCPA; /* set state */ - lpt_svcch = fnc >> 1; /* save channel */ - sim_activate (&lpt_unit, lpt_ptime); - CLR_READY (INT_LPT); /* clear int */ - break; - case 007: /* init scan */ - lpt_prdn = 0; /* clear pr done */ - lpt_wdpos = 0; /* init scan pos */ - if (!sim_is_active (&lpt_unit)) lpt_xfer = 1; - CLR_READY (INT_LPT); /* clear int */ - break; - default: - return IOBADFNC (dat); } - break; - -case ioSKS: /* SKS */ - switch (fnc) { /* case on fnc */ - case 000: /* if xfer rdy */ - if (lpt_xfer) return IOSKIP (dat); - break; - case 002: /* if !alarm */ - if (lpt_unit.flags & UNIT_ATT) return IOSKIP (dat); - break; - case 003: /* if odd col */ - if (lpt_crpos) return IOSKIP (dat); - break; - case 004: /* if !interrupt */ - if (!TST_INTREQ (INT_LPT)) return IOSKIP (dat); - break; - case 011: /* if line printed */ - if (lpt_prdn) return IOSKIP (dat); - break; - case 012: /* if !shuttling */ - if (!(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat); - break; - case 013: - if (lpt_prdn && !(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat); - break; - case 014: /* if !advancing */ - if (!(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat); - break; - case 015: - if (lpt_prdn && !(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat); - break; - case 016: - if (!(lpt_svcst & (LPT_SVCSH | LPT_SVCPA))) return IOSKIP (dat); - break; - case 017: - if (lpt_prdn && !(lpt_svcst & (LPT_SVCSH | LPT_SVCPA))) - return IOSKIP (dat); - break; - default: - return IOBADFNC (dat); } - break; - -case ioOTA: /* OTA */ - if (fnc) return IOBADFNC (dat); /* only fnc 0 */ - if (lpt_xfer) { /* xfer ready? */ - lpt_xfer = 0; /* clear xfer */ - chr = (dat >> (lpt_crpos? 0: 8)) & 077; /* get 6b char */ - if (chr == lpt_drpos) { /* match drum pos? */ - if (chr < 040) chr = chr | 0100; - lpt_buf[2 * lpt_wdpos + lpt_crpos] = chr; } - lpt_wdpos++; /* adv scan pos */ - if (lpt_wdpos >= LPT_SCAN) { /* end of scan? */ - lpt_wdpos = 0; /* reset scan pos */ - lpt_drpos++; /* adv drum pos */ - if (lpt_drpos >= LPT_DRUM) { /* end of drum? */ - lpt_drpos = 0; /* reset drum pos */ - lpt_crpos = lpt_crpos ^ 1; /* shuttle */ - lpt_svcst = lpt_svcst | LPT_SVCSH; - sim_activate (&lpt_unit, lpt_ptime); - } /* end if shuttle */ - else sim_activate (&lpt_unit, lpt_etime); - } /* end if endscan */ - else sim_activate (&lpt_unit, lpt_xtime); - return IOSKIP (dat); } /* skip return */ - break; } /* end case op */ -return dat; -} - -/* Unit service */ - -t_stat lpt_svc (UNIT *uptr) -{ -int32 i; -static const char *lpt_cc[] = { - "\r", - "\n", - "\n\f", - "\n" }; - -if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); -lpt_xfer = 1; -if (lpt_svcst & LPT_SVCSH) { /* shuttling */ - SET_READY (INT_LPT); /* interrupt */ - if (lpt_crpos == 0) lpt_prdn = 1; } -if (lpt_svcst & LPT_SVCPA) { /* paper advance */ - SET_READY (INT_LPT); /* interrupt */ - for (i = LPT_WIDTH - 1; i >= 0; i++) { - if (lpt_buf[i] != ' ') break; } - lpt_buf[i + 1] = 0; - fputs (lpt_buf, uptr->fileref); /* output buf */ - fputs (lpt_cc[lpt_svcch & 03], uptr->fileref); /* output eol */ - uptr->pos = ftell (uptr->fileref); /* update pos */ - for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buf */ - } -lpt_svcst = 0; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ -int32 i; - -lpt_wdpos = lpt_drpos = lpt_crpos = 0; /* clear positions */ -lpt_svcst = lpt_svcch = 0; /* idle state */ -lpt_xfer = 0; /* not rdy to xfer */ -lpt_prdn = 1; /* printing done */ -for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buffer */ -lpt_buf[LPT_WIDTH] = 0; -CLR_READY (INT_LPT); /* clear int, enb */ -CLR_ENABLE (INT_LPT); -sim_cancel (&lpt_unit); /* deactivate unit */ -return SCPE_OK; -} diff --git a/H316/h316_stddev.c b/H316/h316_stddev.c deleted file mode 100644 index 2ff32fbe..00000000 --- a/H316/h316_stddev.c +++ /dev/null @@ -1,539 +0,0 @@ -/* h316_stddev.c: Honeywell 316/516 standard devices - - Copyright (c) 1999-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - ptr 316/516-50 paper tape reader - ptp 316/516-52 paper tape punch - tty 316/516-33 teleprinter - clk/options 316/516-12 real time clocks/internal options - - 25-Apr-03 RMS Revised for extended file support - 01-Mar-03 RMS Added SET/SHOW CLK FREQ support - 22-Dec-02 RMS Added break support - 01-Nov-02 RMS Added 7b/8b support to terminal - 30-May-02 RMS Widened POS to 32b - 03-Nov-01 RMS Implemented upper case for console output - 29-Nov-01 RMS Added read only unit support - 07-Sep-01 RMS Moved function prototypes -*/ - -#include "h316_defs.h" -#include - -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_KSR (1 << UNIT_V_KSR) - -extern uint16 M[]; -extern int32 PC; -extern int32 stop_inst; -extern int32 C, dp, ext, extoff_pending, sc; -extern int32 dev_ready, dev_enable; -extern UNIT cpu_unit; - -int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */ -int32 ptp_power = 0, ptp_ptime; /* punch power, time */ -int32 tty_mode = 0, tty_buf = 0; /* tty mode, buf */ -int32 clk_tps = 60; /* ticks per second */ - -t_stat ptr_svc (UNIT *uptr); -t_stat ptr_reset (DEVICE *dptr); -t_stat ptr_boot (int32 unitno, DEVICE *dptr); -t_stat ptp_svc (UNIT *uptr); -t_stat ptp_reset (DEVICE *dptr); -t_stat tti_svc (UNIT *uptr); -t_stat tto_svc (UNIT *uptr); -t_stat tty_reset (DEVICE *dptr); -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat clk_svc (UNIT *uptr); -t_stat clk_reset (DEVICE *dptr); -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc); - -/* PTR data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit descriptor - ptr_mod PTR modifiers - ptr_reg PTR register list -*/ - -UNIT ptr_unit = { - UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), - SERIAL_IN_WAIT }; - -REG ptr_reg[] = { - { ORDATA (BUF, ptr_unit.buf, 8) }, - { FLDATA (READY, dev_ready, INT_V_PTR) }, - { FLDATA (ENABLE, dev_enable, INT_V_PTR) }, - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptr_stopioe, 0) }, - { NULL } }; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - &ptr_boot, NULL, NULL }; - -/* PTP data structures - - ptp_dev PTP device descriptor - ptp_unit PTP unit descriptor - ptp_mod PTP modifiers - ptp_reg PTP register list -*/ - -UNIT ptp_unit = { - UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG ptp_reg[] = { - { ORDATA (BUF, ptp_unit.buf, 8) }, - { FLDATA (READY, dev_ready, INT_V_PTP) }, - { FLDATA (ENABLE, dev_enable, INT_V_PTP) }, - { FLDATA (POWER, ptp_power, 0) }, - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, - { DRDATA (PWRTIME, ptp_ptime, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptp_stopioe, 0) }, - { NULL } }; - - -DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptp_reset, - NULL, NULL, NULL }; - -/* TTY data structures - - tty_dev TTY device descriptor - tty_unit TTY unit descriptor - tty_reg TTY register list - tty_mod TTy modifiers list -*/ - -#define TTI 0 -#define TTO 1 - -UNIT tty_unit[] = { - { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }, - { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT } }; - -REG tty_reg[] = { - { ORDATA (BUF, tty_buf, 8) }, - { FLDATA (MODE, tty_mode, 0) }, - { FLDATA (READY, dev_ready, INT_V_TTY) }, - { FLDATA (ENABLE, dev_enable, INT_V_TTY) }, - { DRDATA (KPOS, tty_unit[TTI].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (KTIME, tty_unit[TTI].wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPOS, tty_unit[TTO].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TTIME, tty_unit[TTO].wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB tty_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, - { 0 } }; - -DEVICE tty_dev = { - "TTY", tty_unit, tty_reg, tty_mod, - 2, 10, 31, 1, 8, 8, - NULL, NULL, &tty_reset, - NULL, NULL, NULL }; - -/* CLK data structures - - clk_dev CLK device descriptor - clk_unit CLK unit descriptor - clk_mod CLK modifiers - clk_reg CLK register list -*/ - -UNIT clk_unit = { - UDATA (&clk_svc, 0, 0), 16000 }; - -REG clk_reg[] = { - { FLDATA (READY, dev_ready, INT_V_CLK) }, - { FLDATA (ENABLE, dev_enable, INT_V_CLK) }, - { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO }, - { NULL } }; - -MTAB clk_mod[] = { - { MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL, - NULL, &clk_show_freq, NULL }, - { 0 } }; - -DEVICE clk_dev = { - "CLK", &clk_unit, clk_reg, clk_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &clk_reset, - NULL, NULL, NULL }; - -/* Paper tape reader: IO routine */ - -int32 ptrio (int32 inst, int32 fnc, int32 dat) -{ -switch (inst) { /* case on opcode */ -case ioOCP: /* OCP */ - if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */ - if (fnc) sim_cancel (&ptr_unit); /* fnc 1? stop */ - else sim_activate (&ptr_unit, ptr_unit.wait); /* fnc 0? start */ - break; -case ioSKS: /* SKS */ - if (fnc & 013) return IOBADFNC (dat); /* only fnc 0,4 */ - if (((fnc == 0) && TST_READY (INT_PTR)) || /* fnc 0? skip rdy */ - ((fnc == 4) && !TST_INTREQ (INT_PTR))) /* fnc 4? skip !int */ - return IOSKIP (dat); - break; -case ioINA: /* INA */ - if (fnc & 007) return IOBADFNC (dat); /* only fnc 0,10 */ - if (TST_READY (INT_PTR)) { /* ready? */ - CLR_READY (INT_PTR); /* clear ready */ - return IOSKIP (ptr_unit.buf | dat); } /* ret buf, skip */ - break; } /* end case op */ -return dat; -} - -/* Unit service */ - -t_stat ptr_svc (UNIT *uptr) -{ -int32 temp; - -if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptr_stopioe, SCPE_UNATT); -if ((temp = getc (ptr_unit.fileref)) == EOF) { /* read byte */ - if (feof (ptr_unit.fileref)) { - if (ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } - else perror ("PTR I/O error"); - clearerr (ptr_unit.fileref); - return SCPE_IOERR; } -SET_READY (INT_PTR); /* set ready flag */ -ptr_unit.buf = temp & 0377; /* get byte */ -ptr_unit.pos = ftell (ptr_unit.fileref); /* update pos */ -sim_activate (&ptr_unit, ptr_unit.wait); /* reactivate */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptr_reset (DEVICE *dptr) -{ -CLR_READY (INT_PTR); /* clear ready, enb */ -CLR_ENABLE (INT_PTR); -ptr_unit.buf = 0; /* clear buffer */ -sim_cancel (&ptr_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Paper tape reader bootstrap routine */ - -#define PBOOT_START 1 -#define PBOOT_SIZE (sizeof (pboot) / sizeof (int32)) - -static const int32 pboot[] = { - 0010057, /* STA 57 */ - 0030001, /* OCP 1 */ - 0131001, /* READ, INA 1001 */ - 0002003, /* JMP READ */ - 0101040, /* SNZ */ - 0002003, /* JMP READ */ - 0010000, /* STA 0 */ - 0131001, /* READ1, INA 1001 */ - 0002010, /* JMP READ1 */ - 0041470, /* LGL 8 */ - 0130001, /* READ2, INA 1 */ - 0002013, /* JMP READ2 */ - 0110000, /* STA* 0 */ - 0024000, /* IRS 0 */ - 0100040 /* SZE */ -}; - -t_stat ptr_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; - -for (i = 0; i < PBOOT_SIZE; i++) /* copy bootstrap */ - M[PBOOT_START + i] = pboot[i]; -PC = PBOOT_START; -return SCPE_OK; -} - -/* Paper tape punch: IO routine */ - -int32 ptpio (int32 inst, int32 fnc, int32 dat) -{ -switch (inst) { /* case on opcode */ -case ioOCP: /* OCP */ - if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */ - if (fnc) { /* fnc 1? pwr off */ - CLR_READY (INT_PTP); /* not ready */ - ptp_power = 0; /* turn off power */ - sim_cancel (&ptp_unit); } /* stop punch */ - else if (ptp_power == 0) /* fnc 0? start */ - sim_activate (&ptp_unit, ptp_ptime); - break; -case ioSKS: /* SKS */ - if ((fnc & 012) || (fnc == 005)) /* only 0, 1, 4 */ - return IOBADFNC (dat); - if (((fnc == 00) && TST_READY (INT_PTP)) || /* fnc 0? skip rdy */ - ((fnc == 01) /* fnc 1? skip ptp on */ - && (ptp_power || sim_is_active (&ptp_unit))) || - ((fnc == 04) && !TST_INTREQ (INT_PTP))) /* fnc 4? skip !int */ - return IOSKIP (dat); - break; -case ioOTA: /* OTA */ - if (fnc) return IOBADFNC (dat); /* only fnc 0 */ - if (TST_READY (INT_PTP)) { /* if ptp ready */ - CLR_READY (INT_PTP); /* clear ready */ - ptp_unit.buf = dat & 0377; /* store byte */ - sim_activate (&ptp_unit, ptp_unit.wait); - return IOSKIP (dat); } /* skip return */ - break; } -return dat; -} - -/* Unit service */ - -t_stat ptp_svc (UNIT *uptr) -{ - -SET_READY (INT_PTP); /* set flag */ -if (ptp_power == 0) { /* power on? */ - ptp_power = 1; /* ptp is ready */ - return SCPE_OK; } -if ((ptp_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptp_stopioe, SCPE_UNATT); -if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { /* output byte */ - perror ("PTP I/O error"); - clearerr (ptp_unit.fileref); - return SCPE_IOERR; } -ptp_unit.pos = ftell (ptp_unit.fileref); /* update pos */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptp_reset (DEVICE *dptr) -{ -CLR_READY (INT_PTP); /* clear ready, enb */ -CLR_ENABLE (INT_PTP); -ptp_power = 0; /* power off */ -ptp_unit.buf = 0; /* clear buffer */ -sim_cancel (&ptp_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Terminal: IO routine */ - -int32 ttyio (int32 inst, int32 fnc, int32 dat) -{ -switch (inst) { /* case on opcode */ -case ioOCP: /* OCP */ - if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */ - if (fnc && (tty_mode == 0)) { /* input to output? */ - if (!sim_is_active (&tty_unit[TTO])) /* set ready */ - SET_READY (INT_TTY); - tty_mode = 1; } /* mode is output */ - else if ((fnc == 0) && tty_mode) { /* output to input? */ - CLR_READY (INT_TTY); /* clear ready */ - tty_mode = 0; } /* mode is input */ - break; -case ioSKS: /* SKS */ - if (fnc & 012) return IOBADFNC (dat); /* fnc 0,1,4,5 */ - if (((fnc == 0) && TST_READY (INT_TTY)) || /* fnc 0? skip rdy */ - ((fnc == 1) && /* fnc 1? skip !busy */ - tty_mode && !sim_is_active (&tty_unit[TTO])) || - ((fnc == 4) && !TST_INTREQ (INT_TTY)) || /* fnc 4? skip !int */ - ((fnc == 5) && /* fnc 5? skip !xoff */ - !tty_mode && ((tty_buf & 0177) == 023))) - return IOSKIP (dat); - break; -case ioINA: /* INA */ - if (fnc & 005) return IOBADFNC (dat); /* only 0,2,10,12 */ - if (TST_READY (INT_TTY)) { /* ready? */ - if (tty_mode == 0) CLR_READY (INT_TTY); /* inp? clear rdy */ - return IOSKIP (dat | - (tty_buf & ((fnc & 002)? 077: 0377))); } - break; -case ioOTA: - if (fnc & 015) return IOBADFNC (dat); /* only 0,2 */ - if (TST_READY (INT_TTY)) { /* ready? */ - tty_buf = dat & 0377; /* store char */ - if (fnc & 002) { /* binary mode? */ - tty_buf = tty_buf | 0100; /* set ch 7 */ - if (tty_buf & 040) tty_buf = tty_buf & 0277; } - if (tty_mode) { - sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); - CLR_READY (INT_TTY); } - return IOSKIP (dat); } - break; } /* end case op */ -return dat; -} - -/* Unit service routines */ - -t_stat tti_svc (UNIT *uptr) -{ -int32 out, c; - -sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* continue poll */ -if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -out = c & 0177; /* mask echo to 7b */ -if (c & SCPE_BREAK) c = 0; /* break? */ -else if (tty_unit[TTI].flags & UNIT_KSR) { /* KSR? */ - if (islower (out)) out = toupper (out); /* cvt to UC */ - c = out | 0200; } /* add TTY bit */ -else c = c & ((tty_unit[TTI].flags & UNIT_8B)? 0377: 0177); -if (tty_mode == 0) { /* input mode? */ - tty_buf = c; /* put char in buf */ - tty_unit[TTI].pos = tty_unit[TTI].pos + 1; - SET_READY (INT_TTY); /* set flag */ - if (out) sim_putchar (out); } /* echo */ -return SCPE_OK; -} - -t_stat tto_svc (UNIT *uptr) -{ -int32 c; -t_stat r; - -SET_READY (INT_TTY); /* set done flag */ -if (tty_unit[TTO].flags & UNIT_KSR) { /* UC only? */ - c = tty_buf & 0177; /* mask to 7b */ - if (islower (c)) c = toupper (c); } /* cvt to UC */ -else c = tty_buf & ((tty_unit[TTO].flags & UNIT_8B)? 0377: 0177); -if ((r = sim_putchar (c)) != SCPE_OK) return r; /* output char */ -tty_unit[TTO].pos = tty_unit[TTO].pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tty_reset (DEVICE *dptr) -{ -CLR_READY (INT_TTY); /* clear ready, enb */ -CLR_ENABLE (INT_TTY); -tty_mode = 0; /* mode = input */ -tty_buf = 0; -sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */ -sim_cancel (&tty_unit[TTO]); /* cancel output */ -return SCPE_OK; -} - -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -tty_unit[TTI].flags = (tty_unit[TTI].flags & ~(UNIT_KSR | UNIT_8B)) | val; -tty_unit[TTO].flags = (tty_unit[TTO].flags & ~(UNIT_KSR | UNIT_8B)) | val; -return SCPE_OK; -} - -/* Clock/options: IO routine */ - -int32 clkio (int32 inst, int32 fnc, int32 dat) -{ -switch (inst) { /* case on opcode */ -case ioOCP: /* OCP */ - if (fnc & 015) return IOBADFNC (dat); /* only fnc 0,2 */ - CLR_READY (INT_CLK); /* reset ready */ - if (fnc) sim_cancel (&clk_unit); /* fnc = 2? stop */ - else { /* fnc = 0? */ - if (!sim_is_active (&clk_unit)) - sim_activate (&clk_unit, /* activate */ - sim_rtc_init (clk_unit.wait)); } /* init calibr */ - break; -case ioSKS: /* SKS */ - if (fnc == 0) { /* clock skip !int */ - if (!TST_INTREQ (INT_CLK)) return IOSKIP (dat); } - else if ((fnc & 007) == 002) { /* mem parity? */ - if (((fnc == 002) && !TST_READY (INT_MPE)) || - ((fnc == 012) && TST_READY (INT_MPE))) - return IOSKIP (dat); } - else return IOBADFNC (dat); /* invalid fnc */ - break; -case ioOTA: /* OTA */ - if (fnc == 000) dev_enable = dat; /* SMK */ - else if (fnc == 010) { /* OTK */ - C = (dat >> 15) & 1; /* set C */ - if (cpu_unit.flags & UNIT_HSA) /* HSA included? */ - dp = (dat >> 14) & 1; /* set dp */ - if (cpu_unit.flags & UNIT_EXT) { /* ext opt? */ - if (dat & 020000) { /* ext set? */ - ext = 1; /* yes, set */ - extoff_pending = 0; } - else extoff_pending = 1; } /* no, clr later */ - sc = dat & 037; } /* set sc */ - else return IOBADFNC (dat); - break; } -return dat; -} - -/* Unit service */ - -t_stat clk_svc (UNIT *uptr) -{ - -M[M_CLK] = M[M_CLK + 1] & DMASK; /* increment mem ctr */ -if (M[M_CLK] == 0) SET_READY (INT_CLK); /* = 0? set flag */ -sim_activate (&clk_unit, sim_rtc_calb (clk_tps)); /* reactivate */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat clk_reset (DEVICE *dptr) -{ -CLR_READY (INT_CLK); /* clear ready, enb */ -CLR_ENABLE (INT_CLK); -sim_cancel (&clk_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Set frequency */ - -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; -clk_tps = val; -return SCPE_OK; -} - -/* Show frequency */ - -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, (clk_tps == 50)? "50Hz": "60Hz"); -return SCPE_OK; -} diff --git a/H316/h316_sys.c b/H316/h316_sys.c deleted file mode 100644 index a280d4a1..00000000 --- a/H316/h316_sys.c +++ /dev/null @@ -1,346 +0,0 @@ -/* h316_sys.c: Honeywell 316/516 simulator interface - - Copyright (c) 1999-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 17-Sep-01 RMS Removed multiconsole support -*/ - -#include "h316_defs.h" -#include - -extern DEVICE cpu_dev; -extern UNIT cpu_unit; -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE tty_dev, lpt_dev; -extern DEVICE clk_dev; -extern REG cpu_reg[]; -extern uint16 M[]; -extern int32 sim_switches; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax maximum number of words for examine/deposit - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "H316"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 1; - -DEVICE *sim_devices[] = { &cpu_dev, - &ptr_dev, &ptp_dev, - &tty_dev, &lpt_dev, - &clk_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unimplemented instruction", - "Unimplemented I/O device", - "HALT instruction", - "Breakpoint", - "Indirect address loop" }; - -/* Binary loader - - Tbs. -*/ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -return SCPE_FMT; -} - -/* Symbol tables */ - -#define I_V_FL 16 /* flag start */ -#define I_M_FL 07 /* flag mask */ -#define I_V_NPN 0 /* no operand */ -#define I_V_MRF 1 /* mem ref */ -#define I_V_MRX 2 /* mem ref, no idx */ -#define I_V_IOT 3 /* I/O */ -#define I_V_SHF 4 /* shift */ -#define I_V_SK0 5 /* skip 0 */ -#define I_V_SK1 6 /* skip 1 */ -#define I_NPN (I_V_NPN << I_V_FL) -#define I_MRF (I_V_MRF << I_V_FL) -#define I_MRX (I_V_MRX << I_V_FL) -#define I_IOT (I_V_IOT << I_V_FL) -#define I_SHF (I_V_SHF << I_V_FL) -#define I_SK0 (I_V_SK0 << I_V_FL) -#define I_SK1 (I_V_SK1 << I_V_FL) - -static const int32 masks[] = { - 0177777, 0136000, 0176000, 0176000, - 0177700, 0177000, 0177000 }; - -static const char *opcode[] = { - "HLT", "SGL", "DBL", - "DXA", "EXA", "RMP", - "SCA", "INK", "NRM", - "IAB", "ENB", "INH", "ERM", - "CHS", "CRA", "SSP", - "RCB", "CSA", "CMA", - "TCA", "SSM", "SCB", - "CAR", "CAL", "ICL", - "AOA", "ACA", "ICR", "ICA", - "NOP", "SKP", "SSR", "SSS", - "JMP", "JMP*", - "LDA", "LDA*", "ANA", "ANA*", - "STA", "STA*", "ERA", "ERA*", - "ADD", "ADD*", "SUB", "SUB*", - "JST", "JST*", "CAS", "CAS*", - "IRS", "IRS*", "IMA", "IMA*", - "MPY", "MPY*", "DIV", "DIV*", - "STX", "STX*", "LDX", "LDX*", - "LRL", "LRS", "LRR", - "LGR", "ARS", "ARR", - "LLL", "LLS", "LLR", - "LGL", "ALS", "ALR", - "OCP", "SKS", "INA", "OTA", - "SMK", - "SPL", "SPN", "SLZ", /* encode only */ - "SZE", "SR1", "SR2", - "SR3", "SR4", "SRC", - "SMI", "SPS", "SLN", - "SNZ", "SS1", "SS2", - "SS3", "SS4", "SSC", - NULL, NULL, /* decode only */ - NULL }; - -static const int32 opc_val[] = { - 0000000+I_NPN, 0000005+I_NPN, 0000007+I_NPN, - 0000011+I_NPN, 0000013+I_NPN, 0000021+I_NPN, - 0000041+I_NPN, 0000043+I_NPN, 0000101+I_NPN, - 0000201+I_NPN, 0000401+I_NPN, 0001001+I_NPN, 0001401+I_NPN, - 0140024+I_NPN, 0140040+I_NPN, 0140100+I_NPN, - 0140200+I_NPN, 0140320+I_NPN, 0140401+I_NPN, - 0140407+I_NPN, 0140500+I_NPN, 0140600+I_NPN, - 0141044+I_NPN, 0141050+I_NPN, 0141140+I_NPN, - 0141206+I_NPN, 0141216+I_NPN, 0141240+I_NPN, 0141340+I_NPN, - 0101000+I_NPN, 0100000+I_NPN, 0100036+I_NPN, 0101036+I_NPN, - 0002000+I_MRF, 0102000+I_MRF, - 0004000+I_MRF, 0104000+I_MRF, 0006000+I_MRF, 0106000+I_MRF, - 0010000+I_MRF, 0110000+I_MRF, 0012000+I_MRF, 0112000+I_MRF, - 0014000+I_MRF, 0114000+I_MRF, 0016000+I_MRF, 0116000+I_MRF, - 0020000+I_MRF, 0120000+I_MRF, 0022000+I_MRF, 0122000+I_MRF, - 0024000+I_MRF, 0124000+I_MRF, 0026000+I_MRF, 0126000+I_MRF, - 0034000+I_MRF, 0134000+I_MRF, 0036000+I_MRF, 0136000+I_MRF, - 0032000+I_MRX, 0132000+I_MRX, 0072000+I_MRX, 0172000+I_MRX, - 0040000+I_SHF, 0040100+I_SHF, 0040200+I_SHF, - 0040400+I_SHF, 0040500+I_SHF, 0040600+I_SHF, - 0041000+I_SHF, 0041100+I_SHF, 0041200+I_SHF, - 0041400+I_SHF, 0041500+I_SHF, 0041600+I_SHF, - 0030000+I_IOT, 0070000+I_IOT, 0130000+I_IOT, 0170000+I_IOT, - 0170000+I_IOT, - 0100400+I_SK0, 0100200+I_SK0, 0100100+I_SK0, /* encode only */ - 0100040+I_SK0, 0100020+I_SK0, 0100010+I_SK0, - 0100004+I_SK0, 0100002+I_SK0, 0100001+I_SK0, - 0101400+I_SK1, 0101200+I_SK1, 0101100+I_SK1, - 0101040+I_SK1, 0101020+I_SK1, 0101010+I_SK1, - 0101004+I_SK1, 0101002+I_SK1, 0101001+I_SK1, - 0100000+I_SK0, 0101000+I_SK1, /* decode only */ - -1 }; - -/* Operate decode - - Inputs: - *of = output stream - inst = mask bits - class = instruction class code - sp = space needed? - Outputs: - status = space needed -*/ - -int32 fprint_opr (FILE *of, int32 inst, int32 class, int32 sp) -{ -int32 i, j; - -for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - if ((j == class) && (opc_val[i] & inst)) { /* same class? */ - inst = inst & ~opc_val[i]; /* mask bit set? */ - fprintf (of, (sp? " %s": "%s"), opcode[i]); - sp = 1; } } -return sp; -} - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current PC - *val = pointer to data - *uptr = pointer to unit - sw = switches - Outputs: - return = status code -*/ - -#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, i, j, inst, disp; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -inst = val[0]; -if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; - fprintf (of, FMTASC (inst & 0177)); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* characters? */ - fprintf (of, FMTASC ((inst >> 8) & 0177)); - fprintf (of, FMTASC (inst & 0177)); - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; - -/* Instruction decode */ - -for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */ - - switch (j) { /* case on class */ - case I_V_NPN: /* no operands */ - fprintf (of, "%s", opcode[i]); /* opcode */ - break; - case I_V_MRF: case I_V_MRX: /* mem ref */ - disp = inst & DISP; /* displacement */ - fprintf (of, "%s ", opcode[i]); /* opcode */ - if (inst & SC) { /* current sector? */ - if (cflag) fprintf (of, "%-o", (addr & PAGENO) | disp); - else fprintf (of, "C %-o", disp); } - else fprintf (of, "%-o", disp); /* sector zero */ - if ((j == I_V_MRF) && (inst & IDX)) fprintf (of, ",1"); - break; - case I_V_IOT: /* I/O */ - disp = inst & 01777; /* pulse+dev */ - fprintf (of, "%s %o", opcode[i], disp); - break; - case I_V_SHF: /* shift */ - disp = -inst & SHFMASK; /* shift count */ - fprintf (of, "%s %o", opcode[i], disp); - break; - case I_V_SK0: case I_V_SK1: /* skips */ - fprint_opr (of, inst & 0777, j, 0); /* print skips */ - break; } /* end case */ - return SCPE_OK; } /* end if */ - } /* end for */ -return SCPE_ARG; -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = error status -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 cflag, d, i, j, k; -t_stat r; -char gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ -if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (t_value) cptr[0] & 0177; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* char string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (((t_value) cptr[0] & 0177) << 8) | - ((t_value) cptr[1] & 0177); - return SCPE_OK; } - -/* Instruction parse */ - -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; -if (opcode[i] == NULL) return SCPE_ARG; -val[0] = opc_val[i] & DMASK; /* get value */ -j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - -switch (j) { /* case on class */ -case I_V_NPN: /* no operand */ - break; -case I_V_IOT: /* IOT */ - cptr = get_glyph (cptr, gbuf, 0); /* get pulse+dev */ - d = get_uint (gbuf, 8, 01777, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | d; - break; -case I_V_SHF: /* shift */ - cptr = get_glyph (cptr, gbuf, 0); /* get shift count */ - d = get_uint (gbuf, 8, SHFMASK, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (-d & SHFMASK); /* store 2's comp */ - break; -case I_V_MRF: case I_V_MRX: /* mem ref */ - cptr = get_glyph (cptr, gbuf, ','); /* get next field */ - if (k = (strcmp (gbuf, "C") == 0)) { /* C specified? */ - val[0] = val[0] | SC; - cptr = get_glyph (cptr, gbuf, 0); } - else if (k = (strcmp (gbuf, "Z") == 0)) { /* Z specified? */ - cptr = get_glyph (cptr, gbuf, ','); } - d = get_uint (gbuf, 8, X_AMASK, &r); /* construe as addr */ - if (r != SCPE_OK) return SCPE_ARG; - if (d <= DISP) val[0] = val[0] | d; /* fits? */ - else if (cflag && !k && (((addr ^ d) & PAGENO) == 0)) - val[0] = val[0] | (d & DISP) | SC; - else return SCPE_ARG; - if ((j == I_V_MRX) || (*cptr == 0)) break; /* indexed? */ - cptr = get_glyph (cptr, gbuf, 0); - d = get_uint (gbuf, 8, 1, &r); /* get tag */ - if (r != SCPE_OK) return SCPE_ARG; - if (d) val[0] = val[0] | IDX; /* or in index */ - break; -case I_V_SK0: case I_V_SK1: /* skips */ - for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; - cptr = get_glyph (cptr, gbuf, 0)) { - for (i = 0; (opcode[i] != NULL) && - (strcmp (opcode[i], gbuf) != 0) ; i++) ; - k = opc_val[i] & DMASK; - if ((opcode[i] == NULL) || (((k ^ val[0]) & 0177000) != 0)) - return SCPE_ARG; - val[0] = val[0] | k; } - break; } /* end case */ -if (*cptr != 0) return SCPE_ARG; /* junk at end? */ -return SCPE_OK; -} diff --git a/HP2100/hp2100_cpu.c b/HP2100/hp2100_cpu.c deleted file mode 100644 index b28972c4..00000000 --- a/HP2100/hp2100_cpu.c +++ /dev/null @@ -1,2602 +0,0 @@ -/* hp2100_cpu.c: HP 2100 CPU simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 12-Mar-03 RMS Added logical name support - 02-Feb-03 RMS Fixed last cycle bug in DMA output (found by Mike Gemeny) - 22-Nov-02 RMS Added 21MX IOP support - 24-Oct-02 RMS Fixed bugs in IOP and extended instructions - Fixed bugs in memory protection and DMS - Added clock calibration - 25-Sep-02 RMS Fixed bug in DMS decode (found by Robert Alan Byer) - 26-Jul-02 RMS Restructured extended instructions, added IOP support - 22-Mar-02 RMS Changed to allocate memory array dynamically - 11-Mar-02 RMS Cleaned up setjmp/auto variable interaction - 17-Feb-02 RMS Added DMS support - Fixed bugs in extended instructions - 03-Feb-02 RMS Added terminal multiplexor support - Changed PCQ macro to use unmodified PC - Fixed flop restore logic (found by Bill McDermith) - Fixed SZx,SLx,RSS bug (found by Bill McDermith) - Added floating point support - 16-Jan-02 RMS Added additional device support - 07-Jan-02 RMS Fixed DMA register tables (found by Bill McDermith) - 07-Dec-01 RMS Revised to use breakpoint package - 03-Dec-01 RMS Added extended SET/SHOW support - 10-Aug-01 RMS Removed register in declarations - 26-Nov-00 RMS Fixed bug in dual device number routine - 21-Nov-00 RMS Fixed bug in reset routine - 15-Oct-00 RMS Added dynamic device number support - - The register state for the HP 2116 CPU is: - - AR<15:0> A register - addressable as location 0 - BR<15:0> B register - addressable as location 1 - PC<14:0> P register (program counter) - SR<15:0> S register - E extend flag (carry out) - O overflow flag - - The 2100 adds memory protection logic: - - mp_fence<14:0> memory fence register - mp_viol<15:0> memory protection violation register (F register) - - The 21MX adds a pair of index registers and memory expansion logic: - - XR<15:0> X register - YR<15:0> Y register - dms_sr<15:0> dynamic memory system status register - dms_vr<15:0> dynamic memory system violation register - - The original HP 2116 has four instruction formats: memory reference, - shift, alter/skip, and I/O. The HP 2100 added extended memory reference - and extended arithmetic. The HP21MX added extended byte, bit, and word - instructions as well as extended memory. - - The memory reference format is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| op |cp| offset | memory reference - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <14:11> mnemonic action - - 0010 AND A = A & M[MA] - 0011 JSB M[MA] = P, P = MA + 1 - 0100 XOR A = A ^ M[MA] - 0101 JMP P = MA - 0110 IOR A = A | M[MA] - 0111 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0 - 1000 ADA A = A + M[MA] - 1001 ADB B = B + M[MA] - 1010 CPA skip if A != M[MA] - 1011 CPB skip if B != M[MA] - 1100 LDA A = M[MA] - 1101 LDB B = M[MA] - 1110 STA M[MA] = A - 1111 STB M[MA] = B - - <15,10> mode action - - 0,0 page zero direct MA = IR<9:0> - 0,1 current page direct MA = PC<14:0>'IR,9:0> - 1,0 page zero indirect MA = M[IR<9:0>] - 1,1 current page indirect MA = M[PC<14:10>'IR<9:0>] - - Memory reference instructions can access an address space of 32K words. - An instruction can directly reference the first 1024 words of memory - (called page zero), as well as 1024 words of the current page; it can - indirectly access all 32K. -*/ - -/* The shift format is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 0 0 0|ab| 0|s1| op1 |ce|s2|sl| op2 | shift - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | \---+---/ | | | \---+---/ - | | | | | | | - | | | | | | +---- shift 2 opcode - | | | | | +---------- skip if low bit == 0 - | | | | +------------- shift 2 enable - | | | +---------------- clear Extend - | | +---------------------- shift 1 opcode - | +---------------------------- shift 1 enable - +---------------------------------- A/B select - - The alter/skip format is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 0 0 0|ab| 1|regop| e op|se|ss|sl|in|sz|rs| alter/skip - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | \-+-/ \-+-/ | | | | | | - | | | | | | | | +- reverse skip sense - | | | | | | | +---- skip if register == 0 - | | | | | | +------- increment register - | | | | | +---------- skip if low bit == 0 - | | | | +------------- skip if sign bit == 0 - | | | +---------------- skip if Extend == 0 - | | +--------------------- clr/com/set Extend - | +--------------------------- clr/com/set register - +---------------------------------- A/B select - - The I/O transfer format is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 0 0 0|ab| 1|hc| opcode | device | I/O transfer - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | \---+---/\-------+-------/ - | | | | - | | | +--------- device select - | | +---------------------- opcode - | +---------------------------- hold/clear flag - +---------------------------------- A/B select - - The IO transfer instruction controls the specified device. - Depending on the opcode, the instruction may set or clear - the device flag, start or stop I/O, or read or write data. -*/ - -/* The 2100 added an extended memory reference instruction; - the 21MX added extended arithmetic, operate, byte, word, - and bit instructions. Note that the HP 21xx is, despite - the right-to-left bit numbering, a big endian system. - Bits <15:8> are byte 0, and bits <7:0> are byte 1. - - - The extended memory reference format (HP 2100) is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 0 0 0|op| 0| opcode | extended mem ref - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| operand address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The extended arithmetic format (HP 2100) is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 0 0 0 0 0|dr| 0 0| opcode |shift count| extended arithmetic - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The extended operate format (HP 21MX) is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 0 0 0|op| 0| 1 1 1 1 1| opcode | extended operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The extended byte and word format (HP 21MX) is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 0 0 0 1 0 1 1 1 1 1 1| opcode | extended byte/word - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| operand address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0| - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The extended bit operate format (HP 21MX) is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 0 0 0 1 0 1 1 1 1 1 1 1| opcode | extended bit operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| operand address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| operand address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -*/ - -/* This routine is the instruction decode routine for the HP 2100. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - breakpoint encountered - infinite indirection loop - unimplemented instruction and stop_inst flag set - unknown I/O device and stop_dev flag set - I/O error in I/O simulator - - 2. Interrupts. I/O devices are modelled as four parallel arrays: - - device commands as bit array dev_cmd[2][31..0] - device flags as bit array dev_flg[2][31..0] - device flag buffers as bit array dev_fbf[2][31..0] - device controls as bit array dev_ctl[2][31..0] - - The HP 2100 interrupt structure is based on flag, flag buffer,. - and control. If a device flag is set, the flag buffer is set, - the control bit is set, and the device is the highest priority - on the interrupt chain, it requests an interrupt. When the - interrupt is acknowledged, the flag buffer is cleared, preventing - further interrupt requests from that device. The combination of - flag and control set blocks interrupts from lower priority devices. - - Command plays no direct role in interrupts. The command flop - tells whether a device is active. It is set by STC and cleared - by CLC; it is also cleared when the device flag is set. Simple - devices don't need to track command separately from control. - - 3. Non-existent memory. On the HP 2100, reads to non-existent memory - return zero, and writes are ignored. In the simulator, the - largest possible memory is instantiated and initialized to zero. - Thus, only writes need be checked against actual memory size. - - 4. Adding I/O devices. These modules must be modified: - - hp2100_defs.h add interrupt request definition - hp2100_sys.c add sim_devices table entry - - 5. Instruction interruptibility. The simulator is fast enough, compared - to the run-time of the longest instructions, for interruptibility not - to matter. But the HP diagnostics explicitly test interruptibility in - EIS and DMS instructions, and long indirect address chains. Accordingly, - the simulator does "just enough" to pass these tests. In particular, if - an interrupt is pending but deferred at the beginning of an interruptible - instruction, the interrupt is taken at the appropriate point; but there - is no testing for new interrupts during execution (that is, the event - timer is not called). -*/ - -#include "hp2100_defs.h" -#include - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = err_PC - -#define UNIT_V_2100 (UNIT_V_UF + 0) /* 2100 */ -#define UNIT_V_21MX (UNIT_V_UF + 1) /* 21MX */ -#define UNIT_V_EAU (UNIT_V_UF + 2) /* EAU */ -#define UNIT_V_FP (UNIT_V_UF + 3) /* FP */ -#define UNIT_V_MPR (UNIT_V_UF + 4) /* mem prot */ -#define UNIT_V_DMS (UNIT_V_UF + 5) /* DMS */ -#define UNIT_V_IOP (UNIT_V_UF + 6) /* 2100 IOP */ -#define UNIT_V_IOPX (UNIT_V_UF + 7) /* 21MX IOP */ -#define UNIT_V_MSIZE (UNIT_V_UF + 8) /* dummy mask */ -#define UNIT_2100 (1 << UNIT_V_2100) -#define UNIT_21MX (1 << UNIT_V_21MX) -#define UNIT_EAU (1 << UNIT_V_EAU) -#define UNIT_FP (1 << UNIT_V_FP) -#define UNIT_MPR (1 << UNIT_V_MPR) -#define UNIT_DMS (1 << UNIT_V_DMS) -#define UNIT_IOP (1 << UNIT_V_IOP) -#define UNIT_IOPX (1 << UNIT_V_IOPX) -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -#define MOD_2116 1 -#define MOD_2100 2 -#define MOD_21MX 4 - -#define ABORT(val) longjmp (save_env, (val)) - -#define DMAR0 1 -#define DMAR1 2 - -uint16 *M = NULL; /* memory */ -uint32 saved_AR = 0; /* A register */ -uint32 saved_BR = 0; /* B register */ -uint32 PC = 0; /* P register */ -uint32 SR = 0; /* S register */ -uint32 XR = 0; /* X register */ -uint32 YR = 0; /* Y register */ -uint32 E = 0; /* E register */ -uint32 O = 0; /* O register */ -uint32 dev_cmd[2] = { 0 }; /* device command */ -uint32 dev_ctl[2] = { 0 }; /* device control */ -uint32 dev_flg[2] = { 0 }; /* device flags */ -uint32 dev_fbf[2] = { 0 }; /* device flag bufs */ -struct DMA dmac[2] = { { 0 }, { 0 } }; /* DMA channels */ -uint32 ion = 0; /* interrupt enable */ -uint32 ion_defer = 0; /* interrupt defer */ -uint32 intaddr = 0; /* interrupt addr */ -uint32 mp_fence = 0; /* mem prot fence */ -uint32 mp_viol = 0; /* mem prot viol reg */ -uint32 mp_mevff = 0; /* mem exp (dms) viol */ -uint32 mp_evrff = 1; /* update mp_viol */ -uint32 err_PC = 0; /* error PC */ -uint32 dms_enb = 0; /* dms enable */ -uint32 dms_ump = 0; /* dms user map */ -uint32 dms_sr = 0; /* dms status reg */ -uint32 dms_vr = 0; /* dms violation reg */ -uint32 dms_map[MAP_NUM * MAP_LNT] = { 0 }; /* dms maps */ -uint32 iop_sp = 0; /* iop stack */ -uint32 ind_max = 16; /* iadr nest limit */ -uint32 stop_inst = 1; /* stop on ill inst */ -uint32 stop_dev = 0; /* stop on ill dev */ -uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -uint32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -jmp_buf save_env; /* abort handler */ - -struct opt_table { /* options table */ - int32 optf; - int32 cpuf; }; - -static struct opt_table opt_val[] = { - { UNIT_EAU, MOD_2116 }, - { UNIT_FP, MOD_2100 }, - { UNIT_MPR, MOD_2100 | MOD_21MX }, - { UNIT_DMS, MOD_21MX }, - { UNIT_IOP, MOD_2100 | MOD_21MX }, - { 0, 0 } }; - -extern int32 sim_interval; -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern FILE *sim_log; -extern DEVICE *sim_devices[]; - -t_stat Ea (uint32 IR, uint32 *addr, uint32 irq); -t_stat Ea1 (uint32 *addr, uint32 irq); -uint8 ReadB (uint32 addr); -uint8 ReadBA (uint32 addr); -uint16 ReadW (uint32 addr); -uint16 ReadWA (uint32 addr); -uint32 ReadF (uint32 addr); -uint16 ReadIO (uint32 addr, uint32 map); -void WriteB (uint32 addr, uint32 dat); -void WriteBA (uint32 addr, uint32 dat); -void WriteW (uint32 addr, uint32 dat); -void WriteWA (uint32 addr, uint32 dat); -void WriteIO (uint32 addr, uint32 dat, uint32 map); -t_stat iogrp (uint32 ir, uint32 iotrap); -uint32 dms (uint32 va, uint32 map, uint32 prot); -uint32 dms_io (uint32 va, uint32 map); -void mp_dms_jmp (uint32 va); -uint16 dms_rmap (uint32 mapi); -void dms_wmap (uint32 mapi, uint32 dat); -void dms_viol (uint32 va, uint32 st); -uint32 dms_upd_sr (void); -uint32 shift (uint32 inval, uint32 flag, uint32 oper); -uint32 calc_dma (void); -uint32 calc_int (void); -void dma_cycle (uint32 chan, uint32 map); -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat dma0_reset (DEVICE *dptr); -t_stat dma1_reset (DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc); -t_bool dev_conflict (void); - -extern uint32 f_as (uint32 op, t_bool sub); -extern uint32 f_mul (uint32 op); -extern uint32 f_div (uint32 op); -extern uint32 f_fix (void); -extern uint32 f_flt (void); -extern int32 clk_delay (int32 flg); - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifiers list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, VASIZE) }; - -REG cpu_reg[] = { - { ORDATA (P, PC, 15) }, - { ORDATA (A, saved_AR, 16) }, - { ORDATA (B, saved_BR, 16) }, - { ORDATA (X, XR, 16) }, - { ORDATA (Y, YR, 16) }, - { ORDATA (S, SR, 16) }, - { ORDATA (F, mp_fence, 15) }, - { FLDATA (E, E, 0) }, - { FLDATA (O, O, 0) }, - { FLDATA (ION, ion, 0) }, - { FLDATA (ION_DEFER, ion_defer, 0) }, - { ORDATA (IADDR, intaddr, 6) }, - { FLDATA (MPCTL, dev_ctl[PRO/32], INT_V (PRO)) }, - { FLDATA (MPFLG, dev_flg[PRO/32], INT_V (PRO)) }, - { FLDATA (MPFBF, dev_fbf[PRO/32], INT_V (PRO)) }, - { ORDATA (MPVR, mp_viol, 16) }, - { FLDATA (MPMEV, mp_mevff, 0) }, - { FLDATA (MPEVR, mp_evrff, 0) }, - { FLDATA (DMSENB, dms_enb, 0) }, - { FLDATA (DMSCUR, dms_ump, VA_N_PAG) }, - { ORDATA (DMSSR, dms_sr, 16) }, - { ORDATA (DMSVR, dms_vr, 16) }, - { BRDATA (DMSMAP, dms_map, 8, PA_N_SIZE, MAP_NUM * MAP_LNT) }, - { ORDATA (IOPSP, iop_sp, 16) }, - { FLDATA (STOP_INST, stop_inst, 0) }, - { FLDATA (STOP_DEV, stop_dev, 1) }, - { DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT }, - { BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { ORDATA (WRU, sim_int_char, 8) }, - { ORDATA (HCMD, dev_cmd[0], 32), REG_HRO }, - { ORDATA (LCMD, dev_cmd[1], 32), REG_HRO }, - { ORDATA (HCTL, dev_ctl[0], 32), REG_HRO }, - { ORDATA (LCTL, dev_ctl[1], 32), REG_HRO }, - { ORDATA (HFLG, dev_flg[0], 32), REG_HRO }, - { ORDATA (LFLG, dev_flg[1], 32), REG_HRO }, - { ORDATA (HFBF, dev_fbf[0], 32), REG_HRO }, - { ORDATA (LFBF, dev_fbf[1], 32), REG_HRO }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP+UNIT_IOPX, - 0, NULL, "2116", NULL }, - { UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP+UNIT_IOPX, - UNIT_2100+UNIT_EAU, NULL, "2100", NULL }, - { UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP+UNIT_IOPX, - UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS, NULL, "21MX", NULL }, - { UNIT_2100+UNIT_21MX, 0, "2116", NULL, NULL }, - { UNIT_2100+UNIT_21MX, UNIT_2100, "2100", NULL, NULL }, - { UNIT_2100+UNIT_21MX, UNIT_21MX, "21MX", NULL, NULL }, - { UNIT_EAU, UNIT_EAU, "EAU", "EAU", &cpu_set_opt, - NULL, (void *) UNIT_EAU }, - { UNIT_EAU, 0, "no EAU", "NOEAU", &cpu_set_opt, - NULL, (void *) UNIT_EAU }, - { UNIT_FP, UNIT_FP, "FP", "FP", &cpu_set_opt, - NULL, (void *) UNIT_FP }, - { UNIT_FP, 0, "no FP", "NOFP", &cpu_set_opt, - NULL, (void *) UNIT_FP }, - { UNIT_MPR, UNIT_MPR, "MPR", "MPR", &cpu_set_opt, - NULL, (void *) UNIT_MPR }, - { UNIT_MPR, 0, "no MPR", "NOMPR", &cpu_set_opt, - NULL, (void *) UNIT_MPR }, - { UNIT_DMS, UNIT_DMS, "DMS", "DMS", &cpu_set_opt, - NULL, (void *) UNIT_DMS }, - { UNIT_DMS, 0, "no DMS", "NODMS", &cpu_set_opt, - NULL, (void *) UNIT_DMS }, - { UNIT_MSIZE, 2, NULL, "IOP", &cpu_set_opt, - NULL, (void *) UNIT_IOP }, - { UNIT_IOP+UNIT_IOPX, UNIT_IOP, "IOP", NULL, NULL }, - { UNIT_IOP+UNIT_IOPX, UNIT_IOPX, "IOP", NULL, NULL }, - { UNIT_IOP+UNIT_IOPX, 0, "no IOP", "NOIOP", &cpu_set_opt, - NULL, (void *) UNIT_IOP }, - { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, - { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, - { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, - { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, - { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size }, - { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size }, - { UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size }, - { UNIT_MSIZE, 524288, NULL, "512K", &cpu_set_size }, - { UNIT_MSIZE, 1048576, NULL, "1024K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, 15, 1, 8, 16, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -/* DMA controller data structures - - dmax_dev DMAx device descriptor - dmax_reg DMAx register list -*/ - -UNIT dma0_unit = { UDATA (NULL, 0, 0) }; - -REG dma0_reg[] = { - { FLDATA (CMD, dev_cmd[DMA0/32], INT_V (DMA0)) }, - { FLDATA (CTL, dev_ctl[DMA0/32], INT_V (DMA0)) }, - { FLDATA (FLG, dev_flg[DMA0/32], INT_V (DMA0)) }, - { FLDATA (FBF, dev_fbf[DMA0/32], INT_V (DMA0)) }, - { ORDATA (CW1, dmac[0].cw1, 16) }, - { ORDATA (CW2, dmac[0].cw2, 16) }, - { ORDATA (CW3, dmac[0].cw3, 16) }, - { NULL } }; - -DEVICE dma0_dev = { - "DMA0", &dma0_unit, dma0_reg, NULL, - 1, 8, 1, 1, 8, 16, - NULL, NULL, &dma0_reset, - NULL, NULL, NULL }; - -UNIT dma1_unit = { UDATA (NULL, 0, 0) }; - -REG dma1_reg[] = { - { FLDATA (CMD, dev_cmd[DMA1/32], INT_V (DMA1)) }, - { FLDATA (CTL, dev_ctl[DMA1/32], INT_V (DMA1)) }, - { FLDATA (FLG, dev_flg[DMA1/32], INT_V (DMA1)) }, - { FLDATA (FBF, dev_fbf[DMA1/32], INT_V (DMA1)) }, - { ORDATA (CW1, dmac[1].cw1, 16) }, - { ORDATA (CW2, dmac[1].cw2, 16) }, - { ORDATA (CW3, dmac[1].cw3, 16) }, - { NULL } }; - -DEVICE dma1_dev = { - "DMA1", &dma1_unit, dma1_reg, NULL, - 1, 8, 1, 1, 8, 16, - NULL, NULL, &dma1_reset, - NULL, NULL, NULL }; - -/* Extended instruction decode tables */ - -#define E_V_FL 0 /* flags */ -#define E_M_FL 0xFF -#define E_FP (UNIT_FP >> (UNIT_V_UF - E_V_FL)) -#define E_21MX (UNIT_21MX >> (UNIT_V_UF - E_V_FL)) -#define E_DMS (UNIT_DMS >> (UNIT_V_UF - E_V_FL)) -#define E_IOP (UNIT_IOP >> (UNIT_V_UF - E_V_FL)) -#define E_IOPX (UNIT_IOPX >> (UNIT_V_UF - E_V_FL)) -#define E_V_TY 8 /* type */ -#define E_M_TY 0xF -#define E_NO 0 /* no operands */ -#define E_CN 1 /* PC+1: count */ -#define E_AD 2 /* PC+1: addr */ -#define E_AA 3 /* PC+1,2: addr */ -#define E_AC 4 /* PC+1: addr, +2: count */ -#define E_AZ 5 /* PC+1: addr, +2: zero */ -#define ET_NO (E_NO << E_V_TY) -#define ET_AD (E_AD << E_V_TY) -#define ET_AA (E_AA << E_V_TY) -#define ET_CN (E_CN << E_V_TY) -#define ET_AC (E_AC << E_V_TY) -#define ET_AZ (E_AZ << E_V_TY) -#define E_V_TYI 12 /* type if 2100 IOP */ -#define E_GETFL(x) (((x) >> E_V_FL) & E_M_FL) -#define E_GETTY(f,x) (((x) >> \ - ((((f) & E_IOP) && (cpu_unit.flags & UNIT_IOP))? \ - E_V_TYI: E_V_TY)) & E_M_TY) -#define F_NO E_FP | ET_NO -#define F_MR E_FP | ET_AD -#define X_NO E_21MX | ET_NO -#define X_MR E_21MX | ET_AD -#define X_AA E_21MX | ET_AA -#define X_AZ E_21MX | ET_AZ -#define D_NO E_DMS | ET_NO -#define D_MR E_DMS | ET_AD -#define D_AA E_DMS | ET_AA -#define M_NO E_IOPX | ET_NO -#define M_CN E_IOPX | ET_CN -#define M_AC E_IOPX | ET_AC -#define I_NO E_IOP | (ET_NO << (E_V_TYI - E_V_TY)) -#define I_CN E_IOP | (ET_CN << (E_V_TYI - E_V_TY)) -#define I_AC E_IOP | (ET_AC << (E_V_TYI - E_V_TY)) -#define I_AZ E_IOP | (ET_AZ << (E_V_TYI - E_V_TY)) - -static const uint32 e_inst[512] = { - F_MR | I_AC,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* FAD/ILIST */ - F_MR | I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, /* FSB/LAI- */ - I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, - F_MR | I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, /* FMP/LAI+ */ - I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, - F_MR | I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, /* FDV/SAI- */ - I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, - F_NO | I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, /* FIX/SAI+ */ - I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, - F_NO | I_AZ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* FLT/MBYTE */ - 0,0,0,0,0,0,0,0,I_CN,0,0,0,0,0,0,0, /* CRC */ - I_CN,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* TRSLT */ - I_AZ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* WMOVE */ - I_NO,I_NO,I_NO,I_NO,0,0,0,0,0,0,0,0,0,0,0,0, /* READF,PFRIO,PFREI,PFREX */ - I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,I_NO, /* ENQ,PENQ */ - I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* DEQ */ - I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* SBYTE */ - I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* LBYTE */ - I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* REST */ - 0,0,I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0, /* SAVE */ - M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO, /* LAI-/SAI- */ - M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO, - M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO, /* LAI+/SAI+ */ - M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0440 */ - M_CN,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_CN, /* CRC,REST,READF,INS,ENQ,PENQ,DEQ,TR */ - M_AC,M_NO,M_NO,M_NO,M_NO,0,0,0, /* ILIST,PFREI,PFREX,PFRIO,SAVE */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0500 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0520 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0540 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0560 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0600 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0620 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0640 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0660 */ - D_NO,D_NO,D_NO,D_NO,D_NO,D_NO,D_NO,D_NO, /* XMM,test,MBI,MBF,MBW,MWI,MWF,MWW */ - D_NO,D_NO,D_NO,D_NO,D_MR,D_AA,D_NO,D_NO, /* SY*,US*,PA*,PB*,SSM,JRS,nop,nop */ - D_NO,D_NO,D_NO,D_NO,D_MR,D_MR,D_MR,D_NO, /* XMM,XMS,XM*,nop,XL*,XS*,XC*,LF* */ - D_NO,D_NO,D_MR,D_MR,D_MR,D_MR,D_MR,D_MR, /* RS*,RV*,DJP,DJS,SJP,SJS,UJP,UJS */ - X_MR,X_NO,X_MR,X_MR,X_NO,X_MR,X_MR,X_NO, /* S*X,C*X,L*X,STX,CX*,LDX,ADX,X*X */ - X_MR,X_NO,X_MR,X_MR,X_NO,X_MR,X_MR,X_NO, /* S*Y,C*Y,L*Y,STY,CY*,LDY,ADY,X*Y */ - X_NO,X_NO,X_MR,X_NO,X_NO,X_AZ,X_AZ,X_NO, /* ISX,DSX,JLY,LBT,SBT,MBT,CBT,SFB */ - X_NO,X_NO,X_MR,X_AA,X_AA,X_AA,X_AZ,X_AZ }; /* ISY,DSY,JPY,SBS,CBS,TBS,CMW,MVW */ - -/* Interrupt defer table */ - -static const int32 defer_tab[] = { 0, 1, 1, 1, 0, 0, 0, 1 }; - -/* Device dispatch table */ - -uint32 devdisp (uint32 devno, uint32 inst, uint32 IR, uint32 outdat); -int32 cpuio (int32 op, int32 IR, int32 outdat); -int32 ovfio (int32 op, int32 IR, int32 outdat); -int32 pwrio (int32 op, int32 IR, int32 outdat); -int32 proio (int32 op, int32 IR, int32 outdat); -int32 dmsio (int32 op, int32 IR, int32 outdat); -int32 dmpio (int32 op, int32 IR, int32 outdat); -int32 nulio (int32 op, int32 IR, int32 outdat); - -int32 (*dtab[64])() = { - &cpuio, &ovfio, &dmsio, &dmsio, &pwrio, &proio, &dmpio, &dmpio, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; - -t_stat sim_instr (void) -{ -uint32 intrq, dmarq; /* set after setjmp */ -t_stat reason; /* set after setjmp */ -int32 i, dev; /* temp */ -DEVICE *dptr; /* temp */ -DIB *dibp; /* temp */ -int abortval; - -/* Restore register state */ - -if (dev_conflict ()) return SCPE_STOP; /* check consistency */ -AR = saved_AR & DMASK; /* restore reg */ -BR = saved_BR & DMASK; -err_PC = PC = PC & VAMASK; /* load local PC */ -reason = 0; - -/* Restore I/O state */ - -for (i = VARDEV; i <= I_DEVMASK; i++) dtab[i] = NULL; /* clr disp table */ -dev_cmd[0] = dev_cmd[0] & M_FXDEV; /* clear dynamic info */ -dev_ctl[0] = dev_ctl[0] & M_FXDEV; -dev_flg[0] = dev_flg[0] & M_FXDEV; -dev_fbf[0] = dev_fbf[0] & M_FXDEV; -dev_cmd[1] = dev_ctl[1] = dev_flg[1] = dev_fbf[1] = 0; -for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru dev */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if (dibp && !(dptr->flags & DEV_DIS)) { /* exist, enabled? */ - dev = dibp->devno; /* get dev # */ - if (dibp->cmd) { setCMD (dev); } /* restore cmd */ - if (dibp->ctl) { setCTL (dev); } /* restore ctl */ - if (dibp->flg) { setFLG (dev); } /* restore flg */ - clrFBF (dev); /* also sets fbf */ - if (dibp->fbf) { setFBF (dev); } /* restore fbf */ - dtab[dev] = dibp->iot; } } /* set I/O dispatch */ -sim_rtc_init (clk_delay (0)); /* recalibrate clock */ - -/* Abort handling - - If an abort occurs in memory protection, the relocation routine - executes a longjmp to this area OUTSIDE the main simulation loop. - Memory protection errors are the only sources of aborts in the - HP 2100. All referenced variables must be globals, and all sim_instr - scoped automatics must be set after the setjmp. -*/ - -abortval = setjmp (save_env); /* set abort hdlr */ -if (abortval != 0) { /* mem mgt abort? */ - setFLG (PRO); /* req interrupt */ - mp_evrff = 0; } /* block mp_viol upd */ -dmarq = calc_dma (); /* recalc DMA masks */ -intrq = calc_int (); /* recalc interrupts */ - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ -uint32 IR, MA, M1, absel, v1, v2, t; -uint32 fop, eop, etype, eflag; -uint32 skip, mapi, mapj, qs, rs; -uint32 awc, sc, wc, hp, tp, iotrap; -int32 sop1, sop2; - -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; - dmarq = calc_dma (); /* recalc DMA reqs */ - intrq = calc_int (); } /* recalc interrupts */ - -if (dmarq) { - if (dmarq & DMAR0) dma_cycle (0, PAMAP); /* DMA1 cycle? */ - if (dmarq & DMAR1) dma_cycle (1, PBMAP); /* DMA2 cycle? */ - dmarq = calc_dma (); /* recalc DMA reqs */ - intrq = calc_int (); } /* recalc interrupts */ - -if (intrq && ((intrq <= PRO) || !ion_defer)) { /* interrupt request? */ - iotrap = 1; /* I/O trap cell instr */ - clrFBF (intrq); /* clear flag buffer */ - intaddr = intrq; /* save int addr */ - if (dms_enb) dms_sr = dms_sr | MST_ENBI; /* dms enabled? */ - else dms_sr = dms_sr & ~MST_ENBI; - if (dms_ump) { /* user map? */ - dms_sr = dms_sr | MST_UMPI; - dms_ump = SMAP; } /* switch to system */ - else dms_sr = dms_sr & ~MST_UMPI; - IR = ReadW (intrq); /* get dispatch instr */ - ion_defer = 1; /* defer interrupts */ - intrq = 0; /* clear request */ - if (((IR & I_NMRMASK) != I_IO) || /* if not I/O or */ - (I_GETIOOP (IR) == ioHLT)) /* if halt, */ - clrCTL (PRO); } /* protection off */ - -else { iotrap = 0; /* normal instruction */ - err_PC = PC; /* save PC for error */ - if (sim_brk_summ && - sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - if (mp_evrff) mp_viol = PC; /* if ok, upd mp_viol */ - IR = ReadW (PC); /* fetch instr */ - PC = (PC + 1) & VAMASK; - sim_interval = sim_interval - 1; - ion_defer = 0; } - -/* Instruction decode. The 21MX does a 256-way decode on IR<15:8> - - 15 14 13 12 11 10 09 08 instruction - - x <-!= 0-> x x x x memory reference - 0 0 0 0 x 0 x x shift - 0 0 0 0 x 0 x x alter-skip - 1 0 0 0 x 1 x x IO - 1 0 0 0 0 0 x 0 extended arithmetic - 1 0 0 0 0 0 0 1 divide (decoded as 100400) - 1 0 0 0 1 0 0 0 double load (decoded as 104000) - 1 0 0 0 1 0 0 1 double store (decoded as 104400) - 1 0 0 0 1 0 1 0 extended instr group 0 (A/B must be set) - 1 0 0 0 x 0 1 1 extended instr group 1 (A/B ignored) */ - -absel = (IR & I_AB)? 1: 0; /* get A/B select */ -switch ((IR >> 8) & 0377) { /* decode IR<15:8> */ - -/* Memory reference instructions */ - -case 0020:case 0021:case 0022:case 0023: -case 0024:case 0025:case 0026:case 0027: -case 0220:case 0221:case 0222:case 0223: -case 0224:case 0225:case 0226:case 0227: - if (reason = Ea (IR, &MA, intrq)) break; /* AND */ - AR = AR & ReadW (MA); - break; -case 0030:case 0031:case 0032:case 0033: -case 0034:case 0035:case 0036:case 0037: -case 0230:case 0231:case 0232:case 0233: -case 0234:case 0235:case 0236:case 0237: - if (reason = Ea (IR, &MA, intrq)) break; /* JSB */ - WriteW (MA, PC); /* store PC */ - PCQ_ENTRY; - PC = (MA + 1) & VAMASK; /* jump */ - if (IR & I_IA) ion_defer = 1; /* ind? defer intr */ - break; -case 0040:case 0041:case 0042:case 0043: -case 0044:case 0045:case 0046:case 0047: -case 0240:case 0241:case 0242:case 0243: -case 0244:case 0245:case 0246:case 0247: - if (reason = Ea (IR, &MA, intrq)) break; /* XOR */ - AR = AR ^ ReadW (MA); - break; -case 0050:case 0051:case 0052:case 0053: -case 0054:case 0055:case 0056:case 0057: -case 0250:case 0251:case 0252:case 0253: -case 0254:case 0255:case 0256:case 0257: - if (reason = Ea (IR, &MA, intrq)) break; /* JMP */ - mp_dms_jmp (MA); /* validate jump addr */ - PCQ_ENTRY; - PC = MA; /* jump */ - if (IR & I_IA) ion_defer = 1; /* ind? defer int */ - break; -case 0060:case 0061:case 0062:case 0063: -case 0064:case 0065:case 0066:case 0067: -case 0260:case 0261:case 0262:case 0263: -case 0264:case 0265:case 0266:case 0267: - if (reason = Ea (IR, &MA, intrq)) break; /* IOR */ - AR = AR | ReadW (MA); - break; -case 0070:case 0071:case 0072:case 0073: -case 0074:case 0075:case 0076:case 0077: -case 0270:case 0271:case 0272:case 0273: -case 0274:case 0275:case 0276:case 0277: - if (reason = Ea (IR, &MA, intrq)) break; /* ISZ */ - t = (ReadW (MA) + 1) & DMASK; - WriteW (MA, t); - if (t == 0) PC = (PC + 1) & VAMASK; - break; - -/* Memory reference instructions, continued */ - -case 0100:case 0101:case 0102:case 0103: -case 0104:case 0105:case 0106:case 0107: -case 0300:case 0301:case 0302:case 0303: -case 0304:case 0305:case 0306:case 0307: - if (reason = Ea (IR, &MA, intrq)) break; /* ADA */ - v1 = ReadW (MA); - t = AR + v1; - if (t > DMASK) E = 1; - if (((~AR ^ v1) & (AR ^ t)) & SIGN) O = 1; - AR = t & DMASK; - break; -case 0110:case 0111:case 0112:case 0113: -case 0114:case 0115:case 0116:case 0117: -case 0310:case 0311:case 0312:case 0313: -case 0314:case 0315:case 0316:case 0317: - if (reason = Ea (IR, &MA, intrq)) break; /* ADB */ - v1 = ReadW (MA); - t = BR + v1; - if (t > DMASK) E = 1; - if (((~BR ^ v1) & (BR ^ t)) & SIGN) O = 1; - BR = t & DMASK; - break; -case 0120:case 0121:case 0122:case 0123: -case 0124:case 0125:case 0126:case 0127: -case 0320:case 0321:case 0322:case 0323: -case 0324:case 0325:case 0326:case 0327: - if (reason = Ea (IR, &MA, intrq)) break; /* CPA */ - if (AR != ReadW (MA)) PC = (PC + 1) & VAMASK; - break; -case 0130:case 0131:case 0132:case 0133: -case 0134:case 0135:case 0136:case 0137: -case 0330:case 0331:case 0332:case 0333: -case 0334:case 0335:case 0336:case 0337: - if (reason = Ea (IR, &MA, intrq)) break; /* CPB */ - if (BR != ReadW (MA)) PC = (PC + 1) & VAMASK; - break; -case 0140:case 0141:case 0142:case 0143: -case 0144:case 0145:case 0146:case 0147: -case 0340:case 0341:case 0342:case 0343: -case 0344:case 0345:case 0346:case 0347: - if (reason = Ea (IR, &MA, intrq)) break; /* LDA */ - AR = ReadW (MA); - break; -case 0150:case 0151:case 0152:case 0153: -case 0154:case 0155:case 0156:case 0157: -case 0350:case 0351:case 0352:case 0353: -case 0354:case 0355:case 0356:case 0357: - if (reason = Ea (IR, &MA, intrq)) break; /* LDB */ - BR = ReadW (MA); - break; -case 0160:case 0161:case 0162:case 0163: -case 0164:case 0165:case 0166:case 0167: -case 0360:case 0361:case 0362:case 0363: -case 0364:case 0365:case 0366:case 0367: - if (reason = Ea (IR, &MA, intrq)) break; /* STA */ - WriteW (MA, AR); - break; -case 0170:case 0171:case 0172:case 0173: -case 0174:case 0175:case 0176:case 0177: -case 0370:case 0371:case 0372:case 0373: -case 0374:case 0375:case 0376:case 0377: - if (reason = Ea (IR, &MA, intrq)) break; /* STB */ - WriteW (MA, BR); - break; - -/* Alter/skip instructions */ - -case 0004:case 0005:case 0006:case 0007: -case 0014:case 0015:case 0016:case 0017: - skip = 0; /* no skip */ - if (IR & 000400) t = 0; /* CLx */ - else t = ABREG[absel]; - if (IR & 001000) t = t ^ DMASK; /* CMx */ - if (IR & 000001) { /* RSS? */ - if ((IR & 000040) && (E != 0)) skip = 1; /* SEZ,RSS */ - if (IR & 000100) E = 0; /* CLE */ - if (IR & 000200) E = E ^ 1; /* CME */ - if (((IR & 000030) == 000030) && /* SSx,SLx,RSS */ - ((t & 0100001) == 0100001)) skip = 1; - if (((IR & 000030) == 000020) && /* SSx,RSS */ - ((t & SIGN) != 0)) skip = 1; - if (((IR & 000030) == 000010) && /* SLx,RSS */ - ((t & 1) != 0)) skip = 1; - if (IR & 000004) { /* INx */ - t = (t + 1) & DMASK; - if (t == 0) E = 1; - if (t == SIGN) O = 1; } - if ((IR & 000002) && (t != 0)) skip = 1; /* SZx,RSS */ - if ((IR & 000072) == 0) skip = 1; /* RSS */ - } /* end if RSS */ - else { - if ((IR & 000040) && (E == 0)) skip = 1; /* SEZ */ - if (IR & 000100) E = 0; /* CLE */ - if (IR & 000200) E = E ^ 1; /* CME */ - if ((IR & 000020) && /* SSx */ - ((t & SIGN) == 0)) skip = 1; - if ((IR & 000010) && /* SLx */ - ((t & 1) == 0)) skip = 1; - if (IR & 000004) { /* INx */ - t = (t + 1) & DMASK; - if (t == 0) E = 1; - if (t == SIGN) O = 1; } - if ((IR & 000002) && (t == 0)) skip = 1; /* SZx */ - } /* end if ~RSS */ - ABREG[absel] = t; /* store result */ - PC = (PC + skip) & VAMASK; /* add in skip */ - break; /* end if alter/skip */ - -/* Shift instructions */ - -case 0000:case 0001:case 0002:case 0003: -case 0010:case 0011:case 0012:case 0013: - t = shift (ABREG[absel], IR & 01000, IR >> 6); /* do first shift */ - if (IR & 000040) E = 0; /* CLE */ - if ((IR & 000010) && ((t & 1) == 0)) /* SLx */ - PC = (PC + 1) & VAMASK; - ABREG[absel] = shift (t, IR & 00020, IR); /* do second shift */ - break; /* end if shift */ - -/* I/O instructions */ - -case 0204:case 0205:case 0206:case 0207: -case 0214:case 0215:case 0216:case 0217: - reason = iogrp (IR, iotrap); /* execute instr */ - dmarq = calc_dma (); /* recalc DMA */ - intrq = calc_int (); /* recalc interrupts */ - break; /* end if I/O */ - -/* Extended arithmetic */ - -case 0200: /* EAU group 0 */ - if ((cpu_unit.flags & UNIT_EAU) == 0) { /* implemented? */ - reason = stop_inst; - break; } - switch ((IR >> 4) & 017) { /* decode IR<7:4> */ - case 000: /* diagnostic */ - break; - case 001: /* ASL */ - sc = (IR & 017)? (IR & 017): 16; /* get sc */ - O = 0; /* clear ovflo */ - while (sc-- != 0) { /* bit by bit */ - t = BR << 1; /* shift B */ - BR = (BR & SIGN) | (t & 077777) | (AR >> 15); - AR = (AR << 1) & DMASK; - if ((BR ^ t) & SIGN) O = 1; } - break; - case 002: /* LSL */ - sc = (IR & 017)? (IR & 017): 16; /* get sc */ - BR = ((BR << sc) | (AR >> (16 - sc))) & DMASK; - AR = (AR << sc) & DMASK; /* BR'AR lsh left */ - break; - case 003: /* TIMER */ - BR = (BR + 1) & DMASK; /* increment B */ - if (BR) PC = err_PC; /* if !=0, repeat */ - break; - case 004: /* RRL */ - sc = (IR & 017)? (IR & 017): 16; /* get sc */ - t = BR; /* BR'AR rot left */ - BR = ((BR << sc) | (AR >> (16 - sc))) & DMASK; - AR = ((AR << sc) | (t >> (16 - sc))) & DMASK; - break; - case 010: /* MPY */ - if (reason = Ea1 (&MA, intrq)) break; /* get opnd addr */ - sop1 = SEXT (AR); /* sext AR */ - sop2 = SEXT (ReadW (MA)); /* sext mem */ - sop1 = sop1 * sop2; /* signed mpy */ - BR = (sop1 >> 16) & DMASK; /* to BR'AR */ - AR = sop1 & DMASK; - O = 0; /* no overflow */ - break; - default: - reason = stop_inst; - break; } - break; -case 0201: /* divide */ - if ((cpu_unit.flags & UNIT_EAU) == 0) { /* implemented? */ - reason = stop_inst; - break; } - if (reason = Ea1 (&MA, intrq)) break; /* get opnd addr */ - if (rs = qs = BR & SIGN) { /* save divd sign, neg? */ - AR = (~AR + 1) & DMASK; /* make B'A pos */ - BR = (~BR + (AR == 0)) & DMASK; } /* make divd pos */ - v2 = ReadW (MA); /* divr = mem */ - if (v2 & SIGN) { /* neg? */ - v2 = (~v2 + 1) & DMASK; /* make divr pos */ - qs = qs ^ SIGN; } /* sign of quotient */ - if (BR >= v2) O = 1; /* divide work? */ - else { /* maybe... */ - O = 0; /* assume ok */ - v1 = (BR << 16) | AR; /* 32b divd */ - AR = (v1 / v2) & DMASK; /* quotient */ - BR = (v1 % v2) & DMASK; /* remainder */ - if (AR) { /* quotient > 0? */ - if (qs) AR = (~AR + 1) & DMASK; /* apply quo sign */ - if ((AR ^ qs) & SIGN) O = 1; } /* still wrong? ovflo */ - if (rs) BR = (~BR + 1) & DMASK; } /* apply rem sign */ - break; -case 0202: /* EAU group 2 */ - if ((cpu_unit.flags & UNIT_EAU) == 0) { /* implemented? */ - reason = stop_inst; - break; } - switch ((IR >> 4) & 017) { /* decode IR<7:4> */ - case 001: /* ASR */ - sc = (IR & 017)? (IR & 017): 16; /* get sc */ - AR = ((BR << (16 - sc)) | (AR >> sc)) & DMASK; - BR = (SEXT (BR) >> sc) & DMASK; /* BR'AR ash right */ - O = 0; - break; - case 002: /* LSR */ - sc = (IR & 017)? (IR & 017): 16; /* get sc */ - AR = ((BR << (16 - sc)) | (AR >> sc)) & DMASK; - BR = BR >> sc; /* BR'AR log right */ - break; - case 004: /* RRR */ - sc = (IR & 017)? (IR & 017): 16; /* get sc */ - t = AR; /* BR'AR rot right */ - AR = ((AR >> sc) | (BR << (16 - sc))) & DMASK; - BR = ((BR >> sc) | (t << (16 - sc))) & DMASK; - break; - default: - reason = stop_inst; - break; } - break; -case 0210: /* DLD */ - if ((cpu_unit.flags & UNIT_EAU) == 0) { /* implemented? */ - reason = stop_inst; - break; } - if (reason = Ea1 (&MA, intrq)) break; /* get opnd addr */ - AR = ReadW (MA); /* load AR */ - MA = (MA + 1) & VAMASK; - BR = ReadW (MA); /* load BR */ - break; -case 0211: /* DST */ - if ((cpu_unit.flags & UNIT_EAU) == 0) { /* get opnd addr */ - reason = stop_inst; - break; } - if (reason = Ea1 (&MA, intrq)) break; /* get opnd addr */ - WriteW (MA, AR); /* store AR */ - MA = (MA + 1) & VAMASK; - WriteW (MA, BR); /* store BR */ - break; - -/* Extended instructions */ - -case 0212: /* MAC0 ext */ -case 0203:case 0213: /* MAC1 ext */ - eop = IR & 0777; /* extended opcode */ - eflag = E_GETFL (e_inst[eop]); /* get flags */ - if ((eflag & (cpu_unit.flags >> UNIT_V_UF)) == 0) { - reason = stop_inst; /* invalid? error */ - break; } - etype = E_GETTY (eflag, e_inst[eop]); /* get format */ - if (etype > E_CN) { /* at least 1 addr? */ - if (reason = Ea1 (&MA, intrq)) break; } /* get first address */ - if ((etype == E_AC) || (etype == E_CN)) { /* addr + cnt, cnt */ - wc = ReadW (PC); /* get count */ - awc = PC; /* addr of count */ - PC = (PC + 1) & VAMASK; } - else if (etype == E_AZ) { /* addr + zero */ - wc = ReadW (MA); /* get wc */ - awc = PC; /* addr of interim */ - if (wc) { /* wc > 0? */ - if (t = ReadW (PC)) wc = t; } /* use interim if nz */ - WriteW (awc, 0); /* clear interim */ - PC = (PC + 1) & VAMASK; } - else if (etype == E_AA) { /* second addr */ - if (reason = Ea1 (&M1, intrq)) break; } /* get second address */ - - switch (eop) { /* decode IR<8:0> */ - -/* Floating point instructions */ - - case 0000: /* IOP ILIST/FAD */ - if (cpu_unit.flags & UNIT_IOP) /* ILIST (E_AC) */ - goto IOP_ILIST; - fop = ReadF (MA); /* get fop */ - O = f_as (fop, 0); /* add, upd ovflo */ - break; - case 0020: /* IOP LAI-/FSB */ - if (cpu_unit.flags & UNIT_IOP) /* LAI -20 (I_NO) */ - goto IOP_LAIM; - fop = ReadF (MA); /* get fop */ - O = f_as (fop, 1); /* sub, upd ovflo */ - break; - case 0040: /* IOP LAI+/FMP */ - if (cpu_unit.flags & UNIT_IOP) /* LAI 0 (I_NO) */ - goto IOP_LAIP; - fop = ReadF (MA); /* get fop */ - O = f_mul (fop); /* mul, upd ovflo */ - break; - case 0060: /* IOP SAI-/FDV */ - if (cpu_unit.flags & UNIT_IOP) /* SAI -20 (I_NO) */ - goto IOP_SAIM; - fop = ReadF (MA); /* get fop */ - O = f_div (fop); /* div, upd ovflo */ - break; - case 0100: /* IOP SAI+/FIX */ - if (cpu_unit.flags & UNIT_IOP) /* SAI 0 (I_NO) */ - goto IOP_SAIP; - O = f_fix (); /* FIX (E_NO) */ - break; - case 0120: /* IOP MBYTE/FLT */ - if (cpu_unit.flags & UNIT_IOP) /* MBYTE (I_AZ) */ - goto IOP_MBYTE; - O = f_flt (); /* FLT (E_NO) */ - break; - -/* 2100 (and 21MX) IOP instructions */ - - IOP_LAIM: case 0021: case 0022: case 0023: /* IOP LAI- (I_NO) */ - case 0024: case 0025: case 0026: case 0027: - case 0030: case 0031: case 0032: case 0033: - case 0034: case 0035: case 0036: case 0037: - MA = ((IR | 0177760) + BR) & VAMASK; /* IR<3:0> = -offset */ - AR = ReadW (MA); /* load AR */ - break; - IOP_LAIP: case 0041: case 0042: case 0043: /* IOP LAI+ (I_NO) */ - case 0044: case 0045: case 0046: case 0047: - case 0050: case 0051: case 0052: case 0053: - case 0054: case 0055: case 0056: case 0057: - MA = ((IR & 017) + BR) & VAMASK; /* IR<3:0> = +offset */ - AR = ReadW (MA); /* load AR */ - break; - IOP_SAIM: case 0061: case 0062: case 0063: /* IOP SAI- (I_NO) */ - case 0064: case 0065: case 0066: case 0067: - case 0070: case 0071: case 0072: case 0073: - case 0074: case 0075: case 0076: case 0077: - MA = ((IR | 0177760) + BR) & VAMASK; /* IR<3:0> = -offset */ - WriteW (MA, AR); /* store AR */ - break; - IOP_SAIP: case 0101: case 0102: case 0103: /* IOP SAI+ (I_NO) */ - case 0104: case 0105: case 0106: case 0107: - case 0110: case 0111: case 0112: case 0113: - case 0114: case 0115: case 0116: case 0117: - MA = ((IR & 017) + BR) & VAMASK; /* IR<3:0> = +offset */ - WriteW (MA, AR); /* store AR */ - break; - case 0150: /* IOP CRC (I_CN) */ - case 0460: /* IOPX CRC (I_CN) */ - t = (AR & 0xFF) ^ wc; /* start CRC */ - for (i = 0; i < 8; i++) { /* apply polynomial */ - t = (t >> 1) | ((t & 1) << 15); /* rotate right */ - if (t & SIGN) t = t ^ 020001; } /* old t<0>? xor */ - WriteW (awc, t); /* rewrite CRC */ - break; - case 0160: /* IOP TRSLT (I_CN) */ - case 0467: /* IOPX TRSLT (I_CN) */ - if (wc & SIGN) break; /* cnt < 0? */ - while (wc != 0) { /* loop */ - MA = (AR + AR + ReadB (BR)) & VAMASK; - t = ReadB (MA); /* xlate */ - WriteB (BR, t); /* store char */ - BR = (BR + 1) & DMASK; /* incr ptr */ - wc = (wc - 1) & DMASK; /* decr cnt */ - WriteW (awc, wc); - if (wc && intrq) { /* more and intr? */ - PC = err_PC; /* stop for now */ - break; } } - break; - case 0220: /* IOP READF (I_NO) */ - case 0462: /* IOPX READF (I_NO) */ - AR = iop_sp; /* copy stk ptr */ - break; - case 0221: /* IOP PRFIO (I_NO) */ - case 0473: /* IOPX PFRIO (I_NO) */ - IR = ReadW (PC); /* get IO instr */ - PC = (PC + 1) & VAMASK; - WriteW (PC, 1); /* set flag */ - PC = (PC + 1) & VAMASK; - reason = iogrp (IR, 0); /* execute instr */ - break; - case 0222: /* IOP PRFEI (I_NO) */ - case 0471: /* IOPX PFREI (I_NO) */ - IR = ReadW (PC); /* get IO instr */ - PC = (PC + 1) & VAMASK; - WriteW (PC, 1); /* set flag */ - PC = (PC + 1) & VAMASK; - reason = iogrp (IR, 0); /* execute instr */ - /* fall through */ - case 0223: /* IOP PRFEX (I_NO) */ - case 0472: /* IOPX PFREX (I_NO) */ - MA = ReadW (PC); /* exit addr */ - PCQ_ENTRY; - PC = ReadW (MA) & VAMASK; /* jump indirect */ - WriteW (MA, 0); /* clear exit */ - break; - case 0240: /* IOP ENQ (I_NO) */ - case 0464: /* IOPX ENQ (I_NO) */ - hp = ReadW (AR & VAMASK); /* addr of head */ - tp = ReadW ((AR + 1) & VAMASK); /* addr of tail */ - WriteW ((BR - 1) & VAMASK, 0); /* entry link */ - WriteW ((tp - 1) & VAMASK, BR); /* tail link */ - WriteW ((AR + 1) & VAMASK, BR); /* queue tail */ - if (hp != 0) PC = (PC + 1) & VAMASK; /* q not empty? skip */ - break; - case 0257: /* IOP PENQ (I_NO) */ - case 0465: /* IOPX PENQ (I_NO) */ - hp = ReadW (AR & VAMASK); /* addr of head */ - WriteW ((BR - 1) & VAMASK, hp); /* becomes entry link */ - WriteW (AR & VAMASK, BR); /* queue head */ - if (hp == 0) /* q empty? */ - WriteW ((AR + 1) & VAMASK, BR); /* queue tail */ - else PC = (PC + 1) & VAMASK; /* skip */ - break; - case 0260: /* IOP DEQ (I_NO) */ - case 0466: /* IOPX DEQ (I_NO) */ - BR = ReadW (AR & VAMASK); /* addr of head */ - if (BR) { /* queue not empty? */ - hp = ReadW ((BR - 1) & VAMASK); /* read hd entry link */ - WriteW (AR & VAMASK, hp); /* becomes queue head */ - if (hp == 0) /* q now empty? */ - WriteW ((AR + 1) & VAMASK, (AR + 1) & DMASK); - PC = (PC + 1) & VAMASK; } /* skip */ - break; - case 0300: /* IOP SBYTE (I_NO) */ - WriteB (BR, AR); /* store byte */ - BR = (BR + 1) & DMASK; /* incr ptr */ - break; - case 0320: /* IOP LBYTE (I_NO) */ - AR = ReadB (BR); /* load byte */ - BR = (BR + 1) & DMASK; /* incr ptr */ - break; - case 0340: /* IOP REST (I_NO) */ - case 0461: /* IOPX REST (I_NO) */ - iop_sp = (iop_sp - 1) & VAMASK; /* pop E/~O,BR,AR */ - t = ReadW (iop_sp); - O = ((t >> 1) ^ 1) & 1; - E = t & 1; - iop_sp = (iop_sp - 1) & VAMASK; - BR = ReadW (iop_sp); - iop_sp = (iop_sp - 1) & VAMASK; - AR = ReadW (iop_sp); - if (cpu_unit.flags & UNIT_2100) mp_fence = iop_sp; - break; - case 0362: /* IOP SAVE (I_NO) */ - case 0474: /* IOPX SAVE (I_NO) */ - WriteW (iop_sp, AR); /* push AR,BR,E/~O */ - iop_sp = (iop_sp + 1) & VAMASK; - WriteW (iop_sp, BR); - iop_sp = (iop_sp + 1) & VAMASK; - t = ((O ^ 1) << 1) | E; - WriteW (iop_sp, t); - iop_sp = (iop_sp + 1) & VAMASK; - if (cpu_unit.flags & UNIT_2100) mp_fence = iop_sp; - break; - - case 0400: case 0401: case 0402: case 0403: /* IOPX LAI-/SAI- (I_NO) */ - case 0404: case 0405: case 0406: case 0407: - case 0410: case 0411: case 0412: case 0413: - case 0414: case 0415: case 0416: case 0417: - MA = ((IR | 0177760) + BR) & VAMASK; /* IR<3:0> = -offset */ - if (IR & I_AB) AR = ReadW (MA); /* AB = 1? LAI */ - else WriteW (MA, AR); /* AB = 0? SAI */ - break; - case 0420: case 0421: case 0422: case 0423: /* IOPX LAI+/SAI+ (I_NO) */ - case 0424: case 0425: case 0426: case 0427: - case 0430: case 0431: case 0432: case 0433: - case 0434: case 0435: case 0436: case 0437: - MA = ((IR & 017) + BR) & VAMASK; /* IR<3:0> = +offset */ - if (IR & I_AB) AR = ReadW (MA); /* AB = 1? LAI */ - else WriteW (MA, AR); /* AB = 0? SAI */ - break; - case 0463: /* IOPX INS (I_NO) */ - iop_sp = AR; /* init stk ptr */ - break; - case 0470: /* IOPX ILIST (I_CN) */ - IOP_ILIST: - do { /* for count */ - WriteW (MA, AR); /* write AR to mem */ - AR = (AR + 1) & DMASK; /* incr AR */ - MA = (MA + 1) & VAMASK; /* incr MA */ - wc = (wc - 1) & DMASK; } /* decr count */ - while (wc != 0); - break; - -/* DMS instructions, move alternate - interruptible - - DMS privilege violation rules are - - load map and CTL set (XMM, XMS, XM*, SY*, US*, PA*, PB*) - - load state or fence and UMAP set (JRS, DJP, DJS, SJP, SJS, UJP, UJS, LF*) - - The 21MX manual is incorrect in stating that M*I, M*W, XS* are privileged */ - - case 0701: /* self test */ - ABREG[absel] = ABREG[absel] ^ DMASK; /* CMA or CMB */ - break; - case 0702: /* MBI (E_NO) */ - AR = AR & ~1; /* force A, B even */ - BR = BR & ~1; - while (XR != 0) { /* loop */ - t = ReadB (AR); /* read curr */ - WriteBA (BR, t); /* write alt */ - AR = (AR + 1) & DMASK; /* incr ptrs */ - BR = (BR + 1) & DMASK; - XR = (XR - 1) & DMASK; - if (XR && intrq && !(AR & 1)) { /* more, int, even? */ - PC = err_PC; /* stop for now */ - break; } } - break; - case 0703: /* MBF (E_NO) */ - AR = AR & ~1; /* force A, B even */ - BR = BR & ~1; - while (XR != 0) { /* loop */ - t = ReadBA (AR); /* read alt */ - WriteB (BR, t); /* write curr */ - AR = (AR + 1) & DMASK; /* incr ptrs */ - BR = (BR + 1) & DMASK; - XR = (XR - 1) & DMASK; - if (XR && intrq && !(AR & 1)) { /* more, int, even? */ - PC = err_PC; /* stop for now */ - break; } } - break; - case 0704: /* MBW (E_NO) */ - AR = AR & ~1; /* force A, B even */ - BR = BR & ~1; - while (XR != 0) { /* loop */ - t = ReadBA (AR); /* read alt */ - WriteBA (BR, t); /* write alt */ - AR = (AR + 1) & DMASK; /* incr ptrs */ - BR = (BR + 1) & DMASK; - XR = (XR - 1) & DMASK; - if (XR && intrq && !(AR & 1)) { /* more, int, even? */ - PC = err_PC; /* stop for now */ - break; } } - break; - case 0705: /* MWI (E_NO) */ - while (XR != 0) { /* loop */ - t = ReadW (AR & VAMASK); /* read curr */ - WriteWA (BR & VAMASK, t); /* write alt */ - AR = (AR + 1) & DMASK; /* incr ptrs */ - BR = (BR + 1) & DMASK; - XR = (XR - 1) & DMASK; - if (XR && intrq) { /* more and intr? */ - PC = err_PC; /* stop for now */ - break; } } - break; - case 0706: /* MWF (E_NO) */ - while (XR != 0) { /* loop */ - t = ReadWA (AR & VAMASK); /* read alt */ - WriteW (BR & VAMASK, t); /* write curr */ - AR = (AR + 1) & DMASK; /* incr ptrs */ - BR = (BR + 1) & DMASK; - XR = (XR - 1) & DMASK; - if (XR && intrq) { /* more and intr? */ - PC = err_PC; /* stop for now */ - break; } } - break; - case 0707: /* MWW (E_NO) */ - while (XR != 0) { /* loop */ - t = ReadWA (AR & VAMASK); /* read alt */ - WriteWA (BR & VAMASK, t); /* write alt */ - AR = (AR + 1) & DMASK; /* incr ptrs */ - BR = (BR + 1) & DMASK; - XR = (XR - 1) & DMASK; - if (XR && intrq) { /* more and intr? */ - PC = err_PC; /* stop for now */ - break; } } - break; - -/* DMS, continued */ - - case 0710: /* SYA, SYB (E_NO) */ - case 0711: /* USA, USB (E_NO) */ - case 0712: /* PAA, PAB (E_NO) */ - case 0713: /* PBA, PBB (E_NO) */ - mapi = (IR & 03) << VA_N_PAG; /* map base */ - if (ABREG[absel] & SIGN) { /* store? */ - for (i = 0; i < MAP_LNT; i++) { - t = dms_rmap (mapi + i); /* map to memory */ - WriteW ((ABREG[absel] + i) & VAMASK, t); } } - else { /* load */ - dms_viol (err_PC, MVI_PRV); /* priv if PRO */ - for (i = 0; i < MAP_LNT; i++) { - t = ReadW ((ABREG[absel] + i) & VAMASK); - dms_wmap (mapi + i, t); } } /* mem to map */ - ABREG[absel] = (ABREG[absel] + MAP_LNT) & DMASK; - break; - case 0714: /* SSM (E_AD) */ - WriteW (MA, dms_upd_sr ()); /* store stat */ - break; - case 0715: /* JRS (E_AA) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); - t = ReadW (MA); /* get status */ - dms_enb = 0; /* assume off */ - dms_ump = SMAP; - if (t & 0100000) { /* set enable? */ - dms_enb = 1; - if (t & 0040000) dms_ump = UMAP; } /* set/clr usr */ - PCQ_ENTRY; /* save old PC */ - PC = M1; /* jump */ - ion_defer = 1; /* defer intr */ - break; - -/* DMS, continued */ - - case 0700: case 0720: /* XMM (E_NO) */ - if (XR == 0) break; /* nop? */ - while (XR != 0) { /* loop */ - if (XR & SIGN) { /* store? */ - t = dms_rmap (AR); /* map to mem */ - WriteW (BR & VAMASK, t); - XR = (XR + 1) & DMASK; } - else { /* load */ - dms_viol (err_PC, MVI_PRV); /* priv if PRO */ - t = ReadW (BR & VAMASK); /* mem to map */ - dms_wmap (AR, t); - XR = (XR - 1) & DMASK; } - AR = (AR + 1) & DMASK; - BR = (BR + 1) & DMASK; - if (intrq && ((XR & 0xF) == 0xF)) { /* intr, cnt4 = F? */ - PC = err_PC; /* stop for now */ - break; } } - break; - case 0721: /* XMS (E_NO) */ - if ((XR & SIGN) || (XR == 0)) break; /* nop? */ - dms_viol (err_PC, MVI_PRV); /* priv if PRO */ - while (XR != 0) { - dms_wmap (AR, BR); /* AR to map */ - XR = (XR - 1) & DMASK; - AR = (AR + 1) & DMASK; - BR = (BR + 1) & DMASK; - if (intrq && ((XR & 0xF) == 0xF)) { /* intr, cnt4 = F? */ - PC = err_PC; - break; } } - break; - case 0722: /* XMA, XMB (E_NO) */ - dms_viol (err_PC, MVI_PRV); /* priv if PRO */ - if (ABREG[absel] & 0100000) mapi = UMAP; - else mapi = SMAP; - if (ABREG[absel] & 0000001) mapj = PBMAP; - else mapj = PAMAP; - for (i = 0; i < MAP_LNT; i++) { - t = dms_rmap (mapi + i); /* read map */ - dms_wmap (mapj + i, t); } /* write map */ - break; - case 0724: /* XLA, XLB (E_AD) */ - ABREG[absel] = ReadWA (MA); /* load alt */ - break; - case 0725: /* XSA, XSB (E_AD) */ - WriteWA (MA, ABREG[absel]); /* store alt */ - break; - case 0726: /* XCA, XCB (E_AD) */ - if (ABREG[absel] != ReadWA (MA)) /* compare alt */ - PC = (PC + 1) & VAMASK; - break; - case 0727: /* LFA, LFB (E_NO) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); - dms_sr = (dms_sr & ~(MST_FLT | MST_FENCE)) | - (ABREG[absel] & (MST_FLT | MST_FENCE)); - break; - -/* DMS, continued */ - - case 0730: /* RSA, RSB (E_NO) */ - ABREG[absel] = dms_upd_sr (); /* save stat */ - break; - case 0731: /* RVA, RVB (E_NO) */ - ABREG[absel] = dms_vr; /* save viol */ - break; - case 0732: /* DJP (E_AD) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); - mp_dms_jmp (MA); /* validate jump addr */ - PCQ_ENTRY; /* save curr PC */ - PC = MA; /* new PC */ - dms_enb = 0; /* disable map */ - dms_ump = SMAP; - ion_defer = 1; - break; - case 0733: /* DJS (E_AD) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); - WriteW (MA, PC); /* store ret addr */ - PCQ_ENTRY; /* save curr PC */ - PC = (MA + 1) & VAMASK; /* new PC */ - dms_enb = 0; /* disable map */ - dms_ump = SMAP; - ion_defer = 1; /* defer intr */ - break; - case 0734: /* SJP (E_AD) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); - mp_dms_jmp (MA); /* validate jump addr */ - PCQ_ENTRY; /* save curr PC */ - PC = MA; /* jump */ - dms_enb = 1; /* enable system */ - dms_ump = SMAP; - ion_defer = 1; /* defer intr */ - break; - case 0735: /* SJS (E_AD) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); - t = PC; /* save retn addr */ - PCQ_ENTRY; /* save curr PC */ - PC = (MA + 1) & VAMASK; /* new PC */ - dms_enb = 1; /* enable system */ - dms_ump = SMAP; - WriteW (MA, t); /* store ret addr */ - ion_defer = 1; /* defer intr */ - break; - case 0736: /* UJP (E_AD) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); - mp_dms_jmp (MA); /* validate jump addr */ - PCQ_ENTRY; /* save curr PC */ - PC = MA; /* jump */ - dms_enb = 1; /* enable user */ - dms_ump = UMAP; - ion_defer = 1; /* defer intr */ - break; - case 0737: /* UJS (E_AD) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); - t = PC; /* save retn addr */ - PCQ_ENTRY; /* save curr PC */ - PC = (MA + 1) & VAMASK; /* new PC */ - dms_enb = 1; /* enable user */ - dms_ump = UMAP; - WriteW (MA, t); /* store ret addr */ - ion_defer = 1; /* defer intr */ - break; - -/* Index register instructions */ - - case 0740: /* SAX, SBX (E_AD) */ - MA = (MA + XR) & VAMASK; /* indexed addr */ - WriteW (MA, ABREG[absel]); /* store */ - break; - case 0741: /* CAX, CBX (E_NO) */ - XR = ABREG[absel]; /* copy to XR */ - break; - case 0742: /* LAX, LBX (E_AD) */ - MA = (MA + XR) & VAMASK; /* indexed addr */ - ABREG[absel] = ReadW (MA); /* load */ - break; - case 0743: /* STX (E_AD) */ - WriteW (MA, XR); /* store XR */ - break; - case 0744: /* CXA, CXB (E_NO) */ - ABREG[absel] = XR; /* copy from XR */ - break; - case 0745: /* LDX (E_AD)*/ - XR = ReadW (MA); /* load XR */ - break; - case 0746: /* ADX (E_AD) */ - v1 = ReadW (MA); /* add to XR */ - t = XR + v1; - if (t > DMASK) E = 1; /* set E, O */ - if (((~XR ^ v1) & (XR ^ t)) & SIGN) O = 1; - XR = t & DMASK; - break; - case 0747: /* XAX, XBX (E_NO) */ - t = XR; /* exchange XR */ - XR = ABREG[absel]; - ABREG[absel] = t; - break; - case 0750: /* SAY, SBY (E_AD) */ - MA = (MA + YR) & VAMASK; /* indexed addr */ - WriteW (MA, ABREG[absel]); /* store */ - break; - case 0751: /* CAY, CBY (E_NO) */ - YR = ABREG[absel]; /* copy to YR */ - break; - case 0752: /* LAY, LBY (E_AD) */ - MA = (MA + YR) & VAMASK; /* indexed addr */ - ABREG[absel] = ReadW (MA); /* load */ - break; - case 0753: /* STY (E_AD) */ - WriteW (MA, YR); /* store YR */ - break; - case 0754: /* CYA, CYB (E_NO) */ - ABREG[absel] = YR; /* copy from YR */ - break; - case 0755: /* LDY (E_AD) */ - YR = ReadW (MA); /* load YR */ - break; - case 0756: /* ADY (E_AD) */ - v1 = ReadW (MA); /* add to YR */ - t = YR + v1; - if (t > DMASK) E = 1; /* set E, O */ - if (((~YR ^ v1) & (YR ^ t)) & SIGN) O = 1; - YR = t & DMASK; - break; - case 0757: /* XAY, XBY (E_NO) */ - t = YR; /* exchange YR */ - YR = ABREG[absel]; - ABREG[absel] = t; - break; - case 0760: /* ISX (E_NO) */ - XR = (XR + 1) & DMASK; /* incr XR */ - if (XR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ - break; - case 0761: /* DSX (E_NO) */ - XR = (XR - 1) & DMASK; /* decr XR */ - if (XR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ - break; - case 0762: /* JLY (E_AD) */ - mp_dms_jmp (MA); /* validate jump addr */ - PCQ_ENTRY; - YR = PC; /* ret addr to YR */ - PC = MA; /* jump */ - break; - case 0770: /* ISY (E_NO) */ - YR = (YR + 1) & DMASK; /* incr YR */ - if (YR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ - break; - case 0771: /* DSY (E_NO) */ - YR = (YR - 1) & DMASK; /* decr YR */ - if (YR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ - break; - case 0772: /* JPY (E_NO) */ - MA = (ReadW (PC) + YR) & VAMASK; /* index, no indir */ - PC = (PC + 1) & VAMASK; - mp_dms_jmp (MA); /* validate jump addr */ - PCQ_ENTRY; - PC = MA; /* jump */ - break; - -/* Byte instructions */ - - case 0763: /* LBT (E_NO) */ - AR = ReadB (BR); /* load byte */ - BR = (BR + 1) & DMASK; /* incr ptr */ - break; - case 0764: /* SBT (E_NO) */ - WriteB (BR, AR); /* store byte */ - break; - IOP_MBYTE: /* IOP MBYTE (I_AZ) */ - if (wc & SIGN) break; /* must be positive */ - case 0765: /* MBT (E_AZ) */ - while (wc != 0) { /* while count */ - WriteW (awc, wc); /* for abort */ - t = ReadB (AR); /* move byte */ - WriteB (BR, t); - AR = (AR + 1) & DMASK; /* incr src */ - BR = (BR + 1) & DMASK; /* incr dst */ - wc = (wc - 1) & DMASK; /* decr cnt */ - if (intrq && wc) { /* intr, more to do? */ - PC = err_PC; /* back up PC */ - break; } } /* take intr */ - WriteW (awc, wc); /* clean up inline */ - break; - case 0766: /* CBT (E_AZ) */ - while (wc != 0) { /* while count */ - WriteW (awc, wc); /* for abort */ - v1 = ReadB (AR); /* get src1 */ - v2 = ReadB (BR); /* get src2 */ - if (v1 != v2) { /* compare */ - PC = (PC + 1 + (v1 > v2)) & VAMASK; - BR = (BR + wc) & DMASK; /* update BR */ - wc = 0; /* clr interim */ - break; } - AR = (AR + 1) & DMASK; /* incr src1 */ - BR = (BR + 1) & DMASK; /* incr src2 */ - wc = (wc - 1) & DMASK; /* decr cnt */ - if (intrq && wc) { /* intr, more to do? */ - PC = err_PC; /* back up PC */ - break; } } /* take intr */ - WriteW (awc, wc); /* clean up inline */ - break; - case 0767: /* SFB (E_NO) */ - v1 = AR & 0377; /* test byte */ - v2 = (AR >> 8) & 0377; /* term byte */ - for (;;) { /* scan */ - t = ReadB (BR); /* read byte */ - if (t == v1) break; /* test match? */ - BR = (BR + 1) & DMASK; - if (t == v2) { /* term match? */ - PC = (PC + 1) & VAMASK; - break; } - if (intrq) { /* int pending? */ - PC = err_PC; /* back up PC */ - break; } } /* take intr */ - break; - -/* Bit, word instructions */ - - case 0773: /* SBS (E_AA) */ - WriteW (M1, M[M1] | M [MA]); /* set bit */ - break; - case 0774: /* CBS (E_AA) */ - WriteW (M1, M[M1] & ~M[MA]); /* clear bit */ - break; - case 0775: /* TBS (E_AA) */ - if ((M[MA] & M[M1]) != M[MA]) /* test bit */ - PC = (PC + 1) & VAMASK; - break; - case 0776: /* CMW (E_AZ) */ - while (wc != 0) { /* while count */ - WriteW (awc, wc); /* for abort */ - v1 = ReadW (AR & VAMASK); /* first op */ - v2 = ReadW (BR & VAMASK); /* second op */ - sop1 = (int32) SEXT (v1); /* signed */ - sop2 = (int32) SEXT (v2); - if (sop1 != sop2) { /* compare */ - PC = (PC + 1 + (sop1 > sop2)) & VAMASK; - BR = (BR + wc) & DMASK; /* update BR */ - wc = 0; /* clr interim */ - break; } - AR = (AR + 1) & DMASK; /* incr src1 */ - BR = (BR + 1) & DMASK; /* incr src2 */ - wc = (wc - 1) & DMASK; /* decr cnt */ - if (intrq && wc) { /* intr, more to do? */ - PC = err_PC; /* back up PC */ - break; } } /* take intr */ - WriteW (awc, wc); /* clean up inline */ - break; - case 0200: /* IOP WMOVE (I_AZ) */ - if (wc & SIGN) break; /* must be positive */ - case 0777: /* MVW (E_AZ) */ - while (wc != 0) { /* while count */ - WriteW (awc, wc); /* for abort */ - t = ReadW (AR & VAMASK); /* move word */ - WriteW (BR & VAMASK, t); - AR = (AR + 1) & DMASK; /* incr src */ - BR = (BR + 1) & DMASK; /* incr dst */ - wc = (wc - 1) & DMASK; /* decr cnt */ - if (intrq && wc) { /* intr, more to do? */ - PC = err_PC; /* back up PC */ - break; } } /* take intr */ - WriteW (awc, wc); /* clean up inline */ - break; - default: /* all others NOP */ - break; } /* end case ext */ - break; } /* end case IR */ - -if (reason == STOP_INDINT) { /* indirect intr? */ - PC = err_PC; /* back out of inst */ - ion_defer = 0; /* clear defer */ - reason = 0; } /* continue */ -} /* end while */ - -/* Simulation halted */ - -saved_AR = AR & DMASK; -saved_BR = BR & DMASK; -for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru dev */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if (dibp) { /* exist? */ - dev = dibp->devno; - dibp->cmd = CMD (dev); - dibp->ctl = CTL (dev); - dibp->flg = FLG (dev); - dibp->fbf = FBF (dev); } } -pcq_r->qptr = pcq_p; /* update pc q ptr */ -return reason; -} - -/* Effective address calculation */ - -t_stat Ea (uint32 IR, uint32 *addr, uint32 irq) -{ -uint32 i, MA; - -MA = IR & (I_IA | I_DISP); /* ind + disp */ -if (IR & I_CP) MA = ((PC - 1) & I_PAGENO) | MA; /* current page? */ -for (i = 0; (i < ind_max) && (MA & I_IA); i++) { /* resolve multilevel */ - if ((i >= 2) && irq && /* >3 levels, int req, */ - (cpu_unit.flags & UNIT_MPR)) /* mprot installed? */ - return STOP_INDINT; /* break out */ - MA = ReadW (MA & VAMASK); } -if (i >= ind_max) return STOP_IND; /* indirect loop? */ -*addr = MA; -return SCPE_OK; -} - -/* Effective address, two words */ - -t_stat Ea1 (uint32 *addr, uint32 irq) -{ -uint32 i, MA; - -MA = ReadW (PC); /* get next address */ -PC = (PC + 1) & VAMASK; -for (i = 0; (i < ind_max) && (MA & I_IA); i++) { /* resolve multilevel */ - if ((i >= 2) && irq && /* >3 levels, int req, */ - (cpu_unit.flags & UNIT_MPR)) /* mprot installed? */ - return STOP_INDINT; /* break out */ - MA = ReadW (MA & VAMASK); } -if (i >= ind_max) return STOP_IND; /* indirect loop? */ -*addr = MA; -return SCPE_OK; -} - -/* Shift micro operation */ - -uint32 shift (uint32 t, uint32 flag, uint32 op) -{ -uint32 oldE; - -op = op & 07; /* get shift op */ -if (flag) { /* enabled? */ - switch (op) { /* case on operation */ - case 00: /* signed left shift */ - return ((t & SIGN) | ((t << 1) & 077777)); - case 01: /* signed right shift */ - return ((t & SIGN) | (t >> 1)); - case 02: /* rotate left */ - return (((t << 1) | (t >> 15)) & DMASK); - case 03: /* rotate right */ - return (((t >> 1) | (t << 15)) & DMASK); - case 04: /* left shift, 0 sign */ - return ((t << 1) & 077777); - case 05: /* ext right rotate */ - oldE = E; - E = t & 1; - return ((t >> 1) | (oldE << 15)); - case 06: /* ext left rotate */ - oldE = E; - E = (t >> 15) & 1; - return (((t << 1) | oldE) & DMASK); - case 07: /* rotate left four */ - return (((t << 4) | (t >> 12)) & DMASK); - } /* end case */ - } /* end if */ -if (op == 05) E = t & 1; /* disabled ext rgt rot */ -if (op == 06) E = (t >> 15) & 1; /* disabled ext lft rot */ -return t; /* input unchanged */ -} - -/* IO instruction decode */ - -t_stat iogrp (uint32 ir, uint32 iotrap) -{ -uint32 dev, sop, iodata, ab; - -ab = (ir & I_AB)? 1: 0; /* get A/B select */ -dev = ir & I_DEVMASK; /* get device */ -sop = I_GETIOOP (ir); /* get subopcode */ -if (!iotrap && CTL (PRO) && ((sop == ioHLT) || (dev != OVF))) { /* protected? */ - if (sop == ioLIX) ABREG[ab] = 0; /* A/B writes anyway */ - ABORT (ABORT_PRO); } -iodata = devdisp (dev, sop, ir, ABREG[ab]); /* process I/O */ -ion_defer = defer_tab[sop]; /* set defer */ -if ((sop == ioMIX) || (sop == ioLIX)) /* store ret data */ - ABREG[ab] = iodata & DMASK; -if (sop == ioHLT) return STOP_HALT; /* halt? */ -return (iodata >> IOT_V_REASON); /* return status */ -} - -/* Device dispatch */ - -uint32 devdisp (uint32 devno, uint32 inst, uint32 IR, uint32 dat) -{ -if (dtab[devno]) return dtab[devno] (inst, IR, dat); -else return nulio (inst, IR, dat); -} - -/* Calculate DMA requests */ - -uint32 calc_dma (void) -{ -uint32 r = 0; - -if (CMD (DMA0) && FLG (dmac[0].cw1 & I_DEVMASK)) /* check DMA0 cycle */ - r = r | DMAR0; -if (CMD (DMA1) && FLG (dmac[1].cw1 & I_DEVMASK)) /* check DMA1 cycle */ - r = r | DMAR1; -return r; -} - -/* Calculate interrupt requests - - This routine takes into account all the relevant state of the - interrupt system: ion, dev_flg, dev_fbf, and dev_ctl. - - 1. dev_flg & dev_ctl determines the end of the priority grant. - The break in the chain will occur at the first device for - which dev_flg & dev_ctl is true. This is determined by - AND'ing the set bits with their 2's complement; only the low - order (highest priority) bit will differ. 1 less than - that, or'd with the single set bit itself, is the mask of - possible interrupting devices. If ION is clear, only devices - 4 and 5 are eligible to interrupt. - 2. dev_flg & dev_ctl & dev_fbf determines the outstanding - interrupt requests. All three bits must be on for a device - to request an interrupt. This is the masked under the - result from #1 to determine the highest priority interrupt, - if any. - */ - -uint32 calc_int (void) -{ -int32 j, lomask, mask[2], req[2]; - -lomask = dev_flg[0] & dev_ctl[0] & ~M_NXDEV; /* start chain calc */ -req[0] = lomask & dev_fbf[0]; /* calc requests */ -lomask = lomask & (-lomask); /* chain & -chain */ -mask[0] = lomask | (lomask - 1); /* enabled devices */ -req[0] = req[0] & mask[0]; /* highest request */ -if (ion) { /* ion? */ - if (lomask == 0) { /* no break in chn? */ - mask[1] = dev_flg[1] & dev_ctl[1]; /* do all devices */ - req[1] = mask[1] & dev_fbf[1]; - mask[1] = mask[1] & (-mask[1]); - mask[1] = mask[1] | (mask[1] - 1); - req[1] = req[1] & mask[1]; } - else req[1] = 0; } -else { req[0] = req[0] & (INT_M (PWR) | INT_M (PRO)); - req[1] = 0; } -if (req[0]) { /* if low request */ - for (j = 0; j < 32; j++) { /* find dev # */ - if (req[0] & INT_M (j)) return j; } } -if (req[1]) { /* if hi request */ - for (j = 0; j < 32; j++) { /* find dev # */ - if (req[1] & INT_M (j)) return (32 + j); } } -return 0; -} - -/* Memory access routines */ - -uint8 ReadB (uint32 va) -{ -int32 pa; - -if (dms_enb) pa = dms (va >> 1, dms_ump, RD); -else pa = va >> 1; -if (va & 1) return (M[pa] & 0377); -else return ((M[pa] >> 8) & 0377); -} - -uint8 ReadBA (uint32 va) -{ -uint32 pa; - -if (dms_enb) pa = dms (va >> 1, dms_ump ^ MAP_LNT, RD); -else pa = va >> 1; -if (va & 1) return (M[pa] & 0377); -else return ((M[pa] >> 8) & 0377); -} - -uint16 ReadW (uint32 va) -{ -uint32 pa; - -if (dms_enb) pa = dms (va, dms_ump, RD); -else pa = va; -return M[pa]; -} - -uint16 ReadWA (uint32 va) -{ -uint32 pa; - -if (dms_enb) pa = dms (va, dms_ump ^ MAP_LNT, RD); -else pa = va; -return M[pa]; -} - -uint32 ReadF (uint32 va) -{ -uint32 t = ReadW (va); -uint32 t1 = ReadW ((va + 1) & VAMASK); -return (t << 16) | t1; -} - -uint16 ReadIO (uint32 va, uint32 map) -{ -uint32 pa; - -if (dms_enb) pa = dms_io (va, map); -else pa = va; -return M[pa]; -} - -/* Memory protection test for writes */ - -#define MP_TEST(x) (CTL (PRO) && ((x) > 1) && ((x) < mp_fence)) - -void WriteB (uint32 va, uint32 dat) -{ -uint32 pa; - -if (dms_enb) pa = dms (va >> 1, dms_ump, WR); -else { if (MP_TEST (va >> 1)) ABORT (ABORT_PRO); - pa = va >> 1; } -if (MEM_ADDR_OK (pa)) { - if (va & 1) M[pa] = (M[pa] & 0177400) | (dat & 0377); - else M[pa] = (M[pa] & 0377) | ((dat & 0377) << 8); } -return; -} - -void WriteBA (uint32 va, uint32 dat) -{ -uint32 pa; - -if (dms_enb) { - dms_viol (va >> 1, MVI_WPR); /* viol if prot */ - pa = dms (va >> 1, dms_ump ^ MAP_LNT, WR); } -else { if (MP_TEST (va >> 1)) ABORT (ABORT_PRO); - pa = va >> 1; } -if (MEM_ADDR_OK (pa)) { - if (va & 1) M[pa] = (M[pa] & 0177400) | (dat & 0377); - else M[pa] = (M[pa] & 0377) | ((dat & 0377) << 8); } -return; -} - -void WriteW (uint32 va, uint32 dat) -{ -uint32 pa; - -if (dms_enb) pa = dms (va, dms_ump, WR); -else { if (MP_TEST (va)) ABORT (ABORT_PRO); - pa = va; } -if (MEM_ADDR_OK (pa)) M[pa] = dat; -return; -} - -void WriteWA (uint32 va, uint32 dat) -{ -int32 pa; - -if (dms_enb) { - dms_viol (va, MVI_WPR); /* viol if prot */ - pa = dms (va, dms_ump ^ MAP_LNT, WR); } -else { if (MP_TEST (va)) ABORT (ABORT_PRO); - pa = va; } -if (MEM_ADDR_OK (pa)) M[pa] = dat; -return; -} - -void WriteIO (uint32 va, uint32 dat, uint32 map) -{ -uint32 pa; - -if (dms_enb) pa = dms_io (va, map); -else pa = va; -if (MEM_ADDR_OK (pa)) M[pa] = dat; -return; -} - -/* DMS relocation for CPU access */ - -uint32 dms (uint32 va, uint32 map, uint32 prot) -{ -uint32 pgn, mpr; - -if (va <= 1) return va; /* A, B */ -pgn = VA_GETPAG (va); /* get page num */ -if (pgn == 0) { /* base page? */ - uint32 dms_fence = dms_sr & MST_FENCE; /* get fence value */ - if ((dms_sr & MST_FLT)? /* check unmapped */ - (va >= dms_fence): /* 1B10: >= fence */ - (va < dms_fence)) { /* 0B10: < fence */ - if (prot == WR) dms_viol (va, MVI_BPG); /* if W, viol */ - return va; } } /* no mapping */ -mpr = dms_map[map + pgn]; /* get map reg */ -if (mpr & prot) dms_viol (va, prot << (MVI_V_WPR - MAPA_V_WPR)); -return (PA_GETPAG (mpr) | VA_GETOFF (va)); -} - -/* DMS relocation for IO access */ - -uint32 dms_io (uint32 va, uint32 map) -{ -uint32 pgn, mpr; - -if (va <= 1) return va; /* A, B */ -pgn = VA_GETPAG (va); /* get page num */ -if (pgn == 0) { /* base page? */ - uint32 dms_fence = dms_sr & MST_FENCE; /* get fence value */ - if ((dms_sr & MST_FLT)? /* check unmapped */ - (va >= dms_fence): /* 1B10: >= fence */ - (va < dms_fence)) { /* 0B10: < fence */ - return va; } } /* no mapping */ -mpr = dms_map[map + pgn]; /* get map reg */ -return (PA_GETPAG (mpr) | VA_GETOFF (va)); -} - -/* DMS relocation for console access */ - -uint32 dms_cons (uint32 va, int32 sw) -{ -if (sw & SWMASK ("V")) return dms_io (va, dms_ump); -if (sw & SWMASK ("S")) return dms_io (va, SMAP); -if (sw & SWMASK ("U")) return dms_io (va, UMAP); -if (sw & SWMASK ("P")) return dms_io (va, PAMAP); -if (sw & SWMASK ("Q")) return dms_io (va, PBMAP); -return va; -} - -/* Mem protect and DMS validation for jumps */ - -void mp_dms_jmp (uint32 va) -{ -uint32 pgn = VA_GETPAG (va); /* get page num */ - -if ((pgn == 0) && (va > 1)) { /* base page? */ - uint32 dms_fence = dms_sr & MST_FENCE; /* get fence value */ - if ((dms_sr & MST_FLT)? /* check unmapped */ - (va >= dms_fence): /* 1B10: >= fence */ - (va < dms_fence)) { /* 0B10: < fence */ - dms_viol (va, MVI_BPG); /* if W, viol */ - return; } } /* PRO not set */ -if (CTL (PRO) && (va < mp_fence)) ABORT (ABORT_PRO); /* base page MPR */ -return; -} - -/* DMS read and write maps */ - -uint16 dms_rmap (uint32 mapi) -{ -int32 t; - -mapi = mapi & MAP_MASK; -t = (((dms_map[mapi] >> VA_N_OFF) & PA_M_PAG) | - ((dms_map[mapi] & (RD | WR)) << (MAPM_V_WPR - MAPA_V_WPR))); -return (uint16) t; -} - -void dms_wmap (uint32 mapi, uint32 dat) -{ -mapi = mapi & MAP_MASK; -dms_map[mapi] = ((dat & PA_M_PAG) << VA_N_OFF) | - ((dat >> (MAPM_V_WPR - MAPA_V_WPR)) & (RD | WR)); -return; -} - -/* DMS violation */ - -void dms_viol (uint32 va, uint32 st) -{ -dms_vr = st | VA_GETPAG (va) | - ((st & (MVI_RPR | MVI_WPR))? MVI_MEB: 0) | /* set MEB */ - (dms_enb? MVI_MEM: 0) | /* set MEM */ - (dms_ump? MVI_UMP: 0); /* set UMAP */ -if (CTL (PRO)) { /* protected? */ - mp_mevff = 1; /* signal dms */ - ABORT (ABORT_PRO); } /* abort */ -return; -} - -/* DMS update status */ - -uint32 dms_upd_sr (void) -{ -dms_sr = dms_sr & ~(MST_ENB | MST_UMP | MST_PRO); -if (dms_enb) dms_sr = dms_sr | MST_ENB; -if (dms_ump) dms_sr = dms_sr | MST_UMP; -if (CTL (PRO)) dms_sr = dms_sr | MST_PRO; -return dms_sr; -} - -/* Device 0 (CPU) I/O routine */ - -int32 cpuio (int32 inst, int32 IR, int32 dat) -{ -int i; - -switch (inst) { /* case on opcode */ -case ioFLG: /* flag */ - ion = (IR & I_HC)? 0: 1; /* interrupts off/on */ - return dat; -case ioSFC: /* skip flag clear */ - if (!ion) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (ion) PC = (PC + 1) & VAMASK; - return dat; -case ioLIX: /* load */ - dat = 0; /* returns 0 */ - break; -case ioCTL: /* control */ - if (IR & I_CTL) { /* =CLC 02,03,06..77 */ - devdisp (DMALT0, inst, I_CTL + DMALT0, 0); - devdisp (DMALT1, inst, I_CTL + DMALT1, 0); - for (i = 6; i <= I_DEVMASK; i++) - devdisp (i, inst, I_CTL + i, 0); } - break; -default: - break; } -if (IR & I_HC) ion = 0; /* HC option */ -return dat; -} - -/* Device 1 (overflow) I/O routine */ - -int32 ovfio (int32 inst, int32 IR, int32 dat) -{ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag */ - O = (IR & I_HC)? 0: 1; /* clear/set overflow */ - return dat; -case ioSFC: /* skip flag clear */ - if (!O) PC = (PC + 1) & VAMASK; - break; /* can clear flag */ -case ioSFS: /* skip flag set */ - if (O) PC = (PC + 1) & VAMASK; - break; /* can clear flag */ -case ioMIX: /* merge */ - dat = dat | SR; - break; -case ioLIX: /* load */ - dat = SR; - break; -case ioOTX: /* output */ - SR = dat; - break; -default: - break; } -if (IR & I_HC) O = 0; /* HC option */ -return dat; -} - -/* Device 4 (power fail) I/O routine */ - -int32 pwrio (int32 inst, int32 IR, int32 dat) -{ -switch (inst) { /* case on opcode */ -case ioMIX: /* merge */ - dat = dat | intaddr; - break; -case ioLIX: /* load */ - dat = intaddr; - break; -default: - break; } -return dat; -} - -/* Device 5 (memory protect) I/O routine */ - -int32 proio (int32 inst, int32 IR, int32 dat) -{ -if ((cpu_unit.flags & UNIT_MPR) == 0) /* not installed? */ - return nulio (inst, IR, dat); /* non-existent dev */ -switch (inst) { /* case on opcode */ -case ioSFC: /* skip flag clear */ - if (FLG (PRO) && !mp_mevff) /* skip if mem prot */ - PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (PRO) && mp_mevff) /* skip if DMS */ - PC = (PC + 1) & VAMASK; - return dat; -case ioMIX: /* merge */ - dat = dat | mp_viol; - break; -case ioLIX: /* load */ - dat = mp_viol; - break; -case ioOTX: /* output */ - mp_fence = dat & VAMASK; - if (cpu_unit.flags & UNIT_2100) iop_sp = mp_fence; - break; -case ioCTL: /* control clear/set */ - if ((IR & I_CTL) == 0) { /* STC */ - setCTL (PRO); - dms_vr = 0; - mp_evrff = 1; /* allow mp_viol upd */ - mp_mevff = 0; } /* clear DMS flag */ - break; -default: - break; } -if (IR & I_HC) { clrFLG (PRO); } /* HC option */ -return dat; -} - -/* Devices 2,3 (secondary DMA) I/O routine */ - -int32 dmsio (int32 inst, int32 IR, int32 dat) -{ -int32 ch; - -ch = IR & 1; /* get channel num */ -switch (inst) { /* case on opcode */ -case ioMIX: /* merge */ - dat = dat | dmac[ch].cw3; - break; -case ioLIX: /* load */ - dat = dmac[ch].cw3; - break; -case ioOTX: /* output */ - if (CTL (DMALT0 + ch)) dmac[ch].cw3 = dat; - else dmac[ch].cw2 = dat; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { clrCTL (DMALT0 + ch); } /* CLC */ - else { setCTL (DMALT0 + ch); } /* STC */ - break; -default: - break; } -return dat; -} - -/* Devices 6,7 (primary DMA) I/O routine */ - -int32 dmpio (int32 inst, int32 IR, int32 dat) -{ -int32 ch; - -ch = IR & 1; /* get channel number */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag */ - if ((IR & I_HC) == 0) { /* set->abort */ - setFLG (DMA0 + ch); /* set flag */ - clrCMD (DMA0 + ch); } /* clr cmd */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (DMA0 + ch) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (DMA0 + ch) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioMIX: case ioLIX: /* load, merge */ - dat = DMASK; - break; -case ioOTX: /* output */ - dmac[ch].cw1 = dat; - break; -case ioCTL: /* control */ - if (IR & I_CTL) { clrCTL (DMA0 + ch); } /* CLC: cmd unchgd */ - else { /* STC */ - setCTL (DMA0 + ch); /* set ctl, cmd */ - setCMD (DMA0 + ch); } - break; -default: - break; } -if (IR & I_HC) { clrFLG (DMA0 + ch); } /* HC option */ -return dat; -} - -/* DMA cycle routine - - The last cycle (word count reaches 0) logic is quite tricky. - Input cases: - - CLC requested: issue CLC - Output cases: - - neither STC nor CLC requested: issue CLF - - CLC requested but not STC: issue CLC,C - - STC requested but not CLC: issue STC,C - - STC and CLC both requested: issue STC,C and CLC,C -*/ - -void dma_cycle (uint32 ch, uint32 map) -{ -int32 temp, dev, MA; -int32 inp = dmac[ch].cw2 & DMA2_OI; /* input flag */ - -dev = dmac[ch].cw1 & I_DEVMASK; /* get device */ -MA = dmac[ch].cw2 & VAMASK; /* get mem addr */ -if (inp) { /* input? */ - temp = devdisp (dev, ioLIX, dev, 0); /* do LIA dev */ - WriteIO (MA, temp, map); } /* store data */ -else { temp = ReadIO (MA, map); /* read data */ - devdisp (dev, ioOTX, dev, temp); } /* do OTA dev */ -dmac[ch].cw2 = (dmac[ch].cw2 & DMA2_OI) | ((dmac[ch].cw2 + 1) & VAMASK); -dmac[ch].cw3 = (dmac[ch].cw3 + 1) & DMASK; /* incr wcount */ -if (dmac[ch].cw3) { /* more to do? */ - if (dmac[ch].cw1 & DMA1_STC) /* if STC flag, */ - devdisp (dev, ioCTL, I_HC + dev, 0); /* do STC,C dev */ - else devdisp (dev, ioFLG, I_HC + dev, 0); } /* else CLF dev */ -else { if (inp) { /* last cycle, input? */ - if (dmac[ch].cw1 & DMA1_CLC) /* CLC at end? */ - devdisp (dev, ioCTL, I_CTL + dev, 0); /* yes */ - } /* end input */ - else { /* output */ - devdisp (dev, ioFLG, I_HC + dev, 0); /* clear flag */ - if (dmac[ch].cw1 & DMA1_STC) /* if STC flag, */ - devdisp (dev, ioCTL, dev, 0); /* do STC dev */ - if (dmac[ch].cw1 & DMA1_CLC) /* CLC at end? */ - devdisp (dev, ioCTL, I_CTL + dev, 0); /* yes */ - } /* end output */ - setFLG (DMA0 + ch); /* set DMA flg */ - clrCMD (DMA0 + ch); } /* clr DMA cmd */ -return; -} - -/* Unimplemented device routine */ - -int32 nulio (int32 inst, int32 IR, int32 dat) -{ -switch (inst) { /* case on opcode */ -case ioSFC: /* skip flag clear */ - PC = (PC + 1) & VAMASK; - return (stop_dev << IOT_V_REASON) | dat; -case ioSFS: /* skip flag set */ - return (stop_dev << IOT_V_REASON) | dat; -default: - break; } -if (IR & I_HC) { clrFLG (IR & I_DEVMASK); } /* HC option */ -return (stop_dev << IOT_V_REASON) | dat; -} - -/* Reset routines */ - -t_stat cpu_reset (DEVICE *dptr) -{ -E = 0; -O = 0; -ion = ion_defer = 0; -clrCMD (PWR); -clrCTL (PWR); -clrFLG (PWR); -clrFBF (PWR); -clrCMD (PRO); -clrCTL (PRO); -clrFLG (PRO); -clrFBF (PRO); -mp_fence = 0; /* init mprot */ -mp_viol = 0; -mp_mevff = 0; -mp_evrff = 1; -dms_enb = dms_ump = 0; /* init DMS */ -dms_sr = 0; -dms_vr = 0; -pcq_r = find_reg ("PCQ", NULL, dptr); -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -if (M == NULL) M = calloc (PASIZE, sizeof (unsigned int16)); -if (M == NULL) return SCPE_MEM; -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -return SCPE_OK; -} - -t_stat dma0_reset (DEVICE *tptr) -{ -clrCMD (DMA0); -clrCTL (DMA0); -setFLG (DMA0); -dmac[0].cw1 = dmac[0].cw2 = dmac[0].cw3 = 0; -return SCPE_OK; -} - -t_stat dma1_reset (DEVICE *tptr) -{ -clrCMD (DMA1); -clrCTL (DMA1); -setFLG (DMA1); -dmac[1].cw1 = dmac[1].cw2 = dmac[1].cw3 = 0; -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -int32 d; - -if (addr >= MEMSIZE) return SCPE_NXM; -addr = dms_cons (addr, sw); -if (addr == 0) d = saved_AR; -else if (addr == 1) d = saved_BR; -else d = M[addr]; -if (vptr != NULL) *vptr = d & DMASK; -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -addr = dms_cons (addr, sw); -if (addr == 0) saved_AR = val & DMASK; -else if (addr == 1) saved_BR = val & DMASK; -else M[addr] = val & DMASK; -return SCPE_OK; -} - -/* Memory size validation */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i; - -if ((val <= 0) || (val > PASIZE) || ((val & 07777) != 0) || - (!(uptr->flags & UNIT_21MX) && (val > 32768))) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; -if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_OK; -MEMSIZE = val; -for (i = MEMSIZE; i < PASIZE; i++) M[i] = 0; -return SCPE_OK; -} - -/* Set device number */ - -t_stat hp_setdev (UNIT *uptr, int32 num, char *cptr, void *desc) -{ -DEVICE *dptr = (DEVICE *) desc; -DIB *dibp; -int32 i, newdev; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if ((desc == NULL) || (num > 1)) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newdev = get_uint (cptr, 8, I_DEVMASK - num, &r); -if (r != SCPE_OK) return r; -if (newdev < VARDEV) return SCPE_ARG; -for (i = 0; i <= num; i++, dibp++) dibp->devno = newdev + i; -return SCPE_OK; -} - -/* Show device number */ - -t_stat hp_showdev (FILE *st, UNIT *uptr, int32 num, void *desc) -{ -DEVICE *dptr = (DEVICE *) desc; -DIB *dibp; -int32 i; - -if ((desc == NULL) || (num > 1)) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -fprintf (st, "devno=%o", dibp->devno); -for (i = 1; i <= num; i++) fprintf (st, "/%o", dibp->devno + i); -return SCPE_OK; -} - -/* Make a pair of devices consistent */ - -void hp_enbdis_pair (DEVICE *ccp, DEVICE *dcp) -{ -if (ccp->flags & DEV_DIS) dcp->flags = dcp->flags | DEV_DIS; -else dcp->flags = dcp->flags & ~DEV_DIS; -return; -} - -/* Test for device conflict */ - -t_bool dev_conflict (void) -{ -DEVICE *dptr, *cdptr; -DIB *dibp, *chkp; -int32 i, j, dno; - -for (i = 0; cdptr = sim_devices[i]; i++) { - chkp = (DIB *) cdptr->ctxt; - if (chkp && !(cdptr->flags & DEV_DIS)) { - dno = chkp->devno; - for (j = 0; dptr = sim_devices[j]; j++) { - dibp = (DIB *) dptr->ctxt; - if (dibp && !(dptr->flags & DEV_DIS) && - (chkp != dibp) && (dno == dibp->devno)) { - printf ("%s device number conflict, devno = %d\n", - sim_dname (dptr), dno); - if (sim_log) fprintf (sim_log, - "%s device number conflict, devno = %d\n", - sim_dname (dptr), dno); - return TRUE; } } } } -return FALSE; -} - -/* Configuration validation */ - -t_bool cpu_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 opt = (int32) desc; -int32 mod, i; - -mod = MOD_2116; -if (uptr->flags & UNIT_2100) mod = MOD_2100; -else if (uptr->flags & UNIT_21MX) mod = MOD_21MX; -for (i = 0; opt_val[i].optf != 0; i++) { - if ((opt == opt_val[i].optf) && (mod & opt_val[i].cpuf)) { - if ((mod == MOD_2100) && (val == UNIT_FP)) - uptr->flags = uptr->flags & ~UNIT_IOP; - if ((opt == UNIT_IOP) && val) { - if (mod == MOD_2100) uptr->flags = - (uptr->flags & ~UNIT_FP) | UNIT_IOP | UNIT_MPR; - if (mod == MOD_21MX) uptr->flags |= UNIT_IOPX | UNIT_MPR; } - if (val == UNIT_DMS) uptr->flags |= UNIT_MPR; - return SCPE_OK; } } -return SCPE_NOFNC; -} - diff --git a/HP2100/hp2100_defs.h b/HP2100/hp2100_defs.h deleted file mode 100644 index 3c7940df..00000000 --- a/HP2100/hp2100_defs.h +++ /dev/null @@ -1,269 +0,0 @@ -/* hp2100_defs.h: HP 2100 simulator definitions - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 25-Apr-03 RMS Revised for extended file support - 24-Oct-02 RMS Added indirect address interrupt - 08-Feb-02 RMS Added DMS definitions - 01-Feb-02 RMS Added terminal multiplexor support - 16-Jan-02 RMS Added additional device support - 30-Nov-01 RMS Added extended SET/SHOW support - 15-Oct-00 RMS Added dynamic device numbers - 14-Apr-99 RMS Changed t_addr to unsigned - - The author gratefully acknowledges the help of Jeff Moffat in answering - questions about the HP2100. -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_IODV 2 /* must be 2 */ -#define STOP_HALT 3 /* HALT */ -#define STOP_IBKPT 4 /* breakpoint */ -#define STOP_IND 5 /* indirect loop */ -#define STOP_INDINT 6 /* indirect intr */ -#define STOP_NOCONN 7 /* no connection */ - -#define ABORT_PRO 1 /* protection abort */ - -/* Memory */ - -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) -#define VA_N_SIZE 15 /* virtual addr size */ -#define VASIZE (1 << VA_N_SIZE) -#define VAMASK (VASIZE - 1) /* virt addr mask */ -#define PA_N_SIZE 20 /* phys addr size */ -#define PASIZE (1 << PA_N_SIZE) -#define PAMASK (PASIZE - 1) /* phys addr mask */ - -/* Architectural constants */ - -#define SIGN32 020000000000 /* 32b sign */ -#define SIGN 0100000 /* 16b sign */ -#define DMASK 0177777 /* 16b data mask */ -#define AR M[0] /* A = location 0 */ -#define BR M[1] /* B = location 1 */ -#define ABREG M /* register array */ -#define SEXT(x) ((int32) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK))) - -/* Memory reference instructions */ - -#define I_IA 0100000 /* indirect address */ -#define I_AB 0004000 /* A/B select */ -#define I_CP 0002000 /* current page */ -#define I_DISP 0001777 /* page displacement */ -#define I_PAGENO 0076000 /* page number */ - -/* Other instructions */ - -#define I_NMRMASK 0102000 /* non-mrf opcode */ -#define I_SRG 0000000 /* shift */ -#define I_ASKP 0002000 /* alter/skip */ -#define I_EXTD 0100000 /* extend */ -#define I_IO 0102000 /* I/O */ -#define I_CTL 0004000 /* CTL on/off */ -#define I_HC 0001000 /* hold/clear */ -#define I_DEVMASK 0000077 /* device mask */ -#define I_GETIOOP(x) (((x) >> 6) & 07) /* I/O sub op */ - -/* DMA channels */ - -#define DMA1_STC 0100000 /* DMA - issue STC */ -#define DMA1_CLC 0020000 /* DMA - issue CLC */ -#define DMA2_OI 0100000 /* DMA - output/input */ - -struct DMA { /* DMA channel */ - int32 cw1; /* device select */ - int32 cw2; /* direction, address */ - int32 cw3; /* word count */ -}; - -/* Memory management */ - -#define VA_N_OFF 10 /* offset width */ -#define VA_M_OFF ((1 << VA_N_OFF) - 1) /* offset mask */ -#define VA_GETOFF(x) ((x) & VA_M_OFF) -#define VA_N_PAG (VA_N_SIZE - VA_N_OFF) /* page width */ -#define VA_V_PAG (VA_N_OFF) -#define VA_M_PAG ((1 << VA_N_PAG) - 1) -#define VA_GETPAG(x) (((x) >> VA_V_PAG) & VA_M_PAG) - -/* Maps */ - -#define MAP_NUM 4 /* num maps */ -#define MAP_LNT (1 << VA_N_PAG) /* map length */ -#define MAP_MASK ((MAP_NUM * MAP_LNT) - 1) -#define SMAP 0 /* system map */ -#define UMAP (SMAP + MAP_LNT) /* user map */ -#define PAMAP (UMAP + MAP_LNT) /* port A map */ -#define PBMAP (PAMAP + MAP_LNT) /* port B map */ - -/* Map entries are left shifted by VA_N_OFF, flags in lower 2b */ - -#define PA_N_PAG (PA_N_SIZE - VA_N_OFF) /* page width */ -#define PA_V_PAG (VA_N_OFF) -#define PA_M_PAG ((1 << PA_N_PAG) - 1) -#define MAPM_V_RPR 15 /* in mem: read prot */ -#define MAPM_V_WPR 14 /* write prot */ -#define MAPA_V_RPR 1 /* in array: */ -#define MAPA_V_WPR 0 -#define PA_GETPAG(x) ((x) & (PA_M_PAG << VA_V_PAG)) -#define RD (1 << MAPA_V_RPR) -#define WR (1 << MAPA_V_WPR) - -/* Map status register */ - -#define MST_ENBI 0100000 /* mem enb @ int */ -#define MST_UMPI 0040000 /* usr map @ int */ -#define MST_ENB 0020000 /* mem enb */ -#define MST_UMP 0010000 /* usr map */ -#define MST_PRO 0004000 /* protection */ -#define MST_FLT 0002000 /* fence comp */ -#define MST_FENCE 0001777 /* base page fence */ - -/* Map violation register */ - -#define MVI_V_RPR 15 -#define MVI_V_WPR 14 -#define MVI_RPR (1 << MVI_V_RPR) /* rd viol */ -#define MVI_WPR (1 << MVI_V_WPR) /* wr viol */ -#define MVI_BPG 0020000 /* base page viol */ -#define MVI_PRV 0010000 /* priv viol */ -#define MVI_MEB 0000200 /* me bus enb @ viol */ -#define MVI_MEM 0000100 /* mem enb @ viol */ -#define MVI_UMP 0000040 /* usr map @ viol */ -#define MVI_PAG 0000037 /* pag sel */ - -/* Timers */ - -#define TMR_CLK 0 /* clock */ -#define TMR_MUX 1 /* multiplexor */ - -/* I/O sub-opcodes */ - -#define ioHLT 0 /* halt */ -#define ioFLG 1 /* set/clear flag */ -#define ioSFC 2 /* skip on flag clear */ -#define ioSFS 3 /* skip on flag set */ -#define ioMIX 4 /* merge into A/B */ -#define ioLIX 5 /* load into A/B */ -#define ioOTX 6 /* output from A/B */ -#define ioCTL 7 /* set/clear control */ - -/* I/O devices - fixed assignments */ - -#define CPU 000 /* interrupt control */ -#define OVF 001 /* overflow */ -#define DMALT0 002 /* DMA 0 alternate */ -#define DMALT1 003 /* DMA 1 alternate */ -#define PWR 004 /* power fail */ -#define PRO 005 /* parity/mem protect */ -#define DMA0 006 /* DMA channel 0 */ -#define DMA1 007 /* DMA channel 1 */ -#define VARDEV (DMA1 + 1) /* start of var assign */ -#define M_NXDEV (INT_M (CPU) | INT_M (OVF) | \ - INT_M (DMALT0) | INT_M (DMALT1)) -#define M_FXDEV (M_NXDEV | INT_M (PWR) | INT_M (PRO) | \ - INT_M (DMA0) | INT_M (DMA1)) - -/* I/O devices - variable assignment defaults */ - -#define PTR 010 /* paper tape reader */ -#define TTY 011 /* console */ -#define PTP 012 /* paper tape punch */ -#define CLK 013 /* clock */ -#define LPS 014 /* 12653 line printer */ -#define LPT 015 /* 12845 line printer */ -#define MTD 020 /* 12559A data */ -#define MTC 021 /* 12559A control */ -#define DPD 022 /* 12557A data */ -#define DPC 023 /* 12557A control */ -#define DQD 024 /* 12565A data */ -#define DQC 025 /* 12565A control */ -#define DRD 026 /* 12610A data */ -#define DRC 027 /* 12610A control */ -#define MSD 030 /* 13181A data */ -#define MSC 031 /* 13181A control */ -#define IPLI 032 /* 12556B link in */ -#define IPLO 033 /* 12556B link out */ -#define MUXL 040 /* 12920A lower data */ -#define MUXU 041 /* 12920A upper data */ -#define MUXC 042 /* 12920A control */ - -/* IBL assignments */ - -#define IBL_PTR 0000000 /* PTR */ -#define IBL_DP 0040000 /* DP */ -#define IBL_DQ 0060000 /* DQ */ -#define IBL_MS 0100000 /* MS */ -#define IBL_TBD 0140000 /* tbd */ -#define IBL_V_DEV 6 /* dev in <11:6> */ -#define IBL_FIX 0000001 /* DP fixed */ -#define IBL_LNT 64 /* boot length */ -#define IBL_MASK (IBL_LNT - 1) /* boot length mask */ - -/* Dynamic device information table */ - -struct hp_dib { - int32 devno; /* device number */ - int32 cmd; /* saved command */ - int32 ctl; /* saved control */ - int32 flg; /* saved flag */ - int32 fbf; /* saved flag buf */ - int32 (*iot)(); /* I/O routine */ -}; - -typedef struct hp_dib DIB; - -/* I/O macros */ - -#define INT_V(x) ((x) & 037) /* device bit pos */ -#define INT_M(x) (1u << INT_V (x)) /* device bit mask */ -#define setCMD(D) dev_cmd[(D)/32] = dev_cmd[(D)/32] | INT_M ((D)) -#define clrCMD(D) dev_cmd[(D)/32] = dev_cmd[(D)/32] & ~INT_M (D) -#define setCTL(D) dev_ctl[(D)/32] = dev_ctl[(D)/32] | INT_M ((D)) -#define clrCTL(D) dev_ctl[(D)/32] = dev_ctl[(D)/32] & ~INT_M (D) -#define setFBF(D) dev_fbf[(D)/32] = dev_fbf[(D)/32] | INT_M (D) -#define clrFBF(D) dev_fbf[(D)/32] = dev_fbf[(D)/32] & ~INT_M (D) -#define setFLG(D) dev_flg[(D)/32] = dev_flg[(D)/32] | INT_M (D); \ - setFBF(D) -#define clrFLG(D) dev_flg[(D)/32] = dev_flg[(D)/32] & ~INT_M (D); \ - clrFBF(D) -#define CMD(D) ((dev_cmd[(D)/32] >> INT_V (D)) & 1) -#define CTL(D) ((dev_ctl[(D)/32] >> INT_V (D)) & 1) -#define FLG(D) ((dev_flg[(D)/32] >> INT_V (D)) & 1) -#define FBF(D) ((dev_fbf[(D)/32] >> INT_V (D)) & 1) - -#define IOT_V_REASON 16 -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ - -/* Function prototypes */ - -t_stat hp_setdev (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat hp_showdev (FILE *st, UNIT *uptr, int32 val, void *desc); -void hp_enbdis_pair (DEVICE *ccp, DEVICE *dcp); diff --git a/HP2100/hp2100_diag.txt b/HP2100/hp2100_diag.txt deleted file mode 100644 index 263c10f8..00000000 --- a/HP2100/hp2100_diag.txt +++ /dev/null @@ -1,171 +0,0 @@ -HP2100 Diagnostics - -CPU status writeup sources - -24315 Memory reference group passed in 21MX CE no - - LOAD diagnostic - - RUN 100 - - HLT 77, PC = 3353 - -24316 Alter/skip group passed in 21MX CE no - - LOAD diagnostic - - RUN 100 - - HLT 77, PC = 633 - -24317 Shift/rotate group passed in 21MX CE no - - LOAD diagnostic - - RUN 100 - - HLT 77, PC = 1726 - -24296 Diagnostic configurator passed in 21MX CE no - - LOAD configurator - - SET CPU 21MX - - ATTACH PTR binary image of - diagnostic to be configured - - D S XXYY, where XX = device number - of PTR, YY = device number of TTY - - RUN 2 - - HLT 77, PC = 77237 (for 32K mem) - -24319 Extended arithmetic group passed in 21MX CE no - - load diagnostic via configurator - - D S 0 - - RUN 100 - - prints diagnostic name - - prints END OF PASS 1 and halts - -13206 IOP for 2100 passed 13206 manual no - - load diagnostic via configurator - - D S 0 - - SET CPU 2100 - - SET CPU IOP - - RUN 2000 - - prints diagnostic name - - prints section names, PASS 000001, and halts - - note: will not pass interruptibility tests - -13207 IOP for 21MX passed 13207 manual no - - load diagnostic via configurator - - D S 13 - - SET CPU 21MX - - SET CPU IOP - - RUN 100 - - HLT 74, PC = 2425 - - D S 0 - - CON - - prints diagnostic name - - prints section names, PASS 000001, and halts - -24320 Floating point passed in 21MX CE no - - load diagnostic via configurator - - D S 0 - - RUN 100 - - prints diagnostic name - - prints PASS 000001 and halts - -12943-1 Extended instruction group, part 1 passed 12943 manual no - - load diagnostic via configurator - - D S 0 - - RUN 100 - - prints diagnostic name - - prints PASS 000001 and halts - -12943-2 Extended instruction group, part 2 passed 12943 manual no - - load diagnostic via configurator - - D S XX, where XX = device number - of TTY - - RUN 100 - - HLT 74, PC = 2406 - - D S 0 - - CONTINUE - - prints diagnostic name - - prints PASS 000001 and halts - -24322 Dual channel port controller passed in 21MX CE no - - load diagnostic via configurator - - SET LPS ENA - - SET LPS DIAG - - D S XX, where XX = device number - of LPS - - RUN 100 - - HALT 74, PC = 1541 - - D S 0 - - CONTINUE - - prints diagnostic name - - prints H324 PRESS PRESET AND RUN - - HLT 24, PC = 2312 - - RESET ALL - - CONTINUE - - prints PASS 000001 and halts - -12892 Memory protect-parity error passed in 21MX CE no - - load diagnostic via configurator - - disable all I/O devices except - PTR, TTY, clock - - D S 1400XX, where XX = device number - of PTR - - RUN 100 - - HLT 74, PC = 2444 - - D S 1000 (test select mode) - - CONTINUE - - prints diagnostic name - - HLT 75, PC = 2026 - - D S 0 - - D A 31777 (tests 10-11 can't be run) - - Rings bell and prints - H314 PRESS HALT,PRESET AND RUN WITHIN 30 SECONDS - - WRU (CTRL+E) to interrupt simulation - - RESET ALL - - CONTINUE - - prints PASS 000001 and halts - -12929 Memory expansion unit (DMS) passed in 21MX CE no - - load diagnostic via configurator - - SET CPU 64K - - SET LPS ENA - - SET LPS DIAG - - D S XX, where XX = device number - of LPS - - RUN 100 - - HLT 74, PC = 2435 - - D S 0 - - CONTINUE - - Prints H115 PRESS HALT-PRESET-RUN IN LESS THAN 10 SECONDS - - WRU (CTRL+E) to interrupt simulation - - RESET ALL - - CONTINUE - - Prints H117 PRESET TEST COMPLETE - - Prints PASS 000001 and halts - - Test 23 won't run at >256K mem - (real 21MX limited to 304K) - -Peripherals - -12531 TTY test passed in 21MX CE no - - set TTY TTIME to 100 - - run with test select = 173 - - remaining tests can't be run -12539 time base generator passed in 21MX CE no - - runs with CLK in diag mode -12597 reader/punch passed in 21MX CE no - - set PTP TIME to 100 - - run with test select a=4017 - - remaining tests can't be run -12984 2767 line printer passed in 21MX CE no - - set LPS PTIME, CTIME to 100 - - run with test select a = 15 - - remaining tests can't be run -12960 7900/7901 disk passed in 21MX CE no -12965 2883/2884 disk passed 12965 manual no -12559 3030 magtape not run no documentation -13181 7970B magtape partial in 21MX CE no - - initial s = 102030 - - set MSC CTIME to 180000 - - do not change MSC XTIME - - attach scratch tapes to units 0,1 - - set s = 1201 (suppress CRC/LRC) - - run with test select a = 37757, b = 7767 - - tests 4, 14, 15 are timing dependent - - test 19 uses non-supported read rev -13183 7970E magtape not run in 21MX CE no -12920 multiplexor not run in 21MX CE no diff --git a/HP2100/hp2100_doc.txt b/HP2100/hp2100_doc.txt deleted file mode 100644 index b6440a10..00000000 --- a/HP2100/hp2100_doc.txt +++ /dev/null @@ -1,945 +0,0 @@ -To: Users -From: Bob Supnik -Subj: HP2100 Simulator Usage -Date: 15-Jul-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - Original code published in 1993-2002, written by Robert M Supnik - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - -This memorandum documents the HP 2100 simulator. - - -1. Simulator Files - -sim/ sim_defs.h - sim_rev.h - sim_sock.h - sim_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tape.c - sim_tmxr.c - -sim/hp2100/ hp2100_defs.h - hp2100_cpu.c - hp2100_fp.c - hp2100_dp.c - hp2100_dq.c - hp2100_dr.c - hp2100_ipl.c - hp2100_lps.c - hp2100_lpt.c - hp2100_mt.c - hp2100_ms.c - hp2100_mux.c - hp2100_stddev.c - hp2100_sys.c - -2. HP2100 Features - -The HP2100 simulator is configured as follows: - -device simulates -name(s) - -CPU 2116 CPU with 32KW memory - 2100 CPU with 32KW memory, FP or IOP instructions - 21MX CPU with 1024KW memory, FP or DMS instructions -DMA0, DMA1 dual channel DMA controller -PTR,PTP 12597A paper tape reader/punch -TTY 12631C buffered terminal controller -LPS 12653A printer controller with 2767 printer - 12566B microcircuit interface for diagnostics -LPT 12845A printer controller with 2607 printer -CLK 12539A/B/C time base generator -MUXL,MUXU,MUXC 12920A terminal multiplexor -DP 12557A disk controller with four 2871 drives - 13210A disk controller with four 7900 drives -DQ 12565A disk controller with two 2883 drives -DR 12606B fixed head disk controller with 2770/2771 disks - 12610B drum controller with 2773/2774/2775 drums -MT 12559C magnetic tape controller with one 3030 drive -MS 13181A magnetic tape controller with four 7970B drives - 13183A magnetic tape controller with four 7970E drives -IPLI 12556B interprocessor link, input side -IPLO 12556B interprocessor link, output side - -The HP2100 simulator implements several unique stop conditions: - - - decode of an undefined instruction, and STOP_INST is et - - reference to an undefined I/O device, and STOP_DEV is set - - more than INDMAX indirect references are detected during - memory reference address decoding - -The HP2100 loader supports standard absolute binary format. The DUMP -command is not implemented. - -2.1 CPU - -CPU options include choice of instruction set and memory size. - - SET CPU 2116 2116 CPU - SET CPU 2100 2100 CPU - SET CPU 21MX 21MX CPU - SET CPU EAU EAU instructions (2116 only) - SET CPU NOEAU no EAU instructions (2116 only) - SET CPU FP FP instructions (2100 only) - SET CPU NOFP no FP instructions (2100 only) - SET CPU IOP IOP instructions (2100, 21MX only) - SET CPU NOIOP no IOP instructions (2100, 21MX only) - SET CPU DMS DMS instructions (21MX only) - SET CPU NODMS no DMS instructions (21MX only) - SET CPU 4K set memory size = 4K - SET CPU 8K set memory size = 8K - SET CPU 16K set memory size = 16K - SET CPU 32K set memory size = 32K - SET CPU 64K set memory size = 64K (21MX only) - SET CPU 128K set memory size = 128K (21MX only) - SET CPU 256K set memory size = 256K (21MX only) - SET CPU 512K set memory size = 512K (21MX only) - SET CPU 1024K set memory size = 1024K (21MX only) - -On the 2100, EAU is standard, and the FP and IOP options are mutually -exclusive. On the 21MX, EAU and FP are standard. The 2100 and 21MX -include memory protection as standard; the 21MX optionally includes -DMS (dynamic memory system). - -If memory size is being reduced, and the memory being truncated contains -non-zero data, the simulator asks for confirmation. Data in the truncated -portion of memory is lost. Initial memory size is 32K. - -These switches are recognized when examining or depositing in CPU memory: - - -v if DMS enabled, interpret address as virtual - -s if DMS enabled, force system map - -u if DMS enabled, force user map - -p if DMS enabled, force port A map - -q if DMS enabled, force port B map - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name models size comments - - P all 15 program counter - A all 16 A register - B all 16 B register - X 21MX 16 X index register - Y 21MX 16 Y index register - S all 16 switch/display register - F 2100,21MX 15 memory protection fence - E all 1 extend flag - O all 1 overflow flag - ION all 1 interrupt enable flag - ION_DEFER all 1 interrupt defer flag - IADDR all 6 most recent interrupting device - MPCTL 2100,21MX 1 memory protection enable - MPFLG 2100,21MX 1 memory protection flag - MPFBF 2100,21MX 1 memory protection flag buffer - MPVR 2100,21MX 16 memory protection violation reg - MPEVR 2100,21MX 1 memory protection freeze flag - MPMEV 2100,21MX 1 memory protection DMS error flag - DMSENB 21MX 1 DMS enable - DMSCUR 21MX 1 DMS current mode - DMSSR 21MX 16 DMS status register - DMSVR 21MX 16 DMS violation register - DMSMAP[4][32] 21MX 20 DMS maps - STOP_INST all 1 stop on undefined instruction - STOP_DEV all 1 stop on undefined device - INDMAX all 16 indirect address limit - PCQ[0:63] all 15 P of last JMP, JSB, or interrupt; - most recent P change first - WRU all 8 interrupt character - -2.2 DMA Controllers - -The HP2100 includes two DMA channel controllers (DMA0 and DMA1). Each -DMA channel has the following visible state: - - name size comments - - CMD 1 channel enabled - CTL 1 interrupt enabled - FLG 1 channel ready - FBF 1 channel ready buffer - CW1 16 command word 1 - CW2 16 command word 2 - CW3 16 command word 3 - -2.3 Variable Device Assignments - -On the HP2100, I/O device take their device numbers from the backplane -slot they are plugged into. Thus, device number assignments vary -considerably from system to system, and software package to software -package. The HP2100 simulator supports dynamic device number assignment. -To show the current device number, use the SHOW DEVNO command: - - sim> SHOW PTR DEV - device=10 - -To change the device number, use the SET DEVNO= command: - - sim> SET PTR DEV=30 - sim> SHOW PTR DEV - device=30 - -The new device number must be in the range 010..077 (octal). For devices -with two device numbers, only the lower numbered device number can be -changed; the higher is automatically set to the lower + 1. If a -device number conflict occurs, the simulator will return an error -when started. - -In addition, most devices can be enabled or disabled. To enable a -device, use the SET ENABLED command: - - sim> SET DP ENABLED - -To disable a device, use the SET DISABLED command: - - sim> SET DP DISABLED - -For devices with more than one device number, disabling or enabling any -device in the set disables all the devices. - -2.4 Programmed I/O Devices - -2.4.1 12597A-002 Paper Tape Reader (PTR) - -The paper tape reader (PTR) reads data from a disk file. The POS -register specifies the number of the next data item to be read. -Thus, by changing POS, the user can backspace or advance the reader. - -The paper tape reader supports the BOOT command. BOOT PTR copies the -absolute binary loader into memory and starts it running. - -The paper tape reader implements these registers: - - name size comments - - BUF 8 last data item processed - CMD 1 reader enable - CTL 1 device/interrupt enable - FLG 1 device ready - FBF 1 device ready buffer - POS 32 position in the input file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - end of file 1 report error and stop - 0 out of tape or paper - - OS I/O error x report error and stop - -2.4.2 12597A-005 Paper Tape Punch (PTP) - -The paper tape punch (PTP) writes data to a disk file. The POS -register specifies the number of the next data item to be written. -Thus, by changing POS, the user can backspace or advance the punch. - -The paper tape punch implements these registers: - - name size comments - - BUF 8 last data item processed - CMD 1 punch enable - CTL 1 device/interrupt enable - FLG 1 device ready - FBF 1 device ready buffer - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -2.4.3 12631C Buffered Terminal (TTY) - -The console terminal has three units: keyboard (unit 0), printer -(unit 1), and punch (unit 2). The keyboard reads from the console -keyboard; the printer writes to the simulator console window. The -punch writes to a disk file. The keyboard and printer units (TTY0, -TTY1) can be set to one of three modes: UC, 7B, or 8B. In UC mode, -lower case input and output characters are automatically converted to -upper case. In 7B mode, input and output characters are masked to 7 -bits. In 8B mode, characters are not modified. Changing the mode -of either unit changes both. The default mode is UC. - -The console teleprinter implements these registers: - - name size comments - - BUF 8 last data item processed - MODE 16 mode - CTL 1 device/interrupt enable - FLG 1 device ready - FBF 1 device ready buffer - KPOS 32 number of characters input - KTIME 24 keyboard polling interval - TPOS 32 number of characters printed - TTIME 24 time from I/O initiation to interrupt - PPOS 32 position in the punch output file - STOP_IOE 1 punch stop on I/O error - -Error handling for the punch is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -2.4.4 12653A Printer Controller (LPS) with 2767 Printer - 12566B Microcircuit Interface - -The 12653A line printer uses the 12566B microcircuit interface as -its controller. As a line printer, LPS writes data to a disk file. -The POS register specifies the number of the next data item to be -written. Thus, by changing POS, the user can backspace or advance -the printer. - -As a microcircuit interface, LPS provides the DMA test device for -running the dual channel port controller and DMS diagnostics. Printer -mode verus diagnostic mode is controlled by the commands: - - SET LPS PRINTER configure as line printer - SET LPS DIAG configure for diagnostic tests - -The 12653A is disabled by default. - -The 12653A implements these registers: - - name size comments - - BUF 16 output buffer - STA 16 input buffer or status - CMD 1 printer enable - CTL 1 device/interrupt enable - FLG 1 device ready - FBF 1 device ready buffer - POS 32 position in the output file - CTIME 24 time between characters - PTIME 24 time for a print operation - STOP_IOE 1 stop on I/O error - -In printer mode, error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape or paper - - OS I/O error x report error and stop - -In diagnostic mode, there are no errors; data sent to the output -buffer is looped back to the status register with a fixed delay of 1. - -2.4.5 12845A Printer Controller (LPT) - -The line printer (LPT) writes data to a disk file. The POS register -specifies the number of the next data item to be written. Thus, -by changing POS, the user can backspace or advance the printer. - -The line printer implements these registers: - - name size comments - - BUF 8 last data item processed - CMD 1 printer enable - CTL 1 device/interrupt enable - FLG 1 device ready - FBF 1 device ready buffer - LCNT 7 line count within page - POS 32 position in the output file - CTIME 24 time between characters - PTIME 24 time for a print operation - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape or paper - - OS I/O error x report error and stop - -2.4.6 12539A/B/C Time Base Generator (CLK) - -The time base generator (CLK) implements these registers: - - name size comments - - SEL 3 time base select - CTR 14 repeat counter for < 1Hz operation - CTL 1 device/interrupt enable - FLG 1 device ready - FBF 1 device ready buffer - ERR 1 error flag - TIME[0:7] 31 clock intervals, select = 0..7 - DEVNO 6 current device number (read only) - -The time base generator autocalibrates; the clock interval is adjusted -up or down so that the clock tracks actual elapsed time. Operation at -the fastest rates (100 usec, 1 msec) is not recommended. - -2.4.7 12920A Terminal Multiplexor (MUXL, MUXU, MUXC) - -The 12920A is a 16-line terminal multiplexor, with five additional -receive-only diagnostic lines. It consists of three devices: - - MUX scanning logic (corresponding more or less - to the upper data card) - MUXL individual lines (corresponding more or - less to the lower data card) - MUXC modem control and status logic (corresponding - to the control card) - -The MUX performs input and output through Telnet sessions connected to a -user-specified port. The ATTACH command to the scanning logic specifies -the port to be used: - - ATTACH MUX set up listening port - -where port is a decimal number between 1 and 65535 that is not being used -for other TCP/IP activities. - -Each line (each unit of MUXL) can be set to one of three modes: UC, 7B, -or 8B. In UC mode, lower case input and output characters are converted -automatically to upper case. In 7B mode, input and output characters -are masked to 7 bits. In 8B mode, characters are not modified. The -default mode is UC. In addition, each line supports the DATASET option. -DATASET, when set, enables modem control. The default settings are UC -mode and DATASET disabled. - -The modem controls model a simplified Bell 103A dataset with just four -lines: data terminal ready and request to send from the computer to the -data set, and carrier detect and data set ready from the data set to -the computer. There is no ring detection. If data terminal ready is -set when a Telnet connection starts up, then carrier detect and data -set ready are also set. The connection is established whether data -terminal ready is set or not. - -Once MUX is attached and the simulator is running, the multiplexor listens -for connections on the specified port. It assumes that the incoming -connections are Telnet connections. The connections remain open until -disconnected either by the Telnet client, a SET MUXL DISCONNECT command, -or a DETACH MUX command. - -The SHOW MUX CONNECTIONS command displays the current connections to the -extra terminals. The SHOW MUX STATISTICS command displays statistics for -active connections. The SET MUX DISCONNECT=linenumber disconnects the -specified line. - -The scanner (MUX) implements these registers: - - name size comments - - IBUF 16 input buffer, holds line status - OBUF 16 output buffer, holds channel select - -The lines (MUXL) implements these registers: - - name size comments - - CTL 1 device/interrupt enable - FLG 1 device ready - FBF 1 device ready buffer - STA[0:20] 16 line status, lines 0-20 - RPAR[0:20] 16 receive parameters, lines 0-20 - XPAR[0:15] 16 transmit parameters, lines 0-15 - RBUF[0:20] 8 receive buffer, lines 0-20 - XBUF[0:15] 8 transmit buffer, lines 0-15 - RCHP[0:20] 1 receive character present, lines 0-20 - XDON[0:15] 1 transmit done, lines 0-15 - TIME[0:15] 24 transmit time, lines 0-15 - -The modem control (MUXM) implements these registers: - - name size comments - - CTL 1 device/interrupt enable - FLG 1 device ready - FBF 1 device ready buffer - SCAN 1 scan enabled - CHAN 4 current line - DSO[0:15] 6 C2,C1,ES2,ES1,SS2,SS1, lines 0-15 - DSI[0:15] 2 S2,S1, lines 0-15 - - -The terminal multiplexor does not support save and restore. All open -connections are lost when the simulator shuts down or MUXU is detached. - -2.4.8 Interprocessor Link (IPLI, IPLO) - -The interprocessor link is a pair of 12556B parallel interfaces that -are cross coupled to provide interprocessor communications to a second -copy of the HP2100 simulator. The IPL is intended to support simulation -of a two system HP TimeShared Basic configuration. The links are actually -bidirectional half-duplex; TimeShared Basic uses them unidirectionally. -The IPL is disabled by default. - -To operate, the IPL devices must be enabled and then connected to the IPL -devices in another copy of the simulator. The IPLI device in the first -simulator is connected to the IPLO device in the second, and vice versa. -Connections are established with the ATTACH command. One copy of the -simulator listens for connections on a specified port (ATTACH -L); the -other establishes connections to an IP address and port (ATTACH -C). -Either copy may perform either operation, but the operations must be -done in matched pairs: - - simulator #1 simulator #2 - - sim> set ipli ena sim> set ipli ena - (also enables iplo) (also enables iplo) - sim> att -lw ipli 4000 - Listening on port 4000 - Waiting for connection - sim> att -c iplo 4000 - Connection established Connected to 127.0.0.1 port 4000 - sim> att -lw iplo 4000 - Listening on port 4001 - Waiting for connection - sim> att -c ipli 4001 - Connection established Connected to 127.0.0.1 port 4000 - -Both forms of ATTACH take a modifier -W (wait); if specified, the command -will wait up to 30 seconds for the connection process to complete. ATTACH --C can specify both an IP address and a port, in the form aa.bb.cc.dd:port; -if the IP address is omitted, it defaults to 127.0.0.1 (local system). - -Both IPLI and IPLO implement the BOOT command. BOOT loads the HP Access -Basic Block Loader for the IOP into the top 64 words of memory and starts -it running. - -Both IPLI and IPLO implement these registers: - - name size comments - - BUF 16 buffer - HOLD 8 holding buffer - CMD 1 device enable - CTL 1 device/interrupt enable - FLG 1 device ready - FBF 1 device ready buffer - TIME 24 polling interval for input - STOP_IOE 1 stop on I/O error - -2.5 12557A Disk Controller (DPC, DPD) with 2781 Drives - 13210A Disk Controller (DPC, DPD) with 7900 Drives - -The 12557A/13210A disk controller can be configured as either a -12557A, supporting 2.5MB drives, or a 13210A, supporting 5MB drives, -with the commands: - - SET DP 12557A 2.5MB drives - SET DP 13210A 5.0MB drives - -Drive types cannot be intermixed; the controller is configured for -one type or the other. The 13210A (for 7900/7901 disks) is selected -by default. - -The simulated controller has two separate devices, a data channel and -a device controller. The data channel includes a 128-word (one sector) -buffer for reads and writes. The device controller includes the four -disk drives. Disk drives can be set ONLINE or OFFLINE. - -The 12557A/13210A supports the BOOT command. BOOT DP loads the IBL -for 7900 class disks into memory and starts it running. BOOT -F DP -boots from the fixed platter (head 2). The switch register (S) is -set automatically to the value expected by the IBL loader: - - <15:14> = 01 - <13:12> = 00 - <11:6> = data channel device code - <5:1> = 00000 - <0> = 1 if booting from the fixed platter - -The data channel implements these registers: - - name size comments - - IBUF 16 input buffer - OBUF 16 output buffer - DBUF[0:127] 16 sector buffer - BPTR 7 sector buffer pointer - CMD 1 channel enable - CTL 1 interrupt enable - FLG 1 channel ready - FBF 1 channel ready buffer - XFER 1 transfer in progress flag - WVAL 1 write data valid flag - -The device controller implements these registers: - - name size comments - - OBUF 16 output buffer - BUSY 3 busy (unit #, + 1, of active unit) - CNT 5 check record count - CMD 1 controller enable - CTL 1 interrupt enable - FLG 1 controller ready - FBF 1 controller ready buffer - EOC 1 end of cylinder pending - RARC[0:3] 8 record address register cylinder, drives 0-3 - RARH[0:3] 2 record address register head, drives 0-3 - RARS[0:3] 4 record address register sector, drives 0-3 - STA[0:3] 16 drive status, drives 0-3 - CTIME 24 data transfer command delay time - DTIME 24 data channel command delay time - STIME 24 seek delay time, per cylinder - XTIME 24 interword transfer time - -Error handling is as follows: - - error processed as - - not attached disk not ready - - end of file assume rest of disk is zero - - OS I/O error report error and stop - -2.6 12565A Disk Controller (DQC, DRC) with 2883 Drives - -The 12565A disk controller has two separate devices, a data channel and -a device controller. The data channel includes a 128-word (one sector) -buffer for reads and writes. The device controller includes the two -disk drives. Disk drives can be set ONLINE or OFFLINE. - -The 12565A supports the BOOT command. BOOT DQ loads the IBL for 2883 -class disks into memory and starts it running. The switch register (S) -is set automatically to the value expected by the IBL loader: - - <15:14> = 01 - <13:12> = 10 - <11:6> = data channel device code - <5:0> = 00000 - -The data channel implements these registers: - - name size comments - - IBUF 16 input buffer - OBUF 16 output buffer - DBUF[0:127] 16 sector buffer - BPTR 7 sector buffer pointer - CMD 1 channel enable - CTL 1 interrupt enable - FLG 1 channel ready - FBF 1 channel ready buffer - XFER 1 transfer in progress flag - WVAL 1 write data valid flag - -The device controller implements these registers: - - name size comments - - OBUF 16 output buffer - BUSY 2 busy (unit #, + 1, of active unit) - CNT 9 check record count - CMD 1 controller enable - CTL 1 interrupt enable - FLG 1 controller ready - FBF 1 controller ready buffer - RARC[0:1] 8 record address register cylinder, drives 0-1 - RARH[0:1] 5 record address register head, drives 0-1 - RARS[0:1] 5 record address register sector, drives 0-1 - STA[0:1] 16 drive status, drives 0-3 - CTIME 24 data transfer command delay time - DTIME 24 data channel command delay time - STIME 24 seek delay time, per cylinder - XTIME 24 interword transfer time - -Error handling is as follows: - - error processed as - - not attached disk not ready - - end of file assume rest of disk is zero - - OS I/O error report error and stop - -2.7 12606B Fixed Head Disk Controller (DRC, DRD) with 2770/2771 Disk - 12610B Drum Controller (DRC, DRD) with 2773/2774/2775 Drum - -The 12606B/12610B fixed head disk/drum controller has two separate devices, -a data channel and a device controller. The device controller includes the -actual drive. Ten different models are supported: - - SET DRC 180K 12606B, 180K words - SET DRC 360K 12606B, 360K words - SET DRC 720K 12606B, 720K words - SET DRC 384K 12610B, 84K words - SET DRC 512K 12610B, 512K words - SET DRC 640K 12610B, 640K words - SET DRC 768K 12610B, 768K words - SET DRC 896K 12610B, 896K words - SET DRC 1024K 12610B, 1024K words - SET DRC 1536K 12610B, 1536K words - -The 12606B/12610B support the BOOT command. The BOOT command loads the -first sector from the disk or drum into locations 0-77 and then jumps to 77. -This is very different from the IBL loader protocol used by the 12565A and -the 12557A/13210A. - -The data channel implements these registers: - - name size comments - - IBUF 16 input buffer - OBUF 16 output buffer - CMD 1 channel enable - CTL 1 interrupt enable - FLG 1 channel ready - FBF 1 channel ready buffer - BPTR 6 sector buffer pointer - -The device controller implements these registers: - - name size comments - - CW 16 command word - STA 16 status - CMD 1 controller enable - CTL 1 interrupt enable - FLG 1 controller ready - FBF 1 controller ready buffer - TIME 24 interword transfer time - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error processed as - - not attached disk not ready - -12606B/12610B data files are buffered in memory; therefore, end of file -and OS I/O errors cannot occur. - -2.8 12559C Magnetic Tape Controller (MTC, MTD) with 3030 Drive - -Magnetic tape options include the ability to make the unit write enabled -or write locked. - - SET MTC LOCKED set unit write locked - SET MTC WRITEENABLED set unit write enabled - -The 12559C mag tape drive has two separate devices, a data channel and -a device controller. The data channel includes a maximum record sized -buffer for reads and writes. The device controller includes the tape -unit. - -The BOOT command is not supported. The 12559C was HP's earliest tape -drive and is not supported by most of its operating systems. It is -disabled by default. - -The data channel implements these registers: - - name size comments - - FLG 1 channel ready - DBUF[0:65535] 8 transfer buffer - BPTR 16 buffer pointer (reads and writes) - BMAX 16 buffer size (writes) - -The device controller implements these registers: - - name size comments - - FNC 8 current function - STA 9 tape status - BUF 8 buffer - CTL 1 interrupt enabled - FLG 1 controller ready - FBF 1 controller ready buffer - DTF 1 data transfer flop - FSVC 1 first service flop - POS 32 magtape position - CTIME 24 command delay time - XTIME 24 interword transfer delay time - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error processed as - - not attached tape not ready; if STOP_IOE, stop - - end of file parity error - - OS I/O error parity error; if STOP_IOE, stop - -2.9 13181A Magnetic Tape Controller (MSC, MSD) with 7970B Drives - 18183A Magnetic Tape Controller (MSC, MSD) with 7970E Drives - -Magnetic tape options include the ability to make the unit write enabled -or write locked, and the ability to select the 13181A (800 bpi) controller -or the 13183A (1600 bpi) controller. - - SET MTn LOCKED set unit n write locked - SET MTn WRITEENABLED set unit n write enabled - SET MT 13181A set controller to 13181A - SET MT 13183A set controller to 13183A - -The 13181A/13183A mag tape drive has two separate devices, a data channel -and a device controller. The data channel includes a maximum record -sized buffer for reads and writes. The device controller includes the -tape units. - -The 13181A/13183A supports the BOOT command. BOOT MS loads the IBL for -7970B/E magnetic tape drives into memory and starts it running. BOOT -S -MS causes the loader to space forward the number of files specified in -the A register before starting to load data. The switch register (S) is -set automatically to the value expected by the IBL loader: - - <15:14> = 10 - <13:12> = 00 - <11:6> = data channel device code - <5:1> = 00000 - <0> = 1 if space forward before loading - -The data channel implements these registers: - - name size comments - - BUF 16 data buffer - CTL 1 interrupt enabled - FLG 1 channel ready - FBF 1 channel ready buffer - DBUF[0:65535] 8 transfer buffer - BPTR 17 buffer pointer (reads and writes) - BMAX 17 buffer size (writes) - -The device controller implements these registers: - - name size comments - - STA 12 tape status - BUF 16 buffer - USEL 2 currently selected unit - FSVC 1 first service flop - CTL 1 interrupt enabled - FLG 1 controller ready - FBF 1 controller ready buffer - POS[0:3] 32 magtape position - CTIME 24 command delay time - XTIME 24 interword transfer delay time - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error processed as - - not attached tape not ready; if STOP_IOE, stop - - end of file parity error - - OS I/O error parity error; if STOP_IOE, stop - -2.10 Symbolic Display and Input - -The HP2100 simulator implements symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as two character string - -m display instruction mnemonics - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or -a ASCII character - " or -c two character sixbit string - alphabetic instruction mnemonic - numeric octal number - -Instruction input uses standard HP2100 assembler syntax. There are seven -instruction classes: memory reference, I/O, shift, alter skip, extended -shift, extended memory reference, extended two address reference. - -Memory reference instructions have the format - - memref {C/Z} address{,I} - -where I signifies indirect, C a current page reference, and Z a zero page -reference. The address is an octal number in the range 0 - 077777; if C or -Z is specified, the address is a page offset in the range 0 - 01777. Normally, -C is not needed; the simulator figures out from the address what mode to use. -However, when referencing memory outside the CPU (eg, disks), there is no -valid PC, and C must be used to specify current page addressing. - -IOT instructions have the format - - io device{,C} - -where C signifies that the device flag is to be cleared. The device is an -octal number in the range 0 - 77. - -Shift and alter/skip instructions have the format - - sub-op sub-op sub-op... - -The simulator checks that the combination of sub-opcodes is legal. - -Extended shift instructions have the format - - extshift count - -where count is an octal number in the range 1 - 020. - -Extended memory reference instructions have the format - - extmemref address{,I} - -where I signifies indirect addressing. The address is an octal number in -the range 0 - 077777. - -Extended two address instructions have the format - - ext2addr addr1{,I},addr2{,I} - -where I signifies indirect addressing. Both address 1 and address 2 are -octal numbers in the range 0 - 077777. diff --git a/HP2100/hp2100_dp.c b/HP2100/hp2100_dp.c deleted file mode 100644 index 64a7ad0b..00000000 --- a/HP2100/hp2100_dp.c +++ /dev/null @@ -1,796 +0,0 @@ -/* hp2100_dp.c: HP 2100 12557A/13210A disk simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - dp 12557A 2871 disk subsystem - 13210A 7900 disk subsystem - - 25-Apr-03 RMS Revised for extended file support - Fixed bug(s) in boot (found by Terry Newton) - 10-Nov-02 RMS Added BOOT command, fixed numerous bugs - 15-Jan-02 RMS Fixed INIT handling (found by Bill McDermith) - 10-Jan-02 RMS Fixed f(x)write call (found by Bill McDermith) - 03-Dec-01 RMS Changed DEVNO to use extended SET/SHOW - 24-Nov-01 RMS Changed STA to be an array - 07-Sep-01 RMS Moved function prototypes - 29-Nov-00 RMS Made variable names unique - 21-Nov-00 RMS Fixed flag, buffer power up state -*/ - -#include "hp2100_defs.h" - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define FNC u3 /* saved function */ -#define CYL u4 /* cylinder */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */ - -#define DP_N_NUMWD 7 -#define DP_NUMWD (1 << DP_N_NUMWD) /* words/sector */ -#define DP_NUMSC2 12 /* sectors/srf 12557 */ -#define DP_NUMSC3 24 /* sectors/srf 13210 */ -#define DP_NUMSC (dp_ctype? DP_NUMSC3: DP_NUMSC2) -#define DP_NUMSF 4 /* surfaces/cylinder */ -#define DP_NUMCY 203 /* cylinders/disk */ -#define DP_SIZE2 (DP_NUMSF * DP_NUMCY * DP_NUMSC2 * DP_NUMWD) -#define DP_SIZE3 (DP_NUMSF * DP_NUMCY * DP_NUMSC3 * DP_NUMWD) -#define DP_NUMDRV 4 /* # drives */ - -/* Command word */ - -#define CW_V_FNC 12 /* function */ -#define CW_M_FNC 017 -#define CW_GETFNC(x) (((x) >> CW_V_FNC) & CW_M_FNC) -#define FNC_STA 000 /* status check */ -#define FNC_WD 001 /* write */ -#define FNC_RD 002 /* read */ -#define FNC_SEEK 003 /* seek */ -#define FNC_REF 005 /* refine */ -#define FNC_CHK 006 /* check */ -#define FNC_INIT 011 /* init */ -#define FNC_AR 013 /* address */ -#define FNC_SEEK1 020 /* fake - seek1 */ -#define FNC_SEEK2 021 /* fake - seek2 */ -#define FNC_SEEK3 022 /* fake - seek3 */ -#define FNC_CHK1 023 /* fake - check1 */ -#define FNC_AR1 024 /* fake - arec1 */ -#define CW_V_DRV 0 /* drive */ -#define CW_M_DRV 03 -#define CW_GETDRV(x) (((x) >> CW_V_DRV) & CW_M_DRV) - -/* Disk address words */ - -#define DA_V_CYL 0 /* cylinder */ -#define DA_M_CYL 0377 -#define DA_GETCYL(x) (((x) >> DA_V_CYL) & DA_M_CYL) -#define DA_V_HD 8 /* head */ -#define DA_M_HD 03 -#define DA_GETHD(x) (((x) >> DA_V_HD) & DA_M_HD) -#define DA_V_SC 0 /* sector */ -#define DA_M_SC2 017 -#define DA_M_SC3 037 -#define DA_M_SC (dp_ctype? DA_M_SC3: DA_M_SC2) -#define DA_GETSC(x) (((x) >> DA_V_SC) & DA_M_SC) -#define DA_CKMASK2 037 /* check mask */ -#define DA_CKMASK3 077 -#define DA_CKMASK (dp_ctype? DA_CKMASK3: DA_CKMASK2) - -/* Status in dpc_sta[drv], (u) = unused in 13210, (d) = dynamic */ - -#define STA_ATN 0100000 /* attention (u) */ -#define STA_1ST 0040000 /* first status */ -#define STA_OVR 0020000 /* overrun */ -#define STA_RWU 0010000 /* rw unsafe NI (u) */ -#define STA_ACU 0004000 /* access unsafe NI */ -#define STA_HUNT 0002000 /* hunting NI (12557) */ -#define STA_PROT 0002000 /* protected (13210) */ -#define STA_SKI 0001000 /* incomplete NI (u) */ -#define STA_SKE 0000400 /* seek error */ -/* 0000200 /* unused */ -#define STA_NRDY 0000100 /* not ready (d) */ -#define STA_EOC 0000040 /* end of cylinder */ -#define STA_AER 0000020 /* addr error */ -#define STA_FLG 0000010 /* flagged */ -#define STA_BSY 0000004 /* seeking */ -#define STA_DTE 0000002 /* data error */ -#define STA_ERR 0000001 /* any error (d) */ -#define STA_ALLERR (STA_ATN + STA_1ST + STA_OVR + STA_RWU + STA_ACU + \ - STA_SKI + STA_SKE + STA_NRDY + STA_EOC + STA_AER + \ - STA_FLG + STA_BSY + STA_DTE) -#define STA_MBZ13 (STA_ATN + STA_RWU + STA_SKI) /* zero in 13210 */ - -extern uint16 *M; -extern uint32 PC, SR; -extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; -extern int32 sim_switches; -extern UNIT cpu_unit; - -int32 dp_ctype = 1; /* ctrl type */ -int32 dpc_busy = 0; /* cch unit */ -int32 dpc_cnt = 0; /* check count */ -int32 dpc_eoc = 0; /* end of cyl */ -int32 dpc_stime = 100; /* seek time */ -int32 dpc_ctime = 100; /* command time */ -int32 dpc_xtime = 5; /* xfer time */ -int32 dpc_dtime = 2; /* dch time */ -int32 dpd_obuf = 0, dpd_ibuf = 0; /* dch buffers */ -int32 dpc_obuf = 0; /* cch buffers */ -int32 dpd_xfer = 0; /* xfer in prog */ -int32 dpd_wval = 0; /* write data valid */ -int32 dp_ptr = 0; /* buffer ptr */ -uint8 dpc_rarc[DP_NUMDRV] = { 0 }; /* cylinder */ -uint8 dpc_rarh[DP_NUMDRV] = { 0 }; /* head */ -uint8 dpc_rars[DP_NUMDRV] = { 0 }; /* sector */ -uint16 dpc_sta[DP_NUMDRV] = { 0 }; /* status regs */ -uint16 dpxb[DP_NUMWD]; /* sector buffer */ - -DEVICE dpd_dev, dpc_dev; -int32 dpdio (int32 inst, int32 IR, int32 dat); -int32 dpcio (int32 inst, int32 IR, int32 dat); -t_stat dpc_svc (UNIT *uptr); -t_stat dpd_svc (UNIT *uptr); -t_stat dpc_reset (DEVICE *dptr); -t_stat dpc_vlock (UNIT *uptr, int32 val); -t_stat dpc_attach (UNIT *uptr, char *cptr); -t_stat dpc_boot (int32 unitno, DEVICE *dptr); -void dp_god (int32 fnc, int32 drv, int32 time); -void dp_goc (int32 fnc, int32 drv, int32 time); -t_stat dp_settype (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat dp_showtype (FILE *st, UNIT *uptr, int32 val, void *desc); - -/* DPD data structures - - dpd_dev DPD device descriptor - dpd_unit DPD unit list - dpd_reg DPD register list -*/ - -DIB dp_dib[] = { - { DPD, 0, 0, 0, 0, &dpdio }, - { DPC, 0, 0, 0, 0, &dpcio } }; - -#define dpd_dib dp_dib[0] -#define dpc_dib dp_dib[1] - -UNIT dpd_unit = { UDATA (&dpd_svc, 0, 0) }; - -REG dpd_reg[] = { - { ORDATA (IBUF, dpd_ibuf, 16) }, - { ORDATA (OBUF, dpd_obuf, 16) }, - { FLDATA (CMD, dpd_dib.cmd, 0) }, - { FLDATA (CTL, dpd_dib.ctl, 0) }, - { FLDATA (FLG, dpd_dib.flg, 0) }, - { FLDATA (FBF, dpd_dib.fbf, 0) }, - { FLDATA (XFER, dpd_xfer, 0) }, - { FLDATA (WVAL, dpd_wval, 0) }, - { BRDATA (DBUF, dpxb, 8, 16, DP_NUMWD) }, - { DRDATA (BPTR, dp_ptr, DP_N_NUMWD) }, - { ORDATA (DEVNO, dpd_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB dpd_mod[] = { - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &dpd_dev }, - { 0 } }; - -DEVICE dpd_dev = { - "DPD", &dpd_unit, dpd_reg, dpd_mod, - 1, 10, DP_N_NUMWD, 1, 8, 16, - NULL, NULL, &dpc_reset, - NULL, NULL, NULL, - &dpd_dib, 0 }; - -/* DPC data structures - - dpc_dev DPC device descriptor - dpc_unit DPC unit list - dpc_reg DPC register list - dpc_mod DPC modifier list -*/ - -UNIT dpc_unit[] = { - { UDATA (&dpc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DP_SIZE3) }, - { UDATA (&dpc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DP_SIZE3) }, - { UDATA (&dpc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DP_SIZE3) }, - { UDATA (&dpc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DP_SIZE3) } }; - -REG dpc_reg[] = { - { ORDATA (OBUF, dpc_obuf, 16) }, - { ORDATA (BUSY, dpc_busy, 3), REG_RO }, - { ORDATA (CNT, dpc_cnt, 5) }, - { FLDATA (CMD, dpc_dib.cmd, 0) }, - { FLDATA (CTL, dpc_dib.ctl, 0) }, - { FLDATA (FLG, dpc_dib.flg, 0) }, - { FLDATA (FBF, dpc_dib.fbf, 0) }, - { FLDATA (EOC, dpc_eoc, 0) }, - { BRDATA (RARC, dpc_rarc, 8, 8, DP_NUMDRV) }, - { BRDATA (RARH, dpc_rarh, 8, 2, DP_NUMDRV) }, - { BRDATA (RARS, dpc_rars, 8, 4, DP_NUMDRV) }, - { BRDATA (STA, dpc_sta, 8, 16, DP_NUMDRV) }, - { DRDATA (CTIME, dpc_ctime, 24), PV_LEFT }, - { DRDATA (DTIME, dpc_dtime, 24), PV_LEFT }, - { DRDATA (STIME, dpc_stime, 24), PV_LEFT }, - { DRDATA (XTIME, dpc_xtime, 24), REG_NZ + PV_LEFT }, - { FLDATA (CTYPE, dp_ctype, 0), REG_HRO }, - { URDATA (UCYL, dpc_unit[0].CYL, 10, 8, 0, - DP_NUMDRV, PV_LEFT | REG_HRO) }, - { URDATA (UFNC, dpc_unit[0].FNC, 8, 8, 0, - DP_NUMDRV, REG_HRO) }, - { URDATA (CAPAC, dpc_unit[0].capac, 10, T_ADDR_W, 0, - DP_NUMDRV, PV_LEFT | REG_HRO) }, - { ORDATA (DEVNO, dpc_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB dpc_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "13210A", - &dp_settype, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "12557A", - &dp_settype, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL, - NULL, &dp_showtype, NULL }, - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &dpd_dev }, - { 0 } }; - -DEVICE dpc_dev = { - "DPC", dpc_unit, dpc_reg, dpc_mod, - DP_NUMDRV, 8, 24, 1, 8, 16, - NULL, NULL, &dpc_reset, - &dpc_boot, &dpc_attach, NULL, - &dpc_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 dpdio (int32 inst, int32 IR, int32 dat) -{ -int32 devd; - -devd = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (devd); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - dpd_obuf = dat; - if (!dpc_busy || dpd_xfer) dpd_wval = 1; /* if !overrun, valid */ - break; -case ioMIX: /* merge */ - dat = dat | dpd_ibuf; - break; -case ioLIX: /* load */ - dat = dpd_ibuf; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCTL (devd); /* clr ctl, cmd */ - clrCMD (devd); - dpd_xfer = 0; } /* clr xfer */ - else { /* STC */ - if (!dp_ctype) setCTL (devd); /* 12557: set ctl */ - setCMD (devd); /* set cmd */ - if (dpc_busy && !dpd_xfer) /* overrun? */ - dpc_sta[dpc_busy - 1] |= STA_OVR; } - break; -default: - break; } -if (IR & I_HC) { clrFLG (devd); } /* H/C option */ -return dat; -} - -int32 dpcio (int32 inst, int32 IR, int32 dat) -{ -int32 i, devc, fnc, drv; -int32 devd = dpd_dib.devno; - -devc = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (devc); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - dpc_obuf = dat; - break; -case ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - for (i = 0; i < DP_NUMDRV; i++) - if (dpc_sta[i] & STA_ATN) dat = dat | (1 << i); - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC? */ - clrCTL (devc); /* clr cmd, ctl */ - clrCMD (devc); /* cancel non-seek */ - if (dpc_busy) sim_cancel (&dpc_unit[dpc_busy - 1]); - sim_cancel (&dpd_unit); /* cancel dch */ - dpd_xfer = 0; /* clr dch xfer */ - dpc_busy = 0; } /* clr cch busy */ - else { /* STC */ - setCTL (devc); /* set ctl */ - if (!CMD (devc)) { /* is cmd clr? */ - setCMD (devc); /* set cmd */ - drv = CW_GETDRV (dpc_obuf); /* get fnc, drv */ - fnc = CW_GETFNC (dpc_obuf); /* from cmd word */ - switch (fnc) { /* case on fnc */ - case FNC_STA: /* rd sta */ - if (dp_ctype) { clrFLG (devd); } /* 13210? clr dch flag */ - case FNC_SEEK: case FNC_CHK: /* seek, check */ - case FNC_AR: /* addr rec */ - dp_god (fnc, drv, dpc_dtime); /* sched dch xfr */ - break; - case FNC_RD: case FNC_WD: /* read, write */ - case FNC_REF: case FNC_INIT: /* refine, init */ - dp_goc (fnc, drv, dpc_ctime); /* sched drive */ - break; } /* end case */ - } - } /* end else */ - break; -default: - break; } -if (IR & I_HC) { clrFLG (devc); } /* H/C option */ -return dat; -} - -/* Start data channel operation */ - -void dp_god (int32 fnc, int32 drv, int32 time) -{ -dpd_unit.CYL = drv; /* save unit */ -dpd_unit.FNC = fnc; /* save function */ -sim_activate (&dpd_unit, time); -return; -} - -/* Start controller operation */ - -void dp_goc (int32 fnc, int32 drv, int32 time) -{ -if (sim_is_active (&dpc_unit[drv])) { /* still seeking? */ - sim_cancel (&dpc_unit[drv]); /* stop seek */ - dpc_sta[drv] = dpc_sta[drv] & ~STA_BSY; /* clear busy */ - time = time + dpc_stime; } /* take longer */ -dp_ptr = 0; /* init buf ptr */ -dpc_eoc = 0; /* clear end cyl */ -dpc_busy = drv + 1; /* set busy */ -dpd_xfer = 1; /* xfer in prog */ -dpc_unit[drv].FNC = fnc; /* save function */ -sim_activate (&dpc_unit[drv], time); /* activate unit */ -return; -} - -/* Data channel unit service - - This routine handles the data channel transfers. It also handles - data transfers that are blocked by seek in progress. - - uptr->CYL = target drive - uptr->FNC = target function - - Seek substates - seek - transfer cylinder - seek1 - transfer head/surface - Address record - ar - transfer cylinder - ar1 - transfer head/surface, finish operation - Status check - transfer status, finish operation - Check data - chk - transfer sector count -*/ - -t_stat dpd_svc (UNIT *uptr) -{ -int32 drv, devc, devd, st; - -drv = uptr->CYL; /* get drive no */ -devc = dpc_dib.devno; /* get cch devno */ -devd = dpd_dib.devno; /* get dch devno */ -switch (uptr->FNC) { /* case function */ - -case FNC_SEEK: /* seek, need cyl */ - if (CMD (devd)) { /* dch active? */ - dpc_rarc[drv] = DA_GETCYL (dpd_obuf); /* take cyl word */ - dpd_wval = 0; /* clr data valid */ - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - uptr->FNC = FNC_SEEK1; } /* advance state */ - sim_activate (uptr, dpc_xtime); /* no, wait more */ - break; -case FNC_SEEK1: /* seek, need hd/sec */ - if (CMD (devd)) { /* dch active? */ - dpc_rarh[drv] = DA_GETHD (dpd_obuf); /* get head */ - dpc_rars[drv] = DA_GETSC (dpd_obuf); /* get sector */ - dpd_wval = 0; /* clr data valid */ - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - if (sim_is_active (&dpc_unit[drv])) { /* if busy, */ - dpc_sta[drv] = dpc_sta[drv] | STA_SKE; - break; } /* error, ignore */ - st = abs (dpc_rarc[drv] - dpc_unit[drv].CYL) * dpc_stime; - if (st == 0) st = dpc_stime; /* min time */ - sim_activate (&dpc_unit[drv], st); /* schedule drive */ - dpc_sta[drv] = (dpc_sta[drv] | STA_BSY) & - ~(STA_SKE | STA_SKI | STA_HUNT); - dpc_unit[drv].CYL = dpc_rarc[drv]; /* on cylinder */ - dpc_unit[drv].FNC = FNC_SEEK2; } /* set operation */ - else sim_activate (uptr, dpc_xtime); /* no, wait more */ - break; - -case FNC_AR: /* arec, need cyl */ - if (CMD (devd)) { /* dch active? */ - dpc_rarc[drv] = DA_GETCYL (dpd_obuf); /* take cyl word */ - dpd_wval = 0; /* clr data valid */ - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - uptr->FNC = FNC_AR1; } /* advance state */ - sim_activate (uptr, dpc_xtime); /* no, wait more */ - break; -case FNC_AR1: /* arec, need hd/sec */ - if (CMD (devd)) { /* dch active? */ - dpc_rarh[drv] = DA_GETHD (dpd_obuf); /* get head */ - dpc_rars[drv] = DA_GETSC (dpd_obuf); /* get sector */ - dpd_wval = 0; /* clr data valid */ - setFLG (devc); /* set cch flg */ - clrCMD (devc); /* clr cch cmd */ - setFLG (devd); /* set dch flg */ - clrCMD (devd); } /* clr dch cmd */ - else sim_activate (uptr, dpc_xtime); /* no, wait more */ - break; - -case FNC_STA: /* read status */ - if (CMD (devd) || dp_ctype) { /* dch act or 13210? */ - if (dpc_unit[drv].flags & UNIT_ATT) { /* attached? */ - dpd_ibuf = dpc_sta[drv] & ~STA_ERR; /* clear err */ - if (dp_ctype) dpd_ibuf = /* 13210? */ - (dpd_ibuf & ~(STA_MBZ13 | STA_PROT)) | - (uptr->flags & UNIT_WPRT? STA_PROT: 0); } - else dpd_ibuf = STA_NRDY; /* not ready */ - if (dpd_ibuf & STA_ALLERR) /* errors? set flg */ - dpd_ibuf = dpd_ibuf | STA_ERR; - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - clrCMD (devc); /* clr cch cmd */ - dpc_sta[drv] = dpc_sta[drv] & /* clr sta flags */ - ~(STA_ATN | STA_1ST | STA_OVR | - STA_RWU | STA_ACU | STA_EOC | - STA_AER | STA_FLG | STA_DTE); } - else sim_activate (uptr, dpc_xtime); /* wait more */ - break; - -case FNC_CHK: /* check, need cnt */ - if (CMD (devd)) { /* dch active? */ - dpc_cnt = dpd_obuf & DA_CKMASK; /* get count */ - dpd_wval = 0; /* clr data valid */ -/* setFLG (devd); /* set dch flg */ -/* clrCMD (devd); /* clr dch cmd */ - dp_goc (FNC_CHK1, drv, dpc_xtime); } /* sched drv */ - else sim_activate (uptr, dpc_xtime); /* wait more */ - break; - -default: - return SCPE_IERR; } - -return SCPE_OK; -} - -/* Drive unit service - - This routine handles the data transfers. - - Seek substates - seek2 - done - Refine sector - erase sector, finish operation - Check data - chk1 - finish operation - Read - Write -*/ - -#define GETDA(x,y,z) \ - (((((x) * DP_NUMSF) + (y)) * DP_NUMSC) + (z)) * DP_NUMWD - -t_stat dpc_svc (UNIT *uptr) -{ -int32 da, drv, devc, devd, err; - -err = 0; /* assume no err */ -drv = uptr - dpc_dev.units; /* get drive no */ -devc = dpc_dib.devno; /* get cch devno */ -devd = dpd_dib.devno; /* get dch devno */ -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - setFLG (devc); /* set cch flg */ - clrCMD (devc); /* clr cch cmd */ - dpc_sta[drv] = 0; /* clr status */ - dpc_busy = 0; /* ctlr is free */ - dpd_xfer = dpd_wval = 0; - return SCPE_OK; } -switch (uptr->FNC) { /* case function */ - -case FNC_SEEK2: /* seek done */ - dpc_sta[drv] = (dpc_sta[drv] | STA_ATN) & ~STA_BSY; - if (uptr->CYL >= DP_NUMCY) { /* invalid cyl? */ - dpc_sta[drv] = dpc_sta[drv] | STA_SKE; - uptr->CYL = DP_NUMCY - 1; } -case FNC_SEEK3: /* waiting for flag */ - if (dpc_busy || FLG (devc)) { /* ctrl busy? wait */ - uptr->FNC = FNC_SEEK3; /* next state */ - sim_activate (uptr, dpc_xtime); } - else { - setFLG (devc); /* set cch flg */ - clrCMD (devc); } /* clear cmd */ - return SCPE_OK; - -case FNC_REF: /* refine sector */ - break; /* just a NOP */ - -case FNC_RD: /* read */ -case FNC_CHK1: /* check */ - if (dp_ptr == 0) { /* new sector? */ - if (!CMD (devd) && (uptr->FNC != FNC_CHK1)) break; - if (uptr->CYL != dpc_rarc[drv]) /* wrong cyl? */ - dpc_sta[drv] = dpc_sta[drv] | STA_AER; /* set flag, read */ - if (dpc_rars[drv] >= DP_NUMSC) { /* bad sector? */ - dpc_sta[drv] = dpc_sta[drv] | STA_AER; /* set flag, stop */ - break; } - if (dpc_eoc) { /* end of cyl? */ - dpc_sta[drv] = dpc_sta[drv] | STA_EOC; - break; } - da = GETDA (dpc_rarc[drv], dpc_rarh[drv], dpc_rars[drv]); - dpc_rars[drv] = dpc_rars[drv] + 1; /* incr address */ - if (dpc_rars[drv] >= DP_NUMSC) { /* end of surf? */ - dpc_rars[drv] = 0; /* wrap to */ - dpc_rarh[drv] = dpc_rarh[drv] ^ 1; /* next head */ - dpc_eoc = ((dpc_rarh[drv] & 1) == 0); }/* calc eoc */ - if (err = fseek (uptr->fileref, da * sizeof (int16), - SEEK_SET)) break; - fxread (dpxb, sizeof (int16), DP_NUMWD, uptr->fileref); - if (err = ferror (uptr->fileref)) break; } - dpd_ibuf = dpxb[dp_ptr++]; /* get word */ - if (dp_ptr >= DP_NUMWD) { /* end of sector? */ - if (uptr->FNC == FNC_CHK1) { /* check? */ - dpc_cnt = (dpc_cnt - 1) & DA_CKMASK; /* decr count */ - if (dpc_cnt == 0) break; } /* stop at zero */ - dp_ptr = 0; } /* wrap buf ptr */ - if (CMD (devd) && dpd_xfer) { /* dch on, xfer? */ - setFLG (devd); } /* set flag */ - clrCMD (devd); /* clr dch cmd */ - sim_activate (uptr, dpc_xtime); /* sched next word */ - return SCPE_OK; - -case FNC_INIT: /* init */ -case FNC_WD: /* write */ - if (dp_ptr == 0) { /* start sector? */ - if (!CMD (devd) && !dpd_wval) break; /* xfer done? */ - if (uptr->flags & UNIT_WPRT) { /* wr prot? */ - dpc_sta[drv] = dpc_sta[drv] | STA_FLG; /* set status */ - break; } /* done */ - if ((uptr->CYL != dpc_rarc[drv]) || /* wrong cyl or */ - (dpc_rars[drv] >= DP_NUMSC)) { /* bad sector? */ - dpc_sta[drv] = dpc_sta[drv] | STA_AER; /* set flag, stop */ - break; } - if (dpc_eoc) { /* end of cyl? */ - dpc_sta[drv] = dpc_sta[drv] | STA_EOC; /* set status */ - break; } } /* done */ - dpxb[dp_ptr++] = dpd_wval? dpd_obuf: 0; /* store word/fill */ - dpd_wval = 0; /* clr data valid */ - if (dp_ptr >= DP_NUMWD) { /* buffer full? */ - da = GETDA (dpc_rarc[drv], dpc_rarh[drv], dpc_rars[drv]); - dpc_rars[drv] = dpc_rars[drv] + 1; /* incr address */ - if (dpc_rars[drv] >= DP_NUMSC) { /* end of surf? */ - dpc_rars[drv] = 0; /* wrap to */ - dpc_rarh[drv] = dpc_rarh[drv] ^ 1; /* next head */ - dpc_eoc = ((dpc_rarh[drv] & 1) == 0); }/* calc eoc */ - if (err = fseek (uptr->fileref, da * sizeof (int16), - SEEK_SET)) break; - fxwrite (dpxb, sizeof (int16), DP_NUMWD, uptr->fileref); - if (err = ferror (uptr->fileref)) break; /* error? */ - dp_ptr = 0; } /* next sector */ - if (CMD (devd) && dpd_xfer) { /* dch on, xfer? */ - setFLG (devd); } /* set flag */ - clrCMD (devd); /* clr dch cmd */ - sim_activate (uptr, dpc_xtime); /* sched next word */ - return SCPE_OK; - -default: - return SCPE_IERR; } /* end case fnc */ - -if (!dp_ctype) dpc_sta[drv] = dpc_sta[drv] | STA_ATN; /* 12559 sets ATN */ -setFLG (devc); /* set cch flg */ -clrCMD (devc); /* clr cch cmd */ -dpc_busy = 0; /* ctlr is free */ -dpd_xfer = dpd_wval = 0; -if (err != 0) { /* error? */ - perror ("DP I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat dpc_reset (DEVICE *dptr) -{ -int32 i; - -hp_enbdis_pair (&dpc_dev, &dpd_dev); /* make pair cons */ -dpd_ibuf = dpd_obuf = 0; /* clear buffers */ -dpc_busy = dpc_obuf = 0; -dpc_eoc = 0; -dpd_xfer = dpd_wval = 0; -dp_ptr = 0; -dpc_dib.cmd = dpd_dib.cmd = 0; /* clear cmd */ -dpc_dib.ctl = dpd_dib.ctl = 0; /* clear ctl */ -dpc_dib.fbf = dpd_dib.fbf = 1; /* set fbf */ -dpc_dib.flg = dpd_dib.flg = 1; /* set flg */ -sim_cancel (&dpd_unit); /* cancel dch */ -for (i = 0; i < DP_NUMDRV; i++) { /* loop thru drives */ - sim_cancel (&dpc_unit[i]); /* cancel activity */ - dpc_unit[i].FNC = 0; /* clear function */ - dpc_unit[i].CYL = 0; - dpc_rarc[i] = dpc_rarh[i] = dpc_rars[i] = 0; - if (dpc_unit[i].flags & UNIT_ATT) - dpc_sta[i] = dpc_sta[i] & STA_1ST; - else dpc_sta[i] = 0; } -return SCPE_OK; -} - -/* Attach routine */ - -t_stat dpc_attach (UNIT *uptr, char *cptr) -{ -int32 drv; -t_stat r; - -drv = uptr - dpc_dev.units; /* get drive no */ -r = attach_unit (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; -dpc_sta[drv] = dpc_sta[drv] | STA_1ST; /* update status */ -return r; -} - -/* Set controller type */ - -t_stat dp_settype (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 i; - -if ((val < 0) || (val > 1) || (cptr != NULL)) return SCPE_ARG; -for (i = 0; i < DP_NUMDRV; i++) { - if (dpc_unit[i].flags & UNIT_ATT) return SCPE_ALATT; } -for (i = 0; i < DP_NUMDRV; i++) - dpc_unit[i].capac = (val? DP_SIZE3: DP_SIZE2); -dp_ctype = val; -return SCPE_OK; -} - -/* Show controller type */ - -t_stat dp_showtype (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (dp_ctype) fprintf (st, "13210A"); -else fprintf (st, "12557A"); -return SCPE_OK; -} - -/* 7900/7901 bootstrap routine (HP 12992F ROM) */ - -#define LDR_BASE 077 -#define CHANGE_DEV (1 << 24) - -static const int32 dboot[IBL_LNT] = { - 0106700+CHANGE_DEV, /*ST CLC DC ; clr dch */ - 0106701+CHANGE_DEV, /* CLC CC ; clr cch */ - 0017757, /* JSB STAT ; get status */ - 0067746, /*SK LDB SKCMD ; seek cmd */ - 0106600+CHANGE_DEV, /* OTB DC ; cyl # */ - 0103700+CHANGE_DEV, /* STC DC,C ; to dch */ - 0106601+CHANGE_DEV, /* OTB CC ; seek cmd */ - 0103701+CHANGE_DEV, /* STC CC,C ; to cch */ - 0102300+CHANGE_DEV, /* SFS DC ; addr wd ok? */ - 0027710, /* JMP *-1 ; no, wait */ - 0006400, /* CLB */ - 0102501, /* LIA 1 ; read switches */ - 0002011, /* SLA,RSS ; <0> set? */ - 0047747, /* ADB BIT9 ; head 2 = fixed */ - 0106600+CHANGE_DEV, /* OTB DC ; head/sector */ - 0103700+CHANGE_DEV, /* STC DC,C ; to dch */ - 0102301+CHANGE_DEV, /* SFS CC ; seek done? */ - 0027720, /* JMP *-1 ; no, wait */ - 0017757, /* JSB STAT ; get status */ - 0067776, /* LDB DMACW ; DMA control */ - 0106606, /* OTB 6 */ - 0067750, /* LDB ADDR1 ; memory addr */ - 0106602, /* OTB 2 */ - 0102702, /* STC 2 ; flip DMA ctrl */ - 0067752, /* LDB CNT ; word count */ - 0106602, /* OTB 2 */ - 0063745, /* LDB RDCMD ; read cmd */ - 0102601+CHANGE_DEV, /* OTA CC ; to cch */ - 0103700+CHANGE_DEV, /* STC DC,C ; start dch */ - 0103606, /* STC 6,C ; start DMA */ - 0103701+CHANGE_DEV, /* STC CC,C ; start cch */ - 0102301+CHANGE_DEV, /* SFS CC ; done? */ - 0027737, /* JMP *-1 ; no, wait */ - 0017757, /* JSB STAT ; get status */ - 0027775, /* JMP XT ; done */ - 0037766, /*FSMSK 037766 ; status mask */ - 0004000, /*STMSK 004000 ; unsafe mask */ - 0020000, /*RDCMD 020000 ; read cmd */ - 0030000, /*SKCMD 030000 ; seek cmd */ - 0001000, /*BIT9 001000 ; head 2 select */ - 0102011, /*ADDR1 102011 */ - 0102055, /*ADDR2 102055 */ - 0164000, /*CNT -6144. */ - 0, 0, 0, 0, /* unused */ - 0000000, /*STAT 0 */ - 0002400, /* CLA ; status request */ - 0102601+CHANGE_DEV, /* OTC CC ; to cch */ - 0103701+CHANGE_DEV, /* STC CC,C ; start cch */ - 0102300+CHANGE_DEV, /* SFS DC ; done? */ - 0027763, /* JMP *-1 */ - 0102500+CHANGE_DEV, /* LIA DC ; get status */ - 0013743, /* AND FSMSK ; mask 15,14,3,0 */ - 0002003, /* SZA,RSS ; drive ready? */ - 0127757, /* JMP STAT,I ; yes */ - 0013744, /* AND STMSK ; fault? */ - 0002002, /* SZA */ - 0102030, /* HLT 30 ; yes */ - 0027700, /* JMP ST ; no, retry */ - 0117751, /*XT JSB ADDR2,I ; start program */ - 0120000+CHANGE_DEV, /*DMACW 120000+DC */ - 0000000 }; /* -ST */ - -t_stat dpc_boot (int32 unitno, DEVICE *dptr) -{ -int32 i, dev; - -if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ -dev = dpd_dib.devno; /* get data chan dev */ -PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */ -SR = IBL_DP + (dev << IBL_V_DEV); /* set SR */ -if (sim_switches & SWMASK ('F')) SR = SR | IBL_FIX; /* boot from fixed? */ -for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */ - if (dboot[i] & CHANGE_DEV) /* IO instr? */ - M[PC + i] = (dboot[i] + dev) & DMASK; - else M[PC + i] = dboot[i]; } -M[PC + LDR_BASE] = (~PC + 1) & DMASK; -return SCPE_OK; -} - diff --git a/HP2100/hp2100_dq.c b/HP2100/hp2100_dq.c deleted file mode 100644 index 47edee33..00000000 --- a/HP2100/hp2100_dq.c +++ /dev/null @@ -1,720 +0,0 @@ -/* hp2100_dq.c: HP 2100 12565A disk simulator - - Copyright (c) 1993-2003, Bill McDermith - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of the author shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from the author. - - dq 12565A 2883 disk system - - 25-Apr-03 RMS Fixed bug in status check - 10-Nov-02 RMS Added boot command, rebuilt like 12559/13210 - 09-Jan-02 WOM Copied dp driver and mods for 2883 - - Differences between 12559/13210 and 12565 controllers - - 12565 stops transfers on address miscompares; 12559/13210 only stops writes - - 12565 does not set error on positioner busy - - 12565 does not set positioner busy if already on cylinder - - 12565 does not need eoc logic, it will hit an invalid head number -*/ - -#include "hp2100_defs.h" - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define FNC u3 /* saved function */ -#define CYL u4 /* cylinder */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */ - -#define DQ_N_NUMWD 7 -#define DQ_NUMWD (1 << DQ_N_NUMWD) /* words/sector */ -#define DQ_NUMSC 23 /* sectors/track */ -#define DQ_NUMSF 20 /* tracks/cylinder */ -#define DQ_NUMCY 203 /* cylinders/disk */ -#define DQ_SIZE (DQ_NUMSF * DQ_NUMCY * DQ_NUMSC * DQ_NUMWD) -#define DQ_NUMDRV 2 /* # drives */ - -/* Command word */ - -#define CW_V_FNC 12 /* function */ -#define CW_M_FNC 017 -#define CW_GETFNC(x) (((x) >> CW_V_FNC) & CW_M_FNC) -/* 000 /* unused */ -#define FNC_STA 001 /* status check */ -#define FNC_RCL 002 /* recalibrate */ -#define FNC_SEEK 003 /* seek */ -#define FNC_RD 004 /* read */ -#define FNC_WD 005 /* write */ -#define FNC_RA 006 /* read address */ -#define FNC_WA 007 /* write address */ -#define FNC_CHK 010 /* check */ -#define FNC_LA 013 /* load address */ -#define FNC_AS 014 /* address skip */ - -#define FNC_SEEK1 020 /* fake - seek1 */ -#define FNC_SEEK2 021 /* fake - seek2 */ -#define FNC_SEEK3 022 /* fake - seek3 */ -#define FNC_CHK1 023 /* fake - check1 */ -#define FNC_LA1 024 /* fake - ldaddr1 */ - -#define CW_V_DRV 0 /* drive */ -#define CW_M_DRV 01 -#define CW_GETDRV(x) (((x) >> CW_V_DRV) & CW_M_DRV) - -/* Disk address words */ - -#define DA_V_CYL 0 /* cylinder */ -#define DA_M_CYL 0377 -#define DA_GETCYL(x) (((x) >> DA_V_CYL) & DA_M_CYL) -#define DA_V_HD 8 /* head */ -#define DA_M_HD 037 -#define DA_GETHD(x) (((x) >> DA_V_HD) & DA_M_HD) -#define DA_V_SC 0 /* sector */ -#define DA_M_SC 037 -#define DA_GETSC(x) (((x) >> DA_V_SC) & DA_M_SC) -#define DA_CKMASK 0777 /* check mask */ - -/* Status in dqc_sta[drv] - (d) = dynamic */ - -#define STA_DID 0000200 /* drive ID (d) */ -#define STA_NRDY 0000100 /* not ready (d) */ -#define STA_EOC 0000040 /* end of cylinder */ -#define STA_AER 0000020 /* addr error */ -#define STA_FLG 0000010 /* flagged */ -#define STA_BSY 0000004 /* seeking */ -#define STA_DTE 0000002 /* data error */ -#define STA_ERR 0000001 /* any error */ -#define STA_ALLERR (STA_NRDY + STA_EOC + STA_AER + STA_FLG + STA_DTE) - -extern uint16 *M; -extern uint32 PC, SR; -extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; -extern int32 sim_switches; -extern UNIT cpu_unit; - -int32 dqc_busy = 0; /* cch xfer */ -int32 dqc_cnt = 0; /* check count */ -int32 dqc_stime = 100; /* seek time */ -int32 dqc_ctime = 100; /* command time */ -int32 dqc_xtime = 5; /* xfer time */ -int32 dqc_dtime = 2; /* dch time */ -int32 dqd_obuf = 0, dqd_ibuf = 0; /* dch buffers */ -int32 dqc_obuf = 0; /* cch buffers */ -int32 dqd_xfer = 0; /* xfer in prog */ -int32 dqd_wval = 0; /* write data valid */ -int32 dq_ptr = 0; /* buffer ptr */ -uint8 dqc_rarc[DQ_NUMDRV] = { 0 }; /* cylinder */ -uint8 dqc_rarh[DQ_NUMDRV] = { 0 }; /* head */ -uint8 dqc_rars[DQ_NUMDRV] = { 0 }; /* sector */ -uint16 dqc_sta[DQ_NUMDRV] = { 0 }; /* status regs */ -uint16 dqxb[DQ_NUMWD]; /* sector buffer */ - -DEVICE dqd_dev, dqc_dev; -int32 dqdio (int32 inst, int32 IR, int32 dat); -int32 dqcio (int32 inst, int32 IR, int32 dat); -t_stat dqc_svc (UNIT *uptr); -t_stat dqd_svc (UNIT *uptr); -t_stat dqc_reset (DEVICE *dptr); -t_stat dqc_boot (int32 unitno, DEVICE *dptr); -void dq_god (int32 fnc, int32 drv, int32 time); -void dq_goc (int32 fnc, int32 drv, int32 time); - -/* DQD data structures - - dqd_dev DQD device descriptor - dqd_unit DQD unit list - dqd_reg DQD register list -*/ - -DIB dq_dib[] = { - { DQD, 0, 0, 0, 0, &dqdio }, - { DQC, 0, 0, 0, 0, &dqcio } }; - -#define dqd_dib dq_dib[0] -#define dqc_dib dq_dib[1] - -UNIT dqd_unit = { UDATA (&dqd_svc, 0, 0) }; - -REG dqd_reg[] = { - { ORDATA (IBUF, dqd_ibuf, 16) }, - { ORDATA (OBUF, dqd_obuf, 16) }, - { FLDATA (CMD, dqd_dib.cmd, 0) }, - { FLDATA (CTL, dqd_dib.ctl, 0) }, - { FLDATA (FLG, dqd_dib.flg, 0) }, - { FLDATA (FBF, dqd_dib.fbf, 0) }, - { FLDATA (XFER, dqd_xfer, 0) }, - { FLDATA (WVAL, dqd_wval, 0) }, - { BRDATA (DBUF, dqxb, 8, 16, DQ_NUMWD) }, - { DRDATA (BPTR, dq_ptr, DQ_N_NUMWD) }, - { ORDATA (DEVNO, dqd_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB dqd_mod[] = { - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &dqd_dev }, - { 0 } }; - -DEVICE dqd_dev = { - "DQD", &dqd_unit, dqd_reg, dqd_mod, - 1, 10, DQ_N_NUMWD, 1, 8, 16, - NULL, NULL, &dqc_reset, - NULL, NULL, NULL, - &dqd_dib, 0 }; - -/* DQC data structures - - dqc_dev DQC device descriptor - dqc_unit DQC unit list - dqc_reg DQC register list - dqc_mod DQC modifier list -*/ - -UNIT dqc_unit[] = { - { UDATA (&dqc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DQ_SIZE) }, - { UDATA (&dqc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DQ_SIZE) } }; - -REG dqc_reg[] = { - { ORDATA (OBUF, dqc_obuf, 16) }, - { ORDATA (BUSY, dqc_busy, 2), REG_RO }, - { ORDATA (CNT, dqc_cnt, 9) }, - { FLDATA (CMD, dqc_dib.cmd, 0) }, - { FLDATA (CTL, dqc_dib.ctl, 0) }, - { FLDATA (FLG, dqc_dib.flg, 0) }, - { FLDATA (FBF, dqc_dib.fbf, 0) }, - { BRDATA (RARC, dqc_rarc, 8, 8, DQ_NUMDRV) }, - { BRDATA (RARH, dqc_rarh, 8, 5, DQ_NUMDRV) }, - { BRDATA (RARS, dqc_rars, 8, 5, DQ_NUMDRV) }, - { BRDATA (STA, dqc_sta, 8, 16, DQ_NUMDRV) }, - { DRDATA (CTIME, dqc_ctime, 24), PV_LEFT }, - { DRDATA (DTIME, dqc_dtime, 24), PV_LEFT }, - { DRDATA (STIME, dqc_stime, 24), PV_LEFT }, - { DRDATA (XTIME, dqc_xtime, 24), REG_NZ + PV_LEFT }, - { URDATA (UCYL, dqc_unit[0].CYL, 10, 8, 0, - DQ_NUMDRV, PV_LEFT | REG_HRO) }, - { URDATA (UFNC, dqc_unit[0].FNC, 8, 8, 0, - DQ_NUMDRV, REG_HRO) }, - { ORDATA (DEVNO, dqc_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB dqc_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &dqd_dev }, - { 0 } }; - -DEVICE dqc_dev = { - "DQC", dqc_unit, dqc_reg, dqc_mod, - DQ_NUMDRV, 8, 24, 1, 8, 16, - NULL, NULL, &dqc_reset, - &dqc_boot, NULL, NULL, - &dqc_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 dqdio (int32 inst, int32 IR, int32 dat) -{ -int32 devd; - -devd = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (devd); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - dqd_obuf = dat; - if (!dqc_busy || dqd_xfer) dqd_wval = 1; /* if !overrun, valid */ - break; -case ioMIX: /* merge */ - dat = dat | dqd_ibuf; - break; -case ioLIX: /* load */ - dat = dqd_ibuf; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCTL (devd); /* clr ctl, cmd */ - clrCMD (devd); - dqd_xfer = 0; } /* clr xfer */ - else { /* STC */ - setCTL (devd); /* set ctl, cmd */ - setCMD (devd); - if (dqc_busy && !dqd_xfer) /* overrun? */ - dqc_sta[dqc_busy - 1] |= STA_DTE | STA_ERR; } - break; -default: - break; } -if (IR & I_HC) { clrFLG (devd); } /* H/C option */ -return dat; -} - -int32 dqcio (int32 inst, int32 IR, int32 dat) -{ -int32 devc, fnc, drv; - -devc = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (devc); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - dqc_obuf = dat; - break; -case ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - break; /* no data */ -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC? */ - clrCMD (devc); /* clr cmd, ctl */ - clrCTL (devc); /* cancel non-seek */ - if (dqc_busy) sim_cancel (&dqc_unit[dqc_busy - 1]); - sim_cancel (&dqd_unit); /* cancel dch */ - dqd_xfer = 0; /* clr dch xfer */ - dqc_busy = 0; } /* clr busy */ - else { /* STC */ - setCTL (devc); /* set ctl */ - if (!CMD (devc)) { /* cmd clr? */ - setCMD (devc); /* set cmd, ctl */ - drv = CW_GETDRV (dqc_obuf); /* get fnc, drv */ - fnc = CW_GETFNC (dqc_obuf); /* from cmd word */ - switch (fnc) { /* case on fnc */ - case FNC_SEEK: case FNC_RCL: /* seek, recal */ - case FNC_CHK: /* check */ - dqc_sta[drv] = 0; /* clear status */ - case FNC_STA: case FNC_LA: /* rd sta, load addr */ - dq_god (fnc, drv, dqc_dtime); /* sched dch xfer */ - break; - case FNC_RD: case FNC_WD: /* read, write */ - case FNC_RA: case FNC_WA: /* rd addr, wr addr */ - case FNC_AS: /* address skip */ - dq_goc (fnc, drv, dqc_ctime); /* sched drive */ - break; } /* end case */ - } /* end if !CMD */ - } /* end else */ - break; -default: - break; } -if (IR & I_HC) { clrFLG (devc); } /* H/C option */ -return dat; -} - -/* Start data channel operation */ - -void dq_god (int32 fnc, int32 drv, int32 time) -{ -dqd_unit.CYL = drv; /* save unit */ -dqd_unit.FNC = fnc; /* save function */ -sim_activate (&dqd_unit, time); -return; -} - -/* Start controller operation */ - -void dq_goc (int32 fnc, int32 drv, int32 time) -{ -if (sim_is_active (&dqc_unit[drv])) { /* still seeking? */ - sim_cancel (&dqc_unit[drv]); /* cancel */ - time = time + dqc_stime; } /* take longer */ -dqc_sta[drv] = 0; /* clear status */ -dq_ptr = 0; /* init buf ptr */ -dqc_busy = drv + 1; /* set busy */ -dqd_xfer = 1; /* xfer in prog */ -dqc_unit[drv].FNC = fnc; /* save function */ -sim_activate (&dqc_unit[drv], time); /* activate unit */ -return; -} - -/* Data channel unit service - - This routine handles the data channel transfers. It also handles - data transfers that are blocked by seek in progress. - - uptr->CYL = target drive - uptr->FNC = target function - - Seek substates - seek - transfer cylinder - seek1 - transfer head/surface, sched drive - Recalibrate substates - rcl - clear cyl/head/surface, sched drive - Load address - la - transfer cylinder - la1 - transfer head/surface, finish operation - Status check - transfer status, finish operation - Check data - chk - transfer sector count, sched drive -*/ - -t_stat dqd_svc (UNIT *uptr) -{ -int32 drv, devc, devd, st; - -drv = uptr->CYL; /* get drive no */ -devc = dqc_dib.devno; /* get cch devno */ -devd = dqd_dib.devno; /* get dch devno */ -switch (uptr->FNC) { /* case function */ - -case FNC_SEEK: /* seek, need cyl */ - if (CMD (devd)) { /* dch active? */ - dqc_rarc[drv] = DA_GETCYL (dqd_obuf); /* take cyl word */ - dqd_wval = 0; /* clr data valid */ - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - uptr->FNC = FNC_SEEK1; } /* advance state */ - sim_activate (uptr, dqc_xtime); /* no, wait more */ - break; -case FNC_SEEK1: /* seek, need hd/sec */ - if (CMD (devd)) { /* dch active? */ - dqc_rarh[drv] = DA_GETHD (dqd_obuf); /* get head */ - dqc_rars[drv] = DA_GETSC (dqd_obuf); /* get sector */ - dqd_wval = 0; /* clr data valid */ - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - if (sim_is_active (&dqc_unit[drv])) break; /* if busy */ - st = abs (dqc_rarc[drv] - dqc_unit[drv].CYL) * dqc_stime; - if (st == 0) st = dqc_xtime; /* if on cyl, min time */ - else dqc_sta[drv] = dqc_sta[drv] | STA_BSY; /* set busy */ - sim_activate (&dqc_unit[drv], st); /* schedule op */ - dqc_unit[drv].CYL = dqc_rarc[drv]; /* on cylinder */ - dqc_unit[drv].FNC = FNC_SEEK2; } /* advance state */ - else sim_activate (uptr, dqc_xtime); /* no, wait more */ - break; - -case FNC_RCL: /* recalibrate */ - dqc_rarc[drv] = dqc_rarh[drv] = dqc_rars[drv] = 0; /* clear RAR */ - if (sim_is_active (&dqc_unit[drv])) break; /* ignore if busy */ - st = dqc_unit[drv].CYL * dqc_stime; /* calc diff */ - if (st == 0) st = dqc_xtime; /* if on cyl, min time */ - else dqc_sta[drv] = dqc_sta[drv] | STA_BSY; /* set busy */ - sim_activate (&dqc_unit[drv], st); /* schedule drive */ - dqc_unit[drv].CYL = 0; /* on cylinder */ - dqc_unit[drv].FNC = FNC_SEEK2; /* advance state */ - break; - -case FNC_LA: /* arec, need cyl */ - if (CMD (devd)) { /* dch active? */ - dqc_rarc[drv] = DA_GETCYL (dqd_obuf); /* take cyl word */ - dqd_wval = 0; /* clr data valid */ - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - uptr->FNC = FNC_LA1; } /* advance state */ - sim_activate (uptr, dqc_xtime); /* no, wait more */ - break; -case FNC_LA1: /* arec, need hd/sec */ - if (CMD (devd)) { /* dch active? */ - dqc_rarh[drv] = DA_GETHD (dqd_obuf); /* get head */ - dqc_rars[drv] = DA_GETSC (dqd_obuf); /* get sector */ - dqd_wval = 0; /* clr data valid */ - setFLG (devc); /* set cch flg */ - clrCMD (devc); /* clr cch cmd */ - setFLG (devd); /* set dch flg */ - clrCMD (devd); } /* clr dch cmd */ - else sim_activate (uptr, dqc_xtime); /* no, wait more */ - break; - -case FNC_STA: /* read status */ - if (CMD (devd)) { /* dch active? */ - if (dqc_unit[drv].flags & UNIT_ATT) /* attached? */ - dqd_ibuf = dqc_sta[drv] & ~STA_DID; - else dqd_ibuf = STA_NRDY; - if (drv) dqd_ibuf = dqd_ibuf | STA_DID; - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - clrCMD (devc); /* clr cch cmd */ - dqc_sta[drv] = dqc_sta[drv] & /* clr sta flags */ - ~(STA_DTE | STA_FLG | STA_AER | STA_EOC | STA_ERR); - } - else sim_activate (uptr, dqc_xtime); /* wait more */ - break; - -case FNC_CHK: /* check, need cnt */ - if (CMD (devd)) { /* dch active? */ - dqc_cnt = dqd_obuf & DA_CKMASK; /* get count */ - dqd_wval = 0; /* clr data valid */ -/* setFLG (devd); /* set dch flg */ -/* clrCMD (devd); /* clr dch cmd */ - dq_goc (FNC_CHK1, drv, dqc_ctime); } /* sched drv */ - else sim_activate (uptr, dqc_xtime); /* wait more */ - break; - -default: - return SCPE_IERR; } -return SCPE_OK; -} - -/* Drive unit service - - This routine handles the data transfers. - - Seek substates - seek2 - done - Recalibrate substate - rcl1 - done - Check data substates - chk1 - finish operation - Read - Read address - Address skip (read without header check) - Write - Write address -*/ - -#define GETDA(x,y,z) \ - (((((x) * DQ_NUMSF) + (y)) * DQ_NUMSC) + (z)) * DQ_NUMWD - -t_stat dqc_svc (UNIT *uptr) -{ -int32 da, drv, devc, devd, err; - -err = 0; /* assume no err */ -drv = uptr - dqc_dev.units; /* get drive no */ -devc = dqc_dib.devno; /* get cch devno */ -devd = dqd_dib.devno; /* get dch devno */ -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - setFLG (devc); /* set cch flg */ - clrCMD (devc); /* clr cch cmd */ - dqc_sta[drv] = 0; /* clr status */ - dqc_busy = 0; /* ctlr is free */ - dqd_xfer = dqd_wval = 0; - return SCPE_OK; } -switch (uptr->FNC) { /* case function */ - -case FNC_SEEK2: /* seek done */ - if (uptr->CYL >= DQ_NUMCY) { /* out of range? */ - dqc_sta[drv] = dqc_sta[drv] | STA_BSY | STA_ERR; - dqc_unit[drv].CYL = 0; } - else dqc_sta[drv] = dqc_sta[drv] & ~STA_BSY; /* drive not busy */ -case FNC_SEEK3: - if (dqc_busy || FLG (devc)) { /* ctrl busy? */ - uptr->FNC = FNC_SEEK3; /* next state */ - sim_activate (uptr, dqc_xtime); } /* ctrl busy? wait */ - else { - setFLG (devc); /* set cch flg */ - clrCMD (devc); } /* clr cch cmd */ - return SCPE_OK; - -case FNC_RA: /* read addr */ - if (!CMD (devd)) break; /* dch clr? done */ - if (dq_ptr == 0) dqd_ibuf = uptr->CYL; /* 1st word? */ - else if (dq_ptr == 1) { /* second word? */ - dqd_ibuf = (dqc_rarh[drv] << DA_V_HD) | - (dqc_rars[drv] << DA_V_SC); - dqc_rars[drv] = dqc_rars[drv] + 1; /* incr address */ - if (dqc_rars[drv] >= DQ_NUMSC) /* end of surf? */ - dqc_rars[drv] = 0; } - else break; - dq_ptr = dq_ptr + 1; - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - sim_activate (uptr, dqc_xtime); /* sched next word */ - return SCPE_OK; - -case FNC_AS: /* address skip */ -case FNC_RD: /* read */ -case FNC_CHK1: /* check */ - if (dq_ptr == 0) { /* new sector? */ - if (!CMD (devd) && (uptr->FNC != FNC_CHK1)) break; - if ((uptr->CYL != dqc_rarc[drv]) || /* wrong cyl or */ - (dqc_rars[drv] >= DQ_NUMSC)) { /* bad sector? */ - dqc_sta[drv] = dqc_sta[drv] | STA_AER | STA_ERR; - break; } - if (dqc_rarh[drv] >= DQ_NUMSF) { /* bad head? */ - dqc_sta[drv] = dqc_sta[drv] | STA_EOC | STA_ERR; - break; } - da = GETDA (dqc_rarc[drv], dqc_rarh[drv], dqc_rars[drv]); - dqc_rars[drv] = dqc_rars[drv] + 1; /* incr address */ - if (dqc_rars[drv] >= DQ_NUMSC) { /* end of surf? */ - dqc_rars[drv] = 0; /* wrap to */ - dqc_rarh[drv] = dqc_rarh[drv] + 1; } /* next head */ - if (err = fseek (uptr->fileref, da * sizeof (int16), - SEEK_SET)) break; - fxread (dqxb, sizeof (int16), DQ_NUMWD, uptr->fileref); - if (err = ferror (uptr->fileref)) break; } - dqd_ibuf = dqxb[dq_ptr++]; /* get word */ - if (dq_ptr >= DQ_NUMWD) { /* end of sector? */ - if (uptr->FNC == FNC_CHK1) { /* check? */ - dqc_cnt = (dqc_cnt - 1) & DA_CKMASK; /* decr count */ - if (dqc_cnt == 0) break; } /* if zero, done */ - dq_ptr = 0; } /* wrap buf ptr */ - if (CMD (devd) && dqd_xfer) { /* dch on, xfer? */ - setFLG (devd); } /* set flag */ - clrCMD (devd); /* clr dch cmd */ - sim_activate (uptr, dqc_xtime); /* sched next word */ - return SCPE_OK; - -case FNC_WA: /* write address */ -case FNC_WD: /* write */ - if (dq_ptr == 0) { /* sector start? */ - if (!CMD (devd) && !dqd_wval) break; /* xfer done? */ - if(uptr->flags & UNIT_WPRT) { /* write protect? */ - dqc_sta[drv] = dqc_sta[drv] | STA_FLG | STA_ERR; - break; } /* done */ - if ((uptr->CYL != dqc_rarc[drv]) || /* wrong cyl or */ - (dqc_rars[drv] >= DQ_NUMSC)) { /* bad sector? */ - dqc_sta[drv] = dqc_sta[drv] | STA_AER | STA_ERR; - break; } - if (dqc_rarh[drv] >= DQ_NUMSF) { /* bad head? */ - dqc_sta[drv] = dqc_sta[drv] | STA_EOC | STA_ERR; - break; } } /* done */ - dqxb[dq_ptr++] = dqd_wval? dqd_obuf: 0; /* store word/fill */ - dqd_wval = 0; /* clr data valid */ - if (dq_ptr >= DQ_NUMWD) { /* buffer full? */ - da = GETDA (dqc_rarc[drv], dqc_rarh[drv], dqc_rars[drv]); - dqc_rars[drv] = dqc_rars[drv] + 1; /* incr address */ - if (dqc_rars[drv] >= DQ_NUMSC) { /* end of surf? */ - dqc_rars[drv] = 0; /* wrap to */ - dqc_rarh[drv] = dqc_rarh[drv] + 1; } /* next head */ - if (err = fseek (uptr->fileref, da * sizeof (int16), - SEEK_SET)) return TRUE; - fxwrite (dqxb, sizeof (int16), DQ_NUMWD, uptr->fileref); - if (err = ferror (uptr->fileref)) break; - dq_ptr = 0; } - if (CMD (devd) && dqd_xfer) { /* dch on, xfer? */ - setFLG (devd); } /* set flag */ - clrCMD (devd); /* clr dch cmd */ - sim_activate (uptr, dqc_xtime); /* sched next word */ - return SCPE_OK; - -default: - return SCPE_IERR; } /* end case fnc */ - -setFLG (devc); /* set cch flg */ -clrCMD (devc); /* clr cch cmd */ -dqc_busy = 0; /* ctlr is free */ -dqd_xfer = dqd_wval = 0; -if (err != 0) { /* error? */ - perror ("DQ I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat dqc_reset (DEVICE *dptr) -{ -int32 i; - -hp_enbdis_pair (&dqc_dev, &dqd_dev); /* make pair cons */ -dqd_ibuf = dqd_obuf = 0; /* clear buffers */ -dqc_busy = dqc_obuf = 0; -dqd_xfer = dqd_wval = 0; -dq_ptr = 0; -dqc_dib.cmd = dqd_dib.cmd = 0; /* clear cmd */ -dqc_dib.ctl = dqd_dib.ctl = 0; /* clear ctl */ -dqc_dib.fbf = dqd_dib.fbf = 1; /* set fbf */ -dqc_dib.flg = dqd_dib.flg = 1; /* set flg */ -sim_cancel (&dqd_unit); /* cancel dch */ -for (i = 0; i < DQ_NUMDRV; i++) { /* loop thru drives */ - sim_cancel (&dqc_unit[i]); /* cancel activity */ - dqc_unit[i].FNC = 0; /* clear function */ - dqc_unit[i].CYL = 0; - dqc_rarc[i] = dqc_rarh[i] = dqc_rars[i] = 0; /* clear rar */ - dqc_sta[i] = 0; } -return SCPE_OK; -} - -/* Write lock/enable routine */ - -t_stat dqc_vlock (UNIT *uptr, int32 val) -{ -if (uptr->flags & UNIT_ATT) return SCPE_ARG; -return SCPE_OK; -} - -/* 2883/2884 bootstrap routine (subset HP 12992A ROM) */ - -#define LDR_BASE 077 -#define CHANGE_DEV (1 << 24) - -static const int32 dboot[IBL_LNT] = { - 0106700+CHANGE_DEV, /*ST CLC DC ; clr dch */ - 0106701+CHANGE_DEV, /* CLC CC ; clr cch */ - 0067771, /* LDA SKCMD ; seek cmd */ - 0106600+CHANGE_DEV, /* OTB DC ; cyl # */ - 0103700+CHANGE_DEV, /* STC DC,C ; to dch */ - 0106601+CHANGE_DEV, /* OTB CC ; seek cmd */ - 0103701+CHANGE_DEV, /* STC CC,C ; to cch */ - 0102300+CHANGE_DEV, /* SFS DC ; addr wd ok? */ - 0027707, /* JMP *-1 ; no, wait */ - 0006400, /* CLB */ - 0106600+CHANGE_DEV, /* OTB DC ; head/sector */ - 0103700+CHANGE_DEV, /* STC DC,C ; to dch */ - 0102301+CHANGE_DEV, /* SFS CC ; seek done? */ - 0027714, /* JMP *-1 ; no, wait */ - 0063770, /* LDA RDCMD ; get read read */ - 0067776, /* LDB DMACW ; DMA control */ - 0106606, /* OTB 6 */ - 0067772, /* LDB ADDR1 ; memory addr */ - 0106602, /* OTB 2 */ - 0102702, /* STC 2 ; flip DMA ctrl */ - 0067774, /* LDB CNT ; word count */ - 0106602, /* OTB 2 */ - 0102601+CHANGE_DEV, /* OTA CC ; to cch */ - 0103700+CHANGE_DEV, /* STC DC,C ; start dch */ - 0103606, /* STC 6,C ; start DMA */ - 0103701+CHANGE_DEV, /* STC CC,C ; start cch */ - 0102301+CHANGE_DEV, /* SFS CC ; done? */ - 0027732, /* JMP *-1 ; no, wait */ - 0027775, /* JMP XT ; done */ - 0, 0, 0, /* unused */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0020000, /*RDCMD 020000 ; read cmd */ - 0030000, /*SKCMD 030000 ; seek cmd */ - 0102011, /*ADDR1 102011 */ - 0102055, /*ADDR2 102055 */ - 0164000, /*CNT -6144. */ - 0117773, /*XT JSB ADDR2,I ; start program */ - 0120000+CHANGE_DEV, /*DMACW 120000+DC */ - 0000000 }; /* -ST */ - -t_stat dqc_boot (int32 unitno, DEVICE *dptr) -{ -int32 i, dev; - -if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ -dev = dqd_dib.devno; /* get data chan dev */ -PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */ -SR = IBL_DQ + (dev << IBL_V_DEV); /* set SR */ -for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */ - if (dboot[i] & CHANGE_DEV) /* IO instr? */ - M[PC + i] = (dboot[i] + dev) & DMASK; - else M[PC + i] = dboot[i]; } -M[PC + LDR_BASE] = (~PC + 1) & DMASK; -return SCPE_OK; -} diff --git a/HP2100/hp2100_dr.c b/HP2100/hp2100_dr.c deleted file mode 100644 index 9a02a638..00000000 --- a/HP2100/hp2100_dr.c +++ /dev/null @@ -1,422 +0,0 @@ -/* hp2100_dr.c: HP 2100 12606B/12610B fixed head disk/drum simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - fhd 12606B 2770/2771 fixed head disk - 12610B 2773/2774/2775 drum - - These head-per-track devices are buffered in memory, to minimize overhead. - - The drum data channel does not have a command flip-flop. Its control - flip-flop is not wired into the interrupt chain; accordingly, the - simulator uses command rather than control for the data channel. Its - flag does not respond to SFS, SFC, or STF. - - The drum control channel does not have any of the traditional flip-flops. - - 27-Jul-03 RMS Fixed drum sizes - Fixed variable capacity interaction with SAVE/RESTORE - 10-Nov-02 RMS Added BOOT command -*/ - -#include "hp2100_defs.h" -#include - -/* Constants */ - -#define DR_NUMWD 64 /* words/sector */ -#define DR_FNUMSC 90 /* fhd sec/track */ -#define DR_DNUMSC 32 /* drum sec/track */ -#define DR_NUMSC ((drc_unit.flags & UNIT_DR)? DR_DNUMSC: DR_FNUMSC) -#define DR_SIZE (512 * DR_DNUMSC * DR_NUMWD) /* initial size */ -#define UNIT_V_SZ (UNIT_V_UF) /* disk vs drum */ -#define UNIT_M_SZ 017 /* size */ -#define UNIT_SZ (UNIT_M_SZ << UNIT_V_SZ) -#define UNIT_DR (1 << UNIT_V_SZ) /* low order bit */ -#define SZ_180K 000 /* disks */ -#define SZ_360K 002 -#define SZ_720K 004 -#define SZ_1024K 001 /* drums: default size */ -#define SZ_1536K 003 -#define SZ_384K 005 -#define SZ_512K 007 -#define SZ_640K 011 -#define SZ_768K 013 -#define SZ_896K 015 -#define DR_GETSZ(x) (((x) >> UNIT_V_SZ) & UNIT_M_SZ) - -/* Command word */ - -#define CW_WR 0100000 /* write vs read */ -#define CW_V_FTRK 7 /* fhd track */ -#define CW_M_FTRK 0177 -#define CW_V_DTRK 5 /* drum track */ -#define CW_M_DTRK 01777 -#define MAX_TRK (((drc_unit.flags & UNIT_DR)? CW_M_DTRK: CW_M_FTRK) + 1) -#define CW_GETTRK(x) ((drc_unit.flags & UNIT_DR)? \ - (((x) >> CW_V_DTRK) & CW_M_DTRK): \ - (((x) >> CW_V_FTRK) & CW_M_FTRK)) -#define CW_PUTTRK(x) ((drc_unit.flags & UNIT_DR)? \ - (((x) & CW_M_DTRK) << CW_V_DTRK): \ - (((x) & CW_M_FTRK) << CW_V_FTRK)) -#define CW_V_FSEC 0 /* fhd sector */ -#define CW_M_FSEC 0177 -#define CW_V_DSEC 0 /* drum sector */ -#define CW_M_DSEC 037 -#define CW_GETSEC(x) ((drc_unit.flags & UNIT_DR)? \ - (((x) >> CW_V_DSEC) & CW_M_DSEC): \ - (((x) >> CW_V_FSEC) & CW_M_FSEC)) -#define CW_PUTSEC(x) ((drc_unit.flags & UNIT_DR)? \ - (((x) & CW_M_DSEC) << CW_V_DSEC): \ - (((x) & CW_M_FSEC) << CW_V_FSEC)) - -/* Status register */ - -#define DRS_V_NS 8 /* next sector */ -#define DRS_M_NS 0177 -#define DRS_SEC 0100000 /* sector flag */ -#define DRS_RDY 0000200 /* ready */ -#define DRS_RIF 0000100 /* read inhibit */ -#define DRS_SAC 0000040 /* sector coincidence */ -#define DRS_ABO 0000010 /* abort */ -#define DRS_WEN 0000004 /* write enabled */ -#define DRS_PER 0000002 /* parity error */ -#define DRS_BSY 0000001 /* busy */ - -#define GET_CURSEC(x) ((int32) fmod (sim_gtime() / ((double) (x)), \ - ((double) ((drc_unit.flags & UNIT_DR)? DR_DNUMSC: DR_FNUMSC)))) - -extern UNIT cpu_unit; -extern uint16 *M; -extern uint32 PC; -extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; - -int32 drc_cw = 0; /* fnc, addr */ -int32 drc_sta = 0; /* status */ -int32 drd_ibuf = 0; /* input buffer */ -int32 drd_obuf = 0; /* output buffer */ -int32 drd_ptr = 0; /* sector pointer */ -int32 dr_stopioe = 1; /* stop on error */ -int32 dr_time = 10; /* time per word */ - -static int32 sz_tab[16] = { - 184320, 1048576, 368640, 1572864, 737280, 393216, 0, 524288, - 0, 655360, 0, 786432, 0, 917504, 0, 0 }; - -DEVICE drd_dev, drc_dev; -int32 drdio (int32 inst, int32 IR, int32 dat); -int32 drcio (int32 inst, int32 IR, int32 dat); -t_stat drc_svc (UNIT *uptr); -t_stat drc_reset (DEVICE *dptr); -t_stat drc_attach (UNIT *uptr, char *cptr); -t_stat drc_boot (int32 unitno, DEVICE *dptr); -int32 dr_incda (int32 trk, int32 sec, int32 ptr); -t_stat dr_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* DRD data structures - - drd_dev device descriptor - drd_unit unit descriptor - drd_reg register list -*/ - -DIB dr_dib[] = { - { DRD, 0, 0, 0, 0, &drdio }, - { DRC, 0, 0, 0, 0, &drcio } }; - -#define drd_dib dr_dib[0] -#define drc_dib dr_dib[1] - -UNIT drd_unit = { UDATA (NULL, 0, 0) }; - -REG drd_reg[] = { - { ORDATA (IBUF, drd_ibuf, 16) }, - { ORDATA (OBUF, drd_obuf, 16) }, - { FLDATA (CMD, drd_dib.cmd, 0) }, - { FLDATA (CTL, drd_dib.ctl, 0) }, - { FLDATA (FLG, drd_dib.flg, 0) }, - { FLDATA (FBF, drd_dib.fbf, 0) }, - { ORDATA (BPTR, drd_ptr, 6) }, - { ORDATA (DEVNO, drd_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB drd_mod[] = { - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &drd_dev }, - { 0 } }; - -DEVICE drd_dev = { - "DRD", &drd_unit, drd_reg, drd_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, NULL, - NULL, NULL, NULL, - &drd_dib, DEV_DISABLE }; - -/* DRC data structures - - drc_dev device descriptor - drc_unit unit descriptor - drc_mod unit modifiers - drc_reg register list -*/ - -UNIT drc_unit = - { UDATA (&drc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+ - UNIT_MUSTBUF+UNIT_DR+UNIT_BINK, DR_SIZE) }; - -REG drc_reg[] = { - { ORDATA (CW, drc_cw, 16) }, - { ORDATA (STA, drc_sta, 16) }, - { FLDATA (CMD, drc_dib.cmd, 0) }, - { FLDATA (CTL, drc_dib.ctl, 0) }, - { FLDATA (FLG, drc_dib.flg, 0) }, - { FLDATA (FBF, drc_dib.fbf, 0) }, - { DRDATA (TIME, dr_time, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, dr_stopioe, 0) }, - { ORDATA (DEVNO, drc_dib.devno, 6), REG_HRO }, - { DRDATA (CAPAC, drc_unit.capac, 24), REG_HRO }, - { NULL } }; - -MTAB drc_mod[] = { - { UNIT_DR, 0, "disk", NULL, NULL }, - { UNIT_DR, UNIT_DR, "drum", NULL, NULL }, - { UNIT_SZ, (SZ_180K << UNIT_V_SZ), NULL, "180K", &dr_set_size }, - { UNIT_SZ, (SZ_360K << UNIT_V_SZ), NULL, "360K", &dr_set_size }, - { UNIT_SZ, (SZ_720K << UNIT_V_SZ), NULL, "720K", &dr_set_size }, - { UNIT_SZ, (SZ_384K << UNIT_V_SZ), NULL, "384K", &dr_set_size }, - { UNIT_SZ, (SZ_512K << UNIT_V_SZ), NULL, "512K", &dr_set_size }, - { UNIT_SZ, (SZ_640K << UNIT_V_SZ), NULL, "640K", &dr_set_size }, - { UNIT_SZ, (SZ_768K << UNIT_V_SZ), NULL, "768K", &dr_set_size }, - { UNIT_SZ, (SZ_896K << UNIT_V_SZ), NULL, "896K", &dr_set_size }, - { UNIT_SZ, (SZ_1024K << UNIT_V_SZ), NULL, "1024K", &dr_set_size }, - { UNIT_SZ, (SZ_1536K << UNIT_V_SZ), NULL, "1536K", &dr_set_size }, - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &drd_dev }, - { 0 } }; - -DEVICE drc_dev = { - "DRC", &drc_unit, drc_reg, drc_mod, - 1, 8, 21, 1, 8, 16, - NULL, NULL, &drc_reset, - &drc_boot, &drc_attach, NULL, - &drc_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 drdio (int32 inst, int32 IR, int32 dat) -{ -int32 devd, t; - -devd = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioOTX: /* output */ - drd_obuf = dat; - break; -case ioMIX: /* merge */ - dat = dat | drd_ibuf; - break; -case ioLIX: /* load */ - dat = drd_ibuf; - break; -case ioCTL: /* control clear/set */ - if (IR & I_AB) { /* CLC */ - clrCMD (devd); /* clr "ctl" */ - clrFLG (devd); /* clr flg */ - drc_sta = drc_sta & ~DRS_SAC; } /* clear SAC flag */ - else if (!CMD (devd)) { /* STC, not set? */ - setCMD (devd); /* set "ctl" */ - if (drc_cw & CW_WR) { setFLG (devd); } /* prime DMA */ - drc_sta = 0; /* clear errors */ - drd_ptr = 0; /* clear sec ptr */ - sim_cancel (&drc_unit); /* cancel curr op */ - t = CW_GETSEC (drc_cw) - GET_CURSEC (dr_time * DR_NUMWD); - if (t <= 0) t = t + DR_NUMSC; - sim_activate (&drc_unit, t * DR_NUMWD * dr_time); } - break; -default: - break; } -if (IR & I_HC) { clrFLG (devd); } /* H/C option */ -return dat; -} - -int32 drcio (int32 inst, int32 IR, int32 dat) -{ -int32 st; - -switch (inst) { /* case on opcode */ -case ioSFC: /* skip flag clear */ - PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - drc_cw = dat; - break; -case ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - if (drc_unit.flags & UNIT_ATT) /* attached? */ - st = GET_CURSEC (dr_time) | DRS_RDY | drc_sta | - (sim_is_active (&drc_unit)? DRS_BSY: 0); - else st = drc_sta; - dat = dat | st; /* merge status */ - break; -default: - break; } -return dat; -} - -/* Unit service */ - -t_stat drc_svc (UNIT *uptr) -{ -int32 devd, trk, sec; -uint32 da; - -if ((uptr->flags & UNIT_ATT) == 0) { - drc_sta = DRS_ABO; - return IORETURN (dr_stopioe, SCPE_UNATT); } - -drc_sta = drc_sta | DRS_SAC; -devd = drd_dib.devno; /* get dch devno */ -trk = CW_GETTRK (drc_cw); -sec = CW_GETSEC (drc_cw); -da = ((trk * DR_NUMSC) + sec) * DR_NUMWD; - -if (drc_cw & CW_WR) { /* write? */ - if ((da < uptr->capac) && (sec < DR_NUMSC)) { - *(((uint16 *) uptr->filebuf) + da + drd_ptr) = drd_obuf; - if (((uint32) (da + drd_ptr)) >= uptr->hwmark) - uptr->hwmark = da + drd_ptr + 1; } - drd_ptr = dr_incda (trk, sec, drd_ptr); /* inc disk addr */ - if (CMD (devd)) { /* dch active? */ - setFLG (devd); /* set dch flg */ - sim_activate (uptr, dr_time); } /* sched next word */ - else if (drd_ptr) { /* done, need to fill? */ - for ( ; drd_ptr < DR_NUMWD; drd_ptr++) - *(((uint16 *) uptr->filebuf) + da + drd_ptr) = 0; } - } /* end write */ -else { /* read */ - if (CMD (devd)) { /* dch active? */ - if ((da >= uptr->capac) || (sec >= DR_NUMSC)) drd_ibuf = 0; - else drd_ibuf = *(((uint16 *) uptr->filebuf) + da + drd_ptr); - drd_ptr = dr_incda (trk, sec, drd_ptr); - setFLG (devd); /* set dch flg */ - sim_activate (uptr, dr_time); } /* sched next word */ - } -return SCPE_OK; -} - -/* Increment current disk address */ - -int32 dr_incda (int32 trk, int32 sec, int32 ptr) -{ -ptr = ptr + 1; /* inc pointer */ -if (ptr >= DR_NUMWD) { /* end sector? */ - ptr = 0; /* new sector */ - sec = sec + 1; /* adv sector */ - if (sec >= DR_NUMSC) { /* end track? */ - sec = 0; /* new track */ - trk = trk + 1; /* adv track */ - if (trk >= MAX_TRK) trk = 0; } /* wraps at max */ - drc_cw = (drc_cw & CW_WR) | CW_PUTTRK (trk) | CW_PUTSEC (sec); - } -return ptr; -} - -/* Reset routine */ - -t_stat drc_reset (DEVICE *dptr) -{ -hp_enbdis_pair (&drc_dev, &drd_dev); /* make pair cons */ -drc_sta = drc_cw = drd_ptr = 0; -drc_dib.cmd = drd_dib.cmd = 0; /* clear cmd */ -drc_dib.ctl = drd_dib.ctl = 0; /* clear ctl */ -drc_dib.fbf = drd_dib.fbf = 0; /* clear fbf */ -drc_dib.flg = drd_dib.flg = 0; /* clear flg */ -sim_cancel (&drc_unit); -return SCPE_OK; -} - -/* Attach routine */ - -t_stat drc_attach (UNIT *uptr, char *cptr) -{ -int32 sz = sz_tab[DR_GETSZ (uptr->flags)]; - -if (sz == 0) return SCPE_IERR; -uptr->capac = sz; -return attach_unit (uptr, cptr); -} -/* Set size routine */ - -t_stat dr_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 sz; - -if (val < 0) return SCPE_IERR; -if ((sz = sz_tab[DR_GETSZ (val)]) == 0) return SCPE_IERR; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = sz; -return SCPE_OK; -} - -/* Fixed head disk/drum bootstrap routine (disc subset of disc/paper tape loader) */ - -#define CHANGE_DEV (1 << 24) -#define BOOT_BASE 056 -#define BOOT_START 060 - -static const int32 dboot[IBL_LNT - BOOT_BASE] = { - 0020000+CHANGE_DEV, /*DMA 20000+DC */ - 0000000, /* 0 */ - 0107700, /* CLC 0,C */ - 0063756, /* LDA DMA ; DMA ctrl */ - 0102606, /* OTA 6 */ - 0002700, /* CLA,CCE */ - 0102601+CHANGE_DEV, /* OTA CC ; trk = sec = 0 */ - 0001500, /* ERA ; A = 100000 */ - 0102602, /* OTA 2 ; DMA in, addr */ - 0063777, /* LDA M64 */ - 0102702, /* STC 2 */ - 0102602, /* OTA 2 ; DMA wc = -64 */ - 0103706, /* STC 6,C ; start DMA */ - 0067776, /* LDB JSF ; get JMP . */ - 0074077, /* STB 77 ; in base page */ - 0102700+CHANGE_DEV, /* STC DC ; start disc */ - 0024077, /*JSF JMP 77 ; go wait */ - 0177700 }; /*M64 -100 */ - -t_stat drc_boot (int32 unitno, DEVICE *dptr) -{ -int32 i, dev, ad; - -if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ -dev = drd_dib.devno; /* get data chan dev */ -ad = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */ -for (i = 0; i < (IBL_LNT - BOOT_BASE); i++) { /* copy bootstrap */ - if (dboot[i] & CHANGE_DEV) /* IO instr? */ - M[ad + BOOT_BASE + i] = (dboot[i] + dev) & DMASK; - else M[ad + BOOT_BASE + i] = dboot[i]; } -PC = ad + BOOT_START; -return SCPE_OK; -} diff --git a/HP2100/hp2100_fp.c b/HP2100/hp2100_fp.c deleted file mode 100644 index 365413b8..00000000 --- a/HP2100/hp2100_fp.c +++ /dev/null @@ -1,312 +0,0 @@ -/* hp2100_fp.c: HP 2100 floating point instructions - - Copyright (c) 2002-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 15-Jul-03 RMS Fixed signed/unsigned warning - 21-Oct-02 RMS Recoded for compatibility with 21MX microcode algorithms - - The HP2100 uses a unique binary floating point format: - - 15 14 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |S | fraction high | : A - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | fraction low | exponent |XS| : A + 1 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - 15 8 7 1 0 - - where S = 0 for plus fraction, 1 for minus fraction - fraction = s.bbbbb..., 24 binary digits - exponent = 2**+/-n - XS = 0 for plus exponent, 1 for minus exponent - - Numbers can be normalized or unnormalized but are always normalized - when loaded. - - Unpacked floating point numbers are stored in structure ufp - - exp = exponent, 2's complement - h'l = fraction, 2's comp, left justified - - This routine tries to reproduce the algorithms of the 2100/21MX - microcode in order to achieve 'bug-for-bug' compatibility. In - particular, - - - The FIX code produces various results in B. - - The fraction multiply code uses 16b x 16b multiplies to produce - a 31b result. It always loses the low order bit of the product. - - The fraction divide code is an approximation that may produce - an error of 1 LSB. - - Signs are tracked implicitly as part of the fraction. Unnormalized - inputs may cause the packup code to produce the wrong sign. - - "Unclean" zeros (zero fraction, non-zero exponent) are processed - like normal operands. -*/ - -#include "hp2100_defs.h" - -struct ufp { /* unpacked fp */ - int32 exp; /* exp */ - uint32 fr; }; /* frac */ - -#define FP_V_SIGN 31 /* sign */ -#define FP_M_SIGN 01 -#define FP_V_FR 8 /* fraction */ -#define FP_M_FR 077777777 -#define FP_V_EXP 1 /* exponent */ -#define FP_M_EXP 0177 -#define FP_V_EXPS 0 /* exp sign */ -#define FP_M_EXPS 01 -#define FP_SIGN (FP_M_SIGN << FP_V_SIGN) -#define FP_FR (FP_M_FR << FP_V_FR) -#define FP_EXP (FP_M_EXP << FP_V_EXP) -#define FP_EXPS (FP_M_EXPS << FP_V_EXPS) -#define FP_GETSIGN(x) (((x) >> FP_V_SIGN) & FP_M_SIGN) -#define FP_GETEXP(x) (((x) >> FP_V_EXP) & FP_M_EXP) -#define FP_GETEXPS(x) (((x) >> FP_V_EXPS) & FP_M_EXPS) - -#define FP_NORM (1 << (FP_V_SIGN - 1)) /* normalized */ -#define FP_LOW (1 << FP_V_FR) -#define FP_RNDP (1 << (FP_V_FR - 1)) /* round for plus */ -#define FP_RNDM (FP_RNDP - 1) /* round for minus */ - -#define FPAB ((((uint32) AR) << 16) | ((uint32) BR)) - -#define DMASK32 0xFFFFFFFF - -/* Fraction shift; 0 < shift < 32 */ - -#define FR_ARS(v,s) (((v) >> (s)) | (((v) & FP_SIGN)? \ - (DMASK32 << (32 - (s))): 0)) & DMASK32 - -#define FR_NEG(v) ((~(v) + 1) & DMASK32) - -extern uint16 *M; -uint32 UnpackFP (struct ufp *fop, uint32 opnd); -void NegFP (struct ufp *fop); -void NormFP (struct ufp *fop); -uint32 StoreFP (struct ufp *fop); - -/* Floating to integer conversion */ - -uint32 f_fix (void) -{ -struct ufp fop; -uint32 res = 0; - -UnpackFP (&fop, FPAB); /* unpack op */ -if (fop.exp < 0) { /* exp < 0? */ - AR = 0; /* result = 0 */ - return 0; } /* B unchanged */ -if (fop.exp > 15) { /* exp > 15? */ - BR = AR; /* B has high bits */ - AR = 077777; /* result = 77777 */ - return 1; } /* overflow */ -if (fop.exp < 15) { /* if not aligned */ - res = FR_ARS (fop.fr, 15 - fop.exp); /* shift right */ - AR = (res >> 16) & DMASK; } /* AR gets result */ -BR = AR; -if ((AR & SIGN) && ((fop.fr | res) & DMASK)) /* any low bits lost? */ - AR = (AR + 1) & DMASK; /* round up */ -return 0; -} - -/* Integer to floating conversion */ - -uint32 f_flt (void) -{ -struct ufp res = { 15, 0 }; /* +, 2**15 */ - -res.fr = ((uint32) AR) << 16; /* left justify */ -StoreFP (&res); /* store result */ -return 0; /* clr overflow */ -} - -/* Floating point add/subtract */ - -uint32 f_as (uint32 opnd, t_bool sub) -{ -struct ufp fop1, fop2, t; -int32 ediff; - -UnpackFP (&fop1, FPAB); /* unpack A-B */ -UnpackFP (&fop2, opnd); /* get op */ -if (sub) { /* subtract? */ - fop2.fr = FR_NEG (fop2.fr); /* negate frac */ - if (fop2.fr == ((uint32) FP_SIGN)) { /* -1/2? */ - fop2.fr = fop2.fr >> 1; /* special case */ - fop2.exp = fop2.exp + 1; } } -if (fop1.fr == 0) fop1 = fop2; /* op1 = 0? res = op2 */ -else if (fop2.fr != 0) { /* op2 = 0? no add */ - if (fop1.exp < fop2.exp) { /* |op1| < |op2|? */ - t = fop2; /* swap operands */ - fop2 = fop1; - fop1 = t; } - ediff = fop1.exp - fop2.exp; /* get exp diff */ - if (ediff <= 24) { - if (ediff) fop2.fr = FR_ARS (fop2.fr, ediff); /* denorm, signed */ - if ((fop1.fr ^ fop2.fr) & FP_SIGN) /* unlike signs? */ - fop1.fr = fop1.fr + fop2.fr; /* eff subtract */ - else { /* like signs */ - fop1.fr = fop1.fr + fop2.fr; /* eff add */ - if (fop2.fr & FP_SIGN) { /* both -? */ - if ((fop1.fr & FP_SIGN) == 0) { /* overflow? */ - fop1.fr = FP_SIGN | (fop1.fr >> 1); /* renormalize */ - fop1.exp = fop1.exp + 1; } } /* incr exp */ - else if (fop1.fr & FP_SIGN) { /* both +, cry out? */ - fop1.fr = fop1.fr >> 1; /* renormalize */ - fop1.exp = fop1.exp + 1; } /* incr exp */ - } /* end else like */ - } /* end if ediff */ - } /* end if fop2 */ -return StoreFP (&fop1); /* store result */ -} - -/* Floating point multiply - passes diagnostic */ - -uint32 f_mul (uint32 opnd) -{ -struct ufp fop1, fop2; -struct ufp res = { 0, 0 }; -int32 shi1, shi2, t1, t2, t3, t4, t5; - -UnpackFP (&fop1, FPAB); /* unpack A-B */ -UnpackFP (&fop2, opnd); /* unpack op */ -if (fop1.fr && fop2.fr) { /* if both != 0 */ - res.exp = fop1.exp + fop2.exp + 1; /* exp = sum */ - shi1 = SEXT (fop1.fr >> 16); /* mpy hi */ - shi2 = SEXT (fop2.fr >> 16); /* mpc hi */ - t1 = shi2 * ((int32) ((fop1.fr >> 1) & 077600));/* mpc hi * (mpy lo/2) */ - t2 = shi1 * ((int32) ((fop2.fr >> 1) & 077600));/* mpc lo * (mpy hi/2) */ - t3 = t1 + t2; /* cross product */ - t4 = (shi1 * shi2) & ~1; /* mpy hi * mpc hi */ - t5 = (SEXT (t3 >> 16)) << 1; /* add in cross */ - res.fr = (t4 + t5) & DMASK32; } /* bit<0> is lost */ -return StoreFP (&res); /* store */ -} - -/* Floating point divide - reverse engineered from diagnostic */ - -uint32 divx (uint32 ba, uint32 dvr, uint32 *rem) -{ -int32 sdvd = 0, sdvr = 0; -uint32 q, r; - -if (ba & FP_SIGN) sdvd = 1; /* 32b/16b signed dvd */ -if (dvr & SIGN) sdvr = 1; /* use old-fashioned */ -if (sdvd) ba = (~ba + 1) & DMASK32; /* unsigned divides, */ -if (sdvr) dvr = (~dvr + 1) & DMASK; /* as results may ovflo */ -q = ba / dvr; -r = ba % dvr; -if (sdvd ^ sdvr) q = (~q + 1) & DMASK; -if (sdvd) r = (~r + 1) & DMASK; -if (rem) *rem = r; -return q; -} - -uint32 f_div (uint32 opnd) -{ -struct ufp fop1, fop2; -struct ufp quo = { 0, 0 }; -uint32 ba, q0, q1, q2, dvrh; - -UnpackFP (&fop1, FPAB); /* unpack A-B */ -UnpackFP (&fop2, opnd); /* unpack op */ -dvrh = (fop2.fr >> 16) & DMASK; /* high divisor */ -if (dvrh == 0) { /* div by zero? */ - AR = 0077777; /* return most pos */ - BR = 0177776; - return 1; } -if (fop1.fr) { /* dvd != 0? */ - quo.exp = fop1.exp - fop2.exp + 1; /* exp = diff */ - ba = FR_ARS (fop1.fr, 2); /* prevent ovflo */ - q0 = divx (ba, dvrh, &ba); /* Q0 = dvd / dvrh */ - ba = (ba & ~1) << 16; /* remainder */ - ba = FR_ARS (ba, 1); /* prevent ovflo */ - q1 = divx (ba, dvrh, NULL); /* Q1 = rem / dvrh */ - ba = (fop2.fr & 0xFF00) << 13; /* dvrl / 8 */ - q2 = divx (ba, dvrh, NULL); /* dvrl / dvrh */ - ba = -(SEXT (q2)) * (SEXT (q0)); /* -Q0 * Q2 */ - ba = (ba >> 16) & 0xFFFF; /* save ms half */ - if (q1 & SIGN) quo.fr = quo.fr - 0x00010000; /* Q1 < 0? -1 */ - if (ba & SIGN) quo.fr = quo.fr - 0x00010000; /* -Q0*Q2 < 0? */ - quo.fr = quo.fr + ((ba << 2) & 0xFFFF) + q1; /* rest prod, add Q1 */ - quo.fr = quo.fr << 1; /* shift result */ - quo.fr = quo.fr + (q0 << 16); /* add Q0 */ - } /* end if fop1.h */ -return StoreFP (&quo); /* store result */ -} - -/* Utility routines */ - -/* Unpack operand */ - -uint32 UnpackFP (struct ufp *fop, uint32 opnd) -{ -fop->fr = opnd & FP_FR; /* get frac */ -fop->exp = FP_GETEXP (opnd); /* get exp */ -if (FP_GETEXPS (opnd)) fop->exp = fop->exp | ~FP_M_EXP; /* < 0? sext */ -return FP_GETSIGN (opnd); /* return sign */ -} - -/* Normalize unpacked floating point number */ - -void NormFP (struct ufp *fop) -{ -if (fop->fr) { /* any fraction? */ - uint32 test = (fop->fr >> 1) & FP_NORM; - while ((fop->fr & FP_NORM) == test) { /* until norm */ - fop->exp = fop->exp - 1; - fop->fr = (fop->fr << 1); } } -else fop->exp = 0; /* clean 0 */ -return; -} - -/* Round fp number, store, generate overflow */ - -uint32 StoreFP (struct ufp *fop) -{ -uint32 sign, svfr, hi, ov = 0; - -NormFP (fop); /* normalize */ -svfr = fop->fr; /* save fraction */ -sign = FP_GETSIGN (fop->fr); /* save sign */ -fop->fr = (fop->fr + (sign? FP_RNDM: FP_RNDP)) & FP_FR; /* round */ -if ((fop->fr ^ svfr) & FP_SIGN) { /* sign change? */ - fop->fr = (fop->fr >> 1) | (sign? FP_SIGN: 0); /* renormalize */ - fop->exp = fop->exp + 1; } -if (fop->fr == 0) hi = 0; /* result 0? */ -else if (fop->exp < -(FP_M_EXP + 1)) { /* underflow? */ - hi = 0; /* store clean 0 */ - ov = 1; } -else if (fop->exp > FP_M_EXP) { /* overflow? */ - hi = 0x7FFFFFFE; /* all 1's */ - ov = 1; } -else hi = (fop->fr & FP_FR) | /* merge frac */ - ((fop->exp & FP_M_EXP) << FP_V_EXP) | /* and exp */ - ((fop->exp < 0)? (1 << FP_V_EXPS): 0); /* add exp sign */ -AR = (hi >> 16) & DMASK; -BR = hi & DMASK; -return ov; -} diff --git a/HP2100/hp2100_ipl.c b/HP2100/hp2100_ipl.c deleted file mode 100644 index ede40ccf..00000000 --- a/HP2100/hp2100_ipl.c +++ /dev/null @@ -1,476 +0,0 @@ -/* hp2100_ipl.c: HP 2000 interprocessor link simulator - - Copyright (c) 2002-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - ipli, iplo 12556B interprocessor link pair - - 09-May-03 RMS Added network device flag - 31-Jan-03 RMS Links are full duplex (found by Mike Gemeny) -*/ - -#include "hp2100_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" - -#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diagnostic mode */ -#define UNIT_V_ACTV (UNIT_V_UF + 1) /* making connection */ -#define UNIT_V_ESTB (UNIT_V_UF + 2) /* connection established */ -#define UNIT_V_HOLD (UNIT_V_UF + 3) /* character holding */ -#define UNIT_DIAG (1 << UNIT_V_DIAG) -#define UNIT_ACTV (1 << UNIT_V_ACTV) -#define UNIT_ESTB (1 << UNIT_V_ESTB) -#define UNIT_HOLD (1 << UNIT_V_HOLD) -#define IBUF buf /* input buffer */ -#define OBUF wait /* output buffer */ -#define DSOCKET u3 /* data socket */ -#define LSOCKET u4 /* listening socket */ - -extern uint32 PC; -extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; -extern FILE *sim_log; -int32 ipl_ptime = 400; /* polling interval */ -int32 ipl_stopioe = 0; /* stop on error */ -int32 ipl_hold[2] = { 0 }; /* holding character */ - -DEVICE ipli_dev, iplo_dev; -int32 ipliio (int32 inst, int32 IR, int32 dat); -int32 iploio (int32 inst, int32 IR, int32 dat); -int32 iplio (UNIT *uptr, int32 inst, int32 IR, int32 dat); -t_stat ipl_svc (UNIT *uptr); -t_stat ipl_reset (DEVICE *dptr); -t_stat ipl_attach (UNIT *uptr, char *cptr); -t_stat ipl_detach (UNIT *uptr); -t_stat ipl_boot (int32 unitno, DEVICE *dptr); -t_stat ipl_dscln (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat ipl_setdiag (UNIT *uptr, int32 val, char *cptr, void *desc); -t_bool ipl_check_conn (UNIT *uptr); - -/* IPLI data structures - - ipli_dev IPLI device descriptor - ipli_unit IPLI unit descriptor - ipli_reg IPLI register list -*/ - -DIB ipl_dib[] = { - { IPLI, 0, 0, 0, 0, &ipliio }, - { IPLO, 0, 0, 0, 0, &iploio } }; - -#define ipli_dib ipl_dib[0] -#define iplo_dib ipl_dib[1] - -UNIT ipl_unit[] = { - { UDATA (&ipl_svc, UNIT_ATTABLE, 0) }, - { UDATA (&ipl_svc, UNIT_ATTABLE, 0) } }; - -#define ipli_unit ipl_unit[0] -#define iplo_unit ipl_unit[1] - -REG ipli_reg[] = { - { ORDATA (IBUF, ipli_unit.IBUF, 16) }, - { ORDATA (OBUF, ipli_unit.OBUF, 16) }, - { FLDATA (CMD, ipli_dib.cmd, 0) }, - { FLDATA (CTL, ipli_dib.ctl, 0) }, - { FLDATA (FLG, ipli_dib.flg, 0) }, - { FLDATA (FBF, ipli_dib.fbf, 0) }, - { ORDATA (HOLD, ipl_hold[0], 8) }, - { DRDATA (TIME, ipl_ptime, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ipl_stopioe, 0) }, - { ORDATA (DEVNO, ipli_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB ipl_mod[] = { - { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", &ipl_setdiag }, - { UNIT_DIAG, 0, "link mode", "LINK", &ipl_setdiag }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "DISCONNECT", - &ipl_dscln, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &ipli_dev }, - { 0 } }; - -DEVICE ipli_dev = { - "IPLI", &ipli_unit, ipli_reg, ipl_mod, - 1, 10, 31, 1, 16, 16, - &tmxr_ex, &tmxr_dep, &ipl_reset, - &ipl_boot, &ipl_attach, &ipl_detach, - &ipli_dib, DEV_NET | DEV_DISABLE | DEV_DIS }; - -/* IPLO data structures - - iplo_dev IPLO device descriptor - iplo_unit IPLO unit descriptor - iplo_reg IPLO register list -*/ - -REG iplo_reg[] = { - { ORDATA (IBUF, iplo_unit.IBUF, 16) }, - { ORDATA (OBUF, iplo_unit.OBUF, 16) }, - { FLDATA (CMD, iplo_dib.cmd, 0) }, - { FLDATA (CTL, iplo_dib.ctl, 0) }, - { FLDATA (FLG, iplo_dib.flg, 0) }, - { FLDATA (FBF, iplo_dib.fbf, 0) }, - { ORDATA (HOLD, ipl_hold[1], 8) }, - { DRDATA (TIME, ipl_ptime, 24), PV_LEFT }, - { ORDATA (DEVNO, iplo_dib.devno, 6), REG_HRO }, - { NULL } }; - -DEVICE iplo_dev = { - "IPLO", &iplo_unit, iplo_reg, ipl_mod, - 1, 10, 31, 1, 16, 16, - &tmxr_ex, &tmxr_dep, &ipl_reset, - &ipl_boot, &ipl_attach, &ipl_detach, - &iplo_dib, DEV_NET | DEV_DISABLE | DEV_DIS }; - -/* Interprocessor link I/O routines */ - -int32 ipliio (int32 inst, int32 IR, int32 dat) -{ -return iplio (&ipli_unit, inst, IR, dat); -} - -int32 iploio (int32 inst, int32 IR, int32 dat) -{ -return iplio (&iplo_unit, inst, IR, dat); -} - -int32 iplio (UNIT *uptr, int32 inst, int32 IR, int32 dat) -{ -uint32 u, dev, odev; -int32 sta; -int8 msg[2]; - -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - uptr->OBUF = dat; - break; -case ioLIX: /* load */ - dat = uptr->IBUF; /* return val */ - break; -case ioMIX: /* merge */ - dat = dat | uptr->IBUF; /* get return data */ - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCMD (dev); /* clear ctl, cmd */ - clrCTL (dev); } - else { /* STC */ - setCMD (dev); /* set ctl, cmd */ - setCTL (dev); - if (uptr->flags & UNIT_ATT) { /* attached? */ - if ((uptr->flags & UNIT_ESTB) == 0) { /* established? */ - if (!ipl_check_conn (uptr)) /* not established? */ - return STOP_NOCONN; /* lose */ - uptr->flags = uptr->flags | UNIT_ESTB; } - msg[0] = (uptr->OBUF >> 8) & 0377; - msg[1] = uptr->OBUF & 0377; - sta = sim_write_sock (uptr->DSOCKET, msg, 2); - if (sta == SOCKET_ERROR) { - printf ("IPL: socket write error\n"); - return SCPE_IOERR; } - sim_os_sleep (0); } - else if (uptr->flags & UNIT_DIAG) { /* diagnostic mode? */ - u = (uptr - ipl_unit) ^ 1; /* find other device */ - ipl_unit[u].IBUF = uptr->OBUF; /* output to other */ - odev = ipl_dib[u].devno; /* other device no */ - setFLG (odev); } /* set other flag */ - else return SCPE_UNATT; } /* lose */ - break; -default: - break; } -if (IR & I_HC) { clrFLG (dev); } /* H/C option */ -return dat; -} - -/* Unit service - poll for input */ - -t_stat ipl_svc (UNIT *uptr) -{ -int32 u, nb, dev; -int8 msg[2]; - -u = uptr - ipl_unit; /* get link number */ -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* not attached? */ -sim_activate (uptr, ipl_ptime); /* reactivate */ -if ((uptr->flags & UNIT_ESTB) == 0) { /* not established? */ - if (!ipl_check_conn (uptr)) return SCPE_OK; /* check for conn */ - uptr->flags = uptr->flags | UNIT_ESTB; } -nb = sim_read_sock (uptr->DSOCKET, msg, ((uptr->flags & UNIT_HOLD)? 1: 2)); -if (nb < 0) { /* connection closed? */ - printf ("IPL: socket read error\n"); - return SCPE_IOERR; } -if (nb == 0) return SCPE_OK; /* no data? */ -if (uptr->flags & UNIT_HOLD) { /* holdover byte? */ - uptr->IBUF = (ipl_hold[u] << 8) | (((int32) msg[0]) & 0377); - uptr->flags = uptr->flags & ~UNIT_HOLD; } -else if (nb == 1) { - ipl_hold[u] = ((int32) msg[0]) & 0377; - uptr->flags = uptr->flags | UNIT_HOLD; } -else uptr->IBUF = ((((int32) msg[0]) & 0377) << 8) | - (((int32) msg[1]) & 0377); -dev = ipl_dib[u].devno; /* get device number */ -clrCMD (dev); /* clr cmd, set flag */ -setFLG (dev); -return SCPE_OK; -} - -t_bool ipl_check_conn (UNIT *uptr) -{ -SOCKET sock; - -if (uptr->flags & UNIT_ESTB) return TRUE; /* established? */ -if (uptr->flags & UNIT_ACTV) { /* active connect? */ - if (sim_check_conn (uptr->DSOCKET, 0) <= 0) return FALSE; } -else { sock = sim_accept_conn (uptr->LSOCKET, NULL); /* poll connect */ - if (sock == INVALID_SOCKET) return FALSE; /* got a live one? */ - uptr->DSOCKET = sock; } /* save data socket */ -uptr->flags = uptr->flags | UNIT_ESTB; /* conn established */ -return TRUE; -} - -/* Reset routine */ - -t_stat ipl_reset (DEVICE *dptr) -{ -DIB *dibp = (DIB *) dptr->ctxt; -UNIT *uptr = dptr->units; - -hp_enbdis_pair (&ipli_dev, &iplo_dev); /* make pair cons */ -dibp->cmd = dibp->ctl = 0; /* clear cmd, ctl */ -dibp->flg = dibp->fbf = 1; /* set flg, fbf */ -uptr->IBUF = uptr->OBUF = 0; /* clr buffers */ -if (uptr->flags & UNIT_ATT) sim_activate (uptr, ipl_ptime); -else sim_cancel (uptr); /* deactivate unit */ -uptr->flags = uptr->flags & ~UNIT_HOLD; -return SCPE_OK; -} - -/* Attach routine - - attach -l - listen for connection on port - attach -c - connect to ip address and port -*/ - -t_stat ipl_attach (UNIT *uptr, char *cptr) -{ -extern int32 sim_switches; -SOCKET newsock; -uint32 i, t, ipa, ipp, oldf; -char *tptr; -t_stat r; - -r = get_ipaddr (cptr, &ipa, &ipp); -if ((r != SCPE_OK) || (ipp == 0)) return SCPE_ARG; -oldf = uptr->flags; -if (oldf & UNIT_ATT) ipl_detach (uptr); -if ((sim_switches & SWMASK ('C')) || - ((sim_switches & SIM_SW_REST) && (oldf & UNIT_ACTV))) { - if (ipa == 0) ipa = 0x7F000001; - newsock = sim_connect_sock (ipa, ipp); - if (newsock == INVALID_SOCKET) return SCPE_IOERR; - printf ("Connecting to IP address %d.%d.%d.%d, port %d\n", - (ipa >> 24) & 0xff, (ipa >> 16) & 0xff, - (ipa >> 8) & 0xff, ipa & 0xff, ipp); - if (sim_log) fprintf (sim_log, - "Connecting to IP address %d.%d.%d.%d, port %d\n", - (ipa >> 24) & 0xff, (ipa >> 16) & 0xff, - (ipa >> 8) & 0xff, ipa & 0xff, ipp); - uptr->flags = uptr->flags | UNIT_ACTV; - uptr->LSOCKET = 0; - uptr->DSOCKET = newsock; } -else { if (ipa != 0) return SCPE_ARG; - newsock = sim_master_sock (ipp); - if (newsock == INVALID_SOCKET) return SCPE_IOERR; - printf ("Listening on port %d\n", ipp); - if (sim_log) fprintf (sim_log, "Listening on port %d\n", ipp); - uptr->flags = uptr->flags & ~UNIT_ACTV; - uptr->LSOCKET = newsock; - uptr->DSOCKET = 0; } -uptr->IBUF = uptr->OBUF = 0; -uptr->flags = (uptr->flags | UNIT_ATT) & ~(UNIT_ESTB | UNIT_HOLD); -tptr = malloc (strlen (cptr) + 1); /* get string buf */ -if (tptr == NULL) { /* no memory? */ - ipl_detach (uptr); /* close sockets */ - return SCPE_MEM; } -strcpy (tptr, cptr); /* copy ipaddr:port */ -uptr->filename = tptr; /* save */ -sim_activate (uptr, ipl_ptime); /* activate poll */ -if (sim_switches & SWMASK ('W')) { /* wait? */ - for (i = 0; i < 30; i++) { /* check for 30 sec */ - if (t = ipl_check_conn (uptr)) break; /* established? */ - if ((i % 10) == 0) /* status every 10 sec */ - printf ("Waiting for connnection\n"); - sim_os_sleep (1); } /* sleep 1 sec */ - if (t) printf ("Connection established\n"); } -return SCPE_OK; -} - -/* Detach routine */ - -t_stat ipl_detach (UNIT *uptr) -{ -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ -if (uptr->flags & UNIT_ACTV) sim_close_sock (uptr->DSOCKET, 1); -else { if (uptr->flags & UNIT_ESTB) /* if established, */ - sim_close_sock (uptr->DSOCKET, 0); /* close data socket */ - sim_close_sock (uptr->LSOCKET, 1); } /* closen listen socket */ -free (uptr->filename); /* free string */ -uptr->filename = NULL; -uptr->LSOCKET = 0; -uptr->DSOCKET = 0; -uptr->flags = uptr->flags & ~(UNIT_ATT | UNIT_ACTV | UNIT_ESTB); -sim_cancel (uptr); /* don't poll */ -return SCPE_OK; -} - -/* Disconnect routine */ - -t_stat ipl_dscln (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -if (((uptr->flags & UNIT_ATT) == 0) || (uptr->flags & UNIT_ACTV) || - ((uptr->flags & UNIT_ESTB) == 0)) return SCPE_NOFNC; -sim_close_sock (uptr->DSOCKET, 0); -uptr->DSOCKET = 0; -uptr->flags = uptr->flags & ~UNIT_ESTB; -return SCPE_OK; -} - -/* Diagnostic/normal mode routine */ - -t_stat ipl_setdiag (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (val) { - ipli_unit.flags = ipli_unit.flags | UNIT_DIAG; - iplo_unit.flags = iplo_unit.flags | UNIT_DIAG; } -else { ipli_unit.flags = ipli_unit.flags & ~UNIT_DIAG; - iplo_unit.flags = iplo_unit.flags & ~UNIT_DIAG; } -return SCPE_OK; -} - -/* Interprocessor link bootstrap routine (HP Access Manual) */ - -#define LDR_BASE 073 -#define IPL_PNTR 074 -#define PTR_PNTR 075 -#define IPL_DEVA 076 -#define PTR_DEVA 077 - -static const int32 pboot[IBL_LNT] = { - 0163774, /*BBL LDA ICK,I ; IPL sel code */ - 0027751, /* JMP CFG ; go configure */ - 0107700, /*ST CLC 0,C ; intr off */ - 0002702, /* CLA,CCE,SZA ; skip in */ - 0063772, /*CN LDA M26 ; feed frame */ - 0002307, /*EOC CCE,INA,SZA,RSS ; end of file? */ - 0027760, /* JMP EOT ; yes */ - 0017736, /* JSB READ ; get #char */ - 0007307, /* CMB,CCE,INB,SZB,RSS ; 2's comp; null? */ - 0027705, /* JMP EOC ; read next */ - 0077770, /* STB WC ; word in rec */ - 0017736, /* JSB READ ; get feed frame */ - 0017736, /* JSB READ ; get address */ - 0074000, /* STB 0 ; init csum */ - 0077771, /* STB AD ; save addr */ - 0067771, /*CK LDB AD ; check addr */ - 0047773, /* ADB MAXAD ; below loader */ - 0002040, /* SEZ ; E =0 => OK */ - 0102055, /* HLT 55 */ - 0017736, /* JSB READ ; get word */ - 0040001, /* ADA 1 ; cont checksum */ - 0177771, /* STB AD,I ; store word */ - 0037771, /* ISZ AD */ - 0000040, /* CLE ; force wd read */ - 0037770, /* ISZ WC ; block done? */ - 0027717, /* JMP CK ; no */ - 0017736, /* JSB READ ; get checksum */ - 0054000, /* CPB 0 ; ok? */ - 0027704, /* JMP CN ; next block */ - 0102011, /* HLT 11 ; bad csum */ - 0000000, /*RD 0 */ - 0006600, /* CLB,CME ; E reg byte ptr */ - 0103700, /*IO1 STC RDR,C ; start reader */ - 0102300, /*IO2 SFS RDR ; wait */ - 0027741, /* JMP *-1 */ - 0106400, /*IO3 MIB RDR ; get byte */ - 0002041, /* SEZ,RSS ; E set? */ - 0127736, /* JMP RD,I ; no, done */ - 0005767, /* BLF,CLE,BLF ; shift byte */ - 0027740, /* JMP IO1 ; again */ - 0163775, /* LDA PTR,I ; get ptr code */ - 0043765, /*CFG ADA SFS ; config IO */ - 0073741, /* STA IO2 */ - 0043766, /* ADA STC */ - 0073740, /* STA IO1 */ - 0043767, /* ADA MIB */ - 0073743, /* STA IO3 */ - 0027702, /* JMP ST */ - 0063777, /*EOT LDA PSC ; put select codes */ - 0067776, /* LDB ISC ; where xloader wants */ - 0102077, /* HLT 77 */ - 0027702, /* JMP ST */ - 0000000, /* NOP */ - 0102300, /*SFS SFS 0 */ - 0001400, /*STC 1400 */ - 0002500, /*MIB 2500 */ - 0000000, /*WC 0 */ - 0000000, /*AD 0 */ - 0177746, /*M26 -26 */ - 0000000, /*MAX -BBL */ - 0007776, /*ICK ISC */ - 0007777, /*PTR IPT */ - 0000000, /*ISC 0 */ - 0000000 /*IPT 0 */ -}; - -t_stat ipl_boot (int32 unitno, DEVICE *dptr) -{ -int32 i, devi, devp; -extern DIB ptr_dib; -extern UNIT cpu_unit; -extern uint32 SR; -extern uint16 *M; - -devi = ipli_dib.devno; /* get device no */ -devp = ptr_dib.devno; -PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */ -SR = (devi << IBL_V_DEV) | devp; /* set SR */ -for (i = 0; i < IBL_LNT; i++) M[PC + i] = pboot[i]; /* copy bootstrap */ -M[PC + LDR_BASE] = (~PC + 1) & DMASK; /* fix ups */ -M[PC + IPL_PNTR] = M[PC + IPL_PNTR] | PC; -M[PC + PTR_PNTR] = M[PC + PTR_PNTR] | PC; -M[PC + IPL_DEVA] = devi; -M[PC + PTR_DEVA] = devp; -return SCPE_OK; -} - diff --git a/HP2100/hp2100_lps.c b/HP2100/hp2100_lps.c deleted file mode 100644 index cca3e6ed..00000000 --- a/HP2100/hp2100_lps.c +++ /dev/null @@ -1,176 +0,0 @@ -/* hp2100_lps.c: HP 2100 12653A line printer simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - lps 12653A 2767 line printer - (based on 12556B microcircuit interface) - - 25-Apr-03 RMS Revised for extended file support - 24-Oct-02 RMS Added microcircuit test features - 30-May-02 RMS Widened POS to 32b - 03-Dec-01 RMS Changed DEVNO to use extended SET/SHOW - 07-Sep-01 RMS Moved function prototypes - 21-Nov-00 RMS Fixed flag, fbf power up state - Added command flop - 15-Oct-00 RMS Added variable device number support -*/ - -#include "hp2100_defs.h" - -#define LPS_BUSY 0000001 /* busy */ -#define LPS_NRDY 0100000 /* not ready */ -#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diagnostic mode */ -#define UNIT_DIAG (1 << UNIT_V_DIAG) - -extern uint32 PC; -extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; -int32 lps_ctime = 1000; /* char time */ -int32 lps_stopioe = 0; /* stop on error */ -int32 lps_sta = 0; - -DEVICE lps_dev; -int32 lpsio (int32 inst, int32 IR, int32 dat); -t_stat lps_svc (UNIT *uptr); -t_stat lps_reset (DEVICE *dptr); - -/* LPS data structures - - lps_dev LPS device descriptor - lps_unit LPS unit descriptor - lps_reg LPS register list -*/ - -DIB lps_dib = { LPS, 0, 0, 0, 0, &lpsio }; - -UNIT lps_unit = { - UDATA (&lps_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lps_reg[] = { - { ORDATA (BUF, lps_unit.buf, 16) }, - { ORDATA (STA, lps_sta, 16) }, - { FLDATA (CMD, lps_dib.cmd, 0) }, - { FLDATA (CTL, lps_dib.ctl, 0) }, - { FLDATA (FLG, lps_dib.flg, 0) }, - { FLDATA (FBF, lps_dib.fbf, 0) }, - { DRDATA (POS, lps_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (CTIME, lps_ctime, 31), PV_LEFT }, - { DRDATA (PTIME, lps_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lps_stopioe, 0) }, - { ORDATA (DEVNO, lps_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB lps_mod[] = { - { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL }, - { UNIT_DIAG, 0, "printer mode", "PRINTER", NULL }, - { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &lps_dev }, - { 0 } }; - -DEVICE lps_dev = { - "LPS", &lps_unit, lps_reg, lps_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lps_reset, - NULL, NULL, NULL, - &lps_dib, DEV_DISABLE | DEV_DIS }; - -/* Line printer IOT routine */ - -int32 lpsio (int32 inst, int32 IR, int32 dat) -{ -int32 dev; - -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - lps_unit.buf = dat; - break; -case ioLIX: /* load */ - dat = 0; /* default sta = 0 */ -case ioMIX: /* merge */ - if ((lps_unit.flags & UNIT_DIAG) == 0) { /* real lpt? */ - lps_sta = 0; /* create status */ - if ((lps_unit.flags & UNIT_ATT) == 0) - lps_sta = lps_sta | LPS_BUSY | LPS_NRDY; - else if (sim_is_active (&lps_unit)) - lps_sta = lps_sta | LPS_BUSY; } - dat = dat | lps_sta; /* diag, rtn status */ - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCMD (dev); /* clear ctl, cmd */ - clrCTL (dev); } - else { /* STC */ - setCMD (dev); /* set ctl, cmd */ - setCTL (dev); - if (lps_unit.flags & UNIT_DIAG) /* diagnostic? */ - sim_activate (&lps_unit, 1); /* loop back */ - else sim_activate (&lps_unit, /* real lpt, sched */ - (lps_unit.buf < 040)? lps_unit.wait: lps_ctime); } - break; -default: - break; } -if (IR & I_HC) { clrFLG (dev); } /* H/C option */ -return dat; -} - -t_stat lps_svc (UNIT *uptr) -{ -int32 dev; -int32 c = lps_unit.buf & 0177; - -dev = lps_dib.devno; /* get dev no */ -clrCMD (dev); /* clear cmd */ -setFLG (dev); /* set flag, fbf */ -if (lps_unit.flags & UNIT_DIAG) { /* diagnostic? */ - lps_sta = lps_unit.buf; /* loop back */ - return SCPE_OK; } /* done */ -if ((lps_unit.flags & UNIT_ATT) == 0) /* real lpt, att? */ - return IORETURN (lps_stopioe, SCPE_UNATT); -if (fputc (c, lps_unit.fileref) == EOF) { - perror ("LPS I/O error"); - clearerr (lps_unit.fileref); - return SCPE_IOERR; } -lps_unit.pos = lps_unit.pos + 1; /* update pos */ -return SCPE_OK; -} - -/* Reset routine - called from SCP, flags in DIB */ - -t_stat lps_reset (DEVICE *dptr) -{ -lps_dib.cmd = lps_dib.ctl = 0; /* clear cmd, ctl */ -lps_dib.flg = lps_dib.fbf = 1; /* set flg, fbf */ -lps_sta = lps_unit.buf = 0; -sim_cancel (&lps_unit); /* deactivate unit */ -return SCPE_OK; -} diff --git a/HP2100/hp2100_lpt.c b/HP2100/hp2100_lpt.c deleted file mode 100644 index bd7bba70..00000000 --- a/HP2100/hp2100_lpt.c +++ /dev/null @@ -1,194 +0,0 @@ -/* hp2100_lpt.c: HP 2100 12845A line printer simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - lpt 12845A line printer - - 25-Apr-03 RMS Revised for extended file support - 24-Oct-02 RMS Cloned from 12653A -*/ - -#include "hp2100_defs.h" - -#define LPT_PAGELNT 60 /* page length */ - -#define LPT_NBSY 0000001 /* not busy */ -#define LPT_PAPO 0040000 /* paper out */ -#define LPT_RDY 0100000 /* ready */ - -#define LPT_CTL 0100000 /* control output */ -#define LPT_CHAN 0000100 /* skip to chan */ -#define LPT_SKIPM 0000077 /* line count mask */ -#define LPT_CHANM 0000007 /* channel mask */ - -extern uint32 PC; -extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; -int32 lpt_ctime = 1000; /* char time */ -int32 lpt_stopioe = 0; /* stop on error */ -int32 lpt_lcnt = 0; /* line count */ -static int32 lpt_cct[8] = { - 1, 1, 1, 2, 3, LPT_PAGELNT/2, LPT_PAGELNT/4, LPT_PAGELNT/6 }; - -DEVICE lpt_dev; -int32 lptio (int32 inst, int32 IR, int32 dat); -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); -t_stat lpt_attach (UNIT *uptr, char *cptr); - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list -*/ - -DIB lpt_dib = { LPT, 0, 0, 0, 0, &lptio }; - -UNIT lpt_unit = { - UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lpt_reg[] = { - { ORDATA (BUF, lpt_unit.buf, 7) }, - { FLDATA (CMD, lpt_dib.cmd, 0) }, - { FLDATA (CTL, lpt_dib.ctl, 0) }, - { FLDATA (FLG, lpt_dib.flg, 0) }, - { FLDATA (FBF, lpt_dib.fbf, 0) }, - { DRDATA (LCNT, lpt_lcnt, 7) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (CTIME, lpt_ctime, 31), PV_LEFT }, - { DRDATA (PTIME, lpt_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lpt_stopioe, 0) }, - { ORDATA (DEVNO, lpt_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB lpt_mod[] = { - { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &lpt_dev }, - { 0 } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, lpt_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lpt_reset, - NULL, &lpt_attach, NULL, - &lpt_dib, DEV_DISABLE }; - -/* Line printer IOT routine */ - -int32 lptio (int32 inst, int32 IR, int32 dat) -{ -int32 dev; - -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - lpt_unit.buf = dat & (LPT_CTL | 0177); - break; -case ioLIX: /* load */ - dat = 0; /* default sta = 0 */ -case ioMIX: /* merge */ - if (lpt_unit.flags & UNIT_ATT) { - dat = dat | LPT_RDY; - if (!sim_is_active (&lpt_unit)) - dat = dat | LPT_NBSY; } - else dat = dat | LPT_PAPO; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCMD (dev); /* clear ctl, cmd */ - clrCTL (dev); } - else { /* STC */ - setCMD (dev); /* set ctl, cmd */ - setCTL (dev); - sim_activate (&lpt_unit, /* schedule op */ - (lpt_unit.buf & LPT_CTL)? lpt_unit.wait: lpt_ctime); } - break; -default: - break; } -if (IR & I_HC) { clrFLG (dev); } /* H/C option */ -return dat; -} - -t_stat lpt_svc (UNIT *uptr) -{ -int32 i, skip, chan, dev; - -dev = lpt_dib.devno; /* get dev no */ -clrCMD (dev); /* clear cmd */ -if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); -setFLG (dev); /* set flag, fbf */ -if (uptr->buf & LPT_CTL) { /* control word? */ - if (uptr->buf & LPT_CHAN) { - chan = uptr->buf & LPT_CHANM; - if (chan == 0) { /* top of form? */ - fputc ('\f', uptr->fileref); /* ffeed */ - lpt_lcnt = 0; /* reset line cnt */ - skip = 1; } - else if (chan == 1) skip = LPT_PAGELNT - lpt_lcnt - 1; - else skip = lpt_cct[chan] - (lpt_lcnt % lpt_cct[chan]); - } - else { - skip = uptr->buf & LPT_SKIPM; - if (skip == 0) fputc ('\r', uptr->fileref); - } - for (i = 0; i < skip; i++) fputc ('\n', uptr->fileref); - lpt_lcnt = (lpt_lcnt + skip) % LPT_PAGELNT; - } -else fputc (uptr->buf & 0177, uptr->fileref); /* no, just add char */ -if (ferror (uptr->fileref)) { - perror ("LPT I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -lpt_unit.pos = ftell (uptr->fileref); /* update pos */ -return SCPE_OK; -} - -/* Reset routine - called from SCP, flags in DIB */ - -t_stat lpt_reset (DEVICE *dptr) -{ -lpt_dib.cmd = lpt_dib.ctl = 0; /* clear cmd, ctl */ -lpt_dib.flg = lpt_dib.fbf = 1; /* set flg, fbf */ -lpt_unit.buf = 0; -sim_cancel (&lpt_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Attach routine */ - -t_stat lpt_attach (UNIT *uptr, char *cptr) -{ -lpt_lcnt = 0; /* top of form */ -return attach_unit (uptr, cptr); -} diff --git a/HP2100/hp2100_ms.c b/HP2100/hp2100_ms.c deleted file mode 100644 index e607cc88..00000000 --- a/HP2100/hp2100_ms.c +++ /dev/null @@ -1,672 +0,0 @@ -/* hp2100_ms.c: HP 2100 13181A/13183A magnetic tape simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - ms 13181A 7970B 800bpi nine track magnetic tape - 13183A 7970E 1600bpi nine track magnetic tape - - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Revised for magtape library - 18-Oct-02 RMS Added BOOT command, added 13183A support - 30-Sep-02 RMS Revamped error handling - 29-Aug-02 RMS Added end of medium support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Added maximum record length test - - Magnetic tapes are represented as a series of variable records - of the form: - - 32b byte count - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32b byte count - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a byte count of 0. - - Unusually among HP peripherals, the 12559 does not have a command flop, - and its flag and flag buffer power up as clear rather than set. -*/ - -#include "hp2100_defs.h" -#include "sim_tape.h" - -#define MS_NUMDR 4 /* number of drives */ -#define DB_N_SIZE 16 /* max data buf */ -#define DBSIZE (1 << DB_N_SIZE) /* max data cmd */ -#define FNC u3 /* function */ -#define UST u4 /* unit status */ - -/* Command - msc_fnc */ - -#define FNC_CLR 00110 /* clear */ -#define FNC_GAP 00015 /* write gap */ -#define FNC_GFM 00215 /* gap+file mark */ -#define FNC_RC 00023 /* read */ -#define FNC_WC 00031 /* write */ -#define FNC_FSR 00003 /* forward space */ -#define FNC_BSR 00041 /* backward space */ -#define FNC_FSF 00203 /* forward file */ -#define FNC_BSF 00241 /* backward file */ -#define FNC_REW 00101 /* rewind */ -#define FNC_RWS 00105 /* rewind and offline */ -#define FNC_WFM 00211 /* write file mark */ -#define FNC_RFF 00223 /* "read file fwd" */ -#define FNC_V_SEL 9 /* select */ -#define FNC_M_SEL 017 -#define FNC_GETSEL(x) (((x) >> FNC_V_SEL) & FNC_M_SEL) - -#define FNF_MOT 00001 /* motion */ -#define FNF_OFL 00004 -#define FNF_WRT 00010 /* write */ -#define FNF_REV 00040 /* reverse */ -#define FNF_RWD 00100 /* rewind */ -#define FNF_CHS 00400 /* change select */ - -/* Status - stored in msc_sta, unit.UST (u), or dynamic (d) */ - -#define STA_PE 0100000 /* 1600 bpi (d) */ -#define STA_V_SEL 13 /* unit sel (d) */ -#define STA_M_SEL 03 -#define STA_SEL (STA_M_SEL << STA_V_SEL) -#define STA_ODD 0004000 /* odd bytes */ -#define STA_REW 0002000 /* rewinding (u) */ -#define STA_TBSY 0001000 /* transport busy (d) */ -#define STA_BUSY 0000400 /* ctrl busy */ -#define STA_EOF 0000200 /* end of file */ -#define STA_BOT 0000100 /* beg of tape (u) */ -#define STA_EOT 0000040 /* end of tape (u) */ -#define STA_TIM 0000020 /* timing error */ -#define STA_REJ 0000010 /* programming error */ -#define STA_WLK 0000004 /* write locked (d) */ -#define STA_PAR 0000002 /* parity error */ -#define STA_LOCAL 0000001 /* local (d) */ -#define STA_DYN (STA_PE|STA_SEL|STA_TBSY|STA_WLK|STA_LOCAL) - -extern uint16 *M; -extern uint32 PC, SR; -extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; -extern int32 sim_switches; -extern UNIT cpu_unit; - -int32 ms_ctype = 0; /* ctrl type */ -int32 msc_sta = 0; /* status */ -int32 msc_buf = 0; /* buffer */ -int32 msc_usl = 0; /* unit select */ -int32 msc_1st = 0; -int32 msc_ctime = 1000; /* command wait */ -int32 msc_gtime = 1000; /* gap stop time */ -int32 msc_rtime = 1000; /* rewind wait */ -int32 msc_xtime = 15; /* data xfer time */ -int32 msc_stopioe = 1; /* stop on error */ -int32 msd_buf = 0; /* data buffer */ -uint8 msxb[DBSIZE] = { 0 }; /* data buffer */ -t_mtrlnt ms_ptr = 0, ms_max = 0; /* buffer ptrs */ - -DEVICE msd_dev, msc_dev; -int32 msdio (int32 inst, int32 IR, int32 dat); -int32 mscio (int32 inst, int32 IR, int32 dat); -t_stat msc_svc (UNIT *uptr); -t_stat msc_reset (DEVICE *dptr); -t_stat msc_attach (UNIT *uptr, char *cptr); -t_stat msc_detach (UNIT *uptr); -t_stat msc_boot (int32 unitno, DEVICE *dptr); -t_stat ms_map_err (UNIT *uptr, t_stat st); -t_stat ms_settype (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat ms_showtype (FILE *st, UNIT *uptr, int32 val, void *desc); - -/* MSD data structures - - msd_dev MSD device descriptor - msd_unit MSD unit list - msd_reg MSD register list -*/ - -DIB ms_dib[] = { - { MSD, 0, 0, 0, 0, &msdio }, - { MSC, 0, 0, 0, 0, &mscio } }; - -#define msd_dib ms_dib[0] -#define msc_dib ms_dib[1] - -UNIT msd_unit = { UDATA (NULL, 0, 0) }; - -REG msd_reg[] = { - { ORDATA (BUF, msd_buf, 16) }, - { FLDATA (CMD, msd_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, msd_dib.ctl, 0) }, - { FLDATA (FLG, msd_dib.flg, 0) }, - { FLDATA (FBF, msd_dib.fbf, 0) }, - { BRDATA (DBUF, msxb, 8, 8, DBSIZE) }, - { DRDATA (BPTR, ms_ptr, DB_N_SIZE + 1) }, - { DRDATA (BMAX, ms_max, DB_N_SIZE + 1) }, - { ORDATA (DEVNO, msd_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB msd_mod[] = { - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &msd_dev }, - { 0 } }; - -DEVICE msd_dev = { - "MSD", &msd_unit, msd_reg, msd_mod, - 1, 10, DB_N_SIZE, 1, 8, 8, - NULL, NULL, &msc_reset, - NULL, NULL, NULL, - &msd_dib, 0 }; - -/* MSC data structures - - msc_dev MSC device descriptor - msc_unit MSC unit list - msc_reg MSC register list - msc_mod MSC modifier list -*/ - -UNIT msc_unit[] = { - { UDATA (&msc_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, - { UDATA (&msc_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, - { UDATA (&msc_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, - { UDATA (&msc_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) } }; - -REG msc_reg[] = { - { ORDATA (STA, msc_sta, 12) }, - { ORDATA (BUF, msc_buf, 16) }, - { ORDATA (USEL, msc_usl, 2) }, - { FLDATA (FSVC, msc_1st, 0) }, - { FLDATA (CMD, msc_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, msc_dib.ctl, 0) }, - { FLDATA (FLG, msc_dib.flg, 0) }, - { FLDATA (FBF, msc_dib.fbf, 0) }, - { URDATA (POS, msc_unit[0].pos, 10, T_ADDR_W, 0, MS_NUMDR, PV_LEFT) }, - { URDATA (FNC, msc_unit[0].FNC, 8, 8, 0, MS_NUMDR, REG_HRO) }, - { URDATA (UST, msc_unit[0].UST, 8, 12, 0, MS_NUMDR, REG_HRO) }, - { DRDATA (CTIME, msc_ctime, 24), REG_NZ + PV_LEFT }, - { DRDATA (GTIME, msc_gtime, 24), REG_NZ + PV_LEFT }, - { DRDATA (RTIME, msc_rtime, 24), REG_NZ + PV_LEFT }, - { DRDATA (XTIME, msc_xtime, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, msc_stopioe, 0) }, - { FLDATA (CTYPE, ms_ctype, 0), REG_HRO }, - { ORDATA (DEVNO, msc_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB msc_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "13181A", - &ms_settype, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "13183A", - &ms_settype, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL, - NULL, &ms_showtype, NULL }, - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &msd_dev }, - { 0 } }; - -DEVICE msc_dev = { - "MSC", msc_unit, msc_reg, msc_mod, - MS_NUMDR, 10, 31, 1, 8, 8, - NULL, NULL, &msc_reset, - &msc_boot, &msc_attach, &msc_detach, - &msc_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 msdio (int32 inst, int32 IR, int32 dat) -{ -int32 devd; - -devd = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (devd); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - msd_buf = dat; /* store data */ - break; -case ioMIX: /* merge */ - dat = dat | msd_buf; - break; -case ioLIX: /* load */ - dat = msd_buf; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCTL (devd); /* clr ctl, cmd */ - clrCMD (devd); } - else { /* STC */ - setCTL (devd); /* set ctl, cmd */ - setCMD (devd); } - break; -default: - break; } -if (IR & I_HC) { clrFLG (devd); } /* H/C option */ -return dat; -} - -int32 mscio (int32 inst, int32 IR, int32 dat) -{ -int32 i, devc, devd; -t_stat st; -UNIT *uptr = msc_dev.units + msc_usl; -static const uint8 map_sel[16] = { - 0, 0, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3 }; - -devc = IR & I_DEVMASK; /* get device no */ -devd = devc - 1; -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (devc); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - msc_buf = dat; - msc_sta = msc_sta & ~STA_REJ; /* clear reject */ - if ((dat & 0377) == FNC_CLR) break; /* clear always ok */ - if (msc_sta & STA_BUSY) { /* busy? reject */ - msc_sta = msc_sta | STA_REJ; /* dont chg select */ - break; } - if (dat & FNF_CHS) { /* select change */ - msc_usl = map_sel[FNC_GETSEL (dat)]; /* is immediate */ - uptr = msc_dev.units + msc_usl; } - if (((dat & FNF_MOT) && sim_is_active (uptr)) || - ((dat & FNF_REV) && (uptr->UST & STA_BOT)) || - ((dat & FNF_WRT) && sim_tape_wrp (uptr))) - msc_sta = msc_sta | STA_REJ; /* reject? */ - break; -case ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - dat = dat | ((msc_sta | uptr->UST) & ~STA_DYN); - if (uptr->flags & UNIT_ATT) { /* online? */ - if (sim_is_active (uptr)) /* busy */ - dat = dat | STA_TBSY; - if (sim_tape_wrp (uptr)) /* write prot? */ - dat = dat | STA_WLK; } - else dat = dat | STA_TBSY | STA_LOCAL; - if (ms_ctype) dat = dat | STA_PE | /* 13183A? */ - (msc_usl << STA_V_SEL); - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { clrCTL (devc); } /* CLC */ - else { /* STC */ - if ((msc_buf & 0377) == FNC_CLR) { /* clear? */ - for (i = 0; i < MS_NUMDR; i++) { /* loop thru units */ - if (sim_is_active (&msc_unit[i]) && /* write in prog? */ - (msc_unit[i].FNC == FNC_WC) && (ms_ptr > 0)) { - if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr | MTR_ERF)) - ms_map_err (uptr, st); } - if ((msc_unit[i].UST & STA_REW) == 0) - sim_cancel (&msc_unit[i]); } /* stop if now rew */ - clrCTL (devc); /* init device */ - setFLG (devc); - clrCTL (devd); - setFLG (devd); - msc_sta = msd_buf = msc_buf = msc_1st = 0; - return SCPE_OK; } - uptr->FNC = msc_buf & 0377; /* save function */ - if (uptr->FNC & FNF_RWD) /* rewind? */ - sim_activate (uptr, msc_rtime); /* fast response */ - else sim_activate (uptr, msc_ctime); /* schedule op */ - uptr->UST = 0; /* clear status */ - msc_sta = STA_BUSY; /* ctrl is busy */ - msc_1st = 1; - setCTL (devc); } /* go */ - break; -default: - break; } -if (IR & I_HC) { clrFLG (devc); } /* H/C option */ -return dat; -} - -/* Unit service - - If rewind done, reposition to start of tape, set status - else, do operation, set done, interrupt - - Can't be write locked, can only write lock detached unit -*/ - -t_stat msc_svc (UNIT *uptr) -{ -int32 devc, devd; -t_mtrlnt tbc; -t_stat st, r = SCPE_OK; - -devc = msc_dib.devno; /* get device nos */ -devd = msd_dib.devno; - -if ((uptr->flags & UNIT_ATT) == 0) { /* offline? */ - msc_sta = (msc_sta | STA_REJ) & ~STA_BUSY; /* reject */ - setFLG (devc); /* set cch flg */ - return IORETURN (msc_stopioe, SCPE_UNATT); } - -switch (uptr->FNC) { /* case on function */ -case FNC_REW: /* rewind */ -case FNC_RWS: /* rewind offline */ - if (uptr->UST & STA_REW) { /* rewind in prog? */ - sim_tape_rewind (uptr); /* done */ - uptr->UST = STA_BOT; /* set BOT status */ - if (uptr->FNC & FNF_OFL) detach_unit (uptr); - return SCPE_OK; } - uptr->UST = STA_REW; /* set rewinding */ - sim_activate (uptr, msc_ctime); /* sched completion */ - break; /* "done" */ - -case FNC_GFM: /* gap file mark */ -case FNC_WFM: /* write file mark */ - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = ms_map_err (uptr, st); /* map error */ - msc_sta = STA_EOF; /* set EOF status */ - break; - -case FNC_GAP: /* erase gap */ - break; - -case FNC_FSR: /* space forward */ - if (st = sim_tape_sprecf (uptr, &tbc)) /* space rec fwd, err? */ - r = ms_map_err (uptr, st); /* map error */ - if (tbc & 1) msc_sta = msc_sta | STA_ODD; - else msc_sta = msc_sta & ~STA_ODD; - break; - -case FNC_BSR: - if (st = sim_tape_sprecr (uptr, &tbc)) /* space rec rev, err? */ - r = ms_map_err (uptr, st); /* map error */ - if (tbc & 1) msc_sta = msc_sta | STA_ODD; - else msc_sta = msc_sta & ~STA_ODD; - break; - -case FNC_FSF: - while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ; - if (st == MTSE_TMK) /* stopped by tmk? */ - msc_sta = msc_sta | STA_EOF | STA_ODD; /* normal status */ - else r = ms_map_err (uptr, st); /* map error */ - break; - -case FNC_BSF: - while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ; - if (st == MTSE_TMK) /* stopped by tmk? */ - msc_sta = msc_sta | STA_EOF | STA_ODD; /* normal status */ - else r = ms_map_err (uptr, st); /* map error */ - break; - -/* Unit service, continued */ - -case FNC_RFF: /* diagnostic read */ -case FNC_RC: /* read */ - if (msc_1st) { /* first svc? */ - msc_1st = ms_ptr = 0; /* clr 1st flop */ - st = sim_tape_rdrecf (uptr, msxb, &ms_max, DBSIZE); /* read rec */ - if (st == MTSE_RECE) msc_sta = msc_sta | STA_PAR; /* rec in err? */ - else if (st != MTSE_OK) { /* other error? */ - r = ms_map_err (uptr, st); /* map error */ - if (r == SCPE_OK) { /* recoverable? */ - sim_activate (uptr, msc_gtime); /* sched IRG */ - uptr->FNC = 0; /* NOP func */ - return SCPE_OK; } - break; } /* err, done */ - } - if (ms_ptr < ms_max) { /* more chars? */ - if (FLG (devd)) msc_sta = msc_sta | STA_TIM | STA_PAR; - msd_buf = ((uint16) msxb[ms_ptr] << 8) | msxb[ms_ptr + 1]; - ms_ptr = ms_ptr + 2; - setFLG (devd); /* set dch flg */ - sim_activate (uptr, msc_xtime); /* re-activate */ - return SCPE_OK; } - sim_activate (uptr, msc_gtime); /* sched IRG */ - if (uptr->FNC == FNC_RFF) msc_1st = 1; /* diagnostic? */ - else uptr->FNC = 0; /* NOP func */ - return SCPE_OK; - -case FNC_WC: /* write */ - if (msc_1st) msc_1st = ms_ptr = 0; /* no xfer on first */ - else { /* not 1st, next char */ - if (ms_ptr < DBSIZE) { /* room in buffer? */ - msxb[ms_ptr] = msd_buf >> 8; /* store 2 char */ - msxb[ms_ptr + 1] = msd_buf & 0377; - ms_ptr = ms_ptr + 2; - uptr->UST = 0; } - else msc_sta = msc_sta | STA_PAR; } - if (CTL (devd)) { /* xfer flop set? */ - setFLG (devd); /* set dch flag */ - sim_activate (uptr, msc_xtime); /* re-activate */ - return SCPE_OK; } - if (ms_ptr) { /* any data? write */ - if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr)) { /* write, err? */ - r = ms_map_err (uptr, st); /* map error */ - break; } } - sim_activate (uptr, msc_gtime); /* sched IRG */ - uptr->FNC = 0; /* NOP func */ - return SCPE_OK; - -default: /* unknown */ - break; } - -setFLG (devc); /* set cch flg */ -msc_sta = msc_sta & ~STA_BUSY; /* update status */ -return SCPE_OK; -} - -/* Map tape error status */ - -t_stat ms_map_err (UNIT *uptr, t_stat st) -{ -switch (st) { -case MTSE_FMT: /* illegal fmt */ -case MTSE_UNATT: /* unattached */ - msc_sta = msc_sta | STA_REJ; /* reject */ -case MTSE_OK: /* no error */ - return SCPE_IERR; /* never get here! */ -case MTSE_TMK: /* end of file */ - msc_sta = msc_sta | STA_EOF | STA_ODD; /* eof (also sets odd) */ - break; -case MTSE_INVRL: /* invalid rec lnt */ - msc_sta = msc_sta | STA_PAR; - return SCPE_MTRLNT; -case MTSE_IOERR: /* IO error */ - msc_sta = msc_sta | STA_PAR; /* error */ - if (msc_stopioe) return SCPE_IOERR; - break; -case MTSE_RECE: /* record in error */ -case MTSE_EOM: /* end of medium */ - msc_sta = msc_sta | STA_PAR; /* error */ - break; -case MTSE_BOT: /* reverse into BOT */ - uptr->UST = STA_BOT; /* set status */ - break; -case MTSE_WRP: /* write protect */ - msc_sta = msc_sta | STA_REJ; /* reject */ - break; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat msc_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -hp_enbdis_pair (&msc_dev, &msd_dev); /* make pair cons */ -msc_buf = msd_buf = 0; -msc_sta = msc_usl = 0; -msc_1st = 0; -msc_dib.cmd = msd_dib.cmd = 0; /* clear cmd */ -msc_dib.ctl = msd_dib.ctl = 0; /* clear ctl */ -msc_dib.flg = msd_dib.flg = 1; /* set flg */ -msc_dib.fbf = msd_dib.fbf = 1; /* set fbf */ -for (i = 0; i < MS_NUMDR; i++) { - uptr = msc_dev.units + i; - sim_tape_reset (uptr); - sim_cancel (uptr); - uptr->UST = 0; } -return SCPE_OK; -} - -/* Attach routine */ - -t_stat msc_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = sim_tape_attach (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* update status */ -uptr->UST = STA_BOT; -return r; -} - -/* Detach routine */ - -t_stat msc_detach (UNIT* uptr) -{ -uptr->UST = 0; /* update status */ -return sim_tape_detach (uptr); /* detach unit */ -} - -/* Set controller type */ - -t_stat ms_settype (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 i; - -if ((val < 0) || (val > 1) || (cptr != NULL)) return SCPE_ARG; -for (i = 0; i < MS_NUMDR; i++) { - if (msc_unit[i].flags & UNIT_ATT) return SCPE_ALATT; } -ms_ctype = val; -return SCPE_OK; -} - -/* Show controller type */ - -t_stat ms_showtype (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (ms_ctype) fprintf (st, "13183A"); -else fprintf (st, "13181A"); -return SCPE_OK; -} - -/* 7970B/7970E bootstrap routine (HP 12992D ROM) */ - -#define CHANGE_DEV (1 << 24) - -static const int32 mboot[IBL_LNT] = { - 0106501, /*ST LIB 1 ; read sw */ - 0006011, /* SLB,RSS ; bit 0 set? */ - 0027714, /* JMP RD ; no read */ - 0003004, /* CMA,INA ; A is ctr */ - 0073775, /* STA WC ; save */ - 0067772, /* LDA SL0RW ; sel 0, rew */ - 0017762, /*FF JSB CMD ; do cmd */ - 0102301+CHANGE_DEV, /* SFS CC ; done? */ - 0027707, /* JMP *-1 ; wait */ - 0067774, /* LDB FFC ; get file fwd */ - 0037775, /* ISZ WC ; done files? */ - 0027706, /* JMP FF ; no */ - 0067773, /*RD LDB RDCMD ; read cmd */ - 0017762, /* JSB CMD ; do cmd */ - 0103700+CHANGE_DEV, /* STC DC,C ; start dch */ - 0102201+CHANGE_DEV, /* SFC CC ; read done? */ - 0027752, /* JMP STAT ; no, get stat */ - 0102300+CHANGE_DEV, /* SFS DC ; any data? */ - 0027717, /* JMP *-3 ; wait */ - 0107500+CHANGE_DEV, /* LIB DC,C ; get rec cnt */ - 0005727, /* BLF,BLF ; move to lower */ - 0007000, /* CMB ; make neg */ - 0077775, /* STA WC ; save */ - 0102201+CHANGE_DEV, /* SFC CC ; read done? */ - 0027752, /* JMP STAT ; no, get stat */ - 0102300+CHANGE_DEV, /* SFS DC ; any data? */ - 0027727, /* JMP *-3 ; wait */ - 0107500+CHANGE_DEV, /* LIB DC,C ; get load addr */ - 0074000, /* STB 0 ; start csum */ - 0077762, /* STA CMD ; save address */ - 0027742, /* JMP *+4 */ - 0177762, /*NW STB CMD,I ; store data */ - 0040001, /* ADA 1 ; add to csum */ - 0037762, /* ISZ CMD ; adv addr ptr */ - 0102300+CHANGE_DEV, /* SFS DC ; any data? */ - 0027742, /* JMP *-1 ; wait */ - 0107500+CHANGE_DEV, /* LIB DC,C ; get word */ - 0037775, /* ISZ WC ; done? */ - 0027737, /* JMP NW ; no */ - 0054000, /* CPB 0 ; csum ok? */ - 0027717, /* JMP RD+3 ; yes, cont */ - 0102011, /* HLT 11 ; no, halt */ - 0102501+CHANGE_DEV, /*ST LIA CC ; get status */ - 0001727, /* ALF,ALF ; get eof bit */ - 0002020, /* SSA ; set? */ - 0102077, /* HLT 77 ; done */ - 0001727, /* ALF,ALF ; put status back */ - 0001310, /* RAR,SLA ; read ok? */ - 0102000, /* HLT 0 ; no */ - 0027714, /* JMP RD ; read next */ - 0000000, /*CMD 0 */ - 0106601+CHANGE_DEV, /* OTB CC ; output cmd */ - 0102501+CHANGE_DEV, /* LIA CC ; check for reject */ - 0001323, /* RAR,RAR */ - 0001310, /* RAR,SLA */ - 0027763, /* JMP CMD+1 ; try again */ - 0103701+CHANGE_DEV, /* STC CC,C ; start command */ - 0127762, /* JMP CMD,I ; exit */ - 0001501, /*SL0RW 001501 ; select 0, rewind */ - 0001423, /*RDCMD 001423 ; read record */ - 0000203, /*FFC 000203 ; space forward file */ - 0000000, /*WC 000000 */ - 0000000, - 0000000 }; - -t_stat msc_boot (int32 unitno, DEVICE *dptr) -{ -int32 i, dev; - -if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ -dev = msd_dib.devno; /* get data chan dev */ -PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */ -SR = IBL_MS + (dev << IBL_V_DEV); /* set SR */ -if ((sim_switches & SWMASK ('S')) && AR) SR = SR | 1; /* skip? */ -for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */ - if (mboot[i] & CHANGE_DEV) /* IO instr? */ - M[PC + i] = (mboot[i] + dev) & DMASK; - else M[PC + i] = mboot[i]; } -return SCPE_OK; -} diff --git a/HP2100/hp2100_mt.c b/HP2100/hp2100_mt.c deleted file mode 100644 index 320dc7ee..00000000 --- a/HP2100/hp2100_mt.c +++ /dev/null @@ -1,478 +0,0 @@ -/* hp2100_mt.c: HP 2100 12559A magnetic tape simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - mt 12559A 3030 nine track magnetic tape - - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Revised for magtape library - 30-Sep-02 RMS Revamped error handling - 28-Aug-02 RMS Added end of medium support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Added maximum record length test - 20-Jan-02 RMS Fixed bug on last character write - 03-Dec-01 RMS Added read only unit, extended SET/SHOW support - 07-Sep-01 RMS Moved function prototypes - 30-Nov-00 RMS Made variable names unique - 04-Oct-98 RMS V2.4 magtape format - - Magnetic tapes are represented as a series of variable records - of the form: - - 32b byte count - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32b byte count - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a byte count of 0. - - Unusually among HP peripherals, the 12559 does not have a command flop, - and its flag and flag buffer power up as clear rather than set. -*/ - -#include "hp2100_defs.h" -#include "sim_tape.h" - -#define DB_V_SIZE 16 /* max data buf */ -#define DBSIZE (1 << DB_V_SIZE) /* max data cmd */ - -/* Command - mtc_fnc */ - -#define FNC_CLR 0300 /* clear */ -#define FNC_WC 0031 /* write */ -#define FNC_RC 0023 /* read */ -#define FNC_GAP 0011 /* write gap */ -#define FNC_FSR 0003 /* forward space */ -#define FNC_BSR 0041 /* backward space */ -#define FNC_REW 0201 /* rewind */ -#define FNC_RWS 0101 /* rewind and offline */ -#define FNC_WFM 0035 /* write file mark */ - -/* Status - stored in mtc_sta, (d) = dynamic */ - -#define STA_LOCAL 0400 /* local (d) */ -#define STA_EOF 0200 /* end of file */ -#define STA_BOT 0100 /* beginning of tape */ -#define STA_EOT 0040 /* end of tape */ -#define STA_TIM 0020 /* timing error */ -#define STA_REJ 0010 /* programming error */ -#define STA_WLK 0004 /* write locked (d) */ -#define STA_PAR 0002 /* parity error */ -#define STA_BUSY 0001 /* busy (d) */ - -extern uint32 PC; -extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; -int32 mtc_fnc = 0; /* function */ -int32 mtc_sta = 0; /* status register */ -int32 mtc_dtf = 0; /* data xfer flop */ -int32 mtc_1st = 0; /* first svc flop */ -int32 mtc_ctime = 1000; /* command wait */ -int32 mtc_gtime = 1000; /* gap stop time */ -int32 mtc_xtime = 15; /* data xfer time */ -int32 mtc_stopioe = 1; /* stop on error */ -uint8 mtxb[DBSIZE] = { 0 }; /* data buffer */ -t_mtrlnt mt_ptr = 0, mt_max = 0; /* buffer ptrs */ -static const int32 mtc_cmd[] = { - FNC_WC, FNC_RC, FNC_GAP, FNC_FSR, FNC_BSR, FNC_REW, FNC_RWS, FNC_WFM }; - -DEVICE mtd_dev, mtc_dev; -int32 mtdio (int32 inst, int32 IR, int32 dat); -int32 mtcio (int32 inst, int32 IR, int32 dat); -t_stat mtc_svc (UNIT *uptr); -t_stat mtc_reset (DEVICE *dptr); -t_stat mtc_attach (UNIT *uptr, char *cptr); -t_stat mtc_detach (UNIT *uptr); -t_stat mt_map_err (UNIT *uptr, t_stat st); - -/* MTD data structures - - mtd_dev MTD device descriptor - mtd_unit MTD unit list - mtd_reg MTD register list -*/ - -DIB mt_dib[] = { - { MTD, 0, 0, 0, 0, &mtdio }, - { MTC, 0, 0, 0, 0, &mtcio } }; - -#define mtd_dib mt_dib[0] -#define mtc_dib mt_dib[1] - -UNIT mtd_unit = { UDATA (NULL, 0, 0) }; - -REG mtd_reg[] = { - { FLDATA (CMD, mtd_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, mtd_dib.ctl, 0), REG_HRO }, - { FLDATA (FLG, mtd_dib.flg, 0) }, - { FLDATA (FBF, mtd_dib.fbf, 0), REG_HRO }, - { BRDATA (DBUF, mtxb, 8, 8, DBSIZE) }, - { DRDATA (BPTR, mt_ptr, DB_V_SIZE + 1) }, - { DRDATA (BMAX, mt_max, DB_V_SIZE + 1) }, - { ORDATA (DEVNO, mtd_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB mtd_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &mtd_dev }, - { 0 } }; - -DEVICE mtd_dev = { - "MTD", &mtd_unit, mtd_reg, mtd_mod, - 1, 10, 16, 1, 8, 8, - NULL, NULL, &mtc_reset, - NULL, NULL, NULL, - &mtd_dib, DEV_DISABLE | DEV_DIS }; - -/* MTC data structures - - mtc_dev MTC device descriptor - mtc_unit MTC unit list - mtc_reg MTC register list - mtc_mod MTC modifier list -*/ - -UNIT mtc_unit = { UDATA (&mtc_svc, UNIT_ATTABLE + UNIT_ROABLE, 0) }; - -REG mtc_reg[] = { - { ORDATA (FNC, mtc_fnc, 8) }, - { ORDATA (STA, mtc_sta, 9) }, - { ORDATA (BUF, mtc_unit.buf, 8) }, - { FLDATA (CMD, mtc_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, mtc_dib.ctl, 0) }, - { FLDATA (FLG, mtc_dib.flg, 0) }, - { FLDATA (FBF, mtc_dib.fbf, 0) }, - { FLDATA (DTF, mtc_dtf, 0) }, - { FLDATA (FSVC, mtc_1st, 0) }, - { DRDATA (POS, mtc_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (CTIME, mtc_ctime, 24), REG_NZ + PV_LEFT }, - { DRDATA (GTIME, mtc_gtime, 24), REG_NZ + PV_LEFT }, - { DRDATA (XTIME, mtc_xtime, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, mtc_stopioe, 0) }, - { ORDATA (DEVNO, mtc_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB mtc_mod[] = { - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &mtd_dev }, - { 0 } }; - -DEVICE mtc_dev = { - "MTC", &mtc_unit, mtc_reg, mtc_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &mtc_reset, - NULL, &mtc_attach, &mtc_detach, - &mtc_dib, DEV_DISABLE | DEV_DIS }; - -/* IOT routines */ - -int32 mtdio (int32 inst, int32 IR, int32 dat) -{ -int32 devd; - -devd = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (devd); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - mtc_unit.buf = dat & 0377; /* store data */ - break; -case ioMIX: /* merge */ - dat = dat | mtc_unit.buf; - break; -case ioLIX: /* load */ - dat = mtc_unit.buf; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) mtc_dtf = 0; /* CLC: clr xfer flop */ - break; -default: - break; } -if (IR & I_HC) { clrFLG (devd); } /* H/C option */ -return dat; -} - -int32 mtcio (int32 inst, int32 IR, int32 dat) -{ -int32 i, devc, devd, valid; -t_stat st; - -devc = IR & I_DEVMASK; /* get device no */ -devd = devc - 1; -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (devc); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - dat = dat & 0377; - mtc_sta = mtc_sta & ~STA_REJ; /* clear reject */ - if (dat == FNC_CLR) { /* clear? */ - if (sim_is_active (&mtc_unit) && /* write in prog? */ - (mtc_fnc == FNC_WC) && (mt_ptr > 0)) { /* yes, bad rec */ - if (st = sim_tape_wrrecf (&mtc_unit, mtxb, mt_ptr | MTR_ERF)) - mt_map_err (&mtc_unit, st); } - if (((mtc_fnc == FNC_REW) || (mtc_fnc == FNC_RWS)) && - sim_is_active (&mtc_unit)) sim_cancel (&mtc_unit); - mtc_1st = mtc_dtf = 0; - mtc_sta = mtc_sta & STA_BOT; - clrCTL (devc); /* init device */ - clrFLG (devc); - clrCTL (devd); - clrFLG (devd); - return SCPE_OK; } - for (i = valid = 0; i < sizeof (mtc_cmd); i++) /* is fnc valid? */ - if (dat == mtc_cmd[i]) valid = 1; - if (!valid || sim_is_active (&mtc_unit) || /* is cmd valid? */ - ((mtc_sta & STA_BOT) && (dat == FNC_BSR)) || - (sim_tape_wrp (&mtc_unit) && - ((dat == FNC_WC) || (dat == FNC_GAP) || (dat == FNC_WFM)))) - mtc_sta = mtc_sta | STA_REJ; - else { - sim_activate (&mtc_unit, mtc_ctime); /* start tape */ - mtc_fnc = dat; /* save function */ - mtc_sta = STA_BUSY; /* unit busy */ - mt_ptr = 0; /* init buffer ptr */ - clrFLG (devc); /* clear flags */ - clrFLG (devd); - mtc_1st = 1; /* set 1st flop */ - mtc_dtf = 1; } /* set xfer flop */ - break; -case ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - dat = dat | (mtc_sta & ~(STA_LOCAL | STA_WLK | STA_BUSY)); - if (mtc_unit.flags & UNIT_ATT) { /* construct status */ - if (sim_is_active (&mtc_unit)) dat = dat | STA_BUSY; - if (sim_tape_wrp (&mtc_unit)) dat = dat | STA_WLK; } - else dat = dat | STA_BUSY | STA_LOCAL; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { clrCTL (devc); } /* CLC */ - else { setCTL (devc); } /* STC */ - break; -default: - break; } -if (IR & I_HC) { clrFLG (devc); } /* H/C option */ -return dat; -} - -/* Unit service - - If rewind done, reposition to start of tape, set status - else, do operation, set done, interrupt - - Can't be write locked, can only write lock detached unit -*/ - -t_stat mtc_svc (UNIT *uptr) -{ -int32 devc, devd; -t_mtrlnt tbc; -t_stat st, r = SCPE_OK; - -devc = mtc_dib.devno; /* get device nos */ -devd = mtd_dib.devno; -if ((mtc_unit.flags & UNIT_ATT) == 0) { /* offline? */ - mtc_sta = STA_LOCAL | STA_REJ; /* rejected */ - setFLG (devc); /* set cch flg */ - return IORETURN (mtc_stopioe, SCPE_UNATT); } - -switch (mtc_fnc) { /* case on function */ - -case FNC_REW: /* rewind */ - sim_tape_rewind (uptr); /* BOT */ - mtc_sta = STA_BOT; /* update status */ - break; - -case FNC_RWS: /* rewind and offline */ - sim_tape_rewind (uptr); /* clear position */ - return sim_tape_detach (uptr); /* don't set cch flg */ - -case FNC_WFM: /* write file mark */ - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = mt_map_err (uptr, st); /* map error */ - mtc_sta = STA_EOF; /* set EOF status */ - break; - -case FNC_GAP: /* erase gap */ - break; - -case FNC_FSR: /* space forward */ - if (st = sim_tape_sprecf (uptr, &tbc)) /* space rec fwd, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; - -case FNC_BSR: /* space reverse */ - if (st = sim_tape_sprecr (uptr, &tbc)) /* space rec rev, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; - -/* Unit service, continued */ - -case FNC_RC: /* read */ - if (mtc_1st) { /* first svc? */ - mtc_1st = mt_ptr = 0; /* clr 1st flop */ - st = sim_tape_rdrecf (uptr, mtxb, &mt_max, DBSIZE); /* read rec */ - if (st == MTSE_RECE) mtc_sta = mtc_sta | STA_PAR; /* rec in err? */ - else if (st != MTSE_OK) { /* other error? */ - r = mt_map_err (uptr, st); /* map error */ - if (r == SCPE_OK) { /* recoverable? */ - sim_activate (uptr, mtc_gtime); /* sched IRG */ - mtc_fnc = 0; /* NOP func */ - return SCPE_OK; } - break; } /* non-recov, done */ - if (mt_max < 12) { /* record too short? */ - mtc_sta = mtc_sta | STA_PAR; /* set flag */ - break; } - } - if (mt_ptr < mt_max) { /* more chars? */ - if (FLG (devd)) mtc_sta = mtc_sta | STA_TIM; - mtc_unit.buf = mtxb[mt_ptr++]; /* fetch next */ - setFLG (devd); /* set dch flg */ - sim_activate (uptr, mtc_xtime); /* re-activate */ - return SCPE_OK; } - sim_activate (uptr, mtc_gtime); /* schedule gap */ - mtc_fnc = 0; /* nop */ - return SCPE_OK; - -case FNC_WC: /* write */ - if (mtc_1st) mtc_1st = 0; /* no xfr on first */ - else { - if (mt_ptr < DBSIZE) { /* room in buffer? */ - mtxb[mt_ptr++] = mtc_unit.buf; - mtc_sta = mtc_sta & ~STA_BOT; } /* clear BOT */ - else mtc_sta = mtc_sta | STA_PAR; } - if (mtc_dtf) { /* xfer flop set? */ - setFLG (devd); /* set dch flag */ - sim_activate (uptr, mtc_xtime); /* re-activate */ - return SCPE_OK; } - if (mt_ptr) { /* write buffer */ - if (st = sim_tape_wrrecf (uptr, mtxb, mt_ptr)) { /* write, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; } } /* done */ - sim_activate (uptr, mtc_gtime); /* schedule gap */ - mtc_fnc = 0; /* nop */ - return SCPE_OK; - -default: /* unknown */ - break; } - -setFLG (devc); /* set cch flg */ -mtc_sta = mtc_sta & ~STA_BUSY; /* not busy */ -return SCPE_OK; -} - -/* Map tape error status */ - -t_stat mt_map_err (UNIT *uptr, t_stat st) -{ -switch (st) { -case MTSE_FMT: /* illegal fmt */ -case MTSE_UNATT: /* unattached */ - mtc_sta = mtc_sta | STA_REJ; /* reject */ -case MTSE_OK: /* no error */ - return SCPE_IERR; /* never get here! */ -case MTSE_TMK: /* end of file */ - mtc_sta = mtc_sta | STA_EOF; /* eof */ - break; -case MTSE_IOERR: /* IO error */ - mtc_sta = mtc_sta | STA_PAR; /* error */ - if (mtc_stopioe) return SCPE_IOERR; - break; -case MTSE_INVRL: /* invalid rec lnt */ - mtc_sta = mtc_sta | STA_PAR; - return SCPE_MTRLNT; -case MTSE_RECE: /* record in error */ -case MTSE_EOM: /* end of medium */ - mtc_sta = mtc_sta | STA_PAR; /* error */ - break; -case MTSE_BOT: /* reverse into BOT */ - mtc_sta = mtc_sta | STA_BOT; /* set status */ - break; -case MTSE_WRP: /* write protect */ - mtc_sta = mtc_sta | STA_REJ; /* reject */ - break; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat mtc_reset (DEVICE *dptr) -{ -hp_enbdis_pair (&mtc_dev, &mtd_dev); /* make pair cons */ -mtc_fnc = 0; -mtc_1st = mtc_dtf = 0; -mtc_dib.cmd = mtd_dib.cmd = 0; /* clear cmd */ -mtc_dib.ctl = mtd_dib.ctl = 0; /* clear ctl */ -mtc_dib.flg = mtd_dib.flg = 0; /* clear flg */ -mtc_dib.fbf = mtd_dib.fbf = 0; /* clear fbf */ -sim_cancel (&mtc_unit); /* cancel activity */ -sim_tape_reset (&mtc_unit); -if (mtc_unit.flags & UNIT_ATT) mtc_sta = - (sim_tape_bot (&mtc_unit)? STA_BOT: 0) | - (sim_tape_wrp (&mtc_unit)? STA_WLK: 0); -else mtc_sta = STA_LOCAL | STA_BUSY; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat mtc_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = sim_tape_attach (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* update status */ -mtc_sta = STA_BOT; -return r; -} - -/* Detach routine */ - -t_stat mtc_detach (UNIT* uptr) -{ -mtc_sta = 0; /* update status */ -return sim_tape_detach (uptr); /* detach unit */ -} diff --git a/HP2100/hp2100_mux.c b/HP2100/hp2100_mux.c deleted file mode 100644 index 0d0bb4d3..00000000 --- a/HP2100/hp2100_mux.c +++ /dev/null @@ -1,704 +0,0 @@ -/* hp2100_mux.c: HP 2100 12920A terminal multiplexor simulator - - Copyright (c) 2002-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - mux,muxl,muxc 12920A terminal multiplexor - - 09-May-03 RMS Added network device flag - 01-Nov-02 RMS Added 7B/8B support - 22-Aug-02 RMS Updated for changes to sim_tmxr - - The 12920A consists of three separate devices - - mux scanner (upper data card) - muxl lines (lower data card) - muxm modem control (control card) - - The lower data card has no CMD flop; the control card has no CMD flop. - The upper data card has none of the usual flops. -*/ - -#include "hp2100_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" -#include - -#define MUX_LINES 16 /* user lines */ -#define MUX_ILINES 5 /* diag rcv only */ -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */ -#define UNIT_V_MDM (UNIT_V_UF + 2) /* modem control */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_UC (1 << UNIT_V_UC) -#define UNIT_MDM (1 << UNIT_V_MDM) -#define MUXU_INIT_POLL 8000 -#define MUXL_WAIT 500 - -/* Channel number (OTA upper, LIA lower or upper) */ - -#define MUX_V_CHAN 10 /* channel num */ -#define MUX_M_CHAN 037 -#define MUX_CHAN(x) (((x) >> MUX_V_CHAN) & MUX_M_CHAN) - -/* OTA, lower = parameters or data */ - -#define OTL_P 0100000 /* parameter */ -#define OTL_TX 0040000 /* transmit */ -#define OTL_ENB 0020000 /* enable */ -#define OTL_TPAR 0010000 /* xmt parity */ -#define OTL_ECHO 0010000 /* rcv echo */ -#define OTL_DIAG 0004000 /* diagnose */ -#define OTL_SYNC 0004000 /* sync */ -#define OTL_V_LNT 8 /* char length */ -#define OTL_M_LNT 07 -#define OTL_LNT(x) (((x) >> OTL_V_LNT) & OTL_M_LNT) -#define OTL_V_BAUD 0 /* baud rate */ -#define OTL_M_BAUD 0377 -#define OTL_BAUD(x) (((x) >> OTL_V_BAUD) & OTL_M_BAUD) -#define OTL_CHAR 01777 /* char mask */ - -/* LIA, lower = received data */ - -#define LIL_PAR 0100000 /* parity */ -#define PUT_DCH(x) (((x) & MUX_M_CHAN) << MUX_V_CHAN) -#define LIL_CHAR 01777 /* character */ - -/* LIA, upper = status */ - -#define LIU_SEEK 0100000 /* seeking NI */ -#define LIU_DG 0000010 /* diagnose */ -#define LIU_BRK 0000004 /* break */ -#define LIU_LOST 0000002 /* char lost */ -#define LIU_TR 0000001 /* trans/rcv */ - -/* OTA, control */ - -#define OTC_SCAN 0100000 /* scan */ -#define OTC_UPD 0040000 /* update */ -#define OTC_V_CHAN 10 /* channel */ -#define OTC_M_CHAN 017 -#define OTC_CHAN(x) (((x) >> OTC_V_CHAN) & OTC_M_CHAN) -#define OTC_EC2 0000200 /* enable Cn upd */ -#define OTC_EC1 0000100 -#define OTC_C2 0000040 /* Cn flops */ -#define OTC_C1 0000020 -#define OTC_ES2 0000010 /* enb comparison */ -#define OTC_ES1 0000004 -#define OTC_V_ES 2 -#define OTC_SS2 0000002 /* SSn flops */ -#define OTC_SS1 0000001 -#define OTC_RW (OTC_ES2|OTC_ES1|OTC_SS2|OTC_SS1) -#define RTS OCT_C2 /* C2 = rts */ -#define DTR OTC_C1 /* C1 = dtr */ - -/* LIA, control */ - -#define LIC_MBO 0140000 /* always set */ -#define LIC_V_CHAN 10 /* channel */ -#define LIC_M_CHAN 017 -#define PUT_CCH(x) (((x) & OTC_M_CHAN) << OTC_V_CHAN) -#define LIC_I2 0001000 /* change flags */ -#define LIC_I1 0000400 -#define LIC_S2 0000002 /* Sn flops */ -#define LIC_S1 0000001 -#define LIC_V_I 8 /* S1 to I1 */ -#define CDET LIC_S2 /* S2 = cdet */ -#define DSR LIC_S1 /* S1 = dsr */ - -#define LIC_TSTI(ch) (((muxc_lia[ch] ^ muxc_ota[ch]) & \ - ((muxc_ota[ch] & (OTC_ES2|OTC_ES1)) >> OTC_V_ES)) \ - << LIC_V_I) - -extern uint32 PC; -extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; - -uint16 mux_sta[MUX_LINES]; /* line status */ -uint16 mux_rpar[MUX_LINES + MUX_ILINES]; /* rcv param */ -uint16 mux_xpar[MUX_LINES]; /* xmt param */ -uint8 mux_rbuf[MUX_LINES + MUX_ILINES]; /* rcv buf */ -uint8 mux_xbuf[MUX_LINES]; /* xmt buf */ -uint8 mux_rchp[MUX_LINES + MUX_ILINES]; /* rcv chr pend */ -uint8 mux_xdon[MUX_LINES]; /* xmt done */ -uint8 muxc_ota[MUX_LINES]; /* ctrl: Cn,ESn,SSn */ -uint8 muxc_lia[MUX_LINES]; /* ctrl: Sn */ -uint32 mux_tps = 100; /* polls/second */ -uint32 muxl_ibuf = 0; /* low in: rcv data */ -uint32 muxl_obuf = 0; /* low out: param */ -uint32 muxu_ibuf = 0; /* upr in: status */ -uint32 muxu_obuf = 0; /* upr out: chan */ -uint32 muxc_chan = 0; /* ctrl chan */ -uint32 muxc_scan = 0; /* ctrl scan */ - -TMLN mux_ldsc[MUX_LINES] = { 0 }; /* line descriptors */ -TMXR mux_desc = { MUX_LINES, 0, 0, NULL }; /* mux descriptor */ - -DEVICE muxl_dev, muxu_dev, muxc_dev; -int32 muxlio (int32 inst, int32 IR, int32 dat); -int32 muxuio (int32 inst, int32 IR, int32 dat); -int32 muxcio (int32 inst, int32 IR, int32 dat); -t_stat muxi_svc (UNIT *uptr); -t_stat muxo_svc (UNIT *uptr); -t_stat mux_reset (DEVICE *dptr); -t_stat mux_attach (UNIT *uptr, char *cptr); -t_stat mux_detach (UNIT *uptr); -t_stat mux_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat mux_show (FILE *st, UNIT *uptr, int32 val, void *desc); -void mux_data_int (void); -void mux_ctrl_int (void); -void mux_diag (int32 c); - -static uint8 odd_par[256] = { - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 000-017 */ - 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, /* 020-037 */ - 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, /* 040-067 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 060-077 */ - 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, /* 100-117 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 120-137 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 140-157 */ - 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, /* 160-177 */ - 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, /* 200-217 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 220-237 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 240-257 */ - 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, /* 260-277 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 300-317 */ - 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, /* 320-337 */ - 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, /* 340-367 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 }; /* 360-377 */ - -#define RCV_PAR(x) (odd_par[(x) & 0377]? LIL_PAR: 0) - -DIB mux_dib[] = { - { MUXL, 0, 0, 0, 0, &muxlio }, - { MUXU, 0, 0, 0, 0, &muxuio } }; - -#define muxl_dib mux_dib[0] -#define muxu_dib mux_dib[1] - -/* MUX data structures - - muxu_dev MUX device descriptor - muxu_unit MUX unit descriptor - muxu_reg MUX register list - muxu_mod MUX modifiers list -*/ - -UNIT muxu_unit = { UDATA (&muxi_svc, UNIT_ATTABLE, 0), MUXU_INIT_POLL }; - -REG muxu_reg[] = { - { ORDATA (IBUF, muxu_ibuf, 16) }, - { ORDATA (OBUF, muxu_obuf, 16) }, - { FLDATA (CMD, muxu_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, muxu_dib.ctl, 0), REG_HRO }, - { FLDATA (FLG, muxu_dib.flg, 0), REG_HRO }, - { FLDATA (FBF, muxu_dib.fbf, 0), REG_HRO }, - { ORDATA (DEVNO, muxu_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB muxu_mod[] = { - { UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &mux_summ }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &mux_show, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &mux_show, NULL }, - { MTAB_XTD|MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &muxl_dev }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &mux_desc }, - { 0 } }; - -DEVICE muxu_dev = { - "MUX", &muxu_unit, muxu_reg, muxu_mod, - 1, 10, 31, 1, 8, 8, - &tmxr_ex, &tmxr_dep, &mux_reset, - NULL, &mux_attach, &mux_detach, - &muxu_dib, DEV_NET | DEV_DISABLE }; - -/* MUXL data structures - - muxl_dev MUXL device descriptor - muxl_unit MUXL unit descriptor - muxl_reg MUXL register list - muxl_mod MUXL modifiers list -*/ - -UNIT muxl_unit[] = { - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT } }; - -MTAB muxl_mod[] = { - { UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", NULL }, - { UNIT_UC+UNIT_8B, 0 , "7b", "7B", NULL }, - { UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", NULL }, - { UNIT_MDM, 0, "no dataset", "NODATASET", NULL }, - { UNIT_MDM, UNIT_MDM, "dataset", "DATASET", NULL }, - { MTAB_XTD|MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &muxl_dev }, - { 0 } }; - -REG muxl_reg[] = { - { FLDATA (CMD, muxl_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, muxl_dib.ctl, 0) }, - { FLDATA (FLG, muxl_dib.flg, 0) }, - { FLDATA (FBF, muxl_dib.fbf, 0) }, - { BRDATA (STA, mux_sta, 8, 16, MUX_LINES) }, - { BRDATA (RPAR, mux_rpar, 8, 16, MUX_LINES + MUX_ILINES) }, - { BRDATA (XPAR, mux_xpar, 8, 16, MUX_LINES) }, - { BRDATA (RBUF, mux_rbuf, 8, 8, MUX_LINES + MUX_ILINES) }, - { BRDATA (XBUF, mux_xbuf, 8, 8, MUX_LINES) }, - { BRDATA (RCHP, mux_rchp, 8, 1, MUX_LINES + MUX_ILINES) }, - { BRDATA (XDON, mux_xdon, 8, 1, MUX_LINES) }, - { URDATA (TIME, muxl_unit[0].wait, 10, 24, 0, - MUX_LINES, REG_NZ + PV_LEFT) }, - { ORDATA (DEVNO, muxl_dib.devno, 6), REG_HRO }, - { NULL } }; - -DEVICE muxl_dev = { - "MUXL", muxl_unit, muxl_reg, muxl_mod, - MUX_LINES, 10, 31, 1, 8, 8, - NULL, NULL, &mux_reset, - NULL, NULL, NULL, - &muxl_dib, 0 }; - -/* MUXM data structures - - muxc_dev MUXM device descriptor - muxc_unit MUXM unit descriptor - muxc_reg MUXM register list - muxc_mod MUXM modifiers list -*/ - -DIB muxc_dib = { MUXC, 0, 0, 0, 0, &muxcio }; - -UNIT muxc_unit = { UDATA (NULL, 0, 0) }; - -REG muxc_reg[] = { - { FLDATA (CMD, muxc_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, muxc_dib.ctl, 0) }, - { FLDATA (FLG, muxc_dib.flg, 0) }, - { FLDATA (FBF, muxc_dib.fbf, 0) }, - { FLDATA (SCAN, muxc_scan, 0) }, - { ORDATA (CHAN, muxc_chan, 4) }, - { BRDATA (DSO, muxc_ota, 8, 6, MUX_LINES) }, - { BRDATA (DSI, muxc_lia, 8, 2, MUX_LINES) }, - { ORDATA (DEVNO, muxc_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB muxc_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &muxc_dev }, - { 0 } }; - -DEVICE muxc_dev = { - "MUXM", &muxc_unit, muxc_reg, muxc_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &mux_reset, - NULL, NULL, NULL, - &muxc_dib, 0 }; - -/* IOT routines: data cards */ - -int32 muxlio (int32 inst, int32 IR, int32 dat) -{ -int32 dev, ln; - -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - muxl_obuf = dat; /* store data */ - break; -case ioMIX: /* merge */ - dat = dat | muxl_ibuf; - break; -case ioLIX: /* load */ - dat = muxl_ibuf; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { clrCTL (dev); } /* CLC */ - else { /* STC */ - setCTL (dev); /* set ctl */ - ln = MUX_CHAN (muxu_obuf); /* get chan # */ - if (muxl_obuf & OTL_P) { /* parameter set? */ - if (muxl_obuf & OTL_TX) { /* transmit? */ - if (ln < MUX_LINES) /* to valid line? */ - mux_xpar[ln] = muxl_obuf; } - else if (ln < (MUX_LINES + MUX_ILINES)) /* rcv, valid line? */ - mux_rpar[ln] = muxl_obuf; } - else if ((muxl_obuf & OTL_TX) && /* xmit data? */ - (ln < MUX_LINES)) { /* to valid line? */ - if (sim_is_active (&muxl_unit[ln])) /* still working? */ - mux_sta[ln] = mux_sta[ln] | LIU_LOST; - else sim_activate (&muxl_unit[ln], muxl_unit[ln].wait); - mux_xbuf[ln] = muxl_obuf & OTL_CHAR; } /* load buffer */ - } /* end STC */ - break; -default: - break; } -if (IR & I_HC) { /* H/C option */ - clrFLG (dev); /* clear flag */ - mux_data_int (); } /* look for new int */ -return dat; -} - -int32 muxuio (int32 inst, int32 IR, int32 dat) -{ -switch (inst) { /* case on opcode */ -case ioOTX: /* output */ - muxu_obuf = dat; /* store data */ - break; -case ioMIX: /* merge */ - dat = dat | muxu_ibuf; - break; -case ioLIX: /* load */ - dat = muxu_ibuf; - break; -default: - break; } -return dat; -} - -/* IOT routine: control card */ - -int32 muxcio (int32 inst, int32 IR, int32 dat) -{ -int32 dev, ln, t, old; - -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - if (dat & OTC_SCAN) muxc_scan = 1; /* set scan flag */ - else muxc_scan = 0; - if (dat & OTC_UPD) { /* update? */ - ln = OTC_CHAN (dat); /* get channel */ - old = muxc_ota[ln]; /* save prior val */ - muxc_ota[ln] = (muxc_ota[ln] & ~OTC_RW) | /* save ESn,SSn */ - (dat & OTC_RW); - if (dat & OTC_EC2) muxc_ota[ln] = /* if EC2, upd C2 */ - (muxc_ota[ln] & ~OTC_C2) | (dat & OTC_C2); - if (dat & OTC_EC1) muxc_ota[ln] = /* if EC1, upd C1 */ - (muxc_ota[ln] & ~OTC_C1) | (dat & OTC_C1); - if ((muxl_unit[ln].flags & UNIT_MDM) && /* modem ctrl? */ - (old & DTR) && !(muxc_ota[ln] & DTR)) { /* DTR drop? */ - tmxr_msg (mux_ldsc[ln].conn, "\r\nLine hangup\r\n"); - tmxr_reset_ln (&mux_ldsc[ln]); /* reset line */ - muxc_lia[ln] = 0; } /* dataset off */ - } /* end update */ - break; -case ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - t = LIC_MBO | PUT_CCH (muxc_chan) | /* mbo, chan num */ - LIC_TSTI (muxc_chan) | /* I2, I1 */ - (muxc_ota[muxc_chan] & (OTC_ES2 | OTC_ES1)) | /* ES2, ES1 */ - (muxc_lia[muxc_chan] & (LIC_S2 | LIC_S1)); /* S2, S1 */ - dat = dat | t; /* return status */ - muxc_chan = (muxc_chan + 1) & LIC_M_CHAN; /* incr channel */ - break; -case ioCTL: /* ctrl clear/set */ - if (IR & I_CTL) { clrCTL (dev); } /* CLC */ - else { setCTL (dev); } /* STC */ - break; -default: - break; } -if (IR & I_HC) { /* H/C option */ - clrFLG (dev); /* clear flag */ - mux_ctrl_int (); } /* look for new int */ -return dat; -} - -/* Unit service - receive side - - Poll for new connections - Poll all active lines for input -*/ - -t_stat muxi_svc (UNIT *uptr) -{ -int32 ln, c, t; - -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ -t = sim_rtcn_calb (mux_tps, TMR_MUX); /* calibrate */ -sim_activate (uptr, t); /* continue poll */ -ln = tmxr_poll_conn (&mux_desc); /* look for connect */ -if (ln >= 0) { /* got one? */ - if ((muxl_unit[ln].flags & UNIT_MDM) && /* modem ctrl? */ - (muxc_ota[ln] & DTR)) /* DTR? */ - muxc_lia[ln] = muxc_lia[ln] | CDET; /* set cdet */ - muxc_lia[ln] = muxc_lia[ln] | DSR; /* set dsr */ - mux_ldsc[ln].rcve = 1; } /* rcv enabled */ -tmxr_poll_rx (&mux_desc); /* poll for input */ -for (ln = 0; ln < MUX_LINES; ln++) { /* loop thru lines */ - if (mux_ldsc[ln].conn) { /* connected? */ - if (c = tmxr_getc_ln (&mux_ldsc[ln])) { /* get char */ - if (c & SCPE_BREAK) { /* break? */ - mux_sta[ln] = mux_sta[ln] | LIU_BRK; - mux_rbuf[ln] = 0; } /* no char */ - else { /* normal */ - if (mux_rchp[ln]) mux_sta[ln] = mux_sta[ln] | LIU_LOST; - if (muxl_unit[ln].flags & UNIT_UC) { /* cvt to UC? */ - c = c & 0177; - if (islower (c)) c = toupper (c); } - else c = c & ((muxl_unit[ln].flags & UNIT_8B)? 0377: 0177); - if (mux_rpar[ln] & OTL_ECHO) { /* echo? */ - TMLN *lp = &mux_ldsc[ln]; /* get line */ - tmxr_putc_ln (lp, c); /* output char */ - tmxr_poll_tx (&mux_desc); } /* poll xmt */ - mux_rbuf[ln] = c; /* save char */ - mux_rchp[ln] = 1; } /* char pending */ - if (mux_rpar[ln] & OTL_DIAG) mux_diag (c); /* rcv diag? */ - } /* end if char */ - } /* end if connected */ - else muxc_lia[ln] = 0; /* disconnected */ - } /* end for */ -if (!FLG (muxl_dib.devno)) mux_data_int (); /* scan for data int */ -if (!FLG (muxc_dib.devno)) mux_ctrl_int (); /* scan modem */ -return SCPE_OK; -} - -/* Unit service - transmit side */ - -t_stat muxo_svc (UNIT *uptr) -{ -int32 c, ln = uptr - muxl_unit; /* line # */ - -if (mux_ldsc[ln].conn) { /* connected? */ - if (mux_ldsc[ln].xmte) { /* xmt enabled? */ - if ((mux_xbuf[ln] & OTL_SYNC) == 0) { /* start bit 0? */ - TMLN *lp = &mux_ldsc[ln]; /* get line */ - c = mux_xbuf[ln]; /* get char */ - if (muxl_unit[ln].flags & UNIT_UC) { /* cvt to UC? */ - c = c & 0177; - if (islower (c)) c = toupper (c); } - else c = c & ((muxl_unit[ln].flags & UNIT_8B)? 0377: 0177); - if (mux_xpar[ln] & OTL_DIAG) /* xmt diag? */ - mux_diag (mux_xbuf[ln]); /* before munge */ - mux_xdon[ln] = 1; /* set done */ - tmxr_putc_ln (lp, c); /* output char */ - tmxr_poll_tx (&mux_desc); } } /* poll xmt */ - else { /* buf full */ - tmxr_poll_tx (&mux_desc); /* poll xmt */ - sim_activate (uptr, muxl_unit[ln].wait); /* wait */ - return SCPE_OK; } } -if (!FLG (muxl_dib.devno)) mux_data_int (); /* scan for int */ -return SCPE_OK; -} - -/* Look for data interrupt */ - -void mux_data_int (void) -{ -int32 i; - -for (i = 0; i < MUX_LINES; i++) { /* rcv lines */ - if ((mux_rpar[i] & OTL_ENB) && mux_rchp[i]) { /* enabled, char? */ - muxl_ibuf = PUT_CCH (i) | mux_rbuf[i] | /* lo buf = char */ - RCV_PAR (mux_rbuf[i]); - muxu_ibuf = PUT_CCH (i) | mux_sta[i]; /* hi buf = stat */ - mux_rchp[i] = 0; /* clr char, stat */ - mux_sta[i] = 0; - setFLG (muxl_dib.devno); /* interrupt */ - return; } } -for (i = 0; i < MUX_LINES; i++) { /* xmt lines */ - if ((mux_xpar[i] & OTL_ENB) && mux_xdon[i]) { /* enabled, done? */ - muxu_ibuf = PUT_CCH (i) | mux_sta[i] | LIU_TR; /* hi buf = stat */ - mux_xdon[i] = 0; /* clr done, stat */ - mux_sta[i] = 0; - setFLG (muxl_dib.devno); /* interrupt */ - return; } } -for (i = MUX_LINES; i < (MUX_LINES + MUX_ILINES); i++) { /* diag lines */ - if ((mux_rpar[i] & OTL_ENB) && mux_rchp[i]) { /* enabled, char? */ - muxl_ibuf = PUT_CCH (i) | mux_rbuf[i] | /* lo buf = char */ - RCV_PAR (mux_rbuf[i]); - muxu_ibuf = PUT_CCH (i) | mux_sta[i] | LIU_DG; /* hi buf = stat */ - mux_rchp[i] = 0; /* clr char, stat */ - mux_sta[i] = 0; - setFLG (muxl_dib.devno); - return; } } -return; -} - -/* Look for control interrupt */ - -void mux_ctrl_int (void) -{ -int32 i; - -if (muxc_scan == 0) return; -for (i = 0; i < MUX_LINES; i++) { - muxc_chan = (muxc_chan + 1) & LIC_M_CHAN; /* step channel */ - if (LIC_TSTI (muxc_chan)) { /* status change? */ - setFLG (muxc_dib.devno); /* set flag */ - break; } } -return; -} - -/* Set diagnostic lines for given character */ - -void mux_diag (int32 c) -{ -int32 i; - -for (i = MUX_LINES; i < (MUX_LINES + MUX_ILINES); i++) { - if (c & SCPE_BREAK) { /* break? */ - mux_sta[i] = mux_sta[i] | LIU_BRK; - mux_rbuf[i] = 0; } /* no char */ - else { - if (mux_rchp[i]) mux_sta[i] = mux_sta[i] | LIU_LOST; - mux_rchp[i] = 1; - mux_rbuf[i] = c; } } -return; -} - -/* Reset an individual line */ - -void mux_reset_ln (int32 i) -{ -mux_rbuf[i] = mux_xbuf[i] = 0; /* clear state */ -mux_rpar[i] = mux_xpar[i] = 0; -mux_rchp[i] = mux_xdon[i] = 0; -mux_sta[i] = 0; -muxc_ota[i] = muxc_lia[i] = 0; /* clear modem */ -if (mux_ldsc[i].conn) /* connected? */ - muxc_lia[i] = muxc_lia[i] | DSR | /* cdet, dsr */ - (muxl_unit[i].flags & UNIT_MDM? CDET: 0); -sim_cancel (&muxl_unit[i]); -return; -} - -/* Reset routine */ - -t_stat mux_reset (DEVICE *dptr) -{ -int32 i, t; - -if (muxu_dev.flags & DEV_DIS) { /* enb/dis dev */ - muxl_dev.flags = muxu_dev.flags | DEV_DIS; - muxc_dev.flags = muxc_dev.flags | DEV_DIS; } -else { muxl_dev.flags = muxl_dev.flags & ~DEV_DIS; - muxc_dev.flags = muxc_dev.flags & ~DEV_DIS; } -muxl_dib.cmd = muxl_dib.ctl = 0; /* init lower */ -muxl_dib.flg = muxl_dib.fbf = 1; -muxu_dib.cmd = muxu_dib.ctl = 0; /* upper not */ -muxu_dib.flg = muxu_dib.fbf = 0; /* implemented */ -muxc_dib.cmd = muxc_dib.ctl = 0; /* init ctrl */ -muxc_dib.flg = muxc_dib.fbf = 1; -muxc_chan = muxc_scan = 0; /* init modem scan */ -if (muxu_unit.flags & UNIT_ATT) { /* master att? */ - if (!sim_is_active (&muxu_unit)) { - t = sim_rtcn_init (muxu_unit.wait, TMR_MUX); - sim_activate (&muxu_unit, t); } } /* activate */ -else sim_cancel (&muxu_unit); /* else stop */ -for (i = 0; i < MUX_LINES; i++) { - mux_desc.ldsc[i] = &mux_ldsc[i]; - mux_reset_ln (i); } -return SCPE_OK; -} - -/* Attach master unit */ - -t_stat mux_attach (UNIT *uptr, char *cptr) -{ -t_stat r; -int32 t; - -r = tmxr_attach (&mux_desc, uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error */ -t = sim_rtcn_init (muxu_unit.wait, TMR_MUX); -sim_activate (uptr, t); /* start poll */ -return SCPE_OK; -} - -/* Detach master unit */ - -t_stat mux_detach (UNIT *uptr) -{ -int32 i; -t_stat r; - -r = tmxr_detach (&mux_desc, uptr); /* detach */ -for (i = 0; i < MUX_LINES; i++) mux_ldsc[i].rcve = 0; /* disable rcv */ -sim_cancel (uptr); /* stop poll */ -return r; -} - -/* Show summary processor */ - -t_stat mux_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < MUX_LINES; i++) t = t + (mux_ldsc[i].conn != 0); -if (t == 1) fprintf (st, "1 connection"); -else fprintf (st, "%d connections", t); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat mux_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i; - -for (i = 0; (i < MUX_LINES) && (mux_ldsc[i].conn == 0); i++) ; -if (i < MUX_LINES) { - for (i = 0; i < MUX_LINES; i++) { - if (mux_ldsc[i].conn) { - if (val) tmxr_fconns (st, &mux_ldsc[i], i); - else tmxr_fstats (st, &mux_ldsc[i], i); } } } -else fprintf (st, "all disconnected\n"); -return SCPE_OK; -} - diff --git a/HP2100/hp2100_stddev.c b/HP2100/hp2100_stddev.c deleted file mode 100644 index e048401d..00000000 --- a/HP2100/hp2100_stddev.c +++ /dev/null @@ -1,704 +0,0 @@ -/* hp2100_stddev.c: HP2100 standard devices simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTI_CTLILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LII_CTLLE FOR ANY CLAIM, DAMAGES OR OTHER LII_CTLILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - ptr 12597A-002 paper tape reader - ptp 12597A-005 paper tape punch - tty 12531C buffered teleprinter interface - clk 12539C time base generator - - 25-Apr-03 RMS Added extended file support - 22-Dec-02 RMS Added break support - 01-Nov-02 RMS Revised BOOT command for IBL ROMs - Fixed bug in TTY reset, TTY starts in input mode - Fixed bug in TTY mode OTA, stores data as well - Fixed clock to add calibration, proper start/stop - Added UC option to TTY output - 30-May-02 RMS Widened POS to 32b - 22-Mar-02 RMS Revised for dynamically allocated memory - 03-Nov-01 RMS Changed DEVNO to use extended SET/SHOW - 29-Nov-01 RMS Added read only unit support - 24-Nov-01 RMS Changed TIME to an array - 07-Sep-01 RMS Moved function prototypes - 21-Nov-00 RMS Fixed flag, buffer power up state - Added status input for ptp, tty - 15-Oct-00 RMS Added dynamic device number support - - The reader and punch, like most HP devices, have a command flop. The - teleprinter and clock do not. - - The clock autocalibrates. If the specified clock frequency is below - 10Hz, the clock service routine runs at 10Hz and counts down a repeat - counter before generating an interrupt. Autocalibration will not work - if the clock is running at 1Hz or less. - - Clock diagnostic mode corresponds to inserting jumper W2 on the 12539C. - This turns off autocalibration and divides the longest time intervals down - by 10**3. The clk_time values were chosen to allow the diagnostic to - pass its clock calibration test. -*/ - -#include "hp2100_defs.h" -#include -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */ -#define UNIT_V_DIAG (UNIT_V_UF + 2) /* diag mode */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_UC (1 << UNIT_V_UC) -#define UNIT_DIAG (1 << UNIT_V_DIAG) - -#define PTP_LOW 0000040 /* low tape */ -#define TM_MODE 0100000 /* mode change */ -#define TM_KBD 0040000 /* enable keyboard */ -#define TM_PRI 0020000 /* enable printer */ -#define TM_PUN 0010000 /* enable punch */ -#define TP_BUSY 0100000 /* busy */ - -#define CLK_V_ERROR 4 /* clock overrun */ -#define CLK_ERROR (1 << CLK_V_ERROR) - -extern uint16 *M; -extern uint32 PC, SR; -extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; -extern UNIT cpu_unit; - -int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */ -int32 ttp_stopioe = 0; -int32 tty_buf = 0, tty_mode = 0; /* tty buffer, mode */ -int32 clk_select = 0; /* clock time select */ -int32 clk_error = 0; /* clock error */ -int32 clk_ctr = 0; /* clock counter */ -int32 clk_time[8] = /* clock intervals */ - { 155, 1550, 15500, 155000, 155000, 155000, 155000, 155000 }; -int32 clk_tps[8] = /* clock tps */ - { 10000, 1000, 100, 10, 10, 10, 10, 10 }; -int32 clk_rpt[8] = /* number of repeats */ - { 1, 1, 1, 1, 10, 100, 1000, 10000 }; - -DEVICE ptr_dev, ptp_dev, tty_dev, clk_dev; -int32 ptrio (int32 inst, int32 IR, int32 dat); -t_stat ptr_svc (UNIT *uptr); -t_stat ptr_reset (DEVICE *dptr); -t_stat ptr_boot (int32 unitno, DEVICE *dptr); -int32 ptpio (int32 inst, int32 IR, int32 dat); -t_stat ptp_svc (UNIT *uptr); -t_stat ptp_reset (DEVICE *dptr); -int32 ttyio (int32 inst, int32 IR, int32 dat); -t_stat tti_svc (UNIT *uptr); -t_stat tto_svc (UNIT *uptr); -t_stat tty_reset (DEVICE *dptr); -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); -int32 clkio (int32 inst, int32 IR, int32 dat); -t_stat clk_svc (UNIT *uptr); -t_stat clk_reset (DEVICE *dptr); -int32 clk_delay (int32 flg); - -/* PTR data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit descriptor - ptr_mod PTR modifiers - ptr_reg PTR register list -*/ - -DIB ptr_dib = { PTR, 0, 0, 0, 0, &ptrio }; - -UNIT ptr_unit = { - UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), - SERIAL_IN_WAIT }; - -REG ptr_reg[] = { - { ORDATA (BUF, ptr_unit.buf, 8) }, - { FLDATA (CMD, ptr_dib.cmd, 0) }, - { FLDATA (CTL, ptr_dib.ctl, 0) }, - { FLDATA (FLG, ptr_dib.flg, 0) }, - { FLDATA (FBF, ptr_dib.fbf, 0) }, - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptr_stopioe, 0) }, - { ORDATA (DEVNO, ptr_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB ptr_mod[] = { - { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &ptr_dev }, - { 0 } }; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, ptr_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - &ptr_boot, NULL, NULL, - &ptr_dib, DEV_DISABLE }; - -/* PTP data structures - - ptp_dev PTP device descriptor - ptp_unit PTP unit descriptor - ptp_mod PTP modifiers - ptp_reg PTP register list -*/ - -DIB ptp_dib = { PTP, 0, 0, 0, 0, &ptpio }; - -UNIT ptp_unit = { - UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG ptp_reg[] = { - { ORDATA (BUF, ptp_unit.buf, 8) }, - { FLDATA (CMD, ptp_dib.cmd, 0) }, - { FLDATA (CTL, ptp_dib.ctl, 0) }, - { FLDATA (FLG, ptp_dib.flg, 0) }, - { FLDATA (FBF, ptp_dib.fbf, 0) }, - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptp_stopioe, 0) }, - { ORDATA (DEVNO, ptp_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB ptp_mod[] = { - { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &ptp_dev }, - { 0 } }; - -DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, ptp_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptp_reset, - NULL, NULL, NULL, - &ptp_dib, DEV_DISABLE }; - -/* TTY data structures - - tty_dev TTY device descriptor - tty_unit TTY unit descriptor - tty_reg TTY register list - tty_mod TTy modifiers list -*/ - -#define TTI 0 -#define TTO 1 -#define TTP 2 - -DIB tty_dib = { TTY, 0, 0, 0, 0, &ttyio }; - -UNIT tty_unit[] = { - { UDATA (&tti_svc, UNIT_UC, 0), KBD_POLL_WAIT }, - { UDATA (&tto_svc, UNIT_UC, 0), SERIAL_OUT_WAIT }, - { UDATA (&tto_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_8B, 0), SERIAL_OUT_WAIT } }; - -REG tty_reg[] = { - { ORDATA (BUF, tty_buf, 8) }, - { ORDATA (MODE, tty_mode, 16) }, - { FLDATA (CMD, tty_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, tty_dib.ctl, 0) }, - { FLDATA (FLG, tty_dib.flg, 0) }, - { FLDATA (FBF, tty_dib.fbf, 0) }, - { DRDATA (KPOS, tty_unit[TTI].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (KTIME, tty_unit[TTI].wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPOS, tty_unit[TTO].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TTIME, tty_unit[TTO].wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (PPOS, tty_unit[TTP].pos, T_ADDR_W), PV_LEFT }, - { FLDATA (STOP_IOE, ttp_stopioe, 0) }, - { ORDATA (DEVNO, tty_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB tty_mod[] = { - { UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", &tty_set_mode }, - { UNIT_UC+UNIT_8B, 0 , "7b", "7B", &tty_set_mode }, - { UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", &tty_set_mode }, - { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &tty_dev }, - { 0 } }; - -DEVICE tty_dev = { - "TTY", tty_unit, tty_reg, tty_mod, - 3, 10, 31, 1, 8, 8, - NULL, NULL, &tty_reset, - NULL, NULL, NULL, - &tty_dib, 0 }; - -/* CLK data structures - - clk_dev CLK device descriptor - clk_unit CLK unit descriptor - clk_mod CLK modifiers - clk_reg CLK register list -*/ - -DIB clk_dib = { CLK, 0, 0, 0, 0, &clkio }; - -UNIT clk_unit = { - UDATA (&clk_svc, 0, 0) }; - -REG clk_reg[] = { - { ORDATA (SEL, clk_select, 3) }, - { DRDATA (CTR, clk_ctr, 14) }, - { FLDATA (CMD, clk_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, clk_dib.ctl, 0) }, - { FLDATA (FLG, clk_dib.flg, 0) }, - { FLDATA (FBF, clk_dib.fbf, 0) }, - { FLDATA (ERR, clk_error, CLK_V_ERROR) }, - { BRDATA (TIME, clk_time, 10, 24, 8) }, - { ORDATA (DEVNO, clk_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB clk_mod[] = { - { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL }, - { UNIT_DIAG, 0, "calibrated", "CALIBRATED", NULL }, - { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &clk_dev }, - { 0 } }; - -DEVICE clk_dev = { - "CLK", &clk_unit, clk_reg, clk_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &clk_reset, - NULL, NULL, NULL, - &clk_dib, 0 }; - -/* Paper tape reader: IOT routine */ - -int32 ptrio (int32 inst, int32 IR, int32 dat) -{ -int32 dev; - -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioMIX: /* merge */ - dat = dat | ptr_unit.buf; - break; -case ioLIX: /* load */ - dat = ptr_unit.buf; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCMD (dev); /* clear cmd, ctl */ - clrCTL (dev); } - else { /* STC */ - setCMD (dev); /* set cmd, ctl */ - setCTL (dev); - sim_activate (&ptr_unit, ptr_unit.wait); } - break; -default: - break; } -if (IR & I_HC) { clrFLG (dev); } /* H/C option */ -return dat; -} - -/* Unit service */ - -t_stat ptr_svc (UNIT *uptr) -{ -int32 dev, temp; - -dev = ptr_dib.devno; /* get device no */ -clrCMD (dev); /* clear cmd */ -if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptr_stopioe, SCPE_UNATT); -if ((temp = getc (ptr_unit.fileref)) == EOF) { /* read byte */ - if (feof (ptr_unit.fileref)) { - if (ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } - else perror ("PTR I/O error"); - clearerr (ptr_unit.fileref); - return SCPE_IOERR; } -setFLG (dev); /* set flag */ -ptr_unit.buf = temp & 0377; /* put byte in buf */ -ptr_unit.pos = ftell (ptr_unit.fileref); -return SCPE_OK; -} - -/* Reset routine - called from SCP, flags in DIB's */ - -t_stat ptr_reset (DEVICE *dptr) -{ -ptr_dib.cmd = ptr_dib.ctl = 0; /* clear cmd, ctl */ -ptr_dib.flg = ptr_dib.fbf = 1; /* set flg, fbf */ -ptr_unit.buf = 0; -sim_cancel (&ptr_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Paper tape reader bootstrap routine (HP 12992K ROM) */ - -#define LDR_BASE 077 -#define CHANGE_DEV (1 << 24) - -static const int32 pboot[IBL_LNT] = { - 0107700, /*ST CLC 0,C ; intr off */ - 0002401, /* CLA,RSS ; skip in */ - 0063756, /*CN LDA M11 ; feed frame */ - 0006700, /* CLB,CCE ; set E to rd byte */ - 0017742, /* JSB READ ; get #char */ - 0007306, /* CMB,CCE,INB,SZB ; 2's comp */ - 0027713, /* JMP *+5 ; non-zero byte */ - 0002006, /* INA,SZA ; feed frame ctr */ - 0027703, /* JMP *-3 */ - 0102077, /* HLT 77B ; stop */ - 0027700, /* JMP ST ; next */ - 0077754, /* STA WC ; word in rec */ - 0017742, /* JSB READ ; get feed frame */ - 0017742, /* JSB READ ; get address */ - 0074000, /* STB 0 ; init csum */ - 0077755, /* STB AD ; save addr */ - 0067755, /*CK LDB AD ; check addr */ - 0047777, /* ADB MAXAD ; below loader */ - 0002040, /* SEZ ; E =0 => OK */ - 0027740, /* JMP H55 */ - 0017742, /* JSB READ ; get word */ - 0040001, /* ADA 1 ; cont checksum */ - 0177755, /* STA AD,I ; store word */ - 0037755, /* ISZ AD */ - 0000040, /* CLE ; force wd read */ - 0037754, /* ISZ WC ; block done? */ - 0027720, /* JMP CK ; no */ - 0017742, /* JSB READ ; get checksum */ - 0054000, /* CPB 0 ; ok? */ - 0027702, /* JMP CN ; next block */ - 0102011, /* HLT 11 ; bad csum */ - 0027700, /* JMP ST ; next */ - 0102055, /*H55 HALT 55 ; bad address */ - 0027700, /* JMP ST ; next */ - 0000000, /*RD 0 */ - 0006600, /* CLB,CME ; E reg byte ptr */ - 0103700+CHANGE_DEV, /* STC RDR,C ; start reader */ - 0102300+CHANGE_DEV, /* SFS RDR ; wait */ - 0027745, /* JMP *-1 */ - 0106400+CHANGE_DEV, /* MIB RDR ; get byte */ - 0002041, /* SEZ,RSS ; E set? */ - 0127742, /* JMP RD,I ; no, done */ - 0005767, /* BLF,CLE,BLF ; shift byte */ - 0027744, /* JMP RD+2 ; again */ - 0000000, /*WC 000000 ; word count */ - 0000000, /*AD 000000 ; address */ - 0177765, /*M11 -11 ; feed count */ - 0, 0, 0, 0, 0, 0, 0, 0, /* unused */ - 0, 0, 0, 0, 0, 0, 0, /* unused */ - 0000000 }; /*MAXAD -ST ; max addr */ - -t_stat ptr_boot (int32 unitno, DEVICE *dptr) -{ -int32 i, dev; - -dev = ptr_dib.devno; /* get device no */ -PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */ -SR = IBL_PTR + (dev << IBL_V_DEV); /* set SR */ -for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */ - if (pboot[i] & CHANGE_DEV) /* IO instr? */ - M[PC + i] = (pboot[i] + dev) & DMASK; - else M[PC + i] = pboot[i]; } -M[PC + LDR_BASE] = (~PC + 1) & DMASK; -return SCPE_OK; -} - -/* Paper tape punch: IOT routine */ - -int32 ptpio (int32 inst, int32 IR, int32 dat) -{ -int32 dev; - -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - if ((ptp_unit.flags & UNIT_ATT) == 0) - dat = dat | PTP_LOW; /* out of tape? */ - break; -case ioOTX: /* output */ - ptp_unit.buf = dat; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCMD (dev); /* clear cmd, ctl */ - clrCTL (dev); } - else { /* STC */ - setCMD (dev); /* set cmd, ctl */ - setCTL (dev); - sim_activate (&ptp_unit, ptp_unit.wait); } - break; -default: - break; } -if (IR & I_HC) { clrFLG (dev); } /* H/C option */ -return dat; -} - -/* Unit service */ - -t_stat ptp_svc (UNIT *uptr) -{ -int32 dev; - -dev = ptp_dib.devno; /* get device no */ -clrCMD (dev); /* clear cmd */ -setFLG (dev); /* set flag */ -if ((ptp_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptp_stopioe, SCPE_UNATT); -if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { /* output byte */ - perror ("PTP I/O error"); - clearerr (ptp_unit.fileref); - return SCPE_IOERR; } -ptp_unit.pos = ftell (ptp_unit.fileref); /* update position */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptp_reset (DEVICE *dptr) -{ -ptp_dib.cmd = ptp_dib.ctl = 0; /* clear cmd, ctl */ -ptp_dib.flg = ptp_dib.fbf = 1; /* set flg, fbf */ -ptp_unit.buf = 0; -sim_cancel (&ptp_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Terminal: IOT routine */ - -int32 ttyio (int32 inst, int32 IR, int32 dat) -{ -int32 dev; - -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - dat = dat | tty_buf; - if (!(tty_mode & TM_KBD) && sim_is_active (&tty_unit[TTO])) - dat = dat | TP_BUSY; - break; -case ioOTX: /* output */ - if (dat & TM_MODE) tty_mode = dat & (TM_KBD|TM_PRI|TM_PUN); - tty_buf = dat & 0377; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { clrCTL (dev); } /* CLC */ - else { /* STC */ - setCTL (dev); - if (!(tty_mode & TM_KBD)) /* output? */ - sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); } - break; -default: - break; } -if (IR & I_HC) { clrFLG (dev); } /* H/C option */ -return dat; -} - -/* Unit service routines */ - -t_stat tto_out (int32 c) -{ -t_stat ret = SCPE_OK; - -if (tty_mode & TM_PRI) { /* printing? */ - if (tty_unit[TTO].flags & UNIT_UC) { /* UC only? */ - c = c & 0177; - if (islower (c)) c = toupper (c); } - else c = c & ((tty_unit[TTO].flags & UNIT_8B)? 0377: 0177); - ret = sim_putchar (c); /* output char */ - tty_unit[TTO].pos = tty_unit[TTO].pos + 1; } -if (tty_mode & TM_PUN) { /* punching? */ - if ((tty_unit[TTP].flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ttp_stopioe, SCPE_UNATT); - if (putc (c, tty_unit[TTP].fileref) == EOF) { /* output char */ - perror ("TTP I/O error"); - clearerr (tty_unit[TTP].fileref); - return SCPE_IOERR; } - tty_unit[TTP].pos = ftell (tty_unit[TTP].fileref); } -return ret; -} - -t_stat tti_svc (UNIT *uptr) -{ -int32 c, dev; - -dev = tty_dib.devno; /* get device no */ -sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* continue poll */ -if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -if (c & SCPE_BREAK) c = 0; /* break? */ -else if (tty_unit[TTI].flags & UNIT_UC) { /* UC only? */ - c = c & 0177; - if (islower (c)) c = toupper (c); } -else c = c & ((tty_unit[TTI].flags & UNIT_8B)? 0377: 0177); -if (tty_mode & TM_KBD) { /* keyboard enabled? */ - tty_buf = c; /* put char in buf */ - tty_unit[TTI].pos = tty_unit[TTI].pos + 1; - setFLG (dev); /* set flag */ - if (c) return tto_out (c); } /* echo or punch? */ -return SCPE_OK; -} - -t_stat tto_svc (UNIT *uptr) -{ -int32 c, dev; - -dev = tty_dib.devno; /* get device no */ -setFLG (dev); /* set done flag */ -c = tty_buf; -tty_buf = 0377; /* defang buf */ -return tto_out (c); /* print and/or punch */ -} - -/* Reset routine */ - -t_stat tty_reset (DEVICE *dptr) -{ -tty_dib.cmd = tty_dib.ctl = 0; /* clear cmd, ctl */ -tty_dib.flg = tty_dib.fbf = 1; /* set flg, fbf */ -tty_mode = TM_KBD; /* enable input */ -tty_buf = 0; -sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */ -sim_cancel (&tty_unit[TTO]); /* cancel output */ -return SCPE_OK; -} - -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 u = uptr - tty_dev.units; - -if (u > 1) return SCPE_NOFNC; -tty_unit[TTI].flags = (tty_unit[TTI].flags & ~(UNIT_UC | UNIT_8B)) | val; -tty_unit[TTO].flags = (tty_unit[TTO].flags & ~(UNIT_UC | UNIT_8B)) | val; -return SCPE_OK; -} - -/* Clock: IOT routine */ - -int32 clkio (int32 inst, int32 IR, int32 dat) -{ -int32 dev; - -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioMIX: /* merge */ - dat = dat | clk_error; - break; -case ioLIX: /* load */ - dat = clk_error; - break; -case ioOTX: /* output */ - clk_select = dat & 07; /* save select */ - sim_cancel (&clk_unit); /* stop the clock */ - clrCTL (dev); /* clear control */ - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCTL (dev); /* turn off clock */ - sim_cancel (&clk_unit); } /* deactivate unit */ - else { /* STC */ - setCTL (dev); /* set CTL */ - if (!sim_is_active (&clk_unit)) { /* clock running? */ - sim_activate (&clk_unit, - sim_rtc_init (clk_delay (0))); /* no, start clock */ - clk_ctr = clk_delay (1); } /* set repeat ctr */ - clk_error = 0; } /* clear error */ - break; -default: - break; } -if (IR & I_HC) { clrFLG (dev); } /* H/C option */ -return dat; -} - -/* Unit service */ - -t_stat clk_svc (UNIT *uptr) -{ -int32 tim, dev; - -dev = clk_dib.devno; /* get device no */ -if (!CTL (dev)) return SCPE_OK; /* CTL off? done */ -if (clk_unit.flags & UNIT_DIAG) /* diag mode? */ - tim = clk_delay (0); /* get fixed delay */ -else tim = sim_rtc_calb (clk_tps[clk_select]); /* calibrate delay */ -sim_activate (uptr, tim); /* reactivate */ -clk_ctr = clk_ctr - 1; /* decrement counter */ -if (clk_ctr <= 0) { /* end of interval? */ - tim = FLG (dev); - if (FLG (dev)) clk_error = CLK_ERROR; /* overrun? error */ - else { setFLG (dev); } /* else set flag */ - clk_ctr = clk_delay (1); } /* reset counter */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat clk_reset (DEVICE *dptr) -{ -clk_dib.cmd = clk_dib.ctl = 0; /* clear cmd, ctl */ -clk_dib.flg = clk_dib.fbf = 1; /* set flg, fbf */ -clk_error = 0; /* clear error */ -clk_select = 0; /* clear select */ -clk_ctr = 0; /* clear counter */ -sim_cancel (&clk_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Clock delay routine */ - -int32 clk_delay (int32 flg) -{ -int32 sel = clk_select; - -if ((clk_unit.flags & UNIT_DIAG) && (sel >= 4)) sel = sel - 3; -if (flg) return clk_rpt[sel]; -else return clk_time[sel]; -} diff --git a/HP2100/hp2100_sys.c b/HP2100/hp2100_sys.c deleted file mode 100644 index f0fce56a..00000000 --- a/HP2100/hp2100_sys.c +++ /dev/null @@ -1,580 +0,0 @@ -/* hp2100_sys.c: HP 2100 simulator interface - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 22-Mar-02 RMS Revised for dynamically allocated memory - 14-Feb-02 RMS Added DMS instructions - 04-Feb-02 RMS Fixed bugs in alter/skip display and parsing - 01-Feb-02 RMS Added terminal multiplexor support - 16-Jan-02 RMS Added additional device support - 17-Sep-01 RMS Removed multiconsole support - 27-May-01 RMS Added multiconsole support - 14-Mar-01 RMS Revised load/dump interface (again) - 30-Oct-00 RMS Added examine to file support - 15-Oct-00 RMS Added dynamic device number support - 27-Oct-98 RMS V2.4 load interface -*/ - -#include "hp2100_defs.h" -#include - -extern DEVICE cpu_dev; -extern UNIT cpu_unit; -extern DEVICE dma0_dev, dma1_dev; -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE tty_dev, clk_dev; -extern DEVICE lps_dev, lpt_dev; -extern DEVICE mtd_dev, mtc_dev; -extern DEVICE msd_dev, msc_dev; -extern DEVICE dpd_dev, dpc_dev; -extern DEVICE dqd_dev, dqc_dev; -extern DEVICE drd_dev, drc_dev; -extern DEVICE muxl_dev, muxu_dev, muxc_dev; -extern DEVICE ipli_dev, iplo_dev; -extern REG cpu_reg[]; -extern uint16 *M; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax maximum number of words for examine/deposit - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "HP 2100"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 3; - -DEVICE *sim_devices[] = { - &cpu_dev, - &dma0_dev, - &dma1_dev, - &ptr_dev, - &ptp_dev, - &tty_dev, - &clk_dev, - &lps_dev, - &lpt_dev, - &dpd_dev, &dpc_dev, - &dqd_dev, &dqc_dev, - &drd_dev, &drc_dev, - &mtd_dev, &mtc_dev, - &msd_dev, &msc_dev, - &muxl_dev, &muxu_dev, &muxc_dev, - &ipli_dev, &iplo_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unimplemented instruction", - "Non-existent I/O device", - "HALT instruction", - "Breakpoint", - "Indirect address loop", - "Indirect address interrupt (should not happen!)", - "No connection on interprocessor link" }; - -/* Binary loader - - The binary loader consists of blocks preceded and trailed by zero frames. - A block consists of 16b words (punched big endian), as follows: - - count'xxx - origin - word 0 - : - word count-1 - checksum - - The checksum includes the origin but not the count. -*/ - -int32 fgetw (FILE *fileref) -{ -int c1, c2; - -if ((c1 = fgetc (fileref)) == EOF) return -1; -if ((c2 = fgetc (fileref)) == EOF) return -1; -return ((c1 & 0377) << 8) | (c2 & 0377); -} - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 origin, csum, zerocnt, count, word, i; - -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; -for (zerocnt = 1;; zerocnt = -10) { /* block loop */ - for (;; zerocnt++) { /* skip 0's */ - if ((count = fgetc (fileref)) == EOF) return SCPE_OK; - else if (count) break; - else if (zerocnt == 0) return SCPE_OK; } - if (fgetc (fileref) == EOF) return SCPE_FMT; - if ((origin = fgetw (fileref)) < 0) return SCPE_FMT; - csum = origin; /* seed checksum */ - for (i = 0; i < count; i++) { /* get data words */ - if ((word = fgetw (fileref)) < 0) return SCPE_FMT; - if (MEM_ADDR_OK (origin)) M[origin] = word; - origin = origin + 1; - csum = csum + word; } - if ((word = fgetw (fileref)) < 0) return SCPE_FMT; - if ((word ^ csum) & DMASK) return SCPE_CSUM; } -return SCPE_OK; -} - -/* Symbol tables */ - -#define I_V_FL 16 /* flag start */ -#define I_M_FL 017 /* flag mask */ -#define I_V_NPN 0 /* no operand */ -#define I_V_NPC 1 /* no operand + C */ -#define I_V_MRF 2 /* mem ref */ -#define I_V_ASH 3 /* alter/skip, shift */ -#define I_V_ESH 4 /* extended shift */ -#define I_V_EMR 5 /* extended mem ref */ -#define I_V_IO1 6 /* I/O + HC */ -#define I_V_IO2 7 /* I/O only */ -#define I_V_EGZ 010 /* ext grp, 1 op + 0 */ -#define I_V_EG2 011 /* ext grp, 2 op */ -#define I_NPN (I_V_NPN << I_V_FL) -#define I_NPC (I_V_NPC << I_V_FL) -#define I_MRF (I_V_MRF << I_V_FL) -#define I_ASH (I_V_ASH << I_V_FL) -#define I_ESH (I_V_ESH << I_V_FL) -#define I_EMR (I_V_EMR << I_V_FL) -#define I_IO1 (I_V_IO1 << I_V_FL) -#define I_IO2 (I_V_IO2 << I_V_FL) -#define I_EGZ (I_V_EGZ << I_V_FL) -#define I_EG2 (I_V_EG2 << I_V_FL) - -static const int32 masks[] = { - 0177777, 0176777, 0074000, 0170000, - 0177760, 0177777, 0176700, 0177700, - 0177777, 0177777 }; - -static const char *opcode[] = { - "NOP", "NOP", "AND", "JSB", - "XOR", "JMP", "IOR", "ISZ", - "ADA", "ADB" ,"CPA", "CPB", - "LDA", "LDB", "STA", "STB", - "DIAG", "ASL", "LSL", "TIMER", - "RRL", "ASR", "LSR", "RRR", - "MPY", "DIV", "DLD", "DST", - "FAD", "FSB", "FMP", "FDV", - "FIX", "FLT", - "STO", "CLO", "SOC", "SOS", - "HLT", "STF", "CLF", - "SFC", "SFS", "MIA", "MIB", - "LIA", "LIB", "OTA", "OTB", - "STC", "CLC", - "SYA", "USA", "PAA", "PBA", - "XMA", - "XLA", "XSA", "XCA", "LFA", - "RSA", "RVA", - "MBI", "MBF", - "MBW", "MWI", "MWF", "MWW", - "SYB", "USB", "PAB", "PBB", - "SSM", "JRS", - "XMM", "XMS", "XMB", - "XLB", "XSB", "XCB", "LFB", - "RSB", "RVB", "DJP", "DJS", - "SJP", "SJS", "UJP", "UJS", - "SAX", "SBX", "CAX", "CBX", - "LAX", "LBX", "STX", - "CXA", "CXB", "LDX", - "ADX", "XAX", "XBX", - "SAY", "SBY", "CAY", "CBY", - "LAY", "LBY", "STY", - "CYA", "CYB", "LDY", - "ADY", "XAY", "XBY", - "ISX", "DSX", "JLY", "LBT", - "SBT", "MBT", "CBT", "SBT", - "ISY", "DSY", "JPY", "SBS", - "CBS", "TBS", "CMW", "MVW", - NULL, /* decode only */ - NULL }; - -static const int32 opc_val[] = { - 0000000+I_NPN, 0002000+I_NPN, 0010000+I_MRF, 0014000+I_MRF, - 0020000+I_MRF, 0024000+I_MRF, 0030000+I_MRF, 0034000+I_MRF, - 0040000+I_MRF, 0044000+I_MRF, 0050000+I_MRF, 0054000+I_MRF, - 0060000+I_MRF, 0064000+I_MRF, 0070000+I_MRF, 0074000+I_MRF, - 0100000+I_NPN, 0100020+I_ESH, 0100040+I_ESH, 0100060+I_NPN, - 0100100+I_ESH, 0101020+I_ESH, 0101040+I_ESH, 0101100+I_ESH, - 0100200+I_EMR, 0100400+I_EMR, 0104200+I_EMR, 0104400+I_EMR, - 0105000+I_EMR, 0105020+I_EMR, 0105040+I_EMR, 0105060+I_EMR, - 0105100+I_NPN, 0105120+I_NPN, - 0102101+I_NPN, 0103101+I_NPN, 0102201+I_NPC, 0102301+I_NPC, - 0102000+I_IO1, 0102100+I_IO2, 0103100+I_IO2, - 0102200+I_IO2, 0102300+I_IO2, 0102400+I_IO1, 0106400+I_IO1, - 0102500+I_IO1, 0106500+I_IO1, 0102600+I_IO1, 0106600+I_IO1, - 0102700+I_IO1, 0106700+I_IO1, - 0101710+I_NPN, 0101711+I_NPN, 0101712+I_NPN, 0101713+I_NPN, - 0101722+I_NPN, - 0101724+I_EMR, 0101725+I_EMR, 0101726+I_EMR, 0101727+I_NPN, - 0101730+I_NPN, 0101731+I_NPN, - 0105702+I_NPN, 0105703+I_NPN, - 0105704+I_NPN, 0105705+I_NPN, 0105706+I_NPN, 0105707+I_NPN, - 0105710+I_NPN, 0105711+I_NPN, 0105712+I_NPN, 0105713+I_NPN, - 0105714+I_EMR, 0105715+I_EG2, - 0105720+I_NPN, 0105721+I_NPN, 0105722+I_NPN, - 0105724+I_EMR, 0105725+I_EMR, 0105726+I_EMR, 0105727+I_NPN, - 0105730+I_NPN, 0105731+I_NPN, 0105732+I_EMR, 0105733+I_EMR, - 0105734+I_EMR, 0105735+I_EMR, 0105736+I_EMR, 0105737+I_EMR, - 0101740+I_EMR, 0105740+I_EMR, 0101741+I_NPN, 0105741+I_NPN, - 0101742+I_EMR, 0105742+I_EMR, 0105743+I_EMR, - 0101744+I_NPN, 0105744+I_NPN, 0105745+I_EMR, - 0105746+I_EMR, 0101747+I_NPN, 0105747+I_NPN, - 0101750+I_EMR, 0105750+I_EMR, 0101751+I_NPN, 0105751+I_NPN, - 0101752+I_EMR, 0105752+I_EMR, 0105753+I_EMR, - 0101754+I_NPN, 0105754+I_NPN, 0105755+I_EMR, - 0105756+I_EMR, 0101757+I_NPN, 0105757+I_NPN, - 0105760+I_NPN, 0105761+I_NPN, 0105762+I_EMR, 0105763+I_NPN, - 0105764+I_NPN, 0105765+I_EGZ, 0105766+I_EGZ, 0105767+I_NPN, - 0105770+I_NPN, 0105771+I_NPN, 0105772+I_EMR, 0105773+I_EG2, - 0105774+I_EG2, 0105775+I_EG2, 0105776+I_EGZ, 0105777+I_EGZ, - 0000000+I_ASH, /* decode only */ - -1 }; - -/* Decode tables for shift and alter/skip groups */ - -static const char *stab[] = { - "ALS", "ARS", "RAL", "RAR", "ALR", "ERA", "ELA", "ALF", - "BLS", "BRS", "RBL", "RBR", "BLR", "ERB", "ELB", "BLF", - "CLA", "CMA", "CCA", "CLB", "CMB", "CCB", - "SEZ", "CLE", "CLE", "CME", "CCE", - "SSA", "SSB", "SLA", "SLB", - "ALS", "ARS", "RAL", "RAR", "ALR", "ERA", "ELA", "ALF", - "BLS", "BRS", "RBL", "RBR", "BLR", "ERB", "ELB", "BLF", - "INA", "INB", "SZA", "SZB", "RSS", - NULL }; - -static const int32 mtab[] = { - 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, - 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, - 0006400, 0007000, 0007400, 0006400, 0007000, 0007400, - 0002040, 0002040, 0002100, 0002200, 0002300, - 0006020, 0006020, 0004010, 0004010, - 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, - 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, - 0006004, 0006004, 0006002, 0006002, 0002001, - 0 }; - -static const int32 vtab[] = { - 0001000, 0001100, 0001200, 0001300, 0001400, 0001500, 0001600, 0001700, - 0005000, 0005100, 0005200, 0005300, 0005400, 0005500, 0005600, 0005700, - 0002400, 0003000, 0003400, 0006400, 0007000, 0007400, - 0002040, 0000040, 0002100, 0002200, 0002300, - 0002020, 0006020, 0000010, 0004010, - 0000020, 0000021, 0000022, 0000023, 0000024, 0000025, 0000026, 0000027, - 0004020, 0004021, 0004022, 0004023, 0004024, 0004025, 0004026, 0004027, - 0002004, 0006004, 0002002, 0006002, 0002001, - -1 }; - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current PC - *val = pointer to data - *uptr = pointer to unit - sw = switches - Outputs: - return = status code -*/ - -#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, cm, i, j, inst, disp; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -inst = val[0]; -if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; - fprintf (of, FMTASC (inst & 0177)); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* characters? */ - fprintf (of, FMTASC ((inst >> 8) & 0177)); - fprintf (of, FMTASC (inst & 0177)); - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; - -/* Instruction decode */ - -for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */ - - switch (j) { /* case on class */ - case I_V_NPN: /* no operands */ - fprintf (of, "%s", opcode[i]); /* opcode */ - break; - case I_V_NPC: /* no operands + C */ - fprintf (of, "%s", opcode[i]); - if (inst & I_HC) fprintf (of, " C"); - break; - case I_V_MRF: /* mem ref */ - disp = inst & I_DISP; /* displacement */ - fprintf (of, "%s ", opcode[i]); /* opcode */ - if (inst & I_CP) { /* current page? */ - if (cflag) fprintf (of, "%-o", (addr & I_PAGENO) | disp); - else fprintf (of, "C %-o", disp); } - else fprintf (of, "%-o", disp); /* page zero */ - if (inst & I_IA) fprintf (of, ",I"); - break; - case I_V_ASH: /* shift, alter-skip */ - cm = FALSE; - for (i = 0; mtab[i] != 0; i++) { - if ((inst & mtab[i]) == vtab[i]) { - inst = inst & ~(vtab[i] & 01777); - if (cm) fprintf (of, ","); - cm = TRUE; - fprintf (of, "%s", stab[i]); } } - if (!cm) return SCPE_ARG; /* nothing decoded? */ - break; - case I_V_ESH: /* extended shift */ - disp = inst & 017; /* shift count */ - if (disp == 0) disp = 16; - fprintf (of, "%s %d", opcode[i], disp); - break; - case I_V_EMR: /* extended mem ref */ - fprintf (of, "%s %-o", opcode[i], val[1] & VAMASK); - if (val[1] & I_IA) fprintf (of, ",I"); - return -1; /* extra word */ - case I_V_IO1: /* IOT with H/C */ - fprintf (of, "%s %-o", opcode[i], inst & I_DEVMASK); - if (inst & I_HC) fprintf (of, ",C"); - break; - case I_V_IO2: /* IOT */ - fprintf (of, "%s %-o", opcode[i], inst & I_DEVMASK); - break; - case I_V_EGZ: /* ext grp 1 op + 0 */ - fprintf (of, "%s %-o", opcode[i], val[1] & VAMASK); - if (val[1] & I_IA) fprintf (of, ",I"); - return -2; /* extra words */ - case I_V_EG2: /* ext grp 2 op */ - fprintf (of, "%s %-o", opcode[i], val[1] & VAMASK); - if (val[1] & I_IA) fprintf (of, ",I"); - fprintf (of, " %-o", val[2] & VAMASK); - if (val[2] & I_IA) fprintf (of, ",I"); - return -2; } /* extra words */ - return SCPE_OK; } /* end if */ - } /* end for */ -return SCPE_ARG; -} - -/* Get address with indirection - - Inputs: - *cptr = pointer to input string - Outputs: - val = address - -1 if error -*/ - -int32 get_addr (char *cptr) -{ -int32 d; -t_stat r; -char gbuf[CBUFSIZE]; - -cptr = get_glyph (cptr, gbuf, ','); /* get next field */ -d = get_uint (gbuf, 8, VAMASK, &r); /* construe as addr */ -if (r != SCPE_OK) return -1; -if (*cptr != 0) { /* more? */ - cptr = get_glyph (cptr, gbuf, 0); /* look for indirect */ - if (*cptr != 0) return -1; /* should be done */ - if (strcmp (gbuf, "I")) return -1; /* I? */ - d = d | I_IA; } -return d; -} - -/* Symbolic input - - Inputs: - *iptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = error status -*/ - -t_stat parse_sym (char *iptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 cflag, d, i, j, k, clef, tbits; -t_stat r, ret; -char *cptr, gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*iptr)) iptr++; /* absorb spaces */ -if ((sw & SWMASK ('A')) || ((*iptr == '\'') && iptr++)) { /* ASCII char? */ - if (iptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (t_value) iptr[0] & 0177; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*iptr == '"') && iptr++)) { /* char string? */ - if (iptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (((t_value) iptr[0] & 0177) << 8) | - ((t_value) iptr[1] & 0177); - return SCPE_OK; } - -/* Instruction parse */ - -ret = SCPE_OK; -cptr = get_glyph (iptr, gbuf, 0); /* get opcode */ -for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; -if (opcode[i]) { /* found opcode? */ - val[0] = opc_val[i] & DMASK; /* get value */ - j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - - switch (j) { /* case on class */ - case I_V_NPN: /* no operand */ - break; - case I_V_NPC: /* no operand + C */ - if (*cptr != 0) { - cptr = get_glyph (cptr, gbuf, 0); - if (strcmp (gbuf, "C")) return SCPE_ARG; - val[0] = val[0] | I_HC; } - break; - case I_V_MRF: /* mem ref */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - if (k = (strcmp (gbuf, "C") == 0)) { /* C specified? */ - val[0] = val[0] | I_CP; - cptr = get_glyph (cptr, gbuf, 0); } - else if (k = (strcmp (gbuf, "Z") == 0)) { /* Z specified? */ - cptr = get_glyph (cptr, gbuf, ','); } - if ((d = get_addr (gbuf)) < 0) return SCPE_ARG; - if ((d & VAMASK) <= I_DISP) val[0] = val[0] | d; - else if (cflag && !k && (((addr ^ d) & I_PAGENO) == 0)) - val[0] = val[0] | (d & (I_IA | I_DISP)) | I_CP; - else return SCPE_ARG; - break; - case I_V_ESH: /* extended shift */ - cptr = get_glyph (cptr, gbuf, 0); - d = get_uint (gbuf, 10, 16, &r); - if ((r != SCPE_OK) || (d == 0)) return SCPE_ARG; - val[0] = val[0] | (d & 017); - break; - case I_V_EMR: /* extended mem ref */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - if ((d = get_addr (gbuf)) < 0) return SCPE_ARG; - val[1] = d; - ret = -1; - break; - case I_V_IO1: /* IOT + optional C */ - cptr = get_glyph (cptr, gbuf, ','); /* get device */ - d = get_uint (gbuf, 8, I_DEVMASK, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | d; - if (*cptr != 0) { - cptr = get_glyph (cptr, gbuf, 0); - if (strcmp (gbuf, "C")) return SCPE_ARG; - val[0] = val[0] | I_HC; } - break; - case I_V_IO2: /* IOT */ - cptr = get_glyph (cptr, gbuf, 0); /* get device */ - d = get_uint (gbuf, 8, I_DEVMASK, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | d; - break; - case I_V_EGZ: /* ext grp 1 op + 0 */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - if ((d = get_addr (gbuf)) < 0) return SCPE_ARG; - val[1] = d; - val[2] = 0; - ret = -2; - break; - case I_V_EG2: /* ext grp 2 op */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - if ((d = get_addr (gbuf)) < 0) return SCPE_ARG; - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - if ((k = get_addr (gbuf)) < 0) return SCPE_ARG; - val[1] = d; - val[2] = k; - ret = -2; - break; } /* end case */ - if (*cptr != 0) return SCPE_ARG; /* junk at end? */ - return ret; - } /* end if opcode */ - -/* Shift or alter-skip - - Each opcode is matched by a mask, specifiying the bits affected, and - the value, specifying the value. As opcodes are processed, the mask - values are used to specify which fields have already been filled in. - - The mask has two subfields, the type bits (A/B and A/S), and the field - bits. The type bits, once specified by any instruction, must be - consistent in all other instructions. The mask bits assure that no - field is filled in twice. - - Two special cases: - - 1. The dual shift field in shift requires checking how much of the - target word has been filled in before assigning the shift value. - To implement this, shifts are listed twice is the decode table. - If the current subopcode is a shift in the first part of the table - (entries 0..15), and CLE has been seen or the first shift field is - filled in, the code forces a mismatch. The glyph will match in - the second part of the table. - - 2. CLE processing must be deferred until the instruction can be - classified as shift or alter-skip, since it has two different - bit values in the two classes. To implement this, CLE seen is - recorded as a flag and processed after all other subopcodes. -*/ - -clef = FALSE; -tbits = 0; -val[0] = 0; -for (cptr = get_glyph (iptr, gbuf, ','); gbuf[0] != 0; - cptr = get_glyph (cptr, gbuf, ',')) { /* loop thru glyphs */ - if (strcmp (gbuf, "CLE") == 0) { /* CLE? */ - if (clef) return SCPE_ARG; /* already seen? */ - clef = TRUE; /* set flag */ - continue; } - for (i = 0; stab[i] != NULL; i++) { /* find subopcode */ - if ((strcmp (gbuf, stab[i]) == 0) && - ((i >= 16) || (!clef && ((val[0] & 001710) == 0)))) break; } - if (stab[i] == NULL) return SCPE_ARG; - if (tbits & mtab[i] & (I_AB | I_ASKP) & (vtab[i] ^ val[0])) - return SCPE_ARG; - if (tbits & mtab[i] & ~(I_AB | I_ASKP)) return SCPE_ARG; - tbits = tbits | mtab[i]; /* fill type+mask */ - val[0] = val[0] | vtab[i]; } /* fill value */ -if (clef) { /* CLE seen? */ - if (val[0] & I_ASKP) { /* alter-skip? */ - if (tbits & 0100) return SCPE_ARG; /* already filled in? */ - else val[0] = val[0] | 0100; } - else val[0] = val[0] | 040; } /* fill in shift */ -return ret; -} diff --git a/I1401/i1401_cd.c b/I1401/i1401_cd.c deleted file mode 100644 index 666c2b50..00000000 --- a/I1401/i1401_cd.c +++ /dev/null @@ -1,282 +0,0 @@ -/* i1401_cd.c: IBM 1402 card reader/punch - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - cdr card reader - cdp card punch - stack stackers (5 units) - 0 normal - 1 1 - 2 2/8 - 3 unused - 4 4 - - Cards are represented as ASCII text streams terminated by newlines. - This allows cards to be created and edited as normal files. - - 25-Apr-03 RMS Revised for extended file support - 30-May-02 RMS Widened POS to 32b - 30-Jan-02 RMS New zero footprint card bootstrap from Van Snyder - 29-Nov-01 RMS Added read only unit support - 13-Apr-01 RMS Revised for register arrays -*/ - -#include "i1401_defs.h" -#include - -extern uint8 M[]; -extern int32 ind[64], ssa, iochk; -extern char bcd_to_ascii[64]; -extern char ascii_to_bcd[128]; -int32 s1sel, s2sel, s4sel, s8sel; -char rbuf[CBUFSIZE]; /* > CDR_WIDTH */ -t_stat cdr_svc (UNIT *uptr); -t_stat cdr_boot (int32 unitno, DEVICE *dptr); -t_stat cdr_attach (UNIT *uptr, char *cptr); -t_stat cd_reset (DEVICE *dptr); - -/* Card reader data structures - - cdr_dev CDR descriptor - cdr_unit CDR unit descriptor - cdr_reg CDR register list -*/ - -UNIT cdr_unit = { - UDATA (&cdr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), 100 }; - -REG cdr_reg[] = { - { FLDATA (LAST, ind[IN_LST], 0) }, - { FLDATA (ERR, ind[IN_READ], 0) }, - { FLDATA (S1, s1sel, 0) }, - { FLDATA (S2, s2sel, 0) }, - { DRDATA (POS, cdr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, cdr_unit.wait, 24), PV_LEFT }, - { BRDATA (BUF, rbuf, 8, 8, CDR_WIDTH) }, - { NULL } }; - -DEVICE cdr_dev = { - "CDR", &cdr_unit, cdr_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &cd_reset, - &cdr_boot, &cdr_attach, NULL }; - -/* CDP data structures - - cdp_dev CDP device descriptor - cdp_unit CDP unit descriptor - cdp_reg CDP register list -*/ - -UNIT cdp_unit = { - UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }; - -REG cdp_reg[] = { - { FLDATA (ERR, ind[IN_PNCH], 0) }, - { FLDATA (S4, s4sel, 0) }, - { FLDATA (S8, s8sel, 0) }, - { DRDATA (POS, cdp_unit.pos, T_ADDR_W), PV_LEFT }, - { NULL } }; - -DEVICE cdp_dev = { - "CDP", &cdp_unit, cdp_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &cd_reset, - NULL, NULL, NULL }; - -/* Stacker data structures - - stack_dev STACK device descriptor - stack_unit STACK unit descriptors - stack_reg STACK register list -*/ - -UNIT stack_unit[] = { - { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }, - { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }, - { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }, - { UDATA (NULL, UNIT_DIS, 0) }, /* unused */ - { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) } }; - -REG stack_reg[] = { - { DRDATA (POS0, stack_unit[0].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (POS1, stack_unit[1].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (POS28, stack_unit[2].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (POS4, stack_unit[4].pos, T_ADDR_W), PV_LEFT }, - { NULL } }; - -DEVICE stack_dev = { - "STKR", stack_unit, stack_reg, NULL, - 5, 10, 31, 1, 8, 7, - NULL, NULL, &cd_reset, - NULL, NULL, NULL }; - -/* Card read routine - - Modifiers have been checked by the caller - No modifiers are recognized (column binary is not implemented) -*/ - -t_stat read_card (int32 ilnt, int32 mod) -{ -int32 i; -t_stat r; - -if (sim_is_active (&cdr_unit)) { /* busy? */ - sim_cancel (&cdr_unit); /* cancel */ - if (r = cdr_svc (&cdr_unit)) return r; } /* process */ -if ((cdr_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ -ind[IN_READ] = ind[IN_LST] = s1sel = s2sel = 0; /* default stacker */ -for (i = 0; i < CBUFSIZE; i++) rbuf[i] = 0; /* clear buffer */ -fgets (rbuf, CBUFSIZE, cdr_unit.fileref); /* read card */ -if (feof (cdr_unit.fileref)) return STOP_NOCD; /* eof? */ -if (ferror (cdr_unit.fileref)) { /* error? */ - perror ("Card reader I/O error"); - clearerr (cdr_unit.fileref); - if (iochk) return SCPE_IOERR; - ind[IN_READ] = 1; - return SCPE_OK; } -cdr_unit.pos = ftell (cdr_unit.fileref); /* update position */ -if (ssa) { /* if last cd on */ - getc (cdr_unit.fileref); /* see if more */ - if (feof (cdr_unit.fileref)) ind[IN_LST] = 1; /* eof? set flag */ - fseek (cdr_unit.fileref, cdr_unit.pos, SEEK_SET); } -for (i = 0; i < CDR_WIDTH; i++) { /* cvt to BCD */ - rbuf[i] = ascii_to_bcd[rbuf[i]]; - M[CDR_BUF + i] = (M[CDR_BUF + i] & WM) | rbuf[i]; } -M[CDR_BUF - 1] = 060; /* mem mark */ -sim_activate (&cdr_unit, cdr_unit.wait); /* activate */ -return SCPE_OK; -} - -/* Card reader service. If a stacker select is active, copy to the - selected stacker. Otherwise, copy to the normal stacker. If the - unit is unattached, simply exit. -*/ - -t_stat cdr_svc (UNIT *uptr) -{ -int32 i; - -if (s1sel) uptr = &stack_unit[1]; /* stacker 1? */ -else if (s2sel) uptr = &stack_unit[2]; /* stacker 2? */ -else uptr = &stack_unit[0]; /* then default */ -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ -for (i = 0; i < CDR_WIDTH; i++) rbuf[i] = bcd_to_ascii[rbuf[i]]; -for (i = CDR_WIDTH - 1; (i >= 0) && (rbuf[i] == ' '); i--) rbuf[i] = 0; -rbuf[CDR_WIDTH] = 0; /* null at end */ -fputs (rbuf, uptr->fileref); /* write card */ -fputc ('\n', uptr->fileref); /* plus new line */ -if (ferror (uptr->fileref)) { /* error? */ - perror ("Card stacker I/O error"); - clearerr (uptr->fileref); - if (iochk) return SCPE_IOERR; } -uptr->pos = ftell (uptr->fileref); /* update position */ -return SCPE_OK; -} - -/* Card punch routine - - Modifiers have been checked by the caller - No modifiers are recognized (column binary is not implemented) -*/ - -t_stat punch_card (int32 ilnt, int32 mod) -{ -int32 i; -static char pbuf[CDP_WIDTH + 1]; /* + null */ -UNIT *uptr; - -if (s8sel) uptr = &stack_unit[2]; /* stack 8? */ -else if (s4sel) uptr = &stack_unit[4]; /* stack 4? */ -else uptr = &cdp_unit; /* normal output */ -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ -ind[IN_PNCH] = s4sel = s8sel = 0; /* clear flags */ - -M[CDP_BUF - 1] = 012; /* set prev loc */ -for (i = 0; i < CDP_WIDTH; i++) pbuf[i] = bcd_to_ascii[M[CDP_BUF + i] & CHAR]; -for (i = CDP_WIDTH - 1; (i >= 0) && (pbuf[i] == ' '); i--) pbuf[i] = 0; -pbuf[CDP_WIDTH] = 0; /* trailing null */ -fputs (pbuf, uptr->fileref); /* output card */ -fputc ('\n', uptr->fileref); /* plus new line */ -if (ferror (uptr->fileref)) { /* error? */ - perror ("Card punch I/O error"); - clearerr (uptr->fileref); - if (iochk) return SCPE_IOERR; - ind[IN_PNCH] = 1; } -uptr->pos = ftell (uptr->fileref); /* update position */ -return SCPE_OK; -} - -/* Select stack routine - - Modifiers have been checked by the caller - Modifiers are 1, 2, 4, 8 for the respective stack -*/ - -t_stat select_stack (int32 ilnt, int32 mod) -{ -if (mod == 1) s1sel = 1; -else if (mod == 2) s2sel = 1; -else if (mod == 4) s4sel = 1; -else if (mod == 8) s8sel = 1; -return SCPE_OK; -} - -/* Card reader/punch reset */ - -t_stat cd_reset (DEVICE *dptr) -{ -ind[IN_LST] = ind[IN_READ] = ind[IN_PNCH] = 0; /* clear indicators */ -s1sel = s2sel = s4sel = s8sel = 0; /* clear stacker sel */ -sim_cancel (&cdr_unit); /* clear reader event */ -return SCPE_OK; -} - -/* Card reader attach */ - -t_stat cdr_attach (UNIT *uptr, char *cptr) -{ -ind[IN_LST] = ind[IN_READ] = 0; /* clear last card */ -return attach_unit (uptr, cptr); -} - -/* Bootstrap routine */ - -#define BOOT_START 0 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (unsigned char)) - -static const unsigned char boot_rom[] = { - OP_R + WM, OP_NOP + WM }; /* R, NOP */ - -t_stat cdr_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_IS; - -for (i = 0; i < CDR_WIDTH; i++) M[CDR_BUF + i] = 0; /* clear buffer */ -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_IS = BOOT_START; -return SCPE_OK; -} diff --git a/I1401/i1401_cpu.c b/I1401/i1401_cpu.c deleted file mode 100644 index bee63ac9..00000000 --- a/I1401/i1401_cpu.c +++ /dev/null @@ -1,1563 +0,0 @@ -/* i1401_cpu.c: IBM 1401 CPU simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 12-Jul-03 RMS Moved ASCII/BCD tables to included file - Revised fetch to model hardware - Removed length checking in fetch phase - 16-Mar-03 RMS Fixed mnemonic, instruction lengths, and reverse - scan length check bug for MCS - Fixed MCE bug, BS off by 1 if zero suppress - Fixed chaining bug, D lost if return to SCP - Fixed H branch, branch occurs after continue - Added check for invalid 8 character MCW, LCA - 03-Jun-03 RMS Added 1311 support - 22-May-02 RMS Added multiply and divide - 30-Dec-01 RMS Added old PC queue - 30-Nov-01 RMS Added extended SET/SHOW support - 10-Aug-01 RMS Removed register in declarations - 07-Dec-00 RMS Fixed bugs found by Charles Owen - -- 4,7 char NOPs are legal - -- 1 char B is chained BCE - -- MCE moves whole char after first - 14-Apr-99 RMS Changed t_addr to unsigned - - The register state for the IBM 1401 is: - - IS I storage address register (PC) - AS A storage address register (address of first operand) - BS B storage address register (address of second operand) - ind[0:63] indicators - SSA sense switch A - IOCHK I/O check - PRCHK process check - - The IBM 1401 is a variable instruction length, decimal data system. - Memory consists of 4000, 8000, 12000, or 16000 BCD characters, each - containing six bits of data and a word mark. There are no general - registers; all instructions are memory to memory, using explicit - addresses or an address pointer from a prior instruction. - - BCD numeric data consists of the low four bits of a character (DIGIT), - encoded as X, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, X, X, X, X, X. The high - two bits (ZONE) encode the sign of the data as +, +, -, +. Character - data uses all six bits of a character. Numeric and character fields are - delimited by a word mark. Fields are typically processed in descending - address order (low-order data to high-order data). - - The 1401 encodes a decimal address, and an index register number, in - three characters: - - character zone digit - addr + 0 <1:0> of thousands hundreds - addr + 1 index register # tens - addr + 2 <3:2> of thousands ones - - Normally the digit values 0, 11, 12, 13, 14, 15 are illegal in addresses. - However, in indexing, digits are passed through the adder, and illegal - values are normalized to legal counterparts. - - The 1401 has six instruction formats: - - op A and B addresses, if any, from AS and BS - op d A and B addresses, if any, from AS and BS - op aaa B address, if any, from BS - op aaa d B address, if any, from BS - op aaa bbb - op aaa bbb d - - where aaa is the A address, bbb is the B address, and d is a modifier. - The opcode has word mark set; all other characters have word mark clear. -*/ - -/* This routine is the instruction decode routine for the IBM 1401. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - breakpoint encountered - illegal addresses or instruction formats - I/O error in I/O simulator - - 2. Interrupts. The 1401 has no interrupt structure. - - 3. Non-existent memory. On the 1401, references to non-existent - memory halt the processor. - - 4. Adding I/O devices. These modules must be modified: - - i1401_cpu.c add device dispatching code to iodisp - i1401_sys.c add sim_devices table entry -*/ - -#include "i1401_defs.h" -#include "i1401_dat.h" - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = saved_IS - -/* These macros validate addresses. If an addresses error is detected, - they return an error status to the caller. These macros should only - be used in a routine that returns a t_stat value. -*/ - -#define MM(x) x = x - 1; \ - if (x < 0) { \ - x = BA + MAXMEMSIZE - 1; \ - reason = STOP_WRAP; \ - break; } - -#define PP(x) x = x + 1; \ - if (ADDR_ERR (x)) { \ - x = BA + (x % MAXMEMSIZE); \ - reason = STOP_WRAP; \ - break; } - -#define BRANCH if (ADDR_ERR (AS)) { \ - reason = STOP_INVBR; \ - break; } \ - if (cpu_unit.flags & XSA) BS = IS; \ - else BS = BA + 0; \ - PCQ_ENTRY; \ - IS = AS; - -uint8 M[MAXMEMSIZE] = { 0 }; /* main memory */ -int32 saved_IS = 0; /* saved IS */ -int32 AS = 0; /* AS */ -int32 BS = 0; /* BS */ -int32 D = 0; /* modifier */ -int32 as_err = 0, bs_err = 0; /* error flags */ -int32 hb_pend = 0; /* halt br pending */ -uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -int32 ind[64] = { 0 }; /* indicators */ -int32 ssa = 1; /* sense switch A */ -int32 prchk = 0; /* process check stop */ -int32 iochk = 0; /* I/O check stop */ -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -int32 store_addr_h (int32 addr); -int32 store_addr_t (int32 addr); -int32 store_addr_u (int32 addr); -int32 div_add (int32 ap, int32 bp, int32 aend); -int32 div_sub (int32 ap, int32 bp, int32 aend); -void div_sign (int32 dvrc, int32 dvdc, int32 qp, int32 rp); -t_stat iomod (int32 ilnt, int32 mod, const int32 *tptr); -t_stat iodisp (int32 dev, int32 unit, int32 flag, int32 mod); - -extern t_stat read_card (int32 ilnt, int32 mod); -extern t_stat punch_card (int32 ilnt, int32 mod); -extern t_stat select_stack (int32 mod); -extern t_stat carriage_control (int32 mod); -extern t_stat write_line (int32 ilnt, int32 mod); -extern t_stat inq_io (int32 flag, int32 mod); -extern t_stat mt_io (int32 unit, int32 flag, int32 mod); -extern t_stat dp_io (int32 fnc, int32 flag, int32 mod); -extern t_stat mt_func (int32 unit, int32 mod); -extern t_stat sim_activate (UNIT *uptr, int32 delay); - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifier list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BCD + STDOPT, - MAXMEMSIZE) }; - -REG cpu_reg[] = { - { DRDATA (IS, saved_IS, 14), PV_LEFT }, - { DRDATA (AS, AS, 14), PV_LEFT }, - { DRDATA (BS, BS, 14), PV_LEFT }, - { FLDATA (ASERR, as_err, 0) }, - { FLDATA (BSERR, bs_err, 0) }, - { ORDATA (D, D, 7) }, - { FLDATA (SSA, ssa, 0) }, - { FLDATA (SSB, ind[IN_SSB], 0) }, - { FLDATA (SSC, ind[IN_SSC], 0) }, - { FLDATA (SSD, ind[IN_SSD], 0) }, - { FLDATA (SSE, ind[IN_SSE], 0) }, - { FLDATA (SSF, ind[IN_SSF], 0) }, - { FLDATA (SSG, ind[IN_SSG], 0) }, - { FLDATA (EQU, ind[IN_EQU], 0) }, - { FLDATA (UNEQ, ind[IN_UNQ], 0) }, - { FLDATA (HIGH, ind[IN_HGH], 0) }, - { FLDATA (LOW, ind[IN_LOW], 0) }, - { FLDATA (OVF, ind[IN_OVF], 0) }, - { FLDATA (IOCHK, iochk, 0) }, - { FLDATA (PRCHK, prchk, 0) }, - { FLDATA (HBPEND, hb_pend, 0) }, - { BRDATA (ISQ, pcq, 10, 14, PCQ_SIZE), REG_RO+REG_CIRC }, - { DRDATA (ISQP, pcq_p, 6), REG_HRO }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { XSA, XSA, "XSA", "XSA", NULL }, - { XSA, 0, "no XSA", "NOXSA", NULL }, - { HLE, HLE, "HLE", "HLE", NULL }, - { HLE, 0, "no HLE", "NOHLE", NULL }, - { BBE, BBE, "BBE", "BBE", NULL }, - { BBE, 0, "no BBE", "NOBBE", NULL }, - { MA, MA, "MA", 0, NULL }, - { MA, 0, "no MA", 0, NULL }, - { MR, MR, "MR", "MR", NULL }, - { MR, 0, "no MR", "NOMR", NULL }, - { EPE, EPE, "EPE", "EPE", NULL }, - { EPE, 0, "no EPE", "NOEPE", NULL }, - { MDV, MDV, "MDV", "MDV", NULL }, - { MDV, 0, "no MDV", "NOMDV", NULL }, - { UNIT_MSIZE, 4000, NULL, "4K", &cpu_set_size }, - { UNIT_MSIZE, 8000, NULL, "8K", &cpu_set_size }, - { UNIT_MSIZE, 12000, NULL, "12K", &cpu_set_size }, - { UNIT_MSIZE, 16000, NULL, "16K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 10, 14, 1, 8, 7, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -/* Tables */ - -/* Opcode table - length, dispatch, and option flags. This table is - used by the symbolic input routine to validate instruction lengths */ - -const int32 op_table[64] = { - 0, /* 00: illegal */ - L1 | L2 | L4 | L5, /* read */ - L1 | L2 | L4 | L5, /* write */ - L1 | L2 | L4 | L5, /* write and read */ - L1 | L2 | L4 | L5, /* punch */ - L1 | L4, /* read and punch */ - L1 | L2 | L4 | L5, /* write and read */ - L1 | L2 | L4 | L5, /* write, read, punch */ - L1, /* 10: read feed */ - L1, /* punch feed */ - 0, /* illegal */ - L1 | L4 | L7 | AREQ | BREQ | MA, /* modify address */ - L1 | L4 | L7 | AREQ | BREQ | MDV, /* multiply */ - 0, /* illegal */ - 0, /* illegal */ - 0, /* illegal */ - 0, /* 20: illegal */ - L1 | L4 | L7 | BREQ | NOWM, /* clear storage */ - L1 | L4 | L7 | AREQ | BREQ, /* subtract */ - 0, /* illegal */ - L5 | IO, /* magtape */ - L1 | L8 | BREQ, /* branch wm or zone */ - L1 | L8 | BREQ | BBE, /* branch if bit eq */ - 0, /* illegal */ - L1 | L4 | L7 | AREQ | BREQ, /* 30: move zones */ - L1 | L4 | L7 | AREQ | BREQ, /* move supress zero */ - 0, /* illegal */ - L1 | L4 | L7 | AREQ | BREQ | NOWM, /* set word mark */ - L1 | L4 | L7 | AREQ | BREQ | MDV, /* divide */ - 0, /* illegal */ - 0, /* illegal */ - 0, /* illegal */ - 0, /* 40: illegal */ - 0, /* illegal */ - L2 | L5, /* select stacker */ - L1 | L4 | L7 | L8 | BREQ | MLS | IO, /* load */ - L1 | L4 | L7 | L8 | BREQ | MLS | IO, /* move */ - HNOP | L1 | L2 | L4 | L5 | L7 | L8, /* nop */ - 0, /* illegal */ - L1 | L4 | L7 | AREQ | BREQ | MR, /* move to record */ - L1 | L4 | AREQ | MLS, /* 50: store A addr */ - 0, /* illegal */ - L1 | L4 | L7 | AREQ | BREQ, /* zero and subtract */ - 0, /* illegal */ - 0, /* illegal */ - 0, /* illegal */ - 0, /* illegal */ - 0, /* illegal */ - 0, /* 60: illegal */ - L1 | L4 | L7 | AREQ | BREQ, /* add */ - L1 | L4 | L5 | L8, /* branch */ - L1 | L4 | L7 | AREQ | BREQ, /* compare */ - L1 | L4 | L7 | AREQ | BREQ, /* move numeric */ - L1 | L4 | L7 | AREQ | BREQ, /* move char edit */ - L2 | L5, /* carriage control */ - 0, /* illegal */ - L1 | L4 | L7 | AREQ | MLS, /* 70: store B addr */ - 0, /* illegal */ - L1 | L4 | L7 | AREQ | BREQ, /* zero and add */ - HNOP | L1 | L2 | L4 | L5 | L7 | L8, /* halt */ - L1 | L4 | L7 | AREQ | BREQ, /* clear word mark */ - 0, /* illegal */ - 0, /* illegal */ - 0 }; /* illegal */ - -const int32 len_table[9] = { 0, L1, L2, 0, L4, L5, 0, L7, L8 }; - -/* Address character conversion tables. Illegal characters are marked by - the flag BA but also contain the post-adder value for indexing */ - -const int32 hun_table[64] = { - BA+000, 100, 200, 300, 400, 500, 600, 700, - 800, 900, 000, BA+300, BA+400, BA+500, BA+600, BA+700, - BA+1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, - 1800, 1900, 1000, BA+1300, BA+1400, BA+1500, BA+1600, BA+1700, - BA+2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, - 2800, 2900, 2000, BA+2300, BA+2400, BA+2500, BA+2600, BA+2700, - BA+3000, 3100, 3200, 3300, 3400, 3500, 3600, 3700, - 3800, 3900, 3000, BA+3300, BA+3400, BA+3500, BA+3600, BA+3700 }; - -const int32 ten_table[64] = { - BA+00, 10, 20, 30, 40, 50, 60, 70, - 80, 90, 00, BA+30, BA+40, BA+50, BA+60, BA+70, - X1+00, X1+10, X1+20, X1+30, X1+40, X1+50, X1+60, X1+70, - X1+80, X1+90, X1+00, X1+30, X1+40, X1+50, X1+60, X1+70, - X2+00, X2+10, X2+20, X2+30, X2+40, X2+50, X2+60, X2+70, - X2+80, X2+90, X2+00, X2+30, X2+40, X2+50, X2+60, X2+70, - X3+00, X3+10, X3+20, X3+30, X3+40, X3+50, X3+60, X3+70, - X3+80, X3+90, X3+00, X3+30, X3+40, X3+50, X3+60, X3+70 }; - -const int32 one_table[64] = { - BA+0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 0, BA+3, BA+4, BA+5, BA+6, BA+7, - BA+4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, - 4008, 4009, 4000, BA+4003, BA+4004, BA+4005, BA+4006, BA+4007, - BA+8000, 8001, 8002, 8003, 8004, 8005, 8006, 8007, - 8008, 8009, 8000, BA+8003, BA+8004, BA+8005, BA+8006, BA+8007, - BA+12000, 12001, 12002, 12003, 12004, 12005, 12006, 12007, - 12008, 12009, 12000, BA+12003, BA+12004, BA+12005, BA+12006, BA+12007 }; - -const int32 bin_to_bcd[16] = { - 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; - -const int32 bcd_to_bin[16] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 3, 4, 5, 6, 7 }; - -/* Indicator resets - a 1 marks an indicator that resets when tested */ - -static const int32 ind_table[64] = { - 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 07 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 17 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 27 */ - 0, 1, 1 , 0, 1, 0, 0, 0, /* 30 - 37 */ - 0, 0, 1, 0, 0, 0, 0, 0, /* 40 - 47 */ - 0, 0, 1, 0, 1, 0, 0, 0, /* 50 - 57 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 67 */ - 0, 0, 1, 0, 0, 0, 0, 0 }; /* 70 - 77 */ - -/* Character collation table for compare with HLE option */ - -static const int32 col_table[64] = { - 000, 067, 070, 071, 072, 073, 074, 075, - 076, 077, 066, 024, 025, 026, 027, 030, - 023, 015, 056, 057, 060, 061, 062, 063, - 064, 065, 055, 016, 017, 020, 021, 022, - 014, 044, 045, 046, 047, 050, 051, 052, - 053, 054, 043, 007, 010, 011, 012, 013, - 006, 032, 033, 034, 035, 036, 037, 040, - 041, 042, 031, 001, 002, 003, 004, 005 }; - -/* Summing table for two decimal digits, converted back to BCD - Also used for multiplying two decimal digits, converted back to BCD, - with carry forward -*/ - -static const int32 sum_table[100] = { - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE }; - -static const int32 cry_table[100] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 }; - -/* Legal modifier tables */ - -static const int32 w_mod[] = { BCD_S, BCD_SQUARE, -1 }; -static const int32 ss_mod[] = { 1, 2, 4, 8, -1 }; -static const int32 mtf_mod[] = { BCD_B, BCD_E, BCD_M, BCD_R, BCD_U, -1 }; - -t_stat sim_instr (void) -{ -extern int32 sim_interval; -int32 IS, ilnt, flags; -int32 op, xa, t, wm, ioind, dev, unit; -int32 a, b, i, asave, bsave; -int32 carry, lowprd, sign, ps; -int32 quo, ahigh, qs; -int32 qzero, qawm, qbody, qsign, qdollar, qaster, qdecimal; -t_stat reason, r1, r2; - -/* Restore saved state */ - - -IS = saved_IS; -if (as_err) AS = AS | BA; /* flag bad addresses */ -if (bs_err) BS = BS | BA; -as_err = bs_err = 0; /* reset error flags */ -reason = 0; - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ - -if (hb_pend) { /* halt br pending? */ - hb_pend = 0; /* clear flag */ - BRANCH; } /* execute branch */ - -saved_IS = IS; /* commit prev instr */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } - -if (sim_brk_summ && sim_brk_test (IS, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - -sim_interval = sim_interval - 1; - -/* Instruction fetch - 1401 fetch works as follows: - - - Each character fetched enters the B register. This register is not - visible; the variable t represents the B register. - - Except for the first and last cycles, each character fetched enters - the A register. This register is not visible; the variable D represents - the A register, because this is the instruction modifier for 2, 5, and 8 - character instructions. - - At the start of the second cycle (first address character), the A-address - register and, for most instructions, the B-address register, are cleared - to blanks. The simulator represents addresses in binary and creates the - effect of blanks (address is bad) if less than three A-address characters - are found. Further, the simulator accumulates only the A-address, and - replicates it to the B-address at the appropriate point. - - At the start of the fifth cycle (fourth address character), the B-address - register is cleared to blanks. Again, the simulator creates the effect of - blanks (address is bad) if less than three B-address characters are found. - - The 1401 does explicitly check for valid instruction lengths. Most 2,3,5,6 - character instructions will be invalid because the A-address or B-address - (or both) are invalid. -*/ - -if ((M[IS] & WM) == 0) { /* I-Op: WM under op? */ - reason = STOP_NOWM; /* no, error */ - break; } -op = M[IS] & CHAR; /* get opcode */ -flags = op_table[op]; /* get op flags */ -if ((flags == 0) || (flags & ALLOPT & ~cpu_unit.flags)) { - reason = STOP_NXI; /* illegal inst? */ - break; } -if (op == OP_SAR) BS = AS; /* SAR? save ASTAR */ -PP (IS); - -if ((t = M[IS]) & WM) goto CHECK_LENGTH; /* I-1: WM? 1 char inst */ -D = ioind = t; /* could be D char, % */ -AS = hun_table[t]; /* could be A addr */ -PP (IS); /* if %xy, BA is set */ - -if ((t = M[IS]) & WM) { /* I-2: WM? 2 char inst */ - AS = AS | BA; /* ASTAR bad */ - if (!(flags & MLS)) BS = AS; - goto CHECK_LENGTH; } -D = dev = t; /* could be D char, dev */ -AS = AS + ten_table[t]; /* build A addr */ -PP (IS); - -if ((t = M[IS]) & WM) { /* I-3: WM? 3 char inst */ - AS = AS | BA; /* ASTAR bad */ - if (!(flags & MLS)) BS = AS; - goto CHECK_LENGTH; } -D = unit = t; /* could be D char, unit */ -if (unit == BCD_ZERO) unit = 0; /* convert unit to binary */ -AS = AS + one_table[t]; /* finish A addr */ -xa = (AS >> V_INDEX) & M_INDEX; /* get index reg */ -if (xa && (ioind != BCD_PERCNT) && (cpu_unit.flags & XSA)) { /* indexed? */ - AS = AS + hun_table[M[xa] & CHAR] + ten_table[M[xa + 1] & CHAR] + - one_table[M[xa + 2] & CHAR]; - AS = (AS & INDEXMASK) % MAXMEMSIZE; } -if (!(flags & MLS)) BS = AS; /* not MLS? B = A */ -PP (IS); - -if ((t = M[IS]) & WM) goto CHECK_LENGTH; /* I-4: WM? 4 char inst */ -if ((op == OP_B) && (t == BCD_BLANK)) goto CHECK_LENGTH; /* BR + space? */ -D = t; /* could be D char */ -BS = hun_table[t]; /* could be B addr */ -PP (IS); - -if ((t = M[IS]) & WM) { /* I-5: WM? 5 char inst */ - BS = BS | BA; /* BSTAR bad */ - goto CHECK_LENGTH; } -D = t; /* could be D char */ -BS = BS + ten_table[t]; /* build B addr */ -PP (IS); - -if ((t = M[IS]) & WM) { /* I-6: WM? 6 char inst */ - BS = BS | BA; /* BSTAR bad */ - goto CHECK_LENGTH; } -D = t; /* could be D char */ -BS = BS + one_table[t]; /* finish B addr */ -xa = (BS >> V_INDEX) & M_INDEX; /* get index reg */ -if (xa && (cpu_unit.flags & XSA)) { /* indexed? */ - BS = BS + hun_table[M[xa] & CHAR] + ten_table[M[xa + 1] & CHAR] + - one_table[M[xa + 2] & CHAR]; - BS = (BS & INDEXMASK) % MAXMEMSIZE; } -PP (IS); - -if (flags & NOWM) goto CHECK_LENGTH; /* I-7: SWM? done */ -if ((t = M[IS]) & WM) goto CHECK_LENGTH; /* WM? 7 char inst */ -D = t; /* last char is D */ -while (((t = M[IS]) & WM) == 0) { /* I-8: repeats until WM */ - D = t; /* last char is D */ - PP (IS); } - -CHECK_LENGTH: -ilnt = IS - saved_IS; /* get lnt */ -//if (((flags & len_table [(ilnt <= 8)? ilnt: 8]) == 0) && /* valid lnt? */ -// ((flags & HNOP) == 0)) reason = STOP_INVL; -if ((flags & BREQ) && ADDR_ERR (BS)) reason = STOP_INVB; /* valid A? */ -if ((flags & AREQ) && ADDR_ERR (AS)) reason = STOP_INVA; /* valid B? */ -if (reason) break; /* error in fetch? */ -switch (op) { /* case on opcode */ - -/* Move/load character instructions A check B check - - MCW copy A to B, preserving B WM, here fetch - until either A or B WM - LCA copy A to B, overwriting B WM, here fetch - until A WM - - Instruction lengths: - - 1 chained A and B - 2,3 invalid A-address - 4 chained B address - 5,6 invalid B-address - 7 normal - 8+ normal + modifier -*/ - -case OP_MCW: /* move char */ - if ((ilnt >= 4) && (ioind == BCD_PERCNT)) { /* I/O form? */ - reason = iodisp (dev, unit, MD_NORM, D); /* dispatch I/O */ - break; } - if (ADDR_ERR (AS)) { /* check A addr */ - reason = STOP_INVA; - break; } - do { - wm = M[AS] | M[BS]; - M[BS] = (M[BS] & WM) | (M[AS] & CHAR); /* move char */ - MM (AS); MM (BS); } /* decr pointers */ - while ((wm & WM) == 0); /* stop on A,B WM */ - break; - -case OP_LCA: /* load char */ - if ((ilnt >= 4) && (ioind == BCD_PERCNT)) { /* I/O form? */ - reason = iodisp (dev, unit, MD_WM, D); - break; } - if (ADDR_ERR (AS)) { /* check A addr */ - reason = STOP_INVA; - break; } - do { - wm = M[BS] = M[AS]; /* move char + wmark */ - MM (AS); MM (BS); } /* decr pointers */ - while ((wm & WM) == 0); /* stop on A WM */ - break; - -/* Other move instructions A check B check - - MCM copy A to B, preserving B WM, fetch fetch - until record or group mark - MCS copy A to B, clearing B WM, until A WM; fetch fetch - reverse scan and suppress leading zeroes - MN copy A char digit to B char digit, fetch fetch - preserving B zone and WM - MZ copy A char zone to B char zone, fetch fetch - preserving B digit and WM - - Instruction lengths: - - 1 chained - 2,3 invalid A-address - 4 self (B-address = A-address) - 5,6 invalid B-address - 7 normal - 8+ normal + ignored modifier -*/ - -case OP_MCM: /* move to rec/group */ - do { - t = M[AS]; - M[BS] = (M[BS] & WM) | (M[AS] & CHAR); /* move char */ - PP (AS); PP (BS); } /* incr pointers */ - while (((t & CHAR) != BCD_RECMRK) && (t != (BCD_GRPMRK + WM))); - break; - -case OP_MCS: /* move suppress zero */ - bsave = BS; /* save B start */ - qzero = 1; /* set suppress */ - do { - wm = M[AS]; - M[BS] = M[AS] & ((BS != bsave)? CHAR: DIGIT); /* copy char */ - MM (AS); MM (BS); } /* decr pointers */ - while ((wm & WM) == 0); /* stop on A WM */ - if (reason) break; /* addr err? stop */ - do { - PP (BS); /* adv B */ - t = M[BS]; /* get B, cant be WM */ - if ((t == BCD_ZERO) || (t == BCD_COMMA)) { - if (qzero) M[BS] = 0; } - else if ((t == BCD_BLANK) || (t == BCD_MINUS)) ; - else if (((t == BCD_DECIMAL) && (cpu_unit.flags & EPE)) || - (t <= BCD_NINE)) qzero = 0; - else qzero = 1; } - while (BS < bsave); - PP (BS); /* BS end is B+1 */ - break; - -case OP_MN: /* move numeric */ - M[BS] = (M[BS] & ~DIGIT) | (M[AS] & DIGIT); /* move digit */ - MM (AS); MM (BS); /* decr pointers */ - break; - -case OP_MZ: /* move zone */ - M[BS] = (M[BS] & ~ZONE) | (M[AS] & ZONE); /* move high bits */ - MM (AS); MM (BS); /* decr pointers */ - break; - -/* Branch instruction A check B check - - Instruction lengths: - - 1 branch if B char equals d, chained if branch here - 2,3 invalid B-address if branch here - 4 unconditional branch if branch - 5 branch if indicator[d] is set if branch - 6 invalid B-address if branch here - 7 branch if B char equals d, if branch here - d is last character of B-address - 8 branch if B char equals d if branch here -*/ - -case OP_B: /* branch */ - if (ilnt == 4) { BRANCH; } /* uncond branch? */ - else if (ilnt == 5) { /* branch on ind? */ - if (ind[D]) { BRANCH; } /* test indicator */ - if (ind_table[D]) ind[D] = 0; } /* reset if needed */ - else { /* branch char eq */ - if (ADDR_ERR (BS)) { /* validate B addr */ - reason = STOP_INVB; - break; } - if ((M[BS] & CHAR) == D) { BRANCH; } /* char equal? */ - else { MM (BS); } } - break; - -/* Other branch instructions A check B check - - BWZ branch if (d<0>: B char WM) if branch fetch - (d<1>: B char zone = d zone) - BBE branch if B char & d non-zero if branch fetch - - Instruction lengths: - 1 chained - 2,3 invalid A-address and B-address - 4 self (B-address = A-address, d = last character of A-address) - 5,6 invalid B-address - 7 normal, d = last character of B-address - 8+ normal -*/ - -case OP_BWZ: /* branch wm or zone */ - if (((D & 1) && (M[BS] & WM)) || /* d1? test wm */ - ((D & 2) && ((M[BS] & ZONE) == (D & ZONE)))) /* d2? test zone */ - { BRANCH; } - else { MM (BS); } /* decr pointer */ - break; - -case OP_BBE: /* branch if bit eq */ - if (M[BS] & D & CHAR) { BRANCH; } /* any bits set? */ - else { MM (BS); } /* decr pointer */ - break; - -/* Arithmetic instructions A check B check - - ZA move A to B, normalizing A sign, fetch fetch - preserving B WM, until B WM - ZS move A to B, complementing A sign, fetch fetch - preserving B WM, until B WM - A add A to B fetch fetch - S subtract A from B fetch fetch - C compare A to B fetch fetch - - Instruction lengths: - - 1 chained - 2,3 invalid A-address - 4 self (B-address = A-address) - 5,6 invalid B-address - 7 normal - 8+ normal + ignored modifier -*/ - -case OP_ZA: case OP_ZS: /* zero and add/sub */ - a = i = 0; /* clear flags */ - do { - if (a & WM) wm = M[BS] = (M[BS] & WM) | BCD_ZERO; - else { - a = M[AS]; /* get A char */ - t = (a & CHAR)? bin_to_bcd[a & DIGIT]: 0; - wm = M[BS] = (M[BS] & WM) | t; /* move digit */ - MM (AS); } - if (i == 0) i = M[BS] = M[BS] | - ((((a & ZONE) == BBIT) ^ (op == OP_ZS))? BBIT: ZONE); - MM (BS); } - while ((wm & WM) == 0); /* stop on B WM */ - break; - -case OP_A: case OP_S: /* add/sub */ - bsave = BS; /* save sign pos */ - a = M[AS]; /* get A digit/sign */ - b = M[BS]; /* get B digit/sign */ - MM (AS); - qsign = ((a & ZONE) == BBIT) ^ ((b & ZONE) == BBIT) ^ (op == OP_S); - t = bcd_to_bin[a & DIGIT]; /* get A binary */ - t = bcd_to_bin[b & DIGIT] + (qsign? 10 - t: t); /* sum A + B */ - carry = (t >= 10); /* get carry */ - b = (b & ~DIGIT) | sum_table[t]; /* get result */ - if (qsign && ((b & BBIT) == 0)) b = b | ZONE; /* normalize sign */ - M[BS] = b; /* store result */ - MM (BS); - if (b & WM) { /* b wm? done */ - if (qsign && (carry == 0)) M[bsave] = /* compl, no carry? */ - WM + ((b & ZONE) ^ ABIT) + sum_table[10 - t]; - break; } - do { - if (a & WM) a = WM; /* A WM? char = 0 */ - else { - a = M[AS]; /* else get A */ - MM (AS); } - b = M[BS]; /* get B */ - t = bcd_to_bin[a & DIGIT]; /* get A binary */ - t = bcd_to_bin[b & DIGIT] + (qsign? 9 - t: t) + carry; - carry = (t >= 10); /* get carry */ - if ((b & WM) && (qsign == 0)) { /* last, no recomp? */ - M[BS] = WM + sum_table[t] + /* zone add */ - (((a & ZONE) + b + (carry? ABIT: 0)) & ZONE); - ind[IN_OVF] = carry; } /* ovflo if carry */ - else M[BS] = (b & WM) + sum_table[t]; /* normal add */ - MM (BS); } - while ((b & WM) == 0); /* stop on B WM */ - if (reason) break; /* address err? */ - if (qsign && (carry == 0)) { /* recompl, no carry? */ - M[bsave] = M[bsave] ^ ABIT; /* XOR sign */ - for (carry = 1; bsave != BS; --bsave) { /* rescan */ - t = 9 - bcd_to_bin[M[bsave] & DIGIT] + carry; - carry = (t >= 10); - M[bsave] = (M[bsave] & ~DIGIT) | sum_table[t]; } } - break; - -case OP_C: /* compare */ - if (ilnt != 1) { /* if not chained */ - ind[IN_EQU] = 1; /* clear indicators */ - ind[IN_UNQ] = ind[IN_HGH] = ind[IN_LOW] = 0; } - do { - a = M[AS]; /* get characters */ - b = M[BS]; - wm = a | b; /* get word marks */ - if ((a & CHAR) != (b & CHAR)) { /* unequal? */ - ind[IN_EQU] = 0; /* set indicators */ - ind[IN_UNQ] = 1; - ind[IN_HGH] = col_table[b & CHAR] > col_table [a & CHAR]; - ind[IN_LOW] = ind[IN_HGH] ^ 1; } - MM (AS); MM (BS); } /* decr pointers */ - while ((wm & WM) == 0); /* stop on A, B WM */ - if ((a & WM) && !(b & WM)) { /* short A field? */ - ind[IN_EQU] = ind[IN_LOW] = 0; - ind[IN_UNQ] = ind[IN_HGH] = 1; } - if (!(cpu_unit.flags & HLE)) /* no HLE? */ - ind[IN_EQU] = ind[IN_LOW] = ind[IN_HGH] = 0; - break; - -/* I/O instructions A check B check - - R read a card if branch - W write to line printer if branch - WR write and read if branch - P punch a card if branch - RP read and punch if branch - WP : write and punch if branch - WRP write read and punch if branch - RF read feed (nop) - PF punch feed (nop) - SS select stacker if branch - CC carriage control if branch - - Instruction lengths: - - 1 normal - 2,3 normal, with modifier - 4 branch; modifier, if any, is last character of branch address - 5 branch + modifier - 6+ normal, with modifier -*/ - -case OP_R: /* read */ - if (reason = iomod (ilnt, D, NULL)) break; /* valid modifier? */ - reason = read_card (ilnt, D); /* read card */ - BS = CDR_BUF + CDR_WIDTH; - if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ - break; - -case OP_W: /* write */ - if (reason = iomod (ilnt, D, w_mod)) break; /* valid modifier? */ - reason = write_line (ilnt, D); /* print line */ - BS = LPT_BUF + LPT_WIDTH; - if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ - break; - -case OP_P: /* punch */ - if (reason = iomod (ilnt, D, NULL)) break; /* valid modifier? */ - reason = punch_card (ilnt, D); /* punch card */ - BS = CDP_BUF + CDP_WIDTH; - if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ - break; - -case OP_WR: /* write and read */ - if (reason = iomod (ilnt, D, w_mod)) break; /* valid modifier? */ - reason = write_line (ilnt, D); /* print line */ - r1 = read_card (ilnt, D); /* read card */ - BS = CDR_BUF + CDR_WIDTH; - if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ - if (reason == SCPE_OK) reason = r1; /* merge errors */ - break; - -case OP_WP: /* write and punch */ - if (reason = iomod (ilnt, D, w_mod)) break; /* valid modifier? */ - reason = write_line (ilnt, D); /* print line */ - r1 = punch_card (ilnt, D); /* punch card */ - BS = CDP_BUF + CDP_WIDTH; - if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ - if (reason == SCPE_OK) reason = r1; /* merge errors */ - break; - -case OP_RP: /* read and punch */ - if (reason = iomod (ilnt, D, NULL)) break; /* valid modifier? */ - reason = read_card (ilnt, D); /* read card */ - r1 = punch_card (ilnt, D); /* punch card */ - BS = CDP_BUF + CDP_WIDTH; - if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ - if (reason == SCPE_OK) reason = r1; /* merge errors */ - break; - -case OP_WRP: /* write, read, punch */ - if (reason = iomod (ilnt, D, w_mod)) break; /* valid modifier? */ - reason = write_line (ilnt, D); /* print line */ - r1 = read_card (ilnt, D); /* read card */ - r2 = punch_card (ilnt, D); /* punch card */ - BS = CDP_BUF + CDP_WIDTH; - if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ - if (reason == SCPE_OK) reason = (r1 == SCPE_OK)? r2: r1; - break; - -case OP_SS: /* select stacker */ - if (reason = iomod (ilnt, D, ss_mod)) break; /* valid modifier? */ - if (reason = select_stack (D)) break; /* sel stack, error? */ - if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ - break; - -case OP_CC: /* carriage control */ - if (reason = carriage_control (D)) break; /* car ctrl, error? */ - if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ - break; - -/* MTF - magtape functions - must be at least 4 characters - - Instruction lengths: - - 1-3 invalid I/O address - 4 normal, d-character is unit - 5 normal - 6+ normal, d-character is last character -*/ - -case OP_MTF: /* magtape function */ - if (ilnt < 4) reason = STOP_INVL; /* too short? */ - else if (ioind != BCD_PERCNT) reason = STOP_INVA; - else if (reason = iomod (ilnt, D, mtf_mod)) break; /* valid modifier? */ - reason = mt_func (unit, D); /* mt func, error? */ - break; /* can't branch */ - -case OP_RF: case OP_PF: /* read, punch feed */ - break; /* nop's */ - -/* Move character and edit - - Control flags - qsign sign of A field (0 = +, 1 = minus) - qawm A field WM seen and processed - qzero zero suppression enabled - qbody in body (copying A field characters) - qdollar EPE only; $ seen in body - qaster EPE only; * seen in body - qdecimal EPE only; . seen on first rescan - - MCE operates in one to three scans, the first of which has three phases - - 1 right to left qbody = 0, qawm = 0 => right status - qbody = 1, qawm = 0 => body - qbody = 0, qawm = 1 => left status - 2 left to right - 3 right to left, extended print end only - - The first A field character is masked to its digit part, all others - are copied intact - - Instruction lengths: - - 1 chained - 2,3 invalid A-address - 4 self (B-address = A-address) - 5,6 invalid B-address - 7 normal - 8+ normal + ignored modifier -*/ - -case OP_MCE: /* edit */ - a = M[AS]; /* get A char */ - b = M[BS]; /* get B char */ - if (a & WM) { /* one char A field? */ - reason = STOP_MCE1; - break; } - if (b & WM) { /* one char B field? */ - reason = STOP_MCE2; - break; } - t = a & DIGIT; MM (AS); /* get A digit */ - qsign = ((a & ZONE) == BBIT); /* get A field sign */ - qawm = qzero = qbody = 0; /* clear other flags */ - qdollar = qaster = qdecimal = 0; /* clear EPE flags */ - -/* Edit pass 1 - from right to left, under B field control - - * in status or !epe, skip B; else, set qaster, repl with A - $ in status or !epe, skip B; else, set qdollar, repl with A - 0 in right status or body, if !qzero, set A WM; set qzero, repl with A - else, if !qzero, skip B; else, if (!B WM) set B WM - blank in right status or body, repl with A; else, skip B - C,R,- in status, blank B; else, skip B - , in status, blank B, else, skip B - & blank B -*/ - - do { - b = M[BS]; /* get B char */ - M[BS] = M[BS] & ~WM; /* clr WM */ - switch (b & CHAR) { /* case on B char */ - case BCD_ASTER: /* * */ - if (!qbody || qdollar || !(cpu_unit.flags & EPE)) break; - qaster = 1; /* flag */ - goto A_CYCLE; /* take A cycle */ - case BCD_DOLLAR: /* $ */ - if (!qbody || qaster || !(cpu_unit.flags & EPE)) break; - qdollar = 1; /* flag */ - goto A_CYCLE; /* take A cycle */ - case BCD_ZERO: /* 0 */ - if (qawm && !qzero && !(b & WM)) { - M[BS] = BCD_ZERO + WM; /* mark with WM */ - qzero = 1; /* flag supress */ - break; } - if (!qzero) t = t | WM; /* first? set WM */ - qzero = 1; /* flag supress */ - /* fall through */ - case BCD_BLANK: /* blank */ - if (qawm) break; /* any A left? */ - A_CYCLE: - M[BS] = t; /* copy char */ - if (a & WM) { /* end of A field? */ - qbody = 0; /* end body */ - qawm = 1; } - else { - qbody = 1; /* in body */ - a = M[AS]; MM (AS); /* next A */ - t = a & CHAR; } - break; - case BCD_C: case BCD_R: case BCD_MINUS: /* C, R, - */ - if (!qsign && !qbody) M[BS] = BCD_BLANK; - break; - case BCD_COMMA: /* , */ - if (!qbody) M[BS] = BCD_BLANK; /* bl if status */ - break; - case BCD_AMPER: /* & */ - M[BS] = BCD_BLANK; /* blank B field */ - break; } /* end switch */ - MM (BS); } /* decr B pointer */ - while ((b & WM) == 0); /* stop on B WM */ - - if (reason) break; /* address err? */ - if (!qawm || !qzero) { /* rescan? */ - if (qdollar) reason = STOP_MCE3; /* error if $ */ - break; } - -/* Edit pass 2 - from left to right, supressing zeroes */ - - do { - b = M[++BS]; /* get B char */ - switch (b & CHAR) { /* case on B char */ - case BCD_ONE: case BCD_TWO: case BCD_THREE: - case BCD_FOUR: case BCD_FIVE: case BCD_SIX: - case BCD_SEVEN: case BCD_EIGHT: case BCD_NINE: - qzero = 0; /* turn off supr */ - break; - case BCD_ZERO: case BCD_COMMA: /* 0 or , */ - if (qzero && !qdecimal) /* if supr, blank */ - M[BS] = qaster? BCD_ASTER: BCD_BLANK; - break; - case BCD_BLANK: /* blank */ - if (qaster) M[BS] = BCD_ASTER; /* if EPE *, repl */ - break; - case BCD_DECIMAL: /* . */ - if (qzero && (cpu_unit.flags & EPE)) - qdecimal = 1; /* flag for EPE */ - case BCD_PERCNT: case BCD_WM: case BCD_BS: - case BCD_TS: case BCD_MINUS: - break; /* ignore */ - default: /* other */ - qzero = 1; /* restart supr */ - break; } } /* end case, do */ - while ((b & WM) == 0); - - M[BS] = M[BS] & ~WM; /* clear B WM */ - if (!qdollar && !(qdecimal && qzero)) { /* rescan again? */ - BS++; /* BS = addr WM + 1 */ - break; } - if (qdecimal && qzero) qdollar = 0; /* no digits? clr $ */ - -/* Edit pass 3 (extended print only) - from right to left */ - - for (;; ) { /* until chars */ - b = M[BS]; /* get B char */ - if ((b == BCD_BLANK) && qdollar) { /* blank & flt $? */ - M[BS] = BCD_DOLLAR; /* insert $ */ - break; } /* exit for */ - if (b == BCD_DECIMAL) { /* decimal? */ - M[BS] = qaster? BCD_ASTER: BCD_BLANK; - break; } /* exit for */ - if ((b == BCD_ZERO) && !qdollar) /* 0 & ~flt $ */ - M[BS] = qaster? BCD_ASTER: BCD_BLANK; - BS--; } /* end for */ - break; /* done at last! */ - -/* Multiply. Comments from the PDP-10 based simulator by Len Fehskens. - - Multiply, with variable length operands, is necessarily done the same - way you do it with paper and pencil, except that partial products are - added into the incomplete final product as they are computed, rather - than at the end. The 1401 multiplier format allows the product to - be developed in place, without scratch storage. - - The A field contains the multiplicand, length LD. The B field must be - LD + 1 + length of multiplier. Locate the low order multiplier digit, - and at the same time zero out the product field. Then compute the sign - of the result. - - Instruction lengths: - - 1 chained - 2,3 invalid A-address - 4 self (B-address = A-address) - 5,6 invalid B-address - 7 normal - 8+ normal + ignored modifier -*/ - -case OP_MUL: - asave = AS; bsave = lowprd = BS; /* save AS, BS */ - do { - a = M[AS]; /* get mpcd char */ - M[BS] = BCD_ZERO; /* zero prod */ - MM (AS); MM (BS); } /* decr pointers */ - while ((a & WM) == 0); /* until A WM */ - if (reason) break; /* address err? */ - M[BS] = BCD_ZERO; /* zero hi prod */ - MM (BS); /* addr low mpyr */ - sign = ((M[asave] & ZONE) == BBIT) ^ ((M[BS] & ZONE) == BBIT); - -/* Outer loop on multiplier (BS) and product digits (ps), - inner loop on multiplicand digits (AS). - AS and ps cannot produce an address error. -*/ - - do { - ps = bsave; /* ptr to prod */ - AS = asave; /* ptr to mpcd */ - carry = 0; /* init carry */ - b = M[BS]; /* get mpyr char */ - do { - a = M[AS]; /* get mpcd char */ - t = (bcd_to_bin[a & DIGIT] * /* mpyr * mpcd */ - bcd_to_bin[b & DIGIT]) + /* + c + partial prod */ - carry + bcd_to_bin[M[ps] & DIGIT]; - carry = cry_table[t]; - M[ps] = (M[ps] & WM) | sum_table[t]; - MM (AS); ps--; } - while ((a & WM) == 0); /* until mpcd done */ - M[BS] = (M[BS] & WM) | BCD_ZERO; /* zero mpyr just used */ - t = bcd_to_bin[M[ps] & DIGIT] + carry; /* add carry to prod */ - M[ps] = (M[ps] & WM) | sum_table[t]; /* store */ - bsave--; /* adv prod ptr */ - MM (BS); } /* adv mpyr ptr */ - while ((b & WM) == 0); /* until mpyr done */ - M[lowprd] = M[lowprd] | ZONE; /* assume + */ - if (sign) M[lowprd] = M[lowprd] & ~ABIT; /* if minus, B only */ - break; - -/* Divide. Comments from the PDP-10 based simulator by Len Fehskens. - - Divide is done, like multiply, pretty much the same way you do it with - pencil and paper; successive subtraction of the divisor from a substring - of the dividend while counting up the corresponding quotient digit. - - Let LS be the length of the divisor, LD the length of the dividend: - - AS points to the low order divisor digit. - - BS points to the high order dividend digit. - - The low order dividend digit is identified by sign (zone) bits. - - To the left of the dividend is a zero field of length LS + 1. - The low quotient is at low dividend - LS - 1. As BS points to the - high dividend, the low dividend is at BS + LD - 1, so the low - quotient is at BS + LD - LS - 2. The longest possible quotient is - LD - LS + 1, so the first possible non-zero quotient bit will be - found as BS - 2. - - This pointer calculation assumes that the divisor has no leading zeroes. - For each leading zero, the start of the quotient will be one position - further left. - - Start by locating the high order non-zero digit of the divisor. This - also tests for a divide by zero. - - Instruction lengths: - - 1 chained - 2,3 invalid A-address - 4 self (B-address = A-address) - 5,6 invalid B-address - 7 normal - 8+ normal + ignored modifier -*/ - -case OP_DIV: - asave = AS; ahigh = -1; - do { - a = M[AS]; /* get dvr char */ - if ((a & CHAR) != BCD_ZERO) ahigh = AS; /* mark non-zero */ - MM (AS); } - while ((a & WM) == 0); - if (reason) break; /* address err? */ - if (ahigh < 0) { /* div? by zero */ - ind[IN_OVF] = 1; /* set ovf indic */ - qs = bsave = BS; /* quo, dividend */ - do { - b = M[bsave]; /* find end divd */ - PP (bsave); } /* marked by zone */ - while ((b & ZONE) == 0); - if (reason) break; /* address err? */ - if (ADDR_ERR (qs)) { /* address err? */ - reason = STOP_WRAP; /* address wrap? */ - break; } - div_sign (M[asave], b, qs - 1, bsave - 1); /* set signs */ - BS = (BS - 2) - (asave - (AS + 1)); /* final bs */ - break; } - bsave = BS + (asave - ahigh); /* end subdivd */ - qs = (BS - 2) - (ahigh - (AS + 1)); /* quo start */ - -/* Divide loop - done with subroutines to keep the code clean. - In the loop, - - asave = low order divisor - bsave = low order subdividend - qs = current quotient digit -*/ - - do { - quo = 0; /* clear quo digit */ - if (ADDR_ERR (qs) || ADDR_ERR (bsave)) { - reason = STOP_WRAP; /* address wrap? */ - break; } - b = M[bsave]; /* save low divd */ - do { - t = div_sub (asave, bsave, ahigh); /* subtract */ - quo++; } /* incr quo digit */ - while (t == 0); /* until borrow */ - div_add (asave, bsave, ahigh); quo--; /* restore */ - M[qs] = (M[qs] & WM) | sum_table[quo]; /* store quo digit */ - bsave++; qs++; } /* adv divd, quo */ - while ((b & ZONE) == 0); /* until B sign */ - if (reason) break; /* address err? */ - -/* At this point, - - AS = high order divisor - 1 - asave = unit position of divisor - b = unit character of dividend - bsave = unit position of remainder + 1 - qs = unit position of quotient + 1 -*/ - - div_sign (M[asave], b, qs - 1, bsave - 1); /* set signs */ - BS = qs - 2; /* BS = quo 10's pos */ - break; - -/* Word mark instructions A check B check - - SWM set WM on A char and B char fetch fetch - CWM clear WM on A char and B char fetch fetch - - Instruction lengths: - - 1 chained - 2,3 invalid A-address - 4 one operand (B-address = A-address) - 5,6 invalid B-address - 7 two operands (SWM cannot be longer than 7) - 8+ two operands + ignored modifier -*/ - -case OP_SWM: /* set word mark */ - M[BS] = M[BS] | WM; /* set A field mark */ - M[AS] = M[AS] | WM; /* set B field mark */ - MM (AS); MM (BS); /* decr pointers */ - break; - -case OP_CWM: /* clear word mark */ - M[BS] = M[BS] & ~WM; /* clear A field mark */ - M[AS] = M[AS] & ~WM; /* clear B field mark */ - MM (AS); MM (BS); /* decr pointers */ - break; - -/* Clear storage instruction A check B check - - CS clear from B down to nearest hundreds if branch fetch - address - - Instruction lengths: - - 1 chained - 2,3 invalid A-address and B-address - 4 one operand (B-address = A-address) - 5,6 invalid B-address - 7 branch - 8+ one operand, branch ignored -*/ - -case OP_CS: /* clear storage */ - t = (BS / 100) * 100; /* lower bound */ - while (BS >= t) M[BS--] = 0; /* clear region */ - if (BS < 0) BS = BS + MEMSIZE; /* wrap if needed */ - if (ilnt == 7) { BRANCH; } /* branch variant? */ - break; - -/* Modify address instruction A check B check - - MA add A addr and B addr, store at B addr fetch fetch - - Instruction lengths: - 1 chained - 2,3 invalid A-address and B-address - 4 self (B-address = A-address) - 5,6 invalid B-address - 7 normal - 8+ normal + ignored modifier -*/ - -case OP_MA: /* modify address */ - a = one_table[M[AS] & CHAR]; MM (AS); /* get A address */ - a = a + ten_table[M[AS] & CHAR]; MM (AS); - a = a + hun_table[M[AS] & CHAR]; MM (AS); - b = one_table[M[BS] & CHAR]; MM (BS); /* get B address */ - b = b + ten_table[M[BS] & CHAR]; MM (BS); - b = b + hun_table[M[BS] & CHAR]; MM (BS); - t = ((a + b) & INDEXMASK) % MAXMEMSIZE; /* compute sum */ - M[BS + 3] = (M[BS + 3] & WM) | store_addr_u (t); - M[BS + 2] = (M[BS + 2] & (WM + ZONE)) | store_addr_t (t); - M[BS + 1] = (M[BS + 1] & WM) | store_addr_h (t); - if (((a % 4000) + (b % 4000)) >= 4000) BS = BS + 2; /* carry? */ - break; - -/* Store address instructions A-check B-check - - SAR store A* at A addr fetch - SBR store B* at A addr fetch - - Instruction lengths: - 1 chained - 2,3 invalid A-address - 4 normal - 5+ B-address overwritten from instruction; - invalid address ignored -*/ - -case OP_SAR: case OP_SBR: /* store A, B reg */ - M[AS] = (M[AS] & WM) | store_addr_u (BS); MM (AS); - M[AS] = (M[AS] & WM) | store_addr_t (BS); MM (AS); - M[AS] = (M[AS] & WM) | store_addr_h (BS); MM (AS); - break; - -/* NOP - no validity checking, all instructions length ok */ - -case OP_NOP: /* nop */ - break; - -/* HALT - unless length = 4 (branch), no validity checking; all lengths ok */ - -case OP_H: /* halt */ - if (ilnt == 4) hb_pend = 1; /* set pending branch */ - reason = STOP_HALT; /* stop simulator */ - saved_IS = IS; /* commit instruction */ - break; - -default: - reason = STOP_NXI; /* unimplemented */ - break; } /* end switch */ -} /* end while */ - -/* Simulation halted */ - -as_err = ADDR_ERR (AS); /* get addr err flags */ -bs_err = ADDR_ERR (BS); -AS = AS & ADDRMASK; /* clean addresses */ -BS = BS & ADDRMASK; -pcq_r->qptr = pcq_p; /* update pc q ptr */ -return reason; -} /* end sim_instr */ - -/* store addr_x - convert address to BCD character in x position - - Inputs: - addr = address to convert - Outputs: - char = converted address character -*/ - -int32 store_addr_h (int32 addr) -{ -int32 thous; - -thous = (addr / 1000) & 03; -return bin_to_bcd[(addr % 1000) / 100] | (thous << V_ZONE); -} - -int32 store_addr_t (int32 addr) -{ -return bin_to_bcd[(addr % 100) / 10]; -} - -int32 store_addr_u (int32 addr) -{ -int32 thous; - -thous = (addr / 1000) & 014; -return bin_to_bcd[addr % 10] | (thous << (V_ZONE - 2)); -} - -/* div_add - add string for divide */ - -int32 div_add (int32 ap, int32 bp, int32 aend) -{ -int32 a, b, c, r; - -c = 0; /* init carry */ -do { a = M[ap]; b = M[bp]; /* get operands */ - r = bcd_to_bin[b & DIGIT] + /* sum digits + c */ - bcd_to_bin[a & DIGIT] + c; - c = (r >= 10); /* set carry out */ - M[bp] = sum_table[r]; /* store result */ - ap--; bp--; } -while (ap >= aend); -return c; -} - -/* div_sub - substract string for divide */ - -int32 div_sub (int32 ap, int32 bp, int32 aend) -{ -int32 a, b, c, r; - -c = 0; /* init borrow */ -do { a = M[ap]; b = M[bp]; /* get operands */ - r = bcd_to_bin[b & DIGIT] - /* a - b - borrow */ - bcd_to_bin[a & DIGIT] - c; - c = (r < 0); /* set borrow out */ - M[bp] = sum_table[r + 10]; /* store result */ - ap--; bp--; } -while (ap >= aend); -b = M[bp] & CHAR; /* borrow position */ -if (b != BCD_ZERO) { /* non-zero? */ - r = bcd_to_bin[b & DIGIT] - c; /* subtract borrow */ - M[bp] = sum_table[r]; /* store result */ - return 0; } /* subtract worked */ -return c; /* return borrow */ -} - -/* div_sign - set signs for divide */ - -void div_sign (int32 dvrc, int32 dvdc, int32 qp, int32 rp) -{ -int32 sign = dvrc & ZONE; /* divisor sign */ - -M[rp] = M[rp] | ZONE; /* assume rem pos */ -if (sign == BBIT) M[rp] = M[rp] & ~ABIT; /* if dvr -, rem - */ -M[qp] = M[qp] | ZONE; /* assume quo + */ -if (((dvdc & ZONE) == BBIT) ^ (sign == BBIT)) /* dvr,dvd diff? */ - M[qp] = M[qp] & ~ABIT; /* make quo - */ -return; -} - -/* iomod - check on I/O modifiers - - Inputs: - ilnt = instruction length - mod = modifier character - tptr = pointer to table of modifiers, end is -1 - Output: - status = SCPE_OK if ok, STOP_INVM if invalid -*/ - -t_stat iomod (int32 ilnt, int32 mod, const int32 *tptr) -{ -if ((ilnt != 2) && (ilnt != 5) && (ilnt < 8)) return SCPE_OK; -if (tptr == NULL) return STOP_INVM; -do { if (mod == *tptr++) return SCPE_OK; } -while (*tptr >= 0); -return STOP_INVM; -} - -/* iodisp - dispatch load or move to I/O routine - - Inputs: - dev = device number - unit = unit number - flag = move (MD_NORM) vs load (MD_WM) - mod = modifier -*/ - -t_stat iodisp (int32 dev, int32 unit, int32 flag, int32 mod) -{ -if (dev == IO_INQ) return inq_io (flag, mod); /* inq terminal? */ -if (dev == IO_DP) return dp_io (unit, flag, mod); /* disk pack? */ -if (dev == IO_MT) return mt_io (unit, flag, mod); /* magtape? */ -if (dev == IO_MTB) { /* binary? */ - if (flag == MD_WM) return STOP_INVM; /* invalid */ - return mt_io (unit, MD_BIN, mod); } -return STOP_NXD; /* not implemented */ -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -int32 i; - -for (i = 0; i < 64; i++) ind[i] = 0; /* clr indicators */ -ind[IN_UNC] = 1; /* ind[0] always on */ -AS = 0; as_err = 1; /* clear AS */ -BS = 0; bs_err = 1; /* clear BS */ -D = 0; /* clear D */ -hb_pend = 0; /* no halt br */ -pcq_r = find_reg ("ISQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & (WM + CHAR); -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -M[addr] = val & (WM + CHAR); -return SCPE_OK; -} - -/* Memory size change */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val % 1000) != 0)) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; -if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_OK; -MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; -if (MEMSIZE > 4000) cpu_unit.flags = cpu_unit.flags | MA; -else cpu_unit.flags = cpu_unit.flags & ~MA; -return SCPE_OK; -} diff --git a/I1401/i1401_dat.h b/I1401/i1401_dat.h deleted file mode 100644 index 02e6ac00..00000000 --- a/I1401/i1401_dat.h +++ /dev/null @@ -1,57 +0,0 @@ -/* i1401_dat.h: IBM 1401 character conversion tables - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. -*/ - -/* ASCII to BCD conversion */ - -const char ascii_to_bcd[128] = { - 000, 000, 000, 000, 000, 000, 000, 000, /* 000 - 037 */ - 000, 000, 000, 000, 000, 000, 000, 000, - 000, 000, 000, 000, 000, 000, 000, 000, - 000, 000, 000, 000, 000, 000, 000, 000, - 000, 052, 077, 013, 053, 034, 060, 032, /* 040 - 077 */ - 017, 074, 054, 037, 033, 040, 073, 021, - 012, 001, 002, 003, 004, 005, 006, 007, - 010, 011, 015, 056, 076, 035, 016, 072, - 014, 061, 062, 063, 064, 065, 066, 067, /* 100 - 137 */ - 070, 071, 041, 042, 043, 044, 045, 046, - 047, 050, 051, 022, 023, 024, 025, 026, - 027, 030, 031, 075, 036, 055, 020, 057, - 000, 061, 062, 063, 064, 065, 066, 067, /* 140 - 177 */ - 070, 071, 041, 042, 043, 044, 045, 046, - 047, 050, 051, 022, 023, 024, 025, 026, - 027, 030, 031, 000, 000, 000, 000, 000 }; - -/* BCD to ASCII conversion - also the "full" print chain */ - -char bcd_to_ascii[64] = { - ' ', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '0', '#', '@', ':', '>', '(', - '^', '/', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', '\'', ',', '%', '=', '\\', '+', - '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', '!', '$', '*', ']', ';', '_', - '&', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', '?', '.', ')', '[', '<', '"' }; diff --git a/I1401/i1401_defs.h b/I1401/i1401_defs.h deleted file mode 100644 index a93427fb..00000000 --- a/I1401/i1401_defs.h +++ /dev/null @@ -1,278 +0,0 @@ -/* i1401_defs.h: IBM 1401 simulator definitions - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 16-Mar-03 RMS Fixed mnemonic for MCS - 03-Jun-02 RMS Added 1311 support - 14-Apr-99 RMS Converted t_addr to unsigned - - This simulator is based on the 1401 simulator written by Len Fehskens - with assistance from Sarah Lee Harris and Bob Supnik. This one's for - you, Len. I am grateful to Paul Pierce and Charles Owen for their help - in answering questions, gathering source material, and debugging. -*/ - -#include "sim_defs.h" - -/* Simulator stop codes */ - -#define STOP_NXI 1 /* unimpl instr */ -#define STOP_NXM 2 /* non-exist mem */ -#define STOP_NXD 3 /* non-exist dev */ -#define STOP_NOWM 4 /* no WM under op */ -#define STOP_INVA 5 /* invalid A addr */ -#define STOP_INVB 6 /* invalid B addr */ -#define STOP_INVL 7 /* invalid length */ -#define STOP_INVM 8 /* invalid modifier */ -#define STOP_INVBR 9 /* invalid branch */ -#define STOP_IBKPT 10 /* breakpoint */ -#define STOP_HALT 11 /* halt */ -#define STOP_INVMTU 12 /* invalid MT unit */ -#define STOP_MTZ 13 /* MT zero lnt rec */ -#define STOP_MTL 14 /* MT write lock */ -#define STOP_CCT 15 /* inv CCT channel */ -#define STOP_NOCD 16 /* no cards left */ -#define STOP_WRAP 17 /* AS, BS mem wrap */ -#define STOP_MCE1 18 /* MCE short A field */ -#define STOP_MCE2 19 /* MCE short B field */ -#define STOP_MCE3 20 /* MCE hanging $ */ -#define STOP_IOC 21 /* I/O check */ -#define STOP_INVDSC 22 /* invalid disk sector */ -#define STOP_INVDCN 23 /* invalid disk count */ -#define STOP_INVDSK 24 /* invalid disk unit */ -#define STOP_INVDFN 25 /* invalid disk func */ -#define STOP_INVDLN 26 /* invalid disk reclen */ -#define STOP_WRADIS 27 /* write address dis */ -#define STOP_WRCHKE 28 /* write check error */ -#define STOP_INVDAD 39 /* invalid disk addr */ -#define STOP_INVDCY 30 /* invalid direct seek */ - -/* Memory and devices */ - -#define MAXMEMSIZE 16000 /* max memory */ -#define MEMSIZE (cpu_unit.capac) /* current memory */ -#define CDR_BUF 1 /* card rdr buffer */ -#define CDR_WIDTH 80 /* card rdr width */ -#define CDP_BUF 101 /* card punch buffer */ -#define CDP_WIDTH 80 /* card punch width */ -#define LPT_BUF 201 /* line print buffer */ -#define LPT_WIDTH 132 /* line print width */ -#define CCT_LNT 132 /* car ctrl length */ -#define INQ_WIDTH 80 /* inq term width */ -#define ADDR_ERR(x) (((uint32) (x)) >= MEMSIZE) - -/* Binary address format - - <14:0> address, with index added in - <23:16> index register memory address - <25:24> address error bits -*/ - -#define ADDRMASK 037777 /* addr mask */ -#define INDEXMASK 077777 /* addr + index mask */ -#define V_INDEX 16 -#define M_INDEX 0177 -#define V_ADDRERR 24 -#define BA (1 << V_ADDRERR) /* bad addr digit */ -#define X1 (87 << V_INDEX) /* index reg 1 */ -#define X2 (92 << V_INDEX) /* index reg 2 */ -#define X3 (97 << V_INDEX) /* index reg 3 */ - -/* CPU instruction control flags. The flag definitions must be harmonized - with the UNIT flag definitions used by the simulator. */ - -/* Lengths */ - -#define L1 0001 /* 1: op */ -#define L2 0002 /* 2: op d */ -#define L4 0004 /* 4: op aaa */ -#define L5 0010 /* 5: op aaa d */ -#define L7 0020 /* 7: op aaa bbb */ -#define L8 0040 /* 8: op aaa bbb d */ - -/* CPU options, stored in cpu_unit.flags */ - -#define MDV (1 << (UNIT_V_UF + 0)) /* multiply/divide */ -#define MR (1 << (UNIT_V_UF + 1)) /* move record */ -#define XSA (1 << (UNIT_V_UF + 2)) /* index, store addr */ -#define EPE (1 << (UNIT_V_UF + 3)) /* expanded edit */ -#define MA (1 << (UNIT_V_UF + 4)) /* modify address */ -#define BBE (1 << (UNIT_V_UF + 5)) /* br bit equal */ -#define HLE (1 << (UNIT_V_UF + 6)) /* high/low/equal */ -#define UNIT_MSIZE (1 << (UNIT_V_UF + 7)) /* fake flag */ -#define ALLOPT (MDV + MR + XSA + EPE + MA + BBE + HLE) -#define STDOPT (MDV + MR + XSA + EPE + MA + BBE + HLE) - -/* Fetch control */ - -#define AREQ (1 << (UNIT_V_UF + 8)) /* validate A */ -#define BREQ (1 << (UNIT_V_UF + 9)) /* validate B */ -#define MLS (1 << (UNIT_V_UF + 10)) /* move load store */ -#define NOWM (1 << (UNIT_V_UF + 11)) /* no WM at end */ -#define HNOP (1 << (UNIT_V_UF + 12)) /* halt or nop */ -#define IO (1 << (UNIT_V_UF + 13)) /* IO */ -#define UNIT_BCD (1 << (UNIT_V_UF + 14)) /* BCD strings */ - -#if (UNIT_V_UF < 6) || ((UNIT_V_UF + 14) > 31) - Definition error: flags overlap -#endif - -/* BCD memory character format */ - -#define WM 0100 /* word mark */ -#define ZONE 0060 /* zone */ -#define BBIT 0040 /* 1 in valid sign */ -#define ABIT 0020 /* sign (1 = +) */ -#define DIGIT 0017 /* digit */ -#define CHAR 0077 /* character */ - -#define V_WM 6 -#define V_ZONE 4 -#define V_DIGIT 0 - -/* Interesting BCD characters */ - -#define BCD_BLANK 000 -#define BCD_ONE 001 -#define BCD_TWO 002 -#define BCD_THREE 003 -#define BCD_FOUR 004 -#define BCD_FIVE 005 -#define BCD_SIX 006 -#define BCD_SEVEN 007 -#define BCD_EIGHT 010 -#define BCD_NINE 011 -#define BCD_ZERO 012 -#define BCD_ALT 020 -#define BCD_S 022 -#define BCD_U 024 -#define BCD_W 026 -#define BCD_RECMRK 032 -#define BCD_COMMA 033 -#define BCD_PERCNT 034 -#define BCD_WM 035 -#define BCD_BS 036 -#define BCD_TS 037 -#define BCD_MINUS 040 -#define BCD_M 044 -#define BCD_R 051 -#define BCD_DOLLAR 053 -#define BCD_ASTER 054 -#define BCD_AMPER 060 -#define BCD_A 061 -#define BCD_B 062 -#define BCD_C 063 -#define BCD_E 065 -#define BCD_DECIMAL 073 -#define BCD_SQUARE 074 -#define BCD_GRPMRK 077 - -/* Opcodes */ - -#define OP_R 001 /* read */ -#define OP_W 002 /* write */ -#define OP_WR 003 /* write and read */ -#define OP_P 004 /* punch */ -#define OP_RP 005 /* read and punch */ -#define OP_WP 006 /* write and punch */ -#define OP_WRP 007 /* write read punch */ -#define OP_RF 010 /* reader feed */ -#define OP_PF 011 /* punch feed */ -#define OP_MA 013 /* modify address */ -#define OP_MUL 014 /* multiply */ -#define OP_CS 021 /* clear storage */ -#define OP_S 022 /* subtract */ -#define OP_MTF 024 /* magtape function */ -#define OP_BWZ 025 /* branch wm or zone */ -#define OP_BBE 026 /* branch bit equal */ -#define OP_MZ 030 /* move zone */ -#define OP_MCS 031 /* move suppr zeroes */ -#define OP_SWM 033 /* set word mark */ -#define OP_DIV 034 /* divide */ -#define OP_SS 042 /* select stacker */ -#define OP_LCA 043 /* load characters */ -#define OP_MCW 044 /* move characters */ -#define OP_NOP 045 /* no op */ -#define OP_MCM 047 /* move to rec/grp mk */ -#define OP_SAR 050 /* store A register */ -#define OP_ZS 052 /* zero and subtract */ -#define OP_A 061 /* add */ -#define OP_B 062 /* branch */ -#define OP_C 063 /* compare */ -#define OP_MN 064 /* move numeric */ -#define OP_MCE 065 /* move char and edit */ -#define OP_CC 066 /* carriage control */ -#define OP_SBR 070 /* store B register */ -#define OP_ZA 072 /* zero and add */ -#define OP_H 073 /* halt */ -#define OP_CWM 074 /* clear word mark */ - -/* I/O addresses */ - -#define IO_INQ 023 /* inquiry terminal */ -#define IO_MT 024 /* magtape */ -#define IO_MTB 062 /* binary magtape */ -#define IO_DP 066 /* 1311 diskpack */ - -/* I/O modes */ - -#define MD_NORM 0 /* normal (move) */ -#define MD_WM 1 /* word mark (load) */ -#define MD_BIN 2 /* binary */ - -/* Indicator characters */ - -#define IN_UNC 000 /* unconditional */ -#define IN_CC9 011 /* carr ctrl chan 9 */ -#define IN_CC12 014 /* carr ctrl chan 12 */ -#define IN_UNQ 021 /* unequal */ -#define IN_EQU 022 /* equal */ -#define IN_LOW 023 /* low */ -#define IN_HGH 024 /* high */ -#define IN_DPW 025 /* parity/compare check */ -#define IN_LNG 026 /* wrong lnt record */ -#define IN_UNA 027 /* unequal addr cmp */ -#define IN_DSK 030 /* disk error */ -#define IN_OVF 031 /* overflow */ -#define IN_LPT 032 /* printer error */ -#define IN_PRO 034 /* process check */ -#define IN_DBY 036 /* disk busy */ -#define IN_END 042 /* end indicator */ -#define IN_TAP 043 /* tape error */ -#define IN_ACC 045 /* access error */ -#define IN_BSY 047 /* printer busy */ -#define IN_INR 050 /* inquiry request */ -#define IN_PCB 051 /* printer carr busy */ -#define IN_PNCH 052 /* punch error */ -#define IN_INC 054 /* inquiry clear */ -#define IN_LST 061 /* last card */ -#define IN_SSB 062 /* sense switch B */ -#define IN_SSC 063 /* sense switch C */ -#define IN_SSD 064 /* sense switch D */ -#define IN_SSE 065 /* sense switch E */ -#define IN_SSF 066 /* sense switch F */ -#define IN_SSG 067 /* sense switch G */ -#define IN_READ 072 /* reader error */ - -#define CRETIOE(f,c) return ((f)? (c): SCPE_OK) diff --git a/I1401/i1401_doc.txt b/I1401/i1401_doc.txt deleted file mode 100644 index 83d4b9d0..00000000 --- a/I1401/i1401_doc.txt +++ /dev/null @@ -1,503 +0,0 @@ -To: Users -From: Bob Supnik -Subj: IBM 1401 Simulator Usage -Date: 15-Jul-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - Original code published in 1993-2003, written by Robert M Supnik - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - -This memorandum documents the IBM 1401 simulator. - - -1. Simulator Files - -sim/ sim_defs.h - sim_rev.h - sim_sock.h - sim_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tape.c - sim_tmxr.c - -sim/i1401/ i1401_defs.h - i1401_dat.h - i1401_cpu.c - i1401_cd.c - i1401_iq.c - i1401_lp.c - i1401_dp.c - i1401_mt.c - i1401_sys.c - -2. IBM 1401 Features - -The IBM 1401 simulator is configured as follows: - -device simulates -name(s) - -CPU IBM 1401 CPU with 16K of memory -CDR,CDP IBM 1402 card reader/punch -LPT IBM 1403 line printer -INQ IBM 1407 inquiry terminal -DP IBM 1311 disk pack with five drives -MT IBM 729 7-track magnetic tape controller with six drives - -The IBM 1401 simulator implements many unique stop conditions. On almost -any kind of error the simulator stops: - - unimplemented opcode - reference to non-existent memory - reference to non-existent device - no word mark under opcode - invalid A address - invalid B address - invalid instruction length - invalid modifier character - invalid branch address - invalid magtape unit number - invalid magtape record length - write to locked magtape drive - skip to unpunched carriage control tape channel - card reader hopper empty - address register wrap-around - single character A field in MCE - single character B field in MCE - hanging $ in MCE with EPE enabled - I/O check with I/O stop switch set - invalid disk drive - invalid disk sector address - invalid disk sector count - invalid disk address compare - -The LOAD command is used to load a line printer carriage-control tape. -The DUMP command is not implemented. - -2.1 CPU - -The CPU options include a number of special features and the size of main -memory. Note that the Modify Address special feature is always included -when memory size is greater than 4K. - - SET CPU XSA enable advanced programming special feature - SET CPU NOXSA disable advanced programming - SET CPU HLE enable high/low/equal special feature - SET CPU NOHLE disable high/low/equal - SET CPU BBE enable branch on bit equal special feature - SET CPU NOBBE disable branch on bit equal - SET CPU MR enable move record special feature - SET CPU NOMR disable move record - SET CPU EPE enable extended print edit special feature - SET CPU NOEPE disable extended print edit - SET CPU MDV enable multiply/divide special feature - SET CPU NOMDV disable multiply/divide - SET CPU 4K set memory size = 4K - SET CPU 8K set memory size = 8K - SET CPU 12K set memory size = 12K - SET CPU 16K set memory size = 16K - -If memory size is being reduced, and the memory being truncated contains -non-zero data, the simulator asks for confirmation. Data in the truncated -portion of memory is lost. Initially, memory size is 16K, and all special -features are enabled. - -Memory is implemented as 7 bit BCD characters, as follows: - - 6 5 4 3 2 1 0 - - word B bit A bit 8 4 2 1 - mark <-- zone --> <-------- digit --------> - -In BCD, the decimal digits 0-9 are (octal) values 012, 001, 002, 003, 004, -005, 006, 007, 010, 011, respectively. Signs are encoded in the zone bits, -with 00, 01, and 11 being positive, and 10 being negative. - -CPU registers include the visible state of the processor. The 1401 has no -interrupt system. - - name size comments - - IS 14 instruction storage address register (PC) - AS 14 A storage address register - BS 14 B storage address register - ASERR 1 AS invalid flag - BSERR 1 BS invalid flag - SSA 1 sense switch A - SSB 1 sense switch B - SSC 1 sense switch C - SSD 1 sense switch D - SSE 1 sense switch E - SSF 1 sense switch F - SSG 1 sense switch G - EQU 1 equal compare indicator - UNEQ 1 unequal compare indicator - HIGH 1 high compare indicator - LOW 1 low compare indicator - OVF 1 overflow indicator - IOCHK 1 I/O check switch - PRCHK 1 process check switch - ISQ[0:63] 14 IS prior to last branch; - most recent IS change first - WRU 8 interrupt character - -2.2 1402 Card Reader/Punch (CDR, CDP, STKR) - -The IBM 1402 card/reader punch is simulated as three independent devices: -the card reader (CDR), the card punch (CDP), and the reader and punch -stackers (STKR). STRK units 0, 1, 2, and 4 correspond to the reader -normal stacker, reader stacker 1, shared stacker 2/8, and punch stacker -4, respectively. - -The card reader supports the BOOT command. BOOT CDR reads a card image -into locations 1-80, sets a word mark under location 1, clears storage, -and then transfers control to location 1. - -The card reader reads data from disk files, while the punch and stackers -write data to disk files. Cards are simulated as ASCII text lines with -terminating newlines; column binary is not supported. For each unit, -the POS register specifies the number of the next data item to be read or -written. Thus, by changing POS, the user can backspace or advance these -devices. - -The card reader registers are: - - name size comments - - LAST 1 last card indicator - ERR 1 error indicator - S1 1 stacker 1 select flag - S2 1 stacker 2 select flag - POS 32 position - TIME 24 delay window for stacker select - BUF[0:79] 8 reader buffer - -The card punch registers are: - - ERR 1 error indicator - S4 1 stacker 4 select flag - S8 1 stacker 8 select flag - -The stacker registers are: - - POS0 32 position, normal reader stack - POS1 32 position, reader stacker 1 - POS2 32 position, shared stacker 2/8 - POS4 32 position, punch stacker 4 - -Error handling is as follows: - - device error processed as - - reader end of file if SSA set, set LAST indicator - on next Read, report error and stop - - reader,punch not attached report error and stop - OS I/O error print error message - if IOCHK set, report error and stop - otherwise, set ERR indicator - - stacker not attached ignored - OS I/O error print error message - if IOCHK set, report error and stop - -2.3 1403 Line Printer (LPT) - -The IBM 1403 line printer (LPT) writes its data, converted to ASCII, to -a disk file. The line printer supports three different print character -sets or "chains": - - SET LPT PCF full 64 character chain - SET LPT PCA 48 character business chain - SET LPT PCH 48 character FORTRAN chain - -In addition, the line printer can be programmed with a carriage control -tape. The LOAD command loads a new carriage control tape: - - LOAD load carriage control tape file - -The format of a carriage control tape consists of multiple lines. Each -line contains an optional repeat count, enclosed in parentheses, optionally -followed by a series of column numbers separated by commas. Column numbers -must be between 1 and 12; a column number of zero denotes top of form. The -following are all legal carriage control specifications: - - no punch - (5) 5 lines with no punches - 1,5,7,8 columns 1, 5, 7, 8 punched - (10)2 10 lines with column 2 punched - 1,0 column 1 punched; top of form - -The default form is 66 lines long, with column 1 and the top of form mark -on line 1, and the rest blank. - -The line printer registers are: - - name size comments - - LINES 8 number of newlines after next print - LFLAG 1 carriage control flag (1 = skip, 0 = space) - CCTP 8 carriage control tape pointer - CCTL 8 carriage control tape length (read only) - ERR 1 error indicator - POS 32 position - CCT[0:131] 32 carriage control tape array - -Error handling is as follows: - - error processed as - - not attached report error and stop - - OS I/O error print error message - if IOCHK set, report error and stop - otherwise, set ERR indicator - -2.4 1407 Inquiry Terminal (INQ) - -The IBM 1407 inquiry terminal (INQ) is a half-duplex console. It polls -the console keyboard periodically for inquiry requests. The inquiry -terminal registers are: - - name size comments - - INQC 7 inquiry request character (initially ESC) - INR 1 inquiry request indicator - INC 1 inquiry cleared indicator - TIME 24 polling interval - -When the 1401 CPU requests input from the keyboard, the message [Enter] -is printed out, followed by a new line. The CPU hangs waiting for input -until either the return/enter key is pressed, or the inquiry request -character is typed in. The latter cancels the type-in and sets INC. - -The inquiry terminal has no errors. - -2.5 1311 Disk Pack (DP) - -The disk pack controller supports 5 drives, numbered 0 through 4. Disk -pack options include the ability to enable address writing (formatting). - - SET DPn ADDROFF set unit n address enable off - SET DPn ADDRON set unit n address enable on - -Units can also be set ONLINE or OFFLINE. - -Unlike most simulated disks, the 1311 includes explicit representation -for sector addresses. This is to support non-standard formats, such as -the inclusion of the drive number in the sector address. As a result, -1311 sectors are 106 characters long: 6 address characters and 100 -data characters. If the 1311 has not been formatted, the addresses -are blanks and are synthesized, if needed, based on the sector number. - -The 1311 also supports two modes of operation: move mode and load mode. -In move mode, word marks are ignored on writes and left untouched on reads, -and sectors hold 100 characters. In load mode, word marks are included -on writes and stored on reads, and sectors hold 90 characters. No attempt -is made to deal with sectors written in load mode and read in move mode, -or vice versa; on a real 1401, this causes a fatal parity error. - -The disk pack controller implements these registers: - - name size comments - - ACC 1 access error indicator - PWC 1 parity or write check error indicator - WLR 1 wrong length record error indicator - UNA 1 unequal address compare error indicator - DSK 1 any disk error indicator - BSY 1 disk access busy indicator - LASTF 3 most recent function - TIME 24 seek time - -The 1311 has a primative overlapped seek capability. If TIME is set -non-zero, the 1311 will report itself busy for the specified amount -of time following a seek. This allows programs to utilize the seek -time for processing. - -Error handling is as follows: - - error processed as - - not attached set DSK indicator - if IOCHK set, report error and stop - -1311 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.6 729 Magnetic Tape (MT) - -The magnetic tape controller supports six drives, numbered 1 through 6. -Magnetic tape options include the ability to make units write enabled or -or write locked. - - SET MTn LOCKED set unit n write locked - SET MTn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFLINE. The magnetic tape simulator -supports the BOOT command. BOOT MT reads the first record off tape, -starting at location 1, and then branches to it. - -The magnetic tape controller implements these registers: - - name size comments - - END 1 end of file indicator - ERR 1 error indicator - PAR 1 parity error indicator - POS1..6 32 position, drives 1..6 - -Error handling is as follows: - - error processed as - - not attached report error and stop - - end of file set error indicator - - OS I/O error print error message - set error indicator - if IOCHK set, report error and stop - -2.7 Symbolic Display and Input - -The IBM 1401 simulator implements symbolic display and input. Display is -controlled by command line switches: - - -c display as single character - (BCD for CPU and MT, ASCII for others) - -s display as wordmark terminated BCD string - (CPU only) - -m display instruction mnemonics - (CPU only) - -d display 50 characters per line, with word - marks denoted by "1" on the line below - -In a CPU character display, word marks are denoted by ~. - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or " or -c or -s characters (BCD for CPU and MT, ASCII - for others) - alphabetic instruction mnemonic - numeric octal number - -Instruction input is free format, with spaces separating fields. There -are six instruction formats: 1, 2, 4, 5, 7, and 8 characters: - - 1 character opcode - 2 character opcode 'modifier - 4 character opcode address - 5 character opcode address 'modifier - 7 character opcode address address - 8 character opcode address address 'modifier - -Addresses are always decimal, except for special I/O addresses in the A -field, which may be specified as %xy, where x denotes the device and y -the unit number. - -For the CPU, string input may encompass multiple characters. A word mark -is denoted by ~ and must precede the character to be marked. All other -devices can only accept single character input, without word marks. - -2.7 Character Sets - -The IBM 1401 uses a 6b character code called BCD (binary coded decimal). -Some of the characters have no equivalent in ASCII and require different -representations: - -BCD ASCII IBM 1401 print -code representation character chains - -00 space -01 1 -02 2 -03 3 -04 4 -05 5 -06 6 -07 7 -10 8 -11 9 -12 0 -13 # = in H chain -14 @ ' in H chain -15 : blank in A, H chains -16 > blank in A, H chains -17 ( tape mark blank in A, H chains -20 ^ alternate blank blank in A, H chains -21 / -22 S -23 T -24 U -25 V -26 W -27 X -30 Y -31 Z -32 ' record mark -33 , -34 % ( in H chain -35 = word mark blank in A, H chains -36 \ blank in A, H chains -37 + blank in A, H chains -40 - -41 J -42 K -43 L -44 M -45 N -46 O -47 P -50 Q -51 R -52 ! -53 $ -54 * -55 ] blank in A, H chains -56 ; blank in A, H chains -57 _ delta blank in A, H chains -60 & -61 A -62 B -63 C -64 D -65 E -66 F -67 G -70 H -71 I -72 ? -73 . -74 ) lozenge -75 [ blank in A, H chains -76 < blank in A, H chains -77 " group mark blank in A, H chains diff --git a/I1401/i1401_dp.c b/I1401/i1401_dp.c deleted file mode 100644 index 1e2a0686..00000000 --- a/I1401/i1401_dp.c +++ /dev/null @@ -1,555 +0,0 @@ -/* i1401_dp.c: IBM 1311 disk simulator - - Copyright (c) 2002-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - dp 1311 disk pack - - 18-Oct-02 RMS Fixed bug in address comparison logic - 19-Sep-02 RMS Minor edit for consistency with 1620 - 15-Jun-02 RMS Reworked address comparison logic - - The 1311 disk pack has 100 cylinders, 10 tracks/cylinder, 20 sectors/track. - Each sector contains 106 characters of information: - - 6c sector address - 100c sector data - - By default, a sector's address field will be '000000', which is illegal. - This is interpreted to mean the implied sector number that would be in - place if the disk pack had been formatted with sequential sector numbers. - - The sector data can be 100 characters without word marks, or 90 characters - with word marks. Load mode transfers 90 characters per sector with - word marks, move mode transfers 100 characters per sector without word - marks. No attempt is made to catch incompatible writes (eg, load mode - write followed by move mode read). -*/ - -#include "i1401_defs.h" - -#define DP_NUMDR 5 /* #drives */ -#define UNIT_V_WAE (UNIT_V_UF + 0) /* write addr enab */ -#define UNIT_WAE (1 << UNIT_V_WAE) - -/* Disk format */ - -#define DP_ADDR 6 /* address */ -#define DP_DATA 100 /* data */ -#define DP_NUMCH (DP_ADDR + DP_DATA) - -#define DP_NUMSC 20 /* #sectors */ -#define DP_NUMSF 10 /* #surfaces */ -#define DP_NUMCY 100 /* #cylinders */ -#define DP_TOTSC (DP_NUMCY*DP_NUMSF*DP_NUMSC) -#define DP_SIZE (DP_TOTSC*DP_NUMCH) - -/* Disk control field */ - -#define DCF_DRV 0 /* drive select */ -#define DCF_SEC 1 /* sector addr */ -#define DCF_SEC_LEN 6 -#define DCF_CNT (DCF_SEC + DCF_SEC_LEN) /* sector count */ -#define DCF_CNT_LEN 3 -#define DCF_LEN (DCF_CNT + DCF_CNT_LEN) -#define DCF_DIR 1 /* direct seek */ -#define DCF_DIR_LEN 4 -#define DCF_DIR_FL (DCF_DIR + DCF_DIR_LEN) /* direct seek flag */ -#define DCF_DSEEK 0xB - -/* Functions */ - -#define FNC_SEEK 0 /* seek */ -#define FNC_CHECK 3 /* check */ -#define FNC_READ 1 /* read sectors */ -#define FNC_RSCO 5 /* read sec cnt overlay */ -#define FNC_RTRK 6 /* read track */ -#define FNC_WOFF 10 /* offset for write */ -#define FNC_WRITE 11 /* write sectors */ -#define FNC_WRSCO 15 /* write sec cnt overlay */ -#define FNC_WRTRK 16 /* write track */ - -#define CYL u3 /* current cylinder */ - -extern uint8 M[]; /* memory */ -extern int32 ind[64]; -extern int32 AS, BS, iochk; -extern int32 bcd_to_bin[16]; -extern int32 bin_to_bcd[16]; -extern UNIT cpu_unit; - -int32 dp_lastf = 0; /* prior function */ -int32 dp_time = 0; /* seek time */ - -t_stat dp_reset (DEVICE *dptr); -t_stat dp_rdadr (UNIT *uptr, int32 sec, int32 flg, int32 wchk); -t_stat dp_rdsec (UNIT *uptr, int32 sec, int32 flg, int32 wchk); -t_stat dp_wradr (UNIT *uptr, int32 sec, int32 flg); -t_stat dp_wrsec (UNIT *uptr, int32 sec, int32 flg); -int32 dp_fndsec (UNIT *uptr, int32 sec, int32 dcf); -t_stat dp_nexsec (UNIT *uptr, int32 psec, int32 dcf); -t_bool dp_zeroad (uint8 *ap); -t_bool dp_cmp_ad (uint8 *ap, int32 dcf); -int32 dp_trkop (int32 drv, int32 sec); -int32 dp_cvt_bcd (int32 ad, int32 len); -void dp_cvt_bin (int32 ad, int32 len, int32 val, int32 flg); -int32 dp_get_cnt (int32 dcf); -void dp_fill (UNIT *uptr, uint32 da, int32 cnt); - -/* DP data structures - - dp_dev DSK device descriptor - dp_unit DSK unit list - dp_reg DSK register list - dp_mod DSK modifier list -*/ - -UNIT dp_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) } }; - -REG dp_reg[] = { - { FLDATA (ACC, ind[IN_ACC], 0) }, - { FLDATA (PWC, ind[IN_DPW], 0) }, - { FLDATA (WLR, ind[IN_LNG], 0) }, - { FLDATA (UNA, ind[IN_UNA], 0) }, - { FLDATA (ERR, ind[IN_DSK], 0) }, - { FLDATA (BSY, ind[IN_DBY], 0) }, - { DRDATA (LASTF, dp_lastf, 3) }, - { DRDATA (TIME, dp_time, 24), PV_LEFT }, - { URDATA (CYL, dp_unit[0].CYL, 10, 8, 0, - DP_NUMDR, PV_LEFT + REG_RO) }, - { NULL } }; - -MTAB dp_mod[] = { - { UNIT_WAE, 0, "write address disabled", "ADDROFF", NULL }, - { UNIT_WAE, UNIT_WAE, "write address enabled", "ADDRON", NULL }, - { 0 } }; - -DEVICE dp_dev = { - "DP", dp_unit, dp_reg, dp_mod, - DP_NUMDR, 10, 21, 1, 8, 7, - NULL, NULL, &dp_reset, - NULL, NULL, NULL }; - -/* Disk IO routine - - Inputs: - fnc = function character - flg = load vs move mode - mod = modifier character - Outputs: - status = status -*/ - -t_stat dp_io (int32 fnc, int32 flg, int32 mod) -{ -int32 dcf, drv, sec, psec, cnt, qwc, qzr, diff; -UNIT *uptr; -t_stat r; - -dcf = BS; /* save DCF addr */ -qwc = 0; /* not wcheck */ -ind[IN_DPW] = ind[IN_LNG] = ind[IN_UNA] = 0; /* clr indicators */ -ind[IN_DSK] = ind[IN_ACC] = ind[IN_DBY] = 0; -if (sim_is_active (&dp_unit[0])) { /* ctlr busy? */ - ind[IN_DBY] = ind[IN_DSK] = 1; /* set indicators */ - return SCPE_OK; } /* done */ - -AS = dcf + 6; /* AS for most ops */ -BS = dcf + DCF_CNT - 1; /* minimum DCF */ -if (ADDR_ERR (BS)) return STOP_WRAP; /* DCF in memory? */ -if (M[dcf] & BBIT) drv = M[dcf + DCF_SEC + 1] & 0xE; /* impl sel? cyl 8-4-2 */ -else drv = M[dcf] & DIGIT; /* get drive sel */ -if ((drv == 0) || (drv & 1) || (drv > BCD_ZERO)) /* bad drive #? */ - return STOP_INVDSK; -drv = bcd_to_bin[drv] >> 1; /* convert */ -uptr = dp_dev.units + drv; /* get unit ptr */ -if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ - ind[IN_DSK] = ind[IN_ACC] = 1; /* no, error */ - CRETIOE (iochk, SCPE_UNATT); } - -if ((fnc == FNC_SEEK) && /* seek and */ - (M[dcf + DCF_DIR_FL] & DCF_DSEEK) == DCF_DSEEK) { /* direct flag? */ - diff = dp_cvt_bcd (dcf + DCF_DIR, DCF_DIR_LEN); /* cvt diff */ - if (diff < 0) return STOP_INVDSC; /* error? */ - diff = diff >> 1; /* diff is *2 */ - if ((M[dcf + DCF_DIR + DCF_DIR_LEN - 1] & ZONE) == BBIT) - diff = -diff; /* get sign */ - uptr->CYL = uptr->CYL + diff; /* bound seek */ - if (uptr->CYL < 0) uptr->CYL = 0; - else if (uptr->CYL >= DP_NUMCY) { /* too big? */ - uptr->CYL = 0; /* system hangs */ - return STOP_INVDCY; } - sim_activate (&dp_unit[0], dp_time); /* set ctlr busy */ - return SCPE_OK; } /* done! */ - -sec = dp_cvt_bcd (dcf + DCF_SEC, DCF_SEC_LEN); /* cvt sector */ -if ((sec < 0) || (sec >= (DP_NUMDR * DP_TOTSC))) /* bad sector? */ - return STOP_INVDSC; -if (fnc == FNC_SEEK) { /* seek? */ - uptr->CYL = (sec / (DP_NUMSF * DP_NUMSC)) % /* set cyl # */ - DP_NUMCY; - sim_activate (&dp_unit[0], dp_time); /* set ctlr busy */ - return SCPE_OK; } /* done! */ - -BS = dcf + DCF_LEN; /* full DCF */ -if (ADDR_ERR (BS)) return STOP_WRAP; /* DCF in memory? */ -cnt = dp_get_cnt (dcf); /* get count */ -if (cnt < 0) return STOP_INVDCN; /* bad count? */ - -if (fnc >= FNC_WOFF) return STOP_INVDFN; /* invalid func */ -if (mod == BCD_W) { /* write? */ - if (fnc == FNC_CHECK) { /* write check? */ - qwc = 1; /* special read */ - fnc = dp_lastf; } /* use last func */ - else { - dp_lastf = fnc; /* save func */ - fnc = fnc + FNC_WOFF; } } /* change to write */ -else if (mod == BCD_R) dp_lastf = fnc; /* read? save func */ -else return STOP_INVM; /* other? error */ - -switch (fnc) { /* case on function */ -case FNC_RSCO: /* read sec cnt ov */ - BS = dcf + DCF_CNT; /* set count back */ - /* fall thru */ -case FNC_READ: /* read */ - psec = dp_fndsec (uptr, sec, dcf); /* find sector */ - if (psec < 0) CRETIOE (iochk, STOP_INVDAD); /* addr cmp error? */ - for (;;) { /* loop */ - qzr = (--cnt == 0); /* set zero latch */ - dp_cvt_bin (dcf + DCF_CNT, DCF_CNT_LEN, cnt, MD_WM); /* redo count */ - if (r = dp_rdsec (uptr, psec, flg, qwc)) /* read sector */ - break; - cnt = dp_get_cnt (dcf); /* get new count */ - if (cnt < 0) return STOP_INVDCN; /* bad count? */ - if (qzr) break; /* zero latch? done */ - sec++; psec++; /* next sector */ - dp_cvt_bin (dcf + DCF_SEC, DCF_SEC_LEN, sec, flg); /* rewr sec */ - if (r = dp_nexsec (uptr, psec, dcf)) break; /* find next */ - } - break; /* done, clean up */ - -case FNC_RTRK: /* read track */ - AS = dcf + 9; /* special AS */ - psec = dp_trkop (drv, sec); /* start of track */ - for (;;) { /* loop */ - qzr = (--cnt == 0); /* set zero latch */ - dp_cvt_bin (dcf + DCF_CNT, DCF_CNT_LEN, cnt, MD_WM); /* redo count */ - if (r = dp_rdadr (uptr, psec, flg, qwc)) /* read addr */ - break; /* error? */ - if (r = dp_rdsec (uptr, psec, flg, qwc)) /* read data */ - break; /* error? */ - cnt = dp_get_cnt (dcf); /* get new count */ - if (cnt < 0) return STOP_INVDCN; /* bad count? */ - if (qzr) break; /* zero latch? done */ - psec = dp_trkop (drv, sec) + ((psec + 1) % DP_NUMSC); } - break; /* done, clean up */ - -case FNC_WRSCO: /* write sec cnt ov */ - BS = dcf + DCF_CNT; /* set count back */ - /* fall through */ -case FNC_WRITE: /* read */ - psec = dp_fndsec (uptr, sec, dcf); /* find sector */ - if (psec < 0) CRETIOE (iochk, STOP_INVDAD); /* addr cmp error? */ - for (;;) { /* loop */ - qzr = (--cnt == 0); /* set zero latch */ - dp_cvt_bin (dcf + DCF_CNT, DCF_CNT_LEN, cnt, MD_WM); /* rewr cnt */ - if (r = dp_wrsec (uptr, psec, flg)) break; /* write data */ - if (qzr) break; /* zero latch? done */ - sec++; psec++; /* next sector */ - dp_cvt_bin (dcf + DCF_SEC, DCF_SEC_LEN, sec, flg); /* rewr sec */ - if (r = dp_nexsec (uptr, psec, dcf)) break; /* find next */ - } - break; /* done, clean up */ - -case FNC_WRTRK: /* write track */ - if ((uptr->flags & UNIT_WAE) == 0) /* enabled? */ - return STOP_WRADIS; - AS = dcf + 9; /* special AS */ - psec = dp_trkop (drv, sec); /* start of track */ - for (;;) { /* loop */ - qzr = (--cnt == 0); /* set zero latch */ - dp_cvt_bin (dcf + DCF_CNT, DCF_CNT_LEN, cnt, MD_WM); /* redo count */ - if (r = dp_wradr (uptr, psec, flg)) break; /* write addr */ - if (r = dp_wrsec (uptr, psec, flg)) break; /* write data */ - if (qzr) break; /* zero latch? done */ - psec = dp_trkop (drv, sec) + ((psec + 1) % DP_NUMSC); } - break; /* done, clean up */ - -default: /* unknown */ - return STOP_INVDFN; } - -if (r == SCPE_OK) { /* normal so far? */ - BS++; /* advance BS */ - if (ADDR_ERR (BS)) return STOP_WRAP; /* address error? */ - if (M[BS - 1] != (WM + BCD_GRPMRK)) { /* GM + WM at end? */ - ind[IN_LNG] = ind[IN_DSK] = 1; /* no, error */ - r = STOP_INVDLN; } } -CRETIOE (iochk || !ind[IN_DSK], r); /* return status */ -} - -/* Read or compare address with memory */ - -t_stat dp_rdadr (UNIT *uptr, int32 sec, int32 flg, int32 qwc) -{ -int32 i; -uint8 ac; -int32 da = (sec % DP_TOTSC) * DP_NUMCH; /* char number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ -t_bool zad = dp_zeroad (ap); /* zero address */ -static const int32 dec_tab[DP_ADDR] = /* powers of 10 */ - { 100000, 10000, 1000, 100, 10, 1} ; - -for (i = 0; i < DP_ADDR; i++) { /* copy address */ - if (M[BS] == (WM | BCD_GRPMRK)) { /* premature GWM? */ - ind[IN_LNG] = ind[IN_DSK] = 1; /* error */ - return STOP_INVDLN; } - if (zad) { /* addr zero? */ - ac = sec / dec_tab[i]; /* get addr digit */ - sec = sec % dec_tab[i]; /* get remainder */ - ac = bcd_to_bin[ac]; } /* cvt to BCD */ - else ac = *ap; /* addr char */ - if (qwc) { /* wr chk? skip if zad */ - if (!zad && (flg? (M[BS] != ac): /* L? cmp with WM */ - ((M[BS] & CHAR) != (ac & CHAR)))) { /* M? cmp w/o WM */ - ind[IN_DPW] = ind[IN_DSK] = 1; - return STOP_WRCHKE; } } - else if (flg) M[BS] = ac & CHAR; /* load mode */ - else M[BS] = (M[BS] & WM) | (ac & CHAR); /* move mode */ - ap++; BS++; /* adv ptrs */ - if (ADDR_ERR (BS)) return STOP_WRAP; } -return SCPE_OK; -} - -/* Read or compare data with memory */ - -t_stat dp_rdsec (UNIT *uptr, int32 sec, int32 flg, int32 qwc) -{ -int32 i, lim; -int32 da = (sec % DP_TOTSC) * DP_NUMCH; /* char number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da + DP_ADDR; /* buf ptr */ - -lim = flg? (DP_DATA - 10): DP_DATA; /* load vs move */ -for (i = 0; i < lim; i++) { /* copy data */ - if (M[BS] == (WM | BCD_GRPMRK)) { /* premature GWM? */ - ind[IN_LNG] = ind[IN_DSK] = 1; /* error */ - return STOP_INVDLN; } - if (qwc) { /* write check? */ - if (flg? (M[BS] != *ap): /* load mode cmp */ - ((M[BS] & CHAR) != (*ap & CHAR))) { /* move mode cmp */ - ind[IN_DPW] = ind[IN_DSK] = 1; /* error */ - return STOP_WRCHKE; } } - else if (flg) M[BS] = *ap & (WM | CHAR); /* load mode */ - else M[BS] = (M[BS] & WM) | (*ap & CHAR); /* word mode */ - ap++; BS++; /* adv ptrs */ - if (ADDR_ERR (BS)) return STOP_WRAP; } -return SCPE_OK; -} - -/* Write address to disk */ - -t_stat dp_wradr (UNIT *uptr, int32 sec, int32 flg) -{ -int32 i; -uint32 da = (sec % DP_TOTSC) * DP_NUMCH; /* char number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ - -for (i = 0; i < DP_ADDR; i++) { /* copy address */ - if (M[BS] == (WM | BCD_GRPMRK)) { /* premature GWM? */ - dp_fill (uptr, da, DP_NUMCH - i); /* fill, set err */ - ind[IN_LNG] = ind[IN_DSK] = 1; /* error */ - return STOP_INVDLN; } - if (flg) *ap = M[BS] & (WM | CHAR); /* L? copy WM */ - else *ap = M[BS] & CHAR; /* M? strip WM */ - if (da >= uptr->hwmark) uptr->hwmark = da + 1; - da++; ap++; BS++; /* adv ptrs */ - if (ADDR_ERR (BS)) return STOP_WRAP; } -return SCPE_OK; -} - -/* Write data to disk */ - -t_stat dp_wrsec (UNIT *uptr, int32 sec, int32 flg) -{ -int32 i, lim; -uint32 da = ((sec % DP_TOTSC) * DP_NUMCH) + DP_ADDR; /* char number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ - -lim = flg? (DP_DATA - 10): DP_DATA; /* load vs move */ -for (i = 0; i < lim; i++) { /* copy data */ - if (M[BS] == (WM | BCD_GRPMRK)) { /* premature GWM? */ - dp_fill (uptr, da, DP_DATA - i); /* fill, set err */ - ind[IN_LNG] = ind[IN_DSK] = 1; /* error */ - return STOP_INVDLN; } - if (flg) *ap = M[BS] & (WM | CHAR); /* load, copy WM */ - else *ap = M[BS] & CHAR; /* move, strip WM */ - if (da >= uptr->hwmark) uptr->hwmark = da + 1; - da++; ap++; BS++; /* adv ptrs */ - if (ADDR_ERR (BS)) return STOP_WRAP; } -return SCPE_OK; -} - -/* Find sector */ - -int32 dp_fndsec (UNIT *uptr, int32 sec, int32 dcf) -{ -int32 ctrk = sec % (DP_NUMSF * DP_NUMSC); /* curr trk-sec */ -int32 psec = ((uptr->CYL) * (DP_NUMSF * DP_NUMSC)) + ctrk; -int32 da = psec * DP_NUMCH; /* char number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ -int32 i; - -if (dp_zeroad (ap)) return psec; /* addr zero? ok */ -if (dp_cmp_ad (ap, dcf)) return psec; /* addr comp? ok */ -psec = psec - (psec % DP_NUMSC); /* sector 0 */ -for (i = 0; i < DP_NUMSC; i++, psec++) { /* check track */ - da = psec * DP_NUMCH; /* char number */ - ap = ((uint8 *) uptr->filebuf) + da; /* word pointer */ - if (dp_zeroad (ap)) continue; /* no implicit match */ - if (dp_cmp_ad (ap, dcf)) return psec; } /* match? */ -ind[IN_UNA] = ind[IN_DSK] = 1; /* no match */ -return -1; -} - -/* Find next sector - must be sequential, cannot cross cylinder boundary */ - -t_stat dp_nexsec (UNIT *uptr, int32 psec, int32 dcf) -{ -int32 ctrk = psec % (DP_NUMSF * DP_NUMSC); /* curr trk-sec */ -int32 da = psec * DP_NUMCH; /* word number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ - -if (ctrk) { /* not trk zero? */ - if (dp_zeroad (ap)) return SCPE_OK; /* addr zero? ok */ - if (dp_cmp_ad (ap, dcf)) return SCPE_OK; } /* addr comp? ok */ -ind[IN_UNA] = ind[IN_DSK] = 1; /* no, error */ -return STOP_INVDAD; -} - -/* Test for zero address */ - -t_bool dp_zeroad (uint8 *ap) -{ -int32 i; - -for (i = 0; i < DP_ADDR; i++, ap++) { /* loop thru addr */ - if (*ap & CHAR) return FALSE; } /* nonzero? lose */ -return TRUE; /* all zeroes */ -} - -/* Compare disk address to memory sector address - always omit word marks */ - -t_bool dp_cmp_ad (uint8 *ap, int32 dcf) -{ -int32 i; -uint8 c; - -for (i = 0; i < DP_ADDR; i++, ap++) { /* loop thru addr */ - c = M[dcf + DCF_SEC + i]; /* sector addr char */ - if ((c & CHAR) != (*ap & CHAR)) /* cmp w/o WM */ - return FALSE; } -return TRUE; /* compare ok */ -} - -/* Track operation setup */ - -int32 dp_trkop (int32 drv, int32 sec) -{ -int32 ctrk = (sec / DP_NUMSC) % DP_NUMSF; - -return ((drv * DP_TOTSC) + (dp_unit[drv].CYL * DP_NUMSF * DP_NUMSC) + - (ctrk * DP_NUMSC)); -} - -/* Convert DCF BCD field to binary */ - -int32 dp_cvt_bcd (int32 ad, int32 len) -{ -uint8 c; -int32 r; - -for (r = 0; len > 0; len--) { /* loop thru char */ - c = M[ad] & DIGIT; /* get digit */ - if ((c == 0) || (c > BCD_ZERO)) return -1; /* invalid? */ - r = (r * 10) + bcd_to_bin[c]; /* cvt to bin */ - ad++; } /* next digit */ -return r; -} - -/* Convert binary to DCF BCD field */ - -void dp_cvt_bin (int32 ad, int32 len, int32 val, int32 flg) -{ -int32 r; - -for ( ; len > 0; len--) { /* loop thru char */ - r = val % 10; /* get digit */ - if (flg) M[ad + len - 1] = bin_to_bcd[r]; /* load mode? */ - else M[ad + len - 1] = (M[ad + len - 1] & WM) | bin_to_bcd[r]; - val = val / 10; } -return; -} - -/* Get and validate count */ - -int32 dp_get_cnt (int32 dcf) -{ -int32 cnt = dp_cvt_bcd (dcf + DCF_CNT, DCF_CNT_LEN); /* get new count */ -if (cnt < 0) return -1; /* bad count? */ -if (cnt == 0) return 1000; /* 0 => 1000 */ -return cnt; -} - -/* Fill sector buffer with blanks */ - -void dp_fill (UNIT *uptr, uint32 da, int32 cnt) -{ -while (cnt-- > 0) { /* fill with blanks */ - *(((uint8 *) uptr->filebuf) + da) = BCD_BLANK; - if (da >= uptr->hwmark) uptr->hwmark = da + 1; - da++; } -return; -} - -/* Reset routine */ - -t_stat dp_reset (DEVICE *dptr) -{ -int32 i; - -for (i = 0; i < DP_NUMDR; i++) dp_unit[i].CYL = 0; /* reset cylinder */ -dp_lastf = 0; /* clear state */ -ind[IN_DPW] = ind[IN_LNG] = ind[IN_UNA] = 0; /* clr indicators */ -ind[IN_DSK] = ind[IN_ACC] = ind[IN_DBY] = 0; -sim_cancel (&dp_unit[0]); /* cancel timer */ -return SCPE_OK; -} diff --git a/I1401/i1401_iq.c b/I1401/i1401_iq.c deleted file mode 100644 index 5e8c5691..00000000 --- a/I1401/i1401_iq.c +++ /dev/null @@ -1,155 +0,0 @@ -/* i1401_iq.c: IBM 1407 inquiry terminal - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - inq 1407 inquiry terminal - - 22-Dec-02 RMS Added break support - 07-Sep-01 RMS Moved function prototypes - 14-Apr-99 RMS Changed t_addr to unsigned -*/ - -#include "i1401_defs.h" -#include - -extern volatile int32 stop_cpu; -extern uint8 M[]; -extern int32 BS, iochk, ind[64]; -extern char ascii_to_bcd[128], bcd_to_ascii[64]; -extern UNIT cpu_unit; - -int32 inq_char = 033; /* request inq */ -t_stat inq_svc (UNIT *uptr); -t_stat inq_reset (DEVICE *dptr); - -void puts_tty (char *cptr); - -/* INQ data structures - - inq_dev INQ device descriptor - inq_unit INQ unit descriptor - inq_reg INQ register list -*/ - -UNIT inq_unit = { UDATA (&inq_svc, 0, 0), KBD_POLL_WAIT }; - -REG inq_reg[] = { - { ORDATA (INQC, inq_char, 7) }, - { FLDATA (INR, ind[IN_INR], 0) }, - { FLDATA (INC, ind[IN_INC], 0) }, - { DRDATA (TIME, inq_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -DEVICE inq_dev = { - "INQ", &inq_unit, inq_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &inq_reset, - NULL, NULL, NULL }; - -/* Terminal I/O - - Modifiers have not been checked; legal modifiers are R and W -*/ - -t_stat inq_io (int32 flag, int32 mod) -{ -int32 i, t, wm_seen = 0; - -ind[IN_INC] = 0; /* clear inq clear */ -switch (mod) { /* case on mod */ -case BCD_R: /* input */ -/* if (ind[IN_INR] == 0) return SCPE_OK; /* return if no req */ - ind[IN_INR] = 0; /* clear req */ - puts_tty ("[Enter]\r\n"); /* prompt */ - for (i = 0; M[BS] != (BCD_GRPMRK + WM); i++) { /* until GM + WM */ - while (((t = sim_poll_kbd ()) == SCPE_OK) || - (t & SCPE_BREAK)) { - if (stop_cpu) return SCPE_STOP; } /* interrupt? */ - if (t < SCPE_KFLAG) return t; /* if not char, err */ - t = t & 0177; - if ((t == '\r') || (t == '\n')) break; - if (t == inq_char) { /* cancel? */ - ind[IN_INC] = 1; /* set indicator */ - puts_tty ("\r\n[Canceled]\r\n"); - return SCPE_OK; } - if (i && ((i % INQ_WIDTH) == 0)) puts_tty ("\r\n"); - sim_putchar (t); /* echo */ - if (flag == MD_WM) { /* word mark mode? */ - if ((t == '~') && (wm_seen == 0)) wm_seen = WM; - else { - M[BS] = wm_seen | ascii_to_bcd[t]; - wm_seen = 0; } } - else M[BS] = (M[BS] & WM) | ascii_to_bcd[t]; - if (!wm_seen) BS++; - if (ADDR_ERR (BS)) { - BS = BA | (BS % MAXMEMSIZE); - return STOP_NXM; } } - puts_tty ("\r\n"); - M[BS++] = BCD_GRPMRK + WM; - return SCPE_OK; -case BCD_W: /* output */ - for (i = 0; (t = M[BS++]) != (BCD_GRPMRK + WM); i++) { - if ((flag == MD_WM) && (t & WM)) { - if (i && ((i % INQ_WIDTH) == 0)) puts_tty ("\r\n"); - sim_putchar ('~'); } - if (i && ((i % INQ_WIDTH) == 0)) puts_tty ("\r\n"); - sim_putchar (bcd_to_ascii[t & CHAR]); - if (ADDR_ERR (BS)) { - BS = BA | (BS % MAXMEMSIZE); - return STOP_NXM; } } - puts_tty ("\r\n"); - return SCPE_OK; -default: - return STOP_INVM; } /* invalid mod */ -} - -/* Unit service - polls for WRU or inquiry request */ - -t_stat inq_svc (UNIT *uptr) -{ -int32 temp; - -sim_activate (&inq_unit, inq_unit.wait); /* continue poll */ -if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ -if ((temp & 0177) == inq_char) ind[IN_INR] = 1; /* set indicator */ -return SCPE_OK; -} - -/* Output multiple characters */ - -void puts_tty (char *cptr) -{ -if (cptr == NULL) return; -while (*cptr != 0) sim_putchar (*cptr++); -return; -} - -/* Reset routine */ - -t_stat inq_reset (DEVICE *dptr) -{ -ind[IN_INR] = ind[IN_INC] = 0; /* clear indicators */ -sim_activate (&inq_unit, inq_unit.wait); /* activate poll */ -return SCPE_OK; -} diff --git a/I1401/i1401_lp.c b/I1401/i1401_lp.c deleted file mode 100644 index 696b6f32..00000000 --- a/I1401/i1401_lp.c +++ /dev/null @@ -1,233 +0,0 @@ -/* i1401_lp.c: IBM 1403 line printer simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - lpt 1403 line printer - - 25-Apr-03 RMS Revised for extended file support - 30-May-02 RMS Widened POS to 32b - 13-Apr-01 RMS Revised for register arrays -*/ - -#include "i1401_defs.h" - -extern uint8 M[]; -extern char bcd_to_ascii[64]; -extern int32 iochk, ind[64]; - -int32 cct[CCT_LNT] = { 03 }; -int32 cctlnt = 66, cctptr = 0, lines = 0, lflag = 0; - -t_stat lpt_reset (DEVICE *dptr); -t_stat lpt_attach (UNIT *uptr, char *cptr); -t_stat space (int32 lines, int32 lflag); - -char bcd_to_pca[64] = { - ' ', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '0', '#', '@', ' ', ' ', ' ', - ' ', '/', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', ' ', ',', '%', ' ', ' ', ' ', - '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', '-', '$', '*', ' ', ' ', ' ', - '&', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', '&', '.', ')', ' ', ' ', ' ' }; -char bcd_to_pch[64] = { - ' ', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '0', '=', '\'', ' ', ' ', ' ', - ' ', '/', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', ' ', ',', '(', ' ', ' ', ' ', - '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', '-', '$', '*', ' ', ' ', ' ', - '&', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', '&', '.', ')', ' ', ' ', ' ' }; -char *pch_table[4] = { - bcd_to_ascii, bcd_to_pca, bcd_to_pch, bcd_to_ascii }; - -#define UNIT_V_PCHAIN (UNIT_V_UF + 0) -#define UNIT_M_PCHAIN 03 -#define M_PCF 00 /* full */ -#define M_PCA 01 /* business */ -#define M_PCH 02 /* Fortran */ -#define UNIT_PCHAIN (UNIT_M_PCHAIN << UNIT_V_PCHAIN) -#define PCF (M_PCF << UNIT_V_PCHAIN) -#define PCA (M_PCA << UNIT_V_PCHAIN) -#define PCH (M_PCH << UNIT_V_PCHAIN) -#define GET_PCHAIN(x) (((x) >> UNIT_V_PCHAIN) & UNIT_M_PCHAIN) -#define CHP(ch,val) ((val) & (1 << (ch))) - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list -*/ - -UNIT lpt_unit = { - UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }; - -REG lpt_reg[] = { - { FLDATA (ERR, ind[IN_LPT], 0) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { BRDATA (CCT, cct, 8, 32, CCT_LNT) }, - { DRDATA (LINES, lines, 8), PV_LEFT }, - { DRDATA (CCTP, cctptr, 8), PV_LEFT }, - { DRDATA (CCTL, cctlnt, 8), REG_RO + PV_LEFT }, - { NULL } }; - -MTAB lpt_mod[] = { - { UNIT_PCHAIN, PCF, "F chain", "PCF", NULL }, - { UNIT_PCHAIN, PCA, "A chain", "PCA", NULL }, - { UNIT_PCHAIN, PCH, "H chain", "PCH", NULL }, - { 0 } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, lpt_mod, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &lpt_reset, - NULL, &lpt_attach, NULL }; - -/* Print routine - - Modifiers have been checked by the caller - SQUARE = word mark mode - S = suppress automatic newline -*/ - -t_stat write_line (int32 ilnt, int32 mod) -{ -int32 i, t, wm, sup; -char *pch; -static char lbuf[LPT_WIDTH + 1]; /* + null */ - -if ((lpt_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ -wm = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_SQUARE); -sup = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_S); -ind[IN_LPT] = 0; /* clear error */ -pch = pch_table[GET_PCHAIN (lpt_unit.flags)]; /* get print chain */ -for (i = 0; i < LPT_WIDTH; i++) { /* convert print buf */ - t = M[LPT_BUF + i]; - if (wm) lbuf[i] = (t & WM)? '1': ' '; /* wmarks -> 1 or sp */ - else lbuf[i] = pch[t & CHAR]; } /* normal */ -M[LPT_BUF + 1] = 0; /* trailing null */ -for (i = LPT_WIDTH - 1; (i >= 0) && (lbuf[i] == ' '); i--) lbuf[i] = 0; -fputs (lbuf, lpt_unit.fileref); /* write line */ -if (lines) space (lines, lflag); /* cc action? do it */ -else if (sup == 0) space (1, FALSE); /* default? 1 line */ -else { fputc ('\r', lpt_unit.fileref); /* sup -> overprint */ - lpt_unit.pos = ftell (lpt_unit.fileref); } /* update position */ -lines = lflag = 0; /* clear cc action */ -if (ferror (lpt_unit.fileref)) { /* error? */ - perror ("Line printer I/O error"); - clearerr (lpt_unit.fileref); - if (iochk) return SCPE_IOERR; - ind[IN_LPT] = 1; } -return SCPE_OK; -} - -/* Carriage control routine - - The modifier has not been checked, its format is - <5:4> = 00, skip to channel now - = 01, space lines after - = 10, space lines now - = 11, skip to channel after - <3:0> = number of lines or channel number -*/ - -t_stat carriage_control (int32 mod) -{ -int32 i, action; - -action = (mod & ZONE) >> V_ZONE; /* get mod type */ -mod = mod & DIGIT; /* isolate value */ -switch (action) { -case 0: /* to channel now */ - if ((mod == 0) || (mod > 12) || CHP (mod, cct[cctptr])) return SCPE_OK; - for (i = 1; i < cctlnt + 1; i++) { /* sweep thru cct */ - if (CHP (mod, cct[(cctptr + i) % cctlnt])) - return space (i, TRUE); } - return STOP_CCT; /* runaway channel */ -case 1: /* space after */ - if (mod <= 3) { - lines = mod; /* save # lines */ - lflag = FALSE; /* flag spacing */ - ind[IN_CC9] = ind[IN_CC12] = 0; } - return SCPE_OK; -case 2: /* space now */ - if (mod <= 3) return space (mod, FALSE); - return SCPE_OK; -case 3: /* to channel after */ - if ((mod == 0) || (mod > 12)) return SCPE_OK; /* check channel */ - ind[IN_CC9] = ind[IN_CC12] = 0; - for (i = 1; i < cctlnt + 1; i++) { /* sweep thru cct */ - if (CHP (mod, cct[(cctptr + i) % cctlnt])) { - lines = i; /* save # lines */ - lflag = TRUE; /* flag skipping */ - return SCPE_OK; } } - return STOP_CCT; } /* runaway channel */ -return SCPE_OK; -} - -/* Space routine - space or skip n lines - - Inputs: - count = number of lines to space or skip - sflag = skip (TRUE) or space (FALSE) -*/ - -t_stat space (int32 count, int32 sflag) -{ -int32 i; - -if ((lpt_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT; -cctptr = (cctptr + count) % cctlnt; /* adv cct, mod lnt */ -if (sflag && CHP (0, cct[cctptr])) /* skip, top of form? */ - fputs ("\n\f", lpt_unit.fileref); /* nl, ff */ -else { for (i = 0; i < count; i++) - fputc ('\n', lpt_unit.fileref); } -lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */ -ind[IN_CC9] = CHP (9, cct[cctptr]) != 0; /* set indicators */ -ind[IN_CC12] = CHP (12, cct[cctptr]) != 0; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ -cctptr = 0; /* clear cct ptr */ -lines = lflag = 0; /* no cc action */ -ind[IN_LPT] = 0; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat lpt_attach (UNIT *uptr, char *cptr) -{ -cctptr = 0; /* clear cct ptr */ -lines = 0; /* no cc action */ -ind[IN_LPT] = 0; -return attach_unit (uptr, cptr); -} diff --git a/I1401/i1401_mt.c b/I1401/i1401_mt.c deleted file mode 100644 index d5888b8b..00000000 --- a/I1401/i1401_mt.c +++ /dev/null @@ -1,329 +0,0 @@ -/* i1401_mt.c: IBM 1401 magnetic tape simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - mt 7-track magtape - - 16-Aug-03 RMS End-of-record on load read works like move read - (verified on real 1401) - Added diagnostic read (space forward) - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 15-Mar-03 RMS Fixed end-of-record on load read yet again - 28-Feb-03 RMS Modified for magtape library - 31-Oct-02 RMS Added error record handling - 10-Oct-02 RMS Fixed end-of-record on load read writes WM plus GM - 30-Sep-02 RMS Revamped error handling - 28-Aug-02 RMS Added end of medium support - 12-Jun-02 RMS End-of-record on move read preserves old WM under GM - (found by Van Snyder) - 03-Jun-02 RMS Modified for 1311 support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Added protection against bad record lengths - 30-Jan-02 RMS New zero footprint tape bootstrap from Van Snyder - 20-Jan-02 RMS Changed write enabled modifier - 29-Nov-01 RMS Added read only unit support - 18-Apr-01 RMS Changed to rewind tape before boot - 07-Dec-00 RMS Widened display width from 6 to 8 bits to see record lnt - CEO Added tape bootstrap - 14-Apr-99 RMS Changed t_addr to unsigned - 04-Oct-98 RMS V2.4 magtape format - - Magnetic tapes are represented as a series of variable 16b records - of the form: - - 32b byte count - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32b byte count - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a byte count of 0. -*/ - -#include "i1401_defs.h" -#include "sim_tape.h" - -#define MT_NUMDR 7 /* #drives */ -#define MT_MAXFR (MAXMEMSIZE * 2) /* max transfer */ - -extern uint8 M[]; /* memory */ -extern int32 ind[64]; -extern int32 BS, iochk; -extern UNIT cpu_unit; -uint8 dbuf[MT_MAXFR]; /* tape buffer */ -t_stat mt_reset (DEVICE *dptr); -t_stat mt_boot (int32 unitno, DEVICE *dptr); -t_stat mt_map_status (t_stat st); -UNIT *get_unit (int32 unit); - -/* MT data structures - - mt_dev MT device descriptor - mt_unit MT unit list - mt_reg MT register list - mt_mod MT modifier list -*/ - -UNIT mt_unit[] = { - { UDATA (NULL, UNIT_DIS, 0) }, /* doesn't exist */ - { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + - UNIT_ROABLE + UNIT_BCD, 0) }, - { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + - UNIT_ROABLE + UNIT_BCD, 0) }, - { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + - UNIT_ROABLE + UNIT_BCD, 0) }, - { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + - UNIT_ROABLE + UNIT_BCD, 0) }, - { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + - UNIT_ROABLE + UNIT_BCD, 0) }, - { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + - UNIT_ROABLE + UNIT_BCD, 0) } }; - -REG mt_reg[] = { - { FLDATA (END, ind[IN_END], 0) }, - { FLDATA (ERR, ind[IN_TAP], 0) }, - { DRDATA (POS1, mt_unit[1].pos, T_ADDR_W), PV_LEFT + REG_RO }, - { DRDATA (POS2, mt_unit[2].pos, T_ADDR_W), PV_LEFT + REG_RO }, - { DRDATA (POS3, mt_unit[3].pos, T_ADDR_W), PV_LEFT + REG_RO }, - { DRDATA (POS4, mt_unit[4].pos, T_ADDR_W), PV_LEFT + REG_RO }, - { DRDATA (POS5, mt_unit[5].pos, T_ADDR_W), PV_LEFT + REG_RO }, - { DRDATA (POS6, mt_unit[6].pos, T_ADDR_W), PV_LEFT + REG_RO }, - { NULL } }; - -MTAB mt_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { 0 } }; - -DEVICE mt_dev = { - "MT", mt_unit, mt_reg, mt_mod, - MT_NUMDR, 10, 31, 1, 8, 8, - NULL, NULL, &mt_reset, - &mt_boot, &sim_tape_attach, &sim_tape_detach }; - -/* Function routine - - Inputs: - unit = unit character - mod = modifier character - Outputs: - status = status -*/ - -t_stat mt_func (int32 unit, int32 mod) -{ -t_mtrlnt tbc; -UNIT *uptr; -t_stat st; - -if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid unit? */ -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ -switch (mod) { /* case on modifier */ - -case BCD_A: /* diagnostic read */ - ind[IN_END] = 0; /* clear end of file */ - st = sim_tape_sprecf (uptr, &tbc); /* space fwd */ - break; - -case BCD_B: /* backspace */ - ind[IN_END] = 0; /* clear end of file */ - st = sim_tape_sprecr (uptr, &tbc); /* space rev */ - break; /* end case */ - -case BCD_E: /* erase = nop */ - if (sim_tape_wrp (uptr)) return STOP_MTL; - return SCPE_OK; - -case BCD_M: /* write tapemark */ - st = sim_tape_wrtmk (uptr); /* write tmk */ - break; - -case BCD_R: /* rewind */ - sim_tape_rewind (uptr); /* update position */ - return SCPE_OK; - -case BCD_U: /* unload */ - sim_tape_rewind (uptr); /* update position */ - return detach_unit (uptr); /* detach */ - -default: - return STOP_INVM; } - -return mt_map_status (st); -} - -/* Read and write routines - - Inputs: - unit = unit character - flag = normal, word mark, or binary mode - mod = modifier character - Outputs: - status = status - - Fine point: after a read, the system writes a group mark just - beyond the end of the record. However, first it checks for a - GM + WM; if present, the GM + WM is not changed. Otherwise, - an MCW read sets a GM, preserving the current WM; while an LCA - read sets a GM and clears the WM. -*/ - -t_stat mt_io (int32 unit, int32 flag, int32 mod) -{ -int32 t, wm_seen; -t_mtrlnt i, tbc; -t_stat st; -UNIT *uptr; - -if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid unit? */ -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ - -switch (mod) { -case BCD_R: /* read */ - ind[IN_TAP] = ind[IN_END] = 0; /* clear error */ - wm_seen = 0; /* no word mk seen */ - st = sim_tape_rdrecf (uptr, dbuf, &tbc, MT_MAXFR); /* read rec */ - if (st == MTSE_RECE) ind[IN_TAP] = 1; /* rec in error? */ - else if (st != MTSE_OK) break; /* stop on error */ - for (i = 0; i < tbc; i++) { /* loop thru buf */ - if (M[BS] == (BCD_GRPMRK + WM)) { /* GWM in memory? */ - BS++; /* incr BS */ - if (ADDR_ERR (BS)) { /* test for wrap */ - BS = BA | (BS % MAXMEMSIZE); - return STOP_WRAP; } - return SCPE_OK; } /* done */ - t = dbuf[i]; /* get char */ - if ((flag != MD_BIN) && (t == BCD_ALT)) t = BCD_BLANK; - if (flag == MD_WM) { /* word mk mode? */ - if ((t == BCD_WM) && (wm_seen == 0)) wm_seen = WM; - else { - M[BS] = wm_seen | (t & CHAR); - wm_seen = 0; } } - else M[BS] = (M[BS] & WM) | (t & CHAR); - if (!wm_seen) BS++; - if (ADDR_ERR (BS)) { /* check next BS */ - BS = BA | (BS % MAXMEMSIZE); - return STOP_WRAP; } } -/* if (M[BS] != (BCD_GRPMRK + WM)) { /* not GM+WM at end? */ -/* if (flag == MD_WM) M[BS] = BCD_GRPMRK; /* LCA: clear WM */ -/* else M[BS] = (M[BS] & WM) | BCD_GRPMRK; } /* MCW: save WM */ - M[BS] = (M[BS] & WM) | BCD_GRPMRK; /* write GM, save WM */ - BS++; /* adv BS */ - if (ADDR_ERR (BS)) { /* check final BS */ - BS = BA | (BS % MAXMEMSIZE); - return STOP_WRAP; } - break; - -case BCD_W: - if (uptr->flags & MTUF_WRP) return STOP_MTL; /* locked? */ - if (M[BS] == (BCD_GRPMRK + WM)) return STOP_MTZ; /* eor? */ - ind[IN_TAP] = ind[IN_END] = 0; /* clear error */ - for (tbc = 0; (t = M[BS++]) != (BCD_GRPMRK + WM); ) { - if ((t & WM) && (flag == MD_WM)) dbuf[tbc++] = BCD_WM; - if (((t & CHAR) == BCD_BLANK) && (flag != MD_BIN)) - dbuf[tbc++] = BCD_ALT; - else dbuf[tbc++] = t & CHAR; - if (ADDR_ERR (BS)) { /* check next BS */ - BS = BA | (BS % MAXMEMSIZE); - return STOP_WRAP; } } - st = sim_tape_wrrecf (uptr, dbuf, tbc); /* write record */ - if (ADDR_ERR (BS)) { /* check final BS */ - BS = BA | (BS % MAXMEMSIZE); - return STOP_WRAP; } - break; -default: - return STOP_INVM; } - -return mt_map_status (st); -} - -/* Get unit pointer from unit number */ - -UNIT *get_unit (int32 unit) -{ -if ((unit <= 0) || (unit >= MT_NUMDR)) return NULL; -return mt_dev.units + unit; -} - -/* Map tape status */ - -t_stat mt_map_status (t_stat st) -{ -switch (st) { -case MTSE_OK: /* no error */ -case MTSE_BOT: /* reverse into BOT */ - break; -case MTSE_FMT: /* illegal fmt */ - return SCPE_IERR; -case MTSE_UNATT: /* not attached */ - return SCPE_UNATT; -case MTSE_INVRL: /* invalid rec lnt */ - return SCPE_MTRLNT; -case MTSE_TMK: /* end of file */ - ind[IN_END] = 1; /* set end mark */ - break; -case MTSE_IOERR: /* IO error */ - ind[IN_TAP] = 1; /* set error */ - if (iochk) return SCPE_IOERR; - break; -case MTSE_RECE: /* record in error */ -case MTSE_EOM: /* end of medium */ - ind[IN_TAP] = 1; /* set error */ - break; -case MTSE_WRP: /* write protect */ - return STOP_MTL; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat mt_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -for (i = 0; i < MT_NUMDR; i++) { /* clear pos flag */ - if (uptr = get_unit (i)) MT_CLR_PNU (uptr); } -ind[IN_END] = ind[IN_TAP] = 0; /* clear indicators */ -return SCPE_OK; -} - -/* Bootstrap routine */ - -t_stat mt_boot (int32 unitno, DEVICE *dptr) -{ -extern int32 saved_IS; - -sim_tape_rewind (&mt_unit[unitno]); /* force rewind */ -BS = 1; /* set BS = 001 */ -mt_io (unitno, MD_WM, BCD_R); /* LDA %U1 001 R */ -saved_IS = 1; -return SCPE_OK; -} diff --git a/I1401/i1401_sys.c b/I1401/i1401_sys.c deleted file mode 100644 index 27e61090..00000000 --- a/I1401/i1401_sys.c +++ /dev/null @@ -1,339 +0,0 @@ -/* i1401_sys.c: IBM 1401 simulator interface - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 16-Mar-03 RMS Fixed mnemonic for MCS - 03-Jun-02 RMS Added 1311 support - 18-May-02 RMS Added -D feature from Van Snyder - 26-Jan-02 RMS Fixed H, NOP with no trailing wm (found by Van Snyder) - 17-Sep-01 RMS Removed multiconsole support - 13-Jul-01 RMS Fixed bug in symbolic output (found by Peter Schorn) - 27-May-01 RMS Added multiconsole support - 14-Mar-01 RMS Revised load/dump interface (again) - 30-Oct-00 RMS Added support for examine to file - 27-Oct-98 RMS V2.4 load interface -*/ - -#include "i1401_defs.h" -#include - -#define LINE_LNT 80 -extern DEVICE cpu_dev, inq_dev, lpt_dev; -extern DEVICE cdr_dev, cdp_dev, stack_dev; -extern DEVICE dp_dev, mt_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern uint8 M[]; -extern char bcd_to_ascii[64], ascii_to_bcd[128]; -extern char *get_glyph (char *cptr, char *gbuf, char term); -extern int32 store_addr_h (int32 addr); -extern int32 store_addr_t (int32 addr); -extern int32 store_addr_u (int32 addr); - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax maximum number of words for examine/deposit - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "IBM 1401"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = LINE_LNT; - -DEVICE *sim_devices[] = { - &cpu_dev, - &inq_dev, - &cdr_dev, - &cdp_dev, - &stack_dev, - &lpt_dev, - &mt_dev, - &dp_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unimplemented instruction", - "Non-existent memory", - "Non-existent device", - "No WM at instruction start", - "Invalid A address", - "Invalid B address", - "Invalid instruction length", - "Invalid modifer", - "Invalid branch address", - "Breakpoint", - "HALT instruction", - "Invalid MT unit number", - "Invalid MT record length", - "Write to locked MT unit", - "Skip to unpunched CCT channel", - "Card reader empty", - "Address register wrap", - "MCE data field too short", - "MCE control field too short", - "MCE EPE hanging $", - "I/O check", - "Invalid disk sector address", - "Invalid disk sector count", - "Invalid disk unit", - "Invalid disk function", - "Invalid disk record length", - "Write track while disabled", - "Write check error", - "Disk address miscompare", - "Direct seek cylinder exceeds maximum" - }; - -/* Binary loader -- load carriage control tape - - A carriage control tape consists of entries of the form - - (repeat count) column number,column number,column number,... - - The CCT entries are stored in cct[0:lnt-1], cctlnt contains the - number of entries -*/ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 col, rpt, ptr, mask, cctbuf[CCT_LNT]; -t_stat r; -extern int32 cctlnt, cctptr, cct[CCT_LNT]; -char cbuf[CBUFSIZE], gbuf[CBUFSIZE]; - -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; -ptr = 0; -for ( ; (cptr = fgets (cbuf, CBUFSIZE, fileref)) != NULL; ) { /* until eof */ - mask = 0; - if (*cptr == '(') { /* repeat count? */ - cptr = get_glyph (cptr + 1, gbuf, ')'); /* get 1st field */ - rpt = get_uint (gbuf, 10, CCT_LNT, &r); /* repeat count */ - if (r != SCPE_OK) return SCPE_FMT; } - else rpt = 1; - while (*cptr != 0) { /* get col no's */ - cptr = get_glyph (cptr, gbuf, ','); /* get next field */ - col = get_uint (gbuf, 10, 12, &r); /* column number */ - if (r != SCPE_OK) return SCPE_FMT; - mask = mask | (1 << col); } /* set bit */ - for ( ; rpt > 0; rpt--) { /* store vals */ - if (ptr >= CCT_LNT) return SCPE_FMT; - cctbuf[ptr++] = mask; } } -if (ptr == 0) return SCPE_FMT; -cctlnt = ptr; -cctptr = 0; -for (rpt = 0; rpt < cctlnt; rpt++) cct[rpt] = cctbuf[rpt]; -return SCPE_OK; -} - -/* Symbol table */ - -const char *opcode[64] = { - NULL, "R", "W", "WR", "P", "RP", "WP", "WRP", - "RF", "WF", NULL, "MA", "MUL", NULL, NULL, NULL, - NULL, "CS", "S", NULL, "MTF", "BWZ", "BBE", NULL, - "MZ", "MCS", NULL, "SWM", "DIV", NULL, NULL, NULL, - NULL, NULL, "SS", "LCA", "MCW", "NOP", NULL, "MCM", - "SAR", NULL, "ZS", NULL, NULL, NULL, NULL, NULL, - NULL, "A", "B", "C", "MN", "MCE", "CC", NULL, - "SBR", NULL, "ZA", "H", "CWM", NULL, NULL, NULL }; - -/* Print an address from three characters */ - -void fprint_addr (FILE *of, t_value *dig) -{ -int32 addr, xa; -extern int32 hun_table[64], ten_table[64], one_table[64]; - -addr = hun_table[dig[0]] + ten_table[dig[1]] + one_table[dig[2]]; -xa = (addr >> V_INDEX) & M_INDEX; -if (xa) fprintf (of, " %d,%d", addr & ADDRMASK, ((xa - (X1 >> V_INDEX)) / 5) + 1); -else if (addr >= MAXMEMSIZE) fprintf (of, " %d*", addr & ADDRMASK); -else fprintf (of, " %d", addr); -return; -} - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current address - *val = values to decode - *uptr = pointer to unit - sw = switches - Outputs: - return = if >= 0, error code - if < 0, number of extra words retired -*/ - -#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 op, flags, ilnt, i, t; -extern int32 op_table[64], len_table[9]; - -if (sw & SWMASK ('C')) { /* character? */ - t = val[0]; - if (uptr->flags & UNIT_BCD) - fprintf (of, (t & WM)? "~%c": "%c", bcd_to_ascii[t & CHAR]); - else fprintf (of, FMTASC (t & 0177)); - return SCPE_OK; } -if ((uptr != NULL) && (uptr != &cpu_unit)) return SCPE_ARG; /* CPU? */ -if (sw & SWMASK ('D')) { /* dump? */ - for (i = 0; i < 50; i++) fprintf (of, "%c", bcd_to_ascii[val[i]&CHAR]) ; - fprintf (of, "\n\t"); - for (i = 0; i < 50; i++) fprintf (of, (val[i]&WM)? "1": " ") ; - return -(i - 1); } -if (sw & SWMASK ('S')) { /* string? */ - i = 0; - do { - t = val[i++]; - fprintf (of, (t & WM)? "~%c": "%c", bcd_to_ascii[t & CHAR]); } - while ((i < LINE_LNT) && ((val[i] & WM) == 0)); - return -(i - 1); } -if ((sw & SWMASK ('M')) == 0) return SCPE_ARG; - -if ((val[0] & WM) == 0) return STOP_NOWM; /* WM under op? */ -op = val[0]& CHAR; /* isolate op */ -flags = op_table[op]; /* get flags */ -for (ilnt = 1; ilnt < sim_emax; ilnt++) if (val[ilnt] & WM) break; -if ((flags & (NOWM | HNOP)) && (ilnt > 7)) ilnt = 7; /* cs, swm, h, nop? */ -else if ((op == OP_B) && (ilnt > 4) && (val[4] == BCD_BLANK)) ilnt = 4; -else if ((ilnt > 8) && (op != OP_NOP)) ilnt = 8; /* cap length */ -if (((flags & len_table[ilnt]) == 0) && /* valid lnt, */ - ((op != OP_NOP) == 0)) return STOP_INVL; /* nop? */ -fprintf (of, "%s",opcode[op]); /* print opcode */ -if (ilnt > 2) { /* A address? */ - if (((flags & IO) || (op == OP_NOP)) && (val[1] == BCD_PERCNT)) - fprintf (of, " %%%c%c", bcd_to_ascii[val[2]], bcd_to_ascii[val[3]]); - else fprint_addr (of, &val[1]); } -if (ilnt > 5) fprint_addr (of, &val[4]); /* B address? */ -if ((ilnt == 2) || (ilnt == 5) || (ilnt == 8)) /* d character? */ - fprintf (of, " '%c", bcd_to_ascii[val[ilnt - 1]]); -return -(ilnt - 1); /* return # chars */ -} - -/* get_addr - get address + index pair */ - -t_stat get_addr (char *cptr, t_value *val) -{ -int32 addr, index; -t_stat r; -char gbuf[CBUFSIZE]; - -cptr = get_glyph (cptr, gbuf, ','); /* get address */ -addr = get_uint (gbuf, 10, MAXMEMSIZE, &r); -if (r != SCPE_OK) return SCPE_ARG; -if (*cptr != 0) { /* more? */ - cptr = get_glyph (cptr, gbuf, ' '); - index = get_uint (gbuf, 10, 3, &r); - if ((r != SCPE_OK) || (index == 0)) return SCPE_ARG; } -else index = 0; -if (*cptr != 0) return SCPE_ARG; -val[0] = store_addr_h (addr); -val[1] = store_addr_t (addr) | (index << V_ZONE); -val[2] = store_addr_u (addr); -return SCPE_OK; -} - -/* get_io - get I/O address */ - -t_stat get_io (char *cptr, t_value *val) -{ -if ((cptr[0] != '%') || (cptr[3] != 0) || !isalnum (cptr[1]) || - !isalnum (cptr[2])) return SCPE_ARG; -val[0] = BCD_PERCNT; -val[1] = ascii_to_bcd[cptr[1]]; -val[2] = ascii_to_bcd[cptr[2]]; -return SCPE_OK; -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = > 0 error code - <= 0 -number of extra words -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 i, op, ilnt, t, cflag, wm_seen; -extern int32 op_table[64], len_table[9]; -char gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ -if ((sw & SWMASK ('C')) || (sw & SWMASK ('S')) || (*cptr == '~') || - ((*cptr == '\'') && cptr++) || ((*cptr == '"') && cptr++)) { - wm_seen = 0; - for (i = 0; (i < sim_emax) && (*cptr != 0); ) { - t = *cptr++; /* get character */ - if (cflag && (wm_seen == 0) && (t == '~')) wm_seen = WM; - else if (uptr->flags & UNIT_BCD) { - if (t < 040) return SCPE_ARG; - val[i++] = ascii_to_bcd[t] | wm_seen; - wm_seen = 0; } - else val[i++] = t; } - if ((i == 0) || wm_seen) return SCPE_ARG; - return -(i-1); } - -if (cflag == 0) return SCPE_ARG; /* CPU only */ -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -for (op = 0; op < 64; op++) /* look it up */ - if (opcode[op] && strcmp (gbuf, opcode[op]) == 0) break; -if (op >= 64) return SCPE_ARG; /* successful? */ -val[0] = op | WM; /* store opcode */ -cptr = get_glyph (cptr, gbuf, 0); /* get addr or d */ -if (((op_table[op] && IO) && (get_io (gbuf, &val[1]) == SCPE_OK)) || - (get_addr (gbuf, &val[1]) == SCPE_OK)) { - cptr = get_glyph (cptr, gbuf, 0); /* get addr or d */ - if (get_addr (gbuf, &val[4]) == SCPE_OK) { - cptr = get_glyph (cptr, gbuf, ','); /* get d */ - ilnt = 7; } /* a and b addresses */ - else ilnt = 4; } /* a address */ -else ilnt = 1; /* no addresses */ -if ((gbuf[0] == '\'') || (gbuf[0] == '"')) { /* d character? */ - t = gbuf[1]; - if ((gbuf[2] != 0) || (*cptr != 0) || (t < 040)) - return SCPE_ARG; /* end and legal? */ - val[ilnt] = ascii_to_bcd[t]; /* save D char */ - ilnt = ilnt + 1; } -else if (gbuf[0] != 0) return SCPE_ARG; /* not done? */ -if ((op_table[op] & len_table[ilnt]) == 0) return STOP_INVL; -return -(ilnt - 1); -} diff --git a/I1620/i1620_cd.c b/I1620/i1620_cd.c deleted file mode 100644 index 4c3ecb86..00000000 --- a/I1620/i1620_cd.c +++ /dev/null @@ -1,405 +0,0 @@ -/* i1620_cd.c: IBM 1622 card reader/punch - - Copyright (c) 2002-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - cdr 1622 card reader - cdp 1622 card punch - - 25-Apr-03 RMS Revised for extended file support - - Cards are represented as ASCII text streams terminated by newlines. - This allows cards to be created and edited as normal files. -*/ - -#include "i1620_defs.h" - -#define CD_LEN 80 - -extern uint8 M[MAXMEMSIZE]; -extern uint8 ind[NUM_IND]; -extern UNIT cpu_unit; -extern int32 io_stop; - -char cdr_buf[CD_LEN + 2]; -char cdp_buf[CD_LEN + 2]; - -t_stat cdr_reset (DEVICE *dptr); -t_stat cdr_attach (UNIT *uptr, char *cptr); -t_stat cdr_boot (int32 unitno, DEVICE *dptr); -t_stat cdr_read (void); -t_stat cdp_reset (DEVICE *dptr); -t_stat cdp_write (uint32 len); -t_stat cdp_num (uint32 pa, uint32 ndig, t_bool dump); - -/* Card reader data structures - - cdr_dev CDR descriptor - cdr_unit CDR unit descriptor - cdr_reg CDR register list -*/ - -UNIT cdr_unit = { - UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) }; - -REG cdr_reg[] = { - { FLDATA (LAST, ind[IN_LAST], 0) }, - { DRDATA (POS, cdr_unit.pos, T_ADDR_W), PV_LEFT }, - { NULL } }; - -DEVICE cdr_dev = { - "CDR", &cdr_unit, cdr_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &cdr_reset, - &cdr_boot, &cdr_attach, NULL }; - -/* CDP data structures - - cdp_dev CDP device descriptor - cdp_unit CDP unit descriptor - cdp_reg CDP register list -*/ - -UNIT cdp_unit = { - UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }; - -REG cdp_reg[] = { - { DRDATA (POS, cdp_unit.pos, T_ADDR_W), PV_LEFT }, - { NULL } }; - -DEVICE cdp_dev = { - "CDP", &cdp_unit, cdp_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &cdp_reset, - NULL, NULL, NULL }; - -/* Data tables. The card reader presents unusual problems. - - Unique codes needed for 11-2-8 (uses !) and 12-7-8 (uses ") . - - Can punch both 11 (-) and 11-0 (uses ]). - On input, the nul and nl generated by C are converted to - spaces; tabs and line feeds are also converted to spaces. - -/* Card reader (ASCII) to numeric (one digit) */ - -const char cdr_to_num[128] = { - 0x00, -1, -1, -1, -1, -1, -1, -1, /* 00 */ - -1, 0x00, 0x00, -1, -1, 0x00, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */ - -1, -1, -1, -1, -1, -1, -1, -1, - 0x00, 0x1A, 0x1F, 0x00, 0x1B, 0x0A, 0x0F, 0x0A, /* !"#$%&' */ - 0x0C, 0x0C, 0x1C, 0x00, 0x0B, 0x10, 0x1B, 0x01, /* ()*+,-./ */ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */ - 0x08, 0x09, 0x00, 0x1E, 0x1E, 0x0B, 0x0E, 0x1A, /* 89:;<=>? */ - 0x0C, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* @ABCDEFG */ - 0x08, 0x09, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /* HIJKLMNO */ - 0x17, 0x18, 0x19, 0x02, 0x03, 0x04, 0x05, 0x06, /* PQRSTUVW */ - 0x07, 0x08, 0x09, 0x00, 0x0E, 0x10, 0x0F, 0x1F, /* XYZ[\]^_ */ - -1, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* abcdefg */ - 0x08, 0x09, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /* hijklmno */ - 0x17, 0x18, 0x19, 0x02, 0x03, 0x04, 0x05, 0x06, /* pqrstuvw */ - 0x07, 0x08, 0x09, -1, -1, -1, -1, -1 }; /* xyz */ - -/* Numeric (flag + digit) to card punch (ASCII) */ - -const char num_to_cdp[32] = { - '0', '1', '2', '3', '4', '5', '6', '7', /* 0 */ - '8', '9', '\'', ',', ' ', '&', ' ', '&', - ']', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* F + 0 */ - 'Q', 'R', '!', '$', -1, -1, -1, '"' }; - -/* Card reader (ASCII) to alphameric (two digits) - - 11-2-8 (!) reads as 5A - 11-7-8 (_) reads as 5F - 12-2-8 (?) reads inconsistently (here 02) - 12-6-8 (<) reads inconsistently (here 5E) - 12-7-8 (") reads as 5F -*/ - -const char cdr_to_alp[128] = { - 0x00, -1, -1, -1, -1, -1, -1, -1, /* 00 */ - -1, 0x00, 0x00, -1, -1, 0x00, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */ - -1, -1, -1, -1, -1, -1, -1, -1, - 0x00, 0x5A, 0x5F, 0x60, 0x13, 0x0A, 0x0F, 0x0A, /* !"#$%&' */ - 0x24, 0x04, 0x14, 0x10, 0x23, 0x20, 0x03, 0x21, /* ()*+,-./ */ - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 01234567 */ - 0x78, 0x79, 0x70, 0x5E, 0x5E, 0x33, 0x0E, 0x02, /* 89:;<=>? */ - 0x34, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* @ABCDEFG */ - 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* HIJKLMNO */ - 0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* PQRSTUVW */ - 0x67, 0x68, 0x69, 0x40, 0x0E, 0x50, 0x0F, 0x5F, /* XYZ[\]^_ */ - -1, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* abcdefg */ - 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* hijklmno */ - 0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* pqrstuvw */ - 0x67, 0x68, 0x69, -1, -1, -1, -1, -1 }; /* xyz */ - -/* Alphameric (two digits) to card punch (ASCII). Oddities: - - 02 -> 12-2-8 (?), symmetric - 07 -> 12-7-8 ("), reads as 5F - 12 -> 11-2-8 (!), reads as 5A - 15 -> 11,0 (]), reads as 50 - 22 -> 0-2-8 ('), reads as 0A - 32 -> 2-8 (%), reads as 0A - 5B -> 11-3-8 (=), reads as 13 - 6A -> 0-2-8 ('), reads as 0A - 6B -> 0-3-8 (,), reads as 23 - AA -> 0-2-8 ('), reads as 0A - - There is no way to punch 0-5-8 (#), 0-6-8 (\), - 11-5-8 (]), 11-6-8 (;), 11-7-8 (_), - 12-5-8 ([), or 12-6-8 (<) -*/ - -const char alp_to_cdp[256] = { - ' ', -1, '?', '.', ')', -1, -1, '"', /* 00 */ - -1, -1, '\'', -1, -1, -1, -1, '&', - '+', -1, '!', '$', '*', ']', -1, -1, /* 10 */ - -1, -1, -1, -1, -1, -1, -1, -1, - '-', '/', '\'', ',', '(', -1, -1, -1, /* 20 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, '%', '=', '@', ':', ' ', -1, /* 30 */ - -1, -1, '\'', -1, -1, -1, -1, '&', - -1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40 */ - 'H', 'I', -1, -1, -1, -1, -1, -1, - '_', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */ - 'Q', 'R', '?', '=', -1, -1, -1, '"', - -1, '/', 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */ - 'Y', 'Z', '\'', ',', -1, -1, -1, -1, - '0', '1', '2', '3', '4', '5', '6', '7', /* 70 */ - '8', '9', -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* A0 */ - -1, -1, '\'', -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* B0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* C0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* D0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* E0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* F0 */ - -1, -1, -1, -1, -1, -1, -1, -1 }; - -/* Card reader IO routine - - - Hard errors stop the operation and halt the system. - - Invalid characters place a blank in memory and set RDCHK. - If IO stop is set, the system halts at the end of the operation. -*/ - -t_stat cdr (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -int32 i; -int8 cdc; -t_stat r, inv = SCPE_OK; - -switch (op) { /* case on op */ -case OP_RN: /* read numeric */ - r = cdr_read (); /* fill reader buf */ - if (r != SCPE_OK) return r; /* error? */ - for (i = 0; i < CD_LEN; i++) { /* transfer to mem */ - cdc = cdr_to_num[cdr_buf[i]]; /* translate */ - if (cdc < 0) { /* invalid? */ - ind[IN_RDCHK] = 1; /* set read check */ - inv = STOP_INVCHR; /* set return status */ - cdc = 0; } - M[pa] = cdc; /* store digit */ - PP (pa); } /* incr mem addr */ - break; -case OP_RA: /* read alphameric */ - r = cdr_read (); /* fill reader buf */ - if (r != SCPE_OK) return r; /* error? */ - for (i = 0; i < CD_LEN; i++) { /* transfer to mem */ - cdc = cdr_to_alp[cdr_buf[i]]; /* translate */ - if (cdc < 0) { /* invalid? */ - ind[IN_RDCHK] = 1; /* set read check */ - inv = STOP_INVCHR; /* set return status */ - cdc = 0; }; - M[pa] = (M[pa] & FLAG) | (cdc & DIGIT); /* store 2 digits */ - M[pa - 1] = (M[pa - 1] & FLAG) | ((cdc >> 4) & DIGIT); - pa = ADDR_A (pa, 2); } /* incr mem addr */ - break; -default: /* invalid function */ - return STOP_INVFNC; } -CRETIOE (io_stop, inv); -} - -/* Fill card reader buffer - all errors are hard errors */ - -t_stat cdr_read (void) -{ -int32 i; - -ind[IN_LAST] = 0; /* clear last card */ -if ((cdr_unit.flags & UNIT_ATT) == 0) { /* attached? */ - ind[IN_RDCHK] = 1; /* no, error */ - return SCPE_UNATT; } - -for (i = 0; i < CD_LEN + 1; i++) cdr_buf[i] = ' '; /* clear buffer */ -fgets (cdr_buf, CD_LEN, cdr_unit.fileref); /* read card */ -if (feof (cdr_unit.fileref)) return STOP_NOCD; /* eof? */ -if (ferror (cdr_unit.fileref)) { /* error? */ - ind[IN_RDCHK] = 1; /* set read check */ - perror ("CDR I/O error"); - clearerr (cdr_unit.fileref); - return SCPE_IOERR; } -cdr_unit.pos = ftell (cdr_unit.fileref); /* update position */ -getc (cdr_unit.fileref); /* see if more */ -if (feof (cdr_unit.fileref)) ind[IN_LAST] = 1; /* eof? set last */ -fseek (cdr_unit.fileref, cdr_unit.pos, SEEK_SET); /* "backspace" */ -return SCPE_OK; -} - -/* Card reader attach */ - -t_stat cdr_attach (UNIT *uptr, char *cptr) -{ -ind[IN_LAST] = 0; /* clear last card */ -return attach_unit (uptr, cptr); -} - -/* Card reader reset */ - -t_stat cdr_reset (DEVICE *dptr) -{ -ind[IN_LAST] = 0; /* clear last card */ -return SCPE_OK; -} - -/* Bootstrap routine */ - -const static uint8 boot_rom[] = { - 3, 6, 1, 9, 9, 0, 1, 0, 0, 5, 0, 0, /* RNCD 19901 */ - 2, 5, 0, 0, 0, 8, 0, 1, 9, 9, 1, 0x10, /* TD 80,-19910 */ - 3, 1, 1, 9, 9, 0, 0x15, 1, 9, 9, 2, 0, /* TR -19905,19920 */ - 2, 5, 1, 9, 9, 1, 0x10, 0, 0, 0, 8, 0, /* TD -19910,80 */ - 4, 9, 1, 9, 9, 1, 0x15, 0, 0, 0, 0, 0 }; /* BR -19915 */ - -#define BOOT_START 0 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8)) - -t_stat cdr_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -if ((cpu_unit.flags & IF_IA) == 0) return SCPE_NOFNC; /* must have IA */ -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} - -/* Card punch IO routine - - - Hard errors stop the operation and halt the system. - - Invalid characters stop the operation and set WRCHK. - If IO stop is set, the system halts. -*/ - -t_stat cdp (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -int32 i; -int8 cdc; -uint8 z, d; - -switch (op) { /* decode op */ -case OP_DN: - return cdp_num (pa, 20000 - (pa % 20000), TRUE); /* dump numeric */ -case OP_WN: - return cdp_num (pa, CD_LEN, FALSE); /* write numeric */ -case OP_WA: - for (i = 0; i < CD_LEN; i++) { /* one card */ - d = M[pa] & DIGIT; /* get digit pair */ - z = M[pa - 1] & DIGIT; - cdc = alp_to_cdp[(z << 4) | d]; /* translate */ - if (cdc < 0) { /* bad char? */ - ind[IN_WRCHK] = 1; /* set write check */ - CRETIOE (io_stop, STOP_INVCHR); } - cdp_buf[i] = cdc; /* store in buf */ - pa = ADDR_A (pa, 2); } /* incr mem addr */ - return cdp_write (CD_LEN); /* punch buffer */ -default: /* invalid function */ - return STOP_INVFNC; } -return SCPE_OK; -} - -/* Punch card numeric */ - -t_stat cdp_num (uint32 pa, uint32 ndig, t_bool dump) -{ -int32 i, ncd, len; -uint8 d; -int8 cdc; -t_stat r; - -ncd = ndig / CD_LEN; /* number of cards */ -while (ncd-- >= 0) { /* until done */ - len = (ncd >= 0)? CD_LEN: (ndig % CD_LEN); /* card length */ - if (len == 0) break; - for (i = 0; i < len; i++) { /* one card */ - d = M[pa] & (FLAG | DIGIT); /* get char */ - if (dump && (d == FLAG)) cdc = '-'; /* dump? F+0 is diff */ - else cdc = num_to_cdp[d]; /* translate */ - if (cdc < 0) { /* bad char? */ - ind[IN_WRCHK] = 1; /* set write check */ - CRETIOE (io_stop, STOP_INVCHR); } /* stop */ - cdp_buf[i] = cdc; /* store in buf */ - PP (pa); } /* incr mem addr */ - r = cdp_write (len); /* punch card */ - if (r != SCPE_OK) return r; } /* error? */ -return SCPE_OK; -} - -/* Write punch card buffer - all errors are hard errors */ - -t_stat cdp_write (uint32 len) -{ -if ((cdp_unit.flags & UNIT_ATT) == 0) { /* attached? */ - ind[IN_WRCHK] = 1; /* no, error */ - return SCPE_UNATT; } - -while ((len > 0) && (cdp_buf[len - 1] == ' ')) --len; /* trim spaces */ -cdp_buf[len] = '\n'; /* newline, null */ -cdp_buf[len + 1] = 0; - -if (fputs (cdp_buf, cdp_unit.fileref) == EOF) { /* write card */ - ind[IN_WRCHK] = 1; /* error? */ - perror ("CDP I/O error"); - clearerr (cdp_unit.fileref); - return SCPE_IOERR; } -cdp_unit.pos = ftell (cdp_unit.fileref); /* count char */ -return SCPE_OK; -} - -/* Reset card punch */ - -t_stat cdp_reset (DEVICE *dptr) -{ -return SCPE_OK; -} diff --git a/I1620/i1620_cpu.c b/I1620/i1620_cpu.c deleted file mode 100644 index f6cfa8ec..00000000 --- a/I1620/i1620_cpu.c +++ /dev/null @@ -1,1884 +0,0 @@ -/* i1620_cpu.c: IBM 1620 CPU simulator - - Copyright (c) 2002-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - This CPU module incorporates code and comments from the 1620 simulator by - Geoff Kuenning, with his permission. - - 21-Aug-03 RMS Fixed bug in immediate index add (found by Michael Short) - 25-Apr-03 RMS Changed t_addr to uint32 throughout - 18-Oct-02 RMS Fixed bugs in invalid result testing (found by Hans Pufal) - - The simulated register state for the IBM 1620 is: - - 1620 sim comment - - IR1 [PC] program counter - IR2 instruction register 2 (subroutine return address) - OR1 [QAR] Q address - OR2 [PAR] P address - PR1 manual save address - ind[0:99] indicators - - Additional internal registers OR3, PR2, and PR3 are not simulated. - - The IBM 1620 is a fixed instruction length, variable data length, decimal - data system. Memory consists of 20000 - 60000 BCD digits, each containing - four bits of data and a flag. There are no general registers; all - instructions are memory to memory. - - The 1620 uses a fixed, 12 digit instruction format: - - oo ppppp qqqqq - - where - - oo = opcode - ppppp = P (usually destination) address - qqqqq = Q (usually source) address - - Immediate instructions use the qqqqq field as the second operand. - - The 1620 Model 1 uses table lookups for add and multiply; for that reason, - it was nicknamed CADET (Can't Add, Doesn't Even Try). The Model 2 does - adds in hardware and uses the add table memory for index registers. -*/ - -/* This routine is the instruction decode routine for the IBM 1620. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - breakpoint encountered - illegal addresses or instruction formats - I/O error in I/O simulator - - 2. Interrupts. The 1620 has no interrupt structure. - - 3. Non-existent memory. On the 1620, all memory references - are modulo the memory size. - - 4. Adding I/O devices. These modules must be modified: - - i1620_cpu.c add iodisp table entry - i1620_sys.c add sim_devices table entry -*/ - -#include "i1620_defs.h" - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = saved_PC - -uint8 M[MAXMEMSIZE] = { 0 }; /* main memory */ -uint32 saved_PC = 0; /* saved PC */ -uint32 IR2 = 1; /* inst reg 2 */ -uint32 PAR = 0; /* P address */ -uint32 QAR = 0; /* Q address */ -uint32 PR1 = 1; /* proc reg 1 */ -uint32 iae = 1; /* ind addr enb */ -uint32 idxe = 0; /* index enable */ -uint32 idxb = 0; /* index band */ -uint32 io_stop = 1; /* I/O stop */ -uint32 ar_stop = 1; /* arith stop */ -int32 ind_max = 16; /* iadr nest limit */ -uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -uint8 ind[NUM_IND] = { 0 }; /* indicators */ - -extern int32 sim_int_char; -extern int32 sim_interval; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern FILE *sim_log; - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_set_opt1 (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_opt2 (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_save (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_table (UNIT *uptr, int32 val, char *cptr, void *desc); - -int32 get_2d (uint32 ad); -t_stat get_addr (uint32 alast, int32 lnt, t_bool indexok, uint32 *addr); -t_stat cvt_addr (uint32 alast, int32 lnt, t_bool signok, int32 *val); -t_stat get_idx (uint32 aidx); -t_stat xmt_field (uint32 d, uint32 s, uint32 skp); -t_stat xmt_record (uint32 d, uint32 s, t_bool cpy); -t_stat xmt_index (uint32 d, uint32 s); -t_stat xmt_divd (uint32 d, uint32 s); -t_stat xmt_tns (uint32 d, uint32 s); -t_stat xmt_tnf (uint32 d, uint32 s); -t_stat add_field (uint32 d, uint32 s, t_bool sub, t_bool sto, uint32 skp, int32 *sta); -uint32 add_one_digit (uint32 dst, uint32 src, uint32 *cry); -t_stat mul_field (uint32 mpc, uint32 mpy); -t_stat mul_one_digit (uint32 mpyd, uint32 mpcp, uint32 prop, uint32 last); -t_stat div_field (uint32 dvd, uint32 dvr, int32 *ez); -t_stat div_one_digit (uint32 dvd, uint32 dvr, uint32 max, uint32 *quod, uint32 *quop); -t_stat oct_to_dec (uint32 tbl, uint32 s); -t_stat dec_to_oct (uint32 d, uint32 tbl, int32 *ez); -t_stat or_field (uint32 d, uint32 s); -t_stat and_field (uint32 d, uint32 s); -t_stat xor_field (uint32 d, uint32 s); -t_stat com_field (uint32 d, uint32 s); -void upd_ind (void); - -extern tty (uint32 op, uint32 pa, uint32 f0, uint32 f1); -extern ptp (uint32 op, uint32 pa, uint32 f0, uint32 f1); -extern ptr (uint32 op, uint32 pa, uint32 f0, uint32 f1); -extern cdp (uint32 op, uint32 pa, uint32 f0, uint32 f1); -extern cdr (uint32 op, uint32 pa, uint32 f0, uint32 f1); -extern dp (uint32 op, uint32 pa, uint32 f0, uint32 f1); -extern lpt (uint32 op, uint32 pa, uint32 f0, uint32 f1); -extern btp (uint32 op, uint32 pa, uint32 f0, uint32 f1); -extern btr (uint32 op, uint32 pa, uint32 f0, uint32 f1); - -extern t_stat fp_add (uint32 d, uint32 s, t_bool sub); -extern t_stat fp_mul (uint32 d, uint32 s); -extern t_stat fp_div (uint32 d, uint32 s); -extern t_stat fp_fsl (uint32 d, uint32 s); -extern t_stat fp_fsr (uint32 d, uint32 s); - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifier list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX+UNIT_BCD+MI_STD, MAXMEMSIZE) }; - -REG cpu_reg[] = { - { DRDATA (PC, saved_PC, 16), PV_LEFT }, - { DRDATA (IR2, IR2, 16), PV_LEFT }, - { DRDATA (PR1, PR1, 16), PV_LEFT }, - { DRDATA (PAR, PAR, 16), PV_LEFT + REG_RO }, - { DRDATA (QAR, QAR, 16), PV_LEFT + REG_RO }, - { FLDATA (SW1, ind[IN_SW1], 0) }, - { FLDATA (SW2, ind[IN_SW2], 0) }, - { FLDATA (SW3, ind[IN_SW3], 0) }, - { FLDATA (SW4, ind[IN_SW4], 0) }, - { FLDATA (HP, ind[IN_HP], 0) }, - { FLDATA (EZ, ind[IN_EZ], 0) }, - { FLDATA (OVF, ind[IN_OVF], 0) }, - { FLDATA (EXPCHK, ind[IN_EXPCHK], 0) }, - { FLDATA (RDCHK, ind[IN_RDCHK], 0) }, - { FLDATA (WRCHK, ind[IN_WRCHK], 0) }, - { FLDATA (ARSTOP, ar_stop, 0) }, - { FLDATA (IOSTOP, io_stop, 0) }, - { BRDATA (IND, ind, 10, 1, NUM_IND) }, - { FLDATA (IAE, iae, 0) }, - { FLDATA (IDXE, idxe, 0) }, - { FLDATA (IDXB, idxb, 0) }, - { DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT }, - { BRDATA (PCQ, pcq, 10, 14, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { IF_IA, IF_IA, "IA", "IA", &cpu_set_opt1 }, - { IF_IA, 0, "no IA", "NOIA", &cpu_set_opt1 }, - { IF_EDT, IF_EDT, "EDT", "EDT", &cpu_set_opt1 }, - { IF_EDT, 0, "no EDT", "NOEDT", &cpu_set_opt1 }, - { IF_DIV, IF_DIV, "DIV", "DIV", &cpu_set_opt1 }, - { IF_DIV, 0, "no DIV", "NODIV", &cpu_set_opt1 }, - { IF_FP, IF_FP, "FP", "FP", NULL }, - { IF_FP, 0, "no FP", "NOFP", NULL }, - { IF_BIN, IF_BIN, "BIN", "BIN", &cpu_set_opt2 }, - { IF_BIN, 0, "no BIN", "NOBIN", &cpu_set_opt2 }, - { IF_IDX, IF_IDX, "IDX", "IDX", &cpu_set_opt2 }, - { IF_IDX, 0, "no IDX", "NOIDX", &cpu_set_opt2 }, - { IF_MII, IF_MII, "Model 2", "MOD2", &cpu_set_model }, - { IF_MII, 0, "Model 1", "MOD1", &cpu_set_model }, - { UNIT_MSIZE, 20000, NULL, "20K", &cpu_set_size }, - { UNIT_MSIZE, 40000, NULL, "40K", &cpu_set_size }, - { UNIT_MSIZE, 60000, NULL, "60K", &cpu_set_size }, - { UNIT_MSIZE, 0, NULL, "SAVE", &cpu_set_save }, - { UNIT_MSIZE, 0, NULL, "TABLE", &cpu_set_table }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 10, 18, 1, 16, 5, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -/* Instruction table */ - -const int32 op_table[100] = { - 0, /* 0 */ - IF_FP + IF_VPA + IF_VQA, /* FADD */ - IF_FP + IF_VPA + IF_VQA, /* FSUB */ - IF_FP + IF_VPA + IF_VQA, /* FMUL */ - 0, - IF_FP + IF_VPA + IF_VQA, /* FSL */ - IF_FP + IF_MII + IF_VPA + IF_VQA, /* TFL */ - IF_FP + IF_MII + IF_VPA + IF_VQA, /* BTFL */ - IF_FP + IF_VPA + IF_VQA, /* FSR */ - IF_FP + IF_VPA + IF_VQA, /* FDV */ - IF_MII + IF_VPA + IF_IMM, /* 10: BTAM */ - IF_VPA + IF_IMM, /* AM */ - IF_VPA + IF_IMM, /* SM */ - IF_VPA + IF_IMM, /* MM */ - IF_VPA + IF_IMM, /* CM */ - IF_VPA + IF_IMM, /* TDM */ - IF_VPA + IF_IMM, /* TFM */ - IF_VPA + IF_IMM, /* BTM */ - IF_DIV + IF_VPA + IF_IMM, /* LDM */ - IF_DIV + IF_VPA + IF_IMM, /* DM */ - IF_MII + IF_VPA + IF_VQA, /* 20: BTA */ - IF_VPA + IF_VQA, /* A */ - IF_VPA + IF_VQA, /* S */ - IF_VPA + IF_VQA, /* M */ - IF_VPA + IF_VQA, /* C */ - IF_VPA + IF_VQA, /* TD */ - IF_VPA + IF_VQA, /* TF */ - IF_VPA + IF_VQA, /* BT */ - IF_DIV + IF_VPA + IF_VQA, /* LD */ - IF_DIV + IF_VPA + IF_VQA, /* D */ - IF_MII + IF_VPA + IF_VQA, /* 30: TRNM */ - IF_VPA + IF_VQA, /* TR */ - IF_VPA, /* SF */ - IF_VPA, /* CF */ - IF_VPA, /* K */ - IF_VPA, /* DN */ - IF_VPA, /* RN */ - IF_VPA, /* RA */ - IF_VPA, /* WN */ - IF_VPA, /* WA */ - 0, /* 40 */ - 0, /* NOP */ - 0, /* BB */ - IF_VPA + IF_VQA, /* BD */ - IF_VPA + IF_VQA, /* BNF */ - IF_VPA + IF_VQA, /* BNR */ - IF_VPA, /* BI */ - IF_VPA, /* BNI */ - 0, /* H */ - IF_VPA, /* B */ - 0, /* 50 */ - 0, - 0, - 0, - 0, - IF_VPA + IF_VQA, /* BNG - disk sys */ - 0, - 0, - 0, - 0, - IF_MII + IF_VPA, /* 60: BS */ - IF_IDX + IF_VPA + IF_NQX, /* BX */ - IF_IDX + IF_VPA + IF_IMM, /* BXM */ - IF_IDX + IF_VPA + IF_NQX, /* BCX */ - IF_IDX + IF_VPA + IF_IMM, /* BCXM */ - IF_IDX + IF_VPA + IF_NQX, /* BLX */ - IF_IDX + IF_VPA + IF_IMM, /* BLXM */ - IF_IDX + IF_VPA + IF_NQX, /* BSX */ - 0, - 0, - IF_IDX + IF_VPA + IF_VQA, /* 70: MA */ - IF_EDT + IF_VPA + IF_VQA, /* MF */ - IF_EDT + IF_VPA + IF_VQA, /* MF */ - IF_EDT + IF_VPA + IF_VQA, /* TNF */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, /* 80 */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - IF_BIN + IF_VPA + IF_4QA, /* 90: BBT */ - IF_BIN + IF_VPA + IF_4QA, /* BMK */ - IF_BIN + IF_VPA + IF_VQA, /* ORF */ - IF_BIN + IF_VPA + IF_VQA, /* ANDF */ - IF_BIN + IF_VPA + IF_VQA, /* CPLF */ - IF_BIN + IF_VPA + IF_VQA, /* EORF */ - IF_BIN + IF_VPA + IF_VQA, /* OTD */ - IF_BIN + IF_VPA + IF_VQA, /* DTO */ - 0, - 0 - }; - -/* IO dispatch table */ - -t_stat (*iodisp[NUM_IO])(uint32 op, uint32 pa, uint32 f0, uint32 f1) = { - NULL, &tty, &ptp, &ptr, &cdp, /* 00 - 09 */ - &cdr, NULL, &dp, NULL, &lpt, - NULL, NULL, NULL, NULL, NULL, /* 10 - 19 */ - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, /* 20 - 29 */ - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, &btp, &btr, NULL, /* 30 - 39 */ - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, /* 40 - 49 */ - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, /* 50 - 59 */ - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, /* 60 - 69 */ - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, /* 70 - 79 */ - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, /* 80 - 89 */ - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, /* 90 - 99 */ - NULL, NULL, NULL, NULL, NULL }; - -/* Indicator table: -1 = illegal, +1 = resets when tested */ - -const int32 ind_table[NUM_IND] = { - -1, 0, 0, 0, 0, -1, 1, 1, -1, 1, /* 00 - 09 */ - -1, 0, 0, 0, 1, 1, 1, 1, -1, 0, /* 10 - 19 */ - -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, /* 20 - 29 */ - 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, /* 30 - 39 */ - -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, /* 40 - 49 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 50 - 59 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 60 - 69 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 - 79 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 - 89 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; /* 90 - 99 */ - -/* Add table for 1620 Model 1 */ - -const uint8 std_add_table[ADD_TABLE_LEN] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, - 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, - 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, - 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, - 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 }; - - -/* Add table for 1620 Model 2 ("hardware add") */ - -const uint8 sum_table[20] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 }; - -/* Multiply table */ - -const uint8 std_mul_table[MUL_TABLE_LEN] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, - 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, - 0, 0, 3, 0, 6, 0, 9, 0, 2, 1, - 0, 0, 4, 0, 8, 0, 2, 1, 6, 1, - 0, 0, 5, 0, 0, 1, 5, 1, 0, 2, - 0, 0, 6, 0, 2, 1, 8, 1, 4, 2, - 0, 0, 7, 0, 4, 1, 1, 2, 8, 2, - 0, 0, 8, 0, 6, 1, 4, 2, 2, 3, - 0, 0, 9, 0, 8, 1, 7, 2, 6, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, - 0, 1, 2, 1, 4, 1, 6, 1, 8, 1, - 5, 1, 8, 1, 1, 2, 4, 2, 7, 2, - 0, 2, 4, 2, 8, 2, 2, 3, 6, 3, - 5, 2, 0, 3, 5, 3, 0, 4, 5, 4, - 0, 3, 6, 3, 2, 4, 8, 4, 4, 5, - 5, 3, 2, 4, 9, 4, 6, 5, 3, 6, - 0, 4, 8, 4, 6, 5, 4, 6, 2, 7, - 5, 4, 4, 5, 3, 6, 2, 7, 1, 8 }; - -#define BRANCH(x) PCQ_ENTRY; PC = (x) -#define GET_IDXADDR(x) ((idxb? IDX_B: IDX_A) + ((x) * ADDR_LEN) + (ADDR_LEN - 1)) - -t_stat sim_instr (void) -{ -uint32 PC, pla, qla, f0, f1; -int32 i, t, idx, flags, sta, dev, op; -t_stat reason; - -/* Restore saved state */ - -PC = saved_PC; -if ((cpu_unit.flags & IF_IA) == 0) iae = 0; -if ((cpu_unit.flags & IF_IDX) == 0) idxe = idxb = 0; -upd_ind (); /* update indicators */ -reason = 0; - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ -saved_PC = PC; /* commit prev instr */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - -sim_interval = sim_interval - 1; - -/* Instruction fetch and address decode */ - -if (PC & 1) { /* PC odd? */ - reason = STOP_INVIAD; /* stop */ - break; } - -op = get_2d (PC); /* get opcode */ -if (op < 0) { /* invalid? */ - reason = STOP_INVINS; - break; } -flags = op_table[op]; /* get op, flags */ -if ((flags & ALLOPT) && /* need option? */ - !(flags & ALLOPT & cpu_unit.flags)) { /* any set? */ - reason = STOP_INVINS; /* no, error */ - break; } - -pla = ADDR_A (PC, I_PL); /* P last addr */ -qla = ADDR_A (PC, I_QL); /* Q last addr */ -if (flags & IF_VPA) { /* need P? */ - reason = get_addr (pla, 5, TRUE, &PAR); /* get P addr */ - if (reason != SCPE_OK) break; } /* stop if error */ -if (flags & (IF_VQA | IF_4QA | IF_NQX)) { /* need Q? */ - reason = get_addr (qla, /* get Q addr */ - ((flags & IF_4QA)? 4: 5), /* 4 or 5 digits */ - ((flags & IF_NQX)? FALSE: TRUE), /* not or indexed */ - &QAR); - if (reason != SCPE_OK) { /* stop if invalid */ - reason = reason + (STOP_INVQDG - STOP_INVPDG); - break; } } -else if (flags & IF_IMM) QAR = qla; /* immediate? */ -PC = PC + INST_LEN; /* advance PC */ -switch (op) { /* case on op */ - -/* Transmit digit - P,Q are valid */ - -case OP_TD: -case OP_TDM: - M[PAR] = M[QAR] & (FLAG | DIGIT); /* move dig, flag */ - break; - -/* Transmit field - P,Q are valid */ - -case OP_TF: -case OP_TFM: - reason = xmt_field (PAR, QAR, 1); /* xmit field */ - break; - -/* Transmit record - P,Q are valid */ - -case OP_TR: - reason = xmt_record (PAR, QAR, TRUE); /* xmit record */ - break; - -/* Transmit record no record mark - P,Q are valid */ - -case OP_TRNM: - reason = xmt_record (PAR, QAR, FALSE); /* xmit record but */ - break; /* not rec mark */ - -/* Set flag - P is valid */ - -case OP_SF: - M[PAR] = M[PAR] | FLAG; /* set flag on P */ - break; - -/* Clear flag - P is valid */ - -case OP_CF: - M[PAR] = M[PAR] & ~FLAG; /* clear flag on P */ - break; - -/* Branch - P is valid */ - -case OP_B: - BRANCH (PAR); /* branch to P */ - break; - -/* Branch and transmit - P,Q are valid */ - -case OP_BT: -case OP_BTM: - reason = xmt_field (ADDR_S (PAR, 1), QAR, 1); /* xmit field to P-1 */ - IR2 = PC; /* save PC */ - BRANCH (PAR); /* branch to P */ - break; - -/* Branch and transmit floating - P,Q are valid */ - -case OP_BTFL: - reason = xmt_field (ADDR_S (PAR, 1), QAR, 3); /* skip 3 flags */ - IR2 = PC; /* save PC */ - BRANCH (PAR); /* branch to P */ - break; - -/* Branch and transmit address - P,Q are valid */ - -case OP_BTA: -case OP_BTAM: - reason = xmt_field (ADDR_S (PAR, 1), QAR, 4); /* skip 4 flags */ - IR2 = PC; /* save PC */ - BRANCH (PAR); /* branch to P */ - break; - -/* Branch back */ - -case OP_BB: - if (PR1 != 1) { /* PR1 valid? */ - BRANCH (PR1); /* return to PR1 */ - PR1 = 1; } /* invalidate */ - else if (IR2 != 1) { /* IR2 valid? */ - BRANCH (IR2); /* return to IR2 */ - IR2 = 1; } /* invalidate */ - else reason = STOP_INVRTN; /* MAR check */ - break; - -/* Branch on digit (zero) - P,Q are valid */ - -case OP_BD: - if ((M[QAR] & DIGIT) == 0) { /* digit == 0? */ - BRANCH (PAR); } /* branch */ - break; - -/* Branch no flag - P,Q are valid */ - -case OP_BNF: - if ((M[QAR] & FLAG) == 0) { /* flag == 0? */ - BRANCH (PAR); } /* branch */ - break; - -/* Branch no record mark (8-2 not set) - P,Q are valid */ - -case OP_BNR: - if ((M[QAR] & REC_MARK) != REC_MARK) { /* not rec mark? */ - BRANCH (PAR); } /* branch */ - break; - -/* Branch no group mark - P,Q are valid */ - -case OP_BNG: - if ((M[QAR] & DIGIT) != GRP_MARK) { /* not grp mark? */ - BRANCH (PAR); } /* branch */ - break; - -/* Branch (no) indicator - P is valid */ - -case OP_BI: -case OP_BNI: - upd_ind (); /* update indicators */ - t = get_2d (ADDR_A (saved_PC, I_BR)); /* get ind number */ - if ((t < 0) || (ind_table[t] < 0)) { /* not valid? */ - reason = STOP_INVIND; /* stop */ - break; } - if ((ind[t] != 0) ^ (op == OP_BNI)) { /* ind value correct? */ - BRANCH (PAR); } /* branch */ - if (ind_table[t] > 0) ind[t] = 0; /* reset if needed */ - break; - -/* Add/subtract/compare - P,Q are valid */ - -case OP_A: -case OP_AM: - reason = add_field (PAR, QAR, FALSE, TRUE, 0, &sta); /* add, store */ - if (sta == ADD_CARRY) ind[IN_OVF] = 1; /* cout => ovflo */ - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; - break; - -case OP_S: -case OP_SM: - reason = add_field (PAR, QAR, TRUE, TRUE, 0, &sta); /* sub, store */ - if (sta == ADD_CARRY) ind[IN_OVF] = 1; /* cout => ovflo */ - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; - break; - -case OP_C: -case OP_CM: - reason = add_field (PAR, QAR, TRUE, FALSE, 0, &sta); /* sub, nostore */ - if (sta == ADD_CARRY) ind[IN_OVF] = 1; /* cout => ovflo */ - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; - break; - -/* Multiply - P,Q are valid */ - -case OP_M: -case OP_MM: - reason = mul_field (PAR, QAR); /* multiply */ - break; - -/* IO instructions - P is valid */ - -case OP_RA: -case OP_WA: - if ((PAR & 1) == 0) { /* P even? */ - reason = STOP_INVEAD; /* stop */ - break; } -case OP_K: -case OP_DN: -case OP_RN: -case OP_WN: - dev = get_2d (ADDR_A (saved_PC, I_IO)); /* get IO dev */ - f0 = M[ADDR_A (saved_PC, I_CTL)] & DIGIT; /* get function */ - f1 = M[ADDR_A (saved_PC, I_CTL + 1)] & DIGIT; - if ((dev < 0) || (iodisp[dev] == NULL)) /* undefined dev? */ - reason = STOP_INVIO; /* stop */ - else reason = iodisp[dev] (op, PAR, f0, f1); /* call device */ - break; - -/* Divide special feature instructions */ - -case OP_LD: -case OP_LDM: - for (i = 0; i < PROD_AREA_LEN; i++) /* clear prod area */ - M[PROD_AREA + i] = 0; - t = M[QAR] & FLAG; /* save Q sign */ - reason = xmt_divd (PAR, QAR); /* xmit dividend */ - M[PROD_AREA + PROD_AREA_LEN - 1] |= t; /* set sign */ - break; - -/* Divide - P,Q are valid */ - -case OP_D: -case OP_DM: - reason = div_field (PAR, QAR, &t); /* divide */ - ind[IN_EZ] = t; /* set indicator */ - if ((reason == STOP_OVERFL) && !ar_stop) /* ovflo stop? */ - reason = SCPE_OK; /* no */ - break; - -/* Edit special feature instructions */ - -/* Move flag - P,Q are valid */ - -case OP_MF: - M[PAR] = (M[PAR] & ~FLAG) | (M[QAR] & FLAG); /* copy Q flag */ - M[QAR] = M[QAR] & ~FLAG; /* clr Q flag */ - break; - -/* Transmit numeric strip - P,Q are valid, P is source */ - -case OP_TNS: - if ((PAR & 1) == 0) { /* P must be odd */ - reason = STOP_INVEAD; - break; } - reason = xmt_tns (QAR, PAR); /* xmit and strip */ - break; - -/* Transmit numeric fill - P,Q are valid */ - -case OP_TNF: - if ((PAR & 1) == 0) { /* P must be odd */ - reason = STOP_INVEAD; - break; } - reason = xmt_tnf (PAR, QAR); /* xmit and strip */ - break; - -/* Index special feature instructions */ - -/* Move address - P,Q are valid */ - -case OP_MA: - for (i = 0; i < ADDR_LEN; i++) { /* move 5 digits */ - M[PAR] = (M[PAR] & FLAG) | (M[QAR] & DIGIT); - MM (PAR); MM (QAR); } - break; - -/* Branch load index - P,Q are valid, Q not indexed */ - -case OP_BLX: -case OP_BLXM: - idx = get_idx (ADDR_A (saved_PC, I_QL - 1)); /* get index */ - if (idx < 0) { /* disabled? */ - reason = STOP_INVIDX; /* stop */ - break; } - xmt_index (GET_IDXADDR (idx), QAR); /* copy Q to idx */ - BRANCH (PAR); /* branch to P */ - break; - -/* Branch store index - P,Q are valid, Q not indexed */ - -case OP_BSX: - idx = get_idx (ADDR_A (saved_PC, I_QL - 1)); /* get index */ - if (idx < 0) { /* disabled? */ - reason = STOP_INVIDX; /* stop */ - break; } - xmt_index (QAR, GET_IDXADDR (idx)); /* copy idx to Q */ - BRANCH (PAR); /* branch to P */ - break; - -/* Branch and modify index - P,Q are valid, Q not indexed */ - -case OP_BX: - idx = get_idx (ADDR_A (saved_PC, I_QL - 1)); /* get index */ - if (idx < 0) { /* disabled? */ - reason = STOP_INVIDX; /* stop */ - break; } - reason = add_field (GET_IDXADDR (idx), QAR, FALSE, TRUE, 0, &sta); - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; - BRANCH (PAR); /* branch to P */ - break; - -case OP_BXM: - idx = get_idx (ADDR_A (saved_PC, I_QL - 1)); /* get index */ - if (idx < 0) { /* disabled? */ - reason = STOP_INVIDX; /* stop */ - break; } - reason = add_field (GET_IDXADDR (idx), QAR, FALSE, TRUE, 3, &sta); - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; - BRANCH (PAR); /* branch to P */ - break; - -/* Branch conditionally and modify index - P,Q are valid, Q not indexed */ - -case OP_BCX: - idx = get_idx (ADDR_A (saved_PC, I_QL - 1)); /* get index */ - if (idx < 0) { /* disabled? */ - reason = STOP_INVIDX; /* stop */ - break; } - reason = add_field (GET_IDXADDR (idx), QAR, FALSE, TRUE, 0, &sta); - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; - if ((ind[IN_EZ] == 0) && (sta == ADD_NOCRY)) { /* ~z, ~c, ~sign chg? */ - BRANCH (PAR); } /* branch */ - break; - -case OP_BCXM: - idx = get_idx (ADDR_A (saved_PC, I_QL - 1)); /* get index */ - if (idx < 0) { /* disabled? */ - reason = STOP_INVIDX; /* stop */ - break; } - reason = add_field (GET_IDXADDR (idx), QAR, FALSE, TRUE, 3, &sta); - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; - if ((ind[IN_EZ] == 0) && (sta == ADD_NOCRY)) { /* ~z, ~c, ~sign chg? */ - BRANCH (PAR); } /* branch */ - break; - -/* Branch and select - P is valid */ - -case OP_BS: - t = M[ADDR_A (saved_PC, I_SEL)] & DIGIT; /* get select */ - switch (t) { /* case on select */ - case 0: - idxe = idxb = 0; /* indexing off */ - break; - case 1: - idxe = 1; idxb = 0; /* index band A */ - break; - case 2: - idxe = idxb = 1; /* index band B */ - break; - case 8: - iae = 0; /* indirect off */ - break; - case 9: - iae = 1; /* indirect on */ - break; - default: - reason = STOP_INVSEL; /* undefined */ - break; } - BRANCH (PAR); - break; - -/* Binary special feature instructions */ - -/* Branch on bit - P,Q are valid, Q is 4d address */ - -case OP_BBT: - t = M[ADDR_A (saved_PC, I_Q)]; /* get Q0 digit */ - if (t & M[QAR] & DIGIT) { /* match to mem? */ - BRANCH (PAR); } /* branch */ - break; - -/* Branch on mask - P,Q are valid, Q is 4d address */ - -case OP_BMK: - t = M[ADDR_A (saved_PC, I_Q)]; /* get Q0 digit */ - if (((t ^ M[QAR]) & /* match to mem? */ - ((t & FLAG)? (FLAG + DIGIT): DIGIT)) == 0) { - BRANCH (PAR); } /* branch */ - break; - -/* Or - P,Q are valid */ - -case OP_ORF: - reason = or_field (PAR, QAR); /* OR fields */ - break; - -/* AND - P,Q are valid */ - -case OP_ANDF: - reason = and_field (PAR, QAR); /* AND fields */ - break; - -/* Exclusive or - P,Q are valid */ - -case OP_EORF: - reason = xor_field (PAR, QAR); /* XOR fields */ - break; - -/* Complement - P,Q are valid */ - -case OP_CPLF: - reason = com_field (PAR, QAR); /* COM field */ - break; - -/* Octal to decimal - P,Q are valid */ - -case OP_OTD: - reason = oct_to_dec (PAR, QAR); /* convert */ - break; - -/* Decimal to octal - P,Q are valid */ - -case OP_DTO: - reason = dec_to_oct (PAR, QAR, &t); /* convert */ - ind[IN_EZ] = t; /* set indicator */ - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; - break; - -/* Floating point special feature instructions */ - -case OP_FADD: - reason = fp_add (PAR, QAR, FALSE); /* add */ - if (ar_stop && ind[IN_EXPCHK]) reason = STOP_EXPCHK; - break; - -case OP_FSUB: - reason = fp_add (PAR, QAR, TRUE); /* subtract */ - if (ar_stop && ind[IN_EXPCHK]) reason = STOP_EXPCHK; - break; - -case OP_FMUL: - reason = fp_mul (PAR, QAR); /* multiply */ - if (ar_stop && ind[IN_EXPCHK]) reason = STOP_EXPCHK; - break; - -case OP_FDIV: - reason = fp_div (PAR, QAR); /* divide */ - if (ar_stop && ind[IN_OVF]) reason = STOP_FPDVZ; - if (ar_stop && ind[IN_EXPCHK]) reason = STOP_EXPCHK; - break; - -case OP_FSL: - reason = fp_fsl (PAR, QAR); /* shift left */ - break; - -case OP_FSR: - reason = fp_fsr (PAR, QAR); /* shift right */ - break; - -/* Halt */ - -case OP_H: - saved_PC = PC; /* commit inst */ - reason = STOP_HALT; /* stop */ - break; - -/* NOP */ - -case OP_NOP: - break; - -/* Invalid instruction code */ - -default: - reason = STOP_INVINS; /* stop */ - break; } /* end switch */ - } /* end while */ - -/* Simulation halted */ - -pcq_r->qptr = pcq_p; /* update pc q ptr */ -upd_ind (); -return reason; -} - -/* Utility routines */ - -/* Get 2 digit field - - Inputs: - ad = address of high digit - Outputs: - val = field converted to binary - -1 if bad digit -*/ - -int32 get_2d (uint32 ad) -{ -int32 d, d1; - -d = M[ad] & DIGIT; /* get 1st digit */ -d1 = M[ADDR_A (ad, 1)] & DIGIT; /* get 2nd digit */ -if (BAD_DIGIT (d) || BAD_DIGIT (d1)) return -1; /* bad? error */ -return ((d * 10) + d1); /* cvt to binary */ -} - -/* Get address routine - - Inputs: - alast = address of low digit - lnt = length - indexok = TRUE if indexing allowed - &addr = pointer to address output - Output: - return = error status (in terms of P address) - addr = address converted to binary - - Notes: - - If indexing produces a negative result, the effective address is - the 10's complement of the result - - An address that exceeds memory produces a MAR check stop -*/ - -t_stat get_addr (uint32 alast, int32 lnt, t_bool indexok, uint32 *reta) -{ -uint8 indir; -int32 cnt, idx, idxa, idxv, addr; - -if (iae) indir = FLAG; /* init indirect */ -else indir = 0; - -cnt = 0; /* count depth */ -do { indir = indir & M[alast]; /* get indirect */ - if (cvt_addr (alast, lnt, FALSE, &addr)) /* cvt addr to bin */ - return STOP_INVPDG; /* bad? */ - idx = get_idx (ADDR_S (alast, 1)); /* get index reg num */ - if (indexok && (idx > 0)) { /* indexable? */ - idxa = GET_IDXADDR (idx); /* get idx reg addr */ - if (cvt_addr (idxa, ADDR_LEN, TRUE, &idxv)) /* cvt idx reg */ - return STOP_INVPDG; - addr = addr + idxv; /* add in index */ - if (addr < 0) addr = addr + 100000; } /* -? 10's comp */ - if (addr >= (int32) MEMSIZE) return STOP_INVPAD;/* invalid addr? */ - alast = addr; /* new address */ - lnt = ADDR_LEN; } /* std len */ -while (indir && (cnt++ < ind_max)); -if (cnt > ind_max) return STOP_INVPIA; /* indir too deep? */ -*reta = addr; /* return address */ -return SCPE_OK; -} - -/* Convert address to binary - - Inputs: - alast = address of low digit - lnt = length - signok = TRUE if signed - val = address of output - Outputs: - status = 0 if ok, != 0 if error -*/ - -t_stat cvt_addr (uint32 alast, int32 lnt, t_bool signok, int32 *val) -{ -int32 sign = 0, addr = 0, t; - -if (signok && (M[alast] & FLAG)) sign = 1; /* signed? */ -alast = alast - lnt; /* find start */ -do { PP (alast); /* incr mem addr */ - t = M[alast] & DIGIT; /* get digit */ - if (BAD_DIGIT (t)) return STOP_INVDIG; /* bad? error */ - addr = (addr * 10) + t; } /* cvt to bin */ -while (--lnt > 0); -if (sign) *val = -addr; /* minus? */ -else *val = addr; -return SCPE_OK; -} - -/* Get index register number - - Inputs: - aidx = address of low digit - Outputs: - index = >0 if indexed - =0 if not indexed - <0 if indexing disabled -*/ - -t_stat get_idx (uint32 aidx) -{ -int32 i, idx; - -if (idxe == 0) return -1; /* indexing off? */ -for (i = idx = 0; i < 3; i++) { /* 3 flags worth */ - if (M[aidx] & FLAG) idx = idx | (1 << i); /* test flag */ - MM (aidx); } /* next digit */ -return idx; -} - -/* Update indicators routine */ - -void upd_ind (void) -{ -ind[IN_HPEZ] = ind[IN_HP] | ind[IN_EZ]; /* HPEZ = HP | EZ */ -ind[IN_DERR] = ind[IN_DACH] | ind[IN_DWLR] | ind[IN_DCYO]; -ind[IN_ANYCHK] = ind[IN_RDCHK] | ind[IN_WRCHK] | /* ANYCHK = all chks */ - ind[IN_MBREVEN] | ind[IN_MBRODD] | - ind[IN_PRCHK] | ind[IN_DACH]; -ind[IN_IXN] = ind[IN_IXA] = ind[IN_IXB] = 0; /* clr index indics */ -if (!idxe) ind[IN_IXN] = 1; /* off? */ -else if (!idxb) ind[IN_IXA] = 1; /* on, band A? */ -else ind[IN_IXB] = 1; /* no, band B */ -return; -} - -/* Transmit routines */ - -/* Transmit field from 's' to 'd' - ignore first 'skp' flags */ - -t_stat xmt_field (uint32 d, uint32 s, uint32 skp) -{ -uint32 cnt = 0; -uint8 t; - -do { t = M[d] = M[s] & (FLAG | DIGIT); /* copy src to dst */ - MM (d); MM (s); /* decr mem addrs */ - if (cnt++ >= MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while (((t & FLAG) == 0) || (cnt <= skp)); /* until flag */ -return SCPE_OK; -} - -/* Transmit record from 's' to 'd' - copy record mark if 'cpy' = TRUE */ - -t_stat xmt_record (uint32 d, uint32 s, t_bool cpy) -{ -uint32 cnt = 0; - -while ((M[s] & REC_MARK) != REC_MARK) { /* until rec mark */ - M[d] = M[s] & (FLAG | DIGIT); /* copy src to dst */ - PP (d); PP (s); /* incr mem addrs */ - if (cnt++ >= MEMSIZE) return STOP_RWRAP; } /* (stop runaway) */ -if (cpy) M[d] = M[s] & (FLAG | DIGIT); /* copy rec mark */ -return SCPE_OK; -} - -/* Transmit index from 's' to 'd' - fixed five character field */ - -t_stat xmt_index (uint32 d, uint32 s) -{ -int32 i; - -M[d] = M[s] & (FLAG | DIGIT); /* preserve sign */ -MM (d); MM (s); /* decr mem addrs */ -for (i = 0; i < ADDR_LEN - 2; i++) { /* copy 3 digits */ - M[d] = M[s] & DIGIT; /* without flags */ - MM (d); MM (s); } /* decr mem addrs */ -M[d] = (M[s] & DIGIT) | FLAG; /* set flag on last */ -return SCPE_OK; -} - -/* Transmit dividend from 'd' to 's' - clear flag on first digit */ - -t_stat xmt_divd (uint32 d, uint32 s) -{ -uint32 cnt = 0; - -M[d] = M[s] & DIGIT; /* first w/o flag */ -do { MM (d); MM (s); /* decr mem addrs */ - M[d] = M[s] & (FLAG | DIGIT); /* copy src to dst */ - if (cnt++ >= MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while ((M[d] & FLAG) == 0); /* until src flag */ -return SCPE_OK; -} - -/* Transmit numeric strip from 's' to 'd' - s is odd */ - -t_stat xmt_tns (uint32 d, uint32 s) -{ -uint32 cnt = 0; -uint8 t, z; - -t = M[s] & DIGIT; /* get units */ -z = M[s - 1] & DIGIT; /* get zone */ -if ((z == 1) || (z == 5) || ((z == 2) && (t == 0))) /* 1x, 5x, 20? */ - M[d] = t | FLAG; /* set flag */ -else M[d] = t; /* else clear flag */ -do { MM (d); /* decr mem addrs */ - s = ADDR_S (s, 2); - t = M[d] & FLAG; /* save dst flag */ - M[d] = M[s] & (FLAG | DIGIT); /* copy src to dst */ - if (cnt >= MEMSIZE) return STOP_FWRAP; /* (stop runaway) */ - cnt = cnt + 2; } -while (t == 0); /* until dst flag */ -M[d] = M[d] | FLAG; /* set flag at end */ -return SCPE_OK; -} - -/* Transmit numeric fill from 's' to 'd' - d is odd */ - -t_stat xmt_tnf (uint32 d, uint32 s) -{ -uint32 cnt = 0; -uint8 t; - -t = M[s]; /* get 1st digit */ -M[d] = t & DIGIT; /* store */ -M[d - 1] = (t & FLAG)? 5: 7; /* set sign from flag */ -do { MM (s); /* decr mem addr */ - d = ADDR_S (d, 2); - t = M[s]; /* get src digit */ - M[d] = t & DIGIT; /* move to dst, no flag */ - M[d - 1] = 7; /* set zone */ - if (cnt >= MEMSIZE) return STOP_FWRAP; /* (stop runaway) */ - cnt = cnt + 2; } -while ((t & FLAG) == 0); /* until src flag */ -return SCPE_OK; -} - -/* Add routine - - Inputs: - d = destination field low (P) - s = source field low (Q) - sub = TRUE if subtracting - sto = TRUE if storing - skp = number of source field flags, beyond sign, to ignore - Output: - return = status - sta = ADD_NOCRY: no carry out, no sign change - ADD_SCHNG: sign change - ADD_CARRY: carry out - - Reference Manual: "When the sum is zero, the sign of the P field - is retained." -*/ - -t_stat add_field (uint32 d, uint32 s, t_bool sub, t_bool sto, uint32 skp, int32 *sta) -{ -uint32 cry, src, dst, res, comp, dp, dsv; -uint32 src_f = 0, cnt = 0, dst_f; - -*sta = ADD_NOCRY; /* assume no cry */ -dsv = d; /* save dst */ -comp = ((M[d] ^ M[s]) & FLAG) ^ (sub? FLAG: 0); /* set compl flag */ -cry = 0; /* clr carry */ -ind[IN_HP] = ((M[d] & FLAG) == 0); /* set sign from res */ -ind[IN_EZ] = 1; /* assume zero */ - -dst = M[d] & DIGIT; /* 1st digits */ -src = M[s] & DIGIT; -if (BAD_DIGIT (dst) || BAD_DIGIT (src)) /* bad digit? */ - return STOP_INVDIG; -if (comp) src = 10 - src; /* complement? */ -res = add_one_digit (dst, src, &cry); /* add */ -if (sto) M[d] = (M[d] & FLAG) | res; /* store */ -MM (d); MM (s); /* decr mem addrs */ -do { dst = M[d] & DIGIT; /* get dst digit */ - dst_f = M[d] & FLAG; /* get dst flag */ - if (src_f) src = 0; /* src done? src = 0 */ - else { - src = M[s] & DIGIT; /* get src digit */ - if (cnt >= skp) src_f = M[s] & FLAG; /* get src flag */ - MM (s); } /* decr src addr */ - if (BAD_DIGIT (dst) || BAD_DIGIT (src)) /* bad digit? */ - return STOP_INVDIG; - if (comp) src = 9 - src; /* complement? */ - res = add_one_digit (dst, src, &cry); /* add */ - if (sto) M[d] = dst_f | res; /* store */ - MM (d); /* decr dst addr */ - if (cnt++ >= MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while (dst_f == 0); /* until dst done */ -if (!src_f) ind[IN_OVF] = 1; /* !src done? ovf */ -if (comp && !cry && !ind[IN_EZ]) { /* recomp needed? */ - ind[IN_HP] = ind[IN_HP] ^ 1; /* flip indicator */ - if (sto) { /* storing? */ - for (cry = 1, dp = dsv; dp != d; ) { /* rescan */ - dst = M[dp] & DIGIT; /* get dst digit */ - res = add_one_digit (9 - dst, 0, &cry); /* "add" */ - M[dp] = (M[dp] & FLAG) | res; /* store */ - MM (dp); } /* decr dst addr */ - M[dsv] = M[dsv] ^ FLAG; } /* compl sign */ - *sta = ADD_SIGNC; /* sign changed */ - return SCPE_OK; } /* end if recomp */ -if (ind[IN_EZ]) ind[IN_HP] = 0; /* res = 0? clr HP */ -if (!comp && cry) *sta = ADD_CARRY; /* set status */ -return SCPE_OK; -} - -/* Add one digit via table (Model 1) or "hardware" (Model 2) */ - -uint32 add_one_digit (uint32 dst, uint32 src, uint32 *cry) -{ -uint32 res; - -if (*cry) src = src + 1; /* cry in? incr src */ -if (src >= 10) { /* src > 10? */ - src = src - 10; /* src -= 10 */ - *cry = 1; } /* carry out */ -else *cry = 0; /* else no carry */ -if (cpu_unit.flags & IF_MII) /* Model 2? */ - res = sum_table[dst + src]; /* "hardware" */ -else res = M[ADD_TABLE + (dst * 10) + src]; /* table lookup */ -if (res & FLAG) *cry = 1; /* carry out? */ -if (res & DIGIT) ind[IN_EZ] = 0; /* nz? clr ind */ -return res & DIGIT; -} - -/* Multiply routine - - Inputs: - mpc = multiplicand address - mpy = multiplier address - Outputs: - return = status - - Reference manual: "A zero product may have a negative or positive sign, - depending on the signs of the fields at the P and Q addresses." -*/ - -t_stat mul_field (uint32 mpc, uint32 mpy) -{ -int32 i; -uint32 pro; /* prod pointer */ -uint32 mpyd, mpyf; /* mpy digit, flag */ -uint32 cnt = 0; /* counter */ -uint8 sign; /* final sign */ -t_stat r; - -PR1 = 1; /* step on PR1 */ -for (i = 0; i < PROD_AREA_LEN; i++) /* clr prod area */ - M[PROD_AREA + i] = 0; -sign = (M[mpc] & FLAG) ^ (M[mpy] & FLAG); /* get final sign */ -ind[IN_HP] = (sign == 0); /* set indicators */ -ind[IN_EZ] = 1; -pro = PROD_AREA + PROD_AREA_LEN - 1; /* product ptr */ - -/* Loop on multiplier (mpy) and product (pro) digits */ - -do { mpyd = M[mpy] & DIGIT; /* multiplier digit */ - mpyf = (M[mpy] & FLAG) && (cnt != 0); /* last digit flag */ - if (BAD_DIGIT (mpyd)) return STOP_INVDIG; /* bad? */ - r = mul_one_digit (mpyd, mpc, pro, mpyf); /* prod += mpc*mpy_dig */ - if (r != SCPE_OK) return r; /* error? */ - MM (mpy); MM (pro); /* decr mpyr, prod addrs */ - if (cnt++ > MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while ((mpyf == 0) || (cnt <= 1)); /* until mpyr flag */ - -if (ind[IN_EZ]) ind[IN_HP] = 0; /* res = 0? clr HP */ -M[PROD_AREA + PROD_AREA_LEN - 1] |= sign; /* set final sign */ -return SCPE_OK; -} - -/* Multiply step - - Inputs: - mpyd = multiplier digit (tested valid) - mpcp = multiplicand low address - prop = product low address - last = last iteration flag (set flag on high product) - Outputs: - prod += multiplicand * multiplier_digit - return = status - - The multiply table address is constructed as follows: - - double the multiplier digit - - use the 10's digit of the doubled result, + 1, as the 100's digit - of the table address - - use the multiplicand digit as the 10's digit of the table address - - use the unit digit of the doubled result as the unit digit of the - table address - EZ indicator is cleared if a non-zero digit is ever generated -*/ - -t_stat mul_one_digit (uint32 mpyd, uint32 mpcp, uint32 prop, uint32 last) -{ -uint32 mpta, mptb; /* mult table */ -uint32 mptd; /* mult table digit */ -uint32 mpcd, mpcf; /* mpc digit, flag */ -uint32 prwp; /* prod working ptr */ -uint32 prod; /* product digit */ -uint32 cry; /* carry */ -uint32 mpcc, cryc; /* counters */ - -mptb = MUL_TABLE + ((mpyd <= 4)? (mpyd * 2): /* set mpy table 100's, */ - (((mpyd - 5) * 2) + 100)); /* 1's digits */ - -/* Inner loop on multiplicand (mpcp) and product (prop) digits */ - -mpcc = 0; /* multiplicand ctr */ -do { prwp = prop; /* product working ptr */ - mpcd = M[mpcp] & DIGIT; /* multiplicand digit */ - mpcf = M[mpcp] & FLAG; /* multiplicand flag */ - if (BAD_DIGIT (mpcd)) return STOP_INVDIG; /* bad? */ - mpta = mptb + (mpcd * 10); /* mpy table 10's digit */ - cry = 0; /* init carry */ - mptd = M[mpta] & DIGIT; /* mpy table digit */ - if (BAD_DIGIT (mptd)) return STOP_INVDIG; /* bad? */ - prod = M[prwp] & DIGIT; /* product digit */ - if (BAD_DIGIT (prod)) return STOP_INVDIG; /* bad? */ - M[prwp] = add_one_digit (prod, mptd, &cry); /* add mpy tbl to prod */ - MM (prwp); /* decr working ptr */ - mptd = M[mpta + 1] & DIGIT; /* mpy table digit */ - if (BAD_DIGIT (mptd)) return STOP_INVDIG; /* bad? */ - prod = M[prwp] & DIGIT; /* product digit */ - if (BAD_DIGIT (prod)) return STOP_INVDIG; /* bad? */ - M[prwp] = add_one_digit (prod, mptd, &cry); /* add mpy tbl to prod */ - cryc = 0; /* (stop runaway) */ - while (cry) { /* propagate carry */ - MM (prwp); /* decr working ptr */ - prod = M[prwp] & DIGIT; /* product digit */ - if (BAD_DIGIT (prod)) return STOP_INVDIG; /* bad? */ - M[prwp] = add_one_digit (prod, 0, &cry); /* add cry */ - if (cryc++ > MEMSIZE) return STOP_FWRAP; } - MM (mpcp); MM (prop); /* decr mpc, prod ptrs */ - if (mpcc++ > MEMSIZE) return STOP_FWRAP; } -while ((mpcf == 0) || (mpcc <= 1)); /* until mpcf flag */ -if (last) - M[prop] = M[prop] | FLAG; /* flag high product */ -return SCPE_OK; -} - -/* Divide routine - comments from Geoff Kuenning's 1620 simulator - - The destination of the divide is given by: - - 100 - <# digits in quotient> - - Which is more easily calculated as: - - 100 - <# digits in divisor> - <# digits in dividend> - - The quotient goes into 99 minus the divisor length. The - remainder goes into 99. The load dividend instruction (above) - should have specified a P address of 99 minus the size of the - divisor. - - Note that this all implies that "dest" points to the *leftmost* - digit of the dividend. - - After the division, the assumed decimal point will be as many - positions to the left as there are digits in the divisor. In - other words, a 4-digit divisor will produce 4 (assumed) decimal - places. - - There are other ways to do these things. In particular, the - load-dividend instruction doesn't have to specify the above - formula; if it's done differently, then you don't have to get - decimal places. This is not well-explained in the books I have. - - How to divide on a 1620: - - The dividend is the field at 99: - - 90 = _1234567890 - - The divisor is somewhere else in memory: - - _03 - - The divide operation specifies the left-most digit of the - dividend as the place to begin trial subtractions: - - DM 90,3 - - The loop works as follows: - - 1. Call the left-most digit of the dividend "current_dividend". - Call the location current_dividend - - "quotient_digit". - 2. Clear the flag at current_dividend, and set one at - quotient_digit. - - 88 = _001234567890, q_d = 88, c_d = 90 - [Not actually done; divisor length controls subtract.] - 3. Subtract the divisor from the field at current-dividend, - using normal 1620 rules, except that signs are ignored. - Continue these subtractions until either 10 subtractions - have been done, or you get a negative result: - - 88 = _00_2234567890, q_d = 88, c_d = 90 - 4. If 10 subtractions have been done, set the overflow - indicator and abort. Otherwise, add the divisor back to - correct for the oversubtraction: - - 88 = _001234567890, q_d = 88, c_d = 90 - 5. Store the (net) number of subtractions in quotient_digit: - - 88 = _001234567890, q_d = 88, c_d = 90 - 6. If this is not the first pass, clear the flag at - quotient_digit. Increment quotient_digit and - current_dividend, and set a flag at the new - quotient_digit: - - 88 = _0_01234567890, q_d = 89, c_d = 91 - [If first pass, set a flag at quotient digit.] - 7. If current_dividend is not 100, repeat steps 3 through 7. - 8. Set flags at 99 and quotient_digit - 1 according to the - rules of algebra: the quotient's sign is the exclusive-or - of the signs of the divisor and dividend, and the - remainder has the sign of the dividend: - - 10 / 3 = 3 remainder 1 - 10 / -3 = -3 remainder 1 - -10 / 3 = -3 remainder -1 - -10 / -3 = 3 remainder -1 - - This preserves the relationship dd = q * dv + r. - - Our example continues as follows for steps 3 through 7: - - 3. 88 = _0_00_334567890, q_d = 89, c_d = 91 - 4. 88 = _0_00034567890 - 5. 88 = _0_40034567890 - 6. 88 = _04_0034567890, q_d = 90, c_d = 92 - 3. 88 = _04_00_34567890 - 4. 88 = _04_0004567890 - 5. 88 = _04_1004567890 - 6. 88 = _041_004567890, q_d = 91, c_d = 93 - 3. 88 = _041_00_2567890 - 4. 88 = _041_001567890 - 5. 88 = _041_101567890 - 6. 88 = _0411_01567890, q_d = 92, c_d = 94 - 3. 88 = _0411_00_367890 - 4. 88 = _0411_00067890 - 5. 88 = _0411_50067890 - 6. 88 = _04115_0067890, q_d = 93, c_d = 95 - 3. 88 = _04115_00_37890 - 4. 88 = _04115_0007890 - 5. 88 = _04115_2007890 - 6. 88 = _041152_007890, q_d = 94, c_d = 96 - 3. 88 = _041152_00_2890 - 4. 88 = _041152_001890 - 5. 88 = _041152_201890 - 6. 88 = _0411522_01890, q_d = 95, c_d = 97 - 3. 88 = _0411522_00_390 - 4. 88 = _0411522_00090 - 5. 88 = _0411522_60090 - 6. 88 = _04115226_0090, q_d = 96, c_d = 98 - 3. 88 = _04115226_00_30 - 4. 88 = _04115226_0000 - 5. 88 = _04115226_3000 - 6. 88 = _041152263_000, q_d = 97, c_d = 99 - 3. 88 = _041152263_00_3 - 4. 88 = _041152263_000 - 5. 88 = _041152263_000 - 6. 88 = _0411522630_00, q_d = 98, c_d = 100 - - In the actual code below, we elide several of these steps in - various ways for convenience and efficiency. - - Note that the EZ indicator is NOT valid for divide, because it - is cleared by any non-zero result in an intermediate add. The - code maintains its own EZ indicator for the quotient. -*/ - -t_stat div_field (uint32 dvd, uint32 dvr, int32 *ez) -{ -uint32 quop, quod, quos; /* quo ptr, dig, sign */ -uint32 dvds; /* dvd sign */ -t_bool first = TRUE; /* first pass */ -t_stat r; - -dvds = (M[PROD_AREA + PROD_AREA_LEN - 1]) & FLAG; /* dividend sign */ -quos = dvds ^ (M[dvr] & FLAG); /* quotient sign */ -ind[IN_HP] = (quos == 0); /* set indicators */ -*ez = 1; - -/* Loop on current dividend, high order digit at dvd */ - -do { r = div_one_digit (dvd, dvr, 10, &quod, &quop); /* dev quo digit */ - if (r != SCPE_OK) return r; /* error? */ - -/* Store quotient digit and advance current dividend pointer */ - - if (first) { /* first pass? */ - if (quod >= 10) { /* overflow? */ - ind[IN_OVF] = 1; /* set indicator */ - return STOP_OVERFL; } /* stop */ - M[quop] = FLAG | quod; /* set flag on quo */ - first = FALSE; } - else M[quop] = quod; /* store quo digit */ - if (quod) *ez = 0; /* if nz, clr ind */ - PP (dvd); } /* incr dvd ptr */ -while (dvd != (PROD_AREA + PROD_AREA_LEN)); /* until end prod */ - -/* Division done. Set signs of quo, rem, set flag on high order remainder */ - -if (*ez) ind[IN_HP] = 0; /* res = 0? clr HP */ -M[PROD_AREA + PROD_AREA_LEN - 1] |= dvds; /* remainder sign */ -M[quop] = M[quop] | quos; /* quotient sign */ -PP (quop); /* high remainder */ -M[quop] = M[quop] | FLAG; /* set flag */ -return SCPE_OK; -} - -/* Divide step - - Inputs: - dvd = current dividend address (high digit) - dvr = divisor address (low digit) - max = max number of iterations before overflow - &quod = address to store quotient digit - &quop = address to store quotient pointer (can be NULL) - Outputs: - return = status - - Divide step calculates a quotient digit by repeatedly subtracting the - divisor from the current dividend. The divisor's length controls the - subtraction; dividend flags are ignored. -*/ - -t_stat div_one_digit (uint32 dvd, uint32 dvr, uint32 max, - uint32 *quod, uint32 *quop) -{ -uint32 dvrp, dvrd, dvrf; /* dvr ptr, dig, flag */ -uint32 dvdp, dvdd; /* dvd ptr, dig */ -uint32 qd, cry; /* quo dig, carry */ -uint32 cnt; - -for (qd = 0; qd < max; qd++) { /* devel quo dig */ - dvrp = dvr; /* divisor ptr */ - dvdp = dvd; /* dividend ptr */ - cnt = 0; - cry = 1; /* carry in = 1 */ - do { /* sub dvr fm dvd */ - dvdd = M[dvdp] & DIGIT; /* dividend digit */ - if (BAD_DIGIT (dvdd)) return STOP_INVDIG; /* bad? */ - dvrd = M[dvrp] & DIGIT; /* divisor digit */ - dvrf = M[dvrp] & FLAG; /* divisor flag */ - if (BAD_DIGIT (dvrd)) return STOP_INVDIG; /* bad? */ - M[dvdp] = add_one_digit (dvdd, 9 - dvrd, &cry); /* sub */ - MM (dvdp); MM (dvrp); /* decr ptrs */ - if (cnt++ > MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ - while ((dvrf == 0) || (cnt <= 1)); /* until dvr flag */ - if (!cry) { /* !cry = borrow */ - dvdd = M[dvdp] & DIGIT; /* borrow digit */ - if (BAD_DIGIT (dvdd)) return STOP_INVDIG; /* bad? */ - M[dvdp] = add_one_digit (dvdd, 9, &cry); } /* sub */ - if (!cry) break; } /* !cry = negative */ - -/* Add back the divisor to correct for the negative result */ - -dvrp = dvr; /* divisor ptr */ -dvdp = dvd; /* dividend ptr */ -cnt = 0; -cry = 0; /* carry in = 0 */ -do { dvdd = M[dvdp] & DIGIT; /* dividend digit */ - dvrd = M[dvrp] & DIGIT; /* divisor digit */ - dvrf = M[dvrp] & FLAG; /* divisor flag */ - M[dvdp] = add_one_digit (dvdd, dvrd, &cry); /* add */ - MM (dvdp); MM (dvrp); cnt++; } /* decr ptrs */ -while ((dvrf == 0) || (cnt <= 1)); /* until dvr flag */ -if (cry) { /* carry out? */ - dvdd = M[dvdp] & DIGIT; /* borrow digit */ - M[dvdp] = add_one_digit (dvdd, 0, &cry); } /* add */ -if (quop != NULL) *quop = dvdp; /* set quo addr */ -*quod = qd; /* set quo digit */ -return SCPE_OK; -} - -/* Logical operation routines (and, or, xor, complement) - - Inputs: - d = destination address - s = source address - Output: - return = status - - Destination flags are preserved; EZ reflects the result. - COM does not obey normal field length restrictions. -*/ - -t_stat or_field (uint32 d, uint32 s) -{ -uint32 cnt = 0; -int32 t; - -ind[IN_EZ] = 1; /* assume result zero */ -do { t = M[s]; /* get src */ - M[d] = (M[d] & FLAG) | ((M[d] | t) & 07); /* OR src to dst */ - if (M[d] & DIGIT) ind[IN_EZ] = 0; /* nz dig? clr ind */ - MM (d); MM (s); /* decr pointers */ - if (cnt++ >= MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while (((t & FLAG) == 0) || (cnt <= 1)); /* until src flag */ -return SCPE_OK; -} - -t_stat and_field (uint32 d, uint32 s) -{ -uint32 cnt = 0; -int32 t; - -ind[IN_EZ] = 1; /* assume result zero */ -do { t = M[s]; /* get src */ - M[d] = (M[d] & FLAG) | ((M[d] & t) & 07); /* AND src to dst */ - if (M[d] & DIGIT) ind[IN_EZ] = 0; /* nz dig? clr ind */ - MM (d); MM (s); /* decr pointers */ - if (cnt++ >= MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while (((t & FLAG) == 0) || (cnt <= 1)); /* until src flag */ -return SCPE_OK; -} - -t_stat xor_field (uint32 d, uint32 s) -{ -uint32 cnt = 0; -int32 t; - -ind[IN_EZ] = 1; /* assume result zero */ -do { t = M[s]; /* get src */ - M[d] = (M[d] & FLAG) | ((M[d] ^ t) & 07); /* XOR src to dst */ - if (M[d] & DIGIT) ind[IN_EZ] = 0; /* nz dig? clr ind */ - MM (d); MM (s); /* decr pointers */ - if (cnt++ >= MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while (((t & FLAG) == 0) || (cnt <= 1)); /* until src flag */ -return SCPE_OK; -} - -t_stat com_field (uint32 d, uint32 s) -{ -uint32 cnt = 0; -int32 t; - -ind[IN_EZ] = 1; /* assume result zero */ -do { t = M[s]; /* get src */ - M[d] = (t & FLAG) | ((t ^ 07) & 07); /* comp src to dst */ - if (M[d] & DIGIT) ind[IN_EZ] = 0; /* nz dig? clr ind */ - MM (d); MM (s); /* decr pointers */ - if (cnt++ >= MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while ((t & FLAG) == 0); /* until src flag */ -return SCPE_OK; -} - -/* Octal to decimal - - Inputs: - tbl = conversion table address (low digit) - s = source address - Outputs: - product area = converted source - result = status - - OTD is a cousin of multiply. The octal digits in the source are - multiplied by successive values in the conversion table, and the - results are accumulated in the product area. Although the manual - does not say, this code assumes that EZ and HP are affected. - */ - -t_stat oct_to_dec (uint32 tbl, uint32 s) -{ -uint32 cnt = 0, tblc; -uint32 i, sd, sf, tf, sign; -t_stat r; - -for (i = 0; i < PROD_AREA_LEN; i++) /* clr prod area */ - M[PROD_AREA + i] = 0; -sign = M[s] & FLAG; /* save sign */ -ind[IN_EZ] = 1; /* set indicators */ -ind[IN_HP] = (sign == 0); -do { sd = M[s] & DIGIT; /* src digit */ - sf = M[s] & FLAG; /* src flag */ - r = mul_one_digit (sd, tbl, PROD_AREA + PROD_AREA_LEN - 1, sf); - if (r != SCPE_OK) return r; /* err? */ - MM (s); /* decr src addr */ - MM (tbl); /* skip 1st tbl dig */ - tblc = 0; /* count */ - do { - tf = M[tbl] & FLAG; /* get next */ - MM (tbl); /* decr ptr */ - if (tblc++ > MEMSIZE) return STOP_FWRAP; } - while (tf == 0); /* until flag */ - if (cnt++ > MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while (sf == 0); -if (ind[IN_EZ]) ind[IN_HP] = 0; /* res = 0? clr HP */ -M[PROD_AREA + PROD_AREA_LEN - 1] |= sign; /* set sign */ -return SCPE_OK; -} - -/* Decimal to octal - - Inputs: - d = destination address - tbl = conversion table address (low digit of highest power) - &ez = address of soft EZ indicator - product area = field to convert - Outputs: - return = status - - DTO is a cousin to divide. The number in the product area is repeatedly - divided by successive values in the conversion table, and the quotient - digits are stored in the destination. Although the manual does not say, - this code assumes that EZ and HP are affected. - */ - -t_stat dec_to_oct (uint32 d, uint32 tbl, int32 *ez) -{ -uint32 sign, octd, t; -t_bool first = TRUE; -uint32 ctr = 0; -t_stat r; - -sign = M[PROD_AREA + PROD_AREA_LEN - 1] & FLAG; /* input sign */ -*ez = 1; /* set indicators */ -ind[IN_HP] = (sign == 0); -for ( ;; ) { - r = div_one_digit (PROD_AREA + PROD_AREA_LEN - 1, /* divide */ - tbl, 8, &octd, NULL); - if (r != SCPE_OK) return r; /* error? */ - if (first) { /* first pass? */ - if (octd >= 8) { /* overflow? */ - ind[IN_OVF] = 1; /* set indicator */ - return SCPE_OK; } /* stop */ - M[d] = FLAG | octd; /* set flag on quo */ - first = FALSE; } - else M[d] = octd; /* store quo digit */ - if (octd) *ez = 0; /* if nz, clr ind */ - PP (tbl); /* incr tbl addr */ - if ((M[tbl] & REC_MARK) == REC_MARK) break; /* record mark? */ - PP (tbl); /* skip flag */ - if ((M[tbl] & REC_MARK) == REC_MARK) break; /* record mark? */ - do { PP (tbl); /* look for F, rec mk */ - t = M[tbl]; } - while (((t & FLAG) == 0) && ((t & REC_MARK) != REC_MARK)); - MM (tbl); /* step back one */ - PP (d); /* incr quo addr */ - if (ctr++ > MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -if (*ez) ind[IN_HP] = 0; /* res = 0? clr HP */ -M[d] = M[d] | sign; /* set result sign */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -int32 i; -static t_bool one_time = TRUE; - -PR1 = IR2 = 1; /* invalidate PR1,IR2 */ -ind[0] = 0; -for (i = IN_SW4 + 1; i < NUM_IND; i++) ind[i] = 0; /* init indicators */ -if (cpu_unit.flags & IF_IA) iae = 1; /* indirect enabled? */ -else iae = 0; -idxe = idxb = 0; /* indexing off */ -pcq_r = find_reg ("PCQ", NULL, dptr); /* init old PC queue */ -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); /* init breakpoints */ -upd_ind (); /* update indicators */ -if (one_time) cpu_set_table (&cpu_unit, 1, NULL, NULL); /* set default tables */ -one_time = FALSE; -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & (FLAG | DIGIT); -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -M[addr] = val & (FLAG | DIGIT); -return SCPE_OK; -} - -/* Memory size change */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val % 1000) != 0)) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; -if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_OK; -MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; -return SCPE_OK; -} - -/* Model change */ - -t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (val) cpu_unit.flags = (cpu_unit.flags & (UNIT_SCP | UNIT_BCD | MII_OPT)) | - IF_DIV | IF_IA | IF_EDT; -else cpu_unit.flags = cpu_unit.flags & (UNIT_SCP | UNIT_BCD | MI_OPT); -return SCPE_OK; -} - -/* Set/clear Model 1 option */ - -t_stat cpu_set_opt1 (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cpu_unit.flags & IF_MII) { - printf ("Feature is standard on 1620 Model 2\n"); - if (sim_log) fprintf (sim_log, "Feature is standard on 1620 Model 2\n"); - return SCPE_NOFNC; } -return SCPE_OK; -} - -/* Set/clear Model 2 option */ - -t_stat cpu_set_opt2 (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (!(cpu_unit.flags & IF_MII)) { - printf ("Feature is not available on 1620 Model 1\n"); - if (sim_log) fprintf (sim_log, "Feature is not available on 1620 Model 1\n"); - return SCPE_NOFNC; } -return SCPE_OK; -} - -/* Front panel save */ - -t_stat cpu_set_save (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (saved_PC & 1) return SCPE_NOFNC; -PR1 = saved_PC; -return SCPE_OK; -} - -/* Set standard add/multiply tables */ - -t_stat cpu_set_table (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 i; - -for (i = 0; i < MUL_TABLE_LEN; i++) /* set mul table */ - M[MUL_TABLE + i] = std_mul_table[i]; -if (((cpu_unit.flags & IF_MII) == 0) || val) { /* set add table */ - for (i = 0; i < ADD_TABLE_LEN; i++) - M[ADD_TABLE + i] = std_add_table[i]; } -return SCPE_OK; -} diff --git a/I1620/i1620_defs.h b/I1620/i1620_defs.h deleted file mode 100644 index b07cde33..00000000 --- a/I1620/i1620_defs.h +++ /dev/null @@ -1,221 +0,0 @@ -/* i1620_defs.h: IBM 1620 simulator definitions - - Copyright (c) 2002-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - This simulator is based on the 1620 simulator written by Geoff Kuenning. - I am grateful to Al Kossow, the Computer History Museum, and the IBM Corporate - Archives for their help in gathering documentation about the IBM 1620. - - 18-Oct-02 RMS Fixed bug in ADDR_S macro (found by Hans Pufal) -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Simulator stop codes */ - -#define STOP_HALT 1 /* HALT */ -#define STOP_IBKPT 2 /* breakpoint */ -#define STOP_INVINS 3 /* invalid instruction */ -#define STOP_INVDIG 4 /* invalid digit */ -#define STOP_INVCHR 5 /* invalid char */ -#define STOP_INVIND 6 /* invalid indicator */ -#define STOP_INVPDG 7 /* invalid P addr digit */ -#define STOP_INVPAD 8 /* invalid P addr */ -#define STOP_INVPIA 9 /* invalid P indir addr */ -#define STOP_INVQDG 10 /* invalid Q addr digits */ -#define STOP_INVQAD 11 /* invalid Q addr */ -#define STOP_INVQIA 12 /* invalid Q indir addr */ -#define STOP_INVIO 13 /* invalid IO address */ -#define STOP_INVRTN 14 /* invalid return */ -#define STOP_INVFNC 15 /* invalid function */ -#define STOP_INVIAD 16 /* invalid instr addr */ -#define STOP_INVSEL 17 /* invalid select */ -#define STOP_INVIDX 18 /* invalid index instr */ -#define STOP_INVEAD 19 /* invalid even addr */ -#define STOP_INVDCF 20 /* invalid DCF addr */ -#define STOP_INVDRV 21 /* invalid disk drive */ -#define STOP_INVDSC 22 /* invalid disk sector */ -#define STOP_INVDCN 23 /* invalid disk count */ -#define STOP_INVDBA 24 /* invalid disk buf addr */ -#define STOP_DACERR 25 /* disk addr comp err */ -#define STOP_DWCERR 26 /* disk wr check err */ -#define STOP_CYOERR 27 /* cylinder ovflo err */ -#define STOP_WRLERR 28 /* wrong rec lnt err */ -#define STOP_CCT 29 /* runaway CCT */ -#define STOP_FWRAP 30 /* field wrap */ -#define STOP_RWRAP 31 /* record wrap */ -#define STOP_NOCD 32 /* no card in reader */ -#define STOP_OVERFL 33 /* overflow */ -#define STOP_EXPCHK 34 /* exponent error */ -#define STOP_WRADIS 35 /* write addr disabled */ -#define STOP_FPLNT 36 /* invalid fp length */ -#define STOP_FPUNL 37 /* fp lengths unequal */ -#define STOP_FPMF 38 /* no flag on exp */ -#define STOP_FPDVZ 39 /* divide by zero */ - -/* Memory */ - -#define MAXMEMSIZE 60000 /* max mem size */ -#define MEMSIZE (cpu_unit.capac) /* act memory size */ - -/* Processor parameters */ - -#define INST_LEN 12 /* inst length */ -#define ADDR_LEN 5 /* addr length */ -#define MUL_TABLE 100 /* multiply table */ -#define MUL_TABLE_LEN 200 -#define ADD_TABLE 300 /* add table */ -#define ADD_TABLE_LEN 100 -#define IDX_A 300 /* index A base */ -#define IDX_B 340 /* index B base */ -#define PROD_AREA 80 /* product area */ -#define PROD_AREA_LEN 20 /* product area */ -#define PROD_AREA_END (PROD_AREA + PROD_AREA_LEN) - -/* Branch indicator codes */ - -#define NUM_IND 100 /* number of indicators */ - -#define IN_SW1 1 /* sense switch 1 */ -#define IN_SW2 2 /* sense switch 2 */ -#define IN_SW3 3 /* sense switch 3 */ -#define IN_SW4 4 /* sense switch 4 */ -#define IN_RDCHK 6 /* read check (I/O error) */ -#define IN_WRCHK 7 /* write check (I/O error) */ -#define IN_LAST 9 /* last card was just read */ -#define IN_HP 11 /* high or positive result */ -#define IN_EZ 12 /* equal or zero result */ -#define IN_HPEZ 13 /* high/positive or equal/zero */ -#define IN_OVF 14 /* overflow */ -#define IN_EXPCHK 15 /* floating exponent check */ -#define IN_MBREVEN 16 /* even parity check */ -#define IN_MBRODD 17 /* odd parity check */ -#define IN_ANYCHK 19 /* any of read, write, even/odd */ -#define IN_PRCHK 25 /* printer check */ -#define IN_IXN 30 /* IX neither */ -#define IN_IXA 31 /* IX A band */ -#define IN_IXB 32 /* IX B band */ -#define IN_PRCH9 33 /* printer chan 9 */ -#define IN_PRCH12 34 /* printer chan 12 */ -#define IN_PRBSY 35 /* printer busy */ -#define IN_DACH 36 /* disk addr/data check */ -#define IN_DWLR 37 /* disk rec length */ -#define IN_DCYO 38 /* disk cyl overflow */ -#define IN_DERR 39 /* disk any error */ - -/* I/O channel codes */ - -#define NUM_IO 100 /* number of IO chan */ - -#define IO_TTY 1 /* console typewriter */ -#define IO_PTP 2 /* paper-tape punch */ -#define IO_PTR 3 /* paper-tape reader */ -#define IO_CDP 4 /* card punch */ -#define IO_CDR 5 /* card reader */ -#define IO_DSK 7 /* disk */ -#define IO_LPT 9 /* line printer */ -#define IO_BTP 32 /* binary ptp */ -#define IO_BTR 33 /* binary ptr */ - -#define LPT_WIDTH 120 /* line print width */ -#define CCT_LNT 132 /* car ctrl length */ - -#define CRETIOE(f,c) return ((f)? (c): SCPE_OK) - -/* Memory representation: flag + BCD digit per byte */ - -#define FLAG 0x10 -#define DIGIT 0x0F -#define REC_MARK 0xA -#define NUM_BLANK 0xC -#define GRP_MARK 0xF -#define BAD_DIGIT(x) ((x) > 9) - -/* Instruction format */ - -#define I_OP 0 /* opcode */ -#define I_P 2 /* P start */ -#define I_PL 6 /* P end */ -#define I_Q 7 /* Q start */ -#define I_QL 11 /* Q end */ -#define I_IO 8 /* IO select */ -#define I_BR 8 /* indicator select */ -#define I_CTL 10 /* control select */ -#define I_SEL 11 /* BS select */ - -#define ADDR_A(x,a) ((((x) + (a)) >= MEMSIZE)? ((x) + (a) - MEMSIZE): ((x) + (a))) -#define ADDR_S(x,a) (((x) < (a))? ((x) - (a) + MEMSIZE): ((x) - (a))) -#define PP(x) x = ADDR_A(x,1) -#define MM(x) x = ADDR_S(x,1) - -/* CPU options, stored in cpu_unit.flags */ -/* Decoding flags must be part of the same definition set */ - -#define UNIT_SCP ((1 << UNIT_V_UF) - 1) /* mask of SCP flags */ -#define IF_MII (1 << (UNIT_V_UF + 0)) /* model 2 */ -#define IF_DIV (1 << (UNIT_V_UF + 1)) /* automatic divide */ -#define IF_IA (1 << (UNIT_V_UF + 2)) /* indirect addressing */ -#define IF_EDT (1 << (UNIT_V_UF + 3)) /* edit */ -#define IF_FP (1 << (UNIT_V_UF + 4)) /* floating point */ -#define IF_BIN (1 << (UNIT_V_UF + 5)) /* binary */ -#define IF_IDX (1 << (UNIT_V_UF + 6)) /* indexing */ -#define IF_VPA (1 << (UNIT_V_UF + 7)) /* valid P addr */ -#define IF_VQA (1 << (UNIT_V_UF + 8)) /* valid Q addr */ -#define IF_4QA (1 << (UNIT_V_UF + 9)) /* 4 char Q addr */ -#define IF_NQX (1 << (UNIT_V_UF + 10)) /* no Q indexing */ -#define IF_IMM (1 << (UNIT_V_UF + 11)) /* immediate */ -#define UNIT_BCD (1 << (UNIT_V_UF + 12)) /* BCD coded */ -#define UNIT_MSIZE (1 << (UNIT_V_UF + 13)) /* fake flag */ -#define ALLOPT (IF_DIV + IF_IA + IF_EDT + IF_FP + IF_BIN + IF_IDX) -#define MI_OPT (IF_DIV + IF_IA + IF_EDT + IF_FP) -#define MI_STD (IF_DIV + IF_IA + IF_EDT) -#define MII_OPT (ALLOPT) -#define MII_STD (IF_DIV + IF_IA + IF_EDT + IF_BIN + IF_IDX) - -/* Add status codes */ - -#define ADD_NOCRY 0 /* no carry out */ -#define ADD_CARRY 1 /* carry out */ -#define ADD_SIGNC 2 /* sign change */ - -/* Opcodes */ - -enum opcodes { - OP_FADD = 1, OP_FSUB, OP_FMUL, /* 00 - 09 */ - OP_FSL = 5, OP_TFL, OP_BTFL, OP_FSR, OP_FDIV, - OP_BTAM = 10, OP_AM, OP_SM, OP_MM, OP_CM, /* 10 - 19 */ - OP_TDM, OP_TFM, OP_BTM, OP_LDM, OP_DM, - OP_BTA = 20, OP_A, OP_S, OP_M, OP_C, /* 20 - 29 */ - OP_TD, OP_TF, OP_BT, OP_LD, OP_D, - OP_TRNM = 30, OP_TR, OP_SF, OP_CF, OP_K, /* 30 - 39 */ - OP_DN, OP_RN, OP_RA, OP_WN, OP_WA, - OP_NOP = 41, OP_BB, OP_BD, OP_BNF, /* 40 - 49 */ - OP_BNR, OP_BI, OP_BNI, OP_H, OP_B, - OP_BNG = 55, - OP_BS = 60, OP_BX, OP_BXM, OP_BCX, OP_BCXM, /* 60 - 69 */ - OP_BLX, OP_BLXM, OP_BSX, - OP_MA = 70, OP_MF, OP_TNS, OP_TNF, /* 70 - 79 */ - /* 80 - 89 */ - OP_BBT = 90, OP_BMK, OP_ORF, OP_ANDF, OP_CPLF, /* 90 - 99 */ - OP_EORF, OP_OTD, OP_DTO }; diff --git a/I1620/i1620_doc.txt b/I1620/i1620_doc.txt deleted file mode 100644 index 2f408e54..00000000 --- a/I1620/i1620_doc.txt +++ /dev/null @@ -1,518 +0,0 @@ -To: Users -From: Bob Supnik -Subj: IBM 1620 Simulator Usage -Date: 15-Apr-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - Original code published in 1993-2003, written by Robert M Supnik - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - -This memorandum documents the IBM 1620 simulator. This simulator is based on -Geoff Kuenning's 1620 simulator, which is used by permission. - -1. Simulator Files - -sim/ sim_defs.h - sim_rev.h - sim_sock.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tmxr.c - -sim/i1620/ i1620_defs.h - i1620_cpu.c - i1620_fp.c - i1620_tty.c - i1620_pt.c - i1620_cd.c - i1620_lp.c - i1620_dp.c - i1620_sys.c - -2. IBM 1620 Features - -The IBM 1620 simulator is configured as follows: - -device simulates -name(s) - -CPU IBM 1620 Model 1 or Model 2 CPU with 20K to 60K of memory - Model 1 options: indirect addressing, automatic divide, - edit instructions, floating point - Model 2 options: indexing, binary capability, floating point -TTY IBM console terminal -PTR IBM 1621 paper tape reader -PTP IBM 1624 paper tape punch -CDR,CDP IBM 1622 card reader/punch -LPT IBM 1443 line printer -DP IBM 1311 disk pack with four drives - -The IBM 1620 simulator implements many unique stop conditions. On almost -any kind of error the simulator stops: - - unimplemented opcode - reference to non-existent device - invalid digit - invalid alphameric character - invalid P address digit - invalid Q address digit - indirect address limit exceeded - invalid odd address - invalid even address - invalid function - invalid indicator - invalid return address register - skip to unpunched carriage control tape channel - card reader hopper empty - overflow with arithmetic stop switch set - I/O error with I/O stop switch set - invalid disk drive - invalid disk sector address - invalid disk sector count - invalid disk buffer address - disk address compare error - disk cylinder overflow error - disk write check error - field exceeds memory - record exceeds memory - floating point mantissa exceeds maximum length - floating point mantissas not the same length - floating point exponent check with arithmetic stop switch set - floating point exponent missing high flag - -The LOAD command is used to load a line printer carriage-control tape. -The DUMP command is not implemented. - -2.1 CPU - -The CPU options include the CPU model (Model 1 or Model 2), a number of -special features, and the size of main memory. - - SET CPU IA enable indirect addressing - SET CPU NOIA disable indirect addressing - SET CPU EDT enable extra editing instructions - SET CPU NOEDT disable extra editing instructions - SET CPU DIV enable divide instructions - SET CPU NODIV disable divide instructions - SET CPU IDX enable indexing - SET CPU NOIDX disable indexing - SET CPU BIN enable binary instructions - SET CPU NOBIN disable binary instructions - SET CPU FP enable floating point instructions - SET CPU NOFP disable floating point instructions - SET CPU MOD1 set Model 1 - SET CPU MOD2 set Model 2 - SET CPU 20K set memory size = 20K - SET CPU 40K set memory size = 40K - SET CPU 60K set memory size = 60K - -Model 1 options include IA, EDT, DIV, and FP; the first three are on by -default. Model 2 options include IDX, BIN, and FP; IA, EDT, and DIV are -standard on the Model 2. - -If memory size is being reduced, and the memory being truncated contains -non-zero data, the simulator asks for confirmation. Data in the truncated -portion of memory is lost. Initially, the CPU is a Model 1, memory size is -20K, and indirect addressing, editing instructions, and divide are enabled. - -Memory is implemented as 5 bit BCD digits, as follows: - - 4 3 2 1 0 - - flag 8 4 2 1 - <-------- digit --------> - -In BCD, the decimal digits 0-9 are (hex) values 0x0, 0x1, 0x2, 0x3, 0x4, -0x5, 0x6, 0x7, 0x8, 0x9, respectively. 0xA is record mark, 0xC non- -punching blank, and 0xF group mark, respectively. - -CPU registers include the visible state of the processor. The 1620 has no -interrupt system. - - name size comments - - IR1 16 instruction storage address register (PC) - IR2 16 return register - PR1 16 processor register 1 - PAR 16 P address register (OR2) - QAR 16 Q address register (OR1) - SS1 1 sense switch 1 - SS2 1 sense switch 2 - SS3 1 sense switch 3 - SS4 1 sense switch 4 - HP 1 high/positive indicator - EZ 1 equal/zero indicator - ARCHK 1 arithmetic check (overflow) indicator - EXPCHK 1 exponent check indicator - RDCHK 1 read check indicator - WRCHK 1 write check indicator - ARSTOP 1 arithmetic check stop switch - IOSTOP 1 I/O check stop switch - IND[0:99] 1 indicator array - IAE 1 indirect address enable (Model 2 only) - IDXE 1 indexing enable (Model 2 only) - IDXB 1 indexing band select (Model 2 only) - IR1Q[0:63] 16 IR1 prior to last branch; - most recent IR1 change first - WRU 8 interrupt character - -2.2 Console Typewriter (TTY) - -The console typewriter (TTY) is a half-duplex console. The typewriter -registers are: - - name size comments - - COL 7 current column - TIME 24 polling interval - -When the 1620 CPU requests input from the keyboard, a reverse apostrophe -(`) is printed. The CPU hangs waiting for input until the return/enter -key is pressed. The typewriter has no errors. - -2.3 1621 Paper Tape Reader (PTR) - -The paper tape reader (PTR) reads data from a disk file. The POS register -specifies the number of the next data item to be read. Thus, by changing -POS, the user can backspace or advance the reader. - -The paper tape reader supports the BOOT command. BOOT PTR starts the -standard paper tape boot sequence at location 0. - -The paper tape reader implements these registers: - - name size comments - - POS 32 position in the input file - -Error handling is as follows: - - error IOCHK processed as - - not attached x set RDCHK indicator, report error, stop - - end of file x set RDCHK indicator, report error, stop - - OS I/O error x set RDCHK indicator, report error, stop - - parity error 1 set RDCHK indicator, report error, stop - 0 set RDCHK indicator - -2.4 1624 Paper Tape Punch (PTP) - -The paper tape punch (PTP) writes data to a disk file. The POS register -specifies the number of the next data item to be written. Thus, by -changing POS, the user can backspace or advance the punch. - -The paper tape punch implements these registers: - - name size comments - - POS 32 position in the output file - -Error handling is as follows: - - error IOCHK processed as - - not attached x set WRCHK indicator, report error, stop - - OS I/O error x set WRCHK indicator, report error, stop - - invalid char 1 set WRCHK indicator, report error, stop - 0 set WRCHK indicator - -2.5 1622 Card Reader/Punch (CDR, CDP) - -The IBM 1402 card/reader punch is simulated as two independent devices: -the card reader (CDR) and the card punch (CDP). - -The card reader supports the BOOT command. BOOT CDR starts the standard -card boot sequence at location 0. - -The card reader reads data from a disk file, while the punch writes data -to a disk file. Cards are simulated as ASCII text lines with terminating -newlines. For each unit, the POS register specifies the number of the -next data item to be read or written. Thus, by changing POS, the user -can backspace or advance these devices. - -The card reader registers are: - - name size comments - - LAST 1 last card indicator - POS 32 position - -The card punch registes are: - - name size comments - - POS 32 position - -Card reader error handling is as follows: - - error IOCHK processed as - - end of file x set RDCHK indicator, report error, stop - - not attached x set RDCHK indicator, report error, stop - - OS I/O error x set RDCHK indicator, report error, stop - - invalid char 1 set RDCHK indicator, report error, stop - 0 set RDCHK indicator - -Card punch error handling is as follows: - - error IOCHK processed as - - not attached x set WRCHK indicator, report error, stop - - OS I/O error x set WRCHK indicator, report error, stop - - invalid char 1 set WRCHK indicator, report error, stop - 0 set WRCHK indicator - -2.6 1443 Line Printer (LPT) - -The IBM 1443 line printer (LPT) writes its data, converted to ASCII, to -a disk file. The line printer can be programmed with a carriage control -tape. The LOAD command loads a new carriage control tape: - - LOAD load carriage control tape file - -The format of a carriage control tape consists of multiple lines. Each -line contains an optional repeat count, enclosed in parentheses, optionally -followed by a series of column numbers separated by commas. Column numbers -must be between 1 and 12; a column number of zero denotes top of form. The -following are all legal carriage control specifications: - - no punch - (5) 5 lines with no punches - 1,5,7,8 columns 1, 5, 7, 8 punched - (10)2 10 lines with column 2 punched - 1,0 column 1 punched; top of form - -The default form is 66 lines long, with column 1 and the top of form mark -on line 1, and the rest blank. - -The line printer registers are: - - name size comments - - LBUF[0:119] 7 line buffer - BPTR 7 buffer pointer - PCTL 8 saved print control directive - PRCHK 1 print check indicator - PRCH9 1 channel 9 indicator - PRCH12 1 channel 12 indicator - POS 32 position - CCT[0:131] 32 carriage control tape array - CCTP 8 carriage control tape pointer - CCTL 8 carriage control tape length (read only) - -Error handling is as follows: - - error IOCHK processed as - - not attached x set PRCHK, WRCHK indicators, report error, stop - - OS I/O error x set PRCHK, WRCHK indicators, report error, stop - - invalid char 1 set PRCHK, WRCHK indicator, report error, stop - 0 set PRCHK, WRCHK indicator - -2.7 1311 Disk Pack (DP) - -The disk pack controller supports 4 drives, numbered 0 through 3. Disk -pack options include the ability to enable address writing (formatting). - - SET DPn ADDROFF set unit n address enable off - SET DPn ADDRON set unit n address enable on - -Units can also be set ONLINE or OFFLINE. - -Unlike most simulated disks, the 1311 includes explicit representation -for sector addresses. This is to support non-standard formats, such as -the inclusion of the drive number in the sector address. As a result, -1311 sectors are 105 digits long: 5 address digits and 100 data digits. -If the 1311 has not been formatted, the addresses are zeroes and are -synthesized, if needed, based on the sector number. - -The disk pack controller implements these registers: - - name size comments - - ADCHK 1 address check (compare error) indicator - WLRC 1 wrong length record check indicator - CYLO 1 cylinder overflow check indicator - ERR 1 disk error indicator - DPSTOP 1 disk check stop - -Error handling is as follows: - - error DPCHK processed as - - not attached x set ERR indicator, report error, stop - -1311 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.8 Symbolic Display and Input - -The IBM 1620 simulator implements symbolic display and input. Display is -controlled by command line switches: - - -c display as single character (alphameric - for CPU and DP, ASCII for others) - -s display as flag terminated numeric string - (CPU and DP only) - -m display instruction mnemonics - (CPU and DP only) - -d display 50 characters per line, with word - marks denoted by "_" on the line above - -In a CPU string display, word marks are denoted by ~. - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or -c character (alphameric for CPU and DP, ASCII - for others) - " or -s numeric string (CPU and DP only) - alphabetic instruction mnemonic (CPU and DP only) - numeric octal number - -Instruction input is free format and consists of an opcode and up to -three operands: - - op {+/-}ppppp{(idx)},{+-}qqqqq{(idx)},flags - -The p address and, if present, the q address, are always decimal. A -plus sign is ignored; a minus sign denotes indirect addressing (or a -negative immediate operand). If indexing is enabled, addresses may -be indexed; index registers are decimal numbers between 1 and 7. The -flags field is used to set extra flags on the instruction. It consists -of digit numbers in ascending order, with no separators. For example, - - AM -12345(5),67890,110 - -translates into - _ _ ___ _ - 111234567890 - -The flag over digits 3 and 5 specify the P index register; the flag -over digit 6 specifies the P indirect address; the flag over digit 7 -marks the end of the immediate Q operand; and the flags over digits -1 and 10 are specified by the third field. - -2.9 Character Sets - -The IBM 1620 uses single digits to represent numbers, and pairs of -digits to represent characters (alphameric coding). Only a small -number of the 256 possible alphameric codings have legitimate values. -Further, the translation between alphameric and devices varied from -device to device. The simulator implements a code called 1620 ASCII, -which allows all 64 possible card codes to be represented by upper -case ASCII characters. In addition, lower case alphabetic characters -are accepted on input as equivalent to upper case. - -Card code PT code RA RN LPT WA ASCII representation - - C 0 0 blank blank -12 XOC 10 0 + + -11 X 20 F+0 - - -0 O 70 0 0 0 -1 1 71 1 1 1 -2 2 72 2 2 2 -3 C21 73 3 3 3 -4 4 74 4 4 4 -5 C41 75 5 5 5 -6 C42 76 6 6 6 -7 421 77 7 7 7 -8 8 78 8 8 8 -9 C81 79 9 9 9 -12 + 1 XO1 41 1 A A -12 + 2 XO2 42 2 B B -12 + 3 XOC21 43 3 C C -12 + 4 XO4 44 4 D D -12 + 5 XOC41 45 5 E E -12 + 6 XOC42 46 6 F F -12 + 7 XO421 47 7 G G -12 + 8 XO8 48 8 H H -12 + 9 XOC81 49 9 I I -11 + 1 XC1 51 F+1 J J -11 + 2 XC2 52 F+2 K K -11 + 3 X21 53 F+3 L L -11 + 4 XC4 54 F+4 M M -11 + 5 X41 55 F+5 N N -11 + 6 X42 56 F+6 O O -11 + 7 XC421 57 F+7 P P -11 + 8 XC8 58 F+8 Q Q -11 + 9 X81 59 F+9 R R -0 + 1 OC1 21 1 / / -0 + 2 OC2 62 2 S S -0 + 3 O21 63 3 T T -0 + 4 OC4 64 4 U U -0 + 5 O41 65 5 V V -0 + 6 O42 66 6 W W -0 + 7 OC421 67 7 X X -0 + 8 OC8 68 8 Y Y -0 + 9 O81 69 9 Z Z -2 + 8 C82 ? 0A A na % -3 + 8 821 33 B = = -4 + 8 C84 34 C @ @ -5 + 8 841 70 0 0 : -6 + 8 842 ? 0E E na > -7 + 8 C8421 ? 0F F na ^ -12 + 2 + 8 XOC82 ? 5A ? F+A na ? -12 + 3 + 8 XO821 3 ? F+B . . -12 + 4 + 8 XOC84 4 C ) ) -12 + 5 + 8 XO841 40 0 na [ -12 + 6 + 8 XO842 ? 5E ? F+E na < -12 + 7 + 8 XOC8421 5F F+F na " -11 + 2 + 8 X82 5A F+A na ! -11 + 3 + 8 XC821 13 F+B $ $ -11 + 4 + 8 X84 14 F+C * * -11 + 5 + 8 XC841 50 F+0 - ] -11 + 6 + 8 XC842 ? 5E ? F+E na ; -11 + 7 + 8 X8421 5F F+F na _ -0 + 2 + 8 O82 0A A na ' -0 + 3 + 8 OC821 23 B , , -0 + 4 + 8 O84 24 C ( ( -0 + 5 + 8 OC841 60 0 na # -0 + 6 + 8 OC842 0E E na \ -0 + 7 + 8 O8421 0F F na & - - 2 ? - 12 ! - 22 ' - 32 0 - 35 : - 36 blank -11 + 0 50 - ] diff --git a/I1620/i1620_dp.c b/I1620/i1620_dp.c deleted file mode 100644 index 10f2a16c..00000000 --- a/I1620/i1620_dp.c +++ /dev/null @@ -1,463 +0,0 @@ -/* i1620_dp.c: IBM 1311 disk simulator - - Copyright (c) 2002-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - dp 1311 disk pack - - The 1311 disk pack has 100 cylinders, 10 tracks/cylinder, 20 sectors/track. - Each sector contains 105 characters of information: - - 5c sector address - 100c sector data - - By default, a sector's address field will be '00000', which is interpreted - to mean the implied sector number that would be in place if the disk pack - had been formatted with sequential sector numbers. - - 18-Oct-02 RMS Fixed bug in error testing (found by Hans Pufal) -*/ - -#include "i1620_defs.h" - -#define DP_NUMDR 4 /* #drives */ -#define UNIT_V_WAE (UNIT_V_UF + 0) /* write addr enab */ -#define UNIT_WAE (1 << UNIT_V_WAE) - -/* Disk format */ - -#define DP_ADDR 5 /* address */ -#define DP_DATA 100 /* data */ -#define DP_NUMCH (DP_ADDR + DP_DATA) - -#define DP_NUMSC 20 /* #sectors */ -#define DP_NUMSF 10 /* #surfaces */ -#define DP_NUMCY 100 /* #cylinders */ -#define DP_TOTSC (DP_NUMCY * DP_NUMSF * DP_NUMSC) -#define DP_SIZE (DP_TOTSC * DP_NUMCH) - -/* Disk control field */ - -#define DCF_DRV 0 /* drive select */ -#define DCF_SEC 1 /* sector addr */ -#define DCF_SEC_LEN 5 -#define DCF_CNT (DCF_SEC + DCF_SEC_LEN) /* sector count */ -#define DCF_CNT_LEN 3 -#define DCF_ADR (DCF_CNT + DCF_CNT_LEN) /* buffer address */ -#define DCF_ADR_LEN 5 -#define DCF_LEN (DCF_ADR + DCF_ADR_LEN) - -/* Functions */ - -#define FNC_SEEK 1 /* seek */ -#define FNC_SEC 0 /* sectors */ -#define FNC_WCH 1 /* write check */ -#define FNC_NRL 2 /* no rec lnt chk */ -#define FNC_TRK 4 /* tracks */ -#define FNC_WRI 8 /* write offset */ - -#define CYL u3 /* current cylinder */ - -extern uint8 M[MAXMEMSIZE]; /* memory */ -extern uint8 ind[NUM_IND]; -extern UNIT cpu_unit; - -int32 dp_stop = 1; /* disk err stop */ -uint32 dp_ba = 0; /* buffer addr */ - -t_stat dp_reset (DEVICE *dptr); -t_stat dp_rdadr (UNIT *uptr, int32 sec, int32 qnr, int32 qwc); -t_stat dp_rdsec (UNIT *uptr, int32 sec, int32 qnr, int32 qwc); -t_stat dp_wradr (UNIT *uptr, int32 sec, int32 qnr); -t_stat dp_wrsec (UNIT *uptr, int32 sec, int32 qnr); -int32 dp_fndsec (UNIT *uptr, int32 sec, t_bool rd); -t_stat dp_nexsec (UNIT *uptr, int32 sec, int32 psec, t_bool rd); -t_bool dp_zeroad (uint8 *ap); -int32 dp_cvt_ad (uint8 *ap); -int32 dp_trkop (int32 drv, int32 sec); -int32 dp_cvt_bcd (uint32 ad, int32 len); -void dp_fill (UNIT *uptr, uint32 da, int32 cnt); -t_stat dp_tstgm (uint32 c, int32 qnr); - -/* DP data structures - - dp_dev DP device descriptor - dp_unit DP unit list - dp_reg DP register list - dp_mod DP modifier list -*/ - -UNIT dp_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) } }; - -REG dp_reg[] = { - { FLDATA (ADCHK, ind[IN_DACH], 0) }, - { FLDATA (WLRC, ind[IN_DWLR], 0) }, - { FLDATA (CYLO, ind[IN_DCYO], 0) }, - { FLDATA (ERR, ind[IN_DERR], 0) }, - { FLDATA (DPSTOP, dp_stop, 0) }, - { URDATA (CYL, dp_unit[0].CYL, 10, 8, 0, - DP_NUMDR, PV_LEFT + REG_RO) }, - { NULL } }; - -MTAB dp_mod[] = { - { UNIT_WAE, 0, "write address disabled", "ADDROFF", NULL }, - { UNIT_WAE, UNIT_WAE, "write address enabled", "ADDRON", NULL }, - { 0 } }; - -DEVICE dp_dev = { - "DP", dp_unit, dp_reg, dp_mod, - DP_NUMDR, 10, 21, 1, 16, 5, - NULL, NULL, &dp_reset, - NULL, NULL, NULL }; - -/* Disk IO routine */ - -t_stat dp (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -int32 drv, sa, sec, psec, cnt, qwc, qnr, t; -UNIT *uptr; -t_stat r; - -if (pa & 1) return STOP_INVDCF; /* dcf must be even */ -ind[IN_DACH] = ind[IN_DWLR] = 0; /* clr indicators */ -ind[IN_DERR] = ind[IN_DCYO] = 0; -sa = ADDR_A (pa, DCF_SEC); /* ptr to sector */ -if (((dp_unit[0].flags & UNIT_DIS) == 0) && /* only drive 0? */ - (dp_unit[1].flags & UNIT_DIS) && - (dp_unit[2].flags & UNIT_DIS) && - (dp_unit[3].flags & UNIT_DIS)) drv = 0; /* ignore drv select */ -else drv = (((M[pa] & 1)? M[pa]: M[sa]) & 0xE) >> 1; /* drive # */ -if (drv >= DP_NUMDR) return STOP_INVDRV; /* invalid? */ -uptr = dp_dev.units + drv; /* get unit ptr */ -if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ - ind[IN_DERR] = 1; /* no, error */ - CRETIOE (dp_stop, SCPE_UNATT); } - -sec = dp_cvt_bcd (sa, DCF_SEC_LEN); /* cvt sector */ -if ((sec < 0) || (sec >= (DP_NUMDR * DP_TOTSC))) /* bad sector? */ - return STOP_INVDSC; -if (op == OP_K) { /* seek? */ - if (f1 != FNC_SEEK) return STOP_INVFNC; /* really? */ - uptr->CYL = (sec / (DP_NUMSF * DP_NUMSC)) % /* set cyl # */ - DP_NUMCY; - return SCPE_OK; } /* done! */ - -cnt = dp_cvt_bcd (ADDR_A (pa, DCF_CNT), DCF_CNT_LEN); /* get count */ -t = dp_cvt_bcd (ADDR_A (pa, DCF_ADR), DCF_ADR_LEN); /* get address */ -if ((t < 0) || (t & 1)) return STOP_INVDBA; /* bad address? */ -dp_ba = t; /* save addr */ - -if (f1 >= FNC_WRI) return STOP_INVFNC; /* invalid func? */ -if (op == OP_RN) qwc = f1 & FNC_WCH; /* read? set wch */ -else if (op == OP_WN) { /* write? */ - if (op & FNC_WCH) return STOP_INVFNC; /* cant check */ - f1 = f1 + FNC_WRI; } /* offset fnc */ -else return STOP_INVFNC; /* not R or W */ -qnr = f1 & FNC_NRL; /* no rec check? */ - -switch (f1 & ~(FNC_WCH | FNC_NRL)) { /* case on function */ -case FNC_SEC: /* read sectors */ - if (cnt <= 0) return STOP_INVDCN; /* bad count? */ - psec = dp_fndsec (uptr, sec, TRUE); /* find sector */ - if (psec < 0) CRETIOE (dp_stop, STOP_DACERR); /* error? */ - do { /* loop on count */ - if (r = dp_rdsec (uptr, psec, qnr, qwc)) /* read sector */ - break; - sec++; psec++; } /* next sector */ - while ((--cnt > 0) && - ((r = dp_nexsec (uptr, sec, psec, TRUE)) == SCPE_OK)); - break; /* done, clean up */ - -case FNC_TRK: /* read track */ - psec = dp_trkop (drv, sec); /* start of track */ - for (cnt = 0; cnt < DP_NUMSC; cnt++) { /* full track */ - if (r = dp_rdadr (uptr, psec, qnr, qwc)) /* read addr */ - break; /* error? */ - if (r = dp_rdsec (uptr, psec, qnr, qwc)) /* read data */ - break; /* error? */ - psec = dp_trkop (drv, sec) + ((psec + 1) % DP_NUMSC); } - break; /* done, clean up */ - -case FNC_SEC + FNC_WRI: /* write */ - if (cnt <= 0) return STOP_INVDCN; /* bad count? */ - psec = dp_fndsec (uptr, sec, FALSE); /* find sector */ - if (psec < 0) CRETIOE (dp_stop, STOP_DACERR); /* error? */ - do { /* loop on count */ - if (r = dp_tstgm (M[dp_ba], qnr)) break; /* start with gm? */ - if (r = dp_wrsec (uptr, psec, qnr)) break; /* write data */ - sec++; psec++; } /* next sector */ - while ((--cnt > 0) && - ((r = dp_nexsec (uptr, sec, psec, FALSE)) == SCPE_OK)); - break; /* done, clean up */ - -case FNC_TRK + FNC_WRI: /* write track */ - if ((uptr->flags & UNIT_WAE) == 0) /* enabled? */ - return STOP_WRADIS; - psec = dp_trkop (drv, sec); /* start of track */ - for (cnt = 0; cnt < DP_NUMSC; cnt++) { /* full track */ - if (r = dp_tstgm (M[dp_ba], qnr)) break; /* start with gm? */ - if (r = dp_wradr (uptr, psec, qnr)) break; /* write addr */ - if (r = dp_wrsec (uptr, psec, qnr)) break; /* write data */ - psec = dp_trkop (drv, sec) + ((psec + 1) % DP_NUMSC); } - break; /* done, clean up */ - -default: /* unknown */ - return STOP_INVFNC; } - -if ((r == SCPE_OK) && !qnr) { /* eor check? */ - if ((M[dp_ba] & DIGIT) != GRP_MARK) { /* GM at end? */ - ind[IN_DWLR] = ind[IN_DERR] = 1; /* no, error */ - r = STOP_WRLERR; } } -if ((r != SCPE_OK) && /* error? */ - (dp_stop || !ind[IN_DERR])) return r; /* iochk or stop? */ -return SCPE_OK; /* continue */ -} - -/* Read or compare address with memory */ - -t_stat dp_rdadr (UNIT *uptr, int32 sec, int32 qnr, int32 qwc) -{ -int32 i; -uint8 ad; -int32 da = (sec % DP_TOTSC) * DP_NUMCH; /* char number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ -t_bool zad = dp_zeroad (ap); /* zero address */ -static const int32 dec_tab[DP_ADDR] = /* powers of 10 */ - { 10000, 1000, 100, 10, 1} ; - -for (i = 0; i < DP_ADDR; i++) { /* copy/check addr */ - if (zad) { /* addr zero? */ - ad = sec / dec_tab[i]; /* get addr digit */ - sec = sec % dec_tab[i]; } /* get remainder */ - else ad = *ap; /* addr digit */ - if (qwc) { /* write check? */ - if (dp_tstgm (M[dp_ba], qnr)) /* grp mrk in mem? */ - return STOP_WRLERR; /* yes, error */ - if (!zad && (M[dp_ba] != ad)) { /* digits equal? */ - ind[IN_DACH] = ind[IN_DERR] = 1; /* no, error */ - return STOP_DWCERR; } } - else M[dp_ba] = ad & (FLAG | DIGIT); /* store digit */ - if (dp_tstgm (*ap, qnr)) return STOP_WRLERR; /* grp mrk on disk? */ - ap++; PP (dp_ba); } /* adv ptrs */ -return SCPE_OK; -} - -/* Read or compare data with memory */ - -t_stat dp_rdsec (UNIT *uptr, int32 sec, int32 qnr, int32 qwc) -{ -int32 i; -int32 da = (sec % DP_TOTSC) * DP_NUMCH; /* char number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da + DP_ADDR; /* buf ptr */ - -for (i = 0; i < DP_DATA; i++) { /* copy data */ - if (qwc) { /* write check? */ - if (dp_tstgm (M[dp_ba], qnr)) /* grp mrk in mem? */ - return STOP_WRLERR; /* yes, error */ - if (M[dp_ba] != *ap) { /* dig+flags equal? */ - ind[IN_DACH] = ind[IN_DERR] = 1; /* no, error */ - return STOP_DWCERR; } } - else M[dp_ba] = *ap & (FLAG | DIGIT); /* flag + digit */ - if (dp_tstgm (*ap, qnr)) return STOP_WRLERR; /* grp mrk on disk? */ - ap++; PP (dp_ba); } /* adv ptrs */ -return SCPE_OK; -} - -/* Write address to disk */ - -t_stat dp_wradr (UNIT *uptr, int32 sec, int32 qnr) -{ -int32 i; -uint32 da = (sec % DP_TOTSC) * DP_NUMCH; /* char number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ - -for (i = 0; i < DP_ADDR; i++) { /* copy address */ - *ap = M[dp_ba] & (FLAG | DIGIT); /* flag + digit */ - if (da >= uptr->hwmark) uptr->hwmark = da + 1; - if (dp_tstgm (*ap, qnr)) { /* grp mrk fm mem? */ - dp_fill (uptr, da + 1, DP_NUMCH - i - 1); /* fill addr+data */ - return STOP_WRLERR; } /* error */ - da++; ap++; PP (dp_ba); /* adv ptrs */ - } -return SCPE_OK; -} - -/* Write data to disk */ - -t_stat dp_wrsec (UNIT *uptr, int32 sec, int32 qnr) -{ -int32 i; -uint32 da = ((sec % DP_TOTSC) * DP_NUMCH) + DP_ADDR; /* char number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ - -for (i = 0; i < DP_DATA; i++) { /* copy data */ - *ap = M[dp_ba] & (FLAG | DIGIT); /* get character */ - if (da >= uptr->hwmark) uptr->hwmark = da + 1; - if (dp_tstgm (*ap, qnr)) { /* grp mrk fm mem? */ - dp_fill (uptr, da + 1, DP_DATA - i - 1); /* fill data */ - return STOP_WRLERR; } /* error */ - da++; ap++; PP (dp_ba); /* adv ptrs */ - } -return SCPE_OK; -} - -/* Find sector */ - -int32 dp_fndsec (UNIT *uptr, int32 sec, t_bool rd) -{ -int32 ctrk = sec % (DP_NUMSF * DP_NUMSC); /* curr trk-sec */ -int32 psec = ((uptr->CYL) * (DP_NUMSF * DP_NUMSC)) + ctrk; -int32 da = psec * DP_NUMCH; /* char number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ -int32 dskad, i; - -if (dp_zeroad (ap)) return psec; /* addr zero? ok */ -dskad = dp_cvt_ad (ap); /* cvt addr */ -if (dskad == sec) { /* match? */ - if (rd || ((*ap & FLAG) == 0)) return psec; /* read or !wprot? */ - ind[IN_DACH] = ind[IN_DERR] = 1; /* no match */ - return -1; } -psec = psec - (psec % DP_NUMSC); /* sector 0 */ -for (i = 0; i < DP_NUMSC; i++, psec++) { /* check track */ - da = psec * DP_NUMCH; /* char number */ - ap = ((uint8 *) uptr->filebuf) + da; /* word pointer */ - if (dp_zeroad (ap)) continue; /* no implicit match */ - dskad = dp_cvt_ad (ap); /* cvt addr */ - if (dskad == sec) { /* match? */ - if (rd || ((*ap & FLAG) == 0)) return psec; /* read or !wprot? */ - ind[IN_DACH] = ind[IN_DERR] = 1; /* no match */ - return -1; } } -ind[IN_DACH] = ind[IN_DERR] = 1; /* no match */ -return -1; -} - -/* Find next sector - must be sequential, cannot cross cylinder boundary */ - -t_stat dp_nexsec (UNIT *uptr, int32 sec, int32 psec, t_bool rd) -{ -int32 ctrk = psec % (DP_NUMSF * DP_NUMSC); /* curr trk-sec */ -int32 da = psec * DP_NUMCH; /* word number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ -int32 dskad; - -if (ctrk) { /* not trk zero? */ - if (dp_zeroad (ap)) return SCPE_OK; /* addr zero? ok */ - dskad = dp_cvt_ad (ap); /* cvt addr */ - if ((dskad == sec) && /* match? */ - (rd || ((*ap & FLAG) == 0))) return SCPE_OK; /* read or !wprot? */ - ind[IN_DACH] = ind[IN_DERR] = 1; /* no, error */ - return STOP_DACERR; } -ind[IN_DCYO] = ind[IN_DERR] = 1; /* cyl overflow */ -return STOP_CYOERR; -} - -/* Test for zero address */ - -t_bool dp_zeroad (uint8 *ap) -{ -int32 i; - -for (i = 0; i < DP_ADDR; i++, ap++) { /* loop thru addr */ - if (*ap & DIGIT) return FALSE; } /* nonzero? lose */ -return TRUE; /* all zeroes */ -} - -/* Test for group mark when enabled */ - -t_stat dp_tstgm (uint32 c, int32 qnr) -{ -if (!qnr && ((c & DIGIT) == GRP_MARK)) { /* premature GM? */ - ind[IN_DWLR] = ind[IN_DERR] = 1; /* error */ - return STOP_WRLERR; } -return SCPE_OK; -} - -/* Convert disk address to binary - invalid char force bad address */ - -int32 dp_cvt_ad (uint8 *ap) -{ -int32 i, r; -uint8 c; - -for (i = r = 0; i < DP_ADDR; i++, ap++) { /* loop thru addr */ - c = *ap & DIGIT; /* get digit */ - if (BAD_DIGIT (c)) return -1; /* bad digit? */ - r = (r * 10) + c; } /* bcd to binary */ -return r; -} - -/* Track operation setup */ - -int32 dp_trkop (int32 drv, int32 sec) -{ -int32 ctrk = (sec / DP_NUMSC) % DP_NUMSF; - -return ((drv * DP_TOTSC) + (dp_unit[drv].CYL * DP_NUMSF * DP_NUMSC) + - (ctrk * DP_NUMSC)); -} - -/* Convert DCF BCD field to binary */ - -int32 dp_cvt_bcd (uint32 ad, int32 len) -{ -uint8 c; -int32 r; - -for (r = 0; len > 0; len--) { /* loop thru char */ - c = M[ad] & DIGIT; /* get digit */ - if (BAD_DIGIT (c)) return -1; /* invalid? */ - r = (r * 10) + c; /* cvt to bin */ - PP (ad); } /* next digit */ -return r; -} - -/* Fill sector buffer with zero */ - -void dp_fill (UNIT *uptr, uint32 da, int32 cnt) -{ -while (cnt-- > 0) { /* fill with zeroes*/ - *(((uint8 *) uptr->filebuf) + da) = 0; - if (da >= uptr->hwmark) uptr->hwmark = da + 1; - da++; } -return; -} - -/* Reset routine */ - -t_stat dp_reset (DEVICE *dptr) -{ -int32 i; - -for (i = 0; i < DP_NUMDR; i++) dp_unit[i].CYL = 0; /* reset cylinder */ -ind[IN_DACH] = ind[IN_DWLR] = 0; /* clr indicators */ -ind[IN_DERR] = ind[IN_DCYO] = 0; -return SCPE_OK; -} diff --git a/I1620/i1620_fp.c b/I1620/i1620_fp.c deleted file mode 100644 index 0cb54a96..00000000 --- a/I1620/i1620_fp.c +++ /dev/null @@ -1,388 +0,0 @@ -/* i1620_fp.c: IBM 1620 floating point simulator - - Copyright (c) 2002-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - The IBM 1620 uses a variable length floating point format, with a fixed - two digit decimal exponent and a variable length decimal mantissa: - - _ S_S - M.......MEE - - where S represents flag bits if the mantissa or exponent are negative. -*/ - -#include "i1620_defs.h" - -#define FP_LMAX 100 /* max fp mant lnt */ -#define FP_EMAX 99 /* max fp exponent */ - -/* Unpacked floating point operand */ - -struct fp_opnd { - int32 sign; /* 0 => +, 1 => - */ - int32 exp; /* binary exponent */ - uint32 lnt; /* mantissa length */ - uint32 addr; /* mantissa addr */ - uint32 zero; /* 0 => nz, 1 => zero */ -}; - -typedef struct fp_opnd FPA; - -extern uint8 M[MAXMEMSIZE]; /* main memory */ -extern uint8 ind[NUM_IND]; /* indicators */ -extern UNIT cpu_unit; - -t_stat fp_scan_mant (uint32 ad, uint32 *lnt, uint32 *zro); -t_stat fp_zero (FPA *fp); - -extern t_stat xmt_field (uint32 d, uint32 s, uint32 skp); -extern t_stat add_field (uint32 d, uint32 s, t_bool sub, t_bool sto, int32 *sta); -extern t_stat mul_field (uint32 d, uint32 s); -extern t_stat xmt_divd (uint32 d, uint32 s); -extern t_stat div_field (uint32 dvd, uint32 dvr, int32 *ez); - -/* Unpack and validate a floating point argument */ - -t_stat fp_unpack (uint32 ad, FPA *fp) -{ -uint8 d0, d1, esign; - -esign = M[ad] & FLAG; /* get exp sign */ -d0 = M[ad] & DIGIT; /* get exp lo digit */ -MM (ad); -if ((M[ad] & FLAG) == 0) return STOP_FPMF; /* no flag on hi exp? */ -d1 = M[ad] & DIGIT; /* get exp hi digit */ -MM (ad); -fp->addr = ad; /* save mant addr */ -if (BAD_DIGIT (d1) || BAD_DIGIT (d0)) return STOP_INVDIG; /* exp bad dig? */ -fp->exp = ((d1 * 10) + d0) * (esign? -1: 1); /* convert exponent */ -fp->sign = (M[ad] & FLAG)? 1: 0; /* get mantissa sign */ -return fp_scan_mant (fp->addr, &(fp->lnt), &(fp->zero)); -} - -/* Unpack and validate source and destination arguments */ - -t_stat fp_unpack_two (uint32 dad, uint32 sad, FPA *dfp, FPA *sfp) -{ -t_stat r; - -if ((r = fp_unpack (dad, dfp)) != SCPE_OK) return r; /* unpack dst */ -if ((r = fp_unpack (sad, sfp)) != SCPE_OK) return r; /* unpack src */ -if (sfp->lnt != dfp->lnt) return STOP_FPUNL; /* lnts must be equal */ -return SCPE_OK; -} - -/* Pack floating point result */ - -t_stat fp_pack (FPA *fp) -{ -int32 e; -uint32 i, mad; - -e = (fp->exp >= 0)? fp->exp: -fp->exp; /* get |exp| */ -if (e > FP_EMAX) { /* too big? */ - ind[IN_EXPCHK] = 1; /* set indicator */ - if (fp->exp < 0) return fp_zero (fp); /* underflow? */ - mad = fp->addr; - for (i = 0; i < fp->lnt; i++) { /* mant = 99...99 */ - M[mad] = (M[mad] & FLAG) | 9; - MM (mad); } - e = FP_EMAX; } /* cap at max */ -M[ADDR_A (fp->addr, 1)] = (e / 10) | FLAG; /* high exp digit */ -M[ADDR_A (fp->addr, 2)] = (e % 10) | /* low exp digit */ - ((fp->exp < 0)? FLAG: 0); -return SCPE_OK; -} - -/* Shift mantissa right n positions */ - -void fp_rsh (FPA *fp, uint32 n) -{ -uint32 i, sad, dad; - -if (n == 0) return; /* zero? done */ -sad = ADDR_S (fp->addr, n); /* src = addr - n */ -dad = fp->addr; /* dst = n */ -for (i = 0; i < fp->lnt; i++) { /* move digits */ - if (i >= (fp->lnt - n)) M[dad] = M[dad] & FLAG; - else M[dad] = (M[dad] & FLAG) | (M[sad] & DIGIT); - MM (dad); - MM (sad); } -return; -} - -/* Shift mantissa left 1 position */ - -void fp_lsh_1 (FPA *fp) -{ -uint32 i, mad, nxt; - -mad = ADDR_S (fp->addr, fp->lnt - 1); /* hi order digit */ -for (i = 0; i < (fp->lnt - 1); i++) { /* move lnt-1 digits */ - nxt = ADDR_A (mad, 1); - M[mad] = (M[mad] & FLAG) | (M[nxt] & DIGIT); - mad = nxt; } -M[mad] = M[mad] & FLAG; /* clear last digit */ -return; -} - -/* Clear floating point number */ - -t_stat fp_zero (FPA *fp) -{ -uint32 i, mad = fp->addr; - -for (i = 0; i < fp->lnt; i++) { /* clear mantissa */ - M[mad] = (i? M[mad] & FLAG: 0); /* clear sign bit */ - MM (mad); } -M[ADDR_A (fp->addr, 1)] = FLAG + 9; /* exp = -99 */ -M[ADDR_A (fp->addr, 2)] = FLAG + 9; /* exp = -99 */ -ind[IN_EZ] = 1; /* result = 0 */ -ind[IN_HP] = 0; -return SCPE_OK; -} - -/* Scan floating point mantissa for length and (optionally) zero */ - -t_stat fp_scan_mant (uint32 ad, uint32 *lnt, uint32 *zro) -{ -uint8 d, l, z; - -z = 1; /* assume zero */ -for (l = 1; l <= FP_LMAX; l++) { /* scan to get length */ - d = M[ad] & DIGIT; /* get mant digit */ - if (d) z = 0; /* non-zero? */ - if ((l != 1) && (M[ad] & FLAG)) { /* flag past first dig? */ - *lnt = l; /* set returns */ - if (zro) *zro = z; - return SCPE_OK; } - MM (ad); } -return STOP_FPLNT; /* too long */ -} - -/* Copy floating point mantissa */ - -void fp_copy_mant (uint32 d, uint32 s, uint32 l) -{ -uint32 i; - -if (ind[IN_HP]) M[d] = M[d] & ~FLAG; /* clr/set sign */ -else M[d] = M[d] | FLAG; -for (i = 0; i < l; i++) { /* copy src */ - M[d] = (M[d] & FLAG) | (M[s] & DIGIT); /* preserve flags */ - MM (d); - MM (s); } -return; -} - -/* Compare floating point mantissa */ - -int32 fp_comp_mant (uint32 d, uint32 s, uint32 l) -{ -uint8 i, dd, sd; - -d = ADDR_S (d, l - 1); /* start of mantissa */ -s = ADDR_S (s, l - 1); -for (i = 0; i < l; i++) { /* compare dst:src */ - dd = M[d] & DIGIT; /* get dst digit */ - sd = M[s] & DIGIT; /* get src digit */ - if (dd > sd) return 1; /* >? done */ - if (dd < sd) return -1; /* = ((int32) dfp.lnt))) { /* src = 0, or too small? */ - if (dfp.zero) return fp_zero (&dfp); /* res = dst, zero? */ - ind[IN_EZ] = 0; /* res nz, set EZ, HP */ - ind[IN_HP] = (dfp.sign == 0); - return SCPE_OK; } -if (dfp.zero || (dif <= -((int32) dfp.lnt))) { /* dst = 0, or too small? */ - if (sfp.zero) return fp_zero (&dfp); /* res = src, zero? */ - r = xmt_field (d, s, 3); /* copy src to dst */ - ind[IN_EZ] = 0; /* res nz, set EZ, HP */ - ind[IN_HP] = (dfp.sign == 0); - return r; } - -if (dif > 0) { /* dst exp > src exp? */ - sad = sfp.addr; /* save src in save area */ - for (i = 0; i < sfp.lnt; i++) { - sav_src[i] = M[sad]; - MM (sad); } - fp_rsh (&sfp, dif); } /* denormalize src */ -else if (dif < 0) { /* dst exp < src exp? */ - dfp.exp = sfp.exp; /* res exp = src exp */ - fp_rsh (&dfp, -dif); } /* denormalize dst */ -r = add_field (dfp.addr, sfp.addr, sub, TRUE, &sta); /* add mant, set EZ, HP */ -if (dif > 0) { /* src denormalized? */ - sad = sfp.addr; /* restore src from */ - for (i = 0; i < sfp.lnt; i++) { /* save area */ - M[sad] = sav_src[i]; - MM (sad); } } -if (r != SCPE_OK) return r; /* add error? */ - -hi = ADDR_S (dfp.addr, dfp.lnt - 1); /* addr of hi digit */ -if (sta == ADD_CARRY) { /* carry out? */ - fp_rsh (&dfp, 1); /* shift mantissa */ - M[hi] = FLAG + 1; /* high order 1 */ - dfp.exp = dfp.exp + 1; - ind[IN_EZ] = 0; /* not zero */ - ind[IN_HP] = (dfp.sign == 0); } /* set HP */ -else if (ind[IN_EZ]) return fp_zero (&dfp); /* result zero? */ -else { while ((M[hi] & DIGIT) == 0) { /* until normalized */ - fp_lsh_1 (&dfp); /* left shift */ - dfp.exp = dfp.exp - 1; } } /* decr exponent */ - -return fp_pack (&dfp); /* pack and exit */ -} - -/* Floating point multiply */ - -t_stat fp_mul (uint32 d, uint32 s) -{ -FPA sfp, dfp; -uint32 pad; -t_stat r; - -r = fp_unpack_two (d, s, &dfp, &sfp); /* unpack operands */ -if (r != SCPE_OK) return r; /* error? */ -if (sfp.zero || dfp.zero) return fp_zero (&dfp); /* either zero? */ - -r = mul_field (dfp.addr, sfp.addr); /* mul, set EZ, HP */ -if (r != SCPE_OK) return r; -if (M[ADDR_S (PROD_AREA_END, 2 * dfp.lnt)] & DIGIT) { /* hi prod dig set? */ - pad = ADDR_S (PROD_AREA_END - 1, dfp.lnt); /* no normalization */ - dfp.exp = dfp.exp + sfp.exp; } /* res exp = sum */ -else { pad = ADDR_S (PROD_AREA_END, dfp.lnt); /* 'normalize' 1 */ - dfp.exp = dfp.exp + sfp.exp - 1; } /* res exp = sum - 1 */ -fp_copy_mant (dfp.addr, pad, dfp.lnt); /* copy prod to mant */ - -return fp_pack (&dfp); /* pack and exit */ -} - -/* Floating point divide */ - -t_stat fp_div (uint32 d, uint32 s) -{ -FPA sfp, dfp; -uint32 i, pad, a100ml, a99ml; -int32 ez; -t_stat r; - -r = fp_unpack_two (d, s, &dfp, &sfp); /* unpack operands */ -if (r != SCPE_OK) return r; /* error? */ -if (sfp.zero) { /* divide by zero? */ - ind[IN_OVF] = 1; /* dead jim */ - return SCPE_OK; } -if (dfp.zero) return fp_zero (&dfp); /* divide into zero? */ - -for (i = 0; i < PROD_AREA_LEN; i++) /* clear prod area */ - M[PROD_AREA + i] = 0; -a100ml = ADDR_S (PROD_AREA_END, dfp.lnt); /* 100 - lnt */ -a99ml = ADDR_S (PROD_AREA_END - 1, dfp.lnt); /* 99 - lnt */ -if (fp_comp_mant (dfp.addr, sfp.addr, dfp.lnt) >= 0) { /* |Mdst| >= |Msrc|? */ - pad = a100ml; - dfp.exp = dfp.exp - sfp.exp + 1; } /* res exp = diff + 1 */ -else { pad = a99ml; - dfp.exp = dfp.exp - sfp.exp; } /* res exp = diff */ -r = xmt_divd (pad, dfp.addr); /* xmt dividend */ -if (r != SCPE_OK) return r; /* error? */ -r = div_field (a100ml, sfp.addr, &ez); /* divide fractions */ -if (r != SCPE_OK) return r; /* error? */ -if (ez) return fp_zero (&dfp); /* result zero? */ - -ind[IN_HP] = ((dfp.sign ^ sfp.sign) == 0); /* set res sign */ -ind[IN_EZ] = 0; /* not zero */ -fp_copy_mant (dfp.addr, a99ml, dfp.lnt); /* copy result */ - -return fp_pack (&dfp); -} - -/* Floating shift right */ - -t_stat fp_fsr (uint32 d, uint32 s) -{ -uint32 cnt; -uint8 t; - -if (d == s) return SCPE_OK; /* no move? */ - -cnt = 0; -M[d] = (M[d] & FLAG) | (M[s] & DIGIT); /* move 1st wo flag */ -do { MM (d); /* decr ptrs */ - MM (s); - t = M[d] = M[s] & (FLAG | DIGIT); /* copy others */ - if (cnt++ > MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while ((t & FLAG) == 0); /* until src flag */ - -cnt = 0; -do { MM (d); /* decr pointer */ - t = M[d]; /* save old val */ - M[d] = 0; /* zero field */ - if (cnt++ > MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while ((t & FLAG) == 0); /* until dst flag */ -return SCPE_OK; -} - -/* Floating shift left - note that dst is addr of high order digit */ - -t_stat fp_fsl (uint32 d, uint32 s) -{ -uint32 i, lnt; -uint8 sign; -t_stat r; - -if (d == s) return SCPE_OK; -sign = M[s] & FLAG; /* get src sign */ -r = fp_scan_mant (s, &lnt, NULL); /* get src length */ -if (r != SCPE_OK) return r; /* error? */ -s = ADDR_S (s, lnt - 1); /* hi order src */ -M[d] = M[s] & (FLAG | DIGIT); /* move 1st w flag */ -M[s] = M[s] & ~FLAG; /* clr flag from src */ -for (i = 1; i < lnt; i++) { /* move src to dst */ - PP (d); /* incr ptrs */ - PP (s); - M[d] = M[s] & DIGIT; } /* move just digit */ -PP (d); /* incr pointer */ -while ((M[d] & FLAG) == 0) { /* until flag */ - M[d] = 0; /* clear field */ - PP (d); } -if (sign) M[d] = FLAG; /* -? zero under sign */ -return SCPE_OK; -} diff --git a/I1620/i1620_lp.c b/I1620/i1620_lp.c deleted file mode 100644 index 28283f61..00000000 --- a/I1620/i1620_lp.c +++ /dev/null @@ -1,316 +0,0 @@ -/* i1620_lp.c: IBM 1443 line printer simulator - - Copyright (c) 2002-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - lpt 1443 line printer - - 25-Apr-03 RMS Revised for extended file support -*/ - -#include "i1620_defs.h" - -#define LPT_BSIZE 197 /* buffer size */ - -#define K_IMM 0x10 /* control now */ -#define K_LIN 0x20 /* spc lines */ -#define K_CH10 0x40 /* chan 10 */ -#define K_LCNT 0x03 /* line count */ -#define K_CHAN 0x0F /* channel */ - -extern uint8 M[MAXMEMSIZE]; -extern uint8 ind[NUM_IND]; -extern UNIT cpu_unit; -extern uint32 io_stop; - -uint32 cct[CCT_LNT] = { 03 }; /* car ctrl tape */ -int32 cct_lnt = 66, cct_ptr = 0; /* cct len, ptr */ -int32 lpt_bptr = 0; /* lpt buf ptr */ -char lpt_buf[LPT_BSIZE + 1]; /* lpt buf */ -int32 lpt_savctrl = 0; /* saved spc ctrl */ - -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); -t_stat lpt_attach (UNIT *uptr, char *cptr); -void lpt_buf_init (void); -t_stat lpt_num (uint32 pa, uint32 len, uint32 f1); -t_stat lpt_print (void); -t_stat lpt_space (int32 lines, int32 lflag); - -#define CHP(ch,val) ((val) & (1 << (ch))) - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list -*/ - -UNIT lpt_unit = { - UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 50) }; - -REG lpt_reg[] = { - { BRDATA (LBUF, lpt_buf, 8, 8, LPT_BSIZE + 1) }, - { DRDATA (BPTR, lpt_bptr, 8) }, - { HRDATA (PCTL, lpt_savctrl, 8) }, - { FLDATA (PRCHK, ind[IN_PRCHK], 0) }, - { FLDATA (PRCH9, ind[IN_PRCH9], 0) }, - { FLDATA (PRCH12, ind[IN_PRCH12], 0) }, - { FLDATA (PRBSY, ind[IN_PRBSY], 0) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { BRDATA (CCT, cct, 8, 32, CCT_LNT) }, - { DRDATA (CCTP, cct_ptr, 8), PV_LEFT }, - { DRDATA (CCTL, cct_lnt, 8), REG_RO + PV_LEFT }, - { NULL } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &lpt_reset, - NULL, &lpt_attach, NULL }; - -/* Data tables */ - -/* Numeric (flag plus digit) to lineprinter (ASCII) */ - -const char num_to_lpt[32] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '\'', ' ', '@', ':', ' ', 'G', - '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'W', ' ', '*', ' ', -1, 'X' }; - -/* Alphameric (digit pair) to lineprinter (ASCII) */ - -const char alp_to_lpt[256] = { - ' ', -1, '?', '.', ')', -1, -1, -1, /* 00 */ - -1, -1, -1, -1, -1, -1, -1, -1, - '+', -1, '!', '$', '*', ' ', -1, -1, /* 10 */ - -1, -1, -1, -1, -1, -1, -1, -1, - '-', '/', '\'', ',', '(', -1, -1, -1, /* 20 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, '0', '=', '@', ':', -1, -1, /* 30 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40 */ - 'H', 'I', -1, -1, -1, -1, -1, -1, - '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */ - 'Q', 'R', -1, -1, -1, -1, -1, -1, - -1, '/', 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */ - 'Y', 'Z', -1, -1, -1, -1, -1, -1, - '0', '1', '2', '3', '4', '5', '6', '7', /* 70 */ - '8', '9', -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* A0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* B0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* C0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* D0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* E0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* F0 */ - -1, -1, -1, -1, -1, -1, -1, -1 }; - -/* Line printer IO routine - - - Hard errors halt the system. - - Invalid characters print a blank, set the WRCHK and PRCHK - flags, and halt the system if IO stop is set. -*/ - -t_stat lpt (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -int8 lpc; -uint8 z, d; -t_stat r, inv = SCPE_OK; - -sim_cancel (&lpt_unit); /* "stall" until */ -ind[IN_PRBSY] = 0; /* printer free */ - -switch (op) { /* decode op */ -case OP_K: /* control */ - lpt_savctrl = (f0 << 4) | f1; /* form ctrl */ - if (lpt_savctrl & K_IMM) return lpt_print (); /* immediate? */ - break; -case OP_DN: - return lpt_num (pa, 20000 - (pa % 20000), f1); /* dump numeric */ -case OP_WN: - return lpt_num (pa, 0, f1); /* write numeric */ -case OP_WA: - for ( ; lpt_bptr < LPT_BSIZE; lpt_bptr++) { /* only fill buf */ - d = M[pa] & DIGIT; /* get digit */ - z = M[pa - 1] & DIGIT; /* get zone */ - if ((d & REC_MARK) == REC_MARK) break; /* 8-2 char? */ - lpc = alp_to_lpt[(z << 4) | d]; /* translate pair */ - if (lpc < 0) { /* bad char? */ - ind[IN_WRCHK] = ind[IN_PRCHK] = 1; /* wr chk */ - inv = STOP_INVCHR; } /* set return status */ - lpt_buf[lpt_bptr] = lpc & 0x7F; /* fill buffer */ - pa = ADDR_A (pa, 2); } /* incr mem addr */ - if ((f1 & 1) == 0) { ; /* print now? */ - r = lpt_print (); /* print line */ - if (r != SCPE_OK) return r; } - CRETIOE (io_stop, inv); -default: /* invalid function */ - return STOP_INVFNC; } -return SCPE_OK; -} - -/* Print numeric */ - -t_stat lpt_num (uint32 pa, uint32 len, uint32 f1) -{ -uint32 end; -uint8 d; -int8 lpc; -t_stat r, inv = SCPE_OK; - -end = pa + len; -for ( ; lpt_bptr < LPT_BSIZE; lpt_bptr++) { /* only fill buf */ - d = M[pa]; /* get digit */ - if (len? (pa >= end): /* end reached? */ - ((d & REC_MARK) == REC_MARK)) break; - lpc = num_to_lpt[d]; /* translate */ - if (lpc < 0) { /* bad char? */ - ind[IN_WRCHK] = ind[IN_PRCHK] = 1; /* wr chk */ - inv = STOP_INVCHR; } /* set return status */ - lpt_buf[lpt_bptr++] = lpc & 0x7F; /* fill buffer */ - PP (pa); } /* incr mem addr */ -if ((f1 & 1) == 0) { /* print now? */ - r = lpt_print (); /* print line */ - if (r != SCPE_OK) return r; } -CRETIOE (io_stop, inv); -} - -/* Print and space */ - -t_stat lpt_print (void) -{ -int32 i, chan, ctrl = lpt_savctrl; - -if ((lpt_unit.flags & UNIT_ATT) == 0) { /* not attached? */ - ind[IN_PRCHK] = ind[IN_WRCHK] = 1; /* wr, pri check */ - return SCPE_UNATT; } - -ind[IN_PRBSY] = 1; /* print busy */ -sim_activate (&lpt_unit, lpt_unit.time); /* start timer */ - -for (i = LPT_WIDTH; i <= LPT_BSIZE; i++) /* clear unprintable */ - lpt_buf[i] = ' '; -while ((lpt_bptr > 0) && (lpt_buf[lpt_bptr - 1] == ' ')) - lpt_buf[--lpt_bptr] = 0; /* trim buffer */ -if (lpt_bptr) { /* any line? */ - fputs (lpt_buf, lpt_unit.fileref); /* print */ - lpt_unit.pos = ftell (lpt_unit.fileref); /* update pos */ - lpt_buf_init (); /* reinit buf */ - if (ferror (lpt_unit.fileref)) { /* error? */ - ind[IN_PRCHK] = ind[IN_WRCHK] = 1; /* wr, pri check */ - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } } - -lpt_savctrl = 0x61; /* reset ctrl */ -if ((ctrl & K_LIN) == ((ctrl & K_IMM)? 0: K_LIN)) /* space lines? */ - return lpt_space (ctrl & K_LCNT, FALSE); -chan = lpt_savctrl & K_CHAN; /* basic chan */ -if (lpt_savctrl & K_CH10) { /* chan 10-12? */ - if (chan == 0) chan = 10; - else if (chan == 3) chan = 11; - else if (chan == 4) chan = 12; - else chan = 0; } -if ((chan == 0) || (chan > 12)) return STOP_INVFNC; -for (i = 1; i < cct_lnt + 1; i++) { /* sweep thru cct */ - if (CHP (chan, cct[(cct_ptr + i) % cct_lnt])) - return lpt_space (i, TRUE); } -return STOP_CCT; /* runaway channel */ -} - -/* Space routine - space or skip n lines - - Inputs: - count = number of lines to space or skip - sflag = skip (TRUE) or space (FALSE) -*/ - -t_stat lpt_space (int32 count, int32 sflag) -{ -int32 i; - -cct_ptr = (cct_ptr + count) % cct_lnt; /* adv cct, mod lnt */ -if (sflag && CHP (0, cct[cct_ptr])) /* skip, top of form? */ - fputs ("\n\f", lpt_unit.fileref); /* nl, ff */ -else { for (i = 0; i < count; i++) /* count lines */ - fputc ('\n', lpt_unit.fileref); } -lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */ -ind[IN_PRCH9] = CHP (9, cct[cct_ptr]) != 0; /* set indicators */ -ind[IN_PRCH12] = CHP (12, cct[cct_ptr]) != 0; -if (ferror (lpt_unit.fileref)) { /* error? */ - ind[IN_PRCHK] = ind[IN_WRCHK] = 1; /* wr, pri check */ - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } -return SCPE_OK; -} - -/* Unit service - clear printer busy */ - -t_stat lpt_svc (UNIT *uptr) -{ -ind[IN_PRBSY] = 0; -return SCPE_OK; -} - -/* Initialize lpt buffer */ - -void lpt_buf_init (void) -{ -int32 i; - -lpt_bptr = 0; -for (i = 0; i < LPT_WIDTH + 1; i++) lpt_buf[i] = 0; -return; -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ -lpt_buf_init (); /* clear buffer */ -cct_ptr = 0; /* clear cct ptr */ -lpt_savctrl = 0x61; /* clear cct action */ -ind[IN_PRCHK] = ind[IN_PRBSY] = 0; /* clear indicators */ -ind[IN_PRCH9] = ind[IN_PRCH12] = 0; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat lpt_attach (UNIT *uptr, char *cptr) -{ -lpt_reset (&lpt_dev); -return attach_unit (uptr, cptr); -} diff --git a/I1620/i1620_pt.c b/I1620/i1620_pt.c deleted file mode 100644 index 2f213077..00000000 --- a/I1620/i1620_pt.c +++ /dev/null @@ -1,436 +0,0 @@ -/* i1620_pt.c: IBM 1621/1624 paper tape reader/punch simulator - - Copyright (c) 2002-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - ptr 1621 paper tape reader - ptp 1624 paper tape punch - - 25-Apr-03 RMS Revised for extended file support -*/ - -#include "i1620_defs.h" - -#define PT_EL 0x80 /* end record */ -#define PT_X 0x40 /* X */ -#define PT_O 0x20 /* O */ -#define PT_C 0x10 /* C */ -#define PT_FD 0x7F /* deleted */ - -extern uint8 M[MAXMEMSIZE]; -extern uint8 ind[NUM_IND]; -extern UNIT cpu_unit; -extern uint32 io_stop; - -t_stat ptr_reset (DEVICE *dptr); -t_stat ptr_boot (int32 unitno, DEVICE *dptr); -t_stat ptr_read (uint8 *c, t_bool ignfeed); -t_stat ptp_reset (DEVICE *dptr); -t_stat ptp_write (uint32 c); -t_stat ptp_num (uint32 pa, uint32 len); - -/* PTR data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit descriptor - ptr_reg PTR register list -*/ - -UNIT ptr_unit = { - UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) }; - -REG ptr_reg[] = { - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, - { NULL } }; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - &ptr_boot, NULL, NULL }; - -/* PTP data structures - - ptp_dev PTP device descriptor - ptp_unit PTP unit descriptor - ptp_reg PTP register list -*/ - -UNIT ptp_unit = { - UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }; - -REG ptp_reg[] = { - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, - { NULL } }; - -DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptp_reset, - NULL, NULL, NULL }; - -/* Data tables */ - -/* Paper tape reader odd parity chart: 1 = bad, 0 = ok */ - -const int8 bad_par[128] = { - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 00 */ - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 10 */ - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 20 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 30 */ - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 40 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 50 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 60 */ - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; /* 70 */ - -/* Paper tape read (7b) to numeric (one digit) */ - -const int8 ptr_to_num[128] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* - */ - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* C */ - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* O */ - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* OC */ - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* X */ - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x10, 0x1E, 0x1F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* XC */ - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x10, 0x1E, 0x1F, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* XO */ - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* XOC */ - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F }; - -/* Paper tape read (7b) to alphameric (two digits) - Codes XO82, 82, XO842, 842 do not have consistent translations -*/ - -const int8 ptr_to_alp[128] = { - 0x00, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* - */ - 0x78, 0x79, -1, 0x33, 0x34, 0x70, -1, 0x0F, - 0x00, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* C */ - 0x78, 0x79, -1, 0x33, 0x34, 0x70, -1, 0x0F, - 0x70, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* O */ - 0x68, 0x69, 0x0A, 0x23, 0x24, 0x60, 0x0E, 0x0F, - 0x70, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* OC */ - 0x68, 0x69, 0x0A, 0x23, 0x24, 0x60, 0x0E, 0x0F, - 0x20, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* X */ - 0x58, 0x59, 0x5A, 0x13, 0x14, 0x50, 0x5E, 0x5F, - 0x20, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* XC */ - 0x58, 0x59, 0x5A, 0x13, 0x14, 0x50, 0x5E, 0x5F, - 0x10, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* XO */ - 0x48, 0x49, -1, 0x03, 0x04, 0x40, -1, 0x7F, - 0x10, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* XOC */ - 0x48, 0x49, -1, 0x03, 0x04, 0x40, -1, 0x7F }; - -/* Numeric (flag + digit) to paper tape punch */ - -const int8 num_to_ptp[32] = { - 0x20, 0x01, 0x02, 0x13, 0x04, 0x15, 0x16, 0x07, /* 0 */ - 0x08, 0x19, 0x2A, 0x3B, 0x1C, 0x0D, 0x3E, 0x3F, - 0x40, 0x51, 0x52, 0x43, 0x54, 0x45, 0x46, 0x57, /* F + 0 */ - 0x58, 0x49, 0x4A, 0x5B, 0x4C, 0x5D, 0x5E, 0x4F }; - -/* Alphameric (two digits) to paper tape punch */ - -const int8 alp_to_ptp[256] = { - 0x10, -1, 0x7A, 0x6B, 0x7C, -1, -1, 0x7F, /* 00 */ - -1, -1, 0x2A, -1, -1, -1, -1, 0x1F, - 0x70, -1, 0x4A, 0x5B, 0x4C, -1, -1, -1, /* 10 */ - -1, -1, -1, -1, -1, -1, -1, -1, - 0x40, 0x31, 0x2A, 0x3B, 0x2C, -1, -1, -1, /* 20 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 0x1A, 0x0B, 0x1C, 0x0D, 0x0E, -1, /* 30 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 0x61, 0x62, 0x73, 0x64, 0x75, 0x76, 0x67, /* 40 */ - 0x68, 0x79, -1, -1, -1, -1, -1, -1, - 0x40, 0x51, 0x52, 0x43, 0x54, 0x45, 0x46, 0x57, /* 50 */ - 0x58, 0x49, 0x4A, -1, -1, -1, -1, 0x4F, - -1, 0x31, 0x32, 0x23, 0x34, 0x25, 0x26, 0x37, /* 60 */ - 0x38, 0x29, -1, -1, -1, -1, -1, -1, - 0x20, 0x01, 0x02, 0x13, 0x04, 0x15, 0x16, 0x07, /* 70 */ - 0x08, 0x19, 0x7A, -1, -1, -1, -1, 0x7F, - -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* A0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* B0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* C0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* D0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* E0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* F0 */ - -1, -1, -1, -1, -1, -1, -1, -1 }; - -/* Paper tape reader IO routine - - - Hard errors halt the operation and the system. - - Parity errors place an invalid character in memory and set - RDCHK, but the read continues until end of record. If IO - stop is set, the system then halts. -*/ - -t_stat ptr (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -uint32 i; -int8 mc; -uint8 ptc; -t_stat r, inv = SCPE_OK; - -switch (op) { /* case on op */ -case OP_RN: /* read numeric */ - for (i = 0; i < MEMSIZE; i++) { /* (stop runaway) */ - r = ptr_read (&ptc, TRUE); /* read frame */ - if (r != SCPE_OK) return r; /* error? */ - if (ptc & PT_EL) { /* end record? */ - M[pa] = REC_MARK; /* store rec mark */ - CRETIOE (io_stop, inv); } /* done */ - if (bad_par[ptc]) { /* bad parity? */ - ind[IN_RDCHK] = 1; /* set read check */ - inv = STOP_INVCHR; /* set return status */ - M[pa] = 0; } /* store zero */ - else M[pa] = ptr_to_num[ptc]; /* translate, store */ - PP (pa); } /* incr mem addr */ - break; -case OP_RA: /* read alphameric */ - for (i = 0; i < MEMSIZE; i = i + 2) { /* (stop runaway) */ - r = ptr_read (&ptc, TRUE); /* read frame */ - if (r != SCPE_OK) return r; /* error? */ - if (ptc & PT_EL) { /* end record? */ - M[pa] = REC_MARK; /* store rec mark */ - M[pa - 1] = 0; - CRETIOE (io_stop, inv); } /* done */ - mc = ptr_to_alp[ptc]; /* translate */ - if (bad_par[ptc] || (mc < 0)) { /* bad par or char? */ - ind[IN_RDCHK] = 1; /* set read check */ - inv = STOP_INVCHR; /* set return status */ - mc = 0; } /* store blank */ - M[pa] = (M[pa] & FLAG) | (mc & DIGIT); /* store 2 digits */ - M[pa - 1] = (M[pa - 1] & FLAG) | ((mc >> 4) & DIGIT); - pa = ADDR_A (pa, 2); } /* incr mem addr */ - break; -default: /* invalid function */ - return STOP_INVFNC; } -return STOP_RWRAP; -} - -/* Binary paper tape reader IO routine - see above for error handling */ - -t_stat btr (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -uint32 i; -uint8 ptc; -t_stat r, inv = SCPE_OK; - -if ((cpu_unit.flags & IF_BIN) == 0) return STOP_INVIO; -switch (op) { /* case on op */ -case OP_RA: /* read alphameric */ - for (i = 0; i < MEMSIZE; i = i + 2) { /* (stop runaway) */ - r = ptr_read (&ptc, FALSE); /* read frame */ - if (r != SCPE_OK) return r; /* error? */ - if (ptc & PT_EL) { /* end record? */ - M[pa] = REC_MARK; /* store rec mark */ - M[pa - 1] = 0; - CRETIOE (io_stop, inv); } /* done */ - if (bad_par[ptc]) { /* bad parity? */ - ind[IN_RDCHK] = 1; /* set read check */ - inv = STOP_INVCHR; } /* set return status */ - M[pa] = (M[pa] & FLAG) | (ptc & 07); /* store 2 digits */ - M[pa - 1] = (M[pa - 1] & FLAG) | - (((ptc >> 5) & 06) | ((ptc >> 3) & 1)); - pa = ADDR_A (pa, 2); } /* incr mem addr */ - break; -default: /* invalid function */ - return STOP_INVFNC; } -return STOP_RWRAP; -} - -/* Read ptr frame - all errors are 'hard' errors and halt the system */ - -t_stat ptr_read (uint8 *c, t_bool ignfeed) -{ -int32 temp; - -if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */ - ind[IN_RDCHK] = 1; /* no, error */ - return SCPE_UNATT; } - -do { if ((temp = getc (ptr_unit.fileref)) == EOF) { /* read char */ - ind[IN_RDCHK] = 1; /* err, rd chk */ - if (feof (ptr_unit.fileref)) - printf ("PTR end of file\n"); - else perror ("PTR I/O error"); - clearerr (ptr_unit.fileref); - return SCPE_IOERR; } - *c = temp & 0377; /* save char */ - ptr_unit.pos = ptr_unit.pos + 1; } /* incr file addr */ -while (ignfeed && (*c == PT_FD)); /* until not feed */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptr_reset (DEVICE *dptr) -{ -return SCPE_OK; -} - -/* Bootstrap routine */ - -const static uint8 boot_rom[] = { - 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* NOP */ - 3, 6, 0, 0, 0, 3, 1, 0, 0, 3, 0, 0, /* RNPT 31 */ - 2, 5, 0, 0, 0, 7, 1, 0, 0, 0, 0, 0, /* TD 71,loc */ - 3, 6, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, /* RNPT loc1 */ - 2, 6, 0, 0, 0, 6, 6, 0, 0, 0, 3, 5, /* TF 66,35 */ - 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* TDM loc2,loc3 */ - 4, 9, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0 }; /* BR 12 */ - -#define BOOT_START 0 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8)) - -t_stat ptr_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} - -/* Paper tape punch IO routine - - - Hard errors halt the operation and the system. - - Parity errors stop the operation and set WRCHK. - If IO stop is set, the system then halts. -*/ - -t_stat ptp (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -uint32 i; -int8 ptc; -uint8 z, d; -t_stat r; - -switch (op) { /* decode op */ -case OP_DN: - return ptp_num (pa, 20000 - (pa % 20000)); /* dump numeric */ -case OP_WN: - return ptp_num (pa, 0); /* punch numeric */ -case OP_WA: - for (i = 0; i < MEMSIZE; i = i + 2) { /* stop runaway */ - d = M[pa] & DIGIT; /* get digit */ - z = M[pa - 1] & DIGIT; /* get zone */ - if ((d & REC_MARK) == REC_MARK) /* 8-2 char? */ - return ptp_write (PT_EL); /* end record */ - ptc = alp_to_ptp[(z << 4) | d]; /* translate pair */ - if (ptc < 0) { /* bad char? */ - ind[IN_WRCHK] = 1; /* write check */ - CRETIOE (io_stop, STOP_INVCHR); } - r = ptp_write (ptc); /* write char */ - if (r != SCPE_OK) return r; /* error? */ - pa = ADDR_A (pa, 2); } /* incr mem addr */ - break; -default: /* invalid function */ - return STOP_INVFNC; } -return STOP_RWRAP; -} - -/* Binary paper tape punch IO routine - see above for error handling */ - -t_stat btp (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -uint32 i; -uint8 ptc, z, d; -t_stat r; - -if ((cpu_unit.flags & IF_BIN) == 0) return STOP_INVIO; -switch (op) { /* decode op */ -case OP_WA: - for (i = 0; i < MEMSIZE; i = i + 2) { /* stop runaway */ - d = M[pa] & DIGIT; /* get digit */ - z = M[pa - 1] & DIGIT; /* get zone */ - if ((d & REC_MARK) == REC_MARK) /* 8-2 char? */ - return ptp_write (PT_EL); /* end record */ - ptc = ((z & 06) << 5) | ((z & 01) << 3) | (d & 07); - if (bad_par[ptc]) ptc = ptc | PT_C; /* set parity */ - r = ptp_write (ptc); /* write char */ - if (r != SCPE_OK) return r; /* error? */ - pa = ADDR_A (pa, 2); } /* incr mem addr */ - break; -default: /* invalid function */ - return STOP_INVFNC; } -return STOP_RWRAP; -} - -/* Punch tape numeric - cannot generate parity errors */ - -t_stat ptp_num (uint32 pa, uint32 len) -{ -t_stat r; -uint8 d; -uint32 i, end; - -end = pa + len; -for (i = 0; i < MEMSIZE; i++) { /* stop runaway */ - d = M[pa] & (FLAG | DIGIT); /* get char */ - if (len? (pa >= end): /* dump: end reached? */ - ((d & REC_MARK) == REC_MARK)) /* write: rec mark? */ - return ptp_write (PT_EL); /* end record */ - r = ptp_write (num_to_ptp[d]); /* write */ - if (r != SCPE_OK) return r; /* error? */ - PP (pa); } /* incr mem addr */ -return STOP_RWRAP; -} - -/* Write ptp frame - all errors are hard errors */ - -t_stat ptp_write (uint32 c) -{ -if ((ptp_unit.flags & UNIT_ATT) == 0) { /* attached? */ - ind[IN_WRCHK] = 1; /* no, error */ - return SCPE_UNATT; } - -if (putc (c, ptp_unit.fileref) == EOF) { /* write char */ - ind[IN_WRCHK] = 1; /* error? */ - perror ("PTP I/O error"); - clearerr (ptp_unit.fileref); - return SCPE_IOERR; } -ptp_unit.pos = ptp_unit.pos + 1; /* count char */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptp_reset (DEVICE *dptr) -{ -return SCPE_OK; -} diff --git a/I1620/i1620_sys.c b/I1620/i1620_sys.c deleted file mode 100644 index 43951d1d..00000000 --- a/I1620/i1620_sys.c +++ /dev/null @@ -1,491 +0,0 @@ -/* i1620_sys.c: IBM 1620 simulator interface - - Copyright (c) 2002-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. -*/ - -#include "i1620_defs.h" -#include - -#define LINE_LNT 50 - -extern DEVICE cpu_dev, tty_dev; -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE lpt_dev; -extern DEVICE cdr_dev, cdp_dev; -extern DEVICE dp_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern uint8 M[MAXMEMSIZE]; -extern char cdr_to_alp[128], alp_to_cdp[256]; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax maximum number of words for examine/deposit - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "IBM 1620"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = LINE_LNT; - -DEVICE *sim_devices[] = { - &cpu_dev, - &tty_dev, - &ptr_dev, - &ptp_dev, - &cdr_dev, - &cdp_dev, - &lpt_dev, - &dp_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "HALT instruction", - "Breakpoint", - "Invalid instruction", - "Invalid digit", - "Invalid character", - "Invalid indicator", - "Invalid digit in P address", - "Invalid P address", - "P address exceeds indirect address limit", - "Invalid digit in Q address", - "Invalid Q address", - "Q address exceeds indirect address limit", - "Invalid IO device", - "Invalid return register", - "Invalid IO function", - "Instruction address must be even", - "Invalid select code", - "Index instruction with no band selected", - "P address must be odd", - "DCF address must be even", - "Invalid disk drive", - "Invalid disk sector address", - "Invalid disk sector count", - "Invalid disk buffer address", - "Disk address compare error", - "Disk write check error", - "Disk cylinder overflow error", - "Disk wrong length record error", - "Invalid CCT", - "Field exceeds memory", - "Record exceeds memory", - "No card in reader", - "Overflow check", - "Exponent check", - "Write address function disabled", - "Floating point mantissa too long", - "Floating point mantissa lengths unequal", - "Floating point exponent flag missing", - "Floating point divide by zero" }; - -/* Binary loader -- load carriage control tape - - A carriage control tape consists of entries of the form - - (repeat count) column number,column number,column number,... - - The CCT entries are stored in cct[0:lnt-1], cctlnt contains the - number of entries -*/ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 col, rpt, ptr, mask, cctbuf[CCT_LNT]; -t_stat r; -extern int32 cct_lnt, cct_ptr, cct[CCT_LNT]; -char cbuf[CBUFSIZE], gbuf[CBUFSIZE]; - -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; -ptr = 0; -for ( ; (cptr = fgets (cbuf, CBUFSIZE, fileref)) != NULL; ) { /* until eof */ - mask = 0; - if (*cptr == '(') { /* repeat count? */ - cptr = get_glyph (cptr + 1, gbuf, ')'); /* get 1st field */ - rpt = get_uint (gbuf, 10, CCT_LNT, &r); /* repeat count */ - if (r != SCPE_OK) return SCPE_FMT; } - else rpt = 1; - while (*cptr != 0) { /* get col no's */ - cptr = get_glyph (cptr, gbuf, ','); /* get next field */ - col = get_uint (gbuf, 10, 12, &r); /* column number */ - if (r != SCPE_OK) return SCPE_FMT; - mask = mask | (1 << col); } /* set bit */ - for ( ; rpt > 0; rpt--) { /* store vals */ - if (ptr >= CCT_LNT) return SCPE_FMT; - cctbuf[ptr++] = mask; } } -if (ptr == 0) return SCPE_FMT; -cct_lnt = ptr; -cct_ptr = 0; -for (rpt = 0; rpt < cct_lnt; rpt++) cct[rpt] = cctbuf[rpt]; -return SCPE_OK; -} - -/* Symbol table */ - -struct opc { - char *str; /* mnemonic */ - uint32 opv; /* opcode & flags */ - uint32 qv; /* q field */ -}; - -#define I_V_FL 16 /* flags */ -#define I_M_QX 0x01 /* Q indexable */ -#define I_M_QM 0x02 /* Q immediate */ -#define I_M_QNP 0x00 /* Q no print */ -#define I_M_QCP 0x04 /* Q cond print */ -#define I_M_QP 0x08 /* Q print */ -#define I_M_PCP 0x00 /* P cond print */ -#define I_M_PP 0x10 /* P print */ -#define I_GETQF(x) (((x) >> I_V_FL) & 0x03) -#define I_GETQP(x) (((x) >> I_V_FL) & 0x0C) -#define I_GETPP(x) (((x) >> I_V_FL) & 0x10) - -#define I_2 ((I_M_PP | I_M_QP | I_M_QX) << I_V_FL) -#define I_2M ((I_M_PP | I_M_QP | I_M_QM) << I_V_FL) -#define I_2X ((I_M_PP | I_M_QP | I_M_QX | I_M_QM) << I_V_FL) -#define I_2S ((I_M_PP | I_M_QP) << I_V_FL) -#define I_1 ((I_M_PP | I_M_QCP) << I_V_FL) -#define I_1E ((I_M_PP | I_M_QNP) << I_V_FL) -#define I_0 ((I_M_PCP | I_M_QCP) << I_V_FL) -#define I_0E ((I_M_PCP | I_M_QNP) << I_V_FL) - -struct opc opcode[] = { - { "RNTY", 36+I_1E, 100 }, { "RATY", 37+I_1E, 100 }, - { "WNTY", 38+I_1E, 100 }, { "WATY", 39+I_1E, 100 }, - { "DNTY", 35+I_1E, 100 }, { "SPTY", 34+I_0E, 101 }, - { "RCTY", 34+I_0E, 102 }, { "BKTY", 34+I_0E, 103 }, - { "IXTY", 34+I_0E, 104 }, { "TBTY", 34+I_0E, 108 }, - { "RNPT", 36+I_1E, 300 }, { "RAPT", 37+I_1E, 300 }, - { "WNPT", 38+I_1E, 200 }, { "WAPT", 39+I_1E, 200 }, - { "DNPT", 35+I_1E, 200 }, - { "RNCD", 36+I_1E, 500 }, { "RACD", 37+I_1E, 500 }, - { "WNCD", 38+I_1E, 400 }, { "WACD", 39+I_1E, 400 }, - { "DNCD", 35+I_1E, 400 }, - { "PRN", 38+I_1E, 900 }, { "PRNS", 38+I_1E, 901 }, - { "PRA", 39+I_1E, 900 }, { "PRAS", 39+I_1E, 901 }, - { "PRD", 35+I_1E, 900 }, { "PRDS", 35+I_1E, 901 }, - { "SK", 34+I_1E, 701 }, - { "RDGN", 36+I_1E, 700 }, { "CDGN", 36+I_1E, 701 }, - { "RDN", 36+I_1E, 702 }, { "CDN", 36+I_1E, 703 }, - { "RTGN", 36+I_1E, 704 }, { "CTGN", 36+I_1E, 705 }, - { "RTN", 36+I_1E, 706 }, { "CTN", 36+I_1E, 707 }, - { "WDGN", 38+I_1E, 700 }, { "WDN", 38+I_1E, 702 }, - { "WTGN", 38+I_1E, 704 }, { "WTN", 38+I_1E, 706 }, - { "RBPT", 37+I_1E, 3300 }, { "WBPT", 39+I_1E, 3200 }, - { "BC1", 46+I_1E, 100 }, { "BNC1", 47+I_1E, 100 }, - { "BC2", 46+I_1E, 200 }, { "BNC2", 47+I_1E, 200 }, - { "BC3", 46+I_1E, 300 }, { "BNC3", 47+I_1E, 300 }, - { "BC4", 46+I_1E, 400 }, { "BNC4", 47+I_1E, 400 }, - { "BLC", 46+I_1E, 900 }, { "BNLC", 47+I_1E, 900 }, - { "BH", 46+I_1E, 1100 }, { "BNH", 47+I_1E, 1100 }, - { "BP", 46+I_1E, 1100 }, { "BNP", 47+I_1E, 1100 }, - { "BE", 46+I_1E, 1200 }, { "BNE", 47+I_1E, 1200 }, - { "BZ", 46+I_1E, 1200 }, { "BNZ", 47+I_1E, 1200 }, - { "BNL", 46+I_1E, 1300 }, { "BL", 47+I_1E, 1300 }, - { "BNN", 46+I_1E, 1300 }, { "BN", 47+I_1E, 1300 }, - { "BV", 46+I_1E, 1400 }, { "BNV", 47+I_1E, 1400 }, - { "BXV", 46+I_1E, 1500 }, { "BNXV", 47+I_1E, 1500 }, - { "BA", 46+I_1E, 1900 }, { "BNA", 47+I_1E, 1900 }, - { "BNBS", 46+I_1E, 3000 }, { "BEBS", 47+I_1E, 3000 }, - { "BBAS", 46+I_1E, 3100 }, { "BANS", 47+I_1E, 3100 }, - { "BBBS", 46+I_1E, 3200 }, { "BBNS", 47+I_1E, 3200 }, - { "BCH9", 46+I_1E, 3300 }, - { "BCOV", 46+I_1E, 3400 }, - { "BSNX", 60+I_1E, 0 }, { "BSBA", 60+I_1E, 1 }, - { "BSBB", 60+I_1E, 2 }, - { "BSNI", 60+I_1E, 8 }, { "BSIA", 60+I_1E, 9 }, - - { "FADD", 1+I_2, 0 }, { "FSUB", 2+I_2, 0 }, - { "FMUL", 3+I_2, 0 }, { "FSL", 5+I_2, 0 }, - { "TFL", 6+I_2, 0 }, { "BTFL", 7+I_2, 0 }, - { "FSR", 8+I_2, 0 }, { "FDIV", 9+I_2, 0 }, - { "BTAM", 10+I_2M, 0 }, { "AM", 11+I_2M, 0 }, - { "SM", 12+I_2M, 0 }, { "MM", 13+I_2M, 0 }, - { "CM", 14+I_2M, 0 }, { "TDM", 15+I_2S, 0 }, - { "TFM", 16+I_2M, 0 }, { "BTM", 17+I_2M, 0 }, - { "LDM", 18+I_2M, 0 }, { "DM", 19+I_2M, 0 }, - { "BTA", 20+I_2, 0 }, { "A", 21+I_2, 0 }, - { "S", 22+I_2, 0 }, { "M", 23+I_2, 0 }, - { "C", 24+I_2, 0 }, { "TD", 25+I_2, 0 }, - { "TF", 26+I_2, 0 }, { "BT", 27+I_2, 0 }, - { "LD", 28+I_2, 0 }, { "D", 29+I_2, 0 }, - { "TRNM", 30+I_2, 0 }, { "TR", 31+I_2, 0 }, - { "SF", 32+I_1, 0 }, { "CF", 33+I_1, 0 }, - { "K", 34+I_2S, 0 }, { "DN", 35+I_2S, 0 }, - { "RN", 36+I_2S, 0 }, { "RA", 37+I_2S, 0 }, - { "WN", 38+I_2S, 0 }, { "WA", 39+I_2S, 0 }, - { "NOP", 41+I_0, 0 }, { "BB", 42+I_0, 0 }, - { "BD", 43+I_2, 0 }, { "BNF", 44+I_2, 0 }, - { "BNR", 45+I_2, 0 }, { "BI", 46+I_2S, 0 }, - { "BNI", 47+I_2S, 0 }, { "H", 48+I_0, 0 }, - { "B", 49+I_1, 0 }, { "BNG", 55+I_2, 0 }, - { "BS", 60+I_2S, 0 }, { "BX", 61+I_2, 0 }, - { "BXM", 62+I_2X, 0 }, { "BCX", 63+I_2, 0 }, - { "BCXM", 64+I_2X, 0 }, { "BLX", 65+I_2, 0 }, - { "BLXM", 66+I_2X, 0 }, { "BSX", 67+I_2, 0 }, - { "MA", 70+I_2, 0 }, { "MF", 71+I_2, 0 }, - { "TNS", 72+I_2, 0 }, { "TNF", 73+I_2, 0 }, - { "BBT", 90+I_2, 0 }, { "BMK", 91+I_2, 0 }, - { "ORF", 92+I_2, 0 }, { "ANDF", 93+I_2, 0 }, - { "CPFL", 94+I_2, 0 }, { "EORF", 95+I_2, 0 }, - { "OTD", 96+I_2, 0 }, { "DTO", 97+I_2, 0 }, - { NULL, 0, 0 } }; - -/* Print an address from five characters */ - -void fprint_addr (FILE *of, int32 spc, t_value *dig, t_bool flg) -{ -int32 i, idx; - -fputc (spc, of); /* spacer */ -if (dig[ADDR_LEN - 1] & FLAG) { /* signed? */ - fputc ('-', of); /* print minus */ - dig[ADDR_LEN - 1] = dig[ADDR_LEN - 1] & ~FLAG; } -for (i = 0; i < ADDR_LEN; i++) /* print digits */ - fprintf (of, "%X", dig[i] & DIGIT); -if ((cpu_unit.flags & IF_IDX) && flg) { /* indexing? */ - for (i = idx = 0; i < ADDR_LEN - 2; i++) { /* get index reg */ - if (dig[ADDR_LEN - 2 - i] & FLAG) - idx = idx | (1 << i); - dig[ADDR_LEN - 2 - i] = dig[ADDR_LEN - 2 - i] & ~FLAG; } - if (idx) fprintf (of, "(%d)", idx); } /* print */ -return; -} - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current address - *val = values to decode - *uptr = pointer to unit - sw = switches - Outputs: - return = if >= 0, error code - if < 0, number of extra words retired -*/ - -#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 pmp, qmp, i, c, d, any; -uint32 op, qv, opfl; - -if (uptr == NULL) uptr = &cpu_unit; -if (sw & SWMASK ('C')) { /* character? */ - if (uptr->flags & UNIT_BCD) { - if (addr & 1) return SCPE_ARG; /* must be even */ - c = ((val[0] & DIGIT) << 4) | (val[1] & DIGIT); - if (alp_to_cdp[c] > 0) - fprintf (of, "%c", alp_to_cdp[c]); - else fprintf (of, "<%02x>", c); - return -1; } - else fprintf (of, FMTASC (val[0] & 0177)); - return SCPE_OK; } -if ((uptr->flags & UNIT_BCD) == 0) return SCPE_ARG; /* CPU or disk? */ -if (sw & SWMASK ('D')) { /* dump? */ - for (i = d = 0; i < LINE_LNT; i++) d = d | val[i]; - if (d & FLAG) { /* any flags? */ - for (i = 0; i < LINE_LNT; i++) /* print flags */ - fprintf (of, (val[i] & FLAG)? "_": " "); - fprintf (of, "\n\t"); } - for (i = 0; i < LINE_LNT; i++) /* print digits */ - fprintf (of, "%X", val[i] & DIGIT) ; - return -(i - 1); } -if (sw & SWMASK ('S')) { /* string? */ - if (addr & 1) return SCPE_ARG; /* must be even */ - for (i = 0; i < LINE_LNT; i = i + 2) { - c = ((val[i] & DIGIT) << 4) | (val[i + 1] & DIGIT); - if (alp_to_cdp[c] < 0) break; - fprintf (of, "%c", alp_to_cdp[c]); } - if (i == 0) { - fprintf (of, "<%02X>", c); - return -1; } - return -(i - 1); } -if ((sw & SWMASK ('M')) == 0) return SCPE_ARG; - -if (addr & 1) return SCPE_ARG; /* must be even */ -op = ((val[0] & DIGIT) * 10) + (val[1] & DIGIT); /* get opcode */ -for (i = qv = pmp = qmp = 0; i < ADDR_LEN; i++) { /* test addr */ - if (val[I_P + i]) pmp = 1; - if (val[I_Q + i]) qmp = 1; - qv = (qv * 10) + (val[I_Q + i] & DIGIT); } -if ((val[0] | val[1]) & FLAG) pmp = qmp = 1; /* flags force */ -for (i = 0; opcode[i].str != NULL; i++) { /* find opcode */ - opfl = opcode[i].opv & 0xFF0000; - if ((op == (opcode[i].opv & 0xFF)) && - ((qv == opcode[i].qv) || - ((opfl != I_1E) && (opfl != I_0E)))) break; } -if (opcode[i].str == NULL) return SCPE_ARG; -if (I_GETQP (opfl) == I_M_QNP) qmp = 0; /* Q no print? */ - -fprintf (of, opcode[i].str); /* print opcode */ -if (I_GETPP (opfl) == I_M_PP) /* P required? */ - fprint_addr (of, ' ', &val[I_P], I_M_QX); -else if ((I_GETPP (opfl) == I_M_PCP) && (pmp || qmp)) /* P opt & needed? */ - fprint_addr (of, ' ', &val[I_P], 0); -if (I_GETQP (opfl) == I_M_QP) { /* Q required? */ - fprint_addr (of, ',', &val[I_Q], I_GETQF (opfl)); - if (I_GETQF (opfl) & I_M_QM) /* immediate? */ - val[I_Q] = val[I_Q] & ~FLAG; } /* clr hi Q flag */ -else if ((I_GETQP (opfl) == I_M_QCP) && (pmp || qmp)) /* Q opt & needed? */ - fprint_addr (of, ',', &val[I_Q], 0); -for (i = any = 0; i < INST_LEN; i++) { /* print rem flags */ - if (val[i] & FLAG) { - if (!any) fputc (',', of); - any = 1; - fprintf (of, "%d", i); } } -return -(INST_LEN - 1); -} - -/* parse_addr - get sign + address + index */ - -t_stat parse_addr (char *cptr, t_value *val, int32 flg) -{ -int32 i, sign = 0, addr, index; -static int32 idx_tst[ADDR_LEN] = { 0, 4, 2, 1, 0 }; -char *tptr; - -if (*cptr == '+') cptr++; /* +? skip */ -else if (*cptr == '-') { /* -? skip, flag */ - sign = 1; - cptr++; } -errno = 0; /* get address */ -addr = strtoul (cptr, &tptr, 16); -if (errno || (cptr == tptr) || (addr > 0xFFFFF)) /* err or too big? */ - return SCPE_ARG; -if ((cpu_unit.flags & IF_IDX) && (flg & I_M_QX) && /* index allowed? */ - (*tptr == '(')) { /* index specified */ - errno = 0; - index = strtoul (cptr = tptr + 1, &tptr, 10); /* get index */ - if (errno || (cptr == tptr) || (index > 7)) /* err or too big? */ - return SCPE_ARG; - if (*tptr++ != ')') return SCPE_ARG; } -else index = 0; -if (*tptr != 0) return SCPE_ARG; /* all done? */ -for (i = ADDR_LEN - 1; i >= 0; i--) { /* cvt addr to dig */ - val[i] = (addr & 0xF) | ((index & idx_tst[i])? FLAG: 0); - addr = addr >> 4; } -if (sign) val[ADDR_LEN - 1] = val[ADDR_LEN - 1] | FLAG; /* set sign */ -if (flg & I_M_QM) val[0] = val[0] | FLAG; /* set immediate */ -return SCPE_OK; -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = > 0 error code - <= 0 -number of extra words -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 i, qv, opfl, last; -char t, la, *fptr, gbuf[CBUFSIZE]; - -while (isspace (*cptr)) cptr++; /* absorb spaces */ -if ((sw & SWMASK ('C')) || ((*cptr == '\'') && cptr++)) { /* character? */ - if ((t = *cptr & 0x7F) == 0) return SCPE_ARG; /* get char */ - if (uptr->flags & UNIT_BCD) { /* BCD? */ - if (addr & 1) return SCPE_ARG; - t = cdr_to_alp[t]; /* convert */ - if (t < 0) return SCPE_ARG; /* invalid? */ - val[0] = (t >> 4) & DIGIT; /* store */ - val[1] = t & DIGIT; - return -1; } - else val[0] = t; /* store ASCII */ - return SCPE_OK; } - -if ((uptr->flags & UNIT_BCD) == 0) return SCPE_ARG; /* CPU or disk? */ -if ((sw & SWMASK ('S')) || ((*cptr == '"') && cptr++)) { /* string? */ - if (addr & 1) return SCPE_ARG; /* must be even */ - for (i = 0; (i < sim_emax) && (*cptr != 0); i = i + 2) { - t = *cptr++ & 0x7F; /* get character */ - t = cdr_to_alp[t]; /* convert */ - if (t < 0) return SCPE_ARG; /* invalid? */ - val[i] = (t >> 4) & DIGIT; /* store */ - val[i + 1] = t & DIGIT; } - if (i == 0) return SCPE_ARG; /* final check */ - return -(i - 1); } - -if (addr & 1) return SCPE_ARG; /* even addr? */ -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -for (i = 0; opcode[i].str != NULL; i++) { /* look it up */ - if (strcmp (gbuf, opcode[i].str) == 0) break; } -if (opcode[i].str == NULL) return SCPE_ARG; /* successful? */ -opfl = opcode[i].opv & 0xFF0000; /* get flags */ -val[0] = (opcode[i].opv & 0xFF) / 10; /* store opcode */ -val[1] = (opcode[i].opv & 0xFF) % 10; -qv = opcode[i].qv; -for (i = ADDR_LEN - 1; i >= 0; i--) { /* set P,Q fields */ - val[I_P + i] = 0; - val[I_Q + i] = qv % 10; - qv = qv /10; } - -cptr = get_glyph (cptr, gbuf, ','); /* get P field */ -if (gbuf[0]) { /* any? */ - if (parse_addr (gbuf, &val[I_P], (I_GETPP (opfl)? - I_M_QX: 0))) return SCPE_ARG; } -else if (I_GETPP (opfl) == I_M_PP) return SCPE_ARG; - -if (I_GETQP (opfl) != I_M_QNP) { /* Q field allowed? */ - cptr = get_glyph (cptr, gbuf, ','); /* get Q field */ - if (gbuf[0]) { /* any? */ - if (parse_addr (gbuf, &val[I_Q], I_GETQF (opfl))) - return SCPE_ARG; } - else if (I_GETQP (opfl) == I_M_QP) return SCPE_ARG; } - -cptr = get_glyph (cptr, fptr = gbuf, ' '); /* get flag field */ -last = -1; /* none yet */ -while (t = *fptr++) { /* loop through */ - if ((t < '0') || (t > '9')) return SCPE_ARG; /* must be digit */ - t = t - '0'; /* convert */ - if (t == 1) { /* ambiguous? */ - la = *fptr++; /* get next */ - if (la == '0') t = 10; /* 10? */ - else if ((la == '1') && (*fptr == 0)) t = 11; /* 11 & end field? */ - else --fptr; } /* dont lookahead */ - if (t <= last) return SCPE_ARG; /* in order? */ - val[t] = val[t] | FLAG; /* set flag */ - last = t; } /* continue */ - -if (*cptr != 0) return SCPE_ARG; -return -(INST_LEN - 1); -} diff --git a/I1620/i1620_tty.c b/I1620/i1620_tty.c deleted file mode 100644 index 47f20906..00000000 --- a/I1620/i1620_tty.c +++ /dev/null @@ -1,347 +0,0 @@ -/* i1620_tty.c: IBM 1620 typewriter - - Copyright (c) 2002-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - tty console typewriter - - 22-Dec-02 RMS Added break test -*/ - -#include "i1620_defs.h" - -#define TTO_COLMAX 80 - -int32 tto_col = 0; - -extern uint8 M[MAXMEMSIZE]; -extern uint8 ind[NUM_IND]; -extern UNIT cpu_unit; -extern uint32 io_stop; - -void tti_unlock (void); -t_stat tti_rnum (int8 *c); -t_stat tti_ralp (int8 *c); -t_stat tti_read (int8 *c); -t_stat tto_num (uint32 pa, uint32 len); -t_stat tto_write (uint32 c); -t_stat tty_svc (UNIT *uptr); -t_stat tty_reset (DEVICE *dptr); - -/* TTY data structures - - tty_dev TTY device descriptor - tty_unit TTY unit descriptor - tty_reg TTY register list -*/ - -UNIT tty_unit = { UDATA (&tty_svc, 0, 0), KBD_POLL_WAIT }; - -REG tty_reg[] = { - { DRDATA (COL, tto_col, 7) }, - { DRDATA (TIME, tty_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -DEVICE tty_dev = { - "TTY", &tty_unit, tty_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &tty_reset, - NULL, NULL, NULL }; - -/* Data tables */ - -/* Keyboard to numeric */ - -const char *tti_to_num = "0123456789'=@:;\""; - -/* Keyboard to alphameric (digit pair) - translates LC to UC */ - -const int8 tti_to_alp[128] = { - -1, -1, -1, -1, -1, -1, -1, -1, /* 00 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */ - -1, -1, -1, -1, -1, -1, -1, -1, - 0x00, 0x02, 0x0F, -1, 0x13, -1, -1, -1, /* !"#$%&' */ - 0x24, 0x04, 0x14, 0x10, 0x23, 0x20, 0x03, 0x21, /* ()*+,-./ */ - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 01234567 */ - 0x78, 0x79, -1, -1, -1, 0x33, -1, -1, /* 89:;<=>? */ - 0x34, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* @ABCDEFG */ - 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* HIJKLMNO */ - 0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* PQRSTUVW */ - 0x67, 0x68, 0x69, -1, -1, -1, -1, -1, /* XYZ[\]^_ */ - -1, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* abcdefg */ - 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* hijklmno */ - 0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* pqrstuvw */ - 0x67, 0x68, 0x69, -1, -1, -1, -1, -1 }; /* xyz */ - -/* Numeric (digit) to typewriter */ - -const char num_to_tto[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '\'', '=', '@', ':', ';', '"' }; - -/* Alphameric (digit pair) to typewriter */ - -const char alp_to_tto[256] = { - ' ', -1, '?', '.', ')', -1, -1, -1, /* 00 */ - -1, -1, -1, -1, -1, -1, -1, -1, - '+', -1, '!', '$', '*', ' ', -1, -1, /* 10 */ - -1, -1, -1, -1, -1, -1, -1, -1, - '-', '/', '\'', ',', '(', -1, -1, -1, /* 20 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, '0', '=', '@', ':', -1, -1, /* 30 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40 */ - 'H', 'I', -1, -1, -1, -1, -1, -1, - '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */ - 'Q', 'R', -1, -1, -1, -1, -1, -1, - -1, '/', 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */ - 'Y', 'Z', -1, -1, -1, -1, -1, -1, - '0', '1', '2', '3', '4', '5', '6', '7', /* 70 */ - '8', '9', -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* A0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* B0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* C0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* D0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* E0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* F0 */ - -1, -1, -1, -1, -1, -1, -1, -1 }; - -/* Terminal IO - - - On input, parity errors cannot occur. - - On input, release-start does NOT cause a record mark to be stored. - - On output, invalid characters type an invalid character and set WRCHK. - If IO stop is set, the system halts at the end of the operation. -*/ - -t_stat tty (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -t_addr i; -uint8 d; -int8 ttc; -t_stat r, inv = SCPE_OK; - -switch (op) { /* case on op */ -case OP_K: /* control */ - switch (f1) { /* case on control */ - case 1: /* space */ - tto_write (' '); - break; - case 2: /* return */ - tto_write ('\r'); - break; - case 3: /* backspace */ - if ((cpu_unit.flags & IF_MII) == 0) return STOP_INVFNC; - tto_write ('\b'); - break; - case 4: /* index */ - if ((cpu_unit.flags & IF_MII) == 0) return STOP_INVFNC; - tto_write ('\n'); - break; - case 8: /* tab */ - tto_write ('\t'); - break; - default: - return STOP_INVFNC; } - return SCPE_OK; -case OP_RN: /* read numeric */ - tti_unlock (); /* unlock keyboard */ - for (i = 0; i < MEMSIZE; i++) { /* (stop runaway) */ - r = tti_rnum (&ttc); /* read char */ - if (r != SCPE_OK) return r; /* error? */ - if (ttc == 0x7F) return SCPE_OK; /* end record? */ - M[pa] = ttc & (FLAG | DIGIT); /* store char */ - PP (pa); } /* incr mem addr */ - break; -case OP_RA: /* read alphameric */ - tti_unlock (); - for (i = 0; i < MEMSIZE; i = i + 2) { /* (stop runaway) */ - r = tti_ralp (&ttc); /* read char */ - if (r != SCPE_OK) return r; /* error? */ - if (ttc == 0x7F) return SCPE_OK; /* end record? */ - M[pa] = (M[pa] & FLAG) | (ttc & DIGIT); /* store 2 digits */ - M[pa - 1] = (M[pa - 1] & FLAG) | ((ttc >> 4) & DIGIT); - pa = ADDR_A (pa, 2); } /* incr mem addr */ - break; -case OP_DN: - return tto_num (pa, 20000 - (pa % 20000)); /* dump numeric */ -case OP_WN: - return tto_num (pa, 0); /* type numeric */ -case OP_WA: - for (i = 0; i < MEMSIZE; i = i + 2) { /* stop runaway */ - d = M[pa] & DIGIT; /* get digit */ - if ((d & 0xA) == REC_MARK) /* 8-2 char? */ - CRETIOE (io_stop, inv); /* end record */ - d = ((M[pa - 1] & DIGIT) << 4) | d; /* get digit pair */ - ttc = alp_to_tto[d]; /* translate */ - if (ttc < 0) { /* bad char? */ - ind[IN_WRCHK] = 1; /* set write check */ - inv = STOP_INVCHR; } /* set return status */ - tto_write (ttc & 0x7F); /* write */ - pa = ADDR_A (pa, 2); } /* incr mem addr */ - break; -default: /* invalid function */ - return STOP_INVFNC; } -return STOP_RWRAP; -} - -/* Read numerically - cannot generate parity errors */ - -t_stat tti_rnum (int8 *c) -{ -int8 flg = 0; -char *cp, raw; -t_stat r; - -*c = -1; /* no char yet */ -do { r = tti_read (&raw); /* get char */ - if (r != SCPE_OK) return r; /* error? */ - if (raw == '\r') *c = 0x7F; /* return? mark */ - else if (raw == '~') flg = FLAG; /* flag? mark */ - else if (cp = strchr (tti_to_num, raw)) /* legal? */ - *c = ((int8) (cp - tti_to_num)) | flg; /* assemble char */ - else raw = 007; /* beep! */ - tto_write (raw); } /* echo */ -while (*c == -1); -return SCPE_OK; -} - -/* Read alphamerically - cannot generate parity errors */ - -t_stat tti_ralp (int8 *c) -{ -char raw; -t_stat r; - -*c = -1; /* no char yet */ -do { r = tti_read (&raw); /* get char */ - if (r != SCPE_OK) return r; /* error? */ - if (raw == '\r') *c = 0x7F; /* return? mark */ - else if (tti_to_alp[raw] >= 0) /* legal char? */ - *c = tti_to_alp[raw]; /* xlate */ - else raw = 007; /* beep! */ - tto_write (raw); } /* echo */ -while (*c == -1); -return SCPE_OK; -} - -/* Read from keyboard */ - -t_stat tti_read (int8 *c) -{ -int32 t; - -do { t = sim_poll_kbd (); } /* get character */ -while ((t == SCPE_OK) || (t & SCPE_BREAK)); /* ignore break */ -if (t < SCPE_KFLAG) return t; /* error? */ -*c = t & 0177; /* store character */ -return SCPE_OK; -} - -/* Write numerically - cannot generate parity errors */ - -t_stat tto_num (uint32 pa, uint32 len) -{ -t_stat r; -uint8 d; -uint32 i, end; - -end = pa + len; -for (i = 0; i < MEMSIZE; i++) { /* (stop runaway) */ - d = M[pa]; /* get char */ - if (len? (pa >= end): /* dump: end reached? */ - ((d & REC_MARK) == REC_MARK)) /* write: rec mark? */ - return SCPE_OK; /* end operation */ - if (d & FLAG) tto_write ('~'); /* flag? */ - r = tto_write (num_to_tto[d & DIGIT]); /* write */ - if (r != SCPE_OK) return r; /* error? */ - PP (pa); } /* incr mem addr */ -return STOP_RWRAP; -} - -/* Write, maintaining position */ - -t_stat tto_write (uint32 c) -{ -int32 rpt; - -if (c == '\t') { /* tab? */ - rpt = 8 - (tto_col % 8); /* distance to next */ - tto_col = tto_col + rpt; /* tab over */ - while (rpt-- > 0) sim_putchar (' '); /* use spaces */ - return SCPE_OK; } -if (c == '\r') { /* return? */ - sim_putchar ('\r'); /* crlf */ - sim_putchar ('\n'); - tto_col = 0; /* clear colcnt */ - return SCPE_OK; } -if ((c == '\n') || (c == 007)) { /* non-spacing? */ - sim_putchar (c); - return SCPE_OK; } -if (c == '\b') tto_col = tto_col? tto_col - 1: 0; /* backspace? */ -else tto_col++; /* normal */ -if (tto_col > TTO_COLMAX) { /* line wrap? */ - sim_putchar ('\r'); - sim_putchar ('\n'); - tto_col = 0; } -sim_putchar (c); -return SCPE_OK; -} - -/* Unit service - polls for WRU */ - -t_stat tty_svc (UNIT *uptr) -{ -int32 temp; - -sim_activate (&tty_unit, tty_unit.wait); /* continue poll */ -if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tty_reset (DEVICE *dptr) -{ -sim_activate (&tty_unit, tty_unit.wait); /* activate poll */ -tto_col = 0; -return SCPE_OK; -} - -/* TTI unlock - signals that we are ready for keyboard input */ - -void tti_unlock (void) -{ -tto_write ('`'); -return; -} diff --git a/Ibm1130/1130consoleblank.bmp b/Ibm1130/1130consoleblank.bmp deleted file mode 100644 index 9b6c7780a979d0729d4867f67638e44e32db7eb1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 887934 zcmeI3!IdmYj$LcGC)X5#Yc41NSKLqn>cTSuP%KJAC7Q3w`oBUyb948Mh>Q%wzkW_< z12C95-UY(Ed%EVo|Ih#ZfBxeie?I?B|N1Zb*Z=wtfBf!>tBBb_yYk5KmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$## zAOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;| zfB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U< z00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa z0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV= z5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHaf zKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_ z009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz z00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_< z0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb z2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$## zAOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;| zfB*y_009U<00Izz00bZa0SG_<0u2cKqdb;VV*haPLyTIRY**!Yjo2Q>$aiMl9+|ih zfB*y_@VgO+kAgoLl|$szr5~{m>#0H8HeBb3)OfX>h5-QxKmY;|IQ&2y27i#%T+c~F zOZ6FLD^lwZw=Q8r00Izzz;8%kd^ke*VK8#u@6MmFlSo~%ZDSN4?)w$-MhHLv0ucBR z0{SA%ABDr<=M)^39M00bbgBZ2pPt={wH-H|^vLjVF0fWSEce?er7%o9Ti&ObkPUVV7u zeAId5t1oiC44-U!UiFfbF(3c|2tc3#fw>)?qY?OwgfLHXmkng4LwulM}@fjd7+ z`A)Ds47(%YFzCG)5P$##Akc|Gz4KT0!+Le#cpg6C=Eh&|`TI+EzESx#VYm?-2`5YS z1Z)UE00I!$nt*Qmap6nFFjjvbmigxk{(2rh;pWC)@A;Q6-N|0%*VW<9K}TfxsT;8& z009UQiTr=hY2G;mV5{X1Rwwb2y92-@Jd&( z#_iVN14_p^PabmTyH(pxvs~u^$5P$##Ag~vKxYGS0sBzhLZAfOd@2LLs zl)s)k$p!=1Rwwb2>b|vH+-%9 z3K>75k(WXM0uX=z1nv;<2kTDqV>xel#bbrB3jz>;00baV3HXEcP5&kCyU(v$ups~e z2tWV=PZIEF>&bHtw}0#5hi@bZ0SG_<0uXqZfInL@9zNu7_&S0RfB*y_0D;&(TN^C18M2teRR2pHYJ%wV2`7zgmr) znvV?u2tWV=5ZIAGeA?o}Hx$*N^KJZ~YSrMUmimJw@oES_00I!$mw>)0wfNz#f;C?4 zdcxc6C}6k|d|NTR2m%m*00bHk&_|>`Ly;m?+HenpHSK5Z!ye4+4kZl=_LO_J>GTNq$C2azCUt%76d_AOL}V z35>5v{icl1jTO};2QeT30SG_<0{sZYH!)o4<(t^A=_rB#1Rwx`Ljv&;3|CwDCLVGl z2muH{00R98)Q_M)e>SAI+L!Vp*{%#f;}E&^v~cSZHUuC50SG|gJp{(bsQ%S^>ldop zmnGF?+cw7b;ntw+>R!Hu1PDL?0uX?}cMupKqrW~%fBzS^`h}|YWdSwWwvDlUxDJMU z`3e#s009U<00Q4c;P8{=pbS5E3Q+P$vmv+Ib{!ms-8*j~2Lcd)00bcL`2_T7tIsG{ zky`n1>tC%#PR+-L00bZa0SN3!AUg&&dwf zNA8WQWXvNFj&*DApijgKmY;|fB*y_009U<00Izz00bZa z0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV= z5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHaf zKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_ z009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz z00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_< z0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb z2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$## zAOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;| zfB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U< z00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa z0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV= z5P$##AOHafKmY;|fB*y_009U<00Izz00bZaf%g#j$3On@o)>NR7RYSZvL7#)nOU^} zGAlB~KaBvhy6OmIR%D2;2rx5{SrH(<3juz`t4=`%GAjbBI5Pv86#?SA5a3t5>J(%k zvm&sHGc%A`5g@(`0e;1+PC*7TD*~%HGXt3w0phz5;8(or6l5T?BCv`xGmu#kAifI$ ze#NU!K?X7_0;@PP1DO>8;=2&wSG?*JWFWI5u!=J?kXaERz6$|<#j8$11~MxGt2i?Q znH2%zyAa@4yy_HWAhRN{iZe5iSrH(<3juz`t4=`%GAjbBI5Pv86#?SA5a3t5>J(%k zvm&sHGc%A`5g@(`0e;1+PC*7TD*~%HGXt3w0phz5;8(or6l5T?BCv`xGmu#kAifI$ ze#NU!K?X7_0;@PP1DO>8;=2&wSG?*JWFWI5u!=J?kXaERz6$|<#j8$11~MxGt2i?Q znH2%zyAa@4yy_HWAhRN{iZe5iSrH(<3juz`t4=`%GAjbBI5Pv86#?SA5a3t5>J(%k zvm&sHGc%A`5g@(`0e;1+PC*7TD*~%HGXt3w0phz5;8(or6l5T?BCv`xGmu#kAifI$ ze#NU!K?X7_0;@PP1DO>8;=2&wSG?*JWFWI5u!=J?kXaERz6$|<#j8$11~MxGt2i?Q znH2%zyAa@4yy_HWAhRN{iZe5iSrH(<3juz`t4=`%GAjbBI5Pv86#?SA5a3t5>J(%k zvm&sHGc%A`5g@(`0e;1+PC*7TD*~%HGXt3w0phz5;8(or6l5T?BCv`xGmu#kAifI$ ze#NU!K?X7_0;@PP1DO>8;=2&wSG?*JWFWI5u!=J?kXaERz6$|<#j8$11~MxGt2i?Q znH2%zyAa@4yy_HWAhRN{iZe5iSrH(<3juz`t4=`%GAjbBI5Pv86#?SA5a3t5>J(%k zvm&sHGc%A`5g@(`0e;1+PC*7TD*~%HGXt3w0phz5;8(or6l5T?BCv`xGmu#kAifI$ ze#NU!K?X7_0;@PP1DO>8;=2&wSG?*JWFWI5u!=J?kXaERz6$|<#j8$11~MxGt2i?Q znH2%zyAa@4yy_HWAhRN{iZe5iSrH(<3juz`t4=`%GAjbBI5Pv86#?SA5a3t5>J(%k zvm&sHGc%A`5g@(`0e;1+PC*7TD*~%HGXt3w0phz5xcMtq+ISw;rR|UH{q^R@3-AeF zD&T>FAJ{TVdaOdrd49W(x?|jt`Fu&^ggf=roT%;LGU6P)Vvf}J4*NW(uF9^@eAFCK zehqqi4W8JsePkX64-bjVm%RP(MFb)6vjk$)4~wZe)jmvK1s~q117EfGOXqwkd8mG1 zOQ?I`gu12Lt47T6ukO0cuL;$jUws&(yXJ>ox5N@I1U`zuoms6p)&7!@hc}M5Jh}aWL+-y(nf3V+ zmPpn)5xI2hmTF&abi!A6UFO$>YWt1%jjwL6`78U*+w0zuKS$<+?myyQ|&Jm|L{h?<;^GDf1NXJxaO}K51df9 zRQpS>{?f+FfVtyN9OJ4Iftuv39K3IM zuZ;VuLlZSk1`vb{e+G2H&?RwSr2hO=HxF%HF z?>aZ?mTKSGRr6Q&W9QVj`C{lJzu0T%-AA#i6_ zYfiQASEyZ&ZPY93#%kYud)-p)%k5uE9(8_oi)(mz<9P4O&+&nW#$~lNq1uP1&B3~* z+H+<^lw9*ycI=wnzmEBr|6Vgk=3R=^H%3C7P&2C?yX?Mp`#3hv^t)zb&b(7|J?E?W zbuTsq-bvu*td1YW&E&)SpWHhNI6V0>_*n4|6#T%JQM@aB>;!MWL@_6L?=a?sIdZ2+ zA3JZq6M1-h)b^@#RCAnssNy^)R=--?YqyX3B3(009U<;CCayH}QAtIC>!f0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;| zfB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U< z00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa z0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00O@=fq(Eo00Izrg21Nt z=M#$Ax;KIIiIuj0@AXL0f8GC)3OBBSqGobpzIv+*vEf$jp4cr6Ro?67`*$gd?%>V@ zE+>}3n4x__q&BX>s5g@n6Vh88!WT;eMa|^Ifb~`vV#BT4J+WIDs{DcLMO(Dd&toTi(=JsN-NBs+h|>9dD!~n^ z_8c6m&at7)Sehd>;m$_C{Q*Pg&m6XkNQE2MKv6R}F;2bJh1hVbc2DdUhAMyHdWkJB zIV8?}*i|vn9o(6~<;2#WR=f5^aWBn=Grgq9p*@20(j4)b4;VUa=CEBvDtxgtP}EFL zj8kuQAvWBq-4nZop~~y^a^h-fJkI|W`19Wt9Dj#ldyad_h7Wv+p<|;vxHAD!I-k$l zood$}Dek3e{1yJ^pE>~5cD{pmBK7TGwRQf?VY`S_xN!{>HIozL)LUJM4Yz9d#BO1z z@_M(d+!`PDD&lygIevHt)*7C)^`htw?o2?G&gV1wC3igTj@)4nBivYu)kD`o?H#uM z4#Sag>|=j*)XZVKh*Y?74HPw#6XVodU5E|0YWKu$VW{$Y!>rth#~n3RYmV*N@aw$f z$V&_z8{NU335e49eAez%+dXn{82UR5B@DZ|4%Y3F;GBq$)4cIvL+8vKwu?xG8`nTl zGdVF%z14--aI1Dt>=uS9ub0fqRlGjq`tn9C)yQzis_nWx@_o)r3>_Zb!JP?+()oOj z9z_#R8dUR7(tdEM$6(aPHBi({PW;e%s|&H=R_*6k&8MxZ@_J3lt&f)!40{!Ed>G-5 zLt@D%zr@ht(H-2GfGC}hq8q2CRD0EOC~77r#;Lcu5F2jQ z?up&PQ04VTI&rl$9_RlG{Q2(+j=#e=u@9Gg=JSTmkM7{k1Vrh4KHVlaRFUyK-=jD| z$42BkT)k!Huw6td+_(mcn#qZA>a8xshFi6JVz)3R!>!uSubNL=Rps?QId^O3O*;;}x$BuU zy)n9jI};G4^HF?%=m`$TSi>e8jH zjh8uZNKhHk9o(6KD4maD?Pj${2OW_y9(VRv;O}8@f()gNzbm8W)J)mqIWIstt|SaC z%^bFiNQE2MKv6R}F;2bJh1hVbc2DdUhANM%V|Q1IqC2=Vfy;@lgHi1<9wSoYmk}jI z&Tw_$9Ip|l9cFr5>lO#Ap@f;kb`h!Y#nM1gGdVF%z14--aI1Dt>=uS9ulI&*Mf`Xv zB691}u$?njoin>5)4S%Q9C^Ud;n5x3nSdyr&*$ix`HzYOm_`kcs* zxLp~x>meiVzgn6(Y!{IVH?D!AW^!VjdaDbu;a2UQ*ewiI?n}cLiz8#T=6p5cz4tfz z?T;CHQFI4)CLl`Z^XbNoE>zdH4R`81GFF`vhFzUDXDTutuU5mha%3MqTADd*7m*4# zu7RRva$=l%s|&H=R_&hHEeus&FOYD@QVkCKe#DvgH`aO{u=S$o4(?1ql+NeVja$ut z;x%X3Uy3;S&fZ!^Y&={V!TMLbW)9m$q{5ABps1Og7^mLqLTtEIyC-%FLzTz9QQcwJ zoMGROIP?C-xqvT4^rGkv?o2?G&gavOGyJ)OT2gR4HLXTu*QMBUnK|~3G#?eaX4h}5 zhSFvZ+eM_pjccH&nVcA>-s(bZxK+C+b_+w5$GuVAVb`2t>+dj>Fbum9ar`7La^?cQ z6wztX9o(6KD4oxzn_~DQGRK|pa%1(bRs6gF?V34k7m*4#u7RRva$=l%s|&H=R_&hH zEeus&Z<27mr1*G7M7E3?vFl*u47aA895t36`>Pj4cW`F{qI5o=?pN)?VX!8=)?U4C z6+eHwcFi2Ni%5kV*FaG-IWbPX)rHt_t9DQ97KSRXH%Yj4>AqbLsrLO7p2^f3qdT}W z0Z}@i&%?$Y2A^rx`QF#QPN&Trwu?xG8`nTlGdVF%z14--aI1Dt>=uS9ulLfqTQg7W zdPucTw!CmjZ;bBX&ICm1d_LdbxEIdA;ZZ#Xqc*OAqGod9ht^wNhz+-DKfh`|ZB>=W z1)_+bSi0$IyE4aLZwc4&mm7LfbO(1PAWG+>__lt%d;nGl_85%XxCV-v$%!9YZ*?Iy z+^YTjs`<24Rld4IHjPVBbO(1Pa5=FI#tiKfBDHZ1M!lJwn2_G;LTtEI`=@>N&g)U- zn|}LNWlK?X2X`iLIk8IMfdB*`@Gyb%PtV7$KCG9GyA$}>nWQiXKmY;|fB*y_009U< z00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHaf>_TAoe~5_sApn6NB(TdxN1YJ3 zNkG4*)&IlGj&aGE|9?`pi%5mr*FaG-IWbPX)rHt_t9DQ9E{2Nd`3(tN&Zn5{`0ZQO zEIIMB-O-f_H?D!AW^!VpdaDbu;a2UQ*j)@2zq&?tj7v^*2X`iLXJQ$QncI&?YU3J= zdNVmO9=+9t*l?@%T|R}bQ^oK2?OW9>Inf>5nZTWiWiV!LKOU)#YcT4~amk79;LZf@Oe}*jbNlf~ZCryj#y)n9jI};G4%Ym%Dd$=8+ zv$4lu)W$VX)J#tN(0Z#2vEf$jmsicFC8+puaoMQ%SPc&QOOcv<@|OC>CvCkkx`R6t z5T(mGoO}0VYkqcnkHM&oYoMr^ocN*jRu^K!t=ccInomnm@#C_xQSYuA9QKzYO0JJi zmRrw%xvle~JGe6eQM#PN@9xygTYr9FkHM&oYoMr^ocN*jRu^K!t=ccInomnm@#8YF zQSX)-9QI+v!N_r3XU0-}%L{G2CAxz<6A-1#Ijp^VVS|3^s2+n+8`nTlGdb}?>#Z)t zhFi5?UNxVVpyJ0hWg~7a#m6(JDXyUZ4r4^Z4mV!$LRT+}?%>V@MCo!4-7>ehw#ln9 z#^cprfxrI`0#1-oPaAGTYEDg%J)ZF**)|U2W7U6^GjrH3A{B0214Yf`#5na<7h=P$ z+C8zm7%JX(i!YET4WIesIS*{ttD`%(Gl4r3Tbo$z(UcLX@ym!3B4@ZdaE{lA(+)E| zBz22}Hnci(*e)U!zE~P4Y9=Sfskgci8*bI^iQUCe@#EgGap?MPxnsmpcecDLN3V|V z;LZd@>2f}!iE`^R`lU!T?mRM9ofC##omn$iai`T{YI3bj@tMPR5vg$F8YpTeC&sC_ zx)2*~)$WPi#Zd9SI%NBCa4$pkM|W^%0-|&|pUSDNudZzy&ODEdRp*3ZSEtRHij2pr z)v&D`+4H0L%wfBTRJd^s6g86*k^|5beEuw6td+_(mcn#qZA>a8xshFi6J zVs|lAyzh-e<1*oJ*G~miZFC2BCU9qB=f00f#O0319sd>h=UmCHOR{T1-Fuih_SP*v z;c{stIBn*zT|^vwvB=)8{wTPaoZm`ahz+-P))Tvnq2hgY$o5l%wq-)-Qp>Z%V^aCL%nX5(;|&yVil&IE+?at@7sfHmIg zez$#CgI>CdpVXr*Gl%UWQsKrmP}EFLj8kuQAvWBq-4nZuq2k9)VxwLx4i3Yvb5`+4 zuse);&U`{doNPmfM2^o_Ji3EB6A-1#`K+`nUfXXl4r_Sqy*&n_Hm-r9W^&?()>~bO z4Yz8)ylOrzLB)?t#zwt!92|yS=Qu9Ik5^?VSlwaQ;IL03Ub5k1Ys4o))^`*P>@^Y&HpWx_KX=ff3=?%>V@MCo!4 zXSS`d009X6Ac4pJGXT4G zC-8$K$EzU#0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_0D;{J?EXKPQa=PB z@Ph<)zW}Kp0zp8(rjviZce^FYiGTQZM^`G`rUr_d$%%>TtuDldTeW*)cQI5v&u>WJ zaz4dmyAR(s0aEefUlamYnDg?o8m$#4;E&w;zwx#x)rA zW^!UYdaDbu;a2Vb*6d=a_>)h}c1w~I-NBs++?m)q7}fSjDClPd!&Oj`!zIUk+IJgz zOyR|Rl6s47emGSI+9(V!`sY3?~>tNu{z>4^Sf=mF}j00 z6A-1#`BaXZRqbf8+_747B670iSA4gj8fFgLMWn)wYoMr^oEWFx>OyR|Rl6s47emGS zI;!>v*2sN(WIEr5U-W&3-WA=!oe7B2<$TtzReLoUCpmR#*fsKf!%$Dw8)pvNMWn)w zYoMr^oEWFx>OyR|Rl6s47emGS>Zta7^+lSKZA8M!3C?`Ep<<#txHAD!x}4A2)@r+D z3i?q{wwH$Chz+OJNbLG1S8tp-Y!{IVH?D!AW^!VjdaDbu;a2UQ*j)@2?^~$aBdADy z9F(EB-N>m+Bj;^@_3G#j?o2?GF6Yxt9KDu1p1GBZj~p*WWVmBBmb~S=4ZU~fuw6td z+_(mcn#qZA>a8xshFi6JVs|lAysx8b*Bh+bHD}nXh~qZ=qVF^GuILW#OhA+_=d*UL z+U}i#<5@-O>aW~?`Oi___y$7-%pA6hNQE2MKv6R}F;2bJh1hVbc2DdshKl!%RP7p6 z+)Fl;VEfPIzn-y6rVZOZ@LLVNF1mv|6A-1#`K*nr_Wkxfw(I`+U&>T5Gl%UWQsKrm zP}EFLj8kuQAvWBq-4nZuq2hhFRNKJ^j8~oW*sG&ExHEw}6I+{D?fXr6Y}ftszm%zB zW)9m$q{0_V14Yf`#5na<7h=P$+C8zm7%JX(OSK(*zYq7m7m*5IEDaPjlN00ATV03^w`%vq?qaBT-&fUk@B!mh=REf6=nn2o;LgPU zU=ttc`{fqNnK^71sf}x(sF|D?r{3y9Y`9hXE}ufzsp2p1ljjrO^A^>q7e#k)X99O7 zwzjO=V;Dxn@i6R;j`;7&Q2zOrNEkJI>90@R!>!sqvAY;5-gk>_8@{6)v2n8G92vtNf5(gFhzoe$(BaV?+?jwVUCw81nR{J3 zScB2ix_7nYxC}ohXO34t{8z7-Icyh^3OBBSqGobpoO-JZvEf$jp4eRs74Lh-whiA= zj@UTaRda@Y9`RAn8+uW62X`hQN|*ClTjnts4f0YL)vb2jzKT2NGGWy4)xSD+=CEBv zD%`jRikiuZaq6uu#D-h7dt!GnRJ^Yj+cpkwDy{l)!lB`y@@0=_*fsKN?K6k%B2wYTHBi({ zPK;A;bs;v~s@)U2i=pCux7e0Z?Qt)SG{+ruWH#oU!^k-KC4W^zbO(1PAWE0>>2A6& zBQnP$LGDS8lUK$wdskWW8*c5aCw3P@#rr0)Jq-OF z#<)_#4!7obX#~BbxR@Tv_j-8Y`ud-4_?J9F4B zA{B0214Yf`#5na<7h=P$+C8zm7%JX3Nwpmu#>rA--gIAnpzDn8;LZdD|8hPL8*~^H z`G|*mb0i||C5QM-oi=mWE+Q3fTmwbTM^}prYj*;_&xE5C0uX=z1Rwwb z2tWV=5P$##AOHafKmY;|fB*y_009U<00IzrIf32(2UF^Y00e%Jz{_tW4urtZ640+{ z_kRev)-O5n58v+SN`DAw8xpvjPcfS(_OB@=`U1T_dBdj`)xod133%kJ3wL4%eMuMa|^IIQ3Q+V#BT4J+ZqOD&99zwH35$<1llq)*Rcjad?7*&l`GUbO(1P zAWE0>>E4Z|RM)l*vEij*oSZN=zT~go65YX_35e3=eAYfj2i>WfGi*m@V;thY zKIA=y>X|ug7m*4#u7RRva$=l%s|&H=R_&hHT?`fPOG$QpYCLSE9Y!1-s(bZxK+C+b{9j% z`~bO4Yz8)ylOrzLB)Ufcj}$zOHOnLcP4OWV&}n7WIVN@iVXMH z;@_^*yfi1z5$}4fp%={@wu?xGFOUX`n#qZA>a8xshFi6JVs|lA{A(|tpFK@-qC2=V zfjbi$gHc`Ev!U*f;GLy8*^!q|k?NT_Y!{IVUn~t2HIozL)LUJM4Yz9d#O`9K_OyR|Rl6s47emF@%g3&b zab@}MNFJ*-$A>6*7HIozL)LUJM4Yz9d#O`9K_OyR|Rl6s47emF@%O~8r zRPCE-b<2Bf6&BsWoe7B2<$Qi@iys@L9)nRE*FaG-Iq^g5tuDldTeV+aHJ_HC;_D?7 zZe6PO&9u7ZJ+=yq?%>V@MCo!4Keok>4N{N6sEuo&sF|Gjq4ic5V#BT4FRz+UOHlET zT{54!OLC$+xHEw}6RR8^2tWV=j}iE^FWvomr1vwwZjV(ZIrArgNDvUE`x8PY1Rwx` z--p0s{~3T?yA$|*CLE;@fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P-nT z3GDtqm{LCkAn=0(UVbBSAOwDvfPPJn{iDC1xl3~5AHLnul?qQq14Yf`#6@J3i|LP^9 zEq=bb_q+2|Sab(>CLl_e^QoNgZq_@`?=cv)aSaqTlM_F*-s(bZxK;b*Rr6^HD*l

B;TSy!vpj>WS{)&IImEZ0&5d2X;qf`0-MW$abe{ye3D2-4_~q^~_OyR|Rl6s47emFz&2t!0a6BXVm-pwt*GL@oepmHGcW`F{qI5Z*?yQWBF;sk9H4&-qu;<7)p~mCPx4Ehzx`R6t5T(ocjBZxfwhi@n*e4M!)#q?# zl<-ZXqLXJ1+eM_pjccH&nVcA>-s(bZxK+C+b{9j%$1QXiQE)uI{o+p3YMk>UuF8n+ z;LZd@>2f}!q1Cl*!&7k*xmOC~77r#;Lcu5F2jQ?up&SQ1Nk1&5=m>WLL#U zcW`F{cP9353=V^19_FPv@`ID3VrCB8MWn(PO9MsCUA@R?IKd)3#5UfW^!VjdaDbu;a2UQ z*j)@2e|fju$+ifiVXMH z;@_^*yfi1z5$}4fp%={@wu?xG`_({EGdVF%z14--aI1Dt>@J3i_vKS<1?}2!@Fa4% zbduonUD8(#9Uk4moe7B2<$TsQMPIx$8_vA5G$%VEELor`ihIwc%imjO~utn3KoSNrJbGGavY?!=pR6GXYV$oX^^(XoQz$ z!yUY{G$+T4Ug)ZxnZtGwsc_>OC~77r#;Lcu5F2jQ?up&SQ1QNbs_px#8n%^LAID`3 z+pEL9v1#?95@ih*Y?74HPw#6XVodU5E|0YWKwMVyJjuKGhyK)mW?fA`nojr5dE+Q3fTmwbTa8xshFi6JVs|lAe7&sX`l<1k*gE+o=bRj(S44MkX9A*hIiGX06dBJ6 z|Bqc#a8PU(H%)AO-gBxn8v z5D5aJG*1E%2tWV=5P0lA1F&m%0!%&xAOHafKmY;|fB*y_009U<00Izz00bZa0SG_< z0uX=z1Rwx`hY9TdKbTTK1R(H(1RlP5*a(5oB%oi@$NtmB4-_Uj@ekkb=t_mBrGcVm za$=%-s|&H=R_&hHT?`e^^BWSloKG=%;M4Q5TO=obwmZ5~;l?#k)J#rHRBv@5Hr%S+ z6T6F{;y?Btd!R7MiSFRe1nx{MgE4da@kni4gHdlLC&r_W#$38vU zIGzW#f8Q3B6y3p{35b#hU}Y%h``YyWlY0zCZCnFI&E&)nt+%=m8*bIUx?w&xuHv7( zpq@YB$pY$j6%*aToeA8T*l26GV(y3xKcg3RWz@`JkJXXs$jWv6NkcE4Icyh^3g09R z6g86*eMuMa|^IIQ3Q+V#BT4J+ZqOD&AL3 zwSDPT!*V@MCo!qYs*HD6seDc?x0p>kH2-*5gXo8(;Qr- zIpG0AXU-h9i%5kV*FaG-IWbPX)rHt_t9DQ9E{2Nt4O49e?bEL&rrP6ns!Lj}3Bw(KYqBFF=q=74XVx^o z<#|KLMt5*$0-|&|pURorF@lFnN}l6$WIppf5mhpC*e)U!Zd?OJ&E&*5^;Q>R!>!sq zvAY;5-j`Cf53e|9-ZbLCo4cM#(;K5ZxHAD!x}48d?^bbjZC;uq&ouX$y{cs9uw6td z+_(mcn#qZA>a8xshFi6JVs|lAysw&SA6{|JylKRNH+MagrZ+}+aAyLdbUB}^-mT*5 z+PpMJo@wqgdsWHIVY`S_xN!{>HIozL)LUJM4Yz9d#O`9KcwaTL>*M$xLmTg;eRqz^ zi0vn#qZA z>a8xshFi6JVs|lAe7#BJ`f=P58FO$%4woDpMs;OZw;pTz0Yhg-cW`F{qI5Z*?vA_Q zhz%_b+mS=pX~T#dudWW66C9Co^U>imhwUO#;l?#k)J#r{Q*U)4Hr%S+6T6F{;(e=B zTS2=v96X6!E}bO!e3$f9Lx)FqaAyLdbUB~3O`{8r*ob~PeqwlwbKGJ_hGF+`OI`H| zCx-H84%~IiI3nY* zM~6puaAyLdbUB~3O`{i%*ihWIjlpk}Qhd%ljEr+0_^Ve$cW`F{qI5Z*qgk~D zj>xEX?cj*VYE7{1oH-JQ)CBLcq18K&@@Ed)MWn)wYoMr^oEWFx>OyR|Rl6s47emGS zN~yMjc5OI#9*F~;JPf<_GzV??kS`h99^Jv635e3=e9nz%x?|N5pLuC$%gkZBh*Y?74HPw#6XVodU5E|0YWKwMVyJlEC)FO8&sb92PfZ@d znp179R#$dJsykL485d5`f zdctG7>Io;d4xc$}7m*4#u7RRva$=l%s|&H=R_&hHT?`fPo21$bhU>Ji8m~I%&U^K) z=nn2oK$I@$bMD$4xzmvca=zn5I&a-uu9Gl4r3%V5mhemqhe*I?9}$%*mktuDldTeW}MC-1Tz75{^uu$RAD za-uu9Gl4r3s~jE(KmY=d5xD&Hd~AaBzWl@Vg9l2^{0Sfu1Vrg$2a>`d009X6Ac4pJ zGXT4GC-8$K$EzU#0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz V00bZa0SG_<0uX=z1hyvd{{eC}S!4hJ diff --git a/Ibm1130/HAND.CUR b/Ibm1130/HAND.CUR deleted file mode 100644 index eb0796dd30b18ae73defe98172ce1b6f3802dd91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 326 zcmb7;K@Ng26h!A+lkQ|^Vl={%r6&-M#03;?qDScsyaGq)k_9qO!GxWO)4cZow0}Cl z28N=*tcwAARi!9IElg|H_gI>BC%HENRLReEz){=++&dtfdYtb)4s75b4R-Al_UhoT zz;;lU0C - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "ibm1130res.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include \r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -///////////////////////////////////////////////////////////////////////////// -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Bitmap -// - -IDB_CONSOLE BITMAP DISCARDABLE "1130consoleblank.bmp" - -IDC_HAND CURSOR DISCARDABLE "HAND.CUR" - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/Ibm1130/ibm1130_conin.h b/Ibm1130/ibm1130_conin.h deleted file mode 100644 index 108e4917..00000000 --- a/Ibm1130/ibm1130_conin.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -// 03 ctrl-C => Program stop (not handled here) -// 05 ctrl-E => Simulator stop (not handled here) -// 08 ctrl-H => Backspace -// 0D ctrl-M (Enter) => EOF -// 11 ctrl-Q => Interrupt request (not handled here) -// 12 ctrl-R => "cent" (R because that's where cent is on the 1130 keyboard) -// 15 ctrl-U => Erase Field -// 7E ~ => "not" -// FF Del => Backspace again - -static uint16 ascii_to_conin[] = /* ASCII to ((hollerith << 4) | special key flags) */ -{ - /* 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F */ - /* 00 */ 0, 0, 0, 0, 0, 0, 0, 0,0x0004, 0, 0, 0, 0,0x0008, 0, 0, - /* 10 */ 0, 0,0x8820, 0, 0,0x0002, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 20 */ 0x0001,0x4820,0x0060,0x0420,0x4420,0x2220,0x8000,0x0120,0x8120,0x4120,0x4220,0x80a0,0x2420,0x4000,0x8420,0x3000, - /* 30 */ 0x2000,0x1000,0x0800,0x0400,0x0200,0x0100,0x0080,0x0040,0x0020,0x0010,0x0820,0x40a0,0x8220,0x00a0,0x20a0,0x2060, - /* 40 */ 0x0220,0x9000,0x8800,0x8400,0x8200,0x8100,0x8080,0x8040,0x8020,0x8010,0x5000,0x4800,0x4400,0x4200,0x4100,0x4080, - /* 50 */ 0x4040,0x4020,0x4010,0x2800,0x2400,0x2200,0x2100,0x2080,0x2040,0x2020,0x2010, 0, 0, 0, 0,0x2120, - /* 60 */ 0,0x9000,0x8800,0x8400,0x8200,0x8100,0x8080,0x8040,0x8020,0x8010,0x5000,0x4800,0x4400,0x4200,0x4100,0x4080, - /* 70 */ 0x4040,0x4020,0x4010,0x2800,0x2400,0x2200,0x2100,0x2080,0x2040,0x2020,0x2010, 0,0xB060, 0, 0,0x0004, - /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* a0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* b0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* c0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* d0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* e0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* f0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x0004, -}; diff --git a/Ibm1130/ibm1130_conout.h b/Ibm1130/ibm1130_conout.h deleted file mode 100644 index 478e005d..00000000 --- a/Ibm1130/ibm1130_conout.h +++ /dev/null @@ -1,58 +0,0 @@ -/* IBM1130 CONSOLE OUTPUT TO ASCII CONVERSION TABLE - * - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -#define _0_ '\0' - -#define CENT_ '\xA2' /* cent and not: standard DOS mapping */ -#define NOT_ '\xAC' -#define IGNR_ '\xFF' -#define CRLF_ '\r' - -#define COUT_IS_CTRL 0x01 /* conout characters with bit 1 set are controls: */ - -#define COUT_CTRL_BLACK 0x04 /* none or one of these bits */ -#define COUT_CTRL_RED 0x08 - -#define COUT_CTRL_LINEFEED 0x02 /* plus none or one of these bits */ -#define COUT_CTRL_BACKSPACE 0x10 -#define COUT_CTRL_SPACE 0x20 -#define COUT_CTRL_TAB 0x40 -#define COUT_CTRL_RETURN 0x80 - -#ifdef _MSC_VER -# pragma warning(disable:4245) /* enable int->char demotion warning caused by characters with high-bit set */ -#endif - -static unsigned char conout_to_ascii[] = /* console output code to ASCII */ -{ - /* 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F */ - /* 00 */ '.', IGNR_,CENT_, '\n', '@', IGNR_,'%', _0_, _0_, IGNR_,_0_, _0_, _0_, _0_, _0_, _0_, - /* 10 */ 'F', '\b', 'f', _0_, 'G', _0_, 'g', _0_, 'B', _0_, 'b', _0_, 'C', _0_, 'c', _0_, - /* 20 */ 'I', ' ', 'i', _0_, 'H', _0_, 'h', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* 30 */ 'D', _0_, 'd', _0_, 'E', _0_, 'e', _0_, _0_, _0_, _0_, _0_, 'A', _0_, 'a', _0_, - /* 40 */ '$', '\t', '!', _0_, '&', _0_, '>', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* 50 */ 'O', _0_, 'o', _0_, 'P', _0_, 'o', _0_, 'K', _0_, 'k', _0_, 'L', _0_, 'l', _0_, - /* 60 */ 'R', _0_, 'r', _0_, 'Q', _0_, 'q', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* 70 */ 'M', _0_, 'm', _0_, 'N', _0_, 'n', _0_, _0_, _0_, _0_, _0_, 'J', _0_, 'j', _0_, - /* 80 */ ',', CRLF_, ':', _0_, '-', _0_, '?', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* 90 */ 'W', _0_, 'w', _0_, 'X', _0_, 'x', _0_, 'S', _0_, 's', _0_, 'T', _0_, 't', _0_, - /* A0 */ 'Z', _0_, 'z', _0_, 'Y', _0_, 'y', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* B0 */ 'U', _0_, 'u', _0_, 'V', _0_, 'v', _0_, _0_, _0_, _0_, _0_, '/', _0_, '_', _0_, - /* C0 */ '#', _0_, '=', _0_, '0', _0_, '|', _0_, _0_, _0_, _0_, _0_, 'J', _0_, 'j', _0_, - /* D0 */ '6', _0_, ';', _0_, '7', _0_, '*', _0_, '2', _0_, '+', _0_, '3', _0_, '<', _0_, - /* E0 */ '9', _0_, '"', _0_, '8', _0_, '\'', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* F0 */ '4', _0_, NOT_, _0_, '5', _0_, ')', _0_, _0_, _0_, _0_, _0_, '1', _0_, '(', _0_, -}; - -#ifdef _MSC_VER -# pragma warning(default:4245) /* enable int->char demotion warning */ -#endif diff --git a/Ibm1130/ibm1130_cpu.c b/Ibm1130/ibm1130_cpu.c deleted file mode 100644 index f258bda8..00000000 --- a/Ibm1130/ibm1130_cpu.c +++ /dev/null @@ -1,1872 +0,0 @@ -/* ibm1130_cpu.c: IBM 1130 CPU simulator - - Based on the SIMH package written by Robert M Supnik - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - - 25-Jun-01 BLK Written - 10-May-02 BLK Fixed bug in MDX instruction - 27-Mar-02 BLK Made BOSC work even in short form - 16-Aug-02 BLK Fixed bug in multiply instruction; didn't work with negative values - 18-Mar-03 BLK Fixed bug in divide instruction; didn't work with negative values - 23-Jul-03 BLK Prevented tti polling in CGI mode - - The register state for the IBM 1130 CPU is: - - IAR instruction address register - ACC accumulator - EXT accumulator extension - Oflow overflow bit - Carry carry bit - CES console entry switches - ipl current interrupt level, -1 = non interrupt - iplpending bitmap of pending interrupts - wait_state current CPU state: running or waiting - DSW console run/stop switch device status word - RUNMODE processor step/run mode (may also imply IntRun) - BREAK breakpoint address - WRU simulator-break character - IntRun Int Run flag (causes level 5 interrupt after every instruction) - ILSW0..5 interrupt level status words - - The SAR (storage address register) and SBR (storage buffer register) are updated - but not saved in the CPU state; they matter only to the GUI. - - Interrupt handling: interrupts occur when any device on any level has an - active interrupt. XIO commands can clear specific IRQ bits. When this - happens, we have to evaluate all devices on the same IRQ level for remaining - indicators. The flag int_req is set with a bit corresponding to the IRQ level - when any interrupt indicator is activated. - - The 1130 console has a switch that controls several run modes: SS (single processor - step), SCLK (single clock step), SINST (single instruction step), INT_RUN - (IRQ 5 after each non interrupt-handler instruction) and RUN (normal operation). - This simulator does not implement SS and SCLK. The simulator GUI console handles - SINST, so we only have to worry about INT_RUN. The console command SET CPU IntRun sets - the tmode (trace mode) flag; this causes a level 5 interrupt after each - instruction. - - The IBM 1130 instruction formats are - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | opcode | F| T | | general format - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | opcode | 0| T | DISPLACEMENT | short instruction - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | opcode | 1| T | I| MODIFIER | long instruction - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | ADDRESS | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - opcode in MSBits - - F = format. 0 = short (1 word), 1 = long (2 word) instruction - - T = Tag 00 = no index register (e.g. IAR relative) - 01 = use index register 1 (e.g. core address 1 = M[1]) - 02 = use index register 2 (e.g. core address 2 = M[2]) - 03 = use index register 3 (e.g. core address 3 = M[3]) - - DISPLACEMENT = two's complement (must be sign-extended) - - I = Indirect - - Note that IAR = instruction address+1 when instruction is being decoded. - - In normal addressing mode, effective address (EA) is computed as follows: - - F = 0 T = 0 EA = IAR + DISPLACEMENT - 0 1 IAR + DISPLACEMENT + M[1] - 0 2 IAR + DISPLACEMENT + M[2] - 0 3 IAR + DISPLACEMENT + M[3] - - F = 1 T = 0 I = 0 EA = ADDRESS - 1 1 0 ADDRESS + M[1] - 1 2 0 ADDRESS + M[2] - 1 3 0 ADDRESS + M[3] - 1 0 1 M[ADDRESS] - 1 1 1 M[ADDRESS + M[1]] - 1 2 1 M[ADDRESS + M[2]] - 1 3 1 M[ADDRESS + M[3]] - - Loads or stores are then made to/from MEM[EA]. Some instructions have special - weird addressing modes. Simulator code precomputes standard addressing for - all instructions though it's not always used. - - General notes: - - Adding I/O devices requires modifications to three modules: - - ibm1130_defs.h add interrupt request definitions - ibm1130_cpu.c add XIO command linkages - ibm1130_sys.c add to sim_devices -*/ - -/* ------------------------------------------------------------------------ - * Definitions - * ------------------------------------------------------------------------ */ - -#include - -#include "ibm1130_defs.h" - -#define save_ibkpt (cpu_unit.u3) /* will be SAVEd */ - -#define UPDATE_BY_TIMER -#define ENABLE_BACKTRACE -#define CGI_SUPPORT - -static void cgi_start(void); -static void cgi_stop(t_stat reason); - -// hook pointers from scp.c -void (*sim_vm_init) (void) = &sim_init; -extern char* (*sim_vm_read) (char *ptr, int32 size, FILE *stream); -extern void (*sim_vm_post) (t_bool from_scp); -extern CTAB *sim_vm_cmd; - -// space to store extra simulator-specific commands -#define MAX_EXTRA_COMMANDS 10 -CTAB x_cmds[MAX_EXTRA_COMMANDS]; - -#ifdef WIN32 -# define CRLF "\r\n" -#else -# define CRLF "\n" -#endif - -/* ------------------------------------------------------------------------ - * initializers for globals - * ------------------------------------------------------------------------ */ - -#define SIGN_BIT(v) ((v) & 0x8000) -#define DWSIGN_BIT(v) ((v) & 0x80000000) - -uint16 M[MAXMEMSIZE]; /* core memory, up to 32Kwords (note: don't even think about trying 64K) */ -uint16 ILSW[6] = {0,0,0,0,0,0}; /* interrupt level status words */ -int32 IAR; /* instruction address register */ -int32 prev_IAR; /* instruction address register at start of current instruction */ -int32 SAR, SBR; /* storage address/buffer registers */ -int32 OP, TAG, CCC; /* instruction decoded pieces */ -int32 CES; /* console entry switches */ -int32 ACC, EXT; /* accumulator and extension */ -int32 RUNMODE; /* processor run/step mode */ -int32 ipl = -1; /* current interrupt level (-1 = not handling irq) */ -int32 iplpending = 0; /* interrupted IPL's */ -int32 tbit = 0; /* trace flag (causes level 5 IRQ after each instr) */ -int32 V = 0, C = 0; /* condition codes */ -int32 wait_state = 0; /* wait state (waiting for an IRQ) */ -int32 wait_lamp = TRUE; /* alternate indicator to light the wait lamp on the GUI */ -int32 int_req = 0; /* sum of interrupt request levels active */ -int32 int_lamps = 0; /* accumulated version of int_req - gives lamp persistence */ -int32 int_mask; /* current active interrupt mask (ipl sensitive) */ -int32 mem_mask; -int32 cpu_dsw = 0; /* CPU device status word */ -int32 ibkpt_addr = -1; /* breakpoint addr */ -int32 sim_gui = TRUE; /* enable gui */ -t_bool running = FALSE; /* TRUE if CPU is running */ -t_bool power = TRUE; /* TRUE if CPU power is on */ -t_bool cgi = FALSE; /* TRUE if we are running as a CGI program */ -t_stat reason; /* CPU execution loop control */ - -static int32 int_masks[6] = { - 0x00, 0x20, 0x30, 0x38, 0x3C, 0x3E /* IPL 0 is highest prio (sees no other interrupts) */ -}; - -/* ------------------------------------------------------------------------ - * Function declarations - * ------------------------------------------------------------------------ */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_svc (UNIT *uptr); -t_stat cpu_set_size (UNIT *uptr, int32 value, char *cptr, void *desc); -void calc_ints (void); - -extern t_stat ts_wr (int32 data, int32 addr, int32 access); -extern t_stat detach_cmd (int flags, char *cptr); -extern UNIT cr_unit; -extern int32 sim_switches; - -#ifdef ENABLE_BACKTRACE - static void archive_backtrace(char *inst); - static void reset_backtrace (void); - static void show_backtrace (int nshow); - static t_stat backtrace_cmd (int flag, char *cptr); -#else - #define archive_backtrace(inst) - #define reset_backtrace() - #define show_backtrace(ntrace) -#endif - -static void init_console_window (void); -static void destroy_console_window (void); -static t_stat view_cmd (int flag, char *cptr); -static t_stat cgi_cmd (int flag, char *cptr); -static t_stat cpu_attach (UNIT *uptr, char *cptr); -static t_bool bsctest (int32 DSPLC, t_bool reset_V); -static void exit_irq (void); -static void trace_instruction (void); - -/* ------------------------------------------------------------------------ - * CPU data structures: - * cpu_dev CPU device descriptor - * cpu_unit CPU unit descriptor - * cpu_reg CPU register list - * cpu_mod CPU modifier list - * ------------------------------------------------------------------------ */ - -UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX | UNIT_BINK | UNIT_ATTABLE | UNIT_SEQ, INIMEMSIZE) }; - -REG cpu_reg[] = { - { HRDATA (IAR, IAR, 32) }, - { HRDATA (ACC, ACC, 32) }, - { HRDATA (EXT, EXT, 32) }, - { FLDATA (Oflow, V, 1) }, - { FLDATA (Carry, C, 1) }, - { HRDATA (CES, CES, 32) }, - { HRDATA (ipl, ipl, 32), REG_RO }, - { HRDATA (iplpending, iplpending, 32), REG_RO }, - { HRDATA (wait_state, wait_state, 32)}, - { HRDATA (DSW, cpu_dsw, 32), REG_RO }, - { HRDATA (RUNMODE, RUNMODE, 32) }, - { HRDATA (BREAK, ibkpt_addr, 32) }, - { ORDATA (WRU, sim_int_char, 8) }, - { FLDATA (IntRun, tbit, 1) }, - - { HRDATA (ILSW0, ILSW[0], 32), REG_RO }, - { HRDATA (ILSW1, ILSW[1], 32), REG_RO }, - { HRDATA (ILSW2, ILSW[2], 32), REG_RO }, - { HRDATA (ILSW3, ILSW[3], 32), REG_RO }, - { HRDATA (ILSW4, ILSW[4], 32), REG_RO }, - { HRDATA (ILSW5, ILSW[5], 32), REG_RO }, - - { NULL} -}; - -MTAB cpu_mod[] = { - { UNIT_MSIZE, 4096, NULL, "4KW", &cpu_set_size}, - { UNIT_MSIZE, 8192, NULL, "8KW", &cpu_set_size}, - { UNIT_MSIZE, 16384, NULL, "16KW", &cpu_set_size}, - { UNIT_MSIZE, 32768, NULL, "32KW", &cpu_set_size}, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 16, 16, 1, 16, 16, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, cpu_attach, NULL}; // attaching to CPU creates cpu log file - -/* ------------------------------------------------------------------------ - Memory read/write -- save SAR and SBR on the way in and out - * ------------------------------------------------------------------------ */ - -int32 ReadW (int32 a) -{ - SAR = a; - SBR = (int32) M[(a) & mem_mask]; - return SBR; -} - -void WriteW (int32 a, int32 d) -{ - SAR = a; - SBR = d; - M[a & mem_mask] = (int16) d; -} - -/* ------------------------------------------------------------------------ - * upcase - force a string to uppercase (ASCII) - * ------------------------------------------------------------------------ */ - -char *upcase (char *str) -{ - char *s; - - for (s = str; *s; s++) { - if (*s >= 'a' && *s <= 'z') - *s -= 32; - } - - return str; -} - -/* ------------------------------------------------------------------------ - * calc_ints - set appropriate bits in int_req if any interrupts are pending on given levels - * - * int_req: - * bit 5 4 3 2 1 0 - * \ \ \ \ \ \ - * \ \ \ \ \ interrupt level 5 pending (lowest priority) - * \ . . . - * interrupt level 0 pending (highest priority) - * - * int_mask is set according to current interrupt level (ipl) - * - * 0 0 0 0 0 0 ipl = 0 (currently servicing highest priority interrupt) - * 1 0 0 0 0 0 1 - * 1 1 0 0 0 0 2 - * 1 1 1 0 0 0 3 - * 1 1 1 1 0 0 4 - * 1 1 1 1 1 0 5 (currently servicing lowest priority interrupt) - * 1 1 1 1 1 1 -1 (not servicing an interrupt) - * ------------------------------------------------------------------------ */ - -void calc_ints (void) -{ - register int i; - register int32 newbits = 0; - - GUI_BEGIN_CRITICAL_SECTION // using critical section here so we don't mislead the GUI thread - - for (i = 6; --i >= 0; ) { - newbits >>= 1; - if (ILSW[i]) - newbits |= 0x20; - } - - int_req = newbits; - int_lamps |= int_req; - int_mask = (ipl < 0) ? 0xFFFF : int_masks[ipl]; /* be sure this is set correctly */ - - GUI_END_CRITICAL_SECTION -} - -/* ------------------------------------------------------------------------ - * instruction processor - * ------------------------------------------------------------------------ */ - -#define INCREMENT_IAR IAR = (IAR + 1) & mem_mask -#define DECREMENT_IAR IAR = (IAR - 1) & mem_mask - -void bail (char *msg) -{ - printf("%s\n", msg); - exit(1); -} - -static void weirdop (char *msg, int offset) -{ - printf("Weird opcode: %s at %04x\n", msg, IAR+offset); -} - -static char *xio_devs[] = { - "0?", "console", "1142card", "1134papertape", - "dsk0", "1627plot", "1132print", "switches", - "1231omr", "2501card", "comm", "b?", - "sys7", "d?", "e?", "f?", - "10?", "dsk1", "dsk2", "dsk3", - "dsk4", "dsk5", "dsk6", "dsk7+", - "18?", "2250disp", "1a?", "1b", - "1c?", "1d?", "1e?", "1f?" -}; - -static char *xio_funcs[] = { - "0?", "write", "read", "sense_irq", - "control", "initw", "initr", "sense" -}; - -t_stat sim_instr (void) -{ - extern int32 sim_interval; - extern UNIT *sim_clock_queue; - int32 i, eaddr, INDIR, IR, F, DSPLC, word2, oldval, newval, src, src2, dst, abit, xbit; - int32 iocc_addr, iocc_op, iocc_dev, iocc_func, iocc_mod; - char msg[50]; - int cwincount = 0, status; - static long ninstr = 0; - static char *intlabel[] = {"INT0","INT1","INT2","INT3","INT4","INT5"}; - -#ifdef CGI_SUPPORT - if (cgi) - cgi_start(); -#endif - - if (running) /* this is definitely not reentrant */ - return -1; - - if (! power) /* this matters only to the GUI */ - return STOP_POWER_OFF; - - running = TRUE; - - mem_mask = MEMSIZE - 1; /* set other useful variables */ - calc_ints(); - - /* Main instruction fetch/decode loop */ - - reason = 0; - wait_lamp = 0; /* release lock on wait lamp */ - -#ifdef GUI_SUPPORT - update_gui(TRUE); - gui_run(TRUE); -#endif - - while (reason == 0) { - IAR &= mem_mask; - -#ifdef GUI_SUPPORT -#ifndef UPDATE_BY_TIMER -#if (UPDATE_INTERVAL > 0) - if (--cwincount <= 0) { - update_gui(FALSE); /* update console lamps only every so many instructions */ - cwincount = UPDATE_INTERVAL + (rand() % MIN(UPDATE_INTERVAL, 32)); - } -#else - update_gui(FALSE); -#endif // ifdef UPDATE_INTERVAL -#endif // ifndef UPDATE_BY_TIMER -#endif // ifdef GUI_SUPPORT - - if (sim_interval <= 0) { /* any events timed out? */ - if (sim_clock_queue != NULL) { - if ((status = sim_process_event()) != 0) - reason = status; - calc_ints(); - continue; - } - } - - if (int_req & int_mask) { /* any pending interrupts? */ - for (i = 0; i <= 5; i++) /* find highest pending interrupt */ - if ((int_req & int_mask) & (0x20 >> i)) - break; - - if (i >= 6) { /* nothing to do? */ - calc_ints(); /* weird. recalculate */ - continue; /* back to fetch */ - } - - GUI_BEGIN_CRITICAL_SECTION - - if (ipl >= 0) /* save previous IPL in bit stack */ - iplpending |= (0x20 >> ipl); - - ipl = i; /* set new interrupt level */ - int_mask = int_masks[i]; /* set appropriate mask */ - - GUI_END_CRITICAL_SECTION - - wait_state = 0; /* exit wait state */ - eaddr = ReadW(8+i); /* get IRQ vector */ - archive_backtrace(intlabel[i]); - WriteW(eaddr, IAR); /* save IAR */ - IAR = (eaddr+1) & mem_mask; /* go to next address */ - continue; /* now continue processing */ - } /* end if int_req */ - - if (wait_state) { /* waiting? */ - sim_interval = 0; /* run the clock out */ - - if (sim_qcount() <= (cgi ? 0 : 1)) { /* one routine queued? we're waiting for keyboard only */ - if (keyboard_is_busy()) { /* we are actually waiting for a keystroke */ - if ((status = sim_process_event()) != 0) /* get it with wait_state still set */ - reason = status; - } - else { /* CPU is not expecting a keystroke (keyboard interrupt) */ - if (wait_state == WAIT_OP) - reason = STOP_WAIT; /* end the simulation */ - else - reason = STOP_INVALID_INSTR; - } - } - - if (gdu_active()) /* but don't stop simulator if 2250 GDU is running */ - reason = 0; - - continue; - } - - if (IAR == ibkpt_addr) { /* simulator breakpoint? */ - save_ibkpt = ibkpt_addr; /* save bkpt */ - ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG; /* disable */ - sim_activate(&cpu_unit, 1); /* sched re-enable after next instruction */ - reason = STOP_IBKPT; /* stop simulation */ - cwincount = 0; - continue; - } - - ninstr++; - if (cpu_unit.flags & UNIT_ATT) - trace_instruction(); /* log CPU details if logging is enabled */ - - prev_IAR = IAR; /* save IAR before incrementing it */ - - IR = ReadW(IAR); /* fetch 1st word of instruction */ - INCREMENT_IAR; - sim_interval = sim_interval - 1; /* this constitutes one tick of the simulation clock */ - - OP = (IR >> 11) & 0x1F; /* opcode */ - F = IR & 0x0400; /* format bit: 1 = long instr */ - TAG = IR & 0x0300; /* tag bits: index reg x */ - if (TAG) - TAG >>= 8; - - // here I compute the usual effective address on the assumption that the instruction will need it. Some don't. - - if (F) { /* long instruction, ASSUME it's valid (have to decrement IAR if not) */ - INDIR = IR & 0x0080; /* indirect bit */ - DSPLC = IR & 0x007F; /* displacement or modifier */ - if (DSPLC & 0x0040) - DSPLC |= ~ 0x7F; /* sign extend */ - - word2 = ReadW(IAR); /* get reference address */ - INCREMENT_IAR; /* bump the instruction address register */ - - eaddr = word2; /* assume standard addressing & compute effective address */ - if (TAG) /* if indexed */ - eaddr += ReadW(TAG); /* add index register value (stored in core) */ - if (INDIR) /* if indirect addressing */ - eaddr = ReadW(eaddr); /* pick up referenced address */ - } - else { /* short instruction, use displacement */ - INDIR = 0; /* never indirect */ - DSPLC = IR & 0x00FF; /* get displacement */ - if (DSPLC & 0x0080) - DSPLC |= ~ 0xFF; - - if (TAG) /* if indexed */ - eaddr = ReadW(TAG) + DSPLC; /* add index register value (stored in core) */ - else - eaddr = IAR + DSPLC; /* otherwise relative to IAR after fetch */ - } - - switch (OP) { /* decode instruction */ - case 0x01: /* --- XIO --- */ - iocc_addr = ReadW(eaddr); /* get IOCC packet */ - iocc_op = ReadW(eaddr|1); /* note 'or' not plus, address must be even for proper operation */ - - iocc_dev = (iocc_op >> 11) & 0x001F; - iocc_func = (iocc_op >> 8) & 0x0007; - iocc_mod = iocc_op & 0x00FF; - - if (cpu_unit.flags & UNIT_ATT) - trace_io("* XIO %s %s mod %02x addr %04x", xio_funcs[iocc_func], xio_devs[iocc_dev], iocc_mod, iocc_addr); - - ACC = 0; /* ACC is destroyed, and default XIO_SENSE_DEV result is 0 */ - - switch (iocc_func) { - case XIO_UNUSED: - sprintf(msg, "Unknown op %x on device %02x", iocc_func, iocc_dev); - xio_error(msg); - break; - - case XIO_SENSE_IRQ: /* examine current Interrupt Level Status Word */ - ACC = (ipl >= 0) ? ILSW[ipl] : 0; - break; - - default: /* perform device-specific operation */ - switch (iocc_dev) { - case 0x01: /* console keyboard and printer */ - xio_1131_console(iocc_addr, iocc_func, iocc_mod); - break; - case 0x02: /* 1142 card reader/punch */ - xio_1142_card(iocc_addr, iocc_func, iocc_mod); - break; - case 0x03: /* 1134 paper tape reader/punch */ - xio_1134_papertape(iocc_addr, iocc_func, iocc_mod); - break; - case 0x04: /* CPU disk storage */ - xio_disk(iocc_addr, iocc_func, iocc_mod, 0); - break; - case 0x05: /* 1627 plotter */ - xio_1627_plotter(iocc_addr, iocc_func, iocc_mod); - break; - case 0x06: /* 1132 Printer */ - xio_1132_printer(iocc_addr, iocc_func, iocc_mod); - break; - case 0x07: /* console switches, stop key, run mode */ - xio_1131_switches(iocc_addr, iocc_func, iocc_mod); - break; - case 0x08: /* 1231 optical mark reader */ - xio_1231_optical(iocc_addr, iocc_func, iocc_mod); - break; - case 0x09: /* 2501 card reader */ - xio_2501_card(iocc_addr, iocc_func, iocc_mod); - break; - case 0x0a: /* synchronous comm adapter */ - xio_1131_synch(iocc_addr, iocc_func, iocc_mod); - break; - case 0x0c: /* IBM System/7 interprocessor link */ - xio_system7(iocc_addr, iocc_func, iocc_mod); - break; - case 0x11: /* 2310 Disk Storage, Drive 1, or 2311 Disk Storage Drive. Drive 1, Disk 1 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, 1); - break; - case 0x12: /* 2310 Disk Storage, Drive 2, or 2311 Disk Storage Drive. Drive 1, Disk 2 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, 2); - break; - case 0x13: /* 2310 Disk Storage, Drive 3, or 2311 Disk Storage Drive. Drive 1, Disk 3 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, 3); - break; - case 0x14: /* 2310 Disk Storage, Drive 4, or 2311 Disk Storage Drive. Drive 1, Disk 4 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, 4); - break; - case 0x15: /* 1403 Printer */ - xio_1403_printer(iocc_addr, iocc_func, iocc_mod); - break; - case 0x16: /* 2311 Disk Storage Drive. Drive 1, Disk 5 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, -1); - break; - case 0x17: /* 2311 Disk Storage Drive, Drive 2, Disk 1 through 5 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, -1); - break; - case 0x19: /* 2250 Display Unit */ - xio_2250_display(iocc_addr, iocc_func, iocc_mod); - break; - default: - sprintf(msg, "unknown device %02x", iocc_dev); - xio_error(msg); - break; - } - } - - calc_ints(); /* after every XIO, reset int_mask just in case */ - break; - - case 0x02: /* --- SLA,SLT,SLC,SLCA,NOP - Shift Left family --- */ - if (F) { - weirdop("Long Left Shift", -2); - DECREMENT_IAR; - } - - CCC = ((TAG == 0) ? DSPLC : ReadW(TAG)) & 0x003F; - if (CCC == 0) - break; /* shift of zero is a NOP */ - - switch (IR & 0x00C0) { - case 0x0040: /* SLCA */ - if (TAG) { - while (CCC > 0 && (ACC & 0x8000) == 0) { - ACC <<= 1; - CCC--; - } - C = (CCC != 0); - WriteW(TAG, ReadW(TAG) & 0xFF00 | CCC); /* put low 6 bits back into index register and zero bits 8 and 9 */ - break; - } - /* if TAG == 0, fall through and treat like normal shift SLA */ - - case 0x0000: /* SLA */ - while (CCC > 0) { - C = (ACC & 0x8000); - ACC = (ACC << 1) & 0xFFFF; - CCC--; - } - break; - - case 0x00C0: /* SLC */ - if (TAG) { - while (CCC > 0 && (ACC & 0x8000) == 0) { - abit = (EXT & 0x8000) >> 15; - ACC = ((ACC << 1) & 0xFFFF) | abit; - EXT = (EXT << 1); - CCC--; - } - C = (CCC != 0); - WriteW(TAG, ReadW(TAG) & 0xFF00 | CCC); /* put 6 bits back into low byte of index register */ - break; - } - /* if TAG == 0, fall through and treat like normal shift SLT */ - - case 0x0080: /* SLT */ - while (CCC > 0) { - C = (ACC & 0x8000); - abit = (EXT & 0x8000) >> 15; - ACC = ((ACC << 1) & 0xFFFF) | abit; - EXT = (EXT << 1) & 0xFFFF; - CCC--; - } - break; - - default: - bail("SLA switch, can't happen"); - break; - } - break; - - case 0x03: /* --- SRA, SRT, RTE - Shift Right family --- */ - if (F) { - weirdop("Long Right Shift", -2); - DECREMENT_IAR; - } - - CCC = ((TAG == 0) ? DSPLC : ReadW(TAG)) & 0x3F; - if (CCC == 0) - break; /* NOP */ - - switch (IR & 0x00C0) { - case 0x0000: /* SRA */ - ACC = (CCC < 16) ? ((ACC & 0xFFFF) >> CCC) : 0; - CCC = 0; - break; - - case 0x0040: /* invalid */ - wait_state = WAIT_INVALID_OP; - break; - - case 0x0080: /* SRT */ - while (CCC > 0) { - xbit = (ACC & 0x0001) << 15; - abit = (ACC & 0x8000); - ACC = (ACC >> 1) & 0x7FFF | abit; - EXT = (EXT >> 1) & 0x7FFF | xbit; - CCC--; - } - break; - - case 0x00C0: /* RTE */ - while (CCC > 0) { - abit = (EXT & 0x0001) << 15; - xbit = (ACC & 0x0001) << 15; - ACC = (ACC >> 1) & 0x7FFF | abit; - EXT = (EXT >> 1) & 0x7FFF | xbit; - CCC--; - } - break; - - default: - bail("SRA switch, can't happen"); - break; - } - break; - - case 0x04: /* --- LDS - Load Status --- */ - if (F) { /* never fetches second word */ - weirdop("Long LDS", -2); - DECREMENT_IAR; - } - - V = (DSPLC & 1); - C = (DSPLC & 2) >> 1; - break; - - case 0x05: /* --- STS - Store Status --- */ - newval = ReadW(eaddr) & 0xFF00; - if (C) - newval |= 2; - if (V) - newval |= 1; - - WriteW(eaddr, newval); - C = V = 0; /* clear flags after storing */ - break; - - case 0x06: /* --- WAIT --- */ - wait_state = WAIT_OP; - /* note: not valid in long mode, but what happens if we try? */ - if (F) { - weirdop("Long WAIT", -2); - DECREMENT_IAR; /* assume it wouldn't have fetched 2nd word */ - } - break; - - case 0x08: /* --- BSI - Branch and store IAR --- */ - if (F) { - if (bsctest(IR, F)) /* do standard BSC long format testing */ - break; /* if any condition is true, do nothing */ - } - WriteW(eaddr, IAR); /* do subroutine call */ - archive_backtrace("BSI"); /* save info in back-trace buffer */ - IAR = (eaddr + 1) & mem_mask; - break; - - case 0x09: /* --- BSC - Branch and skip on Condition --- */ - if (F) { - if (bsctest(IR, F)) /* long format; any indicator cancels branch */ - break; - - archive_backtrace((DSPLC & 0x40) ? "BOSC" : "BSC"); /* save info in back-trace buffer */ - IAR = eaddr; /* no indicator means branch taken */ - } - else { /* short format: skip if any indicator hits */ - if (bsctest(IR, F)) { - archive_backtrace((DSPLC & 0x40) ? "BOSC" : "BSC"); /* save info in back-trace buffer */ - INCREMENT_IAR; - } - } -// 27Mar02: moved this test out of the (F) condition; BOSC works even in the -// short form. The displacement field in this instruction is always the set of -// condition bits, and the interrupt clear bit doesn't collide. - if (DSPLC & 0x40) { /* BOSC = exit from interrupt handler */ - exit_irq(); - cwincount = 0; - } - break; - - case 0x0c: /* --- LDX - Load Index --- */ - if (F) - eaddr = (INDIR) ? ReadW(word2) : word2; - else - eaddr = DSPLC; - - if (TAG) - WriteW(TAG, eaddr); - else { - archive_backtrace("LDX"); /* save info in back-trace buffer */ - IAR = eaddr; /* what happens in short form? can onlyjump to low addresses? */ - } - break; - - case 0x0d: /* --- STX - Store Index --- */ - if (F) { /* compute EA without any indexing */ - eaddr = (INDIR) ? ReadW(word2) : word2; - } - else { - eaddr = IAR + DSPLC; - } - WriteW(eaddr, TAG ? ReadW(TAG) : IAR); - break; - - case 0x0e: /* --- MDX - Modify Index and Skip --- */ - if (F) { /* long mode: adjust memory location */ - if (TAG) { - oldval = ReadW(TAG); /* add word2 to index */ - newval = oldval + (INDIR ? ReadW(word2) : word2); - WriteW(TAG, newval); - } - else { - oldval = ReadW(word2); - DSPLC = IR & 0x00FF; /* use extended displacement (includes INDIR bit) */ - if (DSPLC & 0x0080) - DSPLC |= ~ 0xFF; - newval = oldval + DSPLC; /* add modifier to @word2 */ - WriteW(word2, newval); - } - } - else { /* short mode: adust IAR or index */ - if (TAG) { - oldval = ReadW(TAG);/* add displacement to index */ - newval = oldval + DSPLC; - WriteW(TAG, newval); - } - else { - oldval = IAR; /* add displacement to IAR */ - newval = IAR + DSPLC; - archive_backtrace("MDX"); - IAR = newval & mem_mask; - } - } - - if ((F || TAG) && (((newval & 0xFFFF) == 0) || ((oldval & 0x8000) != (newval & 0x8000)))) { - archive_backtrace("SKP"); - INCREMENT_IAR; /* skip if index sign change or zero */ - } - break; - - case 0x10: /* --- A - Add --- */ - /* in adds and subtracts, carry is set or cleared, overflow is set only */ - src = ReadW(eaddr); - src2 = ACC; - ACC = (ACC + src) & 0xFFFF; - - C = ACC < src; - if (! V) - V = SIGN_BIT((~src ^ src2) & (src ^ ACC)); - break; - - case 0x11: /* --- AD - Add Double --- */ - src = ((ACC << 16) | (EXT & 0xFFFF)); - src2 = (ReadW(eaddr) << 16) + ReadW(eaddr|1); - dst = src + src2; - ACC = (dst >> 16) & 0xFFFF; - EXT = dst & 0xFFFF; - - C = (unsigned int32) dst < (unsigned int32) src; - if (! V) - V = DWSIGN_BIT((~src ^ src2) & (src ^ dst)); - break; - - case 0x12: /* --- S - Subtract --- */ - src = ACC; - src2 = ReadW(eaddr); - ACC = (ACC-src2) & 0xFFFF; - - C = src2 < src; - if (! V) - V = SIGN_BIT((src ^ src2) & (src ^ ACC)); - break; - - case 0x13: /* --- SD - Subtract Double --- */ - src = ((ACC << 16) | (EXT & 0xFFFF)); - src2 = (ReadW(eaddr) << 16) + ReadW(eaddr|1); - dst = src - src2; - ACC = (dst >> 16) & 0xFFFF; - EXT = dst & 0xFFFF; - - C = (unsigned int32) src2 < (unsigned int32) src; - if (! V) - V = DWSIGN_BIT((src ^ src2) & (src ^ dst)); - break; - - case 0x14: /* --- M - Multiply --- */ - if ((src = ACC & 0xFFFF) & 0x8000) /* sign extend the values */ - src |= ~0xFFFF; - if ((src2 = ReadW(eaddr)) & 0x8000) - src2 |= ~0xFFFF; - - dst = src * src2; - ACC = (dst >> 16) & 0xFFFF; /* split the results */ - EXT = dst & 0xFFFF; - break; - - case 0x15: /* --- D - Divide --- */ - src = ((ACC << 16) | (EXT & 0xFFFF)); - if ((src2 = ReadW(eaddr)) & 0x8000) - src2 |= ~0xFFFF; /* oops: sign extend was missing, fixed 18Mar03 */ - - if (src2 == 0) - V = 1; /* divide by zero just sets overflow, ACC & EXT are undefined */ - else { - ACC = (src / src2) & 0xFFFF; - EXT = (src % src2) & 0xFFFF; - } - break; - - case 0x18: /* --- LD - Load ACC --- */ - ACC = ReadW(eaddr); - break; - - case 0x19: /* --- LDD - Load Double --- */ - ACC = ReadW(eaddr); - EXT = ReadW(eaddr|1); /* notice address is |1 not +1 */ - break; - - case 0x1a: /* --- STO - Store ACC --- */ - WriteW(eaddr, ACC); - break; - - case 0x1b: /* --- STD - Store Double --- */ - WriteW(eaddr|1, EXT); - WriteW(eaddr, ACC); /* order is important: if odd addr, only ACC is stored */ - break; - - case 0x1c: /* --- AND - Logical AND --- */ - ACC &= ReadW(eaddr); - break; - - case 0x1d: /* --- OR - Logical OR --- */ - ACC |= ReadW(eaddr); - break; - - case 0x1e: /* --- EOR - Logical Excl OR --- */ - ACC ^= ReadW(eaddr); - break; - - default: -/* all invalid instructions act like waits */ -/* case 0x00: */ -/* case 0x07: */ -/* case 0x0a: */ -/* case 0x0b: */ -/* case 0x0e: */ -/* case 0x0f: */ -/* case 0x16: */ -/* case 0x17: */ -/* case 0x1f: */ - wait_state = WAIT_INVALID_OP; - if (F) - DECREMENT_IAR; /* assume it wouldn't have fetched 2nd word? */ - - break; - } /* end instruction decode switch */ - - if (RUNMODE != MODE_RUN && RUNMODE != MODE_INT_RUN) - reason = STOP_WAIT; - - if (tbit && (ipl < 0)) { /* if INT_RUN mode, set IRQ5 after this instr */ - GUI_BEGIN_CRITICAL_SECTION - SETBIT(cpu_dsw, CPU_DSW_INT_RUN); - SETBIT(ILSW[5], ILSW_5_INT_RUN); - int_req |= INT_REQ_5; - GUI_END_CRITICAL_SECTION - } - } /* end main loop */ - -#ifdef GUI_SUPPORT - gui_run(FALSE); -#endif - - running = FALSE; - int_lamps = 0; /* display only currently active interrupts while halted */ - - if (reason == STOP_WAIT || reason == STOP_INVALID_INSTR) { - wait_state = 0; // on resume, don't wait - wait_lamp = TRUE; // but keep the lamp lit on the GUI - } - -#ifdef CGI_SUPPORT - if (cgi) - cgi_stop(reason); -#endif - - return reason; -} - -/* ------------------------------------------------------------------------ - * bsctest - perform standard set of condition tests. We return TRUE if any - * of the condition bits specified in DSPLC test positive, FALSE if none are true. - * If reset_V is TRUE, we reset the oVerflow flag after testing it. - * ------------------------------------------------------------------------ */ - -static t_bool bsctest (int32 DSPLC, t_bool reset_V) -{ - if (DSPLC & 0x01) { /* Overflow off (note inverted sense) */ - if (! V) - return TRUE; - else if (reset_V) /* reset after testing */ - V = 0; - } - - if (DSPLC & 0x02) { /* Carry off (note inverted sense) */ - if (! C) - return TRUE; - } - - if (DSPLC & 0x04) /* Even */ - if ((ACC & 1) == 0) - return TRUE; - - if (DSPLC & 0x08) /* Positive */ - if ((ACC & 0x8000) == 0 && ACC != 0) - return TRUE; - - if (DSPLC & 0x10) /* Negative */ - if (ACC & 0x8000) - return TRUE; - - if (DSPLC & 0x20) /* Zero */ - if ((ACC & 0xFFFF) == 0) - return TRUE; - - return FALSE; -} - -/* ------------------------------------------------------------------------ - * exit_irq - pop interrupt stack as part of return from subroutine (BOSC) - * ------------------------------------------------------------------------ */ - -static void exit_irq (void) -{ - int i, bit; - - GUI_BEGIN_CRITICAL_SECTION - - ipl = -1; /* default: return to main processor level */ - int_mask = 0xFFFF; - - if (iplpending) { /* restore previous interrupt status */ - for (i = 0, bit = 0x20; i < 6; i++, bit >>= 1) { - if (iplpending & bit) { - iplpending &= ~bit; - ipl = i; - int_mask = int_masks[i]; - break; - } - } - } - GUI_END_CRITICAL_SECTION - - calc_ints(); /* recompute pending interrupt mask */ -} /* because we probably cleared some ILSW bits before this instruction */ - -/* let a device halt the simulation */ - -void break_simulation (t_stat stopreason) -{ - reason = stopreason; -} - -/* ------------------------------------------------------------------------ - * SIMH required routines - * ------------------------------------------------------------------------ */ - -/* ------------------------------------------------------------------------ - * Reset routine - * ------------------------------------------------------------------------ */ - -t_stat cpu_reset (DEVICE *dptr) -{ - wait_state = 0; /* cancel wait */ - wait_lamp = TRUE; /* but keep the wait lamp lit on the GUI */ - - if (cpu_unit.flags & UNIT_ATT) { /* record reset in CPU log */ - fseek(cpu_unit.fileref, 0, SEEK_END); - fprintf(cpu_unit.fileref, "---RESET---" CRLF); - } - - GUI_BEGIN_CRITICAL_SECTION - - reset_backtrace(); - - ipl = -1; - int_mask = 0xFFFF; - int_req = 0; /* hmmm, it SHOULD reset the int req, right? */ - int_lamps = 0; - iplpending = 0; - memset(ILSW, 0, sizeof(ILSW)); - - cpu_dsw = 0; /* clear int req and prot stop bits */ - tbit = 0; /* cancel INT_RUN mode */ - - C = V = 0; /* clear processor flags */ - IAR = SAR = SBR = 0; /* clear IAR and other registers */ - ACC = EXT = OP = TAG = CCC = C = V = 0; - - mem_mask = MEMSIZE - 1; /* wraparound mask */ - - GUI_END_CRITICAL_SECTION - - return cpu_svc(&cpu_unit); /* reset breakpoint */ -} - -/* ------------------------------------------------------------------------ - * Memory examine - * ------------------------------------------------------------------------ */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ - if (vptr == NULL) return SCPE_ARG; - - /* check this out -- save command hits it in weird way */ - /* I wish I remembered what I meant when I wrote that */ - if (addr < MEMSIZE) { - *vptr = M[addr] & 0xFFFF; - return SCPE_OK; - } - return SCPE_NXM; -} - -/* ------------------------------------------------------------------------ - * Memory deposit - * ------------------------------------------------------------------------ */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ - if (addr < MEMSIZE) { - M[addr] = val & 0xFFFF; - return SCPE_OK; - } - return SCPE_NXM; -} - -/* ------------------------------------------------------------------------ - * Breakpoint service - * ------------------------------------------------------------------------ */ - -t_stat cpu_svc (UNIT *uptr) -{ - if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt) - ibkpt_addr = save_ibkpt; - - save_ibkpt = -1; - return SCPE_OK; -} - -/* ------------------------------------------------------------------------ - * Memory allocation - * ------------------------------------------------------------------------ */ - -t_stat cpu_set_size (UNIT *uptr, int32 value, char *cptr, void *desc) -{ - t_bool used; - int32 i; - - if ((value <= 0) || (value > MAXMEMSIZE) || ((value & 0xFFF) != 0)) - return SCPE_ARG; - - for (i = value, used = FALSE; i < (int32) MEMSIZE; i++) { - if (M[i] != 0) { - used = TRUE; - break; - } - } - - if (used && ! get_yn ("Really truncate memory [N]?", FALSE)) - return SCPE_OK; - - for (i = MEMSIZE; i < value; i++) /* clear expanded area */ - M[i] = 0; - - MEMSIZE = value; - mem_mask = MEMSIZE - 1; - - return SCPE_OK; -} - -/* ------------------------------------------------------------------------ - * IO function for console switches - * ------------------------------------------------------------------------ */ - -void xio_1131_switches (int32 addr, int32 func, int32 modify) -{ - char msg[80]; - - switch (func) { - case XIO_READ: - WriteW(addr, CES); - break; - - case XIO_SENSE_DEV: - ACC = cpu_dsw; - if (modify & 0x01) { /* reset interrupts */ - CLRBIT(cpu_dsw, CPU_DSW_PROGRAM_STOP|CPU_DSW_INT_RUN); - CLRBIT(ILSW[5], ILSW_5_INT_RUN); /* (these bits are set in the keyboard handler in 1130_stddev.c) */ - } - break; - - default: - sprintf(msg, "Invalid console switch function %x", func); - xio_error(msg); - } -} - -/* ------------------------------------------------------------------------ - * Illegal IO operation. Not yet sure what the actual CPU does in this case - * ------------------------------------------------------------------------ */ - -void xio_error (char *msg) -{ - printf("*** XIO error at %04x: %s\n", prev_IAR, msg); - if (cgi) - break_simulation(STOP_CRASH); -} - -/* ------------------------------------------------------------------------ - * register_cmd - add a command to the extensible command table - * ------------------------------------------------------------------------ */ - -t_stat register_cmd (char *name, t_stat (*action)(int32 flag, char *ptr), int arg, char *help) -{ - int i; - - for (i = 0; i < MAX_EXTRA_COMMANDS; i++) { // find end of command table - if (x_cmds[i].action == action) - return SCPE_OK; // command is already there, just return - if (x_cmds[i].name == NULL) - break; - } - - if (i >= (MAX_EXTRA_COMMANDS-1)) { // no more room (we need room for the NULL) - fprintf(stderr, "The command table is full - rebuild the simulator with more free slots\n"); - return SCPE_ARG; - } - - x_cmds[i].action = action; // add new command - x_cmds[i].name = name; - x_cmds[i].arg = arg; - x_cmds[i].help = help; - - i++; - x_cmds[i].action = NULL; // move the NULL terminator - x_cmds[i].name = NULL; - - return SCPE_OK; -} - -/* ------------------------------------------------------------------------ - * echo_cmd - just echo the command line - * ------------------------------------------------------------------------ */ - -static t_stat echo_cmd (int flag, char *cptr) -{ - printf("%s\n", cptr); - return SCPE_OK; -} - -/* ------------------------------------------------------------------------ - * sim_init - initialize simulator upon startup of scp, before reset - * ------------------------------------------------------------------------ */ - -void sim_init (void) -{ - sim_gui = ! (sim_switches & SWMASK('G')); /* -g means no GUI */ - - sim_vm_cmd = x_cmds; /* provide list of additional commands */ - -#ifdef GUI_SUPPORT - // set hook routines for GUI command processing - if (sim_gui) { - sim_vm_read = &read_cmdline; - sim_vm_post = &update_gui; - } -#endif - -#ifdef ENABLE_BACKTRACE - // add the BACKTRACE command - register_cmd("BACKTRACE", &backtrace_cmd, 0, "ba{cktrace} {n} list last n branches/skips/interrupts\n"); -#endif - - register_cmd("VIEW", &view_cmd, 0, "v{iew} filename view a text file with notepad\n"); - -#ifdef CGI_SUPPORT - register_cmd("CGI", &cgi_cmd, 0, "cgi run simulator in CGI mode\n"); -#endif - - register_cmd("ECHO", &echo_cmd, 0, "echo args... echo arguments passed to command\n"); -} - -/* ------------------------------------------------------------------------ - * archive_backtrace - record a jump, skip, branch or whatever - * ------------------------------------------------------------------------ */ - -#ifdef ENABLE_BACKTRACE - -#define MAXARCHIVE 16 - -static struct tag_arch { - int iar; - char *inst; -} arch[MAXARCHIVE]; -int narchived = 0, archind = 0; - -static void archive_backtrace (char *inst) -{ - static int prevind; - - if (narchived < MAXARCHIVE) - narchived++; - - if (narchived > 0 && arch[prevind].iar == prev_IAR) - return; - - arch[archind].iar = prev_IAR; - arch[archind].inst = inst; - - prevind = archind; - archind = (archind+1) % MAXARCHIVE; -} - -static void reset_backtrace (void) -{ - narchived = 0; - archind = 0; -} - -void void_backtrace (int afrom, int ato) -{ - int i; - - afrom &= mem_mask; - ato &= mem_mask; - - for (i = 0; i < narchived; i++) - if (arch[i].iar >= afrom && arch[i].iar <= ato) - arch[i].inst = "OVERWRITTEN"; -} - -static void show_backtrace (int nshow) -{ - int n = narchived, i = archind; - - if (n > nshow) n = nshow; - - while (--n >= 0) { - i = (i > 0) ? (i-1) : (MAXARCHIVE-1); - printf("from %04x (%s) ", arch[i].iar, arch[i].inst); - } - - if (narchived) - putchar('\n'); -} - -static t_stat backtrace_cmd (int flag, char *cptr) -{ - int n; - - if ((n = atoi(cptr)) <= 0) - n = 6; - - show_backtrace(n); - return SCPE_OK; -} -#else - -// stub this for the disk routine - -void void_backtrace (int afrom, int ato) -{ -} - -#endif - -// CPU log routines -- attaching a file to the CPU creates a trace of instructions and register values -// -// Syntax is WEIRD: -// -// attach cpu logfile log instructions and registers to file "logfile" -// attach -f cpu cpu.log log instructions, registers and floating point acc -// attach -m cpu mapfile logfile read addresses from "mapfile", log instructions to "logfile" -// attach -f -m cpu mapfile logfile same and log floating point stuff too -// -// mapfile if specified is a list of symbols and addresses of the form: -// symbol hexval -// -// e.g. -// FSIN 082E -// FARC 09D4 -// FMPY 09A4 -// NORM 0976 -// XMDS 095A -// START 021A -// -// These values are easily obtained from a load map created by -// XEQ L -// -// The log output is of the form -// -// IAR ACC EXT (flt) XR1 XR2 XR3 CVI FAC OPERATION -// --------------- ---- ---- -------- ---- ---- ---- --- ------------- ----------------------- -// 002a 002a 1234 5381 0.14222 00b3 0236 3f7e CV 1.04720e+000 4c80 BSC I ,0028 -// 081d PAUSE+000d 1234 5381 0.14222 00b3 0236 3f7e CV 1.04720e+000 7400 MDM L 00f0,0 (0) -// 0820 PAUSE+0010 1234 5381 0.14222 00b3 0236 3f7e CV 1.04720e+000 7201 MDX 2 0001 -// 0821 PAUSE+0011 1234 5381 0.14222 00b3 0237 3f7e CV 1.04720e+000 6a03 STX 2 0003 -// 0822 PAUSE+0012 1234 5381 0.14222 00b3 0237 3f7e CV 1.04720e+000 6600 LDX L2 0231 -// 0824 PAUSE+0014 1234 5381 0.14222 00b3 0231 3f7e CV 1.04720e+000 4c00 BSC L ,0237 -// 0237 START+001d 1234 5381 0.14222 00b3 0231 3f7e CV 1.04720e+000 4480 BSI I ,3fff -// 082f FSIN +0001 1234 5381 0.14222 00b3 0231 3f7e CV 1.04720e+000 4356 BSI 3 0056 -// 3fd5 ILS01+35dd 1234 5381 0.14222 00b3 0231 3f7e CV 1.04720e+000 4c00 BSC L ,08de -// -// IAR - instruction address register value, optionally including symbol and offset -// ACC - accumulator -// EXT - extension -// flt - ACC+EXT interpreted as the mantissa of a floating pt number (value 0.5 -> 1) -// XR* - index registers -// CVI - carry, overflow and interrupt indicators -// FAC - floating point accumulator (exponent at 125+XR3, mantissa at 126+XR3 and 127+XR3) -// OP - opcode value and crude disassembly -// -// flt and FAC are displayed only when the -f flag is specified in the attach command -// The label and offset and displayed only when the -m flag is specified in the attach command -// -// The register values shown are the values BEFORE the instruction is executed. -// - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw); - -typedef struct tag_symentry { - struct tag_symentry *next; - int addr; - char sym[6]; -} SYMENTRY, *PSYMENTRY; - -static PSYMENTRY syms = NULL; -static t_bool new_log, log_fac; - -static t_stat cpu_attach (UNIT *uptr, char *cptr) -{ - char mapfile[200], buf[200], sym[100]; - int addr; - PSYMENTRY n, prv, s; - FILE *fd; - - unlink(cptr); // delete old log file, if present - new_log = TRUE; - log_fac = sim_switches & SWMASK ('F'); // display the FAC and the ACC/EXT as fixed point. - - for (s = syms; s != NULL; s = n) { // free any old map entries - n = s->next; - free(s); - } - syms = NULL; - - if (sim_switches & SWMASK('M')) { // use a map file to display relative addresses - cptr = get_glyph(cptr, mapfile, 0); - if (! *mapfile) { - printf("/m must be followed by a filename\n"); - return SCPE_ARG; - } - if ((fd = fopen(mapfile, "r")) == NULL) { - perror(mapfile); - return SCPE_OPENERR; - } - - while (fgets(buf, sizeof(buf), fd) != NULL) { // read symbols & addresses, link in descending address order - if (sscanf(buf, "%s %x", sym, &addr) != 2) - continue; - if (*buf == ';') - continue; - - for (prv = NULL, s = syms; s != NULL; prv = s, s = s->next) { - if (s->addr < addr) - break; - } - - if ((n = malloc(sizeof(SYMENTRY))) == NULL) { - printf("out of memory reading map!\n"); - break; - } - - sym[5] = '\0'; - strcpy(n->sym, sym); - upcase(n->sym); - n->addr = addr; - - if (prv == NULL) { - n->next = syms; - syms = n; - } - else { - n->next = prv->next; - prv ->next = n; - } - } - fclose(fd); - } - - return attach_unit(uptr, cptr); -} - -static void trace_instruction (void) -{ - t_value v[2]; - float fac; - short exp; - int addr; - PSYMENTRY s; - long mant, sign; - char facstr[20], fltstr[20]; - - if ((cpu_unit.flags & UNIT_ATT) == 0) - return; - - if (new_log) { - fseek(cpu_unit.fileref, 0, SEEK_END); - new_log = FALSE; - - fprintf(cpu_unit.fileref, " IAR%s ACC EXT %s XR1 XR2 XR3 CVI %sOPERATION" CRLF, - syms ? " " : "", log_fac ? " (flt) " : "", log_fac ? " FAC " : ""); - fprintf(cpu_unit.fileref, "----%s ---- ---- %s---- ---- ---- --- %s-----------------------" CRLF, - syms ? "-----------" : "", log_fac ? "-------- " : "", log_fac ? "------------- " : ""); - } - - if (! log_fac) - facstr[0] = fltstr[0] = '\0'; - else { - mant = ((ACC & 0xFFFF) << 16) | (EXT & 0xFFFF); - if (mant == 0x80000000) { - sign = TRUE; - fac = 1.f; - } - else { - if ((sign = mant & 0x80000000)) - mant = -mant; - fac = (float) mant * ((float) 1./ (float) (unsigned long) 0x80000000); - } - sprintf(fltstr, "%c%.5f ", sign ? '-' : ' ', fac); - - if (BETWEEN(M[3], 0x300, MEMSIZE-128)) { - exp = (M[M[3]+125] & 0xFF) - 128; - mant = (M[M[3]+126] << 8) | ((M[M[3]+127] >> 8) & 0xFF); - if ((sign = (mant & 0x00800000))) - mant = (-mant) & 0x00FFFFFF; - - fac = (float) mant * ((float) 1. / (float) 0x00800000); - - if (exp > 30) { - fac *= (float) (1 << 30); - exp -= 30; - while (exp > 0) - fac *= 2; - } - else if (exp > 0) - fac *= (float) (1 << exp); - else if (exp < -30) { - fac /= (float) (1 << 30); - exp += 30; - while (exp < 0) - fac /= 2; - } - else if (exp < 0) - fac /= (float) (1 << -exp); - - sprintf(facstr, "%c%.5e ", sign ? '-' : ' ', fac); - } - else - strcpy(facstr, " "); - } - - addr = IAR & 0xFFFF; - fprintf(cpu_unit.fileref, "%04x ", addr); - - if (syms) { - for (s = syms; s != NULL; s = s->next) - if (s->addr <= addr) - break; - - if (s == NULL) - fprintf(cpu_unit.fileref, " %04x ", addr); - else - fprintf(cpu_unit.fileref, "%-5s+%04x ", s->sym, addr - s->addr); - } - - fprintf(cpu_unit.fileref, "%04x %04x %s%04x %04x %04x %c%c%c %s", - ACC & 0xFFFF, EXT & 0xFFFF, fltstr, M[1] & 0xFFFF, M[2] & 0xFFFF, M[3] & 0xFFFF, - C ? 'C' : ' ', V ? 'V' : ' ', (ipl < 0) ? ' ' : (ipl+'0'), facstr); - - v[0] = M[ IAR & mem_mask]; - v[1] = M[(IAR+1) & mem_mask]; - fprint_sym(cpu_unit.fileref, IAR & mem_mask, v, NULL, SWMASK('M')); /* disassemble instruction */ - - fputs(CRLF, cpu_unit.fileref); -} - -void trace_io (char *fmt, ...) -{ - va_list args; - - if ((cpu_unit.flags & UNIT_ATT) == 0) - return; - - va_start(args, fmt); // get pointer to argument list - vfprintf(cpu_unit.fileref, fmt, args); // write errors to terminal (stderr) - va_end(args); - - fputs(CRLF, cpu_unit.fileref); -} - -/* debugging */ - -void debug_print (char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vprintf(fmt, args); - if (cpu_unit.flags & UNIT_ATT) - vfprintf(cpu_unit.fileref, fmt, args); - va_end(args); - - if (strchr(fmt, '\n') == NULL) { // be sure to emit a newline - putchar('\n'); - if (cpu_unit.flags & UNIT_ATT) - putc('\n', cpu_unit.fileref); - } -} - -#ifdef WIN32 -#include -#endif - -// view_cmd - let user view and/or edit a file (e.g. a printer output file, script, or source deck) - -static t_stat view_cmd (int flag, char *cptr) -{ -#ifdef WIN32 - char cmdline[256]; - - sprintf(cmdline, "notepad %s", cptr); - WinExec(cmdline, SW_SHOWNORMAL); -#endif - return SCPE_OK; -} - -#ifdef CGI_SUPPORT - -int cgi_maxsec = 0; // default run time limit - -// cgi_cmd - enable cgi mode. Specify time limit on command line if desired - -static t_stat cgi_cmd (int flag, char *cptr) -{ - cgi = TRUE; // set CGI flag - - while (*cptr && *cptr <= ' ') - cptr++; - - if (*cptr) - cgi_maxsec = atoi(cptr); // set time limit, if specified - - return SCPE_OK; -} - -// cgi_timeout - called when timer runs out - -static void cgi_timeout (int dummy) -{ - break_simulation(STOP_TIMED_OUT); // stop the simulator -} - -// cgi_clockfail - report failure to set alarm - -static void cgi_clockfail (void) -{ - printf("Set CGI time limit failed!"); -} - -// cgi_start_timer - OS dependent routine to set things up so that -// cgi_timeout() will be called after cgi_maxsec seconds. - -#if defined(WIN32) - static DWORD WINAPI cgi_timer_thread (LPVOID arg) - { - Sleep(cgi_maxsec*1000); // timer thread -- wait, then call timeout routine - cgi_timeout(0); - return 0; - } - - static void cgi_start_timer (void) - { - DWORD dwThreadID; - - if (CreateThread(NULL, 0, cgi_timer_thread, NULL, 0, &dwThreadID) == NULL) - cgi_clockfail(); - } -#else - #include - - #if defined(SIGVTALRM) && defined(ITMER_VIRTUAL) - - // setitimer counts actual runtime CPU seconds, so is insensitive to - // system load and is a better timer to use. Be sure to check, though, - // that it actually works on your OS. Note that time spent performing - // I/O does not count -- this counts user mode CPU time only, so - // the elapsed time it allows could be much larger, especially if - // the job is spewing output. - - #include - - static void cgi_start_timer (void) - { - struct itimerval rtime, otime; - - rtime.it_value.tv_sec = cgi_maxsec; - rtime.it_value.tv_usec = 0; - rtime.it_interval.tv_sec = cgi_maxsec; - rtime.it_interval.tv_usec = 0; - - if (signal(SIGVTALRM, cgi_timeout) == SIG_ERR) // set alarm handler - cgi_clockfail(); - else if (setitimer(ITIMER_VIRTUAL, &rtime, &otime)) // start timer - cgi_clockfail(); - } - - #elif defined(SIGALRM) - #include - - // if it's all we have, standard POSIX alarm will do the trick too - - static void cgi_start_timer (void) - { - if (signal(SIGALRM, cgi_timeout) == SIG_ERR) // set alarm handler - cgi_clockfail(); - else if (alarm(cgi_maxsec)) // start timer - cgi_clockfail(); - } - - #else - // don't seem to have a clock available. Better say so. - - static void cgi_start_timer (void) - { - printf("CGI time limit is not supported by this build\n"); - } - - #endif -#endif - -static void cgi_start(void) -{ - if (cgi_maxsec > 0) // if time limit was specified, set timer now - cgi_start_timer(); - -// printf("Content-type: text/html\n\n\n\n IBM 1130 Simulation Results\n\n\n

");
-}
-
-static void cgi_stop(t_stat reason)
-{
-	typedef enum {O_END, O_FORTRAN, O_MONITOR} ORIGIN;
-	char *errmsg = "";
-	static struct tag_pretstop {
-		int acc;
-		ORIGIN orig;
-		char *msg;
-	} pretstop[] = {
-		0xF000, O_FORTRAN, "No *IOCS was specified but I/O was attempted",
-		0xF001, O_FORTRAN, "Local unit defined incorrectly, or no *IOCS for specified device",
-		0xF002, O_FORTRAN, "Requested record exceeds buffer size",
-		0xF003, O_FORTRAN, "Illegal character encountered in input record",
-		0xF004, O_FORTRAN, "Exponent too large or too small in input",
-		0xF005, O_FORTRAN, "More than one exponent encountered in input",
-		0xF006, O_FORTRAN, "More than one sign encountered in input",
-		0xF007, O_FORTRAN, "More than one decimal point encountered in input",
-		0xF008, O_FORTRAN, "Read of output-only device, or write to input-only device",
-		0xF009, O_FORTRAN, "Real variable transmitted with I format or integer transmitted with E or F",
-		0xF020, O_FORTRAN, "Illegal unit reference",
-		0xF021, O_FORTRAN, "Read list exceeds length of write list",
-		0xF022, O_FORTRAN, "Record does not exist in read list",
-		0xF023, O_FORTRAN, "Maximum length of $$$$$ area on disk has been exceeded",
-		0xF024, O_FORTRAN, "*IOCS (UDISK) was not specified",
-		0xF100, O_FORTRAN, "File not defined by DEFINE FILE statement",
-		0xF101, O_FORTRAN, "File record number too large, zero or negative",
-		0xF103, O_FORTRAN, "*IOCS(DISK) was not specified",
-		0xF105, O_FORTRAN, "Length of a list element exceeds record length in DEFINE FILE",
-		0xF107, O_FORTRAN, "Attempt to read or write an invalid sector address (may occur if a core image program is run with too little room in working storage)",
-		0xF10A, O_FORTRAN, "Define file table and/or core image header corrupted, probably by an out-of-bounds array subscript",
-		0x1000, O_MONITOR, "1442 card read/punch or 1442 punch: not ready or hopper empty. [emulator: attach a file to CR or CP and go]",
-		0x1001, O_MONITOR, "Illegal device, function or word count",
-		0x100F, O_MONITOR, "Occurs in a DUP operation after DUP error D112",
-		0x2000, O_MONITOR, "Keyboard/Console Printer not ready",
-		0x2001, O_MONITOR, "Illegal device, function or word count",
-		0x3000, O_MONITOR, "1134/1055 Paper Tape not ready",
-		0x3001, O_MONITOR, "Illegal device, function or word count, or invalid check digit",
-		0x4000, O_MONITOR, "2501 Card Reader not ready",
-		0x4001, O_MONITOR, "Illegal device, function or word count",
-		0x5000, O_MONITOR, "Disk not ready",
-		0x5001, O_MONITOR, "Illegal device, function or word count, or attempt to write in protected area",
-		0x5002, O_MONITOR, "Write select or power unsafe",
-		0x5003, O_MONITOR, "Read/write/seek failure after 16 attempts or disk overflow. Extension may display logical drive number in bits 0..3 and working storage address in bits 4..15. Program Start retries 16 more times.",
-		0x5004, O_MONITOR, "Same as above from routine DISK1 and DISKN, or, an uninitialized cartridge is online during a cold start.",
-		0x6000, O_MONITOR, "1132 Printer not ready or out of paper",
-		0x6001, O_MONITOR, "Illegal device, function or word count",
-		0x7000, O_MONITOR, "1627 Plotter not ready",
-		0x7001, O_MONITOR, "Illegal device, function or word count",
-		0x8001, O_MONITOR, "SCA error: Illegal function or word count",
-		0x8002, O_MONITOR, "SCA error: if STR mode, receive or transmit operation not completed;\n"
-						   "if BSC mode, invalid start characters in the I/O area for a transmit operation",
-		0x8003, O_MONITOR, "SCA error: if STR mode, failed to synchronize before attempt to read or write, or, attempted to receive before receiving INQ sequence;\n"
-						   "if BSC mode, invalid number of identification characters for an identification specification operation",
-		0x9000, O_MONITOR, "1403 printer no ready or out of paper",
-		0x9001, O_MONITOR, "Illegal device, function or word count",
-		0x9002, O_MONITOR, "Parity check, scan check or ring check",
-		0xA000, O_MONITOR, "1231 Optical Mark Reader not ready",
-		0xA001, O_MONITOR, "Illegal device, function or word count",
-		0xA002, O_MONITOR, "Feed check, last document was processed. Clear jam, do not refeed",
-		0xA003, O_MONITOR, "Feed check, last document not  processed. Clear jam and refeed",
-		0,      O_END, 	   NULL
-	};
-	int i;
-
-	detach_cmd(0, "prt");		/* flush last print line */
-
-	if (reason == STOP_TIMED_OUT)
-		printf("\n
Sorry, emulation run time exceeded %d second%s\n", cgi_maxsec, (cgi_maxsec == 1) ? "" : "s"); - else if (IAR != 0x2a || ACC != 0x1000) { - ACC &= 0xFFFF; - for (i = 0; pretstop[i].orig != O_END; i++) { - if (pretstop[i].acc == ACC) { - errmsg = pretstop[i].msg; - break; - } - } - printf("\n
Abnormal exit: %s\nIAR = %04x, ACC = %04x\n", errmsg, IAR, ACC); - } - -// printf("
\n\n\n"); - exit(0); /* save w/o writing disk image */ -} - -#endif // ifdef CGI_SUPPORT diff --git a/Ibm1130/ibm1130_cr.c b/Ibm1130/ibm1130_cr.c deleted file mode 100644 index 283d107c..00000000 --- a/Ibm1130/ibm1130_cr.c +++ /dev/null @@ -1,2079 +0,0 @@ -#include "ibm1130_defs.h" -#include "ibm1130_fmt.h" - -/* ibm1130_cr.c: IBM 1130 1442 Card Reader simulator - - Based on the SIMH package written by Robert M Supnik - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - - * Update 2003-07-23: Added autodetect for card decks (029 vs binary), - made this the default. - - * Update 2003-06-21: Fixed bug in XIO_SENSE: op_complete and response - bits were being cleared before the DSW was saved in ACC. Somehow DMS - worked with this, but APL didn't. - - * Update 2002-02-29: Added deck-list option. - - * Update 2003-02-08: Fixed error in declaration of array list_save, pointed - out by Ray Comas. - -* ----------------------------------------------------------------------- -* USAGE NOTES -* ----------------------------------------------------------------------- - -* Attach switches: - - The ATTACH CR command accepts several command-line switches - - -q quiet mode, the simulator will not print the name of each file it opens - while processing deck files (which are discussed below). For example, - - ATTACH -q @deckfile - - -l makes the simulator convert lower case letters in text decks - to the IBM lower-case Hollerith character codes. Normally, the simulator - converts lower case input to the uppercase Hollerith character codes. - (Lowercase codes are used in APL\1130 save decks). - - -d prints a lot of simulator debugging information - - -f converts tabs in an ascii file to spaces according to Fortran column conventions - -a converts tabs in an ascii file to spaces according to 1130 Assembler column conventions - -t converts tabs in an ascii file to spaces, with tab settings every 8 columns - - (See below for a discussion of tab formatting) - - The ATTACH CP command accepts the -d switch. - -* Deck lists - If you issue an attach command and specify the filename as - "@filename", the file is interpreted as a list of filenames to - be read in sequence; the effect is that the reader sees the concatenation - of all of the files listed. The simulator "reset" does NOT rewind the deck list. - - Filenames may be quoted if they contain spaces. - - The strings %1, %2, etc, if they appear, are replaced with arguments passed - on the attach command line after the name of the deckfile. These can be the - arguments to ibm1130, or to the "do" command if a "do" script is executing, if the - attach command is constructed this way: - - attach @deckfile %1 %2 %3 - - This will pass the ibm1130 or do script arguments to attach, which will make - them available in the deckfile. Then, for instance the line - - %1.for - - would be substituted accordingly. - - Blank lines and lines starting with ; # or * are ignored as comments. - - Filenames may be followed by whitespace and one or more mode options: - The mode options are: - - b forces interpration as raw binary - a forces conversion from ascii to 029 coding, tabs are left alone - af forces 029 ascii conversion, and interprets tabs in Fortran mode - aa forces 029 ascii conversion, and interprets tabs in 1130 Assembler mode - at forces 029 ascii conversion, and interprets tabs with settings every 8 spaces - - If "a" or "b" mode is not specified, the device mode setting is used. In this case, - if the mode is "auto", the simulator will select binary or 029 by inspecting each - file in turn. - - If a tab mode is not specified, tabs are left unmolested (and are treated as invalid characters) - - Example: - - attach cr @decklist - - reads filenames from file "decklist," which might contain: - - file01.for xf - file02.dat a - file03 bin b - file04 bin - - ('a' means 029, so, if you need 026 coding, specify the - device default as the correct 026 code and omit the 'a' on the text files lines). - - Literal text cards can be entered in deck files by preceding an input - line with an exclamation point. For example, - - !// JOB - !// FOR - program.for - !// XEQ - program.dat - - looks like two literal supervisor control cards, followed by the contents - of file program.for, followed by an // XEQ card, followed by the contents - of file program.dat. - - %n tokens are not replaced in literal cards. - - The line - - !BREAK - - has a special meaning: when read from a deck file, it stops the - emulator as if "IMMEDIATE STOP" was pressed. This returns control to - the command interpreter or to the current DO command script. - -* Card image format. - Card files can be ascii text or binary. There are several ASCII modes: - CODE_029, CODE_26F, etc, corresponding to different code sets. - Punch and reader modes can be set independently using - - set cr binary set cp binary * - set cr 029 set cp 029 - set cr 026f set cp 026f - set cr 026c set cp 026c - set cr auto * - - (* = default mode) - - In "auto" mode, the card reader will examine the first 160 bytes of - the deck and guess whether the card is binary or 029 text encoded. - When a deck file is used with auto mode, the simulator guesses for - each file named in the deck file. - -* Tab formatting. The attach command and deckfile entries can indicate - that tabs are to be converted to spaces, to help let you write free-form - source files. There are three tab conversion modes, which are set - with the attach command or in a decklist, as discussed earlier - - Fortran mode: - Input lines of the form - - [label]statement - - or - - [label]+continuation - - (where + is any nonalphabetic character) are rearranged in the - appropriate manner: - - 1 2 - 12345678901234567890... - ------------------------ - label statement - label+continuation - - However, you must take care that you don't end up with statement text after column 72. - - Input lines with * or C in column 1 (comments and directives) and lines without tabs - are left alone. - - (The ! escape is not used before Fortran directives as before Assembler directives) - - Assembler mode: - Input lines of the form - - [label][opcode][tag][L][argument] - - are rearranged so that the input fields are placed in the appropriate columns - - The label must start on the first character of the line. If there is no label, - the first character(s) before the opcode must be whitespace. Following the opcode, there - MUST be a tab character, followed by the format and tag. Following the format and tag - may be exactly one whitespace character, and then starts the argument. - - Input lines with * in column 1 and blank lines are turned into Assembler comments, - with the * in the Opcode field. - - Assembler directive lines at the beginning of the deck must be preceded by - ! to indicate that they are not comments. For example, - - !*LIST - * This is a comment - - Plain Tab mode: - Tabs are replaced with spaces. Tab settings are assumed to be eight characters wide, - as is standard for vi, notepad, etc. - -* CGI mode note: The command - - attach cr - - - will attach the card reader to stdin. However, this is not compatible - with the default encoding autodetect feature, so the command must be - preceded with - - set cr 029 - -* ----------------------------------------------------------------------- -* PROGRAMMING NOTES -* ----------------------------------------------------------------------- - -NOTE - there is a problem with this code. The Device Status Word (DSW) is -computed from current conditions when requested by an XIO load status -command; the value of DSW available to the simulator's examine & save -commands may NOT be accurate. This should probably be fixed. (I think there's -a way to have the expression evaluator call a routine? That would be one -way to solve the problem, the other is to keep DSW up-to-date all the time). - - The 1442 card read/punch has several cycles: - - feed cycle: moves card from hopper to read station - card from read station to punch station - card from punch station to stacker - - read or punch: operates on card at read or punch station (but not both). - - The simulator requires input cards to be read from the file attached - to the card reader unit. A feed cycle reads one line (text mode) or - 160 bytes (binary mode) from the input file to the read station buffer, - copies the read station buffer to the punch station buffer, and if - the punch unit is attached to a file, writes the punch station buffer to - the output file. - - The read and punch cycles operate on the appropriate card buffer. - - Detaching the card punch flushes the punch station buffer if necessary. - - As does the 1442, a read or punch cycle w/o a feed cycle causes a - feed cycle first. - - A feed cycle on an empty deck (reader unattaced or at EOF) clears - the appropriate buffer, so you can punch w/o attaching a deck to - the card reader. - --- -- this may need changing depending on how things work in hardware. TBD. -|| A read cycle on an empty deck causes an error. -|| Hmmm -- what takes the place of the Start button on --- the card reader? - - Binary format is stored using fxwrite of short ints, in this format: - - 1 1 - 2 2 0 1 2 3 4 5 6 7 8 9 - * * * * * * * * * * * * 0 0 0 0 - - MSB LSB - byte 0 [ 6] [ 7] [ 8] [ 9] 0 0 0 0 - byte 1 [12] [11] [ 0] [ 1] [ 2] [ 3] [ 4] [ 5] - - This means we can read words (little endian) and get this in memory: - - 12 11 0 1 2 3 4 5 6 7 8 9 - - - - - - which is what the 1130 sees. - - ASCII can be read in blocks of 80 characters but can be terminated by newline prematurely. - - Booting: card reader IPL loads 80 columns (1 card) into memory starting - at location 0 in a split fashion: - - ________________ _ _ _ - / - 12 | - 11 | - 0 | - 1 | - 2 | - 3 | Punched card - 4 | - 5 | - 6 | - 7 | - 8 | - 9 | - +------------------ - - - - - 12 11 0 1 2 3 4 5 6 7 8 9 <- columns of cold start card - | | | | | 0 0 0 / \ | | | | | | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15| - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | OPCODE | F| Tag | DISPLACEMENT | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The zeros mean that all IPL instructions are short form, - nonindexed. The 3 column is repeated in bits 8 and 9 so - it's a sign bit. - - Boot command on a binary deck does this. Boot on an unattached - reader loads one of the built-in boot card images. Boot with an ASCII - deck isn't allowed. -*/ - -#define READ_DELAY 35 // see how small a number we can get away with -#define PUNCH_DELAY 35 -#define FEED_DELAY 25 - -// umm, this is a weird little future project of mine. -// #define ENABLE_PHYSICAL_CARD_READER_SUPPORT - -// #define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT) - -extern int32 sim_switches; -extern UNIT cpu_unit; - -static t_stat cr_svc (UNIT *uptr); -static t_stat cr_reset (DEVICE *dptr); -static t_stat cr_set_code (UNIT *uptr, int32 match, char *cptr, void *desc); -static t_stat cr_attach (UNIT *uptr, char *cptr); -static t_stat cr_detach (UNIT *uptr); -static int32 guess_cr_code (void); - -static t_stat cp_reset (DEVICE *dptr); -static t_stat cp_set_code (UNIT *uptr, int32 match, char *cptr, void *desc); -static t_stat cp_attach (UNIT *uptr, char *cptr); -static t_stat cp_detach (UNIT *uptr); - -static int16 cr_dsw = 0; /* device status word */ -static int32 cr_wait = READ_DELAY; /* read per-column wait */ -static int32 cf_wait = PUNCH_DELAY; /* punch per-column wait */ -static int32 cp_wait = FEED_DELAY; /* feed op wait */ -static int32 cr_count= 0; /* read and punch card count */ -static int32 cp_count= 0; - -#define UNIT_V_OPERATION (UNIT_V_UF + 0) /* operation in progress */ -#define UNIT_V_CODE (UNIT_V_UF + 2) /* three bits */ -#define UNIT_V_EMPTY (UNIT_V_UF + 5) -#define UNIT_V_SCRATCH (UNIT_V_UF + 6) -#define UNIT_V_QUIET (UNIT_V_UF + 7) -#define UNIT_V_DEBUG (UNIT_V_UF + 8) -#define UNIT_V_PHYSICAL (UNIT_V_UF + 9) -#define UNIT_V_LASTPUNCH (UNIT_V_UF + 10) /* used in unit_cp only */ -#define UNIT_V_LOWERCASE (UNIT_V_UF + 10) /* used in unit_cr only */ -#define UNIT_V_ACTCODE (UNIT_V_UF + 11) /* used in unit_cr only, 3 bits */ - -#define UNIT_OP (3u << UNIT_V_OPERATION) /* two bits */ -#define UNIT_CODE (7u << UNIT_V_CODE) /* three bits */ -#define UNIT_EMPTY (1u << UNIT_V_EMPTY) -#define UNIT_SCRATCH (1u << UNIT_V_SCRATCH) /* temp file */ -#define UNIT_QUIET (1u << UNIT_V_QUIET) -#define UNIT_DEBUG (1u << UNIT_V_DEBUG) -#define UNIT_PHYSICAL (1u << UNIT_V_PHYSICAL) -#define UNIT_LASTPUNCH (1u << UNIT_V_LASTPUNCH) -#define UNIT_LOWERCASE (1u << UNIT_V_LOWERCASE) /* permit lowercase input (needed for APL) */ -#define UNIT_ACTCODE (7u << UNIT_V_ACTCODE) - -#define OP_IDLE (0u << UNIT_V_OPERATION) -#define OP_READING (1u << UNIT_V_OPERATION) -#define OP_PUNCHING (2u << UNIT_V_OPERATION) -#define OP_FEEDING (3u << UNIT_V_OPERATION) - -#define SET_OP(op) {cr_unit.flags &= ~UNIT_OP; cr_unit.flags |= (op);} -#define CURRENT_OP (cr_unit.flags & UNIT_OP) - -#define CODE_AUTO (0u << UNIT_V_CODE) -#define CODE_029 (1u << UNIT_V_CODE) -#define CODE_026F (2u << UNIT_V_CODE) -#define CODE_026C (3u << UNIT_V_CODE) -#define CODE_BINARY (4u << UNIT_V_CODE) - -#define GET_CODE(un) (un.flags & UNIT_CODE) -#define SET_CODE(un,cd) {un.flags &= ~UNIT_CODE; un.flags |= (cd);} - -#define ACTCODE_029 (CODE_029 << (UNIT_V_ACTCODE-UNIT_V_CODE)) // these are used ONLY in MTAB. Elsewhere -#define ACTCODE_026F (CODE_026F << (UNIT_V_ACTCODE-UNIT_V_CODE)) // we use values CODE_xxx with macros -#define ACTCODE_026C (CODE_026C << (UNIT_V_ACTCODE-UNIT_V_CODE)) // GET_ACTCODE and SET_ACTCODE. -#define ACTCODE_BINARY (CODE_BINARY << (UNIT_V_ACTCODE-UNIT_V_CODE)) - - // get/set macros for actual-code field, these use values like CODE_029 meant for the UNIT_CODE field -#define GET_ACTCODE(un) ((un.flags & UNIT_ACTCODE) >> (UNIT_V_ACTCODE-UNIT_V_CODE)) -#define SET_ACTCODE(un,cd) {un.flags &= ~UNIT_ACTCODE; un.flags |= (cd) << (UNIT_V_ACTCODE-UNIT_V_CODE);} - -#define COLUMN u4 /* column field in unit record */ - -UNIT cr_unit = { UDATA (&cr_svc, UNIT_ATTABLE|UNIT_ROABLE, 0) }; -UNIT cp_unit = { UDATA (NULL, UNIT_ATTABLE, 0) }; - -MTAB cr_mod[] = { - { UNIT_CODE, CODE_029, "029", "029", &cr_set_code}, - { UNIT_CODE, CODE_026F, "026F", "026F", &cr_set_code}, - { UNIT_CODE, CODE_026C, "026C", "026C", &cr_set_code}, - { UNIT_CODE, CODE_BINARY, "BINARY", "BINARY", &cr_set_code}, - { UNIT_CODE, CODE_AUTO, "AUTO", "AUTO", &cr_set_code}, - { UNIT_ACTCODE, ACTCODE_029, "(029)", NULL, NULL}, /* display-only, shows current mode */ - { UNIT_ACTCODE, ACTCODE_026F, "(026F)", NULL, NULL}, - { UNIT_ACTCODE, ACTCODE_026C, "(026C)", NULL, NULL}, - { UNIT_ACTCODE, ACTCODE_BINARY, "(BINARY)", NULL, NULL}, - { 0 } }; - -MTAB cp_mod[] = { - { UNIT_CODE, CODE_029, "029", "029", &cp_set_code}, - { UNIT_CODE, CODE_026F, "026F", "026F", &cp_set_code}, - { UNIT_CODE, CODE_026C, "026C", "026C", &cp_set_code}, - { UNIT_CODE, CODE_BINARY, "BINARY", "BINARY", &cp_set_code}, - { 0 } }; - -REG cr_reg[] = { - { HRDATA (CRDSW, cr_dsw, 16) }, /* device status word */ - { DRDATA (CRTIME, cr_wait, 24), PV_LEFT }, /* operation wait */ - { DRDATA (CFTIME, cf_wait, 24), PV_LEFT }, /* operation wait */ - { DRDATA (CRCOUNT, cr_count, 32),PV_LEFT }, /* number of cards read since last attach cmd */ - { NULL } }; - -REG cp_reg[] = { - { DRDATA (CPTIME, cp_wait, 24), PV_LEFT }, /* operation wait */ - { DRDATA (CPCOUNT, cp_count, 32),PV_LEFT }, /* number of cards punched since last attach cmd */ - { NULL } }; - -DEVICE cr_dev = { - "CR", &cr_unit, cr_reg, cr_mod, - 1, 16, 16, 1, 16, 16, - NULL, NULL, cr_reset, - cr_boot, cr_attach, cr_detach}; - -DEVICE cp_dev = { - "CP", &cp_unit, cp_reg, cp_mod, - 1, 16, 16, 1, 16, 16, - NULL, NULL, cp_reset, - NULL, cp_attach, cp_detach}; - -#define CR_DSW_READ_RESPONSE 0x8000 /* device status word bits */ -#define CR_DSW_PUNCH_RESPONSE 0x4000 -#define CR_DSW_ERROR_CHECK 0x2000 -#define CR_DSW_LAST_CARD 0x1000 -#define CR_DSW_OP_COMPLETE 0x0800 -#define CR_DSW_FEED_CHECK 0x0100 -#define CR_DSW_BUSY 0x0002 -#define CR_DSW_NOT_READY 0x0001 - -typedef struct { - uint16 hollerith; - char ascii; -} CPCODE; - -static CPCODE cardcode_029[] = -{ - 0x0000, ' ', - 0x8000, '&', // + in 026 Fortran - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0820, ':', - 0x0420, '#', // = in 026 Fortran - 0x0220, '@', // ' in 026 Fortran - 0x0120, '\'', - 0x00A0, '=', - 0x0060, '"', - 0x8820, '\xA2', // cent, in MS-DOS encoding (this is in guess_cr_code as well) - 0x8420, '.', - 0x8220, '<', // ) in 026 Fortran - 0x8120, '(', - 0x80A0, '+', - 0x8060, '|', - 0x4820, '!', - 0x4420, '$', - 0x4220, '*', - 0x4120, ')', - 0x40A0, ';', - 0x4060, '\xAC', // not, in MS-DOS encoding (this is in guess_cr_code as well) - 0x2420, ',', - 0x2220, '%', // ( in 026 Fortran - 0x2120, '_', - 0x20A0, '>', - 0xB000, 'a', - 0xA800, 'b', - 0xA400, 'c', - 0xA200, 'd', - 0xA100, 'e', - 0xA080, 'f', - 0xA040, 'g', - 0xA020, 'h', - 0xA010, 'i', - 0xD000, 'j', - 0xC800, 'k', - 0xC400, 'l', - 0xC200, 'm', - 0xC100, 'n', - 0xC080, 'o', - 0xC040, 'p', - 0xC020, 'q', - 0xC010, 'r', - 0x6800, 's', - 0x6400, 't', - 0x6200, 'u', - 0x6100, 'v', - 0x6080, 'w', - 0x6040, 'x', - 0x6020, 'y', - 0x6010, 'z', // these odd punch codes are used by APL: - 0x1010, '\001', // no corresponding ASCII using ^A - 0x0810, '\002', // SYN using ^B - 0x0410, '\003', // no corresponding ASCII using ^C - 0x0210, '\004', // PUNCH ON using ^D - 0x0110, '\005', // READER STOP using ^E - 0x0090, '\006', // UPPER CASE using ^F - 0x0050, '\013', // EOT using ^K - 0x0030, '\016', // no corresponding ASCII using ^N - 0x1030, '\017', // no corresponding ASCII using ^O - 0x0830, '\020', // no corresponding ASCII using ^P - -}; - -static CPCODE cardcode_026F[] = // 026 fortran -{ - 0x0000, ' ', - 0x8000, '+', - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0420, '=', - 0x0220, '\'', // ' in 026 Fortran - 0x8420, '.', - 0x8220, ')', - 0x4420, '$', - 0x4220, '*', - 0x2420, ',', - 0x2220, '(', -}; - -static CPCODE cardcode_026C[] = // 026 commercial -{ - 0x0000, ' ', - 0x8000, '+', - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0420, '=', - 0x0220, '\'', // ' in 026 Fortran - 0x8420, '.', - 0x8220, ')', - 0x4420, '$', - 0x4220, '*', - 0x2420, ',', - 0x2220, '(', -}; - -extern int cgi; -extern void sub_args (char *instr, char *tmpbuf, int32 maxstr, int32 nargs, char *arg[]); - -static int16 ascii_to_card[256]; - -static CPCODE *cardcode; -static int ncardcode; -static FILE *deckfile = NULL; -static char tempfile[128]; -static int cardnum; -static int any_punched = 0; - -#define MAXARGLEN 80 /* max length of a saved attach command argument */ -#define MAXARGS 10 /* max number of arguments to save */ -static char list_save[MAXARGS][MAXARGLEN], *list_arg[MAXARGLEN]; -static int list_nargs = 0; -static char* (*tab_proc)(char*) = NULL; /* tab reformatting routine */ - -static uint16 punchstation[80]; -static uint16 readstation[80]; -static enum {STATION_EMPTY, STATION_LOADED, STATION_READ, STATION_PUNCHED} punchstate = STATION_EMPTY, readstate = STATION_EMPTY; - -static t_bool nextdeck (void); -static void checkdeck (void); - -static t_stat pcr_attach(UNIT *uptr, char *devname); -static t_stat pcr_detach(UNIT *uptr); -static t_stat pcr_svc(UNIT *uptr); -static void pcr_xio_sense(int modify); -static void pcr_xio_feedcycle(void); -static void pcr_xio_startread(void); -static void pcr_reset(void); -static int pcr_read_data(void); - -/* lookup_codetable - use code flag setting to get code table pointer and length */ - -static t_bool lookup_codetable (int32 match, CPCODE **pcode, int *pncode) -{ - switch (match) { - case CODE_029: - *pcode = cardcode_029; - *pncode = sizeof(cardcode_029) / sizeof(CPCODE); - break; - - case CODE_026F: - *pcode = cardcode_026F; - *pncode = sizeof(cardcode_026F) / sizeof(CPCODE); - break; - - case CODE_026C: - *pcode = cardcode_026C; - *pncode = sizeof(cardcode_026C) / sizeof(CPCODE); - break; - - case CODE_BINARY: - *pcode = NULL; - *pncode = 0; - break; - - default: - printf("Eek! Undefined code table index"); - return FALSE; - } - return TRUE; -} - -t_stat set_active_cr_code (int match) -{ - CPCODE *code; - int i, ncode; - - SET_ACTCODE(cr_unit, match); - - if (! lookup_codetable(match, &code, &ncode)) - return SCPE_ARG; - - memset(ascii_to_card, 0, sizeof(ascii_to_card)); - - for (i = 0; i < ncode; i++) // set ascii to card code table - ascii_to_card[code[i].ascii] = code[i].hollerith; - - return SCPE_OK; -} - -static t_stat cr_set_code (UNIT *uptr, int32 match, char *cptr, void *desc) -{ - if (match == CODE_AUTO) - match = guess_cr_code(); - - return set_active_cr_code(match); -} - -static int32 guess_cr_code (void) -{ - int i; - long filepos; - int32 guess; - union { - uint16 w[80]; // one card image, viewed as 80 short words - char c[160]; // same, viewed as 160 characters - } line; - - // here, we can see if the attached file is binary or ascii and auto-set the - // mode. If we the file is a binary deck, we should be able to read a record of 80 short - // words, and the low 4 bits of each word must be zero. If the file was an ascii deck, - // then these low 4 bits are the low 4 bits of every other character in the first 160 - // chararacters of the file. They would all only be 0 if all of these characters were - // in the following set: {NUL ^P space 0 @ P ` p} . It seems very unlikely that - // this would happen, as even if the deck consisted of untrimmed card images and - // the first two lines were blank, the 81'st character would be a newline, and it would - // appear at one of the every-other characters seen on little-endian machines, anyway. - // So: if the code mode is AUTO, we can use this test and select either BINARY or 029. - // Might as well also check for the all-blanks and newlines case in case this is a - // big-endian machine. - - - guess = CODE_029; // assume ASCII, 029 - - if ((cr_unit.flags & UNIT_ATT) && (cr_unit.fileref != NULL)) { - filepos = ftell(cr_unit.fileref); // remember current position in file - fseek(cr_unit.fileref, 0, SEEK_SET); // go to first record of file - // read card image; if file too short, leave guess set to 029 - if (fxread(line.w, sizeof(line.w[0]), 80, cr_unit.fileref) == 80) { - guess = CODE_BINARY; // we got a card image, assume binary - - for (i = 0; i < 80; i++) { // make sure low bits are zeroes, which our binary card format promises - if (line.w[i] & 0x000F) { - guess = CODE_029; // low bits set, must be ascii text - break; - } - } - - if (guess == CODE_BINARY) { // if we saw no low bits, it could have been all spaces. - guess = CODE_029; // so now assume file is text - for (i = 0; i < 160; i++) { // ensure all 160 characters are 7-bit ASCII (or not or cent) - if ((strchr("\r\n\t\xA2\xAC", line.c[i]) == NULL) && ! BETWEEN(line.c[i], ' ', '\x7F')) { - guess = CODE_BINARY; // oops, null or weird character, it's binary after all - break; - } - } - } - } - - fseek(cr_unit.fileref, filepos, SEEK_SET); // return to original position - } - - return guess; -} - -static t_stat cp_set_code (UNIT *uptr, int32 match, char *cptr, void *desc) -{ - CPCODE *code; - int ncode; - - if (! lookup_codetable(match, &code, &ncode)) - return SCPE_ARG; - - cardcode = code; // save code table for punch output - ncardcode = ncode; - - return SCPE_OK; -} - -t_stat load_cr_boot (int drvno, int switches) -{ - int i; - char *name, msg[80]; - t_bool expand; - uint16 word, *boot; - static uint16 dms_boot_data[] = { /* DMSV2M12, already expanded to 16 bits */ - 0xc80a, 0x18c2, 0xd008, 0xc019, 0x8007, 0xd017, 0xc033, 0x100a, - 0xd031, 0x7015, 0x000c, 0xe800, 0x0020, 0x08f8, 0x4828, 0x7035, - 0x70fa, 0x4814, 0xf026, 0x2000, 0x8800, 0x9000, 0x9800, 0xa000, - 0xb000, 0xb800, 0xb810, 0xb820, 0xb830, 0xb820, 0x3000, 0x08ea, - 0xc0eb, 0x4828, 0x70fb, 0x9027, 0x4830, 0x70f8, 0x8001, 0xd000, - 0xc0f4, 0xd0d9, 0xc01d, 0x1804, 0xe8d6, 0xd0d9, 0xc8e3, 0x18d3, - 0xd017, 0x18c4, 0xd0d8, 0x9016, 0xd815, 0x90db, 0xe8cc, 0xd0ef, - 0xc016, 0x1807, 0x0035, 0x00d0, 0xc008, 0x1803, 0xe8c4, 0xd00f, - 0x080d, 0x08c4, 0x1003, 0x4810, 0x70d9, 0x3000, 0x08df, 0x3000, - 0x7010, 0x00d1, 0x0028, 0x000a, 0x70f3, 0x0000, 0x00d0, 0xa0c0 - }; - static uint16 apl_boot_data[] = { /* APLIPL, already expanded */ - 0x7021, 0x3000, 0x7038, 0xa0c0, 0x0002, 0x4808, 0x0003, 0x0026, - 0x0001, 0x0001, 0x000c, 0x0000, 0x0000, 0x0800, 0x48f8, 0x0027, - 0x7002, 0x08f2, 0x3800, 0xe0fe, 0x18cc, 0x100e, 0x10c1, 0x4802, - 0x7007, 0x4828, 0x7005, 0x4804, 0x7001, 0x70f3, 0x08e7, 0x70e1, - 0x08ed, 0x70f1, 0xc0e0, 0x1807, 0xd0de, 0xc0df, 0x1801, 0xd0dd, - 0x800d, 0xd00c, 0xc0e3, 0x1005, 0xe80a, 0xd009, 0xc0d8, 0x1008, - 0xd0d6, 0xc0dd, 0x1008, 0x80d4, 0xd0da, 0x1000, 0xb000, 0x00f6, - 0x70e7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x9000, 0x4004, 0x40c0, 0x8001, 0x4004, 0x40c0, 0x0000, 0x0000 }; - static uint16 aplp_boot_data[] = { /* APLIPL Privileged, already expanded */ - 0x7021, 0x3000, 0x7038, 0xa0c0, 0x0002, 0x4808, 0x0003, 0x0026, - 0x0001, 0x0001, 0x000c, 0x0000, 0x0000, 0x0800, 0x48f8, 0x0027, - 0x7002, 0x08f2, 0x3800, 0xe0fe, 0x18cc, 0x100e, 0x10c1, 0x4802, - 0x7007, 0x4828, 0x7005, 0x4804, 0x7001, 0x70f3, 0x08e7, 0x70e1, - 0x08ed, 0x70f1, 0xc0e0, 0x1807, 0xd0de, 0xc0df, 0x1801, 0xd0dd, - 0x800d, 0xd00c, 0xc0e3, 0x1005, 0xe80a, 0xd009, 0xc0d8, 0x1008, - 0xd0d6, 0xc0dd, 0x1008, 0x80d4, 0xd0da, 0x1002, 0xb000, 0x00f6, - 0x70e7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x9000, 0x4004, 0x40c0, 0x8001, 0x4004, 0x40c0, 0x4004, 0x4001 - }; - - if ((switches & SWMASK('A')) && (switches & SWMASK('P'))) { - boot = aplp_boot_data; - name = "APL\\1130 Privileged"; - expand = FALSE; - } - else if (switches & SWMASK('A')) { - boot = apl_boot_data; - name = "APL\\1130"; - expand = FALSE; - } - else { - boot = dms_boot_data; - name = "DMS V2M12"; - expand = FALSE; - } - - if (drvno >= 0) /* if specified, set toggle switches to disk drive no */ - CES = drvno; /* so BOOT DSK1 will work correctly (DMS boot uses this) */ - - IAR = 0; /* clear IAR */ - - for (i = 0; i < 80; i++) { /* store the boot image to core words 0..79 */ - word = boot[i]; /* expanding the 12-bit card data to 16 bits if not already expanded */ - if (expand) - word = (word & 0xF800) | ((word & 0x0400) ? 0x00C0 : 0x0000) | ((word & 0x03F0) >> 4); - - WriteW(i, word); - } - /* quiet switch or CGI mode inhibit the boot remark */ - if ((switches & SWMASK('Q') == 0) && ! cgi) { - sprintf(msg,"Loaded %s cold start card\n", name); - -#ifdef GUI_SUPPORT - remark_cmd(msg); -#else - printf(msg); -#endif - } - - return SCPE_OK; -} - -t_stat cr_boot (int unitno, DEVICE *dptr) -{ - t_stat rval; - uint16 buf[80]; - int i; - - if ((rval = reset_all(0)) != SCPE_OK) - return rval; - - if (! (cr_unit.flags & UNIT_ATT)) /* no deck; load standard boot anyway */ - return load_cr_boot(-1, 0); - - if (GET_ACTCODE(cr_unit) != CODE_BINARY) { - printf("Can only boot from card reader when set to BINARY mode"); - return SCPE_IOERR; - } - - if (cr_unit.fileref == NULL) /* this will happen if no file in deck file can be opened */ - return SCPE_IOERR; - - if (fxread(buf, sizeof(buf[0]), 80, cr_unit.fileref) != 80) - return SCPE_IOERR; - - IAR = 0; /* Program Load sets IAR = 0 */ - - for (i = 0; i < 80; i++) /* shift 12 bits into 16 */ - WriteW(i, (buf[i] & 0xF800) | ((buf[i] & 0x0400) ? 0x00C0 : 0x0000) | ((buf[i] & 0x03F0) >> 4)); - - return SCPE_OK; -} - -char card_to_ascii (uint16 hol) -{ - int i; - - for (i = 0; i < ncardcode; i++) - if (cardcode[i].hollerith == hol) - return cardcode[i].ascii; - - return '?'; -} - -// hollerith_to_ascii - provide a generic conversion for simulator debugging - -char hollerith_to_ascii (uint16 hol) -{ - int i; - - for (i = 0; i < ncardcode; i++) - if (cardcode_029[i].hollerith == hol) - return cardcode[i].ascii; - - return ' '; -} - -/* feedcycle - move cards to next station */ - -static void feedcycle (t_bool load, t_bool punching) -{ - char buf[84], *x, *result; - int i, nread, nwrite, ch; - - /* write punched card if punch is attached to a file */ - if (cp_unit.flags & UNIT_ATT) { - if (any_punched && punchstate != STATION_EMPTY) { - if (GET_CODE(cp_unit) == CODE_BINARY) { - fxwrite(punchstation, sizeof(punchstation[0]), 80, cp_unit.fileref); - } - else { - for (i = 80; --i >= 0; ) { /* find last nonblank column */ - if (punchstation[i] != 0) - break; - } - - /* i is now index of last character to output or -1 if all blank */ - - for (nwrite = 0; nwrite <= i; nwrite++) { /* convert characters */ - buf[nwrite] = card_to_ascii(punchstation[nwrite]); - } - - /* nwrite is now number of characters to output */ - -#ifdef WIN32 - buf[nwrite++] = '\r'; /* add CR before NL for microsoft */ -#endif - buf[nwrite++] = '\n'; /* append newline */ - fxwrite(buf, sizeof(char), nwrite, cp_unit.fileref); - } - } - - cp_count++; - } - - if (! load) // all we wanted to do was flush the punch - return; - - /* slide cards from reader to punch. If we know we're punching, - * generate a blank card in any case. Otherwise, it should take two feed - * cycles to get a read card from the hopper to punch station */ - - if (readstate == STATION_EMPTY) { - if (punching) { - memset(punchstation, 0, sizeof(punchstation)); - punchstate = STATION_LOADED; - } - else - punchstate = STATION_EMPTY; - } - else { - memcpy(punchstation, readstation, sizeof(punchstation)); - punchstate = STATION_LOADED; - } - - /* load card into read station */ - -again: /* jump here if we've loaded a new deck after emptying the previous one */ - - if (cr_unit.flags & UNIT_ATT) { - - memset(readstation, 0, sizeof(readstation)); /* blank out the card image */ - - if (cr_unit.fileref == NULL) - nread = 0; - - else if (GET_ACTCODE(cr_unit) == CODE_BINARY) /* binary read is straightforward */ - nread = fxread(readstation, sizeof(readstation[0]), 80, cr_unit.fileref); - - else if (fgets(buf, sizeof(buf), cr_unit.fileref) == NULL) /* read up to 80 chars */ - nread = 0; /* hmm, end of file */ - - else { /* check for newline */ - if ((x = strchr(buf, '\r')) == NULL) - x = strchr(buf, '\n'); - - if (x == NULL) { /* there were no delimiters, burn rest of line */ - while ((ch = getc(cr_unit.fileref)) != EOF) { /* get character */ - if (ch == '\n') /* newline, done */ - break; - - if (ch == '\r') { /* CR, try to take newline too */ - ch = getc(cr_unit.fileref); - if (ch != EOF && ch != '\n') /* hmm, put it back */ - ungetc(ch, cr_unit.fileref); - - break; - } - } - nread = 80; /* take just the first 80 characters */ - } - else - nread = x-buf; /* reduce length of string */ - - if (! (cr_unit.flags & UNIT_LOWERCASE)) - upcase(buf); /* force uppercase */ - - if (tab_proc != NULL) { /* apply tab editing, if specified */ - buf[nread] = '\0'; /* .. be sure string is terminated */ - result = (*tab_proc)(buf); /* .. convert tabs spaces */ - nread = strlen(result); /* .. set new read length */ - } - else - result = buf; - - for (i = 0; i < nread; i++) /* convert ascii to punch code */ - readstation[i] = ascii_to_card[result[i]]; - - nread = 80; /* even if line was blank consider it present */ - } - - if (nread <= 0) { /* set hopper flag accordingly */ - if (deckfile != NULL && nextdeck()) - goto again; - - if (punching) /* pretend we loaded a blank card */ - nread = 80; - } - - if (nread == 0) { - SETBIT(cr_unit.flags, UNIT_EMPTY); - readstate = STATION_EMPTY; - cardnum = -1; /* nix the card counter */ - } - else { - CLRBIT(cr_unit.flags, UNIT_EMPTY); - readstate = STATION_LOADED; - cardnum++; /* advance card counter */ - cr_count++; - } - } -// else -// readstate = STATION_EMPTY; - - cr_unit.COLUMN = -1; /* neither device is currently cycling */ - cp_unit.COLUMN = -1; -} - -#ifdef NO_USE_FOR_THIS_CURRENTLY - -/* this routine should probably be hooked up to the GUI somehow */ - -/* NPRO - nonprocess runout, flushes out the reader/punch */ - -static void npro (void) -{ - if (cr_unit.flags & UNIT_ATT) - fseek(cr_unit.fileref, 0, SEEK_END); /* push reader to EOF */ - if (deckfile != NULL) - fseek(deckfile, 0, SEEK_END); /* skip to end of deck list */ - - cardnum = -1; /* nix the card counter */ - - if (punchstate == STATION_PUNCHED) - feedcycle(FALSE, FALSE); /* flush out card just punched */ - - readstate = punchstate = STATION_EMPTY; - cr_unit.COLUMN = -1; /* neither device is currently cycling */ - cp_unit.COLUMN = -1; - SETBIT(cr_unit.flags, UNIT_EMPTY); /* set hopper empty */ -} - -#endif - -/* skipbl - skip leading whitespace in a string */ - -static char * skipbl (char *str) -{ - while (*str && *str <= ' ') - str++; - - return str; -} - -/* alltrim - remove all leading and trailing whitespace from a string */ - -static char * alltrim (char *str) -{ - char *s, *lastnb; - - if ((s = skipbl(str)) != str) /* slide down over leading whitespace */ - strcpy(str, s); - - for (lastnb = str-1, s = str; *s; s++) /* point to last nonblank characteter in string */ - if (*s > ' ') - lastnb = s; - - lastnb[1] = '\0'; /* clip just after it */ - - return str; -} - -/* checkdeck - set hopper empty status based on condition of current reader file */ - -static void checkdeck (void) -{ - t_bool empty; - - if (cr_unit.fileref == NULL) { /* there is no open file */ - empty = TRUE; - } - else { - fseek(cr_unit.fileref, 0, SEEK_END); /* seek to end of file */ - empty = ftell(cr_unit.fileref) <= 0; /* file is empty if there was nothing in it*/ - cardnum = 0; /* reset card counter */ - fseek(cr_unit.fileref, 0, SEEK_SET); /* rewind deck */ - } - - if (empty) { - SETBIT(cr_unit.flags, UNIT_EMPTY); - if (cr_unit.fileref != NULL) /* real file but it's empty, hmmm, try another */ - nextdeck(); - } - else { - CLRBIT(cr_unit.flags, UNIT_EMPTY); - } -} - -/* nextdeck - attempt to load a new file from the deck list into the hopper */ - -static t_bool nextdeck (void) -{ - char buf[200], tmpbuf[200], *fname, *tn, *c, quote, *mode; - int code; - long fpos; - static char white[] = " \t\r\n"; - - cardnum = 0; /* reset card counter */ - - if (deckfile == NULL) /* we can't help */ - return FALSE; - - code = GET_CODE(cr_unit); /* default code as set */ - - if (cr_unit.fileref != NULL) { /* this pulls the rug out from under scp */ - fclose(cr_unit.fileref); /* since the attach flag is still set. be careful! */ - cr_unit.fileref = NULL; - - if (cr_unit.flags & UNIT_SCRATCH) { - unlink(tempfile); - CLRBIT(cr_unit.flags, UNIT_SCRATCH); - } - } - - for (;;) { /* get a filename */ - tab_proc = NULL; /* default: no tab editing */ - - if (fgets(buf, sizeof(buf), deckfile) == NULL) - break; /* oops, no more names */ - - alltrim(buf); /* remove leading and trailing spaces */ - - if (! *buf) - continue; /* empty line */ - - if (*buf == '#' || *buf == '*' || *buf == ';') - continue; /* comment */ - - if (strnicmp(buf, "!BREAK", 6) == 0) { /* stop the simulation */ - break_simulation(STOP_DECK_BREAK); - continue; - } - - if (buf[0] == '!') { /* literal text line, make a temporary file */ - if (*tempfile == '\0') { - if ((tn = tempnam(".", "1130")) == NULL) { - printf("Cannot create temporary card file name\n"); - break_simulation(STOP_DECK_BREAK); - return 0; - } - strcpy(tempfile, tn); - strcat(tempfile, ".tmp"); - } - - if ((cr_unit.fileref = fopen(tempfile, "wb+")) == NULL) { - printf("Cannot create temporary file %s\n", tempfile); - break_simulation(STOP_DECK_BREAK); - return 0; - } - - SETBIT(cr_unit.flags, UNIT_SCRATCH); - - for (;;) { /* store literal cards into temporary file */ - upcase(buf+1); - fputs(buf+1, cr_unit.fileref); - putc('\n', cr_unit.fileref); - - if (cpu_unit.flags & UNIT_ATT) - trace_io("(Literal card %s\n)", buf+1); - if (! (cr_unit.flags & UNIT_QUIET)) - printf( "(Literal card %s)\n", buf+1); - - fpos = ftell(deckfile); - if (fgets(buf, sizeof(buf), deckfile) == NULL) - break; /* oops, end of file */ - if (buf[0] != '!' || strnicmp(buf, "!BREAK", 6) == 0) - break; - alltrim(buf); - } - fseek(deckfile, fpos, SEEK_SET); /* restore deck file to just before non-literal card */ - - fseek(cr_unit.fileref, 0, SEEK_SET); /* rewind scratch file for reading */ - code = CODE_029; /* assume literal cards use keycode 029 */ - break; - } - - sub_args(buf, tmpbuf, sizeof(buf), list_nargs, list_arg); /* substitute in stuff from the attach command line */ - - fname = c = buf; /* pick filename from string */ - - if (*c == '\'' || *c == '"') { /* quoted string */ - quote = *c; /* remember the quote type */ - strcpy(c, c+1); /* slide string down over the quote */ - while (*c && (*c != quote)) - c++; /* skip to end of quote */ - } - else { /* not quoted; look for terminating whitespace */ - while (*c && (*c > ' ')) - c++; - } - - if (*c) - *c++ = 0; /* term arg at space or closing quote & move to next character */ - - if (! *fname) /* blank line, no filename */ - continue; - - if ((cr_unit.fileref = fopen(fname, "rb")) == NULL) { - printf("File '%s' specified in deck file '%s' cannot be opened\n", fname, cr_unit.filename+1); - continue; - } - - mode = c = skipbl(c); /* skip to next token, which would be mode, if present */ - - switch (*c) { - case 'b': - case 'B': - code = CODE_BINARY; /* force code */ - c++; /* accept mode character by moving past it */ - break; - - case 'a': - case 'A': - code = CODE_029; - c++; - - switch (*c) { /* is ascii mode followed by another character? */ - case 'F': - case 'f': - tab_proc = EditToFortran; - c++; - break; - - case 'A': - case 'a': - tab_proc = EditToAsm; - c++; - break; - - case 't': - case 'T': - tab_proc = EditToWhitespace; - c++; - break; - } - } - - if (*skipbl(c)) /* there should be nothing left */ - printf("* Bad mode specifier %s after filename %s in deck file", mode, fname); - - if (code == CODE_AUTO) /* otherwise if mode is auto, guess it, otherwise use default */ - code = guess_cr_code(); - - if (cpu_unit.flags & UNIT_ATT) - trace_io("(Opened %s deck %s%s)\n", (code == CODE_BINARY) ? "binary" : "text", fname, tab_proc ? (*tab_proc)(NULL) : ""); - - if (! (cr_unit.flags & UNIT_QUIET)) - printf( "(Opened %s deck %s%s)\n", (code == CODE_BINARY) ? "binary" : "text", fname, tab_proc ? (*tab_proc)(NULL) : ""); - - break; - } - - checkdeck(); - - if (code != CODE_AUTO) /* if code was determined, set it */ - set_active_cr_code(code); /* (it may be left at CODE_AUTO when deckfile is exhausted */ - - return (cr_unit.flags & UNIT_EMPTY) == 0; /* return TRUE if a deck has been loaded */ -} - -static t_stat cr_reset (DEVICE *dptr) -{ - if (GET_ACTCODE(cr_unit) == CODE_AUTO) - SET_ACTCODE(cr_unit, CODE_029); /* if actual code is not yet set, select 029 for now*/ - - cr_set_code(&cr_unit, GET_ACTCODE(cr_unit), NULL, NULL); /* reset to specified code table */ - - readstate = STATION_EMPTY; - - cr_dsw = 0; - sim_cancel(&cr_unit); /* cancel any pending ops */ - calc_ints(); - - SET_OP(OP_IDLE); - - cr_unit.COLUMN = -1; /* neither device is currently cycling */ - - if (cr_unit.flags & UNIT_PHYSICAL) { - pcr_reset(); - return SCPE_OK; - } - - SETBIT(cr_unit.flags, UNIT_EMPTY); /* assume hopper empty */ - - if (cr_unit.flags & UNIT_ATT) { -// if (deckfile != NULL) { /* do NOT rewind the deck file */ -// fseek(deckfile, 0, SEEK_SET); -// nextdeck(); -// } -// else -// checkdeck(); - - if (cr_unit.fileref != NULL) - feedcycle(FALSE, FALSE); - } - - return SCPE_OK; -} - -static t_stat cp_reset (DEVICE *dptr) -{ - if (GET_CODE(cp_unit) == CODE_AUTO) - SET_CODE(cp_unit, CODE_BINARY); /* punch is never in auto mode; turn it to binary on startup */ - - cp_set_code(&cp_unit, GET_CODE(cp_unit), NULL, NULL); - punchstate = STATION_EMPTY; - - cp_unit.COLUMN = -1; - return SCPE_OK; -} - -static t_stat cr_attach (UNIT *uptr, char *cptr) -{ - t_stat rval; - t_bool use_decklist; - char *c, *arg, quote; - -// no - don't cancel pending read? -// sim_cancel(uptr); /* cancel pending operations */ - - CLRBIT(uptr->flags, UNIT_QUIET|UNIT_DEBUG|UNIT_PHYSICAL|UNIT_LOWERCASE); /* set options */ - - tab_proc = NULL; - - if (sim_switches & SWMASK('D')) SETBIT(uptr->flags, UNIT_DEBUG); - if (sim_switches & SWMASK('Q')) SETBIT(uptr->flags, UNIT_QUIET); - if (sim_switches & SWMASK('L')) SETBIT(uptr->flags, UNIT_LOWERCASE); - - if (sim_switches & SWMASK('F')) tab_proc = EditToFortran; - if (sim_switches & SWMASK('A')) tab_proc = EditToAsm; - if (sim_switches & SWMASK('T')) tab_proc = EditToWhitespace; - - cr_detach(uptr); /* detach file and possibly deckfile */ - CLRBIT(uptr->flags, UNIT_SCRATCH); - - c = cptr; /* extract arguments */ - for (list_nargs = 0; list_nargs < MAXARGS; list_nargs++) { - while (*c && (*c <= ' ')) /* skip blanks */ - c++; - - if (! *c) - break; /* all done */ - - arg = c; /* save start */ - while (*c && (*c > ' ')) { - if (*c == '\'' || *c == '"') { /* quoted string */ - for (quote = *c++; *c;) - if (*c++ == quote) - break; - } - else c++; - } - - if (*c) - *c++ = 0; /* term arg at space */ - - list_arg[list_nargs] = list_save[list_nargs]; /* set pointer to permanent storage location */ - strncpy(list_arg[list_nargs], arg, MAXARGLEN); /* store copy */ - } - - if (list_nargs <= 0) /* need at least 1 */ - return SCPE_2FARG; - - cardnum = 0; /* reset card counter */ - use_decklist = FALSE; - - cptr = list_arg[0]; /* filename is first argument */ - -#ifdef ENABLE_ENABLE_PHYSICAL_CARD_READER_SUPPORT - if (*cptr == '=') { /* open physical card reader device */ - if ((rval = pcr_attach(uptr, ++cptr)) != SCPE_OK) - return rval; - } -#endif - - if (*cptr == '@') { - use_decklist = TRUE; - cptr++; - } - - if (strcmp(cptr, "-") == 0 && ! use_decklist) { /* standard input */ - if (uptr -> flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ - uptr->filename = calloc(CBUFSIZE, sizeof(char)); - strcpy(uptr->filename, "(stdin)"); - uptr->fileref = stdin; - SETBIT(uptr->flags, UNIT_ATT); - uptr->pos = 0; - } - else if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) - return rval; - - if (use_decklist) { /* if we skipped the '@', store the actually-specified name */ - strncpy(uptr->filename, cptr-1, CBUFSIZE); - deckfile = cr_unit.fileref; /* save the deck file stream in our local variable */ - cr_unit.fileref = NULL; - nextdeck(); - } - else { - checkdeck(); - cr_set_code(&cr_unit, GET_CODE(cr_unit), NULL, NULL); - } - - // there is a read pending. Pull the card in to make it go - if (CURRENT_OP == OP_READING || CURRENT_OP == OP_PUNCHING || CURRENT_OP == OP_FEEDING) - feedcycle(TRUE, (cp_unit.flags & UNIT_ATT) != 0); - -// no - don't reset the reader -// cr_reset(&cr_dev); /* reset the whole thing */ -// cp_reset(&cp_dev); - - return SCPE_OK; -} - -static t_stat cr_detach (UNIT *uptr) -{ - t_stat rval; - - cr_count = 0; /* clear read count */ - - if (cr_unit.flags & UNIT_PHYSICAL) - return pcr_detach(uptr); - - if (cr_unit.flags & UNIT_ATT && deckfile != NULL) { - if (cr_unit.fileref != NULL) /* close the active card deck */ - fclose(cr_unit.fileref); - - if (cr_unit.flags & UNIT_SCRATCH) { - unlink(tempfile); - CLRBIT(cr_unit.flags, UNIT_SCRATCH); - } - - cr_unit.fileref = deckfile; /* give scp a file to close */ - } - - if (uptr->fileref == stdout) { - CLRBIT(uptr->flags, UNIT_ATT); - free(uptr->filename); - uptr->filename = NULL; - rval = SCPE_OK; - } - else - rval = detach_unit(uptr); - - return rval; -} - -static t_stat cp_attach (UNIT *uptr, char *cptr) -{ - /* if -d is specified turn on debugging (bit is in card reader UNIT) */ - if (sim_switches & SWMASK('D')) SETBIT(cr_unit.flags, UNIT_DEBUG); - - return attach_unit(uptr, cptr); -} - -static t_stat cp_detach (UNIT *uptr) -{ - if (cp_unit.flags & UNIT_ATT) - if (punchstate == STATION_PUNCHED) - feedcycle(FALSE, FALSE); /* flush out card just punched */ - - any_punched = 0; /* reset punch detected */ - cp_count = 0; /* clear punch count */ - - return detach_unit(uptr); -} - -static void op_done (void) -{ - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("!CR Op Complete, card %d", cardnum); - - SET_OP(OP_IDLE); - SETBIT(cr_dsw, CR_DSW_OP_COMPLETE); - SETBIT(ILSW[4], ILSW_4_1442_CARD); - calc_ints(); -} - -static t_stat cr_svc (UNIT *uptr) -{ - if (uptr->flags & UNIT_PHYSICAL) - return pcr_svc(uptr); - - switch (CURRENT_OP) { - case OP_IDLE: - break; - - case OP_FEEDING: - op_done(); - break; - - case OP_READING: - if (readstate == STATION_EMPTY) { /* read active but no cards? hang */ - sim_activate(&cr_unit, cf_wait); - break; - } - - if (++cr_unit.COLUMN < 80) { - SETBIT(cr_dsw, CR_DSW_READ_RESPONSE); - SETBIT(ILSW[0], ILSW_0_1442_CARD); - calc_ints(); - sim_activate(&cr_unit, cr_wait); - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("!CR Read Response %d : %d", cardnum, cr_unit.COLUMN+1); - } - else { - readstate = STATION_READ; - op_done(); - } - break; - - case OP_PUNCHING: - if (punchstate == STATION_EMPTY) { /* punch active but no cards? hang */ - sim_activate(&cr_unit, cf_wait); - break; - } - - if (cp_unit.flags & UNIT_LASTPUNCH) { - punchstate = STATION_PUNCHED; - op_done(); - } - else if (++cp_unit.COLUMN < 80) { - SETBIT(cr_dsw, CR_DSW_PUNCH_RESPONSE); - SETBIT(ILSW[0], ILSW_0_1442_CARD); - calc_ints(); - sim_activate(&cr_unit, cp_wait); - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("!CR Punch Response"); - } - else { - punchstate = STATION_PUNCHED; - op_done(); - } - break; - } - - return SCPE_OK; -} - -void xio_1142_card (int32 addr, int32 func, int32 modify) -{ - char msg[80]; - int ch; - int16 wd; - t_bool lastcard; - - switch (func) { - case XIO_SENSE_DEV: - if (cr_unit.flags & UNIT_PHYSICAL) { - pcr_xio_sense(modify); - return; - } - - if (cp_unit.flags & UNIT_ATT) - lastcard = FALSE; /* if punch file is open, assume infinite blank cards in reader */ - else if ((cr_unit.flags & UNIT_ATT) == 0) - lastcard = TRUE; /* if nothing to read, hopper's empty */ - else if (readstate == STATION_LOADED) - lastcard = FALSE; - else if (cr_unit.fileref == NULL) - lastcard = TRUE; - else if ((ch = getc(cr_unit.fileref)) != EOF) { - ungetc(ch, cr_unit.fileref); /* put character back; hopper's not empty */ - lastcard = FALSE; - } - else if (deckfile != NULL && nextdeck()) - lastcard = FALSE; - else - lastcard = TRUE; /* there is nothing left to read for a next card */ - - CLRBIT(cr_dsw, CR_DSW_LAST_CARD|CR_DSW_BUSY|CR_DSW_NOT_READY); - - if (lastcard) - SETBIT(cr_dsw, CR_DSW_LAST_CARD); - - if (CURRENT_OP != OP_IDLE) - SETBIT(cr_dsw, CR_DSW_BUSY|CR_DSW_NOT_READY); - else if (readstate == STATION_EMPTY && punchstate == STATION_EMPTY && lastcard) - SETBIT(cr_dsw, CR_DSW_NOT_READY); - - ACC = cr_dsw; /* return the DSW */ - - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Sense %04x%s%s", cr_dsw & 0xFFFF, (modify & 1) ? " RESET0" : "", (modify & 2) ? " RESET4" : ""); - - if (modify & 0x01) { /* reset interrupts */ - CLRBIT(cr_dsw, CR_DSW_READ_RESPONSE|CR_DSW_PUNCH_RESPONSE); - CLRBIT(ILSW[0], ILSW_0_1442_CARD); - } - - if (modify & 0x02) { - CLRBIT(cr_dsw, CR_DSW_OP_COMPLETE); - CLRBIT(ILSW[4], ILSW_4_1442_CARD); - } - break; - - case XIO_READ: /* get card data into word pointed to in IOCC packet */ - if (cr_unit.flags & OP_READING) { - if (cr_unit.COLUMN < 0) { - xio_error("1442: Premature read!"); - } - else if (cr_unit.COLUMN < 80) { - WriteW(addr, readstation[cr_unit.COLUMN]); - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Read %03x", (readstation[cr_unit.COLUMN] >> 4)); - } - else if (cr_unit.COLUMN == 80) { - xio_error("1442: Read past column 80!"); - cr_unit.COLUMN++; // don't report it again - } - } - else { -// don't complain: APL\1130 issues both reads and writes on every interrupt -// (probably to keep the code small). Apparently it's just ignored if corresponding -// control didn't initiate a read cycle. -// xio_error("1442: Read when not in a read cycle!"); - } - break; - - case XIO_WRITE: - if (cr_unit.flags & OP_PUNCHING) { - if (cp_unit.COLUMN < 0) { - xio_error("1442: Premature write!"); - } - else if (cp_unit.flags & UNIT_LASTPUNCH) { - xio_error("1442: Punch past last-punch column!"); - cp_unit.COLUMN = 81; - } - else if (cp_unit.COLUMN < 80) { - wd = ReadW(addr); /* store one word to punch buffer */ - punchstation[cp_unit.COLUMN] = wd & 0xFFF0; - if (wd & 0x0008) /* mark this as last column to be punched */ - SETBIT(cp_unit.flags, UNIT_LASTPUNCH); - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Punch %03x%s", (wd >> 4) & 0xFFF, (wd & 8) ? " LAST" : ""); - } - else if (cp_unit.COLUMN == 80) { - xio_error("1442: Punch past column 80!"); - cp_unit.COLUMN++; // don't report it again - } - } - else { -// don't complain: APL\1130 issues both reads and writes on every interrupt -// (probably to keep the code small). Apparently it's just ignored if corresponding -// control didn't initiate a punch cycle. -// xio_error("1442: Write when not in a punch cycle!"); - } - break; - - case XIO_CONTROL: - switch (modify & 7) { - case 1: /* start punch */ - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Start Punch"); - if (punchstate != STATION_LOADED) - feedcycle(TRUE, TRUE); - - SET_OP(OP_PUNCHING); - cp_unit.COLUMN = -1; - - CLRBIT(cp_unit.flags, UNIT_LASTPUNCH); - - any_punched = 1; /* we've started punching, so enable writing to output deck file */ - - sim_cancel(&cr_unit); - sim_activate(&cr_unit, cp_wait); - break; - - case 2: /* feed cycle */ - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Feed"); - - if (cr_unit.flags & UNIT_PHYSICAL) { - pcr_xio_feedcycle(); - return; - } - feedcycle(TRUE, (cp_unit.flags & UNIT_ATT) != 0); - - SET_OP(OP_FEEDING); - - sim_cancel(&cr_unit); - sim_activate(&cr_unit, cf_wait); - break; - - case 4: /* start read */ - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Start read"); - - if (cp_unit.flags & UNIT_PHYSICAL) { - pcr_xio_startread(); - return; - } - - if (readstate != STATION_LOADED) - feedcycle(TRUE, (cp_unit.flags & UNIT_ATT) != 0); - - SET_OP(OP_READING); - cr_unit.COLUMN = -1; - - sim_cancel(&cr_unit); - sim_activate(&cr_unit, cr_wait); - break; - - case 0: - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR NOP"); - break; - - default: - sprintf(msg, "1442: Multiple operations in XIO_CONTROL: %x", modify); - xio_error(msg); - return; - } - - break; - - default: - sprintf(msg, "Invalid 1442 XIO function %x", func); - xio_error(msg); - break; - } -} - -#if ! (defined(ENABLE_PHYSICAL_CARD_READER_SUPPORT) && defined(WIN32)) - - /* stub out the physical card reader routines */ - - static t_stat pcr_attach (UNIT *uptr, char *devname) {return SCPE_ARG;} - static t_stat pcr_detach (UNIT *uptr) {return detach_unit(uptr);} - static t_stat pcr_svc (UNIT *uptr) {return SCPE_OK;} - static void pcr_xio_sense (int modify) {} - static void pcr_xio_feedcycle (void) {} - static void pcr_xio_startread (void) {} - static void pcr_reset (void) {} - static int pcr_read_data (void) {return 0;} - -#else - -/* - * This code supports a physical card reader interface I built. Details - * available upon request, write to brian@ibm1130.org - - * NOTE: THIS IS NOT COMPLETE OR EVEN CLOSE, JUST SOME CODE SLAMMED INTO THE FILE - */ - -#include - -#define PCR_STATUS_READY 1 -#define PCR_STATUS_ERROR 2 -#define PCR_STATUS_HEMPTY 4 -#define PCR_STATUS_EOF 8 -#define PCR_STATUS_PICKING 16 - -static char pcr_status = '?'; -static void pcr_cmd (char cmd); - -static t_stat pcr_attach (UNIT *uptr, char *devname) -{ - HANDLE hPort; - DCB dcb; - COMMTIMEOUTS cto; - DWORD nerr; - /* open the COM port */ - hPort = CreateFile(devname, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); - if (hPort == INVALID_HANDLE_VALUE) - return SCPE_OPENERR; - - memset(&dcb, 0, sizeof(dcb)); /* set communications parameters */ - - dcb.DCBlength = sizeof(DCB); - dcb.BaudRate = CBR_115200; /* for the USB virtual com port, baud rate is irrelevant */ - dcb.fBinary = 1; - dcb.fParity = 0; - dcb.fOutxCtsFlow = 0; - dcb.fOutxDsrFlow = 0; - dcb.fDtrControl = DTR_CONTROL_ENABLE; - dcb.fDsrSensitivity = FALSE; - dcb.fTXContinueOnXoff = 0; - dcb.fOutX = 0; - dcb.fInX = 0; - dcb.fErrorChar = 0; - dcb.fNull = 0; - dcb.fRtsControl = RTS_CONTROL_ENABLE; - dcb.fAbortOnError = 0; - dcb.XonLim = 0; - dcb.XoffLim = 0; - dcb.ByteSize = 8; - dcb.Parity = NOPARITY; - dcb.StopBits = ONESTOPBIT; - dcb.XonChar = 0; - dcb.XoffChar = 0; - dcb.ErrorChar = 0; - dcb.EofChar = 0; - dcb.EvtChar = 0; - - if (! SetCommState(hPort, &dcb)) { - CloseHandle(hPort); - printf("Call to SetCommState failed\n"); - return SCPE_OPENERR; - } - - cto.ReadIntervalTimeout = 100; // stop if 100 msec elapses between two received bytes - cto.ReadTotalTimeoutMultiplier = 0; // no length sensitivity - cto.ReadTotalTimeoutConstant = 400; // allow 400 msec for a read (reset command can take a while) - - cto.WriteTotalTimeoutMultiplier = 0; - cto.WriteTotalTimeoutConstant = 200; // allow 200 msec for a write - - if (! SetCommTimeouts(hPort, &cto)) { - CloseHandle(hPort); - printf("Call to SetCommTimeouts failed\n"); - return SCPE_OPENERR; - } - - PurgeComm(hPort, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); - ClearCommError(hPort, &nerr, NULL); - - SETBIT(uptr->flags, UNIT_PHYSICAL|UNIT_ATT); /* mark device as attached */ - uptr->filename = calloc(strlen(devname)+1, sizeof(char)); - strcpy(uptr->filename, devname); - - uptr->fileref = (FILE *) hPort; /* store the handle in the slot for the file pointer */ - - cr_unit.COLUMN = -1; /* neither device is currently cycling */ - return SCPE_OK; -} - -static t_stat pcr_detach (UNIT *uptr) -{ - CLRBIT(cr_unit.flags, UNIT_PHYSICAL|UNIT_ATT); /* drop the attach and physical bits */ - - CloseHandle((HANDLE) (uptr->fileref)); /* close the COM port */ - uptr->fileref = NULL; - - free(uptr->filename); /* release the name copy */ - uptr->filename = NULL; - - return SCPE_OK; -} - -static void pcr_xio_sense (int modify) -{ - CLRBIT(cr_dsw, CR_DSW_LAST_CARD|CR_DSW_BUSY|CR_DSW_NOT_READY|CR_DSW_ERROR_CHECK); - - if (pcr_status & PCR_STATUS_HEMPTY) /* set 1130 status bits based on last status recv'd from */ - SETBIT(cr_dsw, CR_DSW_LAST_CARD); /* the card reader */ - - if (pcr_status & PCR_STATUS_ERROR) - SETBIT(cr_dsw, CR_DSW_ERROR_CHECK); - - if (pcr_status & PCR_STATUS_PICKING) - SETBIT(cr_dsw, CR_DSW_BUSY); - - if (! (pcr_status & PCR_STATUS_READY)) - SETBIT(cr_dsw, CR_DSW_NOT_READY); - - if (modify & 0x01) { /* reset simulated interrupts */ - CLRBIT(cr_dsw, CR_DSW_READ_RESPONSE|CR_DSW_PUNCH_RESPONSE); - CLRBIT(ILSW[0], ILSW_0_1442_CARD); - } - - if (modify & 0x02) { - CLRBIT(cr_dsw, CR_DSW_OP_COMPLETE); - CLRBIT(ILSW[4], ILSW_4_1442_CARD); - } - - ACC = cr_dsw; /* return the DSW */ - - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Sense %04x%s%s", cr_dsw, (modify & 1) ? " RESET0" : "", (modify & 2) ? " RESET4" : ""); -} - -static void pcr_xio_feedcycle (void) -{ - pcr_cmd('P'); // initiate pick - SET_OP(OP_FEEDING); -} - -static void pcr_xio_startread (void) -{ - pcr_cmd('P'); // initiate pick - SET_OP(OP_READING); -} - -static void pcr_reset (void) -{ - pcr_cmd('X'); // cancel pending pick -} - -static t_stat pcr_svc (UNIT *uptr) -{ - switch (CURRENT_OP) { - case OP_IDLE: - break; - - case OP_FEEDING: - op_done(); - break; - - case OP_READING: -/* this needs to poll the usb port for a = or ! */ - - if (readstate == STATION_EMPTY) { /* read active but no cards? hang */ - sim_activate(&cr_unit, cf_wait); - break; - } - - if (++cr_unit.COLUMN < 80) { - SETBIT(cr_dsw, CR_DSW_READ_RESPONSE); - SETBIT(ILSW[0], ILSW_0_1442_CARD); - calc_ints(); - sim_activate(&cr_unit, cr_wait); - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("!CR Read Response %d : %d", cardnum, cr_unit.COLUMN+1); - } - else { - readstate = STATION_READ; - op_done(); - } - break; - - case OP_PUNCHING: - return cr_svc(uptr); - } - - return SCPE_OK; -} - -static void pcr_cmd (char cmd) -{ - DWORD nio; - char resp; - int ntries = 10; - BOOL resend = TRUE; - - while (--ntries >= 0) { - if (resend && cmd != 0) { - if (! WriteFile((HANDLE) cr_unit.fileref, &cmd, 1, &nio, NULL)) { - printf("* Error writing to card reader interface\n"); - return; - } - } - - resend = TRUE; - - nio = 0; - ReadFile((HANDLE) cr_unit.fileref, &resp, 1, &nio, NULL); - - if (nio != 1) { - printf("* Timeout reading from card reader interface\n"); - continue; - } - - if (resp == '?') - continue; // it didn't recognize the command - - if (resp >= '@' && resp <= '_') { - pcr_status = resp; - return; - } - - if (resp == '!') { // we were expecting a response, but got a cancellation notice from pending pick - resend = FALSE; // status byte is coming - ntries++; // no penalty - } - else if (resp == '=') { // we were expecting a response, but are getting data from a pending pick - pcr_read_data(); - resend = FALSE; // status byte is coming - ntries++; // no penalty - continue; - } - // else -- just ignore it? - } - - printf("* Card reader interface failed to respond within 10 tries\n"); -} - -static int pcr_read_data (void) -{ - DWORD nio; - - ReadFile((HANDLE) cr_unit.fileref, readstation, 160, &nio, NULL); - return nio == 160; -} - -#endif diff --git a/Ibm1130/ibm1130_defs.h b/Ibm1130/ibm1130_defs.h deleted file mode 100644 index 61b75024..00000000 --- a/Ibm1130/ibm1130_defs.h +++ /dev/null @@ -1,294 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -/* ibm1130_defs.h: IBM-1130 simulator definitions - */ - -#include "sim_defs.h" /* main SIMH defns (include path should include .., or make a copy) */ -#include -#include - -#if defined(VMS) - # include /* to pick up 'unlink' */ -#endif - -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) -#define MAX(a,b) (((a) >= (b)) ? (a) : (b)) - -#ifndef WIN32 - int strnicmp (char *a, char *b, int n); - int strcmpi (char *a, char *b); -#endif - -// #define GUI_SUPPORT // uncomment to compile the GUI extensions. It's defined in the windows ibm1130.mak makefile - -/* ------------------------------------------------------------------------ */ -/* Architectural constants */ - -#define MAXMEMSIZE (32768) /* 32Kwords */ -#define INIMEMSIZE (16384) /* 16Kwords */ -#define MEMSIZE (cpu_unit.capac) - -#define UNIT_MSIZE (1 << (UNIT_V_UF + 7)) /* flag for memory size setting */ - -#define ILL_ADR_FLAG 0x40000000 /* an impossible 1130 address */ - -/* ------------------------------------------------------------------------ */ -/* Global state */ - -extern int cgi; // TRUE if we are running as a CGI program -extern int sim_gui; - -extern uint16 M[]; /* core memory, up to 32Kwords (note: don't even think about trying 64K) */ -extern uint16 ILSW[]; /* interrupt level status words */ -extern int32 IAR; /* instruction address register */ -extern int32 prev_IAR; /* instruction address register at start of current instruction */ -extern int32 SAR, SBR; /* storage address/buffer registers */ -extern int32 OP, TAG, CCC; /* instruction decoded pieces */ -extern int32 CES; /* console entry switches */ -extern int32 ACC, EXT; /* accumulator and extension */ -extern int32 RUNMODE; /* processor run/step mode */ -extern int32 ipl; /* current interrupt level (-1 = not handling irq) */ -extern int32 iplpending; /* interrupted IPL's */ -extern int32 tbit; /* trace flag (causes level 5 IRQ after each instr) */ -extern int32 V, C; /* condition codes */ -extern int32 wait_state; /* wait state (waiting for an IRQ) */ -extern int32 wait_lamp; /* alternate indicator to light the wait lamp on the GUI */ -extern int32 int_req; /* sum of interrupt request levels active */ -extern int32 int_lamps; /* accumulated version of int_req - gives lamp persistence */ -extern int32 int_mask; /* current active interrupt mask (ipl sensitive) */ -extern int32 mem_mask; -extern int32 cpu_dsw; /* CPU device status word */ -extern int32 sim_int_char; /* interrupt character */ -extern t_bool running; -extern t_bool power; -extern t_bool cgi; /* TRUE if we are running as a CGI program */ -extern t_stat reason; /* CPU execution loop control */ - -#define WAIT_OP 1 /* wait state causes: wait instruction, invalid instruction*/ -#define WAIT_INVALID_OP 2 - -#define MODE_SS 3 /* RUNMODE values. SS and SMC are not implemented in this simulator */ -#define MODE_SMC 2 -#define MODE_INT_RUN 1 -#define MODE_RUN 0 -#define MODE_SI -1 -#define MODE_DISP -2 -#define MODE_LOAD -3 - -/* ------------------------------------------------------------------------ */ -/* debugging */ -/* ------------------------------------------------------------------------ */ - -#define ENABLE_DEBUG_PRINT -#define ENABLE_DEBUG_TO_LOG - -#ifdef ENABLE_DEBUG_PRINT -# define DEBUG_PRINT debug_print -#else -# ifdef ENABLE_DEBUG_TO_LOG -# define DEBUG_PRINT trace_io -# else -# define DEBUG_PRINT if (0) debug_print -# endif -#endif - -void debug_print(char *fmt, ...); - -/* ------------------------------------------------------------------------ */ -/* memory IO routines */ - -int32 ReadW (int32 a); -void WriteW (int32 a, int32 d); - -/* ------------------------------------------------------------------------ */ -/* handy macros */ - -#define CLRBIT(v,b) ((v) &= ~(b)) -#define SETBIT(v,b) ((v) |= (b)) -#define BETWEEN(v,a,b) (((v) >= (a)) && ((v) <= (b))) - -/* ------------------------------------------------------------------------ */ -/* Simulator stop codes */ - -#define STOP_WAIT 1 /* wait, no events */ -#define STOP_INVALID_INSTR 2 /* bad instruction */ -#define STOP_IBKPT 3 /* simulator breakpoint */ -#define STOP_INCOMPLETE 4 /* simulator coding not complete here */ -#define STOP_POWER_OFF 5 /* no power */ -#define STOP_DECK_BREAK 6 /* !BREAK in deck file */ -#define STOP_PHASE_BREAK 7 /* phase load break */ -#define STOP_CRASH 8 /* program has crashed badly */ -#define STOP_TIMED_OUT 9 /* simulation time limit exceeded */ - -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ - -#define INT_REQ_0 0x01 /* bits for interrupt levels (ipl, iplpending, int_req, int_mask) */ -#define INT_REQ_1 0x02 -#define INT_REQ_2 0x04 -#define INT_REQ_3 0x08 -#define INT_REQ_4 0x10 -#define INT_REQ_5 0x20 - -#define XIO_UNUSED 0x00 /* XIO commands */ -#define XIO_WRITE 0x01 -#define XIO_READ 0x02 -#define XIO_SENSE_IRQ 0x03 -#define XIO_CONTROL 0x04 -#define XIO_INITW 0x05 -#define XIO_INITR 0x06 -#define XIO_SENSE_DEV 0x07 - -#define XIO_FAILED 0x20 /* fake function to record error */ - -/* ILSW bits - set by appropriate device whenever an interrupt is outstanding */ - -#define ILSW_0_1442_CARD 0x8000 /* ILSW 0 is not really defined on the 1130 */ - -#define ILSW_1_1132_PRINTER 0x8000 // had these backwards! -#define ILSW_1_SCA 0x4000 - -#define ILSW_2_1131_DISK 0x8000 - -#define ILSW_2_2310_DRV_1 0x4000 -#define ILSW_2_2310_DRV_2 0x2000 -#define ILSW_2_2310_DRV_3 0x1000 -#define ILSW_2_2310_DRV_4 0x0800 /* can have 2310 or 2311 */ - -#define ILSW_2_2311_DRV_1_DISK_1 0x4000 -#define ILSW_2_2311_DRV_1_DISK_2 0x2000 -#define ILSW_2_2311_DRV_1_DISK_3 0x1000 -#define ILSW_2_2311_DRV_1_DISK_4 0x0800 - -#define ILSW_2_2311_DRV_1_DISK_5 0x0400 -#define ILSW_2_2311_DRV_2_DISK_1 0x0200 -#define ILSW_2_2311_DRV_2_DISK_2 0x0100 -#define ILSW_2_2311_DRV_2_DISK_3 0x0080 -#define ILSW_2_2311_DRV_2_DISK_4 0x0040 -#define ILSW_2_2311_DRV_2_DISK_5 0x0020 - -#define ILSW_2_SAC_BIT_11 0x0010 -#define ILSW_2_SAC_BIT_12 0x0008 -#define ILSW_2_SAC_BIT_13 0x0004 -#define ILSW_2_SAC_BIT_14 0x0002 -#define ILSW_2_SAC_BIT_15 0x0001 - -#define ILSW_3_1627_PLOTTER 0x8000 -#define ILSW_3_SAC_BIT_01 0x4000 -#define ILSW_3_SAC_BIT_02 0x2000 -#define ILSW_3_SAC_BIT_03 0x1000 -#define ILSW_3_2250_DISPLAY 0x0800 -#define ILSW_3_SYSTEM7 0x0800 -#define ILSW_3_SAC_BIT_05 0x0400 -#define ILSW_3_SAC_BIT_06 0x0200 -#define ILSW_3_SAC_BIT_07 0x0100 -#define ILSW_3_SAC_BIT_08 0x0080 -#define ILSW_3_SAC_BIT_09 0x0040 -#define ILSW_3_SAC_BIT_10 0x0020 -#define ILSW_3_SAC_BIT_11 0x0010 -#define ILSW_3_SAC_BIT_12 0x0008 -#define ILSW_3_SAC_BIT_13 0x0004 -#define ILSW_3_SAC_BIT_14 0x0002 -#define ILSW_3_SAC_BIT_15 0x0001 - -#define ILSW_4_1134_TAPE 0x8000 -#define ILSW_4_1055_TAPE 0x8000 -#define ILSW_4_CONSOLE 0x4000 -#define ILSW_4_1442_CARD 0x2000 -#define ILSW_4_2501_CARD 0x1000 -#define ILSW_4_1403_PRINTER 0x0800 -#define ILSW_4_1231_MARK 0x0400 -#define ILSW_4_SAC_BIT_06 0x0200 -#define ILSW_4_SAC_BIT_07 0x0100 -#define ILSW_4_SAC_BIT_08 0x0080 -#define ILSW_4_SAC_BIT_09 0x0040 -#define ILSW_4_SAC_BIT_10 0x0020 -#define ILSW_4_SAC_BIT_11 0x0010 -#define ILSW_4_SAC_BIT_12 0x0008 -#define ILSW_4_SAC_BIT_13 0x0004 -#define ILSW_4_SAC_BIT_14 0x0002 -#define ILSW_4_SAC_BIT_15 0x0001 - -#define ILSW_5_INT_RUN 0x8000 -#define ILSW_5_PROGRAM_STOP 0x8000 -#define ILSW_5_SAC_BIT_01 0x4000 -#define ILSW_5_SAC_BIT_02 0x2000 -#define ILSW_5_SAC_BIT_03 0x1000 -#define ILSW_5_SAC_BIT_04 0x0800 -#define ILSW_5_SAC_BIT_05 0x0400 -#define ILSW_5_SAC_BIT_06 0x0200 -#define ILSW_5_SAC_BIT_07 0x0100 -#define ILSW_5_SAC_BIT_08 0x0080 -#define ILSW_5_SAC_BIT_09 0x0040 -#define ILSW_5_SAC_BIT_10 0x0020 -#define ILSW_5_SAC_BIT_11 0x0010 -#define ILSW_5_SAC_BIT_12 0x0008 -#define ILSW_5_SAC_BIT_13 0x0004 -#define ILSW_5_SAC_BIT_14 0x0002 -#define ILSW_5_SAC_BIT_15 0x0001 - -//* CPU DSW bits - -#define CPU_DSW_PROGRAM_STOP 0x8000 -#define CPU_DSW_INT_RUN 0x4000 - -/* prototypes: xio handlers */ - -void xio_1131_console (int32 addr, int32 func, int32 modify); // console keyboard and printer -void xio_1142_card (int32 addr, int32 func, int32 modify); // standard card reader/punch -void xio_1134_papertape (int32 addr, int32 func, int32 modify); // paper tape reader/punch -void xio_disk (int32 addr, int32 func, int32 modify, int drv); // internal CPU disk -void xio_1627_plotter (int32 addr, int32 func, int32 modify); // XY plotter -void xio_1132_printer (int32 addr, int32 func, int32 modify); // standard line printer -void xio_1131_switches (int32 addr, int32 func, int32 modify); // console buttons & switches -void xio_1231_optical (int32 addr, int32 func, int32 modify); // optical mark page reader -void xio_2501_card (int32 addr, int32 func, int32 modify); // alternate high-speed card reader -void xio_1131_synch (int32 addr, int32 func, int32 modify); // synchronous communications adapter -void xio_system7 (int32 addr, int32 func, int32 modify); // system/7 interprocessor IO link -void xio_1403_printer (int32 addr, int32 func, int32 modify); // alternate high-speed printer -void xio_2250_display (int32 addr, int32 func, int32 modify); // vector display processor -void xio_error (char *msg); - -void bail (char *msg); -t_stat load_cr_boot (int drv, int switches); -t_stat cr_boot (int unitno, DEVICE *dptr); -void calc_ints (void); /* recalculate interrupt bitmask */ -void trace_io (char *fmt, ...); /* debugging printout */ -void scp_panic (char *msg); /* bail out of simulator */ -char *upcase(char *str); -void break_simulation (t_stat reason); /* let a device halt the simulation */ -char hollerith_to_ascii (uint16 hol); /* for debugging use only */ -t_bool gdu_active (void); -void remark_cmd (char *remark); -void stuff_cmd (char *cmd); -void update_gui (t_bool force); -void sim_init (void); -t_stat register_cmd (char *name, t_stat (*action)(int32 flag, char *ptr), int arg, char *help); - -/* GUI interface routines */ -t_bool keyboard_is_busy (void); -void forms_check (int set); /* device notification to console lamp display */ -void print_check (int set); -void keyboard_selected (int select); -void disk_ready (int ready); -void disk_unlocked (int unlocked); -void gui_run(int running); -char *read_cmdline (char *ptr, int size, FILE *stream); - -#ifdef GUI_SUPPORT -# define GUI_BEGIN_CRITICAL_SECTION begin_critical_section(); -# define GUI_END_CRITICAL_SECTION end_critical_section(); - void begin_critical_section (void); - void end_critical_section (void); -#else -# define GUI_BEGIN_CRITICAL_SECTION -# define GUI_END_CRITICAL_SECTION -#endif diff --git a/Ibm1130/ibm1130_disk.c b/Ibm1130/ibm1130_disk.c deleted file mode 100644 index 756b2e5a..00000000 --- a/Ibm1130/ibm1130_disk.c +++ /dev/null @@ -1,875 +0,0 @@ -/* ibm1130_disk.c: IBM 1130 disk IO simulator - -NOTE - there is a problem with this code. The Device Status Word (DSW) is -computed from current conditions when requested by an XIO load status -command; the value of DSW available to the simulator's examine & save -commands may NOT be accurate. This should probably be fixed. - - Based on the SIMH package written by Robert M Supnik - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * Revision History - * 15-jun-03 moved actual read on XIO read to end of time interval, - * as the APL boot card required 2 instructions to run between the - * time read was initiated and the time the data was read (a jump and a wait) - * - * 01-sep-02 corrected treatment of -m and -r flags in dsk_attach - * in cgi mode, so that file is opened readonly but emulated - * disk is writable. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - */ - -#include "ibm1130_defs.h" -#include "memory.h" - -#define TRACE_DMS_IO // define to enable debug of DMS phase IO - -#ifdef TRACE_DMS_IO -extern int32 sim_switches; -extern int32 sim_quiet; -static int trace_dms = 0; -static void tracesector (int iswrite, int nwords, int addr, int sector); -static t_stat where_cmd (int flag, char *ptr); -static t_stat phdebug_cmd (int flag, char *ptr); -static t_stat fdump_cmd (int flags, char *cptr); -static void enable_dms_tracing (int newsetting); -#endif - -/* Constants */ - -#define DSK_NUMWD 321 /* words/sector */ -#define DSK_NUMSC 4 /* sectors/surface */ -#define DSK_NUMSF 2 /* surfaces/cylinder */ -#define DSK_NUMCY 203 /* cylinders/drive */ -#define DSK_NUMTR (DSK_NUMCY * DSK_NUMSF) /* tracks/drive */ -#define DSK_NUMDR 5 /* drives/controller */ -#define DSK_SIZE (DSK_NUMCY * DSK_NUMSF * DSK_NUMSC * DSK_NUMWD) /* words/drive */ - -#define UNIT_V_RONLY (UNIT_V_UF + 0) /* hwre write lock */ -#define UNIT_V_OPERR (UNIT_V_UF + 1) /* operation error flag */ -#define UNIT_V_HARDERR (UNIT_V_UF + 2) /* hard error flag (reset on power down) */ -#define UNIT_RONLY (1u << UNIT_V_RONLY) -#define UNIT_OPERR (1u << UNIT_V_OPERR) -#define UNIT_HARDERR (1u << UNIT_V_HARDERR) - -#define MEM_MAPPED(uptr) (uptr->flags & UNIT_BUF) /* disk buffered in memory */ - -#define IO_NONE 0 /* last operation, used to ensure fseek between read and write */ -#define IO_READ 1 -#define IO_WRITE 2 - -#define DSK_DSW_DATA_ERROR 0x8000 /* device status word bits */ -#define DSK_DSW_OP_COMPLETE 0x4000 -#define DSK_DSW_NOT_READY 0x2000 -#define DSK_DSW_DISK_BUSY 0x1000 -#define DSK_DSW_CARRIAGE_HOME 0x0800 -#define DSK_DSW_SECTOR_MASK 0x0003 - - /* device status words */ -static int16 dsk_dsw[DSK_NUMDR] = {DSK_DSW_NOT_READY, DSK_DSW_NOT_READY, DSK_DSW_NOT_READY, DSK_DSW_NOT_READY, DSK_DSW_NOT_READY}; -static int16 dsk_sec[DSK_NUMDR] = {0}; /* next-sector-up */ -static char dsk_lastio[DSK_NUMDR]; /* last stdio operation: IO_READ or IO_WRITE */ -int32 dsk_swait = 50; /* seek time -- see how short a delay we can get away with */ -int32 dsk_rwait = 50; /* rotate time */ -static t_bool raw_disk_debug = FALSE; - -static t_stat dsk_svc (UNIT *uptr); -static t_stat dsk_reset (DEVICE *dptr); -static t_stat dsk_attach (UNIT *uptr, char *cptr); -static t_stat dsk_detach (UNIT *uptr); -static t_stat dsk_boot (int unitno, DEVICE *dptr); - -static void diskfail (UNIT *uptr, int errflag); - -/* DSK data structures - - dsk_dev disk device descriptor - dsk_unit unit descriptor - dsk_reg register list -*/ - -UNIT dsk_unit[] = { - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) } -}; - -#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT) - -/* Parameters in the unit descriptor */ - -#define CYL u3 /* current cylinder */ -#define FUNC u4 /* current function */ - -REG dsk_reg[] = { - { HRDATA (DSKDSW0, dsk_dsw[0], 16) }, - { HRDATA (DSKDSW1, dsk_dsw[1], 16) }, - { HRDATA (DSKDSW2, dsk_dsw[2], 16) }, - { HRDATA (DSKDSW3, dsk_dsw[3], 16) }, - { HRDATA (DSKDSW4, dsk_dsw[4], 16) }, - { DRDATA (STIME, dsk_swait, 24), PV_LEFT }, - { DRDATA (RTIME, dsk_rwait, 24), PV_LEFT }, - { NULL } }; - -MTAB dsk_mod[] = { - { UNIT_RONLY, 0, "write enabled", "ENABLED", NULL }, - { UNIT_RONLY, UNIT_RONLY, "write locked", "LOCKED", NULL }, - { 0 } }; - -DEVICE dsk_dev = { - "DSK", dsk_unit, dsk_reg, dsk_mod, - DSK_NUMDR, 16, 16, 1, 16, 16, - NULL, NULL, &dsk_reset, - dsk_boot, dsk_attach, dsk_detach}; - -static int32 dsk_ilswbit[DSK_NUMDR] = { /* interrupt level status word bits for the drives */ - ILSW_2_1131_DISK, - ILSW_2_2310_DRV_1, - ILSW_2_2310_DRV_2, - ILSW_2_2310_DRV_3, - ILSW_2_2310_DRV_4, -}; - -static int32 dsk_ilswlevel[DSK_NUMDR] = -{ - 2, /* interrupt levels for the drives */ - 2, 2, 2, 2 -}; - -typedef enum {DSK_FUNC_IDLE, DSK_FUNC_READ, DSK_FUNC_VERIFY, DSK_FUNC_WRITE, DSK_FUNC_SEEK, DSK_FUNC_FAILED} DSK_FUNC; - -static struct tag_dsk_action { /* stores data needed for pending IO activity */ - int32 io_address; - uint32 io_filepos; - int io_nwords; - int io_sector; -} dsk_action[DSK_NUMDR]; - -/* xio_disk - XIO command interpreter for the disk drives */ -/* - * device status word: - * - * 0 data error, occurs when: - * 1. A modulo 4 error is detected during a read, read-check, or write operation. - * 2. The disk storage is in a read or write mode at the leading edge of a sector pulse. - * 3. A seek-incomplete signal is received from the 2311. - * 4. A write select error has occurred in the disk storage drive. - * 5. The power unsafe latch is set in the attachment. - * Conditions 1, 2, and 3 are turned off by a sense device command with modifier bit 15 - * set to 1. Conditions 4 and 5 are turned off by powering the drive off and back on. - * 1 operation complete - * 2 not ready, occurs when disk not ready or busy or disabled or off-line or - * power unsafe latch set. Also included in the disk not ready is the write select error, - * which can be a result of power unsafe or write select. - * 3 disk busy - * 4 carriage home (on cyl 0) - * 15-16: number of next sector spinning into position. - */ - -extern void void_backtrace (int afrom, int ato); - -void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv) -{ - int i, rev, nsteps, newcyl, sec, nwords; - uint32 newpos; // changed from t_addr to uint32 in anticipation of simh 64-bit development - char msg[80]; - UNIT *uptr = dsk_unit+drv; - int16 buf[DSK_NUMWD]; - - if (! BETWEEN(drv, 0, DSK_NUMDR-1)) { // hmmm, invalid drive */ - if (func != XIO_SENSE_DEV) { // tried to use it, too - // just do nothing, as if the controller isn't there. NAMCRA at N0116300 tests for drives by attempting reads -// sprintf(msg, "Op %x on invalid drive number %d", func, drv); -// xio_error(msg); - } - return; - } - - CLRBIT(uptr->flags, UNIT_OPERR); /* clear pending error flag from previous op, if any */ - - switch (func) { - case XIO_INITR: - if (! IS_ONLINE(uptr)) { /* disk is offline */ - diskfail(uptr, UNIT_HARDERR); /* make error stick till reset or attach */ - break; - } - - sim_cancel(uptr); /* cancel any pending ops */ - dsk_dsw[drv] |= DSK_DSW_DISK_BUSY; /* and mark the disk as busy */ - - nwords = M[iocc_addr++ & mem_mask]; /* get word count w/o upsetting SAR/SBR */ - - if (nwords == 0) /* this is bad -- on real 1130, this locks up disk controller ! */ - break; - - if (! BETWEEN(nwords, 1, DSK_NUMWD)) { /* count bad */ - SETBIT(uptr->flags, UNIT_OPERR); /* set data error DSW bit when op complete */ - nwords = DSK_NUMWD; /* limit xfer to proper sector size */ - } - - sec = modify & 0x07; /* get sector on cylinder */ - - if ((modify & 0x0080) == 0) { /* it's a real read if it's not a read check */ - // ah. We have a problem. The APL boot card counts on there being time for at least one - // more instruction to execute between the XIO read and the time the data starts loading - // into core. So, we have to defer the actual read operation a bit. Might as well wait - // until it's time to issue the operation complete interrupt. This means saving the - // IO information, then performing the actual read in dsk_svc. - - newpos = (uptr->CYL*DSK_NUMSC*DSK_NUMSF + sec)*2*DSK_NUMWD; - - dsk_action[drv].io_address = iocc_addr; - dsk_action[drv].io_nwords = nwords; - dsk_action[drv].io_sector = sec; - dsk_action[drv].io_filepos = newpos; - - uptr->FUNC = DSK_FUNC_READ; - } - else { - trace_io("* DSK%d verify %d.%d (%x)", drv, uptr->CYL, sec, uptr->CYL*8 + sec); - - if (raw_disk_debug) - printf("* DSK%d verify %d.%d (%x)", drv, uptr->CYL, sec, uptr->CYL*8 + sec); - - uptr->FUNC = DSK_FUNC_VERIFY; - } - - sim_activate(uptr, dsk_rwait); - break; - - case XIO_INITW: - if (! IS_ONLINE(uptr)) { /* disk is offline */ - diskfail(uptr, UNIT_HARDERR); /* make error stick till reset or attach */ - break; - } - - if (uptr->flags & UNIT_RONLY) { /* oops, write to RO disk? permanent error */ - diskfail(uptr, UNIT_HARDERR); - break; - } - - sim_cancel(uptr); /* cancel any pending ops */ - dsk_dsw[drv] |= DSK_DSW_DISK_BUSY; /* and mark drive as busy */ - - nwords = M[iocc_addr++ & mem_mask]; /* get word count w/o upsetting SAR/SBR */ - - if (nwords == 0) /* this is bad -- locks up disk controller ! */ - break; - - if (! BETWEEN(nwords, 1, DSK_NUMWD)) { /* count bad */ - SETBIT(uptr->flags, UNIT_OPERR); /* set data error DSW bit when op complete */ - nwords = DSK_NUMWD; /* limit xfer to proper sector size */ - } - - sec = modify & 0x07; /* get sector on cylinder */ - newpos = (uptr->CYL*DSK_NUMSC*DSK_NUMSF + sec)*2*DSK_NUMWD; - - trace_io("* DSK%d wrote %d words from M[%04x-%04x] to %d.%d (%x, %x)", drv, nwords, iocc_addr & mem_mask, (iocc_addr + nwords - 1) & mem_mask, uptr->CYL, sec, uptr->CYL*8 + sec, newpos); - - if (raw_disk_debug) - printf("* DSK%d XIO @ %04x wrote %d words from M[%04x-%04x] to %d.%d (%x, %x)\n", drv, prev_IAR, nwords, iocc_addr & mem_mask, (iocc_addr + nwords - 1) & mem_mask, uptr->CYL, sec, uptr->CYL*8 + sec, newpos); - -#ifdef TRACE_DMS_IO - if (trace_dms) - tracesector(1, nwords, iocc_addr & mem_mask, uptr->CYL*8 + sec); -#endif - for (i = 0; i < nwords; i++) - buf[i] = M[iocc_addr++ & mem_mask]; - - for (; i < DSK_NUMWD; i++) /* rest of sector gets zeroed */ - buf[i] = 0; - - i = uptr->CYL*8 + sec; - if (buf[0] != i) - printf("*DSK writing bad sector#\n"); - - if (MEM_MAPPED(uptr)) { - memcpy((char *) uptr->filebuf + newpos, buf, 2*DSK_NUMWD); - uptr->hwmark = newpos + 2*DSK_NUMWD; - } - else { - if (uptr->pos != newpos || dsk_lastio[drv] != IO_WRITE) { - fseek(uptr->fileref, newpos, SEEK_SET); - dsk_lastio[drv] = IO_WRITE; - } - - fxwrite(buf, 2, DSK_NUMWD, uptr->fileref); - uptr->pos = newpos + 2*DSK_NUMWD; - } - - uptr->FUNC = DSK_FUNC_WRITE; - sim_activate(uptr, dsk_rwait); - break; - - case XIO_CONTROL: /* step fwd/rev */ - if (! IS_ONLINE(uptr)) { - diskfail(uptr, UNIT_HARDERR); - break; - } - - sim_cancel(uptr); - - rev = modify & 4; - nsteps = iocc_addr & 0x00FF; - if (nsteps == 0) /* 0 steps does not cause op complete interrupt */ - break; - - newcyl = uptr->CYL + (rev ? (-nsteps) : nsteps); - if (newcyl < 0) - newcyl = 0; - else if (newcyl >= DSK_NUMCY) - newcyl = DSK_NUMCY-1; - - uptr->FUNC = DSK_FUNC_SEEK; - uptr->CYL = newcyl; - sim_activate(uptr, dsk_swait); /* schedule interrupt */ - - dsk_dsw[drv] |= DSK_DSW_DISK_BUSY; - trace_io("* DSK%d at cyl %d", drv, newcyl); - break; - - case XIO_SENSE_DEV: - CLRBIT(dsk_dsw[drv], DSK_DSW_CARRIAGE_HOME|DSK_DSW_NOT_READY); - - if ((uptr->flags & UNIT_HARDERR) || (dsk_dsw[drv] & DSK_DSW_DISK_BUSY) || ! IS_ONLINE(uptr)) - SETBIT(dsk_dsw[drv], DSK_DSW_NOT_READY); - else if (uptr->CYL <= 0) { - SETBIT(dsk_dsw[drv], DSK_DSW_CARRIAGE_HOME); - uptr->CYL = 0; - } - - dsk_sec[drv] = (dsk_sec[drv] + 1) % 4; /* advance the "next sector" count every time */ - ACC = dsk_dsw[drv] | dsk_sec[drv]; - - if (modify & 0x01) { /* reset interrupts */ - CLRBIT(dsk_dsw[drv], DSK_DSW_OP_COMPLETE|DSK_DSW_DATA_ERROR); - CLRBIT(ILSW[dsk_ilswlevel[drv]], dsk_ilswbit[drv]); - } - break; - - default: - sprintf(msg, "Invalid disk XIO function %x", func); - xio_error(msg); - } -} - -/* diskfail - schedule an operation complete that sets the error bit */ - -static void diskfail (UNIT *uptr, int errflag) -{ - sim_cancel(uptr); /* cancel any pending ops */ - SETBIT(uptr->flags, errflag); /* set the error flag */ - uptr->FUNC = DSK_FUNC_FAILED; /* tell svc routine why it failed */ - sim_activate(uptr, 1); /* schedule an immediate op complete interrupt */ -} - -t_stat dsk_svc (UNIT *uptr) -{ - int drv = uptr - dsk_unit, i, nwords, sec; - int16 buf[DSK_NUMWD]; - uint32 newpos; // changed from t_addr to uint32 in anticipation of simh 64-bit development - int32 iocc_addr; - - if (uptr->FUNC == DSK_FUNC_IDLE) /* service function called with no activity? not good, but ignore */ - return SCPE_OK; - - CLRBIT(dsk_dsw[drv], DSK_DSW_DISK_BUSY); /* activate operation complete interrupt */ - SETBIT(dsk_dsw[drv], DSK_DSW_OP_COMPLETE); - - if (uptr->flags & (UNIT_OPERR|UNIT_HARDERR)) { /* word count error or data error */ - SETBIT(dsk_dsw[drv], DSK_DSW_DATA_ERROR); - CLRBIT(uptr->flags, UNIT_OPERR); /* soft error is one time occurrence; don't clear hard error */ - } - /* schedule interrupt */ - SETBIT(ILSW[dsk_ilswlevel[drv]], dsk_ilswbit[drv]); - - switch (uptr->FUNC) { /* take care of business */ - case DSK_FUNC_IDLE: - case DSK_FUNC_VERIFY: - case DSK_FUNC_WRITE: - case DSK_FUNC_SEEK: - case DSK_FUNC_FAILED: - break; - - case DSK_FUNC_READ: /* actually read the data into core */ - iocc_addr = dsk_action[drv].io_address; /* recover saved parameters */ - nwords = dsk_action[drv].io_nwords; - newpos = dsk_action[drv].io_filepos; - sec = dsk_action[drv].io_sector; - - if (MEM_MAPPED(uptr)) { - memcpy(buf, (char *) uptr->filebuf + newpos, 2*DSK_NUMWD); - } - else { - if (uptr->pos != newpos || dsk_lastio[drv] != IO_READ) { - fseek(uptr->fileref, newpos, SEEK_SET); - dsk_lastio[drv] = IO_READ; - uptr->pos = newpos; - } - fxread(buf, 2, DSK_NUMWD, uptr->fileref); // read whole sector so we're in position for next read - uptr->pos = newpos + 2*DSK_NUMWD; - } - - void_backtrace(iocc_addr, iocc_addr + nwords - 1); // mark prev instruction as altered - - trace_io("* DSK%d read %d words from %d.%d (%x, %x) to M[%04x-%04x]", drv, nwords, uptr->CYL, sec, uptr->CYL*8 + sec, newpos, iocc_addr & mem_mask, - (iocc_addr + nwords - 1) & mem_mask); - -// // this will help debug the monitor by letting me watch phase loading - if (raw_disk_debug) - printf("* DSK%d XIO @ %04x read %d words from %d.%d (%x, %x) to M[%04x-%04x]\n", drv, prev_IAR, nwords, uptr->CYL, sec, uptr->CYL*8 + sec, newpos, iocc_addr & mem_mask, - (iocc_addr + nwords - 1) & mem_mask); - - i = uptr->CYL*8 + sec; - if (buf[0] != i) - printf("*DSK read bad sector #\n"); - - for (i = 0; i < nwords; i++) - M[(iocc_addr+i) & mem_mask] = buf[i]; - -#ifdef TRACE_DMS_IO - if (trace_dms) - tracesector(0, nwords, iocc_addr & mem_mask, uptr->CYL*8 + sec); -#endif - break; - - default: - fprintf(stderr, "Unexpected FUNC %x in dsk_svc(%d)\n", uptr->FUNC, drv); - break; - - } - - uptr->FUNC = DSK_FUNC_IDLE; // we're done with this operation - - return SCPE_OK; -} - -t_stat dsk_reset (DEVICE *dptr) -{ - int drv; - UNIT *uptr; - -#ifdef TRACE_DMS_IO - // add the WHERE command. It finds the phase that was loaded at given address and indicates - // the offset in the phase - register_cmd("WHERE", &where_cmd, 0, "w{here} address find phase and offset of an address\n"); - register_cmd("PHDEBUG", &phdebug_cmd, 0, "ph{debug} off|phlo phhi break on phase load\n"); - register_cmd("FDUMP", &fdump_cmd, 0, NULL); -#endif - - for (drv = 0, uptr = dsk_dev.units; drv < DSK_NUMDR; drv++, uptr++) { - sim_cancel(uptr); - - CLRBIT(ILSW[2], dsk_ilswbit[drv]); - CLRBIT(uptr->flags, UNIT_OPERR|UNIT_HARDERR); - - uptr->CYL = 0; - uptr->FUNC = DSK_FUNC_IDLE; - dsk_dsw[drv] = (uptr->flags & UNIT_ATT) ? DSK_DSW_CARRIAGE_HOME : 0; - } - - calc_ints(); - - return SCPE_OK; -} - -static t_stat dsk_attach (UNIT *uptr, char *cptr) -{ - int drv = uptr - dsk_unit; - t_stat rval; - - sim_cancel(uptr); // cancel current IO - dsk_lastio[drv] = IO_NONE; - - if (uptr->flags & UNIT_ATT) // dismount current disk - if ((rval = dsk_detach(uptr)) != SCPE_OK) - return rval; - - uptr->CYL = 0; // reset the device - uptr->FUNC = DSK_FUNC_IDLE; - dsk_dsw[drv] = DSK_DSW_CARRIAGE_HOME; - - CLRBIT(uptr->flags, UNIT_RO|UNIT_ROABLE|UNIT_BUFABLE|UNIT_BUF|UNIT_RONLY|UNIT_OPERR|UNIT_HARDERR); - CLRBIT(ILSW[2], dsk_ilswbit[drv]); - calc_ints(); - - if (sim_switches & SWMASK('M')) // if memory mode (e.g. for CGI), buffer the file - SETBIT(uptr->flags, UNIT_BUFABLE); - - if (sim_switches & SWMASK('R')) // read lock mode - SETBIT(uptr->flags, UNIT_RO|UNIT_ROABLE|UNIT_RONLY); - - if (cgi && (sim_switches & SWMASK('M'))) { // if cgi and memory mode, - sim_switches |= SWMASK('R'); // have attach_unit open file in readonly mode - SETBIT(uptr->flags, UNIT_ROABLE|UNIT_MUSTBUF); // but don't set the UNIT_RONLY flag so DMS can write to the buffered image - } - - if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) { // mount new disk - SETBIT(dsk_dsw[drv], DSK_DSW_NOT_READY); - return rval; - } - - if (drv == 0) { - disk_ready(TRUE); - disk_unlocked(FALSE); - } - - enable_dms_tracing(sim_switches & SWMASK('D')); - raw_disk_debug = sim_switches & SWMASK('G'); - - return SCPE_OK; -} - -static t_stat dsk_detach (UNIT *uptr) -{ - t_stat rval; - int drv = uptr - dsk_unit; - - sim_cancel(uptr); - - if ((rval = detach_unit (uptr)) != SCPE_OK) - return rval; - - CLRBIT(ILSW[2], dsk_ilswbit[drv]); - CLRBIT(uptr->flags, UNIT_OPERR|UNIT_HARDERR); - calc_ints(); - - uptr->CYL = 0; - uptr->FUNC = DSK_FUNC_IDLE; - dsk_dsw[drv] = DSK_DSW_NOT_READY; - - if (drv == 0) { - disk_unlocked(TRUE); - disk_ready(FALSE); - } - - return SCPE_OK; -} - -// boot routine - if they type BOOT DSK, load the standard boot card. - -static t_stat dsk_boot (int unitno, DEVICE *dptr) -{ - t_stat rval; - - if ((rval = reset_all(0)) != SCPE_OK) - return rval; - - return load_cr_boot(unitno, sim_switches); -} - -#ifdef TRACE_DMS_IO - -static struct { - int phid; - char *name; -} phase[] = { -# include "dmsr2v12phases.h" - 0xFFFF, "" -}; - -#pragma pack(2) -#define MAXSLET ((3*320)/4) -struct tag_slet { - int16 phid; - int16 addr; - int16 nwords; - int16 sector; -} slet[MAXSLET] = { -# include "dmsr2v12slet.h" // without RPG, use this info until overwritten by actual data from disk -}; - -#pragma pack() - -#define MAXMSEG 100 -struct tag_mseg { - char *name; - int addr, offset, len, phid; -} mseg[MAXMSEG]; -int nseg = 0; - -static void enable_dms_tracing (int newsetting) -{ - nseg = 0; // clear the segment map - - if ((newsetting && trace_dms) || ! (newsetting || trace_dms)) - return; - - trace_dms = newsetting; - if (! sim_quiet) - printf("DMS disk tracing is now %sabled\n", trace_dms ? "en" : "dis"); -} - -char * saywhere (int addr) -{ - int i; - static char buf[150]; - - for (i = 0; i < nseg; i++) { - if (addr >= mseg[i].addr && addr < (mseg[i].addr+mseg[i].len)) { - sprintf(buf, "/%04x = /%04x + /%x in ", addr, mseg[i].addr - mseg[i].offset, addr-mseg[i].addr + mseg[i].offset); - if (mseg[i].phid > 0) - sprintf(buf+strlen(buf), "phase %02x (%s)", mseg[i].phid, mseg[i].name); - else - sprintf(buf+strlen(buf), "%s", mseg[i].name); - - return buf; - } - } - return NULL; -} - -static int phdebug_lo = -1, phdebug_hi = -1; - -static t_stat phdebug_cmd (int flag, char *ptr) -{ - int val1, val2; - - if (strcmpi(ptr, "off") == 0) - phdebug_lo = phdebug_hi = -1; - else { - switch(sscanf(ptr, "%x%x", &val1, &val2)) { - case 1: - phdebug_lo = phdebug_hi = val1; - enable_dms_tracing(TRUE); - break; - - case 2: - phdebug_lo = val1; - phdebug_hi = val2; - enable_dms_tracing(TRUE); - break; - - default: - printf("Usage: phdebug off | phdebug phfrom [phto]\n"); - break; - } - } - return SCPE_OK; -} - -static t_stat where_cmd (int flag, char *ptr) -{ - int addr; - char *where; - - if (! trace_dms) { - printf("Tracing is disabled. To enable, attach disk with -d switch\n"); - return SCPE_OK; - } - - if (sscanf(ptr, "%x", &addr) != 1) - return SCPE_ARG; - - if ((where = saywhere(addr)) == NULL) - printf("/%04x not found\n", addr); - else - printf("%s\n", where); - - return SCPE_OK; -} - -// savesector - save info on a sector just read. THIS IS NOT YET TESTED - -static void addseg (int i) -{ - if (! trace_dms) - return; - - if (nseg >= MAXMSEG) { - printf("(Memory map full, disabling tracing)\n"); - trace_dms = 0; - nseg = -1; - return; - } - memcpy(mseg+i+1, mseg+i, (nseg-i)*sizeof(mseg[0])); - nseg++; -} - -static void delseg (int i) -{ - if (! trace_dms) - return; - - if (nseg > 0) { - nseg--; - memcpy(mseg+i, mseg+i+1, (nseg-i)*sizeof(mseg[0])); - } -} - -static void savesector (int addr, int offset, int len, int phid, char *name) -{ - int i; - - if (! trace_dms) - return; - - addr++; // first word is sector address, so account for that - len--; - - for (i = 0; i < nseg; i++) { - if (addr >= (mseg[i].addr+mseg[i].len)) // entirely after this entry - continue; - - if (mseg[i].addr < addr) { // old one starts before this. split it - addseg(i); - mseg[i].len = addr-mseg[i].addr; - i++; - mseg[i].addr = addr; - mseg[i].len -= mseg[i-1].len; - } - - break; - } - - addseg(i); // add new segment. Old one ends up after this - - if (i >= MAXMSEG) - return; - - mseg[i].addr = addr; - mseg[i].offset = offset; - mseg[i].phid = phid; - mseg[i].len = len; - mseg[i].name = name; - - i++; // delete any segments completely covered - - while (i < nseg && (mseg[i].addr+mseg[i].len) <= (addr+len)) - delseg(i); - - if (i < nseg && mseg[i].addr < (addr+len)) { // old one extends past this. Retain the end - mseg[i].len = (mseg[i].addr+mseg[i].len) - (addr+len); - mseg[i].addr = addr+len; - } -} - -static void tracesector (int iswrite, int nwords, int addr, int sector) -{ - int i, phid = 0, sletind = -1, offset = 0; - char *name = NULL; - - if (nwords < 3 || ! trace_dms) - return; - - switch (sector) { // explicitly known sector name - case 0: name = "ID/COLD START"; break; - case 1: name = "DCOM"; break; - case 2: name = "RESIDENT IMAGE"; break; - case 3: - case 4: - case 5: name = "SLET"; // save just-read or written SLET info - memmove(&slet[(320/4)*(sector-3)], &M[addr+1], nwords*2); - break; - case 6: name = "RELOAD TABLE"; break; - case 7: name = "PAGE HEADER"; break; - } - - printf("* %04x: %3d /%04x %c %3d.%d ", - prev_IAR, nwords, addr, iswrite ? '>' : '<', sector/8, sector%8); - - if (name == NULL) { // look up sector in SLET - for (i = 0; i < MAXSLET; i++) { - if (slet[i].phid == 0) // not found - goto done; - else if (slet[i].sector > sector) { - if (--i >= 0) { - if (sector >= slet[i].sector && sector <= (slet[i].sector + slet[i].nwords/320)) { - phid = slet[i].phid; - offset = (sector-slet[i].sector)*320; - break; - } - } - goto done; - } - if (slet[i].sector == sector) { - phid = slet[i].phid; // we found the starting sector - break; - } - } - - if (i >= MAXSLET) // was not found - goto done; - - name = "?"; - for (i = sizeof(phase)/sizeof(phase[0]); --i >= 0; ) { - if (phase[i].phid == phid) { // look up name - name = phase[i].name; - break; - } - } - printf("%02x %s", phid, name); - } - else - printf("%s", name); - -done: - putchar('\n'); - - if (phid >= phdebug_lo && phid <= phdebug_hi && offset == 0) - break_simulation(STOP_PHASE_BREAK); // break on read of first sector of indicated phases - - if (name != NULL && *name != '?' && ! iswrite) - savesector(addr, offset, nwords, phid, name); -} - -static t_stat fdump_cmd (int flags, char *cptr) -{ - int addr = 0x7a24; // address of next statement; - int sofst = 0x7a26, symaddr; - int cword, nwords, stype, has_stnum, strel = 1, laststno = 0; - - addr = M[addr & mem_mask] & mem_mask; // get address of first statement - sofst = M[sofst & mem_mask] & mem_mask; // get address of symbol table - - for (;;) { - cword = M[addr]; - nwords = (cword >> 2) & 0x01FF; - stype = (cword >> 1) & 0x7C00; - has_stnum = (cword & 1); - - if (has_stnum) { - laststno++; - strel = 0; - } - - printf("/%04x [%4d +%3d] %3d - %04x", addr, laststno, strel, nwords, stype); - - if (has_stnum) { - addr++; - nwords--; - symaddr = sofst - (M[addr] & 0x7FF)*3 + 3; - printf(" [%04x %04x %04x]", M[symaddr], M[symaddr+1], M[symaddr+2]); - } - - if (stype == 0x5000) { // error record - printf(" (err %d)", M[addr+1]); - } - - if (stype == 0x0800) - break; - - addr += nwords; - putchar('\n'); - - if (nwords == 0) { - printf("0 words?\n"); - break; - } - strel++; - } - - printf("\nEnd found at /%04x, EOFS = /%04x\n", addr, M[0x7a25 & mem_mask]); - return SCPE_OK; -} - -#endif // TRACE_DMS_IO diff --git a/Ibm1130/ibm1130_fmt.c b/Ibm1130/ibm1130_fmt.c deleted file mode 100644 index faccb046..00000000 --- a/Ibm1130/ibm1130_fmt.c +++ /dev/null @@ -1,303 +0,0 @@ -// ibm1130_fmt.c : interpret tabs in 1130 Assembler or Fortran source -// Bob Flanders -// ------------------------------------------------------------------------------------------- -// -// These routines are used by ibm1130_cr.c when the user has indicated -// that the input text is formatted with tabs. Input lines are edited -// into the appropriate column format. Three edit modes are recognized: -// -// Assembler mode: -// Input lines of the form -// -// [label][opcode][tag][L][argument] -// -// are rearranged so that the input fields are placed in the appropriate columns -// -// The label must start on the first character of the line. If there is no label, -// the first character(s) before the opcode must be whitespace. Following the opcode, there -// MUST be a tab character, followed by the format and tag. Following the format and tag -// may be exactly one whitespace character, and then starts the argument. -// -// Input lines with * in column 1 and blank lines are turned into Assembler comments, -// with the * in the Opcode field. -// -// Assembler directive lines at the beginning of the deck must be preceded by -// ! to indicate that they are not comments. For example, -// -// !*LIST -// * This is a comment -// -// Fortran mode: -// Input lines of the form -// -// [label]statement -// -// or -// -// [label]Xcontinuation -// -// where X is a non alphabetic contination character are rearranged in the -// appropriate manner: -// -// 1 2 -// 12345678901234567890... -// ------------------------ -// label statement -// labelXcontinuation -// -// However, you must take care that you don't end up with statement text after column 72. -// -// Input lines with * or C in column 1 are left alone (comments and directives) -// -// (The ! escape is not used before Fortran directives as before Assembler directives) -// -// Tab mode: -// Tabs are replaced with spaces. Tab settings are assumed to be eight characters wide, -// as is standard for vi, notepad, etc. -// ------------------------------------------------------------------------------------------- - -#include -#include -#include -#include -#include -#include "ibm1130_fmt.h" - -#define MAXLINE 81 // maximum output line size -#define WORKSZ 256 // size for tab work area -#define TAGOFFSET 12 // offset for tag field -#define FMTOFFSET 11 // offset for format field - -#define MIN(a,b) ((a < b) ? a : b) -#define AMSG " with Assembler Reformat" -#define FMSG " with FORTRAN Reformat" -#define AFORMAT "%20.20s%-60.60s"," " -#define ACOMMENTFMT "%20.20s%-60.60s"," " -#define ABLANKLINE "%20.20s*"," " -#define FFORMAT "%-5.5s %-74.74s" -#define FCONTFMT "%-5.5s%-75.75s" - -char gszLabel[6]; // work area for label -char gszArg[MAXLINE]; // .. argument -char gszOutput[MAXLINE]; // .. output -short gaiAsmTabs[] = {7,12,15,20,25,30,35,40,45,52,0};// tab stops for assembler - -short gaiPlainTabs[] = {9, 17, 25, 33, 41, 49, 57, 65, 73, 0};// tab stops for just plain tabs - -// /////////////// -// helper routines - -/////////////////////////////////////////////////// -// ExpandTabs: Expand tabs to spaces - -char* ExpandTabs(char* p_szInbuf, // expand tabs .. input buffer - char* p_szOutbuf, // .. output buffer - short* p_aiTabs) // .. array of tab stops (1 based) -- 0 end of array -{ -short iI, // input position - iO, // output position - iT; // next tab stop - -char cX; // character to test - - iI = 0; // init input position - iO = 0; // init output position - iT = 0; // init tab stop - - while (cX = *(p_szInbuf + iI)) // while there are characters - { - if (cX == '\t') // q. tab character? - { // a. yes .. - while ((p_aiTabs[iT] <= iO + 1) // search for next valid stop .. - && (p_aiTabs[iT] != 0)) // .. or end of table - iT++; // .. go to next tab - - if (p_aiTabs[iT] != 0) // q. end of tab array? - { // a. no .. - while (iO < (p_aiTabs[iT] - 1)) // fill to tab with blanks - *(p_szOutbuf + iO++) = ' '; // .. put in a blank - - } - else // Otherwise ... - *(p_szOutbuf + iO++) = ' '; // .. Translate to blank - } - else // Otherwise .. not tab - *(p_szOutbuf + iO++) = cX; // .. save the input char - - iI++; // next input character - } - - *(p_szOutbuf + iO) = 0; // end the string.. - return p_szOutbuf; // .. return output area addr -} - -///////////////////////////////////// -// extract next token, modify pointer - -char* GetToken(char* p_szOut, // output location - int p_iLen, // max output length - char**p_pszToken) // pointer to input token -{ -int iI; // work integer -char* pszX; // work pointer - - pszX = *p_pszToken; // get pointer to token - - for (iI = 0; *(pszX + iI) && (!isspace(*(pszX + iI)));) // while not whitespace & not end - iI++; // .. count token length - - memset(p_szOut, 0, p_iLen); // zero out output area - - if (iI > 0) // q. any chars? - strncpy(p_szOut, *p_pszToken, MIN(iI, p_iLen-1)); // a. yes.. copy max of p_iLen-1 - - *p_pszToken += iI; // point beyond token - return p_szOut; // .. return token pointer -} - -///////////////////////////////////////////////////////// -// EditToAsm - convert tab-formatted text line to 1130 Assembler format - -char *EditToAsm (char* p_pszEdit) // convert line to 1130 assembler -{ -char pszLine[MAXLINE]; // source line -char pszWork[WORKSZ]; // work buffer -char acTFWrk[2]; // tag/format work area -size_t iI; // work integer - - if (p_pszEdit == NULL) // q. null request? - return AMSG; // a. yes .. return display message - - if (*p_pszEdit == '!') // leave lines starting with ! alone - return EditToWhitespace(p_pszEdit+1); - - if (*p_pszEdit == '*') // q. comment line? - { // a. yes.. - strncpy(pszWork, EditToWhitespace(p_pszEdit), MAXLINE); // .. convert any tabs - sprintf(gszOutput, ACOMMENTFMT, pszWork); // .. put the comment out there in the opcode column - return gszOutput; // .. and return it - } - - strncpy(pszLine, p_pszEdit, MAXLINE-1); // copy the line local - - ExpandTabs(pszLine, pszWork, gaiAsmTabs); // expand the tabs - strncpy(pszLine, pszWork, MAXLINE-1); // copy the line back - - for (iI = strlen(pszLine); iI--;) // trim trailing whitespace - { - if (*(pszLine + iI) <= ' ') // q. space or less? - *(pszLine + iI) = 0; // a. yes .. remove it - else // otherwise - break; // .. done. Leave loop. - } - - if (strlen(pszLine) == 0) // q. blank line? - { // a. yes .. Assembler abhors these so - sprintf(gszOutput, ABLANKLINE); // format as comment statement - return gszOutput; // .. and return it - } - - - // TODO: Add code to process a strip switch - // comment? - - if (strlen(pszLine) > (TAGOFFSET + 1)) // q. line long enough? - { // a. yes.. reorder tag/format - memcpy(acTFWrk, pszLine + FMTOFFSET, 2); // get tag/format - memset((pszLine + FMTOFFSET), ' ', 2); // .. blank 'em out - - for (iI = 0; iI < 2; iI ++) - if (isalpha(acTFWrk[iI])) // q. alpha char? - *(pszLine + FMTOFFSET) = acTFWrk[iI]; // a. yes .. make it format - else if (isdigit(acTFWrk[iI])) // q. digit? - *(pszLine + TAGOFFSET) = acTFWrk[iI]; // a. yes .. make it the tag - } - - sprintf(gszOutput, AFORMAT, pszLine); // format the line - - return gszOutput; // return formatted line -} - -///////////////////////////////////////////////////////// -// EditToFortran - convert tab-formatted input text line to FORTRAN format -// (a la DEC Fortran) - -char *EditToFortran(char* p_pszEdit) // convert line to 1130 assembler -{ -char pszLine[MAXLINE]; // source line -char* pszWork; // work pointer -size_t iI; // work integer -char bContinue; // true if continue - - if (p_pszEdit == NULL) // q. null request? - return FMSG; // a. yes .. return display message - - if (strchr(p_pszEdit, '\t') == NULL) // q. no tab in the line? - return p_pszEdit; // a. nope, return line as is, assume it's formatted correctly - - if (*p_pszEdit == 'C' || *p_pszEdit == '*' || *p_pszEdit == '\0') // q. comment or directive or blank line? - { // a. yes.. don't restructure - return EditToWhitespace(p_pszEdit); - } - - strncpy(pszLine, p_pszEdit, MAXLINE-1); // copy the line local - - for (iI = strlen(pszLine); iI--;) // trim trailing whitespace - { - if (*(pszLine + iI) <= ' ') // q. space or less? - *(pszLine + iI) = 0; // a. yes .. remove it - else // otherwise - break; // .. done. Leave loop. - } - - // TODO: Add code to process a strip switch - // comment? - - pszWork = (char*) pszLine; // set pointer to line - GetToken(gszLabel, 6, &pszWork); // get the line, if any. - - pszWork++; // skip tab/whitespace - - // continuation... - bContinue = ((isdigit(*pszWork) && (*pszWork != '0')) // if first char non-zero digit - || (!isspace(*pszWork) && !isalpha(*pszWork))); // .. or non-alpha non-blank - - memset(gszArg, 0, MAXLINE); // .. and arguments - - strncpy(gszArg, pszWork, 75); // copy rest to argument - - sprintf(gszOutput, (bContinue) ? FCONTFMT : FFORMAT, // format the line - gszLabel, // .. statement # - gszArg); // .. code - - return gszOutput; // return formatted line -} - -///////////////////////////////////////////////////////// -// EditToWhitespace - expand tabs at 8 space intervals. - -char* EditToWhitespace(char *p_pszEdit) -{ -int iI; /* work integer */ -char pszLine[MAXLINE]; // source line -char pszWork[WORKSZ]; // work buffer - - if (p_pszEdit == NULL) // q. null request? - return AMSG; // a. yes .. return display message - - strncpy(pszLine, p_pszEdit, MAXLINE-1); // copy the line local - - ExpandTabs(pszLine, pszWork, gaiPlainTabs); // expand the tabs - strncpy(gszOutput, pszWork, MAXLINE-1); // copy the line back - - for (iI = strlen(gszOutput); iI--;) // look at each character - { - if (*(gszOutput + iI) <= ' ') // q. space or less? - *(gszOutput + iI) = 0; // a. yes .. remove it - else // otherwise - break; // .. done. Leave loop. - } - - - return gszOutput; /* ... return buffer */ -} diff --git a/Ibm1130/ibm1130_fmt.h b/Ibm1130/ibm1130_fmt.h deleted file mode 100644 index 170d1c88..00000000 --- a/Ibm1130/ibm1130_fmt.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * (C) Copyright 2003, Bob Flander. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to bob@jftr.com - */ - -/* ibm1130_asm.h: definition of routines in ibm1130_asm.c - */ - -char* EditToAsm(char*); // convert edit format to 1130 assembler format -char* EditToFortran(char*); // convert edit format to Fortran format -char* EditToWhitespace(char*); // clean white space, tabstops every 8 positions diff --git a/Ibm1130/ibm1130_gdu.c b/Ibm1130/ibm1130_gdu.c deleted file mode 100644 index a1501609..00000000 --- a/Ibm1130/ibm1130_gdu.c +++ /dev/null @@ -1,1118 +0,0 @@ -#include "ibm1130_defs.h" - -/* ibm1130_gdu.c: IBM 1130 2250 Graphical Display Unit - - (Under construction) -// stuff to fix: -// "store revert" might be backwards? -// alpha keyboard is not implemented -// pushbuttons are not implemented -// there is something about interrupts being deferred during a subroutine transition? - - Based on the SIMH package written by Robert M Supnik - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - */ - -#define BLIT_MODE // normally defined, undefine when debugging generate_image() -//#define DEBUG_LIGHTPEN // normally undefined, define to visualize light-pen sensing - -#define DEFAULT_GDU_RATE 20 // default frame rate -#define DEFAULT_PEN_THRESHOLD 3 // default looseness of light-pen hit -#define INDWIDTH 32 // width of an indicator (there are two columns of these) -#define INITSIZE 512 // initial window size - -#define GDU_DSW_ORDER_CONTROLLED_INTERRUPT 0x8000 -#define GDU_DSW_KEYBOARD_INTERUPT 0x4000 -#define GDU_DSW_DETECT_INTERRUPT 0x2000 -#define GDU_DSW_CYCLE_STEAL_CHECK 0x1000 -#define GDU_DSW_DETECT_STATUS 0x0800 -#define GDU_DSW_LIGHT_PEN_SWITCH 0x0100 -#define GDU_DSW_BUSY 0x0080 -#define GDU_DSW_CHARACTER_MODE 0x0040 -#define GDU_DSW_POINT_MODE 0x0020 -#define GDU_DSW_ADDR_DISP 0x0003 - -#define GDU_FKEY_DATA_AVAILABLE 0x8000 -#define GDU_FKEY_KEY_CODE 0x1F00 -#define GDU_FKEY_OVERLAY_CODE 0x00FF - -#define GDU_AKEY_DATA_AVAILABLE 0x8000 -#define GDU_AKEY_END 0x1000 -#define GDU_AKEY_CANCEL 0x0800 -#define GDU_AKEY_ADVANCE 0x0400 -#define GDU_AKEY_BACKSPACE 0x0200 -#define GDU_AKEY_JUMP 0x0100 -#define GDU_AKEY_KEY_CODE 0x00FF - -/* -------------------------------------------------------------------------------------- */ - -#define UNIT_V_DISPLAYED (UNIT_V_UF + 0) -#define UNIT_V_DETECTS_ENABLED (UNIT_V_UF + 1) -#define UNIT_V_INTERRUPTS_DEFERRED (UNIT_V_UF + 2) -#define UNIT_V_LARGE_CHARS (UNIT_V_UF + 3) - -#define UNIT_DISPLAYED (1u << UNIT_V_DISPLAYED) /* display windows is up */ -#define UNIT_DETECTS_ENABLED (1u << UNIT_V_DETECTS_ENABLED) /* light pen detects are enabled */ -#define UNIT_INTERRUPTS_DEFERRED (1u << UNIT_V_INTERRUPTS_DEFERRED) /* light pen interrupts are deferred */ -#define UNIT_LARGE_CHARS (1u << UNIT_V_LARGE_CHARS) /* large character mode */ - -static t_stat gdu_reset (DEVICE *dptr); - -static int16 gdu_dsw = 1; /* device status word */ -static int16 gdu_ar = 0; /* address register */ -static int16 gdu_x = 0; /* X deflection */ -static int16 gdu_y = 0; /* Y deflection */ -static int16 gdu_fkey = 0; /* function keyboard register */ -static int16 gdu_akey = 0; /* alphanumeric keyboard register */ -static int16 gdu_revert = 0; /* revert address register */ -static int32 gdu_indicators = 0; /* programmed indicator lamps */ -static int32 gdu_threshold = DEFAULT_PEN_THRESHOLD; /* mouse must be within 3/1024 of line to be a hit */ -static int32 gdu_rate = DEFAULT_GDU_RATE; /* refresh rate. 0 = default */ - -UNIT gdu_unit = { UDATA (NULL, 0, 0) }; - -REG gdu_reg[] = { - { HRDATA (GDUDSW, gdu_dsw, 16) }, /* device status word */ - { HRDATA (GDUAR, gdu_ar, 16) }, /* address register */ - { HRDATA (GDUXREG, gdu_x, 16) }, /* X deflection register */ - { HRDATA (GDUYREG, gdu_y, 16) }, /* Y deflection register */ - { HRDATA (GDUFKEY, gdu_fkey, 16) }, /* function keyboard register */ - { HRDATA (GDUAKEY, gdu_akey, 16) }, /* alphanumeric keyboard register */ - { HRDATA (GDUREVERT,gdu_revert, 16) }, /* revert address register */ - { HRDATA (GDUAKEY, gdu_indicators, 32) }, /* programmed indicators */ - { DRDATA (GDUTHRESH,gdu_threshold, 32) }, /* mouse closeness threshhold */ - { DRDATA (GDURATE, gdu_rate, 32) }, /* refresh rate in frames/sec */ - { NULL } }; - -DEVICE gdu_dev = { - "GDU", &gdu_unit, gdu_reg, NULL, - 1, 16, 16, 1, 16, 16, - NULL, NULL, gdu_reset, - NULL, NULL, NULL}; - -/* -------------------------------------------------------------------------------------- */ - -#ifndef GUI_SUPPORT - -static t_stat gdu_reset (DEVICE *dptr) -{ - return SCPE_OK; -} - -void xio_2250_display (int32 addr, int32 func, int32 modify) -{ - // ignore commands to nonexistent device -} - -t_bool gdu_active (void) -{ - return 0; -} - -/* -------------------------------------------------------------------------------------- */ -#else // GUI_SUPPORT defined - -/******* PLATFORM INDEPENDENT CODE ********************************************************/ - -static int32 gdu_instaddr; // address of first word of instruction -static int xmouse, ymouse, lpen_dist, lpen_dist2; // current mouse pointer, scaled closeness threshhold, same squared -static double sfactor; // current scaling factor -static t_bool last_abs = TRUE; // last positioning instruction was absolute -static t_bool mouse_present = FALSE; // mouse is/is not in the window - -static void clear_interrupts (void); -static void set_indicators (int32 new_inds); -static void start_regeneration (void); -static void halt_regeneration (void); -static void draw_characters (void); -static void notify_window_closed (void); - -// routines that must be implemented per-platform - -static void DrawLine(int x0, int y0, int x1, int y1); -static void DrawPoint(int x, int y); -static void CheckGDUKeyboard(void); -static t_bool CreateGDUWindow(void); -static void StartGDUUpdates(void); -static void StopGDUUpdates(void); -static void GetMouseCoordinates(void); -static void UpdateGDUIndicators(void); -static void ShowPenHit (int x, int y); -static void EraseGDUScreen (void); - -/* -------------------------------------------------------------------------------------- */ - -void xio_2250_display (int32 addr, int32 func, int32 modify) -{ - switch (func) { - case XIO_SENSE_DEV: - ACC = (gdu_dsw & GDU_DSW_BUSY) ? GDU_DSW_BUSY : gdu_dsw; - if (modify & 1) - clear_interrupts(); - break; - - case XIO_READ: /* store status data into word pointed to by IOCC packet */ - if (gdu_dsw & GDU_DSW_BUSY) /* not permitted while device is busy */ - break; - - WriteW(addr, gdu_ar); /* save status information */ - WriteW(addr+1, gdu_dsw); - WriteW(addr+2, gdu_x & 0x7FF); - WriteW(addr+3, gdu_y & 0x7FF); - WriteW(addr+4, gdu_fkey); - WriteW(addr+5, gdu_akey); - gdu_ar = addr+6; /* this alters the channel address register? */ - - clear_interrupts(); /* read status clears the interrupts */ - break; - - case XIO_WRITE: - if (gdu_dsw & GDU_DSW_BUSY) /* treated as no-op if display is busy */ - break; - - if (modify & 0x80) { /* bit 8 on means set indicators, 0 means start regeneration */ - set_indicators((ReadW(addr) << 16) | ReadW(addr+1)); - } - else { - gdu_ar = addr; - gdu_fkey = 0; - gdu_akey = 0; - clear_interrupts(); - start_regeneration(); - } - break; - - case XIO_CONTROL: - if (modify & 0x80) { /* bit 8 on means reset, off is no-op */ - gdu_reset(&gdu_dev); - set_indicators((addr << 16) | addr); - } - break; - - default: /* all other commands are no-ops */ - break; - } -} - -static t_stat gdu_reset (DEVICE *dptr) -{ - halt_regeneration(); - clear_interrupts(); - set_indicators(0); - gdu_x = gdu_y = 512; - CLRBIT(gdu_unit.flags, UNIT_INTERRUPTS_DEFERRED | UNIT_DETECTS_ENABLED | UNIT_LARGE_CHARS); - gdu_dsw = 1; - return SCPE_OK; -} - -static void clear_interrupts (void) -{ - CLRBIT(gdu_dsw, GDU_DSW_ORDER_CONTROLLED_INTERRUPT | GDU_DSW_KEYBOARD_INTERUPT | GDU_DSW_DETECT_INTERRUPT); - CLRBIT(ILSW[3], ILSW_3_2250_DISPLAY); - calc_ints(); -} - -static void gdu_interrupt (int32 dswbit) -{ - SETBIT(gdu_dsw, dswbit); - SETBIT(ILSW[3], ILSW_3_2250_DISPLAY); - calc_ints(); - halt_regeneration(); -} - -static void set_indicators (int32 new_inds) -{ - gdu_indicators = new_inds; - if (gdu_unit.flags & UNIT_DISPLAYED) - UpdateGDUIndicators(); -} - -static void start_regeneration (void) -{ - SETBIT(gdu_dsw, GDU_DSW_BUSY); - - if (gdu_unit.flags & UNIT_DISPLAYED) { - StartGDUUpdates(); - } - else { - if (! CreateGDUWindow()) - return; - SETBIT(gdu_unit.flags, UNIT_DISPLAYED); - } -} - -static void halt_regeneration (void) -{ - if (gdu_dsw & GDU_DSW_BUSY) { - StopGDUUpdates(); - CLRBIT(gdu_dsw, GDU_DSW_BUSY); - } - EraseGDUScreen(); -} - -static void notify_window_closed (void) -{ - if (gdu_dsw & GDU_DSW_BUSY) { - StopGDUUpdates(); - CLRBIT(gdu_dsw, GDU_DSW_BUSY); - } - CLRBIT(gdu_unit.flags, UNIT_DISPLAYED); - gdu_reset(&gdu_dev); -} - -static int32 read_gduword (void) -{ - int32 w; - - w = M[gdu_ar++ & mem_mask]; - gdu_dsw = (gdu_dsw & ~GDU_DSW_ADDR_DISP) | ((gdu_ar - gdu_instaddr) & GDU_DSW_ADDR_DISP); - - return w; -} - -#define DIST2(x0,y0,x1,y1) (((x1)-(x0))*((x1)-(x0))+((y1)-(y0))*((y1)-(y0))) - -static void draw (int32 newx, int32 newy, t_bool beam) -{ - int xmin, xmax, ymin, ymax, xd, yd; - double s; - int hit = FALSE; - - if (beam) { - if (gdu_dsw & GDU_DSW_POINT_MODE) { - DrawPoint(newx, newy); - -#ifdef DEBUG_LIGHTPEN - if (DIST2(newx, newy, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; -#else - if (gdu_unit.flags & UNIT_DETECTS_ENABLED && mouse_present) - if (DIST2(newx, newy, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; -#endif - } - else { - DrawLine(gdu_x, gdu_y, newx, newy); - - // calculate proximity of light pen to the line -#ifndef DEBUG_LIGHTPEN - if (gdu_unit.flags & UNIT_DETECTS_ENABLED && mouse_present) { -#endif - if (gdu_x <= newx) - xmin = gdu_x, xmax = newx; - else - xmin = newx, xmax = gdu_x; - - if (gdu_y <= newy) - ymin = gdu_y, ymax = newy; - else - ymin = newy, ymax = gdu_y; - - if (newx == gdu_x) { - // line is vertical. Nearest point is an endpoint if the mouse is above or - // below the line segment, otherwise the segment point at the same y as the mouse - xd = gdu_x; - yd = (ymouse <= ymin) ? ymin : (ymouse >= ymax) ? ymax : ymouse; - - if (DIST2(xd, yd, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; - } - else if (newy == gdu_y) { - // line is horizontal. Nearest point is an endpoint if the mouse is to the left or - // the right of the line segment, otherwise the segment point at the same x as the mouse - xd = (xmouse <= xmin) ? xmin : (xmouse >= xmax) ? xmax : xmouse; - yd = gdu_y; - - if (DIST2(xd, yd, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; - } - else { - // line is diagonal. See if the mouse is inside the box lpen_dist wider than the line segment's bounding rectangle - if (xmouse >= (xmin-lpen_dist) && xmouse <= (xmax+lpen_dist) && ymouse >= (ymin-lpen_dist) || ymouse <= (ymax+lpen_dist)) { - // compute the point at the intersection of the line through the line segment and the normal - // to that line through the mouse. This is the point on the line through the line segment - // nearest the mouse - - s = (double)(newy - gdu_y) / (double)(newx - gdu_x); // slope of line segment - xd = (int) ((ymouse + xmouse/s - gdu_y + s*gdu_x) / (s + 1./s) + 0.5); - - // if intersection is beyond either end of the line segment, the nearest point to the - // mouse is nearest segment end, otherwise it's the computed intersection point - if (xd < xmin || xd > xmax) { -#ifdef DEBUG_LIGHTPEN - // if it's a hit, set xd and yd so we can display the hit - if (DIST2(gdu_x, gdu_y, xmouse, ymouse) <= lpen_dist2) { - hit = TRUE; - xd = gdu_x; - yd = gdu_y; - } - else if (DIST2(newx, newy, xmouse, ymouse) <= lpen_dist2) { - hit = TRUE; - xd = newx; - yd = newy; - } -#else - if (DIST2(gdu_x, gdu_y, xmouse, ymouse) <= lpen_dist2 || DIST2(newx, newy, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; -#endif - } - else { - yd = (int) (gdu_y + s*(xd - gdu_x) + 0.5); - if (DIST2(xd, yd, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; - } - } - } -#ifndef DEBUG_LIGHTPEN - } -#endif - } - } - - if (hit) { -#ifdef DEBUG_LIGHTPEN - ShowPenHit(xd, yd); - if (gdu_unit.flags & UNIT_DETECTS_ENABLED && mouse_present) - SETBIT(gdu_dsw, GDU_DSW_DETECT_STATUS); -#else - SETBIT(gdu_dsw, GDU_DSW_DETECT_STATUS); -#endif - } - - gdu_x = newx; - gdu_y = newy; -} - -static void generate_image (void) -{ - int32 instr, new_addr, newx, newy; - t_bool run = TRUE, accept; - - if (! (gdu_dsw & GDU_DSW_BUSY)) - return; - - GetMouseCoordinates(); - - lpen_dist = (int) (gdu_threshold/sfactor + 0.5); // mouse-to-line threshhold at current scaling factor - lpen_dist2 = lpen_dist * lpen_dist; - - while (run) { - if ((gdu_dsw & GDU_DSW_DETECT_STATUS) && ! (gdu_unit.flags & UNIT_INTERRUPTS_DEFERRED)) { - CLRBIT(gdu_dsw, GDU_DSW_DETECT_STATUS); // clear when interrupt is activated - gdu_interrupt(GDU_DSW_DETECT_INTERRUPT); - run = FALSE; - break; - } - - gdu_instaddr = gdu_ar; // remember address of GDU instruction - instr = read_gduword(); // fetch instruction (and we really are cycle stealing here!) - - switch ((instr >> 12) & 0xF) { // decode instruction - case 0: // short branch - case 1: - gdu_revert = gdu_ar; // save revert address & get new address - gdu_ar = read_gduword() & 0x1FFF; - if (gdu_dsw & GDU_DSW_CHARACTER_MODE) { - draw_characters(); // in character mode this means we are at character data - gdu_ar = gdu_revert; - } - break; - - case 2: // long branch/interrupt - new_addr = read_gduword(); // get next word - accept = ((instr & 1) ? (gdu_dsw & GDU_DSW_LIGHT_PEN_SWITCH) : TRUE) && ((instr & 2) ? (gdu_dsw & GDU_DSW_DETECT_STATUS) : TRUE); - - if (instr & 2) // clear after testing - CLRBIT(gdu_dsw, GDU_DSW_DETECT_STATUS); - - if (instr & 0x0400) // NOP - accept = FALSE; - - if (accept) { - if (instr & 0x0800) { // branch - gdu_revert = gdu_ar; - - if (instr & 0x0080) // indirect - new_addr = M[new_addr & mem_mask]; - - gdu_ar = new_addr; - - if (gdu_dsw & GDU_DSW_CHARACTER_MODE) { - draw_characters(); - gdu_ar = gdu_revert; - } - } - else { // interrupt - gdu_interrupt(GDU_DSW_ORDER_CONTROLLED_INTERRUPT); - run = FALSE; - } - } - break; - - case 3: // control instructions - CLRBIT(gdu_dsw, GDU_DSW_CHARACTER_MODE); - - switch ((instr >> 8) & 0xF) { - case 1: // set pen mode - if ((instr & 0xC) == 8) - SETBIT(gdu_unit.flags, UNIT_DETECTS_ENABLED); - else if ((instr & 0xC) == 4) - CLRBIT(gdu_unit.flags, UNIT_DETECTS_ENABLED); - - if ((instr & 0x3) == 2) - SETBIT(gdu_unit.flags, UNIT_INTERRUPTS_DEFERRED); - else if ((instr & 0x3) == 1) - CLRBIT(gdu_unit.flags, UNIT_INTERRUPTS_DEFERRED); - break; - - case 2: // set graphic mode - if (instr & 1) - SETBIT(gdu_dsw, GDU_DSW_POINT_MODE); - else - CLRBIT(gdu_dsw, GDU_DSW_POINT_MODE); - break; - - case 3: // set character mode - SETBIT(gdu_dsw, GDU_DSW_CHARACTER_MODE); - if (instr & 1) - SETBIT(gdu_unit.flags, UNIT_LARGE_CHARS); - else - CLRBIT(gdu_unit.flags, UNIT_LARGE_CHARS); - break; - - case 4: // start timer - run = FALSE; // (which, for us, means stop processing until next timer message) - CheckGDUKeyboard(); - break; - - case 5: // store revert - M[gdu_ar & mem_mask] = gdu_revert; - read_gduword(); // skip to next address - break; - - case 6: // revert - gdu_ar = gdu_revert; - break; - - default: // all others treated as no-ops - break; - } - break; - - case 4: // long absolute - case 5: - CLRBIT(gdu_dsw, GDU_DSW_CHARACTER_MODE); - newx = instr & 0x3FF; - newy = read_gduword() & 0x3FF; - draw(newx, newy, instr & 0x1000); - last_abs = TRUE; - break; - - case 6: // short absolute - case 7: - CLRBIT(gdu_dsw, GDU_DSW_CHARACTER_MODE); - newx = gdu_x; - newy = gdu_y; - if (instr & 0x0800) - newy = instr & 0x3FF; - else - newx = instr & 0x3FF; - draw(newx, newy, instr & 0x1000); - last_abs = TRUE; - break; - - default: // high bit set - it's a relative instruction - CLRBIT(gdu_dsw, GDU_DSW_CHARACTER_MODE); - newx = (instr >> 8) & 0x3F; - newy = instr & 0x3F; - - if (instr & 0x4000) // sign extend x - values are in 2's complement - newx |= -1 & ~0x3F; // although documentation doesn't make that clear - - if (instr & 0x0040) // sign extend y - newy |= -1 & ~0x3F; - - newx = gdu_x + newx; - newy = gdu_y + newy; - draw(newx, newy, instr & 0x0080); - last_abs = FALSE; - break; - } - } -} - -static struct charinfo { // character mode scaling info: - int dx, dy; // character and line spacing - double sx, sy; // scaling factors: character units to screen units - int xoff, yoff; // x and y offset to lower left corner of character - int suby; // subscript/superscript offset -} cx[2] = { - {14, 20, 1.7, 2.0, -6, -7, 6}, // regular - {21, 30, 2.5, 3.0, -9, -11, 9} // large -}; - -static void draw_characters (void) -{ - int32 w, x0, y0, x1, y1, yoff = 0, ninstr = 0; - t_bool dospace, didstroke = FALSE; - struct charinfo *ci; - - ci = &cx[(gdu_unit.flags & UNIT_LARGE_CHARS) ? 1 : 0]; - x0 = gdu_x + ci->xoff; // starting position - y0 = gdu_y + ci->yoff; - - do { - if (++ninstr > 29) { // too many control words - gdu_interrupt(GDU_DSW_CYCLE_STEAL_CHECK); - return; - } - - dospace = TRUE; - w = M[gdu_ar++ & mem_mask]; // get next stroke or control word - - x1 = (w >> 12) & 7; - y1 = (w >> 8) & 7; - - if (x1 == 7) { // this is a character control word - dospace = FALSE; // inhibit character spacing - - switch (y1) { - case 1: // subscript - if (yoff == 0) // (ignored if superscript is in effect) - yoff = -ci->suby; - break; - -// case 2: // no-op or null (nothing to do) -// default: // all unknowns are no-ops -// break; - - case 4: // superscript - yoff = ci->suby; - break; - - case 7: // new line - gdu_x = 0; - gdu_y -= ci->dy; - if (gdu_y < 0 && last_abs) - gdu_y = 1024 - ci->dy; // this is a guess - break; - } - } - else { // this is stroke data -- extract two strokes - x1 = gdu_x + (int) (x1*ci->sx + 0.5); - y1 = gdu_y + (int) ((y1+yoff)*ci->sy + 0.5); - - if (w & 0x0800) { - didstroke = TRUE; - DrawLine(x0, y0, x1, y1); - } - - x0 = (w >> 4) & 7; - y0 = w & 7; - - x0 = gdu_x + (int) (x0*ci->sx + 0.5); - y0 = gdu_y + (int) ((y0+yoff)*ci->sy + 0.5); - - if (w & 0x0008) { - didstroke = TRUE; - DrawLine(x1, y1, x0, y0); - } - } - - if (dospace) { - gdu_x += ci->dx; - if (gdu_x > 1023 && last_abs) { // line wrap - gdu_x = 0; - gdu_y -= ci->dy; - } - } - } while ((w & 0x0080) == 0); // repeat until we hit revert bit - - if (didstroke && mouse_present && (gdu_unit.flags & UNIT_DETECTS_ENABLED)) { - if (xmouse >= (gdu_x - ci->xoff/2) && xmouse <= (gdu_x + ci->xoff/2) && - ymouse >= (gdu_y - ci->yoff/2) && ymouse <= (gdu_y + ci->yoff/2)) - SETBIT(gdu_dsw, GDU_DSW_DETECT_STATUS); - } -} - -/******* PLATFORM SPECIFIC CODE ***********************************************************/ - -#ifdef WIN32 - -#include -#include - -#define APPCLASS "IBM2250GDU" // window class name - -#define RGB_GREEN RGB(0,255,0) // handy colors -#define RGB_RED RGB(255,0,0) - -static HINSTANCE hInstance; -static HWND hwGDU = NULL; -static HDC hdcGDU = NULL; -static HBITMAP hBmp = NULL; -static int curwid = 0; -static int curht = 0; -static BOOL wcInited = FALSE; -static int GDUPumpID = 0; -static HANDLE hGDUPump = INVALID_HANDLE_VALUE; -static HPEN hGreenPen = NULL; -static HBRUSH hRedBrush = NULL; -#ifdef DEBUG_LIGHTPEN -static HPEN hRedPen = NULL; -#endif -static HBRUSH hGrayBrush, hDarkBrush; -static HPEN hBlackPen; - -static LRESULT APIENTRY GDUWndProc (HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam); -static DWORD WINAPI GDUPump (LPVOID arg); - -static void destroy_GDU_window (void) -{ - if (hwGDU != NULL) - SendMessage(hwGDU, WM_CLOSE, 0, 0); // cross thread call is OK - - if (hGDUPump != INVALID_HANDLE_VALUE) { // this is not the most graceful way to do it - TerminateThread(hGDUPump, 0); - hGDUPump = INVALID_HANDLE_VALUE; - GDUPumpID = 0; - hwGDU = NULL; - } - - if (hdcGDU != NULL) { - DeleteDC(hdcGDU); - hdcGDU = NULL; - } - - if (hBmp != NULL) { - DeleteObject(hBmp); - hBmp = NULL; - } - - if (hGreenPen != NULL) { - DeleteObject(hGreenPen); - hGreenPen = NULL; - } - - if (hRedBrush != NULL) { - DeleteObject(hRedBrush); - hRedBrush = NULL; - } - -#ifdef DEBUG_LIGHTPEN - if (hRedPen != NULL) { - DeleteObject(hRedPen); - hRedPen = NULL; - } -#endif -} - -static t_bool CreateGDUWindow (void) -{ - static BOOL did_atexit = FALSE; - - if (hwGDU != NULL) { // window already exists - StartGDUUpdates(); - return TRUE; - } - - hInstance = GetModuleHandle(NULL); - - if (hGDUPump == INVALID_HANDLE_VALUE) - hGDUPump = CreateThread(NULL, 0, GDUPump, 0, 0, &GDUPumpID); - - if (! did_atexit) { - atexit(destroy_GDU_window); - did_atexit = TRUE; - } - - return TRUE; -} - -// windows message handlers ---------------------------------------------------- - -// close the window - -static void gdu_WM_CLOSE (HWND hWnd) -{ - DestroyWindow(hWnd); -} - -// the window is being destroyed - -static void gdu_WM_DESTROY (HWND hWnd) -{ - notify_window_closed(); - hwGDU = NULL; -} - -// adjust the min and max resizing boundaries - -static void gdu_WM_GETMINMAXINFO (HWND hWnd, LPMINMAXINFO mm) -{ - mm->ptMinTrackSize.x = 100 + 2*INDWIDTH; - mm->ptMinTrackSize.y = 100; -} - -static void PaintImage (HDC hDC, BOOL draw_indicators) -{ - HPEN hOldPen; - RECT r; - int wid, ht, x, y, dy, i, j, ycirc; - unsigned long bit; - - GetClientRect(hwGDU, &r); - wid = r.right+1 - 2*INDWIDTH; - ht = r.bottom+1; - sfactor = (double) MIN(wid,ht) / 1024.; - - if (gdu_dsw & GDU_DSW_BUSY) { -#ifdef BLIT_MODE - // if compiled for BLIT_MODE, draw the image into a memory display context, then - // blit the new image over window. This eliminates the flicker that a normal erase-and- - // repaint would cause. - - if (wid != curwid || ht != curht) { // dimensions have changed, discard old memory display context - if (hdcGDU != NULL) { - DeleteDC(hdcGDU); - hdcGDU = NULL; - } - curwid = wid; - curht = ht; - } - - if (hdcGDU == NULL) { // allocate memory display context & select a bitmap into it - hdcGDU = CreateCompatibleDC(hDC); - if (hBmp != NULL) - DeleteObject(hBmp); - hBmp = CreateCompatibleBitmap(hDC, wid, ht); - SelectObject(hdcGDU, hBmp); - } - - PatBlt(hdcGDU, 0, 0, wid, ht, BLACKNESS); // start with a black screen - - hOldPen = SelectObject(hdcGDU, hGreenPen); - - SetMapMode(hdcGDU, MM_ANISOTROPIC); - SetWindowExtEx(hdcGDU, 1024, -1024, NULL); - SetViewportExtEx(hdcGDU, wid, ht, NULL); - SetWindowOrgEx(hdcGDU, 0, 1023, NULL); - - generate_image(); // run the display program to paint the image into the memory context - - SetWindowExtEx(hdcGDU, wid, ht, NULL); // undo the scaling so the blit isn't distorted - SetViewportExtEx(hdcGDU, wid, ht, NULL); - SetWindowOrgEx(hdcGDU, 0, 0, NULL); - BitBlt(hDC, 0, 0, wid, ht, hdcGDU, 0, 0, SRCCOPY); // blit the new image over the old - - SelectObject(hdcGDU, hOldPen); -#else - // for testing purposes -- draw the image directly onto the screen. - // Compile this way when you want to single-step through the image drawing routine, - // so you can see the draws occur. - hdcGDU = hDC; - hOldPen = SelectObject(hdcGDU, hGreenPen); - - SetMapMode(hdcGDU, MM_ANISOTROPIC); - SetWindowExtEx(hdcGDU, 1024, -1024, NULL); - SetViewportExtEx(hdcGDU, wid, ht, NULL); - SetWindowOrgEx(hdcGDU, 0, 1023, NULL); - - generate_image(); - - SelectObject(hdcGDU, hOldPen); - hdcGDU = NULL; -#endif - } - - if (draw_indicators) { - x = r.right-2*INDWIDTH+1; - dy = ht / 16; - ycirc = MIN(dy-2, 8); - - r.left = x; - FillRect(hDC, &r, hGrayBrush); - SelectObject(hDC, hBlackPen); - - bit = 0x80000000L; - for (i = 0; i < 2; i++) { - MoveToEx(hDC, x, 0, NULL); - LineTo(hDC, x, r.bottom); - y = 0; - for (j = 0; j < 16; j++) { - MoveToEx(hDC, x, y, NULL); - LineTo(hDC, x+INDWIDTH, y); - - SelectObject(hDC, (gdu_indicators & bit) ? hRedBrush : hDarkBrush); - Pie(hDC, x+1, y+1, x+1+ycirc, y+1+ycirc, x+1, y+1, x+1, y+1); - - y += dy; - bit >>= 1; - } - x += INDWIDTH; - } - } -} - -// repaint the window - -static void gdu_WM_PAINT (HWND hWnd) -{ - PAINTSTRUCT ps; - HDC hDC; - // code for display - hDC = BeginPaint(hWnd, &ps); - PaintImage(hDC, TRUE); - EndPaint(hWnd, &ps); -} - -// the window has been resized - -static void gdu_WM_SIZE (HWND hWnd, UINT state, int cx, int cy) -{ - InvalidateRect(hWnd, NULL, FALSE); -} - -// tweak the sizing rectangle during a resize to guarantee a square window - -static void gdu_WM_SIZING (HWND hWnd, WPARAM fwSide, LPRECT r) -{ - switch (fwSide) { - case WMSZ_LEFT: - case WMSZ_RIGHT: - case WMSZ_BOTTOMLEFT: - case WMSZ_BOTTOMRIGHT: - r->bottom = r->right - r->left - 2*INDWIDTH + r->top; - break; - - case WMSZ_TOP: - case WMSZ_BOTTOM: - case WMSZ_TOPRIGHT: - r->right = r->bottom - r->top + r->left + 2*INDWIDTH; - break; - - case WMSZ_TOPLEFT: - r->left = r->top - r->bottom + r->right - 2*INDWIDTH; - break; - } -} - -// the refresh timer has gone off - -static void gdu_WM_TIMER (HWND hWnd, UINT id) -{ - HDC hDC; - - if (running) { // if CPU is running, update picture -#ifdef BLIT_MODE - hDC = GetDC(hWnd); // blit the new image right over the old - PaintImage(hDC, FALSE); - ReleaseDC(hWnd, hDC); -#else - InvalidateRect(hWnd, NULL, TRUE); // repaint -#endif - } -} - -// window procedure ------------------------------------------------------------ - -#define HANDLE(msg) case msg: return HANDLE_##msg(hWnd, wParam, lParam, gdu_##msg); - -#ifndef HANDLE_WM_SIZING -// void Cls_OnSizing(HWND hwnd, UINT fwSide, LPRECT r) -# define HANDLE_WM_SIZING(hwnd, wParam, lParam, fn) \ - ((fn)((hwnd), (UINT)(wParam), (LPRECT)(lParam)), 0L) -#endif - -static LRESULT APIENTRY GDUWndProc (HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) -{ - switch (iMessage) { - HANDLE(WM_CLOSE); - HANDLE(WM_GETMINMAXINFO); - HANDLE(WM_DESTROY); - HANDLE(WM_PAINT); - HANDLE(WM_SIZE); - HANDLE(WM_SIZING); - HANDLE(WM_TIMER); - default: // any message we don't process - return DefWindowProc(hWnd, iMessage, wParam, lParam); - } - return 0L; -} - -// graphic calls ---------------------------------------------------------------- - -static void DrawLine (int x0, int y0, int x1, int y1) -{ - MoveToEx(hdcGDU, x0, y0, NULL); - LineTo(hdcGDU, x1, y1); -} - -static void DrawPoint (int x, int y) -{ - SetPixel(hdcGDU, x, y, RGB_GREEN); -} - -static void UpdateGDUIndicators(void) -{ - if (hwGDU != NULL) - InvalidateRect(hwGDU, NULL, TRUE); -} - -static void CheckGDUKeyboard (void) -{ -} - -static UINT idTimer = 0; - -static void StartGDUUpdates (void) -{ - int msec; - - if (idTimer == 0) { - msec = (gdu_rate == 0) ? (1000 / DEFAULT_GDU_RATE) : 1000/gdu_rate; - idTimer = SetTimer(hwGDU, 1, msec, NULL); - } -} - -static void StopGDUUpdates (void) -{ - if (idTimer != 0) { - KillTimer(hwGDU, 1); - idTimer = 0; - } -} - -static void GetMouseCoordinates() -{ - POINT p; - RECT r; - - GetCursorPos(&p); - GetClientRect(hwGDU, &r); - if (! ScreenToClient(hwGDU, &p)) { - xmouse = ymouse = -2000; - mouse_present = FALSE; - return; - } - - if (p.x < r.left || p.x >= r.right || p.y < r.top || p.y > r.bottom) { - mouse_present = FALSE; - return; - } - - // convert mouse coordinates to scaled coordinates - - xmouse = (int) (1024./(r.right+1.-2*INDWIDTH)*p.x + 0.5); - ymouse = 1023 - (int) (1024./(r.bottom+1.)*p.y + 0.5); - mouse_present = TRUE; -} - -t_bool gdu_active (void) -{ - return gdu_dsw & GDU_DSW_BUSY; -} - -static void EraseGDUScreen (void) -{ - if (hwGDU != NULL) /* redraw screen. it will be blank if GDU is not running */ - InvalidateRect(hwGDU, NULL, TRUE); -} - -/* GDUPump - thread responsible for creating and displaying the graphics window */ - -static DWORD WINAPI GDUPump (LPVOID arg) -{ - MSG msg; - WNDCLASS wc; - - if (! wcInited) { /* register Window class */ - memset(&wc, 0, sizeof(wc)); - wc.style = CS_NOCLOSE; - wc.lpfnWndProc = GDUWndProc; - wc.hInstance = hInstance; - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = GetStockObject(BLACK_BRUSH); - wc.lpszClassName = APPCLASS; - - if (! RegisterClass(&wc)) { - GDUPumpID = 0; - return 0; - } - - wcInited = TRUE; - } - - if (hGreenPen == NULL) - hGreenPen = CreatePen(PS_SOLID, 1, RGB_GREEN); - -#ifdef DEBUG_LIGHTPEN - if (hRedPen == NULL) - hRedPen = CreatePen(PS_SOLID, 1, RGB_RED); -#endif - - if (hRedBrush == NULL) - hRedBrush = CreateSolidBrush(RGB_RED); - - hGrayBrush = GetStockObject(GRAY_BRUSH); - hDarkBrush = GetStockObject(DKGRAY_BRUSH); - hBlackPen = GetStockObject(BLACK_PEN); - - if (hwGDU == NULL) { /* create window */ - hwGDU = CreateWindow(APPCLASS, - "2250 Display", - WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, - CW_USEDEFAULT, CW_USEDEFAULT, // initial x, y position - INITSIZE+2*INDWIDTH, INITSIZE, // initial width and height - NULL, // parent window handle - NULL, // use class menu - hInstance, // program instance handle - NULL); // create parameters - - if (hwGDU == NULL) { - GDUPumpID = 0; - return 0; - } - } - - ShowWindow(hwGDU, SW_SHOWNOACTIVATE); /* display it */ - UpdateWindow(hwGDU); - - StartGDUUpdates(); - - while (GetMessage(&msg, hwGDU, 0, 0)) { /* message pump - this basically loops forevermore */ - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - if (hwGDU != NULL) { - DestroyWindow(hwGDU); /* but if a quit message got posted, clean up */ - hwGDU = NULL; - } - - GDUPumpID = 0; - return 0; -} - -#ifdef DEBUG_LIGHTPEN -static void ShowPenHit (int x, int y) -{ - HPEN hOldPen; - - hOldPen = SelectObject(hdcGDU, hRedPen); - DrawLine(x-10, y-10, x+10, y+10); - DrawLine(x-10, y+10, x+10, y-10); - SelectObject(hdcGDU, hOldPen); -} -#endif - -#endif // WIN32 defined -#endif // GUI_SUPPORT defined diff --git a/Ibm1130/ibm1130_gui.c b/Ibm1130/ibm1130_gui.c deleted file mode 100644 index 8a1461cb..00000000 --- a/Ibm1130/ibm1130_gui.c +++ /dev/null @@ -1,1269 +0,0 @@ -/* ibm1130_gui.c: IBM 1130 CPU simulator Console Display - * - * Based on the SIMH package written by Robert M Supnik - * - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - * - * 17-May-02 BLK Pulled out of ibm1130_cpu.c - */ - -/* ------------------------------------------------------------------------ - * Definitions - * ------------------------------------------------------------------------ */ - -#include -#include - -#include "ibm1130_defs.h" -#include "ibm1130res.h" - -#define UPDATE_BY_TIMER - -#ifdef UPDATE_BY_TIMER -# define UPDATE_INTERVAL 20 // set to desired number of updates/second -#else -# define UPDATE_INTERVAL 5000 // GUI: set to 100000/f where f = desired updates/second of 1130 time -#endif - -/* ------------------------------------------------------------------------ - * Function declarations - * ------------------------------------------------------------------------ */ - -t_stat console_reset (DEVICE *dptr); - -/* ------------------------------------------------------------------------ - * Console display - on Windows builds (only) this code displays the 1130 console - * and toggle switches. It really enhances the experience. - * - * Currently, when the IPS throttle is nonzero, I update the display after every - * UPDATE_INTERVAL instructions, plus or minus a random amount to avoid aliased - * sampling in loops. When UPDATE_INTERVAL is defined as zero, we update every - * instruction no matter what the throttle. This makes the simulator too slow - * but it's cool and helpful during development. - * ------------------------------------------------------------------------ */ - -#define UNIT_V_DISPLAY (UNIT_V_UF + 0) -#define UNIT_DISPLAY (1u << UNIT_V_DISPLAY) - -MTAB console_mod[] = { - { UNIT_DISPLAY, 0, "off", "OFF", NULL }, - { UNIT_DISPLAY, UNIT_DISPLAY, "on", "ON", NULL }, - { 0 } -}; - -UNIT console_unit = {UDATA (NULL, UNIT_DISABLE|UNIT_DISPLAY, 0) }; - -DEVICE console_dev = { - "GUI", &console_unit, NULL, console_mod, - 1, 16, 16, 1, 16, 16, - NULL, NULL, console_reset, - NULL, NULL, NULL -}; - -// reset for the "console" display device - -extern char *read_line (char *cptr, int size, FILE *stream); -extern FILE *sim_log; - -#ifndef GUI_SUPPORT - void update_gui (int force) {} /* stubs for non-GUI builds */ - void forms_check (int set) {} - void print_check (int set) {} - void keyboard_select (int select) {} - void keyboard_selected (int select) {} - void disk_ready (int ready) {} - void disk_unlocked (int unlocked) {} - void gui_run (int running) {} - static void init_console_window (void) {} - static void destroy_console_window (void) {} - - t_stat console_reset (DEVICE *dptr) {return SCPE_OK;} - void stuff_cmd (char *cmd) {} - char *read_cmdline (char *ptr, int size, FILE *stream) {return read_line(ptr, size, stream);} - void remark_cmd (char *remark) {printf("%s\n", remark); if (sim_log) fprintf(sim_log, "%s\n", remark);} -#else - -t_stat console_reset (DEVICE *dptr) -{ - if (! sim_gui) { - SETBIT(console_unit.flags, UNIT_DIS); // disable the GUI - CLRBIT(console_unit.flags, UNIT_DISPLAY); // turn the GUI off - } - - update_gui(FALSE); - return SCPE_OK; -} - -/* scp_panic - report fatal internal programming error */ - -void scp_panic (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - -#ifdef WIN32 - /* only WIN32 is defined right now */ - -#include - -#define BUTTON_WIDTH 90 -#define BUTTON_HEIGHT 50 - -#define IDC_KEYBOARD_SELECT 0 -#define IDC_DISK_UNLOCK 1 -#define IDC_RUN 2 -#define IDC_PARITY_CHECK 3 -#define IDC_UNUSED 4 -#define IDC_FILE_READY 5 -#define IDC_FORMS_CHECK 6 -#define IDC_POWER_ON 7 -#define IDC_POWER 8 -#define IDC_PROGRAM_START 9 -#define IDC_PROGRAM_STOP 10 -#define IDC_LOAD_IAR 11 -#define IDC_KEYBOARD 12 -#define IDC_IMM_STOP 13 -#define IDC_RESET 14 -#define IDC_PROGRAM_LOAD 15 - -#define LAMPTIME 500 // 500 msec delay on updating -#define FLASH_TIMER_ID 1 -#define UPDATE_TIMER_ID 2 - -static BOOL class_defined = FALSE; -static HWND hConsoleWnd = NULL; -static HBITMAP hBitmap = NULL; -static HFONT hFont = NULL; -static HFONT hBtnFont = NULL; -static HBRUSH hbLampOut = NULL; -static HBRUSH hbWhite = NULL; -static HBRUSH hbBlack = NULL; -static HBRUSH hbGray = NULL; -static HPEN hSwitchPen = NULL; -static HPEN hWhitePen = NULL; -static HPEN hBlackPen = NULL; -static HPEN hLtGreyPen = NULL; -static HPEN hGreyPen = NULL; -static HPEN hDkGreyPen = NULL; -static int hUpdateTimer = 0; -static int hFlashTimer = 0; - -static HCURSOR hcArrow = NULL; -static HCURSOR hcHand = NULL; -static HINSTANCE hInstance; -static HDC hCDC = NULL; -static char szConsoleClassName[] = "1130CONSOLE"; -static DWORD PumpID = 0; -static HANDLE hPump = INVALID_HANDLE_VALUE; -static int bmwid, bmht; - -static struct tag_btn { - int x, y; - char *txt; - BOOL pushable, state; - COLORREF clr; - HBRUSH hbrLit, hbrDark; - HWND hBtn; -} btn[] = { - 0, 0, "KEYBOARD\nSELECT", FALSE, FALSE, RGB(255,255,180), NULL, NULL, NULL, - 0, 1, "DISK\nUNLOCK", FALSE, TRUE, RGB(255,255,180), NULL, NULL, NULL, - 0, 2, "RUN", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL, - 0, 3, "PARITY\nCHECK", FALSE, FALSE, RGB(255,0,0), NULL, NULL, NULL, - - 1, 0, "", FALSE, FALSE, RGB(255,255,180), NULL, NULL, NULL, - 1, 1, "FILE\nREADY", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL, - 1, 2, "FORMS\nCHECK", FALSE, FALSE, RGB(255,255,0), NULL, NULL, NULL, - 1, 3, "POWER\nON", FALSE, TRUE, RGB(255,255,180), NULL, NULL, NULL, - - 2, 0, "POWER", TRUE, FALSE, RGB(255,255,180), NULL, NULL, NULL, - 2, 1, "PROGRAM\nSTART", TRUE, FALSE, RGB(0,255,0), NULL, NULL, NULL, - 2, 2, "PROGRAM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL, - 2, 3, "LOAD\nIAR", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, - - 3, 0, "KEYBOARD", TRUE, FALSE, RGB(255,255,180), NULL, NULL, NULL, - 3, 1, "IMM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL, - 3, 2, "CHECK\nRESET", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, - 3, 3, "PROGRAM\nLOAD", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, -}; -#define NBUTTONS (sizeof(btn) / sizeof(btn[0])) - -static void init_console_window (void); -static void destroy_console_window (void); -LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -static DWORD WINAPI Pump (LPVOID arg); - -#define NIXOBJECT(hObj) if (hObj != NULL) {DeleteObject(hObj); hObj = NULL;} - -/* ------------------------------------------------------------------------ - * init_console_window - display the 1130 console. Actually just creates a thread - * to run the Pump routine which does the actual work. - * ------------------------------------------------------------------------ */ - -static void init_console_window (void) -{ - static BOOL did_atexit = FALSE; - - if (hConsoleWnd != NULL) - return; - - if (PumpID == 0) - hPump = CreateThread(NULL, 0, Pump, 0, 0, &PumpID); - - if (! did_atexit) { - atexit(destroy_console_window); - did_atexit = TRUE; - } -} - -/* ------------------------------------------------------------------------ - * destroy_console_window - delete GDI objects. - * ------------------------------------------------------------------------ */ - -static void destroy_console_window (void) -{ - int i; - - if (hConsoleWnd != NULL) - SendMessage(hConsoleWnd, WM_CLOSE, 0, 0); // cross thread call is OK - - if (hPump != INVALID_HANDLE_VALUE) { // this is not the most graceful way to do it - TerminateThread(hPump, 0); - hPump = INVALID_HANDLE_VALUE; - PumpID = 0; - hConsoleWnd = NULL; - } - if (hCDC != NULL) { - DeleteDC(hCDC); - hCDC = NULL; - } - - NIXOBJECT(hBitmap) - NIXOBJECT(hbLampOut) - NIXOBJECT(hFont) - NIXOBJECT(hBtnFont); - NIXOBJECT(hcHand) - NIXOBJECT(hSwitchPen) - NIXOBJECT(hLtGreyPen) - NIXOBJECT(hGreyPen) - NIXOBJECT(hDkGreyPen) - - for (i = 0; i < NBUTTONS; i++) { - NIXOBJECT(btn[i].hbrLit); - NIXOBJECT(btn[i].hbrDark); - } - -// if (class_defined) { -// UnregisterClass(hInstance, szConsoleClassName); -// class_defined = FALSE; -// } -} - -/* ------------------------------------------------------------------------ - * these variables hold the displayed versions of the system registers - * ------------------------------------------------------------------------ */ - -static int shown_iar = 0, shown_sar = 0, shown_sbr = 0, shown_afr = 0, shown_acc = 0, shown_ext = 0; -static int shown_op = 0, shown_tag = 0, shown_irq = 0, shown_ccc = 0, shown_cnd = 0, shown_wait = 0; -static int shown_ces = 0, shown_runmode = MODE_RUN; -static int CND; - -/* ------------------------------------------------------------------------ - * RedrawRegion - mark a region for redrawing without background erase - * ------------------------------------------------------------------------ */ - -static void RedrawRegion (HWND hWnd, int left, int top, int right, int bottom) -{ - RECT r; - - r.left = left; - r.top = top; - r.right = right; - r.bottom = bottom; - - InvalidateRect(hWnd, &r, FALSE); -} - -/* ------------------------------------------------------------------------ - * RepaintRegion - mark a region for redrawing with background erase - * ------------------------------------------------------------------------ */ - -static void RepaintRegion (HWND hWnd, int left, int top, int right, int bottom) -{ - RECT r; - - r.left = left; - r.top = top; - r.right = right; - r.bottom = bottom; - - InvalidateRect(hWnd, &r, TRUE); -} - -/* ------------------------------------------------------------------------ - * update_gui - sees if anything on the console display has changed, and invalidates - * the changed regions. Then it calls UpdateWindow to force an immediate repaint. This - * function (update_gui) should probably not be called every time through the main - * instruction loop but it should be called at least whenever wait_state or int_req change, and then - * every so many instructions. It's also called after every simh command so manual changes are - * reflected instantly. - * ------------------------------------------------------------------------ */ - -void update_gui (BOOL force) -{ - int i; - BOOL state; - static int in_here = FALSE; - static int32 displayed = 0; - - if ((int32)(console_unit.flags & UNIT_DISPLAY) != displayed) { // setting has changed - displayed = console_unit.flags & UNIT_DISPLAY; - if (displayed) - init_console_window(); - else - destroy_console_window(); - } - - if (hConsoleWnd == NULL) - return; - - GUI_BEGIN_CRITICAL_SECTION /* only one thread at a time, please */ - if (in_here) { - GUI_END_CRITICAL_SECTION - return; - } - in_here = TRUE; - GUI_END_CRITICAL_SECTION - - CND = 0; /* combine carry and V as two bits */ - if (C) - CND |= 2; - if (V) - CND |= 1; - - int_lamps |= int_req; - if (ipl >= 0) - int_lamps |= (0x20 >> ipl); - - if (RUNMODE == MODE_LOAD) - SBR = CES; /* in load mode, SBR follows the console switches */ - - if (IAR != shown_iar) - {shown_iar = IAR; RedrawRegion(hConsoleWnd, 75, 8, 364, 32);} /* lamps: don't bother erasing bkgnd */ - if (SAR != shown_sar) - {shown_sar = SAR; RedrawRegion(hConsoleWnd, 75, 42, 364, 65);} - if (ACC != shown_acc) - {shown_acc = ACC; RedrawRegion(hConsoleWnd, 75, 141, 364, 164);} - if (EXT != shown_ext) - {shown_ext = EXT; RedrawRegion(hConsoleWnd, 75, 174, 364, 197);} - if (SBR != shown_sbr) - {shown_sbr = SBR; RedrawRegion(hConsoleWnd, 75, 77, 364, 97);} - if (OP != shown_op) - {shown_op = OP; RedrawRegion(hConsoleWnd, 501, 8, 595, 32);} - if (TAG != shown_tag) - {shown_tag = TAG; RedrawRegion(hConsoleWnd, 501, 77, 595, 97);} - - if (int_lamps != shown_irq) - {shown_irq = int_lamps; RedrawRegion(hConsoleWnd, 501, 108, 595, 130);} - - if (CCC != shown_ccc) - {shown_ccc = CCC; RedrawRegion(hConsoleWnd, 501, 141, 595, 164);} - if (CND != shown_cnd) - {shown_cnd = CND; RedrawRegion(hConsoleWnd, 501, 174, 595, 197);} - if ((wait_state|wait_lamp) != shown_wait) - {shown_wait= (wait_state|wait_lamp); RedrawRegion(hConsoleWnd, 380, 77, 414, 97);} - if (CES != shown_ces) - {shown_ces = CES; RepaintRegion(hConsoleWnd, 115, 230, 478, 275);} /* console entry sw: do erase bkgnd */ - if (RUNMODE != shown_runmode) - {shown_runmode = RUNMODE;RepaintRegion(hConsoleWnd, 270, 359, 330, 418);} - - int_lamps = 0; - - // this loop works with lamp buttons that are calculated on-the-fly only - for (i = 0; i < NBUTTONS; i++) { - if (btn[i].pushable) - continue; - - switch (i) { - case IDC_RUN: - state = hFlashTimer || (running && ! wait_state); - break; - - // this button is always off -// case IDC_PARITY_CHECK: - - // these buttons are enabled/disabled directly -// case IDC_POWER_ON: -// case IDC_FILE_READY: -// case IDC_FORMS_CHECK: -// case IDC_KEYBOARD_SELECT: -// case IDC_DISK_UNLOCK: - default: - continue; - } - - if (state != btn[i].state) { // state has changed - EnableWindow(btn[i].hBtn, state); - btn[i].state = state; - } - } - - in_here = FALSE; -} - -WNDPROC oldButtonProc = NULL; - -/* ------------------------------------------------------------------------ - * ------------------------------------------------------------------------ */ - -LRESULT CALLBACK ButtonProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - int i; - - i = GetWindowLong(hWnd, GWL_ID); - - if (! btn[i].pushable) { - if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP || uMsg == WM_LBUTTONDBLCLK) - return 0; - - if (uMsg == WM_CHAR) - if ((TCHAR) wParam == ' ') - return 0; - } - - return CallWindowProc(oldButtonProc, hWnd, uMsg, wParam, lParam); -} - -/* ------------------------------------------------------------------------ - * ------------------------------------------------------------------------ */ - -static int occurs (char *txt, char ch) -{ - int count = 0; - - while (*txt) - if (*txt++ == ch) - count++; - - return count; -} - -/* ------------------------------------------------------------------------ -// turns out to get properly colored buttons you have to paint them yourself. Sheesh. -// On the plus side, this lets do a better job of aligning the button text than -// the button would by itself. - * ------------------------------------------------------------------------ */ - -void PaintButton (LPDRAWITEMSTRUCT dis) -{ - int i = dis->CtlID, nc, nlines, x, y, dy; - BOOL down = dis->itemState & ODS_SELECTED; - HPEN hOldPen; - HFONT hOldFont; - UINT oldAlign; - COLORREF oldBk; - char *txt, *tstart; - - if (! BETWEEN(i, 0, NBUTTONS-1)) - return; - - FillRect(dis->hDC, &dis->rcItem, ((btn[i].pushable || power) && IsWindowEnabled(btn[i].hBtn)) ? btn[i].hbrLit : btn[i].hbrDark); - - if (! btn[i].pushable) { - hOldPen = SelectObject(dis->hDC, hBlackPen); - MoveToEx(dis->hDC, dis->rcItem.left, dis->rcItem.top, NULL); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.top); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.bottom-1); - LineTo(dis->hDC, dis->rcItem.left, dis->rcItem.bottom-1); - LineTo(dis->hDC, dis->rcItem.left, dis->rcItem.top); - } - else if (down) { - // do the three-D thing - hOldPen = SelectObject(dis->hDC, hDkGreyPen); - MoveToEx(dis->hDC, dis->rcItem.left, dis->rcItem.bottom-2, NULL); - LineTo(dis->hDC, dis->rcItem.left, dis->rcItem.top); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.top); - - SelectObject(dis->hDC, hWhitePen); - MoveToEx(dis->hDC, dis->rcItem.left, dis->rcItem.bottom-1, NULL); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.bottom-1); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.top); - - SelectObject(dis->hDC, hGreyPen); - MoveToEx(dis->hDC, dis->rcItem.left+1, dis->rcItem.bottom-3, NULL); - LineTo(dis->hDC, dis->rcItem.left+1, dis->rcItem.top+1); - LineTo(dis->hDC, dis->rcItem.right-3, dis->rcItem.top+1); - } - else { - hOldPen = SelectObject(dis->hDC, hWhitePen); - MoveToEx(dis->hDC, dis->rcItem.left, dis->rcItem.bottom-2, NULL); - LineTo(dis->hDC, dis->rcItem.left, dis->rcItem.top); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.top); - - SelectObject(dis->hDC, hDkGreyPen); - MoveToEx(dis->hDC, dis->rcItem.left, dis->rcItem.bottom-1, NULL); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.bottom-1); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.top); - - SelectObject(dis->hDC, hGreyPen); - MoveToEx(dis->hDC, dis->rcItem.left+1, dis->rcItem.bottom-2, NULL); - LineTo(dis->hDC, dis->rcItem.right-2, dis->rcItem.bottom-2); - LineTo(dis->hDC, dis->rcItem.right-2, dis->rcItem.top+1); - } - - SelectObject(dis->hDC, hOldPen); - - hOldFont = SelectObject(dis->hDC, hBtnFont); - oldAlign = SetTextAlign(dis->hDC, TA_CENTER|TA_TOP); - oldBk = SetBkMode(dis->hDC, TRANSPARENT); - - txt = btn[i].txt; - nlines = occurs(txt, '\n')+1; - x = (dis->rcItem.left + dis->rcItem.right) / 2; - y = (dis->rcItem.top + dis->rcItem.bottom) / 2; - - dy = 14; - y = y - (nlines*dy)/2; - - if (down) { - x += 1; - y += 1; - } - - for (;;) { - for (nc = 0, tstart = txt; *txt && *txt != '\n'; txt++, nc++) - ; - - TextOut(dis->hDC, x, y, tstart, nc); - - if (*txt == '\0') - break; - - txt++; - y += dy; - } - - SetTextAlign(dis->hDC, oldAlign); - SetBkMode(dis->hDC, oldBk); - SelectObject(dis->hDC, hOldFont); -} - -/* ------------------------------------------------------------------------ - * ------------------------------------------------------------------------ */ - -HWND CreateSubclassedButton (HWND hwParent, int i) -{ - HWND hBtn; - int x, y; - int r, g, b; - - y = bmht - (4*BUTTON_HEIGHT) + BUTTON_HEIGHT * btn[i].y; - x = (btn[i].x < 2) ? (btn[i].x*BUTTON_WIDTH) : (bmwid - (4-btn[i].x)*BUTTON_WIDTH); - - if ((hBtn = CreateWindow("BUTTON", btn[i].txt, WS_CHILD|WS_VISIBLE|BS_CENTER|BS_MULTILINE|BS_OWNERDRAW, - x, y, BUTTON_WIDTH, BUTTON_HEIGHT, hwParent, (HMENU) i, hInstance, NULL)) == NULL) - return NULL; - - btn[i].hBtn = hBtn; - - if (oldButtonProc == NULL) - oldButtonProc = (WNDPROC) GetWindowLong(hBtn, GWL_WNDPROC); - - btn[i].hbrLit = CreateSolidBrush(btn[i].clr); - - if (! btn[i].pushable) { - r = GetRValue(btn[i].clr) / 4; - g = GetGValue(btn[i].clr) / 4; - b = GetBValue(btn[i].clr) / 4; - - btn[i].hbrDark = CreateSolidBrush(RGB(r,g,b)); - EnableWindow(hBtn, FALSE); - } - - SetWindowLong(hBtn, GWL_WNDPROC, (LONG) ButtonProc); - return hBtn; -} - -/* ------------------------------------------------------------------------ - * Pump - thread that takes care of the console window. It has to be a separate thread so that it gets - * execution time even when the simulator is compute-bound or IO-blocked. This routine creates the window - * and runs a standard Windows message pump. The window function does the actual display work. - * ------------------------------------------------------------------------ */ - -static DWORD WINAPI Pump (LPVOID arg) -{ - MSG msg; - int wx, wy, i; - RECT r, ra; - BITMAP bm; - WNDCLASS cd; - HDC hDC; - HWND hActWnd; - - hActWnd = GetForegroundWindow(); - - if (! class_defined) { /* register Window class */ - hInstance = GetModuleHandle(NULL); - - memset(&cd, 0, sizeof(cd)); - cd.style = CS_NOCLOSE; - cd.lpfnWndProc = ConsoleWndProc; - cd.cbClsExtra = 0; - cd.cbWndExtra = 0; - cd.hInstance = hInstance; - cd.hIcon = NULL; - cd.hCursor = hcArrow; - cd.hbrBackground = NULL; - cd.lpszMenuName = NULL; - cd.lpszClassName = szConsoleClassName; - - if (! RegisterClass(&cd)) { - PumpID = 0; - return 0; - } - - class_defined = TRUE; - } - - hbWhite = GetStockObject(WHITE_BRUSH); /* create or fetch useful GDI objects */ - hbBlack = GetStockObject(BLACK_BRUSH); /* create or fetch useful GDI objects */ - hbGray = GetStockObject(GRAY_BRUSH); - hSwitchPen = CreatePen(PS_SOLID, 5, RGB(255,255,255)); - - hWhitePen = GetStockObject(WHITE_PEN); - hBlackPen = GetStockObject(BLACK_PEN); - hLtGreyPen = CreatePen(PS_SOLID, 1, RGB(190,190,190)); - hGreyPen = CreatePen(PS_SOLID, 1, RGB(128,128,128)); - hDkGreyPen = CreatePen(PS_SOLID, 1, RGB(64,64,64)); - - hcArrow = LoadCursor(NULL, IDC_ARROW); - hcHand = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_HAND)); - - if (hBitmap == NULL) - hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_CONSOLE)); - if (hbLampOut == NULL) - hbLampOut = CreateSolidBrush(RGB(50,50,50)); - if (hFont == NULL) - hFont = CreateFont(-10, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, FIXED_PITCH, FF_SWISS, "Arial"); - if (hBtnFont == NULL) - hBtnFont = CreateFont(-12, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, FIXED_PITCH, FF_SWISS, "Arial"); - - if (hConsoleWnd == NULL) { /* create window */ - if ((hConsoleWnd = CreateWindow(szConsoleClassName, "IBM 1130", WS_OVERLAPPED, 0, 0, 200, 200, NULL, NULL, hInstance, NULL)) == NULL) { - PumpID = 0; - return 0; - } - } - - GetObject(hBitmap, sizeof(bm), &bm); /* get bitmap size */ - bmwid = bm.bmWidth; - bmht = bm.bmHeight; - - for (i = 0; i < NBUTTONS; i++) { - CreateSubclassedButton(hConsoleWnd, i); - - if (! btn[i].pushable) - EnableWindow(btn[i].hBtn, btn[i].state); - } - - GetWindowRect(hConsoleWnd, &r); /* get window size as created */ - wx = r.right - r.left + 1; - wy = r.bottom - r.top + 1; - - if (hCDC == NULL) { /* get a memory DC and select the bitmap into ti */ - hDC = GetDC(hConsoleWnd); - hCDC = CreateCompatibleDC(hDC); - SelectObject(hCDC, hBitmap); - ReleaseDC(hConsoleWnd, hDC); - } - - GetClientRect(hConsoleWnd, &r); - wx = (wx - r.right - 1) + bmwid; /* compute new desired size based on how client area came out */ - wy = (wy - r.bottom - 1) + bmht; - MoveWindow(hConsoleWnd, 0, 0, wx, wy, FALSE); /* resize window */ - - ShowWindow(hConsoleWnd, SW_SHOWNOACTIVATE); /* display it */ - UpdateWindow(hConsoleWnd); - - if (hActWnd != NULL) { /* bring console (sim) window back to top */ - GetWindowRect(hConsoleWnd, &r); - ShowWindow(hActWnd, SW_NORMAL); /* and move it just below the display window */ - SetWindowPos(hActWnd, HWND_TOP, 0, r.bottom, 0, 0, SWP_NOSIZE); - GetWindowRect(hActWnd, &ra); - if (ra.bottom >= GetSystemMetrics(SM_CYSCREEN)) { /* resize if it goes of bottom of screen */ - ra.bottom = GetSystemMetrics(SM_CYSCREEN) - 1; - SetWindowPos(hActWnd, 0, 0, 0, ra.right-ra.left+1, ra.bottom-ra.top+1, SWP_NOZORDER|SWP_NOMOVE); - } - } - - if (running) /* if simulator is already running, start update timer */ - gui_run(TRUE); - - while (GetMessage(&msg, hConsoleWnd, 0, 0)) { /* message pump - this basically loops forevermore */ - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - if (hConsoleWnd != NULL) { - DestroyWindow(hConsoleWnd); /* but if a quit message got posted, clean up */ - hConsoleWnd = NULL; - } - - PumpID = 0; - return 0; -} - -/* ------------------------------------------------------------------------ - * DrawBits - starting at position (x,y), draw lamps for nbits bits of word 'bits', looking only at masked bits - * ------------------------------------------------------------------------ */ - -static void DrawBits (HDC hDC, int x, int y, int bits, int nbits, int mask, char *syms) -{ - int i, b = 0x0001 << (nbits-1); - - for (i = 0; i < nbits; i++, b >>= 1) { - if (mask & b) { /* select white or black lettering then write 2 chars */ - SetTextColor(hDC, (b & bits && power) ? RGB(255,255,255) : RGB(0,0,0)); - TextOut(hDC, x, y, syms, 2); - } - syms += 2; /* go to next symbol pair */ - - if (i < 10) - x += 15; /* step between lamps */ - else - x += 19; - - if (x < 500) { - if (b & 0x1110) - x += 10; /* step over nibble divisions on left side */ - else if (b & 0x0001) - x += 9; - } - } -} - -/* ------------------------------------------------------------------------ - * DrawToggles - display the console sense switches - * ------------------------------------------------------------------------ */ - -static void DrawToggles (HDC hDC, int bits) -{ - int b, x; - - for (b = 0x8000, x = 122; b != 0; b >>= 1) { - if (shown_ces & b) { /* up */ - SelectObject(hDC, hbWhite); - Rectangle(hDC, x, 232, x+9, 240); - SelectObject(hDC, hbGray); - Rectangle(hDC, x, 239, x+9, 255); - } - else { /* down */ - SelectObject(hDC, hbWhite); - Rectangle(hDC, x, 263, x+9, 271); - SelectObject(hDC, hbGray); - Rectangle(hDC, x, 248, x+9, 264); - } - - x += (b & 0x1111) ? 31 : 21; - } -} - -/* ------------------------------------------------------------------------ - * DrawRunmode - draw the run mode rotary switch's little tip - * ------------------------------------------------------------------------ */ - -void DrawRunmode (HDC hDC, int mode) -{ - double angle = (mode*45. + 90.) * 3.1415926 / 180.; /* convert mode position to angle in radians */ - double ca, sa; /* sine and cosine */ - int x0, y0, x1, y1; - HPEN hOldPen; - - ca = cos(angle); - sa = sin(angle); - - x0 = 301 + (int) (20.*ca + 0.5); /* inner radius */ - y0 = 389 - (int) (20.*sa + 0.5); - x1 = 301 + (int) (25.*ca + 0.5); /* outer radius */ - y1 = 389 - (int) (25.*sa + 0.5); - - hOldPen = SelectObject(hDC, hSwitchPen); - - MoveToEx(hDC, x0, y0, NULL); - LineTo(hDC, x1, y1); - - SelectObject(hDC, hOldPen); -} - -/* ------------------------------------------------------------------------ - * HandleClick - handle mouse clicks on the console window. Now we just - * look at the console sense switches. Actual says this is a real click, rather - * than a mouse-region test. Return value TRUE means the cursor is over a hotspot. - * ------------------------------------------------------------------------ */ - -static BOOL HandleClick (HWND hWnd, int xh, int yh, BOOL actual) -{ - int b, x, r, ang, i; - - for (b = 0x8000, x = 122; b != 0; b >>= 1) { - if (BETWEEN(xh, x-3, x+8+3) && BETWEEN(yh, 230, 275)) { - if (actual) { - CES ^= b; /* a hit. Invert the bit and redisplay */ - update_gui(TRUE); - } - return TRUE; - } - x += (b & 0x1111) ? 31 : 21; - } - - if (BETWEEN(xh, 245, 355) && BETWEEN(yh, 345, 425)) { /* hit near rotary switch */ - ang = (int) (atan2(301.-xh, 389.-yh)*180./3.1415926); /* this does implicit 90 deg rotation by the way */ - r = (int) sqrt((xh-301)*(xh-301)+(yh-389)*(yh-389)); - if (r > 12) { - for (i = MODE_LOAD; i <= MODE_INT_RUN; i++) { - if (BETWEEN(ang, i*45-12, i*45+12)) { - if (actual) { - RUNMODE = i; - update_gui(TRUE); - } - return TRUE; - } - } - - } - } - - return FALSE; -} - -/* ------------------------------------------------------------------------ - * DrawConsole - refresh the console display. (This routine could be sped up by intersecting - * the various components' bounding rectangles with the repaint rectangle. The bounding rects - * could be put into an array and used both here and in the refresh routine). - * - * RedrawRegion -> force repaint w/o background redraw. used for lamps which are drawn in the same place in either state - * RepaintRegion-> repaint with background redraw. Used for toggles which change position. - * ------------------------------------------------------------------------ */ - -static void DrawConsole (HDC hDC) -{ - static char digits[] = " 0 1 2 3 4 5 6 7 8 9101112131415"; - static char cccs[] = "3216 8 4 2 1"; - static char cnds[] = " C V"; - static char waits[] = " W"; - HFONT hOldFont, hOldBrush; - - hOldFont = SelectObject(hDC, hFont); /* use that tiny font */ - hOldBrush = SelectObject(hDC, hbWhite); - - SetBkMode(hDC, TRANSPARENT); /* overlay letters w/o changing background */ - - DrawBits(hDC, 76, 15, shown_iar, 16, 0x3FFF, digits); - DrawBits(hDC, 76, 48, shown_sar, 16, 0x3FFF, digits); - DrawBits(hDC, 76, 81, shown_sbr, 16, 0xFFFF, digits); - DrawBits(hDC, 76, 147, shown_acc, 16, 0xFFFF, digits); - DrawBits(hDC, 76, 180, shown_ext, 16, 0xFFFF, digits); - - DrawBits(hDC, 506, 15, shown_op, 5, 0x001F, digits); - DrawBits(hDC, 506, 81, shown_tag, 4, 0x0007, digits); - DrawBits(hDC, 506, 114, shown_irq, 6, 0x003F, digits); - DrawBits(hDC, 506, 147, shown_ccc, 6, 0x003F, cccs); - DrawBits(hDC, 506, 180, shown_cnd, 2, 0x0003, cnds); - - DrawBits(hDC, 390, 81, shown_wait?1:0,1, 0x0001, waits); - - DrawToggles(hDC, shown_ces); - - DrawRunmode(hDC, shown_runmode); - - SelectObject(hDC, hOldFont); - SelectObject(hDC, hOldBrush); -} - -/* ------------------------------------------------------------------------ - * Handles button presses. Remember that this occurs in the context of - * the Pump thread, not the simulator thread. - * ------------------------------------------------------------------------ */ - -void flash_run (void) -{ - EnableWindow(btn[IDC_RUN].hBtn, TRUE); // enable the run lamp - - if (hFlashTimer != 0) - KillTimer(hConsoleWnd, FLASH_TIMER_ID); // (re)schedule lamp update - - hFlashTimer = SetTimer(hConsoleWnd, FLASH_TIMER_ID, LAMPTIME, NULL); -} - -void gui_run (int running) -{ - if (running && hUpdateTimer == 0 && hConsoleWnd != NULL) { - hUpdateTimer = SetTimer(hConsoleWnd, UPDATE_TIMER_ID, 1000/UPDATE_INTERVAL, NULL); - } - else if (hUpdateTimer != 0 && ! running) { - KillTimer(hConsoleWnd, UPDATE_TIMER_ID); - hUpdateTimer = 0; - } - flash_run(); /* keep run lamp active for a while after we stop running */ -} - -void HandleCommand (HWND hWnd, WPARAM wParam, LPARAM lParam) -{ - int i; - - switch (wParam) { - case IDC_POWER: /* toggle system power */ - power = ! power; - reset_all(0); - if (running && ! power) { /* turning off */ - reason = STOP_POWER_OFF; -// this prevents message pump from running, which unfortunately locks up -// the emulator thread when it calls gui_run(FALSE) which calls EnableWindow on the Run lamp -// while (running) -// Sleep(10); /* wait for execution thread to exit */ - } - - btn[IDC_POWER_ON].state = power; - EnableWindow(btn[IDC_POWER_ON].hBtn, power); - - for (i = 0; i < NBUTTONS; i++) /* repaint all of the lamps */ - if (! btn[i].pushable) - InvalidateRect(btn[i].hBtn, NULL, TRUE); - - break; - - case IDC_PROGRAM_START: /* begin execution */ - if (! running) { - switch (RUNMODE) { - case MODE_INT_RUN: - case MODE_RUN: - case MODE_SI: - stuff_cmd("go"); - break; - - case MODE_DISP: /* display core and advance IAR */ - ReadW(IAR); - IAR = IAR+1; - flash_run(); /* illuminate run lamp for .5 sec */ - break; - - case MODE_LOAD: /* store to core and advance IAR */ - WriteW(IAR, CES); - IAR = IAR+1; - flash_run(); - break; - } - } - break; - - case IDC_PROGRAM_STOP: - if (running) { /* potential race condition here */ - GUI_BEGIN_CRITICAL_SECTION - SETBIT(cpu_dsw, CPU_DSW_PROGRAM_STOP); - SETBIT(ILSW[5], ILSW_5_PROGRAM_STOP); - int_req |= INT_REQ_5; - GUI_END_CRITICAL_SECTION - } - break; - - case IDC_LOAD_IAR: - if (! running) { - IAR = CES & 0x3FFF; /* set IAR from console entry switches */ - } - break; - - case IDC_KEYBOARD: /* toggle between console/keyboard mode */ - break; - - case IDC_IMM_STOP: - if (running) { - reason = STOP_WAIT; /* terminate execution without setting wait_mode */ - -// this prevents message pump from running, which unfortunately locks up -// the emulator thread when it calls gui_run(FALSE) which calls EnableWindow on the Run lamp -// while (running) -// Sleep(10); /* wait for execution thread to exit */ - } - break; - - case IDC_RESET: - if (! running) { /* check-reset is disabled while running */ - reset_all(0); - forms_check(0); /* clear forms-check status */ - print_check(0); - } - break; - - case IDC_PROGRAM_LOAD: - if (! running) { /* if card reader is attached to a file, do cold start read of one card */ - IAR = 0; /* reset IAR */ -// stuff_cmd("boot cr"); - if (cr_boot(0, NULL) != SCPE_OK) /* load boot card */ - remark_cmd("IPL failed"); - } - break; - } - - update_gui(FALSE); -} - -/* ------------------------------------------------------------------------ - * ConsoleWndProc - window process for the console display - * ------------------------------------------------------------------------ */ - -LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - HDC hDC; - PAINTSTRUCT ps; - POINT p; - RECT clip, xsect, rbmp; - int i; - - switch (uMsg) { - case WM_CLOSE: - DestroyWindow(hWnd); - break; - - case WM_DESTROY: - gui_run(FALSE); - hConsoleWnd = NULL; - break; - - case WM_ERASEBKGND: - hDC = (HDC) wParam; - GetClipBox(hDC, &clip); - SetRect(&rbmp, 0, 0, bmwid, bmht); - if (IntersectRect(&xsect, &clip, &rbmp)) - BitBlt(hDC, xsect.left, xsect.top, xsect.right-xsect.left+1, xsect.bottom-xsect.top+1, hCDC, xsect.left, xsect.top, SRCCOPY); -// rbmp.top = rbmp.bottom; -// rbmp.bottom += 200; -// if (IntersectRect(&xsect, &clip, &rbmp)) -// FillRect(hDC, &xsect, hbBlack); - return TRUE; /* let Paint do this so we know what the update region is (ps.rcPaint) */ - - case WM_PAINT: - hDC = BeginPaint(hWnd, &ps); - DrawConsole(hDC); - EndPaint(hWnd, &ps); - break; - - case WM_COMMAND: /* button click */ - HandleCommand(hWnd, wParam, lParam); - break; - - case WM_DRAWITEM: - PaintButton((LPDRAWITEMSTRUCT) lParam); - break; - - case WM_SETCURSOR: - GetCursorPos(&p); - ScreenToClient(hWnd, &p); - SetCursor(HandleClick(hWnd, p.x, p.y, FALSE) ? hcHand : hcArrow); - return TRUE; - - case WM_LBUTTONDOWN: - HandleClick(hWnd, LOWORD(lParam), HIWORD(lParam), TRUE); - break; - - case WM_CTLCOLORBTN: - i = GetWindowLong((HWND) lParam, GWL_ID); - if (BETWEEN(i, 0, NBUTTONS-1)) - return (LRESULT) (power && IsWindowEnabled((HWND) lParam) ? btn[i].hbrLit : btn[i].hbrDark); - - case WM_TIMER: - if (wParam == FLASH_TIMER_ID && hFlashTimer != 0) { - KillTimer(hWnd, FLASH_TIMER_ID); - hFlashTimer = 0; - } - update_gui(FALSE); - break; - - default: - return DefWindowProc(hWnd, uMsg, wParam, lParam); - } - - return 0; -} - -enum {PRINTER_OK = 0, FORMS_CHECK = 1, PRINT_CHECK = 2, BOTH_CHECK = 3} printerstatus = PRINTER_OK; - -void forms_check (int set) -{ - COLORREF oldcolor = btn[IDC_FORMS_CHECK].clr; - - if (set) - SETBIT(printerstatus, FORMS_CHECK); - else - CLRBIT(printerstatus, FORMS_CHECK); - - btn[IDC_FORMS_CHECK].clr = (printerstatus & PRINT_CHECK) ? RGB(255,0,0) : RGB(255,255,0); - - btn[IDC_FORMS_CHECK].state = printerstatus; - - if (btn[IDC_FORMS_CHECK].hBtn != NULL) { - EnableWindow(btn[IDC_FORMS_CHECK].hBtn, printerstatus); - - if (btn[IDC_FORMS_CHECK].clr != oldcolor) - InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); // change color in any case - } -} - -void print_check (int set) -{ - COLORREF oldcolor = btn[IDC_FORMS_CHECK].clr; - - if (set) - SETBIT(printerstatus, PRINT_CHECK); - else - CLRBIT(printerstatus, PRINT_CHECK); - - btn[IDC_FORMS_CHECK].clr = (printerstatus & PRINT_CHECK) ? RGB(255,0,0) : RGB(255,255,0); - - btn[IDC_FORMS_CHECK].state = printerstatus; - - if (btn[IDC_FORMS_CHECK].hBtn != NULL) { - EnableWindow(btn[IDC_FORMS_CHECK].hBtn, printerstatus); - - if (btn[IDC_FORMS_CHECK].clr != oldcolor) - InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); // change color in any case - } -} - -void keyboard_selected (int select) -{ - btn[IDC_KEYBOARD_SELECT].state = select; - - if (btn[IDC_KEYBOARD_SELECT].hBtn != NULL) - EnableWindow(btn[IDC_KEYBOARD_SELECT].hBtn, select); -} - -void disk_ready (int ready) -{ - btn[IDC_FILE_READY].state = ready; - - if (btn[IDC_FILE_READY].hBtn != NULL) - EnableWindow(btn[IDC_FILE_READY].hBtn, ready); -} - -void disk_unlocked (int unlocked) -{ - btn[IDC_DISK_UNLOCK].state = unlocked; - - if (btn[IDC_DISK_UNLOCK].hBtn != NULL) - EnableWindow(btn[IDC_DISK_UNLOCK].hBtn, unlocked); -} - -CRITICAL_SECTION critsect; - -void begin_critical_section (void) -{ - static BOOL mustinit = TRUE; - - if (mustinit) { - InitializeCriticalSection(&critsect); - mustinit = FALSE; - } - - EnterCriticalSection(&critsect); -} - -void end_critical_section (void) -{ - LeaveCriticalSection(&critsect); -} - -#ifndef MIN -# define MIN(a,b) (((a) <= (b)) ? (a) : (b)) -#endif - -/* win32 - use a separate thread to read command lines so the GUI - * can insert commands as well */ - -static HANDLE hCmdThread = NULL; -static DWORD iCmdThreadID = 0; -static HANDLE hCmdReadEvent = NULL; -static HANDLE hCmdReadyEvent = NULL; -static BOOL scp_stuffed = FALSE, scp_reading = FALSE; -static char cmdbuffer[256]; - -/* CmdThread - separate thread to read commands from stdin upon request */ - -static DWORD WINAPI CmdThread (LPVOID arg) -{ - for (;;) { - WaitForSingleObject(hCmdReadEvent, INFINITE); /* wait for request */ - read_line(cmdbuffer, sizeof(cmdbuffer), stdin); /* read one line */ - scp_stuffed = FALSE; /* say how we got it */ - SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */ - } - return 0; -} - -char *read_cmdline (char *ptr, int size, FILE *stream) -{ - char *cptr; - - if (hCmdThread == NULL) { /* set up command-reading thread */ - if ((hCmdReadEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) - scp_panic("Can't create command line read event"); - - if ((hCmdReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) - scp_panic("Can't create command line ready event"); - /* start up the command thread */ - if ((hCmdThread = CreateThread(NULL, 0, CmdThread, NULL, 0, &iCmdThreadID)) == NULL) - scp_panic("Unable to create command line reading thread"); - } - - scp_reading = TRUE; - - SetEvent(hCmdReadEvent); /* let read thread get one line */ - WaitForSingleObject(hCmdReadyEvent, INFINITE); /* wait for read thread or GUI to respond */ - - scp_reading = FALSE; - - strncpy(ptr, cmdbuffer, MIN(size, sizeof(cmdbuffer))); /* copy line to caller's buffer */ - - for (cptr = ptr; isspace(*cptr); cptr++) /* absorb spaces */ - ; - - if (scp_stuffed) { /* stuffed command needs to be echoed */ - printf("%s\n", cptr); - if (sim_log) fprintf(sim_log, "%s\n", cptr); - } - - return cptr; -} - -/* stuff_cmd - force a command into the read_cmdline output buffer. Called asynchronously by GUI */ - -void stuff_cmd (char *cmd) -{ - strcpy(cmdbuffer, cmd); /* save the string */ - scp_stuffed = TRUE; /* note where it came from */ - SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */ -} - -/* remark_cmd - print a remark from inside a command processor. This routine takes - * into account the possiblity that the command might have been stuffed, in which - * case the sim> prompt needs to be reprinted. - */ - -void remark_cmd (char *remark) -{ - printf("%s\n", remark); - if (sim_log) fprintf(sim_log, "%s\n", remark); - if (scp_reading) { - printf("sim> "); - if (sim_log) fprintf(sim_log, "sim> "); - } -} - -#endif // WIN32 defined -#endif // GUI_SUPPORT defined diff --git a/Ibm1130/ibm1130_prt.c b/Ibm1130/ibm1130_prt.c deleted file mode 100644 index dd3053cc..00000000 --- a/Ibm1130/ibm1130_prt.c +++ /dev/null @@ -1,773 +0,0 @@ -/* ibm1130_prt.c: IBM 1130 line printer emulation - - Based on the SIMH simulator package written by Robert M Supnik - - Brian Knittel - Revision History - 2002.09.13 - Added 1403 support. New file, taken from part of ibm1130_stddev.c - - Note: The 1403 is much faster, even in emulation, because it takes much - less CPU power to run it. DMS doesn't use the WAIT command when waiting for - printer operations to complete, so it ends up burning LOTS of cpu cycles. - The 1403 printer doesn't require as many. HOWEVER: DMS must be loaded for the 1403, - and Fortran IOCS control cards must specify it. - - The 1132 is still the default printer. - - As written, we can't have two printers. - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - */ - -#include "ibm1130_defs.h" - -/*************************************************************************************** - * 1132 PRINTER - ***************************************************************************************/ - -#define PRT1132_DSW_READ_EMITTER_RESPONSE 0x8000 -#define PRT1132_DSW_SKIP_RESPONSE 0x4000 -#define PRT1132_DSW_SPACE_RESPONSE 0x2000 -#define PRT1132_DSW_CARRIAGE_BUSY 0x1000 -#define PRT1132_DSW_PRINT_SCAN_CHECK 0x0800 -#define PRT1132_DSW_NOT_READY 0x0400 -#define PRT1132_DSW_PRINTER_BUSY 0x0200 - -#define PRT1132_DSW_CHANNEL_MASK 0x00FF /* 1132 printer DSW bits */ -#define PRT1132_DSW_CHANNEL_1 0x0080 -#define PRT1132_DSW_CHANNEL_2 0x0040 -#define PRT1132_DSW_CHANNEL_3 0x0020 -#define PRT1132_DSW_CHANNEL_4 0x0010 -#define PRT1132_DSW_CHANNEL_5 0x0008 -#define PRT1132_DSW_CHANNEL_6 0x0004 -#define PRT1132_DSW_CHANNEL_9 0x0002 -#define PRT1132_DSW_CHANNEL_12 0x0001 - -#define PRT1403_DSW_PARITY_CHECK 0x8000 /* 1403 printer DSW bits */ -#define PRT1403_DSW_TRANSFER_COMPLETE 0x4000 -#define PRT1403_DSW_PRINT_COMPLETE 0x2000 -#define PRT1403_DSW_CARRIAGE_COMPLETE 0x1000 -#define PRT1403_DSW_RING_CHECK 0x0400 -#define PRT1403_DSW_SYNC_CHECK 0x0200 -#define PRT1403_DSW_CH9 0x0010 -#define PRT1403_DSW_CH12 0x0008 -#define PRT1403_DSW_CARRIAGE_BUSY 0x0004 -#define PRT1403_DSW_PRINTER_BUSY 0x0002 -#define PRT1403_DSW_NOT_READY 0x0001 - -#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT) - -static t_stat prt1132_svc(UNIT *uptr); -static t_stat prt1403_svc(UNIT *uptr); -static t_stat prt_svc (UNIT *uptr); -static t_stat prt_reset (DEVICE *dptr); -static t_stat prt_attach (UNIT *uptr, char *cptr); -static t_stat prt_detach (UNIT *uptr); - -static int16 PRT_DSW = 0; /* device status word */ -static int32 prt_swait = 500; /* line skip wait */ -static int32 prt_cwait = 1250; /* character rotation wait */ -static int32 prt_fwait = 100; /* fast wait, for 1403 operations */ -static int32 prt_twait = 50; /* transfer wait, for 1403 operations */ -#define SKIPTARGET (uptr->u4) /* target for skip operation */ - -#define UNIT_V_FORMCHECK (UNIT_V_UF + 0) /* out of paper error */ -#define UNIT_V_DATACHECK (UNIT_V_UF + 1) /* printer overrun error */ -#define UNIT_V_SKIPPING (UNIT_V_UF + 2) /* printer skipping */ -#define UNIT_V_SPACING (UNIT_V_UF + 3) /* printer is spacing */ -#define UNIT_V_PRINTING (UNIT_V_UF + 4) /* printer printing */ -#define UNIT_V_TRANSFERRING (UNIT_V_UF + 5) /* unit is transferring print buffer (1403 only) */ -#define UNIT_V_1403 (UNIT_V_UF + 6) /* printer model is 1403 rather than 1132 */ -#define UNIT_V_PARITYCHECK (UNIT_V_UF + 7) /* error flags for 1403 */ -#define UNIT_V_RINGCHECK (UNIT_V_UF + 8) -#define UNIT_V_SYNCCHECK (UNIT_V_UF + 9) - -#define UNIT_FORMCHECK (1u << UNIT_V_FORMCHECK) -#define UNIT_DATACHECK (1u << UNIT_V_DATACHECK) -#define UNIT_SKIPPING (1u << UNIT_V_SKIPPING) -#define UNIT_SPACING (1u << UNIT_V_SPACING) -#define UNIT_PRINTING (1u << UNIT_V_PRINTING) -#define UNIT_TRANSFERRING (1u << UNIT_V_TRANSFERRING) -#define UNIT_1403 (1u << UNIT_V_1403) -#define UNIT_PARITYCHECK (1u << UNIT_V_PARITYCHECK) -#define UNIT_RINGCHECK (1u << UNIT_V_RINGCHECK) -#define UNIT_SYNCCHECK (1u << UNIT_V_SYNCCHECK) - -UNIT prt_unit[] = { - { UDATA (&prt_svc, UNIT_ATTABLE, 0) }, -}; - -#define IS_1403(uptr) (uptr->flags & UNIT_1403) /* model test */ -#define IS_1132(uptr) ((uptr->flags & UNIT_1403) == 0) /* model test */ - -/* Parameter in the unit descriptor (1132 printer) */ - -#define CMD_NONE 0 -#define CMD_SPACE 1 -#define CMD_SKIP 2 -#define CMD_PRINT 3 - -REG prt_reg[] = { - { HRDATA (PRTDSW, PRT_DSW, 16) }, /* device status word */ - { DRDATA (STIME, prt_swait, 24), PV_LEFT }, /* line skip wait */ - { DRDATA (CTIME, prt_cwait, 24), PV_LEFT }, /* character rotation wait */ - { DRDATA (CTIME, prt_fwait, 24), PV_LEFT }, /* 1403 fast wait */ - { DRDATA (CTIME, prt_twait, 24), PV_LEFT }, /* 1403 transfer wait */ - { NULL } }; - -MTAB prt_mod[] = { - { UNIT_1403, 0, "1132", "1132", NULL }, /* model option */ - { UNIT_1403, UNIT_1403, "1403", "1403", NULL }, - { 0 } }; - -DEVICE prt_dev = { - "PRT", prt_unit, prt_reg, prt_mod, - 1, 16, 16, 1, 16, 16, - NULL, NULL, &prt_reset, - NULL, prt_attach, prt_detach}; - -#define PRT_COLUMNS 120 -#define PRT_ROWLEN 120 -#define MAX_OVPRINT 20 - -static char prtbuf[PRT_ROWLEN*MAX_OVPRINT]; -static int nprint[PRT_COLUMNS], ncol[MAX_OVPRINT], maxnp; -static int prt_nchar, prt_row; /* current printwheel position, current page row */ -static int prt_nnl; /* number of queued newlines */ - -#define CC_CHANNEL_1 0x0800 /* carriage control tape punch values */ -#define CC_CHANNEL_2 0x0400 -#define CC_CHANNEL_3 0x0200 -#define CC_CHANNEL_4 0x0100 -#define CC_CHANNEL_5 0x0080 -#define CC_CHANNEL_6 0x0040 /* 7, 8, 10 and 11 are not used on 1132 printer */ -#define CC_CHANNEL_7 0x0020 -#define CC_CHANNEL_8 0x0010 -#define CC_CHANNEL_9 0x0008 -#define CC_CHANNEL_10 0x0004 -#define CC_CHANNEL_11 0x0002 -#define CC_CHANNEL_12 0x0001 - -#define CC_1403_BITS 0x0FFF /* all bits for 1403, most for 1132 */ -#define CC_1132_BITS (CC_1403_BITS & ~(CC_CHANNEL_7|CC_CHANNEL_8|CC_CHANNEL_10|CC_CHANNEL_11)) - -#define PRT_PAGELENGTH 66 - -static int cctape[PRT_PAGELENGTH]; /* standard carriage control tape */ - -static struct tag_ccpunches { /* list of rows and punches on tape */ - int row, channels; -} -ccpunches[] = { - 2, CC_CHANNEL_1, // channel 1 = top of form - 62, CC_CHANNEL_12 // channel 12 = bottom of form -}, -cccgi[] = { - 2, CC_CHANNEL_1 // channel 1 = top of form; no bottom of form -}; - -#include "ibm1130_prtwheel.h" - -// cc_format_1132 and cc_format_1403 - turn cctape bits into proper format for DSW or status read - -static int cc_format_1132 (int bits) -{ - return ((bits & (CC_CHANNEL_1|CC_CHANNEL_2|CC_CHANNEL_3|CC_CHANNEL_4|CC_CHANNEL_5|CC_CHANNEL_6)) >> 4) | - ((bits & CC_CHANNEL_9) >> 3) | - (bits & CC_CHANNEL_12); -} - -#define cc_format_1403(bits) (bits) - -// reset_prt_line - clear the print line following paper advancement - -static void reset_prt_line (void) -{ - memset(nprint, 0, sizeof(nprint)); - memset(ncol, 0, sizeof(ncol)); - maxnp = 0; -} - -// save_1132_prt_line - fire hammers for character 'ch' - -static t_bool save_1132_prt_line (int ch) -{ - int i, r, addr = 32; - int32 mask = 0, wd = 0; - - for (i = 0; i < PRT_COLUMNS; i++) { - if (mask == 0) { // fetch next word from memory - mask = 0x8000; - wd = M[addr++]; - } - - if (wd & mask) { // hammer is to fire in this column - if ((r = nprint[i]) < MAX_OVPRINT) { - if (ncol[r] <= i) { // we haven't moved this far yet - if (ncol[r] == 0) // first char in this row? - memset(prtbuf+r*PRT_ROWLEN, ' ', PRT_COLUMNS); // blank out the new row - ncol[r] = i+1; // remember new row length - } - prtbuf[r*PRT_ROWLEN + i] = (char) ch; // save the character - - nprint[i]++; // remember max overprintings for this column - maxnp = MAX(maxnp, nprint[i]); - } - } - - mask >>= 1; // prepare to examine next bit - } - - return wd & 1; // return TRUE if the last word has lsb set, which means all bits had been set -} - -// write_line - write collected line to output file. No need to trim spaces as the hammers -// are never fired for them, so ncol[r] is the last printed position on each line. - -static void newpage (FILE *fd) -{ - if (cgi) - fputs("
\n", fd); - else - putc('\f', fd); // formfeed -} - -static void flush_prt_line (FILE *fd, int spacemode) -{ - int r; - - if (! (spacemode || maxnp)) // nothing to do - return; - - prt_row = (prt_row+1) % PRT_PAGELENGTH; // NEXT line - - if (spacemode && ! maxnp) { // spacing only - if (prt_row == 0 && prt_nnl) { -#ifdef WIN32 - if (! cgi) - putc('\r', fd); // DOS/Windows: end with cr/lf -#endif - putc('\n', fd); // otherwise end with lf - if (spacemode & UNIT_SKIPPING) // add formfeed if we crossed page boundary while skipping - newpage(fd); - prt_nnl = 0; - } - else - prt_nnl++; - - return; - } - - if (prt_nnl) { // there are queued newlines -// if we spaced to top of form, don't emit formfeed. We'd only ever emit the formfeed if we skipped via control tape channels -// if (prt_row == 0 && prt_nnl) { // we spaced to top of form -//#ifdef WIN32 -// if (! cgi) -// putc('\r', fd); // DOS/Windows: end with cr/lf -//#endif -// putc('\n', fd); // otherwise end with lf -// newpage(fd); -// prt_nnl = 0; -// } -// else { - while (prt_nnl > 0) { // spit out queued newlines -#ifdef WIN32 - if (! cgi) - putc('\r', fd); // DOS/Windows: end with cr/lf -#endif - putc('\n', fd); // otherwise end with lf - prt_nnl--; - } -// } - } - - for (r = 0; r < maxnp; r++) { - if (r > 0) - putc('\r', fd); // carriage return between overprinted lines - fxwrite(&prtbuf[r*PRT_ROWLEN], 1, ncol[r], fd); - } - - reset_prt_line(); - - prt_nnl++; // queue a newline -} - -// 1132 printer commands - -#define PRT_CMD_START_PRINTER 0x0080 -#define PRT_CMD_STOP_PRINTER 0x0040 -#define PRT_CMD_START_CARRIAGE 0x0004 -#define PRT_CMD_STOP_CARRIAGE 0x0002 -#define PRT_CMD_SPACE 0x0001 - -#define PRT_CMD_MASK 0x00C7 - -extern char * saywhere (int addr); - -static void mytrace (int start, char *what) -{ - char *where; - - if ((where = saywhere(prev_IAR)) == NULL) where = "?"; - trace_io("%s %s at %04x: %s\n", start ? "start" : "stop", what, prev_IAR, where); -} - -/* xio_1132_printer - XIO command interpreter for the 1132 printer */ - -void xio_1132_printer (int32 iocc_addr, int32 func, int32 modify) -{ - char msg[80]; - UNIT *uptr = &prt_unit[0]; - - switch (func) { - case XIO_READ: - M[iocc_addr & mem_mask] = codewheel1132[prt_nchar].ebcdic << 8; - - if ((uptr->flags & UNIT_PRINTING) == 0) /* if we're not printing, advance this after every test */ - prt_nchar = (prt_nchar + 1) % WHEELCHARS_1132; - break; - - case XIO_SENSE_DEV: - ACC = PRT_DSW; - if (modify & 0x01) { /* reset interrupts */ - CLRBIT(PRT_DSW, PRT1132_DSW_READ_EMITTER_RESPONSE | PRT1132_DSW_SKIP_RESPONSE | PRT1132_DSW_SPACE_RESPONSE); - CLRBIT(ILSW[1], ILSW_1_1132_PRINTER); - } - break; - - case XIO_CONTROL: - if (modify & PRT_CMD_START_PRINTER) { - SETBIT(uptr->flags, UNIT_PRINTING); -// mytrace(1, "printing"); - } - - if (modify & PRT_CMD_STOP_PRINTER) { - CLRBIT(uptr->flags, UNIT_PRINTING); -// mytrace(0, "printing"); - } - - if (modify & PRT_CMD_START_CARRIAGE) { - SETBIT(uptr->flags, UNIT_SKIPPING); -// mytrace(1, "skipping"); - } - - if (modify & PRT_CMD_STOP_CARRIAGE) { - CLRBIT(uptr->flags, UNIT_SKIPPING); -// mytrace(0, "skipping"); - } - - if (modify & PRT_CMD_SPACE) { - SETBIT(uptr->flags, UNIT_SPACING); -// mytrace(1, "space"); - } - - sim_cancel(uptr); - if (uptr->flags & (UNIT_SKIPPING|UNIT_SPACING|UNIT_PRINTING)) { // busy bits = doing something - SETBIT(PRT_DSW, PRT1132_DSW_PRINTER_BUSY); - sim_activate(uptr, prt_cwait); - } - else - CLRBIT(PRT_DSW, PRT1132_DSW_PRINTER_BUSY); - - if (uptr->flags & (UNIT_SKIPPING|UNIT_SPACING)) - SETBIT(PRT_DSW, PRT1132_DSW_CARRIAGE_BUSY); - else - CLRBIT(PRT_DSW, PRT1132_DSW_CARRIAGE_BUSY); - - if ((uptr->flags & (UNIT_SKIPPING|UNIT_SPACING)) == (UNIT_SKIPPING|UNIT_SPACING)) { - sprintf(msg, "1132 printer skip and space at same time?"); - xio_error(msg); - } - break; - - default: - sprintf(msg, "Invalid 1132 printer XIO function %x", func); - xio_error(msg); - } -} - -#define SET_ACTION(u,a) {(u)->flags &= ~(UNIT_SKIPPING|UNIT_SPACING|UNIT_PRINTING|UNIT_TRANSFERRING); (u)->flags |= a;} - -static t_stat prt_svc (UNIT *uptr) -{ - return IS_1403(uptr) ? prt1403_svc(uptr) : prt1132_svc(uptr); -} - -// prt1132_svc - emulated timeout for 1132 operation - -static t_stat prt1132_svc (UNIT *uptr) -{ - if (PRT_DSW & PRT1132_DSW_NOT_READY) { // cancel operation if printer went offline - SETBIT(uptr->flags, UNIT_FORMCHECK); - SET_ACTION(uptr, 0); - forms_check(TRUE); // and turn on forms check lamp - return SCPE_OK; - } - - if (uptr->flags & UNIT_SPACING) { - flush_prt_line(uptr->fileref, UNIT_SPACING); - - CLRBIT(PRT_DSW, PRT1132_DSW_CHANNEL_MASK|PRT1132_DSW_PRINTER_BUSY|PRT1132_DSW_CARRIAGE_BUSY); - SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row]) | PRT1132_DSW_SPACE_RESPONSE); - SETBIT(ILSW[1], ILSW_1_1132_PRINTER); - CLRBIT(uptr->flags, UNIT_SPACING); // done with this - calc_ints(); - } - - if (uptr->flags & UNIT_SKIPPING) { - do { - flush_prt_line(uptr->fileref, UNIT_SKIPPING); - CLRBIT(PRT_DSW, PRT1132_DSW_CHANNEL_MASK); - SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row])); - } while ((cctape[prt_row] & CC_1132_BITS) == 0); // slew directly to a cc tape punch - - SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row]) | PRT1132_DSW_SKIP_RESPONSE); - SETBIT(ILSW[1], ILSW_1_1132_PRINTER); - calc_ints(); - } - - if (uptr->flags & UNIT_PRINTING) { - if (! save_1132_prt_line(codewheel1132[prt_nchar].ascii)) { // save previous printed line - SETBIT(uptr->flags, UNIT_DATACHECK); // buffer wasn't set in time - SET_ACTION(uptr, 0); - print_check(TRUE); // and turn on forms check lamp - return SCPE_OK; - } - - prt_nchar = (prt_nchar + 1) % WHEELCHARS_1132; // advance print drum - - SETBIT(PRT_DSW, PRT1132_DSW_READ_EMITTER_RESPONSE); // issue interrupt to tell printer to set buffer - SETBIT(ILSW[1], ILSW_1_1132_PRINTER); // we'll save the printed stuff just before next emitter response (later than on real 1130) - calc_ints(); - } - - if (uptr->flags & (UNIT_SPACING|UNIT_SKIPPING|UNIT_PRINTING)) { // still doing something - SETBIT(PRT_DSW, PRT1132_DSW_PRINTER_BUSY); - sim_activate(uptr, prt_cwait); - } - else - CLRBIT(PRT_DSW, PRT1132_DSW_PRINTER_BUSY); - - return SCPE_OK; -} - -void save_1403_prt_line (int32 addr) -{ - int i, j, r, ch, even = TRUE; - unsigned char ebcdic; - int32 wd; - - for (i = 0; i < PRT_COLUMNS; i++) { - if (even) { // fetch next word from memory - wd = M[addr++]; - ebcdic = (unsigned char) ((wd >> 8) & 0x7F); - even = FALSE; - } - else { - ebcdic = (unsigned char) (wd & 0x7F); // use low byte of previously fetched word - even = TRUE; - } - - ch = ' '; // translate ebcdic to ascii. Don't bother checking for parity errors - for (j = 0; j < WHEELCHARS_1403; j++) { - if (codewheel1403[j].ebcdic == ebcdic) { - ch = codewheel1403[j].ascii; - break; - } - } - - if (ch > ' ') { - if ((r = nprint[i]) < MAX_OVPRINT) { - if (ncol[r] <= i) { // we haven't moved this far yet - if (ncol[r] == 0) // first char in this row? - memset(prtbuf+r*PRT_ROWLEN, ' ', PRT_COLUMNS); // blank out the new row - ncol[r] = i+1; // remember new row length - } - prtbuf[r*PRT_ROWLEN + i] = (char) ch; // save the character - - nprint[i]++; // remember max overprintings for this column - maxnp = MAX(maxnp, nprint[i]); - } - } - } -} - -void xio_1403_printer (int32 iocc_addr, int32 func, int32 modify) -{ - UNIT *uptr = &prt_unit[0]; - - switch (func) { - case XIO_INITW: /* print a line */ - save_1403_prt_line(iocc_addr); /* put formatted line into our print buffer */ - - SETBIT(uptr->flags, UNIT_TRANSFERRING); /* schedule transfer complete interrupt */ - SETBIT(PRT_DSW, PRT1403_DSW_PRINTER_BUSY); - sim_activate(uptr, prt_twait); - break; - - case XIO_CONTROL: /* initiate single space */ - if (uptr->flags & UNIT_SKIPPING) { - xio_error("1403 printer skip and space at same time?"); - } - else { - SETBIT(uptr->flags, UNIT_SPACING); - SETBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY); - sim_activate(uptr, prt_fwait); - } - break; - - case XIO_WRITE: /* initiate skip */ - if (uptr->flags & UNIT_SPACING) { - xio_error("1403 printer skip and space at same time?"); - } - else { - SETBIT(uptr->flags, UNIT_SKIPPING); - SKIPTARGET = ReadW(iocc_addr) & CC_1403_BITS; /* get CC bits that we're to match */ - SETBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY); - sim_activate(uptr, prt_fwait); - } - break; - - case XIO_SENSE_DEV: /* get device status word */ - ACC = PRT_DSW; - if (modify & 0x01) { /* reset interrupts */ - CLRBIT(PRT_DSW, PRT1403_DSW_PARITY_CHECK | PRT1403_DSW_TRANSFER_COMPLETE | - PRT1403_DSW_PRINT_COMPLETE | PRT1403_DSW_CARRIAGE_COMPLETE | - PRT1403_DSW_RING_CHECK | PRT1403_DSW_SYNC_CHECK); - CLRBIT(ILSW[4], ILSW_4_1403_PRINTER); - } - break; - } -} - -static t_stat prt1403_svc(UNIT *uptr) -{ - if (PRT_DSW & PRT1403_DSW_NOT_READY) { // cancel operation if printer went offline - SET_ACTION(uptr, 0); - forms_check(TRUE); // and turn on forms check lamp - } - else if (uptr->flags & UNIT_TRANSFERRING) { // end of transfer - CLRBIT(uptr->flags, UNIT_TRANSFERRING); - SETBIT(uptr->flags, UNIT_PRINTING); // schedule "print complete" - - SETBIT(PRT_DSW, PRT1403_DSW_TRANSFER_COMPLETE); // issue transfer complete interrupt - SETBIT(ILSW[4], ILSW_4_1403_PRINTER); - } - else if (uptr->flags & UNIT_PRINTING) { - CLRBIT(uptr->flags, UNIT_PRINTING); - CLRBIT(PRT_DSW, PRT1403_DSW_PRINTER_BUSY); - - SETBIT(PRT_DSW, PRT1403_DSW_PRINT_COMPLETE); - SETBIT(ILSW[4], ILSW_4_1403_PRINTER); // issue print complete interrupt - } - else if (uptr->flags & UNIT_SKIPPING) { - do { // find line with exact match of tape punches - flush_prt_line(uptr->fileref, UNIT_SKIPPING); - } while (cctape[prt_row] != SKIPTARGET); // slew directly to requested cc tape punch - - CLRBIT(uptr->flags, UNIT_SKIPPING); // done with this - CLRBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY); - - SETBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_COMPLETE); - SETBIT(ILSW[4], ILSW_4_1403_PRINTER); - } - else if (uptr->flags & UNIT_SPACING) { - flush_prt_line(uptr->fileref, UNIT_SPACING); - - CLRBIT(uptr->flags, UNIT_SPACING); // done with this - CLRBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY); - - SETBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_COMPLETE); - SETBIT(ILSW[4], ILSW_4_1403_PRINTER); - } - - if (uptr->flags & (UNIT_PRINTING|UNIT_SKIPPING|UNIT_SPACING|UNIT_TRANSFERRING)) - sim_activate(uptr, prt_fwait); - - CLRBIT(PRT_DSW, PRT1403_DSW_CH9|PRT1403_DSW_CH12); // set the two CC bits in the DSW - if (cctape[prt_row] & CC_CHANNEL_9) - SETBIT(PRT_DSW, PRT1403_DSW_CH9); - if (cctape[prt_row] & CC_CHANNEL_12) - SETBIT(PRT_DSW, PRT1403_DSW_CH12); - - calc_ints(); - return SCPE_OK; -} - -/* delete_cmd - SCP command to delete a file */ - -static t_stat delete_cmd (int flag, char *cptr) -{ - char gbuf[CBUFSIZE]; - int status; - - cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ - if (*gbuf == 0) return SCPE_2FARG; - if (*cptr != 0) return SCPE_2MARG; /* now eol? */ - - status = unlink(gbuf); /* delete the file */ - - if (status != 0 && errno != ENOENT) /* print message if failed and file exists */ - perror(gbuf); - - return SCPE_OK; -} - -/* prt_reset - reset emulated printer */ - -static t_stat prt_reset (DEVICE *dptr) -{ - UNIT *uptr = &prt_unit[0]; - int i; - -// add a DELETE filename command so we can be sure to have clean listings - register_cmd("DELETE", &delete_cmd, 0, "del{ete} filename remove file\n"); - - sim_cancel(uptr); - - memset(cctape, 0, sizeof(cctape)); // copy punch list into carriage control tape image - - if (cgi) - for (i = 0; i < (sizeof(cccgi)/sizeof(cccgi[0])); i++) - cctape[cccgi[i].row-1] |= cccgi[i].channels; - else - for (i = 0; i < (sizeof(ccpunches)/sizeof(ccpunches[0])); i++) - cctape[ccpunches[i].row-1] |= ccpunches[i].channels; - - prt_nchar = 0; - prt_row = 0; - prt_nnl = 0; - - CLRBIT(uptr->flags, UNIT_FORMCHECK|UNIT_DATACHECK|UNIT_PRINTING|UNIT_SPACING|UNIT_SKIPPING| - UNIT_TRANSFERRING|UNIT_PARITYCHECK|UNIT_RINGCHECK|UNIT_SYNCCHECK); - - if (IS_1132(uptr)) { - CLRBIT(ILSW[1], ILSW_1_1132_PRINTER); - PRT_DSW = cc_format_1132(cctape[prt_row]); - if (! IS_ONLINE(uptr)) - SETBIT(PRT_DSW, PRT1132_DSW_NOT_READY); - } - else { - CLRBIT(ILSW[4], ILSW_4_1403_PRINTER); - PRT_DSW = 0; - if (cctape[prt_row] & CC_CHANNEL_9) - SETBIT(PRT_DSW, PRT1403_DSW_CH9); - if (cctape[prt_row] & CC_CHANNEL_12) - SETBIT(PRT_DSW, PRT1403_DSW_CH12); - if (! IS_ONLINE(uptr)) - SETBIT(PRT_DSW, PRT1403_DSW_NOT_READY); - } - - SET_ACTION(uptr, 0); - calc_ints(); - reset_prt_line(); - - forms_check(FALSE); - return SCPE_OK; -} - -static t_stat prt_attach (UNIT *uptr, char *cptr) -{ - t_stat rval; - /* assume failure */ - SETBIT(PRT_DSW, IS_1132(uptr) ? PRT1132_DSW_NOT_READY : PRT1403_DSW_NOT_READY); - - if (uptr->flags & UNIT_ATT) { - if ((rval = prt_detach(uptr)) != SCPE_OK) { - return rval; - } - } - - sim_cancel(uptr); - - if (strcmp(cptr, "-") == 0) { /* connect printer to stdout */ - if (uptr -> flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ - uptr->filename = calloc(CBUFSIZE, sizeof(char)); - strcpy(uptr->filename, "(stdout)"); - uptr->fileref = stdout; - SETBIT(uptr->flags, UNIT_ATT); - uptr->pos = 0; - } - else if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) { - return rval; - } - - fseek(uptr->fileref, 0, SEEK_END); /* if we opened an existing file, append to it */ - - if (IS_1132(uptr)) { - CLRBIT(ILSW[1], ILSW_1_1132_PRINTER); - CLRBIT(uptr->flags, UNIT_FORMCHECK|UNIT_DATACHECK); - } - else { - CLRBIT(ILSW[4], ILSW_4_1403_PRINTER); - CLRBIT(uptr->flags, UNIT_PARITYCHECK|UNIT_RINGCHECK|UNIT_SYNCCHECK); - } - - SET_ACTION(uptr, 0); - calc_ints(); - - prt_nchar = 0; - prt_nnl = 0; - prt_row = 0; - reset_prt_line(); - - if (IS_1132(uptr)) { - PRT_DSW = (PRT_DSW & ~PRT1132_DSW_CHANNEL_MASK) | cc_format_1132(cctape[prt_row]); - - if (IS_ONLINE(uptr)) - CLRBIT(PRT_DSW, PRT1132_DSW_NOT_READY); - } - else { - CLRBIT(PRT_DSW, PRT1403_DSW_CH9 | PRT1403_DSW_CH12); - if (cctape[prt_row] & CC_CHANNEL_9) - SETBIT(PRT_DSW, PRT1403_DSW_CH9); - if (cctape[prt_row] & CC_CHANNEL_12) - SETBIT(PRT_DSW, PRT1403_DSW_CH12); - - if (IS_ONLINE(uptr)) - CLRBIT(PRT_DSW, PRT1132_DSW_NOT_READY); - } - - forms_check(FALSE); - return SCPE_OK; -} - -static t_stat prt_detach (UNIT *uptr) -{ - t_stat rval; - - flush_prt_line(uptr->fileref, TRUE); - - if (uptr->fileref == stdout) { - CLRBIT(uptr->flags, UNIT_ATT); - free(uptr->filename); - uptr->filename = NULL; - } - else if ((rval = detach_unit(uptr)) != SCPE_OK) - return rval; - - sim_cancel(uptr); - - if (IS_1132(uptr)) { - CLRBIT(ILSW[1], ILSW_1_1132_PRINTER); - CLRBIT(uptr->flags, UNIT_FORMCHECK|UNIT_DATACHECK); - SETBIT(PRT_DSW, PRT1132_DSW_NOT_READY); - } - else { - CLRBIT(ILSW[4], ILSW_4_1403_PRINTER); - SETBIT(PRT_DSW, PRT1403_DSW_NOT_READY); - } - SET_ACTION(uptr, 0); - - calc_ints(); - - forms_check(FALSE); - return SCPE_OK; -} diff --git a/Ibm1130/ibm1130_prtwheel.h b/Ibm1130/ibm1130_prtwheel.h deleted file mode 100644 index c39c1e59..00000000 --- a/Ibm1130/ibm1130_prtwheel.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -struct tag_codewheel { - unsigned char ascii; - unsigned char ebcdic; -}; - -static struct tag_codewheel codewheel1132[] = -{ /* characters and EBCDIC codes in printwheel order */ - 'A', 0xC1, - 'B', 0xC2, - 'C', 0xC3, - 'D', 0xC4, - 'F', 0xC6, - 'H', 0xC8, - 'I', 0xC9, - 'S', 0xE2, - 'T', 0xE3, - 'U', 0xE4, - 'V', 0xE5, - '1', 0xF1, - '2', 0xF2, - '3', 0xF3, - '4', 0xF4, - '5', 0xF5, - '6', 0xF6, - '7', 0xF7, - '8', 0xF8, - '9', 0xF9, - '0', 0xF0, - '=', 0x7E, - '$', 0x5B, - '.', 0x4B, - '\'', 0x7D, - ',', 0x6B, - ')', 0x5D, - '-', 0x60, - '(', 0x4D, - '+', 0x4E, - '/', 0x61, - '*', 0x5C, - '&', 0x50, - 'J', 0xD1, - 'K', 0xD2, - 'L', 0xD3, - 'M', 0xD4, - 'N', 0xD5, - 'O', 0xD6, - 'P', 0xD7, - 'Q', 0xD8, - 'R', 0xD9, - 'E', 0xC5, - 'G', 0xC7, - 'W', 0xE6, - 'X', 0xE7, - 'Y', 0xE8, - 'Z', 0xE9, -}; - -#define WHEELCHARS_1132 (sizeof(codewheel1132)/sizeof(codewheel1132[0])) - -static struct tag_codewheel codewheel1403[] = -{ - 'A', 0x64, - 'B', 0x25, - 'C', 0x26, - 'D', 0x67, - 'E', 0x68, - 'F', 0x29, - 'G', 0x2A, - 'H', 0x6B, - 'I', 0x2C, - 'J', 0x58, - 'K', 0x19, - 'L', 0x1A, - 'M', 0x5B, - 'N', 0x1C, - 'O', 0x5D, - 'P', 0x5E, - 'Q', 0x1F, - 'R', 0x20, - 'S', 0x0D, - 'T', 0x0E, - 'U', 0x4F, - 'V', 0x10, - 'W', 0x51, - 'X', 0x52, - 'Y', 0x13, - 'Z', 0x54, - '0', 0x49, - '1', 0x40, - '2', 0x01, - '3', 0x02, - '4', 0x43, - '5', 0x04, - '6', 0x45, - '7', 0x46, - '8', 0x07, - '9', 0x08, - ' ', 0x7F, - '.', 0x6E, - '(', 0x57, - '+', 0x6D, - '&', 0x15, - '$', 0x62, - '*', 0x23, - ')', 0x2F, - '-', 0x61, - '/', 0x4C, - ',', 0x16, - '\'', 0x0B, - '=', 0x4A, -}; - -#define WHEELCHARS_1403 (sizeof(codewheel1403)/sizeof(codewheel1403[0])) - - diff --git a/Ibm1130/ibm1130_stddev.c b/Ibm1130/ibm1130_stddev.c deleted file mode 100644 index 0cc477d4..00000000 --- a/Ibm1130/ibm1130_stddev.c +++ /dev/null @@ -1,1274 +0,0 @@ -/* ibm1130_stddev.c: IBM 1130 standard I/O devices simulator - - Based on the SIMH simulator package written by Robert M Supnik - - Brian Knittel - - Revision History: - 2003.06.15 - added output translation code to accomodate APL font - added input translation feature to assist emulation of 1130 console keyboard for APL - changes to console input and output IO emulation, fixed bugs exposed by APL interpreter - - 2002.09.13 - pulled 1132 printer out of this file into ibm1130_prt.c - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - * - * Notes about overstrike mapping: - * The 1130 console printer used a Selectric typewriter element. The APL interpreter - * used overprinting to construct some APL symbols, for example, a round O overstruck] - * with | to get the greek phi. This doesn't accomodate a glass terminal! Instead, - * modern APL fonts have separate character codes for the complex characters. - * To have APL\1130 output appear correctly, we have to do three things: - * - * use simh's telnet feature to connect to the 1130 console stream - * have the telnet program use an APL font - * detect combinations of overstruck symbols, and generate the approrpiate alternate codes. - * - * There is a built-in table of font mappings and overstrike mappings, for the APLPLUS.TTF - * truetype font widely available on the Internet. An font descriptor file can be used - * to specify alternate mappings. - * - * The APL font codes and overstrike mapping can be enabled with the simh command - * - * set tto apl - * - * and disabled with - * - * set tto ascii (this is the default) - * - * APL also uses the red and black ribbon selection. The emulator will output - * ansi red/black foreground commands with the setting - * - * set tto ansi - * - * The codes can be disabled with - * - * set tto noansi (this is the default) - * - * Finally, when APL mode is active, the emulator does some input key translations - * to let the standard ASCII keyboard more closely match the physical layout of the - * 1130 console keyboard. The numeric and punctuation key don't have their - * traditional meaning under APL. The input mapping lets you use the APL keyboard - * layout shown in the APL documentation. - * - * The translations are: - * FROM - * ASCII Position on keyboard To 1130 Key APL interpretation - * ------------------------------------ -------------------------------- - * [ (key to right of P) \r Enter left arrow - * ; (1st key to right of L) \b Backspace [ - * ' (2nd key to right of L) ^U Erase Fld ] - * 2 (key above Q) @ @ up shift - * 3 (key above W) % % up right shift - * 4 (key above E) * * + - * 5 (key above R) < < multiply - * 8 (key above U) - - Return - * 9 (key above I) / / Backspace - * - (key above P) ^Q INT REQ ATTN - * Enter - - Return - * backsp / / Backspace - */ - -#include "ibm1130_defs.h" -#include - -/* #define DEBUG_CONSOLE */ - -/* ---------------------------------------------------------------------------- */ - -static void badio (char *dev) -{ -// the real 1130 just ignores attempts to use uninstalled devices. They get tested -// at times, so it's best to be quiet about this -// printf("%s I/O is not yet supported", dev); -// wait_state = WAIT_INVALID_OP; -} - -void xio_1134_papertape (int32 addr, int32 func, int32 modify) {badio("papertape");} -void xio_1627_plotter (int32 addr, int32 func, int32 modify) {badio("plotter");} -void xio_1231_optical (int32 addr, int32 func, int32 modify) {badio("optical mark");} -void xio_2501_card (int32 addr, int32 func, int32 modify) {badio("2501 card");} -void xio_1131_synch (int32 addr, int32 func, int32 modify) {badio("SCA");} -void xio_system7 (int32 addr, int32 func, int32 modify) {badio("System 7");} - -/* ---------------------------------------------------------------------------- */ - -#define MAX_OUTPUT_COLUMNS 100 /* width of 1130 console printer */ -#define MAX_OS_CHARS 4 /* maximum number of overstruck characters that can be mapped */ -#define MAX_OS_MAPPINGS 100 /* maximum number of overstrike mappings */ - -typedef struct tag_os_map { /* os_map = overstrike mapping */ - int ch; /* ch = output character */ - int nin; /* nin = number of overstruck characters */ - unsigned char inlist[MAX_OS_CHARS]; /* inlist = overstruck ASCII characters, sorted. NOT NULL TERMINATED */ -} OS_MAP; - -extern UNIT *sim_clock_queue; -extern int cgi; - -static int32 tti_dsw = 0; /* device status words */ -static int32 tto_dsw = 0; -static int32 con_dsw = 0; - -static unsigned char conout_map[256]; /* 1130 console code to ASCII translation. 0 = undefined, 0xFF = IGNR_ = no output */ -static unsigned char conin_map[256]; /* input mapping */ -static int curcol = 0; /* current typewriter element column, leftmost = 0 */ -static int maxcol = 0; /* highest curcol seen in this output line */ -static char black_ribbon[30]; /* output escape sequence for black ribbon shift */ -static char red_ribbon[30]; /* output escape sequence for red ribbon shift */ - -static OS_MAP os_buf[MAX_OUTPUT_COLUMNS]; /* current typewriter output line, holds character struck in each column */ -static OS_MAP os_map[MAX_OS_MAPPINGS]; /* overstrike mapping entries */ -static int n_os_mappings; /* number of overstrike mappings */ - -static t_stat tti_svc(UNIT *uptr); -static t_stat tto_svc(UNIT *uptr); -static t_stat tti_reset(DEVICE *dptr); -static t_stat tto_reset(DEVICE *dptr); - -static t_stat emit_conout_character(int ch); -static t_stat map_conout_character(int ch); -static void reset_mapping (void); -static void set_conout_mapping(int32 flags); -static t_stat validate_conout_mapping(UNIT *uptr, int32 match, char *cvptr, void *desc); -static void set_default_mapping(int32 flags); -static void finish_conout_mapping(int32 flags); -static void strsort (int n, unsigned char *s); /* sorts an array of n characters */ -static int os_map_comp (OS_MAP *a, OS_MAP *b); /* compares two mapping entries */ -static t_stat font_cmd(int32 flag, char *cptr); /* handles font command */ -static void read_map_file(FILE *fd); /* reads a font map file */ -static t_bool str_match(char *str, char *keyword); /* keyword/string comparison */ -static char * handle_map_ansi_definition(char **pc); /* input line parsers for map file sections */ -static char * handle_map_input_definition(char **pc); -static char * handle_map_output_definition(char **pc); -static char * handle_map_overstrike_definition(char **pc); - -extern t_stat sim_poll_kbd(void); -extern t_stat sim_wait_kbd(void); -extern t_stat sim_putchar(int32 out); - -#define UNIT_V_CSET (UNIT_V_UF + 0) /* user flag: character set */ -#define UNIT_V_LOCKED (UNIT_V_UF + 2) /* user flag: keyboard locked */ -#define UNIT_V_ANSI (UNIT_V_UF + 3) - -#define CSET_ASCII (0u << UNIT_V_CSET) -#define CSET_1130 (1u << UNIT_V_CSET) -#define CSET_APL (2u << UNIT_V_CSET) -#define CSET_MASK (3u << UNIT_V_CSET) -#define ENABLE_ANSI (1u << UNIT_V_ANSI) - -#define KEYBOARD_LOCKED (1u << UNIT_V_LOCKED) - -#define IRQ_KEY 0x11 /* ctrl-Q */ -#define PROGRAM_STOP_KEY 0x10 /* ctrl-P */ - -#include "ibm1130_conout.h" /* conout_to_ascii table */ -#include "ibm1130_conin.h" /* ascii_to_conin table */ - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit descriptor - tti_reg TTI register list -*/ - -UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }; - -REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, 16) }, - { ORDATA (DSW, tti_dsw, 16) }, - { DRDATA (POS, tti_unit.pos, 31), PV_LEFT }, - { DRDATA (STIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB tti_mod[] = { - { CSET_MASK, CSET_ASCII, "ASCII", "ASCII", NULL}, - { CSET_MASK, CSET_1130, "1130", "1130", NULL}, - { 0 } }; - -DEVICE tti_dev = { - "KEYBOARD", &tti_unit, tti_reg, tti_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tti_reset, - NULL, NULL, NULL }; - -/* TTO data structures - - tto_dev TTO device descriptor - tto_unit TTO unit descriptor - tto_reg TTO register list -*/ - -UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT }; - -REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, 16) }, - { ORDATA (DSW, tto_dsw, 16) }, - { DRDATA (POS, tto_unit.pos, 31), PV_LEFT }, - { DRDATA (STIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -MTAB tto_mod[] = { - { CSET_MASK, CSET_ASCII, "ASCII", "ASCII", validate_conout_mapping, NULL, NULL}, - { CSET_MASK, CSET_1130, "1130", "1130", validate_conout_mapping, NULL, NULL}, - { CSET_MASK, CSET_APL, "APL", "APL", validate_conout_mapping, NULL, NULL}, - { ENABLE_ANSI,0, "NOANSI", "NOANSI", NULL}, - { ENABLE_ANSI,ENABLE_ANSI, "ANSI", "ANSI", NULL}, - { 0 } }; - -DEVICE tto_dev = { - "TTO", &tto_unit, tto_reg, tto_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto_reset, - NULL, NULL, NULL }; - -/* Terminal input routines - - tti_svc process event (character ready) - tti_reset process reset - tto_svc process event (print character) - tto_reset process reset -*/ - -#define TT_DSW_PRINTER_RESPONSE 0x8000 -#define TT_DSW_KEYBOARD_RESPONSE 0x4000 -#define TT_DSW_INTERRUPT_REQUEST 0x2000 -#define TT_DSW_KEYBOARD_CONSOLE 0x1000 -#define TT_DSW_PRINTER_BUSY 0x0800 -#define TT_DSW_PRINTER_NOT_READY 0x0400 -#define TT_DSW_KEYBOARD_BUSY 0x0200 - -void xio_1131_console (int32 iocc_addr, int32 func, int32 modify) -{ - int ch; - char msg[80]; - - switch (func) { - case XIO_CONTROL: - SETBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); /* select and unlock the keyboard */ - keyboard_selected(TRUE); - CLRBIT(tti_unit.flags, KEYBOARD_LOCKED); - tti_unit.buf = 0; /* no key character yet */ - break; - - case XIO_READ: - WriteW(iocc_addr, tti_unit.buf); /* return keycode */ - CLRBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); /* this ends selected mode */ - keyboard_selected(FALSE); - SETBIT(tti_unit.flags, KEYBOARD_LOCKED); /* keyboard is locked when not selected */ - tti_unit.buf = 0; /* subsequent reads will return zero */ - break; - - case XIO_WRITE: - ch = (ReadW(iocc_addr) >> 8) & 0xFF; /* get character to write */ - tto_unit.buf = emit_conout_character(ch); /* output character and save write status */ - - SETBIT(tto_dsw, TT_DSW_PRINTER_BUSY); - sim_activate(&tto_unit, tto_unit.wait); /* schedule interrupt */ - break; - - case XIO_SENSE_DEV: - ACC = tto_dsw | tti_dsw; - if (modify & 0x01) { /* reset interrupts */ - CLRBIT(tto_dsw, TT_DSW_PRINTER_RESPONSE); - CLRBIT(tti_dsw, TT_DSW_KEYBOARD_RESPONSE); - CLRBIT(tti_dsw, TT_DSW_INTERRUPT_REQUEST); - CLRBIT(ILSW[4], ILSW_4_CONSOLE); - } - break; - - default: - sprintf(msg, "Invalid console XIO function %x", func); - xio_error(msg); - } -} - -// emit_conout_character - write character with 1130 console code 'ch' - -t_stat emit_conout_character (int ch) -{ - t_stat status; - -#ifdef DEBUG_CONSOLE - printf("{%02x}", ch); -#endif - - if ((tto_unit.flags & CSET_MASK) == CSET_1130) /* 1130 (binary) mode, write the raw 8-bit value */ - return sim_putchar(ch); - - if (ch & COUT_IS_CTRL) { - /* red/black shift can be combined with another control */ - /* if present, emit the color shift characters alone */ - - if (ch & COUT_CTRL_BLACK) { - if ((status = map_conout_character(COUT_IS_CTRL|COUT_CTRL_BLACK)) != SCPE_OK) - return status; - } - else if (ch & COUT_CTRL_RED) { - if ((status = map_conout_character(COUT_IS_CTRL|COUT_CTRL_RED)) != SCPE_OK) - return status; - } - - ch &= ~(COUT_CTRL_BLACK|COUT_CTRL_RED); /* remove the ribbon shift bits */ - - if (ch & ~COUT_IS_CTRL) { /* if another control remains, emit it */ - if ((status = map_conout_character(ch)) != SCPE_OK) - return status; - } - - return SCPE_OK; - } - - return map_conout_character(ch); -} - -static void Beep (void) // notify user keyboard was locked or key was bad -{ - sim_putchar(7); -} - -// tti_svc - keyboard polling (never stops) - -static t_stat tti_svc (UNIT *uptr) -{ - int32 temp; - - if (cgi) /* if running in CGI mode, no keyboard and no keyboard polling! */ - return SCPE_OK; - /* otherwise, so ^E can interrupt the simulator, */ - sim_activate(&tti_unit, tti_unit.wait); /* always continue polling keyboard */ - - temp = sim_poll_kbd(); - - if (temp < SCPE_KFLAG) - return temp; /* no char or error? */ - - temp &= 0xFF; /* remove SCPE_KFLAG */ - - if ((tti_unit.flags & CSET_MASK) == CSET_ASCII) - temp = conin_map[temp] & 0xFF; /* perform input translation */ - - if (temp == IRQ_KEY) { /* INT REQ (interrupt request) key */ - SETBIT(tti_dsw, TT_DSW_INTERRUPT_REQUEST); /* queue interrupt */ - SETBIT(ILSW[4], ILSW_4_CONSOLE); - calc_ints(); - - CLRBIT(tti_unit.flags, KEYBOARD_LOCKED); /* keyboard restore, according to func. char. manual */ - -#ifdef DEBUG_CONSOLE - printf("[*IRQ*]"); -#endif - tti_unit.buf = 0; /* subsequent reads need to return 0 (required by APL\1130) */ - return SCPE_OK; - } - - if (temp == PROGRAM_STOP_KEY) { /* simulate the program stop button */ - SETBIT(con_dsw, CPU_DSW_PROGRAM_STOP); - SETBIT(ILSW[5], ILSW_5_PROGRAM_STOP); - calc_ints(); - -#ifdef DEBUG_CONSOLE - printf("[*PSTOP*]"); -#endif - - return SCPE_OK; - } - - if ((tti_unit.flags & KEYBOARD_LOCKED) || ! (tti_dsw & TT_DSW_KEYBOARD_BUSY)) { - Beep(); - return SCPE_OK; - } - - if ((tti_unit.flags & CSET_MASK) == CSET_ASCII) - temp = ascii_to_conin[temp]; - - if (temp == 0) { /* ignore invalid characters */ - Beep(); - calc_ints(); - return SCPE_OK; - } - - tti_unit.buf = temp & 0xFFFE; /* save keystroke except last bit (not defined) */ - tti_unit.pos = tti_unit.pos + 1; /* but it lets us distinguish 0 from no punch ' ' */ - -#ifdef DEBUG_CONSOLE - printf("[%04x]", tti_unit.buf & 0xFFFF); -#endif - -// CLRBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); /* clear busy flag (unselect keyboard) */ -// keyboard_selected(FALSE); - - SETBIT(tti_unit.flags, KEYBOARD_LOCKED); /* prevent further keystrokes */ - - SETBIT(tti_dsw, TT_DSW_KEYBOARD_RESPONSE); /* queue interrupt */ - SETBIT(ILSW[4], ILSW_4_CONSOLE); - calc_ints(); - - return SCPE_OK; -} - -static t_stat tti_reset (DEVICE *dptr) -{ - tti_unit.buf = 0; - tti_dsw = 0; - - CLRBIT(ILSW[4], ILSW_4_CONSOLE); - calc_ints(); - keyboard_selected(FALSE); - - SETBIT(tti_unit.flags, KEYBOARD_LOCKED); - - if (cgi) - sim_cancel(&tti_unit); /* in cgi mode, never poll keyboard */ - else - sim_activate(&tti_unit, tti_unit.wait); /* otherwise, always poll keyboard */ - - return SCPE_OK; -} - -t_bool keyboard_is_busy (void) /* return TRUE if keyboard is not expecting a character */ -{ - return (tti_dsw & TT_DSW_KEYBOARD_BUSY); -} - -static t_stat tto_svc (UNIT *uptr) -{ - CLRBIT(tto_dsw, TT_DSW_PRINTER_BUSY); - SETBIT(tto_dsw, TT_DSW_PRINTER_RESPONSE); - - SETBIT(ILSW[4], ILSW_4_CONSOLE); - calc_ints(); - - return (t_stat) tto_unit.buf; /* return status saved during output conversion */ -} - -static t_stat tto_reset (DEVICE *dptr) -{ - tto_unit.buf = 0; - tto_dsw = 0; - - CLRBIT(ILSW[4], ILSW_4_CONSOLE); - calc_ints(); - - sim_cancel(&tto_unit); /* deactivate unit */ - - set_conout_mapping(tto_unit.flags); /* initialize the overstrike mappings */ - /* register the font-mapping command */ - register_cmd("FONT", font_cmd, 0, "font MAPFILE use font mapping definitions in MAPFILE\n"); - - return SCPE_OK; -} - -#ifdef _MSC_VER -# pragma warning(disable:4245) /* enable int->char demotion warning caused by characters with high-bit set */ -#endif - -static struct { /* default input mapping for APL */ - unsigned char in; - unsigned char out; -} conin_to_APL[] = -{ /* these map input keys to those in like positions on 1130 keyboard */ - '[', '\r', /* enter (EOF) is APL left arrow */ - ';', '\b', /* backspace is APL [ */ - '\'', '\x15', /* ctrl-U, erase field, is APL ]*/ - '2', '@', /* APL upshift */ - '3', '%', /* APL rightshift */ - '4', '*', /* APL + and - */ - '5', '<', /* APL x and divide */ - '8', '-', /* APL return */ - '9', '/', /* APL backspace */ - '-', IRQ_KEY, /* ctrl-q (INT REQ), APL ATTN */ - '\r', '-', /* APL return */ - '\b', '/' /* APL backspace */ -}; - -#define NCONIN_TO_APL (sizeof(conin_to_APL)/sizeof(conin_to_APL[0])) - -static struct { /* default output mapping for APLPLUS font */ - unsigned char in; - unsigned char out; -} conout_to_APL[] = -{ - '\x01', IGNR_, /* controls */ - '\x03', '\n', - '\x05', IGNR_, /* (black and red are handled by ansi sequences) */ - '\x09', IGNR_, - '\x11', '\b', - '\x21', ' ', - '\x41', '\t', - '\x81', CRLF_, - - '\xC4', '\x30', /* (if you're curious, order here is position on APL typeball) */ - '\xE4', '\x38', - '\xD4', '\x37', - '\xF4', '\x35', - '\xDC', '\x33', - '\xFC', '\x31', - '\xC2', '\x29', - '\xE2', '\x9F', - '\xD2', '\x89', - '\xF2', '\x88', - '\xDA', '\xAF', - '\xC6', '\x5E', - '\xE6', '\xAC', - '\xD6', '\x3E', - '\xF6', '\x3D', - '\xDE', '\x3C', - '\xFE', '\xA8', - '\xC0', '\x5D', - '\xE0', '\x39', - '\xD0', '\x36', - '\xF0', '\x34', - '\xD8', '\x32', - - '\x84', '\x84', - '\xA4', '\x59', - '\x94', '\x58', - '\xB4', '\x56', - '\x9C', '\x54', - '\xBC', '\x2F', - '\x82', '\x3B', - '\xA2', '\x9B', - '\x92', '\xBE', - '\xB2', '\x87', - '\x9A', '\x97', - '\x86', '\x85', - '\xA6', '\x86', - '\x96', '\x9C', - '\xB6', '\x9E', - '\x9E', '\x7E', - '\xBE', '\x5C', - '\x80', '\x2C', - '\xA0', '\x5A', - '\x90', '\x57', - '\xB0', '\x55', - '\x98', '\x53', - - '\x44', '\x2B', - '\x64', '\x51', - '\x54', '\x50', - '\x74', '\x4E', - '\x5C', '\x4C', - '\x7C', '\x4A', - '\x42', '\x28', - '\x62', '\xBD', - '\x52', '\xB1', - '\x72', '\x7C', - '\x5A', '\x27', - '\x46', '\x2D', - '\x66', '\x3F', - '\x56', '\x2A', - '\x76', '\x82', - '\x5E', '\x8C', - '\x7E', '\xB0', - '\x40', '\x5B', - '\x60', '\x52', - '\x50', '\x4F', - '\x70', '\x4D', - '\x58', '\x4B', - - '\x04', '\xD7', - '\x24', '\x48', - '\x14', '\x47', - '\x34', '\x45', - '\x1C', '\x43', - '\x3C', '\x41', - '\x02', '\x3A', - '\x22', '\xBC', - '\x12', '\x5F', - '\x32', '\x98', - '\x1A', '\x83', - '\x06', '\xF7', - '\x26', '\x91', - '\x16', '\x92', - '\x36', '\xB9', - '\x1E', '\x9D', - '\x3E', '\xB8', - '\x00', '\x2E', - '\x20', '\x49', - '\x10', '\x46', - '\x30', '\x44', - '\x18', '\x42', -}; - -#define NCONOUT_TO_APL (sizeof(conout_to_APL)/sizeof(conout_to_APL[0])) - -static OS_MAP default_os_map[] = // overstrike mapping for APLPLUS font -{ - '\x8a', 2, "\x5e\x7e", - '\x8b', 2, "\x9f\x7e", - '\x8d', 2, "\x8c\x27", - '\x8e', 3, "\x8c\x2d\x3a", - '\x8f', 2, "\x91\x5f", - '\x90', 2, "\x92\x7e", - '\x93', 2, "\x91\x7c", - '\x94', 2, "\x92\x7c", - '\x95', 2, "\xb0\x82", - '\x96', 2, "\xb0\x83", - '\x99', 2, "\x2d\x5c", - '\x9a', 2, "\x2d\x2f", - '\xae', 2, "\x2c\x2d", - '\xb2', 2, "\xb1\x7c", - '\xb3', 2, "\xb1\x5c", - '\xb4', 2, "\xb1\x2d", - '\xb5', 2, "\xb1\x2a", - '\xba', 2, "\xb9\x5f", - '\xd0', 2, "\x30\x7e", - '\xd8', 2, "\x4f\x2f", - '\x21', 2, "\x27\x2e", - '\xa4', 2, "\xb0\xb1", /* map degree in circle to circle cross (APL uses this as character error symbol) */ - '\xf0', 2, "\xb0\xa8", - '\xfe', 2, "\x3a\xa8", -}; - -#ifdef _MSC_VER -# pragma warning(default:4245) /* enable int->char demotion warning */ -#endif - -/* os_map_comp - compare to OS_MAP entries */ - -static int os_map_comp (OS_MAP *a, OS_MAP *b) -{ - unsigned char *sa, *sb; - int i; - - if (a->nin > b->nin) - return +1; - - if (a->nin < b->nin) - return -1; - - sa = a->inlist; - sb = b->inlist; - - for (i = a->nin; --i >= 0;) { - if (*sa > *sb) - return +1; - - if (*sa < *sb) - return -1; - - sa++; - sb++; - } - - return 0; -} - -/* strsort - sorts the n characters of array 's' using insertion sort */ - -static void strsort (int n, unsigned char *s) -{ - unsigned char temp; - int i, big; - - while (--n > 0) { // repeatedly - big = 0; // find largest value of s[0]...s[n] - for (i = 1; i <= n; i++) - if (s[i] > s[big]) big = i; - - temp = s[n]; // put largest value at end of array - s[n] = s[big]; - s[big] = temp; - } -} - -/* file format: - -[font XXX] // font named XXX -OUT // failure character -OUT IN // single character mapping -OUT IN IN ... // overstrike mapping - -*/ - -static void set_conout_mapping (int32 flags) -{ - curcol = 0; - maxcol = 0; - - // set the default mappings. We may later override them with settings from an ini file - - set_default_mapping(flags); -} - -// finish_conout_mapping - sort the finalized overstrike mapping - -static void finish_conout_mapping (int32 flags) -{ - int i, n, big; - OS_MAP temp; - - for (i = 0; i < n_os_mappings; i++) // sort the inlist strings individually - strsort(os_map[i].nin, os_map[i].inlist); - - for (n = n_os_mappings; --n > 0; ) { // then sort the os_map array itself with insertion sort - big = 0; // find largest value of s[0]...s[n] - for (i = 1; i <= n; i++) - if (os_map_comp(os_map+i, os_map+big) > 0) big = i; - - if (big != n) { - temp = os_map[n]; // put largest value at end of array - os_map[n] = os_map[big]; - os_map[big] = temp; - } - } -} - -// validate_conout_mapping - called when set command gets a new value - -static t_stat validate_conout_mapping (UNIT *uptr, int32 match, char *cvptr, void *desc) -{ - set_conout_mapping(match); - return SCPE_OK; -} - -static void reset_mapping (void) -{ - int i; - - black_ribbon[0] = '\0'; /* erase the ribbon sequences */ - red_ribbon[0] = '\0'; - - memset(conout_map, 0, sizeof(conout_map)); /* erase output mapping */ - - n_os_mappings = 0; /* erase overstrike mapping */ - - for (i = (sizeof(conin_map)/sizeof(conin_map[0])); --i >= 0; ) - conin_map[i] = (unsigned char) i; /* default conin_map is identity map */ -} - -// set_default_mapping - create standard font and overstrike map - -static void set_default_mapping (int32 flags) -{ - int i; - - reset_mapping(); - - strcpy(black_ribbon, "\033[30m"); - strcpy(red_ribbon, "\033[31m"); - - switch (flags & CSET_MASK) { - case CSET_1130: - break; - - case CSET_ASCII: - memcpy(conout_map, conout_to_ascii, sizeof(conout_to_ascii)); - break; - - case CSET_APL: - for (i = NCONOUT_TO_APL; --i >= 0; ) - conout_map[conout_to_APL[i].in] = conout_to_APL[i].out; - - for (i = NCONIN_TO_APL; --i >= 0; ) - conin_map[conin_to_APL[i].in] = conin_to_APL[i].out; - - memcpy(os_map, default_os_map, sizeof(default_os_map)); - n_os_mappings = (sizeof(default_os_map) / sizeof(default_os_map[0])); - break; - } - - finish_conout_mapping(flags); // sort conout mapping if necessary -} - -// sim_putstr - write a string to the console - -t_stat sim_putstr (char *s) -{ - t_stat status; - - while (*s) { - if ((status = sim_putchar(*s)) != SCPE_OK) - return status; - - s++; - } - - return SCPE_OK; -} - -// map_conout_character - translate and write a single character - -static t_stat map_conout_character (int ch) -{ - t_stat status; - int i, cmp; - - if (ch == (COUT_IS_CTRL|COUT_CTRL_BLACK)) - return (tto_unit.flags & ENABLE_ANSI) ? sim_putstr(black_ribbon) : SCPE_OK; - - if (ch == (COUT_IS_CTRL|COUT_CTRL_RED)) - return (tto_unit.flags & ENABLE_ANSI) ? sim_putstr(red_ribbon) : SCPE_OK; - - if ((ch = conout_map[ch & 0xFF]) == 0) - ch = '?'; // unknown character? print ? - - if (ch == '\n') { // newline: reset overstrike buffer - curcol = 0; - maxcol = -1; - } - else if (ch == '\r') { // carriage return: rewind to column 0 - curcol = 0; - maxcol = -1; // assume it advances paper too - } - else if (ch == '\b') { // backspace: back up one character - if (curcol > 0) - curcol--; - } - else if (n_os_mappings && ch != (unsigned char) IGNR_) { - if (curcol > maxcol) { // first time in this column, no overstrike possible yet - os_buf[curcol].nin = 0; - maxcol = curcol; - } - - if (ch != ' ' && ch != 0) { // (if it's not a blank or unknown) - os_buf[curcol].inlist[os_buf[curcol].nin] = (unsigned char) ch; - strsort(++os_buf[curcol].nin, os_buf[curcol].inlist); - } - - if (os_buf[curcol].nin == 0) // if nothing but blanks seen, - ch = ' '; // output is a blank - else if (os_buf[curcol].nin == 1) { // if only one printing character seen, display it - ch = os_buf[curcol].inlist[0]; - } - else { // otherwise look up mapping - ch = '?'; - - for (i = 0; i < n_os_mappings; i++) { - cmp = os_map_comp(&os_buf[curcol], &os_map[i]); - if (cmp == 0) { // a hit - ch = os_map[i].ch; - break; - } - else if (cmp < 0) // not found - break; - } - } - - if (curcol < MAX_OUTPUT_COLUMNS) - curcol++; - } - - switch (ch) { - case IGNR_: - break; - - case CRLF_: - if (! cgi) { - if ((status = sim_putchar('\r')) != SCPE_OK) - return status; - - tto_unit.pos++; - } - - if ((status = sim_putchar('\n')) != SCPE_OK) - return status; - - tto_unit.pos++; /* hmm, why do we count these? */ - break; - - default: - if ((status = sim_putchar(ch)) != SCPE_OK) - return status; - - tto_unit.pos++; - break; - } - - return SCPE_OK; -} - -/* font_cmd - parse a font mapping file. Sets input and output translations */ - -static t_stat font_cmd (int32 flag, char *cptr) -{ - char *fname, quote; - FILE *fd; - - while (*cptr && (*cptr <= ' ')) cptr++; /* skip blanks */ - if (! *cptr) return SCPE_2FARG; /* argument missing */ - - fname = cptr; /* save start */ - while (*cptr && (*cptr > ' ')) { - if (*cptr == '\'' || *cptr == '"') { /* quoted string */ - quote = *cptr; /* remember quote character */ - strcpy(cptr, cptr+1); /* slide string down over the quote */ - - while (*cptr && *cptr != quote) /* find closing quote */ - cptr++; - - if (*cptr == quote) /* if closer was found, slide down over it */ - strcpy(cptr, cptr+1); - } - else /* skip over regular character */ - cptr++; - } - *cptr = '\0'; /* terminate name */ - - if ((fd = fopen(fname, "r")) == NULL) - return SCPE_OPENERR; - - reset_mapping(); /* remove all default mappings */ - - read_map_file(fd); - fclose(fd); - - finish_conout_mapping(tto_unit.flags); - return SCPE_OK; -} - -/* str_match - compare the string str to the keyword, case insensitive */ - -static t_bool str_match (char *str, char *keyword) -{ - char kch, sch; - - while (*keyword) { /* see if str matches the keyword... */ - kch = *keyword++; /* get pair of characters */ - sch = *str++; - - if (BETWEEN(kch, 'A', 'Z')) kch += 32; /* change upper to lower case */ - if (BETWEEN(sch, 'A', 'Z')) sch += 32; - - if (kch != sch) /* characters must match; if not, quit */ - return FALSE; - } - - return *str <= ' ' || *str == ';'; /* success if the input string ended or is in whitespace or comment */ -} - -/* read_map_file - process definition lines in opened mapping file */ - -static void read_map_file (FILE *fd) -{ - char str[256], *c, *errmsg; - int lineno = 0; - enum {SECT_UNDEFINED, SECT_DEFAULT, SECT_ANSI, SECT_INPUT, SECT_OUTPUT, SECT_OVERSTRIKE} - section = SECT_UNDEFINED; - - while (fgets(str, sizeof(str), fd) != NULL) { - ++lineno; /* count input lines */ - - if ((c = strchr(str, '\n')) != NULL) /* terminate at newline */ - *c = '\0'; - - for (c = str; *c && *c <= ' '; c++) /* skip blanks */ - ; - - if (c[0] == '\0' || c[0] == ';') /* ignore blank lines and lines starting with ; */ - continue; - - if (*c == '[') { - if (str_match(c, "[default]")) { /* check for section separators */ - set_default_mapping(tto_unit.flags); - section = SECT_UNDEFINED; - continue; - } - if (str_match(c, "[ansi]")) { - section = SECT_ANSI; - continue; - } - if (str_match(c, "[input]")) { - section = SECT_INPUT; - continue; - } - if (str_match(c, "[output]")) { - section = SECT_OUTPUT; - continue; - } - if (str_match(c, "[overstrike]")) { - section = SECT_OVERSTRIKE; - continue; - } - } - - switch (section) { /* if we get here, we have a definition line */ - case SECT_ANSI: - errmsg = handle_map_ansi_definition(&c); - break; - case SECT_INPUT: - errmsg = handle_map_input_definition(&c); - break; - case SECT_OUTPUT: - errmsg = handle_map_output_definition(&c); - break; - case SECT_OVERSTRIKE: - errmsg = handle_map_overstrike_definition(&c); - break; - default: - errmsg = "line occurs before valid [section]"; - break; - } - - if (errmsg == NULL) { /* if no other error detected, */ - while (*c && *c <= ' ') /* skip past any whitespace */ - c++; - - if (*c && *c != ';') /* if line doesn't end or run into a comment, complain */ - errmsg = "too much stuff on input line"; - } - - if (errmsg != NULL) { /* print error message and offending line */ - printf("* Warning: %s", errmsg); - - switch (section) { /* add section name if possible */ - case SECT_ANSI: errmsg = "ansi"; break; - case SECT_INPUT: errmsg = "input"; break; - case SECT_OUTPUT: errmsg = "output"; break; - case SECT_OVERSTRIKE: errmsg = "overstrike"; break; - default: errmsg = NULL; break; - } - if (errmsg != NULL) - printf(" in [%s] section", errmsg); - - printf(", line %d\n%s\n", lineno, str); - } - } -} - -/* get_num_char - read an octal or hex character specification of exactly 'ndigits' digits - * the input pointers is left pointing to the last character of the number, so that it - * may be incremented by the caller - */ - -static char * get_num_char (char **pc, unsigned char *out, int ndigits, int base, char *errmsg) -{ - unsigned char ch = 0, digit; - char *c = *pc; - - while (--ndigits >= 0) { /* collect specified number of digits */ - if (BETWEEN(*c, '0', '9')) - digit = *c - '0'; - else if (BETWEEN(*c, 'A', 'F')) - digit = *c - 'A' + 10; - else if (BETWEEN(*c, 'a', 'f')) - digit = *c - 'a' + 10; - else - digit = base; - - if (digit >= base) /* bad digit */ - return errmsg; - - ch = ch * base + digit; /* accumulate digit */ - c++; - } - - *out = ch; /* return parsed character */ - *pc = c-1; /* make input pointer point to last character seen */ - return NULL; /* no error */ -} - -/* get_characters - read character specification(s) from input string pointed to - * by *pc. Results stored in outstr; up to nmax characters parsed. Actual number - * found returned in *nout. Returns NULL on success or error message if syntax - * error encountered. *pc is advanced to next whitespace or whatever followed input. - */ - -static char * get_characters (char **pc, char *outstr, int nmax, int *nout) -{ - char *c = *pc, *out = outstr, *errstr; - - while (*c && *c <= ' ') /* skip leading whitespace */ - c++; - - while (--nmax >= 0) { /* get up to maximum number of characters */ - if (*c == ';' || *c <= ' ') /* we ran into a comment, whitespace or end of string: we're done */ - break; - - if (*c == '\\') { /* backslash escape of some sort */ - switch (*++c) { - case 'b': /* backspace */ - case 'B': - *out++ = '\b'; - break; - - case 'e': /* ascii ESCAPE */ - case 'E': - *out++ = '\033'; - break; - - case 'f': /* formfeed */ - case 'F': - *out++ = '\f'; - break; - - case 'n': /* newline */ - case 'N': - *out++ = '\n'; - break; - - case 'r': /* return */ - case 'R': - *out++ = '\r'; - break; - - case 't': /* tab */ - case 'T': - *out++ = '\t'; - break; - - case 'x': /* hex specification */ - case 'X': - c++; - if ((errstr = get_num_char(&c, out, 2, 16, "bad hex character")) != NULL) - return errstr; - - out++; /* advance out pointer */ - break; - - default: /* anything else */ - if (BETWEEN(*c, '0', '7')) { /* octal specification */ - if ((errstr = get_num_char(&c, out, 3, 8, "bad octal character")) != NULL) - return errstr; - - out++; /* advance out pointer */ - } - else if (BETWEEN(*c, 'A', 'Z') || BETWEEN(*c, 'a', 'z')) - return "invalid \\ escape"; /* other \x letters are bad */ - else { - *out++ = *c; /* otherwise, accept \x as literal character x */ - } - break; - } - } - else if (*c == '^') { /* control character */ - c++; - if (BETWEEN(*c, 'A', 'Z')) /* convert alpha, e.g. A -> 1 */ - *out++ = *c - 'A' + 1; - else if (BETWEEN(*c, 'a', 'z')) - *out++ = *c - 'z' + 1; - else /* non alpha is bad */ - return "invalid control letter"; - } - else if (str_match(c, "IGNORE")) { /* magic word: a character that will never be output */ - *out++ = IGNR_; - c += 6; - } - else { - *out++ = *c; /* save literal character */ - } - - c++; - } - - if (*c && *c != ';' && *c > ' ') /* we should be at end of string, whitespace or comment */ - return "too many characters specified"; - - *pc = c; /* save advanced pointer */ - *nout = out-outstr; /* save number of characters stored */ - - return NULL; /* no error */ -} - -/* handle_map_ansi_definition - process line in [ansi] section */ - -static char * handle_map_ansi_definition (char **pc) -{ - char *outstr, *errmsg; - int n; - - if (str_match(*pc, "black")) { /* find which string we're setting */ - outstr = black_ribbon; /* this is where we'll save the output string */ - *pc += 5; /* skip over the token */ - } - else if (str_match(*pc, "red")) { - outstr = red_ribbon; - *pc += 3; - } - else - return "invalid variable name"; - /* get list of characters */ - if ((errmsg = get_characters(pc, outstr, sizeof(black_ribbon)-1, &n)) != NULL) - return errmsg; - - outstr[n] = '\0'; /* null terminate the string */ - - return (n > 0) ? NULL : "missing output string"; /* NULL if OK, error msg if no characters */ -} - -/* handle_map_input_definition - process line in [input] section */ - -static char * handle_map_input_definition (char **pc) -{ - unsigned char cin, cout; - char *errmsg; - int n; - - if ((errmsg = get_characters(pc, &cin, 1, &n)) != NULL) /* get input character */ - return errmsg; - - if (n != 1) - return "missing input character"; - - if ((errmsg = get_characters(pc, &cout, 1, &n)) != NULL) /* get output character */ - return errmsg; - - if (n != 1) - return "missing output character"; - - conin_map[cin] = cout; /* set the mapping */ - return NULL; -} - -/* handle_map_output_definition - process line in [output] section */ - -static char * handle_map_output_definition (char **pc) -{ - unsigned char cin, cout; - char *errmsg; - int n; - - if ((errmsg = get_characters(pc, &cin, 1, &n)) != NULL) /* get input character */ - return errmsg; - - if (n != 1) - return "missing input character"; - - if ((errmsg = get_characters(pc, &cout, 1, &n)) != NULL) /* get output character */ - return errmsg; - - if (n != 1) - return "missing output character"; - - conout_map[cin] = cout; /* set the mapping */ - return NULL; -} - -/* handle_map_overstrike_definition - process line in [overstrike] section */ - -static char * handle_map_overstrike_definition (char **pc) -{ - unsigned char ch, inlist[MAX_OS_CHARS]; - char *errmsg; - int nin; - - if (n_os_mappings >= MAX_OS_MAPPINGS) /* os_map is full, no more room */ - return "too many overstrike mappings"; - /* get output character */ - if ((errmsg = get_characters(pc, &ch, 1, &nin)) != NULL) - return errmsg; - - if (nin != 1) - return "missing output character"; - /* get input list */ - if ((errmsg = get_characters(pc, inlist, MAX_OS_CHARS, &nin)) != NULL) - return errmsg; - - if (nin < 2) /* expect at least two characters overprinted */ - return "missing input list"; - - os_map[n_os_mappings].ch = ch; /* save in next os_map slot */ - os_map[n_os_mappings].nin = nin; - memmove(os_map[n_os_mappings].inlist, inlist, nin); - - n_os_mappings++; - return NULL; -} diff --git a/Ibm1130/ibm1130_sys.c b/Ibm1130/ibm1130_sys.c deleted file mode 100644 index ba3a4f49..00000000 --- a/Ibm1130/ibm1130_sys.c +++ /dev/null @@ -1,495 +0,0 @@ -/* ibm1130_sys.c: IBM 1130 simulator interface - - Based on PDP-11 simulator written by Robert M Supnik - - Revision History - 0.26 2002Apr24 - Added !BREAK in card deck file to stop simulator - 0.25 2002Apr18 - Fixed some card reader problems. It starts the reader - properly if you attach a deck while it's waiting to a read. - 0.24 2002Mar27 - Fixed BOSC bug; BOSC works in short instructions too - 0.23 2002Feb26 - Added @decklist feature for ATTACH CR. - 0.22 2002Feb26 - Replaced "strupr" with "upcase" for compatibility. - 0.21 2002Feb25 - Some compiler compatibiity changes, couple of compiler-detected - bugs - 0.01 2001Jul31 - Derived from pdp11_sys.c, which carries this disclaimer: - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - */ - -#include "ibm1130_defs.h" -#include -#include - -extern DEVICE cpu_dev, console_dev, dsk_dev, cr_dev, cp_dev; -extern DEVICE tti_dev, tto_dev, prt_dev, log_dev; -extern DEVICE gdu_dev, console_dev; - -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern int32 saved_PC; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "IBM 1130"; -char sim_version[] = "V0.30"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { - &cpu_dev, /* the cpu */ - &dsk_dev, /* disk drive(s) */ - &cr_dev, /* card reader/punch */ - &cp_dev, - &tti_dev, /* console keyboard, selectric printer */ - &tto_dev, - &prt_dev, /* 1132 printer */ - &console_dev, /* console display (windows GUI) */ - &gdu_dev, /* 2250 display */ - NULL -}; - -const char *sim_stop_messages[] = { - "Unknown error", - "Wait", - "Invalid command", - "Simulator breakpoint", - "Use of incomplete simulator function", - "Power off", - "!BREAK in card deck file", - "Phase load break", - "Program has run amok", - "Run time limit exceeded" -}; - -/* Loader. IPL is normally performed by card reader (boot command). This function - * loads hex data from a file for testing purposes. The format is: - * - * blank lines or lines starting with ; / or # are ignored as comments - * - * @XXXX set load addresss to hex value XXXX - * XXXX store hex word value XXXX at current load address and increment address - * ... - * =XXXX set IAR to hex value XXXX - * ZXXXX zero XXXX words and increment load address - * SXXXX set console entry switches to XXXX. This lets a program specify the - * default value for the toggle switches. - * - * Multiple @ and data sections may be entered. If more than one = or S value is specified - * the last one wins. - * - * Note: the load address @XXXX and data values XXXX can be followed by the letter - * R to indicate that the values are relocatable addresses. This is ignored in this loader, - * but the asm1130 cross assembler may put them there. - */ - -t_stat my_load (FILE *fileref, char *cptr, char *fnam) -{ - char line[150], *c; - int iaddr = -1, runaddr = -1, val, nwords; - - while (fgets(line, sizeof(line), fileref) != NULL) { - for (c = line; *c && *c <= ' '; c++) // find first nonblank - ; - - if (*c == '\0' || *c == '#' || *c == '/' || *c == ';') - continue; // empty line or comment - - if (*c == '@') { // set load address - if (sscanf(c+1, "%x", &iaddr) != 1) - return SCPE_FMT; - } - else if (*c == '=') { - if (sscanf(c+1, "%x", &runaddr) != 1) - return SCPE_FMT; - } - else if (*c == 's' || *c == 'S') { - if (sscanf(c+1, "%x", &val) != 1) - return SCPE_FMT; - - CES = val & 0xFFFF; // preload console entry switches - } - else if (*c == 'z' || *c == 'Z') { - if (sscanf(c+1, "%x", &nwords) != 1) - return SCPE_FMT; - - if (iaddr == -1) - return SCPE_FMT; - - while (--nwords >= 0) { - WriteW(iaddr, 0); - iaddr++; - } - } - else if (strchr("0123456789abcdefABCDEF", *c) != NULL) { - if (sscanf(c, "%x", &val) != 1) - return SCPE_FMT; - - if (iaddr == -1) - return SCPE_FMT; - - WriteW(iaddr, val); // store data - iaddr++; - } - else - return SCPE_FMT; // unexpected data - } - - if (runaddr != -1) - IAR = runaddr; - - return SCPE_OK; -} - -t_stat my_save (FILE *fileref, char *cptr, char *fnam) -{ - int iaddr, nzeroes = 0, nwords = (int) (MEMSIZE/2), val; - - fprintf(fileref, "=%04x\r\n", IAR); - fprintf(fileref, "@0000\r\n"); - for (iaddr = 0; iaddr < nwords; iaddr++) { - val = ReadW(iaddr); - if (val == 0) // queue up zeroes - nzeroes++; - else { - if (nzeroes >= 4) { // spit out a Z directive - fprintf(fileref, "Z%04x\r\n", nzeroes); - nzeroes = 0; - } - else { // write queued zeroes literally - while (nzeroes > 0) { - fprintf(fileref, " 0000\r\n"); - nzeroes--; - } - } - fprintf(fileref, " %04x\r\n", val); - } - } - if (nzeroes >= 4) { // emit any queued zeroes - fprintf(fileref, "Z%04x\r\n", nzeroes); - nzeroes = 0; - } - else { - while (nzeroes > 0) { - fprintf(fileref, " 0000\r\n"); - nzeroes--; - } - } - - return SCPE_OK; -} - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ - if (flag) - return my_save(fileref, cptr, fnam); - else - return my_load(fileref, cptr, fnam); -} - -/* Specifier decode - - Inputs: - *of = output stream - addr = current PC - spec = specifier - nval = next word - flag = TRUE if decoding for CPU - iflag = TRUE if decoding integer instruction - Outputs: - count = -number of extra words retired -*/ - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current PC - *val = values to decode - *uptr = pointer to unit - sw = switches - Outputs: - return = if >= 0, error code - if < 0, number of extra words retired -*/ - -static char *opcode[] = { - "?00 ", "XIO ", "SLA ", "SRA ", - "LDS ", "STS ", "WAIT", "?07 ", - "BSI ", "BSC ", "?0A ", "?0B ", - "LDX ", "STX ", "MDX ", "?0F ", - "A ", "AD ", "S ", "SD ", - "M ", "D ", "?16 ", "?17 ", - "LD ", "LDD ", "STO ", "STD ", - "AND ", "OR ", "EOR ", "?1F ", -}; - -static char relative[] = { // true if short mode displacements are IAR relative - FALSE, TRUE, FALSE, FALSE, - FALSE, TRUE, FALSE, FALSE, - TRUE, FALSE, FALSE, FALSE, - TRUE, TRUE, TRUE, FALSE, - TRUE, TRUE, TRUE, TRUE, - TRUE, TRUE, FALSE, FALSE, - TRUE, TRUE, TRUE, TRUE, - TRUE, TRUE, TRUE, FALSE -}; - -static char *lsopcode[] = {"SLA ", "SLCA ", "SLT ", "SLC "}; -static char *rsopcode[] = {"SRA ", "?188 ", "SRT ", "RTE "}; -static char tagc[] = " 123"; - -static int ascii_to_ebcdic_table[128] = -{ - 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f, - 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61, - 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f, - - 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6, - 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d, - 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96, - 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07, -}; - -static int ebcdic_to_ascii (int ch) -{ - int j; - - for (j = 32; j < 128; j++) - if (ascii_to_ebcdic_table[j] == ch) - return j; - - return '?'; -} - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) -{ - int32 cflag, ch, OP, F, TAG, INDIR, DSPLC, IR, eaddr; - char *mnem, tst[12]; - - cflag = (uptr == NULL) || (uptr == &cpu_unit); - -// if (sw & SWMASK ('A')) { /* ASCII? not useful */ -// fprintf (of, (c1 < 040)? "<%03o>": "%c", c1); -// return SCPE_OK; -// } - - if (sw & SWMASK ('C')) /* character? not useful -- make it EBCDIC */ - sw |= SWMASK('E'); - - if (sw & SWMASK ('E')) { /* EBCDIC! */ - ch = ebcdic_to_ascii((val[0] >> 8) & 0xFF); /* take high byte first */ - fprintf (of, (ch < ' ')? "<%03o>": "%c", ch); - ch = ebcdic_to_ascii(val[0] & 0xFF); - fprintf (of, (ch < ' ')? "<%03o>": "%c", ch); - return SCPE_OK; - } - - if (sw & SWMASK ('H')) { /* HOLLERITH! now THIS is useful! */ - ch = hollerith_to_ascii((int16) val[0]); - fprintf (of, (ch < ' ')? "<%03o>": "%c", ch); - return SCPE_OK; - } - - if (! (sw & SWMASK ('M'))) - return SCPE_ARG; - - IR = val[0]; - OP = (IR >> 11) & 0x1F; /* opcode */ - F = IR & 0x0400; /* format bit: 1 = long instr */ - TAG = IR & 0x0300; /* tag bits: index reg select */ - if (TAG) - TAG >>= 8; - - if (F) { /* long instruction, ASSUME it's valid (have to decrement IAR if not) */ - INDIR = IR & 0x0080; /* indirect bit */ - DSPLC = IR & 0x007F; /* displacement or modifier */ - if (DSPLC & 0x0040) - DSPLC |= ~ 0x7F; /* sign extend */ - - eaddr = val[1]; /* get reference address */ - } - else { /* short instruction, use displacement */ - INDIR = 0; /* never indirect */ - DSPLC = IR & 0x00FF; /* get displacement */ - if (DSPLC & 0x0080) - DSPLC |= ~ 0xFF; - - eaddr = DSPLC; - if (relative[OP] && ! TAG) - eaddr += addr+1; /* turn displacement into address */ - } - - mnem = opcode[OP]; /* get mnemonic */ - if (OP == 0x02) { /* left shifts are special */ - mnem = lsopcode[(DSPLC >> 6) & 0x0003]; - DSPLC &= 0x003F; - eaddr = DSPLC; - } - else if (OP == 0x03) { /* right shifts too */ - mnem = rsopcode[(DSPLC >> 6) & 0x0003]; - DSPLC &= 0x003F; - eaddr = DSPLC; - } - else if ((OP == 0x08 && F)|| OP == 0x09) { // BSI L and BSC any - if (OP == 0x09 && (IR & 0x40)) - mnem = "BOSC"; - - tst[0] = '\0'; - if (DSPLC & 0x20) strcat(tst, "Z"); - if (DSPLC & 0x10) strcat(tst, "-"); - if (DSPLC & 0x08) strcat(tst, "+"); - if (DSPLC & 0x04) strcat(tst, "E"); - if (DSPLC & 0x02) strcat(tst, "C"); - if (DSPLC & 0x01) strcat(tst, "O"); - - if (F) { - fprintf(of, "%04x %s %c%c %s,%04x ", IR & 0xFFFF, mnem, F ? (INDIR ? 'I' : 'L') : ' ', tagc[TAG], tst, eaddr & 0xFFFF); - return -1; - } - fprintf(of, "%04x %s %c%c %s ", IR & 0xFFFF, mnem, F ? (INDIR ? 'I' : 'L') : ' ', tagc[TAG], tst); - return SCPE_OK; - } - else if (OP == 0x0e && TAG == 0) { // MDX with no tag => MDM or jump - if (F) { - fprintf(of, "%04x %s %c%c %04x,%x (%d) ", IR & 0xFFFF, "MDM ", (INDIR ? 'I' : 'L'), tagc[TAG], eaddr & 0xFFFF, DSPLC & 0xFFFF, DSPLC); - return -1; - } - mnem = "JMP "; - } - - fprintf(of, "%04x %s %c%c %04x ", IR & 0xFFFF, mnem, F ? (INDIR ? 'I' : 'L') : ' ', tagc[TAG], eaddr & 0xFFFF); - return F ? -1 : SCPE_OK; /* inform how many words we read */ -} - -int32 get_reg (char *cptr, const char *strings[], char mchar) -{ -return -1; -} - -/* Number or memory address - - Inputs: - *cptr = pointer to input string - *dptr = pointer to output displacement - *pflag = pointer to accumulating flags - Outputs: - cptr = pointer to next character in input string - NULL if parsing error - - Flags: 0 (no result), A_NUM (number), A_REL (relative) -*/ - -char *get_addr (char *cptr, int32 *dptr, int32 *pflag) -{ - return 0; -} - -/* Specifier decode - - Inputs: - *cptr = pointer to input string - addr = current PC - n1 = 0 if no extra word used - -1 if extra word used in prior decode - *sptr = pointer to output specifier - *dptr = pointer to output displacement - cflag = true if parsing for the CPU - iflag = true if integer specifier - Outputs: - status = = -1 extra word decoded - = 0 ok - = +1 error -*/ - -t_stat get_spec (char *cptr, t_addr addr, int32 n1, int32 *sptr, t_value *dptr, - int32 cflag, int32 iflag) -{ - return -1; -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = > 0 error code - <= 0 -number of extra words -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ - return SCPE_ARG; -} - -#ifndef WIN32 - -int strnicmp (char *a, char *b, int n) -{ - int ca, cb; - - for (;;) { - if (--n < 0) // still equal after n characters? quit now - return 0; - - if ((ca = *a) == 0) // get character, stop on null terminator - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) // if different, return comparison - return ca; - - a++, b++; - } -} - -int strcmpi (char *a, char *b) -{ - int ca, cb; - - for (;;) { - if ((ca = *a) == 0) // get character, stop on null terminator - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) // if different, return comparison - return ca; - - a++, b++; - } -} - -#endif diff --git a/Ibm1130/ibm1130res.h b/Ibm1130/ibm1130res.h deleted file mode 100644 index ce47382e..00000000 --- a/Ibm1130/ibm1130res.h +++ /dev/null @@ -1,18 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by ibm1130.rc -// - -#define IDB_CONSOLE 101 -#define IDC_HAND 102 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 103 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/Ibm1130/makefile b/Ibm1130/makefile deleted file mode 100644 index 7aabb801..00000000 --- a/Ibm1130/makefile +++ /dev/null @@ -1,74 +0,0 @@ -# (This makefile is for operating systems other than Windows, -# or compilers other than Microsoft's. For MS builds, use the -# .mak files found in this directory and the utils directory). -# -# If you are building the emulator and utilities as part of -# the SIMH package, please: -# -# Be sure that you there are NO copies of scp.c, scp_tty.c, -# sim_sock.c, sim_tmxr.c, sim_rev.h, sim_defs.h, sim_sock.h and -# sim_tmxr.h in the ibm1130 subdirectory. Delete them if there -# are. -# -# Do not use this makefile with "make all" or "make ibm1130". -# Use the SIMH build files instead. -# -# If and when you download updates for this simulator from -# www.ibm1130.org, get ibm1130code.zip and ibm1130software.zip -# separately. -# -# If you have downloaded the emulator independently of SIMH (e.g, from -# www.ibm1130.org), please: -# -# Be sure that you DO have copies of scp.c, scp_tty.c, sim_sock.c, -# sim_tmxr.c, sim_rev.h, sim_defs.h, sim_sock.h and sim_tmxr.h -# in this folder. -# -# Use this file to make the emulator. -# -# If and when you download updates for this simulator from -# www.ibm1130.org, get ibm1130.zip. When you expand it, -# also expand ibm1130sofware.zip, which is inside. -# -# In either case, if you want to build DMS or work with assembly -# language programs outside of DMS, you'll want to make the utilities -# by cd'ing to the utils directory and running make there. - -# CC Command -# -# Note: -O2 is sometimes broken in GCC when setjump/longjump is being -# used. Try -O2 only with released simulators. -# -CC = gcc -O0 -lm -I . -#CC = gcc -O2 -g -lm -I . - - -# -# Common Libraries -# -BIN = -SIM = scp.c scp_tty.c sim_sock.c sim_tmxr.c -SIM_INC = sim_defs.h sim_rev.h sim_sock.h sim_tmxr.h - -# -# Emulator source files and compile time options -# - -ibm1130D = ./ -ibm1130 = ${ibm1130D}ibm1130_sys.c ${ibm1130D}ibm1130_cpu.c \ - ${ibm1130D}ibm1130_cr.c ${ibm1130D}ibm1130_disk.c \ - ${ibm1130D}ibm1130_stddev.c ${ibm1130D}ibm1130_gdu.c \ - ${ibm1130D}ibm1130_gui.c ${ibm1130D}ibm1130_prt.c \ - ${ibm1130D}ibm1130_fmt.c - -ibm1130_INC = ibm1130res.h ibm1130_conin.h ibm1130_conout.h \ - ibm1130_defs.h ibm1130_prtwheel.h ibm1130_fmt.h \ - dmsr2v12phases.h dmsr2v12slet.h - -# -# Build the emulator -# - -${BIN}ibm1130 : ${ibm1130} ${SIM} ${ibm1130_INC} ${SIM_INC} - ${CC} ${ibm1130} ${SIM} -o $@ - diff --git a/Ibm1130/readme1130.txt b/Ibm1130/readme1130.txt deleted file mode 100644 index e7a20831..00000000 --- a/Ibm1130/readme1130.txt +++ /dev/null @@ -1,189 +0,0 @@ -Here's the 1130 simulator as it stands now. - -Status: 22Jul2003 - - * Added support for APL\1130 output translations - and some bug fixes uncovered by APL. - -Status: 13Sep2002 - - * Added support for 1403 printer. It's MUCH faster - even in emulation. Not important for general use, - but it will help the CGI version a lot. - -Status: 16Aug2002 - - * Disk Monitor System R2V12 is available including the - Macro Assembler, Fortran Compiler and System Library. - - * There was a bug in the multiply instruction. This has - been fixed, and now the single precision trig functions - work correctly. - - * The card punch does not yet work correctly. - - * The card reader, punch and disk don't compute their device - status word until an XIO requests it; this is probably bad - as the "examine" command will show the wrong value. Doesn't - affect functioning of emulated software, though. - - * Documentation is a work in progress, see ibm1130.doc - in ibm1130software.zip. We hope to have it finished in - October. This is a Word document. Will distribute as a - PDF when it's finished. - - * Thanks to Oscar E Wyss (www.cosecans.ch) for - the DMS V12 source code listings and one card - programs, to Douglas W. Jones for the DMS V10, 11 and - 12 microfiche (which will end up scanned on IBM1130.org). - - * Thanks to Robert Alan Byer for adding the 1130 - to the simh makefiles & testing the builds on several - platforms. - - * For updated information about the 1130 and for - future 1130 OS and application software developments, - check www.ibm1130.org periodically. Sign up for the - mailing list to get updates as they occur! - - * Cross-assembler has been updated to handle card image input - correctly. The DMS sources seems to mix up @ and ' - as a leading symbol in labels, I have to find out why - this is. - -BUILD NOTES: if you download this simulator directly from -IBM1130.org, the makefile, source, and binaries are all in -the main directory. If you use the version from Bob Supnik's -SIMH distribution, the makefile is in the main simh -directory, and the SCP files used are Bob's. For a -Windows build, use the .mak file in the IBM1130 directory, -as this incorporates the GUI. - -Make the utilities in the utils directory if you want -to actually build and load DMS from scratch. Move the -executables to a common directory in your search path - -Brian Knittel -brian@ibm1130.org - --------------------------------------------------------------------------- -Some sample things to run: -(it's best to hit CHECK RESET or type "reset" between program runs!) - -* Run a Fortran Program - ibm1130 - do job roots - do job csort - -* List the monitor system disk's contents - ibm1130 - do job list - -* Look into the files "job", "roots.job" and "csort.job" and "list.job" - to see the actual input files - -* When the jobs have run (stop at 2A with 1000 in the - accumulator), detach the printer (det prt) and look at - the output file: for.lst or asm.lst. The supplied "job" - script displays the print output automatically on Windows - builds. - --------------------------------------------------------------------------- -Contents: - -There are several programs: - - ibm1130 the simulator - asm1130 cross assembler - bindump dumps contents of relocatable format object decks (xxx.bin) - checkdisk validates DMS disk format - diskview dumps contents of DMS disk directory - mkboot creates IPL and Core Image Format Decks from .bin - viewdeck displays contents of Hollerith-format binary decks - -Files in the software (sw) directory: - - actual 1130 software: - dms.dsk disk image file containing Disk Monitor System - zdcip.asm disk cartridge initialization program - zcrdumpc.asm a cold-start-mode one card memory dump program - dmsboot.asm source code for the DMS cold start loader - - contributed software: - onecard/* one-card programs from Oscar Wyss - --------------------------------------------------------------------------- -Status of the simulator: - -* There is a reasonably fun console GUI available for Windows builds, - as well as support for the 2250 graphical display. - -* The card reader emulator now supports deck files with literal cards and - breakpoints. The command "attach cr @filename" tells the simulator to - read data from the files named in the specified file. Input lines are of - the following form: - - filename a -- input file to be read as ascii text - filename b -- input file to be read as binary card images - !xyz... -- literal text xyz..., treated as a card - !break -- halts the simulator - #comment -- remarks - -* The do command may have arguments after the filename. These may be - interpolated in the script and in card reader deck files with %1, %2, etc - --------------------------------------------------------------------------- -sample usage --------------------------------------------------------------------------- - -ibm1130 - starts SIMH-based simulator. - Optional command line arguments: -q quiet mode, -g no GUI - - Enhancements: - - * Windows builds display a console window - - * CPU activity log - - the command "attach cpu file.log" will make the simulator - write a detailed log of CPU and IO activity, good for - debugging. Turn off with "detach cpu". - - * DO command [arg1 arg2...] - reads file 'filename' for SIMH commands. Lets you write - simh command files to be run from the prompt rather - than just the command line. In the do command file, %1 will - be replaced by the first command line argument, etc. This - applies to the script run from the ibm1130 command line too. - - * DELETE filename - deletes the named file - - * VIEW filename - displays the named file with "notepad." (Windows only). - --------------------------------------------------------------------------- -asm1130 -l program.asm - - compiles source file, creates simulator load - file (program.out) and listing file (program.lst) - - The cross assembler wants files either in strict column - layout matching the IBM spec, or, if tabs are present in the - source file, - - labelopcodeflagsoperand - - The output file is in the format used by the 1130 simulator's - load command. - --------------------------------------------------------------------------- - -Note: the DMS disk is built with the Windows batch file "mkdms.bat". - -Subnote: DMS cannot be built with the 1130's native assembler. - - --------------------------------------------------------------------------- -check www.ibm1130.org for updates... \ No newline at end of file diff --git a/Ibm1130/readme_update.txt b/Ibm1130/readme_update.txt deleted file mode 100644 index aab52dbc..00000000 --- a/Ibm1130/readme_update.txt +++ /dev/null @@ -1,48 +0,0 @@ -Version: 10 July 2003 - -History (partial): - -2003-07-10 Fixed disk and console terminal bugs uncovered by - APL\1130. Added APL keyboard and output font support - to enable use of APL\1130. APL will be released soon. - -2003-03-18 Fixed bug in asm1130 that produced an error message - with a (legal) offset of +127 in MDX instructions. - - Fixed sign bug in 1130 emulator divide instruction. - -Interim 1130 distribution: --------------------------------------------- - -folders: - . sources - winrel windows executables - windebug windows executables - utils accessory programs - utils\winrel windows executables - utils\windebug windows executables - sw working directory for DMS build & execution - sw\dmsR2V12 Disk Monitor System sources - -programs: - asm1130 cross assembler - bindump object deck dump tool, also used to sort decks by phase id - checkdisk DMS disk image check and dump - diskview work in progress, interpreted disk image dump - ibm1130 emulator - mkboot object deck to IPL and core image converter - viewdeck binary to hollerith deck viewer if needed to view phase ID cards and ident fields - -batch file: - mkdms.bat builds DMS objects and binary cards. Need a shell script version of this. - -IBM1130 simulator DO command scripts: - format format a disk image named DMS.DSK - loaddms format and install DMS onto the formatted DMS.DSK - for run a Fortran program - list list the disk contents - asm assemble a program - -ancillary files: - loaddms.deck list of files stacked into the card reader for loaddms - *.deck other sample deck files diff --git a/Ibm1130/utils/asm1130.c b/Ibm1130/utils/asm1130.c deleted file mode 100644 index 5cf9e31f..00000000 --- a/Ibm1130/utils/asm1130.c +++ /dev/null @@ -1,4499 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -// --------------------------------------------------------------------------------- -// ASM1130 - IBM 1130 Cross Assembler -// -// Version -// 1.08 - 2003Mar18 - Fixed bug that complained about valid MDX displacement of +127 -// 1.07 - 2003Jan05 - Filenames are now left in lower case. SYMBOLS.SYS stays all upper case -// 1.06 - 2002May02 - Fixed bug in ebdic constants (data goes into low byte) -// First stab at adding ISS level # info, this is iffy -// 1.05 - 2002Apr24 - Made negative BSS size a warning not an error, as it -// it's looking like it happens twice in PTMASMBL. -// This version still doesn't do fixed point numbers and -// negative floats may be wrong. -// 1.04 - 2002Apr18 - Added binary (card loader format) output, removed -// interim IPL output formats and moved that to MKBOOT. -// Enhanced relocatable code handling. Added floating -// point constants, but don't know how to make fixed point -// constants yet. Made amenable to syntax variations found -// in the DMS sources. Doesn't properly handle ILS -// modules yet and ISS is probably wrong. -// 1.03 - 2002Apr10 - numerous fixes, began to add relative/absolute support -// 1.02 - 2002Feb26 - replaced "strupr" with "upcase" for compatibility -// 1.01 - 2002Feb25 - minor compiler compatibility changes -// 1.00 - 2002Feb01 - first release. Tested only under Win32. -// --------------------------------------------------------------------------------- -// -// Usage: -// asm1130 [-bvsx] [-o[file]] [-l[file]] [-rN.M] file... -// -// Description: -// -b binary output (.bin, relocatable absolute format) -// -v verbose -// -s print symbol table -// -x print cross references -// -o output file (default is name of first source file + extension .out or .bin) -// -l listing file (default is name of first source file + extension .lst) -// -y preload system symbol table SYMBOLS.SYS (from the current directory) -// -w write the system symbol table SYMBOLS.SYS in the current directory -// -W same as -w but don't prompt to confirm overwriting existing file -// -r set DMS release to release N version M, for sbrk cards -// -// Listing and symbol table output can be turned on by *LIST directives in the source, too -// Listing file default extension is .LST -// -// Input files can use strict IBM 1130 Assembler column format, or loose formatting -// with tabs, or any mix on a line-by-line basis. Input files default extension is .ASM. -// -// Strict specification is: -// -// label columns 1 - 5 -// opcode 7 - 10 -// tag 12 -// index 13 -// arguments 15 - 51 -// -// Loose, indicated by presence of ascii tab character(s): -// -// labelopcodeindex and format indicatorsarguments -// -// In both cases, the IBM convention that the arguments section ends with the -// first nonblank applies. This means that ".DC 1, 2, 3" assembles only the 1! -// -// Output file format is that used by the LOAD command in my 1130 -// simulator. Lines are any of the following. All values are in hex: -// -// @addr load address for subsequent words is addr -// Znwords Zero the next "nwords" and increment load address by nwords. -// =addr set IAR register to address addr (a convenience) -// value load value at load address and increment load address -// -// Output file default extension is .OUT or .BIN for binary assemblies -// -// Note: this version does not handle relative assembly, and so doesn't carry -// absolute/relative indication through expression calculation. -// -// Seems to work. Was able to assemble the resident monitor OK. -// >>> Look for "bug here" though, for things to check out. -// -// Notes: -// org_advanced tells whether * in an expression refers to the address AFTER the -// instruction (1 or 2 words, depending on length). This is the case for opcodes -// but not all directives. -// -// Added special coldstart format directives: -// -// .IPL 1130,XXXXXXXX -// .IPL 1800,XXXXXXXX -// -// (these are not standard IBM) -// -// These directives cause the output file to be written in binary in either 1130 or -// 1800 IPL format. In 1130 format, the index bits are lost and the displacement -// is sign extended. In 1800 format, the data are punched 8 bits at a time into -// two columns per word. If an identifier is not given, data are punched into -// all 80 columns. If an identifier is given, data is punched in columns 0 through -// 72, and the identification XXXXXXXX is punched in columns 73 through 80. (If -// there are multiple output cards the last ident character is incremented). A -// warning is issued if 1130 assembly results in lost bits. These directives -// should be the first in the file as you don't want text and binary mixed in -// the same output file. -// -// Revision History -// 16Apr02 1.03 Added sector break, relocation flag output -// 02Apr02 1.02 Fixed bug in BOSC: it CAN be a short instruction. -// Added directives for 1130 and 1800 IPL output formats -// Added conditional assembly directives -// --------------------------------------------------------------------------------- - -#include -#include -#include -#include -#include -#include -#include - -// ---------------------------------------------------------------1------------------ -// DEFINITIONS -// --------------------------------------------------------------------------------- - -// I have found some IBM source code where @ and ' seem interchangable. -// Comment out this define to make @ and ' different in symbol names, keep to make equivalent - -#if defined(VMS) - # include /* to pick up 'unlink' */ -#endif - -#define BETWEEN(v,a,b) (((v) >= (a)) && ((v) <= (b))) -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) -#define MAX(a,b) (((a) >= (b)) ? (a) : (b)) - -#ifndef WIN32 - int strnicmp (char *a, char *b, int n); - int strcmpi (char *a, char *b); -#endif - -#define FIX_ATS - -#define DMSVERSION "V2M12" /* required 5 characters on sector break card col 67-71 */ - -#define DOLLAREXIT "/38" // hmmm, are these really fixed absolutely in all versions? -#define DOLLARDUMP "/3F" - -#define SYSTEM_TABLE "SYMBOLS.SYS" - -#define BOOL int -#define TRUE 1 -#define FALSE 0 - -#define VERSION "ASM1130 CROSS ASSEMBLER V1.08" - -#define ISTV 0x33 // magic number from DMS R2V12 monitorm symbol @ISTV - -#define MAXLITERALS 300 -#define MAXENTRIES 14 - -#define LINEFORMAT " %4ld | %s" -#define LEFT_MARGIN " |" - // XXXX XXXX XXXX XXXX XXXX XXXX - // org w1 w2 w3 w4 w5 - // XXXX 1111 2222 3333 4444 LLLL | - // 12345678901234567890123456789012 - -typedef enum {ABSOLUTE = 0, RELATIVE = 1, LIBF = 2, CALL = 3} RELOC; - -typedef struct tag_symbol { // symbol table entry: - char *name; // name of symbol - int value; // value (absolute) - int pass; // defined during pass # - int defined; // definition state, see #defines below - RELOC relative; // ABSOLUTE = absolute, RELATIVE = relative - struct tag_symbol *next; // next symbol in list - struct tag_xref *xrefs; // cross references -} SYMBOL, *PSYMBOL; - -#define S_UNDEFINED 0 // values of 'defined' -#define S_PROVISIONAL 1 // usually an expression with forward references -#define S_DEFINED 2 // ordering must be undef < prov < def - -typedef struct tag_xref { // cross reference entry - char *fname; // filename - int lno; // line number - BOOL definition; // true = definition, false = reference - struct tag_xref *next; // next reference -} XREF, *PXREF; - -typedef struct tag_expr { // expression result: absolute or relative - int value; - RELOC relative; -} EXPR; - -typedef enum {PROGTYPE_ABSOLUTE = 1, PROGTYPE_RELOCATABLE = 2, PROGTYPE_LIBF = 3, PROGTYPE_CALL = 4, - PROGTYPE_ISSLIBF = 5, PROGTYPE_ISSCALL = 6, PROGTYPE_ILS = 7} PROGTYPE; - -typedef enum {SUBTYPE_INCORE = 0, SUBTYPE_FORDISK = 1, SUBTYPE_ARITH = 2, - SUBTYPE_FORNONDISK = 3, SUBTYPE_FUNCTION=8} SUBTYPE; - -typedef enum {INTMODE_UNSPECIFIED = 0, INTMODE_MATCHREAL = 0x0080, INTMODE_ONEWORD = 0x0090} INTMODE; -typedef enum {REALMODE_UNSPECIFIED = 0, REALMODE_STANDARD = 0x0001, REALMODE_EXTENDED = 0x0002} REALMODE; - -#define OP_INDEXED 0x0300 // 1130 opcode modifier bits -#define OP_LONG 0x0400 -#define OP_INDIRECT 0x0080 - -typedef enum {OUTMODE_LOAD, OUTMODE_1130, OUTMODE_1800, OUTMODE_BINARY} OUTMODE; - -#ifdef WIN32 -# define OUTWRITEMODE "wb" // write outfile in binary mode -# define ENDLINE "\r\n" // explictly write CR/LF -#else -# define OUTWRITEMODE "w" // use native mode -# define ENDLINE "\n" -#endif - -// --------------------------------------------------------------------------------- -// GLOBALS -// --------------------------------------------------------------------------------- - -// command line syntax -char *usestr = -"Usage: asm1130 [-bpsvwxy] [-o[file]] [-l[file]] [-rN.M] file...\n\n" -"-b binary (relocatable format) output; default is simulator LOAD format\n" -"-p count passes required; no assembly output is created with this flag" -"-s add symbol table to listing\n" -"-v verbose mode\n" -"-w write system symbol table as SYMBOLS.SYS\n" -"-W same as -w but do not confirm overwriting previous file\n" -"-x add cross reference table to listing\n" -"-y preload system symbol table SYMBOLS.SYS\n" -"-o set output file; default is first input file + .out or .bin\n" -"-l create listing file; default is first input file + .lst\n" -"-r set dms version to VN RM for system SBRK cards"; - -BOOL verbose = FALSE; // verbose mode flag -BOOL tabformat = FALSE; // TRUE if tabs were seen in the file -int pass; // current assembler pass (1 or 2) -char curfn[256]; // current input file name -char progname[8]; // base name of primary input file -char *outfn = NULL; // output file name -int lno; // current input file line number -BOOL preload = FALSE; // preload system symbol table -BOOL savetable = FALSE; // write system symbol table -BOOL saveprompt = TRUE; // prompt before overwriting -int nerrors = 0; // count of errors -int nwarnings = 0; // count of warnings -FILE *fin = NULL; // current input file -FILE *fout = NULL; // output file stream -OUTMODE outmode = OUTMODE_LOAD; // output file mode -int outcols = 0; // columns written in using card output -int maxiplcols = 80; -char cardid[9]; // characters used for IPL card ID -FILE *flist = NULL; // listing file stream -char *listfn = NULL; // listing filename -BOOL do_list = FALSE; // flag: create listing -BOOL passcount = FALSE; // flag: count passes only -BOOL list_on = TRUE; // listing is currently enabled -BOOL do_xref = FALSE; // cross reference listing -BOOL do_syms = FALSE; // symbol table listing -BOOL ended = FALSE; // end of current file -BOOL hasforward = FALSE; // true if there are any forward references -char listline[350]; // output listing line -BOOL line_error; // already saw an error on current line -RELOC relocate = RELATIVE; // relocatable assembly mode -BOOL assembled = FALSE; // true if any output has been generated -int nwout; // number of words written on current line -int org = 0; // output address (origin) -int org_advanced; // if TRUE, * means instruction addr+(value) during evaluation -int pta = -1; // program transfer address -BOOL cexpr = FALSE; // "C" expression syntax -PSYMBOL symbols = NULL; // the symbol table (linear search) -BOOL check_control = TRUE; // check for control cards -PROGTYPE progtype = PROGTYPE_RELOCATABLE; // program type -INTMODE intmode = INTMODE_UNSPECIFIED; // integer mode -REALMODE realmode = REALMODE_UNSPECIFIED; // real mode -int nintlevels = 0; // # of interrupt levels for ISS -int intlevel_primary = 0; // primary level for ISS and level for ILS -int intlevel_secondary = 0; // secondary level for ISS -int iss_number = 0; // ISS number -PSYMBOL entry[MAXENTRIES]; // entries for subroutines -int nentries = 0; -int ndefined_files = 0; - -struct lit { // accumulated literals waiting to be output - int value; // constant value - int tagno; // constant symbol tag number (e.g. _L001) - BOOL hex; // constant was expressed in hex - BOOL even; // constant was operand of a double-width instruction (e.g. AD) -} literal[MAXLITERALS]; - -int n_literals = 0, lit_tag = 0; -BOOL requires_even_address; // target of current instruction -BOOL dmes_saved; // odd character left over from dmes ending in ' -int dmes_savew; -char opfield[256]; // extracted operand field from source line -char dmsversion[12] = DMSVERSION; // version number for SBRK cards -const char whitespace[] = " \t"; // whitespace - -int ascii_to_ebcdic_table[128] = -{ -// - 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f, -// - 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f, -// spac ! " # $ % & ' ( ) * + , - . / - 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61, -// 0 1 2 3 4 5 6 7 8 9 : ; < = > ? - 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f, -// @ A B C D E F G H I J K L M N O - 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6, -// P Q R S T U V W X Y Z [ \ ] & _ - 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d, -// a b c d e f g h i j k l m n o - 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96, -// p q r s t u v w x y z { | } ~ - 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07, -}; - -int ascii_to_1403_table[128] = -{ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f */ - 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, - 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, - 0x7f,0x7f,0x7f,0x7f,0x62,0x7f,0x15,0x0b, 0x57,0x2f,0x23,0x6d,0x16,0x61,0x6e,0x4c, - 0x49,0x40,0x01,0x02,0x43,0x04,0x45,0x46, 0x07,0x08,0x7f,0x7f,0x7f,0x4a,0x7f,0x7f, - 0x7f,0x64,0x25,0x26,0x67,0x68,0x29,0x2a, 0x6b,0x2c,0x58,0x19,0x1a,0x5b,0x1c,0x5d, - 0x5e,0x1f,0x20,0x0d,0x0e,0x4f,0x10,0x51, 0x52,0x13,0x54,0x7f,0x7f,0x7f,0x7f,0x7f, - 0x7f,0x64,0x25,0x26,0x67,0x68,0x29,0x2a, 0x6b,0x2c,0x58,0x19,0x1a,0x5b,0x1c,0x5d, - 0x5e,0x1f,0x20,0x0d,0x0e,0x4f,0x10,0x51, 0x52,0x13,0x54,0x7f,0x7f,0x7f,0x7f,0x7f -}; - -#include "../ibm1130_conout.h" /* conout_to_ascii_table */ -#include "../ibm1130_prtwheel.h" /* 1132 printer printwheel data */ - -// --------------------------------------------------------------------------------- -// PROTOTYPES -// --------------------------------------------------------------------------------- - -void bail (char *msg); -void flag (char *arg); -void proc (char *fname); -void startpass (int n); -void errprintf (char *fmt, ...); -void asm_error (char *fmt, ...); -void asm_warning (char *fmt, ...); -char *astring (char *str); -PSYMBOL lookup_symbol (char *name, BOOL define); -void add_xref (PSYMBOL s, BOOL definition); -int get_symbol (char *name); -void set_symbol (char *name, int value, int known, RELOC relative); -char * gtok (char **pc, char *tok); -char *skipbl (char *c); -void sym_list (void); -void xref_list (void); -void listhdr (void); -int getexpr (char *pc, BOOL undefined_ok, EXPR *expr); -void passreport (void); -void listout (BOOL reset); -void output_literals (BOOL eof); -char *upcase (char *str); -void prep_line (char *line); -int ascii_to_hollerith (int ch); -char *detab (char *str); -void preload_symbols (void); -void save_symbols (void); -void bincard_init (void); -void bincard_writecard (char *sbrk_text); -void bincard_writedata (void); -void bincard_flush (void); -void bincard_sbrk (char *line); -void bincard_setorg (int neworg); -void bincard_writew (int word, RELOC relative); -void bincard_endcard (void); -void handle_sbrk (char *line); -void bincard_typecard (void); -void namecode (unsigned short *words, char *tok); - -// --------------------------------------------------------------------------------- -// main routine -// --------------------------------------------------------------------------------- - -int main (int argc, char **argv) -{ - int i, sawfile = FALSE; - - for (i = 1; i < argc; i++) // process command line switches - if (*argv[i] == '-') - flag(argv[i]+1); - - startpass(1); // first pass, process files - - for (i = 1; i < argc; i++) - if (*argv[i] != '-') - proc(argv[i]), sawfile = TRUE; - - if (! sawfile) // should have seen at least one file - bail(usestr); - - if (passcount) { - passreport(); - return 0; - } - - startpass(2); // second pass, process files again - - for (i = 1; i < argc; i++) - if (*argv[i] != '-') - proc(argv[i]); - - if (outmode == OUTMODE_LOAD) { - if (pta >= 0) // write start address to the load file - fprintf(fout, "=%04x" ENDLINE, pta & 0xFFFF); - } - else - bincard_endcard(); - - if (flist) { - if (nerrors || nwarnings) { // summarize (or summarise) - if (nerrors == 0) - fprintf(flist, "There %s ", (nwarnings == 1) ? "was" : "were"); - else - fprintf(flist, "\nThere %s %d error%s %s", - (nerrors == 1) ? "was" : "were", nerrors, (nerrors == 1) ? "" : "s", nwarnings ? "and " : ""); - - if (nwarnings > 0) - fprintf(flist, "%d warning%s ", nwarnings, (nwarnings == 1) ? "" : "s"); - - fprintf(flist, "in this assembly\n"); - } - else - fprintf(flist, "\nThere were no errors in this assembly\n"); - } - - if (flist) { // finish the listing - if (pta >= 0) - fprintf(flist, "\nProgram transfer address = %04x\n", pta); - - if (do_xref) - xref_list(); - else if (do_syms) - sym_list(); - } - - if (savetable) - save_symbols(); - - return 0; // all done -} - -// --------------------------------------------------------------------------------- -// flag - process one command line switch -// --------------------------------------------------------------------------------- - -void flag (char *arg) -{ - int major, minor; - - while (*arg) { - switch (*arg++) { - case 'o': // output (load) file name - if (! *arg) - bail(usestr); - outfn = arg; - return; - - case 'p': - passcount = TRUE; - break; - - case 'v': // mumble while running - verbose = TRUE; - break; - - case 'x': // print cross reference table - do_xref = TRUE; - break; - - case 's': // print symbol table - do_syms = TRUE; - break; - - case 'l': // listing file name - listfn = (* arg) ? arg : NULL; - do_list = TRUE; - return; - - case 'W': - saveprompt = FALSE; - // fall through - case 'w': - savetable = TRUE; - break; - - case 'y': - preload = TRUE; - break; - - case 'b': - outmode = OUTMODE_BINARY; - break; - - case 'r': - if (sscanf(arg, "%d.%d", &major, &minor) != 2) - bail(usestr); - sprintf(dmsversion, "V%01.1dM%02.2d", major, minor); - return; - - default: - bail(usestr); - break; - } - } -} - -// --------------------------------------------------------------------------------- -// bail - print error message on stderr (only) and exit -// --------------------------------------------------------------------------------- - -void bail (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - -// --------------------------------------------------------------------------------- -// errprintf - print error message to stderr -// --------------------------------------------------------------------------------- - -void errprintf (char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); // get pointer to argument list - - vfprintf(stderr, fmt, args); // write errors to terminal (stderr) - - va_end(args); -} - -// --------------------------------------------------------------------------------- -// asm_error - report an error to listing file and to user's console -// --------------------------------------------------------------------------------- - -void asm_error (char *fmt, ...) -{ - va_list args; - - if (pass == 1) // only print on pass 2 - return; - - va_start(args, fmt); // get pointer to argument list - - fprintf(stderr, "E: %s (%d): ", curfn, lno); - vfprintf(stderr, fmt, args); // write errors to terminal (stderr) - putc('\n', stderr); - - if (flist != NULL && list_on) { - listout(FALSE); - line_error = TRUE; - - fprintf(flist, "**** Error: "); - vfprintf(flist, fmt, args); // write errors to listing file - putc('\n', flist); - } - - nerrors++; - va_end(args); -} - -// --------------------------------------------------------------------------------- -// asm_warning - same but warnings are not counted -// --------------------------------------------------------------------------------- - -void asm_warning (char *fmt, ...) -{ - va_list args; - - if (pass == 1) // only print on pass 2 - return; - - va_start(args, fmt); // get pointer to argument list - - fprintf(stderr, "W: %s (%d): ", curfn, lno); - vfprintf(stderr, fmt, args); // write errors to terminal (stderr) - putc('\n', stderr); - - if (flist != NULL && list_on) { - listout(FALSE); - line_error = TRUE; - - fprintf(flist, "**** Warning: "); - vfprintf(flist, fmt, args); // write errors to listing file - putc('\n', flist); - } - - nwarnings++; -} - -// --------------------------------------------------------------------------------- -// sym_list - print the symbol table -// --------------------------------------------------------------------------------- - -void sym_list (void) -{ - PSYMBOL s; - int n = 5; - - if (symbols == NULL || flist == NULL) - return; - - fprintf(flist, "\n=== SYMBOL TABLE ==============================================================\n"); - - for (s = symbols, n = 0; s != NULL; s = s->next) { - if (n >= 5) { - putc('\n', flist); - n = 0; - } - else if (n > 0) - fprintf(flist, " "); - - fprintf(flist, "%-6s ", s->name); - if (s->defined == S_DEFINED) - fprintf(flist, "%04x%s", s->value & 0xFFFF, s->relative ? "R" : " "); - else - fprintf(flist, "UUUU "); - - n++; - } - fprintf(flist, "\n"); -} - -// --------------------------------------------------------------------------------- -// passreport - report # of passes required for assembly on the 1130 -// --------------------------------------------------------------------------------- - -void passreport (void) -{ - PSYMBOL s; - - for (s = symbols; s != NULL; s = s->next) { - if (s->defined == S_UNDEFINED || s->defined == S_PROVISIONAL) { - printf("There are undefined symbols. Cannot determine pass requirement.\n"); - return; - } - } - - if (hasforward) - printf("There are forward references. Two passes are required.\n"); - else - printf("There are no forward references. Only one pass is required.\n"); -} - -// --------------------------------------------------------------------------------- -// xref_list - print the cross-reference table -// --------------------------------------------------------------------------------- - -void xref_list (void) -{ - int n = 0; - PXREF x; - PSYMBOL s; - - if (flist == NULL || symbols == NULL) - return; - - fprintf(flist, "\n=== CROSS REFERENCES ==========================================================\n"); - - if (symbols == NULL || flist == NULL) - return; - - fprintf(flist, "Name Val Defd Referenced\n"); - - for (s = symbols; s != NULL; s = s->next) { - fprintf(flist, "%-5s %04x%s", s->name, s->value & 0xFFFF, s->relative ? "R" : " "); - - for (x = s->xrefs; x != NULL; x = x->next) - if (x->definition) - break; - - if (x == NULL) - fprintf(flist, "----"); - else - fprintf(flist, " %4d", x->lno); - - for (n = 0, x = s->xrefs; x != NULL; x = x->next) { - if (x->definition) - continue; - - if (n >= 12) { - n = 0; - fprintf(flist, "\n "); - } - fprintf(flist, " %4d", x->lno); - n++; - } - putc('\n', flist); - } -} - -// --------------------------------------------------------------------------------- -// listhdr - print a banner header in the listing file. Since it's not paginated -// at this time, this is not used often. -// --------------------------------------------------------------------------------- - -void listhdr (void) -{ - time_t t; - - time(&t); - fprintf(flist, "%s -- %s -- %s\n", VERSION, dmsversion, ctime(&t)); -} - -// --------------------------------------------------------------------------------- -// astring - allocate a copy of a string -// --------------------------------------------------------------------------------- - -char *astring (char *str) -{ - static char *s = NULL; - - if (s != NULL) - if (strcmp(s, str) == 0) // if same as immediately previous allocation - return s; // return same pointer (why did I do this?) - - if ((s = malloc(strlen(str)+1)) == NULL) - bail("out of memory"); - - strcpy(s, str); - return s; -} - -// --------------------------------------------------------------------------------- -// lookup_symbol - get pointer to a symbol. -// If define is TRUE, creates and marks 'undefined' if not previously defined. -// --------------------------------------------------------------------------------- - -PSYMBOL lookup_symbol (char *name, BOOL define) -{ - PSYMBOL s, n, prv = NULL; - int c; - char *at; - - if (strlen(name) > 5) { // (sigh) - asm_error("Symbol '%s' is longer than 5 letters", name); - name[5] = '\0'; - } - -#ifdef FIX_ATS - while ((at = strchr(name, '@')) != NULL) - *at = '\''; -#endif - // search sorted list of symbols - for (s = symbols; s != NULL; prv = s, s = s->next) { - c = strcmpi(s->name, name); - if (c == 0) - return s; - if (c > 0) - break; - } - - if (! define) - return NULL; // not found - - if ((n = malloc(sizeof(SYMBOL))) == NULL) - bail("out of memory"); - - n->name = astring(name); // symbol was undefined -- add it now - n->value = 0; - n->defined = FALSE; - n->xrefs = NULL; - n->defined = FALSE; - - n->next = s; // link in alpha order - - if (prv == NULL) // we stopped before first item in list - symbols = n; - else - prv->next = n; // insert after item before place we stopped - - return n; -} - -// --------------------------------------------------------------------------------- -// add_xref - add a cross reference entry to a symbol -// --------------------------------------------------------------------------------- - -void add_xref (PSYMBOL s, BOOL definition) -{ - PXREF x, prv = NULL, n; - - if (pass == 1 || ! do_xref) // define only during 2nd pass and only if listing was requested - return; - - for (x = s->xrefs; x != NULL; prv = x, x = x->next) - if (strcmpi(x->fname, curfn) == 0 && x->lno == lno) - return; // ignore multiple refs on same line - - if ((n = malloc(sizeof(XREF))) == NULL) - bail("out of memory"); - - n->fname = astring(curfn); - n->lno = lno; - n->definition = definition; - - n->next = x; // link at end of existing list - - if (prv == NULL) - s->xrefs = n; - else - prv->next = n; -} - -// --------------------------------------------------------------------------------- -// get_symbol - get a symbol value, defining if necessary -// --------------------------------------------------------------------------------- - -int get_symbol (char *name) -{ - PSYMBOL s; - - s = lookup_symbol(name, TRUE); // lookup, define if necessary - - if (pass == 2) // should be defined by now - if (! s->defined) - asm_error("Symbol '%s' is undefined", name); - - add_xref(s, FALSE); // note the reference - - return s->value; -} - -// --------------------------------------------------------------------------------- -// set_symbol - set a symbol value. Known = TRUE means we really know the value; -// FALSE means we're calculating it with forward referenced values or something like -// that. -// --------------------------------------------------------------------------------- - -void set_symbol (char *name, int value, int known, RELOC relative) -{ - PSYMBOL s; - char *at; - - if (strlen(name) > 5) { - asm_error("Symbol '%s' is longer than 5 letters", name); - name[5] = '\0'; - } - -#ifdef FIX_ATS - while ((at = strchr(name, '@')) != NULL) - *at = '\''; -#endif - - s = lookup_symbol(name, TRUE); - - if (s->defined == S_DEFINED) // once defined, it should not change - if (s->value != value) - asm_error("Symbol '%s' %s", name, (s->pass == pass) ? "is multiply defined" : "changed between passes"); - - s->value = value; - s->relative = relative; - s->defined = known ? S_DEFINED : S_PROVISIONAL; - s->pass = pass; - - if (! known) - hasforward = TRUE; - - add_xref(s, TRUE); // record the place of definition -} - -// --------------------------------------------------------------------------------- -// skipbl - return pointer to first nonblank character in string s -// --------------------------------------------------------------------------------- - -char *skipbl (char *s) -{ - while (*s && *s <= ' ') - s++; - - return s; -} - -// --------------------------------------------------------------------------------- -// gtok - extracts a whitespace-delimited token from the string pointed to by *pc; -// stores the token into the buffer tok and returns pointer to same. Returns NULL -// when there are no tokens. Best to call repeatedly with a pointer to the source -// buffer, e.g. -// char *pbuf = buf; -// while (gtok(&pbuf, token) != NULL) ... -// --------------------------------------------------------------------------------- - -char * gtok (char **pc, char *tok) -{ - char *s = *pc, *otok = tok; - - while (*s && *s <= ' ') // skip blanks - s++; - - if (! *s) { // no tokens to be found - *tok = '\0'; - *pc = s; - return NULL; - } - - while (*s > ' ') // save nonblanks into 'tok' - *tok++ = *s++; - - *tok = '\0'; // terminate - *pc = s; // adjust caller's pointer - - return otok; // return pointer to token -} - -// listing format: -// -// ADDR CODE SOURCE -// 0000 0000 0000 0000 0000 | XXXXXXXXXXXXXXXXX - -// --------------------------------------------------------------------------------- -// trim - remove trailing whitespace from string s -// --------------------------------------------------------------------------------- - -char *trim (char *s) -{ - char *os = s, *nb; - - for (nb = s-1; *s; s++) - if (*s > ' ') - nb = s; - - nb[1] = '\0'; - return os; -} - -// --------------------------------------------------------------------------------- -// listout - emit current constructed output listing line held in "listline" and -// if "reset" is true, prepare listline for second and subsequent listing lines -// for a given input statement. -// --------------------------------------------------------------------------------- - -void listout (BOOL reset) -{ - if (flist && list_on && ! line_error) { - trim(listline); - fputs(listline, flist); - putc('\n', flist); - if (reset) - sprintf(listline, LEFT_MARGIN, org); - } -} - -// --------------------------------------------------------------------------------- -// storew - store a word in the output medium (hex or binary file). Most of the time -// writew is used. Advances the origin! -// --------------------------------------------------------------------------------- - -void storew (int word, RELOC relative) -{ - if (pass == 2) { // save in output (load) file. - switch (outmode) { - case OUTMODE_BINARY: - bincard_writew(word, relative); - break; - - case OUTMODE_LOAD: - fprintf(fout, " %04x%s" ENDLINE, word & 0xFFFF, - (relative == ABSOLUTE) ? "" : (relative == RELATIVE) ? "R" : - (relative == LIBF) ? "L" : (relative == CALL) ? "$" : "?"); - break; - - default: - bail("in storew, can't happen"); - } - } - - if (relative != LIBF) - org++; - - assembled = TRUE; // remember that we wrote something -} - -// --------------------------------------------------------------------------------- -// setw - store a word value in the current listing output line in position 'pos'. -// --------------------------------------------------------------------------------- - -void setw (int pos, int word, RELOC relative) -{ - char tok[10], *p; - int i; - - if (flist == NULL || ! list_on) - return; - - sprintf(tok, "%04x", word & 0xFFFF); - - for (i = 0, p = listline + 5*pos; i < 4; i++) - p[i] = tok[i]; - - if (relative == RELATIVE) - p[i] = 'R'; - else if (relative != ABSOLUTE) - p[i] = '*'; -} - -// --------------------------------------------------------------------------------- -// writew - emit an assembled word value. Words are also displayed in the listing file. -// if relative is true, a relocation entry should be recorded. -// --------------------------------------------------------------------------------- - -void writew (int word, RELOC relative) -{ // first, the listing stuff... - if (nwout == 0) { // on first output word, display address in column 0 - setw(0, org, FALSE); - } - else if (nwout >= 4) { // if 4 words have already been written, start new line - listout(TRUE); - nwout = 0; - } - - nwout++; - setw(nwout, word, relative); // display word in the listing line - - storew(word, relative); // write it to the output medium -} - -// --------------------------------------------------------------------------------- -// setorg - take note of new load address -// --------------------------------------------------------------------------------- - -void setorg (int neworg) -{ - if (pass == 2) { - setw(0, neworg, FALSE); // display in listing file in column 0 - - if (outmode == OUTMODE_LOAD) { // write new load address to the output file - fprintf(fout, "@%04x%s" ENDLINE, neworg & 0xFFFF, relocate ? "R" : ""); - } - else { - bincard_setorg(neworg); - } - } - - org = neworg; -} - -// --------------------------------------------------------------------------------- -// org_even - force load address to an even address -// --------------------------------------------------------------------------------- - -void org_even (void) -{ - if (org & 1) - setorg(org+1); -} - -// --------------------------------------------------------------------------------- -// tabtok - get the token in tab-delimited column number i, from source string c, -// saving in string 'tok'. If save is nonnull, we copy the entire remainder of -// the input string in buffer 'save' (in contrast to 'tok' which gets only the -// first whitespace delimited token). -// --------------------------------------------------------------------------------- - -void tabtok (char *c, char *tok, int i, char *save) -{ - *tok = '\0'; - - while (--i >= 0) { // skip to i'th tab-delimited field - if ((c = strchr(c, '\t')) == NULL) { - if (save) // was none - *save = '\0'; - return; - } - c++; - } - - while (*c == ' ') // skip leading blanks - c++; - - if (save != NULL) // save copy of entire remainder - strcpy(save, c); - - while (*c > ' ') { // take up to any whitespace - if (*c == '(') { // if we start with a paren, take all up to closing paren including spaces - while (*c && *c != ')') - *tok++ = *c++; - } - else if (*c == '.') { // period means literal character following - *tok++ = *c++; - if (*c) - *tok++ = *c++; - } - else - *tok++ = *c++; - } - - *tok = '\0'; -} - -// --------------------------------------------------------------------------------- -// coltok - extract a token from string c, saving to buffer tok, by examining -// columns ifrom through ito only. If save is nonnull, the entire remainder -// of the input from ifrom to the end is saved there. In this routine -// if condense is true, we save all nonwhite characters in the column range; -// not the usual thing. This helps us coalesce the format, tag, & index things -// nto one string for the simple minded parser. If condense is FALSE, we terminate -// on the first nonblank, except that if we start with a (, we take up to ) and -// then terminate on a space. -// -// ifrom and ito on entry are column numbers, not indices; we change that right away -// --------------------------------------------------------------------------------- - -void coltok (char *c, char *tok, int ifrom, int ito, BOOL condense, char *save) -{ - char *otok = tok; - int i; - - ifrom--; - ito--; - - for (i = 0; i < ifrom; i++) { - if (c[i] == '\0') { // line ended before this column - *tok = '\0'; - if (save) - *save = '\0'; - return; - } - } - - if (save) // save from ifrom on - strcpy(save, c+i); - - if (condense) { - for (; i <= ito; i++) { // save only nonwhite characters - if (c[i] > ' ') - *tok++ = c[i]; - } - } - else { - if (c[i] == ' ' && save != NULL)// if it starts with a space, it's empty - *save = '\0'; - - while (i <= ito) { // take up to any whitespace - if (c[i] <= ' ') - break; - else if (c[i] == '(') { // starts with paren? take to close paren - while (i <= ito && c[i]) { - if ((*tok++ = c[i++]) == ')') - break; - } - } - else if (c[i] == '.') { // period means literal character following - *tok++ = c[i++]; - if (i <= ito && c[i]) - *tok++ = c[i++]; - } - else - *tok++ = c[i++]; - } - } - - *tok = '\0'; - trim(otok); -} - -// --------------------------------------------------------------------------------- -// opcode table -// --------------------------------------------------------------------------------- - -// modifiers for the opcode definition table: - -#define L "L" // long -#define X "X" // absolute displacement -#define I "I" // indirect -#define IDX "0123" // indexed (some LDX commands in the DMS source say LDX L0, so accept 0 -#define E "E" // even address -#define NONE "" -#define ALL L X I IDX // hope non-Microsoft C accepts and concatenates strings like this -#define ANY "\xFF" -#define NUMS "0123456789" - -#define IS_DBL 0x0001 // double word operand implies even address -#define IS_ABS 0x0002 // always uses absolute addressing mode (implied X) -#define NO_IDX 0x0004 // even with 1 or 2 modifier, this is not really indexed (for STX/LDX) -#define NO_ARGS 0x0008 // statement takes no arguments -#define TRAP 0x1000 // debug this instruction - -struct tag_op { // OPCODE TABLE - char *mnem; - int opcode; - void (*handler)(struct tag_op *op, char *label, char *mods, char *arg); - char *mods_allowed; - char *mods_implied; - int flags; -}; - // special opcode handlers -void std_op (struct tag_op *op, char *label, char *mods, char *arg); -void b_op (struct tag_op *op, char *label, char *mods, char *arg); -void bsc_op (struct tag_op *op, char *label, char *mods, char *arg); -void bsi_op (struct tag_op *op, char *label, char *mods, char *arg); -void mdx_op (struct tag_op *op, char *label, char *mods, char *arg); -void shf_op (struct tag_op *op, char *label, char *mods, char *arg); - -void x_aif (struct tag_op *op, char *label, char *mods, char *arg); -void x_aifb (struct tag_op *op, char *label, char *mods, char *arg); -void x_ago (struct tag_op *op, char *label, char *mods, char *arg); -void x_agob (struct tag_op *op, char *label, char *mods, char *arg); -void x_anop (struct tag_op *op, char *label, char *mods, char *arg); -void x_abs (struct tag_op *op, char *label, char *mods, char *arg); -void x_call (struct tag_op *op, char *label, char *mods, char *arg); -void x_dsa (struct tag_op *op, char *label, char *mods, char *arg); -void x_file (struct tag_op *op, char *label, char *mods, char *arg); -void x_link (struct tag_op *op, char *label, char *mods, char *arg); -void x_libf (struct tag_op *op, char *label, char *mods, char *arg); -void x_org (struct tag_op *op, char *label, char *mods, char *arg); -void x_opt (struct tag_op *op, char *label, char *mods, char *arg); -void x_ces (struct tag_op *op, char *label, char *mods, char *arg); -void x_bes (struct tag_op *op, char *label, char *mods, char *arg); -void x_bss (struct tag_op *op, char *label, char *mods, char *arg); -void x_dc (struct tag_op *op, char *label, char *mods, char *arg); -void x_dec (struct tag_op *op, char *label, char *mods, char *arg); -void x_ebc (struct tag_op *op, char *label, char *mods, char *arg); -void x_end (struct tag_op *op, char *label, char *mods, char *arg); -void x_ent (struct tag_op *op, char *label, char *mods, char *arg); -void x_epr (struct tag_op *op, char *label, char *mods, char *arg); -void x_equ (struct tag_op *op, char *label, char *mods, char *arg); -void x_exit (struct tag_op *op, char *label, char *mods, char *arg); -void x_ils (struct tag_op *op, char *label, char *mods, char *arg); -void x_iss (struct tag_op *op, char *label, char *mods, char *arg); -void x_libr (struct tag_op *op, char *label, char *mods, char *arg); -void x_lorg (struct tag_op *op, char *label, char *mods, char *arg); -void x_dmes (struct tag_op *op, char *label, char *mods, char *arg); -void x_dn (struct tag_op *op, char *label, char *mods, char *arg); -void x_dump (struct tag_op *op, char *label, char *mods, char *arg); -void x_pdmp (struct tag_op *op, char *label, char *mods, char *arg); -void x_hdng (struct tag_op *op, char *label, char *mods, char *arg); -void x_list (struct tag_op *op, char *label, char *mods, char *arg); -void x_spac (struct tag_op *op, char *label, char *mods, char *arg); -void x_spr (struct tag_op *op, char *label, char *mods, char *arg); -void x_ejct (struct tag_op *op, char *label, char *mods, char *arg); -void x_trap (struct tag_op *op, char *label, char *mods, char *arg); -void x_xflc (struct tag_op *op, char *label, char *mods, char *arg); - -struct tag_op ops[] = { - ".OPT", 0, x_opt, NONE, NONE, 0, // non-IBM extensions - "TRAP", 0, x_trap, NONE, NONE, 0, // assembler breakpoint trap - ".CES", 0, x_ces, NONE, NONE, 0, // lets us specify simulated console entry switch values for startup - - "ABS", 0, x_abs, NONE, NONE, 0, - "BES", 0, x_bes, E, NONE, 0, // standard pseudo-ops - "BSS", 0, x_bss, E, NONE, 0, - "DC", 0, x_dc, NONE, NONE, 0, - "DEC", 0, x_dec, E, E, IS_DBL, - "DMES", 0, x_dmes, ANY, NONE, 0, - "DN", 0, x_dn, NONE, NONE, 0, - "DSA", 0, x_dsa, NONE, NONE, 0, - "DUMP", 0, x_dump, NONE, NONE, 0, - "EBC", 0, x_ebc, NONE, NONE, 0, - "EJCT", 0, x_ejct, NONE, NONE, 0, - "END", 0, x_end, NONE, NONE, 0, - "ENT", 0, x_ent, NONE, NONE, 0, - "EPR", 0, x_epr, NONE, NONE, 0, - "EQU", 0, x_equ, NONE, NONE, 0, - "EXIT", 0, x_exit, NONE, NONE, 0, // alias for call $exit since we don't have macros yet - "FILE", 0, x_file, NONE, NONE, 0, - "HDNG", 0, x_hdng, ANY, NONE, 0, - "ILS", 0, x_ils, NUMS, NONE, 0, - "ISS", 0, x_iss, NUMS, NONE, 0, - "LIBF", 0, x_libf, NONE, NONE, 0, - "LIBR", 0, x_libr, NONE, NONE, 0, - "LINK", 0, x_link, NONE, NONE, 0, - "LIST", 0, x_list, NONE, NONE, 0, - "LORG", 0, x_lorg, NONE, NONE, 0, - "ORG", 0, x_org, NONE, NONE, 0, - "PDMP", 0, x_pdmp, NONE, NONE, 0, - "SPAC", 0, x_spac, NONE, NONE, 0, - "SPR", 0, x_spr, NONE, NONE, 0, - "XFLC", 0, x_xflc, NONE, NONE, 0, - - "A", 0x8000, std_op, ALL, NONE, 0, // standard addressing ops - "AD", 0x8800, std_op, ALL, NONE, IS_DBL, - "AND", 0xE000, std_op, ALL, NONE, 0, - "BSI", 0x4000, bsi_op, ALL, NONE, 0, - "CALL", 0x4000, x_call, ALL, L, 0, // alias for BSI L, or external call - "D" , 0xA800, std_op, ALL, NONE, 0, - "EOR", 0xF000, std_op, ALL, NONE, 0, - "LD", 0xC000, std_op, ALL, NONE, 0, - "LDD", 0xC800, std_op, ALL, NONE, IS_DBL, - "LDS", 0x2000, std_op, NONE, NONE, IS_ABS, - "LDX", 0x6000, std_op, ALL, NONE, IS_ABS|NO_IDX, - "M", 0xA000, std_op, ALL, NONE, 0, - "MDX", 0x7000, mdx_op, ALL, NONE, 0, - "MDM", 0x7000, mdx_op, L, L, 0, // like MDX L - "NOP", 0x1000, std_op, NONE, NONE, NO_ARGS, - "OR", 0xE800, std_op, ALL, NONE, 0, - "S", 0x9000, std_op, ALL, NONE, 0, - "SD", 0x9800, std_op, ALL, NONE, IS_DBL, - "STD", 0xD800, std_op, ALL, NONE, IS_DBL, - "STO", 0xD000, std_op, ALL, NONE, 0, - "STS", 0x2800, std_op, ALL, NONE, 0, - "STX", 0x6800, std_op, ALL, NONE, NO_IDX, - "WAIT", 0x3000, std_op, NONE, NONE, NO_ARGS, - "XCH", 0x1810, std_op, NONE, NONE, 0, // same as RTE 16 - "XIO", 0x0800, std_op, ALL, NONE, IS_DBL, - - "BSC", 0x4800, bsc_op, ALL, NONE, 0, // branch family - "BOSC", 0x4840, bsc_op, ALL, NONE, 0, // is BOSC always long form? No. - "SKP", 0x4800, bsc_op, NONE, NONE, 0, // alias for BSC one word version - - "B", 0x4800, b_op, ALL, NONE, 0, // alias for MDX or BSC L - "BC", 0x4802, std_op, ALL, L, 0, // alias for BSC L - "BN", 0x4828, std_op, ALL, L, 0, // alias for BSC L - "BNN", 0x4810, std_op, ALL, L, 0, // alias for BSC L - "BNP", 0x4808, std_op, ALL, L, 0, // alias for BSC L - "BNZ", 0x4820, std_op, ALL, L, 0, // alias for BSC L - "BO", 0x4801, std_op, ALL, L, 0, // alias for BSC L - "BOD", 0x4840, std_op, ALL, L, 0, // alias for BSC L - "BP", 0x4830, std_op, ALL, L, 0, // alias for BSC L - "BZ", 0x4818, std_op, ALL, L, 0, // alias for BSC L - - "RTE", 0x18C0, shf_op, IDX X, X, 0, // shift family - "SLA", 0x1000, shf_op, IDX X, X, 0, - "SLC", 0x10C0, shf_op, IDX X, X, 0, - "SLCA", 0x1040, shf_op, IDX X, X, 0, - "SLT", 0x1080, shf_op, IDX X, X, 0, - "SRA", 0x1800, shf_op, IDX X, X, 0, - "SRT", 0x1880, shf_op, IDX X, X, 0, - - "AIF", 0, x_aif, NONE, NONE, 0, // assemble if - "AIFB", 0, x_aifb, NONE, NONE, 0, // assemble if - "AGO", 0, x_ago, NONE, NONE, 0, // assemble goto - "AGOB", 0, x_agob, NONE, NONE, 0, // assemble goto - "ANOP", 0, x_anop, NONE, NONE, 0, // assemble target - - NULL // end of table -}; - -// --------------------------------------------------------------------------------- -// addextn - apply file extension 'extn' to filename 'fname' and put result in 'outbuf' -// if outbuf is NULL, we allocate a buffer -// --------------------------------------------------------------------------------- - -char *addextn (char *fname, char *extn, char *outbuf) -{ - char *buf, line[500], *c; - - buf = (outbuf == NULL) ? line : outbuf; - - strcpy(buf, fname); // create listfn from first source filename (e.g. xxx.lst); - if ((c = strrchr(buf, '\\')) == NULL) - if ((c = strrchr(buf, '/')) == NULL) - if ((c = strrchr(buf, ':')) == NULL) - c = buf; - - if ((c = strrchr(c, '.')) == NULL) - strcat(buf, extn); - else - strcpy(c, extn); - - return (outbuf == NULL) ? astring(line) : outbuf; -} - -// --------------------------------------------------------------------------------- -// controlcard - examine an assembler control card (* in column 1) -// --------------------------------------------------------------------------------- - -BOOL controlcard (char *line) -{ - if (strnicmp(line, "*LIST", 5) == 0) { // turn on listing file even if not specified on command line - do_list = list_on = TRUE; - return TRUE; - } - - if (strnicmp(line, "*XREF", 5) == 0) { - do_xref = TRUE; - return TRUE; - } - - if (strnicmp(line, "*PRINT SYMBOL TABLE", 19) == 0) { - do_syms = TRUE; - return TRUE; - } - - if (strnicmp(line, "*SAVE SYMBOL TABLE", 18) == 0) { - savetable = TRUE; - return TRUE; - } - - if (strnicmp(line, "*SYSTEM SYMBOL TABLE", 20) == 0) { - preload = TRUE; - preload_symbols(); - return TRUE; - } - - return FALSE; -} - -// --------------------------------------------------------------------------------- -// stuff - insert characters into a line -// --------------------------------------------------------------------------------- - -void stuff (char *buf, char *tok, int maxchars) -{ - while (*tok) { - *buf++ = *tok++; - - if (maxchars) - if (--maxchars <= 0) - break; - } -} - -// --------------------------------------------------------------------------------- -// format_line - construct a source code input line from components -// --------------------------------------------------------------------------------- - -void format_line (char *buf, char *label, char *op, char *mods, char *args, char *remarks) -{ - int i; - - if (tabformat) { - sprintf(buf, "%s\t%s\t%s\t%s\t%s", label, op, mods, args, remarks); - } - else { - for (i = 0; i < 72; i++) - buf[i] = ' '; - buf[i] = '\0'; - - stuff(buf+20, label, 5); - stuff(buf+26, op, 4); - stuff(buf+31, mods, 2); - stuff(buf+34, args, 72-34); - } -} - -// --------------------------------------------------------------------------------- -// lookup_op - find an opcode -// --------------------------------------------------------------------------------- - -struct tag_op * lookup_op (char *mnem) -{ - struct tag_op *op; - int i; - - for (op = ops; op->mnem != NULL; op++) { - if ((i = strcmp(op->mnem, mnem)) == 0) - return op; - - if (i > 0) - break; - } - return NULL; -} - -// --------------------------------------------------------------------------------- -// bincard - routines to write IBM 1130 Card object format -// --------------------------------------------------------------------------------- - -unsigned short bincard[54]; // the 54 data words that can fit on a binary format card -char binflag[45]; // the relocation flags of the 45 buffered object words (0, 1, 2, 3) -int bincard_n = 0; // number of object words stored in bincard (0-45) -int bincard_seq = 0; // card output sequence number -int bincard_org = 0; // origin of current card-full -int bincard_maxaddr = 0; -BOOL bincard_first = TRUE; // TRUE when we're to write the program type card - -// bincard_init - prepare a new object data output card - -void bincard_init (void) -{ - memset(bincard, 0, sizeof(bincard)); // clear card data - memset(binflag, 0, sizeof(binflag)); // clear relocation data - bincard_n = 0; // no data - bincard[0] = bincard_org; // store load address - bincard_maxaddr = MAX(bincard_maxaddr, bincard_org-1); // save highest address written-to (this may be a BSS) -} - -// binard_writecard - emit a card. sbrk_text = NULL for normal data cards, points to comment text for sbrk card -// note: sbrk_text if not NULL MUST be a writeable buffer of at LEAST 71 characters - -void bincard_writecard (char *sbrk_text) -{ - unsigned short binout[80]; - char ident[12]; - int i, j; - - if (sbrk_text != NULL) { // sbrk card has 4 binary words followed by comment text - for (j = 66; j < 71; j++) // be sure input columns 67..71 are nonblank (have version number) - if (sbrk_text[j] <= ' ') - break; - - if (j < 71) // sbrk card didn't have the info, stuff in current release - for (j = 0; j < 5; j++) - sbrk_text[66+j] = dmsversion[j]; - - binout[0] = 0; - binout[1] = 0; - binout[2] = 0; - binout[3] = 0x1000; - - sbrk_text += 5; // start at the real column 6 (after *SBRK - for (j = 5; j < 72; j++) - binout[j] = (*sbrk_text) ? ascii_to_hollerith(*sbrk_text++) : 0; - - } - else { // binary card format packs 54 words into 72 columns - for (i = j = 0; i < 54; i += 3, j += 4) { - binout[j ] = ( bincard[i] & 0xFFF0); - binout[j+1] = ((bincard[i] << 12) & 0xF000) | ((bincard[i+1] >> 4) & 0x0FF0); - binout[j+2] = ((bincard[i+1] << 8) & 0xFF00) | ((bincard[i+2] >> 8) & 0x00F0); - binout[j+3] = ((bincard[i+2] << 4) & 0xFFF0); - } - } - - sprintf(ident, "%08ld", ++bincard_seq); // append sequence text - memmove(ident, progname, MIN(strlen(progname), 4)); - - for (i = 0; i < 8; i++) - binout[j++] = ascii_to_hollerith(ident[i]); - - fwrite(binout, sizeof(binout[0]), 80, fout); // write card image -} - -// binard_writedata - emit an object data card - -void bincard_writedata (void) -{ - unsigned short rflag = 0; - int i, j, nflag = 0; - - bincard[1] = 0; // checksum - bincard[2] = 0x0A00 | bincard_n; // data card type + word count - - for (i = 0, j = 3; i < bincard_n; i++) { // construct relocation indicator bitmap - if (nflag == 8) { - bincard[j++] = rflag; - rflag = 0; - nflag = 0; - } - rflag = (rflag << 2) | (binflag[i] & 3); - nflag++; - } - - if (nflag > 0) - bincard[j] = rflag << (16 - 2*nflag); - - bincard_writecard(FALSE); // emit the card -} - -// bincard_flush - flush any pending binary data - -void bincard_flush (void) -{ - if (bincard_n > 0) - bincard_writedata(); - - bincard_init(); -} - -// bincard_sbrk - emit an SBRK card - -void bincard_sbrk (char *line) -{ - if (bincard_first) - bincard_typecard(); - else - bincard_flush(); - - bincard_writecard(line); -} - -// bincard_setorg - set the origin - -void bincard_setorg (int neworg) -{ - bincard_org = neworg; // set origin for next card - bincard_flush(); // flush any current data & store origin -} - -// bincard_endcard - write end of program card - -void bincard_endcard (void) -{ - bincard_flush(); - - bincard[0] = (bincard_maxaddr + 2) & ~1; // effective length: add 1 to max origin, then 1 more to round up - bincard[1] = 0; - bincard[2] = 0x0F00; - bincard[3] = pta & 0xFFFF; - - bincard_writecard(NULL); -} - -// bincard_typecard - write the program type - -void bincard_typecard (void) -{ - int i; - - if (! bincard_first) - return; - - bincard_first = FALSE; - - memset(bincard, 0, sizeof(bincard)); - - bincard[2] = (unsigned short) ((progtype << 8) | intmode | realmode); - -// all indices not listed are documented as 'reserved' - - switch (progtype) { - case PROGTYPE_ABSOLUTE: - case PROGTYPE_RELOCATABLE: -// bincard[ 4] = 0; // length of common (fortran only) - bincard[ 5] = 0x0003; -// bincard[ 6] = 0; // length of work area (fortran only) - bincard[ 8] = ndefined_files; - namecode(&bincard[9], progname); - bincard[11] = (pta < 0) ? 0 : pta; - break; - - case PROGTYPE_LIBF: - case PROGTYPE_CALL: - bincard[ 5] = 3*nentries; - for (i = 0; i < nentries; i++) { - namecode(&bincard[9+3*i], entry[i]->name); - bincard[11+3*i] = entry[i]->value; - } - break; - - case PROGTYPE_ISSLIBF: - case PROGTYPE_ISSCALL: - bincard[ 5] = 6+nintlevels; - namecode(&bincard[9], entry[0]->name); - bincard[11] = entry[0]->value; - bincard[12] = iss_number + ISTV; // magic number ISTV is 0x33 in DMS R2V12 - bincard[13] = iss_number; - bincard[14] = nintlevels; - bincard[15] = intlevel_primary; - bincard[16] = intlevel_secondary; - bincard[29] = 1; - break; - - case PROGTYPE_ILS: - bincard[ 2] = (unsigned short) (progtype << 8); - bincard[ 5] = 4; - bincard[12] = intlevel_primary; - break; - - default: - bail("in bincard_typecard, can't happen"); - } - - bincard[1] = 0; // checksum - - bincard_writecard(NULL); - - bincard_init(); -} - -// bincard_writew - write a word to the current output card. - -void bincard_writew (int word, RELOC relative) -{ - if (pass != 2) - return; - - if (bincard_first) - bincard_typecard(); - else if (bincard_n >= 45) // flush full card buffer - bincard_flush(); - - binflag[bincard_n] = relative & 3; // store relocation bits and data word - bincard[9+bincard_n++] = word; - - if (relative != LIBF) { - bincard_maxaddr = MAX(bincard_maxaddr, bincard_org); - bincard_org++; - } -} - -// writetwo - notification that we are about to write two words which must stay together - -void writetwo (void) -{ - if (pass == 2 && outmode == OUTMODE_BINARY && bincard_n >= 44) - bincard_flush(); -} - -// handle_sbrk - handle an SBRK directive. -// This was not part of the 1130 assembler; they assembled DMS on a 360 - -void handle_sbrk (char *line) -{ - char rline[90]; - - if (pass != 2) - return; - - strncpy(rline, line, 81); // get a copy and pad it if necessary to 80 characters - rline[80] = '\0'; - while (strlen(rline) < 80) - strcat(rline, " "); - - switch (outmode) { - case OUTMODE_LOAD: - fprintf(fout, "#SBRK%s\n", trim(rline+5)); - - case OUTMODE_BINARY: - bincard_sbrk(rline); - break; - - default: - bail("in handle_sbrk, can't happen"); - } -} - -// --------------------------------------------------------------------------------- -// namecode - turn a string into a two-word packed name -// --------------------------------------------------------------------------------- - -void namecode (unsigned short *words, char *tok) -{ - long val = 0; - int i, ch; - - for (i = 0; i < 5; i++) { // pick up bits - if (*tok) - ch = *tok++; - else - ch = ' '; - - val = (val << 6) | (ascii_to_ebcdic_table[ch] & 0x3F); - } - - words[0] = (unsigned short) (val >> 16); - words[1] = (unsigned short) val; -} - -// --------------------------------------------------------------------------------- -// parse_line - parse one input line. -// --------------------------------------------------------------------------------- - -void parse_line (char *line) -{ - char label[100], mnem[100], arg[200], mods[20], *c; - struct tag_op *op; - - if (line[0] == '/' && line[1] == '/') // job control card? probably best to ignore it - return; - - if (line[0] == '*') { // control card comment or comment in tab-format file - if (check_control) // pay attention to control cards only at top of file - if (! controlcard(line)) - check_control = FALSE; // first non-control card shuts off sensitivity to them - - if (strnicmp(line+1, "SBRK", 4) == 0) - handle_sbrk(line); - - return; - } - - check_control = FALSE; // non-control card, consider them no more - - label[0] = '\0'; // prepare to extract fields - mods[0] = '\0'; - mnem[0] = '\0'; - arg[0] = '\0'; - - if (tabformat || strchr(line, '\t') != NULL) { // if input line has tabs, parse loosely - tabformat = TRUE; // this is a tab-formatted file - - for (c = line; *c && *c <= ' '; c++) // find first nonblank - ; - - if (*c == '*' || ! *c) // ignore as a comment - return; - - tabtok(line, label, 0, NULL); - tabtok(line, mnem, 1, NULL); - tabtok(line, mods, 2, NULL); - tabtok(line, arg, 3, opfield); - } - else { // if no tabs, use strict card-column format - if (line[20] == '*') // comment - return; - - line[72] = '\0'; // clip off sequence - - coltok(line, label, 21, 25, TRUE, NULL); - coltok(line, mnem, 27, 30, TRUE, NULL); - coltok(line, mods, 32, 33, TRUE, NULL); - coltok(line, arg, 35, 72, FALSE, opfield); - } - -// I don't know where I got this idea, but it's wrong... -// if (strchr(mods, '1') || strchr(mods, '2') || strchr(mods, '3')) { // index + X means ignore X -// if ((c = strchr(mods, 'X')) != NULL) -// strcpy(c, c+1); // remove the X -// } - - if (*label) // display org in any line with a label - setw(0, org, FALSE); - - if (! *mnem) { // label w/o mnemonic, just define the symbol - if (*label) - set_symbol(label, org, TRUE, relocate); - return; - } - - if ((op = lookup_op(mnem)) == NULL) { // look up mnemonic - if (*label) - set_symbol(label, org, TRUE, relocate);// at least define the label - - asm_error("Unknown opcode '%s'", mnem); - return; - } - - if (op->flags & TRAP) // assembler debugging breakpoint - x_trap(op, label, mods, arg); - - if (*op->mods_allowed != '\xFF') { // validate modifiers against list of allowed characters - for (c = mods; *c; ) { - if (strchr(op->mods_allowed, *c) == NULL) { - asm_warning("Modifier '%c' not permitted", *c); - strcpy(c, c+1); // remove it and keep parsing - } - else - c++; - } - } - - strcat(mods, op->mods_implied); // tack on implied modifiers - - if (strchr(mods, 'I')) // indirect implies long - strcat(mods, "L"); - - requires_even_address = op->flags & IS_DBL; - - org_advanced = strchr(mods, 'L') ? 2 : 1; // by default, * means address + 1 or 2. Sometimes it doesn't - (op->handler)(op, label, mods, arg); -} - -// --------------------------------------------------------------------------------- -// get one input line from current file or macro -// --------------------------------------------------------------------------------- - -BOOL get_line (char *buf, int nbuf, BOOL onelevel) -{ - char *retval; - - if (ended) // we hit the END command - return FALSE; - - // if macro active, return line from macro buffer, otherwise read from file - // do not pop end-of-macro if onelevel is TRUE - - if ((retval = fgets(buf, nbuf, fin)) == NULL) - return FALSE; - - lno++; // count the line - return TRUE; -} - -// --------------------------------------------------------------------------------- -// proc - process one pass of one source file -// --------------------------------------------------------------------------------- - -void proc (char *fname) -{ - char line[256], *c; - int i; - - if (strchr(fname, '.') == NULL) // if input file has no extension, - addextn(fname, ".asm", curfn); // set appropriate file extension - else - strcpy(curfn, fname); // otherwise use extension specified - -// let's leave filename case alone even if it doesn't matter -//#if (defined(WIN32) || defined(VMS)) -// upcase(curfn); // only force uppercase of name on Windows and VMS -//#endif - - if (progname[0] == '\0') { // pick up primary filename - if ((c = strrchr(curfn, '\\')) == NULL) - if ((c = strrchr(curfn, '/')) == NULL) - if ((c = strrchr(curfn, ':')) == NULL) - c = curfn; - - strncpy(progname, c, sizeof(progname)); // take name after path - progname[sizeof(progname)-1] = '\0'; - if ((c = strchr(progname, '.')) != NULL)// remove extension - *c = '\0'; - } - - lno = 0; // reset global input line number - ended = FALSE; // have not seen END statement - - if (listfn == NULL) // if list file name is undefined, - listfn = addextn(fname, ".lst", NULL); // create from first filename - - if (verbose) - fprintf(stderr, "--- Starting file %s pass %d\n", curfn, pass); - - if ((fin = fopen(curfn, "r")) == NULL) { - perror(curfn); // oops - exit(1); - } - - if (flist) { // put banner in listing file - strcpy(listline,"=== FILE ======================================================================"); - for (i = 9, c = curfn; *c;) - listline[i++] = *c++; - listline[i] = ' '; - fputs(listline, flist); - putc('\n', flist); - list_on = TRUE; - } - // read all lines till EOF or END statement - while (get_line(line, sizeof(line), FALSE)) { - prep_line(line); // preform standard line prep - parse_line(line); // parse - listout(FALSE); // complete the listing - } - - fclose(fin); - - if (n_literals > 0) { // force out any pending literal constants at end of file - output_literals(TRUE); - listout(FALSE); - } -} - -// --------------------------------------------------------------------------------- -// prep_line - prepare input line for parsing -// --------------------------------------------------------------------------------- - -void prep_line (char *line) -{ - char *c; - - upcase(line); // uppercase it - nwout = 0; // number of words output so far - line_error = FALSE; // no errors on this line so far - - for (c = line; *c; c++) { // truncate at newline - if (*c == '\r' || *c == '\n') { - *c = '\0'; - break; - } - } - - if (flist && list_on) { // construct beginning of listing line - if (tabformat) - sprintf(listline, LINEFORMAT, lno, detab(line)); - else { - if (strlen(line) > 20) // get the part where the commands start - c = line+20; - else - c = ""; - - sprintf(listline, LINEFORMAT, lno, c); - stuff(listline, line, 20); // stuff the left margin in to the left side - } - } -} - -// --------------------------------------------------------------------------------- -// opcmp - operand name comparison routine for qsort -// --------------------------------------------------------------------------------- - -int opcmp (const void *a, const void *b) -{ - return strcmp(((struct tag_op *) a)->mnem, ((struct tag_op *) b)->mnem); -} - -// --------------------------------------------------------------------------------- -// preload_symbols - load a saved symbol table -// --------------------------------------------------------------------------------- - -void preload_symbols (void) -{ - FILE *fd; - char str[200], sym[20]; - int v; - static BOOL preloaded_already = FALSE; - - if (pass > 1 || preloaded_already) - return; - - preloaded_already = TRUE; - - if ((fd = fopen(SYSTEM_TABLE, "r")) == NULL) // read the system symbol tabl - perror(SYSTEM_TABLE); - else { - while (fgets(str, sizeof(str), fd) != NULL) { - if (sscanf(str, "%s %x", sym, &v) == 2) - set_symbol(sym, v, TRUE, FALSE); - } - fclose(fd); - } -} - -// --------------------------------------------------------------------------------- -// save_symbols - save a symbol table -// --------------------------------------------------------------------------------- - -void save_symbols (void) -{ - FILE *fd; - char str[20]; - PSYMBOL s; - - if (relocate) { - fprintf(stderr, "Can't save symbol table unless ABS assembly\n"); - return; - } - - if ((fd = fopen(SYSTEM_TABLE, "r")) != NULL) { - fclose(fd); - if (saveprompt) { - printf("Overwrite system symbol table %s? ", SYSTEM_TABLE); - fgets(str, sizeof(str), stdin); - if (str[0] != 'y' && str[0] != 'Y') - return; - } - unlink(SYSTEM_TABLE); - } - - if ((fd = fopen(SYSTEM_TABLE, "w")) == NULL) { - perror(SYSTEM_TABLE); - return; - } - - for (s = symbols; s != NULL; s = s->next) - fprintf(fd, "%-5s %04x\n", s->name, s->value); - - fclose(fd); -} - -// --------------------------------------------------------------------------------- -// startpass - initialize data structures, prepare to start a pass -// --------------------------------------------------------------------------------- - -void startpass (int n) -{ - int nops; - struct tag_op *p; - - pass = n; // reset globals: pass number - nerrors = 0; // error count - org = 0; // load address (origin) - lno = 0; // input line number - relocate = TRUE; // relocatable assembly mode - assembled = FALSE; // true if any output has been generated - list_on = do_list; // listing enable - dmes_saved = FALSE; // partial character strings output - - n_literals = 0; // literal values pending output - lit_tag = 0; - - if (pass == 1) { // first pass only - for (nops = 0, p = ops; p->mnem != NULL; p++, nops++) // count opcodes - ; - - qsort(ops, nops, sizeof(*p), opcmp); // sort the opcode table - - if (preload) - preload_symbols(); - } - else { // second pass only - if (outfn == NULL) - outfn = addextn(curfn, (outmode == OUTMODE_LOAD) ? ".out" : ".bin" , NULL); - - if ((fout = fopen(outfn, OUTWRITEMODE)) == NULL) { // open output file - perror(outfn); - exit(1); - } - - if (do_list) { // open listing file - if ((flist = fopen(listfn, "w")) == NULL) { - perror(listfn); - exit(1); - } - listhdr(); // print banner - } - } -} - -// --------------------------------------------------------------------------------- -// x_dc - DC define constant directive -// --------------------------------------------------------------------------------- - -void x_dc (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; -// char *tok; - - org_advanced = 1; // assume * means this address+1 -// doesn't make sense, but I think I found DMS listings to support it - - if (strchr(mods, 'E') != NULL) // force even address - org_even(); - - setw(0, org, FALSE); // display org in listing line - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - -// just one!? - getexpr(arg, FALSE, &expr); - writew(expr.value, expr.relative); // store value - - // pick up values, comma delimited -// for (tok = strtok(arg, ","); tok != NULL; tok = strtok(NULL, ",")) { -// getexpr(tok, FALSE, &expr); -// writew(expr.value, expr.relative); // store value -// } -} - -// --------------------------------------------------------------------------------- -// x_dec - DEC define double word constant directive. -// --------------------------------------------------------------------------------- - -// wd[0]: 8 unused bits | characteristic (= exponent+128) -// wd[1]: sign + 15 msb of mantissa in 2's complement -// wd[2]: 16 lsb of mantissa - -// NOTE: these are wrong with Fixed point numbers - -void convert_double_to_extended (double d, unsigned short *wd) -{ - int neg, exp; - unsigned long mantissa; - unsigned char *byte = (unsigned char *) &d; - - if (d == 0.) { - wd[0] = wd[1] = wd[2] = 0; - return; - } - // 7 6 5 4 0 - // d = ansi real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM - - neg = byte[7] & 0x80; - exp = ((byte[7] & 0x7F) << 4) | ((byte[6] & 0xF0) >> 4); // extract exponent - exp -= 1023; // remove bias - - exp++; // shift to account for implied 1 we added - - // get 32 bits worth of mantissa. add the implied point - mantissa = 0x80000000L | ((byte[6] & 0x0F) << 27) | (byte[5] << 19) | (byte[4] << 11) | (byte[3] << 3) | ((byte[2] & 0xE0) >> 5); - - if (mantissa & (0x80000000L >> 31)) // keep 31 bits, round if necessary - mantissa += (0x80000000L >> 31); - - mantissa >>= (32-31); // get into low 31 bits - - // now turn into IBM 1130 extended precision - - exp += 128; - - if (neg) - mantissa = (unsigned long) (- (long) mantissa); // two's complement - - wd[0] = (unsigned short) (exp & 0xFF); - wd[1] = (unsigned short) ((neg ? 0x8000 : 0) | ((mantissa >> (31-15)) & 0x7FFF)); - wd[2] = (unsigned short) (mantissa & 0xFFFF); -} - -void convert_double_to_standard (double d, unsigned short *wd) -{ - int neg, exp; - unsigned long mantissa; - unsigned char *byte = (unsigned char *) &d; - - if (d == 0.) { - wd[0] = wd[1] = 0; - return; - } - // 7 6 5 4 0 - // d = ansi real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM - - neg = byte[7] & 0x80; - exp = ((byte[7] & 0x7F) << 4) | ((byte[6] & 0xF0) >> 4); // extract exponent - exp -= 1023; // remove bias - - exp++; // shift to account for implied 1 we added - - // get 32 bits worth of mantissa. add the implied point - mantissa = 0x80000000L | ((byte[6] & 0x0F) << 27) | (byte[5] << 19) | (byte[4] << 11) | (byte[3] << 3) | ((byte[2] & 0xE0) >> 5); - -// if (mantissa & (0x80000000L >> 23)) // keep 23 bits, round if necessary -// mantissa += (0x80000000L >> 23); - -// DEBUG -// printf("%8.4lf: %08lx %d\n", d, mantissa, exp); - - mantissa >>= (32-23); // get into low 23 bits - - // now turn into IBM 1130 standard precision - - exp += 128; - - if (neg) - mantissa = (unsigned long) (- (long) mantissa); // two's complement - - wd[0] = (unsigned short) ((neg ? 0x8000 : 0) | ((mantissa >> (23-15)) & 0x7FFF)); - wd[1] = (unsigned short) ((mantissa & 0x00FF) << 8) | (exp & 0xFF); - -// DEBUG -// printf(" D %04x%04x\n", wd[0], wd[1]); -} - -void convert_double_to_fixed (double d, unsigned short *wd, int bexp) -{ - int neg, exp, rshift; - unsigned long mantissa; - unsigned char *byte = (unsigned char *) &d; - - if (d == 0.) { - wd[0] = wd[1] = 0; - return; - } - // 7 6 5 4 0 - // d = ansi real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM - - neg = byte[7] & 0x80; - exp = ((byte[7] & 0x7F) << 4) | ((byte[6] & 0xF0) >> 4); // extract exponent - exp -= 1023; // remove bias - - exp++; // shift to account for implied 1 we added - - // get 32 bits worth of mantissa. add the implied point - mantissa = 0x80000000L | ((byte[6] & 0x0F) << 27) | (byte[5] << 19) | (byte[4] << 11) | (byte[3] << 3) | ((byte[2] & 0xE0) >> 5); - - mantissa >>= 1; // shift it out of the sign bit - -// DEBUG -// printf("%8.4lf: %08lx %d\n", d, mantissa, exp); - - rshift = bexp - exp; - - if (rshift > 0) { - mantissa >>= rshift; - } - else if (rshift < 0) { - mantissa >>= (-rshift); - asm_warning("Fixed point overflow"); - } - - if (neg) - mantissa = (unsigned long) (- (long) mantissa); // two's complement - -// DEBUG -// printf(" B %08lx\n", mantissa); - - wd[0] = (unsigned short) ((mantissa >> 16) & 0xFFFF); // return all of the bits; no exponent here - wd[1] = (unsigned short) (mantissa & 0xFFFF); -} - -void getDconstant (char *tok, unsigned short *wd) -{ - unsigned long l; - char *b, *fmt; - double d; - int bexp, fixed; - - wd[0] = 0; - wd[1] = 0; - - if (strchr(tok, '.') == NULL && strchr(tok, 'B') == NULL && strchr(tok, 'E') == NULL) { - fmt = "%ld"; - if (*tok == '/') { // I don't see that this is legal but can't hurt to allow it - fmt = "%lx"; - tok++; - } - if (sscanf(tok, fmt, &l) != 1) { // no decimal means it's an integer? - asm_error("Syntax error in constant"); - } - else { - wd[0] = (unsigned short) ((l >> 16) & 0xFFFF); // high word - wd[1] = (unsigned short) (l & 0xFFFF); // low word - } - return; - } - - fixed = 0; - if ((b = strchr(tok, 'B')) != NULL) { - fixed = 1; - bexp = atoi(b+1); - *b = '\0'; // truncate at the b - } - if (sscanf(tok, "%lg", &d) != 1) { - asm_error("Syntax error in constant"); - return; - } - - if (fixed) - convert_double_to_fixed(d, wd, bexp); - else - convert_double_to_standard(d, wd); -} - -// If the input value is an integer with no decimal point and no B or E, -// DEC generates a double INTEGER value. -// IBM documentation ranges from ambiguous to wrong on this point, but -// examination of the DMS microfiche supports this. - -void x_dec (struct tag_op *op, char *label, char *mods, char *arg) -{ -// char *tok; - unsigned short wd[2]; - - org_advanced = 2; // assume * means address after this location, since it's +1 for dc? - - org_even(); // even address is implied - setw(0, org, FALSE); // display the origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - -// just one!? - getDconstant(arg, wd); - writew(wd[0], FALSE); // write hiword, then loword - writew(wd[1], FALSE); - - // pick up values, comma delimited -// for (tok = strtok(arg, ","); tok != NULL; tok = strtok(NULL, ",")) { -// getDconstant(tok, wd); -// -// writew(wd[0], FALSE); // write hiword, then loword -// writew(wd[1], FALSE); -} - -void x_xflc (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *tok, *b; - double d; - int bexp, fixed; - unsigned short wd[3]; - - org_advanced = 2; // who knows? - - setw(0, org, FALSE); // display the origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - // pick up values, comma delimited - for (tok = strtok(arg, ","); tok != NULL; tok = strtok(NULL, ",")) { - bexp = 0; - if ((b = strchr(tok, 'B')) != NULL) { - bexp = atoi(b+1); - fixed = TRUE; - *b = '\0'; // truncate at the b - asm_warning("Fixed point extended floating constant?"); - } - - if (sscanf(tok, "%lg", &d) != 1) { - asm_error("Syntax error in constant"); - d = 0.; - } - - convert_double_to_extended(d, wd); - - writew(wd[0], ABSOLUTE); - writew(wd[1], ABSOLUTE); - writew(wd[2], ABSOLUTE); - } -} - -// --------------------------------------------------------------------------------- -// x_equ - EQU directive -// --------------------------------------------------------------------------------- - -void x_equ (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - org_advanced = FALSE; // * means this address, not incremented - - getexpr(arg, FALSE, &expr); - - setw(0, expr.value, expr.relative); // show this as address - - if (*label) // EQU is all about defining labels, better have one - set_symbol(label, expr.value, TRUE, expr.relative); -// else // IBM assembler doesn't complain about this -// asm_error("EQU without label?"); -} - -// --------------------------------------------------------------------------------- -// x_lorg - LORG directive -- output queued literal values -// --------------------------------------------------------------------------------- - -void x_lorg (struct tag_op *op, char *label, char *mods, char *arg) -{ - org_advanced = FALSE; // * means this address (not used, though) - output_literals(FALSE); // generate .DC's for queued literal values -} - -// --------------------------------------------------------------------------------- -// x_abs - ABS directive -// --------------------------------------------------------------------------------- - -void x_abs (struct tag_op *op, char *label, char *mods, char *arg) -{ - if (assembled) - asm_error("ABS must be first statement"); - - relocate = ABSOLUTE; - - switch (progtype) { - case PROGTYPE_ABSOLUTE: - case PROGTYPE_RELOCATABLE: - progtype = PROGTYPE_ABSOLUTE; // change program type, still assumed to be mainline - break; - - case PROGTYPE_LIBF: - case PROGTYPE_CALL: - case PROGTYPE_ISSLIBF: - case PROGTYPE_ISSCALL: - case PROGTYPE_ILS: - asm_error("ABS not allowed with LIBF, ENT, ILS or ISS"); - break; - - default: - bail("in x_libr, can't happen"); - } -} - -// --------------------------------------------------------------------------------- -// x_call - ORG pseudo-op -// --------------------------------------------------------------------------------- - -void x_call (struct tag_op *op, char *label, char *mods, char *arg) -{ - unsigned short words[2]; - static struct tag_op *bsi = NULL; - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (! *arg) { - asm_error("CALL missing argument"); - return; - } - - if (pass == 1) { // it will take two words in any case - org += 2; - return; - } - - setw(0, org, FALSE); // display origin - - if (lookup_symbol(arg, FALSE) != NULL) { // it's a defined symbol? - if (bsi == NULL) - if ((bsi = lookup_op("BSI")) == NULL) - bail("Can't find BSI op"); - - (bsi->handler)(bsi, "", "L", arg); - } - else { - namecode(words, arg); // emit namecode for loader - - writetwo(); - writew(words[0], CALL); - writew(words[1], ABSOLUTE); - } -} - -// --------------------------------------------------------------------------------- -// x_org - ORG directive -// --------------------------------------------------------------------------------- - -void x_org (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - org_advanced = FALSE; // * means this address - - if (*label) // label is defined BEFORE the new origin is set!!! - set_symbol(label, org, TRUE, relocate); - - if (getexpr(arg, FALSE, &expr) != S_DEFINED) - return; - - setorg(expr.value); // set origin to this value -} - -// --------------------------------------------------------------------------------- -// x_end - END directive -// --------------------------------------------------------------------------------- - -void x_end (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - org_advanced = FALSE; // * means this address - - if (*arg) { // they're specifing the program start address - if (getexpr(arg, FALSE, &expr) == S_DEFINED) - pta = expr.value; - } - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - setw(0, org, FALSE); // display origin - - ended = TRUE; // assembly is done, stop reading file -} - -// --------------------------------------------------------------------------------- -// x_ent - ENT op -// --------------------------------------------------------------------------------- - -void x_ent (struct tag_op *op, char *label, char *mods, char *arg) -{ - PSYMBOL s; - - org_advanced = FALSE; // * means this address - - if (pass < 2) - return; - -// if (*label) // define label -// set_symbol(label, org, TRUE, relocate); -// -// setw(0, org, FALSE); // display origin - - if (! *arg) - asm_error("No entry label specified"); - - else if ((s = lookup_symbol(arg, FALSE)) == NULL) - asm_error("Entry symbol %s not defined", arg); - - else if (nentries >= MAXENTRIES) - asm_error("Too many entries, limit is %d", MAXENTRIES); - - else - entry[nentries++] = s; // save symbol pointer - - switch (progtype) { - case PROGTYPE_ABSOLUTE: - asm_error("ENT not allowed with ABS"); - break; - case PROGTYPE_RELOCATABLE: - progtype = PROGTYPE_CALL; - break; - case PROGTYPE_LIBF: - case PROGTYPE_CALL: - case PROGTYPE_ISSLIBF: - case PROGTYPE_ISSCALL: - break; - case PROGTYPE_ILS: - asm_error("Can't mix ENT and ILS, can you?"); - break; - default: - bail("in x_libr, can't happen"); - } -} - -// --------------------------------------------------------------------------------- -// declare a libf-type subprogram -// --------------------------------------------------------------------------------- - -void x_libr (struct tag_op *op, char *label, char *mods, char *arg) -{ - switch (progtype) { - case PROGTYPE_ABSOLUTE: - asm_error("LIBR not allowed with ABS"); - break; - case PROGTYPE_RELOCATABLE: - case PROGTYPE_LIBF: - case PROGTYPE_CALL: - progtype = PROGTYPE_LIBF; - break; - case PROGTYPE_ISSLIBF: - case PROGTYPE_ISSCALL: - progtype = PROGTYPE_ISSLIBF; - break; - case PROGTYPE_ILS: - asm_error("Can't use LIBR in an ILS"); - break; - default: - bail("in x_libr, can't happen"); - } -} - -// --------------------------------------------------------------------------------- -// x_ils - ILS directive -// --------------------------------------------------------------------------------- - -void x_ils (struct tag_op *op, char *label, char *mods, char *arg) -{ - switch (progtype) { - case PROGTYPE_ABSOLUTE: - asm_error("ILS not allowed with ABS"); - break; - case PROGTYPE_RELOCATABLE: - case PROGTYPE_ILS: - progtype = PROGTYPE_ILS; - break; - case PROGTYPE_LIBF: - case PROGTYPE_CALL: - asm_error("Invalid placement of ILS"); - break; - case PROGTYPE_ISSLIBF: - case PROGTYPE_ISSCALL: - break; - default: - bail("in x_libr, can't happen"); - } - - intlevel_primary = atoi(mods); -} - -// --------------------------------------------------------------------------------- -// x_iss - ISS directive -// --------------------------------------------------------------------------------- - -void x_iss (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *tok; - - switch (progtype) { - case PROGTYPE_ABSOLUTE: - asm_error("ISS not allowed with ABS"); - break; - case PROGTYPE_RELOCATABLE: - case PROGTYPE_CALL: - case PROGTYPE_ISSCALL: - progtype = PROGTYPE_ISSCALL; - break; - case PROGTYPE_LIBF: - case PROGTYPE_ISSLIBF: - progtype = PROGTYPE_ISSLIBF; - break; - case PROGTYPE_ILS: - asm_error("Can't mix ISS and ILS"); - default: - bail("in x_libr, can't happen"); - } - - iss_number = atoi(mods); // get ISS number - - opfield[16] = '\0'; // be sure not to look too far into this - - nintlevels = 0; // # of interrupt levels for ISS - intlevel_primary = 0; // primary level for ISS and level for ILS - intlevel_secondary = 0; // secondary level for ISS - - if ((tok = strtok(opfield, " ")) == NULL) - asm_error("ISS missing entry label"); - else - x_ent(NULL, label, "", arg); // process as an ENT - - if ((tok = strtok(NULL, " ")) != NULL) { // get associated levels - nintlevels++; - intlevel_primary = atoi(tok); - } - - if ((tok = strtok(NULL, " ")) != NULL) { - nintlevels++; - intlevel_secondary = atoi(tok); - } -} - -void x_spr (struct tag_op *op, char *label, char *mods, char *arg) -{ - realmode = REALMODE_STANDARD; -} - -void x_epr (struct tag_op *op, char *label, char *mods, char *arg) -{ - realmode = REALMODE_EXTENDED; -} - -void x_dsa (struct tag_op *op, char *label, char *mods, char *arg) -{ - unsigned short words[2]; - - setw(0, org, FALSE); // display origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (! *arg) { - asm_error("DSA missing filename"); - } - else { - namecode(words, arg); - writetwo(); - writew(words[0], CALL); // special relocation bits here 3 and 1 - writew(words[1], RELATIVE); - } -} - -void x_link (struct tag_op *op, char *label, char *mods, char *arg) -{ - unsigned short words[2]; - char nline[128]; - - setw(0, org, FALSE); // display origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (! *arg) { - asm_error("LINK missing program name"); - } - else { - format_line(nline, label, "CALL", "", "$LINK", ""); - parse_line(nline); - - namecode(words, arg); - writew(words[0], ABSOLUTE); // special relocation bits here 3 and 1 - writew(words[1], ABSOLUTE); - } -} - -void x_libf (struct tag_op *op, char *label, char *mods, char *arg) -{ - unsigned short words[2]; - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (! *arg) { - asm_error("LIBF missing argument"); - return; - } - - if (pass == 1) { // it will take one words in any case - org++; - return; - } - - setw(0, org, FALSE); // display origin - - namecode(words, arg); // emit namecode for loader - - writetwo(); - writew(words[0], LIBF); // this one does NOT advance org! - writew(words[1], ABSOLUTE); -} - -void x_file (struct tag_op *op, char *label, char *mods, char *arg) -{ - int i, n, r; - EXPR vals[5]; - char *tok; - - for (i = 0; i < 5; i++) { - if ((tok = strtok(arg, ",")) == NULL) { - asm_error("FILE has insufficient arguments"); - return; - } - arg = NULL; // for next strtok call - - if (i == 3) { - if (strcmpi(tok, "U") != 0) - asm_error("Argument 4 must be the letter U"); - } - else if (getexpr(tok, FALSE, &vals[i]) == S_DEFINED) { - if (i <= 3 && vals[i].relative) - asm_error("Argument %d must be absolute", i+1); - else if (pass == 2 && vals[i].value == 0) - asm_error("Argument %d must be nonzero", i+1); - } - } - - writew(vals[0].value, ABSOLUTE); - writew(vals[1].value, ABSOLUTE); - writew(vals[2].value, ABSOLUTE); - writew(vals[4].value, vals[i].relative); - writew(0, ABSOLUTE); - n = MAX(1, vals[2].value); - r = 320/n; - writew(r, ABSOLUTE); - r = MAX(1, r); - writew((16*vals[1].value)/r, ABSOLUTE); - - if (pass == 2) - ndefined_files++; -} - -// --------------------------------------------------------------------------------- -// x_trap - place to set a breakpoint -// --------------------------------------------------------------------------------- - -void x_trap (struct tag_op *op, char *label, char *mods, char *arg) -{ - // debugging breakpoint -} - -// --------------------------------------------------------------------------------- -// x_ces - .CES directive (nonstandard). Specify a value for the console entry -// switches. When this program is loaded into the simulator, the switches will -// be set accordingly. Handy for bootstraps and other programs that read -// the switches. -// --------------------------------------------------------------------------------- - -void x_ces (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - if (outmode != OUTMODE_LOAD) // this works only in our loader format - return; - - if (getexpr(arg, FALSE, &expr) != S_DEFINED) - return; - - if (pass == 2) - fprintf(fout, "S%04x" ENDLINE, expr.value & 0xFFFF); -} - -// --------------------------------------------------------------------------------- -// x_bss - BSS directive - reserve space in core -// --------------------------------------------------------------------------------- - -void x_bss (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - org_advanced = FALSE; // * means this address - - if (! *arg) { - expr.value = 0; - expr.relative = ABSOLUTE; - } - else if (getexpr(arg, FALSE, &expr) != S_DEFINED) - return; - - if (strchr(mods, 'E') != NULL) // force even address - org_even(); - - if (expr.relative) - asm_error("BSS size must be an absolute value"); - - setw(0, org, FALSE); // display origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (expr.value < 0) - asm_warning("Negative BSS size"); - - else if (expr.value > 0) { - if (outmode == OUTMODE_LOAD) { - org += expr.value; // advance the origin by appropriate number of words - if (pass == 2) // emit new load address in output file - fprintf(fout, "@%04x%s" ENDLINE, org & 0xFFFF, relocate ? "R" : ""); - } - else { - org += expr.value; // advance the origin by appropriate number of words - if (pass == 2) - bincard_setorg(org); - } - } -} - -// --------------------------------------------------------------------------------- -// x_bes - Block Ended by Symbol directive. Like BSS but label gets address AFTER the space, instead of first address -// --------------------------------------------------------------------------------- - -void x_bes (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - org_advanced = FALSE; // * means this address - - if (! *arg) { // arg field = space - expr.value = 0; - expr.relative = ABSOLUTE; - } - else if (getexpr(arg, FALSE, &expr) != S_DEFINED) - return; - - if (strchr(mods, 'E') != NULL && (org & 1) != 0) - org_even(); // force even address - - if (expr.relative) - asm_error("BES size must be an absolute value"); - - if (expr.value < 0) - asm_warning("Negative BES size"); - - else if (expr.value > 0) { - setw(0, org+expr.value, FALSE); // display NEW origin - - if (outmode == OUTMODE_LOAD) { - org += expr.value; // advance the origin - if (pass == 2) // emit new load address in output file - fprintf(fout, "@%04x%s" ENDLINE, org & 0xFFFF, relocate ? "R" : ""); - } - else { - org += expr.value; // advance the origin - bincard_setorg(org); - } - } - - if (*label) // NOW define the label - set_symbol(label, org, TRUE, relocate); -} - -// --------------------------------------------------------------------------------- -// x_dmes - DMES define message directive. Various encodings, none pretty. -// --------------------------------------------------------------------------------- - -int dmes_wd; -int dmes_nc; -enum {CODESET_CONSOLE, CODESET_1403, CODESET_1132, CODESET_EBCDIC} dmes_cs; -void stuff_dmes (int ch, int rpt); - -void x_dmes (struct tag_op *op, char *label, char *mods, char *arg) -{ - int rpt; - char *c = opfield; - BOOL cont = FALSE; - - if (dmes_saved) { // previous DMES had an odd character saved - dmes_wd = dmes_savew; - dmes_nc = 1; // stick it into the outbut buffer - } - else - dmes_nc = dmes_wd = 0; // clear output buffer - - trim(opfield); // remove trailing blanks from rest of input line (use whole thing) - setw(0, org, FALSE); // display origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (strchr(mods, '1') != NULL) // determine the encoding scheme - dmes_cs = CODESET_1403; - else if (strchr(mods, '2') != NULL) - dmes_cs = CODESET_1132; - else if (strchr(mods, '0') != NULL || ! *mods) - dmes_cs = CODESET_CONSOLE; - else { - asm_error("Invalid printer code in tag field"); - dmes_cs = CODESET_EBCDIC; - } - - while (*c) { // pick up characters - if (*c == '\'') { // quote (') is the escape character - c++; - - rpt = 0; // get repeat count - while (BETWEEN(*c, '0', '9')) { - rpt = rpt*10 + *c++ - '0'; - } - if (rpt <= 0) // no count = insert one copy - rpt = 1; - - switch (*c) { // handle escape codes - case '\'': - stuff_dmes(*c, 1); - break; - - case 'E': - *c = '\0'; // end - break; - - case 'X': - case 'S': - stuff_dmes(' ', rpt); - break; - - case 'F': - stuff_dmes(*++c, rpt); // repeat character - break; - - case ' ': - case '\0': - cont = TRUE; - *c = '\0'; // end - break; - - case 'T': - if (dmes_cs != CODESET_CONSOLE) { -badcode: asm_error("Invalid ' escape for selected printer"); - break; - } - stuff_dmes(0x41, -rpt); // tab - break; - - case 'D': - if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x11, -rpt); // backspace - break; - - case 'B': - if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x05, -rpt); // black - break; - - case 'A': - if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x09, -rpt); // red - break; - - case 'R': - if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x81, -rpt); // return - break; - - case 'L': - if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x03, -rpt); // line feed - break; - - default: - asm_error("Invalid ' escape in DMES"); - *c = '\0'; - break; - } - } - else // just copy literal character - stuff_dmes(*c, 1); - - if (*c) - c++; - } - - dmes_saved = FALSE; - - if (dmes_nc) { // odd number of characters - if (cont) { - dmes_saved = TRUE; - dmes_savew = dmes_wd; // save for next time - } - else - stuff_dmes(' ', 1); // pad with a space to force out even # of characters - } -} - -// --------------------------------------------------------------------------------- -// stuff_dmes - insert 'rpt' copies of character 'ch' into output words -// --------------------------------------------------------------------------------- - -void stuff_dmes (int ch, int rpt) -{ - int nch, i; // nch is translated output value - - if (rpt < 0) { // negative repeat means no translation needed - rpt = -rpt; - nch = ch; - } - else { - switch (dmes_cs) { - case CODESET_CONSOLE: - nch = 0x21; - for (i = 0; i < 256; i++) { - if (conout_to_ascii[i] == ch) { - nch = i; - break; - } - } - break; - - case CODESET_EBCDIC: - nch = ascii_to_ebcdic_table[ch & 0x7F]; - if (nch == 0) - nch = 0x7F; - break; - - case CODESET_1403: - nch = ascii_to_1403_table[ch & 0x7F]; - if (nch == 0) - nch = 0x7F; - break; - - case CODESET_1132: - nch = 0x40; - for (i = 0; i < WHEELCHARS_1132; i++) { - if (codewheel1132[i].ascii == ch) { - nch = codewheel1132[i].ebcdic; - break; - } - } - break; - - default: - bail("bad cs in x_dmes, can't happen"); - break; - } - } - - while (--rpt >= 0) { // pack them into words, output when we have two - if (dmes_nc == 0) { - dmes_wd = (nch & 0xFF) << 8; - dmes_nc = 1; - } - else { - dmes_wd |= (nch & 0xFF); - writew(dmes_wd, FALSE); - dmes_nc = 0; - } - } -} - -// --------------------------------------------------------------------------------- -// x_ebc - handle EBCDIC string definition (delimited with periods) -// --------------------------------------------------------------------------------- - -void x_ebc (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *p; - -// setw(0, org, FALSE); - if (*label) - set_symbol(label, org, TRUE, relocate); - - p = trim(opfield); // remove trailing blanks from rest of input line (use whole thing) - - if (*p != '.') { - asm_error("EBC data must start with ."); - return; - } - p++; // skip leading period - - dmes_nc = dmes_wd = 0; // clear output buffer (we're borrowing the DMES packer) - dmes_cs = CODESET_EBCDIC; - - while (*p && *p != '.') // store packed ebcdic - stuff_dmes(*p++, 1); - - if (dmes_nc) // odd number of characters - stuff_dmes(' ', 1); // pad with a space to force out even # of characters - - if (*p != '.') - asm_error("EBC missing closing ."); -} - -// --------------------------------------------------------------------------------- -// x_dn - define name DN directive. Pack 5 characters into two words. This by the -// way is the reason the language Forth is not Fourth. -// --------------------------------------------------------------------------------- - -void x_dn (struct tag_op *op, char *label, char *mods, char *arg) -{ - unsigned short words[2]; - - setw(0, org, FALSE); // display origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - namecode(words, arg); - - writew(words[0], ABSOLUTE); - writew(words[1], ABSOLUTE); -} - -// --------------------------------------------------------------------------------- -// x_dump - DUMP directive - pretend we saw "call $dump, call $exit" -// --------------------------------------------------------------------------------- - -void x_dump (struct tag_op *op, char *label, char *mods, char *arg) -{ - x_pdmp(op, label, mods, arg); - x_exit(NULL, "", "", ""); // compile "call $exit" -} - -// --------------------------------------------------------------------------------- -// x_pdmp - PDMP directive - like DUMP but without the call $exit -// --------------------------------------------------------------------------------- - -void x_pdmp (struct tag_op *op, char *label, char *mods, char *arg) -{ - char nline[200], *tok; - EXPR addr[3]; - int i; - - for (i = 0, tok = strtok(arg, ","); i < 3 && tok != NULL; i++, tok = strtok(NULL, ",")) { - if (getexpr(tok, FALSE, addr+i) != S_DEFINED) { - addr[i].value = (i == 1) ? 0x3FFF : 0; - addr[i].relative = ABSOLUTE; - } - } - - org_advanced = FALSE; // * means this address+1 - - format_line(nline, label, "BSI", "L", DOLLARDUMP, ""); - parse_line(nline); // compile "call $dump" - - writew(addr[2].value, ABSOLUTE); // append arguments (0, start, end address) - writew(addr[0].value, addr[0].relative); - writew(addr[1].value, addr[1].relative); -} - -// --------------------------------------------------------------------------------- -// x_hdng - HDNG directive -// --------------------------------------------------------------------------------- - -void x_hdng (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *c; - - // label is not entered into the symbol table - - if (flist == NULL || ! list_on) { - line_error = TRUE; // inhibit listing: don't print the HDNG statement - return; - } - - line_error = TRUE; // don't print the statement - - c = skipbl(opfield); - trim(c); - fprintf(flist, "\f%s\n\n", c); // print page header -} - -// --------------------------------------------------------------------------------- -// x_list - LIST directive. enable or disable listing -// --------------------------------------------------------------------------------- - -void x_list (struct tag_op *op, char *label, char *mods, char *arg) -{ - BOOL on; - - // label is not entered into the symbol table - - line_error = TRUE; // don't print the LIST statement - - if (flist == NULL || ! list_on) { - return; - } - - if (strcmpi(arg, "ON") == 0) - on = TRUE; - else if (strcmpi(arg, "OFF") == 0) - on = FALSE; - else - on = do_list; - - list_on = on; -} - -// --------------------------------------------------------------------------------- -// x_spac - SPAC directive. Put blank lines in listing -// --------------------------------------------------------------------------------- - -void x_spac (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - // label is not entered into the symbol table - - if (flist == NULL || ! list_on) { - line_error = TRUE; // don't print the SPAC statement - return; - } - - if (getexpr(arg, FALSE, &expr) != S_DEFINED) - return; - - line_error = TRUE; // don't print the statement - - while (--expr.value >= 0) - putc('\n', flist); -} - -// --------------------------------------------------------------------------------- -// x_ejct - EJCT directive - put formfeed in listing -// --------------------------------------------------------------------------------- - -void x_ejct (struct tag_op *op, char *label, char *mods, char *arg) -{ - // label is not entered into the symbol table - - if (flist == NULL || ! list_on) { - line_error = TRUE; // don't print the EJCT statement - return; - } - - line_error = TRUE; // don't print the statement - - putc('\f', flist); -} - -// --------------------------------------------------------------------------------- -// basic_opcode - construct a standard opcode value from op table entry and modifier chars -// --------------------------------------------------------------------------------- - -int basic_opcode (struct tag_op *op, char *mods) -{ - int opcode = op->opcode; // basic code value - - if (strchr(mods, '1') != 0) // indexing - opcode |= 0x0100; - else if (strchr(mods, '2') != 0) - opcode |= 0x0200; - else if (strchr(mods, '3') != 0) - opcode |= 0x0300; - - if (strchr(mods, 'L')) { // two-word format - opcode |= OP_LONG; - if (strchr(mods, 'I') != 0) // and indirect to boot - opcode |= OP_INDIRECT; - } - - return opcode; -} - -// --------------------------------------------------------------------------------- -// std_op - assemble a vanilla opcode -// --------------------------------------------------------------------------------- - -void std_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - int opcode = basic_opcode(op, mods); - BOOL val_ok = FALSE; - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (*arg && ! (op->flags & NO_ARGS)) { // get value argument - if (getexpr(arg, FALSE, &expr) == S_DEFINED) - val_ok = TRUE; - } - else { - expr.value = 0; - expr.relative = FALSE; - } - - if (opcode & OP_LONG) { // two-word format, just write code and value - writew(opcode, FALSE); - writew(expr.value, expr.relative); - } - else { // one-word format - if (strchr(mods, 'I') != 0) - asm_error("Indirect mode not permitted on one-word instructions"); - - if (val_ok && ! (strchr(mods, 'X') || (op->flags & IS_ABS) || ((opcode & OP_INDEXED) && ! (op->flags & NO_IDX)))) - expr.value -= (org+1); // compute displacement - - if (expr.value < -128 || expr.value > 127) {// check range - asm_error("Offset of %d is too large", expr.value); - expr.value = 0; - } - - writew(opcode | (expr.value & 0x00FF), FALSE);// that's the code - } -} - -// --------------------------------------------------------------------------------- -// mdx_op - assemble a MDX family instruction -// --------------------------------------------------------------------------------- - -void mdx_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR dest, incr = {0, FALSE}; - int opcode = basic_opcode(op, mods); - char *tok; - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if ((tok = strtok(arg, ",")) == NULL) { // argument format is dest[,increment] -// asm_error("Destination not specified"); // seems not to be an error, IBM omits it sometimes - dest.value = 0; - dest.relative = ABSOLUTE; - } - else - getexpr(tok, FALSE, &dest); // parse the address - - tok = strtok(NULL, ","); // look for second argument - - if (opcode & OP_LONG) { // two word format - if (opcode & OP_INDEXED) { // format: MDX 2 dest - if (tok != NULL) - asm_error("This format takes only one argument"); - } - else { // format: MDX dest,increment - if (opcode & OP_INDIRECT) - asm_error("Indirect can't be used without indexing"); - - if (tok == NULL) { -// asm_error("This format takes two arguments"); - incr.value = 0; - incr.relative = ABSOLUTE; - } - else - getexpr(tok, FALSE, &incr); - - if (incr.value < -128 || incr.value > 127) // displacement style (fixed in ver 1.08) - asm_error("Invalid increment value (8 bits signed)"); - - opcode |= (incr.value & 0xFF); - } - - writew(opcode, ABSOLUTE); - writew(dest.value, dest.relative); - } - else { // one word format MDX val - if (tok != NULL) - asm_error("This format takes only one argument"); - - if (! (strchr(mods, 'X') || (opcode & OP_INDEXED))) - dest.value -= (org+1); // compute displacement - - if (dest.value < -128 || dest.value > 127) - asm_error("Offset/Increment of %d is too large", dest.value); - - writew(opcode | (dest.value & 0xFF), FALSE); - } -} - -// --------------------------------------------------------------------------------- -// bsi_op - BSI long instruction is like a BSC L, short is standard -// --------------------------------------------------------------------------------- - -void bsi_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - if (strchr(mods, 'L') || strchr(mods, 'I')) - bsc_op(op, label, mods, arg); - else - std_op(op, label, mods, arg); -} - -// --------------------------------------------------------------------------------- -// b_op - branch; use short or long version -// -------------------------------------------------------------------------------- - -void b_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - static struct tag_op *mdx = NULL; - - if (strchr(mods, 'L') || strchr(mods, 'I')) { - bsi_op(op, label, mods, arg); - return; - } - - if (mdx == NULL) - if ((mdx = lookup_op("MDX")) == NULL) - bail("Can't find MDX op"); - - (mdx->handler)(mdx, label, mods, arg); -} - -// --------------------------------------------------------------------------------- -// bsc_op - compute a BSC family instruction -// --------------------------------------------------------------------------------- - -void bsc_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR dest; - int opcode = basic_opcode(op, mods); - char *tok, *tests; - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (opcode & OP_LONG) { // two word format - if ((tok = strtok(arg, ",")) == NULL) { // format is BSC dest[,tests] - asm_error("Destination not specified"); - dest.value = 0; - dest.relative = ABSOLUTE; - } - else - getexpr(tok, FALSE, &dest); - - tests = strtok(NULL, ","); // get test characters - } - else - tests = arg; // short format is BSC tests - - if (tests != NULL) { // stick in the testing bits - for (; *tests; tests++) { - switch (*tests) { - // bit 0x40 is the BOSC bit - case 'Z': opcode |= 0x20; break; - case '-': opcode |= 0x10; break; - case '+': - case '&': opcode |= 0x08; break; - case 'E': opcode |= 0x04; break; - case 'C': opcode |= 0x02; break; - case 'O': opcode |= 0x01; break; - default: - asm_error("Invalid test flag: '%c'", *tests); - } - } - } - - writew(opcode, ABSOLUTE); // emit code - if (opcode & OP_LONG) - writew(dest.value, dest.relative); -} - -// --------------------------------------------------------------------------------- -// shf_op - assemble a shift instruction -// --------------------------------------------------------------------------------- - -void shf_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - int opcode = basic_opcode(op, mods); - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (opcode & OP_INDEXED) { // shift value comes from index register - expr.value = 0; - expr.relative = ABSOLUTE; - } - else - getexpr(arg, FALSE, &expr); - - if (expr.relative) { - asm_error("Shift value is a relative address"); - expr.relative = ABSOLUTE; - } - - if (expr.value < 0 || expr.value > 32) { // check range - asm_error("Shift count of %d is invalid", expr.value); - expr.value = 0; - } - - writew(opcode | (expr.value & 0x3F), FALSE); // put shift count into displacement field -} - -// --------------------------------------------------------------------------------- -// x_mdm - MDM instruction -// --------------------------------------------------------------------------------- - -void x_mdm (struct tag_op *op, char *label, char *mods, char *arg) -{ - int opcode = basic_opcode(op, mods); - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - // oh dear: bug here - asm_error("'%s' is not yet supported", op->mnem); -} - -// --------------------------------------------------------------------------------- -// x_exit - EXIT directive. Assembler manual says it treats like CALL $EXIT, but -// object code reveals the truth: jump to $EXIT, which is a small value, so we can use LDX. -// --------------------------------------------------------------------------------- - -void x_exit (struct tag_op *op, char *label, char *mods, char *arg) -{ - char nline[120]; - - format_line(nline, label, "LDX", "X", DOLLAREXIT, ""); - parse_line(nline); -} - -// --------------------------------------------------------------------------------- -// x_opt - .OPT directive. Nonstandard. Possible values: -// -// .OPT CEXPR - use C precedence in evaluating expressions rather than strict left-right -// --------------------------------------------------------------------------------- - -void x_opt (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *tok; - - org_advanced = FALSE; // * means this address - - if (*label) { - asm_error("Label not permitted on .OPT statement"); - return; - } - // look for OPT arguments - for (tok = strtok(arg, ","); tok != NULL; tok = strtok(NULL, ",")) { - if (strcmp(tok, "CEXPR") == 0) { - cexpr = TRUE; // use C expression precedence (untested) - } - else - asm_error("Unknown .OPT: '%s'", tok); - } -} - -// --------------------------------------------------------------------------------- -// askip - skip input lines until a line with the target label appears -// --------------------------------------------------------------------------------- - -void askip (char *target) -{ - char nline[200], cur_label[20], *c; - - while (get_line(nline, sizeof(nline), TRUE)) { // read next line (but don't exit a macro) - listout(FALSE); // end listing of previous input line - - prep_line(nline); // preform standard line prep - - strncpy(cur_label, nline, 6); // get first 5 characters - cur_label[5] = '\0'; - - for (c = cur_label; *c > ' '; c++) // truncate at first whitespace - ; - *c = '\0'; - // stop if there's a match - if ((target == NULL) ? (cur_label[0] == '\0') : strcmp(target, cur_label) == 0) { - parse_line(nline); // process this line - return; - } - } - - if (target != NULL) - asm_error("Label %s not found", target); -} - -// --------------------------------------------------------------------------------- -// x_aif - process conditional assembly jump -// --------------------------------------------------------------------------------- - -void x_aif (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *target, *tok; - EXPR expr1, expr2; - BOOL istrue; - enum {OP_EQ, OP_LT, OP_GT, OP_NE, OP_LE, OP_GE} cmp_op; - - // label is not entered into the symbol table - - arg = skipbl(arg); - if (*arg != '(') { - asm_error("AIF operand must start with ("); - return; - } - - arg++; // skip the paren - - // normally whitespace is never found in the arg string (see tabtok and coltok). - // However, spaces inside parens are permitted. - - if ((tok = strtok(arg, whitespace)) == NULL) { - asm_error("AIF missing first expression"); - return; - } - - getexpr(tok, FALSE, &expr1); - - if ((tok = strtok(NULL, whitespace)) == NULL) { - asm_error("AIF missing conditional operator"); - return; - } - - if (strcmp(tok, "EQ") == 0) - cmp_op = OP_EQ; - else if (strcmp(tok, "LT") == 0) - cmp_op = OP_LT; - else if (strcmp(tok, "GT") == 0) - cmp_op = OP_GT; - else if (strcmp(tok, "NE") == 0) - cmp_op = OP_NE; - else if (strcmp(tok, "LE") == 0) - cmp_op = OP_LE; - else if (strcmp(tok, "GE") == 0) - cmp_op = OP_GE; - else { - asm_error("AIF: %s is not a valid conditional operator", tok); - return; - } - - if ((tok = strtok(NULL, ")")) == NULL) { - asm_error("AIF missing second expression"); - return; - } - - getexpr(tok, FALSE, &expr2); - - switch (cmp_op) { // test the condition - case OP_EQ: istrue = expr1.value == expr2.value; break; - case OP_LT: istrue = expr1.value < expr2.value; break; - case OP_GT: istrue = expr1.value > expr2.value; break; - case OP_NE: istrue = expr1.value != expr2.value; break; - case OP_LE: istrue = expr1.value <= expr2.value; break; - case OP_GE: istrue = expr1.value >= expr2.value; break; - default: bail("in aif, can't happen"); - } - - // After the closing paren coltok and tabtok guarantee we will have no whitespace - - if ((target = strtok(arg, ",")) == NULL) // get target label - asm_warning("Missing target label"); - - if (istrue) - askip(target); // skip to the target -} - -// --------------------------------------------------------------------------------- -// x_aifb - conditional assembly jump back (macro only) -// --------------------------------------------------------------------------------- - -void x_aifb (struct tag_op *op, char *label, char *mods, char *arg) -{ - asm_error("aifb valid in macros only and not implemented in any case"); -} - -// --------------------------------------------------------------------------------- -// x_ago -// --------------------------------------------------------------------------------- - -void x_ago (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *target; - - // label is not entered into the symbol table - - // handle differently in a macro - - if ((target = strtok(arg, ",")) == NULL) // get target label - asm_warning("Missing target label"); - - askip(target); // skip to the target -} - -// --------------------------------------------------------------------------------- -// --------------------------------------------------------------------------------- - -void x_agob (struct tag_op *op, char *label, char *mods, char *arg) -{ - asm_error("agob valid in macros only and not implemented in any case"); -} - -// --------------------------------------------------------------------------------- -// --------------------------------------------------------------------------------- - -void x_anop (struct tag_op *op, char *label, char *mods, char *arg) -{ - // label is not entered into the symbol table - // do nothing else -} - -// --------------------------------------------------------------------------------- -// expression parser, borrowed from older code, no comments, sorry -// --------------------------------------------------------------------------------- - -char *exprptr, *oexprptr; - -#define GETNEXT (*exprptr++) -#define UNGET --exprptr - -#define LETTER 0 /* character types */ -#define DIGIT 1 -#define ETC 2 -#define ILL 3 -#define SPACE 4 -#define MULOP 5 -#define ADDOP 6 -#define EXPOP 7 - -int getnb (void); -void c_expr (EXPR *ap); -void c_expr_m (EXPR *ap); -void c_expr_e (EXPR *ap); -void c_expr_u (EXPR *ap); -void c_term (EXPR *ap); -int c_number (int c, int r, int nchar); -int digit (int c, int r); -int c_esc (int c); -void exprerr (int n); -void a1130_expr (EXPR *ap); -void a1130_term (EXPR *ap); - -char ctype[128] = { // character types -/*^0ABCDEFG */ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, -/*^HIJKLMNO */ ILL, SPACE, SPACE, ILL, SPACE, SPACE, ILL, ILL, -/*^PQRSTUVW */ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, -/*^XYZ */ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, -/* !"#$%&' */ SPACE, ETC, ETC, LETTER, LETTER, MULOP, MULOP, LETTER, /* $ # @ and ' are letters here */ -/* ()*+,-./ */ ETC, ETC, MULOP, ADDOP, ETC, ADDOP, ETC, MULOP, -/* 01234567 */ DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, -/* 89:;<=>? */ DIGIT, DIGIT, ETC, ETC, MULOP, ETC, MULOP, ETC, -/* @ABCDEFG */ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* HIJKLMNO */ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* PQRSTUVW */ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* XYZ[\]^_ */ LETTER, LETTER, LETTER, ETC, ETC, ETC, EXPOP, LETTER, -/* `abcdefg */ ETC, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* hijklmno */ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* pqrstuvw */ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* xyz{|}~ */ LETTER, LETTER, LETTER, ETC, ADDOP, ETC, ETC, ETC -}; - -char *errstr[] = { - "Missing exponent", // 0 - "Undefined symbol", // 1 - "Division by zero", // 2 - "Illegal operator", // 3 - ") expected", // 4 - "Char expected after '", // 5 - "Char expected after .", // 6 - "Number expected after =", // 7 - "Syntax error", // 8 - "Number syntax", // 9 - "Char expected after \\", // 10 - "Relocation error" // 11 -}; - -int getnb () { - int c; - - if (cexpr) { // in C mode, handle normally - while (ctype[(c = GETNEXT)] == SPACE) - ; - } // in 1130 mode, a space terminates the expression. Here, eat the rest - else if ((c = GETNEXT) == ' ') { - while ((c = GETNEXT) != '\0') - ; - } - - return c; -} - -int symbest, exprerrno; -jmp_buf exprjmp; - -// --------------------------------------------------------------------------------- -// getexpr -// --------------------------------------------------------------------------------- - -int getexpr (char *pc, BOOL undefined_ok, EXPR *pval) -{ - symbest = S_DEFINED; // assume no questionable symbols - - pval->value = 0; - pval->relative = ABSOLUTE; - - if (! *pc) // blank expression is same as zero, ok? - return S_DEFINED; - - if (setjmp(exprjmp) != 0) { // encountered a syntax error & bailed - pval->value = 0; - pval->relative = ABSOLUTE; - return S_UNDEFINED; - } - - exprptr = oexprptr = pc; // make global the buffer pointer - - c_expr(pval); - - if (GETNEXT) // expression should have been entirely eaten - exprerr(8); // if characters are left, it's an error - - if (pval->relative < 0 || pval->relative > 1) - exprerr(11); // has to work out to an absolute or a single relative term - - if (symbest == S_DEFINED) // tell how it came out - return S_DEFINED; - - pval->value = 0; - pval->relative = ABSOLUTE; - return (pass == 1 && undefined_ok) ? S_PROVISIONAL : S_UNDEFINED; -} - -// --------------------------------------------------------------------------------- -// output_literals - construct .DC assembler lines to assemble pending literal -// constant values that have accumulated. -// --------------------------------------------------------------------------------- - -void output_literals (BOOL eof) -{ - char line[120], label[12], num[20]; - int i; - - for (i = 0; i < n_literals; i++) { // generate DC statements for any pending literal constants - if (literal[i].even && literal[i].hex) // create the value string - sprintf(num, "/%08lx", literal[i].value); - else if (literal[i].even) - sprintf(num, "%ld", literal[i].value); - else if (literal[i].hex) - sprintf(num, "/%04x", literal[i].value & 0xFFFF); - else - sprintf(num, "%d", literal[i].value); - - sprintf(label, "_L%03d", literal[i].tagno); - format_line(line, label, literal[i].even ? "DEC" : "DC", "", num, "GENERATED LITERAL CONSTANT"); - - if (eof) { - eof = FALSE; // at end of file, for first literal, only prepare blank line - sprintf(listline, LEFT_MARGIN, org); - } - else - listout(TRUE); // push out any pending line(s) - - if (flist && list_on) // this makes stuff appear in the listing - sprintf(listline, LEFT_MARGIN " %s", detab(line)); - - nwout = 0; - - parse_line(line); // assemble the constant definition - } - - n_literals = 0; // clear list -} - -// --------------------------------------------------------------------------------- -// a1130_term - extract one term of an expression -// --------------------------------------------------------------------------------- - -void a1130_term (EXPR *ap) -{ - PSYMBOL s; - char token[80], *t; - int c; - - if (cexpr) { // use C syntax - c_term(ap); - return; - } - - c = GETNEXT; - - if (ctype[c] == DIGIT) { /* number */ - ap->value = c_number(c,10,-1); - ap->relative = ABSOLUTE; - } - else if (c == '+') { /* unary + */ - a1130_term(ap); - } - else if (c == '-') { /* unary - */ - a1130_term(ap); - ap->value = - ap->value; - } - else if (c == '/') { /* / starts a hex constant */ - ap->value = c_number(c,16,-1); - ap->relative = ABSOLUTE; - } - else if (c == '*') { /* asterisk alone = org */ - ap->value = org + org_advanced; // here is where that offset matters! - ap->relative = relocate; - } - else if (c == '.') { /* EBCDIC constant */ - c = GETNEXT; - if (c == '\0') { - UNGET; - c = ' '; - } - c = ascii_to_ebcdic_table[c]; - ap->value = c; // VALUE IS IN LOW BYTE!!! - ap->relative = ABSOLUTE; - } - else if (ctype[c] == LETTER) { /* symbol */ - t = token; - do { - *t++ = c; - c = GETNEXT; - } while (ctype[c] == LETTER || ctype[c] == DIGIT); - UNGET; - *t++ = '\0'; - - s = lookup_symbol(token, TRUE); - add_xref(s, FALSE); - ap->value = s->value; - ap->relative = s->relative; - - symbest = MIN(symbest, s->defined); // this goes to lowest value (undefined < provisional < defined) - if (pass == 2 && s->defined != S_DEFINED) - exprerr(1); - } - else - exprerr(8); -} - -// --------------------------------------------------------------------------------- -// c_expr - evalate an expression -// --------------------------------------------------------------------------------- - -void c_expr (EXPR *ap) -{ - int c; - EXPR rop; - - c_expr_m(ap); // get combined multiplicative terms - for (;;) { // handle +/- precedence operators - if (ctype[c=getnb()] != ADDOP) { - UNGET; - break; - } - c_expr_m(&rop); // right hand operand - switch (c) { - case '+': - ap->value += rop.value; - ap->relative += rop.relative; - break; - - case '-': - ap->value -= rop.value; - ap->relative -= rop.relative; - break; - - case '|': - if (ap->relative || rop.relative) - exprerr(11); - ap->value = ((long) (ap->value)) | ((long) rop.value); - break; - - default: - printf("In expr, can't happen\n"); - } - } -} - -// --------------------------------------------------------------------------------- -// c_expr_m - get multiplicative precedence terms. Again, this is not usually used -// --------------------------------------------------------------------------------- - -void c_expr_m (EXPR *ap) -{ - int c; - EXPR rop; - - c_expr_e(ap); // get exponential precedence term - for (;;) { // get operator - c = getnb(); - if ((c=='<') || (c=='>')) - if (c != getnb()) // << or >> - exprerr(3); - if (ctype[c] != MULOP) { - UNGET; - break; - } - c_expr_e(&rop); // right hand operand - - switch(c) { - case '*': - if (ap->relative && rop.relative) - exprerr(11); - - ap->value *= rop.value; - ap->relative = (ap->relative || rop.relative) ? RELATIVE : ABSOLUTE; - break; - - case '/': - if (rop.value == 0) - exprerr(2); - if (ap->relative || rop.relative) - exprerr(11); - - ap->value /= rop.value; - break; - - case '%': - if (rop.value == 0) - exprerr(2); - if (ap->relative || rop.relative) - exprerr(11); - - ap->value = ((long) (ap->value)) % ((long) rop.value); - break; - - case '&': - if (ap->relative || rop.relative) - exprerr(11); - - ap->value = ((long) (ap->value)) & ((long) rop.value); - break; - - case '>': - if (ap->relative || rop.relative) - exprerr(11); - - ap->value = ((long) (ap->value)) >> ((long) rop.value); - break; - - case '<': - if (ap->relative || rop.relative) - exprerr(11); - - ap->value = ((long) (ap->value)) << ((long) rop.value); - break; - - default: - printf("In expr_m, can't happen\n"); - } - } -} - -// --------------------------------------------------------------------------------- -// c_expr_e - get exponential precedence terms. Again, this is not usually used -// --------------------------------------------------------------------------------- - -void c_expr_e (EXPR *ap) -{ - int c, i, v; - EXPR rop; - - c_expr_u(ap); - for (;;) { - c = getnb(); - if (ctype[c] != EXPOP) { - UNGET; - break; - } - c_expr_u(&rop); - - switch(c) { - case '^': - if (ap->relative || rop.relative) - exprerr(11); - - v = ap->value; - ap->value = 1; - for (i = 0; i < rop.value; i++) - ap->value *= v; - break; - - default: - printf("In expr_e, can't happen\n"); - } - } -} - -// --------------------------------------------------------------------------------- -// c_expr_u - get unary precedence terms. Again, this is not usually used -// --------------------------------------------------------------------------------- - -void c_expr_u (EXPR *ap) -{ - int c; - - if ((c = getnb()) == '!') { - a1130_term(ap); - ap->value = ~ ((long)(ap->value)); - if (ap->relative) - exprerr(11); - } - else if (c == '-') { - a1130_term(ap); - ap->value = - ap->value; - if (ap->relative) - exprerr(11); - } - else { - UNGET; - a1130_term(ap); - } -} - -// --------------------------------------------------------------------------------- -// c_term - get basic operand or parenthesized expression. Again, this is not usually used -// --------------------------------------------------------------------------------- - -void c_term (EXPR *ap) -{ - int c, cc; - PSYMBOL s; - char token[80], *t; - - ap->relative = ABSOLUTE; /* assume absolute */ - - if ((c = getnb()) == '(') { /* parenthesized expr */ - c_expr(ap); /* start over at the top! */ - if ((cc = getnb()) != ')') - exprerr(4); - } - else if (c == '\'') { /* single quote: char */ - if ((c = GETNEXT) == '\0') - c = ' '; - ap->value = c_esc(c); - } - else if (ctype[c] == DIGIT) { /* number */ - ap->value = c_number(c,10,-1); - } - else if (c == '0') { /* 0 starts a hex or octal constant */ - if ((c = GETNEXT) == 'x') { - c = GETNEXT; - ap->value = c_number(c,16,-1); - } - else { - ap->value = c_number(c,8,-1); - } - } - else if (c == '*') { /* asterisk alone = org */ - ap->value = org + org_advanced; - ap->relative = relocate; - } - else if (ctype[c] == LETTER) { /* symbol */ - t = token; - do { - *t++ = c; - c = GETNEXT; - } while (ctype[c] == LETTER || ctype[c] == DIGIT); - UNGET; - *t++ = '\0'; - - s = lookup_symbol(token, TRUE); - ap->value = s->value; - ap->relative = s->relative; - add_xref(s, FALSE); - symbest = MIN(symbest, s->defined); // this goes to lowest value (undefined < provisional < defined) - - if (pass == 2 && s->defined != S_DEFINED) - exprerr(1); - } - else - exprerr(8); -} - -// --------------------------------------------------------------------------------- -// c_number - get a C format constant value. Again, this is not usually used -// --------------------------------------------------------------------------------- - -int c_number (int c, int r, int nchar) -{ - int v, n; - - nchar--; - - if (c == '/' && ! cexpr) { /* special radix stuff */ - r = 16; - c = GETNEXT; - } - else if (r == 10 && c == '0' && cexpr) { /* accept C style 0x## also */ - c = GETNEXT; - if (c == 'x') { - r = 16; - c = GETNEXT; - } - else { - r = 8; - UNGET; - c = '0'; - } - } - - n = 0; /* decode number */ - while ((nchar-- != 0) && (v = digit(c, r)) >= 0) { - if (v >= r) /* out of range! */ - exprerr(9); - - n = r*n + v; - - c = GETNEXT; - if (c == '.') { // maybe make it decimal? - c = GETNEXT; - break; - } - } - - UNGET; - return (n); -} - -// --------------------------------------------------------------------------------- -// digit - get digit value of character c in radix r -// --------------------------------------------------------------------------------- - -int digit (int c, int r) -{ - if (r == 16) { - if (c >= 'A' && c <= 'F') - return (c - 'A' + 10); - } - - if (c >= '0' && c <= '9') - return (c - '0'); - - return (-1); -} - -// --------------------------------------------------------------------------------- -// c_esc - handle C character escape -// --------------------------------------------------------------------------------- - -int c_esc (int c) -{ - if (c != '\\') /* not escaped */ - return(c); - - if ((c = GETNEXT) == '\0') /* must be followed by something */ - exprerr(10); - if ((c >= 'A') && (c <= 'Z')) /* handle upper case */ - c += 'a'-'A'; - if (ctype[c] == LETTER) /* control character abbrevs */ - switch (c) { - case 'b': c = '\b'; break; /* backspace */ - case 'e': c = 27 ; break; /* escape */ - case 'f': c = '\f'; break; /* formfeed */ - case 'n': c = '\n'; break; /* newline */ - case 'r': c = '\r'; break; /* return */ - case 't': c = '\t'; break; /* horiz. tab */ - } - else if (ctype[c] == DIGIT) { /* get character by the numbers */ - c = c_number(c,8,3); /* force octal */ - } - - return c; -} - -// --------------------------------------------------------------------------------- -// exprerr - note an expression syntax error. Longjumps back to caller with failure code -// --------------------------------------------------------------------------------- - -void exprerr (int n) -{ - char msg[256]; - int nex = exprptr-oexprptr; - - strncpy(msg, oexprptr, nex); // show where the problem was - msg[nex] = '\0'; - strcat(msg, " << "); - strcat(msg, errstr[n]); - - asm_error(msg); - - exprerrno = n; - longjmp(exprjmp, 1); -} - -/* ------------------------------------------------------------------------ - * upcase - force a string to uppercase (ASCII) - * ------------------------------------------------------------------------ */ - -char *upcase (char *str) -{ - char *s; - - for (s = str; *s; s++) { - if (*s >= 'a' && *s <= 'z') - *s -= 32; - } - - return str; -} - -/* ------------------------------------------------------------------------ - * hollerith table for IPL card ident field - * ------------------------------------------------------------------------ */ - -typedef struct { - int hollerith; - char ascii; -} CPCODE; - -static CPCODE cardcode_029[] = -{ - 0x0000, ' ', - 0x8000, '&', // + in 026 Fortran - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0820, ':', - 0x0420, '#', // = in 026 Fortran - 0x0220, '@', // ' in 026 Fortran - 0x0120, '\'', - 0x00A0, '=', - 0x0060, '"', - 0x8820, 'c', // cent - 0x8420, '.', - 0x8220, '<', // ) in 026 Fortran - 0x8120, '(', - 0x80A0, '+', - 0x8060, '|', - 0x4820, '!', - 0x4420, '$', - 0x4220, '*', - 0x4120, ')', - 0x40A0, ';', - 0x4060, 'n', // not - 0x2820, 'x', // what? - 0x2420, ',', - 0x2220, '%', // ( in 026 Fortran - 0x2120, '_', - 0x20A0, '>', - 0x2060, '>', -}; - -int ascii_to_hollerith (int ch) -{ - int i; - - for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++) - if (cardcode_029[i].ascii == ch) - return cardcode_029[i].hollerith; - - return 0; -} - -/* ------------------------------------------------------------------------ - * detab - replace tabs with spaces for listing files - * ------------------------------------------------------------------------ */ - -char *detab (char *instr) -{ - static char outstr[256]; - char *out = outstr; - int col = 0; - - while (*instr) { - if (*instr == '\t') { - do { - *out++ = ' '; - col++; - } - while (col & 7); - } - else { - *out++ = *instr; - col++; - } - - instr++; - } - - *out = '\0'; - - return outstr; -} - - -#ifndef WIN32 - -int strnicmp (char *a, char *b, int n) -{ - int ca, cb; - - for (;;) { - if (--n < 0) // still equal after n characters? quit now - return 0; - - if ((ca = *a) == 0) // get character, stop on null terminator - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) // if different, return comparison - return ca; - - a++, b++; - } -} - -int strcmpi (char *a, char *b) -{ - int ca, cb; - - for (;;) { - if ((ca = *a) == 0) // get character, stop on null terminator - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) // if different, return comparison - return ca; - - a++, b++; - } -} - -#endif diff --git a/Ibm1130/utils/asm1130.mak b/Ibm1130/utils/asm1130.mak deleted file mode 100644 index b072c224..00000000 --- a/Ibm1130/utils/asm1130.mak +++ /dev/null @@ -1,161 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "asm1130.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Debug" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/asm1130.exe $(OUTDIR)/asm1130.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"asm1130.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"asm1130.bsc" -BSC32_SBRS= \ - $(INTDIR)/asm1130.sbr - -$(OUTDIR)/asm1130.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:no /PDB:$(OUTDIR)/"asm1130.pdb" /MACHINE:I386\ - /OUT:$(OUTDIR)/"asm1130.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/asm1130.obj - -$(OUTDIR)/asm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/asm1130.exe $(OUTDIR)/asm1130.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"asm1130.pch" /Fo$(INTDIR)/\ - /Fd$(OUTDIR)/"asm1130.pdb" /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"asm1130.bsc" -BSC32_SBRS= \ - $(INTDIR)/asm1130.sbr - -$(OUTDIR)/asm1130.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:yes /PDB:$(OUTDIR)/"asm1130.pdb" /DEBUG /MACHINE:I386\ - /OUT:$(OUTDIR)/"asm1130.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/asm1130.obj - -$(OUTDIR)/asm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\asm1130.c - -$(INTDIR)/asm1130.obj : $(SOURCE) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Ibm1130/utils/bindump.c b/Ibm1130/utils/bindump.c deleted file mode 100644 index 332e42ee..00000000 --- a/Ibm1130/utils/bindump.c +++ /dev/null @@ -1,752 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -// --------------------------------------------------------------------------------- -// BINDUMP - dumps card deck files in assembler object format -// -// Usage: -/// bindump deckfile lists object header info & sector break cards -// bindump -v deckfile lists object data records as well -// bindump -p deckfile for system program, lists phase IDs in the deck -// bindump -s deckfile >outfile for system program, sorts the phases & writes to stdout - -#include -#include -#ifdef WIN32 -# include -# include -# include -#endif - -#ifndef TRUE - #define BOOL int - #define TRUE 1 - #define FALSE 0 -#endif - -typedef enum {R_ABSOLUTE = 0, R_RELATIVE = 1, R_LIBF = 2, R_CALL = 3} RELOC; - -BOOL verbose = FALSE; -BOOL phid = FALSE; -BOOL sort = FALSE; -unsigned short card[80], buf[54], cardtype; - -// bindump - dump a binary (card format) deck to verify sbrks, etc - -void bail (char *msg); -void dump (char *fname); -void dump_data (char *fname); -void dump_phids (char *fname); -char *getname (unsigned short *ptr); -char *getseq (void); -int hollerith_to_ascii (unsigned short h); -void process (char *fname); -void show_raw (char *name); -void show_data (void); -void show_core (void); -void show_endc (void); -void show_81 (void); -void show_main (void); -void show_sub (void); -void show_ils (void); -void show_iss (void); -void show_end (void); -void sort_phases (char *fname); -void trim (char *s); -void unpack (unsigned short *card, unsigned short *buf); -void verify_checksum(unsigned short *buf); - -int main (int argc, char **argv) -{ - char *arg; - static char usestr[] = "Usage: bindump [-psv] filename..."; - int i; - - for (i = 1; i < argc; i++) { - arg = argv[i]; - if (*arg == '-') { - arg++; - while (*arg) { - switch (*arg++) { - case 'v': - verbose = TRUE; - break; - case 'p': - phid = TRUE; // print only phase ID's - break; - case 's': - sort = TRUE; // sort deck by phases, writing to stdout - break; - default: - bail(usestr); - } - } - } - } - - for (i = 1; i < argc; i++) { - arg = argv[i]; - if (*arg != '-') - process(arg); - } - return 0; -} - -void process (char *nm) -{ -#ifdef WIN32 - WIN32_FIND_DATA fd; - HANDLE hFind; - char *c, buf[256]; - - if (strchr(nm, '*') == NULL && strchr(nm, '?') == NULL) - dump(nm); - - else if ((hFind = FindFirstFile(nm, &fd)) == INVALID_HANDLE_VALUE) - fprintf(stderr, "No files matching '%s'\n", nm); - - else { - if ((c = strrchr(nm, '\\')) == NULL) - c = strrchr(nm, ':'); - - do { - if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - continue; - - if (c == NULL) - dump(fd.cFileName); - else { - strcpy(buf, nm); - strcpy(buf + (c-nm+1), fd.cFileName); - dump(buf); - } - - } while (FindNextFile(hFind, &fd)); - - FindClose(hFind); - } -#else - dump(nm); // on unices, sh globs for us -#endif -} - -void dump (char *fname) -{ - if (sort) - sort_phases(fname); - else if (phid) - dump_phids(fname); - else - dump_data(fname); -} - -struct tag_card { - int phid, seq; - unsigned short card[80]; -}; - -int cardcomp (const void *a, const void *b) -{ - short diff; - - diff = ((struct tag_card *) a)->phid - ((struct tag_card *) b)->phid; - - return diff ? diff : (((struct tag_card *) a)->seq - ((struct tag_card *) b)->seq); -} - -void sort_phases (char *fname) -{ - int i, ncards, cardtype, len, seq = 0, phid; - struct tag_card *deck; - FILE *fd; - BOOL saw_sbrk = TRUE; - - if ((fd = fopen(fname, "rb")) == NULL) { - perror(fname); - return; - } - - fseek(fd, 0, SEEK_END); - len = ftell(fd); // get length of file - fseek(fd, 0, SEEK_SET); - - if (len <= 0 || (len % 160) != 0) { - fprintf(stderr, "%s is not a binard deck image\n"); - fclose(fd); - return; - } - - ncards = len / 160; - - if ((deck = (struct tag_card *) malloc(ncards*sizeof(struct tag_card))) == NULL) { - fprintf(stderr, "%s: can't sort, insufficient memory\n"); - fclose(fd); - return; - } - - phid = 0; - for (i = 0; i < ncards; i++) { - if (fread(deck[i].card, sizeof(card[0]), 80, fd) != 80) { - free(deck); - fprintf(stderr, "%s: error reading deck\n"); - fclose(fd); - return; - } - - unpack(deck[i].card, buf); - deck[i].seq = seq++; - deck[i].phid = phid; - - verify_checksum(buf); - - cardtype = (buf[2] >> 8) & 0xFF; - - if (cardtype == 1 || cardtype == 2) { // start of deck is same as sector break - saw_sbrk = TRUE; - } - else if (cardtype == 0) { - fprintf(stderr, "%s is a core image deck\n"); - free(deck); - fclose(fd); - return; - } - else if (cardtype == 0x0A && saw_sbrk) { - phid = (int) (signed short) buf[10]; - if (phid < 0) - phid = -phid; - - deck[i].phid = phid; // this belongs to the new phase - deck[i-1].phid = phid; // as does previous card - saw_sbrk = FALSE; - } - } - fclose(fd); - - qsort(deck, ncards, sizeof(struct tag_card), cardcomp); // sort the deck - -#ifdef WIN32 - _setmode(_fileno(stdout), _O_BINARY); // set standard output to binary mode -#endif - - for (i = 0; i < ncards; i++) // write to stdout - fwrite(deck[i].card, sizeof(card[0]), 80, stdout); - - free(deck); -} - -void dump_phids (char *fname) -{ - FILE *fp; - BOOL first = TRUE; - BOOL saw_sbrk = TRUE, neg; - short id; - - if ((fp = fopen(fname, "rb")) == NULL) { - perror(fname); - return; - } - - printf("\n%s:\n", fname); - - while (fread(card, sizeof(card[0]), 80, fp) > 0) { - unpack(card, buf); - verify_checksum(buf); - - cardtype = (buf[2] >> 8) & 0xFF; - - if (cardtype == 1 && ! first) { // sector break - saw_sbrk = TRUE; - continue; - } - else { - switch (cardtype) { - case 0x00: - printf(" This is a core image deck\n"); - goto done; - break; - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x0F: - break; - - case 0x0A: - if (saw_sbrk) { - id = buf[10]; - if (id < 0) - id = -id, neg = TRUE; - else - neg = FALSE; - printf(" : %3d / %02x%s\n", id, id, neg ? " (neg)" : ""); - saw_sbrk = FALSE; - } - break; - - default: - show_raw("??? "); - } - } -done: - first = FALSE; - } - - fclose(fp); -} - -void dump_data (char *fname) -{ - FILE *fp; - BOOL first = TRUE; - char str[80]; - int i; - - if ((fp = fopen(fname, "rb")) == NULL) { - perror(fname); - return; - } - - printf("\n%s:\n", fname); - - while (fread(card, sizeof(card[0]), 80, fp) > 0) { - unpack(card, buf); - verify_checksum(buf); - - cardtype = (buf[2] >> 8) & 0xFF; - - if (cardtype == 1 && ! first) { // sector break - for (i = 4; i < 72; i++) - str[i] = hollerith_to_ascii(card[i]); - - str[i] = '\0'; - trim(str+4); - printf("*SBRK %s\n", str+4); - continue; - } - else { - switch (cardtype) { - case 0x00: - if (first) - show_raw("CORE"); - if (verbose) - show_core(); - break; - - case 0x01: - show_raw("ABS "); - show_main(); - break; - case 0x02: - show_raw("REL "); - show_main(); - break; - case 0x03: - show_raw("LIB "); - show_sub(); - break; - case 0x04: - show_raw("SUB "); - show_sub(); - break; - case 0x05: - show_raw("ISSL"); - show_iss(); - break; - case 0x06: - show_raw("ISSC"); - show_iss(); - break; - case 0x07: - show_raw("ILS "); - show_ils(); - break; - case 0x0F: - show_raw("END "); - show_end(); - break; - case 0x80: - show_raw("ENDC"); - show_endc(); - break; - case 0x81: - show_raw("81 "); - show_81(); - break; - case 0x0A: - if (verbose) - show_data(); - break; - default: - show_raw("??? "); - } - } - - first = FALSE; - } - - fclose(fp); -} - -void show_data (void) -{ - int i, n, jrel, rflag, nout, ch, reloc; - BOOL first = TRUE; - - n = buf[2] & 0x00FF; - - printf("%04x: ", buf[0]); - - jrel = 3; - nout = 0; - rflag = buf[jrel++]; - for (i = 0; i < n; i++) { - if (nout >= 8) { - rflag = buf[jrel++]; - if (first) { - printf(" %s", getseq()); - first = FALSE; - } - printf("\n "); - nout = 0; - } - reloc = (rflag >> 14) & 0x03; - ch = (reloc == R_ABSOLUTE) ? ' ' : - (reloc == R_RELATIVE) ? 'R' : - (reloc == R_LIBF) ? 'L' : '@'; - - printf("%04x%c ", buf[9+i], ch); - rflag <<= 2; - nout++; - } - putchar('\n'); -} - -void show_core (void) -{ - int i, n, nout; - BOOL first = TRUE; - - n = buf[2] & 0x00FF; - - printf("%04x: ", buf[0]); - - nout = 0; - for (i = 0; i < n; i++) { - if (nout >= 8) { - if (first) { - printf(" %s", getseq()); - first = FALSE; - } - printf("\n "); - nout = 0; - } - printf("%04x ", buf[9+i]); - nout++; - } - putchar('\n'); -} - -void info (int i, char *nm, char type) -{ - if (nm) - printf("%s ", nm); - - switch (type) { - case 'd': - printf("%d ", buf[i]); - break; - - case 'x': - printf("%04x ", buf[i]); - break; - - case 'b': - printf("%02x ", buf[i] & 0xFF); - break; - - case 'n': - printf("%s ", getname(buf+i)); - break; - - default: - bail("BAD TYPE"); - } -} - -void show_main (void) -{ - printf(" "); - info(2, "prec", 'b'); - info(4, "common", 'd'); - info(6, "work", 'd'); - info(8, "files", 'd'); - info(9, "name", 'n'); - info(11, "pta", 'x'); - putchar('\n'); -} - -void show_sub (void) -{ - int i, n; - - printf(" "); - info( 2, "prec", 'b'); - - n = buf[5] / 3; - for (i = 0; i < n; i++) { - info( 9+3*i, "ent", 'n'); - info(11+3*i, NULL, 'x'); - } - - putchar('\n'); -} - -void show_iss (void) -{ - printf(" "); - info(12, "level", 'd'); - putchar('\n'); -} - -void show_ils (void) -{ - printf(" "); - info( 2, "prec", 'b'); - info( 5, "nint6", 'd'); - info( 9, "ent", 'n'); - info(11, NULL, 'x'); - info(14, "nint", 'd'); - info(15, "il1", 'd'); - info(16, "il2", 'd'); - putchar('\n'); -} - -void show_end (void) -{ - printf(" "); - info(0, "size", 'd'); - info(3, "pta", 'x'); - putchar('\n'); -} - -void show_endc(void) -{ - printf(" "); - info(52, "IX3", 'x'); - info(53, "pta", 'x'); - putchar('\n'); -} - -void show_81(void) -{ -} - -void show_raw (char *name) -{ - int i; - printf("*%s", name); - - for (i = 0; i < 12; i++) - printf(" %04x", buf[i]); - - printf(" %s\n", getseq()); -} - -char * getseq (void) -{ - static char seq[10]; - int i; - - for (i = 0; i < 8; i++) - seq[i] = hollerith_to_ascii(card[72+i]); - - seq[i] = '\0'; - return seq; -} - - -void bail (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - -void unpack (unsigned short *icard, unsigned short *obuf) -{ - int i, j; - unsigned short wd1, wd2, wd3, wd4; - - for (i = j = 0; i < 54; i += 3, j += 4) { - wd1 = icard[j]; - wd2 = icard[j+1]; - wd3 = icard[j+2]; - wd4 = icard[j+3]; - - obuf[i ] = (wd1 & 0xFFF0) | ((wd2 >> 12) & 0x000F); - obuf[i+1] = ((wd2 << 4) & 0xFF00) | ((wd3 >> 8) & 0x00FF); - obuf[i+2] = ((wd3 << 8) & 0xF000) | ((wd4 >> 4) & 0x0FFF); - } -} - -void verify_checksum (unsigned short *obuf) -{ -// unsigned short sum; - - if (obuf[1] == 0) // no checksum - return; - -// if (sum != card[1]) -// printf("Checksum %04x doesn't match card %04x\n", sum, card[1]); -} - -typedef struct { - unsigned short hollerith; - char ascii; -} CPCODE; - -static CPCODE cardcode_029[] = -{ - 0x0000, ' ', - 0x8000, '&', // + in 026 Fortran - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0820, ':', - 0x0420, '#', // = in 026 Fortran - 0x0220, '@', // ' in 026 Fortran - 0x0120, '\'', - 0x00A0, '=', - 0x0060, '"', - 0x8820, 'c', // cent - 0x8420, '.', - 0x8220, '<', // ) in 026 Fortran - 0x8120, '(', - 0x80A0, '+', - 0x8060, '|', - 0x4820, '!', - 0x4420, '$', - 0x4220, '*', - 0x4120, ')', - 0x40A0, ';', - 0x4060, 'n', // not - 0x2820, 'x', // what? - 0x2420, ',', - 0x2220, '%', // ( in 026 Fortran - 0x2120, '_', - 0x20A0, '>', - 0x2060, '>', -}; - -int hollerith_to_ascii (unsigned short h) -{ - int i; - - h &= 0xFFF0; - - for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++) - if (cardcode_029[i].hollerith == h) - return cardcode_029[i].ascii; - - return '?'; -} - -// --------------------------------------------------------------------------------- -// trim - remove trailing whitespace from string s -// --------------------------------------------------------------------------------- - -void trim (char *s) -{ - char *nb; - - for (nb = s-1; *s; s++) - if (*s > ' ') - nb = s; - - nb[1] = '\0'; -} - -int ascii_to_ebcdic_table[128] = -{ - 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f, - 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61, - 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f, - - 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6, - 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d, - 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96, - 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07, -}; - -char *getname (unsigned short *ptr) -{ - static char str[6]; - int i, j, ch; - long v; - - v = (ptr[0] << 16L) | ptr[1]; - - for (i = 0; i < 5; i++) { - ch = ((v >> 24) & 0x3F) | 0xC0; // recover those lost two bits - v <<= 6; - - str[i] = ' '; - - for (j = 0; j < (sizeof(ascii_to_ebcdic_table)/sizeof(ascii_to_ebcdic_table[0])); j++) { - if (ascii_to_ebcdic_table[j] == ch) { - str[i] = j; - break; - } - } - } - - str[5] = '\0'; - return str; -} - diff --git a/Ibm1130/utils/bindump.mak b/Ibm1130/utils/bindump.mak deleted file mode 100644 index 192cd550..00000000 --- a/Ibm1130/utils/bindump.mak +++ /dev/null @@ -1,161 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "bindump.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Debug" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/bindump.exe $(OUTDIR)/bindump.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"bindump.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"bindump.bsc" -BSC32_SBRS= \ - $(INTDIR)/bindump.sbr - -$(OUTDIR)/bindump.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:$(OUTDIR)/"bindump.pdb"\ - /MACHINE:I386 /OUT:$(OUTDIR)/"bindump.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/bindump.obj - -$(OUTDIR)/bindump.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/bindump.exe $(OUTDIR)/bindump.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"bindump.pch" /Fo$(INTDIR)/\ - /Fd$(OUTDIR)/"bindump.pdb" /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"bindump.bsc" -BSC32_SBRS= \ - $(INTDIR)/bindump.sbr - -$(OUTDIR)/bindump.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:$(OUTDIR)/"bindump.pdb" /DEBUG\ - /MACHINE:I386 /OUT:$(OUTDIR)/"bindump.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/bindump.obj - -$(OUTDIR)/bindump.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\bindump.c - -$(INTDIR)/bindump.obj : $(SOURCE) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Ibm1130/utils/checkdisk.c b/Ibm1130/utils/checkdisk.c deleted file mode 100644 index 82a879e0..00000000 --- a/Ibm1130/utils/checkdisk.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -// checkdisk - validates and optionally dumps an IBM1130 DMS2 disk image file -// -// Usage: -// checkdisk [-f] [-d cyl.sec|abssec] [-n count] filename -// -// Examples: -// checkdisk file.dsk -// report any misnumbered sectors in file.dsk -// -// checkdisk -f file.dsk -// report and fix any misnumbered sectors -// -// checkdisk -d 198.0 file.dsk -// dump cylinder 198 sector 0 -// -// checkdisk -d 0 file.dsk -// dump absolute sector 0 -// -// checkdisk -d 198.0 -n 4 file.dsk -// dump 4 sectors starting at m.n -// ----------------------------------------------------------------------------------------- -#include -#include -#include -#include "util_io.h" - -#ifdef WIN32 -# include -#else - long filelength (int fno); -# include -# include -#endif - -#ifndef TRUE -# define BOOL int -# define TRUE 1 -# define FALSE 0 -#endif - -#define DSK_NUMWD 321 /* words/sector */ -#define DSK_NUMSC 4 /* sectors/surface */ -#define DSK_NUMSF 2 /* surfaces/cylinder */ -#define DSK_NUMCY 203 /* cylinders/drive */ -#define DSK_NUMDR 5 /* drives/controller */ -#define DSK_SIZE (DSK_NUMCY * DSK_NUMSF * DSK_NUMSC * DSK_NUMWD) /* words/drive */ - -char *usestr = "Usage: checkdisk [-f] [-d cyl.sec|abssec] [-n count] diskfile"; -char *baddisk = "Cannot fix this"; - -void bail (char *msg); -char *lowcase (char *str); - -int main (int argc, char **argv) -{ - FILE *fp; - char *fname = NULL, *arg, *argval; - int i, j, cyl, sec, pos, asec, retry, nbad = 0, nfixed = 0, nline; - BOOL fixit = FALSE, dump = FALSE; - int dsec, nsec = 1; - unsigned short wd, buf[DSK_NUMWD]; - - util_io_init(); - - for (i = 1; i < argc;) { - arg = argv[i++]; - if (*arg == '-') { - arg++; - lowcase(arg); - while (*arg) { - switch (*arg++) { - case 'f': - fixit = TRUE; - break; - - case 'd': - dump = TRUE; - - if (i >= argc) - bail(usestr); - - argval = argv[i++]; - if (strchr(argval, '.') != NULL) { - if (sscanf(argval, "%d.%d", &cyl, &sec) != 2) - bail(usestr); - - dsec = cyl*(DSK_NUMSF*DSK_NUMSC) + sec; - } - else if (sscanf(argval, "%d", &dsec) != 1) - bail(usestr); - - if (dsec < 0 || dsec >= (DSK_NUMCY*DSK_NUMSF*DSK_NUMSC)) - bail("No such sector"); - - break; - - case 'n': - if (i >= argc) - bail(usestr); - - argval = argv[i++]; - if (sscanf(argval, "%d", &nsec) != 1) - bail(usestr); - - if (nsec <= 0) - bail(usestr); - - break; - - default: - bail(usestr); - } - } - } - else if (fname == NULL) - fname = arg; - else - bail(usestr); - } - - if (fname == NULL) - bail(usestr); - - if ((fp = fopen(fname, "rb+")) == NULL) { - perror(fname); - return 1; - } - - if (filelength(fileno(fp)) != 2*DSK_SIZE) { - fprintf(stderr, "File is wrong length, expected %d\n", DSK_SIZE); - bail(baddisk); - } - - for (cyl = 0; cyl < DSK_NUMCY; cyl++) { - for (sec = 0; sec < (DSK_NUMSF*DSK_NUMSC); sec++) { - retry = 1; -again: - asec = cyl*(DSK_NUMSF*DSK_NUMSC) + sec; - pos = asec*2*DSK_NUMWD; - - if (fseek(fp, pos, SEEK_SET) != 0) { - fprintf(stderr, "Error seeking to pos %x\n", pos); - bail(baddisk); - } - - if (fxread(&wd, sizeof(wd), 1, fp) != 1) { - fprintf(stderr, "Error reading word at abs sec %x, cyl %x, sec %x at offset %x\n", asec, cyl, sec, pos); - bail(baddisk); - } - - if (wd != asec) { - fprintf(stderr, "Bad sector #%x at abs sec %x, cyl %x, sec %x at offset %x\n", wd, asec, cyl, sec, pos); - nbad++; - - if (fixit) { - if (fseek(fp, pos, SEEK_SET) != 0) { - fprintf(stderr, "Error seeking to pos %x\n", pos); - bail(baddisk); - } - - if (fxwrite(&asec, sizeof(wd), 1, fp) != 1) { - fprintf(stderr, "Error writing sector # to abs sec %x, cyl %x, sec %x at offset %x\n", asec, cyl, sec, pos); - bail(baddisk); - } - - if (retry) { - retry = 0; - nfixed++; - goto again; - } - - fprintf(stderr, "Failed after retry\n"); - bail(baddisk); - } - } - } - } - - if (nbad) - printf("%d bad sector mark%s %s\n", nbad, (nbad == 1) ? "" : "s", fixit ? "fixed" : "found"); - else if (! dump) - printf("All sector marks OK\n"); - - if (! dump) - return 0; - - pos = dsec*2*DSK_NUMWD; - if (fseek(fp, pos, SEEK_SET) != 0) { - fprintf(stderr, "Error seeking to pos %x\n", pos); - bail(baddisk); - } - - for (i = 0; i < nsec; i++) { - cyl = dsec / (DSK_NUMSF*DSK_NUMSC); - sec = dsec - cyl*(DSK_NUMSF*DSK_NUMSC); - - if (fxread(&buf, sizeof(buf[0]), DSK_NUMWD, fp) != DSK_NUMWD) { - fprintf(stderr, "Error reading abs sec %x, cyl %x, sec %x at offset %x\n", dsec, cyl, sec, pos); - bail(baddisk); - } - - printf("\nSector %d.%d - %d - /%04x label %04x\n", cyl, sec, dsec, dsec, buf[0]); - for (nline = 0, j = 1; j < DSK_NUMWD; j++) { - printf("%04x", buf[j]); - if (++nline == 16) { - putchar('\n'); - nline = 0; - } - else - putchar(' '); - } - - dsec++; - } - - return 0; -} - -void bail (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - -/* ------------------------------------------------------------------------ - * lowcase - force a string to lower case (ASCII) - * ------------------------------------------------------------------------ */ - -char *lowcase (char *str) -{ - char *s; - - for (s = str; *s; s++) { - if (*s >= 'A' && *s <= 'Z') - *s += 32; - } - - return str; -} - -#ifndef WIN32 - -long filelength (int fno) -{ - struct stat sb; - - if (fstat(fno, &sb) != 0) - return 0; - - return (long) sb.st_size; -} -#endif - diff --git a/Ibm1130/utils/checkdisk.mak b/Ibm1130/utils/checkdisk.mak deleted file mode 100644 index e03d955b..00000000 --- a/Ibm1130/utils/checkdisk.mak +++ /dev/null @@ -1,177 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "checkdisk.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Release" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/checkdisk.exe $(OUTDIR)/checkdisk.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"checkdisk.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"checkdisk.bsc" -BSC32_SBRS= \ - $(INTDIR)/checkdisk.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/checkdisk.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib /NOLOGO\ - /SUBSYSTEM:console /INCREMENTAL:no /PDB:$(OUTDIR)/"checkdisk.pdb" /MACHINE:I386\ - /OUT:$(OUTDIR)/"checkdisk.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/checkdisk.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/checkdisk.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/checkdisk.exe $(OUTDIR)/checkdisk.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"checkdisk.pch" /Fo$(INTDIR)/\ - /Fd$(OUTDIR)/"checkdisk.pdb" /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"checkdisk.bsc" -BSC32_SBRS= \ - $(INTDIR)/checkdisk.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/checkdisk.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib /NOLOGO\ - /SUBSYSTEM:console /INCREMENTAL:yes /PDB:$(OUTDIR)/"checkdisk.pdb" /DEBUG\ - /MACHINE:I386 /OUT:$(OUTDIR)/"checkdisk.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/checkdisk.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/checkdisk.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\checkdisk.c -DEP_CHECK=\ - .\util_io.h\ - \MSVC20\INCLUDE\sys\types.h\ - \MSVC20\INCLUDE\sys\stat.h - -$(INTDIR)/checkdisk.obj : $(SOURCE) $(DEP_CHECK) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\util_io.c - -$(INTDIR)/util_io.obj : $(SOURCE) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Ibm1130/utils/diskview.c b/Ibm1130/utils/diskview.c deleted file mode 100644 index 65ee850e..00000000 --- a/Ibm1130/utils/diskview.c +++ /dev/null @@ -1,614 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -// DISKVIEW - lists contents of an 1130 system disk image file. Not finished yet. -// needs LET/SLET listing routine. -// -// usage: -// diskview -v diskfile - -#include -#include -#include -#include -#include "util_io.h" - -#define BETWEEN(v,a,b) (((v) >= (a)) && ((v) <= (b))) -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) -#define MAX(a,b) (((a) >= (b)) ? (a) : (b)) - -#ifndef TRUE -# define TRUE 1 -# define FALSE 0 -# define BOOL int -#endif - -#define NOT_DEF 0x0658 // defective cylinder table entry means no defect - -#define DSK_NUMWD 321 /* words/sector */ -#define DSK_NUMCY 203 /* cylinders/drive */ -#define DSK_SECCYL 8 /* sectors per cylinder */ -#define SECLEN 320 /* data words per sector */ -#define SLETLEN ((3*SECLEN)/4) /* length of slet in records */ - -typedef unsigned short WORD; - -FILE *fp; -WORD buf[DSK_NUMWD]; -WORD dcom[DSK_NUMWD]; - -#pragma pack(2) -struct tag_slet { - WORD phid; - WORD addr; - WORD nwords; - WORD sector; -} slet[SLETLEN]; - -#pragma pack() - -WORD dcyl[3]; -BOOL verbose = FALSE; - -void checksectors (void); -void dump_id (void); -void dump_dcom (void); -void dump_resmon (void); -void dump_slet (void); -void dump_hdng (void); -void dump_scra (void); -void dump_let (void); -void dump_flet (void); -void dump_cib (void); -void getsector (int sec, WORD *sbuf); -void getdcyl (void); -char *lowcase (char *str); - -void bail(char *fmt, ...); -char *trim (char *s); - -int main (int argc, char **argv) -{ - char *fname = NULL, *arg; - static char usestr[] = "Usage: diskview [-v] filename"; - int i; - - util_io_init(); - - for (i = 1; i < argc;) { - arg = argv[i++]; - if (*arg == '-') { - arg++; - lowcase(arg); - while (*arg) { - switch (*arg++) { - case 'v': - verbose = TRUE; - break; - - default: - bail(usestr); - } - } - } - else if (fname == NULL) - fname = arg; - else - bail(usestr); - } - - if (fname == NULL) - bail(usestr); - - if ((fp = fopen(fname, "rb")) == NULL) { - perror(fname); - return 2; - } - - printf("%s:\n", fname); - - checksectors(); - getdcyl(); - - dump_id(); // ID & coldstart - dump_dcom(); // DCOM - dump_resmon(); // resident image - dump_slet(); // SLET - dump_hdng(); // heading sector - dump_scra(); - dump_flet(); - dump_cib(); - dump_let(); - - fclose(fp); - return 0; -} - -// checksectors - verify that all sectors are properly numbered - -void checksectors () -{ - WORD sec = 0; - - fseek(fp, 0, SEEK_SET); - - for (sec = 0; sec < DSK_NUMCY*DSK_SECCYL; sec++) { - if (fxread(buf, sizeof(WORD), DSK_NUMWD, fp) != DSK_NUMWD) - bail("File read error or not a disk image file"); - - if (buf[0] != sec) - bail("Sector /%x is misnumbered, run checkdisk [-f]", sec); - } -} - -// get defective cylinder list - -void getdcyl (void) -{ - fseek(fp, sizeof(WORD), SEEK_SET); // skip sector count - if (fxread(dcyl, sizeof(WORD), 3, fp) != 3) - bail("Unable to read defective cylinder table"); -} - -// getsector - read specified absolute sector - -void getsector (int sec, WORD *sbuf) -{ - int i, cyl, ssec; - - sec &= 0x7FF; // mask of drive bits, if any - - cyl = sec / DSK_SECCYL; // get cylinder - ssec = sec & ~(DSK_SECCYL-1); // mask to get starting sector of cylinder - for (i = 0; i < 3; i++) { // map through defective cylinder table - if (dcyl[i] == ssec) { - sec &= (DSK_SECCYL-1); // mask to get base sector - cyl = DSK_NUMCY-3+i; // replacements are last three on disk - sec += cyl*DSK_SECCYL; // add new cylinder offset - break; - } - } - // read the sector - if (fseek(fp, (sec*DSK_NUMWD+1)*sizeof(WORD), SEEK_SET) != 0) - bail("File seek failed"); - - if (fxread(sbuf, sizeof(WORD), DSK_NUMWD, fp) != DSK_NUMWD) - bail("File read error or not a disk image file"); -} - -void dump (int nwords) -{ - int i, nline = 0; - - for (i = 0; i < nwords; i++) { - if (nline == 16) { - putchar('\n'); - nline = 0; - } - - printf("%04x", buf[i]); - nline++; - } - putchar('\n'); -} - -void showmajor (char *label) -{ - int i; - - printf("\n--- %s ", label); - - for (i = strlen(label); i < 40; i++) - putchar('-'); - - putchar('\n'); - putchar('\n'); -} - -void name (char *label) -{ - printf("%-32.32s ", label); -} - -void pbf (char *label, WORD *buf, int nwords) -{ - int i, nout; - - name(label); - - for (i = nout = 0; i < nwords; i++, nout++) { - if (nout == 8) { - putchar('\n'); - name(""); - nout = 0; - } - printf(" %04x", buf[i]); - } - - putchar('\n'); -} - -void prt (char *label, char *fmt, ...) -{ - va_list args; - - name(label); - - putchar(' '); - va_start(args, fmt); - vprintf(fmt, args); - va_end(args); - - putchar('\n'); -} - -void dump_id (void) -{ - showmajor("Sector 0 - ID & coldstart"); - getsector(0, buf); - - pbf("DCYL def cyl table", buf+ 0, 3); - pbf("CIDN cart id", buf+ 3, 1); - pbf(" copy code", buf+ 4, 1); - pbf("DTYP disk type", buf+ 7, 1); - pbf(" diskz copy", buf+ 30, 8); - pbf(" cold start pgm",buf+270, 8); -} - -// EQUIVALENCES FOR DCOM PARAMETERS -#define NAME 4 // NAME OF PROGRAM/CORE LOAD -#define DBCT 6 // BLOCK CT OF PROGRAM/CORE LOAD -#define FCNT 7 // FILES SWITCH -#define SYSC 8 // SYSTEM/NON-SYSTEM CARTRIDGE INDR -#define JBSW 9 // JOBT SWITCH -#define CBSW 10 // CLB-RETURN SWITCH -#define LCNT 11 // NO. OF LOCALS -#define MPSW 12 // CORE MAP SWITCH -#define MDF1 13 // NO. DUP CTRL RECORDS (MODIF) -#define MDF2 14 // ADDR OF MODIF BUFFER -#define NCNT 15 // NO. OF NOCALS -#define ENTY 16 // RLTV ENTRY ADDR OF PROGRAM -#define RP67 17 // 1442-5 SWITCH -#define TODR 18 // OBJECT WORK STORAGE DRIVE CODE -#define FHOL 20 // ADDR LARGEST HOLE IN FIXED AREA -#define FSZE 21 // BLK CNT LARGEST HOLE IN FXA -#define UHOL 22 // ADDR LAST HOLE IN USER AREA 2-10 -#define USZE 23 // BLK CNT LAST HOLE IN UA 2-10 -#define DCSW 24 // DUP CALL SWITCH -#define PIOD 25 // PRINCIPAL I/O DEVICE INDICATOR -#define PPTR 26 // PRINCIPAL PRINT DEVICE INDICATOR -#define CIAD 27 // RLTV ADDR IN @STRT OF CIL ADDR -#define ACIN 28 // AVAILABLE CARTRIDGE INDICATOR -#define GRPH 29 // 2250 INDICATOR 2G2 -#define GCNT 30 // NO. G2250 RECORDS 2G2 -#define LOSW 31 // LOCAL-CALLS-LOCAL SWITCH 2-2 -#define X3SW 32 // SPECIAL ILS SWITCH 2-2 -#define ECNT 33 // NO. OF *EQUAT RCDS 2-4 -#define ANDU 35 // 1+BLK ADDR END OF UA (ADJUSTED) -#define BNDU 40 // 1+BLK ADDR END OF UA (BASE) -#define FPAD 45 // FILE PROTECT ADDR -#define PCID 50 // CARTRIDGE ID, PHYSICAL DRIVE -#define CIDN 55 // CARTRIDGE ID, LOGICAL DRIVE -#define CIBA 60 // SCTR ADDR OF CIB -#define SCRA 65 // SCTR ADDR OF SCRA -#define FMAT 70 // FORMAT OF PROG IN WORKING STG -#define FLET 75 // SCTR ADDR 1ST SCTR OF FLET -#define ULET 80 // SCTR ADDR 1ST SCTR OF LET -#define WSCT 85 // BLK CNT OF PROG IN WORKING STG -#define CSHN 90 // NO. SCTRS IN CUSHION AREA - -struct tag_dcominfo { - char *nm; - int offset; - char *descr; -} dcominfo[] = { - "NAME", 4, "NAME OF PROGRAM/CORE LOAD", - "DBCT", 6, "BLOCK CT OF PROGRAM/CORE LOAD", - "FCNT", 7, "FILES SWITCH", - "SYSC", 8, "SYSTEM/NON-SYSTEM CARTRIDGE INDR", - "JBSW", 9, "JOBT SWITCH", - "CBSW", 10, "CLB-RETURN SWITCH", - "LCNT", 11, "NO. OF LOCALS", - "MPSW", 12, "CORE MAP SWITCH", - "MDF1", 13, "NO. DUP CTRL RECORDS (MODIF)", - "MDF2", 14, "ADDR OF MODIF BUFFER", - "NCNT", 15, "NO. OF NOCALS", - "ENTY", 16, "RLTV ENTRY ADDR OF PROGRAM", - "RP67", 17, "1442-5 SWITCH", - "TODR", 18, "OBJECT WORK STORAGE DRIVE CODE", - "FHOL", 20, "ADDR LARGEST HOLE IN FIXED AREA", - "FSZE", 21, "BLK CNT LARGEST HOLE IN FXA", - "UHOL", 22, "ADDR LAST HOLE IN USER AREA", - "USZE", 23, "BLK CNT LAST HOLE IN UA", - "DCSW", 24, "DUP CALL SWITCH", - "PIOD", 25, "PRINCIPAL I/O DEVICE INDICATOR", - "PPTR", 26, "PRINCIPAL PRINT DEVICE INDICATOR", - "CIAD", 27, "RLTV ADDR IN @STRT OF CIL ADDR", - "ACIN", 28, "AVAILABLE CARTRIDGE INDICATOR", - "GRPH", 29, "2250 INDICATOR", - "GCNT", 30, "NO. G2250 RECORDS", - "LOSW", 31, "LOCAL-CALLS-LOCAL SWITCH", - "X3SW", 32, "SPECIAL ILS SWITCH", - "ECNT", 33, "NO. OF *EQUAT RCDS", - "ANDU", 35, "1+BLK ADDR END OF UA (ADJUSTED)", - "BNDU", 40, "1+BLK ADDR END OF UA (BASE)", - "FPAD", 45, "FILE PROTECT ADDR", - "PCID", 50, "CARTRIDGE ID, PHYSICAL DRIVE", - "CIDN", 55, "CARTRIDGE ID, LOGICAL DRIVE", - "CIBA", 60, "SCTR ADDR OF CIB", - "SCRA", 65, "SCTR ADDR OF SCRA", - "FMAT", 70, "FORMAT OF PROG IN WORKING STG", - "FLET", 75, "SCTR ADDR 1ST SCTR OF FLET", - "ULET", 80, "SCTR ADDR 1ST SCTR OF LET", - "WSCT", 85, "BLK CNT OF PROG IN WORKING STG", - "CSHN", 90, "NO. SCTRS IN CUSHION AREA", - NULL -}; - -void dump_dcom (void) -{ - struct tag_dcominfo *d; - char txt[50]; - - showmajor("Sector 1 - DCOM"); - getsector(1, dcom); - - for (d = dcominfo; d->nm != NULL; d++) { - sprintf(txt, "%-4.4s %s", d->nm, d->descr); - pbf(txt, dcom+d->offset, 1); - } -} - -void dump_resmon (void) -{ - showmajor("Sector 2 - Resident Image"); - getsector(2, buf); - dump(verbose ? SECLEN : 32); -} - -struct { - int pfrom, pto; - int printed; - char *name; -} sletinfo[] = { - 0x01, 0x12, FALSE, "DUP", - 0x1F, 0x39, FALSE, "Fortran", - 0x51, 0x5C, FALSE, "Cobol", - 0x6E, 0x74, FALSE, "Supervisor", - 0x78, 0x84, FALSE, "Core Load Builder", - 0x8C, 0x8C, FALSE, "Sys 1403 prt", - 0x8D, 0x8D, FALSE, "Sys 1132 prt", - 0x8E, 0x8E, FALSE, "Sys console prt", - 0x8F, 0x8F, FALSE, "Sys 2501 rdr", - 0x90, 0x90, FALSE, "Sys 1442 rdr/pun", - 0x91, 0x91, FALSE, "Sys 1134 paper tape", - 0x92, 0x92, FALSE, "Sys kbd", - 0x93, 0x93, FALSE, "Sys 2501/1442 conv", - 0x94, 0x94, FALSE, "Sys 1134 conv", - 0x95, 0x95, FALSE, "Sys kbd conv", - 0x96, 0x96, FALSE, "Sys diskz", - 0x97, 0x97, FALSE, "Sys disk1", - 0x98, 0x98, FALSE, "Sys diskn", - 0x99, 0x99, FALSE, "(primary print)", - 0x9A, 0x9A, FALSE, "(primary input)", - 0x9B, 0x9B, FALSE, "(primary input excl kbd)", - 0x9C, 0x9C, FALSE, "(primary sys conv)", - 0x9D, 0x9D, FALSE, "(primary conv excl kbd)", - 0xA0, 0xA1, FALSE, "Core Image Loader", - 0xB0, 0xCC, FALSE, "RPG", - 0xCD, 0xCE, FALSE, "Dup Part 2", - 0xCF, 0xF6, FALSE, "Macro Assembler", - 0 -}; - -void dump_slet (void) -{ - int i, j, iphase, nsecs, sec, max_sec = 0; - char sstr[16], *smark; - - showmajor("Sectors 3-5 - SLET"); - for (i = 0; i < 3; i++) { - getsector(3+i, buf); - memmove(((WORD *) slet)+SECLEN*i, buf, SECLEN*sizeof(WORD)); - } - - printf("# PHID Addr Len Sector Secs\n"); - printf("------------------------------------------\n"); - for (i = 0; i < SLETLEN; i++) { - if (slet[i].phid == 0) - break; - - sec = slet[i].sector; - iphase = (int) (signed short) slet[i].phid; - nsecs = (slet[i].nwords + SECLEN-1)/SECLEN; - - if (sec & 0xF800) { - smark = "*"; - sec &= 0x7FF; - } - else - smark = " "; - - for (j = 0; sletinfo[j].pfrom != 0; j++) - if (sletinfo[j].pfrom <= iphase && sletinfo[j].pto >= iphase) - break; - - sprintf(sstr, "(%d.%d)", sec / DSK_SECCYL, slet[i].sector % DSK_SECCYL); - - printf("%3d %04x %4d %04x %04x %04x %s %-7s %3x", - i, slet[i].phid, iphase, slet[i].addr, slet[i].nwords, slet[i].sector, smark, sstr, nsecs); - - if (iphase < 0) - iphase = -iphase; - - if (sletinfo[j].pfrom == 0) - printf(" ???"); - else if (! sletinfo[j].printed) { - printf(" %s", sletinfo[j].name); - sletinfo[j].printed = TRUE; - } - - for (j = 0; j < i; j++) { - if (sec == (slet[j].sector & 0x7FF)) { - printf(" (same as %04x)", slet[j].phid); - break; - } - } - - max_sec = MAX(max_sec, sec+nsecs-1); // find last sector used - - putchar('\n'); - - if (i >= 15 && ! verbose) { - printf("...\n"); - break; - } - } -} - -int ascii_to_ebcdic_table[128] = -{ - 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f, - 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61, - 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f, - - 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6, - 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d, - 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96, - 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07, -}; - -int ebcdic_to_ascii (int ch) -{ - int j; - - for (j = 32; j < 128; j++) - if (ascii_to_ebcdic_table[j] == ch) - return j; - - return '?'; -} - -#define HDR_LEN 120 - -void dump_hdng(void) -{ - int i; - char str[HDR_LEN+1], *p = str; - - showmajor("Sector 7 - Heading"); - getsector(7, buf); - - for (i = 0; i < (HDR_LEN/2); i++) { - *p++ = ebcdic_to_ascii((buf[i] >> 8) & 0xFF); - *p++ = ebcdic_to_ascii( buf[i] & 0xFF); - } - - *p = '\0'; - trim(str); - printf("%s\n", str); -} - -BOOL mget (int offset, char *name) -{ - char title[80]; - - if (dcom[offset] == 0) - return FALSE; - - getsector(dcom[offset], buf); - sprintf(title, "Sector %x - %s", dcom[offset], name); - showmajor(title); - return TRUE; -} - -void dump_scra (void) -{ - if (! mget(SCRA, "SCRA")) - return; - - dump(verbose ? SECLEN : 32); -} - -void dump_let (void) -{ - if (! mget(ULET, "LET")) - return; -} - -void dump_flet (void) -{ - if (! mget(FLET, "FLET")) - return; -} - -void dump_cib (void) -{ - if (! mget(CIBA, "CIB")) - return; - - dump(verbose ? SECLEN : 32); -} - -#define LFHD 5 // WORD COUNT OF LET/FLET HEADER PMN09970 -#define LFEN 3 // NO OF WDS PER LET/FLET ENTRY PMN09980 -#define SCTN 0 // RLTY ADDR OF LET/FLET SCTR NO. PMN09990 -#define UAFX 1 // RLTV ADDR OF SCTR ADDR OF UA/FXA PMN10000 -#define WDSA 3 // RLTV ADDR OF WDS AVAIL IN SCTR PMN10010 -#define NEXT 4 // RLTV ADDR OF ADDR NEXT SCTR PMN10020 -#define LFNM 0 // RLTV ADDR OF LET/FLET ENTRY NAME PMN10030 -#define BLCT 2 // RLTV ADDR OF LET/FLET ENTRY DBCT PMN10040 - -void bail (char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - fprintf(stderr, fmt, args); - va_end(args); - putchar('\n'); - - exit(1); -} - -// --------------------------------------------------------------------------------- -// trim - remove trailing whitespace from string s -// --------------------------------------------------------------------------------- - -char *trim (char *s) -{ - char *os = s, *nb; - - for (nb = s-1; *s; s++) - if (*s > ' ') - nb = s; - - nb[1] = '\0'; - return os; -} - -/* ------------------------------------------------------------------------ - * lowcase - force a string to lowercase (ASCII) - * ------------------------------------------------------------------------ */ - -char *lowcase (char *str) -{ - char *s; - - for (s = str; *s; s++) { - if (*s >= 'A' && *s <= 'Z') - *s += 32; - } - - return str; -} - diff --git a/Ibm1130/utils/diskview.mak b/Ibm1130/utils/diskview.mak deleted file mode 100644 index ef9a8cf3..00000000 --- a/Ibm1130/utils/diskview.mak +++ /dev/null @@ -1,175 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "diskview.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Debug" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/diskview.exe $(OUTDIR)/diskview.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"diskview.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"diskview.bsc" -BSC32_SBRS= \ - $(INTDIR)/diskview.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/diskview.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:no /PDB:$(OUTDIR)/"diskview.pdb" /MACHINE:I386\ - /OUT:$(OUTDIR)/"diskview.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/diskview.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/diskview.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/diskview.exe $(OUTDIR)/diskview.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"diskview.pch" /Fo$(INTDIR)/\ - /Fd$(OUTDIR)/"diskview.pdb" /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"diskview.bsc" -BSC32_SBRS= \ - $(INTDIR)/diskview.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/diskview.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:yes /PDB:$(OUTDIR)/"diskview.pdb" /DEBUG /MACHINE:I386\ - /OUT:$(OUTDIR)/"diskview.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/diskview.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/diskview.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\diskview.c - -$(INTDIR)/diskview.obj : $(SOURCE) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\util_io.c -DEP_UTIL_=\ - .\util_io.h - -$(INTDIR)/util_io.obj : $(SOURCE) $(DEP_UTIL_) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Ibm1130/utils/mkboot.c b/Ibm1130/utils/mkboot.c deleted file mode 100644 index 115cdad4..00000000 --- a/Ibm1130/utils/mkboot.c +++ /dev/null @@ -1,705 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -// --------------------------------------------------------------------------------- -// MKBOOT - reads card loader format cards and produces an absolute core image that -// can then be dumped out in 1130 IPL, 1800 IPL or Core Image loader formats. -// -// Usage: mkboot [-v] binfile outfile [1130|1800|core [loaddr [hiaddr [ident]]]]" -// -// Arguments: -// binfile - name of assembler output file (card loader format, absolute output) -// outfile - name of output file to create -// mode - output mode, default is 1130 IPL format -// loaddr - low address to dump. Default is lowest address loaded from binfile -// hiaddr - high address to dump. Defult is highest address loaded from binfile -// ident - ident string to write in last 8 columns. Omit when when writing an -// 1130 IPL card that requires all 80 columns of data. -// -// Examples: -// mkboot somefile.bin somefile.ipl 1130 -// -// loads somefile.bin, writes object in 1130 IPL format to somefile.ipl -// Up to 80 columns will be written depending on what the object actually uses -// -// mkboot somefile.bin somefile.ipl 1130 0 48 SOMEF -// -// loads somefile.bin. Writes 72 columns (hex 48), with ident columns 73-80 = SOMEF001 -// -// mkboot somefile.bin somefile.dat core 0 0 SOMEF001 -// -// loads somefile.bin and writes a core image format deck with ident SOMEF001, SOMEF002, etc -// -// For other examples of usage, see MKDMS.BAT -// -// 1.00 - 2002Apr18 - first release. Tested only under Win32. The core image -// loader format is almost certainly wrong. Cannot handle -// relocatable input decks, but it works well enough to -// load DSYSLDR1 which is what we are after here. -// --------------------------------------------------------------------------------- - -#include -#include -#include -#include - -#ifndef TRUE - #define BOOL int - #define TRUE 1 - #define FALSE 0 -#endif - -#ifndef WIN32 - int strnicmp (char *a, char *b, int n); - int strcmpi (char *a, char *b); -#endif - -#define BETWEEN(v,a,b) (((v) >= (a)) && ((v) <= (b))) -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) -#define MAX(a,b) (((a) >= (b)) ? (a) : (b)) - -#define MAXADDR 4096 - -typedef enum {R_ABSOLUTE = 0, R_RELATIVE = 1, R_LIBF = 2, R_CALL = 3} RELOC; - -typedef enum {B_1130, B_1800, B_CORE} BOOTMODE; - -BOOL verbose = FALSE; -char *infile = NULL, *outfile = NULL; -BOOTMODE mode = B_1130; -int addr_from = 0, addr_to = 79; -int outcols = 0; // columns written in using card output -int maxiplcols = 80; -char cardid[9]; // characters used for IPL card ID -int pta = 0; -int load_low = 0x7FFFFFF; -int load_high = 0; -unsigned short mem[MAXADDR]; // small core! - -// mkboot - load a binary object deck into core and dump requested bytes as a boot card - -void bail (char *msg); -void verify_checksum(unsigned short *card); -char *upcase (char *str); -void unpack (unsigned short *card, unsigned short *buf); -void dump (char *fname); -void loaddata (char *fname); -void write_1130 (void); -void write_1800 (void); -void write_core (void); -void flushcard(void); -int ascii_to_hollerith (int ch); -void corecard_init (void); -void corecard_writecard (char *sbrk_text); -void corecard_writedata (void); -void corecard_flush (void); -void corecard_setorg (int neworg); -void corecard_writew (int word, RELOC relative); -void corecard_endcard (void); - -char *fname = NULL; -FILE *fout; - -int main (int argc, char **argv) -{ - char *arg; - static char usestr[] = "Usage: mkboot [-v] binfile outfile [1130|1800|core [loaddr [hiaddr [ident]]]]"; - int i, ano = 0, ok; - - for (i = 1; i < argc; i++) { - arg = argv[i]; - if (*arg == '-') { - arg++; - while (*arg) { - switch (*arg++) { - case 'v': - verbose = TRUE; - break; - default: - bail(usestr); - } - } - } - else { - switch (ano++) { - case 0: - infile = arg; - break; - - case 1: - outfile = arg; - break; - - case 2: - if (strcmp(arg, "1130") == 0) mode = B_1130; - else if (strcmp(arg, "1800") == 0) mode = B_1800; - else if (strcmpi(arg, "core") == 0) mode = B_CORE; - else bail(usestr); - break; - - case 3: - if (strnicmp(arg, "0x", 2) == 0) ok = sscanf(arg+2, "%x", &addr_from); - else if (arg[0] == '/') ok = sscanf(arg+1, "%x", &addr_from); - else ok = sscanf(arg, "%d", &addr_from); - if (ok != 1) bail(usestr); - break; - - case 4: - if (strnicmp(arg, "0x", 2) == 0) ok = sscanf(arg+2, "%x", &addr_to); - else if (arg[0] == '/') ok = sscanf(arg+1, "%x", &addr_to); - else ok = sscanf(arg, "%d", &addr_to); - if (ok != 1) bail(usestr); - break; - - case 5: - strncpy(cardid, arg, 9); - cardid[8] = '\0'; - upcase(cardid); - break; - - default: - bail(usestr); - } - } - } - - if (*cardid == '\0') - maxiplcols = (mode == B_1130) ? 80 : 72; - else { - while (strlen(cardid) < 8) - strcat(cardid, "0"); - maxiplcols = 72; - } - - loaddata(infile); - - if (mode == B_1800) - write_1800(); - else if (mode == B_CORE) - write_core(); - else - write_1130(); - - return 0; -} - -void write_1130 (void) -{ - int addr; - unsigned short word; - - if ((fout = fopen(outfile, "wb")) == NULL) { - perror(outfile); - exit(1); - } - - for (addr = addr_from; addr <= addr_to; addr++) { - if (outcols >= maxiplcols) - flushcard(); - - word = mem[addr]; - - // if F or L bits are set, or if high 2 bits of displacement are unequal, it's bad - if ((word & 0x0700) || ! (((word & 0x00C0) == 0) || ((word & 0x00C0) == 0x00C0))) - printf("Warning: word %04x @ %04x may not IPL properly\n", word & 0xFFFF, addr); - - word = ((word & 0xF800) >> 4) | (word & 0x7F); // convert to 1130 IPL format - - putc((word & 0x000F) << 4, fout); // write the 12 bits in little-endian binary AABBCC00 as CC00 AABB - putc((word & 0x0FF0) >> 4, fout); - outcols++; - } - flushcard(); - fclose(fout); -} - -void write_1800 (void) -{ - int addr; - unsigned short word; - - if ((fout = fopen(outfile, "wb")) == NULL) { - perror(outfile); - exit(1); - } - - for (addr = addr_from; addr <= addr_to; addr++) { - word = mem[addr]; - - if (outcols >= maxiplcols) - flushcard(); - - putc(0, fout); - putc(word & 0xFF, fout); // write the low 8 bits in little-endian binary - outcols++; - - putc(0, fout); - putc((word >> 8) & 0xFF, fout); // write the high 8 bits in little-endian binary - outcols++; - } - flushcard(); - fclose(fout); -} - -void write_core (void) -{ - int addr; - - if ((fout = fopen(outfile, "wb")) == NULL) { - perror(outfile); - exit(1); - } - - addr_from = load_low; - addr_to = load_high; - - maxiplcols = 72; - corecard_init(); - corecard_setorg(addr_from); - - for (addr = addr_from; addr <= addr_to; addr++) { - corecard_writew(mem[addr], 0); - } - - corecard_flush(); - corecard_endcard(); - fclose(fout); -} - -void flushcard (void) -{ - int i, hol, ndig; - char fmt[20], newdig[20]; - - if (outcols <= 0) - return; // nothing to flush - - while (outcols < maxiplcols) { // pad to required number of columns with blanks (no punches) - putc(0, fout); - putc(0, fout); - outcols++; - } - - if (*cardid) { // add label - for (i = 0; i < 8; i++) { // write label as specified - hol = ascii_to_hollerith(cardid[i] & 0x7F); - putc(hol & 0xFF, fout); - putc((hol >> 8) & 0xFF, fout); - } - - ndig = 0; // count trailing digits in the label - for (i = 8; --i >= 0; ndig++) - if (! isdigit(cardid[i])) - break; - - i++; // index of first digit in trailing sequence - - if (ndig > 0) { // if any, increment them - sprintf(fmt, "%%0%dd", ndig); // make, e.g. %03d - sprintf(newdig, fmt, atoi(cardid+i)+1); - newdig[ndig] = '\0'; // clip if necessary - strcpy(cardid+i, newdig); // replace for next card's sequence number - } - } - - outcols = 0; -} - -void show_data (unsigned short *buf) -{ - int i, n, jrel, rflag, nout, ch, reloc; - - n = buf[2] & 0x00FF; - - printf("%04x: ", buf[0]); - - jrel = 3; - nout = 0; - rflag = buf[jrel++]; - for (i = 0; i < n; i++) { - if (nout >= 8) { - rflag = buf[jrel++]; - putchar('\n'); - printf(" "); - nout = 0; - } - reloc = (rflag >> 14) & 0x03; - ch = (reloc == R_ABSOLUTE) ? ' ' : - (reloc == R_RELATIVE) ? 'R' : - (reloc == R_LIBF) ? 'L' : '@'; - - printf("%04x%c ", buf[9+i], ch); - rflag <<= 2; - nout++; - } - putchar('\n'); -} - -void loadcard (unsigned short *buf) -{ - int addr, n, i; - - addr = buf[0]; - n = buf[2] & 0x00FF; - - for (i = 0; i < n; i++) { - if (addr >= MAXADDR) - bail("Program doesn't fit into 4K"); - mem[addr] = buf[9+i]; - - load_low = MIN(addr, load_low); - load_high = MAX(addr, load_high); - addr++; - } -} - -void loaddata (char *fname) -{ - FILE *fp; - BOOL first = TRUE; - unsigned short card[80], buf[54], cardtype; - - if ((fp = fopen(fname, "rb")) == NULL) { - perror(fname); - exit(1); - } - - if (verbose) - printf("\n%s:\n", fname); - - while (fread(card, sizeof(card[0]), 80, fp) > 0) { - unpack(card, buf); - verify_checksum(card); - - cardtype = (buf[2] >> 8) & 0xFF; - - if (cardtype == 1 && ! first) { // sector break - if (verbose) - printf("*SBRK\n"); - continue; - } - else { - switch (cardtype) { - case 0x01: - if (verbose) - printf("*ABS\n"); - break; - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - bail("Data must be in absolute format"); - break; - - case 0x0F: - pta = buf[3]; // save program transfer address - if (verbose) - printf("*END\n"); - break; - - case 0x0A: - if (verbose) - show_data(buf); - loadcard(buf); - break; - default: - bail("Unexpected card type"); - } - } - first = FALSE; - } - - fclose(fp); -} - -void bail (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - -void unpack (unsigned short *card, unsigned short *buf) -{ - int i, j; - unsigned short wd1, wd2, wd3, wd4; - - for (i = j = 0; i < 54; i += 3, j += 4) { - wd1 = card[j]; - wd2 = card[j+1]; - wd3 = card[j+2]; - wd4 = card[j+3]; - - buf[i ] = (wd1 & 0xFFF0) | ((wd2 >> 12) & 0x000F); - buf[i+1] = ((wd2 << 4) & 0xFF00) | ((wd3 >> 8) & 0x00FF); - buf[i+2] = ((wd3 << 8) & 0xF000) | ((wd4 >> 4) & 0x0FFF); - } -} - -void verify_checksum (unsigned short *card) -{ -// unsigned short sum; - - if (card[1] == 0) // no checksum - return; - -// if (sum != card[1]) -// printf("Checksum %04x doesn't match card %04x\n", sum, card[1]); -} - -typedef struct { - int hollerith; - char ascii; -} CPCODE; - -static CPCODE cardcode_029[] = -{ - 0x0000, ' ', - 0x8000, '&', // + in 026 Fortran - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0820, ':', - 0x0420, '#', // = in 026 Fortran - 0x0220, '@', // ' in 026 Fortran - 0x0120, '\'', - 0x00A0, '=', - 0x0060, '"', - 0x8820, 'c', // cent - 0x8420, '.', - 0x8220, '<', // ) in 026 Fortran - 0x8120, '(', - 0x80A0, '+', - 0x8060, '|', - 0x4820, '!', - 0x4420, '$', - 0x4220, '*', - 0x4120, ')', - 0x40A0, ';', - 0x4060, 'n', // not - 0x2820, 'x', // what? - 0x2420, ',', - 0x2220, '%', // ( in 026 Fortran - 0x2120, '_', - 0x20A0, '>', - 0x2060, '>', -}; - -int ascii_to_hollerith (int ch) -{ - int i; - - for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++) - if (cardcode_029[i].ascii == ch) - return cardcode_029[i].hollerith; - - return 0; -} - -// --------------------------------------------------------------------------------- -// corecard - routines to write IBM 1130 Card object format -// --------------------------------------------------------------------------------- - -unsigned short corecard[54]; // the 54 data words that can fit on a binary format card -int corecard_n = 0; // number of object words stored in corecard (0-45) -int corecard_seq = 1; // card output sequence number -int corecard_org = 0; // origin of current card-full -int corecard_maxaddr = 0; -BOOL corecard_first = TRUE; // TRUE when we're to write the program type card - -// corecard_init - prepare a new object data output card - -void corecard_init (void) -{ - memset(corecard, 0, sizeof(corecard)); // clear card data - corecard_n = 0; // no data - corecard[0] = corecard_org; // store load address - corecard_maxaddr = MAX(corecard_maxaddr, corecard_org-1); // save highest address written-to (this may be a BSS) -} - -// binard_writecard - emit a card. sbrk_text = NULL for normal data cards, points to comment text for sbrk card - -void corecard_writecard (char *sbrk_text) -{ - unsigned short binout[80]; - int i, j; - - for (i = j = 0; i < 54; i += 3, j += 4) { - binout[j ] = ( corecard[i] & 0xFFF0); - binout[j+1] = ((corecard[i] << 12) & 0xF000) | ((corecard[i+1] >> 4) & 0x0FF0); - binout[j+2] = ((corecard[i+1] << 8) & 0xFF00) | ((corecard[i+2] >> 8) & 0x00F0); - binout[j+3] = ((corecard[i+2] << 4) & 0xFFF0); - } - - for (i = 0; i < 72; i++) { - putc(binout[i] & 0xFF, fout); - putc((binout[i] >> 8) & 0xFF, fout); - } - - outcols = 72; // add the ident - flushcard(); -} - -// binard_writedata - emit an object data card - -void corecard_writedata (void) -{ - corecard[1] = 0; // checksum - corecard[2] = 0x0000 | corecard_n; // data card type + word count - corecard_writecard(FALSE); // emit the card -} - -// corecard_flush - flush any pending binary data - -void corecard_flush (void) -{ - if (corecard_n > 0) - corecard_writedata(); - - corecard_init(); -} - -// corecard_setorg - set the origin - -void corecard_setorg (int neworg) -{ - corecard_org = neworg; // set origin for next card - corecard_flush(); // flush any current data & store origin -} - -// corecard_writew - write a word to the current output card. - -void corecard_writew (int word, RELOC relative) -{ - if (corecard_n >= 50) // flush full card buffer (must be even) - corecard_flush(); - - corecard[3+corecard_n++] = word; - corecard_org++; -} - -// corecard_endcard - write end of program card - -void corecard_endcard (void) -{ - corecard_flush(); - - corecard[0] = 0; // effective length: add 1 to max origin, then 1 more to round up - corecard[1] = 0; - corecard[2] = 0x8000; // they look for negative bit but all else must be zero - corecard[52] = 0xabcd; // index register 3 value, this is for fun - corecard[53] = pta; // hmmm - - corecard_writecard(NULL); -} - -/* ------------------------------------------------------------------------ - * upcase - force a string to uppercase (ASCII) - * ------------------------------------------------------------------------ */ - -char *upcase (char *str) -{ - char *s; - - for (s = str; *s; s++) { - if (*s >= 'a' && *s <= 'z') - *s -= 32; - } - - return str; -} - -#ifndef WIN32 - -int strnicmp (char *a, char *b, int n) -{ - int ca, cb; - - for (;;) { - if (--n < 0) // still equal after n characters? quit now - return 0; - - if ((ca = *a) == 0) // get character, stop on null terminator - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) // if different, return comparison - return ca; - - a++, b++; - } -} - -int strcmpi (char *a, char *b) -{ - int ca, cb; - - for (;;) { - if ((ca = *a) == 0) // get character, stop on null terminator - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) // if different, return comparison - return ca; - - a++, b++; - } -} - -#endif diff --git a/Ibm1130/utils/mkboot.mak b/Ibm1130/utils/mkboot.mak deleted file mode 100644 index a7a784d1..00000000 --- a/Ibm1130/utils/mkboot.mak +++ /dev/null @@ -1,161 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "mkboot.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Debug" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/mkboot.exe $(OUTDIR)/mkboot.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"mkboot.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"mkboot.bsc" -BSC32_SBRS= \ - $(INTDIR)/mkboot.sbr - -$(OUTDIR)/mkboot.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:no /PDB:$(OUTDIR)/"mkboot.pdb" /MACHINE:I386\ - /OUT:$(OUTDIR)/"mkboot.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/mkboot.obj - -$(OUTDIR)/mkboot.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/mkboot.exe $(OUTDIR)/mkboot.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"mkboot.pch" /Fo$(INTDIR)/ /Fd$(OUTDIR)/"mkboot.pdb"\ - /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"mkboot.bsc" -BSC32_SBRS= \ - $(INTDIR)/mkboot.sbr - -$(OUTDIR)/mkboot.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:yes /PDB:$(OUTDIR)/"mkboot.pdb" /DEBUG /MACHINE:I386\ - /OUT:$(OUTDIR)/"mkboot.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/mkboot.obj - -$(OUTDIR)/mkboot.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\mkboot.c - -$(INTDIR)/mkboot.obj : $(SOURCE) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Ibm1130/utils/viewdeck.c b/Ibm1130/utils/viewdeck.c deleted file mode 100644 index 1bbcc30d..00000000 --- a/Ibm1130/utils/viewdeck.c +++ /dev/null @@ -1,242 +0,0 @@ -/* Simple program to display a binary card-image file in ASCII. - * We assume the deck was written with one card per 16-bit word, left-justified, - * and written in PC little-endian order - * - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -#include -#include - -#define TRUE 1 -#define FALSE 0 -typedef int BOOL; - -int hollerith_to_ascii (unsigned short h); -void bail (char *msg); -void format_coldstart (unsigned short *buf); - -int main (int argc, char **argv) -{ - FILE *fd; - char *fname = NULL, line[82], *arg; - BOOL coldstart = FALSE; - unsigned short buf[80]; - int i, lastnb; - static char usestr[] = - "Usage: viewdeck [-c] deckfile\n" - "\n" - "-c: convert cold start card to 16-bit format as a C array initializer\n"; - - for (i = 1; i < argc; i++) { // process command line arguments - arg = argv[i]; - - if (*arg == '-') { - arg++; - while (*arg) { - switch (*arg++) { - case 'c': - coldstart = TRUE; - break; - default: - bail(usestr); - } - } - } - else if (fname == NULL) // first non-switch arg is file name - fname = arg; - else - bail(usestr); // there can be only one name - } - - if (fname == NULL) // there must be a name - bail(usestr); - - if ((fd = fopen(fname, "rb")) == NULL) { - perror(fname); - return 1; - } - - while (fread(buf, sizeof(short), 80, fd) == 80) { - if (coldstart) { - format_coldstart(buf); - break; - } - - lastnb = -1; - for (i = 0; i < 80; i++) { - line[i] = hollerith_to_ascii(buf[i]); - if (line[i] > ' ') - lastnb = i; - } - line[++lastnb] = '\n'; - line[++lastnb] = '\0'; - fputs(line, stdout); - } - - if (coldstart) { - if (fread(buf, sizeof(short), 1, fd) == 1) - bail("Coldstart deck has more than one card"); - } - - fclose(fd); - - return 0; -} - -void format_coldstart (unsigned short *buf) -{ - int i, nout = 0; - unsigned short word; - - for (i = 0; i < 80; i++) { - word = buf[i]; // expand 12-bit card data to 16-bit instruction - word = (word & 0xF800) | ((word & 0x0400) ? 0x00C0 : 0x0000) | ((word & 0x03F0) >> 4); - - if (nout >= 8) { - fputs(",\n", stdout); - nout = 0; - } - else if (i > 0) - fputs(", ", stdout); - - printf("0x%04x", word); - nout++; - } - - putchar('\n'); -} - -typedef struct { - unsigned short hollerith; - char ascii; -} CPCODE; - -static CPCODE cardcode_029[] = -{ - 0x0000, ' ', - 0x8000, '&', // + in 026 Fortran - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0820, ':', - 0x0420, '#', // = in 026 Fortran - 0x0220, '@', // ' in 026 Fortran - 0x0120, '\'', - 0x00A0, '=', - 0x0060, '"', - 0x8820, '\xA2', // cent, in MS-DOS encoding - 0x8420, '.', - 0x8220, '<', // ) in 026 Fortran - 0x8120, '(', - 0x80A0, '+', - 0x8060, '|', - 0x4820, '!', - 0x4420, '$', - 0x4220, '*', - 0x4120, ')', - 0x40A0, ';', - 0x4060, '\xAC', // not, in MS-DOS encoding - 0x2420, ',', - 0x2220, '%', // ( in 026 Fortran - 0x2120, '_', - 0x20A0, '>', - 0xB000, 'a', - 0xA800, 'b', - 0xA400, 'c', - 0xA200, 'd', - 0xA100, 'e', - 0xA080, 'f', - 0xA040, 'g', - 0xA020, 'h', - 0xA010, 'i', - 0xD000, 'j', - 0xC800, 'k', - 0xC400, 'l', - 0xC200, 'm', - 0xC100, 'n', - 0xC080, 'o', - 0xC040, 'p', - 0xC020, 'q', - 0xC010, 'r', - 0x6800, 's', - 0x6400, 't', - 0x6200, 'u', - 0x6100, 'v', - 0x6080, 'w', - 0x6040, 'x', - 0x6020, 'y', - 0x6010, 'z', // these odd punch codes are used by APL: - 0x1010, '\001', // no corresponding ASCII using ^A - 0x0810, '\002', // SYN using ^B - 0x0410, '\003', // no corresponding ASCII using ^C - 0x0210, '\004', // PUNCH ON using ^D - 0x0110, '\005', // READER STOP using ^E - 0x0090, '\006', // UPPER CASE using ^F - 0x0050, '\013', // EOT using ^K - 0x0030, '\016', // no corresponding ASCII using ^N - 0x1030, '\017', // no corresponding ASCII using ^O - 0x0830, '\020', // no corresponding ASCII using ^P -}; - -int hollerith_to_ascii (unsigned short h) -{ - int i; - - h &= 0xFFF0; - - for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++) - if (cardcode_029[i].hollerith == h) - return cardcode_029[i].ascii; - - return '?'; -} - -void bail (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - diff --git a/Ibm1130/utils/viewdeck.mak b/Ibm1130/utils/viewdeck.mak deleted file mode 100644 index 37da412c..00000000 --- a/Ibm1130/utils/viewdeck.mak +++ /dev/null @@ -1,161 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "viewdeck.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/viewdeck.exe $(OUTDIR)/viewdeck.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /ML /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /ML /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /ML /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"viewdeck.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"viewdeck.bsc" -BSC32_SBRS= \ - $(INTDIR)/viewdeck.sbr - -$(OUTDIR)/viewdeck.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no\ - /PDB:$(OUTDIR)/"viewdeck.pdb" /MACHINE:I386 /OUT:$(OUTDIR)/"viewdeck.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/viewdeck.obj - -$(OUTDIR)/viewdeck.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/viewdeck.exe $(OUTDIR)/viewdeck.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /ML /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /ML /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /ML /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"viewdeck.pch" /Fo$(INTDIR)/\ - /Fd$(OUTDIR)/"viewdeck.pdb" /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"viewdeck.bsc" -BSC32_SBRS= \ - $(INTDIR)/viewdeck.sbr - -$(OUTDIR)/viewdeck.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes\ - /PDB:$(OUTDIR)/"viewdeck.pdb" /DEBUG /MACHINE:I386\ - /OUT:$(OUTDIR)/"viewdeck.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/viewdeck.obj - -$(OUTDIR)/viewdeck.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\viewdeck.c - -$(INTDIR)/viewdeck.obj : $(SOURCE) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Interdata/id16_cpu.c b/Interdata/id16_cpu.c deleted file mode 100644 index 7f0eae34..00000000 --- a/Interdata/id16_cpu.c +++ /dev/null @@ -1,1720 +0,0 @@ -/* id16_cpu.c: Interdata 16b CPU simulator - - Copyright (c) 2000-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 07-Feb-03 RMS Fixed bug in SETM, SETMR (found by Mark Pizzolato) - - The register state for the Interdata 16b CPU is: - - R[0:F]<0:15> general registers - F[0:7]<0:31> single precision floating point registers - D[0:7]<0:63> double precision floating point registers - PSW<0:31> processor status word, including - STAT<0:11> status flags - CC<0:3> condition codes - PC<0:15> program counter - int_req[8]<0:31> interrupt requests - int_enb[8]<0:31> interrupt enables - - The Interdata 16b systems have four instruction formats: register to - register, short format, register to memory, and register to storage. - The formats are: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op | R1 | R2 | register-register - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op | R1 | N | short format - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op | R1 | RX | register-memory - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op | R1 | RX | register-storage - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - For register-memory and register-storage instructions, an effective - address is calculated as follows: - - effective addr = address + RX (if RX > 0) - - Register-memory instructions can access an address space of 64K bytes. - - The Interdata 16b product line had many different models, with varying - instruction sets: - - instruction group model = 3 4 5 70 80 716 816 816E - base group (61) y y y y y y y y - AL, LM, STM (3) - y y y y y y y - single prec fp (13) - y y y y y y y - model 5 group (36) - - y y y y y y - double prec fp (17) - - - - - - y y - memory extension (4) - - - - - - - y - - This allows the most common CPU options to be covered by just five - model selections: I3, I4, I5/70/80/716, I816, and I816E. Variations - within a model (e.g., 816 with no floating point or just single - precision floating point) are not implemented. - - The I3 kept its general registers in memory; this is not simulated. - Single precision (only) floating point was implemented in microcode, - did not have a guard digit, and kept the floating point registers in - memory. Double precision floating point was implemented in hardware, - provided a guard digit for single precision (but not double), and - kept the floating point registers in hardware. -*/ - -/* This routine is the instruction decode routine for the Interdata CPU. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - breakpoint encountered - wait state and no I/O outstanding - invalid instruction - I/O error in I/O simulator - - 2. Interrupts. Each device has an interrupt armed flag, an interrupt - request flag, and an interrupt enabled flag. To facilitate evaluation, - all interrupt requests are kept in int_req, and all enables in int_enb. - Interrupt armed flags are local to devices. If external interrupts are - enabled in the PSW, and a request is pending, an interrupt occurs. - - 3. Non-existent memory. On the Interdata 16b, reads to non-existent - memory return zero, and writes are ignored. In the simulator, the - largest possible memory is instantiated and initialized to zero. - Thus, only writes need be checked against actual memory size. - - 4. Adding I/O devices. These modules must be modified: - - id_defs.h add device interrupt definitions - id16_sys.c add sim_devices table entry -*/ - -#include "id_defs.h" - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = oPC -#define VAMASK VAMASK16 -#define VA_S1 0x8000 /* S0/S1 flag */ - -#define UNIT_V_MSIZE (UNIT_V_UF + 0) /* dummy mask */ -#define UNIT_V_ID4 (UNIT_V_UF + 1) -#define UNIT_V_716 (UNIT_V_UF + 2) -#define UNIT_V_816 (UNIT_V_UF + 3) -#define UNIT_V_816E (UNIT_V_UF + 4) -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) -#define UNIT_ID4 (1 << UNIT_V_ID4) -#define UNIT_716 (1 << UNIT_V_716) -#define UNIT_816 (1 << UNIT_V_816) -#define UNIT_816E (1 << UNIT_V_816E) -#define UNIT_TYPE (UNIT_ID4 | UNIT_716 | UNIT_816 | UNIT_816E) - -#define SEXT16(x) (((x) & SIGN16)? ((int32) ((x) | 0xFFFF8000)): \ - ((int32) ((x) & 0x7FFF))) -#define CC_GL_16(x) if ((x) & SIGN16) cc = CC_L; \ - else if (x) cc = CC_G; \ - else cc = 0 -#define CC_GL_32(x) if ((x) & SIGN32) cc = CC_L; \ - else if (x) cc = CC_G; \ - else cc = 0 -#define BUILD_PSW(x) (((PSW & ~CC_MASK) | (x)) & psw_mask) -#define CPU_x16 (cpu_unit.flags & (UNIT_716 | UNIT_816 | UNIT_816E)) - -uint32 GREG[16] = { 0 }; /* general registers */ -uint16 *M = NULL; /* memory */ -uint32 *R = &GREG[0]; /* register set ptr */ -uint32 F[8] = { 0 }; /* sp fp registers */ -dpr_t D[8] = { 0 }; /* dp fp registers */ -uint32 PSW = 0; /* processor status word */ -uint32 psw_mask = PSW_x16; /* PSW mask */ -uint32 PC = 0; /* program counter */ -uint32 SR = 0; /* switch register */ -uint32 DR = 0; /* display register */ -uint32 DRX = 0; /* display extension */ -uint32 drmod = 0; /* mode */ -uint32 srpos = 0; /* switch register pos */ -uint32 drpos = 0; /* display register pos */ -uint32 s0_rel = 0; /* S0 relocation */ -uint32 s1_rel = 0; /* S1 relocation */ -uint32 int_req[INTSZ] = { 0 }; /* interrupt requests */ -uint32 int_enb[INTSZ] = { 0 }; /* interrupt enables */ -int32 blkiop = -1; /* block I/O in prog */ -uint32 qevent = 0; /* events */ -uint32 stop_inst = 0; /* stop on ill inst */ -uint32 stop_wait = 0; /* stop on wait */ -uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -uint32 dec_flgs = 0; /* decode flags */ -uint32 fp_in_hwre = 0; /* ucode/hwre fp */ -uint32 pawidth = PAWIDTH16; /* phys addr mask */ -uint32 cpu_log = 0; /* debug logging */ -struct BlockIO blk_io; /* block I/O status */ -uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout) = { NULL }; - -extern int32 sim_interval; -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern UNIT pic_unit, lfc_unit, pas_unit; /* timers */ - -uint32 ReadB (uint32 loc); -uint32 ReadH (uint32 loc); -void WriteB (uint32 loc, uint32 val); -void WriteH (uint32 loc, uint32 val); -uint32 int_auto (uint32 dev, uint32 cc); -uint32 addtoq (uint32 ea, uint32 val, uint32 flg); -uint32 remfmq (uint32 ea, uint32 r1, uint32 flg); -uint32 newPSW (uint32 val); -uint32 swap_psw (uint32 loc, uint32 cc); -uint32 testsysq (uint32); -uint32 display (uint32 dev, uint32 op, uint32 dat); -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc); - -extern t_bool devtab_init (void); -extern void int_eval (void); -extern uint32 int_getdev (void); -extern t_bool sch_blk (uint32 dev); -extern uint32 f_l (uint32 op, uint32 r1, uint32 r2, uint32 ea); -extern uint32 f_c (uint32 op, uint32 r1, uint32 r2, uint32 ea); -extern uint32 f_as (uint32 op, uint32 r1, uint32 r2, uint32 ea); -extern uint32 f_m (uint32 op, uint32 r1, uint32 r2, uint32 ea); -extern uint32 f_d (uint32 op, uint32 r1, uint32 r2, uint32 ea); -extern uint32 f_fix (uint32 op, uint32 r1, uint32 r2); -extern uint32 f_flt (uint32 op, uint32 r1, uint32 r2); - -/* Instruction decoding table - flags are first implementation */ - -const uint16 decrom[256] = { - 0, /* 00 */ - OP_RR, /* BALR */ - OP_RR, /* BTCR */ - OP_RR, /* BFCR */ - OP_RR, /* NHR */ - OP_RR, /* CLHR */ - OP_RR, /* OHR */ - OP_RR, /* XHR */ - OP_RR, /* LHR */ - OP_RR | OP_716, /* CHR */ - OP_RR, /* AHR */ - OP_RR, /* SHR */ - OP_RR, /* MHR */ - OP_RR, /* DHR */ - OP_RR, /* ACHR */ - OP_RR, /* SCHR */ - 0, 0, 0, /* 10:12 */ - OP_RR | OP_816E | OP_PRV, /* SETMR */ - 0, 0, 0, 0, /* 14:1F */ - 0, 0, 0, 0, 0, 0, 0, 0, - OP_NO | OP_716, /* BTBS */ - OP_NO | OP_716, /* BTFS */ - OP_NO | OP_716, /* BFBS */ - OP_NO | OP_716, /* BFFS */ - OP_NO | OP_716, /* LIS */ - OP_NO | OP_716, /* LCS */ - OP_NO | OP_716, /* AIS */ - OP_NO | OP_716, /* SIS */ - OP_NO | OP_ID4, /* LER */ - OP_NO | OP_ID4, /* CER */ - OP_NO | OP_ID4, /* AER */ - OP_NO | OP_ID4, /* SER */ - OP_NO | OP_ID4, /* MER */ - OP_NO | OP_ID4, /* DER */ - OP_NO | OP_816, /* FXR */ - OP_NO | OP_816, /* FLR */ - 0, 0, 0, /* 30:32 */ - OP_RR | OP_816E | OP_PRV, /* LPSR */ - 0, 0, 0, 0, /* 34:37 */ - OP_NO | OP_816 | OP_DPF, /* LDR */ - OP_NO | OP_816 | OP_DPF, /* CDR */ - OP_NO | OP_816 | OP_DPF, /* ADR */ - OP_NO | OP_816 | OP_DPF, /* SDR */ - OP_NO | OP_816 | OP_DPF, /* MDR */ - OP_NO | OP_816 | OP_DPF, /* DDR */ - OP_NO | OP_816 | OP_DPF, /* FXDR */ - OP_NO | OP_816 | OP_DPF, /* FLDR */ - OP_RX, /* STH */ - OP_RX, /* BAL */ - OP_RX, /* BTC */ - OP_RX, /* BFC */ - OP_RXH, /* NH */ - OP_RXH, /* CLH */ - OP_RXH, /* OH */ - OP_RXH, /* XH */ - OP_RXH, /* LH */ - OP_RXH | OP_716, /* CH */ - OP_RXH, /* AH */ - OP_RXH, /* SH */ - OP_RXH, /* MH */ - OP_RXH, /* DH */ - OP_RXH, /* ACH */ - OP_RXH, /* SCH */ - 0, 0, 0, /* 50:52 */ - OP_RXH | OP_816E | OP_PRV, /* SETM */ - 0, 0, 0, 0, /* 54:5F */ - 0, 0, 0, 0, 0, 0, 0, 0, - OP_RX | OP_ID4, /* STE */ - OP_RXH | OP_716, /* AHM */ - 0, 0, /* 62:63 */ - OP_RX | OP_716, /* ATL */ - OP_RX | OP_716, /* ABL */ - OP_RX | OP_716, /* RTL */ - OP_RX | OP_716, /* RBL */ - OP_RX | OP_ID4, /* LE */ - OP_RX | OP_ID4, /* CE */ - OP_RX | OP_ID4, /* AE */ - OP_RX | OP_ID4, /* SE */ - OP_RX | OP_ID4, /* ME */ - OP_RX | OP_ID4, /* DE */ - 0, 0, /* 6E:6F */ - OP_RX | OP_816 | OP_DPF, /* STD */ - OP_RX | OP_816, /* SME */ - OP_RX | OP_816, /* LME */ - OP_RXH | OP_816E | OP_PRV, /* LPS */ - 0, 0, 0, 0, /* 74:7F */ - OP_RX | OP_816 | OP_DPF, /* LD */ - OP_RX | OP_816 | OP_DPF, /* CD */ - OP_RX | OP_816 | OP_DPF, /* AD */ - OP_RX | OP_816 | OP_DPF, /* SD */ - OP_RX | OP_816 | OP_DPF, /* MD */ - OP_RX | OP_816 | OP_DPF, /* DD */ - OP_RX | OP_816 | OP_DPF, /* STMD */ - OP_RX | OP_816 | OP_DPF, /* LMD */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 80:8F */ - 0, 0, 0, 0, 0, 0, 0, 0, - OP_NO | OP_716, /* SRLS */ - OP_NO | OP_716, /* SLLS */ - OP_NO, /* STBR */ - OP_NO, /* LDBR */ - OP_NO | OP_716, /* EXBR */ - OP_NO | OP_716 | OP_PRV, /* EPSR */ - OP_RR | OP_PRV, /* WBR */ - OP_RR | OP_PRV, /* RBR */ - OP_RR | OP_716 | OP_PRV, /* WHR */ - OP_RR | OP_716 | OP_PRV, /* RHR */ - OP_RR | OP_PRV, /* WDR */ - OP_RR | OP_PRV, /* RDR */ - OP_RR | OP_716, /* MHUR */ - OP_RR | OP_PRV, /* SSR */ - OP_RR | OP_PRV, /* OCR */ - OP_RR | OP_PRV, /* AIR */ - 0, 0, 0, 0, 0, 0, 0, 0, /* A0:AF */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* B0:BF */ - 0, 0, 0, 0, 0, 0, 0, 0, - OP_RX, /* BXH */ - OP_RX, /* BXLE */ - OP_RX | OP_PRV, /* LPSW */ - OP_RS | OP_716, /* THI */ - OP_RS, /* NHI */ - OP_RS, /* CLHI */ - OP_RS, /* OHI */ - OP_RS, /* XHI */ - OP_RS, /* LHI */ - OP_RS | OP_716, /* CHI */ - OP_RS, /* AHI */ - OP_RS, /* SHI */ - OP_RS, /* SRHL */ - OP_RS, /* SLHL */ - OP_RS, /* SRHA */ - OP_RS, /* SLHA */ - OP_RX | OP_ID4, /* STM */ - OP_RX | OP_ID4, /* LM */ - OP_RX, /* STB */ - OP_RX, /* LDB */ - OP_RX | OP_716, /* CLB */ - OP_RX | OP_ID4 | OP_PRV, /* AL */ - OP_RXH | OP_PRV, /* WB */ - OP_RXH | OP_PRV, /* RB */ - OP_RX | OP_716 | OP_PRV, /* WH */ - OP_RX | OP_716 | OP_PRV, /* RH */ - OP_RX | OP_PRV, /* WD */ - OP_RX | OP_PRV, /* RD */ - OP_RXH | OP_716, /* MHU */ - OP_RX | OP_PRV, /* SS */ - OP_RX | OP_PRV, /* OC */ - OP_RX | OP_PRV, /* AI */ - 0, /* E0 */ - OP_RX | OP_716, /* SVC */ - OP_RS | OP_716 | OP_PRV, /* SINT */ - 0, 0, 0, 0, 0, 0, 0, /* E3:E9 */ - OP_RS | OP_716, /* RRL */ - OP_RS | OP_716, /* RLL */ - OP_RS | OP_716, /* SRL */ - OP_RS | OP_716, /* SLL */ - OP_RS | OP_716, /* SRA */ - OP_RS | OP_716, /* SLA */ - 0, 0, 0, 0, 0, 0, 0, 0, /* F0:FF */ - 0, 0, 0, 0, 0, 0, 0, 0 }; - -/* 8/16E relocation constants for S0 and S1, indexed by PSW<8:11> */ - -static uint32 s0_rel_const[16] = { /* addr 0-7FFF */ - 0x00000, 0x00000, 0x00000, 0x00000, /* 0 = no reloc */ - 0x00000, 0x00000, 0x00000, 0x08000, /* 8000 = rel to S1 */ - 0x08000, 0x08000, 0x08000, 0x08000, - 0x08000, 0x08000, 0x08000, 0x00000 }; - -static uint32 s1_rel_const[16] = { /* addr 8000-FFFF */ - 0x00000, 0x08000, 0x10000, 0x18000, /* reloc const must */ - 0x20000, 0x28000, 0x30000, 0xFFF8000, /* "sub" base addr */ - 0x00000, 0x08000, 0x10000, 0x18000, - 0x20000, 0x28000, 0x30000, 0x00000 }; - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifiers list -*/ - -DIB cpu_dib = { d_DS, -1, v_DS, NULL, &display, NULL }; - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK + UNIT_716, - MAXMEMSIZE16) }; - -REG cpu_reg[] = { - { HRDATA (PC, PC, 16) }, - { HRDATA (R0, GREG[0], 16) }, - { HRDATA (R1, GREG[1], 16) }, - { HRDATA (R2, GREG[2], 16) }, - { HRDATA (R3, GREG[3], 16) }, - { HRDATA (R4, GREG[4], 16) }, - { HRDATA (R5, GREG[5], 16) }, - { HRDATA (R6, GREG[6], 16) }, - { HRDATA (R7, GREG[7], 16) }, - { HRDATA (R8, GREG[8], 16) }, - { HRDATA (R9, GREG[9], 16) }, - { HRDATA (R10, GREG[10], 16) }, - { HRDATA (R11, GREG[11], 16) }, - { HRDATA (R12, GREG[12], 16) }, - { HRDATA (R13, GREG[13], 16) }, - { HRDATA (R14, GREG[14], 16) }, - { HRDATA (R15, GREG[15], 16) }, - { HRDATA (FR0, F[0], 32) }, - { HRDATA (FR2, F[1], 32) }, - { HRDATA (FR4, F[2], 32) }, - { HRDATA (FR6, F[3], 32) }, - { HRDATA (FR8, F[4], 32) }, - { HRDATA (FR10, F[5], 32) }, - { HRDATA (FR12, F[6], 32) }, - { HRDATA (FR14, F[7], 32) }, - { HRDATA (D0H, D[0].h, 32) }, - { HRDATA (D0L, D[0].l, 32) }, - { HRDATA (D2H, D[1].h, 32) }, - { HRDATA (D2L, D[1].l, 32) }, - { HRDATA (D4H, D[2].h, 32) }, - { HRDATA (D4L, D[2].l, 32) }, - { HRDATA (D6H, D[3].h, 32) }, - { HRDATA (D6L, D[3].l, 32) }, - { HRDATA (D8H, D[4].h, 32) }, - { HRDATA (D8L, D[4].l, 32) }, - { HRDATA (D10H, D[5].h, 32) }, - { HRDATA (D10L, D[5].l, 32) }, - { HRDATA (D12L, D[6].l, 32) }, - { HRDATA (D12H, D[6].h, 32) }, - { HRDATA (D14H, D[7].h, 32) }, - { HRDATA (D14L, D[7].l, 32) }, - { HRDATA (PSW, PSW, 16) }, - { HRDATA (CC, PSW, 4) }, - { HRDATA (SR, SR, 16) }, - { HRDATA (DR, DR, 32) }, - { HRDATA (DRX, DRX, 8) }, - { FLDATA (DRMOD, drmod, 0) }, - { FLDATA (SRPOS, srpos, 0) }, - { HRDATA (DRPOS, drpos, 3) }, - { BRDATA (IRQ, int_req, 16, 32, 8) }, - { BRDATA (IEN, int_enb, 16, 32, 8) }, - { HRDATA (QEVENT, qevent, 4), REG_HRO }, - { FLDATA (STOP_INST, stop_inst, 0) }, - { FLDATA (STOP_WAIT, stop_inst, 0) }, - { BRDATA (PCQ, pcq, 16, 16, PCQ_SIZE), REG_RO+REG_CIRC }, - { HRDATA (PCQP, pcq_p, 6), REG_HRO }, - { HRDATA (WRU, sim_int_char, 8) }, - { HRDATA (DBGLOG, cpu_log, 16), REG_HIDDEN }, - { HRDATA (BLKIOD, blk_io.dfl, 16), REG_HRO }, - { HRDATA (BLKIOC, blk_io.cur, 16), REG_HRO }, - { HRDATA (BLKIOE, blk_io.end, 16), REG_HRO }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, - { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, - { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size }, - { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, - { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size }, - { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size }, - { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size }, - { UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size }, - { UNIT_TYPE, 0, "I3", "I3", &cpu_set_model }, - { UNIT_TYPE, UNIT_ID4, "I4", "I4", &cpu_set_model }, - { UNIT_TYPE, UNIT_716, "7/16", "716", &cpu_set_model }, - { UNIT_TYPE, UNIT_816, "8/16", "816", &cpu_set_model }, - { UNIT_TYPE, UNIT_816E, "8/16E", "816E", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT", - &cpu_set_consint, NULL, NULL }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 16, 18, 1, 16, 8, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL, - &cpu_dib, 0 }; - -t_stat sim_instr (void) -{ -uint32 cc; -t_stat reason; - -/* Restore register state */ - -if (devtab_init ()) return SCPE_STOP; /* check conflicts */ -pawidth = PAWIDTH16; /* default width */ -if (cpu_unit.flags & UNIT_816E) { /* 8/16E? */ - dec_flgs = 0; /* all instr ok */ - fp_in_hwre = 1; /* fp in hwre */ - pawidth = PAWIDTH16E; /* 18b phys addr */ - psw_mask = PSW_816E; } /* mem ext bits */ -else if (cpu_unit.flags & UNIT_816) { /* 8/16? */ - dec_flgs = OP_816E; - fp_in_hwre = 1; - pawidth = PAWIDTH16; - psw_mask = PSW_x16; } -else if (cpu_unit.flags & UNIT_716) { /* I5, 70, 80, 7/16? */ - dec_flgs = OP_816 | OP_816E; - fp_in_hwre = 0; - pawidth = PAWIDTH16; - psw_mask = PSW_x16; } -else if (cpu_unit.flags & UNIT_ID4) { /* I4? */ - dec_flgs = OP_716 | OP_816 | OP_816E; - fp_in_hwre = 0; - pawidth = PAWIDTH16; - psw_mask = PSW_ID4; } -else { dec_flgs = OP_ID4 | OP_716 | OP_816 | OP_816E; /* I3 */ - fp_in_hwre = 0; - pawidth = PAWIDTH16; - psw_mask = PSW_ID4; } -int_eval (); /* eval interrupts */ -cc = newPSW (PSW & psw_mask); /* split PSW, eval wait */ -sim_rtcn_init (lfc_unit.wait, TMR_LFC); /* init clock */ -sim_rtcn_init (pic_unit.wait, TMR_PIC); /* init timer */ -sim_rtcn_init (pas_unit.wait, TMR_PAS); /* init pas */ -reason = 0; - -/* Process events */ - -while (reason == 0) { /* loop until halted */ -uint32 dev, drom, inc, lim, opnd; -uint32 op, r1, r1p1, r2, ea, oPC; -uint32 rslt, t, map; -int32 sr, st; - -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; - int_eval (); } - -if (qevent) { /* any events? */ - if (qevent & EV_BLK) { /* block I/O in prog? */ - dev = blk_io.dfl & DEV_MAX; /* get device */ - cc = dev_tab[dev] (dev, IO_SS, 0) & 0xF; /* sense status */ - if (cc == STA_BSY) { /* just busy? */ - sim_interval = 0; /* force I/O event */ - continue; } - else if (cc == 0) { /* ready? */ - if (blk_io.dfl & BL_RD) { /* read? */ - t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */ - if ((t == 0) && (blk_io.dfl & BL_LZ)) continue; - blk_io.dfl = blk_io.dfl & ~BL_LZ; /* non-zero seen */ - WriteB (blk_io.cur, t); } /* write mem */ - else { /* write */ - t = ReadB (blk_io.cur); /* read mem */ - dev_tab[dev] (dev, IO_WD, t); } /* put byte */ - if (blk_io.cur != blk_io.end) { /* more to do? */ - blk_io.cur = (blk_io.cur + 1) & VAMASK; /* incr addr */ - continue; } } - qevent = qevent & ~EV_BLK; /* clr block I/O flg */ - int_eval (); /* re-eval intr */ - continue; } - - if ((qevent & EV_INT) && (PSW & PSW_EXI)) { /* interrupt? */ - if (PSW & PSW_AIO) { /* auto enabled? */ - dev = int_getdev (); /* get int dev */ - cc = int_auto (dev, cc); /* do auto intr */ - int_eval (); } /* re-eval intr */ - else cc = swap_psw (EXIPSW, cc); /* old type, swap */ - continue; } - - if (PSW & PSW_WAIT) { /* wait state? */ - t = sim_qcount (); /* events in queue */ - if ((t == 0) || ((t == 1) && stop_wait)) /* empty, or kbd only? */ - reason = STOP_WAIT; /* then stop */ - else sim_interval = 0; /* force check */ - continue; } - - qevent = 0; } /* no events */ - -/* Fetch and decode instruction */ - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - -sim_interval = sim_interval - 1; - -t = ReadH (oPC = PC); /* fetch instr */ -op = (t >> 8) & 0xFF; /* isolate op, R1, R2 */ -r1 = (t >> 4) & 0xF; -r2 = t & 0xF; -drom = decrom[op]; -if ((drom == 0) || (drom & dec_flgs)) { /* not in model? */ - if (stop_inst) reason = STOP_RSRV; /* stop or */ - else cc = swap_psw (ILOPSW, cc); /* swap PSW */ - continue; } -if ((drom & OP_PRV) && (PSW & PSW_PRO)) { /* priv & protected? */ - cc = swap_psw (ILOPSW, cc); /* swap PSW */ - continue; } -switch (drom & OP_MASK) { /* decode instruction */ -case OP_NO: /* no operand */ - opnd = r2; /* assume short */ - break; -case OP_RR: /* reg-reg */ - opnd = R[r2]; /* operand is R2 */ - break; -case OP_RS: /* reg-storage */ -case OP_RX: /* reg-mem */ - PC = (PC + 2) & VAMASK; /* increment PC */ - ea = ReadH (PC); /* fetch address */ - if (r2) ea = (ea + R[r2]) & VAMASK; /* index calculation */ - opnd = ea; /* operand is ea */ - break; -case OP_RXH: /* reg-mem read */ - PC = (PC + 2) & VAMASK; /* increment PC */ - ea = ReadH (PC); /* fetch address */ - if (r2) ea = (ea + R[r2]) & VAMASK; /* index calculation */ - opnd = ReadH (ea); /* fetch operand */ - break; } -PC = (PC + 2) & VAMASK; /* increment PC */ -switch (op) { /* case on opcode */ - -/* Load/store instructions */ - -case 0x08: /* LHR - RR */ -case 0x24: /* LIS - NO */ -case 0x48: /* LH - RXH */ -case 0xC8: /* LHI - RS */ - R[r1] = opnd; /* load operand */ - CC_GL_16 (R[r1]); /* set G,L */ - break; - -case 0x25: /* LCS - NO */ - R[r1] = (~opnd + 1) & DMASK16; /* load complement */ - CC_GL_16 (R[r1]); /* set G,L */ - break; - -case 0x40: /* STH - RX */ - WriteH (ea, R[r1]); /* store register */ - break; - -case 0xD1: /* LM - RX */ - for ( ; r1 <= 0xF; r1++) { /* loop thru reg */ - R[r1] = ReadH (ea); /* load register */ - ea = (ea + 2) & VAMASK; } /* incr mem addr */ - break; - -case 0xD0: /* STM - RX */ - for ( ; r1 <= 0xF; r1++) { /* loop thru reg */ - WriteH (ea, R[r1]); /* store register */ - ea = (ea + 2) & VAMASK; } /* incr mem addr */ - break; - -case 0x93: /* LDBR - NO */ - R[r1] = R[r2] & DMASK8; /* load byte */ - break; -case 0xD3: /* LDB - RX */ - R[r1] = ReadB (ea); /* load byte */ - break; - -case 0x92: /* STBR - NO */ - R[r2] = (R[r2] & ~DMASK8) | (R[r1] & DMASK8); /* store byte */ - break; -case 0xD2: /* STB - RX */ - WriteB (ea, R[r1] & DMASK8); /* store byte */ - break; - -case 0x94: /* EXBR - NO */ - R[r1] = (R[r2] >> 8) | ((R[r2] & DMASK8) << 8); - break; - -/* Control instructions */ - -case 0x01: /* BALR - RR */ -case 0x41: /* BAL - RX */ - PCQ_ENTRY; /* save old PC */ - R[r1] = PC; /* save cur PC */ - PC = opnd; /* branch */ - break; - -case 0x02: /* BTCR - RR */ -case 0x42: /* BTC - RX */ - if (cc & r1) { /* test CC's */ - PCQ_ENTRY; /* branch if true */ - PC = opnd; } - break; - -case 0x20: /* BTBS - NO */ - if (cc & r1) { /* test CC's */ - PCQ_ENTRY; /* branch if true */ - PC = (oPC - r2 - r2) & VAMASK; } - break; - -case 0x21: /* BTFS - NO */ - if (cc & r1) { /* test CC's */ - PCQ_ENTRY; /* branch if true */ - PC = (oPC + r2 + r2) & VAMASK; } - break; - -case 0x03: /* BFCR - RR */ -case 0x43: /* BFC - RX */ - if ((cc & r1) == 0) { /* test CC's */ - PCQ_ENTRY; /* branch if false */ - PC = opnd; } - break; - -case 0x22: /* BFBS - NO */ - if ((cc & r1) == 0) { /* test CC's */ - PCQ_ENTRY; /* branch if false */ - PC = (oPC - r2 - r2) & VAMASK; } - break; - -case 0x23: /* BFFS - NO */ - if ((cc & r1) == 0) { /* test CC's */ - PCQ_ENTRY; /* branch if false */ - PC = (oPC + r2 + r2) & VAMASK; } - break; - -case 0xC0: /* BXH - RX */ - inc = R[(r1 + 1) & 0xF]; /* inc = R1 + 1 */ - lim = R[(r1 + 2) & 0xF]; /* lim = R1 + 2 */ - R[r1] = (R[r1] + inc) & DMASK16; /* R1 = R1 + inc */ - if (R[r1] > lim) { /* if R1 > lim */ - PCQ_ENTRY; /* branch */ - PC = opnd; } - break; - -case 0xC1: /* BXLE - RX */ - inc = R[(r1 + 1) & 0xF]; /* inc = R1 + 1 */ - lim = R[(r1 + 2) & 0xF]; /* lim = R1 + 2 */ - R[r1] = (R[r1] + inc) & DMASK16; /* R1 = R1 + inc */ - if (R[r1] <= lim) { /* if R1 <= lim */ - PCQ_ENTRY; /* branch */ - PC = opnd; } - break; - -/* Logical instructions */ - -case 0x04: /* NHR - RR */ -case 0x44: /* NH - RXH */ -case 0xC4: /* NHI - RS */ - R[r1] = R[r1] & opnd; /* result */ - CC_GL_16 (R[r1]); /* set G,L */ - break; - -case 0x06: /* OHR - RR */ -case 0x46: /* OH - RXH */ -case 0xC6: /* OHI - RS */ - R[r1] = R[r1] | opnd; /* result */ - CC_GL_16 (R[r1]); /* set G,L */ - break; - -case 0x07: /* XHR - RR */ -case 0x47: /* XH - RXH */ -case 0xC7: /* XHI - RS */ - R[r1] = R[r1] ^ opnd; /* result */ - CC_GL_16 (R[r1]); /* set G,L */ - break; - -case 0xC3: /* THI - RS */ - rslt = R[r1] & opnd; /* result */ - CC_GL_16 (rslt); /* set G, L */ - break; - -case 0x05: /* CLHR - RR */ -case 0x45: /* CLH - RXH */ -case 0xC5: /* CLHI - RS */ - rslt = (R[r1] - opnd) & DMASK16; /* result */ - CC_GL_16 (rslt); /* set G,L */ - if (R[r1] < opnd) cc = cc | CC_C; /* set C if borrow */ - if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN16) cc = cc | CC_V; - break; - -case 0xD4: /* CLB - RX */ - opnd = ReadB (ea); /* get operand */ - t = R[r1] & DMASK8; - rslt = (t - opnd) & DMASK16; /* result */ - CC_GL_16 (rslt); /* set G,L */ - if (t < opnd) cc = cc | CC_C; /* set C if borrow */ - break; - -/* Shift instructions */ - -case 0xCC: /* SRHL - RS */ - opnd = opnd & 0xF; /* shift count */ -case 0x90: /* SRLS - NO */ - rslt = R[r1] >> opnd; /* result */ - CC_GL_16 (rslt); /* set G,L */ - if (opnd && ((R[r1] >> (opnd - 1)) & 1)) cc = cc | CC_C; - R[r1] = rslt; /* store result */ - break; - -case 0xCD: /* SLHL - RS */ - opnd = opnd & 0xF; /* shift count */ -case 0x91: /* SLLS - NO */ - rslt = R[r1] << opnd; /* raw result */ - R[r1] = rslt & DMASK16; /* masked result */ - CC_GL_16 (R[r1]); /* set G,L */ - if (opnd && (rslt & 0x10000)) cc = cc | CC_C; /* set C if shft out */ - break; - -case 0xCE: /* SRHA - RS */ - opnd = opnd & 0xF; /* shift count */ - rslt = (SEXT16 (R[r1]) >> opnd) & DMASK16; /* result */ - CC_GL_16 (rslt); /* set G,L */ - if (opnd && ((R[r1] >> (opnd - 1)) & 1)) cc = cc | CC_C; - R[r1] = rslt; /* store result */ - break; - -case 0xCF: /* SLHA - RS */ - opnd = opnd & 0xF; /* shift count */ - rslt = R[r1] << opnd; /* raw result */ - R[r1] = (R[r1] & SIGN16) | (rslt & MMASK16); /* arith result */ - CC_GL_16 (R[r1]); /* set G,L */ - if (opnd && (rslt & SIGN16)) cc = cc | CC_C; /* set C if shft out */ - break; - -case 0xEA: /* RRL - RS */ - r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ - opnd = opnd & 0x1F; /* shift count */ - t = (R[r1] << 16) | R[r1p1]; /* form 32b op */ - if (opnd) rslt = (t >> opnd) | (t << (32 - opnd)); /* result */ - else rslt = t; /* no shift */ - CC_GL_32 (rslt); /* set G,L 32b */ - R[r1] = (rslt >> 16) & DMASK16; /* hi result */ - R[r1p1] = rslt & DMASK16; /* lo result */ - break; - -case 0xEB: /* RLL - RS */ - r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ - opnd = opnd & 0x1F; /* shift count */ - t = (R[r1] << 16) | R[r1p1]; /* form 32b op */ - if (opnd) rslt = (t << opnd) | (t >> (32 - opnd)); /* result */ - else rslt = t; /* no shift */ - CC_GL_32 (rslt); /* set G,L 32b */ - R[r1] = (rslt >> 16) & DMASK16; /* hi result */ - R[r1p1] = rslt & DMASK16; /* lo result */ - break; - -case 0xEC: /* SRL - RS */ - r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ - opnd = opnd & 0x1F; /* shift count */ - t = (R[r1] << 16) | R[r1p1]; /* form 32b op */ - rslt = t >> opnd; /* result */ - CC_GL_32 (rslt); /* set G,L 32b */ - if (opnd && ((t >> (opnd - 1)) & 1)) cc = cc | CC_C; - R[r1] = (rslt >> 16) & DMASK16; /* hi result */ - R[r1p1] = rslt & DMASK16; /* lo result */ - break; - -case 0xED: /* SLL - RS */ - r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ - opnd = opnd & 0x1F; /* shift count */ - t = (R[r1] << 16) | R[r1p1]; /* form 32b op */ - rslt = t << opnd; /* result */ - CC_GL_32 (rslt); /* set G,L 32b */ - if (opnd && ((t << (opnd - 1)) & SIGN32)) cc = cc | CC_C; - R[r1] = (rslt >> 16) & DMASK16; /* hi result */ - R[r1p1] = rslt & DMASK16; /* lo result */ - break; - -case 0xEE: /* SRA - RS */ - r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ - opnd = opnd & 0x1F; /* shift count */ - t = (R[r1] << 16) | R[r1p1]; /* form 32b op */ - rslt = ((int32) t) >> opnd; /* signed result */ - CC_GL_32 (rslt); /* set G,L 32b */ - if (opnd && ((t >> (opnd - 1)) & 1)) cc = cc | CC_C; - R[r1] = (rslt >> 16) & DMASK16; /* hi result */ - R[r1p1] = rslt & DMASK16; /* lo result */ - break; - -case 0xEF: /* SLA - RS */ - r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ - opnd = opnd & 0x1F; /* shift count */ - t = (R[r1] << 16) | R[r1p1]; /* form 32b op */ - rslt = (t & SIGN32) | ((t << opnd) & MMASK32); /* signed result */ - CC_GL_32 (rslt); /* set G,L 32b */ - if (opnd && ((t << opnd) & SIGN32)) cc = cc | CC_C; - R[r1] = (rslt >> 16) & DMASK16; /* hi result */ - R[r1p1] = rslt & DMASK16; /* lo result */ - break; - -/* Arithmetic instructions */ - -case 0x0A: /* AHR - RR */ -case 0x26: /* AIS - NO */ -case 0x4A: /* AH - RXH */ -case 0xCA: /* AHI - RS */ - rslt = (R[r1] + opnd) & DMASK16; /* result */ - CC_GL_16 (rslt); /* set G,L */ - if (rslt < opnd) cc = cc | CC_C; /* set C if carry */ - if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN16) cc = cc | CC_V; - R[r1] = rslt; - break; - -case 0x61: /* AHM - RXH */ - rslt = (R[r1] + opnd) & DMASK16; /* result */ - CC_GL_16 (rslt); /* set G,L */ - if (rslt < opnd) cc = cc | CC_C; /* set C if carry */ - if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN16) cc = cc | CC_V; - WriteH (ea, rslt); /* store in memory */ - break; - -case 0x0B: /* SHR - RR */ -case 0x27: /* SIS - NO */ -case 0x4B: /* SH - RXH */ -case 0xCB: /* SHI - RS */ - rslt = (R[r1] - opnd) & DMASK16; /* result */ - CC_GL_16 (rslt); /* set G,L */ - if (R[r1] < opnd) cc = cc | CC_C; /* set C if borrow */ - if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN16) cc = cc | CC_V; - R[r1] = rslt; - break; - -case 0x09: /* CHR - RR */ -case 0x49: /* CH - RXH */ -case 0xC9: /* CHI - RS */ - sr = SEXT16 (R[r1]); /* sign ext */ - st = SEXT16 (opnd); - if (sr < st) cc = CC_C | CC_L; /* < sets C, L */ - else if (sr > st) cc = CC_G; /* > sets G */ - else cc = 0; - if (((R[r1] ^ opnd) & (~opnd ^ (sr - st))) & SIGN16) - cc = cc | CC_V; - break; - -case 0x0C: /* MHR - RR */ -case 0x4C: /* MH - RXH */ - r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ - rslt = SEXT16 (R[r1p1]) * SEXT16 (opnd); /* multiply */ - R[r1] = (rslt >> 16) & DMASK16; /* hi result */ - R[r1p1] = rslt & DMASK16; /* lo result */ - break; - -case 0x9C: /* MHUR - RR */ -case 0xDC: /* MHU - RXH */ - r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ - rslt = R[r1p1] * opnd; /* multiply, unsigned */ - R[r1] = (rslt >> 16) & DMASK16; /* hi result */ - R[r1p1] = rslt & DMASK16; /* lo result */ - break; - -case 0x0D: /* DHR - RR */ -case 0x4D: /* DH - RXH */ - r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ - sr = (R[r1] << 16) | R[r1p1]; /* signed 32b divd */ - if (opnd) { /* if divisor != 0 */ - st = sr / SEXT16 (opnd); /* signed quotient */ - sr = sr % SEXT16 (opnd); } /* remainder */ - if (opnd && (st < 0x8000) && (st >= -0x8000)) { /* if quo fits */ - R[r1] = sr & DMASK16; /* store remainder */ - R[r1p1] = st & DMASK16; } /* store quotient */ - else if (PSW & PSW_AFI) /* div fault enabled? */ - cc = swap_psw (AFIPSW, cc); /* swap PSW */ - break; - -case 0x0E: /* ACHR - RR */ -case 0x4E: /* ACH - RXH */ - t = R[r1] + opnd + ((cc & CC_C) != 0); /* raw result */ - rslt = t & DMASK16; /* masked result */ - CC_GL_16 (rslt); /* set G,L */ - if (t > DMASK16) cc = cc | CC_C; /* set C if carry */ - if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN16) cc = cc | CC_V; - R[r1] = rslt; /* store result */ - break; - -case 0x0F: /* SCHR - RR */ -case 0x4F: /* SCH - RXH */ - t = R[r1] - opnd - ((cc & CC_C) != 0); /* raw result */ - rslt = t & DMASK16; /* masked result */ - CC_GL_16 (rslt); /* set G,L */ - if (t > DMASK16) cc = cc | CC_C; /* set C if borrow */ - if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN16) cc = cc | CC_V; - R[r1] = rslt; /* store result */ - break; - -/* Floating point instructions */ - -case 0x28: /* LER - NO */ -case 0x38: /* LDR - NO */ -case 0x68: /* LE - RX */ -case 0x78: /* LD - RX */ - cc = f_l (op, r1, r2, ea); /* load */ - if ((cc & CC_V) && (PSW & PSW_FPF) && CPU_x16) /* V set, x/16? */ - cc = swap_psw (FPFPSW, cc); - break; - -case 0x29: /* CER - NO */ -case 0x39: /* CDR - NO */ -case 0x69: /* CE - RX */ -case 0x79: /* CD - RX */ - cc = f_c (op, r1, r2, ea); /* compare */ - break; - -case 0x2A: /* AER - NO */ -case 0x2B: /* SER - NO */ -case 0x3A: /* ADR - NO */ -case 0x3B: /* SDR - NO */ -case 0x6A: /* AE - RX */ -case 0x6B: /* SE - RX */ -case 0x7A: /* AD - RX */ -case 0x7B: /* SD - RX */ - cc = f_as (op, r1, r2, ea); /* add/sub */ - if ((cc & CC_V) && (PSW & PSW_FPF) && CPU_x16) /* V set, x/16? */ - cc = swap_psw (FPFPSW, cc); - break; - -case 0x2C: /* MER - NO */ -case 0x3C: /* MDR - NO */ -case 0x6C: /* ME - RX */ -case 0x7C: /* MD - RX */ - cc = f_m (op, r1, r2, ea); /* multiply */ - if ((cc & CC_V) && (PSW & PSW_FPF) && CPU_x16) /* V set, x/16? */ - cc = swap_psw (FPFPSW, cc); - break; - -case 0x2D: /* DER - NO */ -case 0x3D: /* DDR - NO */ -case 0x6D: /* DE - RX */ -case 0x7D: /* DD - RX */ - cc = f_d (op, r1, r2, ea); /* perform divide */ - if ((cc & CC_V) && ((cc & CC_C) || /* V set, x/16 or */ - ((PSW & PSW_FPF) && CPU_x16))) /* V & C set? */ - cc = swap_psw (FPFPSW, cc); - break; - -case 0x2E: /* FXR - NO */ -case 0x3E: /* FXDR - NO */ - cc = f_fix (op, r1, r2); /* cvt to integer */ - break; - -case 0x2F: /* FLR - NO */ -case 0x3F: /* FLDR - NO */ - cc = f_flt (op, r1, r2); /* cvt to floating */ - break; - -case 0x60: /* STE - RX */ - t = ReadFReg (r1); /* get fp reg */ - WriteF (ea, t, P); /* write */ - break; - -case 0x70: /* STD - RX */ - WriteF (ea, D[r1 >> 1].h, P); /* write hi */ - WriteF ((ea + 4) & VAMASK, D[r1 >> 1].l, P); /* write lo */ - break; - -case 0x71: /* STME - RX */ - for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */ - t = ReadFReg (r1); /* get fp reg */ - WriteF (ea, t, P); /* write */ - ea = (ea + 4) & VAMASK; } /* incr mem addr */ - break; - -case 0x72: /* LME - RX */ - for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */ - t = ReadF (ea, P); /* get value */ - WriteFReg (r1, t); /* write reg */ - ea = (ea + 4) & VAMASK; } /* incr mem addr */ - break; - -case 0x7E: /* STMD - RX */ - for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */ - WriteF (ea, D[r1 >> 1].h, P); /* write register */ - WriteF ((ea + 4) & VAMASK, D[r1 >> 1].l, P); - ea = (ea + 8) & VAMASK; } /* incr mem addr */ - break; - -case 0x7F: /* LMD - RX */ - for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */ - D[r1 >> 1].h = ReadF (ea, P); /* load register */ - D[r1 >> 1].l = ReadF ((ea + 4) & VAMASK, P); - ea = (ea + 8) & VAMASK; } /* incr mem addr */ - break; - -/* Miscellaneous */ - -case 0xE1: /* SVC - RX */ - PCQ_ENTRY; /* save PC */ - WriteH (SVCAP, ea); /* save opnd */ - WriteH (SVOPS, BUILD_PSW (cc)); /* save PS */ - WriteH (SVOPC, PC); /* save PC */ - PC = ReadH (SVNPC + r1 + r1); /* new PC */ - cc = newPSW (ReadH (SVNPS)); /* new PS */ - break; - -case 0xE2: /* SINT - RS */ - dev = opnd & DEV_MAX; /* get dev */ - cc = int_auto (dev, cc); /* auto intr */ - int_eval (); /* re-eval intr */ - break; - -case 0xC2: /* LPSW - RX */ - PCQ_ENTRY; /* effective branch */ - PC = ReadH ((ea + 2) & VAMASK); /* read PC */ - cc = newPSW (ReadH (ea)); /* read PSW */ - if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */ - break; - -case 0x95: /* EPSR - RR */ - R[r1] = BUILD_PSW (cc); /* save PSW */ -case 0x33: /* LPSR - NO */ - cc = newPSW (R[r2]); /* load new PSW */ - if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */ - break; - -case 0x73: /* LPS - RXH */ - cc = newPSW (opnd); /* load new PSW */ - if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */ - break; - -case 0x64: /* ATL - RX */ -case 0x65: /* ABL - RX */ - cc = addtoq (ea, R[r1], op & 1); /* add to q */ - break; - -case 0x66: /* RTL - RX */ -case 0x67: /* RBL - RX */ - cc = remfmq (ea, r1, op & 1); /* remove from q */ - break; - -case 0x13: /* SETMR - RR */ -case 0x53: /* SETM - RXH */ - t = BUILD_PSW (cc); /* old PSW */ - map = PSW_GETMAP (opnd); /* get new map */ - switch (map) { /* case on map */ - case 0x7: - map = 0; /* use 1:1 map */ - R[r1] = R[r1] ^ SIGN16; /* flip sign */ - break; - case 0x8: case 0x9: case 0xA: case 0xB: - case 0xC: case 0xD: case 0xE: - if (R[r1] & SIGN16) map = map & ~0x8; /* S1? clr map<0> */ - else { - map = 0; /* else 1:1 map */ - R[r1] = R[r1] | SIGN16; } /* set sign */ - break; - default: - break; } - t = (t & ~PSW_MAP) | (map << PSW_V_MAP); /* insert map */ - newPSW (t); /* load new PSW */ - CC_GL_16 (R[r1]); /* set G,L */ - break; - -/* I/O instructions */ - -case 0xDE: /* OC - RX */ - opnd = ReadB (ea); /* fetch operand */ -case 0x9E: /* OCR - RR */ - dev = R[r1] & DEV_MAX; - if (DEV_ACC (dev)) { - dev_tab[dev] (dev, IO_ADR, 0); /* select */ - dev_tab[dev] (dev, IO_OC, opnd & DMASK8); /* send command */ - int_eval (); /* re-eval intr */ - cc = 0; } - else cc = CC_V; - break; - -case 0xDA: /* WD - RX */ - opnd = ReadB (ea); /* fetch operand */ -case 0x9A: /* WDR - RR */ - dev = R[r1] & DEV_MAX; - if (DEV_ACC (dev)) { - dev_tab[dev] (dev, IO_ADR, 0); /* select */ - dev_tab[dev] (dev, IO_WD, opnd & DMASK8); /* send data */ - int_eval (); /* re-eval intr */ - cc = 0; } - else cc = CC_V; - break; - -case 0xD8: /* WH - RX */ - opnd = ReadH (ea); /* fetch operand */ -case 0x98: /* WHR - RR */ - dev = R[r1] & DEV_MAX; - if (DEV_ACC (dev)) { - if (dev_tab[dev] (dev, IO_ADR, 0)) /* select; hw ok? */ - dev_tab[dev] (dev, IO_WH, opnd); /* send data */ - else { /* byte only */ - dev_tab[dev] (dev, IO_WD, opnd >> 8); /* send hi byte */ - dev_tab[dev] (dev, IO_WD, opnd & DMASK8); } /* send lo byte */ - int_eval (); /* re-eval intr */ - cc = 0; } - else cc = CC_V; - break; - -case 0x9B: /* RDR - RR */ -case 0xDB: /* RD - RX */ - dev = R[r1] & DEV_MAX; - if (DEV_ACC (dev)) { /* dev exist? */ - dev_tab[dev] (dev, IO_ADR, 0); /* select */ - t = dev_tab[dev] (dev, IO_RD, 0); /* get data */ - cc = 0; } - else { /* no */ - t = 0; /* read zero */ - cc = CC_V; } /* set V */ - if (OP_TYPE (op) != OP_RR) WriteB (ea, t); /* RX or RR? */ - else R[r2] = t & DMASK8; - int_eval (); /* re-eval intr */ - break; - -case 0x99: /* RHR - RR */ -case 0xD9: /* RH - RX */ - dev = R[r1] & DEV_MAX; - if (DEV_ACC (dev)) { /* dev exist? */ - if (dev_tab[dev] (dev, IO_ADR, 0)) /* select, hw ok? */ - t = dev_tab[dev] (dev, IO_RH, 0); /* get data */ - else { /* byte only */ - rslt = dev_tab[dev] (dev, IO_RD, 0); /* get byte */ - t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */ - t = (rslt << 8) | t; } /* merge */ - cc = 0; } - else { /* no */ - t = 0; /* read zero */ - cc = CC_V; } /* set V */ - if (OP_TYPE (op) != OP_RR) WriteH (ea, t); /* RX or RR? */ - else R[r2] = t; - int_eval (); /* re-eval intr */ - break; - -case 0x9F: /* AIR - RR */ -case 0xDF: /* AI - RX */ - R[r1] = int_getdev (); /* get int dev */ - /* fall through */ -case 0x9D: /* SSR - RR */ -case 0xDD: /* SS - RX */ - dev = R[r1] & DEV_MAX; - if (DEV_ACC (dev)) { /* dev exist? */ - dev_tab[dev] (dev, IO_ADR, 0); /* select */ - t = dev_tab[dev] (dev, IO_SS, 0); } /* get status */ - else t = STA_EX; /* no */ - if (OP_TYPE (op) != OP_RR) WriteB (ea, t); /* RR or RX? */ - else R[r2] = t & DMASK8; - cc = t & 0xF; - int_eval (); /* re-eval intr */ - break; - -/* Block I/O instructions - - On a real Interdata system, the block I/O instructions can't be - interrupted or stopped. To model this behavior, while allowing - the instructions to go back through fetch for I/O processing and - WRU testing, the simulator implements a 'block I/O in progress' - flag and status block. If a block I/O is in progress, normal - interrupts and fetches are suppressed until the block I/O is done. -*/ - -case 0x96: /* WBR - RR */ -case 0xD6: /* WB - RXH */ - dev = R[r1] & DEV_MAX; - if (DEV_ACC (dev)) { /* dev exist? */ - if (OP_TYPE (op) != OP_RR) - lim = ReadH ((ea + 2) & VAMASK); - else lim = R[(r2 + 1) & 0xF]; - if (opnd > lim) cc = 0; /* start > end? */ - else { /* no, start I/O */ - dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ - blk_io.dfl = dev; /* set status block */ - blk_io.cur = opnd; - blk_io.end = lim; - qevent = qevent | EV_BLK; } } /* I/O in prog */ - else cc = CC_V; /* nx dev */ - break; - -case 0x97: /* RBR - RR */ -case 0xD7: /* RB - RXH */ - dev = R[r1] & DEV_MAX; - if (DEV_ACC (dev)) { /* dev exist? */ - if (OP_TYPE (op) != OP_RR) - lim = ReadH ((ea + 2) & VAMASK); - else lim = R[(r2 + 1) & 0xF]; - if (opnd > lim) cc = 0; /* start > end? */ - else { /* no, start I/O */ - dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ - blk_io.dfl = dev | BL_RD; /* set status block */ - blk_io.cur = opnd; - blk_io.end = lim; - qevent = qevent | EV_BLK; } } /* I/O in prog */ - else cc = CC_V; /* nx dev */ - break; - -case 0xD5: /* AL - RX */ - dev = ReadB (AL_DEV); /* get device */ - t = ReadB (AL_IOC); /* get command */ - if (DEV_ACC (dev)) { /* dev exist? */ - if (AL_BUF > ea) cc = 0; /* start > end? */ - else { /* no, start I/O */ - dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ - dev_tab[dev] (dev, IO_OC, t); /* start dev */ - blk_io.dfl = dev | BL_RD | BL_LZ; /* set status block */ - blk_io.cur = AL_BUF; - blk_io.end = ea; - qevent = qevent | EV_BLK; } } /* I/O in prog */ - else cc = CC_V; /* nx dev */ - break; } /* end switch */ - } /* end while */ - -/* Simulation halted */ - -PSW = BUILD_PSW (cc); -PC = PC & VAMASK; -pcq_r->qptr = pcq_p; /* update pc q ptr */ -return reason; -} - -/* Load new PSW and memory map */ - -uint32 newPSW (uint32 val) -{ -PSW = val & psw_mask; /* store PSW */ -int_eval (); /* update intreq */ -if (PSW & PSW_WAIT) qevent = qevent | EV_WAIT; /* wait state? */ -else qevent = qevent & ~EV_WAIT; -if (cpu_unit.flags & UNIT_816E) { /* mapping enabled? */ - uint32 map = PSW_GETMAP (PSW); /* get new map */ - s0_rel = s0_rel_const[map]; /* set relocation */ - s1_rel = s1_rel_const[map]; } /* constants */ -else s0_rel = s1_rel = 0; /* no relocation */ -if (PSW & PSW_AIO) SET_ENB (v_DS); /* PSW<4> controls */ -else CLR_ENB (v_DS); /* DS interrupts */ -return PSW & CC_MASK; -} - -/* Swap PSW */ - -uint32 swap_psw (uint32 loc, uint32 cc) -{ -WriteH (loc, BUILD_PSW (cc)); /* write PSW, PC */ -WriteH (loc + 2, PC); -cc = newPSW (ReadH (loc + 4)); /* read PSW, PC */ -PC = ReadH (loc + 6); -if (PSW & PSW_SQI) cc = testsysq (cc); /* sys q int enb? */ -return cc; /* return CC */ -} - -/* Test for queue interrupts */ - -uint32 testsysq (uint32 cc) -{ -int32 qb = ReadH (SQP); /* get sys q addr */ -int32 usd = ReadB (qb + Q16_USD); /* get use count */ - -if (usd) { /* any entries? */ - WriteH (SQIPSW, BUILD_PSW (cc)); /* swap PSW */ - WriteH (SQIPSW + 2, PC); - cc = newPSW (ReadH (SQIPSW + 4)); - PC = ReadH (SQIPSW + 6); } -return cc; -} - -/* Add to head of queue */ - -uint32 addtoq (uint32 ea, uint32 val, uint32 flg) -{ -uint32 slt, usd, wra, t; - -t = ReadH (ea); /* slots/used */ -slt = (t >> 8) & DMASK8; /* # slots */ -usd = t & DMASK8; /* # used */ -if (usd >= slt) return CC_V; /* list full? */ -usd = usd + 1; /* inc # used */ -WriteB (ea + Q16_USD, usd); /* rewrite */ -if (flg) { /* ABL? */ - wra = ReadB ((ea + Q16_BOT) & VAMASK); /* get bottom */ - t = wra + 1; /* adv bottom */ - if (t >= slt) t = 0; /* wrap if necc */ - WriteB ((ea + Q16_BOT) & VAMASK, t); } /* rewrite bottom */ -else { /* ATL */ - wra = ReadB ((ea + Q16_TOP) & VAMASK); /* get top */ - if (wra == 0) wra = (slt - 1) & DMASK8; /* wrap if necc */ - else wra = wra - 1; /* dec top */ - WriteB ((ea + Q16_TOP) & VAMASK, wra); } /* rewrite top */ -WriteH ((ea + Q16_BASE + (wra * Q16_SLNT)) & VAMASK, val); /* write slot */ -return 0; -} - -uint32 remfmq (uint32 ea, uint32 r1, uint32 flg) -{ -uint32 slt, usd, rda, t; - -t = ReadH (ea); /* get slots/used */ -slt = (t >> 8) & DMASK8; /* # slots */ -usd = t & DMASK8; /* # used */ -if (usd == 0) return CC_V; /* empty? */ -usd = usd - 1; /* dec used */ -WriteB (ea + Q16_USD, usd); /* rewrite */ -if (flg) { /* RBL? */ - rda = ReadB ((ea + Q16_BOT) & VAMASK); /* get bottom */ - if (rda == 0) rda = (slt - 1) & DMASK8; /* wrap if necc */ - else rda = rda - 1; /* dec bottom */ - WriteB ((ea + Q16_BOT) & VAMASK, rda); } /* rewrite bottom */ -else { rda = ReadB ((ea + Q16_TOP) & VAMASK); /* RTL, get top */ - t = rda + 1; /* adv top */ - if (t >= slt) t = 0; /* wrap if necc */ - WriteB ((ea + Q16_TOP) & VAMASK, t); } /* rewrite top */ -R[r1] = ReadH ((ea + Q16_BASE + (rda * Q16_SLNT)) & VAMASK); /* read slot */ -if (usd) return CC_G; /* set cc's */ -else return 0; -} - -/* Automatic interrupt processing */ - -#define CCW16_ERR(x) (((x)|CCW16_INIT|CCW16_NOP|CCW16_Q) & \ - ~(CCW16_CHN|CCW16_CON|CCW16_HI)) - -uint32 int_auto (uint32 dev, uint32 cc) -{ -int32 ba, ea, by, vec, ccw, bpi, fnc, trm, st, i, t; -t_bool sysqe = FALSE; -t_bool rpt = FALSE; - -do { - vec = ReadH (INTSVT + dev + dev); /* get vector */ - if ((vec & 1) == 0) { /* immed int? */ - WriteH (vec, BUILD_PSW (cc)); /* write PSW, PC */ - WriteH ((vec + 2) & VAMASK, PC); - cc = newPSW (ReadH ((vec + 4) & VAMASK)); /* read PSW */ - PC = (vec + 6) & VAMASK; /* set new PC */ - return cc; } - vec = vec & ~1; /* get CCW addr */ - ccw = ReadH (vec); /* read CCW */ - if (DEV_ACC (dev)) dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ - if (ccw & CCW16_NOP) break; /* NOP? exit */ - if (ccw & CCW16_INIT) { /* init set? */ - ccw = ccw & ~CCW16_INIT; /* clr init */ - WriteH (vec, ccw); /* rewrite */ - if (ccw & CCW16_OC) { /* OC set? */ - if (DEV_ACC (dev)) { /* dev exist? */ - by = ReadB ((vec + CCB16_IOC) & VAMASK);/* read OC byte */ - dev_tab[dev] (dev, IO_OC, by); } /* send to dev */ - break; } } /* and exit */ - fnc = CCW16_FNC (ccw); /* get func */ - st = 0; /* default status */ - if (fnc == CCW16_DMT) { /* DMT */ - ba = ReadH ((vec + CCB16_STR) & VAMASK); /* get cnt wd */ - ba = (ba - 1) & DMASK16; /* decr */ - WriteH ((vec + CCB16_STR) & VAMASK, ba); /* rewrite */ - if (ba) break; /* nz? exit */ - } /* end if dmt */ - else if (fnc != CCW16_NUL) { /* rd or wr? */ - if (DEV_ACC (dev)) /* dev exist? */ - st = dev_tab[dev] (dev, IO_SS, 0); /* sense status */ - else st = CC_V; /* else timeout */ - if (st & 0xF) { /* error? */ - ccw = CCW16_ERR (ccw); /* neuter CCW */ - WriteH (vec, ccw); } /* rewrite CCW */ - else { /* ok, do xfer */ - bpi = CCW16_BPI (ccw); /* get bytes/int */ - if (bpi == 0) bpi = 16; /* max 16B */ - ba = ReadH ((vec + CCB16_STR) & VAMASK); /* get start */ - for (i = 0; i < bpi; i++) { /* do # bytes */ - if (fnc == CCW16_RD) { /* chan read? */ - by = dev_tab[dev] (dev, IO_RD, 0); /* read byte */ - WriteB (ba, by); } /* store */ - else { /* chan write */ - by = ReadB (ba); /* fetch */ - dev_tab[dev] (dev, IO_WD, by); } /* write byte */ - ba = (ba + 1) & VAMASK; } /* incr addr */ - WriteH ((vec + CCB16_STR) & VAMASK, ba); /* rewrite */ - ea = ReadH ((vec + CCB16_END) & VAMASK); /* get end */ - trm = ReadB ((vec + CCB16_TRM) & VAMASK); /* get term chr */ - if ((ba <= ea) && /* not at end? */ - (((ccw & CCW16_TRM) == 0) || /* not term chr? */ - (by != trm))) break; /* exit */ - ccw = ccw | CCW16_NOP; /* nop CCW */ - WriteH (vec, ccw); /* rewrite CCW */ - } /* end else sta */ - } /* end if r/w */ - -/* Termination phase */ - - t = (dev << 8) | (st & DMASK8); /* form dev/sta */ - WriteH ((vec + CCB16_DEV) & VAMASK, t); /* write dev/sta */ - if (ccw & CCW16_Q) { /* q request? */ - t = ReadH (SQP); /* get sys q addr */ - if (addtoq (t, vec, ccw & CCW16_HI)) { /* add to sys q */ - WriteH (SQOP, vec); /* write to ovflo */ - return swap_psw (SQVPSW, cc); } /* take exception */ - else sysqe = TRUE; } /* made an entry */ - if (ccw & CCW16_CHN) { /* chain */ - t = ReadH ((vec + CCB16_CHN) & VAMASK); /* get chain wd */ - WriteH (INTSVT + dev + dev, t); /* wr int svc tab */ - if (ccw & CCW16_CON) rpt = TRUE; } /* cont? */ - } while (rpt); - -/* Common exit */ - -if (sysqe && (PSW & PSW_SQI)) /* sys q ent & enb? */ - return swap_psw (SQIPSW, cc); /* take sys q int */ -return cc; -} - -/* Display register device */ - -uint32 display (uint32 dev, uint32 op, uint32 dat) -{ -int t; - -switch (op) { -case IO_ADR: /* select */ - if (!drmod) drpos = srpos = 0; /* norm mode? clr */ - return BY; /* byte only */ -case IO_OC: /* command */ - op = op & 0xC0; - if (op == 0x40) { /* x40 = inc */ - drmod = 1; - drpos = srpos = 0; } /* init cntrs */ - else if (op == 0x80) drmod = 0; /* x80 = norm */ - break; -case IO_WD: /* write */ - if (drpos < 4) - DR = (DR & ~(DMASK8 << (drpos * 8))) | (dat << (drpos * 8)); - else if (drpos == 4) DRX = dat; - drpos = (drpos + 1) & - ((cpu_unit.flags & (UNIT_716 | UNIT_816))? 7: 3); - break; -case IO_RD: /* read */ - t = (SR >> (srpos * 8)) & DMASK8; - srpos = srpos ^ 1; - return t; -case IO_SS: /* status */ - return 0x80; } -return 0; -} - -/* Memory interface routines - - ReadB read byte (processor) - ReadH read halfword (processor) - ReadF read fullword (processor) - WriteB write byte (processor) - WriteH write halfword (processor) - WriteF write fullword (processor) - IOReadB read byte (IO) - IOWriteB write byte (IO) - IOReadH read halfword (IO) - IOWriteH write halfword (IO) -*/ - -uint32 ReadB (uint32 loc) -{ -uint32 pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; - -return ((M[pa >> 1] >> ((pa & 1)? 0: 8)) & DMASK8); -} - -uint32 ReadH (uint32 loc) -{ -uint32 pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; - -return M[pa >> 1]; -} - -uint32 ReadF (uint32 loc, uint32 rel) -{ -uint32 pa, pa1; -uint32 loc1 = (loc + 2) & VAMASK; - -loc = loc & VAMASK; /* FP doesn't mask */ -if (rel) { - pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; - pa1 = (loc1 + ((loc1 & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; } -else { pa = loc; - pa1 = loc1; } - -return (((uint32) M[pa >> 1]) << 16) | - ((uint32) M[pa1 >> 1]); -} - -void WriteB (uint32 loc, uint32 val) -{ -uint32 pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; - -val = val & DMASK8; -if (MEM_ADDR_OK (pa)) M[pa >> 1] = ((pa & 1)? - ((M[pa >> 1] & ~DMASK8) | val): - ((M[pa >> 1] & DMASK8) | (val << 8))); -return; -} - -void WriteH (uint32 loc, uint32 val) -{ -uint32 pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; - -if (MEM_ADDR_OK (pa)) M[pa >> 1] = val & DMASK16; -return; -} - -void WriteF (uint32 loc, uint32 val, uint32 rel) -{ -uint32 pa, pa1; -uint32 loc1 = (loc + 2) & VAMASK; - -loc = loc & VAMASK; /* FP doesn't mask */ -if (rel) { - pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; - pa1 = (loc1 + ((loc1 & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; } -else { pa = loc; - pa1 = loc1; } -if (MEM_ADDR_OK (pa)) M[pa >> 1] = (val >> 16) & DMASK16; -if (MEM_ADDR_OK (pa1)) M[pa1 >> 1] = val & DMASK16; -return; -} - -uint32 IOReadB (uint32 loc) -{ -return ((M[loc >> 1] >> ((loc & 1)? 0: 8)) & DMASK8); -} - -void IOWriteB (uint32 loc, uint32 val) -{ -val = val & DMASK8; -M[loc >> 1] = ((loc & 1)? - ((M[loc >> 1] & ~DMASK8) | val): - ((M[loc >> 1] & DMASK8) | (val << 8))); -return; -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -qevent = 0; /* no events */ -newPSW (0); /* PSW = 0 */ -DR = 0; /* clr display */ -drmod = 0; -blk_io.dfl = blk_io.cur = blk_io.end = 0; /* no block IO */ -sim_brk_types = sim_brk_dflt = SWMASK ('E'); /* init bkpts */ -if (M == NULL) M = calloc (MAXMEMSIZE16E >> 1, sizeof (uint16)); -if (M == NULL) return SCPE_MEM; -pcq_r = find_reg ("PCQ", NULL, dptr); /* init PCQ */ -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -if (sw & SWMASK ('V')) { - if (addr > VAMASK) return SCPE_NXM; - addr = (addr + ((addr & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; } -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = IOReadB (addr); -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -if (sw & SWMASK ('V')) { - if (addr > VAMASK) return SCPE_NXM; - addr = (addr + ((addr & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; } -if (addr >= MEMSIZE) return SCPE_NXM; -IOWriteB (addr, val & 0xFF); -return SCPE_OK; -} - -/* Change memory size */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i; - -if ((val <= 0) || ((val & 0xFFF) != 0) || - (((uint32) val) > ((uptr->flags & UNIT_816E)? MAXMEMSIZE16E: MAXMEMSIZE16))) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i = i + 2) mc = mc | M[i >> 1]; -if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_OK; -MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE16E; i = i + 2) M[i >> 1] = 0; -return SCPE_OK; -} - -/* Change CPU model */ - -t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -uint32 i; - -if (!(val & UNIT_816E) && (MEMSIZE > MAXMEMSIZE16)) { - MEMSIZE = MAXMEMSIZE16; - for (i = MEMSIZE; i < MAXMEMSIZE16E; i = i + 2) M[i >> 1] = 0; - printf ("Reducing memory to 64KB\n"); } -return SCPE_OK; -} - -/* Set console interrupt */ - -t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if ((uptr->flags & (UNIT_716 | UNIT_816 | UNIT_816E)) == 0) - return SCPE_NOFNC; -if (PSW & PSW_AIO) SET_INT (v_DS); -return SCPE_OK; -} diff --git a/Interdata/id16_dboot.c b/Interdata/id16_dboot.c deleted file mode 100644 index edbc9c0a..00000000 --- a/Interdata/id16_dboot.c +++ /dev/null @@ -1,352 +0,0 @@ -/* id16_dboot.c: Interdata 16b simulator disk bootstrap - - Copyright (c) 2000-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. -*/ - -#include "id_defs.h" - -#define DBOOT_BEG 0x1000 -#define DBOOT_START 0x100e -#define DBOOT_LEN (sizeof (dboot_rom) / sizeof (uint8)) - -/* Boot ROM: transcription of OS/16 MT2 ALO Direct Access Loader */ - -static uint8 dboot_rom[] = { - 0xca, 0xf0, 0x00, 0x30, - 0xc5, 0xf0, 0x00, 0x3a, - 0x02, 0x8e, - 0x26, 0xf7, - 0x03, 0x0e, - 0xd1, 0xc0, 0x00, 0x78, - 0xd0, 0xc0, 0x13, 0xf6, - 0x07, 0xdd, - 0xc8, 0x10, 0x10, 0x00, - 0xd3, 0xf0, 0x00, 0x7e, - 0xc4, 0xf0, 0x00, 0x0f, - 0x01, 0xe1, - 0xd2, 0xf0, 0x12, 0xe2, - 0xd3, 0xf0, 0x00, 0x7f, - 0x90, 0xf4, - 0x01, 0xe1, - 0xd2, 0xf0, 0x12, 0xe3, - 0xd3, 0xf0, 0x00, 0x7f, - 0xc4, 0xf0, 0x00, 0x0f, - 0x01, 0xe1, - 0xd2, 0xf0, 0x12, 0xe4, - 0xd3, 0x20, 0x00, 0x7d, - 0xd3, 0x30, 0x00, 0x7c, - 0xd3, 0x40, 0x00, 0x7a, - 0xd3, 0x50, 0x00, 0x7b, - 0xc8, 0x70, 0x12, 0xf6, - 0xc8, 0x80, 0x13, 0xf5, - 0x07, 0xaa, - 0x07, 0xcc, - 0x41, 0xe0, 0x11, 0x88, - 0x48, 0xa0, 0x12, 0xfe, - 0x48, 0xc0, 0x13, 0x00, - 0x43, 0x00, 0x10, 0x98, - 0xc8, 0x70, 0x12, 0xf6, - 0x41, 0xe0, 0x11, 0x88, - 0xc8, 0xe0, 0x12, 0xfa, - 0x24, 0x15, - 0xd3, 0x0e, 0x00, 0x24, - 0xc3, 0x00, 0x00, 0x10, - 0x21, 0x3f, - 0xca, 0xe0, 0x00, 0x30, - 0x27, 0x11, - 0x20, 0x38, - 0x48, 0xa0, 0x12, 0xf6, - 0x48, 0xc0, 0x12, 0xf8, - 0x42, 0x30, 0x10, 0x70, - 0x08, 0xaa, - 0x20, 0x33, - 0x43, 0x00, 0x12, 0xb2, - 0x90, 0x05, - 0x42, 0x30, 0x10, 0x88, - 0xc8, 0x60, 0x4f, 0x53, - 0x45, 0x63, 0x00, 0x00, - 0x20, 0x36, - 0xc8, 0x60, 0x31, 0x36, - 0x45, 0x6e, 0x00, 0x02, - 0x20, 0x3b, - 0x48, 0x6e, 0x00, 0x08, - 0x45, 0x60, 0x12, 0xe2, - 0x20, 0x35, - 0xd3, 0x6e, 0x00, 0x0a, - 0xd4, 0x60, 0x12, 0xe4, - 0x20, 0x3a, - 0x08, 0x0e, - 0x07, 0x66, - 0xca, 0x60, 0x20, 0x00, - 0x23, 0x36, - 0x40, 0x06, 0x00, 0x00, - 0x45, 0x06, 0x00, 0x00, - 0x22, 0x37, - 0x48, 0xae, 0x00, 0x0c, - 0x48, 0xce, 0x00, 0x0e, - 0x48, 0x0e, 0x00, 0x10, - 0x48, 0x1e, 0x00, 0x12, - 0x0b, 0x1c, - 0x0f, 0x0a, 0x07, 0xff, - 0x26, 0x11, - 0x0e, 0x0f, - 0xed, 0x00, 0x00, 0x08, - 0xcb, 0x60, 0x02, 0xbe, - 0x08, 0x00, - 0x23, 0x34, - 0x08, 0x86, - 0x08, 0x16, - 0x23, 0x04, - 0x05, 0x16, - 0x22, 0x84, - 0x08, 0x81, - 0x07, 0x77, - 0x27, 0x81, - 0xc8, 0xd1, 0xee, 0xc0, - 0xc8, 0xf0, 0x11, 0x40, - 0x48, 0x0f, 0x00, 0x00, - 0x40, 0x01, 0x00, 0x00, - 0x26, 0xf2, - 0x26, 0x12, - 0xc5, 0xf0, 0x13, 0xfe, - 0x20, 0x88, - 0x0a, 0xed, - 0x40, 0xed, 0x12, 0xf4, - 0x43, 0x0d, 0x11, 0x40, - 0x41, 0xed, 0x11, 0x88, - 0xd1, 0xed, 0x13, 0xf6, - 0xd0, 0xe0, 0x00, 0x78, - 0xd1, 0xed, 0x13, 0xfa, - 0xd0, 0xe0, 0x00, 0x7c, - 0x48, 0x10, 0x00, 0x62, - 0x48, 0x6d, 0x12, 0xf4, - 0xd1, 0xa6, 0x00, 0x00, - 0xd0, 0xa1, 0x00, 0x30, - 0xd1, 0xe6, 0x00, 0x0c, - 0xd0, 0xe1, 0x00, 0x28, - 0x43, 0x00, 0x00, 0x60, - 0x07, 0x00, - 0x07, 0xbb, - 0x0b, 0xcf, - 0x0f, 0xab, - 0x21, 0x13, - 0x26, 0x01, - 0x22, 0x04, - 0x0a, 0xcf, - 0x0e, 0xab, - 0x08, 0xac, - 0x08, 0xc0, - 0x03, 0x0e, - 0xde, 0x2d, 0x12, 0x1e, - 0xc5, 0x50, 0x00, 0x33, - 0x42, 0x2d, 0x11, 0xec, - 0xde, 0x3d, 0x12, 0x1e, - 0x9d, 0x3f, - 0x22, 0x21, - 0x9d, 0x4f, - 0x42, 0x1d, 0x12, 0xb8, - 0xc3, 0xf0, 0x00, 0x10, - 0x20, 0x35, - 0xd0, 0xad, 0x13, 0xea, - 0xc8, 0xf0, 0x00, 0x30, - 0x41, 0xed, 0x11, 0x70, - 0x08, 0x9c, - 0x08, 0xba, - 0x48, 0xad, 0x13, 0xea, - 0x48, 0xcd, 0x13, 0xee, - 0xd1, 0xed, 0x13, 0xf2, - 0xc5, 0xb0, 0x00, 0x18, - 0x21, 0x82, - 0x26, 0xb8, - 0x98, 0x49, - 0xde, 0x4d, 0x12, 0xe7, - 0x9d, 0x3f, - 0x22, 0x21, - 0x9d, 0x4f, - 0x42, 0x7d, 0x12, 0xb8, - 0x20, 0x83, - 0x98, 0x27, - 0x98, 0x28, - 0x98, 0x49, - 0x9a, 0x3b, - 0x41, 0x6d, 0x12, 0x7a, - 0x22, 0x0f, - 0x9d, 0x4f, - 0xc3, 0xf0, 0x00, 0x19, - 0x42, 0x3d, 0x12, 0xb8, - 0xd0, 0xad, 0x13, 0xea, - 0xc8, 0xf5, 0xff, 0xcc, - 0x0a, 0xff, - 0x48, 0xff, 0x12, 0xec, - 0x41, 0xed, 0x11, 0x70, - 0x08, 0x9c, - 0x08, 0xca, - 0x07, 0xaa, - 0xc8, 0xf5, 0xff, 0xcc, - 0xd3, 0xff, 0x12, 0xe8, - 0x41, 0xed, 0x11, 0x70, - 0x40, 0xcd, 0x12, 0xf2, - 0x08, 0xba, - 0x48, 0xad, 0x13, 0xea, - 0x48, 0xcd, 0x13, 0xee, - 0xd1, 0xed, 0x13, 0xf2, - 0xde, 0x4d, 0x12, 0x6e, - 0x9d, 0x3f, - 0x22, 0x21, - 0x98, 0x49, - 0xde, 0x4d, 0x12, 0xd0, - 0x9d, 0x3f, - 0x22, 0x21, - 0xde, 0x4d, 0x12, 0xa2, - 0x9d, 0x3f, - 0x22, 0x21, - 0xd8, 0x4d, 0x12, 0xf2, - 0xde, 0x4d, 0x12, 0xd1, - 0x9d, 0x3f, - 0x22, 0x21, - 0xde, 0x4d, 0x12, 0xe7, - 0x9d, 0x3f, - 0x22, 0x21, - 0x9d, 0x4f, - 0x20, 0x81, - 0xc3, 0xf0, 0x00, 0x53, - 0x42, 0x3d, 0x12, 0xb8, - 0x48, 0xfd, 0x12, 0xf2, - 0x91, 0xfa, - 0x06, 0xf9, - 0xc8, 0x6d, 0x12, 0x2c, - 0x98, 0x27, - 0x98, 0x28, - 0x9a, 0x3b, - 0x98, 0x3f, - 0xde, 0x3d, 0x12, 0xe6, - 0xde, 0x2d, 0x11, 0xaf, - 0x9d, 0x2f, - 0x20, 0x81, - 0xde, 0x2d, 0x12, 0x1e, - 0x99, 0x20, - 0xde, 0x2d, 0x12, 0x1e, - 0x9d, 0x3f, - 0x22, 0x21, - 0x42, 0x1d, 0x12, 0xbc, - 0xc3, 0xf0, 0x00, 0x10, - 0x03, 0x3e, - 0x0b, 0x07, - 0x26, 0x02, - 0xc4, 0x00, 0xff, 0x00, - 0x0a, 0x70, - 0x26, 0x91, - 0x07, 0xbb, - 0x40, 0xbd, 0x12, 0xf2, - 0x03, 0x06, - 0x24, 0xf1, - 0x24, 0x10, - 0x23, 0x04, - 0x08, 0x14, - 0x23, 0x02, - 0x08, 0x13, - 0x24, 0x01, - 0xde, 0x0d, 0x10, 0xdc, - 0x9a, 0x0f, - 0x9a, 0x01, - 0xde, 0x0d, 0x12, 0xe5, - 0xd1, 0xed, 0x13, 0xf6, - 0xd0, 0xe0, 0x00, 0x78, - 0xd1, 0xed, 0x13, 0xfa, - 0xd0, 0xe0, 0x00, 0x7c, - 0x91, 0x0f, - 0x95, 0x10, - 0x22, 0x01, - 0x00, 0x00, 0x00, - 0x80, - 0xc1, - 0xc2, - 0x14, 0x40, 0x40, 0x00, - 0x01, 0x90, - 0x01, 0x40, - 0x04, 0xc0, - 0x00, 0x00, - 0x00, 0x00 -}; - -/* Lower memory setup - - 78 = binary input device address - 79 = binary device input command - 7A = disk device number - 7B = device code - 7C = disk controller address - 7D = selector channel address - 7E:7F = operating system extension (user specified) -*/ - -struct dboot_id { - char *name; - uint32 sw; - uint32 cap; - uint32 dtype; - uint32 offset; - uint32 adder; -}; - -static struct dboot_id dboot_tab[] = { - { "DP", 0, 2, 0x31, o_DP0, 0 }, - { "DP", SWMASK ('F'), 9, 0x32, o_DP0, o_DPF }, - { "DP", 0, 9, 0x33, o_DP0, 0 }, - { "DM", 0, 64, 0x35, o_ID0, 0 }, - { "DM", 0, 244, 0x36, o_ID0, 0 }, - { NULL } }; - -t_stat id_dboot (int32 u, DEVICE *dptr) -{ -extern DIB pt_dib, sch_dib; -extern uint32 PC; -extern int32 sim_switches; -uint32 i, typ, ctlno, off, add, cap, sch_dev; -UNIT *uptr; - -DIB *ddib = (DIB *) dptr->ctxt; /* get disk DIB */ -ctlno = ddib->dno; /* get ctrl devno */ -sch_dev = sch_dib.dno + ddib->sch; /* sch dev # */ -uptr = dptr->units + u; /* get capacity */ -cap = uptr->capac >> 20; -for (i = typ = 0; dboot_tab[i].name != NULL; i++) { - if ((strcmp (dboot_tab[i].name, dptr->name) == 0) && - (dboot_tab[i].cap == cap)) { - typ = dboot_tab[i].dtype; - off = dboot_tab[i].offset; - add = dboot_tab[i].adder; - break; } } -if (typ == 0) return SCPE_NOFNC; - -IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */ -IOWriteB (AL_DEV, pt_dib.dno); /* bin input dev */ -IOWriteB (AL_IOC, 0x99); -IOWriteB (AL_DSKU, ctlno + ((u + 1) * off) + add); /* disk param */ -IOWriteB (AL_DSKT, typ); -IOWriteB (AL_DSKC, ctlno); -IOWriteB (AL_SCH, sch_dev); -PC = DBOOT_START; -return SCPE_OK; -} diff --git a/Interdata/id16_sys.c b/Interdata/id16_sys.c deleted file mode 100644 index be300924..00000000 --- a/Interdata/id16_sys.c +++ /dev/null @@ -1,570 +0,0 @@ -/* id16_sys.c: Interdata 16b simulator interface - - Copyright (c) 2000-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 27-Feb-03 RMS Added relative addressing support -*/ - -#include "id_defs.h" -#include - -#define MSK_SBF 0x0100 - -extern DEVICE cpu_dev; -extern DEVICE sch_dev; -extern DEVICE pt_dev; -extern DEVICE tt_dev, ttp_dev; -extern DEVICE pas_dev, pasl_dev; -extern DEVICE lpt_dev; -extern DEVICE pic_dev, lfc_dev; -extern DEVICE dp_dev, idc_dev; -extern DEVICE fd_dev, mt_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern uint16 *M; - -t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val, t_bool cf); -t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf); -extern t_stat lp_load (FILE *fileref, char *cptr, char *fnam); -extern pt_dump (FILE *of, char *cptr, char *fnam); - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "Interdata 16b"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 8; - -DEVICE *sim_devices[] = { - &cpu_dev, - &sch_dev, - &pt_dev, - &tt_dev, - &ttp_dev, - &pas_dev, - &pasl_dev, - &pic_dev, - &lfc_dev, - &lpt_dev, - &dp_dev, - &idc_dev, - &fd_dev, - &mt_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Reserved instruction", - "HALT instruction", - "Breakpoint", - "Wait state", - "Runaway VFU" }; - -/* Binary loader -- load carriage control tape - Binary dump -- paper tape dump */ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -if (flag) return pt_dump (fileref, cptr, fnam); -return lp_load (fileref, cptr, fnam); -} - -/* Symbol tables */ - -#define I_V_FL 16 /* class bits */ -#define I_M_FL 0xF /* class mask */ -#define I_V_MR 0x0 /* mask-register */ -#define I_V_RR 0x1 /* register-register */ -#define I_V_R 0x2 /* register */ -#define I_V_MX 0x3 /* mask-memory */ -#define I_V_RX 0x4 /* register-memory */ -#define I_V_X 0x5 /* memory */ -#define I_V_FF 0x6 /* float reg-reg */ -#define I_V_FX 0x7 /* float reg-mem */ -#define I_V_SI 0x8 /* short immed */ -#define I_V_SB 0x9 /* short branch */ -#define I_V_SX 0xA /* short ext branch */ -#define I_MR (I_V_MR << I_V_FL) -#define I_RR (I_V_RR << I_V_FL) -#define I_R (I_V_R << I_V_FL) -#define I_MX (I_V_MX << I_V_FL) -#define I_RX (I_V_RX << I_V_FL) -#define I_X (I_V_X << I_V_FL) -#define I_FF (I_V_FF << I_V_FL) -#define I_FX (I_V_FX << I_V_FL) -#define I_SI (I_V_SI << I_V_FL) -#define I_SB (I_V_SB << I_V_FL) -#define I_SX (I_V_SX << I_V_FL) - -#define R_X 0 /* no reg */ -#define R_M 1 /* reg mask */ -#define R_R 2 /* reg int reg */ -#define R_F 3 /* reg flt reg */ - -static const int32 masks[] = { - 0xFF00, 0xFF00, 0xFFF0, 0xFF00, - 0xFF00, 0xFFF0, 0xFF00, 0xFF00, - 0xFF00, 0xFE00, 0xFEF0 }; - -static const uint32 r1_type[] = { - R_M, R_R, R_X, R_M, - R_R, R_X, R_F, R_F, - R_R, R_M, R_X }; - -static const uint32 r2_type[] = { - R_X, R_R, R_R, R_X, - R_X, R_X, R_F, R_X, - R_M, R_X, R_X }; - -static const char *opcode[] = { -"BER", "BNER","BZR", "BNZR", -"BPR", "BNPR","BLR", "BNLR", -"BMR", "BNMR","BOR", "BNOR", -"BCR", "BNCR","BR", -"BES", "BNES","BZS", "BNZS", -"BPS", "BNPS","BLS", "BNLS", -"BMS", "BNMS","BOS", "BNOS", -"BCS", "BNCS","BS", -"BE", "BNE", "BZ", "BNZ", -"BP", "BNP", "BL", "BNL", -"BM", "BNM", "BO", "BNO", -"BC", "BNC", "B", - "BALR","BTCR","BFCR", -"NHR", "CLHR","OHR", "XHR", -"LHR", "CHR", "AHR", "SHR", -"MHR", "DHR", "ACHR","SCHR", - "SETMR", -"BTBS","BTFS","BFBS","BFFS", -"LIS", "LCS", "AIS", "SIS", -"LER", "CER", "AER", "SER", -"MER", "DER", "FXR", "FLR", - "LPSR", -"LDR", "CDR", "ADR", "SDR", -"MDR", "DDR", "FXDR","FLDR", -"STH", "BAL", "BTC", "BFC", -"NH", "CLH", "OH", "XH", -"LH", "CH", "AH", "SH", -"MH", "DH", "ACH", "SCH", - "SETM", -"STE", "AHM", -"ATL", "ABL", "RTL", "RBL", -"LE", "CE", "AE", "SE", -"ME", "DE", -"STD", "STME","LME", "LPS", -"LD", "CD", "AD", "SD", -"MD", "DD", "STMD","LMD", -"SRLS","SLLS","STBR","LBR", -"EXBR","EPSR","WBR", "RBR", -"WHR", "RHR", "WDR", "RDR", -"MHUR","SSR", "OCR", "AIR", -"BXH", "BXLE","LPSW","THI", -"NHI", "CLHI","OHI", "XHI", -"LHI", "CHI", "AHI", "SHI", -"SRHL","SLHL","SRHA","SLHA", -"STM", "LM", "STB", "LB", -"CLB", "AL", "WB", "RB", -"WH", "RH", "WD", "RD", -"MHU", "SS", "OC", "AI", - "SVC", "SINT", - "RRL", "RLL", -"SRL", "SLL", "SRA", "SLA", -NULL }; - -static const uint32 opc_val[] = { -0x0330+I_R, 0x0230+I_R, 0x0330+I_R, 0x0230+I_R, -0x0220+I_R, 0x0320+I_R, 0x0280+I_R, 0x0380+I_R, -0x0210+I_R, 0x0310+I_R, 0x0240+I_R, 0x0340+I_R, -0x0280+I_R, 0x0380+I_R, 0x0300+I_R, -0x2230+I_SX, 0x2030+I_SX, 0x2230+I_SX, 0x2030+I_SX, -0x2020+I_SX, 0x2220+I_SX, 0x2080+I_SX, 0x2280+I_SX, -0x2010+I_SX, 0x2210+I_SX, 0x2040+I_SX, 0x2240+I_SX, -0x2080+I_SX, 0x2280+I_SX, 0x2200+I_SX, -0x4330+I_X, 0x4230+I_X, 0x4330+I_X, 0x4230+I_X, -0x4220+I_X, 0x4320+I_X, 0x4280+I_X, 0x4380+I_X, -0x4210+I_X, 0x4310+I_X, 0x4240+I_X, 0x4340+I_X, -0x4280+I_X, 0x4380+I_X, 0x4300+I_X, - 0x0100+I_RR, 0x0200+I_MR, 0x0300+I_MR, -0x0400+I_RR, 0x0500+I_RR, 0x0600+I_RR, 0x0700+I_RR, -0x0800+I_RR, 0x0900+I_RR, 0x0A00+I_RR, 0x0B00+I_RR, -0x0C00+I_RR, 0x0D00+I_RR, 0x0E00+I_RR, 0x0F00+I_RR, - 0x1300+I_RR, -0x2000+I_SB, 0x2100+I_SB, 0x2200+I_SB, 0x2300+I_SB, -0x2400+I_SI, 0x2500+I_SI, 0x2600+I_SI, 0x2700+I_SI, -0x2800+I_FF, 0x2900+I_FF, 0x2A00+I_FF, 0x2B00+I_FF, -0x2C00+I_FF, 0x2D00+I_FF, 0x2E00+I_RR, 0x2F00+I_RR, - 0x3300+I_R, -0x3800+I_FF, 0x3900+I_FF, 0x3A00+I_FF, 0x3B00+I_FF, -0x3C00+I_FF, 0x3D00+I_FF, 0x3E00+I_RR, 0x3F00+I_RR, -0x4000+I_RX, 0x4100+I_RX, 0x4200+I_MX, 0x4300+I_MX, -0x4400+I_RX, 0x4500+I_RX, 0x4600+I_RX, 0x4700+I_RX, -0x4800+I_RX, 0x4900+I_RX, 0x4A00+I_RX, 0x4B00+I_RX, -0x4C00+I_RX, 0x4D00+I_RX, 0x4E00+I_RX, 0x4F00+I_RX, - 0x5300+I_RX, -0x6000+I_RX, 0x6100+I_RX, -0x6400+I_RX, 0x6500+I_RX, 0x6600+I_RX, 0x6700+I_RX, -0x6800+I_FX, 0x6900+I_FX, 0x6A00+I_FX, 0x6B00+I_FX, -0x6C00+I_FX, 0x6D00+I_FX, -0x7000+I_FX, 0x7100+I_FX, 0x7200+I_FX, 0x7300+I_X, -0x7800+I_FX, 0x7900+I_FX, 0x7A00+I_FX, 0x7B00+I_FX, -0x7C00+I_FX, 0x7D00+I_FX, 0x7E00+I_FX, 0x7F00+I_FX, -0x9000+I_SI, 0x9100+I_SI, 0x9200+I_RR, 0x9300+I_RR, -0x9400+I_RR, 0x9500+I_RR, 0x9600+I_RR, 0x9700+I_RR, -0x9800+I_RR, 0x9900+I_RR, 0x9A00+I_RR, 0x9B00+I_RR, -0x9C00+I_RR, 0x9D00+I_RR, 0x9E00+I_RR, 0x9F00+I_RR, -0xC000+I_RX, 0xC100+I_RX, 0xC200+I_X, 0xC300+I_RX, -0xC400+I_RX, 0xC500+I_RX, 0xC600+I_RX, 0xC700+I_RX, -0xC800+I_RX, 0xC900+I_RX, 0xCA00+I_RX, 0xCB00+I_RX, -0xCC00+I_RX, 0xCD00+I_RX, 0xCE00+I_RX, 0xCF00+I_RX, -0xD000+I_RX, 0xD100+I_RX, 0xD200+I_RX, 0xD300+I_RX, -0xD400+I_RX, 0xD500+I_X, 0xD600+I_RX, 0xD700+I_RX, -0xD800+I_RX, 0xD900+I_RX, 0xDA00+I_RX, 0xDB00+I_RX, -0xDC00+I_RX, 0xDD00+I_RX, 0xDE00+I_RX, 0xDF00+I_RX, - 0xE100+I_RX, 0xE200+I_RX, - 0xEA00+I_RX, 0xEB00+I_RX, -0xEC00+I_RX, 0xED00+I_RX, 0xEE00+I_RX, 0xEF00+I_RX, -0xFFFF }; - -#define GETNUM(d,n) for (k = d = 0; k < n; k++) \ - d = (d << 8) | (((uint32) val[vp++]) & 0xFF) - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current PC - *val = values to decode - *uptr = pointer to unit - sw = switches - Outputs: - return = if >= 0, error code - if < 0, number of extra bytes retired -*/ - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 c, k, num, rdx, vp, lnt; -t_stat r; -DEVICE *dptr; - -if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ -dptr = find_dev_from_unit (uptr); /* find dev */ -if (dptr == NULL) return SCPE_IERR; -if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */ -if (sw & SWMASK ('B')) lnt = 1; /* get length */ -else if (sw & SWMASK ('W')) lnt = 2; -else if (sw & SWMASK ('F')) lnt = 4; -else lnt = (uptr == &cpu_unit)? 2: 1; -if (sw & SWMASK ('D')) rdx = 10; /* get radix */ -else if (sw & SWMASK ('O')) rdx = 8; -else if (sw & SWMASK ('H')) rdx = 16; -else rdx = dptr->dradix; -vp = 0; /* init ptr */ -if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */ - if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */ - if ((val[0] & 0x7F) == 0) return SCPE_ARG; - while (vp < lnt) { /* print string */ - if ((c = (uint32) val[vp++] & 0x7F) == 0) break; - fprintf (of, (c < 0x20)? "<%02X>": "%c", c); } - return -(vp - 1); } /* return # chars */ - -if (sw & SWMASK ('M')) { /* inst format? */ - r = fprint_sym_m (of, addr, val, uptr == &cpu_unit); /* decode inst */ - if (r <= 0) return r; } - -GETNUM (num, lnt); /* get number */ -fprint_val (of, num, rdx, lnt * 8, PV_RZRO); -return -(vp - 1); -} - -/* Symbolic decode for -m - - Inputs: - of = output stream - addr = current PC - *val = values to decode - cf = true if decoding for CPU - Outputs: - return = if >= 0, error code - if < 0, number of extra bytes retired -*/ - -t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val, t_bool cf) -{ -uint32 i, j, k, inst, r1, r2, ea, vp; - -vp = 0; -GETNUM (inst, 2); /* first 16b */ -GETNUM (ea, 2); /* second 16b */ -for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */ - r1 = (inst >> 4) & 0xF; - r2 = inst & 0xF; - fprintf (of, "%s ", opcode[i]); /* print opcode */ - switch (j) { /* case on class */ - case I_V_MR: /* mask-register */ - fprintf (of, "%-X,R%d", r1, r2); - return -1; - case I_V_RR: /* register-register */ - case I_V_FF: /* floating-floating */ - fprintf (of, "R%d,R%d", r1, r2); - return -1; - case I_V_SI: /* short immediate */ - fprintf (of, "R%d,%-X", r1, r2); - return -1; - case I_V_SB: /* short branch */ - fprintf (of, "%-X,", r1); - case I_V_SX: /* ext short branch */ - if (cf) fprintf (of, "%-X", ((inst & MSK_SBF)? - (addr + r2 + r2): (addr - r2 - r2))); - else fprintf (of, ((inst & MSK_SBF)? - ".+%-X": ".-%X"), r2 + r2); - return -1; - case I_V_R: /* register */ - fprintf (of, "R%d", r2); - return -1; - case I_V_MX: /* mask-memory */ - fprintf (of, "%-X,%-X", r1, ea); - break; - case I_V_RX: /* register-memory */ - case I_V_FX: /* floating-memory */ - fprintf (of, "R%d,%-X", r1, ea); - break; - case I_V_X: /* memory */ - fprintf (of, "%-X", ea); - break; } /* end case */ - if (r2) fprintf (of, "(R%d)", r2); - return -3; } /* end if */ - } /* end for */ -return SCPE_ARG; /* no match */ -} - -/* Register number - - Inputs: - *cptr = pointer to input string - **optr = pointer to pointer to next char - rtype = mask, integer, or float - Outputs: - rnum = output register number, -1 if error -*/ - -int32 get_reg (char *cptr, char **optr, int32 rtype) -{ -int32 reg; - -if ((*cptr == 'R') || (*cptr == 'r')) { /* R? */ - cptr++; /* skip */ - if (rtype == R_M) return -1; } /* cant be mask */ -if ((*cptr >= '0') && (*cptr <= '9')) { - reg = *cptr++ - '0'; - if ((*cptr >= '0') && (*cptr <= '9')) - reg = (reg * 10) + (*cptr - '0'); - else --cptr; - if (reg > 0xF) return -1; } -else if ((*cptr >= 'a') && (*cptr <= 'f')) reg = (*cptr - 'a') + 10; -else if ((*cptr >= 'A') && (*cptr <= 'F')) reg = (*cptr - 'A') + 10; -else return -1; -if ((rtype == R_F) && (reg & 1)) return -1; -*optr = cptr + 1; -return reg; -} - -/* Address - - Inputs: - *cptr = pointer to input string - **tptr = pointer to moved pointer - *ea = effective address - *rel = relative flag - addr = base address - cf = true if parsing for CPU - Outputs: - status = SCPE_OK if ok, else error code -*/ - -t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_bool *rel, - t_addr addr, t_bool cf) -{ -int32 sign = 1; - -*ea = 0; -if (*cptr == '.') { /* relative? */ - *rel = TRUE; - cptr++; - if (cf) *ea = addr; - if (*cptr == '+') cptr++; /* .+? */ - else if (*cptr == '-') { /* .-? */ - sign = -1; - cptr++; } - else return SCPE_OK; } -else *rel = FALSE; -errno = 0; -*ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16))); -if (errno || (cptr == *tptr)) return SCPE_ARG; -return SCPE_OK; -} - -#define PUTNUM(d,n) for (k = n; k > 0; k--) \ - val[vp++] = (d >> ((k - 1) * 8)) & 0xFF - -/* Symbolic input */ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 k, rdx, lnt, num, vp; -t_stat r; -DEVICE *dptr; -static const uint32 maxv[5] = { 0, 0xFF, 0xFFFF, 0, 0xFFFFFFFF }; - -if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ -dptr = find_dev_from_unit (uptr); /* find dev */ -if (dptr == NULL) return SCPE_IERR; -if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */ -if (sw & SWMASK ('B')) lnt = 1; /* get length */ -else if (sw & SWMASK ('W')) lnt = 2; -else if (sw & SWMASK ('F')) lnt = 4; -else lnt = (uptr == &cpu_unit)? 2: 1; -if (sw & SWMASK ('D')) rdx = 10; /* get radix */ -else if (sw & SWMASK ('O')) rdx = 8; -else if (sw & SWMASK ('H')) rdx = 16; -else rdx = dptr->dradix; -vp = 0; -if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */ - if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */ - if (*cptr == 0) return SCPE_ARG; - while ((vp < lnt) && *cptr) { /* get chars */ - val[vp++] = *cptr++; } - return -(vp - 1); } /* return # chars */ - -r = parse_sym_m (cptr, addr, val, uptr == &cpu_unit); /* try to parse inst */ -if (r <= 0) return r; - -num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */ -if (r != SCPE_OK) return r; -PUTNUM (num, lnt); /* store */ -return -(lnt - 1); -} - -/* Symbolic input for -m - - Inputs: - *cptr = pointer to input string - addr = current PC - *val = pointer to output values - cf = true if parsing for CPU - Outputs: - status = > 0 error code - <= 0 -number of extra words -*/ - -t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf) -{ -uint32 i, j, k, t, df, db, inst, vp; -int32 st, r1, r2; -t_bool rel; -t_stat r; -char *tptr, gbuf[CBUFSIZE]; - -vp = 0; -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; -if (opcode[i] == NULL) return SCPE_ARG; -inst = opc_val[i] & 0xFFFF; /* get value */ -j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ -if (r1_type[j]) { /* any R1 field? */ - cptr = get_glyph (cptr, gbuf, ','); /* get R1 field */ - if ((r1 = get_reg (gbuf, &tptr, r1_type[j])) < 0) - return SCPE_ARG; - if (*tptr != 0) return SCPE_ARG; /* all done? */ - inst = inst | (r1 << 4); } /* or in R1 */ - -cptr = get_glyph (cptr, gbuf, 0); /* get operand */ -if (*cptr) return SCPE_ARG; /* should be end */ -switch (j) { /* case on class */ - -case I_V_FF: case I_V_SI: /* flt-flt, sh imm */ -case I_V_MR: case I_V_RR: /* mask/reg-reg */ -case I_V_R: /* register */ - if ((r2 = get_reg (gbuf, &tptr, r2_type[j])) < 0) - return SCPE_ARG; - if (*tptr != 0) return SCPE_ARG; /* all done? */ - inst = inst | r2; /* or in R2 */ - break; - -case I_V_FX: /* float-memory */ -case I_V_MX: case I_V_RX: /* mask/reg-mem */ -case I_V_X: /* memory */ - r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */ - if ((r != SCPE_OK) || (t > PAMASK16) || - (!cf && rel)) return SCPE_ARG; - if (*tptr == '(') { /* index? */ - if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0) - return SCPE_ARG; - if (*tptr++ != ')') return SCPE_ARG; - inst = inst | r2; } /* or in R2 */ - if (*tptr != 0) return SCPE_ARG; - PUTNUM (inst, 2); - PUTNUM (t, 2); - return -3; - -case I_V_SB: case I_V_SX: /* short branches */ - r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */ - if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */ - return SCPE_ARG; - st = t; /* signed version */ - if (cf) { /* for CPU? */ - db = (addr - t) & 0x1F; /* back displ */ - df = (t - addr) & 0x1F; /* fwd displ */ - if ((t == ((addr - db) & VAMASK16)) && /* back work and */ - ((j == I_V_SX) || !(inst & MSK_SBF))) /* ext or back br? */ - inst = inst | (db >> 1); /* or in back displ */ - else if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */ - ((j == I_V_SX) || (inst & MSK_SBF))) /* ext or fwd br? */ - inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */ - else return SCPE_ARG; } - else if (rel) { /* periph, must be rel */ - if ((st <= 0) && (st >= -0x1F) && /* relative back? */ - ((j == I_V_SX) || !(inst & MSK_SBF))) - inst = inst | ((-st & 0x1F) >> 1); - else if ((st >= 0) && (st < 0x1F) && /* relative fwd? */ - ((j == I_V_SX) || (inst & MSK_SBF))) - inst = inst | ((t & 0x1F) >> 1); - else return SCPE_ARG; } - else return SCPE_ARG; /* periph & ~rel, err */ - } /* end case */ - -PUTNUM (inst, 2); -return -1; -} diff --git a/Interdata/id32_cpu.c b/Interdata/id32_cpu.c deleted file mode 100644 index a0846485..00000000 --- a/Interdata/id32_cpu.c +++ /dev/null @@ -1,2028 +0,0 @@ -/* id32_cpu.c: Interdata 32b CPU simulator - - Copyright (c) 2000-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - The register state for an Interdata 32b CPU is: - - REG[0:F][2]<0:31> general register sets - F[0:7]<0:31> single precision floating point registers - D[0:7]<0:63> double precision floating point registers - PSW<0:63> processor status word, including - STAT<0:11> status flags - CC<0:3> condition codes - PC<0:31> program counter - int_req[n]<0:31> interrupt requests - int_enb[n]<0:31> interrupt enables - - The Interdata 32b systems have seven instruction formats: register to - register, short format, register and memory (three formats), and register - and immediate (two formats). The formats are: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op | R1 | R2 | register-register - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op | R1 | N | short format - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op | R1 | RX | register-memory 1 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ (absolute 14b) - | 0| 0| address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op | R1 | RX | register-memory 2 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ (relative) - | 1| address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op | R1 | RX | register-memory 3 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ (double index) - | 0| 1| 0| 0| RX2 | address hi | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | address lo | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op | R1 | RX | register-immediate 1 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | immediate | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op | R1 | RX | register-immediate 2 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | immediate hi | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | immediate lo | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - For register-memory 1 and register-immediate 1 and 2 an instructions, an - effective address is calculated as follows: - - effective addr = address + RX (if RX > 0) - - For register-memory 2, an effective address is calculated as follows: - - effective addr = address + PC + RX (if RX > 0) - - For register-memory 3, an effective address is calculated as follows: - - effective addr = address + RX (if RX > 0) + RX2 (if RX2 > 0) - - Register-memory instructions can access an address space of 16M bytes. -*/ - -/* This routine is the instruction decode routine for the Interdata CPU. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - breakpoint encountered - wait state and no I/O outstanding - invalid instruction - I/O error in I/O simulator - - 2. Interrupts. Each device has an interrupt armed flag, an interrupt - request flag, and an interrupt enabled flag. To facilitate evaluation, - all interrupt requests are kept in int_req, and all enables in int_enb. - Interrupt armed flags are local to devices. If external interrupts are - enabled in the PSW, and a request is pending, an interrupt occurs. - - 3. Non-existent memory. On the Interdata 32b, reads to non-existent - memory return zero, and writes are ignored. In the simulator, the - largest possible memory is instantiated and initialized to zero. - Thus, only writes need be checked against actual memory size. - - 4. Adding I/O devices. These modules must be modified: - - id_defs.h add device interrupt definitions - id32_sys.c add sim_devices table entry -*/ - -#include "id_defs.h" -#include - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = oPC -#define VAMASK VAMASK32 -#define NRSETS 2 /* 2 gen reg sets */ -#define PSW_MASK PSW_x32 -#define ABORT(val) longjmp (save_env, (val)) -#define MPRO (-1) - -#define UNIT_V_MSIZE (UNIT_V_UF + 0) /* dummy mask */ -#define UNIT_V_DPFP (UNIT_V_UF + 1) -#define UNIT_V_832 (UNIT_V_UF + 2) -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) -#define UNIT_DPFP (1 << UNIT_V_DPFP) -#define UNIT_832 (1 << UNIT_V_832) -#define UNIT_TYPE (UNIT_DPFP | UNIT_832) - -#define SEXT32(x) (((x) & SIGN32)? ((int32) ((x) | ~0x7FFFFFFF)): \ - ((int32) ((x) & 0x7FFFFFFF))) -#define SEXT16(x) (((x) & SIGN16)? ((int32) ((x) | ~0x7FFF)): \ - ((int32) ((x) & 0x7FFF))) -#define SEXT15(x) (((x) & 0x4000)? ((int32) ((x) | ~0x3FFF)): \ - ((int32) ((x) & 0x3FFF))) -#define CC_GL_16(x) if ((x) & SIGN16) cc = CC_L; \ - else if (x) cc = CC_G; \ - else cc = 0 -#define CC_GL_32(x) if ((x) & SIGN32) cc = CC_L; \ - else if (x) cc = CC_G; \ - else cc = 0 -#define BUILD_PSW(x) (((PSW & ~CC_MASK) | (x)) & PSW_MASK) -#define NEG(x) ((~(x) + 1) & DMASK32) -#define ABS(x) (((x) & SIGN32)? NEG (x): (x)) -#define DNEG(x,y) y = NEG (y); \ - x = (~(x) + (y == 0)) & DMASK32 - -uint32 GREG[16 * NRSETS] = { 0 }; /* general registers */ -uint32 *M = NULL; /* memory */ -uint32 *R = &GREG[0]; /* working reg set */ -uint32 F[8] = { 0 }; /* sp fp registers */ -dpr_t D[8] = { 0 }; /* dp fp registers */ -uint32 PSW = 0; /* processor status word */ -uint32 PC = 0; /* program counter */ -uint32 oPC = 0; /* PC at inst start */ -uint32 SR = 0; /* switch register */ -uint32 DR = 0; /* display register */ -uint32 DRX = 0; /* display extension */ -uint32 drmod = 0; /* mode */ -uint32 srpos = 0; /* switch register pos */ -uint32 drpos = 0; /* display register pos */ -uint32 mac_reg[MAC_LNT] = { 0 }; /* mac registers */ -uint32 mac_sta = 0; /* mac status */ -uint32 int_req[INTSZ] = { 0 }; /* interrupt requests */ -uint32 int_enb[INTSZ] = { 0 }; /* interrupt enables */ -uint32 qevent = 0; /* events */ -uint32 stop_inst = 0; /* stop on ill inst */ -uint32 stop_wait = 0; /* stop on wait */ -uint32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -uint32 dec_flgs = 0; /* decode flags */ -uint32 fp_in_hwre = 0; /* ucode vs hwre fp */ -uint32 pawidth = PAWIDTH32; /* addr mask */ -uint32 cpu_log = 0; /* debug logging */ -jmp_buf save_env; /* abort handler */ -struct BlockIO blk_io; /* block I/O status */ -uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout) = { NULL }; - -extern int32 sim_interval; -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern UNIT pic_unit, lfc_unit, pas_unit; /* timers */ -extern FILE *sim_log; - -uint32 ReadB (uint32 loc, uint32 rel); -uint32 ReadH (uint32 loc, uint32 rel); -void WriteB (uint32 loc, uint32 val, uint32 rel); -void WriteH (uint32 loc, uint32 val, uint32 rel); -uint32 RelocT (uint32 va, uint32 base, uint32 rel, uint32 *pa); -uint32 int_auto (uint32 dev, uint32 cc); -uint32 addtoq (uint32 ea, uint32 val, uint32 flg); -uint32 remfmq (uint32 ea, uint32 r1, uint32 flg); -uint32 exception (uint32 loc, uint32 cc, uint32 flg); -uint32 newPSW (uint32 val); -uint32 testsysq (uint32 cc); -uint32 display (uint32 dev, uint32 op, uint32 dat); -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc); -void set_r_display (uint32 *rbase); - -extern t_bool devtab_init (void); -extern void int_eval (void); -extern uint32 int_getdev (void); -extern void sch_cycle (uint32 ch); -extern t_bool sch_blk (uint32 dev); -extern uint32 f_l (uint32 op, uint32 r1, uint32 r2, uint32 ea); -extern uint32 f_c (uint32 op, uint32 r1, uint32 r2, uint32 ea); -extern uint32 f_as (uint32 op, uint32 r1, uint32 r2, uint32 ea); -extern uint32 f_m (uint32 op, uint32 r1, uint32 r2, uint32 ea); -extern uint32 f_d (uint32 op, uint32 r1, uint32 r2, uint32 ea); -extern uint32 f_fix32 (uint32 op, uint32 r1, uint32 r2); -extern uint32 f_flt32 (uint32 op, uint32 r1, uint32 r2); - -/* Instruction decoding table */ - -const uint16 decrom[256] = { - 0, /* 00 */ - OP_RR, /* BALR */ - OP_RR, /* BTCR */ - OP_RR, /* BFCR */ - OP_RR, /* NR */ - OP_RR, /* CLR */ - OP_RR, /* OR */ - OP_RR, /* XR */ - OP_RR, /* LR */ - OP_RR, /* CR */ - OP_RR, /* AR */ - OP_RR, /* SR */ - OP_RR, /* MHR */ - OP_RR, /* DHR */ - 0, 0, /* 0E:0F */ - OP_NO, /* SRLS */ - OP_NO, /* SLLS */ - OP_RR, /* CHVR */ - 0, 0, 0, 0, 0, /* 13:17 */ - OP_RR | OP_PRV, /* LPSWR */ - 0, 0, 0, /* 19:1B */ - OP_RR, /* MR */ - OP_RR, /* DR */ - 0, 0, /* 1E:1F */ - OP_NO, /* BTBS */ - OP_NO, /* BTFS */ - OP_NO, /* BFBS */ - OP_NO, /* BFFS */ - OP_NO, /* LIS */ - OP_NO, /* LCS */ - OP_NO, /* AIS */ - OP_NO, /* SIS */ - OP_NO, /* LER */ - OP_NO, /* CER */ - OP_NO, /* AER */ - OP_NO, /* SER */ - OP_NO, /* MER */ - OP_NO, /* DER */ - OP_NO, /* FXR */ - OP_NO, /* FLR */ - 0, /* MPBSR - 8/32C */ - 0, /* 31 */ - 0, /* PBR - 8/32C */ - 0, /* 33 */ - OP_RR, /* EXHR */ - 0, 0, 0, /* 35:37 */ - OP_NO | OP_DPF, /* LDR */ - OP_NO | OP_DPF, /* CDR */ - OP_NO | OP_DPF, /* ADR */ - OP_NO | OP_DPF, /* SDR */ - OP_NO | OP_DPF, /* MDR */ - OP_NO | OP_DPF, /* DDR */ - OP_NO | OP_DPF, /* FXDR */ - OP_NO | OP_DPF, /* FLDR */ - OP_RX, /* STH */ - OP_RX, /* BAL */ - OP_RX, /* BTC */ - OP_RX, /* BFC */ - OP_RXH, /* NH */ - OP_RXH, /* CLH */ - OP_RXH, /* OH */ - OP_RXH, /* XH */ - OP_RXH, /* LH */ - OP_RXH, /* CH */ - OP_RXH, /* AH */ - OP_RXH, /* SH */ - OP_RXH, /* MH */ - OP_RXH, /* DH */ - 0, 0, /* 4E:4F */ - OP_RX, /* ST */ - OP_RXF, /* AM */ - 0, 0, /* 52:53 */ - OP_RXF, /* N */ - OP_RXF, /* CL */ - OP_RXF, /* O */ - OP_RXF, /* X */ - OP_RXF, /* L */ - OP_RXF, /* C */ - OP_RXF, /* A */ - OP_RXF, /* S */ - OP_RXF, /* M */ - OP_RXF, /* D */ - OP_RX, /* CRC12 */ - OP_RX, /* CRC16 */ - OP_RX, /* STE */ - OP_RXH, /* AHM */ - 0, /* PB - 8/32C */ - OP_RX, /* LRA */ - OP_RX, /* ATL */ - OP_RX, /* ABL */ - OP_RX, /* RTL */ - OP_RX, /* RBL */ - OP_RX, /* LE */ - OP_RX, /* CE */ - OP_RX, /* AE */ - OP_RX, /* SE */ - OP_RX, /* ME */ - OP_RX, /* DE */ - 0, 0, /* 6E:6F */ - OP_RX | OP_DPF, /* STD */ - OP_RX, /* SME */ - OP_RX, /* LME */ - OP_RX, /* LHL */ - OP_RX, /* TBT */ - OP_RX, /* SBT */ - OP_RX, /* RBT */ - OP_RX, /* CBT */ - OP_RX | OP_DPF, /* LD */ - OP_RX | OP_DPF, /* CD */ - OP_RX | OP_DPF, /* AD */ - OP_RX | OP_DPF, /* SD */ - OP_RX | OP_DPF, /* MD */ - OP_RX | OP_DPF, /* DD */ - OP_RX | OP_DPF, /* STMD */ - OP_RX | OP_DPF, /* LMD */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 80:8F */ - 0, 0, 0, 0, 0, 0, 0, 0, - OP_NO, /* SRHLS */ - OP_NO, /* SLHLS */ - OP_NO, /* STBR */ - OP_NO, /* LDBR */ - OP_NO, /* EXBR */ - OP_NO | OP_PRV, /* EPSR */ - OP_RR | OP_PRV, /* WBR */ - OP_RR | OP_PRV, /* RBR */ - OP_RR | OP_PRV, /* WHR */ - OP_RR | OP_PRV, /* RHR */ - OP_RR | OP_PRV, /* WDR */ - OP_RR | OP_PRV, /* RDR */ - 0, /* 9C */ - OP_RR | OP_PRV, /* SSR */ - OP_RR | OP_PRV, /* OCR */ - 0, /* 9F */ - 0, 0, 0, 0, 0, 0, 0, 0, /* A0:AF */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* B0:BF */ - 0, 0, 0, 0, 0, 0, 0, 0, - OP_RX, /* BXH */ - OP_RX, /* BXLE */ - OP_RXF | OP_PRV, /* LPSW */ - OP_RI1, /* THI */ - OP_RI1, /* NHI */ - OP_RI1, /* CLHI */ - OP_RI1, /* OHI */ - OP_RI1, /* XHI */ - OP_RI1, /* LHI */ - OP_RI1, /* CHI */ - OP_RI1, /* AHI */ - OP_RI1, /* SHI */ - OP_RI1, /* SRHL */ - OP_RI1, /* SLHL */ - OP_RI1, /* SRHA */ - OP_RI1, /* SLHA */ - OP_RX, /* STM */ - OP_RX, /* LM */ - OP_RX, /* STB */ - OP_RX, /* LDB */ - OP_RX, /* CLB */ - OP_RX | OP_PRV, /* AL */ - OP_RXF | OP_PRV, /* WB */ - OP_RXF | OP_PRV, /* RB */ - OP_RX | OP_PRV, /* WH */ - OP_RX | OP_PRV, /* RH */ - OP_RX | OP_PRV, /* WD */ - OP_RX | OP_PRV, /* RD */ - 0, /* DC */ - OP_RX | OP_PRV, /* SS */ - OP_RX | OP_PRV, /* OC */ - 0, /* DF */ - OP_RXH, /* TS */ - OP_RX, /* SVC */ - OP_RI1 | OP_PRV, /* SINT */ - OP_RX | OP_PRV, /* SCP */ - 0, 0, /* E4:E5 */ - OP_RX, /* LA */ - OP_RXF, /* TLATE */ - 0, 0, /* E8:E9 */ - OP_RI1, /* RRL */ - OP_RI1, /* RLL */ - OP_RI1, /* SRL */ - OP_RI1, /* SLL */ - OP_RI1, /* SRA */ - OP_RI1, /* SLA */ - 0, 0, 0, /* F0:F2 */ - OP_RI2, /* TI */ - OP_RI2, /* NI */ - OP_RI2, /* CLI */ - OP_RI2, /* OI */ - OP_RI2, /* XI */ - OP_RI2, /* LI */ - OP_RI2, /* CI */ - OP_RI2, /* AI */ - OP_RI2, /* SI */ - 0, 0, 0, 0 }; /* FC:FF */ - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifiers list -*/ - -DIB cpu_dib = { d_DS, -1, v_DS, NULL, &display }; - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX | UNIT_BINK, MAXMEMSIZE32) }; - -REG cpu_reg[] = { - { HRDATA (PC, PC, 20) }, - { HRDATA (OPC, oPC, 20), REG_HRO }, - { HRDATA (R0, GREG[0], 32) }, - { HRDATA (R1, GREG[1], 32) }, - { HRDATA (R2, GREG[2], 32) }, - { HRDATA (R3, GREG[3], 32) }, - { HRDATA (R4, GREG[4], 32) }, - { HRDATA (R5, GREG[5], 32) }, - { HRDATA (R6, GREG[6], 32) }, - { HRDATA (R7, GREG[7], 32) }, - { HRDATA (R8, GREG[8], 32) }, - { HRDATA (R9, GREG[9], 32) }, - { HRDATA (R10, GREG[10], 32) }, - { HRDATA (R11, GREG[11], 32) }, - { HRDATA (R12, GREG[12], 32) }, - { HRDATA (R13, GREG[13], 32) }, - { HRDATA (R14, GREG[14], 32) }, - { HRDATA (R15, GREG[15], 32) }, - { HRDATA (FR0, F[0], 32) }, - { HRDATA (FR2, F[1], 32) }, - { HRDATA (FR4, F[2], 32) }, - { HRDATA (FR6, F[3], 32) }, - { HRDATA (FR8, F[4], 32) }, - { HRDATA (FR10, F[5], 32) }, - { HRDATA (FR12, F[6], 32) }, - { HRDATA (FR14, F[7], 32) }, - { HRDATA (D0H, D[0].h, 32) }, - { HRDATA (D0L, D[0].l, 32) }, - { HRDATA (D2H, D[1].h, 32) }, - { HRDATA (D2L, D[1].l, 32) }, - { HRDATA (D4H, D[2].h, 32) }, - { HRDATA (D4L, D[2].l, 32) }, - { HRDATA (D6H, D[3].h, 32) }, - { HRDATA (D6L, D[3].l, 32) }, - { HRDATA (D8H, D[4].h, 32) }, - { HRDATA (D8L, D[4].l, 32) }, - { HRDATA (D10H, D[5].h, 32) }, - { HRDATA (D10L, D[5].l, 32) }, - { HRDATA (D12L, D[6].l, 32) }, - { HRDATA (D12H, D[6].h, 32) }, - { HRDATA (D14H, D[7].h, 32) }, - { HRDATA (D14L, D[7].l, 32) }, - { HRDATA (PSW, PSW, 16) }, - { HRDATA (CC, PSW, 4) }, - { HRDATA (SR, SR, 32) }, - { HRDATA (DR, DR, 32) }, - { HRDATA (DRX, DRX, 8) }, - { FLDATA (DRMOD, drmod, 0) }, - { FLDATA (SRPOS, srpos, 0) }, - { HRDATA (DRPOS, drpos, 3) }, - { BRDATA (IRQ, int_req, 16, 32, INTSZ) }, - { BRDATA (IEN, int_enb, 16, 32, INTSZ) }, - { BRDATA (MACREG, mac_reg, 16, 32, MAC_LNT) }, - { HRDATA (MACSTA, mac_sta, 5) }, - { HRDATA (QEVENT, qevent, 4), REG_HRO }, - { FLDATA (STOP_INST, stop_inst, 0) }, - { FLDATA (STOP_WAIT, stop_wait, 0) }, - { BRDATA (PCQ, pcq, 16, 20, PCQ_SIZE), REG_RO+REG_CIRC }, - { HRDATA (PCQP, pcq_p, 6), REG_HRO }, - { HRDATA (WRU, sim_int_char, 8) }, - { HRDATA (DBGLOG, cpu_log, 16), REG_HIDDEN }, - { HRDATA (BLKIOD, blk_io.dfl, 16), REG_HRO }, - { HRDATA (BLKIOC, blk_io.cur, 20), REG_HRO }, - { HRDATA (BLKIOE, blk_io.end, 20), REG_HRO }, - { BRDATA (GREG, GREG, 16, 32, 16 * NRSETS) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size }, - { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size }, - { UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size }, - { UNIT_MSIZE, 524288, NULL, "512K", &cpu_set_size }, - { UNIT_MSIZE, 1048756, NULL, "1M", &cpu_set_size }, - { UNIT_TYPE, 0, "7/32, single precision fp", "732", NULL }, - { UNIT_DPFP, UNIT_DPFP, NULL, "DPFP", NULL }, - { UNIT_TYPE, UNIT_DPFP, "7/32, double precision fp", NULL, NULL }, - { UNIT_TYPE, UNIT_DPFP | UNIT_832, "8/32", "832", NULL }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT", - &cpu_set_consint, NULL, NULL }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 16, 20, 1, 16, 8, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL, - &cpu_dib, 0 }; - -t_stat sim_instr (void) -{ -volatile uint32 cc; /* set before setjmp */ -t_stat reason; /* set after setjmp */ -int abortval; - -/* Restore register state */ - -if (devtab_init ()) return SCPE_STOP; /* check conflicts */ -if (cpu_unit.flags & (UNIT_DPFP | UNIT_832)) { - fp_in_hwre = 1; /* fp in hwre */ - dec_flgs = 0; } /* all instr ok */ -else { fp_in_hwre = 0; /* fp in ucode */ - dec_flgs = OP_DPF; } /* sp only */ -int_eval (); /* eval interrupts */ -cc = newPSW (PSW & PSW_MASK); /* split PSW, eval wait */ -sim_rtcn_init (lfc_unit.wait, TMR_LFC); /* init clock */ -sim_rtcn_init (pic_unit.wait, TMR_PIC); /* init timer */ -sim_rtcn_init (pas_unit.wait, TMR_PAS); /* init pas */ -reason = 0; - -/* Abort handling - - If an abort occurs in memory protection, the relocation routine - executes a longjmp to this area OUTSIDE the main simulation loop. - Memory protection errors are the only sources of aborts in the - Interdata 32b systems. All referenced variables must be globals, - and all sim_instr scoped automatic variables must be volatile or - set after the call on setjmp. -*/ - -abortval = setjmp (save_env); /* set abort hdlr */ -if (abortval != 0) { /* mem mgt abort? */ - qevent = qevent | EV_MAC; /* set MAC intr */ - if (cpu_unit.flags & UNIT_832) PC = oPC; } /* 832? restore PC */ - -/* Event handling */ - -while (reason == 0) { /* loop until halted */ -uint32 dev, drom, opnd, inc, lim, bufa; -uint32 op, r1, r1p1, r2, rx2, ea; -uint32 mpy, mpc, dvr; -uint32 i, rslt, rlo, t; -int32 sr, st; - -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; - int_eval (); } - -if (qevent) { /* any events? */ - if (qevent & EV_MAC) { /* MAC interrupt? */ - qevent = 0; /* clr all events */ - cc = exception (MPRPSW, cc, 0); /* take exception */ - int_eval (); /* re-eval intr */ - continue; } - - if (qevent & EV_BLK) { /* block I/O in prog? */ - dev = blk_io.dfl & DEV_MAX; /* get device */ - cc = dev_tab[dev] (dev, IO_SS, 0) & 0xF; /* sense status */ - if (cc == STA_BSY) { /* just busy? */ - sim_interval = 0; /* force I/O event */ - continue; } - else if (cc == 0) { /* ready, no err? */ - if (blk_io.dfl & BL_RD) { /* read? */ - t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */ - if ((t == 0) && (blk_io.dfl & BL_LZ)) continue; - blk_io.dfl = blk_io.dfl & ~BL_LZ; /* non-zero seen */ - WriteB (blk_io.cur, t, VW); } /* write mem */ - else { /* write */ - t = ReadB (blk_io.cur, VR); /* read mem */ - dev_tab[dev] (dev, IO_WD, t); } /* put byte */ - if (blk_io.cur != blk_io.end) { /* more to do? */ - blk_io.cur = (blk_io.cur + 1) & VAMASK; /* incr addr */ - continue; } } - qevent = qevent & ~EV_BLK; /* clr blk I/O flag */ - int_eval (); /* re-eval intr */ - continue; } - - if ((qevent & EV_INT) && (PSW & PSW_EXI)) { /* interrupt? */ - dev = int_getdev (); /* get int dev */ - cc = int_auto (dev, cc); /* do auto intr */ - int_eval (); /* re-eval intr */ - continue; } - - if (PSW & PSW_WAIT) { /* wait state? */ - t = sim_qcount (); /* events in queue */ - if ((t == 0) || ((t == 1) && stop_wait)) /* empty, or kbd only? */ - reason = STOP_WAIT; /* then stop */ - else sim_interval = 0; /* force check */ - continue; } - - qevent = 0; } /* no events */ - -/* Instruction fetch and decode */ - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - -sim_interval = sim_interval - 1; - -t = ReadH (oPC = PC, VE); /* fetch instr */ -op = (t >> 8) & 0xFF; /* extract op,R1,R2 */ -r1 = (t >> 4) & 0xF; -r2 = t & 0xF; -drom = decrom[op]; /* get decode flags */ -if ((drom == 0) || (drom & dec_flgs)) { /* not in model? */ - if (stop_inst) reason = STOP_RSRV; /* stop or */ - else cc = exception (ILOPSW, cc, 0); /* exception */ - continue; } -if ((drom & OP_PRV) && (PSW & PSW_PRO)) { /* priv & protected? */ - cc = exception (ILOPSW, cc, 0); /* exception */ - continue; } - -switch (drom & OP_MASK) { /* decode instruction */ -case OP_NO: /* no operand */ - opnd = r2; /* assume short */ - PC = (PC + 2) & VAMASK; /* increment PC */ - break; -case OP_RR: /* reg-reg */ - ea = opnd = R[r2]; /* operand is R2 */ - PC = (PC + 2) & VAMASK; /* increment PC */ - break; -case OP_RI1: /* reg-imm 1 */ - t = ReadH ((PC + 2) & VAMASK, VE); /* fetch immed */ - opnd = SEXT16 (t); /* sign extend */ - if (r2) opnd = (opnd + R[r2]) & DMASK32; /* index calculation */ - PC = (PC + 4) & VAMASK; /* increment PC */ - break; -case OP_RI2: /* reg-imm 2 */ - t = ReadH ((PC + 2) & VAMASK, VE); /* fetch imm hi */ - opnd = t << 16; /* shift to place */ - t = ReadH ((PC + 4) & VAMASK, VE); /* fetch imm lo */ - opnd = opnd | t; /* complete imm */ - if (r2) opnd = (opnd + R[r2]) & DMASK32; /* index calculation */ - PC = (PC + 6) & VAMASK; /* increment PC */ - break; -case OP_RX: case OP_RXH: case OP_RXF: /* reg-mem */ - t = ReadH ((PC + 2) & VAMASK, VE); /* fetch addr */ - if ((t & 0xC000) == 0) { /* displacement? */ - PC = (PC + 4) & VAMASK; /* increment PC */ - ea = t; } /* abs 14b displ */ - else if (t & 0x8000) { /* relative? */ - PC = (PC + 4) & VAMASK; /* increment PC */ - ea = PC + SEXT15 (t); } /* add to incr PC */ - else { /* absolute */ - rx2 = (t >> 8) & 0xF; /* get second index */ - ea = (t & 0xFF) << 16; /* shift to place */ - t = ReadH ((PC + 4) & VAMASK, VE); /* fetch addr lo */ - ea = ea | t; /* finish addr */ - if (rx2) ea = ea + R[rx2]; /* index calc 2 */ - PC = (PC + 6) & VAMASK; } /* increment PC */ - if (r2) ea = ea + R[r2]; /* index calculation */ - ea = ea & VAMASK; - if ((drom & OP_MASK) == OP_RXF) /* get fw operand? */ - opnd = ReadF (ea, VR); /* read fullword */ - else if ((drom & OP_MASK) == OP_RXH) { /* get hw operand? */ - t = ReadH (ea, VR); /* read halfword */ - opnd = SEXT16 (t); } /* sign extend */ - else opnd = ea; /* for sloppy code */ - break; -case OP_UNDEF: - return SCPE_IERR; } -if (qevent & EV_MAC) continue; /* MAC abort on fetch? */ -switch (op) { /* case on opcode */ - -/* Load/store instructions */ - -case 0x08: /* LR - RR */ -case 0x24: /* LIS - NO */ -case 0x48: /* LH - RXH */ -case 0x58: /* L - RXF */ -case 0xC8: /* LHI - RI1 */ -case 0xF8: /* LI - RI2 */ - R[r1] = opnd; /* load operand */ - CC_GL_32 (R[r1]); /* set G,L */ - break; - -case 0x73: /* LHL - RX */ - R[r1] = ReadH (ea, VR); /* get op, zero ext */ - CC_GL_32 (R[r1]); /* set G, L */ - break; - -case 0x25: /* LCS - NO */ - R[r1] = NEG (opnd); /* load complement */ - CC_GL_32 (R[r1]); /* set G,L */ - break; - -case 0xE6: /* LA - RX */ - R[r1] = ea; /* load addr */ - break; - -case 0x63: /* LRA - RX */ - cc = RelocT (R[r1] & VAMASK, ea, VR, &R[r1]); /* test reloc */ - break; - -case 0x40: /* STH - RX */ - WriteH (ea, R[r1], VW); /* store register */ - break; - -case 0x50: /* ST - RX */ - WriteF (ea, R[r1], VW); /* store register */ - break; - -case 0xD1: /* LM - RX */ - for ( ; r1 <= 0xF; r1++) { /* loop thru reg */ - R[r1] = ReadF (ea, VR); /* load register */ - ea = (ea + 4) & VAMASK; } /* incr mem addr */ - break; - -case 0xD0: /* STM - RX */ - for ( ; r1 <= 0xF; r1++) { /* loop thru reg */ - WriteF (ea, R[r1], VW); /* store register */ - ea = (ea + 4) & VAMASK; } /* incr mem addr */ - break; - -case 0xE0: /* TS - RXH */ - CC_GL_16 (opnd); /* set cc's */ - WriteH (ea, opnd | SIGN16, VW); /* set MSB */ - break; - -case 0x93: /* LDBR - NO */ - R[r1] = R[r2] & DMASK8; /* load byte */ - break; -case 0xD3: /* LDB - RX */ - R[r1] = ReadB (ea, VR); /* load byte */ - break; - -case 0x92: /* STBR - NO */ - R[r2] = (R[r2] & ~DMASK8) | (R[r1] & DMASK8); /* store byte */ - break; -case 0xD2: /* STB - RX */ - WriteB (ea, R[r1], VW); /* store byte */ - break; - -case 0x34: /* EXHR - NO */ - R[r1] = ((R[r2] >> 16) & DMASK16) | ((R[r2] & DMASK16) << 16); - break; - -case 0x94: /* EXBR - NO */ - R[r1] = (R[r1] & ~DMASK16) | - ((R[r2] >> 8) & DMASK8) | ((R[r2] & DMASK8) << 8); - break; - -/* Control instructions */ - -case 0x01: /* BALR - RR */ -case 0x41: /* BAL - RX */ - PCQ_ENTRY; /* save old PC */ - R[r1] = PC; /* save cur PC */ - PC = ea; /* branch */ - break; - -case 0x02: /* BTCR - RR */ -case 0x42: /* BTC - RX */ - if (cc & r1) { /* test CC's */ - PCQ_ENTRY; /* branch if true */ - PC = ea; } - break; - -case 0x20: /* BTBS - NO */ - if (cc & r1) { /* test CC's */ - PCQ_ENTRY; /* branch if true */ - PC = (oPC - r2 - r2) & VAMASK; } - break; - -case 0x21: /* BTFS - NO */ - if (cc & r1) { /* test CC's */ - PCQ_ENTRY; /* branch if true */ - PC = (oPC + r2 + r2) & VAMASK; } - break; - -case 0x03: /* BFCR - RR */ -case 0x43: /* BFC - RX */ - if ((cc & r1) == 0) { /* test CC's */ - PCQ_ENTRY; /* branch if false */ - PC = ea; } - break; - -case 0x22: /* BFBS - NO */ - if ((cc & r1) == 0) { /* test CC's */ - PCQ_ENTRY; /* branch if false */ - PC = (oPC - r2 - r2) & VAMASK; } - break; - -case 0x23: /* BFFS - NO */ - if ((cc & r1) == 0) { /* test CC's */ - PCQ_ENTRY; /* branch if false */ - PC = (oPC + r2 + r2) & VAMASK; } - break; - -case 0xC0: /* BXH - RX */ - inc = R[(r1 + 1) & 0xF]; /* inc = R1 + 1 */ - lim = R[(r1 + 2) & 0xF]; /* lim = R1 + 2 */ - R[r1] = (R[r1] + inc) & DMASK32; /* R1 = R1 + inc */ - if (R[r1] > lim) { /* if R1 > lim */ - PCQ_ENTRY; /* branch */ - PC = ea; } - break; - -case 0xC1: /* BXLE - RS */ - inc = R[(r1 + 1) & 0xF]; /* inc = R1 + 1 */ - lim = R[(r1 + 2) & 0xF]; /* lim = R1 + 2 */ - R[r1] = (R[r1] + inc) & DMASK32; /* R1 = R1 + inc */ - if (R[r1] <= lim) { /* if R1 <= lim */ - PCQ_ENTRY; /* branch */ - PC = ea; } - break; - -/* Logical instructions */ - -case 0x04: /* NR - RR */ -case 0x44: /* NH - RXH */ -case 0x54: /* N - RXF */ -case 0xC4: /* NHI - RI1 */ -case 0xF4: /* NI - RI2 */ - R[r1] = R[r1] & opnd; /* result */ - CC_GL_32 (R[r1]); /* set G,L */ - break; - -case 0x06: /* OR - RR */ -case 0x46: /* OH - RXH */ -case 0x56: /* O - RXF */ -case 0xC6: /* OHI - RI1 */ -case 0xF6: /* OI - RI2 */ - R[r1] = R[r1] | opnd; /* result */ - CC_GL_32 (R[r1]); /* set G,L */ - break; - -case 0x07: /* XR - RR */ -case 0x47: /* XH - RXH */ -case 0x57: /* X - RXF */ -case 0xC7: /* XHI - RI1 */ -case 0xF7: /* XI - RI2 */ - R[r1] = R[r1] ^ opnd; /* result */ - CC_GL_32 (R[r1]); /* set G,L */ - break; - -case 0xC3: /* THI - RI1 */ -case 0xF3: /* TI - RI2 */ - rslt = R[r1] & opnd; /* result */ - CC_GL_32 (rslt); /* set G, L */ - break; - -case 0x05: /* CLR - RR */ -case 0x45: /* CLH - RXH */ -case 0x55: /* CL - RXF */ -case 0xC5: /* CLHI - RI1 */ -case 0xF5: /* CI - RI2 */ - rslt = (R[r1] - opnd) & DMASK32; /* result */ - CC_GL_32 (rslt); /* set G,L */ - if (R[r1] < opnd) cc = cc | CC_C; /* set C if borrow */ - if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN32) cc = cc | CC_V; - break; - -case 0xD4: /* CLB - RX */ - opnd = ReadB (ea, VR); /* get operand */ - t = R[r1] & DMASK8; - rslt = (t - opnd) & DMASK16; /* result */ - CC_GL_16 (rslt); /* set G,L 16b */ - if (t < opnd) cc = cc | CC_C; /* set C if borrow */ - break; - -case 0x12: /* CHVR - RR */ - t = cc & CC_C; /* save C */ - R[r1] = (SEXT16 (opnd & DMASK16)) & DMASK32; /* result */ - CC_GL_32 (R[r1]); /* set G, L */ - if (R[r1] != opnd) cc = cc | CC_V; /* wont fit? set V */ - cc = cc | t; /* restore C */ - break; - -/* Shift instructions */ - -case 0xCC: /* SRHL - RI1 */ - opnd = opnd & 0xF; /* shift count */ -case 0x90: /* SRHLS - NO */ - rslt = (R[r1] & DMASK16) >> opnd; /* result */ - CC_GL_16 (rslt); /* set G,L 16b */ - if (opnd && (((R[r1] & DMASK16) >> (opnd - 1)) & 1)) cc = cc | CC_C; - R[r1] = (R[r1] & ~DMASK16) | rslt; /* store result */ - break; - -case 0xCD: /* SLHL - RI1 */ - opnd = opnd & 0xF; /* shift count */ -case 0x91: /* SLHLS - NO */ - rslt = R[r1] << opnd; /* result */ - CC_GL_16 (rslt & DMASK16); /* set G,L 16b */ - if (opnd && (rslt & 0x10000)) cc = cc | CC_C; /* set C if shft out */ - R[r1] = (R[r1] & ~DMASK16) | (rslt & DMASK16); /* store result */ - break; - -case 0xCE: /* SRHA - RI1 */ - opnd = opnd & 0xF; /* shift count */ - rslt = (SEXT16 (R[r1]) >> opnd) & DMASK16; /* result */ - CC_GL_16 (rslt); /* set G,L 16b */ - if (opnd && ((R[r1] >> (opnd - 1)) & 1)) cc = cc | CC_C; - R[r1] = (R[r1] & ~DMASK16) | rslt; /* store result */ - break; - -case 0xCF: /* SLHA - RI1 */ - opnd = opnd & 0xF; /* shift count */ - rslt = R[r1] << opnd; /* raw result */ - R[r1] = (R[r1] & ~MMASK16) | (rslt & MMASK16); - CC_GL_16 (R[r1] & DMASK16); /* set G,L 16b */ - if (opnd && (rslt & SIGN16)) cc = cc | CC_C; /* set C if shft out */ - break; - -case 0xEC: /* SRL - RI1 */ - opnd = opnd & 0x1F; /* shift count */ -case 0x10: /* SRLS - NO */ - rslt = R[r1] >> opnd; /* result */ - CC_GL_32 (rslt); /* set G,L */ - if (opnd && ((R[r1] >> (opnd - 1)) & 1)) cc = cc | CC_C; - R[r1] = rslt; /* store result */ - break; - -case 0xED: /* SLL - RI1 */ - opnd = opnd & 0x1F; /* shift count */ -case 0x11: /* SLLS - NO */ - rslt = (R[r1] << opnd) & DMASK32; /* result */ - CC_GL_32 (rslt); /* set G,L */ - if (opnd && ((R[r1] << (opnd - 1)) & SIGN32)) cc = cc | CC_C; - R[r1] = rslt; /* store result */ - break; - -case 0xEE: /* SRA - RI1 */ - opnd = opnd & 0x1F; /* shift count */ - rslt = (SEXT32 (R[r1]) >> opnd) & DMASK32; /* result */ - CC_GL_32 (rslt); /* set G,L */ - if (opnd && ((R[r1] >> (opnd - 1)) & 1)) cc = cc | CC_C; - R[r1] = rslt; /* store result */ - break; - -case 0xEF: /* SLA - RI1 */ - opnd = opnd & 0x1F; /* shift count */ - rslt = (R[r1] << opnd) & DMASK32; /* raw result */ - R[r1] = (R[r1] & SIGN32) | (rslt & MMASK32); /* arith result */ - CC_GL_32 (R[r1]); /* set G,L */ - if (opnd && (rslt & SIGN32)) cc = cc | CC_C; /* set C if shft out */ - break; - -case 0xEA: /* RRL - RI1 */ - opnd = opnd & 0x1F; /* shift count */ - if (opnd) R[r1] = (R[r1] >> opnd) | /* if cnt > 0 */ - ((R[r1] << (32 - opnd)) & DMASK32); /* rotate */ - CC_GL_32 (R[r1]); /* set G,L */ - break; - -case 0xEB: /* RLL - RI1 */ - opnd = opnd & 0x1F; /* shift count */ - if (opnd) R[r1] = ((R[r1] << opnd) & DMASK32) | /* if cnt > 0 */ - (R[r1] >> (32 - opnd)); /* rotate */ - CC_GL_32 (R[r1]); /* set G,L */ - break; - -/* Bit instructions */ - -case 0x74: /* TBT - RX */ - t = 1u << (15 - (R[r1] & 0xF)); /* bit mask in HW */ - ea = (ea + ((R[r1] >> 3) & ~1)) & VAMASK; /* HW location */ - opnd = ReadH (ea, VR); /* read HW */ - if (opnd & t) cc = CC_G; /* test bit */ - else cc = 0; - break; - -case 0x75: /* SBT - RX */ - t = 1u << (15 - (R[r1] & 0xF)); /* bit mask in HW */ - ea = (ea + ((R[r1] >> 3) & ~1)) & VAMASK; /* HW location */ - opnd = ReadH (ea, VR); /* read HW */ - WriteH (ea, opnd | t, VW); /* set bit, rewr */ - if (opnd & t) cc = CC_G; /* test bit */ - else cc = 0; - break; - -case 0x76: /* RBT - RX */ - t = 1u << (15 - (R[r1] & 0xF)); /* bit mask in HW */ - ea = (ea + ((R[r1] >> 3) & ~1)) & VAMASK; /* HW location */ - opnd = ReadH (ea, VR); /* read HW */ - WriteH (ea, opnd & ~t, VW); /* clr bit, rewr */ - if (opnd & t) cc = CC_G; /* test bit */ - else cc = 0; - break; - -case 0x77: /* CBT - RX */ - t = 1u << (15 - (R[r1] & 0xF)); /* bit mask in HW */ - ea = (ea + ((R[r1] >> 3) & ~1)) & VAMASK; /* HW location */ - opnd = ReadH (ea, VR); /* read HW */ - WriteH (ea, opnd ^ t, VW); /* com bit, rewr */ - if (opnd & t) cc = CC_G; /* test bit */ - else cc = 0; - break; - -/* Arithmetic instructions */ - -case 0x0A: /* AR - RR */ -case 0x26: /* AIS - NO */ -case 0x4A: /* AH - RXH */ -case 0x5A: /* A - RXF */ -case 0xCA: /* AHI - RI1 */ -case 0xFA: /* AI - RI2 */ - rslt = (R[r1] + opnd) & DMASK32; /* result */ - CC_GL_32 (rslt); /* set G,L */ - if (rslt < opnd) cc = cc | CC_C; /* set C if carry */ - if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN32) cc = cc | CC_V; - R[r1] = rslt; - break; - -case 0x51: /* AM - RXF */ - rslt = (R[r1] + opnd) & DMASK32; /* result */ - WriteF (ea, rslt, VW); /* write result */ - CC_GL_32 (rslt); /* set G,L */ - if (rslt < opnd) cc = cc | CC_C; /* set C if carry */ - if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN32) cc = cc | CC_V; - break; - -case 0x61: /* AHM - RXH */ - rslt = (R[r1] + opnd) & DMASK16; /* result */ - WriteH (ea, rslt, VW); /* write result */ - CC_GL_16 (rslt); /* set G,L 16b */ - if (rslt < (opnd & DMASK16)) cc = cc | CC_C; /* set C if carry */ - if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN16) cc = cc | CC_V; - break; - -case 0x0B: /* SR - RR */ -case 0x27: /* SIS - NO */ -case 0x4B: /* SH - RXH */ -case 0x5B: /* S - RXF */ -case 0xCB: /* SHI - RI1 */ -case 0xFB: /* SI - RI2 */ - rslt = (R[r1] - opnd) & DMASK32; /* result */ - CC_GL_32 (rslt); /* set G,L */ - if (R[r1] < opnd) cc = cc | CC_C; /* set C if borrow */ - if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN32) cc = cc | CC_V; - R[r1] = rslt; - break; - -case 0x09: /* CR - RR */ -case 0x49: /* CH - RXH */ -case 0x59: /* C - RXF */ -case 0xC9: /* CHI - RI1 */ -case 0xF9: /* CI - RI2 */ - if (R[r1] == opnd) cc = 0; /* =? */ - else if ((R[r1] ^ opnd) & SIGN32) /* unlike signs? */ - cc = (R[r1] & SIGN32)? (CC_C | CC_L): CC_G; - else cc = (R[r1] > opnd)? CC_G: (CC_C | CC_L); /* like signs */ - if (((R[r1] ^ opnd) & (~opnd ^ (R[r1] - opnd))) & SIGN32) - cc = cc | CC_V; - break; - -case 0x0C: /* MHR - RR */ -case 0x4C: /* MH - RXH */ - R[r1] = (SEXT16 (R[r1]) * SEXT16 (opnd)) & DMASK32; /* multiply */ - break; - -case 0x1C: /* MR - RR */ -case 0x5C: /* M - RXF */ - r1p1 = (r1 + 1) & 0xF; - mpc = ABS (opnd); /* |mpcnd| */ - mpy = ABS (R[r1p1]); /* |mplyr| */ - rslt = rlo = 0; /* clr result */ - for (i = 0; i < 32; i++) { /* develop 32b */ - t = 0; /* no cout */ - if (mpy & 1) { /* cond add */ - rslt = (rslt + mpc) & DMASK32; - if (rslt < mpc) t = SIGN32; } - rlo = (rlo >> 1) | ((rslt & 1) << 31); /* shift result */ - rslt = (rslt >> 1) | t; - mpy = mpy >> 1; } /* shift mpylr */ - if ((opnd ^ R[r1p1]) & SIGN32) { - DNEG (rslt, rlo); } - R[r1] = rslt; /* store result */ - R[r1p1] = rlo; - break; - -case 0x0D: /* DHR - RR */ -case 0x4D: /* DH - RXH */ - r1p1 = (r1 + 1) & 0xF; - opnd = opnd & DMASK16; /* force HW opnd */ - if (opnd) { /* if divisor != 0 */ - st = SEXT32 (R[r1]) / SEXT16 (opnd); /* quotient */ - sr = SEXT32 (R[r1]) % SEXT16 (opnd); } /* remainder */ - if (opnd && (st < 0x8000) && (st >= -0x8000)) { /* if quo fits */ - R[r1] = sr & DMASK32; /* store remainder */ - R[r1p1] = st & DMASK32; } /* store quotient */ - else if (PSW & PSW_AFI) /* div fault enabled? */ - cc = exception (AFIPSW, cc, 0); /* exception */ - break; - -case 0x1D: /* DR - RR */ -case 0x5D: /* D - RXF */ - r1p1 = (r1 + 1) & 0xF; - rslt = R[r1]; /* get dividend */ - rlo = R[r1p1]; - if (R[r1] & SIGN32) { DNEG (rslt, rlo); } /* |divd| */ - dvr = ABS (opnd); /* |divr| */ - if (rslt < dvr) { /* will div work? */ - uint32 quos = R[r1] ^ opnd; /* expected sign */ - for (i = t = 0; i < 32; i++) { /* 32 iterations */ - rslt = ((rslt << 1) & DMASK32) | /* shift divd */ - ((rlo >> 31) & 1); - rlo = (rlo << 1) & DMASK32; - t = (t << 1) & DMASK32; /* shift quo */ - if (rslt >= dvr) { /* subtract work? */ - rslt = rslt - dvr; /* divd -= divr */ - t = t | 1; } } /* set quo bit */ - if (quos & SIGN32) t = NEG (t); /* res -? neg quo */ - if (R[r1] & SIGN32) rslt = NEG (rslt); /* adj rem sign */ - if (t && ((t ^ quos) & SIGN32)) { /* res sign wrong? */ - if (PSW & PSW_AFI) /* if enabled, */ - cc = exception (AFIPSW, cc, 0); /* exception */ - break; } - R[r1] = rslt; /* store rem */ - R[r1p1] = t; } /* store quo */ - else if (PSW & PSW_AFI) /* div fault enabled? */ - cc = exception (AFIPSW, cc, 0); /* exception */ - break; - -/* Floating point instructions */ - -case 0x28: /* LER - NO */ -case 0x38: /* LDR - NO */ -case 0x68: /* LE - RX */ -case 0x78: /* LD - RX */ - cc = f_l (op, r1, r2, ea); /* load */ - if ((cc & CC_V) && (PSW & PSW_AFI)) /* V set? */ - cc = exception (AFIPSW, cc, 1); - break; - -case 0x29: /* CER - NO */ -case 0x39: /* CDR - NO */ -case 0x69: /* CE - RX */ -case 0x79: /* CD - RX */ - cc = f_c (op, r1, r2, ea); /* compare */ - break; - -case 0x2A: /* AER - NO */ -case 0x2B: /* SER - NO */ -case 0x3A: /* ADR - NO */ -case 0x3B: /* SDR - NO */ -case 0x6A: /* AE - RX */ -case 0x6B: /* SE - RX */ -case 0x7A: /* AD - RX */ -case 0x7B: /* SD - RX */ - cc = f_as (op, r1, r2, ea); /* add/sub */ - if ((cc & CC_V) && (PSW & PSW_AFI)) /* V set? */ - cc = exception (AFIPSW, cc, 1); - break; - -case 0x2C: /* MER - NO */ -case 0x3C: /* MDR - NO */ -case 0x6C: /* ME - RX */ -case 0x7C: /* MD - RX */ - cc = f_m (op, r1, r2, ea); /* multiply */ - if ((cc & CC_V) && (PSW & PSW_AFI)) /* V set? */ - cc = exception (AFIPSW, cc, 1); - break; - -case 0x2D: /* DER - NO */ -case 0x3D: /* DDR - NO */ -case 0x6D: /* DE - RX */ -case 0x7D: /* DD - RX */ - cc = f_d (op, r1, r2, ea); /* perform divide */ - if ((cc & CC_V) && (PSW & PSW_AFI)) /* V set? */ - cc = exception (AFIPSW, cc, 1); - break; - -case 0x2E: /* FXR - NO */ -case 0x3E: /* FXDR - NO */ - cc = f_fix32 (op, r1, r2); /* cvt to integer */ - break; - -case 0x2F: /* FLR - NO */ -case 0x3F: /* FLDR - NO */ - cc = f_flt32 (op, r1, r2); /* cvt to floating */ - break; - -case 0x60: /* STE - RX */ - t = ReadFReg (r1); /* get sp reg */ - WriteF (ea, t, VW); /* write */ - break; - -case 0x70: /* STD - RX */ - WriteF (ea, D[r1 >> 1].h, VW); /* write hi */ - WriteF ((ea + 4) & VAMASK, D[r1 >> 1].l, VW); /* write lo */ - break; - -case 0x71: /* STME - RX */ - for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */ - t = ReadFReg (r1); /* get sp reg */ - WriteF (ea, t, VW); /* write */ - ea = (ea + 4) & VAMASK; } /* incr mem addr */ - break; - -case 0x72: /* LME - RX */ - for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */ - t = ReadF (ea, VR); /* get value */ - WriteFReg (r1, t); /* write reg */ - ea = (ea + 4) & VAMASK; } /* incr mem addr */ - break; - -case 0x7E: /* STMD - RX */ - for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */ - WriteF (ea, D[r1 >> 1].h, VW); /* write register */ - WriteF ((ea + 4) & VAMASK, D[r1 >> 1].l, VW); - ea = (ea + 8) & VAMASK; } /* incr mem addr */ - break; - -case 0x7F: /* LMD - RX */ - for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */ - D[r1 >> 1].h = ReadF (ea, VR); /* load register */ - D[r1 >> 1].l = ReadF ((ea + 4) & VAMASK, VR); - ea = (ea + 8) & VAMASK; } /* incr mem addr */ - break; - -/* Miscellaneous */ - -case 0xE1: /* SVC - RX */ - PCQ_ENTRY; /* effective branch */ - t = BUILD_PSW (cc); /* save PSW */ - cc = newPSW (ReadF (SVNPS32, P)); /* get new PSW */ - R[13] = ea & 0xFFFFFF; /* parameter */ - R[14] = t; /* old PSW */ - R[15] = PC; /* old PC */ - PC = ReadH (SVNPC + r1 + r1, P); /* new PC */ - if (DBG_LOG (LOG_CPU_C)) fprintf (sim_log, - ">>SVC: oPC = %X, oPSW = %X, nPC = %X, nPSW = %X\n", - pcq[pcq_p], t, PC, PSW); - break; - -case 0xE2: /* SINT - RI1 */ - dev = opnd & DEV_MAX; /* get dev */ - cc = int_auto (dev, cc); /* auto int */ - int_eval (); - break; - -case 0xE3: /* SCP - RX */ - opnd = ReadH (ea, VR); /* zero ext operand */ - if (opnd & CCW32_B1) t = ea + CCB32_B1C; /* point to buf */ - else t = ea + CCB32_B0C; - sr = ReadH (t & VAMASK, VR); /* get count */ - sr = SEXT16 (sr); /* sign extend */ - if (sr <= 0) { /* <= 0? */ - bufa = ReadF ((t + 2) & VAMASK, VR); /* get buf end */ - if (opnd & CCW32_WR) /* write? */ - R[r1] = ReadB ((bufa + sr) & VAMASK, VR); /* R1 gets mem */ - else WriteB ((bufa + sr) & VAMASK, R[r1], VW); /* read, R1 to mem */ - sr = sr + 1; /* inc count */ - CC_GL_32 (sr & DMASK32); /* set cc's */ - WriteH (t & VAMASK, sr, VW); /* rewrite */ - if ((sr > 0) && !(opnd & CCW32_FST)) /* buf switch? */ - WriteH (ea, opnd ^ CCW32_B1, VW); /* flip CCW bit */ - } /* end if */ - else cc = CC_V; - break; - -case 0x18: /* LPSWR - RR */ - PCQ_ENTRY; /* effective branch */ - PC = R[(r2 + 1) & 0xF] & VAMASK; /* new PC (old reg set) */ - if (DBG_LOG (LOG_CPU_C)) fprintf (sim_log, - ">>LPSWR: oPC = %X, oPSW = %X, nPC = %X, nPSW = %X\n", - pcq[pcq_p], BUILD_PSW (cc), PC, opnd); - cc = newPSW (opnd); /* new PSW */ - if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */ - break; - -case 0xC2: /* LPSW - RXF */ - PCQ_ENTRY; /* effective branch */ - PC = ReadF ((ea + 4) & VAMASK, VR) & VAMASK; /* new PC */ - if (DBG_LOG (LOG_CPU_C)) fprintf (sim_log, - ">>LPSW: oPC = %X, oPSW = %X, nPC = %X, nPSW = %X\n", - pcq[pcq_p], BUILD_PSW (cc), PC, opnd); - cc = newPSW (opnd); /* new PSW */ - if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */ - break; - -case 0x95: /* EPSR - NO */ - R[r1] = BUILD_PSW (cc); /* save PSW */ - cc = newPSW (R[r2]); /* load new PSW */ - if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */ - break; - -case 0x64: /* ATL - RX */ -case 0x65: /* ABL - RX */ - cc = addtoq (ea, R[r1], op & 1); /* add to q */ - break; - -case 0x66: /* RTL - RX */ -case 0x67: /* RBL - RX */ - cc = remfmq (ea, r1, op & 1); /* rem from q */ - break; - -case 0x5E: /* CRC12 - RXH */ - opnd = ReadH (ea, VR); /* zero ext opnd */ - t = (R[r1] & 0x3F) ^ opnd; - for (i = 0; i < 6; i++) { - if (t & 1) t = (t >> 1) ^ 0x0F01; - else t = t >> 1; } - WriteH (ea, t, VW); - break; - -case 0x5F: /* CRC16 - RXH */ - opnd = ReadH (ea, VR); /* zero ext opnd */ - t = (R[r1] & 0xFF) ^ opnd; - for (i = 0; i < 8; i++) { - if (t & 1) t = (t >> 1) ^ 0xA001; - else t = t >> 1; } - WriteH (ea, t, VW); - break; - -case 0xE7: /* TLATE - RXF */ - t = (opnd + ((R[r1] & DMASK8) << 1)) & VAMASK; /* table entry */ - rslt = ReadH (t, VR); /* get entry */ - if (rslt & SIGN16) R[r1] = rslt & DMASK8; /* direct xlate? */ - else { PCQ_ENTRY; /* branch */ - PC = rslt << 1; } - break; - -/* I/O instructions */ - -case 0xDE: /* OC - RX */ - opnd = ReadB (ea, VR); /* fetch operand */ -case 0x9E: /* OCR - RR */ - dev = R[r1] & DEV_MAX; - if (DEV_ACC (dev)) { - dev_tab[dev] (dev, IO_ADR, 0); /* select */ - dev_tab[dev] (dev, IO_OC, opnd & DMASK8); /* send command */ - cc = 0; } - else cc = CC_V; - int_eval (); /* re-eval intr */ - break; - -case 0xDA: /* WD - RX */ - opnd = ReadB (ea, VR); /* fetch operand */ -case 0x9A: /* WDR - RR */ - dev = R[r1] & DEV_MAX; - if (DEV_ACC (dev)) { - dev_tab[dev] (dev, IO_ADR, 0); /* select */ - dev_tab[dev] (dev, IO_WD, opnd & DMASK8); /* send data */ - cc = 0; } - else cc = CC_V; - int_eval (); /* re-eval intr */ - break; - -case 0xD8: /* WH - RX */ - opnd = ReadH (ea, VR); /* fetch operand */ -case 0x98: /* WHR - RR */ - dev = R[r1] & DEV_MAX; - if (DEV_ACC (dev)) { - if (dev_tab[dev] (dev, IO_ADR, 0)) /* select; hw ok? */ - dev_tab[dev] (dev, IO_WH, opnd & DMASK16); /* send data */ - else { /* byte only */ - dev_tab[dev] (dev, IO_WD, (opnd >> 8) & DMASK8); /* hi */ - dev_tab[dev] (dev, IO_WD, opnd & DMASK8); } /* send lo byte */ - cc = 0; } - else cc = CC_V; - int_eval (); /* re-eval intr */ - break; - -case 0x9B: /* RDR - RR */ -case 0xDB: /* RD - RX */ - dev = R[r1] & DEV_MAX; - if (DEV_ACC (dev)) { /* dev exist? */ - dev_tab[dev] (dev, IO_ADR, 0); /* select */ - t = dev_tab[dev] (dev, IO_RD, 0); /* get data */ - cc = 0; } - else { /* no */ - t = 0; - cc = CC_V; } - if (OP_TYPE (op) != OP_RR) WriteB (ea, t, VW); /* RX or RR? */ - else R[r2] = t & DMASK8; - int_eval (); /* re-eval intr */ - break; - -case 0x99: /* RHR - RR */ -case 0xD9: /* RH - RS */ - dev = R[r1] & DEV_MAX; - if (DEV_ACC (dev)) { /* dev exist? */ - if (dev_tab[dev] (dev, IO_ADR, 0)) /* select, hw ok? */ - t = dev_tab[dev] (dev, IO_RH, 0); /* get data */ - else { /* byte only */ - rslt = dev_tab[dev] (dev, IO_RD, 0); /* get byte */ - t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */ - t = (rslt << 8) | t; } /* merge */ - cc = 0; } - else { /* no */ - t = 0; - cc = CC_V; } - if (OP_TYPE (op) != OP_RR) WriteH (ea, t, VW); /* RX or RR? */ - else R[r2] = t & DMASK16; - int_eval (); /* re-eval intr */ - break; - -case 0x9D: /* SSR - RR */ -case 0xDD: /* SS - RS */ - dev = R[r1] & DEV_MAX; - if (DEV_ACC (dev)) { /* dev exist? */ - dev_tab[dev] (dev, IO_ADR, 0); /* select */ - t = dev_tab[dev] (dev, IO_SS, 0); } /* get status */ - else t = STA_EX; /* no */ - if (OP_TYPE (op) != OP_RR) WriteB (ea, t, VW); /* RX or RR? */ - else R[r2] = t & DMASK8; - cc = t & 0xF; - int_eval (); /* re-eval intr */ - break; - -/* Block I/O instructions - - On a real Interdata system, the block I/O instructions can't be - interrupted or stopped. To model this behavior, while allowing - the instructions to go back through fetch for I/O processing and - WRU testing, the simulator implements a 'block I/O in progress' - flag and status block. If a block I/O is in progress, normal - interrupts and fetches are suppressed until the block I/O is done. -*/ - -case 0x96: /* WBR - RR */ -case 0xD6: /* WB - RXF */ - dev = R[r1] & DEV_MAX; - if (DEV_ACC (dev)) { /* dev exist? */ - if (OP_TYPE (op) != OP_RR) - lim = ReadF ((ea + 4) & VAMASK, VR); - else lim = R[(r2 + 1) & 0xF]; - if (opnd > lim) cc = 0; /* start > end? */ - else { /* no, start I/O */ - dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ - blk_io.dfl = dev; /* set status block */ - blk_io.cur = opnd; - blk_io.end = lim; - qevent = qevent | EV_BLK; } } /* I/O in prog */ - else cc = CC_V; /* nx dev */ - break; - -case 0x97: /* RBR - RR */ -case 0xD7: /* RB - RXF */ - dev = R[r1] & DEV_MAX; - if (DEV_ACC (dev)) { /* dev exist? */ - if (OP_TYPE (op) != OP_RR) - lim = ReadF ((ea + 4) & VAMASK, VR); - else lim = R[(r2 + 1) & 0xF]; - if (opnd > lim) cc = 0; /* start > end? */ - else { /* no, start I/O */ - dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ - blk_io.dfl = dev | BL_RD; /* set status block */ - blk_io.cur = opnd; - blk_io.end = lim; - qevent = qevent | EV_BLK; } } /* I/O in prog */ - else cc = CC_V; /* nx dev */ - break; - -case 0xD5: /* AL - RX */ - dev = ReadB (AL_DEV, P); /* get device */ - t = ReadB (AL_IOC, P); /* get command */ - if (DEV_ACC (dev)) { /* dev exist? */ - if (AL_BUF > ea) cc = 0; /* start > end? */ - else { /* no, start I/O */ - dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ - dev_tab[dev] (dev, IO_OC, t); /* start dev */ - blk_io.dfl = dev | BL_RD | BL_LZ; /* set status block */ - blk_io.cur = AL_BUF; - blk_io.end = ea; - qevent = qevent | EV_BLK; } } /* I/O in prog */ - else cc = CC_V; /* nx dev */ - break; } /* end switch */ - } /* end while */ - -/* Simulation halted */ - -PSW = BUILD_PSW (cc); -PC = PC & VAMASK; -set_r_display (R); -pcq_r->qptr = pcq_p; /* update pc q ptr */ -return reason; -} - -/* Load new PSW */ - -uint32 newPSW (uint32 val) -{ -uint32 rs = PSW_GETREG (val); /* register set */ - -R = &GREG[rs * 16]; /* set register set */ -PSW = val & PSW_MASK; /* store PSW */ -int_eval (); /* update intreq */ -if (PSW & PSW_WAIT) qevent = qevent | EV_WAIT; /* wait state? */ -else qevent = qevent & ~EV_WAIT; -if (PSW & PSW_EXI) SET_ENB (v_DS); /* enable/disable */ -else CLR_ENB (v_DS); /* console intr */ -return PSW & CC_MASK; -} - -/* Exception handler - 7/32 always uses register set 0 */ - -uint32 exception (uint32 loc, uint32 cc, uint32 flg) -{ -int32 oldPSW = BUILD_PSW (cc); /* save old PSW */ -int32 oldPC = PC; /* save old PC */ - -cc = newPSW (ReadF (loc, P)); /* new PSW */ -PC = ReadF (loc + 4, P) & VAMASK; /* new PC */ -if (cpu_unit.flags & UNIT_832) { /* 8/32? */ - R[14] = oldPSW; /* PSW to new 14 */ - R[15] = oldPC; } /* PC to new 15 */ -else { GREG[14] = oldPSW; /* 7/32, PSW to set 0 14 */ - GREG[15] = oldPC; } /* PC to set 0 15 */ -if (DBG_LOG (LOG_CPU_C)) fprintf (sim_log, - ">>Exc %X: oPC = %X, oPSW = %X, nPC = %X, nPSW = %X\n", - loc, oldPC, oldPSW, PC, PSW | cc | flg); -return cc | flg; /* return CC */ -} - -/* Test for queue interrupts - system queue addresses are physical */ - -uint32 testsysq (uint32 cc) -{ -int32 qb = ReadF (SQP, P); /* get sys q addr */ -int32 usd = ReadH (qb + Q32_USD, P); /* get use count */ - -if (usd) { /* entries? */ - cc = exception (SQTPSW, cc, 0); /* take sysq exc */ - if (cpu_unit.flags & UNIT_832) R[13] = qb; /* R13 = sys q addr */ - else GREG[13] = qb; } -return cc; -} - -/* Add to queue */ - -uint32 addtoq (uint32 ea, uint32 val, uint32 flg) -{ -uint32 slt, usd, wra, t; - -t = ReadF (ea, VR); /* slots/used */ -slt = (t >> 16) & DMASK16; /* # slots */ -usd = t & DMASK16; /* # used */ -if (usd >= slt) return CC_V; /* list full? */ -usd = (usd + 1) & DMASK16; /* inc # used */ -WriteH (ea + Q32_USD, usd, VW); /* rewrite */ -if (flg) { /* ABL? */ - wra = ReadH ((ea + Q32_BOT) & VAMASK, VR); /* get bottom */ - t = wra + 1; /* adv bottom */ - if (t >= slt) t = 0; /* wrap if necc */ - WriteH ((ea + Q32_BOT) & VAMASK, t, VW); } /* rewrite bottom */ -else { wra = ReadH ((ea + Q32_TOP) & VAMASK, VR); /* ATL, get top */ - if (wra == 0) wra = (slt - 1) & DMASK16; /* wrap if necc */ - else wra = wra - 1; /* dec top */ - WriteH ((ea + Q32_TOP) & VAMASK, wra, VW); } /* rewrite top */ -WriteF ((ea + Q32_BASE + (wra * Q32_SLNT)) & VAMASK, val, VW); /* write slot */ -return 0; -} - -/* Remove from queue */ - -uint32 remfmq (uint32 ea, uint32 r1, uint32 flg) -{ -uint32 slt, usd, rda, t; - -t = ReadF (ea, VR); /* get slots/used */ -slt = (t >> 16) & DMASK16; /* # slots */ -usd = t & DMASK16; /* # used */ -if (usd == 0) return CC_V; /* empty? */ -usd = usd - 1; /* dec used */ -WriteH (ea + Q32_USD, usd, VW); /* rewrite */ -if (flg) { /* RBL? */ - rda = ReadH ((ea + Q32_BOT) & VAMASK, VR); /* get bottom */ - if (rda == 0) rda = (slt - 1) & DMASK16; /* wrap if necc */ - else rda = rda - 1; /* dec bottom */ - WriteH ((ea + Q32_BOT) & VAMASK, rda, VW); } /* rewrite bottom */ -else { rda = ReadH ((ea + Q32_TOP) & VAMASK, VR); /* RTL, get top */ - t = rda + 1; /* adv top */ - if (t >= slt) t = 0; /* wrap if necc */ - WriteH ((ea + Q32_TOP) & VAMASK, t, VW); } /* rewrite top */ -R[r1] = ReadF ((ea + Q32_BASE + (rda * Q32_SLNT)) & VAMASK, VR); /* read slot */ -if (usd) return CC_G; -else return 0; -} - -/* Automatic interrupt processing */ - -uint32 int_auto (uint32 dev, uint32 cc) -{ -uint32 addr, vec, by, ccw, ccwa, ccwb; -uint32 i, hw, tblad, tblen, bufe, st, t; -int32 bufc; -uint32 oldPSW = BUILD_PSW (cc); - -vec = ReadH (INTSVT + dev + dev, P); /* get vector */ -newPSW (0x2800); /* new PSW */ -R[0] = oldPSW; /* save old PSW */ -R[1] = PC; /* save PC */ -R[2] = dev; /* set dev # */ -if (DBG_LOG (LOG_CPU_C)) fprintf (sim_log, - ">>Int %X: oPC = %X, oPSW = %X, nPC = %X, nPSW = %X\n", - dev, PC, oldPSW, vec, 0x2800); -if (DEV_ACC (dev)) { /* dev exist? */ - hw = dev_tab[dev] (dev, IO_ADR, 0); /* select, get hw */ - R[3] = st = dev_tab[dev] (dev, IO_SS, 0); } /* sense status */ -else { hw = 0; - R[3] = CC_V; } -if ((vec & 1) == 0) { /* immed int? */ - PC = vec; /* new PC */ - return PSW & CC_MASK; } /* exit */ -R[4] = ccwa = vec & ~1; /* save CCW addr */ -ccw = ReadH (ccwa, VR); /* read CCW */ -if ((ccw & CCW32_EXE) == 0) { /* exec clr? */ - PC = ReadH (ccwa + CCB32_SUB, VR); /* get subr */ - return 0; } /* CC = 0 */ -if (!DEV_ACC (dev) || (st & CCW32_STA (ccw))) { /* bad status? */ - PC = ReadH (ccwa + CCB32_SUB, VR); /* get subr */ - return CC_L; } /* CC = L */ -if (ccw & CCW32_FST) { /* fast mode? */ - t = ReadH (ccwa + CCB32_B0C, VR); /* get count */ - bufc = SEXT16 (t); /* sign ext */ - if (bufc <= 0) { /* still valid? */ - bufe = ReadF (ccwa + CCB32_B0E, VR); /* get end addr */ - addr = (bufe + bufc) & VAMASK; - if (hw) { /* halfword? */ - if (ccw & CCW32_WR) { /* write? */ - t = ReadH (addr, VR); /* get hw */ - dev_tab[dev] (dev, IO_WH, t); } /* send to dev */ - else { /* read */ - t = dev_tab[dev] (dev, IO_RH, 0); /* get hw */ - WriteH (addr, t, VW); } /* write to mem */ - bufc = bufc + 2; } /* adv buf cnt */ - else { /* byte */ - if (ccw & CCW32_WR) { /* write? */ - t = ReadB (addr, VR); /* get byte */ - dev_tab[dev] (dev, IO_WD, t); } /* send to dev */ - else { /* read */ - t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */ - WriteB (addr, t, VW); } /* write to mem */ - bufc = bufc + 1; } /* adv buf cnt */ - WriteH (ccwa + CCB32_B0C, bufc, VW); /* rewrite cnt */ - if (bufc > 0) { - PC = ReadH (ccwa + CCB32_SUB, VR); /* get subr */ - return CC_G; } /* CC = G */ - } /* end if bufc <= 0 */ - } /* end fast */ -else { /* slow mode */ - if (ccw & CCW32_B1) ccwb = ccwa + CCB32_B1C; /* which buf? */ - else ccwb = ccwa + CCB32_B0C; - t = ReadH (ccwb, VR); /* get count */ - bufc = SEXT16 (t); /* sign ext */ - if (bufc <= 0) { /* still valid? */ - bufe = ReadF (ccwb + 2, VR); /* get end addr */ - addr = (bufe + bufc) & VAMASK; - if (ccw & CCW32_WR) { /* write? */ - by = ReadB (addr, VR); /* byte fm mem */ - if (ccw & CCW32_TL) { /* translate? */ - tblad = ReadF (ccwa + CCB32_TAB, VR);/* get tbl addr */ - tblen = (tblad + (by << 1)) & VAMASK; /* tbl entry addr */ - t = ReadH (tblen, VR); /* get tbl entry */ - if ((t & SIGN16) == 0) { /* special xlate? */ - PC = t << 1; /* change PC */ - R[3] = by; /* untrans char */ - return 0; } /* CC = 0 */ - by = t & DMASK8; } /* replace */ - dev_tab[dev] (dev, IO_WD, by); } /* write to dev */ - else { /* read */ - by = dev_tab[dev] (dev, IO_RD, 0); /* get from dev */ - if (ccw & CCW32_TL) { /* translate? */ - tblad = ReadF (ccwa + CCB32_TAB, VR);/* get tbl addr */ - tblen = (tblad + (by << 1)) & VAMASK; /* tbl entry addr */ - t = ReadH (tblen, VR); /* get tbl entry */ - if ((t & SIGN16) == 0) { /* special xlate? */ - PC = t << 1; /* change PC */ - R[3] = by; /* untrans char */ - return 0; } /* CC = 0 */ - WriteB (addr, t, VW); } /* wr trans */ - else WriteB (addr, by, VW); } /* wr orig */ - t = ReadH (ccwa + CCB32_CHK, VR); /* get check wd */ - t = t ^ by; /* start LRC */ - if (ccw & CCW32_CRC) { /* CRC? */ - for (i = 0; i < 8; i++) { - if (t & 1) t = (t >> 1) ^ 0xA001; - else t = t >> 1; } } - WriteH (ccwa + CCB32_CHK, t, VW); /* rewrite chk wd */ - bufc = bufc + 1; /* adv buf cnt */ - WriteH (ccwb, bufc, VW); /* rewrite cnt */ - if (bufc > 0) { /* cnt pos? */ - ccw = ccw ^ CCW32_B1; /* flip buf */ - WriteH (ccwa, ccw, VW); /* rewrite */ - PC = ReadH (ccwa + CCB32_SUB, VR); /* get subr */ - return CC_G; } /* CC = G */ - } /* end if bufc */ - } /* end slow */ -PC = R[1]; /* restore PC */ -return newPSW (R[0]); /* restore PSW, CC */ -} - -/* Display register device */ - -uint32 display (uint32 dev, uint32 op, uint32 dat) -{ -int t; - -switch (op) { -case IO_ADR: /* select */ - if (!drmod) drpos = srpos = 0; /* norm mode? clr */ - return BY; /* byte only */ -case IO_OC: /* command */ - op = op & 0xC0; - if (op == 0x40) { /* x40 = inc */ - drmod = 1; - drpos = srpos = 0; } /* init cntrs */ - else if (op == 0x80) drmod = 0; /* x80 = norm */ - break; -case IO_WD: /* write */ - if (drpos < 4) - DR = (DR & ~(DMASK8 << (drpos * 8))) | (dat << (drpos * 8)); - else if (drpos == 4) DRX = dat; - drpos = (drpos + 1) & 0x7; - break; -case IO_RD: /* read */ - t = (SR >> (srpos * 8)) & DMASK8; - srpos = srpos ^ 1; - return t; -case IO_SS: /* status */ - return 0x80; } -return 0; -} - -/* Relocation and protection */ - -uint32 Reloc (uint32 va, uint32 rel) -{ -uint32 seg, off, mapr, lim; - -seg = VA_GETSEG (va); /* get seg num */ -off = VA_GETOFF (va); /* get offset */ -mapr = mac_reg[seg]; /* get seg reg */ -lim = GET_SRL (mapr); /* get limit */ -if (off >= lim) { /* limit viol? */ - mac_sta = MACS_L; /* set status */ - ABORT (MPRO); } /* abort */ -if ((mapr & SR_PRS) == 0) { /* not present? */ - mac_sta = MACS_NP; /* set status */ - ABORT (MPRO); } /* abort */ -if ((rel == VE) && (mapr & SR_EXP)) { /* exec, prot? */ - mac_sta = MACS_EX; /* set status */ - qevent = qevent | EV_MAC; } /* req intr */ -if ((rel == VW) && (mapr & (SR_WPI | SR_WRP))) { /* write, prot? */ - if (mapr & SR_WRP) { /* write abort? */ - mac_sta = MACS_WP; /* set status */ - ABORT (MPRO); } /* abort */ - else { /* write intr */ - mac_sta = MACS_WI; /* set status */ - qevent = qevent | EV_MAC; } } /* req intr */ -return (off + (mapr & SRF_MASK)) & PAMASK32; /* relocate */ -} - -uint32 RelocT (uint32 va, uint32 base, uint32 rel, uint32 *pa) -{ -uint32 seg, off, mapr, lim; - -seg = VA_GETSEG (va); /* get seg num */ -off = VA_GETOFF (va); /* get offset */ -mapr = ReadF ((base + (seg << 2)) & VAMASK, rel); /* get seg reg */ -lim = GET_SRL (mapr); /* get limit */ -if (off >= lim) return CC_C; /* limit viol? */ -if ((mapr & SR_PRS) == 0) return CC_V; /* not present? */ -*pa = off + (mapr & SRF_MASK); /* translate */ -if (mapr & (SR_WRP | SR_WPI)) return CC_G; /* write prot? */ -if (mapr & SR_EXP) return CC_L; /* exec prot? */ -return 0; /* ok */ -} - -/* Memory interface routines - - ReadB read byte (processor) - ReadH read halfword (processor) - ReadF read fullword (processor) - WriteB write byte (processor) - WriteH write halfword (processor) - WriteF write fullword (processor) - IOReadB read byte (IO) - IOWriteB write byte (IO) -*/ - -uint32 ReadB (uint32 loc, uint32 rel) -{ -uint32 val; -uint32 sc = (3 - (loc & 3)) << 3; - -if ((PSW & PSW_REL) == 0) { /* reloc off? */ - if ((loc & ~03) == MAC_STA) { /* MAC status? */ - val = mac_sta; /* read it */ - qevent = qevent & ~EV_MAC; } /* clr MAC intr */ - else val = M[loc >> 2]; } /* get mem word */ -else if (rel == 0) val = M[loc >> 2]; /* phys ref? */ -else { uint32 pa = Reloc (loc, rel); /* relocate */ - val = M[pa >> 2]; } -return (val >> sc) & DMASK8; -} - -uint32 ReadH (uint32 loc, uint32 rel) -{ -uint32 val; - -if ((PSW & PSW_REL) == 0) { /* reloc off? */ - if ((loc & ~03) == MAC_STA) { /* MAC status? */ - val = mac_sta; /* read it */ - qevent = qevent & ~EV_MAC; } /* clr MAC intr */ - else val = M[loc >> 2]; } /* get mem word */ -else if (rel == 0) val = M[loc >> 2]; /* phys ref? */ -else { uint32 pa = Reloc (loc, rel); /* relocate */ - val = M[pa >> 2]; } -return (val >> ((loc & 2)? 0: 16)) & DMASK16; -} - -uint32 ReadF (uint32 loc, uint32 rel) -{ -uint32 val; - -if ((PSW & PSW_REL) == 0) { /* reloc off? */ - if ((loc & ~03) == MAC_STA) { /* MAC status? */ - val = mac_sta; /* read it */ - qevent = qevent & ~EV_MAC; } /* clr MAC intr */ - else val = M[loc >> 2]; } /* get mem word */ -else if (rel == 0) val = M[loc >> 2]; /* phys ref? */ -else { uint32 pa = Reloc (loc, rel); /* relocate */ - val = M[pa >> 2]; } -return val; -} - -void WriteB (uint32 loc, uint32 val, uint32 rel) -{ -uint32 pa = loc; -uint32 sc = (3 - (loc & 3)) << 3; - -val = val & DMASK8; -if ((PSW & PSW_REL) == 0) { /* reloc off? */ - uint32 idx = (pa - MAC_BASE) >> 2; /* check for MAC */ - if (idx <= MAC_LNT) { - if (idx < MAC_LNT) mac_reg[idx] = - ((mac_reg[idx] & ~(DMASK8 << sc)) | (val << sc)) & SR_MASK; - else { - mac_sta = 0; - qevent = qevent & ~EV_MAC; } } } -else if (rel != 0) pa = Reloc (loc, rel); /* !phys? relocate */ -if (MEM_ADDR_OK (pa)) M[pa >> 2] = - (M[pa >> 2] & ~(DMASK8 << sc)) | (val << sc); -return; -} - -void WriteH (uint32 loc, uint32 val, uint32 rel) -{ -uint32 pa = loc; - -val = val & DMASK16; -if ((PSW & PSW_REL) == 0) { /* reloc off? */ - uint32 idx = (pa - MAC_BASE) >> 2; /* check for MAC */ - if (idx <= MAC_LNT) { - if (idx < MAC_LNT) mac_reg[idx] = ((loc & 2)? - ((mac_reg[idx] & ~DMASK16) | val): - ((mac_reg[idx] & DMASK16) | (val << 16))) & SR_MASK; - else { - mac_sta = 0; - qevent = qevent & ~EV_MAC; } } } -else if (rel != 0) pa = Reloc (loc, rel); /* !phys? relocate */ -if (MEM_ADDR_OK (pa)) M[pa >> 2] = (loc & 2)? - ((M[pa >> 2] & ~DMASK16) | val): - ((M[pa >> 2] & DMASK16) | (val << 16)); -return; -} - -void WriteF (uint32 loc, uint32 val, uint32 rel) -{ -uint32 pa = loc; - -val = val & DMASK32; -if (loc & 2) { - WriteH (loc & VAMASK, (val >> 16) & DMASK16, rel); - WriteH ((loc + 2) & VAMASK, val & DMASK16, rel); - return; } -if ((PSW & PSW_REL) == 0) { /* reloc off? */ - uint32 idx = (pa - MAC_BASE) >> 2; /* check for MAC */ - if (idx <= MAC_LNT) { - if (idx < MAC_LNT) mac_reg[idx] = val & SR_MASK; - else { - mac_sta = 0; - qevent = qevent & ~EV_MAC; } } } -else if (rel != 0) pa = Reloc (loc, rel); /* !phys? relocate */ -if (MEM_ADDR_OK (pa)) M[pa >> 2] = val & DMASK32; -return; -} - -uint32 IOReadB (uint32 loc) -{ -uint32 sc = (3 - (loc & 3)) << 3; - -return (M[loc >> 2] >> sc) & DMASK8; -} - -void IOWriteB (uint32 loc, uint32 val) -{ -uint32 sc = (3 - (loc & 3)) << 3; - -val = val & DMASK8; -M[loc >> 2] = (M[loc >> 2] & ~(DMASK8 << sc)) | (val << sc); -return; -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -qevent = 0; /* no events */ -mac_sta = 0; /* clear MAC */ -newPSW (0); /* PSW = 0 */ -set_r_display (R); -DR = 0; /* clear display */ -drmod = 0; -blk_io.dfl = blk_io.cur = blk_io.end = 0; /* no block I/O */ -sim_brk_types = sim_brk_dflt = SWMASK ('E'); /* init bkpts */ -if (M == NULL) M = calloc (MAXMEMSIZE32 >> 1, sizeof (uint16)); -if (M == NULL) return SCPE_MEM; -pcq_r = find_reg ("PCQ", NULL, dptr); /* init PCQ */ -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -if ((sw & SWMASK ('V')) && (PSW & PSW_REL)) { - int32 cc = RelocT (addr, MAC_BASE, P, &addr); - if (cc & (CC_C | CC_V)) return SCPE_NXM; } -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = IOReadB (addr); -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -if ((sw & SWMASK ('V')) && (PSW & PSW_REL)) { - int32 cc = RelocT (addr, MAC_BASE, P, &addr); - if (cc & (CC_C | CC_V)) return SCPE_NXM; } -if (addr >= MEMSIZE) return SCPE_NXM; -IOWriteB (addr, val & 0xFF); -return SCPE_OK; -} - -/* Change memory size */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -uint32 mc = 0; -uint32 i; - -if ((val <= 0) || (val > MAXMEMSIZE32) || ((val & 0xFFFF) != 0)) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i = i + 4) mc = mc | M[i >> 2]; -if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_OK; -MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE32; i = i + 4) M[i >> 2] = 0; -return SCPE_OK; -} - -/* Set current R pointers for SCP */ - -void set_r_display (uint32 *rbase) -{ -extern REG *find_reg (char *cptr, char **optr, DEVICE *dptr); -REG *rptr; -int32 i; - -rptr = find_reg ("R0", NULL, &cpu_dev); -if (rptr == NULL) return; -for (i = 0; i < 16; i++, rptr++) rptr->loc = (void *) (rbase + i); -return; -} - -/* Set console interrupt */ - -t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (PSW & PSW_EXI) SET_INT (v_DS); -return SCPE_OK; -} diff --git a/Interdata/id32_dboot.c b/Interdata/id32_dboot.c deleted file mode 100644 index 69215974..00000000 --- a/Interdata/id32_dboot.c +++ /dev/null @@ -1,317 +0,0 @@ -/* id32_dboot.c: Interdata 32b simulator disk bootstrap - - Copyright (c) 2000-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 17-Feb-03 RMS Fixed for UNIX bootstrap, upper platter bootstrap -*/ - -#include "id_defs.h" - -#define DBOOT_BEG 0x1000 -#define DBOOT_START 0x100E -#define DBOOT_LEN (sizeof (dboot_rom) / sizeof (uint8)) - -/* Transcribed from 32b Bootstrap Loader, 03-074N81R03A13 */ - -static uint8 dboot_rom[] = { - 0xca, 0xf0, 0x00, 0x30, - 0xc5, 0xf0, 0x00, 0x3a, - 0x02, 0x8e, - 0x26, 0xf7, - 0x03, 0x0e, - 0xe6, 0xd0, 0x0f, 0x30, - 0xd1, 0xe0, 0x00, 0x78, - 0xd0, 0xed, 0x03, 0x40, - 0xd3, 0xf0, 0x00, 0x7e, - 0xc4, 0xf0, 0x00, 0x0f, - 0x41, 0xed, 0x00, 0xd0, - 0xd2, 0xfd, 0x03, 0x25, - 0xd3, 0xf0, 0x00, 0x7f, - 0x10, 0xf4, - 0x41, 0xed, 0x00, 0xd0, - 0xd2, 0xfd, 0x03, 0x26, - 0xd3, 0xf0, 0x00, 0x7f, - 0xc4, 0xf0, 0x00, 0x0f, - 0x41, 0xed, 0x00, 0xd0, - 0xd2, 0xfd, 0x03, 0x27, - 0xd3, 0x20, 0x00, 0x7d, - 0xd3, 0x30, 0x00, 0x7c, - 0xd3, 0x40, 0x00, 0x7a, - 0x24, 0x50, - 0xd3, 0xf0, 0x00, 0x7b, - 0xcb, 0xf0, 0x00, 0x33, - 0x23, 0x23, - 0x11, 0xf1, - 0x08, 0x5f, - 0xe6, 0x7d, 0x03, 0x50, - 0xe6, 0x8d, 0x04, 0x4f, - 0x07, 0xcc, - 0x41, 0xed, 0x01, 0xfc, - 0xd1, 0xed, 0x03, 0x5c, - 0xd0, 0xed, 0x03, 0x48, - 0x58, 0xcd, 0x03, 0x58, - 0x43, 0x3d, 0x01, 0x9c, - 0xe6, 0x7d, 0x03, 0x50, - 0x41, 0xed, 0x01, 0xfc, - 0xe6, 0xed, 0x03, 0x54, - 0x24, 0x15, - 0xf8, 0xf0, 0x4f, 0x53, 0x33, 0x32, - 0xd3, 0x7e, 0x00, 0x24, - 0xc3, 0x70, 0x00, 0x10, - 0x23, 0x3e, - 0xce, 0x70, 0x00, 0xe0, - 0x21, 0xeb, - 0x55, 0xfe, 0x00, 0x00, - 0x21, 0x38, - 0x58, 0x6e, 0x00, 0x08, - 0x10, 0x68, - 0x55, 0x6d, 0x03, 0x24, - 0x44, 0x3d, 0x01, 0xb2, - 0xca, 0xe0, 0x00, 0x30, - 0x27, 0x11, - 0x42, 0x3d, 0x01, 0x66, - 0x58, 0xcd, 0x03, 0x50, - 0x42, 0x3d, 0x01, 0x52, - 0x48, 0x10, 0x00, 0x7e, - 0x42, 0x3d, 0x02, 0xf0, - 0x58, 0xcd, 0x03, 0x48, - 0x43, 0x3d, 0x02, 0xf0, - 0x58, 0x8d, 0x03, 0x4c, - 0x23, 0x07, - 0x58, 0xce, 0x00, 0x0c, - 0x58, 0x8e, 0x00, 0x10, - 0x0b, 0x8c, - 0x26, 0xc1, - 0x11, 0x88, - 0x08, 0x18, - 0xe6, 0xf0, 0x11, 0x18, - 0x58, 0x0f, 0x00, 0x00, - 0x50, 0x01, 0x00, 0x00, - 0x59, 0x01, 0x00, 0x00, - 0x42, 0x3d, 0x03, 0x08, - 0x26, 0xf4, - 0x26, 0x14, - 0xc5, 0xf0, 0x12, 0x78, - 0x20, 0x8c, - 0x08, 0xd8, - 0xcb, 0xd0, 0x01, 0xe8, - 0x03, 0x08, - 0x27, 0x81, - 0x07, 0x77, - 0x41, 0xed, 0x01, 0xfc, - 0xd1, 0xed, 0x03, 0x40, - 0xd0, 0xe0, 0x00, 0x78, - 0x43, 0x00, 0x00, 0x60, - 0xde, 0x2d, 0x03, 0x28, - 0x08, 0x0c, - 0x4d, 0x0d, 0x45, 0x00, 0x03, 0x30, - 0x08, 0x91, - 0x4d, 0x0d, 0x45, 0x00, 0x03, 0x38, - 0x08, 0xa1, - 0x08, 0xb0, - 0x08, 0x55, - 0x42, 0x2d, 0x02, 0x4a, - 0xde, 0x3d, 0x03, 0x28, - 0x9d, 0x3f, - 0x22, 0x21, - 0x9d, 0x4f, - 0x42, 0x1d, 0x02, 0xf4, - 0xc3, 0xf0, 0x00, 0x10, - 0x20, 0x35, - 0x11, 0xa5, - 0x06, 0xba, - 0x98, 0x49, - 0xde, 0x4d, 0x03, 0x2b, - 0x9d, 0x3f, - 0x22, 0x21, - 0x9d, 0x4f, - 0x42, 0x7d, 0x02, 0xf8, - 0x20, 0x83, - 0x41, 0x6d, 0x02, 0x96, - 0x22, 0x0b, - 0x9d, 0x4f, - 0xc3, 0xf0, 0x00, 0x19, - 0x42, 0x3d, 0x02, 0xfc, - 0xde, 0x4d, 0x03, 0x2c, - 0x9d, 0x3f, - 0x22, 0x21, - 0x98, 0x49, - 0xde, 0x4d, 0x03, 0x2e, - 0x9d, 0x3f, - 0x22, 0x21, - 0xde, 0x4d, 0x03, 0x2d, - 0x9d, 0x3f, - 0x22, 0x21, - 0x98, 0x4a, - 0xde, 0x4d, 0x03, 0x2f, - 0x0d, 0x3f, - 0x22, 0x21, - 0xde, 0x4d, 0x03, 0x2b, - 0x9d, 0x3f, - 0x22, 0x21, - 0x9d, 0x4f, - 0x20, 0x81, - 0xc3, 0xf0, 0x00, 0x53, - 0x42, 0x3d, 0x03, 0x00, - 0x08, 0xfa, - 0x11, 0xfa, - 0x06, 0xf9, - 0xe6, 0x6d, 0x02, 0x54, - 0x34, 0x77, - 0x9a, 0x27, - 0x34, 0x77, - 0x98, 0x27, - 0x34, 0x88, - 0x9a, 0x28, - 0x34, 0x88, - 0x98, 0x28, - 0x08, 0x55, - 0x21, 0x24, - 0x98, 0x49, - 0x9a, 0x3b, - 0x23, 0x03, - 0x9a, 0x3b, - 0x98, 0x3f, - 0xde, 0x3d, 0x03, 0x2a, - 0xde, 0x2d, 0x03, 0x29, - 0x9d, 0x2f, - 0x20, 0x81, - 0xde, 0x2d, 0x03, 0x28, - 0x9b, 0x20, - 0x99, 0x21, - 0x34, 0x00, - 0x06, 0x01, - 0xde, 0x2d, 0x03, 0x28, - 0x9d, 0x3f, - 0x22, 0x21, - 0x42, 0x1d, 0x03, 0x04, - 0xc3, 0xf0, 0x00, 0x10, - 0x03, 0x3e, - 0x0b, 0x07, - 0x26, 0x04, - 0xc4, 0x00, 0xff, 0x00, - 0x0a, 0x70, - 0x26, 0x91, - 0x07, 0xaa, - 0x07, 0xbb, - 0x03, 0x06, - 0x24, 0x11, - 0x23, 0x0c, - 0x24, 0x12, - 0x23, 0x0a, - 0x24, 0x13, - 0x23, 0x08, - 0x24, 0x14, - 0x23, 0x06, - 0x24, 0x15, - 0x23, 0x04, - 0x24, 0x16, - 0x23, 0x02, - 0x24, 0x17, - 0x24, 0x01, - 0xde, 0x0d, 0x03, 0x28, - 0x9a, 0x01, - 0xde, 0x0d, 0x03, 0x28, - 0xd1, 0xed, 0x03, 0x40, - 0xd0, 0xe0, 0x00, 0x78, - 0x11, 0x0f, - 0x95, 0x10, - 0x22, 0x01, - 0x00, 0x00, 0x00, 0x00, - 0x48, 0x30, - 0xc1, 0xc2, - 0xc8, 0xc4, - 0xd0, 0xe0, - 0x00, 0x30, - 0x01, 0x90, - 0x01, 0x40, - 0x04, 0xc0, - 0x00, 0x18, - 0x00, 0x14, - 0x00, 0x40, - 0x00, 0x40, - 0x00 -}; - -/* Lower memory setup - - 78 = binary input device address - 79 = binary device input command - 7A = disk device number - 7B = device code - 7C = disk controller address - 7D = selector channel address - 7E:7F = operating system extension (user specified) -*/ - -struct dboot_id { - char *name; - uint32 sw; - uint32 cap; - uint32 dtype; - uint32 offset; - uint32 adder; -}; - -static struct dboot_id dboot_tab[] = { - { "DP", 0, 2, 0x31, o_DP0, 0 }, - { "DP", SWMASK ('F'), 9, 0x32, o_DP0, o_DPF }, - { "DP", 0, 9, 0x33, o_DP0, 0 }, - { "DM", 0, 64, 0x35, o_ID0, 0 }, - { "DM", 0, 244, 0x36, o_ID0, 0 }, - { NULL } }; - -t_stat id_dboot (int32 u, DEVICE *dptr) -{ -extern DIB ttp_dib, sch_dib; -extern uint32 PC; -extern int32 sim_switches; -uint32 i, typ, ctlno, off, add, cap, sch_dev; -UNIT *uptr; - -DIB *ddib = (DIB *) dptr->ctxt; /* get disk DIB */ -ctlno = ddib->dno; /* get ctrl devno */ -sch_dev = sch_dib.dno + ddib->sch; /* sch dev # */ -uptr = dptr->units + u; /* get capacity */ -cap = uptr->capac >> 20; -for (i = typ = 0; dboot_tab[i].name != NULL; i++) { - if ((strcmp (dboot_tab[i].name, dptr->name) == 0) && - ((dboot_tab[i].sw == 0) || (dboot_tab[i].sw & sim_switches)) && - (dboot_tab[i].cap == cap)) { - typ = dboot_tab[i].dtype; - off = dboot_tab[i].offset; - add = dboot_tab[i].adder; - break; } } -if (typ == 0) return SCPE_NOFNC; - -IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */ -IOWriteB (AL_DEV, ttp_dib.dno); /* bin input dev */ -IOWriteB (AL_IOC, 0xa3); -IOWriteB (AL_DSKU, ctlno + ((u + 1) * off) + add); /* disk dev addr */ -IOWriteB (AL_DSKT, typ); /* disk type */ -IOWriteB (AL_DSKC, ctlno); /* disk ctl addr */ -IOWriteB (AL_SCH, sch_dev); -PC = DBOOT_START; -return SCPE_OK; -} diff --git a/Interdata/id32_sys.c b/Interdata/id32_sys.c deleted file mode 100644 index 40ba1399..00000000 --- a/Interdata/id32_sys.c +++ /dev/null @@ -1,699 +0,0 @@ -/* id32_sys.c: Interdata 32b simulator interface - - Copyright (c) 2000-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 15-Jul-03 RMS Fixed signed/unsigned bug in get_imm - 27-Feb-03 RMS Added relative addressing support - 23-Dec-01 RMS Cloned from ID4 sources -*/ - -#include "id_defs.h" -#include - -#define MSK_SBF 0x0100 -#define SEXT15(x) (((x) & 0x4000)? ((x) | ~0x3FFF): ((x) & 0x3FFF)) - -extern DEVICE cpu_dev; -extern DEVICE sch_dev; -extern DEVICE pt_dev; -extern DEVICE tt_dev, ttp_dev; -extern DEVICE pas_dev, pasl_dev; -extern DEVICE lpt_dev; -extern DEVICE pic_dev, lfc_dev; -extern DEVICE dp_dev, idc_dev; -extern DEVICE fd_dev, mt_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern uint32 *M; - -t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val, t_bool cf); -t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf); -extern t_stat lp_load (FILE *fileref, char *cptr, char *fnam); -extern pt_dump (FILE *of, char *cptr, char *fnam); - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "Interdata 32b"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 6; - -DEVICE *sim_devices[] = { - &cpu_dev, - &sch_dev, - &pt_dev, - &tt_dev, - &ttp_dev, - &pas_dev, - &pasl_dev, - &pic_dev, - &lfc_dev, - &lpt_dev, - &dp_dev, - &idc_dev, - &fd_dev, - &mt_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Reserved instruction", - "HALT instruction", - "Breakpoint", - "Wait state", - "Runaway VFU" }; - -/* Binary loader -- load carriage control tape - Binary dump -- paper tape dump */ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -if (flag) return pt_dump (fileref, cptr, fnam); -return lp_load (fileref, cptr, fnam); -} - -/* Symbol tables */ - -#define I_V_FL 16 /* class bits */ -#define I_M_FL 0xF /* class mask */ -#define I_V_MR 0x0 /* mask-register */ -#define I_V_RR 0x1 /* register-register */ -#define I_V_R 0x2 /* register */ -#define I_V_MX 0x3 /* mask-memory */ -#define I_V_RX 0x4 /* register-memory */ -#define I_V_X 0x5 /* memory */ -#define I_V_FF 0x6 /* float reg-reg */ -#define I_V_FX 0x7 /* float reg-mem */ -#define I_V_SI 0x8 /* short immed */ -#define I_V_SB 0x9 /* short branch */ -#define I_V_SX 0xA /* short ext branch */ -#define I_V_RI 0xB /* halfword imm */ -#define I_V_RF 0xC /* fullword imm */ -#define I_MR (I_V_MR << I_V_FL) -#define I_RR (I_V_RR << I_V_FL) -#define I_R (I_V_R << I_V_FL) -#define I_MX (I_V_MX << I_V_FL) -#define I_RX (I_V_RX << I_V_FL) -#define I_X (I_V_X << I_V_FL) -#define I_FF (I_V_FF << I_V_FL) -#define I_FX (I_V_FX << I_V_FL) -#define I_SI (I_V_SI << I_V_FL) -#define I_SB (I_V_SB << I_V_FL) -#define I_SX (I_V_SX << I_V_FL) -#define I_RI (I_V_RI << I_V_FL) -#define I_RF (I_V_RF << I_V_FL) - -#define R_X 0 /* no R1 */ -#define R_M 1 /* R1 mask */ -#define R_R 2 /* R1 int reg */ -#define R_F 3 /* R1 flt reg */ - -static const int32 masks[] = { - 0xFF00, 0xFF00, 0xFFF0, 0xFF00, - 0xFF00, 0xFFF0, 0xFF00, 0xFF00, - 0xFF00, 0xFE00, 0xFEF0, 0xFF00, - 0xFF00 }; - -static const uint32 r1_type[] = { - R_M, R_R, R_X, R_M, - R_R, R_X, R_F, R_F, - R_R, R_M, R_X, R_R, - R_R }; - -static const uint32 r2_type[] = { - R_X, R_R, R_R, R_X, - R_X, R_X, R_F, R_X, - R_M, R_X, R_X, R_X, - R_X }; - -static const char *opcode[] = { -"BER", "BNER","BZR", "BNZR", -"BPR", "BNPR","BLR", "BNLR", -"BMR", "BNMR","BOR", "BNOR", -"BCR", "BNCR","BR", -"BES", "BNES","BZS", "BNZS", -"BPS", "BNPS","BLS", "BNLS", -"BMS", "BNMS","BOS", "BNOS", -"BCS", "BNCS","BS", -"BE", "BNE", "BZ", "BNZ", -"BP", "BNP", "BL", "BNL", -"BM", "BNM", "BO", "BNO", -"BC", "BNC", "B", - "BALR","BTCR","BFCR", -"NR", "CLR", "OR", "XR", -"LR", "CHR", "AR", "SR", -"MHR", "DHR", -"SRLS","SLLS","CHVR", -"LPSWR", -"MR", "DR", -"BTBS","BTFS","BFBS","BFFS", -"LIS", "LCS", "AIS", "SIS", -"LER", "CER", "AER", "SER", -"MER", "DER", "FXR", "FLR", -"MPBSR", "PBR", -"EXHR", -"LDR", "CDR", "ADR", "SDR", -"MDR", "DDR", "FXDR","FLDR", -"STH", "BAL", "BTC", "BFC", -"NH", "CLH", "OH", "XH", -"LH", "CH", "AH", "SH", -"MH", "DH", -"ST", "AM", -"N", "CL", "O", "X", -"L", "C", "A", "S", -"M", "D", "CRC12","CRC16", -"STE", "AHM", "PB", "LRA", -"ATL", "ABL", "RTL", "RBL", -"LE", "CE", "AE", "SE", -"ME", "DE", -"STD", "STME","LME", "LHL", -"TBT", "SBT", "RBT", "CBT", -"LD", "CD", "AD", "SD", -"MD", "DD", "STMD","LMD", -"SRHLS","SLHLS","STBR","LBR", -"EXBR","EPSR","WBR", "RBR", -"WHR", "RHR", "WDR", "RDR", - "SSR", "OCR", -"BXH", "BXLE","LPSW","THI", -"NHI", "CLHI","OHI", "XHI", -"LHI", "CHI", "AHI", "SHI", -"SRHL","SLHL","SRHA","SLHA", -"STM", "LM", "STB", "LB", -"CLB", "AL", "WB", "RB", -"WH", "RH", "WD", "RD", - "SS", "OC", -"TS", "SVC", "SINT","SCP", - "LA", "TLATE", - "RRL", "RLL", -"SRL", "SLL", "SRA", "SLA", - "TI", -"NI", "CLI", "OI", "XI", -"LI", "CI", "AI", "SI", -NULL }; - -static const uint32 opc_val[] = { -0x0330+I_R, 0x0230+I_R, 0x0330+I_R, 0x0230+I_R, -0x0220+I_R, 0x0320+I_R, 0x0280+I_R, 0x0380+I_R, -0x0210+I_R, 0x0310+I_R, 0x0240+I_R, 0x0340+I_R, -0x0280+I_R, 0x0380+I_R, 0x0300+I_R, -0x2230+I_SX, 0x2030+I_SX, 0x2230+I_SX, 0x2030+I_SX, -0x2020+I_SX, 0x2220+I_SX, 0x2080+I_SX, 0x2280+I_SX, -0x2010+I_SX, 0x2210+I_SX, 0x2040+I_SX, 0x2240+I_SX, -0x2080+I_SX, 0x2280+I_SX, 0x2200+I_SX, -0x4330+I_X, 0x4230+I_X, 0x4330+I_X, 0x4230+I_X, -0x4220+I_X, 0x4320+I_X, 0x4280+I_X, 0x4380+I_X, -0x4210+I_X, 0x4310+I_X, 0x4240+I_X, 0x4340+I_X, -0x4280+I_X, 0x4380+I_X, 0x4300+I_X, - 0x0100+I_RR, 0x0200+I_MR, 0x0300+I_MR, -0x0400+I_RR, 0x0500+I_RR, 0x0600+I_RR, 0x0700+I_RR, -0x0800+I_RR, 0x0900+I_RR, 0x0A00+I_RR, 0x0B00+I_RR, -0x0C00+I_RR, 0x0D00+I_RR, -0x1000+I_SI, 0x1100+I_SI, 0x1200+I_RR, -0x1800+I_RR, -0x1C00+I_RR, 0x1D00+I_RR, -0x2000+I_SB, 0x2100+I_SB, 0x2200+I_SB, 0x2300+I_SB, -0x2400+I_SI, 0x2500+I_SI, 0x2600+I_SI, 0x2700+I_SI, -0x2800+I_FF, 0x2900+I_FF, 0x2A00+I_FF, 0x2B00+I_FF, -0x2C00+I_FF, 0x2D00+I_FF, 0x2E00+I_RR, 0x2F00+I_RR, -0x3000+I_RR, 0x3200+I_RR, -0x3400+I_RR, -0x3800+I_FF, 0x3900+I_FF, 0x3A00+I_FF, 0x3B00+I_FF, -0x3C00+I_FF, 0x3D00+I_FF, 0x3E00+I_RR, 0x3F00+I_RR, -0x4000+I_RX, 0x4100+I_RX, 0x4200+I_MX, 0x4300+I_MX, -0x4400+I_RX, 0x4500+I_RX, 0x4600+I_RX, 0x4700+I_RX, -0x4800+I_RX, 0x4900+I_RX, 0x4A00+I_RX, 0x4B00+I_RX, -0x4C00+I_RX, 0x4D00+I_RX, -0x5000+I_RX, 0x5100+I_RX, -0x5400+I_RX, 0x5500+I_RX, 0x5600+I_RX, 0x5700+I_RX, -0x5800+I_RX, 0x5900+I_RX, 0x5A00+I_RX, 0x5B00+I_RX, -0x5C00+I_RX, 0x5D00+I_RX, 0x5E00+I_RX, 0x5F00+I_RX, -0x6000+I_RX, 0x6100+I_RX, 0x6200+I_RX, 0x6300+I_RX, -0x6400+I_RX, 0x6500+I_RX, 0x6600+I_RX, 0x6700+I_RX, -0x6800+I_FX, 0x6900+I_FX, 0x6A00+I_FX, 0x6B00+I_FX, -0x6C00+I_FX, 0x6D00+I_FX, -0x7000+I_FX, 0x7100+I_FX, 0x7200+I_FX, 0x7300+I_RX, -0x7400+I_RX, 0x7500+I_RX, 0x7600+I_RX, 0x7700+I_RX, -0x7800+I_FX, 0x7900+I_FX, 0x7A00+I_FX, 0x7B00+I_FX, -0x7C00+I_FX, 0x7D00+I_FX, 0x7E00+I_FX, 0x7F00+I_FX, -0x9000+I_SI, 0x9100+I_SI, 0x9200+I_RR, 0x9300+I_RR, -0x9400+I_RR, 0x9500+I_RR, 0x9600+I_RR, 0x9700+I_RR, -0x9800+I_RR, 0x9900+I_RR, 0x9A00+I_RR, 0x9B00+I_RR, - 0x9D00+I_RR, 0x9E00+I_RR, -0xC000+I_RX, 0xC100+I_RX, 0xC200+I_RX, 0xC300+I_RI, -0xC400+I_RI, 0xC500+I_RI, 0xC600+I_RI, 0xC700+I_RI, -0xC800+I_RI, 0xC900+I_RI, 0xCA00+I_RI, 0xCB00+I_RI, -0xCC00+I_RI, 0xCD00+I_RI, 0xCE00+I_RI, 0xCF00+I_RI, -0xD000+I_RX, 0xD100+I_RX, 0xD200+I_RX, 0xD300+I_RX, -0xD400+I_RX, 0xD500+I_X, 0xD600+I_RX, 0xD700+I_RX, -0xD800+I_RX, 0xD900+I_RX, 0xDA00+I_RX, 0xDB00+I_RX, - 0xDD00+I_RX, 0xDE00+I_RX, -0xE000+I_RX, 0xE100+I_RX, 0xE200+I_RI, 0xE300+I_RX, - 0xE600+I_RX, 0xE700+I_RX, - 0xEA00+I_RI, 0xEB00+I_RI, -0xEC00+I_RI, 0xED00+I_RI, 0xEE00+I_RI, 0xEF00+I_RI, - 0xF300+I_RF, -0xF400+I_RF, 0xF500+I_RF, 0xF600+I_RF, 0xF700+I_RF, -0xF800+I_RF, 0xF900+I_RF, 0xFA00+I_RF, 0xFB00+I_RF, -0xFFFF }; - -/* Print an RX specifier */ - -t_stat fprint_addr (FILE *of, t_addr addr, uint32 rx, uint32 ea1, - uint32 ea2, t_bool cf) -{ -uint32 rx2; - -if ((ea1 & 0xC000) == 0) { /* RX1 */ - fprintf (of, "%-X", ea1); - if (rx) fprintf (of, "(R%d)", rx); - return -3; } -if (ea1 & 0x8000) { /* RX2 */ - if (cf) { /* for CPU? */ - ea1 = addr + 4 + SEXT15 (ea1); - fprintf (of, "%-X", ea1 & VAMASK32); } - else { /* for dev */ - int32 disp = SEXT15 (ea1); /* get disp */ - if (disp >= -4) fprintf (of, ".+%-X", disp + 4); - else fprintf (of, ".-%-X", -4 - disp); } - if (rx) fprintf (of, "(R%d)", rx); - return -3; } -rx2 = (ea1 >> 8) & 0xF; -fprintf (of, "%-X", ((ea1 << 16) | ea2) & VAMASK32); -if (rx && !rx2) fprintf (of, "(R%d)", rx); -if (rx2) fprintf (of, "(R%d,R%d)", rx, rx2); -return -5; -} - -#define GETNUM(d,n) for (k = d = 0; k < n; k++) \ - d = (d << 8) | (((uint32) val[vp++]) & 0xFF) - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current PC - *val = values to decode - *uptr = pointer to unit - sw = switches - Outputs: - return = if >= 0, error code - if < 0, number of extra bytes retired -*/ - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 c, k, num, rdx, vp, lnt; -t_stat r; -DEVICE *dptr; - -if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ -dptr = find_dev_from_unit (uptr); /* find dev */ -if (dptr == NULL) return SCPE_IERR; -if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */ -if (sw & SWMASK ('B')) lnt = 1; /* get length */ -else if (sw & SWMASK ('W')) lnt = 2; -else if (sw & SWMASK ('F')) lnt = 4; -else lnt = (uptr == &cpu_unit)? 4: 1; -if (sw & SWMASK ('D')) rdx = 10; /* get radix */ -else if (sw & SWMASK ('O')) rdx = 8; -else if (sw & SWMASK ('H')) rdx = 16; -else rdx = dptr->dradix; -vp = 0; /* init ptr */ -if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */ - if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */ - if ((val[0] & 0x7F) == 0) return SCPE_ARG; - while (vp < lnt) { /* print string */ - if ((c = (uint32) val[vp++] & 0x7F) == 0) break; - fprintf (of, (c < 0x20)? "<%02X>": "%c", c); } - return -(vp - 1); } /* return # chars */ - -if (sw & SWMASK ('M')) { /* inst format? */ - r = fprint_sym_m (of, addr, val, uptr == &cpu_unit); /* decode inst */ - if (r <= 0) return r; /* success? */ - lnt = 2; } /* no, skip 16b */ - -GETNUM (num, lnt); /* get number */ -fprint_val (of, num, rdx, lnt * 8, PV_RZRO); -return -(vp - 1); -} - -/* Symbolic decode for -m - - Inputs: - of = output stream - addr = current PC - *val = values to decode - cf = true if parsing for CPU - Outputs: - return = if >= 0, error code - if < 0, number of extra bytes retired -*/ - -t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val, t_bool cf) -{ -uint32 i, j, k, inst, r1, r2, ea1, ea2, vp; - -vp = 0; -GETNUM (inst,2); /* high 16b */ -GETNUM (ea1, 2); /* next 16b */ -GETNUM (ea2, 2); /* next 16b */ -for (i = 0; opc_val[i] != 0xFFFF; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */ - r1 = (inst >> 4) & 0xF; - r2 = inst & 0xF; - fprintf (of, "%s ", opcode[i]); /* print opcode */ - switch (j) { /* case on class */ - case I_V_MR: /* mask-register */ - fprintf (of, "%-X,R%d", r1, r2); - return -1; - case I_V_RR: /* register-register */ - case I_V_FF: /* floating-floating */ - fprintf (of, "R%d,R%d", r1, r2); - return -1; - case I_V_SI: /* short immediate */ - fprintf (of, "R%d,%-X", r1, r2); - return -1; - case I_V_SB: /* short branch */ - fprintf (of, "%-X,", r1); - case I_V_SX: /* ext short branch */ - if (cf) fprintf (of, "%-X", ((inst & MSK_SBF)? - (addr + r2 + r2): (addr - r2 - r2))); - else fprintf (of, ((inst & MSK_SBF)? - ".+%-X": ".-%X"), r2 + r2); - return -1; - case I_V_R: /* register */ - fprintf (of, "R%d", r2); - return -1; - case I_V_RI: /* reg-immed */ - fprintf (of, "R%d,%-X", r1, ea1); - if (r2) fprintf (of, "(R%d)", r2); - return -3; - case I_V_RF: /* reg-full imm */ - fprintf (of, "R%d,%-X", r1, (ea1 << 16) | ea2); - if (r2) fprintf (of, "(R%d)", r2); - return -5; - case I_V_MX: /* mask-memory */ - fprintf (of, "%-X,", r1); - return fprint_addr (of, addr, r2, ea1, ea2, cf); - case I_V_RX: /* register-memory */ - case I_V_FX: /* floating-memory */ - fprintf (of, "R%d,", r1); - case I_V_X: /* memory */ - return fprint_addr (of, addr, r2, ea1, ea2, cf); } - return SCPE_IERR; } /* end if */ - } /* end for */ -return SCPE_ARG; /* no match */ -} - -/* Register number - - Inputs: - *cptr = pointer to input string - **optr = pointer to pointer to next char - rtype = mask, integer, or float - Outputs: - rnum = output register number, -1 if error -*/ - -int32 get_reg (char *cptr, char **optr, int32 rtype) -{ -int32 reg; - -if ((*cptr == 'R') || (*cptr == 'r')) { /* R? */ - cptr++; /* skip */ - if (rtype == R_M) return -1; } /* cant be mask */ -if ((*cptr >= '0') && (*cptr <= '9')) { - reg = *cptr++ - '0'; - if ((*cptr >= '0') && (*cptr <= '9')) - reg = (reg * 10) + (*cptr - '0'); - else --cptr; - if (reg > 0xF) return -1; } -else if ((*cptr >= 'a') && (*cptr <= 'f')) reg = (*cptr - 'a') + 10; -else if ((*cptr >= 'A') && (*cptr <= 'F')) reg = (*cptr - 'A') + 10; -else return -1; -if ((rtype == R_F) && (reg & 1)) return -1; -*optr = cptr + 1; -return reg; -} - -/* Immediate - - Inputs: - *cptr = pointer to input string - *imm = pointer to output value - *inst = pointer to instruction - max = max value - Outputs: - sta = status -*/ - -t_stat get_imm (char *cptr, uint32 *imm, uint32 *inst, uint32 max) -{ -char *tptr; -int32 idx; - -errno = 0; -*imm = strtoul (cptr, &tptr, 16); /* get immed */ -if (errno || (*imm > max) || (cptr == tptr)) return SCPE_ARG; -if (*tptr == '(') { /* index? */ - if ((idx = get_reg (tptr + 1, &tptr, R_R)) < 0) - return SCPE_ARG; - if (*tptr++ != ')') return SCPE_ARG; - *inst = *inst | idx; } -if (*tptr != 0) return SCPE_ARG; -return SCPE_OK; -} - -/* Address - - Inputs: - *cptr = pointer to input string - **tptr = pointer to moved pointer - *ea = effective address - *rel = relative flag - addr = base address - cf = true if parsing for CPU - Outputs: - status = SCPE_OK if ok, else error code -*/ - -t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_bool *rel, - t_addr addr, t_bool cf) -{ -int32 sign = 1; - -*ea = 0; -if (*cptr == '.') { /* relative? */ - *rel = TRUE; - cptr++; - if (cf) *ea = addr; - if (*cptr == '+') cptr++; /* .+? */ - else if (*cptr == '-') { /* .-? */ - sign = -1; - cptr++; } - else return SCPE_OK; } -else *rel = FALSE; -errno = 0; -*ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16))); -if (errno || (cptr == *tptr)) return SCPE_ARG; -return SCPE_OK; -} - -#define PUTNUM(d,n) for (k = n; k > 0; k--) \ - val[vp++] = (d >> ((k - 1) * 8)) & 0xFF - -/* Symbolic input */ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 k, rdx, lnt, num, vp; -t_stat r; -DEVICE *dptr; -static const uint32 maxv[5] = { 0, 0xFF, 0xFFFF, 0, 0xFFFFFFFF }; - -if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ -dptr = find_dev_from_unit (uptr); /* find dev */ -if (dptr == NULL) return SCPE_IERR; -if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */ -if (sw & SWMASK ('B')) lnt = 1; /* get length */ -else if (sw & SWMASK ('W')) lnt = 2; -else if (sw & SWMASK ('F')) lnt = 4; -else lnt = (uptr == &cpu_unit)? 4: 1; -if (sw & SWMASK ('D')) rdx = 10; /* get radix */ -else if (sw & SWMASK ('O')) rdx = 8; -else if (sw & SWMASK ('H')) rdx = 16; -else rdx = dptr->dradix; -vp = 0; -if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */ - if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */ - if (*cptr == 0) return SCPE_ARG; - while ((vp < lnt) && *cptr) { /* get chars */ - val[vp++] = *cptr++; } - return -(vp - 1); } /* return # chars */ - -r = parse_sym_m (cptr, addr, val, uptr == &cpu_unit); /* try to parse */ -if (r <= 0) return r; - -num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */ -if (r != SCPE_OK) return r; -PUTNUM (num, lnt); /* store */ -return -(lnt - 1); -} - -/* Symbolic input for -m - - Inputs: - *cptr = pointer to input string - addr = current PC - *val = pointer to output values - cf = true if parsing for CPU - Outputs: - status = > 0 error code - <= 0 -number of extra words -*/ - -t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf) -{ -uint32 i, j, k, df, db, t, inst, vp; -int32 st, r1, r2, rx2; -t_stat r; -t_bool rel; -char *tptr, gbuf[CBUFSIZE]; - -vp = 0; -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; -if (opcode[i] == NULL) return SCPE_ARG; -inst = opc_val[i] & 0xFFFF; /* get value */ -j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ -if (r1_type[j]) { /* any R1 field? */ - cptr = get_glyph (cptr, gbuf, ','); /* get R1 field */ - if ((r1 = get_reg (gbuf, &tptr, r1_type[j])) < 0) - return SCPE_ARG; - if (*tptr != 0) return SCPE_ARG; - inst = inst | (r1 << 4); } /* or in R1 */ - -cptr = get_glyph (cptr, gbuf, 0); /* get operand */ -if (*cptr) return SCPE_ARG; /* should be end */ -switch (j) { /* case on class */ - -case I_V_FF: case I_V_SI: /* flt-flt, sh imm */ -case I_V_MR: case I_V_RR: /* mask/reg-register */ -case I_V_R: /* register */ - if ((r2 = get_reg (gbuf, &tptr, r2_type[j])) < 0) - return SCPE_ARG; - if (*tptr != 0) return SCPE_ARG; - inst = inst | r2; /* or in R2 */ - break; - -case I_V_FX: /* float-memory */ -case I_V_MX: case I_V_RX: /* mask/reg-memory */ -case I_V_X: /* memory */ - r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */ - if (r != SCPE_OK) return SCPE_ARG; /* error? */ - rx2 = 0; /* assume no 2nd */ - if (*tptr == '(') { /* index? */ - if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0) - return SCPE_ARG; - inst = inst | r2; /* or in R2 */ - if (*tptr == ',') { /* 2nd index? */ - if ((rx2 = get_reg (tptr + 1, &tptr, R_R)) < 0) - return SCPE_ARG; } - if (*tptr++ != ')') return SCPE_ARG; } /* all done? */ - if (*tptr != 0) return SCPE_ARG; - PUTNUM (inst, 2); /* store inst */ - if (!cf && rel) { /* periph, rel */ - st = t - 4; /* displ */ - if (rx2 || (st > 0x3FFF) || (st < -0x4000)) /* rx2 or too big? */ - return SCPE_ARG; - t = (st & 0x7FFF) | 0x8000; - PUTNUM (t, 2); /* store displ */ - return -3; } - if (rx2 == 0) { /* no 2nd? */ - if (t < 0x4000) { /* RX1? */ - PUTNUM (t, 2); /* store ea */ - return -3; } - st = (t - (addr + 4)); /* displ */ - if (cf && (st <= 0x3FFF) && (st >= -0x4000)) { /* RX2? CPU only */ - t = (st & 0x7FFF) | 0x8000; - PUTNUM (t, 2); /* store displ */ - return -3; } } - t = (t & VAMASK32) | 0x40000000 | (rx2 << 24); - PUTNUM (t, 4); /* RX3 */ - return -5; - -case I_V_RI: /* 16b immediate */ - r = get_imm (gbuf, &t, &inst, DMASK16); /* process imm */ - if (r != SCPE_OK) return r; - PUTNUM (inst, 2); /* store inst */ - PUTNUM (t, 2); /* store 16b imm */ - return -3; - -case I_V_RF: - r = get_imm (gbuf, &t, &inst, DMASK32); /* process imm */ - if (r != SCPE_OK) return r; - PUTNUM (inst, 2); /* store inst */ - PUTNUM (t, 4); /* store 32b imm */ - return -5; - -case I_V_SB: case I_V_SX: /* short branches */ - r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */ - if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */ - return SCPE_ARG; - st = t; /* signed version */ - if (cf) { /* for CPU? */ - db = (addr - t) & 0x1F; /* back displ */ - df = (t - addr) & 0x1F; /* fwd displ */ - if ((t == ((addr - db) & VAMASK16)) && /* back work and */ - ((j == I_V_SX) || !(inst & MSK_SBF))) /* ext or back br? */ - inst = inst | (db >> 1); /* or in back displ */ - else if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */ - ((j == I_V_SX) || (inst & MSK_SBF))) /* ext or fwd br? */ - inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */ - else return SCPE_ARG; } - else if (rel) { /* periph, must be rel */ - if ((st <= 0) && (st >= -0x1F) && /* relative back? */ - ((j == I_V_SX) || !(inst & MSK_SBF))) - inst = inst | ((-st & 0x1F) >> 1); - else if ((st >= 0) && (st < 0x1F) && /* relative fwd? */ - ((j == I_V_SX) || (inst & MSK_SBF))) - inst = inst | ((t & 0x1F) >> 1); - else return SCPE_ARG; } - else return SCPE_ARG; /* periph & ~rel, err */ - } /* end case */ - -PUTNUM (inst, 2); -return -1; -} diff --git a/Interdata/id_defs.h b/Interdata/id_defs.h deleted file mode 100644 index 6fd75068..00000000 --- a/Interdata/id_defs.h +++ /dev/null @@ -1,487 +0,0 @@ -/* id_defs.h: Interdata 16b/32b simulator definitions - - Copyright (c) 2000-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - The author gratefully acknowledges the help of Carl Friend and Al Kossow, - who provided key documents about the Interdata product line. - - 21-Jun-03 RMS Changed subroutine argument for ARM compiler conflict - 25-Apr-03 RMS Revised for extended file support - 28-Feb-03 RMS Changed magtape device default to 0x85 -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* undef instr */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_WAIT 4 /* wait */ -#define STOP_VFU 5 /* runaway VFU */ - -/* Memory */ - -#define PAWIDTH16 16 -#define PAWIDTH16E 18 -#define PAWIDTH32 20 -#define MAXMEMSIZE16 (1u << PAWIDTH16) /* max mem size, 16b */ -#define MAXMEMSIZE16E (1u << PAWIDTH16E) /* max mem size, 16b E */ -#define MAXMEMSIZE32 (1u << PAWIDTH32) /* max mem size, 32b */ -#define PAMASK16 (MAXMEMSIZE16 - 1) /* phys mem mask */ -#define PAMASK16E (MAXMEMSIZE16E - 1) -#define PAMASK32 (MAXMEMSIZE32 - 1) - -#define MEMSIZE (cpu_unit.capac) /* act memory size */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) - -/* Single precision floating point registers */ - -#if defined (IFP_IN_MEM) -#define ReadFReg(r) (fp_in_hwre? \ - F[(r) >> 1]: ReadF (((r) << 1) & ~3, P)) -#define WriteFReg(r,v) if (fp_in_hwre) F[(r) >> 1] = (v); \ - else WriteF (((r) << 1) & ~3, (v), P) -#else -#define ReadFReg(r) (F[(r) >> 1]) -#define WriteFReg(r,v) F[(r) >> 1] = (v) -#endif - -/* Double precision floating point registers */ - -struct dpr { - unsigned int32 h; /* high 32b */ - unsigned int32 l; /* low 32b */ -}; - -typedef struct dpr dpr_t; - -/* Architectural constants */ - -#define VAMASK16 (0xFFFF) /* 16b virt addr */ -#define VAMASK32 (0x000FFFFF) /* 32b virt addr */ - -#define SIGN8 0x80 /* 8b sign bit */ -#define DMASK8 0xFF /* 8b data mask */ -#define MMASK8 0x7F /* 8b magnitude mask */ -#define SIGN16 0x8000 /* 16b sign bit */ -#define DMASK16 0xFFFF /* 16b data mask */ -#define MMASK16 0x7FFF /* 16b magnitude mask */ -#define SIGN32 0x80000000 /* 32b sign bit */ -#define DMASK32 0xFFFFFFFF /* 32b data mask */ -#define MMASK32 0x7FFFFFFF /* 32b magn mask */ - -#define CC_C 0x8 /* carry */ -#define CC_V 0x4 /* overflow */ -#define CC_G 0x2 /* greater than */ -#define CC_L 0x1 /* less than */ -#define CC_MASK (CC_C | CC_V | CC_G | CC_L) - -#define PSW_WAIT 0x8000 /* wait */ -#define PSW_EXI 0x4000 /* ext intr enable */ -#define PSW_MCI 0x2000 /* machine check enable */ -#define PSW_AFI 0x1000 /* arith fault enb */ -#define PSW_AIO 0x0800 /* auto I/O int enable */ -#define PSW_FPF 0x0400 /* flt fault enb, 16b */ -#define PSW_REL 0x0400 /* reloc enb, 32b */ -#define PSW_SQI 0x0200 /* sys q int enable */ -#define PSW_PRO 0x0100 /* protect mode */ -#define PSW_V_MAP 4 /* mem map, 16b */ -#define PSW_M_MAP 0xF -#define PSW_MAP (PSW_M_MAP << PSW_V_MAP) -#define PSW_V_REG 4 /* reg set, 32b */ -#define PSW_M_REG 0x1 -#define PSW_ID4 0xF40F /* I3, I4 PSW */ -#define PSW_x16 0xFF0F /* 7/16, 8/16 PSW */ -#define PSW_816E 0xFFFF /* 8/16E PSW */ -#define PSW_x32 0xFFFF /* 7/32, 8/32 PSW */ -#define PSW_GETMAP(x) (((x) >> PSW_V_MAP) & PSW_M_MAP) -#define PSW_GETREG(x) (((x) >> PSW_V_REG) & PSW_M_REG) - -#define MCKOPSW 0x20 /* mchk old PSW, 32b */ -#define FPFPSW 0x28 /* flt fault PSW, 16b */ -#define ILOPSW 0x30 /* ill op PSW */ -#define MCKPSW 0x38 /* mach chk PSW */ -#define EXIPSW 0x40 /* ext intr PSW, 16b */ -#define AFIPSW 0x48 /* arith flt PSW */ -#define SQP 0x80 /* system queue ptr */ -#define SQIPSW 0x82 /* sys q int PSW, 16b */ -#define SQOP 0x8A /* sys q ovf ptr, 16b */ -#define SQVPSW 0x8C /* sys q ovf PSW, 16b */ -#define SQTPSW 0x88 /* sys q int PSW, 32b */ -#define MPRPSW 0x90 /* mprot int PSW, 32b */ -#define SVCAP 0x94 /* svc arg ptr, 16b */ -#define SVOPS 0x96 /* svc old PS, 16b */ -#define SVOPC 0x98 /* svc old PC, 16b */ -#define SVNPS32 0x98 /* svc new PS, 32b */ -#define SVNPS 0x9A /* svc new PS, 16b */ -#define SVNPC 0x9C /* svc new PC */ -#define INTSVT 0xD0 /* int service table */ - -#define AL_DEV 0x78 /* autoload: dev */ -#define AL_IOC 0x79 /* command */ -#define AL_DSKU 0x7A /* disk unit */ -#define AL_DSKT 0x7B /* disk type */ -#define AL_DSKC 0x7C /* disk ctrl */ -#define AL_SCH 0x7D /* sel chan */ -#define AL_EXT 0x7E /* OS extension */ -#define AL_BUF 0x80 /* buffer start */ - -#define Q16_SLT 0 /* list: # slots */ -#define Q16_USD 1 /* # in use */ -#define Q16_TOP 2 /* current top */ -#define Q16_BOT 3 /* next bottom */ -#define Q16_BASE 4 /* base of q */ -#define Q16_SLNT 2 /* slot length */ - -#define Q32_SLT 0 /* list: # slots */ -#define Q32_USD 2 /* # in use */ -#define Q32_TOP 4 /* current top */ -#define Q32_BOT 6 /* next bottom */ -#define Q32_BASE 8 /* base of q */ -#define Q32_SLNT 4 /* slot length */ - -/* CPU event flags */ - -#define EV_MAC 0x01 /* MAC interrupt */ -#define EV_BLK 0x02 /* block I/O in prog */ -#define EV_INT 0x04 /* interrupt pending */ -#define EV_WAIT 0x08 /* wait state pending */ - -/* Block I/O state */ - -struct BlockIO { - uint32 dfl; /* devno, flags */ - uint32 cur; /* current addr */ - uint32 end; /* end addr */ - }; - -#define BL_RD 0x8000 /* block read */ -#define BL_LZ 0x4000 /* skip 0's */ - -/* Instruction decode ROM, for all, 16b, 32b */ - -#define OP_UNDEF 0x0000 /* undefined */ -#define OP_NO 0x0001 /* all: short or fp rr */ -#define OP_RR 0x0002 /* all: reg-reg */ -#define OP_RS 0x0003 /* 16b: reg-storage */ -#define OP_RI1 0x0003 /* 32b: reg-imm 16b */ -#define OP_RX 0x0004 /* all: reg-mem */ -#define OP_RXH 0x0005 /* all: reg-mem, rd HW */ -#define OP_RXF 0x0006 /* 32b: reg-mem, rd FW */ -#define OP_RI2 0x0007 /* 32b: reg-imm 32b */ -#define OP_MASK 0x000F - -#define OP_ID4 0x0010 /* 16b: ID4 */ -#define OP_716 0x0020 /* 16b: 7/16 */ -#define OP_816 0x0040 /* 16b: 8/16 */ -#define OP_816E 0x0080 /* 16b: 8/16E */ - -#define OP_DPF 0x4000 /* all: hwre FP */ -#define OP_PRV 0x8000 /* all: privileged */ - -#define OP_TYPE(x) (decrom[(x)] & OP_MASK) -#define OP_DPFP(x) (decrom[(x)] & OP_DPF) - -/* Device information block */ - -struct interdib { - uint32 dno; /* device number */ - int32 sch; /* sch */ - uint32 irq; /* interrupt */ - uint8 *tplte; /* template */ - uint32 (*iot)(uint32 d, uint32 o, uint32 dat); - void (*ini)(t_bool f); }; - -typedef struct interdib DIB; - -#define TPL_END 0xFF /* template end */ - -/* Device select return codes */ - -#define BY 0 /* 8b only */ -#define HW 1 /* 8b/16b */ - -/* I/O operations */ - -#define IO_ADR 0x0 /* address select */ -#define IO_RD 0x1 /* read byte */ -#define IO_RH 0x2 /* read halfword */ -#define IO_WD 0x3 /* write byte */ -#define IO_WH 0x4 /* write halfword */ -#define IO_OC 0x5 /* output command */ -#define IO_SS 0x6 /* sense status */ - -/* Device command byte */ - -#define CMD_V_INT 6 /* interrupt control */ -#define CMD_M_INT 0x3 -#define CMD_IENB 1 /* enable */ -#define CMD_IDIS 2 /* disable */ -#define CMD_IDSA 3 /* disarm */ -#define CMD_GETINT(x) (((x) >> CMD_V_INT) & CMD_M_INT) - -/* Device status byte */ - -#define STA_BSY 0x8 /* busy */ -#define STA_EX 0x4 /* examine status */ -#define STA_EOM 0x2 /* end of medium */ -#define STA_DU 0x1 /* device unavailable */ - -/* Default device numbers */ - -#define DEV_LOW 0x01 /* lowest intr dev */ -#define DEV_MAX 0xFF /* highest intr dev */ -#define DEVNO (DEV_MAX + 1) /* number of devices */ -#define d_DS 0x01 /* display, switches */ -#define d_TT 0x02 /* teletype */ -#define d_PT 0x03 /* reader */ -#define d_CD 0x04 /* card reader */ -#define d_TTP 0x10 /* PAS as console */ -#define d_PAS 0x10 /* first PAS */ -#define o_PASX 0x01 /* offset to xmt */ -#define d_LPT 0x62 /* line printer */ -#define d_PIC 0x6C /* interval timer */ -#define d_LFC 0x6D /* line freq clk */ -#define d_MT 0x85 /* magtape */ -#define o_MT0 0x10 -#define d_DPC 0xB6 /* disk controller */ -#define o_DP0 0x10 -#define o_DPF 0x01 /* offset to fixed */ -#define d_FD 0xC1 /* floppy disk */ -#define d_SCH 0xF0 /* selector chan */ -#define d_IDC 0xFB /* MSM disk ctrl */ -#define o_ID0 0x01 - -/* Interrupts - - To make interrupt flags independent of device numbers, each device is - assigned an interrupt flag in one of four interrupt words - - word 0 DMA devices - word 1 programmed I/O devices - word 2-3 PAS devices - - Devices are identified by a level and a bit within a level. Priorities - run low to high in the array, right to left within words -*/ - -#define INTSZ 4 /* interrupt words */ -#define SCH_NUMCH 4 /* #channels */ -#define ID_NUMDR 4 /* # MSM drives */ -#define DP_NUMDR 4 /* # DPC drives */ -#define MT_NUMDR 4 /* # MT drives */ - -/* Word 0, DMA devices */ - -#define i_SCH 0 /* highest priority */ -#define i_IDC (i_SCH + SCH_NUMCH) /* MSM disk ctrl */ -#define i_DPC (i_IDC + ID_NUMDR + 1) /* cartridge disk ctrl */ -#define i_MT (i_DPC + DP_NUMDR + 1) /* magtape */ - -#define l_SCH 0 -#define l_IDC 0 -#define l_DPC 0 -#define l_MT 0 - -#define v_SCH (l_SCH * 32) + i_SCH -#define v_IDC (l_IDC * 32) + i_IDC -#define v_DPC (l_DPC * 32) + i_DPC -#define v_MT (l_MT * 32) + i_MT - -/* Word 1, programmed I/O devices */ - -#define i_PIC 0 /* precision clock */ -#define i_LFC 1 /* line clock */ -#define i_FD 2 /* floppy disk */ -#define i_CD 3 /* card reader */ -#define i_LPT 4 /* line printer */ -#define i_PT 5 /* paper tape */ -#define i_TT 6 /* teletype */ -#define i_DS 7 /* display */ -#define i_TTP 10 /* PAS console */ - -#define l_PIC 1 -#define l_LFC 1 -#define l_FD 1 -#define l_CD 1 -#define l_LPT 1 -#define l_PT 1 -#define l_TT 1 -#define l_DS 1 -#define l_TTP 1 - -#define v_PIC (l_PIC * 32) + i_PIC -#define v_LFC (l_LFC * 32) + i_LFC -#define v_FD (l_FD * 32) + i_FD -#define v_CD (l_CD * 32) + i_CD -#define v_LPT (l_LPT * 32) + i_LPT -#define v_PT (l_PT * 32) + i_PT -#define v_TT (l_TT * 32) + i_TT -#define v_DS (l_DS * 32) + i_DS -#define v_TTP (l_TTP * 32) + i_TTP - -/* Word 2-3, PAS devices */ - -#define i_PAS 0 -#define l_PAS 2 -#define v_PAS (l_PAS * 32) + i_PAS -#define v_PASX (v_PAS + 1) /* offset to xmt */ - -/* I/O macros */ - -#define SET_INT(v) int_req[(v) >> 5] = int_req[(v) >> 5] | (1u << ((v) & 0x1F)) -#define CLR_INT(v) int_req[(v) >> 5] = int_req[(v) >> 5] & ~(1u << ((v) & 0x1F)) -#define SET_ENB(v) int_enb[(v) >> 5] = int_enb[(v) >> 5] | (1u << ((v) & 0x1F)) -#define CLR_ENB(v) int_enb[(v) >> 5] = int_enb[(v) >> 5] & ~(1u << ((v) & 0x1F)) - -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ - -/* Device accessible macro */ - -#define DEV_ACC(d) (dev_tab[d] && !sch_blk (d)) - -/* Automatic I/O channel programs, 16b */ - -#define CCB16_CHN -4 /* chain */ -#define CCB16_DEV -2 /* dev no */ -#define CCB16_STS -1 /* status */ -#define CCB16_CCW 0 /* cmd wd */ -#define CCB16_STR 2 /* start */ -#define CCB16_END 4 /* end */ -#define CCB16_IOC 6 /* OC byte */ -#define CCB16_TRM 7 /* term byte */ - -#define CCW16_INIT 0x8000 /* init */ -#define CCW16_NOP 0x4000 /* nop */ -#define CCW16_V_FNC 12 /* function */ -#define CCW16_M_FNC 0x3 -#define CCW16_FNC(x) (((x) >> CCW16_V_FNC) & CCW16_M_FNC) -#define CCW16_RD 0 /* read */ -#define CCW16_WR 1 /* write */ -#define CCW16_DMT 2 /* dec mem */ -#define CCW16_NUL 3 /* null */ -#define CCW16_TRM 0x0400 /* term char */ -#define CCW16_Q 0x0200 /* queue */ -#define CCW16_HI 0x0100 /* queue hi */ -#define CCW16_OC 0x0080 /* OC */ -#define CCW16_CHN 0x0020 /* chain */ -#define CCW16_CON 0x0010 /* continue */ -#define CCW16_V_BPI 0 /* bytes per int */ -#define CCW16_M_BPI 0xF -#define CCW16_BPI(x) (((x) >> CCW16_V_BPI) & CCW16_M_BPI) - -/* Automatic I/O channel programs, 32b */ - -#define CCB32_CCW 0 /* cmd wd */ -#define CCB32_B0C 2 /* buf 0 cnt */ -#define CCB32_B0E 4 /* buf 0 end */ -#define CCB32_CHK 8 /* check word */ -#define CCB32_B1C 10 /* buf 1 cnt */ -#define CCB32_B1E 12 /* buf 1 end */ -#define CCB32_TAB 16 /* trans table */ -#define CCB32_SUB 20 /* subroutine */ - -#define CCW32_V_STA 8 /* status */ -#define CCW32_M_STA 0xFF -#define CCW32_STA(x) (((x) >> CCW32_V_STA) & CCW32_M_STA) -#define CCW32_EXE 0x80 /* execute */ -#define CCW32_CRC 0x10 -#define CCW32_B1 0x08 /* buffer 1 */ -#define CCW32_WR 0x04 /* write */ -#define CCW32_TL 0x02 /* translate */ -#define CCW32_FST 0x01 /* fast mode */ - -/* MAC, 32b */ - -#define P 0 /* physical */ -#define VE 1 /* virtual inst */ -#define VR 2 /* virtual read */ -#define VW 3 /* virtual write */ - -#define MAC_BASE 0x300 /* MAC base */ -#define MAC_STA 0x340 /* MAC status */ -#define MAC_LNT 16 -#define VA_V_OFF 0 /* offset */ -#define VA_M_OFF 0xFFFF -#define VA_GETOFF(x) (((x) >> VA_V_OFF) & VA_M_OFF) -#define VA_V_SEG 16 /* segment */ -#define VA_M_SEG 0xF -#define VA_GETSEG(x) (((x) >> VA_V_SEG) & VA_M_SEG) - -#define SRF_MASK 0x000FFF00 /* base mask */ -#define SRL_MASK 0x0FF00000 /* limit mask */ -#define GET_SRL(x) ((((x) & SRL_MASK) >> 12) + 0x100) -#define SR_EXP 0x80 /* execute prot */ -#define SR_WPI 0x40 /* wr prot int */ -#define SR_WRP 0x20 /* wr prot */ -#define SR_PRS 0x10 /* present */ -#define SR_MASK (SRF_MASK|SRL_MASK|SR_EXP|SR_WPI|SR_WRP|SR_PRS) - -#define MACS_L 0x10 /* limit viol */ -#define MACS_NP 0x08 /* not present */ -#define MACS_WP 0x04 /* write prot */ -#define MACS_WI 0x02 /* write int */ -#define MACS_EX 0x01 /* exec prot */ - -/* Miscellaneous */ - -#define TMR_LFC 0 /* LFC = timer 0 */ -#define TMR_PIC 1 /* PIC = timer 1 */ -#define TMR_PAS 2 /* PAS = timer 2 */ -#define LPT_WIDTH 132 -#define VFU_LNT 132 -#define MIN(x,y) (((x) < (y))? (x): (y)) -#define MAX(x,y) (((x) > (y))? (x): (y)) - -/* Logging */ - -#define LOG_CPU_I 0x0001 /* instructions */ -#define LOG_CPU_C 0x0002 /* context change */ -#define LOG_DP 0x0010 -#define LOG_IDC 0x0020 -#define LOG_MT 0x0040 -#define LOG_FD 0x0080 - -#define DBG_LOG(x) (sim_log && (cpu_log & (x))) - -/* Function prototypes */ - -int32 int_chg (uint32 irq, int32 dat, int32 armdis); -int32 io_2b (int32 val, int32 pos, int32 old); -uint32 IOReadB (uint32 loc); -void IOWriteB (uint32 loc, uint32 val); -uint32 ReadF (uint32 loc, uint32 rel); -void WriteF (uint32 loc, uint32 val, uint32 rel); -uint32 IOReadBlk (uint32 loc, uint32 cnt, uint8 *buf); -uint32 IOWriteBlk (uint32 loc, uint32 cnt, uint8 *buf); -void sch_adr (uint32 ch, uint32 dev); -t_bool sch_actv (uint32 sch, uint32 devno); -void sch_stop (uint32 sch); -uint32 sch_wrmem (uint32 sch, uint8 *buf, uint32 cnt); -uint32 sch_rdmem (uint32 sch, uint8 *buf, uint32 cnt); -t_stat set_sch (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat set_dev (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_sch (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat show_dev (FILE *st, UNIT *uptr, int32 val, void *desc); diff --git a/Interdata/id_diag.txt b/Interdata/id_diag.txt deleted file mode 100644 index ea84a188..00000000 --- a/Interdata/id_diag.txt +++ /dev/null @@ -1,907 +0,0 @@ -Interdata Diagnostics - -Summary - -816E CPU diagnostic, part 1 passed 16b n/a -816E CPU diagnostic, part 2 partial 16b n/a -Series 16 CPU diagnostic, part 1 passed 16b n/a -16b memory diagnostic, part 1 passed 16b n/a -16b memory diagnostic, part 2 passed 16b n/a -816e extended memory diagnostic passed 16b n/a -Series 16 selector channel diagnostic passed 16b n/a -32b CPU diagnostic, part 1 n/a passed 32b -32b CPU diagnostic, part 2 n/a passed 32b -32b CPU diagnostic, part 3 n/a passed 32b -32b memory diagnostic, part 1 n/a passed 32b -32b memory diagnostic, part 2 n/a passed 32b -32b memory diagnostic, part 3 n/a passed 32b -32b memory diagnostic 6a, part 1 n/a passed 32b -32b memory diagnostic 6a, part 2 n/a passed 32b -32b MAC diagnostic, part 1 n/a passed 32b -32b MAC diagnostic, part 2 n/a passed 32b -Common line printer diagnostic passed 16b passed 32b -Common magtape diagnostic passed 16b passed 32b -Common 2.5/10MB disk diagnostic passed 16b passed 32b -32b MSM disk diagnostic passed 32b -Common floppy disk diagnostic passed 16b passed 32b -Common clock diagnostic passed 16b passed 32b - -Not tested: -- 16b floating point -- 32b double precision floating point -- IDC -- PASLA - -------------------------------------------------------------------- - -Operating Instructions - -816E CPU diagnostic, part 1 - -sim> set cpu 816e -sim> att -e pt0 diag.bin -sim> br c2 -sim> boot pt0 - -Breakpoint: PC: 00C2 (EXBR R8,R6) - -sim> run 100 - -MODEL 8/16E PROCESSOR TEST PART 1 06-211R00 -CPU -* 8D - -ENTER 0 OR 1 -1 -NO ERROR - -CPU -* - ---- -816E CPU diagnostic, part 2 - -sim> set cpu 816e -sim> d tt ttime 1000 ; timing dependency -sim> att -e pt0 diag.bin -sim> br c2 -sim> boot pt0 - -Breakpoint: PC: 00C2 (EXBR R8,R6) - -sim> run 100 - -MODEL 8/16E PROCESSOR TEST PART 2 06-212R00 -CPU -* 8D - -SUBTEST - -* (type subtest number) - -Subtests 0, 1, 2, 5, 7, 8, 9 run correctly -Subtest 3, 4 cannot be run (initialization, power fail) -Subtest 6 cannot be run (hexadecimal display) - ---- -Series 16 CPU diagnostic, part 1 -(Central error routine is at 21F4) - -sim> set cpu 816e -sim> att -e pt0 diag.bin ; diagnostic -sim> br c0 -sim> boot pt0 - -Breakpoint, PC: 00C0 (8800) - -sim> d 234a 0202 ; patch to use -sim> d 234c a4a8 ; TTY as console -sim> d 17a b1e4 -sim> run 100 - -SERIES SIXTEEN PROCESSOR TEST PART 1 06-242F01R00 -CPU -* 2D -ENTER 0 OR 1 -1 - -1234567890 - -NO ERROR - -000A 0000 - -CPU -* - ---- -16b memory diagnostic, part 1 - -sim> att -e pt0 diag.bin ; diagnostic -sim> br c2 -sim> boot pt0 - -Breakpoint, PC: 00C2 (EPSR R7,R6) - -sim> run 100 - -02-340 PART 1 06-162F01R01 - -NO ERRORS - ---- -16b memory diagnostic, part 2 - -sim> att -e pt0 diag.bin ; diagnostic -sim> br c2 -sim> boot pt0 - -Breakpoint, PC: 00C2 (EPSR R7,R6) - -sim> run 1000 - -02-340 PART 2 06-162F02R01 - -NO ERRORS - ---- -816e extended memory diagnostic, parts 1 and 2 - -sim> set cpu 816e -sim> set cpu 256k -sim> att -e pt0 diag.bin ; diagnostic -sim> br b4 -sim> boot pt0 - -Breakpoint, PC: 00B4 (LPSW R0,B8) - -sim> run 1000 - -8/16 E EXTENDED MEMORY TEST PART 1 06-221R00 -NO ERROR -* (CR to repeat part 1) -8/16 E EXTENDED MEMORY TEST PART 1 06-221R00 -NO ERROR -* (LF to go on to part 2) - -Breakpoint, PC: 00B4 (LPSW R0,B8) -sim> run 100 - -8/16 E EXTENDED MEMORY TEST PART 2 06-221R00 -PROGRAM DETECTED MAXIMUM MEMORY 3FFFE -*TEST ; standard tests -*RUN - -SUBTEST 0 NO ERROR -SUBTEST 1 NO ERROR -SUBTEST 2 NO ERROR -SUBTEST 3 NO ERROR -SUBTEST 4 NO ERROR -SUBTEST 6 NO ERROR -SUBTEST 7 NO ERROR -SUBTEST 8 NO ERROR -END OF TEST - -* - ---- -Series 16 selector channel diagnostic - -sim> set cpu 816e -sim> set cpu 256k -sim> att -e pt0 diag.bin ; diagnostic -sim> att mt0 foo.tap ; magtape to test -sim> br c0 -sim> boot pt0 - -Breakpoint, PC: 00C0 (LPSW R0,C8) - -sim> d 2e68 2 ; console is TTY -sim> run A00 - -S16 SELCH TEST 06-222 R01 - -TOP OF MEMORY 3 FFFF -* IODEV1 C5 ; magtape -* DEV1 2 -* RUN ; bank 0 by default -TEST 00 - -NO ERROR - -TEST 01 - -NO ERROR - -TEST 02 - -NO ERROR - -TEST 03 - -NO ERROR - -TEST 04 - -NO ERROR - - -* MEMMOD 1 {2,3} ; repeat for banks 1,2,3 -* RUN -TEST 00 - -NO ERROR - -TEST 01 - -NO ERROR - -TEST 02 - -NO ERROR - -TEST 03 - -NO ERROR - -TEST 04 - -NO ERROR - -* ---- -32b CPU diagnostic, part 1 - -sim> att -e mt0 mmd_r07.tap -sim> d -b 7f 7 ; file 8 on MMD R07 tape -sim> boot mt0 - -S32PT1 06-154 R03 -CPU - -*7X -NO ERROR -000A 0000 -* - ---- -32b CPU diagnostic, part 2 - -sim> set tt 7b ; test is parity sensitive -sim> att -e mt0 mmd_r07.tap -sim> d -b 7f 8 ; file 9 on MMD R07 tape -sim> boot mt0 - - -S32PT2R02 -CPU -* -7X -SUBTEST -* (type subtest number) - -Subtests 1, 3, 4, 5, 9 run correctly -Subtest 2 cannot be run (7/32 with halfword mode only) -Subtest 6 cannot be run (hexadecimal display) -Subtests 7,8 cannot be run (initialization, power fail) - ---- -32b CPU diagnostic, part 3 - -sim> att -e mt0 mmd_r07.tap -sim> d -b 7f 9 ; file 10 on MMD R07 tape -sim> boot mt0 - -S32PT3 R01 -CPU -* -8X ; 7X denotes 7/32 with halfword mode -MAC RESPONSE AT 000300 - -SUBTEST -* - -Subtests 1, 2, 3 run correctly -Subtest 4 cannot be run (parity option) - ---- -32b memory diagnostic, part 1 - -sim> att -e mt0 mmd_r07.tap -sim> d -b 7f 17 ; file 24 on MMD R07 tape -sim> br 2000 -sim> boot mt0 - -Breakpoint, PC: 02000 (B 2060) -sim> d -w 2010 0202 ; console is TTY -sim> c - -S32MT1 06-156F01R04 -MAC PRESENT ? (Y OR N) -* -Y -01 -02 -03 -04 -05 -06 -NO ERROR -* - ---- -32b memory diagnostic, part 2 - -sim> att -e mt0 c:\temp\mmd_r07.tap -sim> d -b 7f 18 ; file 25 on MMD R07 tape -sim> br a00 -sim> boot mt0 - -Breakpoint, PC: 00A00 (B A60) -sim> d -w a10 0202 ; console is TTY -sim> c - -S32MT2 06-156F02R04 -AVAILABLE MEMORY -000000 - 0FFFFF -SUBTEST * -0 ; all standard tests -01 -TEST STILL RUNNING ; repeated multiple times -: -NO ERROR -02 -TEST STILL RUNNING ; repeated multiple times -: -NO ERROR -03 -TEST STILL RUNNING ; repeated multiple times -: -NO ERROR -04 -TEST STILL RUNNING ; repeated multiple times -: -NO ERROR -05 -TEST STILL RUNNING ; repeated multiple times -: -NO ERROR -06 -TEST STILL RUNNING ; repeated multiple times -: -NO ERROR -07 -TEST STILL RUNNING ; repeated multiple times -: -NO ERROR -SUBTEST * - ---- -32b memory diagnostic, part 3 - -sim> att -e mt0 c:\temp\mmd_r07.tap -sim> d -b 7f 19 ; file 26 on MMD R07 tape -sim> br a00 -sim> boot mt0 - -Breakpoint, PC: 00A00 (B A60) -sim> d -w a10 0202 ; console is TTY - -sim> c -S32MT3 06-156F03R04 -AVAILABLE MEMORY -000000 - 0FFFFF -* - -TEST STILL RUNNING ; repeated multiple times -: -NO ERROR -* - ---- -32b memory diagnostic, 6a, part 1 - -sim> att -e mt0 c:\temp\mmd_r07.tap -sim> d -b 7f 15 ; file 22 on MMD R07 tape -sim> boot mt0 - -32 BIT S6A MEMORY TEST 06-157F01R01 -AVAILABLE MEMORY -0000-3FFF - -MAC ADDRESS = 300 -TYPE= 3 ; any value, 0-4 -SUBTEST -* 0 -01 -NO ERROR -02 -NO ERROR -03 -NO ERROR -04 -NO ERROR -05 -NO ERROR -06 -NO ERROR -07 -NO ERROR -08 -NO ERROR - -SUBTEST -* - ---- -32b memory diagnostic, 6a, part 2 - -sim> att -e mt0 c:\temp\mmd_r07.tap -sim> d -b 7f 16 ; file 23 on MMD R07 tape -sim> boot mt0 - -32 BIT S6A MEMORY TEST 06-157F02R01 -AVAILABLE MEMORY -0000f-FFFFF - -TYPE= 2 ; any value, 0-4 -SUBTEST -* 0 -01 -NO ERROR -02 -NO ERROR -03 -NO ERROR -04 -NO ERROR -05 -NO ERROR -06 -NO ERROR -07 -NO ERROR -08 -NO ERROR - -SUBTEST -* - ---- -32b MAC diagnostic, part 1 - -sim> att -e mt0 c:\temp\mmd_r07.tap -sim> d -b 7f 24 ; file 37 on MMD R07 tape -sim> boot mt0 - -MACT 06-160F01R03 -AVAILABLE MEMORY -00000- FFFFF - -* RUN -TEST 00 NO ERROR -TEST 01 NO ERROR -TEST 02 NO ERROR -TEST 03 NO ERROR -TEST 04 NO ERROR -TEST 05 NO ERROR -TEST 06 NO ERROR -TEST 07 NO ERROR -TEST 08 NO ERROR -TEST 09 NO ERROR -TEST 0B NO ERROR -* - ---- -sim> att -e mt0 c:\temp\mmd_r07.tap -sim> d -b 7f 25 ; file 38 on MMD R07 tape -sim> br ffd0 ; start != load point -sim> boot mt0 - -Breakpoint, PC: 0FFD0 (B 1093E) - -sim> run 10010 - -MACT 06-160F02R03 - -* RUN -TEST 00 NO ERROR -TEST 01 NO ERROR -TEST 02 NO ERROR -TEST 03 NO ERROR -TEST 04 NO ERROR -TEST 05 NO ERROR -TEST 06 NO ERROR -TEST 07 NO ERROR -TEST 08 NO ERROR -* - ---- -Common line printer diagnostic - -sim> att -e pt0 diag.bin -sim> br c2 -sim> boot pt0 - -Breakpoint: PC: 00C2 (EXBR R8,R6) - -sim> run a00 ; 32b -sim> run a04 ; 16b - -COMMON LINE PRINTER TEST 06-170R02 - -*TEST 0,1,2,3 -*RUN - -TEST 00 -NO ERROR -TEST 01 -NO ERROR -TEST 02 -NO ERROR -TEST 03 -NO ERROR -END OF TEST - -*INTRPT 1 -*RUN - -TEST 00 -NO ERROR -TEST 01 -NO ERROR -TEST 02 -NO ERROR -TEST 03 -NO ERROR -END OF TEST - -* - ---- -Common magtape diagnostic - -sim> att -e pt0 diag.bin -sim> att mt foo.tap -sim> br c4 -sim> boot pt0 - -Breakpoint, PC: 00C4 (EXBR R8,R6) - -sim> run a00 ; 32b -sim> run a04 ; 16b - -COMMON MAGNETIC TAPE TEST PROGRAM 06-172R02 - -*TEST 0,1,2,3,4,5 -*MODE 0 ; prog i/o and selch -*RUN - -TEST 00 -NO ERROR -TEST 01 -NO ERROR -TEST 02 -NO ERROR -TEST 03 -NO ERROR -TEST 04 -NO ERROR -TEST 05 -NO ERROR -END OF TEST - -* - ---- -Common 2.5/10MB disk diagnostic - -sim> att -e pt0 diag.bin -sim> br c2 -sim> boot pt0 - -Breakpoint, PC: 00C2 (EXBR R8,R6) - -sim> set dp0 5440 -sim> set dp1 5440 -sim> att dp0 test0.dsk -sim> att dp1 test1.dsk -sim> run a00 ; 32b -sim> run a04 ; 16b - -COMMON DISC TEST 06-173R01F01 - -*FILE 2 ; FILE 1 to test fixed platter -*LOCYL 0 -*HICYL 197 -*TIMCON 1C0 -*TEST 0,1,2,3,4,6,7,8,9,A,C ; test 5 requires format capability - ; test B requires manual intervention -*RUN - -TEST 00 -NO ERROR -TEST 01 -NO ERROR -TEST 02 -NO ERROR -TEST 03 -NO ERROR -TEST 04 -NO ERROR -TEST 06 -NO ERROR -TEST 07 -NO ERROR -TEST 08 -NO ERROR -TEST 09 -NO ERROR -TEST 0A -NO ERROR -TEST 0C -NO ERROR -END OF TEST - -* - ---- -32b MSM disk diagnostic - -sim> att -e mt0 c:\temp\mmd_r07.tap -sim> d -b 7f 45 ; file 70 on MMD R07 tape -sim> br a00 -sim> boot mt0 - -Breakpoint, PC: 00A00 (B A5E) - -sim> d -w a10 0101 ; patch for TTY console -sim> att dm0 foo.dsk -sim> att dm1 foo1.dsk -sim> c - -MSM DISC TEST 06-200F02R04 (32-BIT) - -*LOCYL 0 -*HICYL 336 ; tests 8,9,A will run a very long - ; time, use 40 to shorten test -*DRIVE 0 -*PACTYP 0 -*TIMVAL 14D -*XFILE 1 -*TEST 0,1,2,3,4,6,7,8,9,A,C ; test 5 requires format capability - ; test B requires manual intervention -*RUN - -TEST 00 -TEST 01 -TEST 02 -TEST 03 -TEST 04 -TEST 06 -TEST 07 -TEST 08 -TEST 09 -TEST 0A -TEST 0C - ---- -Common floppy disk diagnostic - -sim> att -e pt0 diag.bin -sim> att fd0 foo0.flp -sim> att fd1 foo1.flp -sim> br b8 -sim> boot pt0 - -Breakpoint, PC: 000B8 (BS B2) - -sim> d 2a72 bal r15,320a ; patch for multidrive test -sim> run a00 ; 32b -sim> run a04 ; 16b - -COMMON FLOPPY DISC TEST 06-198R00 -UNPROTECT DISKETTE - -*DRIVE AB -*RUN - -DRIVE A UNDER TEST -TEST 00 -NO ERROR -TEST 01 -NO ERROR -TEST 02 -NO ERROR -TEST 03 -NO ERROR -TEST 04 -NO ERROR -TEST 05 -NO ERROR -TEST 06 -NO ERROR -TEST 07 -NO ERROR -DRIVE B UNDER TEST -TEST 00 -NO ERROR -TEST 01 -NO ERROR -TEST 02 -NO ERROR -TEST 03 -NO ERROR -TEST 04 -NO ERROR -TEST 05 -NO ERROR -TEST 06 -NO ERROR -TEST 07 -NO ERROR -END OF TEST - -*TEST 9 ; test 8 requires formatting -*RUN - -TEST 09 -NO ERROR -END OF TEST - -* - ---- -Common clock diagnostic - -sim> att -e pt0 diag.bin -sim> br c4 -sim> boot pt0 - -Breakpoint, PC: 00C4 (EXBR R8,R6) - -sim> d -w e28 4300 ; R09 patches -sim> d -w e2a 10f4 -sim> id -w 10f4:110a -10f4: 4840 -10f6: 188a -10f8: 4850 -10fa: 188c -10fc: de40 -10fe: 1eaf -1100: de50 -1102: 1eaf -1104: 4810 -1106: 0a24 -1108: 4300 -1110: 0e2c -sim> d 1b9c bs 1ba6 -sim> d -w 1102 1eaf - -sim> run a00 ; 32b -sim> run a04 ; 16b - -COMMON UNIVERSAL CLOCK MODULE TEST 06-133R05 - -*TIMVAL 1A4 ; simulator is a fast CPU -*RUN - -TEST 00 -NO ERROR -TEST 01 -NO ERROR -TEST 02 -NO ERROR -TEST 03 -NO ERROR -TEST 04 -NO ERROR -TEST 05 -NO ERROR -TEST 06 -NO ERROR -TEST 07 -NO ERROR -END OF TEST - -* - -------------------------------------------------------------------- -Bugs found - -1. CPU16: instruction decoding interpreting CPU models incorrectly -2. CPU16: SINT should not be conditional on device existing -3. CPU16: immediate interrupts do not do a PSW swap, new PC is block+6 -4. CPU16: SLA, SLHA setting C incorrectly -5. CPU16: diagnostic requires 816E extended memory to run -6. CPU16: CCW16_OC defined incorrectly -7. CPU16, CPU32: autoload not fetching or outputing OC -8. CPU16, CPU32: block I/O completion is off by 1 -9. CPU16, CPU32: ESPR broken, EPSR rx,rx should copy PSW to rx -10. CPU16, CPU32: PCQ displays in octal instead of hexadecimal -11. CPU16, CPU32: SH and variations overflow calculation wrong -12. CPU16, CPU32: SCH overflow calculation wrong -13. CPU16, CPU32: CH and CLH overflow calculation wrong -14. CPU16, CPU32: CH or'ing into CC's instead of loading -15. CPU16, CPU32: RD, RH, SS, AI store some data on non-existent device -16. CPU16, CPU32: console interrupt not implemented -17. CPU16, CPU32: SRHL(s) setting C incorrectly -18. CPU16, CPU32: WDR, OCR not masking register data to 8b -19. CPU32: WH not masking data to 8b or 16b as required -20. CPU32: 32b register sets ordered incorrectly in memory -21. CPU32: wrong slot length in queue instructions -22. CPU32: display device missing its interrupt declaration -23. CPU32: LPSW(R) must load PC before changing PSW -24. CPU32: SLL setting C incorrectly -25. CPU32: bit instructions use halfword memory access and offsets -26. CPU32: CRC sign-extending rather than zero-extending operands -27. CPU32: SCP incrementing counts before, not after, transfer -28. CPU32: CHVR not implemented -29. CPU32: M(R) algorithm wrong -30. CPU32: M(R) using wrong register as first operand -31. CPU32: memory accesses were fullword rather than halfword aligned -32. CPU32: D(R) overflow calculation incorrect -33. CPU32: on 7/32, exceptions use register set 0, regardless of new PSW -34. CPU32: system queue PSW location misdefined -35. CPU32: autodriver channel not shifting bytes left before use as - translation table index -36. CPU32: MAC, LRA using wrong value for limit test -37. CPU32: LRA using wrong value for segment base -38. CPU32: MAC registers are accessible only if protection is off -39. CPU32: MAC status clears only on write, not read -40. CPU32: MAC write protect abort and interrupts implemented incorrectly -41. CPU32: ex/dep -v test used & instead of && -42. CPU32: fetch tests for MAC abort at end of fetch, not per halfword -43. FP: unpack and pack detecting RR format incorrectly -44. FP: need separate microcode/hardware algorithms for add/sub denormalization -45. FP: multiply and divide have 'early out' detection of overflow/underflow -46. FP: compare less than not setting C -47. FP: fix overflow not setting V -48. FP: fix shift needed to be hex digits not binary digits -49. IO: interrupt evaluation routine never sets an interrupt -50. SELCH: transfer count calculation off by 1 -51. SELCH: device data structure set up incorrectly (reset routine) -52. SELCH: stop clears pending interrupts -53. SELCH: register load algorithm incorrect for 6 byte loads -54. PT, LPT, FD: OR'ing status mask instead of AND'ing -55. PT, TT: SET_INT on status change not conditioned on interrupt armed -56. TT: input char converted to UC incorrectly -57. TT: need SET TT BREAK to run CPU test part 2 -58. LPT: not clearing spacing done -59. MT: WREOF not setting EOF status -60. MT: CMD register pointer to wrong place -61. MT: write record byte count taken from wrong variable -62. MT: overrun processing incorrect for selector channel mode -63. PIC, LFC: write data and overflow detection incorrect -64. PIC, LFC: interpolation algorithm for cic read incorrect -65. PIC, LFC: ric reloaded from output buffer on count overflow -66. PIC, LFC: added diagnostic mode, revised use of count vs timer -67. DP: track increment algorithm incorrect -68. DP, IDC: incorrectly setting overrun for less than full sector reads -69. DP: should interrupt on detach (offline) -70. FD: high water mark not updated on write -71. FD: deleted data not implemented, required for diagnostic -72. FD: header CRC not implemented, required for diagnostic -73. FD: function code not stored for service routine -74. FD: LRN to track and sector conversions incorrect -75. FD: reset status incorrect (should be not busy, LRN = 1) -76. FD: extended status track 0 calculation wrong -77. FD: reset does not clear interrupts, requires delay -78. FD: read/write sequencing incorrect -79. FD: command without write data uses implicit LRN -80. FD: extended status is per drive not per controller -81. FD: command start clears only extended status bytes 0,1 -82. FD: IDLE sets after BUSY drops and generates a separate interrupt -83. SYS16, SYS32: WH mistyped as WD in symbol table -84. SYS32: MHR, DHR misdefined -85. PAS: busy set instead of cleared initially -86. IDC: busy set instead of cleared initially -87. IDC, DP: busy not cleared at transfer command complete -88. IDC: busy is not cleared at drive command complete -89. IDC: for MSM compatibility, must absorb WH of head/cylinder -90. IDC: drive command 0x30 is an instant NOP -91. IDC: set cylinder with invalid cylinder sets SKI -92. IDC: read with invalid head sets ACF, not DTE -93. DP, IDC: write with cylinder overflow advanced selch pointer -94. MT: read error must stop selector channel (if active) - diff --git a/Interdata/id_doc.txt b/Interdata/id_doc.txt deleted file mode 100644 index 22ea0fa5..00000000 --- a/Interdata/id_doc.txt +++ /dev/null @@ -1,974 +0,0 @@ -To: Users -From: Bob Supnik -Subj: Interdata 16b/32b Simulator Usage -Date: 15-Jul-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - Original code published in 1993-2003, written by Robert M Supnik - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - -This memorandum documents the Interdata 16b and 32b simulators. - - -1. Simulator Files - -sim/ sim_defs.h - sim_rev.h - sim_sock.h - sim_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tape.c - sim_tmxr.c - -sim/interdata/ id_defs.h - id16_cpu.c [id32_cpu.c] - id16_dboot.c [id32_dboot.c] - id_dp.c - id_fd.c - id_fp.c - id_idc.c - id_io.c - id_lp.c - id_mt.c - id_pas.c - id_pt.c - id_tt.c - id_ttp.c - id_uvc.c - id16_sys.c [id32_sys.c] - -2. Interdata Features - -The Interdata simulator includes simulators for a variety of 16b (I3, I4, -I5, 70, 80, 7/16, 8/16, 8/16E) and 32b (7/32, 8/32) models. This is by -no means a complete sampling of all the variations in the Interdata/Perkin- -Elmer family. The 32b family included options for special communications -instructions (7/32C, 8/32C), as well as a later extension for virtual -memory (3200 series). - -The Interdata simulator is configured as follows: - -device simulates -name(s) - -CPU - 16b Interdata 3, 4, 5, 70, 80, 7/16, or 8/16 CPU with 64KB memory - Interdata 8/16E CPU with 256KB memory -CPU - 32b Interdata 7/32 or 8/32 CPU with 1MB memory -SELCH selector channel (1-4) -PT paper tape reader/punch -TT console terminal, Teletype interface -TTP console terminal, PASLA interface -LFC line frequency clock -PIC programmable interval clock -LPT line printer -FD floppy disk -DP 2.5MB/10MB cartridge disk -DM mass storage module (MSM)/intelligent (IDC) disk controller -MT magnetic tape -PAS programmable asynchronous line controller -PASL programmable asynchronous lines, up to 32 - -The Interdata simulator implements two unique stop conditions: - - - decode of an undefined instruction, and STOP_INST is set - - runaway carriage control tape in the line printer. - -The LOAD command is used to load a carriage control tape for the line -printer. The DUMP command is used to dump a contiguous portion of -memory as a self-loading bootstrap paper tape. The syntax for the DUMP -command is: - - DUMP lowaddr-highaddr - -The low address must be greater than or equal to X'D0'. - -Devices are assigned their default device numbers, as documented in the -Interdata literature. Device numbers can be changed by the command: - - SET DEVNO=num - -Device number conflicts are not checked until simulation starts. If -there is a device number conflict, simulation stops immediately with -an error message. - -Selector channel devices are assigned by default to selector channel 0. -Selector channel assignments can be changed by the command: - - SET SELCH=num - -Selector channel assignments cannot introduce conflicts. - -Most devices can be disabled and enabled, with the commands: - - SET DISABLED - SET ENABLED - -All devices are enabled by default. - -2.1 CPU (16b) - -The CPU options include memory size and CPU type: - - SET CPU I3 Interdata 3 (base instruction set) - SET CPU I4 Interdata 4 (base plus single precision - floating point) - SET CPU 716 Interdata 7/16 (extended instruction set) - (equivalent to Models 5, 70, and 80) - SET CPU 816 Interdata 8/16 (extended plus double - precision floating point) - SET CPU 816E Interdata 8/16E (extended plus double - precision plus expanded memory) - SET CPU 8K set memory size = 8KB - SET CPU 16K set memory size = 16KB - SET CPU 24K set memory size = 24KB - SET CPU 32K set memory size = 32KB - SET CPU 48K set memory size = 48KB - SET CPU 64K set memory size = 64KB - SET CPU 128K set memory size = 128KB (8/16E only) - SET CPU 256K set memory size = 256KB (8/16E only) - SET CPU CONSINT assert console interrupt (7/16, 8/16, - and 8/16E only) - -If memory size is being reduced, and the memory being truncated contains -non-zero data, the simulator asks for confirmation. Data in the truncated -portion of memory is lost. Initial memory size is 64KB. - -These switches are recognized when examining or depositing in CPU memory -(or any other byte oriented device): - - -b examine/deposit bytes - -w examine/deposit halfwords (CPU default) - -f examine/deposit fullwords - -d data radix is decimal - -o data radix is octal - -h data radix is hexadecimal - -v interpret address as virtual - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - PC 16 program counter - R0..R15 16 general registers - FR0..F14 32 single precision floating point registers - D0H..D14H 32 double precision floating point registers, - high order - D0L..D14L 32 double precision floating point registers, - low order - PSW 16 processor status word - CC 4 condition codes, PSW<12:15> - SR 16 switch register - DR 32 display register low 16 bits - DRX 8 display register extension (x/16 only) - DRMOD 1 display mode - DRPOS 2 display pointer position - SRPOS 1 switch pointer position - IRQ[0:3] 32 interrupt requests - IEN[0:3] 32 interrupt enables - STOP_INST 1 stop on undefined instruction - STOP_WAIT 1 stop if wait state and no I/O events pending - PCQ[0:63] 16 PC prior to last branch or interrupt; - most recent PC change first - WRU 8 interrupt character - -2.2 CPU (32b) - -The CPU options include memory size and CPU type: - - SET CPU 732 Interdata 7/32, single precision floating point - SET CPU DPFP Interdata 7/32, double precision floating point - SET CPU 832 Interdata 8/32 (double precision floating point) - SET CPU 64K set memory size = 64KB - SET CPU 128K set memory size = 128KB - SET CPU 256K set memory size = 256KB - SET CPU 512K set memory size = 512KB - SET CPU 1M set memory size = 1024KB - SET CPU CONSINT assert console interrupt - -If memory size is being reduced, and the memory being truncated contains -non-zero data, the simulator asks for confirmation. Data in the truncated -portion of memory is lost. Initial memory size is 1024KB. - -These switches are recognized when examining or depositing in CPU memory -(or any other byte oriented device): - - -b examine/deposit bytes - -w examine/deposit halfwords - -f examine/deposit fullwords (CPU default) - -d data radix is decimal - -o data radix is octal - -h data radix is hexadecimal - -v interpret address as virtual - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - PC 20 program counter - R0..R15 32 active general register set - GREG[32] 32 general register sets, 16 x 2 - FR0..FR14 32 single precision floating point registers - D0H..D14H 32 double precision floating point registers, - high order - D0L..D14L 32 double precision floating point registers, - low order - PSW 16 processor status word - CC 4 condition codes, PSW<12:15> - SR 16 switch register - DR 32 display register low 16 bits - DRX 8 display register extension (x/16 only) - DRMOD 1 display mode - DRPOS 2 display pointer position - SRPOS 1 switch pointer position - MACREG[0:15] 32 memory access controller segment registers - MACSTA 5 memory access controller interrupt status - IRQ[0:3] 32 interrupt requests - IEN[0:3] 32 interrupt enables - STOP_INST 1 stop on undefined instruction - STOP_WAIT 1 stop if wait state and no I/O events pending - PCQ[0:63] 20 PC prior to last branch or interrupt; - most recent PC change first - WRU 8 interrupt character - -2.3 Selector Channel (SELCH) - -An Interdata system can have 1 to 4 selector channels (SELCH0, SELCH1, -SELCH2, SELCH3). The default number of channels is 2. The number of -channels can be changed with the command: - - SET SELCH CHANNELS=num - -All the state for a selector channel can be displayed with the command: - - SHOW SELCH num - -The selector channels implement these registers: - - name size comments - - SA[0:3] 20 start address, channels 0 to 3 - EA[0:3] 20 end address, channels 0 to 3 - CMD[0:3] 8 command, channels 0 to 3 - DEV[0:3] 8 active device, channels 0 to 3 - RDP[0:3] 2 read byte pointer, channels 0 to 3 - WDC[0:3] 3 write data counter, channels 0 to 3 - IREQ 4 interrupt requests; right to left, - channels 0 to 3 - IENB 4 interrupt enables - -2.4 Programmed I/O Devices - -2.4.1 Paper Tape Reader/Punch (PT) - -The paper tape reader and punch (PT units 0 and 1) read data from or -write data to disk files. The RPOS and PPOS registers specify the -number of the next data item to be read and written, respectively. -Thus, by changing RPOS or PPOS, the user can backspace or advance -these devices. - -The paper tape reader supports the BOOT command. BOOT PTR copies the -so-called '50 loader' into memory and starts it running. - -The paper tape controller implements these registers: - - name size comments - - RBUF 8 reader buffer - RPOS 32 reader position in the input file - RTIME 24 time from reader start to interrupt - RSTOP_IOE 1 reader stop on I/O error - PBUF 8 punch buffer - PPOS 32 punch position in the output file - PTIME 24 time from punch start to interrupt - PSTOP_IOE 1 punch stop on I/O error - IREQ 1 paper tape interrupt request - IENB 1 paper tape interrupt enable - IARM 1 paper tape interrupt armed - RD 1 paper tape read/write mode - RUN 1 paper tape running - SLEW 1 paper tape reader slew mode - EOF 1 paper tape reader end of file - -Error handling is as follows: - - type error STOP_IOE processed as - - in,out not attached 1 report error and stop - 0 out of tape - - in end of file 1 report error and stop - 0 out of tape - - in,out OS I/O error x report error and stop - -2.4.2 Console, Teletype Interface (TT) - -The Teletype keyboard (TT0) reads from the console keyboard; the -Teletype printer (TT1) writes to the simulator console window. -The Teletype units (TT0, TT1) can be set to one of three modes: -KSR, 7B, or 8B. In KSR mode, lower case input and output characters -are automatically converted to upper case, and the high order bit is -forced to one on input. In 7B mode, input and output characters are -masked to 7 bits. In 8B mode, characters are not modified. Changing -the mode of either unit changes both. The default mode is KSR. - -The Teletype has a BREAK key, which is not present on today's -keyboards. To simulate pressing the break key, stop the simulator -and use the command: - - SET TT BREAK - -Break status will be asserted, and will remain asserted for the -interval specified by KTIME. - -The Teletype interface implements these registers: - - name size comments - - KBUF 8 input buffer - KPOS 32 number of characters input - KTIME 24 input polling interval - TBUF 8 output buffer - TPOS 32 number of characters output - TTIME 24 time from output start to interrupt - IREQ 1 interrupt request - IENB 1 interrupt enable - IARM 1 interrupt armed - RD 1 read/write mode - FDPX 1 half-duplex - CHP 1 input character pending - -2.4.3 Console, PASLA Interface (TTP) - -Later Interdata system connect the system console via the first -PASLA interface rather than the Teletype interface. The PASLA -console can be simulated with a Telnet session on the first PAS line. -Alternately, the PASLA console can be attached to the simulator -console window, using the TTP device in place of TT. - -To switch the simulator console window to TTP, use the command: - - SET TTP ENABLED or - SET TT DISABLED - -Device TT is automatically disabled and device TTP is enabled. -To switch the simulator console window back to TT, use the command: - - SET TT ENABLED or - SET TTP DISABLED - -Device TTP is automatically disabled and device TT is enabled. -If TTP is enabled at its default device settings, the base address -for the PAS multiplexor must be changed: - - SET PAS DEVNO=12 - -Otherwise, a device number conflict occurs. - -The PASLA keyboard (TTP0) reads from the console keyboard; the -PALSA printer (TTP1) writes to the simulator console window. -The PASLA units (TTP0, TTP1) can be set to one of three modes: -UC, 7B, or 8B. In UC mode, lower case input and output characters -are automatically converted to upper case. In 7B mode, input and -output characters are masked to 7 bits. In 8B mode, characters -are not modified. Changing the mode of either unit changes both. -The default mode is 7B. - -To simulate pressing the break key, stop the simulator and use -the command: - - SET TTP BREAK - -Break status will be asserted, and will remain asserted for the -interval specified by KTIME. - -The PASLA console interface implements these registers: - - name size comments - - CMD 16 command register - STA 8 status register - KBUF 8 input buffer - KPOS 32 number of characters input - KTIME 24 input polling interval - KIREQ 1 input interrupt request - KIENB 1 input interrupt enabled - KARM 1 input interrupt armed - CHP 1 input character pending - TBUF 8 output buffer - TPOS 32 number of characters output - TTIME 24 time from output start to interrupt - TIREQ 1 output interrupt request - TIENB 1 output interrupt enable - TIARM 1 output interrupt armed - -2.4.4 Line Printer (LPT) - -The line printer (LPT) writes data to a disk file. The POS register -specifies the number of the next data item to be written. Thus, -by changing POS, the user can backspace or advance the printer. - -In addition, the line printer can be programmed with a carriage control -tape. The LOAD command loads a new carriage control tape: - - LOAD load carriage control tape file - -The format of a carriage control tape consists of multiple lines. Each -line contains an optional repeat count, enclosed in parentheses, optionally -followed by a series of column numbers separated by commas. Column numbers -must be between 0 and 7; column seven is by convention top of form. The -following are all legal carriage control specifications: - - no punch - (5) 5 lines with no punches - 1,5,7 columns 1, 5, 7 punched - (10)2 10 lines with column 2 punched - 0 column 0 punched - -The default form is 1 line long, with all columns punched. - -The line printer implements these registers: - - name size comments - - BUF 7 last data item processed - BPTR 8 line buffer pointer - LBUF[0:131] 7 line buffer - VFUP 8 vertical forms unit pointer - VFUL 8 vertical forms unit length - VFUT[0:131] 8 vertical forms unit table - IREQ 1 line printer interrupt request - IENB 1 line printer interrupt enable - IARM 1 line printer interrupt armed - POS 32 position in the output file - CTIME 24 character processing time - STIME 24 spacing operation time - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of paper - - OS I/O error x report error and stop - -2.4.5 Line Frequency Clock (LFC) - -The line frequency clock (LFC) frequency can be adjusted as follows: - - SET LFC 60HZ set frequency to 60Hz - SET LFC 50HZ set frequency to 50Hz - -The default is 60Hz. - -The line frequency clock implements these registers: - - name size comments - - IREQ 1 clock interrupt request - IENB 1 clock interrupt enable - IARM 1 clock interrupt armed - TIME 24 clock frequency - -The line frequency clock autocalibrates; the clock interval is adjusted -up or down so that the clock tracks actual elapsed time. - -2.4.6 Programmable Interval Clock (PIC) - -The programmable interval clock (PIC) implements these registers: - - name size comments - - BUF 16 output buffer - RIC 16 reset interval and rate - CIC 12 current interval - DECR 10 current decrement value - RDP 1 read byte select - OVF 1 interval overflow flag - IREQ 1 clock interrupt request - IENB 1 clock interrupt enable - IARM 1 clock interrupt armed - -If the interval requested is an exact multiple of 1 msec, the -programmable clock auto-calibrates; if not, it counts instructions. - -2.4.7 Floppy Disk Controller (FD) - -Floppy disk options include the ability to make units write enabled or -write locked. - - SET FDn LOCKED set unit n write locked - SET FDn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFLINE. - -The floppy disk supports the BOOT command. BOOT FDn copies an autoload -sequence into memory and starts it running. - -The floppy disk controller implements these registers: - - name size comments - - CMD 8 command - STA 8 status - BUF 8 buffer - LRN 16 logical record number - ESTA[0:5] 8 extended status bytes - DBUF[0:127] 8 transfer buffer - DBPTR 8 transfer buffer pointer - IREQ 1 interrupt request - IENB 1 interrupt enabled - IARM 1 interrupt armed - CTIME 24 command response time - STIME 24 seek time, per cylinder - XTIME 24 transfer time, per byte - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -Floppy disk data is buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.4.8 Programmable Asynchronous Line Adapters (PAS, PASL) - -The Programmable Asynchronous Line Adapters (PAS and PASL) represent, -indistinguishably, individual PASLA interfaces, two lines asynchronous -multiplexors, and 8 line asynchronous multiplexors, with a maximum -of 32 lines. All the lines are modelled as a terminal multiplexor, with -PAS as the multiplexor controller, and PASL as the indivdual lines. The -PASLAs perform input and output through Telnet sessions connected to a -user-specified port. The ATTACH command specifies the port to be used: - - ATTACH PAS set up listening port - -where port is a decimal number between 1 and 65535 that is not being used -for other TCP/IP activities. - -Each line (each unit of PASL) can be set to one of three modes: UC, 7B, -or 8B. In UC mode, lower case input and output characters are converted -automatically to upper case. In 7B mode, input and output characters are -masked to 7 bits. In 8B mode, characters are not modified. The default -mode is UC. Each line (each unit of PASL) can also be set for modem -control with the command SET PASLn DATASET. The defaults are 7b mode -and DATASET disabled. - -Once PAS is attached and the simulator is running, the terminals listen -for connections on the specified port. They assume that the incoming -connections are Telnet connections. The connections remain open until -disconnected either by the Telnet client, a SET PAS DISCONNECT command, -or a DETACH PAS command. - -The SHOW PAS CONNECTIONS command displays the current connections to the -extra terminals. The SHOW PAS STATISTICS command displays statistics for -active connections. The SET PAS DISCONNECT=linenumber disconnects the -specified line. - -The controller (PAS) implements these registers: - - name size comments - - STA[0:31] 8 status, lines 0 to 31 - CMD[0:31] 16 command, lines 0 to 31 - RBUF[0:31] 8 receive buffer, lines 0 to 31 - XBUF[0:31] 8 transmit buffer, lines 0 to 31 - RIREQ 32 receive interrupt requests; - right to left, lines 0 to 31 - RIENB 32 receive interrupt enables - RARM[0:31] 1 receive interrupt armed - XIREQ 32 transmit interrupt requests; - right to left, lines 0 to 31 - XIENB 32 transmit interrupt enables - XARM[0:31] 1 transmit interrupt armed - RCHP[0:31] 1 receiver character present, lines 0 to 31 - -The lines (PASL) implements these registers: - - name size comments - - TIME[0:31] 24 transmit time, lines 0 to 31 - -The additional terminals do not support save and restore. All open -connections are lost when the simulator shuts down or PAS is detached. - -2.5 Cartridge Disk Controller (DP) - -Cartridge disk options include the ability to make units write enabled or -write locked, and to select the type of drive: - - SET DPn LOCKED set unit n write locked - SET DPn WRITEENABLED set unit n write enabled - SET DPn 2315 set unit n to 2315 (2.5MB) - SET DPn 5440 set unit n to 5440 (10MB) - -Units can also be set ONLINE or OFFLINE. - -The cartridge disk supports the BOOT command. To boot OS16/32, the hex -form of the operating system file's extension must be placed in locations -7E:7F. The disk bootstrap looks for a valid OS16/32 volume descriptor in -block 0, and uses that to locate the volume directory. It then searches -the directory for a filename of the form OS16xxxx.hhh or OS32xxxx.hhh, -where the xxxx is ignored and hhh is the ASCII form of the extension from -locations 7E:7F. The 32b bootstrap can also boot Wollongong UNIX; locations -7E:7F must be 0. The bootstrap normally boots from the first (removable) -platter in a 5440; to boot from the second (fixed) platter, use BOOT -F. - -All drives have 256 8b bytes per sector. The other disk parameters are: - - drive cylinders surfaces sectors - - 2315 203 2 24 - 5440 408 4 12 - -The cartridge disk controller implements these registers: - - name size comments - - CMD 3 current command - STA 8 controller status - BUF 8 controller buffer - HDSC 8 current head/sector select - CYL 8 current cylinder select - DBUF[0:255] 8 transfer buffer - DBPTR 16 transfer buffer point - DBLNT 16 transfer buffer length - FIRST 1 first DMA service flag - IREQ 5 interrupt requests; right-to-left, - controller, drives 0 to 3 - IENB 5 interrupt enables - IARM[0:3] 1 interrupts armed, drives 0 to 3 - STIME 24 seek latency, per cylinder - RTIME 24 rotational latency, per sector - WTIME 24 inter-word latency - -Error handling is as follows: - - error processed as - - not attached disk not ready - - end of file assume rest of disk is zero - - OS I/O error report error and stop - -2.6 Mass Storage Module/Intelligent Disk Controller (DM) - -MSM/IDC disk controller options include the ability to make units -write enabled or write locked, and to select the type of drive: - - SET DMn LOCKED set unit n write locked - SET DMn WRITEENABLED set unit n write enabled - SET DMn MSM80 set unit n to storage module, 80MB - (67MB formatted) - SET DMn MSM300 set unit n to storage module, 300MB - (262MB formatted) - SET DMn MCCD16 set unit n to medium capacity, 16MB - (13.5MB formatted) - SET DMn MCCD48 set unit n to medium capacity, 48MB - (40.5MB formatted) - SET DMn MCCD80 set unit n to medium capacity, 80MB - (67MB formatted) - SET DMn MSM330F set unit n to storage module, 330MB - (300MB formatted) - -Note that the disk bootstraps can ONLY boot the MSM80 and MSM300. -Units can be set ONLINE or OFFLINE. - -The MSM/IDC controller supports the BOOT command. To boot OS16/32, the hex -form of the operating system file's extension must be placed in locations -7E:7F. The disk bootstrap looks for a valid OS16/32 volume descriptor in -block 0, and uses that to locate the volume directory. It then searches -the directory for a filename of the form OS16xxxx.hhh or OS32xxxx.hhh, -where the xxxx is ignored and hhh is the ASCII form of the extension from -locations 7E:7F. The 32b bootstrap can also boot Wollongong UNIX; locations -7E:7F must be 0. Note that only the MSM80 and MSM300 drives can be boot- -strapped; the boot code does not recognize the other drives. - -All drives have 256 8b bytes per sector. The other disk parameters are: - - drive cylinders surfaces sectors - - MSM80 823 5 64 - MSM300 823 19 64 - MCCD16 823 1 64 - MCCD48 823 3 64 - MCCD80 823 5 64 - MSM300F 1024 16 64 - -The MSM/IDC disk controller implements these registers: - - name size comments - - STA 8 controller status - BUF 8 controller buffer - SEC 8 current sector select - DBUF[0:767] 8 transfer buffer - DBPTR 16 transfer buffer point - DBLNT 16 transfer buffer length - FIRST 1 first DMA service flag - IREQ 5 interrupt requests; right-to-left, - controller, drives 0 to 3 - IENB 5 interrupt enables - SIREQ 5 saved interrupt requests - ICARM 1 controller interrupt armed - IDARM[0:3] 1 drive interrupts armed, drives 0 to 3 - STIME 24 seek latency, per cylinder - RTIME 24 rotational latency, per sector - WTIME 24 inter-word latency - -Error handling is as follows: - - error processed as - - not attached disk not ready - - end of file assume rest of disk is zero - - OS I/O error report error and stop - -2.7 Magnetic Tape Controller (MT) - -Magnetic tape options include the ability to make units write enabled or -or write locked. - - SET MTn LOCKED set unit n write locked - SET MTn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFLINE. - -The magnetic tape supports the BOOT command. BOOT MTn copies an autoload -sequence into memory and starts it running. - -The magnetic tape controller implements these registers: - - name size comments - - CMD 8 command - STA 8 status - BUF 8 buffer - DBUF[0:65535] 8 transfer buffer - DBPTR 16 transfer buffer pointer - DBLNT 16 transfer buffer length - XFR 1 transfer in progress flag - FIRST 1 first DMA service flag - IREQ 4 interrupt requests; right to left, - drives 0 to 3 - IENB 4 interrupt enables - IARM[0:3] 1 interrupts armed, drives 0 to 3 - STOP_IOE 1 stop on I/O error - WTIME 1 word transfer time - RTIME 1 interrecord latency - UST[0:3] 8 unit status, drives 0 to 3 - POS[0:3] 32 tape position, drives 0 to 3 - -Error handling is as follows: - - error processed as - - not attached tape not ready; if STOP_IOE, stop - - end of file set error flag - - OS I/O error set error flag; if STOP_IOE, stop - -2.8 Symbolic Display and Input - -The Interdata simulator implements symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as two character string - -m display instruction mnemonics - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or -a ASCII character - " or -c two character sixbit string - alphabetic instruction mnemonic - numeric octal number - -2.8.1 16b Instruction Input - -Instruction input uses standard Interdata assembler syntax. There are -seven instruction classes: short branch, extended short branch, short -immediate, register, register-register, memory, and register-memory. - -Short branch instructions have the format - - sbop mask,address - -where the mask is a hex (decimal) number between 0 and F (15), and -the address is within +32 (forward branch) or -32 (backward branch) -of the current location. - -Extended short branch instructions have the format - - sbxop address - -where the address is within +32 or -32 of the current location. For -extended short branches, the simulator chooses the forward or backward -direction automatically. - -Short immediate instructions have the format - - siop regnum,immed - -where the register number is a hex (decimal) number, optionally -preceded by R, between 0 and F (15), and the immediate is a hex digit -between 0 and F. - -Register instructions have the format - - rop regnum - -where the register number is a hex (decimal) number, optionally -preceded by R, between 0 and F (15). - -Register-register instructions have the format - - rrop regnum,regnum - -where the register numbers are hex (decimal) numbers, optionally -preceded by R, between 0 and F (15). - -Memory instructions have the format - - mop address{(index)} - -where address is a hex number between 0 and 0xFFFF, and the index -register is a hex (decimal) number, optionally preceded by R, -between 1 and F (15). - -Register-memory instructions have the format - - rmop regnum,address{(index)} - -where the register number is a hex (decimal) number, optionally -preceded by R, between 0 and F (15), the address is a hex number -between 0 and 0xFFFF, and the index register is a hex (decimal) -number, optionally preceded by R, between 1 and F (15). - -2.8.2 32b Instruction Input - -Instruction input uses standard Interdata assembler syntax. There are -nine instruction classes: short branch, extended short branch, short -immediate, 16b immediate, 32b immediate, register, register-register, -memory, and register-memory. Addresses, where required, can be -specified as either absolute numbers or relative to the current -location (.+n or .-n). - -Short branch instructions have the format - - sbop mask,address - -where the mask is a hex (decimal) number between 0 and F (15), and -the address is within +32 (forward branch) or -32 (backward branch) -of the current location. - -Extended short branch instructions have the format - - sbxop address - -where the address is within +32 or -32 of the current location. For -extended short branches, the simulator chooses the forward or backward -direction automatically. - -Short immediate instructions have the format - - siop regnum,immed - -where the register number is a hex (decimal) number, optionally -preceded by R, between 0 and F (15), and the immediate is a hex digit -between 0 and F. - -16b immediate instructins have the format - - i16op regnum,immed16{(index)} - -where the register number is a hex (decimal) number, optionally -preceded by R, between 0 and F (15), the immediate is a hex number -between 0 and 0xFFFF, and the index register is a hex (decimal) -number, optionally preceded by R, between 1 and F (15). - -32b immediate instructions have the format - - i32op regnum,immed32{(index)} - -where the register number is a hex (decimal) number, optionally -preceded by R, between 0 and F (15), the immediate is a hex number -between 0 and 0xFFFFFFFF, and the index register is a hex (decimal) -number, optionally preceded by R, between 1 and F (15). - -Register instructions have the format - - rop regnum - -where the register number is a hex (decimal) number, optionally -preceded by R, between 0 and F (15). - -Register-register instructions have the format - - rrop regnum,regnum - -where the register numbers are hex (decimal) numbers, optionally -preceded by R, between 0 and F (15). - -Memory instructions have the format - - mop address{(index)} or - mop address{(index1,index2)} - -where address is a hex number between 0 and 0xFFFF, and the index -registers are hex (decimal) numbers, optionally preceded by R, -between 1 and F (15). - -Register-memory instructions have the format - - rmop regnum,address{(index)} or - rmop regnum,address{(index1,index2)} - -where the register number is a hex (decimal) number, optionally -preceded by R, between 0 and F (15), the address is a hex number -between 0 and 0xFFFF, and the index registers are hex (decimal) -numbers, optionally preceded by R, between 1 and F (15). - -For memory operands, the simulator automatically chooses the format -(RX1, RX2, RX3) that consumes the fewest bytes. If both RX1 and RX2 -are feasible, the simulator chooses RX1. - diff --git a/Interdata/id_dp.c b/Interdata/id_dp.c deleted file mode 100644 index ea7ab2e3..00000000 --- a/Interdata/id_dp.c +++ /dev/null @@ -1,564 +0,0 @@ -/* id_dp.c: Interdata 2.5MB/10MB cartridge disk simulator - - Copyright (c) 2001-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - dp M46-421 2.5MB/10MB cartridge disk - - 25-Apr-03 RMS Revised for extended file support - 16-Feb-03 RMS Fixed read to test transfer ok before selch operation -*/ - -#include "id_defs.h" -#include - -#define DP_NUMBY 256 /* bytes/sector */ -#define DP_NUMSC 24 /* sectors/track */ - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */ -#define UNIT_M_DTYPE 0x1 -#define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) - -#define CYL u3 /* current cylinder */ -#define STD u4 /* drive status */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -/* Controller status */ - -#define STC_OVR 0x80 /* overrun */ -#define STC_ACF 0x40 /* addr cmp fail */ -#define STC_DEF 0x20 /* def track NI */ -#define STC_CYO 0x10 /* cylinder ovflo */ -#define STC_IDL 0x02 /* ctrl idle */ -#define STC_DTE 0x01 /* xfer error */ -#define SETC_EX (STC_OVR|STC_ACF|STC_DEF|STC_CYO) -#define STC_MASK (STC_OVR|STC_ACF|STC_DEF|STC_CYO|STA_BSY|STC_IDL|STC_DTE) - -/* Controller command */ - -#define CMC_MASK 0xF -#define CMC_CLR 0x8 /* reset */ -#define CMC_RD 0x1 /* read */ -#define CMC_WR 0x2 /* write */ -#define CMC_RCHK 0x3 /* read check */ -#define CMC_RFMT 0x5 /* read fmt NI */ -#define CMC_WFMT 0x6 /* write fmt NI */ - -/* Drive status, ^ = dynamic, * = in unit status */ - -#define STD_WRP 0x80 /* ^write prot */ -#define STD_WCK 0x40 /* write check NI */ -#define STD_ILA 0x20 /* *illegal addr */ -#define STD_ILK 0x10 /* ^addr interlock */ -#define STD_MOV 0x08 /* *heads in motion */ -#define STD_INC 0x02 /* seek incomplete NI */ -#define STD_NRDY 0x01 /* ^not ready */ -#define STD_UST (STD_ILA | STD_MOV) /* set from unit */ -#define SETD_EX (STD_WCK | STD_ILA | STD_ILK) /* set examine */ - -/* Drive command */ - -#define CMD_SK 0x02 /* seek */ -#define CMD_RST 0x01 /* restore */ - -/* Head/sector register */ - -#define HS_SMASK 0x1F /* sector mask */ -#define HS_V_SRF 5 /* surface */ -#define HS_HMASK 0x20 /* head mask */ -#define HS_MASK (HS_HMASK | HS_SMASK) -#define GET_SEC(x) ((x) & HS_SMASK) -#define GET_SRF(x) (((x) & HS_HMASK) >> HS_V_SRF) - -#define GET_SA(p,cy,sf,sc,t) (((((((p)*drv_tab[t].cyl)+(cy))*drv_tab[t].surf)+(sf))* \ - DP_NUMSC)+(sc)) -#define GET_ROTATE(x) ((int) fmod (sim_gtime() / ((double) (x)), \ - ((double) DP_NUMSC))) - -/* This controller supports two different disk drive types: - - type #sectors/ #surfaces/ #cylinders/ - surface cylinder drive - - 2315 24 2 203 - 5440 24 4 408 - - In theory, each drive can be a different type. The size field in - each unit selects the drive capacity for each drive and thus the - drive type. DISKS MUST BE DECLARED IN ASCENDING SIZE AND MUST HAVE - THE SAME SECTORS/TRACK. -*/ - -#define TYPE_2315 0 -#define CYL_2315 203 -#define SURF_2315 2 -#define SIZE_2315 (DP_NUMSC * SURF_2315 * CYL_2315 * DP_NUMBY) - -#define TYPE_5440 1 -#define CYL_5440 408 -#define SURF_5440 2 -#define SIZE_5440 (2 * DP_NUMSC * SURF_5440 * CYL_5440 * DP_NUMBY) - -struct drvtyp { - int32 cyl; /* cylinders */ - uint32 surf; /* surfaces */ - uint32 size; /* #blocks */ -}; - -static struct drvtyp drv_tab[] = { - { CYL_2315, SURF_2315, SIZE_2315 }, - { CYL_5440, SURF_5440, SIZE_5440 }, - { 0 } }; - -extern uint32 int_req[INTSZ], int_enb[INTSZ]; -extern FILE *sim_log; - -uint8 dpxb[DP_NUMBY]; /* xfer buffer */ -uint32 dp_bptr = 0; /* buffer ptr */ -uint32 dp_db = 0; /* ctrl buffer */ -uint32 dp_cyl = 0; /* drive buffer */ -uint32 dp_sta = 0; /* ctrl status */ -uint32 dp_cmd = 0; /* ctrl command */ -uint32 dp_plat = 0; /* platter */ -uint32 dp_hdsc = 0; /* head/sector */ -uint32 dp_svun = 0; /* most recent unit */ -uint32 dp_1st = 0; /* first byte */ -uint32 dpd_arm[DP_NUMDR] = { 0 }; /* drives armed */ -int32 dp_stime = 100; /* seek latency */ -int32 dp_rtime = 100; /* rotate latency */ -int32 dp_wtime = 1; /* word time */ -uint32 dp_log = 0; /* debug log */ -uint8 dp_tplte[(2 * DP_NUMDR) + 2]; /* fix/rmv + ctrl + end */ - -DEVICE dp_dev; -uint32 dp (uint32 dev, uint32 op, uint32 dat); -void dp_ini (t_bool dtpl); -t_stat dp_svc (UNIT *uptr); -t_stat dp_reset (DEVICE *dptr); -t_stat dp_attach (UNIT *uptr, char *cptr); -t_stat dp_detach (UNIT *uptr); -t_stat dp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat dp_rds (UNIT *uptr); -t_stat dp_wds (UNIT *uptr); -t_bool dp_dter (UNIT *uptr, uint32 first); -void dp_done (uint32 flg); - -extern t_stat id_dboot (int32 u, DEVICE *dptr); - -/* DP data structures - - dp_dev DP device descriptor - dp_unit DP unit list - dp_reg DP register list - dp_mod DP modifier list -*/ - -DIB dp_dib = { d_DPC, 0, v_DPC, dp_tplte, &dp, &dp_ini }; - -UNIT dp_unit[] = { - { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) }, - { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) }, - { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) }, - { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) } }; - -REG dp_reg[] = { - { HRDATA (CMD, dp_cmd, 3) }, - { HRDATA (STA, dp_sta, 8) }, - { HRDATA (BUF, dp_db, 8) }, - { HRDATA (PLAT, dp_plat, 1) }, - { HRDATA (HDSC, dp_hdsc, 6) }, - { HRDATA (CYL, dp_cyl, 9) }, - { HRDATA (SVUN, dp_svun, 8), REG_HIDDEN }, - { BRDATA (DBUF, dpxb, 16, 8, DP_NUMBY) }, - { HRDATA (DBPTR, dp_bptr, 9), REG_RO }, - { FLDATA (FIRST, dp_1st, 0) }, - { GRDATA (IREQ, int_req[l_DPC], 16, DP_NUMDR + 1, i_DPC) }, - { GRDATA (IENB, int_enb[l_DPC], 16, DP_NUMDR + 1, i_DPC) }, - { BRDATA (IARM, dpd_arm, 16, 1, DP_NUMDR) }, - { DRDATA (RTIME, dp_rtime, 0), PV_LEFT | REG_NZ }, - { DRDATA (STIME, dp_stime, 0), PV_LEFT | REG_NZ }, - { DRDATA (WTIME, dp_wtime, 0), PV_LEFT | REG_NZ }, - { URDATA (UCYL, dp_unit[0].CYL, 16, 9, 0, - DP_NUMDR, REG_RO) }, - { URDATA (UST, dp_unit[0].STD, 16, 8, 0, - DP_NUMDR, REG_RO) }, - { URDATA (CAPAC, dp_unit[0].capac, 10, T_ADDR_W, 0, - DP_NUMDR, PV_LEFT | REG_HRO) }, - { FLDATA (LOG, dp_log, 0), REG_HIDDEN }, - { HRDATA (DEVNO, dp_dib.dno, 8), REG_HRO }, - { HRDATA (SELCH, dp_dib.sch, 2), REG_HRO }, - { NULL } }; - -MTAB dp_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_2315 << UNIT_V_DTYPE) + UNIT_ATT, - "2315", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_5440 << UNIT_V_DTYPE) + UNIT_ATT, - "5440", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_2315 << UNIT_V_DTYPE), - "2315", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_5440 << UNIT_V_DTYPE), - "5440", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_2315 << UNIT_V_DTYPE), - NULL, "2315", &dp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_5440 << UNIT_V_DTYPE), - NULL, "5440", &dp_set_size }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH", - &set_sch, &show_sch, NULL }, - { 0 } }; - -DEVICE dp_dev = { - "DP", dp_unit, dp_reg, dp_mod, - DP_NUMDR, 16, 24, 1, 16, 8, - NULL, NULL, &dp_reset, - &id_dboot, &dp_attach, &dp_detach, - &dp_dib, DEV_DISABLE }; - -/* Controller: IO routine */ - -uint32 dpc (uint32 dev, uint32 op, uint32 dat) -{ -uint32 f, t, u; -UNIT *uptr; -static uint8 good_cmd[8] = { 0, 1, 1, 1, 0, 0, 0, 0 }; - -switch (op) { /* case IO op */ -case IO_ADR: /* select */ - sch_adr (dp_dib.sch, dev); /* inform sel ch */ - return BY; /* byte only */ -case IO_RD: /* read data */ - if (dp_sta & STC_IDL) /* if idle */ - return GET_ROTATE (dp_rtime); /* return sector */ - else dp_sta = dp_sta | STA_BSY; /* xfr? set busy */ - return dp_db; /* return data */ -case IO_WD: /* write data */ - if (sim_log && dp_log) fprintf (sim_log, - ">>DPC WD = %02X, STA = %02X\n", dat, dp_sta); - if (dp_sta & STC_IDL) dp_hdsc = dat & HS_MASK; /* idle? hdsc */ - else { /* data xfer */ - dp_sta = dp_sta | STA_BSY; /* set busy */ - dp_db = dat & 0xFF; } /* store data */ - break; -case IO_SS: /* status */ - t = dp_sta & STC_MASK; /* get status */ - if (t & SETC_EX) t = t | STA_EX; /* test for EX */ - return t; -case IO_OC: /* command */ - if (sim_log && dp_log) fprintf (sim_log, - ">>DPC OC = %02X, STA = %02X\n", dat, dp_sta); - f = dat & CMC_MASK; /* get cmd */ - if (f & CMC_CLR) { /* clear? */ - dp_reset (&dp_dev); /* reset world */ - break; } - u = (dp_svun - dp_dib.dno - o_DP0) / o_DP0; /* get unit */ - uptr = dp_dev.units + u; /* ignore if busy */ - if (!(dp_sta & STC_IDL) || sim_is_active (uptr)) break; - dp_cmd = f; /* save cmd */ - if (dp_cmd == CMC_WR) dp_sta = 0; /* write: bsy=0 else */ - else dp_sta = STA_BSY; /* bsy=1,idl,err=0 */ - dp_1st = 1; /* xfr not started */ - dp_bptr = 0; /* buffer empty */ - if (dp_svun & o_DPF) dp_plat = 1; /* upper platter? */ - else dp_plat = 0; /* no, lower */ - if (good_cmd[f]) sim_activate (uptr, dp_rtime); /* legal? sched */ - break; } -return 0; -} - -/* Drives: IO routine */ - -uint32 dp (uint32 dev, uint32 op, uint32 dat) -{ -int32 diff; -uint32 t, u; -UNIT *uptr; - -if (dev == dp_dib.dno) return dpc (dev, op, dat); /* controller? */ -u = (dev - dp_dib.dno - o_DP0) / o_DP0; /* get unit num */ -uptr = dp_dev.units + u; /* get unit ptr */ -switch (op) { /* case IO op */ -case IO_ADR: /* select */ - if (dp_sta & STC_IDL) dp_svun = dev; /* idle? save unit */ - return BY; /* byte only */ -case IO_WD: /* write data */ - if (sim_log && dp_log) fprintf (sim_log, - ">>DP%d WD = %02X, STA = %02X\n", u, dat, dp_sta); - if (GET_DTYPE (uptr->flags) == TYPE_2315) /* 2.5MB drive? */ - dp_cyl = dat & 0xFF; /* cyl is 8b */ - else dp_cyl = ((dp_cyl << 8) | dat) & DMASK16; /* insert byte */ - break; -case IO_SS: /* status */ - if (uptr->flags & UNIT_ATT) t = /* onl? */ - ((uptr->flags & UNIT_WPRT)? STD_WRP: 0) | - ((dp_sta & STC_IDL)? 0: STD_ILK) | - (uptr->STD & STD_UST); - else t = STD_MOV | STD_NRDY; /* off = X'09' */ - if (t & SETD_EX) t = t | STA_EX; /* test for ex */ - return t; -case IO_OC: /* command */ - if (sim_log && dp_log) fprintf (sim_log, - ">>DP%d OC = %02X, STA = %02X\n", u, dat, dp_sta); - dpd_arm[u] = int_chg (v_DPC + u + 1, dat, dpd_arm[u]); - if (dat & CMD_SK) t = dp_cyl; /* seek? get cyl */ - else if (dat & CMD_RST) t = 0; /* rest? cyl 0 */ - else break; /* no action */ - diff = t - uptr->CYL; - if (diff < 0) diff = -diff; /* ABS cyl diff */ - else if (diff == 0) diff = 1; /* must be nz */ - uptr->STD = STD_MOV; /* stat = moving */ - uptr->CYL = t; /* put on cyl */ - sim_activate (uptr, diff * dp_stime); /* schedule */ - break; } -return 0; -} - -/* Unit service - - If seek done, on cylinder; - if read check, signal completion; - else, do read or write -*/ - -t_stat dp_svc (UNIT *uptr) -{ -uint32 u = uptr - dp_dev.units; /* get unit number */ -int32 cyl = uptr->CYL; /* get cylinder */ -uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */ -uint32 t; -t_stat r; - -if (uptr->STD & STD_MOV) { /* seek? */ - uptr->STD = 0; /* clr seek in prog */ - if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* offl? hangs */ - if (cyl >= drv_tab[dtype].cyl) { /* bad cylinder? */ - uptr->STD = STD_ILA; /* error */ - uptr->CYL = drv_tab[dtype].cyl - 1; } /* put at edge */ - if (dpd_arm[u]) SET_INT (v_DPC + u + 1); /* req intr */ - return SCPE_OK; } - -switch (dp_cmd & 0x7) { /* case on func */ - -case CMC_RCHK: /* read check */ - dp_dter (uptr, 1); /* check xfr err */ - break; - -case CMC_RD: /* read */ - if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* sch transfer? */ - if (dp_dter (uptr, dp_1st)) return SCPE_OK; /* check xfr err */ - if (r = dp_rds (uptr)) return r; /* read sec, err? */ - dp_1st = 0; - t = sch_wrmem (dp_dib.sch, dpxb, DP_NUMBY); /* write to memory */ - if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* more to do? */ - sim_activate (uptr, dp_rtime); /* reschedule */ - return SCPE_OK; } - break; } /* no, set done */ - - dp_sta = dp_sta | STC_DTE; /* can't work */ - break; - -case CMC_WR: /* write */ - if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* sch transfer? */ - if (dp_dter (uptr, dp_1st)) return SCPE_OK; /* check xfr err */ - dp_bptr = sch_rdmem (dp_dib.sch, dpxb, DP_NUMBY); /* read from mem */ - dp_db = dpxb[dp_bptr - 1]; /* last byte */ - if (r = dp_wds (uptr)) return r; /* write sec, err? */ - dp_1st = 0; - if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* more to do? */ - sim_activate (uptr, dp_rtime); /* reschedule */ - return SCPE_OK; } - break; } /* no, set done */ - - dp_sta = dp_sta | STC_DTE; /* can't work */ - break; } - -dp_done (0); /* done */ -return SCPE_OK; -} - -/* Read data sector */ - -t_stat dp_rds (UNIT *uptr) -{ -uint32 i; - -i = fxread (dpxb, sizeof (uint8), DP_NUMBY, uptr->fileref); -for ( ; i < DP_NUMBY; i++) dpxb[i] = 0; /* fill with 0's */ -if (ferror (uptr->fileref)) { /* error? */ - perror ("DP I/O error"); - clearerr (uptr->fileref); - dp_done (STC_DTE); - return SCPE_IOERR; } -return SCPE_OK; -} - -/* Write data sector */ - -t_stat dp_wds (UNIT *uptr) -{ -for ( ; dp_bptr < DP_NUMBY; dp_bptr++) - dpxb[dp_bptr] = dp_db; /* fill with last */ -fxwrite (dpxb, sizeof (uint8), DP_NUMBY, uptr->fileref); -if (ferror (uptr->fileref)) { /* error? */ - perror ("DP I/O error"); - clearerr (uptr->fileref); - dp_done (STC_DTE); - return SCPE_IOERR; } -return SCPE_OK; -} - -/* Data transfer error test routine */ - -t_bool dp_dter (UNIT *uptr, uint32 first) -{ -uint32 hd, sc, sa; -uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */ - -if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */ - ((uptr->flags & UNIT_WPRT) && (dp_cmd == CMC_WR))) { - dp_done (STC_DTE); /* error, done */ - return TRUE; } -hd = GET_SRF (dp_hdsc); /* get head */ -sc = GET_SEC (dp_hdsc); /* get sector */ -if (dp_cyl != (uint32) uptr->CYL) { /* wrong cylinder? */ - if (dp_cyl == 0) uptr->CYL = 0; - else { - dp_done (STC_ACF); /* error, done */ - return TRUE; } } -if (sc >= DP_NUMSC) { /* bad sector? */ - dp_done (STC_OVR); /* error, done */ - return TRUE; } -if (!first && (sc == 0) && (hd == 0)) { /* cyl overflow? */ - dp_done (STC_CYO); /* error, done */ - return TRUE; } -sa = GET_SA (dp_plat, uptr->CYL, hd, sc, dtype); /* curr disk addr */ -fseek (uptr->fileref, sa * DP_NUMBY, SEEK_SET); -if ((sc + 1) < DP_NUMSC) dp_hdsc = dp_hdsc + 1; /* end of track? */ -else dp_hdsc = (dp_hdsc ^ HS_HMASK) & HS_HMASK; /* sec 0, nxt srf */ -return FALSE; -} - -/* Data transfer done routine */ - -void dp_done (uint32 flg) -{ -dp_sta = (dp_sta | STC_IDL | flg) & ~STA_BSY; /* set flag, idle */ -SET_INT (v_DPC); /* unmaskable intr */ -if (flg) sch_stop (dp_dib.sch); /* if err, stop ch */ -return; -} - -/* Reset routine */ - -t_stat dp_reset (DEVICE *dptr) -{ -uint32 u; -UNIT *uptr; - -dp_cmd = 0; /* clear cmd */ -dp_sta = STA_BSY | STC_IDL; /* idle, busy */ -dp_1st = 0; /* clear flag */ -dp_svun = dp_db = 0; /* clear unit, buf */ -dp_plat = 0; -dp_hdsc = 0; /* clear addr */ -CLR_INT (v_DPC); /* clear ctrl int */ -SET_ENB (v_DPC); /* always enabled */ -for (u = 0; u < DP_NUMDR; u++) { /* loop thru units */ - uptr = dp_dev.units + u; - uptr->CYL = uptr->STD = 0; - CLR_INT (v_DPC + u + 1); /* clear intr */ - CLR_ENB (v_DPC + u + 1); /* clear enable */ - dpd_arm[u] = 0; /* clear arm */ - sim_cancel (uptr); } /* cancel activity */ -return SCPE_OK; -} - -/* Attach routine (with optional autosizing) */ - -t_stat dp_attach (UNIT *uptr, char *cptr) -{ -uint32 i, p; -t_stat r; - -uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size; -r = attach_unit (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* error? */ -uptr->CYL = 0; -if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ -if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK; -if ((p = ftell (uptr->fileref)) == 0) return SCPE_OK; -for (i = 0; drv_tab[i].surf != 0; i++) { - if (p <= drv_tab[i].size) { - uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); - uptr->capac = drv_tab[i].size; - return SCPE_OK; } } -return SCPE_OK; -} - -/* Detach routine (generates an interrupt) */ - -t_stat dp_detach (UNIT *uptr) -{ -uint32 u = uptr - dp_dev.units; - -if (dpd_arm[u]) SET_INT (v_DPC + u + 1); /* if arm, intr */ -return detach_unit (uptr); -} - -/* Set size command validation routine */ - -t_stat dp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = drv_tab[GET_DTYPE (val)].size; -return SCPE_OK; -} - -/* Create device number (T) or interrupt (F) template */ - -void dp_ini (t_bool dtpl) -{ -int32 u, j, dev; - -dp_tplte[0] = 0; /* controller */ -for (u = 0, j = 1; u < DP_NUMDR; u++) { /* loop thru units */ - dev = (u + 1) * o_DP0; /* drive dev # */ - dp_tplte[j++] = dev; - if (dtpl && (GET_DTYPE (dp_unit[u].flags) == TYPE_5440)) - dp_tplte[j++] = dev + o_DPF; } /* if fixed */ -dp_tplte[j] = TPL_END; /* end marker */ -return; -} diff --git a/Interdata/id_fd.c b/Interdata/id_fd.c deleted file mode 100644 index a15b71e2..00000000 --- a/Interdata/id_fd.c +++ /dev/null @@ -1,479 +0,0 @@ -/* id_fd.c: Interdata floppy disk simulator - - Copyright (c) 2001-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - fd M46-630 floppy disk - - A diskette consists of 77 tracks, each with 26 sectors of 128B. The - Interdata floppy uses a logical record numbering scheme from 1 to 2002. - Physical tracks are numbered 0-76, physical sectors 1-26. - - To allow for deleted data handling, a directory is appended to the end - of the image, one byte per LRN. Zero (the default) is a normal record, - non-zero a deleted record. -*/ - -#include "id_defs.h" - -#define FD_NUMTR 77 /* tracks/disk */ -#define FD_NUMSC 26 /* sectors/track */ -#define FD_NUMBY 128 /* bytes/sector */ -#define FD_NUMLRN (FD_NUMTR * FD_NUMSC) /* LRNs/disk */ -#define FD_SIZE (FD_NUMLRN * FD_NUMBY) /* bytes/disk */ -#define FD_NUMDR 4 /* drives/controller */ -#define UNIT_V_WLK (UNIT_V_UF) /* write locked */ -#define UNIT_WLK (1u << UNIT_V_UF) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ -#define LRN u3 /* last LRN */ -#define FNC u4 /* last function */ -#define GET_DA(x) (((x) - 1) * FD_NUMBY) -#define GET_TRK(x) (((x) - 1) / FD_NUMSC) -#define GET_SEC(x) ((((x) - 1) % FD_NUMSC) + 1) -#define LRN_BOOT 5 /* boot block LRN */ - -/* Command byte */ - -#define CMD_V_UNIT 4 /* unit */ -#define CMD_M_UNIT 0x3 -#define GET_UNIT(x) (((x) >> CMD_V_UNIT) & CMD_M_UNIT) -#define CMD_V_FNC 0 /* function */ -#define CMD_M_FNC 0xF -#define GET_FNC(x) (((x) >> CMD_V_FNC) & CMD_M_FNC) -#define FNC_RD 0x1 /* read */ -#define FNC_WR 0x2 /* write */ -#define FNC_RDID 0x3 /* read ID */ -#define FNC_RSTA 0x4 /* read status */ -#define FNC_DEL 0x5 /* write deleted */ -#define FNC_BOOT 0x6 /* boot */ -#define FNC_STOP 0x7 /* stop */ -#define FNC_RESET 0x8 /* reset */ -#define FNC_FMT 0x9 /* format NI */ -#define FNC_STOPPING 0x10 /* stopping */ - -/* Status byte, * = dynamic */ - -#define STA_WRP 0x80 /* *write prot */ -#define STA_DEF 0x40 /* def track NI */ -#define STA_DEL 0x20 /* del record */ -#define STA_ERR 0x10 /* error */ -#define STA_IDL 0x02 /* idle */ -#define STA_OFL 0x01 /* fault */ -#define STA_MASK (STA_DEF|STA_DEL|STA_ERR|STA_BSY|STA_IDL) -#define SET_EX (STA_ERR) /* set EX */ - -/* Extended status, 6 bytes, * = dynamic */ - -#define ES_SIZE 6 -#define ES0_HCRC 0x80 /* ID CRC NI */ -#define ES0_DCRC 0x40 /* data CRC NI */ -#define ES0_LRN 0x20 /* illegal LRN */ -#define ES0_WRP 0x10 /* *write prot */ -#define ES0_ERR 0x08 /* error */ -#define ES0_DEF 0x04 /* def trk NI */ -#define ES0_DEL 0x02 /* del rec NI */ -#define ES0_FLT 0x01 /* fault */ -#define ES1_TK0 0x80 /* track 0 */ -#define ES1_NRDY 0x40 /* not ready */ -#define ES1_NOAM 0x20 /* no addr mk NI */ -#define ES1_CMD 0x10 /* illegal cmd */ -#define ES1_SKE 0x08 /* seek err NI */ -#define ES1_UNS 0x04 /* unsafe NI */ -#define ES1_UNIT 0x03 /* unit # */ - -/* Processing options for commands */ - -#define C_RD 0x1 /* cmd reads disk */ -#define C_WD 0x2 /* cmd writes disk */ - -extern uint32 int_req[INTSZ], int_enb[INTSZ]; - -uint32 fd_sta = 0; /* status */ -uint32 fd_cmd = 0; /* command */ -uint32 fd_db = 0; /* data buffer */ -uint32 fd_bptr = 0; /* buffer pointer */ -uint8 fdxb[FD_NUMBY] = { 0 }; /* sector buffer */ -uint8 fd_es[FD_NUMDR][ES_SIZE] = { 0 }; /* ext status */ -uint32 fd_lrn = 0; /* log rec # */ -uint32 fd_wdv = 0; /* wd valid */ -uint32 fd_stopioe = 1; /* stop on error */ -uint32 fd_arm = 0; /* intr arm */ -int32 fd_ctime = 100; /* command time */ -int32 fd_stime = 10; /* seek, per LRN */ -int32 fd_xtime = 1; /* tr set time */ - -static uint32 ctab[16] = { - 0, C_RD, C_WD, 0, /* 0, rd, wr, 0 */ - 0, C_WD, C_RD, 0, /* 0, del, boot, 0 */ - 0, 0, 0, 0, - 0, 0, 0, 0 }; - -DEVICE fd_dev; -uint32 fd (uint32 dev, uint32 op, uint32 dat); -t_stat fd_svc (UNIT *uptr); -t_stat fd_reset (DEVICE *dptr); -t_stat fd_clr (DEVICE *dptr); -t_stat fd_boot (int32 unitno, DEVICE *dptr); -t_bool fd_dte (UNIT *uptr, t_bool wr); -uint32 fd_crc (uint32 crc, uint32 dat, uint32 cnt); -void fd_done (uint32 u, uint32 nsta, uint32 nes0, uint32 nes1); -void sched_seek (UNIT *uptr, int32 newlrn); - -/* FD data structures - - fd_dev FD device descriptor - fd_unit FD unit list - fd_reg FD register list - fd_mod FD modifier list -*/ - -DIB fd_dib = { d_FD, -1, v_FD, NULL, &fd, NULL }; - -UNIT fd_unit[] = { - { UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) }, - { UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) }, - { UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) }, - { UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) } }; - -REG fd_reg[] = { - { HRDATA (CMD, fd_cmd, 8) }, - { HRDATA (STA, fd_sta, 8) }, - { HRDATA (BUF, fd_db, 8) }, - { HRDATA (LRN, fd_lrn, 16) }, - { BRDATA (ESTA, fd_es, 16, 8, ES_SIZE * FD_NUMDR) }, - { BRDATA (DBUF, fdxb, 16, 8, FD_NUMBY) }, - { HRDATA (DBPTR, fd_bptr, 8) }, - { FLDATA (WDV, fd_wdv, 0) }, - { FLDATA (IREQ, int_req[l_FD], i_FD) }, - { FLDATA (IENB, int_enb[l_FD], i_FD) }, - { FLDATA (IARM, fd_arm, 0) }, - { DRDATA (CTIME, fd_ctime, 24), PV_LEFT }, - { DRDATA (STIME, fd_stime, 24), PV_LEFT }, - { DRDATA (XTIME, fd_xtime, 24), PV_LEFT }, - { FLDATA (STOP_IOE, fd_stopioe, 0) }, - { URDATA (ULRN, fd_unit[0].LRN, 16, 16, 0, FD_NUMDR, REG_HRO) }, - { URDATA (UFNC, fd_unit[0].FNC, 16, 8, 0, FD_NUMDR, REG_HRO) }, - { HRDATA (DEVNO, fd_dib.dno, 8), REG_HRO }, - { NULL } }; - -MTAB fd_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE fd_dev = { - "FD", fd_unit, fd_reg, fd_mod, - FD_NUMDR, 16, 20, 1, 16, 8, - NULL, NULL, &fd_reset, - &fd_boot, NULL, NULL, - &fd_dib, DEV_DISABLE }; - -/* Floppy disk: IO routine */ - -uint32 fd (uint32 dev, uint32 op, uint32 dat) -{ -int32 u, t, fnc; -UNIT *uptr; - -fnc = GET_FNC (fd_cmd); /* get fnc */ -u = GET_UNIT (fd_cmd); /* get unit */ -uptr = fd_dev.units + u; -switch (op) { /* case IO op */ -case IO_ADR: /* select */ - return BY; /* byte only */ -case IO_RD: /* read */ - if (fd_sta & (STA_IDL | STA_BSY)) return fd_db; /* idle, busy? */ - if (fd_bptr < FD_NUMBY) fd_db = fdxb[fd_bptr++];/* get byte */ - if (fd_bptr >= FD_NUMBY) { /* buf end? */ - if (ctab[fnc] & C_RD) { /* disk read? */ - sched_seek (uptr, uptr->LRN + 1); /* sched read */ - fd_sta = fd_sta | STA_BSY; } /* set busy */ - else fd_bptr = 0; } /* just wrap */ - if ((ctab[fnc] & C_RD) && fd_arm) /* if rd & arm, */ - SET_INT (v_FD); /* interrupt */ - return fd_db; /* return buf */ -case IO_WD: /* write */ - if (fd_sta & STA_IDL) { /* idle? */ - fd_lrn = ((fd_lrn << 8) | dat) & DMASK16; /* insert byte */ - fd_wdv = 1; - break; } - if (fd_bptr < FD_NUMBY) /* if room, */ - fdxb[fd_bptr++] = fd_db = dat; /* store byte */ - if (fd_bptr >= FD_NUMBY) { /* buf end? */ - if (ctab[fnc] & C_WD) { /* disk write? */ - sched_seek (uptr, uptr->LRN + 1); /* sched write */ - fd_sta = fd_sta | STA_BSY; } /* set busy */ - else fd_bptr = 0; } /* just wrap */ - if ((ctab[fnc] & C_WD) && fd_arm) /* if wr & arm, */ - SET_INT (v_FD); /* interrupt */ - break; -case IO_SS: /* status */ - t = fd_sta & STA_MASK; /* get status */ - if ((uptr->flags & UNIT_ATT) == 0) t = t | STA_DU; - if (t & SET_EX) t = t | STA_EX; /* test for ex */ - return t; -case IO_OC: /* command */ - fd_arm = int_chg (v_FD, dat, fd_arm); /* upd int ctrl */ - fnc = GET_FNC (dat); /* new fnc */ - fd_cmd = dat; /* save cmd */ - u = GET_UNIT (dat); /* get unit */ - uptr = fd_dev.units + u; - if (fnc == FNC_STOP) { /* stop? */ - uptr->FNC = uptr->FNC | FNC_STOPPING; /* flag stop */ - if (sim_is_active (uptr)) break; /* busy? cont */ - if (ctab[GET_FNC (uptr->FNC)] & C_WD) { /* write? */ - sched_seek (uptr, uptr->LRN + 1); /* sched write */ - fd_sta = fd_sta | STA_BSY; } /* set busy */ - else fd_done (u, 0, 0, 0); /* nrml done */ - break; } - else if (fd_sta & STA_IDL) { /* must be idle */ - if (fnc != FNC_RSTA) { /* !rd status */ - fd_sta = STA_BSY; /* busy, !idle */ - fd_es[u][0] = 0; - fd_es[u][1] = u; } /* init ext sta */ - else fd_sta = (fd_sta & ~STA_IDL) | STA_BSY; - if (fnc == FNC_BOOT) t = LRN_BOOT; /* boot? fixed sec */ - else if (fd_wdv) t = fd_lrn; /* valid data? use */ - else t = uptr->LRN; /* use prev */ - fd_wdv = 0; /* data invalid */ - fd_bptr = 0; /* init buffer */ - uptr->FNC = fnc; /* save function */ - uptr->LRN = t; /* save LRN */ - if (ctab[fnc] & C_RD) sched_seek (uptr, t); /* seek now? */ - else sim_activate (uptr, fd_ctime); } /* start cmd */ - break; } -return 0; -} - -/* Unit service; the action to be taken depends on command */ - -t_stat fd_svc (UNIT *uptr) -{ -uint32 i, u, tk, sc, crc, fnc, da; - -u = uptr - fd_dev.units; /* get unit number */ -fnc = GET_FNC (uptr->FNC); /* get function */ -switch (fnc) { /* case on function */ - -case FNC_RESET: /* reset */ - fd_clr (&fd_dev); /* clear device */ - fd_done (u, 0, 0, 0); /* set idle */ - return SCPE_OK; - -case FNC_STOP: /* stop */ - fd_done (u, 0, 0, 0); /* set idle */ - return SCPE_OK; - -case FNC_BOOT: /* boot, buf empty */ -case FNC_RD: /* read, buf empty */ - if (uptr->FNC & FNC_STOPPING) break; /* stopped? */ - if (fd_dte (uptr, FALSE)) return SCPE_OK; /* xfr error? */ - da = GET_DA (uptr->LRN); /* get disk addr */ - for (i = 0; i < FD_NUMBY; i++) /* read sector */ - fdxb[i] = *(((uint8 *) uptr->filebuf) + da + i); - if (*(((uint8 *) uptr->filebuf) + FD_SIZE + uptr->LRN - 1)) { - fd_sta = fd_sta | STA_DEL; /* deleted? set err */ - fd_es[u][0] = fd_es[u][0] | ES0_DEL; } - fd_es[u][2] = GET_SEC (uptr->LRN); /* set ext sec/trk */ - fd_es[u][3] = GET_TRK (uptr->LRN); - fd_bptr = 0; /* init buf */ - uptr->LRN = uptr->LRN + 1; /* next block */ - break; - -case FNC_WR: case FNC_DEL: /* write block */ - if (fd_dte (uptr, TRUE)) return SCPE_OK; /* xfr error? */ - if (fd_bptr) { /* any transfer? */ - da = GET_DA (uptr->LRN); /* get disk addr */ - for (i = fd_bptr; i < FD_NUMBY; i++) /* pad sector */ - fdxb[i] = fd_db; - for (i = 0; i < FD_NUMBY; i++) /* write sector */ - *(((uint8 *) uptr->filebuf) + da + i) = fdxb[i]; - *(((uint8 *) uptr->filebuf) + FD_SIZE + uptr->LRN - 1) = - (fnc == FNC_DEL)? 1: 0; /* write dir */ - uptr->hwmark = uptr->capac; /* rewrite all */ - fd_es[u][2] = GET_SEC (uptr->LRN); /* set ext sec/trk */ - fd_es[u][3] = GET_TRK (uptr->LRN); - fd_bptr = 0; /* init buf */ - uptr->LRN = uptr->LRN + 1; } /* next block */ - break; - -case FNC_RSTA: /* read status */ - if (uptr->flags & UNIT_WPRT) /* wr protected? */ - fd_es[u][0] = fd_es[u][0] | ES0_WRP; - if (GET_TRK (uptr->LRN) == 0) /* on track 0? */ - fd_es[u][1] = fd_es[u][1] | ES1_TK0; - if ((uptr->flags & UNIT_BUF) == 0) { /* not attached? */ - fd_es[u][0] = fd_es[u][0] | ES0_FLT; /* set err */ - fd_es[u][1] = fd_es[u][1] | ES1_NRDY; } - for (i = 0; i < ES_SIZE; i++) fdxb[i] = fd_es[u][i]; /* copy to buf */ - for (i = ES_SIZE; i < FD_NUMBY; i++) fdxb[i] = 0; - break; - -case FNC_RDID: /* read ID */ - if ((uptr->flags & UNIT_BUF) == 0) { /* not attached? */ - fd_done (u, STA_ERR, ES0_ERR | ES0_FLT, ES1_NRDY); - return SCPE_OK; } - for (i = 0; i < FD_NUMBY; i++) fdxb[i] = 0; /* clr buf */ - tk = GET_TRK (uptr->LRN); /* get track */ - sc = GET_SEC (uptr->LRN); /* get sector */ - fdxb[0] = tk & 0xFF; /* store track */ - fdxb[2] = sc & 0xFF; /* store sector */ - crc = fd_crc (0xFFFF, 0xFE00, 8); /* CRC addr mark */ - crc = fd_crc (crc, tk << 8, 16); /* CRC track */ - crc = fd_crc (crc, sc << 8, 16); /* CRC sector */ - fdxb[4] = (crc >> 8) & 0xFF; /* store CRC */ - fdxb[5] = crc & 0xFF; - break; - -case FNC_FMT: /* format */ -default: - fd_done (u, STA_ERR, ES0_ERR, ES1_CMD); /* ill cmd */ - uptr->LRN = 1; /* on track 0 */ - return SCPE_OK; } - -if (uptr->FNC & FNC_STOPPING) { /* stopping? */ - uptr->FNC = FNC_STOP; /* fnc = STOP */ - sim_activate (uptr, fd_ctime); } /* schedule */ -fd_sta = fd_sta & ~STA_BSY; /* clear busy */ -if (fd_arm) SET_INT (v_FD); /* if armed, int */ -return SCPE_OK; -} - -/* Schedule seek */ - -void sched_seek (UNIT *uptr, int32 newlrn) -{ -int32 diff = newlrn - uptr->LRN; /* LRN diff */ - -if (diff < 0) diff = -diff; /* ABS */ -if (diff < 10) diff = 10; /* MIN 10 */ -sim_activate (uptr, diff * fd_stime); /* schedule */ -return; -} - -/* Command complete */ - -void fd_done (uint32 u, uint32 nsta, uint32 nes0, uint32 nes1) -{ -fd_sta = (fd_sta | STA_IDL | nsta) & ~STA_BSY; /* set idle */ -if (fd_arm) SET_INT (v_FD); /* if armed, int */ -fd_es[u][0] = fd_es[u][0] | nes0; /* set ext state */ -fd_es[u][1] = fd_es[u][1] | nes1; -return; -} - -/* Test for data transfer error */ - -t_bool fd_dte (UNIT *uptr, t_bool wr) -{ -uint32 u = uptr - fd_dev.units; - -if ((uptr->flags & UNIT_BUF) == 0) { /* not attached? */ - fd_done (u, STA_ERR, ES0_ERR | ES0_FLT, ES1_NRDY); - return TRUE; } -if (wr && (uptr->flags & UNIT_WPRT)) { /* wr protected? */ - fd_done (u, STA_ERR, ES0_ERR | ES0_WRP, 0); - return TRUE; } -if ((uptr->LRN == 0) || (uptr->LRN > FD_NUMLRN)) { /* bad LRN? */ - fd_done (u, STA_ERR, ES0_ERR | ES0_LRN, 0); - return TRUE; } -return FALSE; -} - -/* Header CRC calculation */ - -uint32 fd_crc (uint32 crc, uint32 dat, uint32 cnt) -{ -uint32 i, wrk; - -for (i = 0; i < cnt; i++) { - wrk = crc ^ dat; - crc = (crc << 1) & DMASK16; - if (wrk & SIGN16) crc = ((crc ^ 0x1020) + 1) & DMASK16; - dat = (dat << 1) & DMASK16; } -return crc; -} - -/* Reset routine */ - -t_stat fd_clr (DEVICE *dptr) -{ -int32 i, j; -UNIT *uptr; - -fd_sta = STA_IDL; /* idle */ -fd_cmd = 0; /* clear state */ -fd_db = 0; -fd_bptr = 0; -fd_lrn = 1; -fd_wdv = 0; -for (i = 0; i < FD_NUMBY; i++) fdxb[i] = 0; /* clr xfr buf */ -for (i = 0; i < FD_NUMDR; i++) { /* loop thru units */ - for (j = 0; j < ES_SIZE; j++) fd_es[i][j] = 0; /* clr ext sta */ - fd_es[i][2] = 1; /* sector 1 */ - uptr = fd_dev.units + i; - sim_cancel (uptr); /* stop drive */ - uptr->LRN = 1; /* clear state */ - uptr->FNC = 0; } -return SCPE_OK; -} - -t_stat fd_reset (DEVICE *dptr) -{ -CLR_INT (v_FD); /* clear int */ -CLR_ENB (v_FD); /* disable int */ -fd_arm = 0; /* disarm int */ -return fd_clr (dptr);; -} - -/* Bootstrap routine */ - -#define BOOT_START 0x50 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8)) - -static uint8 boot_rom[] = { - 0xD5, 0x00, /* ST: AL CF */ - 0x00, 0xCF, - 0x43, 0x00, /* BR 80 */ - 0x00, 0x80 -}; - -t_stat fd_boot (int32 unitno, DEVICE *dptr) -{ -extern uint32 PC, dec_flgs; -extern uint16 decrom[]; - -if (decrom[0xD5] & dec_flgs) return SCPE_NOFNC; /* AL defined? */ -IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy boot */ -IOWriteB (AL_DEV, fd_dib.dno); /* set dev no */ -IOWriteB (AL_IOC, 0x86 + (unitno << CMD_V_UNIT)); /* set dev cmd, unit num */ -IOWriteB (AL_SCH, 0); /* clr sch dev no */ -PC = BOOT_START; -return SCPE_OK; -} diff --git a/Interdata/id_fp.c b/Interdata/id_fp.c deleted file mode 100644 index 24136f72..00000000 --- a/Interdata/id_fp.c +++ /dev/null @@ -1,471 +0,0 @@ -/* id_fp.c: Interdata floating point instructions - - Copyright (c) 2000-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - The Interdata uses IBM 360 floating point format: - - 0 7 8 15 23 31 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |S| exponent | fraction | :single - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | fraction low | :double - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - where S = 0 for plus, 1 for minus - exponent = 16**n, in excess 64 code - fraction = .hhhhhh, seen as 6-14 hexadecimal digits - - Numbers can be normalized or unnormalized but are always normalized - when loaded. - - Interdata has 8 floating point registers, F0, F2, ... , FE. In floating - point instructions, the low order bit of the register number is ignored. - - On floating point overflow, the exponent and fraction are set to 1's. - On floating point underflow, the exponent and fraction are set to 0's. - - Interdata has both 32b only and 32b/64b floating point implementations. - In 32b only implementations, add and subtract are truncated, but multiply - and divide are rounded, and the floating point registers are kept in - memory. In 64b implementations, all single precision precision operations - are rounded, double precision operations are truncated, and the floating - point registers are kept in separate hardware arrays. -*/ - -#include "id_defs.h" - -struct ufp { /* unpacked fp */ - int32 sign; /* sign */ - int32 exp; /* unbiased exp */ - uint32 h; /* fr high */ - uint32 l; }; /* fr low */ - -#define FP_V_SIGN 31 /* sign */ -#define FP_M_SIGN 0x1 -#define FP_GETSIGN(x) (((x) >> FP_V_SIGN) & FP_M_SIGN) -#define FP_V_EXP 24 /* exponent */ -#define FP_M_EXP 0x7F -#define FP_GETEXP(x) (((x) >> FP_V_EXP) & FP_M_EXP) -#define FP_V_FRH 0 /* fraction */ -#define FP_M_FRH 0xFFFFFF -#define FP_GETFRH(x) (((x) >> FP_V_FRH) & FP_M_FRH) -#define FP_GETFRL(x) (x) - -#define FP_BIAS 0x40 /* exp bias */ -#define FP_CARRY (1 << FP_V_EXP ) /* carry out */ -#define FP_NORM (0xF << (FP_V_EXP - 4)) /* normalized */ -#define FP_ROUND 0x80000000 - -/* Double precision fraction add/subtract/compare */ - -#define FR_ADD(d,s) d.l = (d.l + s.l) & DMASK32; \ - d.h = (d.h + s.h + (d.l < s.l)) & DMASK32 - -#define FR_SUB(d,s) d.h = (d.h - s.h - (d.l < s.l)) & DMASK32; \ - d.l = (d.l - s.l) & DMASK32 - -#define FR_GE(s1,s2) ((s1.h > s2.h) || \ - ((s1.h == s2.h) && (s1.l >= s2.l))) - -/* Variable and constant shifts; for constants, 0 < k < 32 */ - -#define FR_RSH_V(v,s) if ((s) < 32) { \ - v.l = ((v.l >> (s)) | \ - (v.h << (32 - (s)))) & DMASK32; \ - v.h = (v.h >> (s)) & DMASK32; } \ - else { v.l = v.h >> ((s) - 32); \ - v.h = 0; } - -#define FR_RSH_K(v,s) v.l = ((v.l >> (s)) | \ - (v.h << (32 - (s)))) & DMASK32; \ - v.h = (v.h >> (s)) & DMASK32 - -#define FR_LSH_K(v,s) v.h = ((v.h << (s)) | \ - (v.l >> (32 - (s)))) & DMASK32; \ - v.l = (v.l << (s)) & DMASK32 - -#define Q_RND(op) (OP_DPFP (op) == 0) -#define Q_RND_AS(op) ((OP_DPFP (op) == 0) && fp_in_hwre) - -extern uint32 *R; -extern uint32 F[8]; -extern dpr_t D[8]; -extern uint16 decrom[]; -extern uint32 fp_in_hwre; -extern uint32 ReadF (uint32 loc, uint32 rel); -extern void WriteF (uint32 loc, uint32 dat, uint32 rel); -void ReadFP2 (struct ufp *fop, uint32 op, uint32 r2, uint32 ea); -void UnpackFPR (struct ufp *fop, uint32 op, uint32 r1); -void NormUFP (struct ufp *fop); -uint32 StoreFPR (struct ufp *fop, uint32 op, uint32 r1, uint32 rnd); -uint32 StoreFPX (struct ufp *fop, uint32 op, uint32 r1); - -/* Floating point load */ - -uint32 f_l (uint32 op, uint32 r1, uint32 r2, uint32 ea) -{ -struct ufp fop2; - -ReadFP2 (&fop2, op, r2, ea); /* get op, normalize */ -return StoreFPR (&fop2, op, r1, 0); /* store, chk unflo */ -} - -/* Floating point compare */ - -uint32 f_c (uint32 op, uint32 r1, uint32 r2, uint32 ea) -{ -struct ufp fop1, fop2; - -ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */ -UnpackFPR (&fop1, op, r1); /* get op1, norm */ -if (fop1.sign ^ fop2.sign) /* signs differ? */ - return (fop2.sign? CC_G: (CC_C | CC_L)); -if (fop1.exp != fop2.exp) /* exps differ? */ - return (((fop1.exp > fop2.exp) ^ fop1.sign)? CC_G: (CC_C | CC_L)); -if (fop1.h != fop2.h) /* hi fracs differ? */ - return (((fop1.h > fop2.h) ^ fop1.sign)? CC_G: (CC_C | CC_L)); -if (OP_DPFP (op) && (fop1.l != fop2.l)) /* dp: low fracs diff? */ - return (((fop1.l > fop2.l) ^ fop1.sign)? CC_G: (CC_C | CC_L)); -return 0; -} - -/* Floating to integer conversion */ - -uint32 f_fix (uint32 op, uint32 r1, uint32 r2) /* 16b */ -{ -struct ufp res; -uint32 cc; - -UnpackFPR (&res, op, r2); /* get op2, norm */ -if ((res.h == 0) || (res.exp < 0x41)) { /* result zero? */ - R[r1] = 0; - return 0; } -if ((res.exp > 0x44) || /* result too big? */ - ((res.exp == 0x44) && (res.h >= 0x00800000))) { - res.h = MMASK16; - cc = CC_V; } -else { res.h = res.h >> ((0x46 - res.exp) * 4); /* right align frac */ - cc = 0; } -if (res.sign) { - R[r1] = ((res.h ^ DMASK16) + 1) & DMASK16; /* negate result */ - return cc | CC_L; } -R[r1] = res.h & DMASK16; -return cc | CC_G; -} - -uint32 f_fix32 (uint32 op, uint32 r1, uint32 r2) /* 32b */ -{ -struct ufp res; -uint32 cc; - -UnpackFPR (&res, op, r2); /* get op2, norm */ -if ((res.h == 0) || (res.exp < 0x41)) { /* result zero? */ - R[r1] = 0; - return 0; } -if ((res.exp > 0x48) || /* result too big? */ - ((res.exp == 0x48) && (res.h >= 0x00800000))) { - res.h = MMASK32; - cc = CC_V; } -else { FR_LSH_K (res, 8); /* get all in 32b */ - res.h = res.h >> ((0x48 - res.exp) * 4); /* right align frac */ - cc = 0; } -if (res.sign) { - R[r1] = (res.h ^ DMASK32) + 1; /* negate result */ - return cc | CC_L; } -R[r1] = res.h; -return cc | CC_G; -} - -/* Integer to floating conversion */ - -uint32 f_flt (uint32 op, uint32 r1, uint32 r2) /* 16b */ -{ -struct ufp res = { 0, 0x44, 0, 0 }; /* +, 16**4 */ -uint32 cc; - -if (R[r2] == 0) cc = 0; /* zero arg? */ -else if (R[r2] & SIGN16) { /* neg arg? */ - res.sign = FP_M_SIGN; /* set sign */ - res.h = ((~R[r2] + 1) & DMASK16) << 8; /* get magnitude */ - cc = CC_L; } -else { res.h = R[r2] << 8; /* pos nz arg */ - cc = CC_G; } -NormUFP (&res); /* normalize */ -StoreFPR (&res, op, r1, 0); /* store result */ -return cc; -} - -uint32 f_flt32 (uint32 op, uint32 r1, uint32 r2) /* 32b */ -{ -struct ufp res = { 0, 0x48, 0, 0 }; /* +, 16**8 */ -uint32 cc, t; - -t = R[r2]; /* int op */ -if (t) { /* nonzero arg? */ - if (t & SIGN32) { /* neg arg? */ - res.sign = FP_M_SIGN; /* set sign */ - t = (~t + 1) & DMASK32; /* get magnitude */ - cc = CC_L; } - else cc = CC_G; /* pos nz arg */ - res.h = t >> 8; /* hi frac */ - res.l = t << 24; } /* lo frac */ -else cc = 0; /* zero arg */ -NormUFP (&res); /* normalize */ -StoreFPR (&res, op, r1, 0); /* store result */ -return cc; -} - -/* Floating point add/subtract */ - -uint32 f_as (uint32 op, uint32 r1, uint32 r2, uint32 ea) -{ -struct ufp fop1, fop2, t; -int32 ediff; - -ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */ -UnpackFPR (&fop1, op, r1); /* get op1, norm */ -if (op & 1) fop2.sign = fop2.sign ^ 1; /* if sub, inv sign2 */ -if (fop1.h == 0) fop1 = fop2; /* if op1 = 0, res = op2 */ -else if (fop2.h != 0) { /* if op2 = 0, no add */ - if ((fop1.exp < fop2.exp) || /* |op1| < |op2|? */ - ((fop1.exp == fop2.exp) && - ((fop1.h < fop2.h) || - ((fop1.h == fop2.h) && (fop1.l < fop2.l))))) { - t = fop2; /* swap operands */ - fop2 = fop1; - fop1 = t; } - ediff = fop1.exp - fop2.exp; /* exp difference */ - if (OP_DPFP (op) || fp_in_hwre) { /* dbl prec or hwre? */ - if (ediff >= 14) fop2.h = fop2.l = 0; /* diff too big? */ - else if (ediff) { /* any difference? */ - FR_RSH_V (fop2, ediff * 4); } } /* shift frac */ - else { /* sgl prec ucode */ - if (ediff >= 6) fop2.h = 0; /* diff too big? */ - else if (ediff) /* any difference? */ - fop2.h = fop2.h >> (ediff * 4); } /* shift frac */ - if (fop1.sign ^ fop2.sign) { /* eff subtract */ - FR_SUB (fop1, fop2); /* sub fractions */ - NormUFP (&fop1); } /* normalize result */ - else { - FR_ADD (fop1, fop2); /* add fractions */ - if (fop1.h & FP_CARRY) { /* carry out? */ - FR_RSH_K (fop1, 4); /* renormalize */ - fop1.exp = fop1.exp + 1; } } /* incr exp */ - } /* end if fop2 */ -return StoreFPR (&fop1, op, r1, Q_RND_AS (op)); /* store result */ -} - -/* Floating point multiply - - Notes: - - Exponent overflow/underflow is tested right after the exponent - add, without regard to potential changes due to normalization - - Exponent underflow is tested right after normalization, without - regard to changes due to rounding - - Single precision hardware multiply may generate up to 48b - - Double precision multiply generates 56b with no guard bits -*/ - -int32 f_m (uint32 op, uint32 r1, uint32 r2, uint32 ea) -{ -struct ufp fop1, fop2; -struct ufp res = { 0, 0, 0, 0 }; -uint32 i; - -ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */ -UnpackFPR (&fop1, op, r1); /* get op1, norm */ -if (fop1.h && fop2.h) { /* if both != 0 */ - res.sign = fop1.sign ^ fop2.sign; /* sign = diff */ - res.exp = fop1.exp + fop2.exp - FP_BIAS; /* exp = sum */ - if ((res.exp < 0) || (res.exp > FP_M_EXP)) /* ovf/undf? */ - return StoreFPX (&res, op, r1); /* early out */ - if ((fop1.l | fop2.l) == 0) { /* 24b x 24b? */ - for (i = 0; i < 24; i++) { /* 24 iterations */ - if (fop2.h & 1) res.h = res.h + fop1.h; /* add hi only */ - FR_RSH_K (res, 1); /* shift dp res */ - fop2.h = fop2.h >> 1; } - } - else { /* some low 0's */ - if (fop2.l != 0) { /* 56b x 56b? */ - for (i = 0; i < 32; i++) { /* do low 32b */ - if (fop2.l & 1) { FR_ADD (res, fop1); } - FR_RSH_K (res, 1); - fop2.l = fop2.l >> 1; } } - for (i = 0; i < 24; i++) { /* do hi 24b */ - if (fop2.h & 1) { FR_ADD (res, fop1); } - FR_RSH_K (res, 1); - fop2.h = fop2.h >> 1; } - } - NormUFP (&res); /* normalize */ - if (res.exp < 0) /* underflow? */ - return StoreFPX (&res, op, r1); /* early out */ - } -return StoreFPR (&res, op, r1, Q_RND (op)); /* store */ -} - -/* Floating point divide - see overflow/underflow notes for multiply */ - -int32 f_d (uint32 op, uint32 r1, uint32 r2, uint32 ea) -{ -struct ufp fop1, fop2; -struct ufp quo = { 0, 0, 0, 0 }; -int32 i; - -ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */ -UnpackFPR (&fop1, op, r1); /* get op1, norm */ -if (fop2.h == 0) return CC_C | CC_V; /* div by zero? */ -if (fop1.h) { /* dvd != 0? */ - quo.sign = fop1.sign ^ fop2.sign; /* sign = diff */ - quo.exp = fop1.exp - fop2.exp + FP_BIAS; /* exp = diff */ - if ((quo.exp < 0) || (quo.exp > FP_M_EXP)) /* ovf/undf? */ - return StoreFPX (&quo, op, r1); /* early out */ - if (!FR_GE (fop1, fop2)) { - FR_LSH_K (fop1, 4); } /* ensure success */ - else { /* exp off by 1 */ - quo.exp = quo.exp + 1; /* incr exponent */ - if (quo.exp > FP_M_EXP) /* overflow? */ - return StoreFPX (&quo, op, r1); } /* early out */ - for (i = 0; i < (OP_DPFP (op)? 14: 6); i++) { /* 6/14 hex digits */ - FR_LSH_K (quo, 4); /* shift quotient */ - while (FR_GE (fop1, fop2)) { /* while sub works */ - FR_SUB (fop1, fop2); /* decrement */ - quo.l = quo.l + 1; } /* add quo bit */ - FR_LSH_K (fop1, 4); } /* shift divd */ - if (!OP_DPFP (op)) { /* single? */ - quo.h = quo.l; /* move quotient */ - if (fop1.h >= (fop2.h << 3)) quo.l = FP_ROUND; - else quo.l = 0; } - /* don't need to normalize */ - } /* end if fop1.h */ -return StoreFPR (&quo, op, r1, Q_RND (op)); /* store result */ -} - -/* Utility routines */ - -/* Unpack floating point number */ - -void UnpackFPR (struct ufp *fop, uint32 op, uint32 r1) -{ -uint32 hi; - -if (OP_DPFP (op)) { /* double prec? */ - hi = D[r1 >> 1].h; /* get hi */ - fop->l = FP_GETFRL (D[r1 >> 1].l); } /* get lo */ -else { hi = ReadFReg (r1); /* single prec */ - fop->l = 0; } /* lo is zero */ -fop->h = FP_GETFRH (hi); /* get hi frac */ -if (fop->h || fop->l) { /* non-zero? */ - fop->sign = FP_GETSIGN (hi); /* get sign */ - fop->exp = FP_GETEXP (hi); /* get exp */ - NormUFP (fop); } /* normalize */ -else fop->sign = fop->exp = 0; /* clean zero */ -return; -} - -/* Read memory operand */ - -void ReadFP2 (struct ufp *fop, uint32 op, uint32 r2, uint32 ea) -{ -uint32 hi; - -if (OP_TYPE (op) > OP_RR) { /* mem ref? */ - hi = ReadF (ea, VR); /* get hi */ - if (OP_DPFP (op)) fop->l = ReadF (ea + 4, VR); /* dp? get lo */ - else fop->l = 0; } /* sp, lo = 0 */ -else { if (OP_DPFP (op)) { /* RR */ - hi = D[r2 >> 1].h; /* dp? get dp reg */ - fop->l = D[r2 >> 1].l; } - else { - hi = ReadFReg (r2); /* get sp reg */ - fop->l = 0; } } -fop->h = FP_GETFRH (hi); /* get hi frac */ -if (fop->h || fop->l) { /* non-zero? */ - fop->sign = FP_GETSIGN (hi); /* get sign */ - fop->exp = FP_GETEXP (hi); /* get exp */ - NormUFP (fop); } /* normalize */ -else fop->sign = fop->exp = 0; /* clean zero */ -return; -} - -/* Normalize unpacked floating point number */ - -void NormUFP (struct ufp *fop) -{ -if ((fop->h & FP_M_FRH) || fop->l) { /* any fraction? */ - while ((fop->h & FP_NORM) == 0) { /* until norm */ - fop->h = (fop->h << 4) | ((fop->l >> 28) & 0xF); - fop->l = fop->l << 4; - fop->exp = fop->exp - 1; } } -else fop->sign = fop->exp = 0; /* clean 0 */ -return; -} - -/* Round fp number, store, generate condition codes */ - -uint32 StoreFPR (struct ufp *fop, uint32 op, uint32 r1, uint32 rnd) -{ -uint32 hi, cc; - -if (rnd && (fop->l & FP_ROUND)) { /* round? */ - fop->h = fop->h + 1; /* add 1 to frac */ - if (fop->h & FP_CARRY) { /* carry out? */ - fop->h = fop->h >> 4; /* renormalize */ - fop->exp = fop->exp + 1; } } /* incr exp */ -if (fop->h == 0) { /* result 0? */ - hi = fop->l = 0; /* store clean 0 */ - cc = 0; } -else if (fop->exp < 0) { /* underflow? */ - hi = fop->l = 0; /* store clean 0 */ - cc = CC_V; } -else if (fop->exp > FP_M_EXP) { /* overflow? */ - hi = (fop->sign)? 0xFFFFFFFF: 0x7FFFFFFF; - fop->l = 0xFFFFFFFF; - cc = (CC_V | ((fop->sign)? CC_L: CC_G)); } -else { hi = ((fop->sign & FP_M_SIGN) << FP_V_SIGN) | /* pack result */ - ((fop->exp & FP_M_EXP) << FP_V_EXP) | - ((fop->h & FP_M_FRH) << FP_V_FRH); - cc = (fop->sign)? CC_L: CC_G; } /* set cc's */ -if (OP_DPFP (op)) { /* double precision? */ - D[r1 >> 1].h = hi; - D[r1 >> 1].l = fop->l; } -else { WriteFReg (r1, hi); } -return cc; -} - -/* Generate exception result */ - -uint32 StoreFPX (struct ufp *fop, uint32 op, uint32 r1) -{ -uint32 cc = CC_V; - -if (fop->exp < 0) fop->h = fop->l = 0; /* undf? clean 0 */ -else { fop->h = (fop->sign)? 0xFFFFFFFF: 0x7FFFFFFF; /* overflow */ - fop->l = 0xFFFFFFFF; - cc = cc | ((fop->sign)? CC_L: CC_G); } -if (OP_DPFP (op)) { /* double precision? */ - D[r1 >> 1].h = fop->h; - D[r1 >> 1].l = fop->l; } -else { WriteFReg (r1, fop->h); } -return cc; -} diff --git a/Interdata/id_idc.c b/Interdata/id_idc.c deleted file mode 100644 index 97f40bb7..00000000 --- a/Interdata/id_idc.c +++ /dev/null @@ -1,693 +0,0 @@ -/* id_idc.c: Interdata MSM/IDC disk controller simulator - - Copyright (c) 2001-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - idc MSM/IDC disk controller - - 25-Apr-03 RMS Revised for extended file support - 16-Feb-03 RMS Fixed read to test transfer ok before selch operation - - Note: define flag ID_IDC to enable the extra functions of the intelligent - disk controller -*/ - -#include "id_defs.h" - -#define IDC_NUMBY 256 /* bytes/sector */ -#define IDC_NUMSC 64 /* sectors/track */ - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */ -#define UNIT_M_DTYPE 0x7 -#define UNIT_V_AUTO (UNIT_V_UF + 4) /* autosize */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) - -#define CYL u3 /* current cylinder */ -#define HD u4 /* current head */ -#define STD buf /* drive status */ -#define FNC wait /* function */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -#define IDC_DRVMASK ((1 << ID_NUMDR) - 1) /* drive bit mask */ -#define IDC_DIRMASK (IDC_DRVMASK << (i_IDC + 1)) /* drive irq mask */ - -/* Controller status */ - -#define STC_WRP 0x80 /* write protected */ -#define STC_ACF 0x40 /* addr cmp fail */ -#define STC_DEF 0x20 /* def track NI */ -#define STC_CYO 0x10 /* cylinder ovflo */ -#define STC_IDL 0x02 /* ctrl idle */ -#define STC_DTE 0x01 /* xfer error */ -#define SETC_EX (STC_WRP|STC_ACF|STC_DEF|STC_CYO) -#define STC_MASK (STC_WRP|STC_ACF|STC_DEF|STC_CYO|STA_BSY|STC_IDL|STC_DTE) - -/* Controller command */ - -#define CMC_MASK 0x3F -#define CMC_CLR 0x08 /* reset */ -#define CMC_RD 0x01 /* read */ -#define CMC_WR 0x02 /* write */ -#define CMC_RCHK 0x03 /* read check */ -#define CMC_FCHK 0x04 /* format check NI */ -#define CMC_RFMT 0x05 /* read fmt NI */ -#define CMC_WFMT 0x06 /* write fmt NI */ -#define CMC_WFTK 0x07 /* write fmt track NI */ - -/* IDC only functions */ - -#define CMC_RRAM 0x10 /* read RAM */ -#define CMC_WRAM 0x11 /* write RAM */ -#define CMC_EXP0 0x12 /* read page 0 NI */ -#define CMC_RUNC 0x21 /* read uncorr */ -#define CMC_STST 0x30 /* self test */ -#define CMC_WLNG 0x32 /* write long NI */ -#define CMC_LAMP 0x37 /* lamp test */ - -#define CMC_DRV 0x100 /* drive func */ -#define CMC_DRV1 0x200 /* drive func, part 2 */ - -/* Drive status, ^ = dynamic, * = in unit status */ - -#define STD_WRP 0x80 /* ^write prot */ -/* 0x40 /* unused */ -#define STD_ACH 0x20 /* alt chan busy NI */ -#define STD_UNS 0x10 /* *unsafe */ -#define STD_NRDY 0x08 /* ^not ready */ -#define STD_SKI 0x02 /* *seek incomplete */ -#define STD_OFFL 0x01 /* ^offline */ -#define STD_UST (STD_UNS | STD_SKI) /* set from unit */ -#define SETD_EX (STD_WRP | STD_UNS) /* set examine */ - -/* Drive command */ - -#define CMDF_SHD 0x20 /* set head */ -#define CMDF_SCY 0x10 /* set cylinder */ -#define CMD_SK 0x02 /* seek */ -#define CMD_RST 0x01 /* restore */ - -#define CMDX_MASK 0x30 /* ext cmd bits */ -#define CMDX_RLS 0x80 /* release */ -#define CMDX_CLF 0x40 /* clear fault */ -#define CMDX_SVP 0x08 /* servo + */ -#define CMDX_SVM 0x04 /* servo - */ -#define CMDX_DSP 0x02 /* strobe + */ -#define CMDX_DSM 0x01 /* strobe - */ - -/* Geometry masks */ - -#define CY_MASK 0xFFF /* cylinder */ -#define HD_MASK 0x1F /* head mask */ -#define SC_MASK 0x3F /* sector mask */ -#define HCYL_V_HD 10 /* head/cyl word */ -#define HCYL_V_CYL 0 - -#define GET_SA(cy,sf,sc,t) (((((cy)*drv_tab[t].surf)+(sf))* \ - IDC_NUMSC)+(sc)) - -/* The MSM (IDC) controller supports (two) six different disk drive types: - - type #sectors/ #surfaces/ #cylinders/ - surface cylinder drive - - MCCDD16 64 1 823 IDC - MCCDD48 64 3 823 IDC - MCCDD80 64 5 823 IDC - MSM80 64 5 823 MSM - MSM300 64 19 823 MSM - MSM330F 64 16 1024 IDC - - In theory, each drive can be a different type. The size field in - each unit selects the drive capacity for each drive and thus the - drive type. DISKS MUST BE DECLARED IN ASCENDING SIZE AND MUST HAVE - THE SAME SECTORS/TRACK. -*/ - -#define TYPE_MCCDD16 0 -#define SURF_MCCDD16 1 -#define CYL_MCCDD16 823 -#define SIZE_MCCDD16 (IDC_NUMSC * SURF_MCCDD16 * CYL_MCCDD16 * IDC_NUMBY) - -#define TYPE_MCCDD48 1 -#define SURF_MCCDD48 3 -#define CYL_MCCDD48 823 -#define SIZE_MCCDD48 (IDC_NUMSC * SURF_MCCDD48 * CYL_MCCDD48 * IDC_NUMBY) - -#define TYPE_MCCDD80 2 -#define SURF_MCCDD80 5 -#define CYL_MCCDD80 823 -#define SIZE_MCCDD80 (IDC_NUMSC * SURF_MCCDD80 * CYL_MCCDD80 * IDC_NUMBY) - -#define TYPE_MSM80 3 -#define SURF_MSM80 5 -#define CYL_MSM80 823 -#define SIZE_MSM80 (IDC_NUMSC * SURF_MSM80 * CYL_MSM80 * IDC_NUMBY) - -#define TYPE_MSM300 4 -#define SURF_MSM300 19 -#define CYL_MSM300 823 -#define SIZE_MSM300 (IDC_NUMSC * SURF_MSM300 * CYL_MSM300 * IDC_NUMBY) - -#define TYPE_MSM330F 5 -#define SURF_MSM330F 16 -#define CYL_MSM330F 1024 -#define SIZE_MSM330F (IDC_NUMSC * SURF_MSM330F * CYL_MSM330F * IDC_NUMBY) - - -struct drvtyp { - uint32 surf; /* surfaces */ - uint32 cyl; /* cylinders */ - uint32 size; /* #blocks */ - uint32 msmf; /* MSM drive */ -}; - -static struct drvtyp drv_tab[] = { - { SURF_MCCDD16, CYL_MCCDD16, SIZE_MCCDD16, 0 }, - { SURF_MCCDD48, CYL_MCCDD48, SIZE_MCCDD48, 0 }, - { SURF_MCCDD80, CYL_MCCDD80, SIZE_MCCDD80, 0 }, - { SURF_MSM80, CYL_MSM80, SIZE_MSM80, 1 }, - { SURF_MSM300, CYL_MSM300, SIZE_MSM300, 1 }, - { SURF_MSM330F, CYL_MSM330F, SIZE_MSM330F, 0 }, - { 0 } }; - -extern uint32 int_req[INTSZ], int_enb[INTSZ]; - -uint8 idcxb[IDC_NUMBY * 3]; /* xfer buffer */ -uint32 idc_bptr = 0; /* buffer ptr */ -uint32 idc_db = 0; /* ctrl buffer */ -uint32 idd_db = 0; /* drive buffer */ -uint32 idc_sta = 0; /* ctrl status */ -uint32 idc_sec = 0; /* sector */ -uint32 idc_hcyl = 0; /* head/cyl */ -uint32 idc_svun = 0; /* most recent unit */ -uint32 idc_1st = 0; /* first byte */ -uint32 idc_arm = 0; /* ctrl armed */ -uint32 idd_arm[ID_NUMDR] = { 0 }; /* drives armed */ -uint16 idd_dcy[ID_NUMDR] = { 0 }; /* desired cyl */ -uint32 idd_sirq = 0; /* drive saved irq */ -int32 idc_stime = 100; /* seek latency */ -int32 idc_rtime = 100; /* rotate latency */ -int32 idc_ctime = 5; /* command latency */ -uint8 idc_tplte[] = { 0, 1, 2, 3, 4, TPL_END }; /* ctrl + drive */ - -DEVICE idc_dev; -uint32 id (uint32 dev, uint32 op, uint32 dat); -t_stat idc_svc (UNIT *uptr); -t_stat idc_reset (DEVICE *dptr); -t_stat idc_attach (UNIT *uptr, char *cptr); -t_stat idc_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat idc_rds (UNIT *uptr); -t_stat idc_wds (UNIT *uptr); -t_bool idc_dter (UNIT *uptr, uint32 first); -void idc_done (uint32 flg); - -extern t_stat id_dboot (int32 u, DEVICE *dptr); - -/* DP data structures - - idc_dev DP device descriptor - idc_unit DP unit list - idc_reg DP register list - idc_mod DP modifier list -*/ - -DIB idc_dib = { d_IDC, 0, v_IDC, idc_tplte, &id, NULL }; - -UNIT idc_unit[] = { - { UDATA (&idc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(TYPE_MSM80 << UNIT_V_DTYPE), SIZE_MSM80) }, - { UDATA (&idc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(TYPE_MSM80 << UNIT_V_DTYPE), SIZE_MSM80) }, - { UDATA (&idc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(TYPE_MSM80 << UNIT_V_DTYPE), SIZE_MSM80) }, - { UDATA (&idc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(TYPE_MSM80 << UNIT_V_DTYPE), SIZE_MSM80) } }; - -REG idc_reg[] = { - { HRDATA (STA, idc_sta, 8) }, - { HRDATA (BUF, idc_db, 8) }, - { HRDATA (SEC, idc_sec, 8) }, - { HRDATA (HCYL, idc_hcyl, 16) }, - { HRDATA (BUF, idd_db, 8) }, - { HRDATA (SVUN, idc_svun, 2), REG_HIDDEN }, - { BRDATA (DBUF, idcxb, 16, 8, IDC_NUMBY * 3) }, - { HRDATA (DBPTR, idc_bptr, 10), REG_RO }, - { FLDATA (FIRST, idc_1st, 0) }, - { GRDATA (IREQ, int_req[l_IDC], 16, ID_NUMDR + 1, i_IDC) }, - { GRDATA (IENB, int_enb[l_IDC], 16, ID_NUMDR + 1, i_IDC) }, - { GRDATA (SIREQ, idd_sirq, 16, ID_NUMDR, i_IDC + 1), REG_RO }, - { FLDATA (ICARM, idc_arm, 0) }, - { BRDATA (IDARM, idd_arm, 16, 1, ID_NUMDR) }, - { DRDATA (RTIME, idc_rtime, 24), PV_LEFT | REG_NZ }, - { DRDATA (STIME, idc_stime, 24), PV_LEFT | REG_NZ }, - { DRDATA (CTIME, idc_ctime, 24), PV_LEFT | REG_NZ }, - { BRDATA (CYL, idd_dcy, 16, 16, ID_NUMDR) }, - { URDATA (UCYL, idc_unit[0].CYL, 16, 12, 0, - ID_NUMDR, REG_RO) }, - { URDATA (UHD, idc_unit[0].HD, 16, 5, 0, - ID_NUMDR, REG_RO) }, - { URDATA (UFNC, idc_unit[0].FNC, 16, 10, 0, - ID_NUMDR, REG_HRO) }, - { URDATA (UST, idc_unit[0].STD, 16, 8, 0, - ID_NUMDR, REG_RO) }, - { URDATA (CAPAC, idc_unit[0].capac, 10, T_ADDR_W, 0, - ID_NUMDR, PV_LEFT | REG_HRO) }, - { HRDATA (DEVNO, idc_dib.dno, 8), REG_HRO }, - { HRDATA (SELCH, idc_dib.sch, 2), REG_HRO }, - { BRDATA (TPLTE, idc_tplte, 16, 8, ID_NUMDR + 1), REG_HRO }, - { NULL } }; - -MTAB idc_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD16 << UNIT_V_DTYPE) + UNIT_ATT, - "MCCDD16", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD48 << UNIT_V_DTYPE) + UNIT_ATT, - "MCCDD48", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD80 << UNIT_V_DTYPE) + UNIT_ATT, - "MCCDD80", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_MSM330F << UNIT_V_DTYPE) + UNIT_ATT, - "MSM330F", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD16 << UNIT_V_DTYPE), - "MCCDD16", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD48 << UNIT_V_DTYPE), - "MCCDD48", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD80 << UNIT_V_DTYPE), - "MCCDD80", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MSM330F << UNIT_V_DTYPE), - "MSM330F", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_MCCDD16 << UNIT_V_DTYPE), - NULL, "MCCDD16", &idc_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_MCCDD48 << UNIT_V_DTYPE), - NULL, "MCCDD48", &idc_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_MCCDD80 << UNIT_V_DTYPE), - NULL, "MCCDD80", &idc_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_MSM330F << UNIT_V_DTYPE), - NULL, "MSM330F", &idc_set_size }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_MSM80 << UNIT_V_DTYPE) + UNIT_ATT, - "MSM80", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_MSM300 << UNIT_V_DTYPE) + UNIT_ATT, - "MSM300", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MSM80 << UNIT_V_DTYPE), - "MSM80", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MSM300 << UNIT_V_DTYPE), - "MSM300", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_MSM80 << UNIT_V_DTYPE), - NULL, "MSM80", &idc_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_MSM300 << UNIT_V_DTYPE), - NULL, "MSM300", &idc_set_size }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH", - &set_sch, &show_sch, NULL }, - { 0 } }; - -DEVICE idc_dev = { - "DM", idc_unit, idc_reg, idc_mod, - ID_NUMDR, 16, 29, 1, 16, 8, - NULL, NULL, &idc_reset, - &id_dboot, &idc_attach, NULL, - &idc_dib, DEV_DISABLE }; - -/* Controller: IO routine */ - -uint32 idc (uint32 dev, uint32 op, uint32 dat) -{ -uint32 f, t; -UNIT *uptr; - -switch (op) { /* case IO op */ -case IO_ADR: /* select */ - sch_adr (idc_dib.sch, dev); /* inform sel ch */ - return HW; /* halfwords */ -case IO_RD: /* read data */ -case IO_RH: /* read halfword */ - return 0; /* return data */ -case IO_WD: /* write data */ - idc_sec = dat; /* sector */ - break; -case IO_WH: /* write halfword */ - idc_hcyl = dat; /* head/cylinder */ - break; -case IO_SS: /* status */ - t = idc_sta & STC_MASK; /* get status */ - if (t & SETC_EX) t = t | STA_EX; /* test for EX */ - return t; -case IO_OC: /* command */ - idc_arm = int_chg (v_IDC, dat, idc_arm); /* upd int ctrl */ - f = dat & CMC_MASK; /* get cmd */ - uptr = idc_dev.units + idc_svun; /* get unit */ - if (f & CMC_CLR) { /* clear? */ - idc_reset (&idc_dev); /* reset world */ - break; } - if (!(idc_sta & STC_IDL) || /* if !idle, */ - sim_is_active (uptr) || /* unit busy, */ - (f == CMC_EXP0)) break; /* expg, ignore */ - idc_sta = STA_BSY; /* bsy=1,idl,err=0 */ - idc_1st = 1; /* xfr not started */ - idc_bptr = 0; /* buffer empty */ - uptr->FNC = f; /* save cmd */ - sim_activate (uptr, idc_rtime); /* schedule */ - idd_sirq = int_req[l_IDC] & IDC_DIRMASK; /* save drv ints */ - int_req[l_IDC] = int_req[l_IDC] & ~IDC_DIRMASK; /* clr drv ints */ - break; } -return 0; -} - -/* Drives: IO routine */ - -uint32 id (uint32 dev, uint32 op, uint32 dat) -{ -uint32 t, u; -UNIT *uptr; - -if (dev == idc_dib.dno) return idc (dev, op, dat); /* controller? */ -u = (dev - idc_dib.dno - o_ID0) / o_ID0; /* get unit num */ -uptr = idc_dev.units + u; /* get unit ptr */ -switch (op) { /* case IO op */ -case IO_ADR: /* select */ - if (idc_sta & STC_IDL) idc_svun = u; /* idle? save unit */ - return HW; /* byte only */ -case IO_RD: /* read data */ -case IO_RH: - return 0; -case IO_WD: /* write data */ -case IO_WH: /* write halfword */ - idd_db = dat; /* save data */ - break; -case IO_SS: /* status */ - if (uptr->flags & UNIT_ATT) t = - ((uptr->flags & UNIT_WPRT)? STD_WRP: 0) | - (sim_is_active (uptr)? STD_NRDY: 0) | - (uptr->STD & STD_UST); - else t = STD_NRDY | STD_OFFL; /* off = X'09' */ - if (t & SETD_EX) t = t | STA_EX; /* test for ex */ - return t; -case IO_OC: /* command */ - idd_arm[u] = int_chg (v_IDC + u + 1, dat, idd_arm[u]); - if (idd_arm[u] == 0) /* disarmed? */ - idd_sirq &= ~(1 << (v_IDC + u + 1)); /* clr saved req */ - if (sim_is_active (uptr) || /* if busy or */ - !(idc_sta & STC_IDL)) break; /* !idle, ignore */ - if ((dat & CMC_MASK) == CMDX_MASK) break; /* ignore 0x30 */ - uptr->FNC = (dat & CMC_MASK) | CMC_DRV; /* save cmd */ - idc_sta = idc_sta & ~STC_IDL; /* clr idle */ - sim_activate (uptr, idc_ctime); /* schedule */ - break; } -return 0; -} - -/* Unit service - - If drive command, process; if an interrupt is needed (positioning - command), schedule second part - - If data transfer command, process; must use selector channel -*/ - -t_stat idc_svc (UNIT *uptr) -{ -int32 diff; -uint32 f, u = uptr - idc_dev.units; /* get unit number */ -uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */ -uint32 t; -t_stat r; - -if (uptr->FNC & CMC_DRV) { /* drive cmd? */ - f = uptr->FNC & CMC_MASK; /* get cmd */ - if (uptr->FNC & CMC_DRV1) { /* part 2? */ - if (idd_arm[u]) { /* drv int armed? */ - if (idc_sta & STC_IDL) /* ctrl idle? */ - SET_INT (v_IDC + u + 1); /* req intr */ - else idd_sirq |= (1 << (v_IDC + u + 1)); } /* def intr */ - if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; - if (((f & CMDX_MASK) == 0) && /* seek? */ - (f & (CMD_SK | CMD_RST))) { - if (idd_dcy[u] >= drv_tab[dtype].cyl) /* bad cylinder? */ - uptr->STD = uptr->STD | STD_SKI; /* error */ - uptr->CYL = idd_dcy[u]; } /* put on cyl */ - } /* end if p2 */ - else { /* part 1 */ - idc_sta = idc_sta | STC_IDL; /* set idle */ - uptr->FNC = uptr->FNC | CMC_DRV1; /* set part 2 */ - if (f >= CMDX_MASK) { /* extended? */ - if (f & CMDX_CLF) /* clr fault? */ - uptr->STD = uptr->STD & ~STD_UNS; /* clr unsafe */ - if (f & (CMDX_RLS | CMDX_SVP | CMDX_SVM)) /* intr expected? */ - sim_activate (uptr, idc_ctime); } - else if (f >= CMDF_SCY) { /* tag? */ - if (f & CMDF_SHD) uptr->HD = idd_db & HD_MASK; - else if (f & CMDF_SCY) { - if (idd_db >= drv_tab[dtype].cyl) /* bad cylinder? */ - uptr->STD = uptr->STD | STD_SKI; /* set seek inc */ - idd_dcy[u] = idd_db & CY_MASK; } } - else if (f & (CMD_SK | CMD_RST)) { /* seek? */ - if (f == CMD_RST) idd_dcy[u] = 0; /* restore? */ - if (idd_dcy[u] >= drv_tab[dtype].cyl) { /* bad cylinder? */ - uptr->STD = uptr->STD | STD_SKI; /* set seek inc */ - idd_dcy[u] = uptr->CYL; /* no motion */ - sim_activate (uptr, 0); } /* finish asap */ - else { /* cylinder ok */ - uptr->STD = uptr->STD & ~STD_SKI; /* clr seek inc */ - diff = idd_dcy[u] - uptr->CYL; - if (diff < 0) diff = -diff; /* ABS cyl diff */ - else if (diff == 0) diff = 1; /* must be nz */ - sim_activate (uptr, diff * idc_stime); } } - } /* end else p1 */ - return SCPE_OK; } /* end if drv */ - -switch (uptr->FNC & CMC_MASK) { /* case on func */ - -case CMC_RCHK: /* read check */ - idc_dter (uptr, 1); /* check xfr err */ - break; - -#if defined (ID_IDC) -case CMC_RUNC: /* read uncorr */ -#endif -case CMC_RD: /* read */ - if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */ - if (idc_dter (uptr, idc_1st)) return SCPE_OK; /* dte? done */ - if (r = idc_rds (uptr)) return r; /* read sec, err? */ - idc_1st = 0; - t = sch_wrmem (idc_dib.sch, idcxb, IDC_NUMBY); /* write mem */ - if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* more to do? */ - sim_activate (uptr, idc_rtime); /* reschedule */ - return SCPE_OK; } - break; } /* no, set done */ - idc_sta = idc_sta | STC_DTE; /* cant work */ - break; - -case CMC_WR: /* write */ - if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */ - if (idc_dter (uptr, idc_1st)) return SCPE_OK; /* dte? done */ - idc_bptr = sch_rdmem (idc_dib.sch, idcxb, IDC_NUMBY); /* read mem */ - idc_db = idcxb[idc_bptr - 1]; /* last byte */ - if (r = idc_wds (uptr)) return r; /* write sec, err? */ - idc_1st = 0; - if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* more to do? */ - sim_activate (uptr, idc_rtime); /* reschedule */ - return SCPE_OK; } - break; } /* no, set done */ - idc_sta = idc_sta | STC_DTE; /* cant work */ - break; - -case CMC_FCHK: case CMC_RFMT: case CMC_WFMT: case CMC_WFTK: - idc_dter (uptr, 1); - idc_sta = idc_sta | STC_WRP; - break; - -#if defined (ID_IDC) -case CMC_RRAM: /* read RAM */ - if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */ - sch_wrmem (idc_dib.sch, idcxb, IDC_NUMBY * 3); - if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* more to do? */ - sim_activate (uptr, idc_rtime); /* reschedule */ - return SCPE_OK; } - break; } /* no, set done */ - idc_sta = idc_sta | STC_DTE; /* cant work */ - break; - -case CMC_WRAM: /* write RAM */ - if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */ - sch_rdmem (idc_dib.sch, idcxb, IDC_NUMBY * 3); /* read from mem */ - if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* more to do? */ - sim_activate (uptr, idc_rtime); /* reschedule */ - return SCPE_OK; } - break; } /* no, set done */ - idc_sta = idc_sta | STC_DTE; /* cant work */ - break; - -case CMC_STST: case CMC_LAMP: /* tests */ - break; -#endif - -default: - idc_sta = idc_sta | STC_DTE; - break; } - -idc_done (0); /* done */ -return SCPE_OK; -} - -/* Read data sector */ - -t_stat idc_rds (UNIT *uptr) -{ -uint32 i; - -i = fxread (idcxb, sizeof (uint8), IDC_NUMBY, uptr->fileref); -if (ferror (uptr->fileref)) { /* error? */ - perror ("IDC I/O error"); - clearerr (uptr->fileref); - idc_done (STC_DTE); - return SCPE_IOERR; } -for ( ; i < IDC_NUMBY; i++) idcxb[i] = 0; /* fill with 0's */ -return SCPE_OK; -} - -/* Write data sector */ - -t_bool idc_wds (UNIT *uptr) -{ -for ( ; idc_bptr < IDC_NUMBY; idc_bptr++) - idcxb[idc_bptr] = idc_db; /* fill with last */ -fxwrite (idcxb, sizeof (uint8), IDC_NUMBY, uptr->fileref); -if (ferror (uptr->fileref)) { /* error? */ - perror ("IDC I/O error"); - clearerr (uptr->fileref); - idc_done (STC_DTE); - return SCPE_IOERR; } -return FALSE; -} - -/* Data transfer error test routine */ - -t_bool idc_dter (UNIT *uptr, uint32 first) -{ -uint32 cy; -uint32 hd, sc, sa; -uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */ - -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - idc_done (STC_DTE); /* error, done */ - return TRUE; } -if ((uptr->flags & UNIT_WPRT) && (uptr->FNC == CMC_WR)) { - idc_done (STC_WRP); /* error, done */ - return TRUE; } -cy = uptr->CYL; /* get cylinder */ -hd = uptr->HD; /* get head */ -sc = idc_sec & SC_MASK; /* get sector */ -if (cy >= drv_tab[dtype].cyl) { /* bad cylinder? */ - uptr->STD = uptr->STD | STD_SKI; /* error */ - idc_done (STC_DTE); /* error, done */ - return TRUE; } -if (hd >= drv_tab[dtype].surf) { /* bad head? */ - if (first) { /* 1st xfer? */ - uptr->STD = uptr->STD | STD_UNS; /* drive unsafe */ - idc_done (STC_ACF); } - else idc_done (STC_CYO); /* no, cyl ovf */ - return TRUE; } -sa = GET_SA (cy, hd, sc, dtype); /* curr disk addr */ -fseek (uptr->fileref, sa * IDC_NUMBY, SEEK_SET); /* seek to pos */ -idc_sec = (idc_sec + 1) & SC_MASK; /* incr disk addr */ -if (idc_sec == 0) uptr->HD = uptr->HD + 1; -return FALSE; -} - -/* Data transfer done routine */ - -void idc_done (uint32 flg) -{ -idc_sta = (idc_sta | STC_IDL | flg) & ~STA_BSY; /* set flag, idle */ -if (idc_arm) SET_INT (v_IDC); /* if armed, intr */ -int_req[l_IDC] = int_req[l_IDC] | idd_sirq; /* restore drv ints */ -idd_sirq = 0; /* clear saved */ -if (flg) sch_stop (idc_dib.sch); /* if err, stop sch */ -return; -} - -/* Reset routine */ - -t_stat idc_reset (DEVICE *dptr) -{ -uint32 u; -UNIT *uptr; - -idc_sta = STC_IDL | STA_BSY; /* idle, busy */ -idc_1st = 0; /* clear flag */ -idc_svun = idc_db = 0; /* clear unit, buf */ -idc_sec = 0; /* clear addr */ -idc_hcyl = 0; -CLR_INT (v_IDC); /* clear ctrl int */ -CLR_ENB (v_IDC); /* clear ctrl enb */ -idc_arm = 0; /* clear ctrl arm */ -idd_sirq = 0; -for (u = 0; u < ID_NUMDR; u++) { /* loop thru units */ - uptr = idc_dev.units + u; - uptr->CYL = uptr->STD = 0; - uptr->HD = uptr->FNC = 0; - idd_dcy[u] = 0; - CLR_INT (v_IDC + u + 1); /* clear intr */ - CLR_ENB (v_IDC + u + 1); /* clear enable */ - idd_arm[u] = 0; /* clear arm */ - sim_cancel (uptr); } /* cancel activity */ -return SCPE_OK; -} - -/* Attach routine (with optional autosizing) */ - -t_stat idc_attach (UNIT *uptr, char *cptr) -{ -uint32 i, p; -t_stat r; - -uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size; -r = attach_unit (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* error? */ -uptr->CYL = 0; -if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ -if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK; -if ((p = ftell (uptr->fileref)) == 0) return SCPE_OK; -for (i = 0; drv_tab[i].surf != 0; i++) { - if (p <= drv_tab[i].size) { - uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); - uptr->capac = drv_tab[i].size; - return SCPE_OK; } } -return SCPE_OK; -} - -/* Set size command validation routine */ - -t_stat idc_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = drv_tab[GET_DTYPE (val)].size; -return SCPE_OK; -} diff --git a/Interdata/id_io.c b/Interdata/id_io.c deleted file mode 100644 index 88c7d25f..00000000 --- a/Interdata/id_io.c +++ /dev/null @@ -1,567 +0,0 @@ -/* id_io.c: Interdata CPU-independent I/O routines - - Copyright (c) 2001-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 21-Jun-03 RMS Changed subroutine argument for ARM compiler conflict - - Interdata I/O devices are defined by a device information block: - - dno base device number - sch selector channel, -1 if none - irq interrupt request flag - tplte device number template, NULL if one device number - iot I/O processing routine - ini initialization routine - - Interdata I/O uses the following interconnected tables: - - dev_tab[dev] Indexed by device number, points to the I/O instruction - processing routine for the device. - - sch_tab[dev] Indexed by device number, if non-zero, the number + 1 - of the selector channel used by the device. - - int_req[level] Indexed by interrupt level, device interrupt flags. - - int_enb[level] Indexed by interrupt level, device interrupt enable flags. - - int_tab[idx] Indexed by ((interrupt level * 32) + interrupt number), - maps bit positions in int_req to device numbers. -*/ - -#include "id_defs.h" - -/* Selector channel */ - -#define SCHC_EXA 0x40 /* read ext addr */ -#define SCHC_RD 0x20 /* read */ -#define SCHC_GO 0x10 /* go */ -#define SCHC_STOP 0x08 /* stop */ -#define SCHC_SSTA 0x04 /* sel ch status */ -#define SCHC_EXM 0x03 /* ext mem */ - -extern uint32 int_req[INTSZ], int_enb[INTSZ]; -extern uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout); -extern uint32 pawidth; -extern UNIT cpu_unit; -extern FILE *sim_log; -extern DEVICE *sim_devices[]; - -uint32 sch_max = 2; /* sch count */ -uint32 sch_sa[SCH_NUMCH] = { 0 }; /* start addr */ -uint32 sch_ea[SCH_NUMCH] = { 0 }; /* end addr */ -uint8 sch_sdv[SCH_NUMCH] = { 0 }; /* device */ -uint8 sch_cmd[SCH_NUMCH] = { 0 }; /* command */ -uint8 sch_rdp[SCH_NUMCH] = { 0 }; /* read ptr */ -uint8 sch_wdc[SCH_NUMCH] = { 0 }; /* write ctr */ -uint32 sch_tab[DEVNO] = { 0 }; /* dev to sch map */ -uint32 int_tab[INTSZ * 32] = { 0 }; /* int to dev map */ -uint8 sch_tplte[SCH_NUMCH + 1]; /* dnum template */ - -uint32 sch (uint32 dev, uint32 op, uint32 dat); -void sch_ini (t_bool dtpl); -t_stat sch_reset (DEVICE *dptr); -t_stat sch_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat sch_show_reg (FILE *st, UNIT *uptr, int32 val, void *desc); - -/* Selector channel data structures - - sch_dev channel device descriptor - sch_unit channel unit descriptor - sch_mod channel modifiers list - sch_reg channel register list -*/ - -DIB sch_dib = { d_SCH, -1, v_SCH, sch_tplte, &sch, &sch_ini }; - -UNIT sch_unit = { UDATA (NULL, 0, 0) }; - -REG sch_reg[] = { - { HRDATA (CHAN, sch_max, 3), REG_HRO }, - { BRDATA (SA, sch_sa, 16, 20, SCH_NUMCH) }, - { BRDATA (EA, sch_ea, 16, 20, SCH_NUMCH) }, - { BRDATA (CMD, sch_cmd, 16, 8, SCH_NUMCH) }, - { BRDATA (DEV, sch_sdv, 16, 8, SCH_NUMCH) }, - { BRDATA (RDP, sch_rdp, 16, 2, SCH_NUMCH) }, - { BRDATA (WDC, sch_wdc, 16, 3, SCH_NUMCH) }, - { GRDATA (IREQ, int_req[l_SCH], 16, SCH_NUMCH, i_SCH) }, - { GRDATA (IENB, int_enb[l_SCH], 16, SCH_NUMCH, i_SCH) }, - { HRDATA (DEVNO, sch_dib.dno, 8), REG_HRO }, - { NULL } }; - -MTAB sch_mod[] = { - { MTAB_XTD|MTAB_VDV|MTAB_VAL, 0, "channels", "CHANNELS", - &sch_set_nchan, NULL, &sch_reg[0] }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "0", NULL, - NULL, &sch_show_reg, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "1", NULL, - NULL, &sch_show_reg, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 2, "2", NULL, - NULL, &sch_show_reg, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 3, "3", NULL, - NULL, &sch_show_reg, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, &sch_dib }, - { 0 } }; - -DEVICE sch_dev = { - "SELCH", &sch_unit, sch_reg, sch_mod, - 1, 16, 8, 1, 16, 8, - NULL, NULL, &sch_reset, - NULL, NULL, NULL, - &sch_dib, 0 }; - -/* (Extended) selector channel - - There are really three different selector channels: - - 16b selector channel (max 4B of data) - - 18b selector channel (max 4B of data) - - 20b selector channel (max 6B of data) - The algorithm for loading the start and end addresses is taken - from the maintenance manual for the Extended Selector Channel. -*/ - -#define SCH_EXR(ch) ((sch_cmd[ch] & SCHC_EXA) && (pawidth == PAWIDTH32)) - -uint32 sch (uint32 dev, uint32 op, uint32 dat) -{ -uint32 t, bank, sdv, ch = dev - sch_dib.dno; - -switch (op) { /* case IO op */ -case IO_ADR: /* select */ - return BY; /* byte only */ -case IO_RD: /* read data */ - t = (sch_sa[ch] >> (sch_rdp[ch] * 8)) & DMASK8; /* get sa byte */ - if (sch_rdp[ch] == 0) sch_rdp[ch] = /* wrap? */ - SCH_EXR (ch)? 2: 1; - else sch_rdp[ch] = sch_rdp[ch] - 1; /* dec byte ptr */ - return t; -case IO_WD: /* write data */ - if (pawidth != PAWIDTH32) { /* 16b? max 4 */ - if (sch_wdc[ch] >= 4) break; /* stop at 4 */ - sch_sa[ch] = ((sch_sa[ch] << 8) | /* ripple ea to sa */ - (sch_ea[ch] >> 8)) & DMASK16; - sch_ea[ch] = ((sch_ea[ch] << 8) | /* ripple ea low */ - dat) & DMASK16; } /* insert byte */ - else { /* 32b? max 6 */ - if (sch_wdc[ch] >= 6) break; /* stop at 6 */ - if (sch_wdc[ch] != 5) { /* if not last */ - sch_sa[ch] = ((sch_sa[ch] << 8) | /* ripple ea<15:8> to sa */ - ((sch_ea[ch] >> 8) & DMASK8)) & PAMASK32; - sch_ea[ch] = /* ripple ea<7:0> */ - (((sch_ea[ch] & DMASK8) << 8) | dat) & PAMASK32; } - else sch_ea[ch] = ((sch_ea[ch] << 8) | dat) & PAMASK32; } - sch_wdc[ch] = sch_wdc[ch] + 1; /* adv sequencer */ - break; -case IO_SS: /* status */ - if (sch_cmd[ch] & SCHC_GO) return STA_BSY; /* test busy */ - if (sch_cmd[ch] & SCHC_SSTA) return 0; /* test sch sta */ - else { - sdv = sch_sdv[ch]; /* get dev */ - if (dev_tab[sdv] == 0) return CC_V; /* not there? */ - dev_tab[sdv] (sdv, IO_ADR, 0); /* select dev */ - t = dev_tab[sdv] (sdv, IO_SS, 0); /* get status */ - return t & ~STA_BSY; } /* clr busy */ -case IO_OC: /* command */ - bank = 0; /* assume no bank */ - if (pawidth != PAWIDTH32) { /* 16b/18b proc? */ - dat = dat & ~(SCHC_EXA | SCHC_SSTA); /* clr ext func */ - if (pawidth == PAWIDTH16E) /* 18b proc? */ - bank = (dat & SCHC_EXM) << 16; } - if (dat & SCHC_STOP) { /* stop? */ - sch_cmd[ch] = dat & (SCHC_EXA | SCHC_SSTA); /* clr go */ - CLR_INT (v_SCH + ch); /* clr intr */ - sch_rdp[ch] = SCH_EXR (ch)? 2: 1; /* init sequencers */ - sch_wdc[ch] = 0; } - else if (dat & SCHC_GO) { /* go? */ - sch_cmd[ch] = dat & (SCHC_GO | SCHC_RD); - if (sch_wdc[ch] <= 4) { /* 4 bytes? */ - sch_sa[ch] = (sch_sa[ch] & PAMASK16) | bank; /* 16b addr */ - sch_ea[ch] = (sch_ea[ch] & PAMASK16) | bank; } - sch_sa[ch] = sch_sa[ch] & ~1; - if (sch_ea[ch] <= sch_sa[ch]) /* wrap? */ - sch_ea[ch] = sch_ea[ch] | /* modify end addr */ - ((pawidth == PAWIDTH32)? PAMASK32: PAMASK16); } - break; } -return 0; -} - -/* CPU call to test if channel blocks access to device */ - -t_bool sch_blk (uint32 dev) -{ -uint32 ch = sch_tab[dev] - 1; - -if ((ch < sch_max) && (sch_cmd[ch] & SCHC_GO)) return TRUE; -return FALSE; -} - -/* Device call to 'remember' last dev on channel */ - -void sch_adr (uint32 ch, uint32 dev) -{ -if (ch < sch_max) sch_sdv[ch] = dev; -return; -} - -/* Device call to see if selector channel is active for device */ - -t_bool sch_actv (uint32 ch, uint32 dev) -{ -if ((ch < sch_max) && /* chan valid, */ - (sch_cmd[ch] & SCHC_GO) && /* on, and */ - (sch_sdv[ch] == dev)) return TRUE; /* set for dev? */ -return FALSE; /* no */ -} - -/* Device call to read a block of memory */ - -uint32 sch_rdmem (uint32 ch, uint8 *buf, uint32 cnt) -{ -uint32 addr, end, xfr, inc; - -if ((ch >= sch_max) || ((sch_cmd[ch] & SCHC_GO) == 0)) return 0; -addr = sch_sa[ch]; /* start */ -end = sch_ea[ch]; /* end */ -xfr = MIN (cnt, end - addr + 1); /* sch xfr cnt */ -inc = IOReadBlk (addr, xfr, buf); /* read mem */ -if ((addr + inc) > end) { /* end? */ - SET_INT (v_SCH + ch); /* interrupt */ - sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); /* clear GO */ - sch_sa[ch] = sch_sa[ch] + inc - 1; } /* end addr */ -else sch_sa[ch] = sch_sa[ch] + inc; /* next addr */ -return inc; -} - -/* Device call to write a block of memory */ - -uint32 sch_wrmem (uint32 ch, uint8 *buf, uint32 cnt) -{ -uint32 addr, end, xfr, inc; - -if ((ch >= sch_max) || ((sch_cmd[ch] & SCHC_GO) == 0)) return 0; -addr = sch_sa[ch]; /* start */ -end = sch_ea[ch]; /* end */ -xfr = MIN (cnt, end - addr + 1); /* sch xfr cnt */ -inc = IOWriteBlk (addr, xfr, buf); /* write mem */ -if ((addr + inc) > end) { /* end? */ - SET_INT (v_SCH + ch); /* interrupt */ - sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); /* clear GO */ - sch_sa[ch] = sch_sa[ch] + inc - 1; } /* end addr */ -else sch_sa[ch] = sch_sa[ch] + inc; /* next addr */ -return inc; -} - -/* Device call to stop a selector channel */ - -void sch_stop (uint32 ch) -{ -if (ch < sch_max) { - SET_INT (v_SCH + ch); /* interrupt */ - sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); } /* clear GO */ -return; -} - -/* Reset */ - -void sch_reset_ch (uint32 rst_lim) -{ -uint32 ch; - -for (ch = 0; ch < SCH_NUMCH; ch++) { - if (ch >= rst_lim) { - CLR_INT (v_SCH + ch); - SET_ENB (v_SCH + ch); - sch_sa[ch] = sch_ea[ch] = 0; - sch_cmd[ch] = sch_sdv[ch] = 0; - sch_wdc[ch] = 0; - sch_rdp[ch] = 1; } } -return; -} - -t_stat sch_reset (DEVICE *dptr) -{ -sch_reset_ch (0); /* reset all chan */ -return SCPE_OK; -} - -/* Set number of channels */ - -t_stat sch_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 i, newmax; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -newmax = get_uint (cptr, 10, SCH_NUMCH, &r); /* get new max */ -if ((r != SCPE_OK) || (newmax == sch_max)) return r; /* err or no chg? */ -if (newmax == 0) return SCPE_ARG; /* must be > 0 */ -if (newmax < sch_max) { /* reducing? */ - for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru dev */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if (dibp && (dibp->sch >= (int32) newmax)) {/* dev using chan? */ - printf ("Device %02X uses channel %d\n", - dibp->dno, dibp->sch); - if (sim_log) fprintf (sim_log, "Device %02X uses channel %d\n", - dibp->dno, dibp->sch); - return SCPE_OK; } } } -sch_max = newmax; /* set new max */ -sch_reset_ch (sch_max); /* reset chan */ -return SCPE_OK; -} - -/* Show channel registers */ - -t_stat sch_show_reg (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (val < 0) return SCPE_IERR; -if (val >= (int32) sch_max) fprintf (st, "Channel %d disabled\n", val); -else { fprintf (st, "SA: %05X\n", sch_sa[val]); - fprintf (st, "EA: %05X\n", sch_ea[val]); - fprintf (st, "CMD: %02X\n", sch_cmd[val]); - fprintf (st, "DEV: %02X\n", sch_sdv[val]); - fprintf (st, "RDP: %X\n", sch_rdp[val]); - fprintf (st, "WDC: %X\n", sch_wdc[val]); } -return SCPE_OK; -} - -/* Initialize template */ - -void sch_ini (t_bool dtpl) -{ -uint32 i; - -for (i = 0; i < sch_max; i++) sch_tplte[i] = i; -sch_tplte[sch_max] = TPL_END; -return; -} - -/* Evaluate interrupt */ - -void int_eval (void) -{ -int i; -extern uint32 qevent; - -for (i = 0; i < INTSZ; i++) - if (int_req[i] & int_enb[i]) { - qevent = qevent | EV_INT; - return; } -qevent = qevent & ~EV_INT; -return; -} - -/* Return interrupting device */ - -uint32 int_getdev (void) -{ -int32 i, j, t; -uint32 r; - -for (i = t = 0; i < INTSZ; i++) { /* loop thru array */ - if (r = int_req[i] & int_enb[i]) { /* find nz int wd */ - for (j = 0; j < 32; t++, j++) { - if (r & (1u << j)) { - int_req[i] = int_req[i] & ~(1u << j); /* clr request */ - return int_tab[t]; } } } - else t = t + 32; } -return 0; -} - -/* Update device interrupt status */ - -int32 int_chg (uint32 irq, int32 dat, int32 armdis) -{ -int32 t = CMD_GETINT (dat); /* get int ctrl */ - -if (t == CMD_IENB) { /* enable? */ - SET_ENB (irq); - return 1; } -else if (t == CMD_IDIS) { /* disable? */ - CLR_ENB (irq); - return 1; } -if (t == CMD_IDSA) { /* disarm? */ - CLR_ENB (irq); - CLR_INT (irq); - return 0; } -return armdis; -} - -/* Process a 2b field and return unchanged, set, clear, complement */ - -int32 io_2b (int32 val, int32 pos, int32 old) -{ -int32 t = (val >> pos) & 3; -if (t == 0) return old; -if (t == 1) return 1; -if (t == 2) return 0; -return old ^1; -} - -/* Block transfer routines */ - -uint32 IOReadBlk (uint32 loc, uint32 cnt, uint8 *buf) -{ -uint32 i; - -if (!MEM_ADDR_OK (loc) || (cnt == 0)) return 0; -if (!MEM_ADDR_OK (loc + cnt - 1)) cnt = MEMSIZE - loc; -for (i = 0; i < cnt; i++) buf[i] = IOReadB (loc + i); -return cnt; -} - -uint32 IOWriteBlk (uint32 loc, uint32 cnt, uint8 *buf) -{ -uint32 i; - -if (!MEM_ADDR_OK (loc) || (cnt == 0)) return 0; -if (!MEM_ADDR_OK (loc + cnt - 1)) cnt = MEMSIZE - loc; -for (i = 0; i < cnt; i++) IOWriteB (loc + i, buf[i]); -return cnt; -} - -/* Change selector channel for a device */ - -t_stat set_sch (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newch; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if ((dibp == NULL) || (dibp->sch < 0)) return SCPE_IERR; -newch = get_uint (cptr, 16, sch_max - 1, &r); /* get new */ -if (r != SCPE_OK) return r; -dibp->sch = newch; /* store */ -return SCPE_OK; -} - -/* Show selector channel for a device */ - -t_stat show_sch (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -DEVICE *dptr; -DIB *dibp; - -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if ((dibp == NULL) || (dibp->sch < 0)) return SCPE_IERR; -fprintf (st, "selch=%X", dibp->sch); -return SCPE_OK; -} - -/* Change device number for a device */ - -t_stat set_dev (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newdev; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newdev = get_uint (cptr, 16, DEV_MAX, &r); /* get new */ -if ((r != SCPE_OK) || (newdev == dibp->dno)) return r; -if (newdev == 0) return SCPE_ARG; /* must be > 0 */ -dibp->dno = newdev; /* store */ -return SCPE_OK; -} - -/* Show device number for a device */ - -t_stat show_dev (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -DEVICE *dptr; -DIB *dibp; - -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if ((dibp == NULL) || (dibp->dno == 0)) return SCPE_IERR; -fprintf (st, "devno=%02X", dibp->dno); -return SCPE_OK; -} - -/* Init device tables */ - -t_bool devtab_init (void) -{ -DEVICE *dptr; -DIB *dibp; -uint32 i, j, dno, dmsk, doff, t, dmap[DEVNO / 32]; -uint8 *tplte, dflt_tplte[] = { 0, TPL_END }; - -/* Clear tables, device map */ - -for (i = 0; i < DEVNO; i++) { - dev_tab[i] = NULL; - sch_tab[i] = 0; } -for (i = 0; i < (INTSZ * 32); i++) int_tab[i] = 0; -for (i = 0; i < (DEVNO / 32); i++) dmap[i] = 0; - -/* Test each device for conflict; add to map; init tables */ - -for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru devices */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if ((dibp == NULL) || (dptr->flags & DEV_DIS)) continue; /* exist, enabled? */ - dno = dibp->dno; /* get device num */ - if (dibp->ini) dibp->ini (TRUE); /* gen dno template */ - tplte = dibp->tplte; /* get template */ - if (tplte == NULL) tplte = dflt_tplte; /* none? use default */ - for ( ; *tplte != TPL_END; tplte++) { /* loop thru template */ - t = (dno + *tplte) & DEV_MAX; /* loop thru template */ - dmsk = 1u << (t & 0x1F); /* bit to test */ - doff = t / 32; /* word to test */ - if (dmap[doff] & dmsk) { /* in use? */ - printf ("Device number conflict, devno = %02X\n", t); - if (sim_log) fprintf (sim_log, - "Device number conflict, devno = %02X\n", t); - return TRUE; } - dmap[doff] = dmap[doff] | dmsk; - if (dibp->sch >= 0) sch_tab[t] = dibp->sch + 1; - dev_tab[t] = dibp->iot; } - - if (dibp->ini) dibp->ini (FALSE); /* gen int template */ - tplte = dibp->tplte; /* get template */ - if (tplte == NULL) tplte = dflt_tplte; /* none? use default */ - for (j = dibp->irq; *tplte != TPL_END; j++, tplte++) { - int_tab[j] = (dno + *tplte) & DEV_MAX; } - } /* end for i */ -return FALSE; -} diff --git a/Interdata/id_lp.c b/Interdata/id_lp.c deleted file mode 100644 index da118ebf..00000000 --- a/Interdata/id_lp.c +++ /dev/null @@ -1,290 +0,0 @@ -/* id_lp.c: Interdata line printer - - Copyright (c) 2001-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - lpt M46-206 line printer - - 25-Apr-03 RMS Revised for extended file support -*/ - -#include "id_defs.h" -#include - -/* Device definitions */ - -#define UNIT_V_UC (UNIT_V_UF + 0) /* UC only */ -#define UNIT_UC (1 << UNIT_V_UC) -#define SPC_BASE 0x40 /* spacing base */ -#define VFU_BASE 0x78 /* VFU base */ -#define VFU_WIDTH 0x8 /* VFU width */ -#define LF 0xA -#define VT 0xB -#define VT_VFU 4 /* VFU chan for VT */ -#define FF 0xC -#define FF_VFU 8 /* VFU chan for FF */ -#define CR 0xD -#define VFUP(ch,val) ((val) & (1 << (ch))) /* VFU chan test */ - -/* Status byte, * = dynamic */ - -#define STA_PAPE 0x40 /* *paper empty */ -#define STA_MASK (STA_BSY) /* static status */ - -uint32 lpt_sta = STA_BSY; /* status */ -char lpxb[LPT_WIDTH + 1]; /* line buffer */ -uint32 lpt_bptr = 0; /* buf ptr */ -uint32 lpt_spnd = 0; /* space pending */ -uint32 lpt_vfup = 0; /* VFU ptr */ -uint32 lpt_vful = 1; /* VFU lnt */ -uint8 lpt_vfut[VFU_LNT] = { 0xFF }; /* VFU tape */ -uint32 lpt_arm = 0; /* int armed */ -int32 lpt_ctime = 10; /* char time */ -int32 lpt_stime = 1000; /* space time */ -int32 lpt_stopioe = 0; /* stop on err */ - -extern uint32 int_req[INTSZ], int_enb[INTSZ]; - -DEVICE lpt_dev; -uint32 lpt (uint32 dev, uint32 op, uint32 dat); -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); -t_stat lpt_attach (UNIT *uptr, char *cptr); -t_stat lpt_bufout (UNIT *uptr); -t_stat lpt_vfu (UNIT *uptr, int32 ch); -t_stat lpt_spc (UNIT *uptr, int32 cnt); - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptors - lpt_reg LPT register list -*/ - -DIB lpt_dib = { d_LPT, -1, v_LPT, NULL, &lpt, NULL }; - -UNIT lpt_unit = { UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_UC, 0) }; - -REG lpt_reg[] = { - { HRDATA (STA, lpt_sta, 8) }, - { HRDATA (BUF, lpt_unit.buf, 7) }, - { BRDATA (DBUF, lpxb, 16, 7, LPT_WIDTH) }, - { HRDATA (DBPTR, lpt_bptr, 8) }, - { HRDATA (VFUP, lpt_vfup, 8) }, - { HRDATA (VFUL, lpt_vful, 8) }, - { BRDATA (VFUT, lpt_vfut, 16, 8, VFU_LNT) }, - { FLDATA (IREQ, int_req[l_LPT], i_LPT) }, - { FLDATA (IENB, int_enb[l_LPT], i_LPT) }, - { FLDATA (IARM, lpt_arm, 0) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (CTIME, lpt_ctime, 24), PV_LEFT }, - { DRDATA (STIME, lpt_stime, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lpt_stopioe, 0) }, - { HRDATA (DEVNO, lpt_dib.dno, 8), REG_HRO }, - { NULL } }; - -MTAB lpt_mod[] = { - { UNIT_UC, 0, "lower case", "LC", NULL }, - { UNIT_UC, UNIT_UC, "upper case", "UC", NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, lpt_mod, - 1, 10, 31, 1, 16, 7, - NULL, NULL, &lpt_reset, - NULL, &lpt_attach, NULL, - &lpt_dib, DEV_DISABLE }; - -/* Line printer: IO routine */ - -uint32 lpt (uint32 dev, uint32 op, uint32 dat) -{ -int32 t; - -switch (op) { /* case IO op */ -case IO_ADR: /* select */ - return BY; /* byte only */ -case IO_OC: /* command */ - lpt_arm = int_chg (v_LPT, dat, lpt_arm); /* upd int ctrl */ - break; -case IO_WD: /* write */ - t = lpt_unit.buf = dat & 0x7F; /* mask char */ - lpt_sta = STA_BSY; /* set busy */ - if (lpt_spnd || ((t >= LF) && (t <= CR))) /* space op? */ - sim_activate (&lpt_unit, lpt_stime); - else sim_activate (&lpt_unit, lpt_ctime); /* normal char */ - break; -case IO_SS: /* status */ - t = lpt_sta & STA_MASK; /* status byte */ - if ((lpt_unit.flags & UNIT_ATT) == 0) /* test paper out */ - t = t | STA_EX | STA_PAPE | STA_BSY; - return t; } -return 0; -} - -/* Unit service */ - -t_stat lpt_svc (UNIT *uptr) -{ -int32 t; -t_stat r = SCPE_OK; - -lpt_sta = 0; /* clear busy */ -if (lpt_arm) SET_INT (v_LPT); /* armed? intr */ -if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); -t = uptr->buf; /* get character */ -if (lpt_spnd || ((t >= LF) && (t < CR))) { /* spc pend or spc op? */ - lpt_spnd = 0; - if (lpt_bufout (uptr) != SCPE_OK) return SCPE_IOERR; /* print */ - if ((t == 1) || (t == LF)) lpt_spc (uptr, 1); /* single space */ - else if (t == VT) r = lpt_vfu (uptr, VT_VFU - 1); /* VT->VFU */ - else if (t == 0xC) r = lpt_vfu (uptr, FF_VFU - 1); /* FF->VFU */ - else if ((t >= SPC_BASE) && (t < VFU_BASE)) - lpt_spc (uptr, t - SPC_BASE); /* space */ - else if ((t >= VFU_BASE) && (t < VFU_BASE + VFU_WIDTH)) - r = lpt_vfu (uptr, t - VFU_BASE); /* VFU */ - else fputs ("\r", uptr->fileref); /* overprint */ - uptr->pos = ftell (uptr->fileref); /* update position */ - if (ferror (lpt_unit.fileref)) { - perror ("LPT I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } } -else if (t == CR) { /* CR? */ - lpt_spnd = 1; /* set spc pend */ - return lpt_bufout (uptr); } /* print line */ -else if (t >= 0x40) { /* printable? */ - if ((uptr->flags & UNIT_UC) && islower (t)) /* UC only? */ - t = toupper (t); - if (lpt_bptr < LPT_WIDTH) lpxb[lpt_bptr++] = t; } -return r; -} - -/* Printing and spacing routines */ - -t_stat lpt_bufout (UNIT *uptr) -{ -int32 i; -t_stat r = SCPE_OK; - -if (lpt_bptr == 0) return SCPE_OK; /* any char in buf? */ -for (i = LPT_WIDTH - 1; (i >= 0) && (lpxb[i] == ' '); i--) - lpxb[i] = 0; /* backscan line */ -if (lpxb[0]) { /* any char left? */ - fputs (lpxb, uptr->fileref); /* write line */ - lpt_unit.pos = ftell (uptr->fileref); /* update position */ - if (ferror (uptr->fileref)) { - perror ("LPT I/O error"); - clearerr (uptr->fileref); - r = SCPE_IOERR; } } -lpt_bptr = 0; /* reset buffer */ -for (i = 0; i < LPT_WIDTH; i++) lpxb[i] = ' '; -lpxb[LPT_WIDTH] = 0; -return r; -} - -t_stat lpt_vfu (UNIT *uptr, int32 ch) -{ -uint32 i, j; - -if ((ch == (FF_VFU - 1)) && VFUP (ch, lpt_vfut[0])) { /* top of form? */ - fputs ("\n\f", uptr->fileref); /* nl + ff */ - lpt_vfup = 0; /* top of page */ - return SCPE_OK; } -for (i = 1; i < lpt_vful + 1; i++) { /* sweep thru cct */ - lpt_vfup = (lpt_vfup + 1) % lpt_vful; /* adv pointer */ - if (VFUP (ch, lpt_vfut[lpt_vfup])) { /* chan punched? */ - for (j = 0; j < i; j++) fputc ('\n', uptr->fileref); - return SCPE_OK; } } -return STOP_VFU; /* runaway channel */ -} - -t_stat lpt_spc (UNIT *uptr, int32 cnt) -{ -int32 i; - -if (cnt == 0) fputc ('\r', uptr->fileref); -else { for (i = 0; i < cnt; i++) fputc ('\n', uptr->fileref); - lpt_vfup = (lpt_vfup + cnt) % lpt_vful; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ -int32 i; - -sim_cancel (&lpt_unit); /* deactivate */ -lpt_sta = 0; /* clr busy */ -lpt_bptr = 0; /* clr buf ptr */ -for (i = 0; i < LPT_WIDTH; i++) lpxb[i] = ' '; /* clr buf */ -lpxb[LPT_WIDTH] = 0; -CLR_INT (v_LPT); /* clearr int */ -CLR_ENB (v_LPT); /* disable int */ -lpt_arm = 0; /* disarm int */ -return SCPE_OK; -} - -/* Attach routine */ - -t_stat lpt_attach (UNIT *uptr, char *cptr) -{ -lpt_vfup = 0; /* top of form */ -return attach_unit (uptr, cptr); -} - -/* Carriage control load routine */ - -t_stat lp_load (FILE *fileref, char *cptr, char *fnam) -{ -int32 col, ptr, mask, vfubuf[VFU_LNT]; -uint32 rpt; -t_stat r; -char cbuf[CBUFSIZE], gbuf[CBUFSIZE]; - -if (*cptr != 0) return SCPE_ARG; -ptr = 0; -for ( ; (cptr = fgets (cbuf, CBUFSIZE, fileref)) != NULL; ) { /* until eof */ - mask = 0; - if (*cptr == '(') { /* repeat count? */ - cptr = get_glyph (cptr + 1, gbuf, ')'); /* get 1st field */ - rpt = get_uint (gbuf, 10, VFU_LNT, &r); /* repeat count */ - if (r != SCPE_OK) return SCPE_FMT; } - else rpt = 1; - while (*cptr != 0) { /* get col no's */ - cptr = get_glyph (cptr, gbuf, ','); /* get next field */ - col = get_uint (gbuf, 10, 7, &r); /* column number */ - if (r != SCPE_OK) return SCPE_FMT; - mask = mask | (1 << col); } /* set bit */ - for ( ; rpt > 0; rpt--) { /* store vals */ - if (ptr >= VFU_LNT) return SCPE_FMT; - vfubuf[ptr++] = mask; } } -if (ptr == 0) return SCPE_FMT; -lpt_vful = ptr; -lpt_vfup = 0; -for (rpt = 0; rpt < lpt_vful; rpt++) lpt_vfut[rpt] = vfubuf[rpt]; -return SCPE_OK; -} diff --git a/Interdata/id_mt.c b/Interdata/id_mt.c deleted file mode 100644 index 61d671f7..00000000 --- a/Interdata/id_mt.c +++ /dev/null @@ -1,482 +0,0 @@ -/* id_mt.c: Interdata magnetic tape simulator - - Copyright (c) 2001-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - mt M46-494 dual density 9-track magtape controller - - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Revised for magtape library - 20-Feb-03 RMS Fixed read to stop selch on error - - Magnetic tapes are represented as a series of variable 8b records - of the form: - - 32b record length in bytes - exact number - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32b record length in bytes - exact number - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a single record length of 0. - End of tape is two consecutive end of file marks. -*/ - -#include "id_defs.h" -#include "sim_tape.h" - -#define UST u3 /* unit status */ -#define UCMD u4 /* unit command */ -#define MT_MAXFR (1 << 16) /* max transfer */ - -/* Command - in UCMD */ - -#define MTC_SPCR 0x11 /* backspace */ -#define MTC_SKFR 0x13 /* space file rev */ -#define MTC_CLR 0x20 /* clear */ -#define MTC_RD 0x21 /* read */ -#define MTC_WR 0x22 /* write */ -#define MTC_SKFF 0x23 /* space file fwd */ -#define MTC_WEOF 0x30 /* write eof */ -#define MTC_REW 0x38 /* rewind */ -#define MTC_MASK 0x3F -#define MTC_STOP1 0x40 /* stop, set EOM */ -#define MTC_STOP2 0x80 /* stop, set NMTN */ - -/* Status byte, * = in UST */ - -#define STA_ERR 0x80 /* error */ -#define STA_EOF 0x40 /* end of file */ -#define STA_EOT 0x20 /* *end of tape */ -#define STA_NMTN 0x10 /* *no motion */ -#define STA_UFLGS (STA_EOT|STA_NMTN) /* unit flags */ -#define STA_MASK (STA_ERR|STA_EOF|STA_BSY|STA_EOM) -#define SET_EX (STA_ERR|STA_EOF|STA_NMTN) - -extern uint32 int_req[INTSZ], int_enb[INTSZ]; - -uint8 mtxb[MT_MAXFR]; /* xfer buffer */ -uint32 mt_bptr = 0; /* pointer */ -uint32 mt_blnt = 0; /* length */ -uint32 mt_sta = 0; /* status byte */ -uint32 mt_db = 0; /* data buffer */ -uint32 mt_xfr = 0; /* data xfr in prog */ -uint32 mt_arm[MT_NUMDR] = { 0 }; /* intr armed */ -int32 mt_wtime = 10; /* byte latency */ -int32 mt_rtime = 1000; /* record latency */ -int32 mt_stopioe = 1; /* stop on error */ -uint8 mt_tplte[] = { 0, o_MT0, o_MT0*2, o_MT0*3, TPL_END }; - -static const uint8 bad_cmd[64] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }; - -DEVICE mt_dev; -uint32 mt (uint32 dev, uint32 op, uint32 dat); -t_stat mt_svc (UNIT *uptr); -t_stat mt_reset (DEVICE *dptr); -t_stat mt_attach (UNIT *uptr, char *cptr); -t_stat mt_detach (UNIT *uptr); -t_stat mt_boot (int32 unitno, DEVICE *dptr); -t_stat mt_map_err (UNIT *uptr, t_stat st); - -/* MT data structures - - mt_dev MT device descriptor - mt_unit MT unit list - mt_reg MT register list - mt_mod MT modifier list -*/ - -DIB mt_dib = { d_MT, 0, v_MT, mt_tplte, &mt, NULL }; - -UNIT mt_unit[] = { - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) } }; - -REG mt_reg[] = { - { HRDATA (STA, mt_sta, 8) }, - { HRDATA (BUF, mt_db, 8) }, - { BRDATA (DBUF, mtxb, 16, 8, MT_MAXFR) }, - { HRDATA (DBPTR, mt_bptr, 16) }, - { HRDATA (DBLNT, mt_blnt, 17), REG_RO }, - { FLDATA (XFR, mt_xfr, 0) }, - { GRDATA (IREQ, int_req[l_MT], 16, MT_NUMDR, i_MT) }, - { GRDATA (IENB, int_enb[l_MT], 16, MT_NUMDR, i_MT) }, - { BRDATA (IARM, mt_arm, 16, 1, MT_NUMDR) }, - { FLDATA (STOP_IOE, mt_stopioe, 0) }, - { DRDATA (WTIME, mt_wtime, 24), PV_LEFT + REG_NZ }, - { DRDATA (RTIME, mt_rtime, 24), PV_LEFT + REG_NZ }, - { URDATA (UST, mt_unit[0].UST, 16, 8, 0, MT_NUMDR, 0) }, - { URDATA (CMD, mt_unit[0].UCMD, 16, 8, 0, MT_NUMDR, 0) }, - { URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0, - MT_NUMDR, PV_LEFT | REG_RO) }, - { HRDATA (DEVNO, mt_dib.dno, 8), REG_HRO }, - { HRDATA (SELCH, mt_dib.sch, 1), REG_HRO }, - { NULL } }; - -MTAB mt_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH", - &set_sch, &show_sch, NULL }, - { 0 } }; - -DEVICE mt_dev = { - "MT", mt_unit, mt_reg, mt_mod, - MT_NUMDR, 10, 31, 1, 16, 8, - NULL, NULL, &mt_reset, - &mt_boot, &mt_attach, &mt_detach, - &mt_dib, DEV_DISABLE }; - -/* Magtape: IO routine */ - -uint32 mt (uint32 dev, uint32 op, uint32 dat) -{ -uint32 i, f, t; -uint32 u = (dev - mt_dib.dno) / o_MT0; -UNIT *uptr = mt_dev.units + u; - -switch (op) { /* case IO op */ -case IO_ADR: /* select */ - sch_adr (mt_dib.sch, dev); /* inform sel ch */ - return BY; /* byte only */ -case IO_RD: /* read data */ - if (mt_xfr) mt_sta = mt_sta | STA_BSY; /* xfr? set busy */ - return mt_db; /* return data */ -case IO_WD: /* write data */ - if (mt_xfr) { /* transfer? */ - mt_sta = mt_sta | STA_BSY; /* set busy */ - if ((uptr->UCMD & (MTC_STOP1 | MTC_STOP2)) && - ((uptr->UCMD & MTC_MASK) == MTC_WR)) /* while stopping? */ - mt_sta = mt_sta | STA_ERR; } /* write overrun */ - mt_db = dat & DMASK8; /* store data */ - break; -case IO_SS: /* status */ - mt_sta = mt_sta & STA_MASK; /* ctrl status */ - if (uptr->flags & UNIT_ATT) /* attached? */ - t = mt_sta | (uptr->UST & STA_UFLGS); /* yes, unit status */ - else t = mt_sta | STA_DU; /* no, dev unavail */ - if (t & SET_EX) t = t | STA_EX; /* test for ex */ - return t; -case IO_OC: /* command */ - mt_arm[u] = int_chg (v_MT + u, dat, mt_arm[u]); - f = dat & MTC_MASK; /* get cmd */ - if (f == MTC_CLR) { /* clear? */ - mt_reset (&mt_dev); /* reset world */ - break; } - if (((uptr->flags & UNIT_ATT) == 0) || /* ignore if unatt */ - bad_cmd[f] || /* or bad cmd */ - (((f == MTC_WR) || (f == MTC_WEOF)) && /* or write */ - sim_tape_wrp (uptr))) break; /* and protected */ - for (i = 0; i < MT_NUMDR; i++) { /* check other drvs */ - if (sim_is_active (&mt_unit[i]) && /* active? */ - (mt_unit[i].UCMD != MTC_REW)) { /* not rewind? */ - sim_cancel (&mt_unit[i]); /* stop */ - mt_unit[i].UCMD = 0; } - if (sim_is_active (uptr) && /* unit active? */ - !(uptr->UCMD & (MTC_STOP1 | MTC_STOP2))) /* not stopping? */ - break; /* ignore */ - if ((f == MTC_WR) || (f == MTC_REW)) mt_sta = 0;/* write, rew: bsy=0 */ - else mt_sta = STA_BSY; /* bsy=1,nmtn,eom,err=0 */ - mt_bptr = mt_blnt = 0; /* not yet started */ - if ((f == MTC_RD) || (f == MTC_WR)) /* data xfr? */ - mt_xfr = 1; /* set xfr flag */ - else mt_xfr = 0; } - uptr->UCMD = f; /* save cmd */ - uptr->UST = 0; /* clr tape stat */ - sim_activate (uptr, mt_rtime); /* start op */ - break; } -return 0; -} - -/* Unit service - - A given operation can generate up to three interrupts - - - EOF generates an interrupt when set (read, space, wreof) - BUSY will still be set, EOM and NMTN will be clear - - After operation complete + delay, EOM generates an interrupt - BUSY will be clear, EOM will be set, NMTN will be clear - - After a further delay, NMTN generates an interrupt - BUSY will be clear, EOM and NMTN will be set - - Rewind generates an interrupt when NMTN sets -*/ - -t_stat mt_svc (UNIT *uptr) -{ -uint32 i; -int32 u = uptr - mt_dev.units; -uint32 dev = mt_dib.dno + (u * o_MT0); -t_mtrlnt tbc; -t_stat st, r = SCPE_OK; - -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - uptr->UCMD = 0; /* clr cmd */ - uptr->UST = 0; /* set status */ - mt_xfr = 0; /* clr op flags */ - mt_sta = STA_ERR | STA_EOM; /* set status */ - if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */ - return IORETURN (mt_stopioe, SCPE_UNATT); } - -if (uptr->UCMD & MTC_STOP2) { /* stop, gen NMTN? */ - uptr->UCMD = 0; /* clr cmd */ - uptr->UST = STA_NMTN; /* set nmtn, not eot */ - mt_xfr = 0; /* clr xfr */ - if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */ - return SCPE_OK; } - -if (uptr->UCMD & MTC_STOP1) { /* stop, gen EOM? */ - uptr->UCMD = uptr->UCMD | MTC_STOP2; /* clr cmd */ - mt_sta = (mt_sta & ~STA_BSY) | STA_EOM; /* clr busy, set eom */ - if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */ - sim_activate (uptr, mt_rtime); /* schedule */ - return SCPE_OK; } /* end case */ - -switch (uptr->UCMD) { /* case on function */ - -case MTC_REW: /* rewind */ - sim_tape_rewind (uptr); /* reposition */ - uptr->UCMD = 0; /* clr cmd */ - uptr->UST = STA_NMTN | STA_EOT; /* update status */ - mt_sta = mt_sta & ~STA_BSY; /* don't set EOM */ - if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */ - return SCPE_OK; - -/* Unit service, continued - - For read, busy = 1 => buffer empty - For write, busy = 1 => buffer full - For read, data transfers continue for the full length of the - record, or the maximum size of the transfer buffer - For write, data transfers continue until a write is attempted - and the buffer is empty -*/ - -case MTC_RD: /* read */ - if (mt_blnt == 0) { /* first time? */ - st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */ - if (st == MTSE_RECE) mt_sta = mt_sta | STA_ERR; /* rec in err? */ - else if (st != SCPE_OK) { /* other error? */ - r = mt_map_err (uptr, st); /* map error */ - if (sch_actv (mt_dib.sch, dev)) /* if sch, stop */ - sch_stop (mt_dib.sch); - break; } - mt_blnt = tbc; /* set buf lnt */ - } - - if (sch_actv (mt_dib.sch, dev)) { /* sch active? */ - i = sch_wrmem (mt_dib.sch, mtxb, mt_blnt); /* store rec in mem */ - if (sch_actv (mt_dib.sch, dev)) /* sch still active? */ - sch_stop (mt_dib.sch); /* stop chan, long rd */ - else if (i < mt_blnt) /* process entire rec? */ - mt_sta = mt_sta | STA_ERR; } /* no, overrun error */ - else if (mt_bptr < mt_blnt) { /* no, if !eor */ - if (!(mt_sta & STA_BSY)) /* busy still clr? */ - mt_sta = mt_sta | STA_ERR; /* read overrun */ - mt_db = mtxb[mt_bptr++]; /* get next byte */ - mt_sta = mt_sta & ~STA_BSY; /* !busy = buf full */ - if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */ - sim_activate (uptr, mt_wtime); /* reschedule */ - return SCPE_OK; } - break; /* record done */ - -case MTC_WR: /* write */ - if (sch_actv (mt_dib.sch, dev)) { /* sch active? */ - mt_bptr = sch_rdmem (mt_dib.sch, mtxb, MT_MAXFR); /* get rec */ - if (sch_actv (mt_dib.sch, dev)) /* not done? */ - sch_stop (mt_dib.sch); } /* stop chan */ - else if (mt_sta & STA_BSY) { /* no, if !eor */ - if (mt_bptr < MT_MAXFR) /* if room */ - mtxb[mt_bptr++] = mt_db; /* store in buf */ - mt_sta = mt_sta & ~STA_BSY; /* !busy = buf emp */ - if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */ - sim_activate (uptr, mt_wtime); /* reschedule */ - return SCPE_OK; } - - if (mt_bptr) { /* any chars? */ - if (st = sim_tape_wrrecf (uptr, mtxb, mt_bptr)) /* write, err? */ - r = mt_map_err (uptr, st); } /* map error */ - break; /* record done */ - -/* Unit service, continued */ - -case MTC_WEOF: /* write eof */ - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = mt_map_err (uptr, st); /* map error */ - mt_sta = mt_sta | STA_EOF; /* set eof */ - if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */ - break; - -case MTC_SKFF: /* skip file fwd */ - while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ; - if (st == MTSE_TMK) { /* stopped by tmk? */ - mt_sta = mt_sta | STA_EOF; /* set eof */ - if (mt_arm[u]) SET_INT (v_MT + u); } /* set intr */ - else r = mt_map_err (uptr, st); /* map error */ - break; - -case MTC_SKFR: /* skip file rev */ - while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ; - if (st == MTSE_TMK) { /* stopped by tmk? */ - mt_sta = mt_sta | STA_EOF; /* set eof */ - if (mt_arm[u]) SET_INT (v_MT + u); } /* set intr */ - else r = mt_map_err (uptr, st); /* map error */ - break; - -case MTC_SPCR: /* backspace */ - if (st = sim_tape_sprecr (uptr, &tbc)) /* skip rec rev, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; } /* end case */ - -uptr->UCMD = uptr->UCMD | MTC_STOP1; /* set stop stage 1 */ -sim_activate (uptr, mt_rtime); /* schedule */ -return r; -} - -/* Map tape error status */ - -t_stat mt_map_err (UNIT *uptr, t_stat st) -{ -int32 u = uptr - mt_dev.units; - -switch (st) { -case MTSE_FMT: /* illegal fmt */ -case MTSE_UNATT: /* not attached */ - mt_sta = mt_sta | STA_ERR; -case MTSE_OK: /* no error */ - return SCPE_IERR; -case MTSE_TMK: /* end of file */ - mt_sta = mt_sta | STA_EOF; /* set eof */ - if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */ - break; -case MTSE_IOERR: /* IO error */ - mt_sta = mt_sta | STA_ERR; /* set err */ - if (mt_stopioe) return SCPE_IOERR; - break; -case MTSE_INVRL: /* invalid rec lnt */ - mt_sta = mt_sta | STA_ERR; - return SCPE_MTRLNT; -case MTSE_WRP: /* write protect */ -case MTSE_RECE: /* record in error */ -case MTSE_EOM: /* end of medium */ - mt_sta = mt_sta | STA_ERR; /* set err */ - break; -case MTSE_BOT: /* reverse into BOT */ - uptr->UST = uptr->UST | STA_EOT; /* set err */ - break; } /* end switch */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat mt_reset (DEVICE *dptr) -{ -uint32 u; -UNIT *uptr; - -mt_bptr = mt_blnt = 0; /* clr buf */ -mt_sta = STA_BSY; /* clr flags */ -mt_xfr = 0; /* clr controls */ -for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */ - CLR_INT (v_MT + u); /* clear int */ - CLR_ENB (v_MT + u); /* disable int */ - mt_arm[u] = 0; /* disarm int */ - uptr = mt_dev.units + u; - sim_tape_reset (uptr); /* clear pos flag */ - sim_cancel (uptr); /* cancel activity */ - uptr->UST = (uptr->UST & STA_UFLGS) | STA_NMTN; /* init status */ - uptr->UCMD = 0; } /* init cmd */ -return SCPE_OK; -} - -/* Attach routine */ - -t_stat mt_attach (UNIT *uptr, char *cptr) -{ -int32 u = uptr - mt_dev.units; -t_stat r; - -r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; -uptr->UST = STA_EOT; -if (mt_arm[u]) SET_INT (v_MT + u); -return r; -} - -/* Detach routine */ - -t_stat mt_detach (UNIT* uptr) -{ -int32 u = uptr - mt_dev.units; -t_stat r; - -r = sim_tape_detach (uptr); -if (r != SCPE_OK) return r; -if (mt_arm[u]) SET_INT (v_MT + u); -uptr->UST = 0; -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define BOOT_START 0x50 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8)) - -static uint8 boot_rom[] = { - 0xD5, 0x00, /* ST: AL CF */ - 0x00, 0xCF, - 0x43, 0x00, /* BR 80 */ - 0x00, 0x80 -}; - -t_stat mt_boot (int32 unitno, DEVICE *dptr) -{ -extern uint32 PC, dec_flgs; -extern uint16 decrom[]; -extern DIB sch_dib; -uint32 sch_dev; - -if (decrom[0xD5] & dec_flgs) return SCPE_NOFNC; /* AL defined? */ -sim_tape_rewind (&mt_unit[unitno]); /* rewind */ -sch_dev = sch_dib.dno + mt_dib.sch; /* sch dev # */ -IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy boot */ -IOWriteB (AL_DEV, mt_dib.dno + (unitno * o_MT0)); /* set dev no for unit */ -IOWriteB (AL_IOC, 0xA1); /* set dev cmd */ -IOWriteB (AL_SCH, sch_dev); /* set dev no for chan */ -PC = BOOT_START; -return SCPE_OK; -} diff --git a/Interdata/id_pas.c b/Interdata/id_pas.c deleted file mode 100644 index 03591711..00000000 --- a/Interdata/id_pas.c +++ /dev/null @@ -1,548 +0,0 @@ -/* id_pas.c: Interdata programmable async line adapter simulator - - Copyright (c) 2001-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - pas Programmable asynchronous line adapter(s) - - 09-May-03 RMS Added network device flag - - This module implements up to 32 individual serial interfaces, representing - either individual PASLA modules or combinations of the 2-line and 8-line - multiplexors, which are functionally very similar. These interfaces are mapped - to Telnet based connections as the lines of a terminal multiplexor. The - connection polling mechanism and the character input polling for all lines - are done through a single polling job. -*/ - -#include "id_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" -#include - -#define PAS_LINES 32 - -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */ -#define UNIT_V_MDM (UNIT_V_UF + 2) /* modem control */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_UC (1 << UNIT_V_UC) -#define UNIT_MDM (1 << UNIT_V_MDM) - -#define PAS_INIT_POLL 8000 -#define PASL_WAIT 500 - -/* Status byte */ - -#define STA_OVR 0x80 /* overrun RO */ -#define STA_PF 0x40 /* parity err RONI */ -#define STA_NCL2S 0x40 /* not clr to snd XO */ -#define STA_FR 0x20 /* framing err RO */ -#define STA_RCR 0x10 /* rv chan rcv NI */ -#define STA_CROF 0x02 /* carrier off RO */ -#define STA_RING 0x01 /* ring RO */ -#define STA_RCV (STA_OVR|STA_PF|STA_FR|STA_RCR|STA_CROF|STA_RING) -#define SET_EX (STA_OVR|STA_PF|STA_FR) -#define STA_XMT (STA_BSY) - -/* Command bytes 1,0 */ - -#define CMD_DTR (0x20 << 8) /* DTR */ -#define CMD_ECHO (0x10 << 8) /* echoplex */ -#define CMD_RCT (0x08 << 8) /* RCT/DTB NI */ -#define CMD_XMTB (0x04 << 8) /* xmt break NI */ -#define CMD_WRT (0x02 << 8) /* write/read */ -#define CMD_V_CLK 6 /* baud rate */ -#define CMD_M_CLK 0x3 -#define CMD_V_DB 4 /* data bits */ -#define CMD_M_DB 0x3 -#define CMD_STOP 0x80 /* stop bit */ -#define CMD_V_PAR 1 /* parity */ -#define CMD_M_PAR 0x3 -#define GET_PAR(x) (((x) >> CMD_V_PAR) & CMD_M_PAR) -#define PAR_NONE 0 -#define PAR_RAW 1 -#define PAR_ODD 2 -#define PAR_EVEN 3 - -#define CMD_TYP 0x01 /* command type */ - -extern uint32 int_req[INTSZ], int_enb[INTSZ]; - -uint8 pas_sta[PAS_LINES]; /* status */ -uint16 pas_cmd[PAS_LINES]; /* command */ -uint8 pas_rbuf[PAS_LINES]; /* rcv buf */ -uint8 pas_xbuf[PAS_LINES]; /* xmt buf */ -uint8 pas_rarm[PAS_LINES]; /* rcvr int armed */ -uint8 pas_xarm[PAS_LINES]; /* xmt int armed */ -uint8 pas_rchp[PAS_LINES]; /* rcvr chr pend */ -uint32 pas_tps = 50; /* polls/second */ -uint8 pas_tplte[PAS_LINES * 2 + 1]; /* template */ - -TMLN pas_ldsc[PAS_LINES] = { 0 }; /* line descriptors */ -TMXR pas_desc = { 8, 0, 0, &pas_ldsc[0], NULL }; /* mux descriptor */ -#define PAS_ENAB pas_desc.lines - -uint32 pas (uint32 dev, uint32 op, uint32 dat); -void pas_ini (t_bool dtpl); -t_stat pasi_svc (UNIT *uptr); -t_stat paso_svc (UNIT *uptr); -t_stat pas_reset (DEVICE *dptr); -t_stat pas_attach (UNIT *uptr, char *cptr); -t_stat pas_detach (UNIT *uptr); -t_stat pas_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat pas_show (FILE *st, UNIT *uptr, int32 val, void *desc); -int32 pas_par (int32 cmd, int32 c); -t_stat pas_vlines (UNIT *uptr, int32 val, char *cptr, void *desc); -void pas_reset_ln (int32 i); - -/* PAS data structures - - pas_dev PAS device descriptor - pas_unit PAS unit descriptor - pas_reg PAS register list - pas_mod PAS modifiers list -*/ - -DIB pas_dib = { d_PAS, -1, v_PAS, pas_tplte, &pas, &pas_ini }; - -UNIT pas_unit = { UDATA (&pasi_svc, UNIT_ATTABLE, 0), PAS_INIT_POLL }; - -REG pas_nlreg = { DRDATA (NLINES, PAS_ENAB, 6), PV_LEFT }; - -REG pas_reg[] = { - { BRDATA (STA, pas_sta, 16, 8, PAS_LINES) }, - { BRDATA (CMD, pas_cmd, 16, 16, PAS_LINES) }, - { BRDATA (RBUF, pas_rbuf, 16, 8, PAS_LINES) }, - { BRDATA (XBUF, pas_xbuf, 16, 8, PAS_LINES) }, - { BRDATA (IREQ, &int_req[l_PAS], 16, 32, PAS_LINES / 16) }, - { BRDATA (IENB, &int_enb[l_PAS], 16, 32, PAS_LINES / 16) }, - { BRDATA (RARM, pas_rarm, 16, 1, PAS_LINES) }, - { BRDATA (XARM, pas_xarm, 16, 1, PAS_LINES) }, - { BRDATA (RCHP, pas_rchp, 16, 1, PAS_LINES) }, - { HRDATA (DEVNO, pas_dib.dno, 8), REG_HRO }, - { NULL } }; - -MTAB pas_mod[] = { - { MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES", - &pas_vlines, NULL, &pas_nlreg }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &pas_desc }, - { UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &pas_summ }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &pas_show, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &pas_show, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE pas_dev = { - "PAS", &pas_unit, pas_reg, pas_mod, - 1, 10, 31, 1, 16, 8, - &tmxr_ex, &tmxr_dep, &pas_reset, - NULL, &pas_attach, &pas_detach, - &pas_dib, DEV_NET | DEV_DISABLE }; - -/* PASL data structures - - pasl_dev PASL device descriptor - pasl_unit PASL unit descriptor - pasl_reg PASL register list - pasl_mod PASL modifiers list -*/ - -UNIT pasl_unit[] = { - { UDATA (&paso_svc, 0, 0), PASL_WAIT }, /* all but 8 dis */ - { UDATA (&paso_svc, 0, 0), PASL_WAIT }, - { UDATA (&paso_svc, 0, 0), PASL_WAIT }, - { UDATA (&paso_svc, 0, 0), PASL_WAIT }, - { UDATA (&paso_svc, 0, 0), PASL_WAIT }, - { UDATA (&paso_svc, 0, 0), PASL_WAIT }, - { UDATA (&paso_svc, 0, 0), PASL_WAIT }, - { UDATA (&paso_svc, 0, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, - { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT } }; - -MTAB pasl_mod[] = { - { UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", NULL }, - { UNIT_UC+UNIT_8B, 0 , "7b", "7B", NULL }, - { UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", NULL }, - { UNIT_MDM, 0, "no dataset", "NODATASET", NULL }, - { UNIT_MDM, UNIT_MDM, "dataset", "DATASET", NULL }, - { 0 } }; - -REG pasl_reg[] = { - { URDATA (TIME, pasl_unit[0].wait, 16, 24, 0, - PAS_LINES, REG_NZ + PV_LEFT) }, - { NULL } }; - -DEVICE pasl_dev = { - "PASL", pasl_unit, pasl_reg, pasl_mod, - PAS_LINES, 10, 31, 1, 16, 8, - NULL, NULL, &pas_reset, - NULL, NULL, NULL, - NULL, 0 }; - -/* PAS: IO routine */ - -uint32 pas (uint32 dev, uint32 op, uint32 dat) -{ -int32 ln = (dev - pas_dib.dno) >> 1; -int32 xmt = (dev - pas_dib.dno) & 1; -int32 t, old_cmd; - -switch (op) { /* case IO op */ -case IO_ADR: /* select */ - return BY; /* byte only */ -case IO_RD: /* read */ - pas_rchp[ln] = 0; /* clr chr pend */ - pas_sta[ln] = pas_sta[ln] & ~STA_OVR; /* clr overrun */ - return pas_rbuf[ln]; /* return buf */ -case IO_WD: /* write */ - pas_xbuf[ln] = dat & 0xFF; /* store char */ - pas_sta[ln] = pas_sta[ln] | STA_BSY; /* set busy */ - sim_activate (&pasl_unit[ln], pasl_unit[ln].wait); - break; -case IO_SS: /* status */ - if (xmt) { /* xmt side? */ - if (pas_ldsc[ln].conn == 0) /* not conn? */ - t = STA_NCL2S | STA_BSY; /* busy, not clr */ - else t = pas_sta[ln] & STA_XMT; } /* else just busy */ - else { - t = pas_sta[ln] & STA_RCV; /* get static */ - if (!pas_rchp[ln]) t = t | STA_BSY; /* no char? busy */ - if (pas_ldsc[ln].conn == 0) /* not connected? */ - t = t | STA_BSY | STA_EX; /* = !dsr */ - if (t & SET_EX) t = t | STA_EX; } /* test for ex */ - return t; -case IO_OC: /* command */ - old_cmd = pas_cmd[ln]; /* old cmd */ - if (dat & CMD_TYP) { /* type 1? */ - pas_cmd[ln] = (pas_cmd[ln] & 0xFF) | (dat << 8); - if (pas_cmd[ln] & CMD_WRT) /* write? */ - pas_xarm[ln] = int_chg (v_PASX + ln + ln, dat, pas_xarm[ln]); - else pas_rarm[ln] = int_chg (v_PAS + ln + ln, dat, pas_rarm[ln]); } - else pas_cmd[ln] = (pas_cmd[ln] & ~0xFF) | dat; - if (pasl_unit[ln].flags & UNIT_MDM) { /* modem ctrl? */ - if ((pas_cmd[ln] & CMD_DTR) && (pas_sta[ln] & STA_RING)) - pas_sta[ln] = pas_sta[ln] & ~(STA_CROF | STA_RING); - if (old_cmd & ~pas_cmd[ln] & CMD_DTR) { - tmxr_msg (pas_ldsc[ln].conn, "\r\nLine hangup\r\n"); - tmxr_reset_ln (&pas_ldsc[ln]); /* reset line */ - pas_sta[ln] = pas_sta[ln] | STA_CROF; /* no carrier */ - if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln); } } - break; } -return 0; -} - -/* Unit service - receive side - - Poll all active lines for input - Poll for new connections -*/ - -t_stat pasi_svc (UNIT *uptr) -{ -int32 ln, c, out, t; - -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ -t = sim_rtcn_calb (pas_tps, TMR_PAS); /* calibrate */ -sim_activate (uptr, t); /* continue poll */ -ln = tmxr_poll_conn (&pas_desc); /* look for connect */ -if (ln >= 0) { /* got one? */ - if ((pasl_unit[ln].flags & UNIT_MDM) && /* modem control */ - ((pas_cmd[ln] & CMD_DTR) == 0)) /* & !dtr? */ - pas_sta[ln] = pas_sta[ln] | STA_RING | STA_CROF; /* set ring, no cd */ - else pas_sta[ln] = pas_sta[ln] & ~STA_CROF; /* just answer */ - if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln); /* interrupt */ - pas_ldsc[ln].rcve = 1; } /* rcv enabled */ -tmxr_poll_rx (&pas_desc); /* poll for input */ -for (ln = 0; ln < PAS_ENAB; ln++) { /* loop thru lines */ - if (pas_ldsc[ln].conn) { /* connected? */ - if (c = tmxr_getc_ln (&pas_ldsc[ln])) { /* any char? */ - pas_sta[ln] = pas_sta[ln] & ~(STA_FR | STA_PF); - if (pas_rchp[ln]) pas_sta[ln] = pas_sta[ln] | STA_OVR; - if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln); - if (c & SCPE_BREAK) { /* break? */ - pas_sta[ln] = pas_sta[ln] | STA_FR; /* framing error */ - pas_rbuf[ln] = 0; } /* no character */ - else { /* normal */ - out = c & 0x7F; /* echo is 7b */ - if (pasl_unit[ln].flags & UNIT_8B) /* 8b? */ - c = c & 0xFF; - else { /* UC or 7b */ - if ((pasl_unit[ln].flags & UNIT_UC) && islower (out)) - out = toupper (out); /* cvt to UC */ - c = pas_par (pas_cmd[ln], out); } /* apply parity */ - pas_rbuf[ln] = c; /* save char */ - pas_rchp[ln] = 1; /* char pending */ - if ((pas_cmd[ln] & CMD_ECHO) && pas_ldsc[ln].xmte) { - TMLN *lp = &pas_ldsc[ln]; /* get line */ - tmxr_putc_ln (lp, out); /* output char */ - tmxr_poll_tx (&pas_desc); } /* poll xmt */ - } /* end else normal */ - } /* end if char */ - } /* end if conn */ - else if ((pas_sta[ln] & STA_CROF) == 0) { /* not conn, was conn? */ - pas_sta[ln] = pas_sta[ln] | STA_CROF; /* no carrier */ - if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln); } /* intr */ - } /* end for */ -return SCPE_OK; -} - -/* Unit service - transmit side */ - -t_stat paso_svc (UNIT *uptr) -{ -int32 c; -uint32 ln = uptr - pasl_unit; /* line # */ - -if (pas_ldsc[ln].conn) { /* connected? */ - if (pas_ldsc[ln].xmte) { /* xmt enabled? */ - TMLN *lp = &pas_ldsc[ln]; /* get line */ - if (pasl_unit[ln].flags & UNIT_8B) /* 8b? */ - c = pas_par (pas_cmd[ln], pas_xbuf[ln]);/* apply parity */ - else { /* UC or 7b */ - c = pas_xbuf[ln] & 0x7F; /* mask char */ - if ((pasl_unit[ln].flags & UNIT_UC) && islower (c)) - c = toupper (c); } /* cvt to UC */ - tmxr_putc_ln (lp, c); /* output char */ - tmxr_poll_tx (&pas_desc); } /* poll xmt */ - else { /* buf full */ - tmxr_poll_tx (&pas_desc); /* poll xmt */ - sim_activate (uptr, pasl_unit[ln].wait); /* wait */ - return SCPE_OK; } } -pas_sta[ln] = pas_sta[ln] & ~STA_BSY; /* not busy */ -if (pas_xarm[ln]) SET_INT (v_PASX + ln + ln); /* set intr */ -return SCPE_OK; -} - -int32 pas_par (int32 cmd, int32 c) -{ -int32 pf = GET_PAR (cmd); -static const uint8 odd_par[] = { - 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 00 */ - 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, - 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 10 */ - 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, - 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 20 */ - 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, - 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 30 */ - 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, - 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 40 */ - 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, - 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 50 */ - 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, - 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 60 */ - 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, - 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 70 */ - 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, - 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 80 */ - 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, - 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 90 */ - 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, - 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* A0 */ - 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, - 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* B0 */ - 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, - 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* C0 */ - 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, - 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* D0 */ - 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, - 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* E0 */ - 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, - 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* F0 */ - 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80 }; - -switch (pf) { /* case on parity */ -case PAR_ODD: - return (odd_par[c & 0x7F]) | (c & 0x7F); -case PAR_EVEN: - return (odd_par[c & 0x7F] ^ 0x80) | (c & 0x7F); -case PAR_NONE: -case PAR_RAW: - break; } -return c & 0xFF; -} - -/* Reset routine */ - -t_stat pas_reset (DEVICE *dptr) -{ -int32 i, t; - -if (dptr->flags & DEV_DIS) { /* disabled? */ - pas_dev.flags = pas_dev.flags | DEV_DIS; /* disable lines */ - pasl_dev.flags = pasl_dev.flags | DEV_DIS; } -else { pas_dev.flags = pas_dev.flags & ~DEV_DIS; /* enable lines */ - pasl_dev.flags = pasl_dev.flags & ~DEV_DIS; } -if (pas_unit.flags & UNIT_ATT) { /* master att? */ - if (!sim_is_active (&pas_unit)) { - t = sim_rtcn_init (pas_unit.wait, TMR_PAS); - sim_activate (&pas_unit, t); } } /* activate */ -else sim_cancel (&pas_unit); /* else stop */ -for (i = 0; i < PAS_LINES; i++) { - pas_desc.ldsc[i] = &pas_ldsc[i]; - pas_reset_ln (i); } -return SCPE_OK; -} - -/* Attach master unit */ - -t_stat pas_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = tmxr_attach (&pas_desc, uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error */ -sim_rtcn_init (pas_unit.wait, TMR_PAS); -sim_activate (uptr, 100); /* quick poll */ -return SCPE_OK; -} - -/* Detach master unit */ - -t_stat pas_detach (UNIT *uptr) -{ -int32 i; -t_stat r; - -r = tmxr_detach (&pas_desc, uptr); /* detach */ -for (i = 0; i < PAS_LINES; i++) pas_ldsc[i].rcve = 0; /* disable rcv */ -sim_cancel (uptr); /* stop poll */ -return r; -} - -/* Show summary processor */ - -t_stat pas_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < PAS_LINES; i++) t = t + (pas_ldsc[i].conn != 0); -if (t == 1) fprintf (st, "1 connection"); -else fprintf (st, "%d connections", t); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat pas_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i; - -for (i = 0; (i < PAS_LINES) && (pas_ldsc[i].conn == 0); i++) ; -if (i < PAS_LINES) { - for (i = 0; i < PAS_LINES; i++) { - if (pas_ldsc[i].conn) - if (val) tmxr_fconns (st, &pas_ldsc[i], i); - else tmxr_fstats (st, &pas_ldsc[i], i); } } -else fprintf (st, "all disconnected\n"); -return SCPE_OK; -} - -/* Change number of lines */ - -t_stat pas_vlines (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 newln, i, t; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -newln = get_uint (cptr, 10, PAS_LINES, &r); -if ((r != SCPE_OK) || (newln == PAS_ENAB)) return r; -if (newln == 0) return SCPE_ARG; -if (newln < PAS_ENAB) { - for (i = newln, t = 0; i < PAS_ENAB; i++) t = t | pas_ldsc[i].conn; - if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) - return SCPE_OK; - for (i = newln; i < PAS_ENAB; i++) { - if (pas_ldsc[i].conn) { - tmxr_msg (pas_ldsc[i].conn, "\r\nOperator disconnected line\r\n"); - tmxr_reset_ln (&pas_ldsc[i]); } /* reset line */ - pasl_unit[i].flags = pasl_unit[i].flags | UNIT_DIS; - pas_reset_ln (i); } - } -else { for (i = PAS_ENAB; i < newln; i++) { - pasl_unit[i].flags = pasl_unit[i].flags & ~UNIT_DIS; - pas_reset_ln (i); } - } -PAS_ENAB = newln; -return SCPE_OK; -} - -/* Reset an individual line */ - -void pas_reset_ln (int32 i) -{ -CLR_INT (v_PAS + i + i); /* clear int */ -CLR_ENB (v_PAS + i + i); -CLR_INT (v_PASX + i + i); /* disable int */ -CLR_ENB (v_PASX + i + i); -pas_rarm[i] = pas_xarm[i] = 0; /* disarm int */ -pas_rbuf[i] = pas_xbuf[i] = 0; /* clear state */ -pas_cmd[i] = 0; -pas_rchp[i] = 0; -pas_sta[i] = 0; -if (pas_ldsc[i].conn == 0) /* clear carrier */ - pas_sta[i] = pas_sta[i] | STA_CROF; -sim_cancel (&pasl_unit[i]); -return; -} - -/* Init template */ - -void pas_ini (t_bool dtpl) -{ -int32 i, j; - -for (i = j = 0; i < PAS_ENAB; i++) { - pas_tplte[j] = j; - pas_tplte[j + 1] = j + o_PASX; - j = j + 2; } -pas_tplte[j] = TPL_END; -return; -} diff --git a/Interdata/id_pt.c b/Interdata/id_pt.c deleted file mode 100644 index 8a499e6a..00000000 --- a/Interdata/id_pt.c +++ /dev/null @@ -1,352 +0,0 @@ -/* id_pt.c: Interdata paper tape reader - - Copyright (c) 2000-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - pt paper tape reader and punch - - 25-Apr-03 RMS Revised for extended file support - 10-Apr-03 RMS Fixed type problem in ptr service (from Mark Pizzolato) -*/ - -#include "id_defs.h" -#include - -/* Device definitions */ - -#define PTR 0 /* unit subscripts */ -#define PTP 1 - -#define STA_OVR 0x80 /* overrun */ -#define STA_NMTN 0x10 /* no motion */ -#define STA_MASK (STA_BSY | STA_OVR | STA_DU) /* static bits */ -#define SET_EX (STA_OVR | STA_NMTN) /* set EX */ - -#define CMD_V_RUN 4 /* run/stop */ -#define CMD_V_SLEW 2 /* slew/step */ -#define CMD_V_RD 0 /* read/write */ - -extern uint32 int_req[INTSZ], int_enb[INTSZ]; - -uint32 pt_run = 0, pt_slew = 0; /* ptr modes */ -uint32 pt_rd = 1, pt_chp = 0; /* pt state */ -uint32 pt_arm = 0; /* int arm */ -uint32 pt_sta = STA_BSY; /* status */ -uint32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */ - -DEVICE pt_dev; -uint32 pt (uint32 dev, uint32 op, uint32 dat); -t_stat ptr_svc (UNIT *uptr); -t_stat ptp_svc (UNIT *uptr); -t_stat pt_boot (int32 unitno, DEVICE *dptr); -t_stat pt_reset (DEVICE *dptr); - -/* PT data structures - - pt_dev PT device descriptor - pt_unit PT unit descriptors - pt_reg PT register list -*/ - -DIB pt_dib = { d_PT, -1, v_PT, NULL, &pt, NULL }; - -UNIT pt_unit[] = { - { UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), - SERIAL_IN_WAIT }, - { UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), - SERIAL_OUT_WAIT } }; - -REG pt_reg[] = { - { HRDATA (STA, pt_sta, 8) }, - { HRDATA (RBUF, pt_unit[PTR].buf, 8) }, - { DRDATA (RPOS, pt_unit[PTR].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (RTIME, pt_unit[PTR].wait, 24), PV_LEFT }, - { FLDATA (RSTOP_IOE, ptr_stopioe, 0) }, - { HRDATA (PBUF, pt_unit[PTP].buf, 8) }, - { DRDATA (PPOS, pt_unit[PTP].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (PTIME, pt_unit[PTP].wait, 24), PV_LEFT }, - { FLDATA (PSTOP_IOE, ptp_stopioe, 0) }, - { FLDATA (IREQ, int_req[l_PT], i_PT) }, - { FLDATA (IENB, int_enb[l_PT], i_PT) }, - { FLDATA (IARM, pt_arm, 0) }, - { FLDATA (RD, pt_rd, 0) }, - { FLDATA (RUN, pt_run, 0) }, - { FLDATA (SLEW, pt_slew, 0) }, - { FLDATA (CHP, pt_chp, 0) }, - { HRDATA (DEVNO, pt_dib.dno, 8), REG_HRO }, - { NULL } }; - -MTAB pt_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "devno", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE pt_dev = { - "PT", pt_unit, pt_reg, pt_mod, - 2, 10, 31, 1, 16, 8, - NULL, NULL, &pt_reset, - &pt_boot, NULL, NULL, - &pt_dib, DEV_DISABLE }; - -/* Paper tape: IO routine */ - -uint32 pt (uint32 dev, uint32 op, uint32 dat) -{ -uint32 t, old_rd, old_run; - -switch (op) { /* case IO op */ -case IO_ADR: /* select */ - return BY; /* byte only */ -case IO_OC: /* command */ - old_rd = pt_rd; /* save curr rw */ - old_run = pt_run; /* save curr run */ - pt_arm = int_chg (v_PT, dat, pt_arm); /* upd int ctrl */ - pt_rd = io_2b (dat, CMD_V_RD, pt_rd); /* upd read/wr */ - if (old_rd != pt_rd) { /* rw change? */ - pt_sta = pt_sta & ~STA_OVR; /* clr overrun */ - if (sim_is_active (&pt_unit[pt_rd? PTR: PTP])) { - pt_sta = pt_sta | STA_BSY; /* busy = 1 */ - CLR_INT (v_PT); } /* clear int */ - else { /* not active */ - pt_sta = pt_sta & ~STA_BSY; /* busy = 0 */ - if (pt_arm) SET_INT (v_PT); } } /* no, set int */ - if (pt_rd) { /* reader? */ - pt_run = io_2b (dat, CMD_V_RUN, pt_run); /* upd run/stop */ - pt_slew = io_2b (dat, CMD_V_SLEW, pt_slew); /* upd slew/inc */ - if (pt_run) { /* run set? */ - if (old_run == 0) { /* run 0 -> 1? */ - sim_activate (&pt_unit[PTR], pt_unit[PTR].wait); - pt_sta = pt_sta & ~STA_DU; } } /* clear eof */ - else sim_cancel (&pt_unit[PTR]); } /* clr, stop rdr */ - else pt_sta = pt_sta & ~STA_DU; /* punch, clr eof */ - break; -case IO_RD: /* read */ - if (pt_run && !pt_slew) { /* incremental? */ - sim_activate (&pt_unit[PTR], pt_unit[PTR].wait); - pt_sta = pt_sta & ~STA_DU; } /* clr eof */ - pt_chp = 0; /* clr char pend */ - if (pt_rd) pt_sta = pt_sta | STA_BSY; /* set busy */ - return (pt_unit[PTR].buf & 0xFF); /* return char */ -case IO_WD: /* write */ - pt_unit[PTP].buf = dat & DMASK8; /* save char */ - if (!pt_rd) pt_sta = pt_sta | STA_BSY; /* set busy */ - sim_activate (&pt_unit[PTP], pt_unit[PTP].wait); - break; -case IO_SS: /* status */ - t = pt_sta & STA_MASK; /* get status */ - if (pt_rd && !pt_run && !sim_is_active (&pt_unit[PTR])) - t = t | STA_NMTN; /* stopped? */ - if ((pt_unit[pt_rd? PTR: PTP].flags & UNIT_ATT) == 0) - t = t | STA_DU; /* offline? */ - if (t & SET_EX) t = t | STA_EX; /* test for EX */ - return t; } -return 0; -} - -/* Unit service */ - -t_stat ptr_svc (UNIT *uptr) -{ -int32 temp; - -if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptr_stopioe, SCPE_UNATT); -if (pt_rd) { /* read mode? */ - pt_sta = pt_sta & ~STA_BSY; /* clear busy */ - if (pt_arm) SET_INT (v_PT); /* if armed, intr */ - if (pt_chp) pt_sta = pt_sta | STA_OVR; } /* overrun? */ -pt_chp = 1; /* char pending */ -if ((temp = getc (uptr->fileref)) == EOF) { /* error? */ - if (feof (uptr->fileref)) { /* eof? */ - pt_sta = pt_sta | STA_DU; /* set DU */ - if (ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } - else perror ("PTR I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -uptr->buf = temp & DMASK8; /* store char */ -uptr->pos = uptr->pos + 1; /* incr pos */ -if (pt_slew) sim_activate (uptr, uptr->wait); /* slew? continue */ -return SCPE_OK; -} - -t_stat ptp_svc (UNIT *uptr) -{ -if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptp_stopioe, SCPE_UNATT); -if (!pt_rd) { /* write mode? */ - pt_sta = pt_sta & ~STA_BSY; /* clear busy */ - if (pt_arm) SET_INT (v_PT); } /* if armed, intr */ -if (putc (uptr->buf, uptr -> fileref) == EOF) { /* write char */ - perror ("PTP I/O error"); - clearerr (uptr -> fileref); - return SCPE_IOERR; } -uptr -> pos = uptr -> pos + 1; /* incr pos */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat pt_reset (DEVICE *dptr) -{ -sim_cancel (&pt_unit[PTR]); /* deactivate units */ -sim_cancel (&pt_unit[PTP]); -pt_rd = 1; /* read */ -pt_chp = pt_run = pt_slew = 0; /* stop, inc, disarm */ -pt_sta = STA_BSY; /* buf empty */ -CLR_INT (v_PT); /* clear int */ -CLR_ENB (v_PT); /* disable int */ -pt_arm = 0; /* disarm int */ -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define BOOT_START 0x50 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8)) -#define BOOT3_START 0x3E -#define BOOT3_LEN (sizeof (boot_rom) / sizeof (uint8)) - -static uint8 boot_rom[] = { - 0xD5, 0x00, /* ST AL CF */ - 0x00, 0xCF, - 0x43, 0x00, /* BR 80 */ - 0x00, 0x80 -}; - -static uint8 boot3_rom[] = { - 0xC8, 0x20, /* ST LHI 2,80 */ - 0x00, 0x80, - 0xC8, 0x30, /* LHI 3,1 */ - 0x00, 0x01, - 0xC8, 0x40, /* LHI 4,CF */ - 0x00, 0xCF, - 0xD3, 0xA0, /* LB A,78 */ - 0x00, 0x78, - 0xDE, 0xA0, /* OC A,79 */ - 0x00, 0x79, - 0x9D, 0xAE, /* LP SSR A,E */ - 0x42, 0xF0, /* BTC F,LP */ - 0x00, 0x52, - 0x9B, 0xAE, /* RDR A,E */ - 0x08, 0xEE, /* LHR E,E */ - 0x43, 0x30, /* BZ LP */ - 0x00, 0x52, - 0x43, 0x00, /* BR STO */ - 0x00, 0x6C, - 0x9D, 0xAE, /* LP1 SSR A,E */ - 0x42, 0xF0, /* BTC F,LP1 */ - 0x00, 0x64, - 0x9B, 0xAE, /* RDR A,E */ - 0xD2, 0xE2, /* STO STB E,0(2) */ - 0x00, 0x00, - 0xC1, 0x20, /* BXLE 2,LP1 */ - 0x00, 0x64, - 0x43, 0x00, /* BR 80 */ - 0x00, 0x80 -}; - -t_stat pt_boot (int32 unitno, DEVICE *dptr) -{ -extern uint32 PC, dec_flgs; -extern uint16 decrom[]; - -if (decrom[0xD5] & dec_flgs) /* AL defined? */ - IOWriteBlk (BOOT3_START, BOOT3_LEN, boot3_rom); /* no, 50 seq */ -else IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy AL boot */ -IOWriteB (AL_DEV, pt_dib.dno); /* set dev no */ -IOWriteB (AL_IOC, 0x99); /* set dev cmd */ -IOWriteB (AL_SCH, 0); /* clr sch dev no */ -PC = BOOT_START; -return SCPE_OK; -} - -/* Dump routine */ - -#define LOAD_START 0x80 -#define LOAD_LO 0x8A -#define LOAD_HI 0x8E -#define LOAD_CS 0x93 -#define LOAD_LEN (sizeof (load_rom) / sizeof (uint8)) -#define LOAD_LDR 50 - -static uint8 load_rom[] = { - 0x24, 0x21, /* BOOT LIS R2,1 */ - 0x23, 0x03, /* BS BOOT */ - 0x00, 0x00, /* 32b psw pointer */ - 0x00, 0x00, /* 32b reg pointer */ - 0xC8, 0x10, /* ST LHI R1,lo */ - 0x00, 0x00, - 0xC8, 0x30, /* LHI R3,hi */ - 0x00, 0x00, - 0xC8, 0x60, /* LHI R3,cs */ - 0x00, 0x00, - 0xD3, 0x40, /* LB R4,X'78' */ - 0x00, 0x78, - 0xDE, 0x40, /* OC R4,X'79' */ - 0x00, 0x79, - 0x9D, 0x45, /* LDR SSR R4,R5 */ - 0x20, 0x91, /* BTBS 9,.-2 */ - 0x9B, 0x45, /* RDR R4,R5 */ - 0x08, 0x55, /* L(H)R R5,R5 */ - 0x22, 0x34, /* BZS LDR */ - 0xD2, 0x51, /* LOOP STB R5,0(R1) */ - 0x00, 0x00, - 0x07, 0x65, /* X(H)R R6,R5 */ - 0x9A, 0x26, /* WDR R2,R6 */ - 0x9D, 0x45, /* SSR R4,R5 */ - 0x20, 0x91, /* BTBS 9,.-2 */ - 0x9B, 0x45, /* RDR R4,R5 */ - 0xC1, 0x10, /* BXLE R1,LOOP */ - 0x00, 0xA6, - 0x24, 0x78, /* LIS R7,8 */ - 0x91, 0x7C, /* SLLS R7,12 */ - 0x95, 0x57, /* EPSR R5,R7 */ - 0x22, 0x03 /* BS .-6 */ -}; - -t_stat pt_dump (FILE *of, char *cptr, char *fnam) -{ -uint32 i, lo, hi, cs; -char *tptr; -extern DEVICE cpu_dev; - -if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG; -tptr = get_range (cptr, &lo, &hi, cpu_dev.aradix, 0xFFFF, 0); -if ((tptr == NULL) || (lo < INTSVT)) return SCPE_ARG; -if (*tptr != 0) return SCPE_2MARG; -for (i = lo, cs = 0; i <= hi; i++) cs = cs ^ IOReadB (i); -IOWriteBlk (LOAD_START, LOAD_LEN, load_rom); -IOWriteB (LOAD_LO, (lo >> 8) & 0xFF); -IOWriteB (LOAD_LO + 1, lo & 0xFF); -IOWriteB (LOAD_HI, (hi >> 8) & 0xFF); -IOWriteB (LOAD_HI + 1, hi & 0xFF); -IOWriteB (LOAD_CS, cs & 0xFF); -for (i = 0; i < LOAD_LDR; i++) fputc (0, of); -for (i = LOAD_START; i < (LOAD_START + LOAD_LEN); i++) - fputc (IOReadB (i), of); -for (i = 0; i < LOAD_LDR; i++) fputc (0, of); -for (i = lo; i <= hi; i++) fputc (IOReadB (i), of); -for (i = 0; i < LOAD_LDR; i++) fputc (0, of); -return SCPE_OK; -} diff --git a/Interdata/id_tt.c b/Interdata/id_tt.c deleted file mode 100644 index 9c72778f..00000000 --- a/Interdata/id_tt.c +++ /dev/null @@ -1,260 +0,0 @@ -/* id_tt.c: Interdata teletype - - Copyright (c) 2000-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - tt console - - 25-Apr-03 RMS Revised for extended file support - 11-Jan-03 RMS Added TTP support - 22-Dec-02 RMS Added break support -*/ - -#include "id_defs.h" -#include - -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_KSR (1 << UNIT_V_KSR) - -/* Device definitions */ - -#define TTI 0 -#define TTO 1 - -#define STA_OVR 0x80 /* overrun */ -#define STA_BRK 0x20 /* break */ -#define STA_MASK (STA_OVR | STA_BRK | STA_BSY) /* status mask */ -#define SET_EX (STA_OVR | STA_BRK) /* set EX */ - -#define CMD_V_FDPX 4 /* full/half duplex */ -#define CMD_V_RD 2 /* read/write */ - -extern uint32 int_req[INTSZ], int_enb[INTSZ]; - -uint32 tt_sta = STA_BSY; /* status */ -uint32 tt_fdpx = 1; /* tt mode */ -uint32 tt_rd = 1, tt_chp = 0; /* tt state */ -uint32 tt_arm = 0; /* int arm */ - -uint32 tt (uint32 dev, uint32 op, uint32 dat); -t_stat tti_svc (UNIT *uptr); -t_stat tto_svc (UNIT *uptr); -t_stat tt_reset (DEVICE *dptr); -t_stat tt_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat tt_set_break (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat tt_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* TT data structures - - tt_dev TT device descriptor - tt_unit TT unit descriptors - tt_reg TT register list - tt_mod TT modifiers list -*/ - -DIB tt_dib = { d_TT, -1, v_TT, NULL, &tt, NULL }; - -UNIT tt_unit[] = { - { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }, - { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT } -}; - -REG tt_reg[] = { - { HRDATA (STA, tt_sta, 8) }, - { HRDATA (KBUF, tt_unit[TTI].buf, 8) }, - { DRDATA (KPOS, tt_unit[TTI].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (KTIME, tt_unit[TTI].wait, 24), REG_NZ + PV_LEFT }, - { HRDATA (TBUF, tt_unit[TTO].buf, 8) }, - { DRDATA (TPOS, tt_unit[TTO].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TTIME, tt_unit[TTO].wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (IREQ, int_req[l_TT], i_TT) }, - { FLDATA (IENB, int_enb[l_TT], i_TT) }, - { FLDATA (IARM, tt_arm, 0) }, - { FLDATA (RD, tt_rd, 0) }, - { FLDATA (FDPX, tt_fdpx, 0) }, - { FLDATA (CHP, tt_chp, 0) }, - { HRDATA (DEVNO, tt_dib.dno, 8), REG_HRO }, - { NULL } }; - -MTAB tt_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tt_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tt_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tt_set_mode }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "ENABLED", - &tt_set_enbdis, NULL, NULL }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, DEV_DIS, NULL, "DISABLED", - &tt_set_enbdis, NULL, NULL }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "BREAK", - &tt_set_break, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, &tt_dib }, - { 0 } }; - -DEVICE tt_dev = { - "TT", tt_unit, tt_reg, tt_mod, - 2, 10, 31, 1, 16, 8, - NULL, NULL, &tt_reset, - NULL, NULL, NULL, - &tt_dib, 0 }; - -/* Terminal: IO routine */ - -uint32 tt (uint32 dev, uint32 op, uint32 dat) -{ -uint32 old_rd, t; - -switch (op) { /* case IO op */ -case IO_ADR: /* select */ - return BY; /* byte only */ -case IO_OC: /* command */ - old_rd = tt_rd; - tt_arm = int_chg (v_TT, dat, tt_arm); /* upd int ctrl */ - tt_fdpx = io_2b (dat, CMD_V_FDPX, tt_fdpx); /* upd full/half */ - tt_rd = io_2b (dat, CMD_V_RD, tt_rd); /* upd rd/write */ - if (tt_rd != old_rd) { /* rw change? */ - if (tt_rd? tt_chp: !sim_is_active (&tt_unit[TTO])) { - tt_sta = 0; /* busy = 0 */ - if (tt_arm) SET_INT (v_TT); } /* req intr */ - else { - tt_sta = STA_BSY; /* busy = 1 */ - CLR_INT (v_TT); } } /* clr int */ - else tt_sta = tt_sta & ~STA_OVR; /* clr ovflo */ - break; -case IO_RD: /* read */ - tt_chp = 0; /* clear pend */ - if (tt_rd) tt_sta = (tt_sta | STA_BSY) & ~STA_OVR; - return (tt_unit[TTI].buf & 0xFF); -case IO_WD: /* write */ - tt_unit[TTO].buf = dat & 0xFF; /* save char */ - if (!tt_rd) tt_sta = tt_sta | STA_BSY; /* set busy */ - sim_activate (&tt_unit[TTO], tt_unit[TTO].wait); - break; -case IO_SS: /* status */ - t = tt_sta & STA_MASK; /* get status */ - if (t & SET_EX) t = t | STA_EX; /* test for EX */ - return t; } -return 0; -} - -/* Unit service routines */ - -t_stat tti_svc (UNIT *uptr) -{ -int32 out, temp; - -sim_activate (uptr, uptr->wait); /* continue poll */ -tt_sta = tt_sta & ~STA_BRK; /* clear break */ -if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ -if (tt_rd) { /* read mode? */ - tt_sta = tt_sta & ~STA_BSY; /* clear busy */ - if (tt_arm) SET_INT (v_TT); /* if armed, intr */ - if (tt_chp) tt_sta = tt_sta | STA_OVR; } /* got char? overrun */ -tt_chp = 1; /* char pending */ -out = temp & 0x7F; /* echo is 7B */ -if (temp & SCPE_BREAK) { /* break? */ - tt_sta = tt_sta | STA_BRK; /* set status */ - uptr->buf = 0; } /* no character */ -else if (uptr->flags & UNIT_KSR) { /* KSR mode? */ - if (islower (out)) out = toupper (out); /* cvt to UC */ - uptr->buf = out | 0x80; } /* set high bit */ -else uptr->buf = temp & ((tt_unit[TTI].flags & UNIT_8B)? 0xFF: 0x7F); -uptr->pos = uptr->pos + 1; /* incr count */ -if (!tt_fdpx) { /* half duplex? */ - if (out) sim_putchar (out); /* write char */ - tt_unit[TTO].pos = tt_unit[TTO].pos + 1; } -return SCPE_OK; -} - -t_stat tto_svc (UNIT *uptr) -{ -int32 ch; -t_stat r; - -if (!tt_rd) { /* write mode? */ - tt_sta = tt_sta & ~STA_BSY; /* clear busy */ - if (tt_arm) SET_INT (v_TT); } /* if armed, intr */ -if (uptr->flags & UNIT_KSR) { /* KSR mode? */ - ch = uptr->buf & 0x7F; /* mask to 7b */ - if (islower (ch)) ch = toupper (ch); } /* cvt to UC */ -else ch = uptr->buf & ((tt_unit[TTO].flags & UNIT_8B)? 0xFF: 0x7F); -if (!(uptr->flags & UNIT_8B) && /* KSR or 7b? */ - ((ch == 0) || (ch == 0x7F))) return SCPE_OK; /* supr NULL, DEL */ -if ((r = sim_putchar (ch)) != SCPE_OK) return r; /* output */ -uptr->pos = uptr->pos + 1; /* incr count */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tt_reset (DEVICE *dptr) -{ -if (dptr->flags & DEV_DIS) sim_cancel (&tt_unit[TTI]); /* dis? cancel poll */ -else sim_activate (&tt_unit[TTI], tt_unit[TTI].wait); /* activate input */ -sim_cancel (&tt_unit[TTO]); /* cancel output */ -tt_rd = tt_fdpx = 1; /* read, full duplex */ -tt_chp = 0; /* no char */ -tt_sta = STA_BSY; /* buffer empty */ -CLR_INT (v_TT); /* clear int */ -CLR_ENB (v_TT); /* disable int */ -tt_arm = 0; /* disarm int */ -return SCPE_OK; -} - -/* Make mode flags uniform */ - -t_stat tt_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -tt_unit[TTI].flags = (tt_unit[TTI].flags & ~(UNIT_KSR | UNIT_8B)) | val; -tt_unit[TTO].flags = (tt_unit[TTO].flags & ~(UNIT_KSR | UNIT_8B)) | val; -return SCPE_OK; -} - -/* Set input break */ - -t_stat tt_set_break (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (tt_dev.flags & DEV_DIS) return SCPE_NOFNC; -tt_sta = tt_sta | STA_BRK; -if (tt_rd) { /* read mode? */ - tt_sta = tt_sta & ~STA_BSY; /* clear busy */ - if (tt_arm) SET_INT (v_TT); } /* if armed, intr */ -sim_cancel (&tt_unit[TTI]); /* restart TT poll */ -sim_activate (&tt_unit[TTI], tt_unit[TTI].wait); /* so brk is seen */ -return SCPE_OK; -} - -/* Set enabled/disabled */ - -t_stat tt_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -extern DEVICE ttp_dev; -extern t_stat ttp_reset (DEVICE *dptr); - -tt_dev.flags = (tt_dev.flags & ~DEV_DIS) | val; -ttp_dev.flags = (ttp_dev.flags & ~DEV_DIS) | (val ^ DEV_DIS); -tt_reset (&tt_dev); -ttp_reset (&ttp_dev); -return SCPE_OK; -} diff --git a/Interdata/id_ttp.c b/Interdata/id_ttp.c deleted file mode 100644 index b2f2e857..00000000 --- a/Interdata/id_ttp.c +++ /dev/null @@ -1,265 +0,0 @@ -/* id_ttp.c: Interdata PASLA console interface - - Copyright (c) 2000-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - ttp console (on PAS) - - 25-Apr-03 RMS Revised for extended file support -*/ - -#include "id_defs.h" -#include - -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_UC (1 << UNIT_V_UC) - -#define TTI 0 -#define TTO 1 - -/* Status byte */ - -#define STA_OVR 0x80 /* overrun RO */ -#define STA_PF 0x40 /* parity err RO */ -#define STA_FR 0x20 /* framing err RO */ -#define STA_RCV (STA_OVR|STA_PF|STA_FR) -#define SET_EX (STA_OVR|STA_PF|STA_FR) -#define STA_XMT (STA_BSY) - -/* Command bytes 1,0 */ - -#define CMD_ECHO (0x10 << 8) /* echoplex */ -#define CMD_WRT (0x02 << 8) /* write/read */ -#define CMD_TYP 0x01 /* command type */ - -extern uint32 int_req[INTSZ], int_enb[INTSZ]; - -uint32 ttp_sta = 0; /* status */ -uint32 ttp_cmd = 0; /* command */ -uint32 ttp_kchp = 0; /* rcvr chr pend */ -uint32 ttp_karm = 0; /* rcvr int armed */ -uint32 ttp_tarm = 0; /* xmt int armed */ -uint8 ttp_tplte[] = { 0, 1, TPL_END }; - -uint32 ttp (uint32 dev, uint32 op, uint32 dat); -t_stat ttpi_svc (UNIT *uptr); -t_stat ttpo_svc (UNIT *uptr); -t_stat ttp_reset (DEVICE *dptr); -t_stat ttp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat ttp_set_break (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat ttp_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc); - -extern int32 pas_par (int32 cmd, int32 c); - -/* TTP data structures */ - -DIB ttp_dib = { d_TTP, -1, v_TTP, ttp_tplte, &ttp, NULL }; - -UNIT ttp_unit[] = { - { UDATA (&ttpi_svc, 0, 0), KBD_POLL_WAIT }, - { UDATA (&ttpo_svc, 0, 0), SERIAL_OUT_WAIT } -}; - -REG ttp_reg[] = { - { HRDATA (CMD, ttp_cmd, 16) }, - { HRDATA (KBUF, ttp_unit[TTI].buf, 8) }, - { DRDATA (KPOS, ttp_unit[TTI].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (KTIME, ttp_unit[TTI].wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (KIREQ, int_req[l_TTP], i_TTP) }, - { FLDATA (KIENB, int_enb[l_TTP], i_TTP) }, - { FLDATA (KARM, ttp_karm, 0) }, - { FLDATA (CHP, ttp_kchp, 0) }, - { HRDATA (TBUF, ttp_unit[TTO].buf, 8) }, - { DRDATA (TPOS, ttp_unit[TTO].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TTIME, ttp_unit[TTO].wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (TIREQ, int_req[l_TTP], i_TTP + 1) }, - { FLDATA (TIENB, int_enb[l_TTP], i_TTP + 1) }, - { FLDATA (TARM, ttp_tarm, 0) }, - { HRDATA (DEVNO, ttp_dib.dno, 8), REG_HRO }, - { NULL } }; - -MTAB ttp_mod[] = { - { UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", &ttp_set_mode }, - { UNIT_UC+UNIT_8B, 0 , "7b", "7B", &ttp_set_mode }, - { UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", &ttp_set_mode }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "ENABLED", - &ttp_set_enbdis, NULL, NULL }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, DEV_DIS, NULL, "DISABLED", - &ttp_set_enbdis, NULL, NULL }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "BREAK", - &ttp_set_break, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE ttp_dev = { - "TTP", ttp_unit, ttp_reg, ttp_mod, - 2, 10, 31, 1, 16, 8, - NULL, NULL, &ttp_reset, - NULL, NULL, NULL, - &ttp_dib, DEV_DIS }; - - -/* Terminal: I/O routine */ - -uint32 ttp (uint32 dev, uint32 op, uint32 dat) -{ -int32 xmt = dev & 1; -int32 t, old_cmd; - -switch (op) { /* case IO op */ -case IO_ADR: /* select */ - return BY; /* byte only */ -case IO_RD: /* read */ - ttp_kchp = 0; /* clr chr pend */ - ttp_sta = ttp_sta & ~STA_OVR; /* clr overrun */ - return ttp_unit[TTI].buf; /* return buf */ -case IO_WD: /* write */ - ttp_unit[TTO].buf = dat & 0xFF; /* store char */ - ttp_sta = ttp_sta | STA_BSY; /* set busy */ - sim_activate (&ttp_unit[TTO], ttp_unit[TTO].wait); - break; -case IO_SS: /* status */ - if (xmt) t = ttp_sta & STA_XMT; /* xmt? Just busy */ - else { /* rcv */ - t = ttp_sta & STA_RCV; /* get static */ - if (!ttp_kchp) t = t | STA_BSY; /* no char? busy */ - if (t & SET_EX) t = t | STA_EX; } /* test for ex */ - return t; -case IO_OC: /* command */ - old_cmd = ttp_cmd; /* old cmd */ - if (dat & CMD_TYP) { /* type 1? */ - ttp_cmd = (ttp_cmd & 0xFF) | (dat << 8); - if (ttp_cmd & CMD_WRT) /* write? */ - ttp_tarm = int_chg (v_TTP + 1, dat, ttp_tarm); - else ttp_karm = int_chg (v_TTP, dat, ttp_karm); } - else ttp_cmd = (ttp_cmd & ~0xFF) | dat; - break; } -return 0; -} - -/* Unit service */ - -t_stat ttpi_svc (UNIT *uptr) -{ -int32 c, out; - -sim_activate (uptr, uptr->wait); /* continue poll */ -ttp_sta = ttp_sta & ~STA_FR; /* clear break */ -if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -ttp_sta = ttp_sta & ~STA_PF; /* clear parity err */ -if (ttp_kchp) ttp_sta = ttp_sta | STA_OVR; /* overrun? */ -if (ttp_karm) SET_INT (v_TTP); -if (c & SCPE_BREAK) { /* break? */ - ttp_sta = ttp_sta | STA_FR; /* framing error */ - uptr->buf = 0; } /* no character */ -else { c = c & 0xFF; /* char is 8b */ - out = c & 0x7F; /* echo is 7b */ - if (!(uptr->flags & UNIT_8B)) { /* not 8b? */ - if ((uptr->flags & UNIT_UC) && islower (out)) - out = toupper (out); /* cvt to UC */ - c = pas_par (ttp_cmd, out); } /* apply parity */ - uptr->buf = c; /* save char */ - uptr->pos = uptr->pos + 1; /* incr count */ - ttp_kchp = 1; /* char pending */ - if (ttp_cmd & CMD_ECHO) { - sim_putchar (out); - ttp_unit[TTO].pos = ttp_unit[TTO].pos + 1; } } -return SCPE_OK; -} - -t_stat ttpo_svc (UNIT *uptr) -{ -int32 c; -t_stat r; - -ttp_sta = ttp_sta & ~STA_BSY; /* not busy */ -if (ttp_tarm) SET_INT (v_TTP + 1); /* set intr */ -if (uptr->flags & UNIT_8B) /* 8b? */ - c = pas_par (ttp_cmd, uptr->buf); /* apply parity */ -else { c = uptr->buf & 0x7F; /* mask char */ - if ((uptr->flags & UNIT_UC) && islower (c)) - c = toupper (c); } /* cvt to UC */ -if (!(uptr->flags & UNIT_8B) && /* UC or 7b? */ - ((c == 0) || (c == 0x7F))) return SCPE_OK; /* supr NULL, DEL */ -if ((r = sim_putchar (c)) != SCPE_OK) return r; /* output */ -uptr->pos = uptr->pos + 1; /* incr count */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ttp_reset (DEVICE *dptr) -{ -extern DEVICE tt_dev; - -if (dptr->flags & DEV_DIS) sim_cancel (&ttp_unit[TTI]); -else sim_activate (&ttp_unit[TTI], ttp_unit[TTI].wait); -sim_cancel (&ttp_unit[TTO]); -CLR_INT (v_TTP); /* clear int */ -CLR_ENB (v_TTP); -CLR_INT (v_TTP + 1); /* disable int */ -CLR_ENB (v_TTP + 1); -ttp_karm = ttp_tarm = 0; /* disarm int */ -ttp_cmd = 0; -ttp_sta = 0; -ttp_kchp = 0; -return SCPE_OK; -} - -/* Make mode flags uniform */ - -t_stat ttp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -ttp_unit[TTI].flags = (ttp_unit[TTI].flags & ~(UNIT_UC | UNIT_8B)) | val; -ttp_unit[TTO].flags = (ttp_unit[TTO].flags & ~(UNIT_UC | UNIT_8B)) | val; -return SCPE_OK; -} - -/* Set input break */ - -t_stat ttp_set_break (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (ttp_dev.flags & DEV_DIS) return SCPE_NOFNC; -ttp_sta = ttp_sta | STA_FR; -if (ttp_karm) SET_INT (v_TTP); /* if armed, intr */ -sim_cancel (&ttp_unit[TTI]); /* restart TT poll */ -sim_activate (&ttp_unit[TTI], ttp_unit[TTI].wait); -return SCPE_OK; -} - -/* Set enabled/disabled */ - -t_stat ttp_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -extern DEVICE tt_dev; -extern t_stat tt_reset (DEVICE *dptr); - -ttp_dev.flags = (ttp_dev.flags & ~DEV_DIS) | val; -tt_dev.flags = (tt_dev.flags & ~DEV_DIS) | (val ^ DEV_DIS); -ttp_reset (&ttp_dev); -tt_reset (&tt_dev); -return SCPE_OK; -} diff --git a/Interdata/id_uvc.c b/Interdata/id_uvc.c deleted file mode 100644 index 24dcd7cf..00000000 --- a/Interdata/id_uvc.c +++ /dev/null @@ -1,350 +0,0 @@ -/* id_uvc.c: Interdata universal clock - - Copyright (c) 2001-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - pic precision incremental clock - lfc line frequency clock - - 01-Mar-03 RMS Added SET/SHOW LFC FREQ support - Changed precision clock algorithm for V7 UNIX -*/ - -#include "id_defs.h" -#include - -/* Device definitions */ - -#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diag mode */ -#define UNIT_DIAG (1 << UNIT_V_DIAG) - -#define STA_OVF 0x08 /* PIC overflow */ -#define CMD_STRT 0x20 /* start */ -#define PIC_V_RATE 12 /* rate */ -#define PIC_M_RATE 0xF -#define PIC_RATE (PIC_M_RATE << PIC_V_RATE) -#define PIC_CTR 0x0FFF /* PIC counters */ -#define GET_RATE(x) (((x) >> PIC_V_RATE) & PIC_M_RATE) -#define GET_CTR(x) ((x) & PIC_CTR) -#define PIC_TPS 1000 - -extern uint32 int_req[INTSZ], int_enb[INTSZ]; - -int32 pic_db = 0; /* output buf */ -int32 pic_ric = 0; /* reset count */ -int32 pic_cic = 0; /* current count */ -uint32 pic_save = 0; /* saved time */ -uint32 pic_ovf = 0; /* overflow */ -uint32 pic_rdp = 0; -uint32 pic_wdp = 0; -uint32 pic_cnti = 0; /* instr/timer */ -uint32 pic_arm = 0; /* int arm */ -uint32 pic_decr = 1; /* decrement */ -uint16 pic_time[4] = { 1, 10, 100, 1000 }; /* delays */ -uint16 pic_usec[4] = { 1, 10, 100, 1000 }; /* usec per tick */ -static int32 pic_map[16] = { /* map rate to delay */ - 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 }; - -DEVICE pic_dev; -uint32 pic (uint32 dev, uint32 op, uint32 dat); -t_stat pic_svc (UNIT *uptr); -t_stat pic_reset (DEVICE *dptr); -void pic_sched (t_bool strt); -uint32 pic_rd_cic (void); - -int32 lfc_tps = 120; /* ticks per */ -uint32 lfc_arm = 0; /* int arm */ - -DEVICE lfc_dev; -uint32 lfc (uint32 dev, uint32 op, uint32 dat); -t_stat lfc_svc (UNIT *uptr); -t_stat lfc_reset (DEVICE *dptr); -t_stat lfc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat lfc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc); - -/* PIC data structures - - pic_dev PIC device descriptor - pic_unit PIC unit descriptor - pic_reg PIC register list -*/ - -DIB pic_dib = { d_PIC, -1, v_PIC, NULL, &pic, NULL }; - -UNIT pic_unit = { UDATA (&pic_svc, 0, 0), 1000 }; - -REG pic_reg[] = { - { HRDATA (BUF, pic_db, 16) }, - { HRDATA (RIC, pic_ric, 16) }, - { HRDATA (CIC, pic_cic, 12) }, - { FLDATA (RDP, pic_rdp, 0) }, - { FLDATA (WDP, pic_wdp, 0) }, - { FLDATA (OVF, pic_ovf, 0) }, - { FLDATA (IREQ, int_req[l_PIC], i_PIC) }, - { FLDATA (IENB, int_enb[l_PIC], i_PIC) }, - { FLDATA (IARM, pic_arm, 0) }, - { BRDATA (TIME, pic_time, 10, 16, 4), REG_NZ + PV_LEFT }, - { DRDATA (SAVE, pic_save, 32), REG_HRO + PV_LEFT }, - { DRDATA (DECR, pic_decr, 16), REG_HRO + PV_LEFT }, - { FLDATA (MODE, pic_cnti, 0), REG_HRO }, - { HRDATA (DEVNO, pic_dib.dno, 8), REG_HRO }, - { NULL } }; - -MTAB pic_mod[] = { - { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL }, - { UNIT_DIAG, 0, NULL, "NORMAL", NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE pic_dev = { - "PIC", &pic_unit, pic_reg, pic_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &pic_reset, - NULL, NULL, NULL, - &pic_dib, DEV_DISABLE }; - -/* LFC data structures - - lfc_dev LFC device descriptor - lfc_unit LFC unit descriptor - lfc_reg LFC register list -*/ - -DIB lfc_dib = { d_LFC, -1, v_LFC, NULL, &lfc, NULL }; - -UNIT lfc_unit = { UDATA (&lfc_svc, 0, 0), 8333 }; - -REG lfc_reg[] = { - { FLDATA (IREQ, int_req[l_LFC], i_LFC) }, - { FLDATA (IENB, int_enb[l_LFC], i_LFC) }, - { FLDATA (IARM, lfc_arm, 0) }, - { DRDATA (TIME, lfc_unit.wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS, lfc_tps, 8), PV_LEFT + REG_HRO }, - { HRDATA (DEVNO, lfc_dib.dno, 8), REG_HRO }, - { NULL } }; - -MTAB lfc_mod[] = { - { MTAB_XTD|MTAB_VDV, 100, NULL, "50HZ", - &lfc_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 120, NULL, "60HZ", - &lfc_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL, - NULL, &lfc_show_freq, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE lfc_dev = { - "LFC", &lfc_unit, lfc_reg, lfc_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &lfc_reset, - NULL, NULL, NULL, - &lfc_dib, DEV_DISABLE }; - -/* Precision clock: IO routine */ - -uint32 pic (uint32 dev, uint32 op, uint32 dat) -{ -int32 t; - -switch (op) { /* case IO op */ -case IO_ADR: /* select */ - return HW; /* HW capable */ -case IO_RH: /* read halfword */ - pic_rdp = 0; /* clr ptr */ - return pic_rd_cic (); -case IO_RD: /* read */ - t = pic_rd_cic (); /* get cic */ - if (pic_rdp) t = t & DMASK8; /* 2nd? get lo */ - else t = (t >> 8) & DMASK8; /* 1st? get hi */ - pic_rdp = pic_rdp ^ 1; /* flip byte ptr */ - return t; -case IO_WH: /* write halfword */ - pic_wdp = 0; /* clr ptr */ - pic_db = dat; - break; -case IO_WD: /* write */ - if (pic_wdp) pic_db = (pic_db & 0xFF00) | dat; - else pic_db = (pic_db & 0xFF) | (dat << 8); - pic_wdp = pic_wdp ^ 1; /* flip byte ptr */ - break; -case IO_SS: /* sense status */ - if (pic_ovf) { /* overflow? */ - pic_ovf = 0; /* clear flag */ - CLR_INT (v_PIC); /* clear intr */ - return STA_OVF; } - return 0; -case IO_OC: /* output cmd */ - pic_arm = int_chg (v_PIC, dat, pic_arm); /* upd int ctrl */ - if (dat & CMD_STRT) { /* start? */ - pic_ric = pic_db; /* new ric */ - pic_cic = GET_CTR (pic_ric); /* new cic */ - pic_ovf = 0; /* clear flag */ - sim_cancel (&pic_unit); /* stop clock */ - pic_rdp = pic_wdp = 0; /* init ptrs */ - if (pic_ric & PIC_RATE) pic_sched (TRUE); /* any rate? */ - } /* end if start */ - break; } /* end case */ -return 0; -} - -/* Unit service */ - -t_stat pic_svc (UNIT *uptr) -{ -t_bool rate_chg = FALSE; - -if (pic_cnti) pic_cic = 0; /* one shot? */ -pic_cic = pic_cic - pic_decr; /* decrement */ -if (pic_cic <= 0) { /* overflow? */ - if (pic_wdp) pic_ovf = 1; /* broken wr? set flag */ - if (pic_arm) SET_INT (v_PIC); /* if armed, intr */ - if (GET_RATE (pic_ric) != GET_RATE (pic_db)) /* rate change? */ - rate_chg = TRUE; - pic_ric = pic_db; /* new ric */ - pic_cic = GET_CTR (pic_ric); /* new cic */ - if ((pic_ric & PIC_RATE) == 0) return SCPE_OK; } -pic_sched (rate_chg); -return SCPE_OK; -} - -/* Schedule next interval - - If eff rate < 1ms, or diagnostic mode, count instructions - If eff rate = 1ms, and not diagnostic mode, use timer -*/ - -void pic_sched (t_bool strt) -{ -int32 r, t, intv, intv_usec; - -pic_save = sim_grtime (); /* save start */ -r = pic_map[GET_RATE (pic_ric)]; /* get mapped rate */ -intv = pic_cic? pic_cic: 1; /* get cntr */ -intv_usec = intv * pic_usec[r]; /* cvt to usec */ -if (!(pic_unit.flags & UNIT_DIAG) && /* not diag? */ - ((intv_usec % 1000) == 0)) { /* 1ms multiple? */ - pic_cnti = 0; /* clr mode */ - pic_decr = pic_usec[3 - r]; /* set decrement */ - if (strt) t = sim_rtcn_init (pic_time[3], TMR_PIC); /* init or */ - else t = sim_rtcn_calb (PIC_TPS, TMR_PIC); } /* calibrate */ -else { pic_cnti = 1; /* set mode */ - pic_decr = 1; /* decr = 1 */ - t = pic_time[r] * intv; /* interval */ - if (t == 1) t++; } /* for diagn */ -sim_activate (&pic_unit, t); /* activate */ -return; -} - -/* Read (interpolated) current interval */ - -uint32 pic_rd_cic (void) -{ -if (sim_is_active (&pic_unit) && pic_cnti) { /* running, one shot? */ - uint32 delta = sim_grtime () - pic_save; /* interval */ - uint32 tm = pic_time[pic_map[GET_RATE (pic_ric)]]; /* ticks/intv */ - delta = delta / tm; /* ticks elapsed */ - if (delta >= ((uint32) pic_cic)) return 0; /* cap value */ - return pic_cic - delta; } -return pic_cic; -} - -/* Reset routine */ - -t_stat pic_reset (DEVICE *dptr) -{ -sim_cancel (&pic_unit); /* cancel unit */ -pic_ric = pic_cic = 0; -pic_db = 0; -pic_ovf = 0; /* clear state */ -pic_cnti = 0; -pic_decr = 1; -pic_rdp = pic_wdp = 0; -CLR_INT (v_PIC); /* clear int */ -CLR_ENB (v_PIC); /* disable int */ -pic_arm = 0; /* disarm int */ -return SCPE_OK; -} - -/* Line clock: IO routine */ - -uint32 lfc (uint32 dev, uint32 op, uint32 dat) -{ -int32 t; - -switch (op) { /* case IO op */ -case IO_ADR: /* select */ - return BY; /* byte only */ -case IO_OC: /* command */ - lfc_arm = int_chg (v_LFC, dat, lfc_arm); /* upd int ctrl */ - if (lfc_arm && !sim_is_active (&lfc_unit)) { /* starting? */ - t = sim_rtcn_init (lfc_unit.wait, TMR_LFC); - sim_activate (&lfc_unit, t); } /* init clock */ - break; } -return 0; -} - -/* Unit service */ - -t_stat lfc_svc (UNIT *uptr) -{ -int32 t; - -if (lfc_arm) { /* armed? */ - SET_INT (v_LFC); /* req intr */ - if (pic_unit.flags & UNIT_DIAG) t = uptr->wait; /* diag? fixed delay */ - else t = sim_rtcn_calb (lfc_tps, TMR_LFC); /* else calibrate */ - sim_activate (uptr, t); } /* reactivate */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lfc_reset (DEVICE *dptr) -{ -sim_cancel (&lfc_unit); /* cancel unit */ -CLR_INT (v_LFC); /* clear int */ -CLR_ENB (v_LFC); /* disable int */ -lfc_arm = 0; /* disarm int */ -return SCPE_OK; -} - -/* Set frequency */ - -t_stat lfc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -if ((val != 100) && (val != 120)) return SCPE_IERR; -lfc_tps = val; -return SCPE_OK; -} - -/* Show frequency */ - -t_stat lfc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, (lfc_tps == 100)? "50Hz": "60Hz"); -return SCPE_OK; -} - diff --git a/NOVA/eclipse.txt b/NOVA/eclipse.txt deleted file mode 100644 index 4cc9cf08..00000000 --- a/NOVA/eclipse.txt +++ /dev/null @@ -1,24 +0,0 @@ -Charles Owen's Eclipse Modules - -1. Eclipse CPU simulator - -The Eclipse CPU simulator can be used with the Nova definitions and peripheral -modules to produce an Eclipse simulator that will run Eclipse mapped RDOS V7.5. -The compilation procedure is the same as for the Nova simulator, except: - - - the symbol ECLIPSE must be defined - - the module eclipse_cpu.c must be substituted for nova_cpu.c - - the output should be named eclipse rather than nova - -For example, to compile under UNIX, move nova_cpu.c out of the source directory -and then give this command: - - % cc -DECLIPSE eclipse_cpu.c nova_*.c -o eclipse - -2. Alternate terminal emulator - -The module eclipse_tt.c can be used with either an Eclipse or Nova CPU simulator -in place of nova_tt.c. It provides a full emulation of the cursor controls on -the Dasher video terminal but requires that the underlying operating system -interpret VT100 cursor controls. Thus, it works under VMS or UNIX but not under -Windows or OS/2. \ No newline at end of file diff --git a/NOVA/eclipse_cpu.c b/NOVA/eclipse_cpu.c deleted file mode 100644 index 76ab2ead..00000000 --- a/NOVA/eclipse_cpu.c +++ /dev/null @@ -1,3382 +0,0 @@ -/* eclipse_cpu.c: Eclipse CPU simulator - - Modified from the original NOVA simulator by Robert Supnik. - - Copyright (c) 1998-2003, Charles E Owen - Portions Copyright (c) 1993-2002, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - cpu Eclipse central processor - - 28-Jan-02 RMS Cleaned up compiler warnings - 30-Nov-01 RMS Added extended SET/SHOW support - 01-Jun-01 RMS Added second terminal, plotter support - 26-Apr-01 RMS Added device enable/disable support - - The register state for the Eclipse CPU is basically the same as - the NOVA's: - - AC[0:3]<0:15> general registers - C carry flag - PC<0:14> program counter - - In addition, certain low-memory locations are reserved for special - purposes: - - 0: I/O Return Address (from an interrupt) - 1: I/O (Interrupt) handler address - 2: System Call handler address (used by SYC instruction) - 3: Protection Fault handler address - 4: VECTOR stack pointer (VCT Instruction) - 5: Current Interrupt Priority mask - 6: VECTOR stack limit (VCT instruction) - 7: VECTOR stack fault address (VCT again) - 10: Block Pointer (later models only) - 11: Emulation Trap Handler address (microeclipse only) - 20-27: Auto-increment locations (not on microeclipse) - 30-37: Auto-decrement locations (not on microeclipse) - 40: Stack pointer - 41: Frame Pointer - 42: Stack Limit - 43: Stack fault address - 44: XOP Origin address - 45: Floating point fault address - 46: Commercial fault address (not on microeclipse) - 47: Reserved, do not use. - - Note: While all eclipses share most of the "standard" features, - some models added a few quirks and wrinkles, and other models - dropped some features or modified others. Most DG software - is written for a "standard" Eclipse, and avoids these problem - areas. A general overview: - - [subject to major changes as info becomes available!] - - Early (e.g. S/100, S/200, C/300) [Front Panel machines] - - The first Eclipses had the basic MMPU, but certain parts - were kluged, and these were fixed in later MMPU designs. - This results in incompatibility, however. Also, early - CPUs had a feature called "Commercial Instruction Set" - which contained character manipulation, translation - between commercial-format numeric data and FPU formats, - and an elaborate EDIT instruction. Later models kept - only the character manipulation part of this and called - the feature the "Character Instruction Set", leading to - confusion because the initials of both are CIS. AFAIK, - DG dropped support for this MMPU and no version of RDOS - supported it past version 6, if even that. - - Middle (e.g. S/130, C/150, S/230, C/330) [Front Panel] - - These are close to a "Standard". They have the newer, - fixed MMPU. Support for the PIT (Programmed Interval - Timer. The Commercial (not character) instruction set - and FPU are optional. (CIS standard on C models) - - Late (C/350, M/600: [Panel]; S/140, S/280 [Virtual Console]) - - All features of the Middle period are included, plus: - These late Eclipses added a few MMPU wrinkles all their - own, included support for user maps C and D. Character - instruction set is standard, FPU optional. Also, support - for the BMC device. - - MicroEclipse-based (S/20, S/120, Desktops) [Virtual cons.] - - All features of the Late period, in general, plus: - Microeclipses dropped support for the auto increment - and decrement locations at 20-37. They also added - support for invalid instruction traps thru location 11. - The Desktops have an interface to the "Attached Processor", - an 8086, at device code 4. Also, some new CPU device - features to read states info. The Character Instruction - set and FPU are standard on all models. - - The Eclipse instruction set is an elaboration of the NOVA's. The basic - NOVA set is implemented in it's entireity, plus many new Eclipse - instructions are added. Since in theory every possible 16-bit - combination is a NOVA instruction, the Eclipse commands are carved - out of the NOVA set by using the Operate format with the no-load bit - set to 1 and the skip bits set to 000. Since this combination is - in effect a no-op on the NOVA, it was rarely or never used. The - other bits are used to form Eclipse instructions, which have no - other common format. To see the instructions, refer to the Eclipse - section of the instruction decode logic in sim_instr() below. All - Eclipse instructions are checked first, so in case of conflict in - bit patterns, the Eclipse one is executed over the corresponding - NOVA pattern. - - The following discussion talks about NOVA instructions which are - Eclipse instructions also. - - The NOVA has three instruction formats: memory reference, I/O transfer, - and operate. The memory reference format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0| op | AC |in| mode| displacement | memory reference - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <0:4> mnemonic action - - 00000 JMP PC = MA - 00001 JMS AC3 = PC, PC = MA - 00010 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0 - 00011 DSZ M[MA] = M[MA] - 1, skip if M[MA] == 0 - 001'n LDA ACn = M[MA] - 010'n STA M[MA] = ACn - - <5:7> mode action - - 000 page zero direct MA = zext (IR<8:15>) - 001 PC relative direct MA = PC + sext (IR<8:15>) - 010 AC2 relative direct MA = AC2 + sext (IR<8:15>) - 011 AC3 relative direct MA = AC3 + sext (IR<8:15>) - 100 page zero indirect MA = M[zext (IR<8:15>)] - 101 PC relative dinirect MA = M[PC + sext (IR<8:15>)] - 110 AC2 relative indirect MA = M[AC2 + sext (IR<8:15>)] - 111 AC3 relative indirect MA = M[AC3 + sext (IR<8:15>)] - - Memory reference instructions can access an address space of 32K words. - An instruction can directly reference the first 256 words of memory - (called page zero), as well as 256 words relative to the PC, AC2, or - AC3; it can indirectly access all 32K words. If an indirect address - is in locations 00020-00027, the indirect address is incremented and - rewritten to memory before use; if in 00030-00037, decremented and - rewritten. -*/ - -/* The I/O transfer format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 1 1| AC | opcode |pulse| device | I/O transfer - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The IOT instruction sends the opcode, pulse, and specified AC to the - specified I/O device. The device may accept data, provide data, - initiate or cancel operations, or skip on status. - - The operate format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1|srcAC|dstAC| opcode |shift|carry|nl| skip | operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - \______/ \___/ \___/ | | | | - | | | | | | +--- reverse skip sense - | | | | | +--- skip if C == 0 - | | | | +--- skip if result == 0 - | | | +--- don't load result - | | +--- carry in (load as is, - | | set to Zero, - | | set to One, - | | load Complement) - | +--- shift (none, - | left one, - | right one, - | byte swap) - +--- operation (complement, - negate, - move, - increment, - add complement, - subtract, - add, - and) - - The operate instruction can be microprogrammed to perform operations - on the source and destination AC's and the Carry flag. -*/ - -/* This routine is the instruction decode routine for the NOVA. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - breakpoint encountered - infinite indirection loop - unknown I/O device and STOP_DEV flag set - I/O error in I/O simulator - - 2. Interrupts. Interrupts are maintained by four parallel variables: - - dev_done device done flags - dev_disable device interrupt disable flags - dev_busy device busy flags - int_req interrupt requests - - In addition, int_req contains the interrupt enable and ION pending - flags. If ION and ION pending are set, and at least one interrupt - request is pending, then an interrupt occurs. Note that the 16b PIO - mask must be mapped to the simulator's device bit mapping. - - 3. Non-existent memory. On the NOVA, reads to non-existent memory - return zero, and writes are ignored. In the simulator, the - largest possible memory is instantiated and initialized to zero. - Thus, only writes need be checked against actual memory size. - - 4. Adding I/O devices. These modules must be modified: - - eclipse_defs.h add interrupt request definition - eclipse_cpu.c add IOT mask, PI mask, and routine to dev_table - eclipse_sys.c add pointer to data structures to sim_devices -*/ - -/*--------------------------------------------------------------------------- -** ECLIPSE Debugging Facilities -** -** These options are designed to find hard-to-locate flaky bugs by -** providing special error checking and logging. -** -** All are controlled by depositing a value into the DEBUG register. -** A value of zero means no special debugging facilities are turned on. -** This is the default. Debugging invokes a performance hit! Use only -** when necessary. -** -** Debugging means logging information to a file, or to a buffer in -** memory from whence it can be dumped to a file. -** -** 1XXXXX = Log all instructions executed to file "trace.log". -** **CAUTION**: This means the CPU will run SLOWLY and -** the resulting trace.log file will be HUGE. We're talking -** about a megabyte for each 5 seconds or less of wall clock -** time, depending on the speed of your CPU. Note: In this -** mode, interrupts are logged when they are received also. -** -** Note: when detailed logging is off, the last 4096 or so -** instructions executed are saved in a memory buffer, and -** when the sim stops, the "dump" command can write this -** history information to the file "history.log". This only -** works if the DEBUG register is non-zero however, because -** of the performance hit even this recording makes. -** -** XXXXDD = Log all I/O instructions to or from device number -** DD. Log is written to "trace.log", regardless of the -** setting of the instruction trace flag (1XXXXX). If both -** are on, the device traces will be interpersed with the -** instruction traces -- very useful sometimes. -** -** XXX1DD = Device Break. Does a breakpoint in any I/O to -** device DD. Useful, say when a diagnostic gives an -** error message - a device break on 11 (TTO) will stop -** as soon as the error message appears, making the -** trace log much shorter to track back on. -** -** X4XXXX = When this bit is on, the sim will stop if it sees -** an invalid instruction. When DEBUG is zero, any such -** instruction is no-oped with no warning. When DEBUG is -** non-zero, but this bit is 0, a warning will be displayed -** but execution will continue. -** -** X2XXXX = LEF break. When A LEF instruction is executed in -** mapped user space, the sim does a breakpoint right after -** executing the instruction. -** -** Whenever the DEBUG register is non-zero, special error checking -** is enabled in the sim. This will stop the sim automatically -** when a likely error occurs, such as: -** -** 1. Any execution that reaches, or will reach, location 00000. -** 2. Any I/O to device 00 -** 3. An interrupt from device 00. -** 4. An invalid instruction (stop is optional) -** -** Of course, the standard BREAK register is available for breakpoints -** as in all the sims based on this standard. ---------------------------------------------------------------------------*/ - - -#include "nova_defs.h" - -#define UNIT_V_MICRO (UNIT_V_UF) /* Microeclipse? */ -#define UNIT_V_17B (UNIT_V_UF) /* 17 bit MAP */ -#define UNIT_V_MSIZE (UNIT_V_UF+1) /* dummy mask */ -#define UNIT_MICRO (1 << UNIT_V_MICRO) -#define UNIT_17B (1 << UNIT_V_17B) -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -unsigned int16 M[MAXMEMSIZE] = { 0 }; /* memory */ -int32 AC[4] = { 0 }; /* accumulators */ -int32 C = 0; /* carry flag */ -int32 saved_PC = 0; /* program counter */ -int32 SR = 0; /* switch register */ -int32 dev_done = 0; /* device done flags */ -int32 dev_busy = 0; /* device busy flags */ -int32 dev_disable = 0; /* int disable flags */ -int32 iot_enb = -1; /* IOT enables */ -int32 int_req = 0; /* interrupt requests */ -int32 pimask = 0; /* priority int mask */ -int32 pwr_low = 0; /* power fail flag */ -int32 ind_max = 15; /* iadr nest limit */ -int32 stop_dev = 0; /* stop on ill dev */ -int32 old_PC = 0; /* previous PC */ -int32 model = 130; /* Model of Eclipse */ -int32 speed = 0; /* Delay for each instruction */ - -int32 XCT_mode = 0; /* 1 if XCT mode */ -int32 XCT_inst = 0; /* XCT instruction */ -int32 PPC = -1; - -struct ndev dev_table[64]; /* dispatch table */ - -/* Instruction history buffer */ - -#define HISTMAX 4096 - -int32 hnext = 0; /* # of current entry */ -int32 hwrap = 0; /* 1 if wrapped */ -int32 hmax = HISTMAX; /* Maximum entries b4 wrap */ -unsigned int16 hpc[HISTMAX]; -unsigned int16 hinst[HISTMAX]; -unsigned int16 hinst2[HISTMAX]; -unsigned int16 hac0[HISTMAX]; -unsigned int16 hac1[HISTMAX]; -unsigned int16 hac2[HISTMAX]; -unsigned int16 hac3[HISTMAX]; -unsigned short hflags[HISTMAX]; - -/* Flags: 0x01 - carry bit - 0x02 - int enabled - 0x04 - user map a - 0x08 - user map b - 0x10 - user map c - 0x20 - user map d - 0x80 - this is an int, not an inst. - hpc is return addr - hinst is int_req - hac0 is device - hac1 is int addr -*/ - - - -/* the Eclipse MAP unit: This unit is standard in all Eclipse processors - except for the "original" Eclipses, the S/100, S/200, and C/300. These - use a different and more elaborate MMPU that is not compatible with - the one simulated here. All subsequent Eclipses, from the S/130 on up - to the last models S/280 and C/380 use the map simulated here, including - the MicroEclipses. There are model-dependent quirks. That's why we - have to MODEL register. - - The programming of the MMPU can be found in the LMP instruction, below, - and in the instructions directed to DEV_MAP. - - There are two user maps, called A and B, and four data channel maps, - A thru D. They can be enabled/disabled separately. Some models have - two extra user maps, C and D. These are supported where apporpriate. - -*/ - -#define PAGEMASK 01777 /* Largest physical page possible */ -#define MAPMASK 0101777 /* Valid page bits in map */ -#define INVALID 0101777 /* Mask indicating an invalid page */ -int32 MapStat = 0; /* Map status register */ -int32 Inhibit = 0; /* !0=inhibit interrupts : */ - /* 1 = single cycle inhibit */ - /* 2 = inhibit until indirection */ - /* 3 = inhibit next instruction only */ -int32 Enable = 0; /* User map to activate 1=A 2=B */ -int32 Usermap = 0; /* Active Map? 0=supvr mode, 1=user A, 2 = user B */ -int32 Map[8][32]; /* The actual MAPs 0=dch A, 1=A, 2=B, 3-5=dchB-D 6-7 User C-D */ -int32 Map31 = 037; /* Map for block 31 in supervisor mode */ -int32 SingleCycle = 0; /* Map one LDA/STA */ -int32 Check = 0; /* Page Check Register */ -int32 Fault = 0; /* Fault register */ -int32 MapInit = 0; /* 1 when map initialized */ -int32 MapIntMode = 0; /* Save of map user mode when int occurs */ - -int32 Debug_Flags = 0; /* Debug register - selects debug features */ - -int32 Tron = 0; /* For trace files */ -FILE *Trace; - -t_stat reason; -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern DEVICE *sim_devices[]; - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_boot (int32 unitno, DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat Debug_Dump (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat map_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat map_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat map_reset (DEVICE *dptr); -t_stat map_svc (UNIT *uptr); -int32 GetMap(int32 addr); -int32 PutMap(int32 addr, int32 data); -int32 Debug_Entry(int32 PC, int32 inst, int32 inst2, int32 AC0, int32 AC1, int32 AC2, int32 AC3, int32 flags); -t_stat build_devtab (void); - -extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifiers list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, - MAXMEMSIZE) }; - -REG cpu_reg[] = { - { ORDATA (PC, saved_PC, 15) }, - { ORDATA (AC0, AC[0], 16) }, - { ORDATA (AC1, AC[1], 16) }, - { ORDATA (AC2, AC[2], 16) }, - { ORDATA (AC3, AC[3], 16) }, - { FLDATA (C, C, 16) }, - { ORDATA (SR, SR, 16) }, - { ORDATA (PI, pimask, 16) }, - { FLDATA (ION, int_req, INT_V_ION) }, - { FLDATA (ION_DELAY, int_req, INT_V_NO_ION_PENDING) }, - { FLDATA (PWR, pwr_low, 0) }, - { ORDATA (INT, int_req, INT_V_ION+1), REG_RO }, - { ORDATA (BUSY, dev_busy, INT_V_ION+1), REG_RO }, - { ORDATA (DONE, dev_done, INT_V_ION+1), REG_RO }, - { ORDATA (DISABLE, dev_disable, INT_V_ION+1), REG_RO }, - { FLDATA (STOP_DEV, stop_dev, 0) }, - { DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT }, - { ORDATA (DEBUG, Debug_Flags, 16) }, - { DRDATA (MODEL, model, 16) }, - { DRDATA (SPEED, speed, 16) }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_MICRO, UNIT_MICRO, "MICRO", "MICRO", NULL }, - { UNIT_MICRO, 0, "STD", "STD", NULL }, - { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, - { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, - { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size }, - { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, - { UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size }, - { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size }, - { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size }, - { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, - { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size }, - { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size }, - { UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size }, - { UNIT_MSIZE, 524288, NULL, "512K", &cpu_set_size }, - { UNIT_MSIZE, 1048576, NULL, "1024K", &cpu_set_size }, - { UNIT_MSIZE, 0, NULL, "DUMP", &Debug_Dump }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, 17, 1, 8, 16, - &cpu_ex, &cpu_dep, &cpu_reset, - &cpu_boot, NULL, NULL }; - -/* MAP data structures - - map_dev MAP device descriptor - map_unit MAP unit descriptor - map_reg MAP register list - map_mod MAP modifiers list -*/ - -UNIT map_unit = { UDATA (&map_svc, UNIT_17B, MAXMEMSIZE) }; - -REG map_reg[] = { - { ORDATA (STATUS, MapStat, 16) }, - { ORDATA (ENABLE, Enable, 16) }, - { ORDATA (IINHIB, Inhibit, 16) }, - { ORDATA (ACTIVE, Usermap, 16) }, - { ORDATA (MAP31, Map31, 16) }, - { ORDATA (CYCLE, SingleCycle, 16) }, - { ORDATA (CHECK, Check, 16) }, - { ORDATA (FAULT, Fault, 16) }, - { NULL } }; - -MTAB map_mod[] = { - { UNIT_17B, UNIT_17B, "17bit", "17B", NULL }, - { UNIT_17B, 0, "19bit", "19B", NULL }, - { 0 } }; - -DEVICE map_dev = { - "MAP", &map_unit, map_reg, map_mod, - 1, 8, 17, 1, 8, 16, - &map_ex, &map_dep, NULL, - NULL, NULL, NULL }; - -t_stat sim_instr (void) -{ -extern int32 sim_interval; -register int32 PC, IR, i, t, MA, j, k; -register unsigned int32 mddata, uAC0, uAC1, uAC2, uAC3; -int16 sAC0, sAC1, sAC2; -int32 sddata, mi1, mi2; -t_value simeval[20]; -void mask_out (int32 mask); -/* char debstr[128]; */ -/* char debadd[64]; */ -char debmap[4], debion[4]; -int debcar, iodev, iodata, debflags; -int32 DisMap, debpc; -/* int32 sp, sl; */ -int cmdptr, cmsptr, cmopt, cmptr; -int16 cmslen, cmdlen; -int tabaddr, tabptr; -int32 effective(int32 PC, int32 index, int32 disp); -int32 indirect(int32 d); -int32 LEFmode(int32 PC, int32 index, int32 disp, int32 indirect); -int32 LoadMap(int32 w); -int32 Bytepointer(int32 PC, int32 index); -int32 unimp(int32 PC); -int32 pushrtn(int32 pc); - -/* Restore register state */ - -if (build_devtab () != SCPE_OK) return SCPE_IERR; /* build dispatch */ -PC = saved_PC & AMASK; /* load local PC */ -C = C & 0200000; -mask_out (pimask); /* reset int system */ -reason = 0; -if (MapInit == 0) { - MapInit = 1; - for (mi1 = 0; mi1 < 6; mi1++) { /* Initialize MAPs */ - for (mi2 = 0; mi2 < 32; mi2++) { - Map[mi1][mi2] = mi2; - } - } -} - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) - break; -} - -if (speed > 0) for (i = 0; i < speed; i++) { j = 0; } - -if (Fault) { /* Check MAP fault */ - Usermap = 0; /* YES: shutdown map */ - MapStat &= ~01; /* Disable MMPU */ - if (Fault & 0100000) /* If it was validity, */ - MapStat &= ~0170; /* Reset other checkbits */ - MapStat |= Fault & 077777; /* Put in fault code */ - Fault = 0; /* Reset fault code */ - t = (GetMap(040) + 1) & AMASK; /* Push rtn block */ - PutMap(t, AC[0]); - t++; - PutMap(t, AC[1]); - t++; - PutMap(t, AC[2]); - t++; - PutMap(t, AC[3]); - t++; - PutMap(t, (PC & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - int_req = int_req & ~INT_ION; /* Disable interrupts */ - PC = indirect(M[003]); /* JMP to loc 3 */ - continue; -} - -if (int_req > INT_PENDING && !Inhibit) { /* interrupt? */ - int_req = int_req & ~INT_ION; - MapIntMode = MapStat; /* Save Status as it was */ - Usermap = 0; /* Inhibit MAP */ - MapStat &= ~1; /* Disable user map */ - if (XCT_mode) { - M[0] = PC - 1; /* If XCT mode rtn to XCT */ - XCT_mode = 0; /* turn off mode */ - } else { - M[0] = PC; /* Save Return Address */ - } - old_PC = PC; - MA = M[1]; - for (i = 0; i < ind_max * 2; i++) { /* count indirects */ - if ((MA & 0100000) == 0) break; - if ((MA & 077770) == 020) - MA = (M[MA & AMASK] = (M[MA & AMASK] + 1) & 0177777); - else if ((MA & 077770) == 030) - MA = (M[MA & AMASK] = (M[MA & AMASK] - 1) & 0177777); - else MA = M[MA & AMASK]; - } - if (i >= ind_max) { - if ((MapStat & 010) && Usermap) { - Fault = 04000; /* Map fault if IND prot */ - continue; - } else { - reason = STOP_IND_INT; - break; - } - } - if (Debug_Flags) { - iodev = 0; - iodata = int_req & (-int_req); - for (i = DEV_LOW; i <= DEV_HIGH; i++) { - if (iodata & dev_table[i].mask) { - iodev = i; - break; - } - } - if (iodev == 0) { - printf("\n<>\n"); - reason = STOP_IBKPT; - } - if (Debug_Flags & 0100000) { - fprintf(Trace, "--------- Interrupt %o (%o) to %6o ---------\n", int_req, iodev, MA); - } else { - Debug_Entry(PC, int_req, 0, iodev, MA, 0, 0, 0x80); - } - } - PC = MA; -} /* end interrupt */ - -if (Inhibit != 0) { /* Handle 1-instruction inhibit sequence */ - if (Inhibit == 3) /* Used by SYC instruction */ - Inhibit = 4; - if (Inhibit == 4) - Inhibit = 0; -} - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; -} - -if ((PC < 1 || PC > 077777) && Debug_Flags) { - if (PPC != -1) { /* Don't break on 1st instruction */ - printf("\n<>\n\r", PC, PPC); - reason = STOP_IBKPT; - break; - } -} - -PPC = PC; - -if (Debug_Flags) { - if (!Tron) { - Tron = 1; - Trace = fopen("trace.log", "w"); - } - strcpy(debmap, " "); - strcpy(debion, " "); - debcar = 0; - if (C) debcar = 1; - if (Usermap == 1) strcpy(debmap, "A"); - if (Usermap == 2) strcpy(debmap, "B"); - if (Usermap == 5) strcpy(debmap, "C"); - if (Usermap == 6) strcpy(debmap, "D"); - if (int_req & INT_ION) strcpy(debion, "I"); - if (XCT_mode == 0) { - debpc = PC; - simeval[0] = GetMap(PC); - simeval[1] = GetMap(PC+1); - } else { - debpc = 0177777; - simeval[0] = XCT_inst; - simeval[1] = 0; - } - if (Debug_Flags & 0100000) { - fprintf(Trace, "%s%s%06o acs: %06o %06o %06o %06o %01o ", - debion, debmap, debpc, AC[0], AC[1], AC[2], AC[3], debcar); - fprint_sym (Trace, debpc, simeval, NULL, SWMASK('M')); - fprintf(Trace, "\n"); - } else { - debflags = 0; - if (C) debflags |= 0x01; - if (int_req & INT_ION) debflags |= 0x02; - if (Usermap == 1) debflags |= 0x04; - if (Usermap == 2) debflags |= 0x08; - if (Usermap == 3) debflags |= 0x10; - if (Usermap == 4) debflags |= 0x20; - Debug_Entry(debpc, simeval[0], simeval[1], AC[0], AC[1], AC[2], AC[3], debflags); - } -} - -if (XCT_mode == 0) { /* XCT mode? */ - IR = GetMap(PC); /* No: fetch instr */ - if (Fault) continue; /* Give up if fault */ - PC = (PC + 1) & AMASK; /* bump PC */ -} else { - IR = XCT_inst; /* Yes: Get inst to XCT */ - XCT_mode = 0; /* Go back to normal mode */ -} -int_req = int_req | INT_NO_ION_PENDING; /* clear ION delay */ -sim_interval = sim_interval - 1; -t = IR >> 11; /* prepare to decode */ - -/* ---------------- BEGIN Eclipse modification --------------------- */ - -/* Eclipse instruction set. These instructions are checked for - before any of the NOVA ones. Eclipse instructions do not - correspond to any patterns, other than bit 0 being 1 and - the last 4 bits are 1000. Words which are not Eclipse - instructions will be interpreted as Nova instructions. */ - -/* Important Note: The order of the if statements is important. - Frequently executed instructions should come first, to enhance - the speed of the simulation. -*/ - -if ((IR & 0100017) == 0100010) { /* This pattern for all */ - /* Eclipse instructions */ - -/****************************************************************/ -/* This is the standard Eclipse instruction set */ -/****************************************************************/ - - /* Byte operations */ - - if ((IR & 0103777) == 0102710) { /* LDB: Load Byte */ - i = (IR >> 13) & 03; - MA = (AC[i] >> 1) & AMASK; - j = (IR >> 11) & 03; - if (AC[i] & 01) { - AC[j] = GetMap(MA) & 0377; - } else { - AC[j] = (GetMap(MA) >> 8) & 0377; - } - continue; - } - if ((IR & 0103777) == 0103010) { /* STB: Store Byte */ - i = (IR >> 13) & 03; - MA = (AC[i] >> 1); - j = (IR >> 11) & 03; - t = GetMap(MA); - if (AC[i] & 01) { - t &= 0177400; - t |= (AC[j] & 0377); - PutMap(MA, t); - } else { - t &= 0377; - t |= (AC[j] & 0377) << 8; - PutMap(MA, t); - } - continue; - } - - /* Fixed-point arithmetic - loads & saves */ - - if ((IR & 0162377) == 0122070) { /* ELDA: Extended LDA */ - i = (IR >> 11) & 3; - t = GetMap(PC); - if (SingleCycle) Usermap = SingleCycle; - AC[i] = GetMap(effective(PC, (IR >> 8) & 3, t)); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0162377) == 0142070) { /* ESTA: Extended STA */ - i = (IR >> 11) & 3; - t = GetMap(PC); - if (SingleCycle) Usermap = SingleCycle; - PutMap((effective(PC, (IR >> 8) & 3, t)), AC[i]); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100010) { /* ADI: Add Immediate */ - t = (IR >> 11) & 3; - AC[t] = (AC[t] + ((IR >> 13) & 3) + 1) & 0xffff; - continue; - } - if ((IR & 0103777) == 0100110) { /* SBI: Subtract Immediate */ - t = (IR >> 11) & 3; - AC[t] = (AC[t] - (((IR >> 13) & 3) + 1)) & 0xffff; - continue; - } - if ((IR & 0163777) == 0163770) { /* ADDI: Extended Add Immed. */ - t = (IR >> 11) & 3; - i = GetMap(PC); - PC = (PC + 1) & AMASK; - AC[t] = (AC[t] + i) & 0xffff; - continue; - } - if ((IR & 0103777) == 0100710) { /* XCH: Exchange Accumulators */ - t = AC[(IR >> 11) & 3]; - AC[(IR >> 11) & 3] = AC[(IR >> 13) & 3]; - AC[(IR >> 13) & 3] = t; - continue; - } - if ((IR & 0162377) == 0162070) { /* ELEF: Load Effective Addr */ - t = GetMap(PC); - AC[(IR >> 11) & 3] = effective(PC, (IR >> 8) & 3, t); - PC = (PC + 1) & AMASK; - continue; - } - - /* Logical operations */ - - if ((IR & 0163777) == 0143770) { /* ANDI: And Immediate */ - AC[(IR >> 11) & 3] &= GetMap(PC); - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0163777) == 0103770) { /* IORI: Inclusive Or Immed */ - AC[(IR >> 11) & 3] |= GetMap(PC); - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0163777) == 0123770) { /* XORI: Exclusive Or Immed */ - AC[(IR >> 11) & 3] ^= GetMap(PC); - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100410) { /* IOR: Inclusive Or */ - AC[(IR >> 11) & 3] |= AC[(IR >> 13) & 3]; - continue; - } - if ((IR & 0103777) == 0100510) { /* XOR: Exclusive Or */ - AC[(IR >> 11) & 3] ^= AC[(IR >> 13) & 3]; - continue; - } - if ((IR & 0103777) == 0100610) { /* ANC: And with complemented src */ - AC[(IR >> 11) & 3] &= ~(AC[(IR >> 13) & 3]); - continue; - } - - /* Shift operations */ - - if ((IR & 0103777) == 0101210) { /* LSH: Logical Shift */ - register int16 sh; - sh = AC[(IR >> 13) & 3] & 0377; - i = (IR >> 11) & 3; - if (sh & 0200) { - sh = ~sh + 1; - AC[i] = AC[i] >> sh; - } else { - AC[i] = AC[i] << sh; - } - if (sh > 15) AC[i] = 0; - AC[i] &= 0xffff; - continue; - } - if ((IR & 0103777) == 0101310) { /* DLSH: Double logical shift */ - register int16 sh; - sh = AC[(IR >> 13) & 3] & 0377; - i = (IR >> 11) & 3; - uAC0 = AC[i] << 16; - j = i + 1; - if (j == 4) j = 0; - uAC0 |= AC[j]; - if (sh & 0200) { - sh = (~sh + 1) & 0377; - if (sh < 32) - uAC0 = uAC0 >> sh; - } else { - if (sh < 32) - uAC0 = uAC0 << sh; - } - if (sh > 31) uAC0 = 0; - AC[i] = (uAC0 >> 16) & 0xffff; - AC[j] = uAC0 & 0xffff; - continue; - } - if ((IR & 0103777) == 0101410) { /* HXL: Hex shift left */ - t = ((IR >> 13) & 3) + 1; - i = (IR >> 11) & 3; - AC[i] = AC[i] << (t * 4); - AC[i] &= 0xffff; - continue; - } - if ((IR & 0103777) == 0101510) { /* HXR: Hex shift right */ - t = ((IR >> 13) & 3) + 1; - i = (IR >> 11) & 3; - AC[i] = AC[i] >> (t * 4); - AC[i] &= 0xffff; - continue; - } - if ((IR & 0103777) == 0101610) { /* DHXL: Double Hex shift left */ - t = ((IR >> 13) & 3) + 1; - i = (IR >> 11) & 3; - j = i + 1; - if (j == 4) j = 0; - uAC0 = AC[i] << 16; - uAC0 |= AC[j]; - uAC0 = uAC0 << ((t * 4) & 0177); - AC[i] = (uAC0 >> 16) & 0xffff; - AC[j] = uAC0 & 0xffff; - continue; - } - if ((IR & 0103777) == 0101710) { /* DHXR: Double Hex shift right */ - t = ((IR >> 13) & 3) + 1; - i = (IR >> 11) & 3; - j = i + 1; - if (j == 4) j = 0; - uAC0 = AC[i] << 16; - uAC0 |= AC[j]; - uAC0 = uAC0 >> ((t * 4) & 0177); - AC[i] = (uAC0 >> 16) & 0xffff; - AC[j] = uAC0 & 0xffff; - continue; - } - - - /* Bit operations */ - - if ((IR & 0103777) == 0102010) { /* BTO: Set bit to one */ - i = (IR >> 11) & 3; - j = (IR >> 13) & 3; - if (i != j) { - k = (AC[i] >> 4) & AMASK; - MA = indirect(AC[j] + k); - } else { - MA = (AC[i] >> 4) & AMASK; - } - t = AC[i] & 017; - t = GetMap(MA) | (0100000 >> t); - PutMap(MA, t); - continue; - } - if ((IR & 0103777) == 0102110) { /* BTZ: Set bit to zero */ - i = (IR >> 11) & 3; - j = (IR >> 13) & 3; - if (i != j) { - k = (AC[i] >> 4) & AMASK; - MA = indirect(AC[j] + k); - } else { - MA = (AC[j] >> 4) & AMASK; - } - t = AC[i] & 017; - t = GetMap(MA) & ~(0100000 >> t); - PutMap(MA, t); - continue; - } - if ((IR & 0103777) == 0102210) { /* SZB: Skip on zero bit */ - i = (IR >> 11) & 3; - j = (IR >> 13) & 3; - if (i != j) { - k = (AC[i] >> 4) & AMASK; - MA = indirect(AC[j] + k); - } else { - MA = (AC[i] >> 4) & AMASK; - } - t = GetMap(MA) << (AC[i] & 017); - if (!(t & 0100000)) PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102770) { /* SNB: Skip on non-zero bit */ - i = (IR >> 11) & 3; - j = (IR >> 13) & 3; - if (i != j) { - k = (AC[i] >> 4) & AMASK; - MA = indirect(AC[j] + k); - } else { - MA = (AC[j] >> 4) & AMASK; - } - t = GetMap(MA) << (AC[i] & 017); - if (t & 0100000) PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102310) { /* SZBO: skip on zero bit & set to 1 */ - register int32 save; - i = (IR >> 11) & 3; - j = (IR >> 13) & 3; - if (i != j) { - k = (AC[i] >> 4) & AMASK; - MA = indirect(AC[j] + k); - } else { - MA = (AC[j] >> 4) & AMASK; - } - t = AC[i] & 017; - save = GetMap(MA); - t = save | (0100000 >> t); - PutMap(MA, t); - t = save << (AC[i] & 017); - if ((t & 0100000) == 0) - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102410) { /* LOB: Locate lead bit */ - register int32 a, r; - register int16 b, c = 0; - a = AC[(IR >> 13) & 3] & 0xffff; - for (i = 0; i < 16; i++) { - if ((a << i) & 0100000) break; - } - r = (IR >> 11) & 3; - b = AC[r]; - b += i; - AC[r] = b & 0177777; - continue; - } - if ((IR & 0103777) == 0102510) { /* LRB: Locate & reset lead bit */ - register int32 a, r; - register int16 b; - j = (IR >> 13) & 3; - a = AC[j]; - for (i = 0; i < 16; i++) { - if ((a << i) & 0100000) break; - } - r = (IR >> 11) & 3; - b = AC[r]; - b += i; - if (j != r) AC[r] = b & 0177777; - AC[j] &= ~(0100000 >> i); - AC[j] &= 0xffff; - continue; - } - if ((IR & 0103777) == 0102610) { /* COB: Count bits */ - register int32 a; - register int16 b, c = 0; - a = AC[(IR >> 13) & 3]; - for (i = 0; i < 16; i++) { - if ((a >> i) & 1) c++; - } - i = (IR >> 11) & 3; - b = AC[i]; - b += c; - AC[i] = b & 0177777; - continue; - } - - - /* Jump & similar operations */ - - if ((IR & 0176377) == 0102070) { /* EJMP: Extended JMP */ - PC = effective(PC, (IR >> 8) & 3, GetMap(PC)); - continue; - } - if ((IR & 0176377) == 0106070) { /* EJSR: Extended JMP to subr */ - t = effective(PC, (IR >> 8) & 3, GetMap(PC)); - AC[3] = (PC + 1) & AMASK; - PC = t & AMASK; - continue; - } - if ((IR & 0176377) == 0112070) { /* EISZ: Ext Inc & skip if 0 */ - MA = effective(PC, (IR >> 8) & 3, GetMap(PC)); - PutMap(MA, ((GetMap(MA) + 1) & 0xffff)); - if (GetMap(MA) == 0) PC = (PC + 1) & AMASK; - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0176377) == 0116070) { /* EDSZ: Ext Dec & skip if 0 */ - MA = effective(PC, (IR >> 8) & 3, GetMap(PC)); - PutMap(MA, ((GetMap(MA) - 1) & 0xffff)); - if (GetMap(MA) == 0) PC = (PC + 1) & AMASK; - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0101010) { /* SGT: Skip if ACS > ACD */ - register int16 a1, d1; - a1 = AC[(IR >> 13) & 3] & 0xffff; - d1 = AC[(IR >> 11) & 3] & 0xffff; - if (a1 > d1) - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0101110) { /* SGE: Skip if ACS >= ACD */ - register int16 a1, d1; - a1 = AC[(IR >> 13) & 3] & 0xffff; - d1 = AC[(IR >> 11) & 3] & 0xffff; - if (a1 >= d1) - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102370) { /* CLM: Compare to limits */ - register int32 s, d, MA; - int16 H, L, ca; - s = (IR >> 13) & 3; - d = (IR >> 11) & 3; - if (s == d) { - L = GetMap(PC); - PC++; - H = GetMap(PC); - PC++; - } else { - MA = AC[d] & AMASK; - L = GetMap(MA); - H = GetMap(MA + 1); - } - ca = AC[s]; - if (ca >= L && ca <= H) PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0163777) == 0123370) { /* XCT: Execute */ - XCT_mode = 1; /* Set up to execute on next loop */ - XCT_inst = AC[(IR >> 11) & 3]; - continue; - } - - /* Memory block operations */ - - if (IR == 0113710) { /* BAM: Block add & move */ - register int32 w; - t = AC[1]; - if (t < 1 || t > 0100000) - continue; - i = indirect(AC[2]); - j = indirect(AC[3]); - while (t) { - w = GetMap(i); - PutMap(j, ((w + AC[0]) & 0xffff)); - if (Fault) break; - t--; - i++; - j++; - i &= AMASK; - j &= AMASK; - } - AC[1] = t; - AC[2] = i & AMASK; - AC[3] = j & AMASK; - continue; - } - if (IR == 0133710) { /* BLM: Block move */ - t = AC[1]; - if (t < 1 || t > 0100000) - continue; - i = indirect(AC[2]); - j = indirect(AC[3]); - while (t) { - PutMap(j, GetMap(i)); - if (Fault) break; - t--; - i++; - j++; - i &= AMASK; - j &= AMASK; - } - AC[1] = t; - AC[2] = i & AMASK; - AC[3] = j & AMASK; - continue; - } - - - /* Stack operations */ - - if ((IR & 0103777) == 0103110) { /* PSH: Push multiple accums */ - register int32 j; - j = (IR >> 11) & 3; - t = GetMap(040) & AMASK; - i = (IR >> 13) & 3; - if (i == j) { - t++; - PutMap(t, AC[i]); - PutMap(040, (t & AMASK)); - if (t > GetMap(042)) { - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - continue; - } - while (i != j) { - t++; - PutMap(t, AC[i]); - i++; - if (i == 4) i = 0; - } - t++; - PutMap(t, AC[i]); - PutMap(040, (t & AMASK)); - if ((GetMap(040) & AMASK) > GetMap(042)) { - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - continue; - } - if ((IR & 0103777) == 0103210) { /* POP: Pop mult accums */ - j = (IR >> 11) & 3; - t = GetMap(040) & AMASK; - i = (IR >> 13) & 3; - if (i == j) { - AC[i] = GetMap(t); - t--; - PutMap(040, (t & AMASK)); - t = GetMap(040); - if (t < 0100000 && t < 0400) { - PutMap(040, GetMap(042)); - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - continue; - } - while (i != j) { - AC[i] = GetMap(t); - t--; - i--; - if (i == -1) i = 3; - } - AC[i] = GetMap(t); - t--; - PutMap(040, (t & AMASK)); - t = GetMap(040); - if (t < 0100000 && t < 0400) { - PutMap(040, GetMap(042)); - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - continue; - } - if (IR == 0103710) { /* PSHR: Push return addr */ - t = (GetMap(040) + 1) & AMASK; - PutMap(t, (PC + 1)); - PutMap(040, t); - if ((GetMap(040) & AMASK) > GetMap(042)) { - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - continue; - } - if (IR == 0163710) { /* SAVE */ - register int32 savep; - savep = ((GetMap(PC) + GetMap(040)) + 5) & AMASK; - if (savep > GetMap(042)) { - pushrtn(PC-1); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - continue; - } - t = GetMap(040) + 1; - PutMap(t, AC[0]); - t++; - PutMap(t, AC[1]); - t++; - PutMap(t, AC[2]); - t++; - PutMap(t, GetMap(041)); - t++; - savep = PC; - PC = (PC + 1) & AMASK; - PutMap(t, (AC[3] & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - AC[3] = GetMap(040) & AMASK; - PutMap(041, AC[3]); - PutMap(040, ((GetMap(040) + GetMap(savep)) & AMASK)); - continue; - } - if ((IR & 0163777) == 0103370) { /* MSP: Modify stack pointer */ - t = (GetMap(040) + AC[(IR >> 11) & 3]) & 0177777; - if (t > GetMap(042)) { - pushrtn(PC-1); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & AMASK)); - PutMap(042, (GetMap(042) | 0100000)); - continue; - } - PutMap(040, t); - continue; - } - if ((IR & 0176377) == 0102270) { /* PSHJ: Push JMP */ - PutMap(040, (GetMap(040) + 1)); - PutMap((GetMap(040) & AMASK), ((PC + 1) & AMASK)); - if ((GetMap(040) & AMASK) > (GetMap(042) & AMASK)) { - pushrtn(PC+1); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - continue; - } - PC = effective(PC, (IR >> 8) & 3, GetMap(PC)); - continue; - } - if (IR == 0117710) { /* POPJ: Pop PC and Jump */ - PC = GetMap(GetMap(040)) & AMASK; - PutMap(040, (GetMap(040) - 1)); - if (MapStat & 1) { - Usermap = Enable; - Inhibit = 0; - } - t = GetMap(040); - if (t < 0100000 && t < 0400) { - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - continue; - } - if (IR == 0107710) { /* POPB: Pop block */ - PC = GetMap(GetMap(040)) & AMASK; - if (GetMap(GetMap(040)) & 0100000) - C = 0200000; - else - C = 0; - PutMap(040, (GetMap(040) - 1)); - AC[3] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[2] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[1] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[0] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - t = GetMap(040); - if (t < 0100000 && t < 0400) { - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - if (MapStat & 1) { - Usermap = Enable; - Inhibit = 0; - } - continue; - } - if (IR == 0127710) { /* RTN: Return */ - PutMap(040, GetMap(041)); - PC = GetMap(GetMap(040)) & AMASK; - if (GetMap(GetMap(040)) & 0100000) - C = 0200000; - else - C = 0; - PutMap(040, (GetMap(040) - 1)); - AC[3] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[2] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[1] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[0] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - PutMap(041, AC[3]); - t = GetMap(040); - if (t < 0100000 && t < 0400) { - pushrtn(PC); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - PC = indirect(GetMap(043)); - } - if (MapStat & 1) { - Usermap = Enable; - Inhibit = 0; - } - continue; - } - if (IR == 0167710) { /* RSTR: Restore */ - int32 SVPC; - - SVPC = PC; - PC = GetMap(GetMap(040)) & AMASK; - if (PC == 0 && Debug_Flags) { - printf("\n<>\n\r", SVPC); - reason = STOP_IBKPT; - } - if (GetMap(GetMap(040)) & 0100000) - C = 0200000; - else - C = 0; - PutMap(040, (GetMap(040) - 1)); - AC[3] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[2] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[1] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[0] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - PutMap(043, GetMap(GetMap(040))); - PutMap(040, (GetMap(040) - 1)); - PutMap(042, GetMap(GetMap(040))); - PutMap(040, (GetMap(040) - 1)); - PutMap(041, GetMap(GetMap(040))); - PutMap(040, (GetMap(040) - 1)); - PutMap(040, GetMap(GetMap(040))); - /*t = GetMap(040); - if (t < 0100000 && t < 0400) { - pushrtn(PC); - PC = indirect(GetMap(043)); - }*/ - if (MapStat & 1) { - Usermap = Enable; - Inhibit = 0; - } - continue; - } - - /* Multiply / Divide */ - - if (IR == 0143710) { /* MUL: Unsigned Multiply */ - uAC0 = (unsigned int32) AC[0]; - uAC1 = (unsigned int32) AC[1]; - uAC2 = (unsigned int32) AC[2]; - - mddata = (uAC1 * uAC2) + uAC0; - AC[0] = (mddata >> 16) & 0177777; - AC[1] = mddata & 0177777; - continue; - } - if (IR == 0147710) { /* MULS: Signed Multiply */ - sAC0 = AC[0]; - sAC1 = AC[1]; - sAC2 = AC[2]; - - sddata = (sAC1 * sAC2) + sAC0; - AC[0] = (sddata >> 16) & 0177777; - AC[1] = sddata & 0177777; - continue; - } - if (IR == 0153710) { /* DIV: Unsigned Divide */ - uAC0 = (unsigned int32) AC[0]; - uAC1 = (unsigned int32) AC[1]; - uAC2 = (unsigned int32) AC[2]; - - if (uAC0 >= uAC2) C = 0200000; - else { C = 0; - mddata = (uAC0 << 16) | uAC1; - AC[1] = mddata / uAC2; - AC[0] = mddata % uAC2; - } - continue; - } - if (IR == 0157710) { /* DIVS: Signed Divide */ - sAC2 = AC[2]; - - C = 0; - sddata = ((AC[0] & 0xffff) << 16) | (AC[1] & 0xffff); - AC[1] = sddata / sAC2; - AC[0] = sddata % sAC2; - if (AC[0] > 077777 || AC[0] < -077776) C = 0200000; - /*if ((AC[0] & 0xFFFF0000) != 0) C = 0200000;*/ - if (AC[1] > 077777 || AC[1] < -077776) C = 0200000; - /*if ((AC[1] & 0xFFFF0000) != 0) C = 0200000;*/ - AC[0] &= 0177777; - AC[1] &= 0177777; - continue; - } - if (IR == 0137710) { /* DIVX: Sign extend and Divide */ - int32 q; - if (AC[1] & 0100000) { - AC[0] = 0177777; - } else { - AC[0] = 0; - } - sAC0 = AC[0]; - sAC1 = AC[1]; - sAC2 = AC[2]; - - C = 0; - sddata = (sAC0 << 16) | sAC1; - q = sddata / sAC2; - AC[0] = sddata % sAC2; - if (q > 0177777) { - C = 0200000; - } else { - AC[1] = q & 0xffff; - } - continue; - } - if ((IR & 0163777) == 0143370) { /* HLV: Halve */ - t = (IR >> 11) & 3; - if (AC[t] & 0100000) { - AC[t] = (0 - AC[t]) & 0xffff; - AC[t] = AC[t] >> 1; - AC[t] = (0 - AC[t]) & 0xffff; - } else { - AC[t] = (AC[t] >> 1) & 0xffff; - } - continue; - } - - /* Decimal arithmetic */ - - if ((IR & 0103777) == 0100210) { /* DAD: Decimal add */ - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; - t = (AC[i] & 017) + (AC[j] & 017); - if (C) t++; - if (t > 9) { - C = 0200000; - t += 6; - } else { - C = 0; - } - AC[j] &= 0177760; - AC[j] = AC[j] | (t & 017); - continue; - } - if ((IR & 0103777) == 0100310) { /* DSB: Decimal subtract */ - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; - t = (AC[j] & 017) - (AC[i] & 017); - if (!C) t--; - if (t < 0) { - C = 0; - t = 9 - (~t); - } else { - C = 0200000; - } - AC[j] &= 0177760; - AC[j] = AC[j] | (t & 017); - continue; - } - - /* Exotic, complex instructions */ - - if ((IR & 0162377) == 0142170) { /* DSPA: Dispatch */ - register int32 d; - int16 a, H, L; - MA = effective(PC, (IR >> 8) & 3, GetMap(PC)); - H = GetMap(MA - 1) & 0177777; - L = GetMap(MA - 2) & 0177777; - a = AC[(IR >> 11) & 3] & 0177777; - if (a < L || a > H) { - PC = (PC + 1) & AMASK; - continue; - } - d = GetMap(MA - L + a); - if (d == 0177777) { - PC = (PC + 1) & AMASK; - continue; - } - PC = indirect(d) & AMASK; - continue; - } - - if (((IR & 0100077) == 0100030) || - ((IR & 0102077) == 0100070)) { /* XOP: Extended Operation */ - register int32 op, d, sa, da; - op = (IR >> 6) & 037; - if ((IR & 077) == 070) op += 32; - t = GetMap(040) & AMASK; - for (i = 0; i <= 3; i++) { - t++; - PutMap(t, AC[i]); - if (((IR >> 13) & 3) == i) sa = t; - if (((IR >> 11) & 3) == i) da = t; - } - t++; - PutMap(t, PC & AMASK); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - AC[2] = sa; - AC[3] = da; - d = GetMap(GetMap(044) + op); - PC = indirect(d) & AMASK; - if ((GetMap(040) & AMASK) > (GetMap(042) & AMASK)) { - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - continue; - } - if ((IR & 0103777) == 0103510) { /* SYC: System call */ - register int32 j; - DisMap = Usermap; - Usermap = 0; - MapStat &= ~1; /* Disable MAP */ - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; - if (i != 0 || j != 0) { - t = (GetMap(040) + 1) & AMASK; - PutMap(t, AC[0]); - t++; - PutMap(t, AC[1]); - t++; - PutMap(t, AC[2]); - t++; - PutMap(t, AC[3]); - t++; - PutMap(t, (PC & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PutMap(041, (GetMap(040) & AMASK)); - } - PC = indirect(GetMap(2)) & AMASK; - if (DisMap > 0) - Inhibit = 3; /* Special 1-instruction interrupt inhibit */ - if ((GetMap(040) & AMASK) > GetMap(042)) { - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - continue; - } - if (IR == 0113410) { /* LMP: Load Map */ - register int32 w, m; - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o LMP (Map=%o)\n", PC - 1, (MapStat>>7)&07); - t = AC[1]; - i = AC[2]; - while (t) { - if (int_req > INT_PENDING && !Inhibit) { /* interrupt? */ - PC = PC - 1; - break; - } - if (!Usermap || !(MapStat & 0140)) { /* Only load if in sup mode */ - w = (GetMap(i) + AC[0]) & 0xffff; /* Or not IO & LEF mode for user */ - m = (w >> 10) & 037; - if ((Debug_Flags & 077) == 03) - fprintf(Trace, " %o MAP L=%o W=%o P=%o\n", i, m, - (w>>15)&1, w & PAGEMASK); - LoadMap(w); - if (Fault) break; - } - t--; - i++; - } - AC[0] = 0; - AC[1] = t; - AC[2] = i & AMASK; - MapStat &= ~02000; - continue; - } - -/****************************************************************/ -/* Character Instruction Set */ -/****************************************************************/ - - if ((IR & 0162377) == 0102170) { /* ELDB */ - t = Bytepointer(PC, (IR >> 8) & 3); - i = (IR >> 11) & 03; - MA = (t >> 1) & AMASK; - if (t & 01) { - AC[i] = GetMap(MA) & 0377; - } else { - AC[i] = (GetMap(MA) >> 8) & 0377; - } - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0162377) == 0122170) { /* ESTB */ - t = Bytepointer(PC, (IR >> 8) & 3); - i = (IR >> 11) & 03; - MA = (t >> 1) & AMASK; - j = GetMap(MA); - if (t & 01) { - j &= 0177400; - j |= (AC[i] & 0377); - PutMap(MA, j); - } else { - j &= 0377; - j |= (AC[i] & 0377) << 8; - PutMap(MA, j); - } - PC = (PC + 1) & AMASK; - continue; - } - - if ((IR & 077) == 050) { /* All CIS end with 050 except ELDB/ESTB */ - - if (IR == 0153650) { /* CMV Character Move */ - cmdlen = AC[0] & 0177777; /* Set up length & direction */ - cmslen = AC[1] & 0177777; /* For both source & dest */ - cmsptr = AC[3]; /* init byte pointers */ - cmdptr = AC[2]; - C = 0; /* Do carry now b4 cmslen changes */ - if (abs(cmslen) > abs(cmdlen)) - C = 0200000; - for (i = 0; i < abs(cmdlen); i++) { /* Move loop */ - MA = (cmsptr >> 1) & AMASK; /* do an LDB */ - if (cmsptr & 01) { - uAC2 = GetMap(MA) & 0377; /* Use uAC2 for temp */ - } else { - uAC2 = (GetMap(MA) >> 8) & 0377; - } - if (cmslen == 0) { - uAC2 = ' ' & 0377; /* Handle short source */ - } - MA = (cmdptr >> 1) & AMASK; /* do an STB */ - j = GetMap(MA); - if (cmdptr & 01) { - j &= 0177400; - j |= (uAC2 & 0377); - PutMap(MA, j); - } else { - j &= 0377; - j |= (uAC2 & 0377) << 8; - PutMap(MA, j); - } - if (cmslen > 0) { - cmsptr++; - cmslen--; - } - if (cmslen < 0) { - cmsptr--; - cmslen++; - } - if (cmdlen > 0) { - cmdptr++; - } else { - cmdptr--; - } - } - AC[0] = 0; - AC[1] = cmslen & 0177777; - AC[2] = cmdptr & 0177777; - AC[3] = cmsptr & 0177777; - continue; - } - - if (IR == 0157650) { /* CMP Character compare */ - cmdlen = AC[0] & 0177777; /* Set up length & direction */ - cmslen = AC[1] & 0177777; /* For both source & dest */ - cmsptr = AC[3]; /* init byte pointers */ - cmdptr = AC[2]; - t = 0; /* Equal unless otherwise */ - while (1) { /* Compare loop */ - MA = (cmsptr >> 1) & AMASK; /* do an LDB - string 1 */ - if (cmslen != 0) { - if (cmsptr & 01) { - uAC2 = GetMap(MA) & 0377; /* Use uAC2 for temp */ - } else { - uAC2 = (GetMap(MA) >> 8) & 0377; - } - } else { - uAC2 = ' ' & 0377; - } - MA = (cmdptr >> 1) & AMASK; /* do an LDB - string 2 */ - if (cmdlen != 0) { - if (cmdptr & 01) { - uAC3 = GetMap(MA) & 0377; /* Use uAC2 for temp */ - } else { - uAC3 = (GetMap(MA) >> 8) & 0377; - } - } else { - uAC3 = ' ' & 0377; - } - if (uAC2 > uAC3) { - t = 1; - break; - } - if (uAC2 < uAC3) { - t = -1; - break; - } - if (cmslen > 0) { - cmsptr++; - cmslen--; - } - if (cmslen < 0) { - cmsptr--; - cmslen++; - } - if (cmdlen > 0) { - cmdptr++; - cmdlen--; - } - if (cmdlen < 0) { - cmdptr--; - cmdlen++; - } - if (cmslen == 0 && cmdlen == 0) - break; - } - AC[1] = t & 0177777; - AC[0] = cmdlen & 0177777; - AC[2] = cmdptr & 0177777; - AC[3] = cmsptr & 0177777; - continue; - } - if (IR == 0163650) { /* CTR Character translate */ - tabaddr = indirect(AC[0]); /* Get address of table */ - tabptr = M[tabaddr] & 0177777; /* Get byte pointer */ - cmslen = AC[1] & 0177777; /* Length: both source & dest */ - cmopt = 0; /* Default: COMPARE option */ - if (cmslen < 0) { - cmopt=1; /* MOVE option */ - cmslen = 0 - cmslen; - } - cmsptr = AC[3]; /* init byte pointers */ - cmdptr = AC[2]; - t = 0; /* Equal unless otherwise */ - while (1) { /* Translation loop */ - MA = (cmsptr >> 1) & AMASK; /* do an LDB - string 1 */ - if (cmsptr & 01) { - j = GetMap(MA) & 0377; - } else { - j = (GetMap(MA) >> 8) & 0377; - } - cmptr = tabptr + j; /* Translate */ - MA = (cmptr >> 1) & AMASK; - if (cmptr & 01) { - uAC2 = GetMap(MA) & 0377; - } else { - uAC2 = (GetMap(MA) >> 8) & 0377; - } - if (cmopt) { /* MOVE... */ - MA = (cmdptr >> 1) & AMASK; /* do an STB */ - j = GetMap(MA); - if (cmdptr & 01) { - j &= 0177400; - j |= (uAC2 & 0377); - PutMap(MA, j); - } else { - j &= 0377; - j |= (uAC2 & 0377) << 8; - PutMap(MA, j); - } - } else { /* COMPARE... */ - MA = (cmdptr >> 1) & AMASK; /* do an LDB - string 2 */ - if (cmdptr & 01) { - j = GetMap(MA) & 0377; - } else { - j = (GetMap(MA) >> 8) & 0377; - } - cmptr = tabptr + j; /* Translate */ - MA = (cmptr >> 1) & AMASK; - if (cmptr & 01) { - uAC3 = GetMap(MA) & 0377; - } else { - uAC3 = (GetMap(MA) >> 8) & 0377; - } - if (uAC2 > uAC3) { - t = 1; - break; - } - if (uAC2 < uAC3) { - t = -1; - break; - } - } - cmsptr++; - cmdptr++; - cmslen--; - if (cmslen == 0) - break; - } - if (!cmopt) AC[1] = t; - else - AC[1] = 0; - AC[0] = tabaddr & 077777; - AC[2] = cmdptr & 0177777; - AC[3] = cmsptr & 0177777; - continue; - } - if (IR == 0167650) { /* CMT Char move till true */ - tabaddr = indirect(AC[0]); /* Set up length & direction */ - cmslen = AC[1] & 0177777; /* For both source & dest */ - cmsptr = AC[3]; /* init byte pointers */ - cmdptr = AC[2]; - while (1) { /* Move loop */ - MA = (cmsptr >> 1) & AMASK; /* do an LDB */ - if (cmsptr & 01) { - uAC2 = GetMap(MA) & 0377; /* Use uAC2 for temp */ - } else { - uAC2 = (GetMap(MA) >> 8) & 0377; - } - t = M[tabaddr + (uAC2 >> 4)]; /* Test bit table */ - if (t << (uAC2 & 0x0F) & 0100000) /* quit if bit == 1 */ - break; - MA = (cmdptr >> 1) & AMASK; /* do an STB */ - j = GetMap(MA); - if (cmdptr & 01) { - j &= 0177400; - j |= (uAC2 & 0377); - PutMap(MA, j); - } else { - j &= 0377; - j |= (uAC2 & 0377) << 8; - PutMap(MA, j); - } - if (cmslen > 0) { - cmsptr++; - cmdptr++; - cmslen--; - } - if (cmslen < 0) { - cmsptr--; - cmdptr--; - cmslen++; - } - if (cmslen == 0) - break; - } - AC[0] = tabaddr & 077777; - AC[1] = cmslen & 0177777; - AC[2] = cmdptr & 0177777; - AC[3] = cmsptr & 0177777; - continue; - } - - /*********************************************************** - ** "Commercial" instructions. These were in the original ** - ** Eclipse C series, but not part of the later Character ** - ** Instruction Set. ** - ***********************************************************/ - - if ((IR & 0163777) == 0103650) { /* LDI Load Integer */ - unimp(PC); - continue; - } - if ((IR & 0163777) == 0123650) { /* STI Store Integer */ - unimp(PC); - continue; - } - if (IR == 0143650) { /* LDIX Load Int Extended */ - unimp(PC); - continue; - } - if (IR == 0143750) { /* STIX Store Int Extended */ - unimp(PC); - continue; - } - if ((IR & 0163777) == 0143150) { /* FINT Integerize */ - unimp(PC); - continue; - } - if (IR == 0177650) { /* LSN Load Sign */ - unimp(PC); - continue; - } - if (IR == 0173650) { /* EDIT */ - unimp(PC); - continue; - } - } - - /* FPU Instructions */ - - if ((IR & 0103777) == 0102050) { /* FLDS Load FP single */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102150) { /* FLDD Load FP double */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102250) { /* FSTS Store FP single */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102350) { /* FSTD Store FP double */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102450) { /* FLAS Float from AC */ - continue; - } - if ((IR & 0103777) == 0102550) { /* FLMD Float from memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102650) { /* FFAS Fix to AC */ - continue; - } - if ((IR & 0103777) == 0102750) { /* FFMD Fix to Memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0103550) { /* FMOV Move FP */ - continue; - } - if ((IR & 0103777) == 0100050) { /* FAS Add single to AC */ - continue; - } - if ((IR & 0103777) == 0101050) { /* FAMS Add single to memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100150) { /* FAD Add double */ - continue; - } - if ((IR & 0103777) == 0101150) { /* FAMD Add double to memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100250) { /* FSS Sub single to AC */ - continue; - } - if ((IR & 0103777) == 0101250) { /* FSMS Sub single from memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100350) { /* FSD Sub double from AC */ - continue; - } - if ((IR & 0103777) == 0101350) { /* FSMD Sub double from memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100450) { /* FMS Mult single by AC */ - continue; - } - if ((IR & 0103777) == 0101450) { /* FMMS Mult double by memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100550) { /* FMD Mult double by AC */ - continue; - } - if ((IR & 0103777) == 0101550) { /* FMMD Mult double by memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100650) { /* FDS Div single by AC */ - continue; - } - if ((IR & 0103777) == 0101650) { /* FDMS Div double by memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100650) { /* FDD Div double by AC */ - continue; - } - if ((IR & 0103777) == 0101650) { /* FDMD Div double by memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0163777) == 0163050) { /* FNEG Negate */ - continue; - } - if ((IR & 0163777) == 0103050) { /* FNOM Normalize*/ - continue; - } - if ((IR & 0163777) == 0143050) { /* FAB Absolute Value*/ - continue; - } - if ((IR & 0163777) == 0123050) { /* FRH Read High Word */ - continue; - } - if ((IR & 0163777) == 0103150) { /* FSCAL Scale */ - continue; - } - if ((IR & 0163777) == 0123150) { /* FEXP Load Exponent */ - continue; - } - if ((IR & 0163777) == 0163150) { /* FHLV Halve */ - continue; - } - if ((IR & 0103777) == 0103450) { /* FCMP FP Compare */ - continue; - } - if ((IR & 0163777) == 0123350) { /* FLST Load Status */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0163777) == 0103350) { /* FSST Store Status */ - PC = (PC + 1) & AMASK; - continue; - } - if (IR == 0143350) { /* FTE Trap Enable */ - continue; - } - if (IR == 0147350) { /* FTD Trap Disable */ - continue; - } - if (IR == 0153350) { /* FCLE Clear Errors */ - continue; - } - if (IR == 0163350) { /* FPSH Push State */ - continue; - } - if (IR == 0167350) { /* FPOP Pop State */ - continue; - } - if (IR == 0103250) { /* FNS No Skip */ - continue; - } - if (IR == 0107250) { /* FSA Always Skip */ - continue; - } - if (IR == 0137250) { /* FSGT */ - continue; - } - if (IR == 0123250) { /* FSLT */ - continue; - } - if (IR == 0113250) { /* FSEQ */ - continue; - } - if (IR == 0133250) { /* FSLE */ - continue; - } - if (IR == 0127250) { /* FSGE */ - continue; - } - if (IR == 0117250) { /* FSNE */ - continue; - } - if (IR == 0143250) { /* FSNM */ - continue; - } - if (IR == 0153250) { /* FSNU */ - continue; - } - if (IR == 0163250) { /* FSNO */ - continue; - } - if (IR == 0147250) { /* FSND */ - continue; - } - if (IR == 0157250) { /* FSNUD */ - continue; - } - if (IR == 0167250) { /* FSNOD */ - continue; - } - if (IR == 0173250) { /* FSNUO */ - continue; - } - if (IR == 0177250) { /* FSNER */ - continue; - } - - if (Debug_Flags) { - printf("\n<>\n\r", IR, PC-1); - if (Debug_Flags & 040000) reason = STOP_IBKPT; - } -} - -if (IR == 061777) { /* VCT: Vector on Interrupt */ - int32 stkchg, vtable; - int32 ventry, dctadr; - int32 old40, old41, old42, old43; - - /* Ok, folks, this is one helluva instruction */ - - stkchg = GetMap(PC) & 0100000; /* Save stack change bit */ - vtable = GetMap(PC) & AMASK; /* Address of vector table */ - - iodev = 0; - int_req = (int_req & ~INT_DEV) | /* Do an INTA w/o an accum */ - (dev_done & ~dev_disable); - iodata = int_req & (-int_req); - for (i = DEV_LOW; i <= DEV_HIGH; i++) { - if (iodata & dev_table[i].mask) { - iodev = i; - break; - } - } - - ventry = GetMap(vtable + iodev); /* Get Vector Entry */ - - if (!(ventry & 0100000)) { /* Direct bit = 0? */ - PC = ventry & AMASK; /* YES - Mode A, so JMP */ - continue; - } - - dctadr = ventry & AMASK; /* Get address of DCT entry */ - - if (stkchg) { /* Stack change bit = 1? */ - old40 = GetMap(040); /* Save stack info */ - old41 = GetMap(041); - old42 = GetMap(042); - old43 = GetMap(043); - PutMap(040, GetMap(004)); /* Loc 4 to stack ptr */ - PutMap(042, GetMap(006)); /* Loc 6 to stack limit */ - PutMap(043, GetMap(007)); /* Loc 7 into stack limit */ - PutMap(040, (GetMap(040) + 1)); /* Push old contents on new stk */ - PutMap(GetMap(040) & AMASK, old40); - PutMap(040, (GetMap(040) + 1)); - PutMap(GetMap(040) & AMASK, old41); - PutMap(040, (GetMap(040) + 1)); - PutMap(GetMap(040) & AMASK, old42); - PutMap(040, (GetMap(040) + 1)); - PutMap(GetMap(040) & AMASK, old43); - } - - t = GetMap(dctadr & AMASK); /* Get word 0 of DCT */ - - if (t & 0100000) { /* Push bit set ? */ - PutMap(040, (GetMap(040) + 1)); /* Push "Standard rtn block" */ - PutMap(GetMap(040) & AMASK, AC[0]); - PutMap(040, (GetMap(040) + 1)); - PutMap(GetMap(040) & AMASK, AC[1]); - PutMap(040, (GetMap(040) + 1)); - PutMap(GetMap(040) & AMASK, AC[2]); - PutMap(040, (GetMap(040) + 1)); - PutMap(GetMap(040) & AMASK, AC[3]); - PutMap(040, (GetMap(040) + 1)); - PutMap(GetMap(040) & AMASK, GetMap(0)); - if (GetMap(0) == 0 && Debug_Flags) { - printf("\n<>\n\r", PC); - reason = STOP_IBKPT; - } - if (C) PutMap(GetMap(040) & AMASK, (GetMap(GetMap(040) & AMASK) | 0100000)); - } - - /************************************************************************* - ** At this point, the instruction is not an Eclipse one. Therefore ** - ** decode it as a Nova instruction just like the Nova does. ** - *************************************************************************/ - - AC[2] = dctadr & AMASK; /* DCT Addr into AC2 */ - - PutMap(040, (GetMap(040) + 1)); /* Push pri int mask onto stack */ - PutMap(GetMap(040) & AMASK, pimask); - - AC[0] = GetMap(dctadr + 1) | pimask;/* Build new mask from word 1 of dct */ - PutMap(005, AC[0]); - - mask_out(pimask = AC[0]); /* Do a mask out inst */ - - PC = GetMap(dctadr) & AMASK; /* Finally, JMP to int routine */ - - continue; -} - -/* Memory reference instructions */ - -if (t < 014) { /* mem ref? */ - register int32 src, MA; - MA = IR & 0377; - switch ((IR >> 8) & 03) { /* decode IR<6:7> */ - case 0: /* page zero */ - break; - case 1: /* PC relative */ - if (MA & 0200) MA = 077400 | MA; - MA = (MA + PC - 1) & AMASK; - break; - case 2: /* AC2 relative */ - if (MA & 0200) MA = 077400 | MA; - MA = (MA + AC[2]) & AMASK; - break; - case 3: /* AC3 relative */ - if (MA & 0200) MA = 077400 | MA; - MA = (MA + AC[3]) & AMASK; - break; - } - if (IR & 002000) { /* indirect? */ - for (i = 0; i < (ind_max * 2); i++) { /* count indirects */ - if ((MA & 077770) == 020 && !(cpu_unit.flags & UNIT_MICRO)) - MA = (PutMap(MA & AMASK, (GetMap(MA & AMASK) + 1) & 0177777)); - else if ((MA & 077770) == 030 && !(cpu_unit.flags & UNIT_MICRO)) - MA = (PutMap(MA & AMASK, (GetMap(MA & AMASK) - 1) & 0177777)); - else MA = GetMap(MA & AMASK); - if (MapStat & 1) { /* Start MAP */ - Usermap = Enable; - Inhibit = 0; - } - if ((MA & 0100000) == 0) break; - if (i >= ind_max && (MapStat & 010) && Usermap) break; - } - if (i >= ind_max) { - if ((MapStat & 010) && Usermap) { - Fault = 04000; /* Map fault if IND prot */ - continue; - } - if (i >= (ind_max * 2) && !(Fault)) { - reason = STOP_IND; - break; - } - } - } - -/* Memory reference, continued */ - - switch (t) { /* decode IR<1:4> */ - case 001: /* JSR */ - AC[3] = PC; - case 000: /* JMP */ - old_PC = PC; - PC = MA; - break; - case 002: /* ISZ */ - src = (GetMap(MA) + 1) & 0177777; - if (MEM_ADDR_OK (MA)) PutMap(MA, src); - if (src == 0) PC = (PC + 1) & AMASK; - break; - case 003: /* DSZ */ - src = (GetMap(MA) - 1) & 0177777; - if (MEM_ADDR_OK (MA)) PutMap(MA, src); - if (src == 0) PC = (PC + 1) & AMASK; - break; - case 004: /* LDA 0 */ - if (SingleCycle) Usermap = SingleCycle; - AC[0] = GetMap(MA); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - break; - case 005: /* LDA 1 */ - if (SingleCycle) Usermap = SingleCycle; - AC[1] = GetMap(MA); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - break; - case 006: /* LDA 2 */ - if (SingleCycle) Usermap = SingleCycle; - AC[2] = GetMap(MA); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - break; - case 007: /* LDA 3 */ - if (SingleCycle) Usermap = SingleCycle; - AC[3] = GetMap(MA); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - break; - case 010: /* STA 0 */ - if (SingleCycle) - Usermap = SingleCycle; - if (MEM_ADDR_OK (MA)) PutMap(MA, AC[0]); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - break; - case 011: /* STA 1 */ - if (SingleCycle) - Usermap = SingleCycle; - if (MEM_ADDR_OK (MA)) PutMap(MA, AC[1]); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - break; - case 012: /* STA 2 */ - if (SingleCycle) - Usermap = SingleCycle; - if (MEM_ADDR_OK (MA)) PutMap(MA, AC[2]); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - break; - case 013: /* STA 3 */ - if (SingleCycle) - Usermap = SingleCycle; - if (MEM_ADDR_OK (MA)) PutMap(MA, AC[3]); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - break; } /* end switch */ - } /* end mem ref */ - -/* Operate instruction */ - -else if (t & 020) { /* operate? */ - register int32 src, srcAC, dstAC; - srcAC = (t >> 2) & 3; /* get reg decodes */ - dstAC = t & 03; - switch ((IR >> 4) & 03) { /* decode IR<10:11> */ - case 0: /* load */ - src = AC[srcAC] | C; - break; - case 1: /* clear */ - src = AC[srcAC]; - break; - case 2: /* set */ - src = AC[srcAC] | 0200000; - break; - case 3: /* complement */ - src = AC[srcAC] | (C ^ 0200000); - break; } /* end switch carry */ - switch ((IR >> 8) & 07) { /* decode IR<5:7> */ - case 0: /* COM */ - src = src ^ 0177777; - break; - case 1: /* NEG */ - src = ((src ^ 0177777) + 1) & 0377777; - break; - case 2: /* MOV */ - break; - case 3: /* INC */ - src = (src + 1) & 0377777; - break; - case 4: /* ADC */ - src = ((src ^ 0177777) + AC[dstAC]) & 0377777; - break; - case 5: /* SUB */ - src = ((src ^ 0177777) + AC[dstAC] + 1) & 0377777; - break; - case 6: /* ADD */ - src = (src + AC[dstAC]) & 0377777; - break; - case 7: /* AND */ - src = src & (AC[dstAC] | 0200000); - break; } /* end switch oper */ - -/* Operate, continued */ - - switch ((IR >> 6) & 03) { /* decode IR<8:9> */ - case 0: /* nop */ - break; - case 1: /* L */ - src = ((src << 1) | (src >> 16)) & 0377777; - break; - case 2: /* R */ - src = ((src >> 1) | (src << 16)) & 0377777; - break; - case 3: /* S */ - src = ((src & 0377) << 8) | ((src >> 8) & 0377) | - (src & 0200000); - break; } /* end switch shift */ - switch (IR & 07) { /* decode IR<13:15> */ - case 0: /* nop */ - break; - case 1: /* SKP */ - PC = (PC + 1) & AMASK; - break; - case 2: /* SZC */ - if (src < 0200000) PC = (PC + 1) & AMASK; - break; - case 3: /* SNC */ - if (src >= 0200000) PC = (PC + 1) & AMASK; - break; - case 4: /* SZR */ - if ((src & 0177777) == 0) PC = (PC + 1) & AMASK; - break; - case 5: /* SNR */ - if ((src & 0177777) != 0) PC = (PC + 1) & AMASK; - break; - case 6: /* SEZ */ - if (src <= 0200000) PC = (PC + 1) & AMASK; - break; - case 7: /* SBN */ - if (src > 0200000) PC = (PC + 1) & AMASK; - break; } /* end switch skip */ - if ((IR & 000010) == 0) { /* load? */ - AC[dstAC] = src & 0177777; - C = src & 0200000; } /* end if load */ - } /* end if operate */ - -/* IOT instruction */ - -else { /* IOT */ - register int32 dstAC, pulse, code, device, iodata; - char pulcode[4]; - - if ((MapStat & 0100) && Usermap) { /* We are in LEF Mode */ - AC[(IR >> 11) & 3] = LEFmode(PC - 1, (IR >> 8) & 3, IR & 0377, IR & 02000); - if (Debug_Flags & 020000) { - printf("\n\r<>\n\r", PC-1); - reason = STOP_IBKPT; - } - continue; - } - - dstAC = t & 03; /* decode fields */ - if ((MapStat & 040) && Usermap) { /* I/O protection fault */ - Fault = 020000; - continue; - } - code = (IR >> 8) & 07; - pulse = (IR >> 6) & 03; - device = IR & 077; - if (Debug_Flags && device == 0) { - printf("\n\r<>\n\r", PC-1); - reason = STOP_IBKPT; - } - if ((Debug_Flags & 0100) && (device == (Debug_Flags & 077))) { - printf("\n\r<>\n\r", device); - reason = STOP_IBKPT; - } - if (code == ioSKP) { /* IO skip? */ - switch (pulse) { /* decode IR<8:9> */ - case 0: /* skip if busy */ - if ((device == 077)? (int_req & INT_ION) != 0: - (dev_busy & dev_table[device].mask) != 0) - PC = (PC + 1) & AMASK; - break; - case 1: /* skip if not busy */ - if ((device == 077)? (int_req & INT_ION) == 0: - (dev_busy & dev_table[device].mask) == 0) - PC = (PC + 1) & AMASK; - break; - case 2: /* skip if done */ - if ((device == 077)? pwr_low != 0: - (dev_done & dev_table[device].mask) != 0) - PC = (PC + 1) & AMASK; - break; - case 3: /* skip if not done */ - if ((device == 077)? pwr_low == 0: - (dev_done & dev_table[device].mask) == 0) - PC = (PC + 1) & AMASK; - break; } /* end switch */ - } /* end IO skip */ - -/* IOT, continued */ - - else if (device == DEV_CPU) { /* CPU control */ - switch (code) { /* decode IR<5:7> */ - case ioNIO: /* Get CPU ID */ - switch (model) { - case 280: /* S280 */ - AC[0] = 021102; - break; - case 380: - AC[0] = 013212; /* C380 */ - break; - default: - break; - } - break; /* Otherwise no-op */ - case ioDIA: /* read switches */ - AC[dstAC] = SR; - break; - case ioDIB: /* int ack */ - AC[dstAC] = 0; - int_req = (int_req & ~INT_DEV) | - (dev_done & ~dev_disable); - iodata = int_req & (-int_req); - for (i = DEV_LOW; i <= DEV_HIGH; i++) { - if (iodata & dev_table[i].mask) { - AC[dstAC] = i; break; } } - break; - case ioDOB: /* mask out */ - mask_out (pimask = AC[dstAC]); - break; - case ioDIC: /* io reset IORST */ - reset_all (0); /* reset devices */ - Usermap = 0; /* reset MAP */ - MapStat &= 04; /* Reset MAP status */ - MapIntMode = 0; - Inhibit = 0; - Map31 = 037; - Check = SingleCycle = 0; - Fault = 0; - break; - case ioDOC: /* halt */ - reason = STOP_HALT; - break; } /* end switch code */ - switch (pulse) { /* decode IR<8:9> */ - case iopS: /* ion */ - int_req = (int_req | INT_ION) & ~INT_NO_ION_PENDING; - break; - case iopC: /* iof */ - int_req = int_req & ~INT_ION; - break; } /* end switch pulse */ - } /* end CPU control */ - - else if (device == DEV_ECC) { - switch (code) { - case ioDIA: /* Read Fault Address */ - AC[dstAC] = 0; - break; - case ioDIB: /* Read fault code */ - AC[dstAC] = 0; - break; - case ioDOA: /* Enable ERCC */ - break; } - } - - else if (device == DEV_MAP) { /* MAP control */ - switch (code) { /* decode IR<5:7> */ - case ioNIO: /* No I/O -- Single */ - if (!Usermap || !(MapStat & 0140)) { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o NIO %o (No I/O, clear faults)\n", PC-1, dstAC); - MapStat &= ~036000; /* NIO Clears all faults */ - } else { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o NIO %o (No I/O, clear faults) NO EXEC(User mode)\n", PC-1, dstAC); - } - break; - case ioDIA: /* Read map status */ - if (!Usermap || !(MapStat & 0140)) { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DIA %o=%o (Read Map Status)\n", PC-1, dstAC, MapStat); - AC[dstAC] = MapStat & 0xFFFE; - if (MapIntMode & 1) /* Bit 15 is mode asof last int */ - AC[dstAC] |= 1; - } else { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DIA %o=%o (Read Map Status) NO EXEC(User mode)\n", PC-1, dstAC, MapStat); - } - break; - case ioDOA: /* Load map status */ - if (!Usermap || !(MapStat & 0140)) { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DOA %o=%o (Load Map Status)\n", PC-1, dstAC, AC[dstAC]); - MapStat = AC[dstAC]; - MapIntMode = 0; - Enable = 1; - if (MapStat & 04) Enable = 2; - Check &= ~01600; - Check |= MapStat & 01600; - if (MapStat & 1) - Inhibit = 2; /* Inhibit interrupts */ - } else { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DOA %o=%o (Load Map Status) NO EXEC(User mode)\n", PC-1, dstAC, AC[dstAC]); - } - break; - case ioDIB: /* not used */ - break; - case ioDOB: /* map block 31 */ - if (!Usermap || !(MapStat && 0140)) { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DOB %o=%o (Map Blk 31)\n", PC-1, dstAC, AC[dstAC]); - Map31 = AC[dstAC] & PAGEMASK; - MapStat &= ~02000; - } else { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DOB %o=%o (Map Blk 31) NO EXEC (User Mode)\n", PC-1, dstAC, AC[dstAC]); - } - break; - case ioDIC: /* Page Check */ - if (!Usermap || !(MapStat & 0140)) { - switch ((Check>>7) & 07) { - case 0: i=1; break; - case 1: i=6; break; - case 2: i=2; break; - case 3: i=7; break; - case 4: i=0; break; - case 5: i=4; break; - case 6: i=3; break; - case 7: i=5; break; - default: break; - } - j = (Check >> 10) & 037; - AC[dstAC] = Map[i][j] & 0101777; - AC[dstAC] |= ((Check << 5) & 070000); - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DIC %o=%o (Page Check)\n", PC-1, dstAC, AC[dstAC]); - MapStat &= ~02000; - } else { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DIC %o=%o (Page Check) NO EXEC(User mode)\n", PC-1, dstAC, AC[dstAC]); - } - break; - case ioDOC: /* Init Page Check */ - if (!Usermap || !(MapStat & 0140)) { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DOC %o=%o (Init Pg Chk)\n", PC-1, dstAC, AC[dstAC]); - Check = AC[dstAC]; - MapStat &= ~01600; - MapStat |= (Check & 01600); - MapStat &= ~02000; - } else { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DOC %o=%o (Init Pg Chk) NO EXEC(User mode)\n", PC-1, dstAC, AC[dstAC]); - } - break; - } /* end switch code */ - switch (pulse) { - case iopP: - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o xxxP (Single Cycle)\n", PC-1); - if (Usermap) { - MapStat &= 0177776; - Usermap = 0; - Inhibit = 0; - } else { - SingleCycle = Enable; - Inhibit = 1; /* Inhibit interrupts */ - } - break; } - } /* end CPU control */ - else if (dev_table[device].routine) { /* normal device */ - iodata = dev_table[device].routine (pulse, code, AC[dstAC]); - reason = iodata >> IOT_V_REASON; - if (code & 1) AC[dstAC] = iodata & 0177777; - if ((Debug_Flags & 077) == device && Debug_Flags != 0) { - strcpy(pulcode, ""); - switch (pulse) { - case iopP: - strcpy(pulcode, "P"); - break; - case iopS: - strcpy(pulcode, "S"); - break; - case iopC: - strcpy(pulcode, "C"); - break; - default: - break; - } - switch(code) { - case ioNIO: - fprintf(Trace, "[%o] %o NIO%s %o\n", device, PC-1, pulcode, AC[dstAC]); - break; - case ioDIA: - fprintf(Trace, "[%o] %o DIA%s %o\n", device, PC-1, pulcode, iodata); - break; - case ioDIB: - fprintf(Trace, "[%o] %o DIB%s %o\n", device, PC-1, pulcode, iodata); - break; - case ioDIC: - fprintf(Trace, "[%o] %o DIC%s %o\n", device, PC-1, pulcode, iodata); - break; - case ioDOA: - fprintf(Trace, "[%o] %o DOA%s %o\n", device, PC-1, pulcode, AC[dstAC]); - break; - case ioDOB: - fprintf(Trace, "[%o] %o DOB%s %o\n", device, PC-1, pulcode, AC[dstAC]); - break; - case ioDOC: - fprintf(Trace, "[%o] %o DOC%s %o\n", device, PC-1, pulcode, AC[dstAC]); - break; - default: - break; - } /* end switch */ - } /* end if debug */ - } /* end else if */ - else reason = stop_dev; } /* end if IOT */ -} /* end while */ - -/* Simulation halted */ - -saved_PC = PC; -return reason; -} - -/* Computes and returns a 16-bit effective address, given a - program counter, index, and a displacement. -*/ - -int32 effective(int32 PC, int32 index, int32 disp) -{ - register int32 i, MA; - MA = disp & 077777; - switch (index) { /* decode IR<6:7> */ - case 0: /* page zero */ - break; - case 1: /* PC relative */ - MA = (MA + PC) & AMASK; - break; - case 2: /* AC2 relative */ - MA = (MA + AC[2]) & AMASK; - break; - case 3: /* AC3 relative */ - MA = (MA + AC[3]) & AMASK; - break; - } /* end switch mode */ - - if (disp & 0100000) { /* indirect? */ - for (i = 0; i < ind_max * 2; i++) { /* count indirects */ - MA = GetMap(MA & AMASK); - if (SingleCycle) Usermap = 0; - if (MapStat & 1) { /* Start MAP */ - Usermap = Enable; - Inhibit = 0; - } - if ((MA & 0100000) == 0) break; - if ((MapStat & 010) && Usermap && i >= ind_max) break; - } - if (i >= ind_max && (MapStat & 010) && Usermap) { - Fault = 04000; /* Map fault if IND prot */ - } - if (i >= (ind_max * 2) && !(Fault)) { - reason = STOP_IND_INT; /* Stop machine */ - } - } - return (MA & AMASK); -} - -/* Computes and returns a 16-bit effective address, given a - program counter, index, and a displacement. This is a - version supporting the LEF map mode instruction, as - opposed to the ELEF instruction. -*/ - -int32 LEFmode(int32 PC, int32 index, int32 disp, int32 indirect) -{ - register int32 i, MA; - int16 sMA; - MA = disp & 077777; - switch (index) { /* decode IR<6:7> */ - case 0: /* page zero */ - break; - case 1: /* PC relative */ - MA = (MA + PC) & AMASK; - break; - case 2: /* AC2 relative */ - sMA = MA; - if (MA & 0200) sMA |= 0xff00; - MA = (sMA + AC[2]) & AMASK; - break; - case 3: /* AC3 relative */ - sMA = MA; - if (MA & 0200) sMA |= 0xff00; - MA = (sMA + AC[3]) & AMASK; - break; - } /* end switch mode */ - - if (indirect) { /* indirect? */ - for (i = 0; i < (ind_max * 2); i++) { /* count indirects */ - if ((MA & 077770) == 020 && !(cpu_unit.flags & UNIT_MICRO)) - MA = (PutMap(MA & AMASK, (GetMap(MA & AMASK) + 1) & 0177777)); - else if ((MA & 077770) == 030 && !(cpu_unit.flags & UNIT_MICRO)) - MA = (PutMap(MA & AMASK, (GetMap(MA & AMASK) - 1) & 0177777)); - else MA = GetMap(MA & AMASK); - if (SingleCycle) Usermap = 0; - if (MapStat & 1) { /* Start MAP */ - Usermap = Enable; - Inhibit = 0; - } - if ((MA & 0100000) == 0) break; - if ((MapStat & 010) && Usermap && i >= ind_max) break; - } - if (i >= ind_max && (MapStat & 010) && Usermap) { - Fault = 04000; /* Map fault if IND prot */ - } - if (i >= (ind_max * 2) && !(Fault)) { - reason = STOP_IND_INT; /* Stop machine */ - } - } - return (MA & AMASK); -} - -/* Computes a "Byte pointer" for the Character Instruction set */ -/* This address in 'PC' must point to the displacement word of the instruction */ - -int32 Bytepointer(int32 PC, int32 index) -{ - register int32 MA; - switch (index) { /* decode IR<6:7> */ - case 0: /* page zero */ - MA = 0; - break; - case 1: /* PC relative */ - MA = PC & AMASK; - break; - case 2: /* AC2 relative */ - MA = AC[2] & AMASK; - break; - case 3: /* AC3 relative */ - MA = AC[3] & AMASK; - break; - } /* end switch mode */ - MA = (MA * 2) & 0177777; - MA = MA + M[PC]; - return (MA & 0177777); -} - -/* Given an address, returns either that address if bit 0 is 0, or - or follows an indirection chain until bit 0 is 0 -*/ - -int32 indirect(int32 d) -{ - int i; - - if (d & 0100000) { /* indirect? */ - for (i = 0; i < ind_max * 2; i++) { /* count indirects */ - if ((d & 077770) == 020 && !(cpu_unit.flags & UNIT_MICRO)) - d = (PutMap(d & AMASK, ((GetMap(d & AMASK) + 1) & 0177777))); - else if ((d & 077770) == 030 && !(cpu_unit.flags & UNIT_MICRO)) - d = (PutMap(d & AMASK, ((GetMap(d & AMASK) - 1) & 0177777))); - else d = GetMap(d & AMASK); - if (MapStat & 1) { /* Start MAP */ - Usermap = Enable; - Inhibit = 0; - } - if ((d & 0100000) == 0) break; - if ((MapStat & 010) && Usermap && i >= ind_max) break; - } - if (i >= ind_max && (MapStat & 010) && Usermap) { - Fault = 04000; /* Map fault if IND prot */ - } - if (i >= (ind_max * 2) && !(Fault)) { - reason = STOP_IND; /* Stop machine */ - } - } - return (d); -} - -/* Push a standard return block onto the stack */ - -int32 pushrtn(int32 pc) -{ - int32 t; - - t = (GetMap(040) + 1) & AMASK; - PutMap(t, AC[0]); - t++; - PutMap(t, AC[1]); - t++; - PutMap(t, AC[2]); - t++; - PutMap(t, AC[3]); - t++; - PutMap(t, pc); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - return 0; -} - - -/* Eclipse memory get/put - uses MAP if enabled */ - -int32 GetMap(int32 addr) -{ - int32 page; - uint32 paddr; - - switch (Usermap) { - case 0: - if (addr < 076000) - return M[addr]; - paddr = ((Map31 & PAGEMASK) << 10) | (addr & 001777); - if (paddr < MEMSIZE) - return M[paddr]; - else - return (0); - break; - case 1: - page = (addr >> 10) & 037; - paddr = ((Map[1][page] & 01777) << 10) | (addr & 001777); - if (Map[1][page] == INVALID && !SingleCycle) - Fault = 0100000; - if (paddr < MEMSIZE) - return M[paddr]; - else - return (0); - break; - case 2: - page = (addr >> 10) & 037; - paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777); - if (Map[2][page] == INVALID && !SingleCycle) - Fault = 0100000; - if (paddr < MEMSIZE) - return M[paddr]; - else - return (0); - break; - case 6: - page = (addr >> 10) & 037; - paddr = ((Map[6][page] & PAGEMASK) << 10) | (addr & 001777); - if (Map[6][page] == INVALID && !SingleCycle) - Fault = 0100000; - if (paddr < MEMSIZE) - return M[paddr]; - else - return (0); - break; - case 7: - page = (addr >> 10) & 037; - paddr = ((Map[7][page] & PAGEMASK) << 10) | (addr & 001777); - if (Map[7][page] == INVALID && !SingleCycle) - Fault = 0100000; - if (paddr < MEMSIZE) - return M[paddr]; - else - return (0); - break; - default: - printf("\n\r<>\n\r"); - return M[addr]; - break; - } -} - -int32 PutMap(int32 addr, int32 data) -{ - int32 page; - uint32 paddr; - - switch (Usermap) { - case 0: - if (addr < 076000) { - M[addr] = data; - return (data); - } - paddr = ((Map31 & PAGEMASK) << 10) | (addr & 001777); - if (paddr < MEMSIZE) M[paddr] = data; - break; - case 1: - page = (addr >> 10) & 037; - paddr = ((Map[1][page] & PAGEMASK) << 10) | (addr & 001777); - if (((Map[1][page] & 0100000) && (MapStat & 020)) || Map[1][page] == INVALID) Fault = 010000; - else if (paddr < MEMSIZE) M[paddr] = data; - break; - case 2: - page = (addr >> 10) & 037; - paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777); - if (((Map[2][page] & 0100000) && (MapStat & 020)) || Map[2][page] == INVALID) Fault = 010000; - else if (paddr < MEMSIZE) M[paddr] = data; - break; - case 6: - page = (addr >> 10) & 037; - paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777); - if (((Map[6][page] & 0100000) && (MapStat & 020)) || Map[6][page] == INVALID) Fault = 010000; - else if (paddr < MEMSIZE) M[paddr] = data; - break; - case 7: - page = (addr >> 10) & 037; - paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777); - if (((Map[7][page] & 0100000) && (MapStat & 020)) || Map[7][page] == INVALID) Fault = 010000; - else if (paddr < MEMSIZE) M[paddr] = data; - break; - default: - M[addr] = data; - break; - } - return (data); -} - -#if 0 -int16 GetDCHMap(int32 map, int32 addr) -{ - uint32 paddr; - if (!(MapStat & 02)) return M[addr]; - paddr = ((Map[map][(addr >> 10) & 037] & PAGEMASK) << 10) | (addr & 001777); - if (paddr < MEMSIZE) - return M[paddr]; - return (0); -} - -int16 PutDCHMap(int32 map, int32 addr, int16 data) -{ - uint32 paddr; - if (!(MapStat & 02)) { - M[addr] = data; - return (data); - } - paddr = ((Map[map][(addr >> 10) & 037] & PAGEMASK) << 10) | (addr & 001777); - if (paddr < MEMSIZE) - M[paddr] = data; - return (data); -} -#endif - -/* Given a map number and a logical, returns the physical address, unless - the map is not active, in which case logical = physical. This is - used primarily by the I/O routines to map data channel read/writes. -*/ - -int32 MapAddr(int32 map, int32 addr) -{ - int32 paddr; - if ((map == 0 || map > 2) && !(MapStat & 02)) return addr; - if (map > 0 && map < 3 && Usermap == 0) return addr; - paddr = ((Map[map][(addr >> 10) & 037] & PAGEMASK) << 10) | (addr & 001777); - return paddr; -} - -/* Loads a word into the Eclipse Maps */ - -int32 LoadMap(int32 w) -{ - int32 m; - - m = (w >> 10) & 037; - switch ((MapStat >> 7) & 07) { - case 0: /* Load user A Map */ - Map[1][m] = w & MAPMASK; - break; - case 1: /* Load user C Map */ - Map[6][m] = w & MAPMASK; - break; - case 2: /* Load user B Map */ - Map[2][m] = w & MAPMASK; - break; - case 3: /* Load user D Map */ - Map[7][m] = w & MAPMASK; - break; - case 4: /* Load DCH A Map */ - Map[0][m] = w & MAPMASK; - break; - case 5: /* Load DCH C Map */ - Map[4][m] = w; - break; - case 6: /* Load DCH B Map */ - Map[3][m] = w; - break; - case 7: /* Load DCH D Map */ - Map[5][m] = w; - break; - default: - break; - } - return 0; -} - -/* Displays an error on a unimplemented (in this sim) instr. */ - -int32 unimp(int32 PC) -{ - if (Debug_Flags) - printf("\n\r\007<<>>\n\r", PC - 1, GetMap(PC - 1)); - return 0; -} - -/* New priority mask out */ - -void mask_out (int32 newmask) -{ -int32 i; - -dev_disable = 0; -for (i = DEV_LOW; i <= DEV_HIGH; i++) { - if (newmask & dev_table[i].pi) - dev_disable = dev_disable | dev_table[i].mask; } -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -return; -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -int_req = int_req & ~INT_ION; -pimask = 0; -dev_disable = 0; -pwr_low = 0; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & 0177777; -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -M[addr] = val & 0177777; -return SCPE_OK; -} - -/* Alter memory size */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; -if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_OK; -MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; -return SCPE_OK; -} - -/* MAP device services */ - -t_stat map_svc (UNIT *uptr) -{ -return SCPE_OK; -} - -/* Map examine */ - -t_stat map_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -if ((addr & 077) >= 037 || addr > 737) return SCPE_NXM; -uptr->u4 = -2; /* signal to print_sys in eclipse_sys.c: do not map */ -if (vptr != NULL) *vptr = Map[(addr >> 6) & 3][addr & 037] & 0177777; -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat map_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -if ((addr & 077) >= 037 || addr > 0737) return SCPE_NXM; -uptr->u4 = -2; /* signal to print_sys in eclipse_sys.c: do not map */ -Map[(addr >> 6) & 3][addr & 037] = val & 0177777; -return SCPE_OK; -} - -/* Bootstrap routine for CPU */ - -#define BOOT_START 00000 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) - -static const int32 boot_rom[] = { - 062677, /* IORST ;Reset all I/O */ - 060477, /* READS 0 ;Read SR into AC0 */ - 024026, /* LDA 1,C77 ;Get dev mask */ - 0107400, /* AND 0,1 ;Isolate dev code */ - 0124000, /* COM 1,1 ;- device code - 1 */ - 010014, /* LOOP: ISZ OP1 ;Device code to all */ - 010030, /* ISZ OP2 ;I/O instructions */ - 010032, /* ISZ OP3 */ - 0125404, /* INC 1,1,SZR ;done? */ - 000005, /* JMP LOOP ;No, increment again */ - 030016, /* LDA 2,C377 ;place JMP 377 into */ - 050377, /* STA 2,377 ;location 377 */ - 060077, /* OP1: 060077 ;start device (NIOS 0) */ - 0101102, /* MOVL 0,0,SZC ;Test switch 0, low speed? */ - 000377, /* C377: JMP 377 ;no - jmp 377 & wait */ - 004030, /* LOOP2: JSR GET+1 ;Get a frame */ - 0101065, /* MOVC 0,0,SNR ;is it non-zero? */ - 000017, /* JMP LOOP2 ;no, ignore */ - 004027, /* LOOP4: JSR GET ;yes, get full word */ - 046026, /* STA 1,@C77 ;store starting at 100 */ - /* ;2's complement of word ct */ - 010100, /* ISZ 100 ;done? */ - 000022, /* JMP LOOP4 ;no, get another */ - 000077, /* C77: JMP 77 ;yes location ctr and */ - /* ;jmp to last word */ - 0126420, /* GET: SUBZ 1,1 ; clr AC1, set carry */ - /* OP2: */ - 063577, /* LOOP3: 063577 ;done? (SKPDN 0) - 1 */ - 000030, /* JMP LOOP3 ;no -- wait */ - 060477, /* OP3: 060477 ;y--read in ac0 (DIAS 0,0) */ - 0107363, /* ADDCS 0,1,SNC ;add 2 frames swapped - got 2nd? */ - 000030, /* JMP LOOP3 ;no go back after it */ - 0125300, /* MOVS 1,1 ;yes swap them */ - 001400, /* JMP 0,3 ;rtn with full word */ - 0 /* 0 ;padding */ -}; - -t_stat cpu_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} - -int32 Debug_Entry(int32 PC, int32 inst, int32 inst2, int32 AC0, int32 AC1, int32 AC2, int32 AC3, int32 flags) -{ - hpc[hnext] = PC & 0xffff; - hinst[hnext] = inst & 0xffff; - hinst2[hnext] = inst2 & 0xffff; - hac0[hnext] = AC0 & 0xffff; - hac1[hnext] = AC1 & 0xffff; - hac2[hnext] = AC2 & 0xffff; - hac3[hnext] = AC3 & 0xffff; - hflags[hnext] = flags & 0xffff; - hnext++; - if (hnext >= hmax) { - hwrap = 1; - hnext = 0; - } - return 0; -} - -int32 Debug_Dump(UNIT *uptr, int32 val, char *cptr, void *desc) -{ - char debmap[4], debion[4]; - t_value simeval[20]; - int debcar; - FILE *Dumpf; - int start, end, ctr; - int count = 0; - - if (!Debug_Flags || Debug_Flags & 0100000) { - printf("History was not logged. Deposit a non-zero value\n"); - printf("in DEBUG with bit 0 being 1 to build history.\n"); - return SCPE_OK; - } - Dumpf = fopen("history.log", "w"); - if (!hwrap) { - start = 0; - end = hnext; - } else { - start = hnext; - end = hnext - 1; - if (end < 0) end = hmax; - } - ctr = start; - while (1) { - if (ctr == end) - break; - count++; - strcpy(debion, " "); - strcpy(debmap, " "); - debcar = 0; - if (hflags[ctr] & 0x80) { - fprintf(Dumpf, "--------- Interrupt %o (%o) to %6o ---------\n", - hinst[ctr], hac0[ctr], hac1[ctr]); - } else { - if (hflags[ctr] & 0x01) debcar = 1; - if (hflags[ctr] & 0x02) strcpy(debion, "I"); - if (hflags[ctr] & 0x04) strcpy(debmap, "A"); - if (hflags[ctr] & 0x08) strcpy(debmap, "B"); - if (hflags[ctr] & 0x10) strcpy(debmap, "C"); - if (hflags[ctr] & 0x20) strcpy(debmap, "D"); - fprintf(Dumpf, "%s%s%06o acs: %06o %06o %06o %06o %01o ", - debion, debmap, hpc[ctr], hac0[ctr], hac1[ctr], hac2[ctr], - hac3[ctr], debcar); - simeval[0] = hinst[ctr]; - simeval[1] = hinst2[ctr]; - fprint_sym (Dumpf, hpc[ctr], simeval, NULL, SWMASK('M')); - fprintf(Dumpf, "\n"); - } - ctr++; - if (ctr > hmax) - ctr = 0; - } - fclose(Dumpf); - printf("\n%d records dumped to history.log\n", count); - return SCPE_OK; -} - -/* Build dispatch table */ - -t_stat build_devtab (void) -{ -DEVICE *dptr; -DIB *dibp; -int32 i, dn; - -for (i = 0; i < 64; i++) { /* clr dev_table */ - dev_table[i].mask = 0; - dev_table[i].pi = 0; - dev_table[i].routine = NULL; } -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ - if (dibp = (DIB *) dptr->ctxt) { /* get DIB */ - dn = dibp->dnum; /* get dev num */ - dev_table[dn].mask = dibp->mask; /* copy entries */ - dev_table[dn].pi = dibp->pi; - dev_table[dn].routine = dibp->routine; } } -return SCPE_OK; -} diff --git a/NOVA/eclipse_tt.c b/NOVA/eclipse_tt.c deleted file mode 100644 index 972d80f7..00000000 --- a/NOVA/eclipse_tt.c +++ /dev/null @@ -1,395 +0,0 @@ -/* eclipse_tt.c: Eclipse console terminal simulator - - Copyright (c) 1998-2003, Charles E Owen - Portions copyright (c) 1993-2002, Robert M Supnik - Written by Charles Owen, used by gracious permission - Commercial use prohibited - - tti terminal input - tto terminal output - - 25-Apr-03 RMS Revised for extended file support - 03-Oct-02 RMS Added DIBs - 30-May-02 RMS Widened POS to 32b - 28-Jan-02 RMS Cleaned up compiler warnings -*/ - -#include "nova_defs.h" - -#define UNIT_V_DASHER (UNIT_V_UF + 0) /* Dasher mode */ -#define UNIT_DASHER (1 << UNIT_V_DASHER) - -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 tti (int32 pulse, int32 code, int32 AC); -int32 tto (int32 pulse, int32 code, int32 AC); -t_stat tti_svc (UNIT *uptr); -t_stat tto_svc (UNIT *uptr); -t_stat tti_reset (DEVICE *dptr); -t_stat tto_reset (DEVICE *dptr); -t_stat ttx_setmod (UNIT *uptr, int32 value, char *cptr, void *desc); -void translate_in(); -int32 translate_out(int32 c); -int32 putseq(char *seq); - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit descriptor - tti_reg TTI register list - ttx_mod TTI/TTO modifiers list -*/ - -DIB tti_dib = { DEV_TTI, INT_TTI, PI_TTI, &tti }; - -UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }; - -REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_TTI) }, - { FLDATA (DONE, dev_done, INT_V_TTI) }, - { FLDATA (DISABLE, dev_disable, INT_V_TTI) }, - { FLDATA (INT, int_req, INT_V_TTI) }, - { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB ttx_mod[] = { - { UNIT_DASHER, 0, "ANSI", "ANSI", &ttx_setmod }, - { UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx_setmod }, - { 0 } }; - -DEVICE tti_dev = { - "TTI", &tti_unit, tti_reg, ttx_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tti_reset, - NULL, NULL, NULL, - &tti_dib, 0 }; - -/* TTO data structures - - tto_dev TTO device descriptor - tto_unit TTO unit descriptor - tto_reg TTO register list -*/ - -DIB tto_dib = { DEV_TTO, INT_TTO, PI_TTO, &tto }; - -UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT }; - -REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_TTO) }, - { FLDATA (DONE, dev_done, INT_V_TTO) }, - { FLDATA (DISABLE, dev_disable, INT_V_TTO) }, - { FLDATA (INT, int_req, INT_V_TTO) }, - { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -DEVICE tto_dev = { - "TTO", &tto_unit, tto_reg, ttx_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto_reset, - NULL, NULL, NULL, - &tto_dib, 0 }; - - - -/* Terminal input: IOT routine */ - -int32 tti (int32 pulse, int32 code, int32 AC) -{ -int32 iodata; - -iodata = (code == ioDIA)? tti_unit.buf & 0377: 0; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_TTI; /* set busy */ - dev_done = dev_done & ~INT_TTI; /* clear done, int */ - int_req = int_req & ~INT_TTI; - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_TTI; /* clear busy */ - dev_done = dev_done & ~INT_TTI; /* clear done, int */ - int_req = int_req & ~INT_TTI; - break; } /* end switch */ -return iodata; -} - -/* Unit service */ - -t_stat tti_svc (UNIT *uptr) -{ -int32 temp; - -sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ -if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ -tti_unit.buf = temp & 0177; -/* --- BEGIN MODIFIED CODE --- */ -if (tti_unit.flags & UNIT_DASHER) /* translate input */ - translate_in(); -/* --- END MODIFIED CODE --- */ -dev_busy = dev_busy & ~INT_TTI; /* clear busy */ -dev_done = dev_done | INT_TTI; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -tti_unit.pos = tti_unit.pos + 1; -return SCPE_OK; -} - -/* -------------------- BEGIN INSERTION -----------------------*/ - -int curpos = 0; /* used by translate_out() */ -int row = 0, col = 0; /* ditto - for cursor positioning */ -int spec200 = 0; /* signals next char is 'special' */ - -/* Translation: Vt100 input to D200 keycodes. */ - -void translate_in() -{ - char rev = 0; - - if (tti_unit.buf == '\r') - rev = '\n'; - if (tti_unit.buf == '\n') - rev = '\r'; - if (rev) - tti_unit.buf = rev; -} - -/* -------------------- END INSERTION -----------------------*/ - -/* Reset routine */ - -t_stat tti_reset (DEVICE *dptr) -{ -tti_unit.buf = 0; -dev_busy = dev_busy & ~INT_TTI; /* clear busy */ -dev_done = dev_done & ~INT_TTI; /* clear done, int */ -int_req = int_req & ~INT_TTI; -sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ -return SCPE_OK; -} - -/* Terminal output: IOT routine */ - -int32 tto (int32 pulse, int32 code, int32 AC) -{ -if (code == ioDOA) tto_unit.buf = AC & 0377; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_TTO; /* set busy */ - dev_done = dev_done & ~INT_TTO; /* clear done, int */ - int_req = int_req & ~INT_TTO; - sim_activate (&tto_unit, tto_unit.wait); /* activate unit */ - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_TTO; /* clear busy */ - dev_done = dev_done & ~INT_TTO; /* clear done, int */ - int_req = int_req & ~INT_TTO; - sim_cancel (&tto_unit); /* deactivate unit */ - break; } /* end switch */ -return 0; -} - -/* Unit service */ - -t_stat tto_svc (UNIT *uptr) -{ -int32 c, temp; - -dev_busy = dev_busy & ~INT_TTO; /* clear busy */ -dev_done = dev_done | INT_TTO; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -c = tto_unit.buf & 0177; -/* --- BEGIN MODIFIED CODE --- */ -if (tto_unit.flags & UNIT_DASHER) { - if ((temp = translate_out(c)) != SCPE_OK) return temp; -} else { - if ((temp = sim_putchar (c)) != SCPE_OK) return temp; - tto_unit.pos = tto_unit.pos + 1; -} -/* --- END MODIFIED CODE --- */ -return SCPE_OK; -} - -/* -------------------- BEGIN INSERTION -----------------------*/ - -/* Translation routine - D200 screen controls to VT-100 controls. */ - -int32 translate_out(int32 c) -{ - int32 temp; - char outstr[32]; - - if (spec200 == 1) { /* Special terminal control seq */ - spec200 = 0; - switch (c) { - case 'C': /* read model ID */ - return SCPE_OK; - case 'E': /* Reverse video off */ - return SCPE_OK; - case 'D': /* Reverse video on */ - return SCPE_OK; - default: - return SCPE_OK; - } - } - if (curpos == 1) { /* 2nd char of cursor position */ - col = c & 0x7f; - curpos++; - return (SCPE_OK); - } - if (curpos == 2) { /* 3rd char of cursor position */ - row = c & 0x7f; - curpos = 0; - sprintf(outstr, "\033[%d;%dH", row+1, col+1); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - return (SCPE_OK); - } - switch (c) { /* Single-char command or data */ - case 003: /* Blink enable */ - break; - case 004: /* Blink disable */ - break; - case 005: /* Read cursor address */ - break; - case 010: /* Cursor home */ - sprintf(outstr, "\033[1;1H"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - row = col = 0; - return (SCPE_OK); - case 012: /* Newline */ - if ((temp = sim_putchar('\r')) != SCPE_OK) return temp; - tto_unit.pos += 1; - if ((temp = sim_putchar(c)) != SCPE_OK) return temp; - tto_unit.pos += 1; - col = 1; - row++; - if (row > 24) row = 1; - return (SCPE_OK); - case 013: /* Erase EOL */ - sprintf(outstr, "\033[K"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - return (SCPE_OK); - case 014: /* Erase screen */ - sprintf(outstr, "\033[1;1H\033[2J"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - row = col = 0; - return (SCPE_OK); - case 015: /* CR */ - if ((temp = sim_putchar(c)) != SCPE_OK) return temp; - tto_unit.pos += 1; - col = 1; - return (SCPE_OK); - case 016: /* Blink On */ - sprintf(outstr, "\033[5m"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - return (SCPE_OK); - case 017: /* Blink off */ - sprintf(outstr, "\033[25m"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - return (SCPE_OK); - case 020: /* Write cursor address */ - curpos = 1; - return SCPE_OK; - case 024: /* underscore on */ - sprintf(outstr, "\033[4m"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - return (SCPE_OK); - case 025: /* underscore off */ - sprintf(outstr, "\033[24m"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - return (SCPE_OK); - break; - case 027: /* cursor up */ - sprintf(outstr, "\033[A"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - row--; - if (row < 1) row = 24; - return (SCPE_OK); - case 030: /* cursor right */ - sprintf(outstr, "\033[C"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - col++; - if (col > 80) { - col = 1; - row++; - if (row > 24) row = 1; - } - return (SCPE_OK); - case 031: /* Cursor left */ - sprintf(outstr, "\033[D"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - tto_unit.pos += 1; - col--; - if (col < 1) { - col = 80; - row--; - if (row < 1) row = 24; - } - return (SCPE_OK); - case 032: /* Cursor down */ - sprintf(outstr, "\033[B"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - row++; - if (row > 24) row = 1; - return (SCPE_OK); - case 034: /* Dim on */ - sprintf(outstr, "\033[22m"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - return (SCPE_OK); - case 035: /* Dim off */ - sprintf(outstr, "\033[1m"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - return (SCPE_OK); - case 036: /* Special sequence */ - spec200 = 1; - return SCPE_OK; - default: /* ..A character of data */ - if ((temp = sim_putchar(c)) != SCPE_OK) return temp; - tto_unit.pos += 1; - col++; - if (col > 80) { - col = 1; - row++; - if (row > 24) row = 24; - } - return (SCPE_OK); - } - return SCPE_OK; -} - -int32 putseq(char *seq) -{ - int i, len, temp; - - len = strlen(seq); - for (i = 0; i < len; i++) { - if ((temp = sim_putchar(seq[i])) != SCPE_OK) - return temp; - tto_unit.pos += 1; - } - return SCPE_OK; -} - -/* -------------------- END INSERTION -----------------------*/ - -/* Reset routine */ - -t_stat tto_reset (DEVICE *dptr) -{ -tto_unit.buf = 0; -dev_busy = dev_busy & ~INT_TTO; /* clear busy */ -dev_done = dev_done & ~INT_TTO; /* clear done, int */ -int_req = int_req & ~INT_TTO; -sim_cancel (&tto_unit); /* deactivate unit */ -return SCPE_OK; -} - -t_stat ttx_setmod (UNIT *uptr, int32 value, char *cptr, void *desc) -{ -tti_unit.flags = (tti_unit.flags & ~UNIT_DASHER) | value; -tto_unit.flags = (tto_unit.flags & ~UNIT_DASHER) | value; -return SCPE_OK; -} diff --git a/NOVA/nova_clk.c b/NOVA/nova_clk.c deleted file mode 100644 index 315e4050..00000000 --- a/NOVA/nova_clk.c +++ /dev/null @@ -1,163 +0,0 @@ -/* nova_clk.c: NOVA real-time clock simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - clk real-time clock - - 01-Mar-03 RMS Added SET/SHOW CLK FREQ support - 03-Oct-02 RMS Added DIB - 17-Sep-01 RMS Added terminal multiplexor support - 17-Mar-01 RMS Moved function prototype - 05-Mar-01 RMS Added clock calibration - 24-Sep-97 RMS Fixed bug in unit service (found by Charles Owen) -*/ - -#include "nova_defs.h" - -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 clk_sel = 0; /* selected freq */ -int32 clk_time[4] = { 16000, 100000, 10000, 1000 }; /* freq table */ -int32 clk_tps[4] = { 60, 10, 100, 1000 }; /* ticks per sec */ -int32 clk_adj[4] = { 1, -5, 2, 20 }; /* tmxr adjust */ -int32 tmxr_poll = 16000; /* tmxr poll */ - -int32 clk (int32 pulse, int32 code, int32 AC); -t_stat clk_svc (UNIT *uptr); -t_stat clk_reset (DEVICE *dptr); -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc); - -/* CLK data structures - - clk_dev CLK device descriptor - clk_unit CLK unit descriptor - clk_reg CLK register list -*/ - -DIB clk_dib = { DEV_CLK, INT_CLK, PI_CLK, &clk }; - -UNIT clk_unit = { UDATA (&clk_svc, 0, 0) }; - -REG clk_reg[] = { - { ORDATA (SELECT, clk_sel, 2) }, - { FLDATA (BUSY, dev_busy, INT_V_CLK) }, - { FLDATA (DONE, dev_done, INT_V_CLK) }, - { FLDATA (DISABLE, dev_disable, INT_V_CLK) }, - { FLDATA (INT, int_req, INT_V_CLK) }, - { DRDATA (TIME0, clk_time[0], 24), REG_NZ + PV_LEFT }, - { DRDATA (TIME1, clk_time[1], 24), REG_NZ + PV_LEFT }, - { DRDATA (TIME2, clk_time[2], 24), REG_NZ + PV_LEFT }, - { DRDATA (TIME3, clk_time[3], 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS0, clk_tps[0], 6), PV_LEFT + REG_HRO }, - { NULL } }; - -MTAB clk_mod[] = { - { MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "LINE", NULL, - NULL, &clk_show_freq, NULL }, - { 0 } }; - -DEVICE clk_dev = { - "CLK", &clk_unit, clk_reg, clk_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &clk_reset, - NULL, NULL, NULL, - &clk_dib, 0 }; - -/* IOT routine */ - -int32 clk (int32 pulse, int32 code, int32 AC) -{ -if (code == ioDOA) { /* DOA */ - clk_sel = AC & 3; /* save select */ - sim_rtc_init (clk_time[clk_sel]); } /* init calibr */ -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_CLK; /* set busy */ - dev_done = dev_done & ~INT_CLK; /* clear done, int */ - int_req = int_req & ~INT_CLK; - if (!sim_is_active (&clk_unit)) /* not running? */ - sim_activate (&clk_unit, /* activate */ - sim_rtc_init (clk_time[clk_sel])); /* init calibr */ - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_CLK; /* clear busy */ - dev_done = dev_done & ~INT_CLK; /* clear done, int */ - int_req = int_req & ~INT_CLK; - sim_cancel (&clk_unit); /* deactivate unit */ - break; } /* end switch */ -return 0; -} - -/* Unit service */ - -t_stat clk_svc (UNIT *uptr) -{ -int32 t; - -dev_done = dev_done | INT_CLK; /* set done */ -dev_busy = dev_busy & ~INT_CLK; /* clear busy */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -t = sim_rtc_calb (clk_tps[clk_sel]); /* calibrate delay */ -sim_activate (&clk_unit, t); /* reactivate unit */ -if (clk_adj[clk_sel] > 0) /* clk >= 60Hz? */ - tmxr_poll = t * clk_adj[clk_sel]; /* poll is longer */ -else tmxr_poll = t / (-clk_adj[clk_sel]); /* poll is shorter */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat clk_reset (DEVICE *dptr) -{ -clk_sel = 0; -dev_busy = dev_busy & ~INT_CLK; /* clear busy */ -dev_done = dev_done & ~INT_CLK; /* clear done, int */ -int_req = int_req & ~INT_CLK; -sim_cancel (&clk_unit); /* deactivate unit */ -tmxr_poll = clk_time[0]; /* poll is default */ -return SCPE_OK; -} - -/* Set line frequency */ - -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; -clk_tps[0] = val; -return SCPE_OK; -} - -/* Show line frequency */ - -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, (clk_tps[0] == 50)? "50Hz": "60Hz"); -return SCPE_OK; -} diff --git a/NOVA/nova_cpu.c b/NOVA/nova_cpu.c deleted file mode 100644 index 864786d7..00000000 --- a/NOVA/nova_cpu.c +++ /dev/null @@ -1,900 +0,0 @@ -/* nova_cpu.c: NOVA CPU simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - cpu Nova central processor - - 19-Jan-03 RMS Changed CMASK to CDMASK for Apple Dev Kit conflict - 03-Oct-02 RMS Added DIB infrastructure - 30-Dec-01 RMS Added old PC queue - 07-Dec-01 RMS Revised to use breakpoint package - 30-Nov-01 RMS Added extended SET/SHOW support - 10-Aug-01 RMS Removed register in declarations - 17-Jul-01 RMS Moved function prototype - 26-Apr-01 RMS Added device enable/disable support - 05-Mar-01 RMS Added clock calibration - 22-Dec-00 RMS Added Bruce Ray's second terminal - 15-Dec-00 RMS Added Charles Owen's CPU bootstrap - 08-Dec-00 RMS Changes from Bruce Ray - -- fixed trap test to include Nova 3 - -- fixed DIV and DIVS divide by 0 - -- fixed RETN to set SP from FP - -- fixed IORST to preserve carry - -- added "secret" Nova 4 PSHN/SAVEN instructions - -- added plotter support - 15-Oct-00 RMS Fixed bug in MDV test, added stack, byte, trap instructions - 14-Apr-98 RMS Changed t_addr to unsigned - 15-Sep-97 RMS Added read and write breakpoints - - The register state for the NOVA CPU is: - - AC[0:3]<0:15> general registers - C carry flag - PC<0:14> program counter - - The NOVA has three instruction formats: memory reference, I/O transfer, - and operate. The memory reference format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0| op | AC |in| mode| displacement | memory reference - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <0:4> mnemonic action - - 00000 JMP PC = MA - 00001 JMS AC3 = PC, PC = MA - 00010 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0 - 00011 DSZ M[MA] = M[MA] - 1, skip if M[MA] == 0 - 001'n LDA ACn = M[MA] - 010'n STA M[MA] = ACn - - <5:7> mode action - - 000 page zero direct MA = zext (IR<8:15>) - 001 PC relative direct MA = PC + sext (IR<8:15>) - 010 AC2 relative direct MA = AC2 + sext (IR<8:15>) - 011 AC3 relative direct MA = AC3 + sext (IR<8:15>) - 100 page zero indirect MA = M[zext (IR<8:15>)] - 101 PC relative indirect MA = M[PC + sext (IR<8:15>)] - 110 AC2 relative indirect MA = M[AC2 + sext (IR<8:15>)] - 111 AC3 relative indirect MA = M[AC3 + sext (IR<8:15>)] - - Memory reference instructions can access an address space of 32K words. - An instruction can directly reference the first 256 words of memory - (called page zero), as well as 256 words relative to the PC, AC2, or - AC3; it can indirectly access all 32K words. If an indirect address - is in locations 00020-00027, the indirect address is incremented and - rewritten to memory before use; if in 00030-00037, decremented and - rewritten. -*/ - -/* The I/O transfer format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 1 1| AC | opcode |pulse| device | I/O transfer - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The IOT instruction sends the opcode, pulse, and specified AC to the - specified I/O device. The device may accept data, provide data, - initiate or cancel operations, or skip on status. - - The operate format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1|srcAC|dstAC| opcode |shift|carry|nl| skip | operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - \______/ \___/ \___/ | | | | - | | | | | | +--- reverse skip sense - | | | | | +--- skip if C == 0 - | | | | +--- skip if result == 0 - | | | +--- don't load result - | | +--- carry in (load as is, - | | set to Zero, - | | set to One, - | | load Complement) - | +--- shift (none, - | left one, - | right one, - | byte swap) - +--- operation (complement, - negate, - move, - increment, - add complement, - subtract, - add, - and) - - The operate instruction can be microprogrammed to perform operations - on the source and destination AC's and the Carry flag. - - Some notes from Bruce Ray: - - 1. DG uses the value of the autoindex location -before- the - modification to determine if additional indirect address - levels are to be performed. Most DG emulators conform to - this standard, but some vendor machines (i.e. Point 4 Mark 8) - do not. - - 2. Infinite indirect references may occur on unmapped systems - and can "hang" the hardware. Some DG diagnostics perform - 10,000s of references during a single instruction. - - 3. Nova 3 adds the following instructions to the standard Nova - instruction set: - - trap instructions - stack push/pop instructions - save/return instructions - stack register manipulation instructions - unsigned MUL/DIV - - 4. Nova 4 adds the following instructions to the Nova 3 instruction - set: - - signed MUL/DIV - load/store byte - secret (undocumented) stack instructions [PSHN, SAVN] - - 5. Nova, Nova 3 and Nova 4 unsigned mul/div instructions are the - same instruction code values on all machines. -*/ - -/* This routine is the instruction decode routine for the NOVA. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - breakpoint encountered - infinite indirection loop - unknown I/O device and STOP_DEV flag set - I/O error in I/O simulator - - 2. Interrupts. Interrupts are maintained by four parallel variables: - - dev_done device done flags - dev_disable device interrupt disable flags - dev_busy device busy flags - int_req interrupt requests - - In addition, int_req contains the interrupt enable and ION pending - flags. If ION and ION pending are set, and at least one interrupt - request is pending, then an interrupt occurs. Note that the 16b PIO - mask must be mapped to the simulator's device bit mapping. - - 3. Non-existent memory. On the NOVA, reads to non-existent memory - return zero, and writes are ignored. In the simulator, the - largest possible memory is instantiated and initialized to zero. - Thus, only writes need be checked against actual memory size. - - 4. Adding I/O devices. These modules must be modified: - - nova_defs.h add interrupt request definition - nova_sys.c add sim_devices entry -*/ - -#include "nova_defs.h" - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC - -#define INCA(x) (((x) + 1) & AMASK) -#define DECA(x) (((x) - 1) & AMASK) -#define SEXT(x) (((x) & SIGN)? ((x) | ~DMASK): (x)) -#define STK_CHECK(x,y) if (((x) & 0377) < (y)) int_req = int_req | INT_STK -#define IND_STEP(x) M[x] & A_IND; \ - if (((x) & 077770) == AUTO_INC) \ - M[x] = (M[x] + 1) & 0177777; \ - else if (((x) & 077770) == AUTO_DEC) \ - M[x] = (M[x] - 1) & 0177777; \ - x = M[x] & AMASK - -#define UNIT_V_MDV (UNIT_V_UF + 0) /* MDV present */ -#define UNIT_V_STK (UNIT_V_UF + 1) /* stack instr */ -#define UNIT_V_BYT (UNIT_V_UF + 2) /* byte instr */ -#define UNIT_V_MSIZE (UNIT_V_UF + 3) /* dummy mask */ -#define UNIT_MDV (1 << UNIT_V_MDV) -#define UNIT_STK (1 << UNIT_V_STK) -#define UNIT_BYT (1 << UNIT_V_BYT) -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) -#define UNIT_IOPT (UNIT_MDV | UNIT_STK | UNIT_BYT) -#define UNIT_NOVA3 (UNIT_MDV | UNIT_STK) -#define UNIT_NOVA4 (UNIT_MDV | UNIT_STK | UNIT_BYT) - -uint16 M[MAXMEMSIZE] = { 0 }; /* memory */ -int32 AC[4] = { 0 }; /* accumulators */ -int32 C = 0; /* carry flag */ -int32 saved_PC = 0; /* program counter */ -int32 SP = 0; /* stack pointer */ -int32 FP = 0; /* frame pointer */ -int32 SR = 0; /* switch register */ -int32 dev_done = 0; /* device done flags */ -int32 dev_busy = 0; /* device busy flags */ -int32 dev_disable = 0; /* int disable flags */ -int32 int_req = 0; /* interrupt requests */ -int32 pimask = 0; /* priority int mask */ -int32 pwr_low = 0; /* power fail flag */ -int32 ind_max = 16; /* iadr nest limit */ -int32 stop_dev = 0; /* stop on ill dev */ -uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -struct ndev dev_table[64]; /* dispatch table */ - -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern DEVICE *sim_devices[]; - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_boot (int32 unitno, DEVICE *dptr); -t_stat build_devtab (void); - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifiers list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK + UNIT_MDV, - MAXMEMSIZE) }; - -REG cpu_reg[] = { - { ORDATA (PC, saved_PC, 15) }, - { ORDATA (AC0, AC[0], 16) }, - { ORDATA (AC1, AC[1], 16) }, - { ORDATA (AC2, AC[2], 16) }, - { ORDATA (AC3, AC[3], 16) }, - { FLDATA (C, C, 16) }, - { ORDATA (SP, SP, 16) }, - { ORDATA (FP, FP, 16) }, - { ORDATA (SR, SR, 16) }, - { ORDATA (PI, pimask, 16) }, - { FLDATA (ION, int_req, INT_V_ION) }, - { FLDATA (ION_DELAY, int_req, INT_V_NO_ION_PENDING) }, - { FLDATA (STKOVF, int_req, INT_V_STK) }, - { FLDATA (PWR, pwr_low, 0) }, - { ORDATA (INT, int_req, INT_V_ION+1), REG_RO }, - { ORDATA (BUSY, dev_busy, INT_V_ION+1), REG_RO }, - { ORDATA (DONE, dev_done, INT_V_ION+1), REG_RO }, - { ORDATA (DISABLE, dev_disable, INT_V_ION+1), REG_RO }, - { FLDATA (STOP_DEV, stop_dev, 0) }, - { DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT }, - { BRDATA (PCQ, pcq, 8, 16, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_IOPT, UNIT_NOVA3, "NOVA3", "NOVA3", NULL }, - { UNIT_IOPT, UNIT_NOVA4, "NOVA4", "NOVA4", NULL }, - { UNIT_IOPT, UNIT_MDV, "MDV", "MDV", NULL }, - { UNIT_IOPT, 0, "none", "NONE", NULL }, - { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, - { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, - { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size }, - { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, - { UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size }, - { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size }, - { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size }, - { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, 15, 1, 8, 16, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -t_stat sim_instr (void) -{ -extern int32 sim_interval; -int32 PC, IR, i; -t_stat reason; -void mask_out (int32 mask); -extern int32 clk_sel, clk_time[4]; - -/* Restore register state */ - -if (build_devtab () != SCPE_OK) return SCPE_IERR; /* build dispatch */ -PC = saved_PC & AMASK; /* load local PC */ -C = C & CBIT; -mask_out (pimask); /* reset int system */ -reason = 0; -sim_rtc_init (clk_time[clk_sel]); /* init calibration */ - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } - -if (int_req > INT_PENDING) { /* interrupt? */ - int32 MA, indf; - int_req = int_req & ~INT_ION; /* intr off */ - PCQ_ENTRY; /* save old PC */ - M[INT_SAV] = PC; - if (int_req & INT_STK) { /* stack overflow? */ - int_req = int_req & ~INT_STK; /* clear */ - MA = STK_JMP; } /* jmp @3 */ - else MA = INT_JMP; /* intr: jmp @1 */ - for (i = 0, indf = 1; indf && (i < ind_max); i++) { - indf = IND_STEP (MA); } /* indirect loop */ - if (i >= ind_max) { - reason = STOP_IND_INT; - break; } - PC = MA; } /* end interrupt */ - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - -IR = M[PC]; /* fetch instr */ -PC = (PC + 1) & AMASK; -int_req = int_req | INT_NO_ION_PENDING; /* clear ION delay */ -sim_interval = sim_interval - 1; - -/* Operate instruction */ - -if (IR & I_OPR) { /* operate? */ - int32 src, srcAC, dstAC; - srcAC = I_GETSRC (IR); /* get reg decodes */ - dstAC = I_GETDST (IR); - switch (I_GETCRY (IR)) { /* decode carry */ - case 0: /* load */ - src = AC[srcAC] | C; - break; - case 1: /* clear */ - src = AC[srcAC]; - break; - case 2: /* set */ - src = AC[srcAC] | CBIT; - break; - case 3: /* complement */ - src = AC[srcAC] | (C ^ CBIT); - break; } /* end switch carry */ - switch (I_GETALU (IR)) { /* decode ALU */ - case 0: /* COM */ - src = src ^ DMASK; - break; - case 1: /* NEG */ - src = ((src ^ DMASK) + 1) & CDMASK; - break; - case 2: /* MOV */ - break; - case 3: /* INC */ - src = (src + 1) & CDMASK; - break; - case 4: /* ADC */ - src = ((src ^ DMASK) + AC[dstAC]) & CDMASK; - break; - case 5: /* SUB */ - src = ((src ^ DMASK) + AC[dstAC] + 1) & CDMASK; - break; - case 6: /* ADD */ - src = (src + AC[dstAC]) & CDMASK; - break; - case 7: /* AND */ - src = src & (AC[dstAC] | CBIT); - break; } /* end switch oper */ - -/* Operate, continued */ - - switch (I_GETSHF (IR)) { /* decode shift */ - case 0: /* nop */ - break; - case 1: /* L */ - src = ((src << 1) | (src >> 16)) & CDMASK; - break; - case 2: /* R */ - src = ((src >> 1) | (src << 16)) & CDMASK; - break; - case 3: /* S */ - src = ((src & 0377) << 8) | ((src >> 8) & 0377) | - (src & CBIT); - break; } /* end switch shift */ - switch (I_GETSKP (IR)) { /* decode skip */ - case 0: /* nop */ - if ((IR & I_NLD) && (cpu_unit.flags & UNIT_STK)) { - int32 indf, MA; /* Nova 3 or 4 trap */ - PCQ_ENTRY; /* save old PC */ - M[TRP_SAV] = (PC - 1) & AMASK; - MA = TRP_JMP; /* jmp @47 */ - for (i = 0, indf = 1; indf && (i < ind_max); i++) { - indf = IND_STEP (MA); } /* resolve ind */ - if (i >= ind_max) { /* indirect loop? */ - reason = STOP_IND_TRP; - break; } - PC = MA; /* new PC */ - break; } - break; - case 1: /* SKP */ - PC = (PC + 1) & AMASK; - break; - case 2: /* SZC */ - if (src < CBIT) PC = (PC + 1) & AMASK; - break; - case 3: /* SNC */ - if (src >= CBIT) PC = (PC + 1) & AMASK; - break; - case 4: /* SZR */ - if ((src & DMASK) == 0) PC = (PC + 1) & AMASK; - break; - case 5: /* SNR */ - if ((src & DMASK) != 0) PC = (PC + 1) & AMASK; - break; - case 6: /* SEZ */ - if (src <= CBIT) PC = (PC + 1) & AMASK; - break; - case 7: /* SBN */ - if (src > CBIT) PC = (PC + 1) & AMASK; - break; } /* end switch skip */ - if ((IR & I_NLD) == 0) { /* load? */ - AC[dstAC] = src & DMASK; - C = src & CBIT; } /* end if load */ - } /* end if operate */ - -/* Memory reference instructions */ - -else if (IR < 060000) { /* mem ref? */ - int32 src, MA, indf; - MA = I_GETDISP (IR); /* get disp */ - switch (I_GETMODE (IR)) { /* decode mode */ - case 0: /* page zero */ - break; - case 1: /* PC relative */ - if (MA & DISPSIGN) MA = 077400 | MA; - MA = (MA + PC - 1) & AMASK; - break; - case 2: /* AC2 relative */ - if (MA & DISPSIGN) MA = 077400 | MA; - MA = (MA + AC[2]) & AMASK; - break; - case 3: /* AC3 relative */ - if (MA & DISPSIGN) MA = 077400 | MA; - MA = (MA + AC[3]) & AMASK; - break; } /* end switch mode */ - - if (indf = IR & I_IND) { /* indirect? */ - for (i = 0; indf && (i < ind_max); i++) { /* count */ - indf = IND_STEP (MA); } /* resolve indirect */ - if (i >= ind_max) { /* too many? */ - reason = STOP_IND; - break; } } - -/* Memory reference, continued */ - - switch (I_GETOPAC (IR)) { /* decode op + AC */ - case 001: /* JSR */ - AC[3] = PC; - case 000: /* JMP */ - PCQ_ENTRY; - PC = MA; - break; - case 002: /* ISZ */ - src = (M[MA] + 1) & DMASK; - if (MEM_ADDR_OK (MA)) M[MA] = src; - if (src == 0) PC = (PC + 1) & AMASK; - break; - case 003: /* DSZ */ - src = (M[MA] - 1) & DMASK; - if (MEM_ADDR_OK (MA)) M[MA] = src; - if (src == 0) PC = (PC + 1) & AMASK; - break; - case 004: /* LDA 0 */ - AC[0] = M[MA]; - break; - case 005: /* LDA 1 */ - AC[1] = M[MA]; - break; - case 006: /* LDA 2 */ - AC[2] = M[MA]; - break; - case 007: /* LDA 3 */ - AC[3] = M[MA]; - break; - case 010: /* STA 0 */ - if (MEM_ADDR_OK (MA)) M[MA] = AC[0]; - break; - case 011: /* STA 1 */ - if (MEM_ADDR_OK (MA)) M[MA] = AC[1]; - break; - case 012: /* STA 2 */ - if (MEM_ADDR_OK (MA)) M[MA] = AC[2]; - break; - case 013: /* STA 3 */ - if (MEM_ADDR_OK (MA)) M[MA] = AC[3]; - break; } /* end switch */ - } /* end mem ref */ - -/* IOT instruction */ - -else { /* IOT */ - int32 dstAC, pulse, code, device, iodata; - dstAC = I_GETDST (IR); /* decode fields */ - code = I_GETIOT (IR); - pulse = I_GETPULSE (IR); - device = I_GETDEV (IR); - if (code == ioSKP) { /* IO skip? */ - switch (pulse) { /* decode IR<8:9> */ - case 0: /* skip if busy */ - if ((device == DEV_CPU)? (int_req & INT_ION) != 0: - (dev_busy & dev_table[device].mask) != 0) - PC = (PC + 1) & AMASK; - break; - case 1: /* skip if not busy */ - if ((device == DEV_CPU)? (int_req & INT_ION) == 0: - (dev_busy & dev_table[device].mask) == 0) - PC = (PC + 1) & AMASK; - break; - case 2: /* skip if done */ - if ((device == DEV_CPU)? pwr_low != 0: - (dev_done & dev_table[device].mask) != 0) - PC = (PC + 1) & AMASK; - break; - case 3: /* skip if not done */ - if ((device == DEV_CPU)? pwr_low == 0: - (dev_done & dev_table[device].mask) == 0) - PC = (PC + 1) & AMASK; - break; } /* end switch */ - } /* end IO skip */ - -/* IOT, continued */ - - else if (device == DEV_MDV) { - switch (code) { /* case on opcode */ - case ioNIO: /* frame ptr */ - if (cpu_unit.flags & UNIT_STK) { - if (pulse == iopN) FP = AC[dstAC] & AMASK; - if (pulse == iopC) AC[dstAC] = FP; } - break; - case ioDIA: /* load byte */ - if (cpu_unit.flags & UNIT_BYT) - AC[dstAC] = (M[AC[pulse] >> 1] >> - ((AC[pulse] & 1)? 0: 8)) & 0377; - else AC[dstAC] = 0; - break; - case ioDOA: /* stack ptr */ - if (cpu_unit.flags & UNIT_STK) { - if (pulse == iopN) SP = AC[dstAC] & AMASK; - if (pulse == iopC) AC[dstAC] = SP; } - break; - case ioDIB: /* push, pop */ - if (cpu_unit.flags & UNIT_STK) { - if (pulse == iopN) { /* push */ - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[dstAC]; - STK_CHECK (SP, 1); } - if (pulse == iopC) { /* pop */ - AC[dstAC] = M[SP]; - SP = DECA (SP); } - if ((pulse == iopP) && /* Nova 4 pshn */ - (cpu_unit.flags & UNIT_BYT)) { - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[dstAC]; - if (SP > M[042]) int_req = int_req | INT_STK ; - } - } - break; - case ioDOB: /* store byte */ - if (cpu_unit.flags & UNIT_BYT) { - int32 MA, val; - MA = AC[pulse] >> 1; - val = AC[dstAC] & 0377; - if (MEM_ADDR_OK (MA)) M[MA] = (AC[pulse] & 1)? - ((M[MA] & ~0377) | val): - ((M[MA] & 0377) | (val << 8)); } - break; - case ioDIC: /* save, return */ - if (cpu_unit.flags & UNIT_STK) { - if (pulse == iopN) { /* save */ - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[0]; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[1]; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[2]; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = FP; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = (C >> 1) | - (AC[3] & AMASK); - AC[3] = FP = SP & AMASK; - STK_CHECK (SP, 5); } - if (pulse == iopC) { /* retn */ - PCQ_ENTRY; - SP = FP & AMASK; - C = (M[SP] << 1) & CBIT; - PC = M[SP] & AMASK; - SP = DECA (SP); - AC[3] = M[SP]; - SP = DECA (SP); - AC[2] = M[SP]; - SP = DECA (SP); - AC[1] = M[SP]; - SP = DECA (SP); - AC[0] = M[SP]; - SP = DECA (SP); - FP = AC[3] & AMASK; } - if ((pulse == iopP) && /* Nova 4 saven */ - (cpu_unit.flags & UNIT_BYT)) { - int32 frameSz = M[PC] ; - PC = INCA (PC) ; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[0]; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[1]; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[2]; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = FP; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = (C >> 1) | - (AC[3] & AMASK); - AC[3] = FP = SP & AMASK ; - SP = (SP + frameSz) & AMASK ; - if (SP > M[042]) int_req = int_req | INT_STK; - } - } - break; - case ioDOC: - if ((dstAC == 2) && (cpu_unit.flags & UNIT_MDV)) { - uint32 mddata, uAC0, uAC1, uAC2; - uAC0 = (uint32) AC[0]; - uAC1 = (uint32) AC[1]; - uAC2 = (uint32) AC[2]; - if (pulse == iopP) { /* mul */ - mddata = (uAC1 * uAC2) + uAC0; - AC[0] = (mddata >> 16) & DMASK; - AC[1] = mddata & DMASK; } - if (pulse == iopS) { /* div */ - if ((uAC0 >= uAC2) || (uAC2 == 0)) C = CBIT; - else { - C = 0; - mddata = (uAC0 << 16) | uAC1; - AC[1] = mddata / uAC2; - AC[0] = mddata % uAC2; } } } - if ((dstAC == 3) && (cpu_unit.flags & UNIT_BYT)) { - int32 mddata; - if (pulse == iopC) { /* muls */ - mddata = (SEXT (AC[1]) * SEXT (AC[2])) + SEXT (AC[0]); - AC[0] = (mddata >> 16) & DMASK; - AC[1] = mddata & DMASK; } - if (pulse == iopN) { /* divs */ - if (AC[2] == 0) C = CBIT; - else { - mddata = (SEXT (AC[0]) << 16) | AC[1]; - AC[1] = mddata / SEXT (AC[2]); - AC[0] = mddata % SEXT (AC[2]); - if ((AC[1] > 077777) || (AC[1] < -0100000)) - C = CBIT; - else C = 0; - AC[0] = AC[0] & DMASK; } } } - break; } /* end case code */ - } /* end if mul/div */ - -/* IOT, continued */ - - else if (device == DEV_CPU) { /* CPU control */ - switch (code) { /* decode IR<5:7> */ - case ioDIA: /* read switches */ - AC[dstAC] = SR; - break; - case ioDIB: /* int ack */ - AC[dstAC] = 0; - int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); - iodata = int_req & (-int_req); - for (i = DEV_LOW; i <= DEV_HIGH; i++) { - if (iodata & dev_table[i].mask) { - AC[dstAC] = i; break; } } - break; - case ioDOB: /* mask out */ - mask_out (pimask = AC[dstAC]); - break; - case ioDIC: /* io reset */ - reset_all (0); /* reset devices */ - break; - case ioDOC: /* halt */ - reason = STOP_HALT; - break; } /* end switch code */ - switch (pulse) { /* decode IR<8:9> */ - case iopS: /* ion */ - int_req = (int_req | INT_ION) & ~INT_NO_ION_PENDING; - break; - case iopC: /* iof */ - int_req = int_req & ~INT_ION; - break; } /* end switch pulse */ - } /* end CPU control */ - else if (dev_table[device].routine) { /* normal device */ - iodata = dev_table[device].routine (pulse, code, AC[dstAC]); - reason = iodata >> IOT_V_REASON; - if (code & 1) AC[dstAC] = iodata & 0177777; } - else reason = stop_dev; - } /* end if IOT */ -} /* end while */ - -/* Simulation halted */ - -saved_PC = PC; -pcq_r->qptr = pcq_p; /* update pc q ptr */ -return reason; -} - -/* New priority mask out */ - -void mask_out (int32 newmask) -{ -int32 i; - -dev_disable = 0; -for (i = DEV_LOW; i <= DEV_HIGH; i++) { - if (newmask & dev_table[i].pi) - dev_disable = dev_disable | dev_table[i].mask; } -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -return; -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -int_req = int_req & ~(INT_ION | INT_STK); -pimask = 0; -dev_disable = 0; -pwr_low = 0; -pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & DMASK; -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -M[addr] = val & DMASK; -return SCPE_OK; -} - -/* Alter memory size */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -t_addr i; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; -if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_OK; -MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; -return SCPE_OK; -} - -/* Build dispatch table */ - -t_stat build_devtab (void) -{ -DEVICE *dptr; -DIB *dibp; -int32 i, dn; - -for (i = 0; i < 64; i++) { /* clr dev_table */ - dev_table[i].mask = 0; - dev_table[i].pi = 0; - dev_table[i].routine = NULL; } -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ - if (dibp = (DIB *) dptr->ctxt) { /* get DIB */ - dn = dibp->dnum; /* get dev num */ - dev_table[dn].mask = dibp->mask; /* copy entries */ - dev_table[dn].pi = dibp->pi; - dev_table[dn].routine = dibp->routine; } } -return SCPE_OK; -} - -/* Bootstrap routine for CPU */ - -#define BOOT_START 00000 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) - -static const int32 boot_rom[] = { - 0062677, /* IORST ;reset all I/O */ - 0060477, /* READS 0 ;read SR into AC0 */ - 0024026, /* LDA 1,C77 ;get dev mask */ - 0107400, /* AND 0,1 ;isolate dev code */ - 0124000, /* COM 1,1 ;- device code - 1 */ - 0010014, /* LOOP: ISZ OP1 ;device code to all */ - 0010030, /* ISZ OP2 ;I/O instructions */ - 0010032, /* ISZ OP3 */ - 0125404, /* INC 1,1,SZR ;done? */ - 0000005, /* JMP LOOP ;no, increment again */ - 0030016, /* LDA 2,C377 ;place JMP 377 into */ - 0050377, /* STA 2,377 ;location 377 */ - 0060077, /* OP1: 060077 ;start device (NIOS 0) */ - 00101102, /* MOVL 0,0,SZC ;test switch 0, low speed? */ - 0000377, /* C377: JMP 377 ;no - jmp 377 & wait */ - 0004030, /* LOOP2: JSR GET+1 ;get a frame */ - 0101065, /* MOVC 0,0,SNR ;is it non-zero? */ - 0000017, /* JMP LOOP2 ;no, ignore */ - 0004027, /* LOOP4: JSR GET ;yes, get full word */ - 0046026, /* STA 1,@C77 ;store starting at 100 */ - /* ;2's complement of word ct */ - 0010100, /* ISZ 100 ;done? */ - 0000022, /* JMP LOOP4 ;no, get another */ - 0000077, /* C77: JMP 77 ;yes location ctr and */ - /* ;jmp to last word */ - 0126420, /* GET: SUBZ 1,1 ; clr AC1, set carry */ - /* OP2: */ - 0063577, /* LOOP3: 063577 ;done? (SKPDN 0) - 1 */ - 0000030, /* JMP LOOP3 ;no -- wait */ - 0060477, /* OP3: 060477 ;y -- read in ac0 (DIAS 0,0) */ - 0107363, /* ADDCS 0,1,SNC ;add 2 frames swapped - got 2nd? */ - 0000030, /* JMP LOOP3 ;no go back after it */ - 0125300, /* MOVS 1,1 ;yes swap them */ - 0001400, /* JMP 0,3 ;rtn with full word */ - 0000000 /* 0 ;padding */ -}; - -t_stat cpu_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} - -/* 1-to-1 map for I/O devices */ - -int32 MapAddr (int32 map, int32 addr) -{ -return addr; -} diff --git a/NOVA/nova_defs.h b/NOVA/nova_defs.h deleted file mode 100644 index fdad7f22..00000000 --- a/NOVA/nova_defs.h +++ /dev/null @@ -1,271 +0,0 @@ -/* nova_defs.h: NOVA/Eclipse simulator definitions - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 19-Jan-03 RMS Changed CMASK to CDMASK for Apple Dev kit conflict - 03-Oct-02 RMS Added device information structure - 22-Dec-00 RMS Added Bruce Ray's second terminal support - 10-Dec-00 RMS Added Charles Owen's Eclipse support - 08-Dec-00 RMS Added Bruce Ray's plotter support - 15-Oct-00 RMS Added stack, byte, trap instructions - 14-Apr-99 RMS Changed t_addr to unsigned - 16-Mar-95 RMS Added dynamic memory size - 06-Dec-95 RMS Added magnetic tape - - The author gratefully acknowledges the help of Tom West, Diana Englebart, - Carl Friend, Bruce Ray, and Charles Owen in resolving questions about - the NOVA. -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_IND 4 /* indirect loop */ -#define STOP_IND_INT 5 /* ind loop, intr */ -#define STOP_IND_TRP 6 /* ind loop, trap */ - -/* Memory */ - -#if defined (ECLIPSE) -#define MAXMEMSIZE 1048576 /* max memory size */ -#else -#define MAXMEMSIZE 32768 /* max memory size */ -#endif -#define AMASK 077777 /* logical addr mask */ -#define PAMASK (MAXMEMSIZE - 1) /* physical addr mask */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define A_V_IND 15 /* ind: indirect */ -#define A_IND (1 << A_V_IND) -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) - -/* Architectural constants */ - -#define SIGN 0100000 /* sign */ -#define DMASK 0177777 /* data mask */ -#define CBIT (DMASK + 1) /* carry bit */ -#define CDMASK (CBIT | DMASK) /* carry + data */ - -/* Reserved memory locations */ - -#define INT_SAV 0 /* intr saved PC */ -#define INT_JMP 1 /* intr jmp @ */ -#define STK_JMP 3 /* stack jmp @ */ -#define TRP_SAV 046 /* trap saved PC */ -#define TRP_JMP 047 /* trap jmp @ */ -#define AUTO_INC 020 /* start autoinc */ -#define AUTO_DEC 030 /* start autodec */ - -/* Instruction format */ - -#define I_OPR 0100000 /* operate */ -#define I_M_SRC 03 /* OPR: src AC */ -#define I_V_SRC 13 -#define I_GETSRC(x) (((x) >> I_V_SRC) & I_M_SRC) -#define I_M_DST 03 /* dst AC */ -#define I_V_DST 11 -#define I_GETDST(x) (((x) >> I_V_DST) & I_M_DST) -#define I_M_ALU 07 /* OPR: ALU op */ -#define I_V_ALU 8 -#define I_GETALU(x) (((x) >> I_V_ALU) & I_M_ALU) -#define I_M_SHF 03 /* OPR: shift */ -#define I_V_SHF 6 -#define I_GETSHF(x) (((x) >> I_V_SHF) & I_M_SHF) -#define I_M_CRY 03 /* OPR: carry */ -#define I_V_CRY 4 -#define I_GETCRY(x) (((x) >> I_V_CRY) & I_M_CRY) -#define I_V_NLD 3 /* OPR: no load */ -#define I_NLD (1 << I_V_NLD) -#define I_M_SKP 07 /* OPR: skip */ -#define I_V_SKP 0 -#define I_GETSKP(x) (((x) >> I_V_SKP) & I_M_SKP) - -#define I_M_OPAC 017 /* MRF: opcode + AC */ -#define I_V_OPAC 11 -#define I_GETOPAC(x) (((x) >> I_V_OPAC) & I_M_OPAC) -#define I_V_IND 10 /* MRF: indirect */ -#define I_IND (1 << I_V_IND) -#define I_M_MODE 03 /* MRF: mode */ -#define I_V_MODE 8 -#define I_GETMODE(x) (((x) >> I_V_MODE) & I_M_MODE) -#define I_M_DISP 0377 /* MRF: disp */ -#define I_V_DISP 0 -#define I_GETDISP(x) (((x) >> I_V_DISP) & I_M_DISP) -#define DISPSIZE (I_M_DISP + 1) /* page size */ -#define DISPSIGN (DISPSIZE >> 1) /* page sign */ - -#define I_M_IOT 07 /* IOT: code */ -#define I_V_IOT 8 -#define I_GETIOT(x) (((x) >> I_V_IOT) & I_M_IOT) -#define I_M_PULSE 03 /* IOT pulse */ -#define I_V_PULSE 6 -#define I_GETPULSE(x) (((x) >> I_V_PULSE) & I_M_PULSE) -#define I_M_DEV 077 /* IOT: device */ -#define I_V_DEV 0 -#define I_GETDEV(x) (((x) >> I_V_DEV) & I_M_DEV) - -#define I_M_XOP 037 /* XOP: code */ -#define I_V_XOP 6 -#define I_GETXOP(x) (((x) >> I_V_XOP) & I_M_XOP) - -/* IOT return codes */ - -#define IOT_V_REASON 16 /* set reason */ -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ - -/* IOT fields */ - -#define ioNIO 0 /* opcode field */ -#define ioDIA 1 -#define ioDOA 2 -#define ioDIB 3 -#define ioDOB 4 -#define ioDIC 5 -#define ioDOC 6 -#define ioSKP 7 - -#define iopN 0 /* pulse field */ -#define iopS 1 -#define iopC 2 -#define iopP 3 - -/* Device numbers */ - -#define DEV_LOW 010 /* lowest intr dev */ -#define DEV_HIGH 051 /* highest intr dev */ -#define DEV_MDV 001 /* multiply/divide */ -#define DEV_ECC 002 /* ECC memory control */ -#define DEV_MAP 003 /* MMPU control */ -#define DEV_TTI 010 /* console input */ -#define DEV_TTO 011 /* console output */ -#define DEV_PTR 012 /* paper tape reader */ -#define DEV_PTP 013 /* paper tape punch */ -#define DEV_CLK 014 /* clock */ -#define DEV_PLT 015 /* plotter */ -#define DEV_CDR 016 /* card reader */ -#define DEV_LPT 017 /* line printer */ -#define DEV_DSK 020 /* fixed head disk */ -#define DEV_MTA 022 /* magtape */ -#define DEV_DCM 024 /* data comm mux */ -#define DEV_ADCV 030 /* A/D converter */ -#define DEV_DKP 033 /* disk pack */ -#define DEV_CAS 034 /* cassette */ -#define DEV_TTI1 050 /* second console input */ -#define DEV_TTO1 051 /* second console output */ -#define DEV_CPU 077 /* CPU control */ - -/* I/O structure - - The NOVA I/O structure is tied together by dev_table, indexed by - the device number. Each entry in dev_table consists of - - mask device mask for busy, done (simulator representation) - pi pi disable bit (hardware representation) - routine IOT action routine - - dev_table is populated at run time from the device information - blocks in each device. -*/ - -struct ndev { - int32 mask; /* done/busy mask */ - int32 pi; /* assigned pi bit */ - int32 (*routine)(); /* dispatch routine */ - }; - -struct nova_dib { - int32 dnum; /* device number */ - int32 mask; /* done/busy mask */ - int32 pi; /* assigned pi bit */ - int32 (*routine)(); /* dispatch routine */ - }; - -typedef struct nova_dib DIB; - -/* Device flags (simulator representation) - - Priority (for INTA) runs from low numbers to high -*/ - -#define INT_V_DKP 3 /* moving head disk */ -#define INT_V_DSK 4 /* fixed head disk */ -#define INT_V_MTA 5 /* magnetic tape */ -#define INT_V_LPT 6 /* line printer */ -#define INT_V_CLK 7 /* clock */ -#define INT_V_PTR 8 /* paper tape reader */ -#define INT_V_PTP 9 /* paper tape punch */ -#define INT_V_PLT 10 /* plotter */ -#define INT_V_TTI 11 /* keyboard */ -#define INT_V_TTO 12 /* terminal */ -#define INT_V_TTI1 13 /* second keyboard */ -#define INT_V_TTO1 14 /* second terminal */ -#define INT_V_STK 15 /* stack overflow */ -#define INT_V_NO_ION_PENDING 16 /* ion delay */ -#define INT_V_ION 17 /* interrupts on */ - -#define INT_DKP (1 << INT_V_DKP) -#define INT_DSK (1 << INT_V_DSK) -#define INT_MTA (1 << INT_V_MTA) -#define INT_LPT (1 << INT_V_LPT) -#define INT_CLK (1 << INT_V_CLK) -#define INT_PTR (1 << INT_V_PTR) -#define INT_PTP (1 << INT_V_PTP) -#define INT_PLT (1 << INT_V_PLT) -#define INT_TTI (1 << INT_V_TTI) -#define INT_TTO (1 << INT_V_TTO) -#define INT_TTI1 (1 << INT_V_TTI1) -#define INT_TTO1 (1 << INT_V_TTO1) -#define INT_STK (1 << INT_V_STK) -#define INT_NO_ION_PENDING (1 << INT_V_NO_ION_PENDING) -#define INT_ION (1 << INT_V_ION) -#define INT_DEV ((1 << INT_V_STK) - 1) /* device ints */ -#define INT_PENDING INT_ION+INT_NO_ION_PENDING - -/* PI disable bits */ - -#define PI_DKP 0000400 -#define PI_DSK 0000100 -#define PI_MTA 0000040 -#define PI_LPT 0000010 -#define PI_CLK 0000004 -#define PI_PTR 0000020 -#define PI_PTP 0000004 -#define PI_PLT 0000010 -#define PI_TTI 0000002 -#define PI_TTO 0000001 -#define PI_TTI1 PI_TTI -#define PI_TTO1 PI_TTO -/* #define PI_CDR 0000040 */ -/* #define PI_DCM 0100000 */ -/* #define PI_CAS 0000040 */ -/* #define PI_ADCV 0000002 */ - -/* Function prototypes */ - -int32 MapAddr (int32 map, int32 addr); -t_stat set_enb (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat set_dsb (UNIT *uptr, int32 val, char *cptr, void *desc); diff --git a/NOVA/nova_dkp.c b/NOVA/nova_dkp.c deleted file mode 100644 index 9dd91026..00000000 --- a/NOVA/nova_dkp.c +++ /dev/null @@ -1,723 +0,0 @@ -/* nova_dkp.c: NOVA moving head disk simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - dkp moving head disk - - 25-Apr-03 RMS Revised autosizing - 08-Oct-02 RMS Added DIB - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Changed FLG, CAPAC to arrays - 26-Apr-01 RMS Added device enable/disable support - 12-Dec-00 RMS Added Eclipse support from Charles Owen - 15-Oct-00 RMS Editorial changes - 14-Apr-99 RMS Changed t_addr to unsigned - 15-Sep-97 RMS Fixed bug in DIB/DOB for new disks - 15-Sep-97 RMS Fixed bug in cylinder extraction (found by Charles Owen) - 10-Sep-97 RMS Fixed bug in error reporting (found by Charles Owen) - 25-Nov-96 RMS Defaulted to autosize - 29-Jun-96 RMS Added unit disable support -*/ - -#include "nova_defs.h" - -#define DKP_NUMDR 4 /* #drives */ -#define DKP_NUMWD 256 /* words/sector */ -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */ -#define UNIT_M_DTYPE 017 -#define UNIT_V_AUTO (UNIT_V_UF + 5) /* autosize */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) -#define FUNC u3 /* function */ -#define CYL u4 /* on cylinder */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -/* Unit, surface, sector, count register - - Original format: 2b, 6b, 4b, 4b - Revised format: 2b, 5b, 5b, 4b -*/ - -#define USSC_V_COUNT 0 /* count */ -#define USSC_M_COUNT 017 -#define USSC_V_OSECTOR 4 /* old: sector */ -#define USSC_M_OSECTOR 017 -#define USSC_V_OSURFACE 8 /* old: surface */ -#define USSC_M_OSURFACE 077 -#define USSC_V_NSECTOR 4 /* new: sector */ -#define USSC_M_NSECTOR 037 -#define USSC_V_NSURFACE 9 /* new: surface */ -#define USSC_M_NSURFACE 037 -#define USSC_V_UNIT 14 /* unit */ -#define USSC_M_UNIT 03 -#define USSC_UNIT (USSC_M_UNIT << USSC_V_UNIT) -#define GET_COUNT(x) (((x) >> USSC_V_COUNT) & USSC_M_COUNT) -#define GET_SECT(x,dt) ((drv_tab[dt].newf)? \ - (((x) >> USSC_V_NSECTOR) & USSC_M_NSECTOR): \ - (((x) >> USSC_V_OSECTOR) & USSC_M_OSECTOR) ) -#define GET_SURF(x,dt) ((drv_tab[dt].newf)? \ - (((x) >> USSC_V_NSURFACE) & USSC_M_NSURFACE): \ - (((x) >> USSC_V_OSURFACE) & USSC_M_OSURFACE) ) -#define GET_UNIT(x) (((x) >> USSC_V_UNIT) & USSC_M_UNIT) - -/* Flags, command, cylinder register - - Original format: 5b, 2b, 1b + 8b (surrounding command) - Revised format: 5b, 2b, 9b -*/ - -#define FCCY_V_OCYL 0 /* old: cylinder */ -#define FCCY_M_OCYL 0377 -#define FCCY_V_OCMD 8 /* old: command */ -#define FCCY_M_OCMD 3 -#define FCCY_V_OCEX 10 /* old: cyl extend */ -#define FCCY_OCEX (1 << FCCY_V_OCEX) -#define FCCY_V_NCYL 0 /* new: cylinder */ -#define FCCY_M_NCYL 0777 -#define FCCY_V_NCMD 9 /* new: command */ -#define FCCY_M_NCMD 3 -#define FCCY_READ 0 -#define FCCY_WRITE 1 -#define FCCY_SEEK 2 -#define FCCY_RECAL 3 -#define FCCY_FLAGS 0174000 /* flags */ -#define GET_CMD(x,dt) ((drv_tab[dt].newf)? \ - (((x) >> FCCY_V_NCMD) & FCCY_M_NCMD): \ - (((x) >> FCCY_V_OCMD) & FCCY_M_OCMD) ) -#define GET_CYL(x,dt) ((drv_tab[dt].newf)? \ - (((x) >> FCCY_V_NCYL) & FCCY_M_NCYL): \ - ((((x) >> FCCY_V_OCYL) & FCCY_M_OCYL) | \ - ((dt != TYPE_D44)? 0: \ - (((x) & FCCY_OCEX) >> (FCCY_V_OCEX - FCCY_V_OCMD)))) ) - -/* Status */ - -#define STA_ERR 0000001 /* error */ -#define STA_DLT 0000002 /* data late */ -#define STA_CRC 0000004 /* crc error */ -#define STA_UNS 0000010 /* unsafe */ -#define STA_XCY 0000020 /* cross cylinder */ -#define STA_CYL 0000040 /* nx cylinder */ -#define STA_DRDY 0000100 /* drive ready */ -#define STA_SEEK3 0000200 /* seeking unit 3 */ -#define STA_SEEK2 0000400 /* seeking unit 2 */ -#define STA_SEEK1 0001000 /* seeking unit 1 */ -#define STA_SEEK0 0002000 /* seeking unit 0 */ -#define STA_SKDN3 0004000 /* seek done unit 3 */ -#define STA_SKDN2 0010000 /* seek done unit 2 */ -#define STA_SKDN1 0020000 /* seek done unit 1 */ -#define STA_SKDN0 0040000 /* seek done unit 0 */ -#define STA_DONE 0100000 /* operation done */ - -#define STA_DYN (STA_DRDY | STA_CYL) /* set from unit */ -#define STA_EFLGS (STA_ERR | STA_DLT | STA_CRC | STA_UNS | \ - STA_XCY | STA_CYL) /* error flags */ -#define STA_DFLGS (STA_DONE | STA_SKDN0 | STA_SKDN1 | \ - STA_SKDN2 | STA_SKDN3) /* done flags */ - -#define GET_SA(cy,sf,sc,t) (((((cy)*drv_tab[t].surf)+(sf))* \ - drv_tab[t].sect)+(sc)) - -/* This controller supports many different disk drive types: - - type #sectors/ #surfaces/ #cylinders/ new format? - surface cylinder drive - - floppy 8 1 77 no - DS/DD floppy 16 2 77 yes - Diablo 31 12 2 203 no - 6225 20 2 245 yes - Century 111 6 10 203 no - Diablo 44 12 4 408 no - 6099 32 4 192 yes - 6227 20 6 245 yes - 6070 24 4 408 yes - Century 114 12 20 203 no - 6103 32 8 192 yes - 4231 23 19 411 yes - - In theory, each drive can be a different type. The size field in - each unit selects the drive capacity for each drive and thus the - drive type. DISKS MUST BE DECLARED IN ASCENDING SIZE. -*/ - -#define TYPE_FLP 0 -#define SECT_FLP 8 -#define SURF_FLP 1 -#define CYL_FLP 77 -#define SIZE_FLP (SECT_FLP * SURF_FLP * CYL_FLP * DKP_NUMWD) -#define NFMT_FLP FALSE - -#define TYPE_DSDD 1 -#define SECT_DSDD 16 -#define SURF_DSDD 2 -#define CYL_DSDD 77 -#define SIZE_DSDD (SECT_DSDD * SURF_DSDD * CYL_DSDD * DKP_NUMWD) -#define NFMT_DSDD TRUE - -#define TYPE_D31 2 -#define SECT_D31 12 -#define SURF_D31 2 -#define CYL_D31 203 -#define SIZE_D31 (SECT_D31 * SURF_D31 * CYL_D31 * DKP_NUMWD) -#define NFMT_D31 FALSE - -#define TYPE_6225 3 -#define SECT_6225 20 -#define SURF_6225 2 -#define CYL_6225 245 -#define SIZE_6225 (SECT_6225 * SURF_6225 * CYL_6225 * DKP_NUMWD) -#define NFMT_6225 TRUE - -#define TYPE_C111 4 -#define SECT_C111 6 -#define SURF_C111 10 -#define CYL_C111 203 -#define SIZE_C111 (SECT_C111 * SURF_C111 * CYL_C111 * DKP_NUMWD) -#define NFMT_C111 FALSE - -#define TYPE_D44 5 -#define SECT_D44 12 -#define SURF_D44 4 -#define CYL_D44 408 -#define SIZE_D44 (SECT_D44 * SURF_D44 * CYL_D44 * DKP_NUMWD) -#define NFMT_D44 FALSE - -#define TYPE_6099 6 -#define SECT_6099 32 -#define SURF_6099 4 -#define CYL_6099 192 -#define SIZE_6099 (SECT_6099 * SURF_6099 * CYL_6099 * DKP_NUMWD) -#define NFMT_6099 TRUE - -#define TYPE_6227 7 -#define SECT_6227 20 -#define SURF_6227 6 -#define CYL_6227 245 -#define SIZE_6227 (SECT_6227 * SURF_6227 * CYL_6227 * DKP_NUMWD) -#define NFMT_6227 TRUE - -#define TYPE_6070 8 -#define SECT_6070 24 -#define SURF_6070 4 -#define CYL_6070 408 -#define SIZE_6070 (SECT_6070 * SURF_6070 * CYL_6070 * DKP_NUMWD) -#define NFMT_6070 TRUE - -#define TYPE_C114 9 -#define SECT_C114 12 -#define SURF_C114 20 -#define CYL_C114 203 -#define SIZE_C114 (SECT_C114 * SURF_C114 * CYL_C114 * DKP_NUMWD) -#define NFMT_C114 FALSE - -#define TYPE_6103 10 -#define SECT_6103 32 -#define SURF_6103 8 -#define CYL_6103 192 -#define SIZE_6103 (SECT_6103 * SURF_6103 * CYL_6103 * DKP_NUMWD) -#define NFMT_6103 TRUE - -#define TYPE_4231 11 -#define SECT_4231 23 -#define SURF_4231 19 -#define CYL_4231 411 -#define SIZE_4231 (SECT_4231 * SURF_4231 * CYL_4231 * DKP_NUMWD) -#define NFMT_4231 TRUE - -struct drvtyp { - int32 sect; /* sectors */ - int32 surf; /* surfaces */ - int32 cyl; /* cylinders */ - int32 size; /* #blocks */ - int32 newf; /* new format flag */ -}; - -struct drvtyp drv_tab[] = { - { SECT_FLP, SURF_FLP, CYL_FLP, SIZE_FLP, NFMT_FLP }, - { SECT_DSDD, SURF_DSDD, CYL_DSDD, SIZE_DSDD, NFMT_DSDD }, - { SECT_D31, SURF_D31, CYL_D31, SIZE_D31, NFMT_D31 }, - { SECT_6225, SURF_6225, CYL_6225, SIZE_6225, NFMT_6225 }, - { SECT_C111, SURF_C111, CYL_C111, SIZE_C111, NFMT_C111 }, - { SECT_D44, SURF_D44, CYL_D44, SIZE_D44, NFMT_D44 }, - { SECT_6099, SURF_6099, CYL_6099, SIZE_6099, NFMT_6099 }, - { SECT_6227, SURF_6227, CYL_6227, SIZE_6227, NFMT_6227 }, - { SECT_6070, SURF_6070, CYL_6070, SIZE_6070, NFMT_6070 }, - { SECT_C114, SURF_C114, CYL_C114, SIZE_C114, NFMT_C114 }, - { SECT_6103, SURF_6103, CYL_6103, SIZE_6103, NFMT_6103 }, - { SECT_4231, SURF_4231, CYL_4231, SIZE_4231, NFMT_4231 }, - { 0 } }; - -extern uint16 M[]; -extern UNIT cpu_unit; -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 dkp_ma = 0; /* memory address */ -int32 dkp_ussc = 0; /* unit/sf/sc/cnt */ -int32 dkp_fccy = 0; /* flags/cylinder */ -int32 dkp_sta = 0; /* status register */ -int32 dkp_swait = 100; /* seek latency */ -int32 dkp_rwait = 100; /* rotate latency */ - -DEVICE dkp_dev; -int32 dkp (int32 pulse, int32 code, int32 AC); -t_stat dkp_svc (UNIT *uptr); -t_stat dkp_reset (DEVICE *dptr); -t_stat dkp_boot (int32 unitno, DEVICE *dptr); -t_stat dkp_attach (UNIT *uptr, char *cptr); -t_stat dkp_go (void); -t_stat dkp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* DKP data structures - - dkp_dev DKP device descriptor - dkp_unit DKP unit list - dkp_reg DKP register list - dkp_mod DKP modifier list -*/ - -DIB dkp_dib = { DEV_DKP, INT_DKP, PI_DKP, &dkp }; - -UNIT dkp_unit[] = { - { UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) }, - { UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) }, - { UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) }, - { UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) } }; - -REG dkp_reg[] = { - { ORDATA (FCCY, dkp_fccy, 16) }, - { ORDATA (USSC, dkp_ussc, 16) }, - { ORDATA (STA, dkp_sta, 16) }, - { ORDATA (MA, dkp_ma, 16) }, - { FLDATA (INT, int_req, INT_V_DKP) }, - { FLDATA (BUSY, dev_busy, INT_V_DKP) }, - { FLDATA (DONE, dev_done, INT_V_DKP) }, - { FLDATA (DISABLE, dev_disable, INT_V_DKP) }, - { DRDATA (STIME, dkp_swait, 24), PV_LEFT }, - { DRDATA (RTIME, dkp_rwait, 24), PV_LEFT }, - { URDATA (CAPAC, dkp_unit[0].capac, 10, T_ADDR_W, 0, - DKP_NUMDR, PV_LEFT | REG_HRO) }, - { NULL } }; - -MTAB dkp_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_FLP << UNIT_V_DTYPE) + UNIT_ATT, - "6030 (floppy)", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_DSDD << UNIT_V_DTYPE) + UNIT_ATT, - "6097 (DS/DD floppy)", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_D31 << UNIT_V_DTYPE) + UNIT_ATT, - "4047 (Diablo 31)", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_D44 << UNIT_V_DTYPE) + UNIT_ATT, - "4234/6045 (Diablo 44)", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_C111 << UNIT_V_DTYPE) + UNIT_ATT, - "4048 (Century 111)", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_C114 << UNIT_V_DTYPE) + UNIT_ATT, - "2314/4057 (Century 114)", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_6225 << UNIT_V_DTYPE) + UNIT_ATT, - "6225", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_6227 << UNIT_V_DTYPE) + UNIT_ATT, - "6227", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_6099 << UNIT_V_DTYPE) + UNIT_ATT, - "6099", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_6103 << UNIT_V_DTYPE) + UNIT_ATT, - "6103", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_6070 << UNIT_V_DTYPE) + UNIT_ATT, - "6070", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_4231 << UNIT_V_DTYPE) + UNIT_ATT, - "4231/3330", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_FLP << UNIT_V_DTYPE), - "6030 (floppy)", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_DSDD << UNIT_V_DTYPE), - "6097 (DS/DD floppy)", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_D31 << UNIT_V_DTYPE), - "4047 (Diablo 31)", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_D44 << UNIT_V_DTYPE), - "4234/6045 (Diablo 44)", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_C111 << UNIT_V_DTYPE), - "4048 (Century 111)", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_C114 << UNIT_V_DTYPE), - "2314/4057 (Century 114)", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_6225 << UNIT_V_DTYPE), - "6225", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_6227 << UNIT_V_DTYPE), - "6227", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_6099 << UNIT_V_DTYPE), - "6099", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_6103 << UNIT_V_DTYPE), - "6103", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_6070 << UNIT_V_DTYPE), - "6070", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_4231 << UNIT_V_DTYPE), - "4231/3330", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_FLP << UNIT_V_DTYPE), - NULL, "FLOPPY", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_FLP << UNIT_V_DTYPE), - NULL, "6030", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_DSDD << UNIT_V_DTYPE), - NULL, "DSDDFLOPPY", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_DSDD << UNIT_V_DTYPE), - NULL, "6097", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_D31 << UNIT_V_DTYPE), - NULL, "D31", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_D31 << UNIT_V_DTYPE), - NULL, "4047", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_D44 << UNIT_V_DTYPE), - NULL, "D44", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_D44 << UNIT_V_DTYPE), - NULL, "4234", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_D44 << UNIT_V_DTYPE), - NULL, "6045", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_C111 << UNIT_V_DTYPE), - NULL, "C111", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_C111 << UNIT_V_DTYPE), - NULL, "4048", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_C114 << UNIT_V_DTYPE), - NULL, "C114", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_C114 << UNIT_V_DTYPE), - NULL, "2314", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_C114 << UNIT_V_DTYPE), - NULL, "4057", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_6225 << UNIT_V_DTYPE), - NULL, "6225", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_6227 << UNIT_V_DTYPE), - NULL, "6227", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_6099 << UNIT_V_DTYPE), - NULL, "6099", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_6103 << UNIT_V_DTYPE), - NULL, "6103", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_6070 << UNIT_V_DTYPE), - NULL, "6070", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_4231 << UNIT_V_DTYPE), - NULL, "4231", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_4231 << UNIT_V_DTYPE), - NULL, "3330", &dkp_set_size }, - { 0 } }; - -DEVICE dkp_dev = { - "DP", dkp_unit, dkp_reg, dkp_mod, - DKP_NUMDR, 8, 30, 1, 8, 16, - NULL, NULL, &dkp_reset, - &dkp_boot, &dkp_attach, NULL, - &dkp_dib, DEV_DISABLE }; - -/* IOT routine */ - -int32 dkp (int32 pulse, int32 code, int32 AC) -{ -UNIT *uptr; -int32 u, rval, dtype; - -rval = 0; -uptr = dkp_dev.units + GET_UNIT (dkp_ussc); /* select unit */ -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -switch (code) { /* decode IR<5:7> */ -case ioDIA: /* DIA */ - dkp_sta = dkp_sta & ~STA_DYN; /* clear dynamic */ - if (uptr->flags & UNIT_ATT) dkp_sta = dkp_sta | STA_DRDY; - if (uptr->CYL >= drv_tab[dtype].cyl) - dkp_sta = dkp_sta | STA_CYL; /* bad cylinder? */ - if (dkp_sta & STA_EFLGS) dkp_sta = dkp_sta | STA_ERR; - rval = dkp_sta; - break; -case ioDOA: /* DOA */ - if ((dev_busy & INT_DKP) == 0) { - dkp_fccy = AC; /* save cmd, cyl */ - dkp_sta = dkp_sta & ~(AC & FCCY_FLAGS); } - break; -case ioDIB: /* DIB */ - rval = dkp_ma; /* return buf addr */ - break; -case ioDOB: /* DOB */ - if ((dev_busy & INT_DKP) == 0) dkp_ma = - AC & (drv_tab[dtype].newf? DMASK: AMASK); - break; -case ioDIC: /* DIC */ - rval = dkp_ussc; /* return unit, sect */ - break; -case ioDOC: /* DOC */ - if ((dev_busy & INT_DKP) == 0) dkp_ussc = AC; /* save unit, sect */ - break; } /* end switch code */ - -/* IOT, continued */ - -u = GET_UNIT(dkp_ussc); /* select unit */ -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_DKP; /* set busy */ - dev_done = dev_done & ~INT_DKP; /* clear done */ - int_req = int_req & ~INT_DKP; /* clear int */ - if (dkp_go ()) break; /* new cmd, error? */ - dev_busy = dev_busy & ~INT_DKP; /* clear busy */ - dev_done = dev_done | INT_DKP; /* set done */ - int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); - dkp_sta = dkp_sta | STA_DONE; - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_DKP; /* clear busy */ - dev_done = dev_done & ~INT_DKP; /* clear done */ - int_req = int_req & ~INT_DKP; /* clear int */ - dkp_sta = dkp_sta & ~(STA_DFLGS + STA_EFLGS); - if (dkp_unit[u].FUNC != FCCY_SEEK) sim_cancel (&dkp_unit[u]); - break; -case iopP: /* pulse */ - dev_done = dev_done & ~INT_DKP; /* clear done */ - if (dkp_go ()) break; /* new seek command */ - dev_done = dev_done | INT_DKP; /* set done */ - int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); - dkp_sta = dkp_sta | (STA_SKDN0 >> u); /* set seek done */ - break; } /* end case pulse */ -return rval; -} - -/* New command, start vs pulse handled externally - Returns true if command ok, false if error -*/ - -t_stat dkp_go (void) -{ -UNIT *uptr; -int32 newcyl, func, u, dtype; - -dkp_sta = dkp_sta & ~STA_EFLGS; /* clear errors */ -u = GET_UNIT (dkp_ussc); /* get unit number */ -uptr = dkp_dev.units + u; /* get unit */ -if (((uptr->flags & UNIT_ATT) == 0) || sim_is_active (uptr)) { - dkp_sta = dkp_sta | STA_ERR; /* attached or busy? */ - return FALSE; } -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -func = GET_CMD (dkp_fccy, dtype); /* get function */ -newcyl = GET_CYL (dkp_fccy, dtype); /* get cylinder */ -switch (func) { /* decode command */ -case FCCY_READ: case FCCY_WRITE: - sim_activate (uptr, dkp_rwait); /* schedule */ - break; -case FCCY_RECAL: /* recalibrate */ - newcyl = 0; - func = FCCY_SEEK; -case FCCY_SEEK: /* seek */ - sim_activate (uptr, dkp_swait * abs (newcyl - uptr->CYL)); - dkp_sta = dkp_sta | (STA_SEEK0 >> u); /* set seeking */ - uptr->CYL = newcyl; /* on cylinder */ - break; } /* end case command */ -uptr->FUNC = func; /* save command */ -return TRUE; /* no error */ -} - -/* Unit service - - If seek done, put on cylinder; - else, do read or write - If controller was busy, clear busy, set done, interrupt - - Memory access: sectors are read into/written from an intermediate - buffer to allow word-by-word mapping of memory addresses on the - Eclipse. This allows each word written to memory to be tested - for out of range. -*/ - -t_stat dkp_svc (UNIT *uptr) -{ -int32 sc, sa, xcsa, bda; -int32 sx, dx, pa, u; -int32 dtype, err, newsect, newsurf; -uint32 awc; -t_stat rval; -static uint16 tbuf[DKP_NUMWD]; /* transfer buffer */ - -rval = SCPE_OK; -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -if (uptr->FUNC == FCCY_SEEK) { /* seek? */ - if (uptr->CYL >= drv_tab[dtype].cyl) /* bad cylinder? */ - dkp_sta = dkp_sta | STA_ERR | STA_CYL; - dev_done = dev_done | INT_DKP; /* set done */ - int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); - u = uptr - dkp_dev.units; /* get unit number */ - dkp_sta = (dkp_sta | (STA_SKDN0 >> u)) /* set seek done */ - & ~(STA_SEEK0 >> u); /* clear seeking */ - return SCPE_OK; } - -if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */ - ((uptr->flags & UNIT_WPRT) && (uptr->FUNC == FCCY_WRITE))) - dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error */ - -else if ((uptr->CYL >= drv_tab[dtype].cyl) || /* bad cylinder */ - (GET_SURF (dkp_ussc, dtype) >= drv_tab[dtype].surf) || /* bad surface */ - (GET_SECT (dkp_ussc, dtype) >= drv_tab[dtype].sect)) /* or bad sector? */ - dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; - -else if (GET_CYL (dkp_fccy, dtype) != uptr->CYL) /* address error? */ - dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; - -else { sc = 16 - GET_COUNT (dkp_ussc); /* get sector count */ - sa = GET_SA (uptr->CYL, GET_SURF (dkp_ussc, dtype), - GET_SECT (dkp_ussc, dtype), dtype); /* get disk block */ - xcsa = GET_SA (uptr->CYL + 1, 0, 0, dtype); /* get next cyl addr */ - if ((sa + sc) > xcsa ) { /* across cylinder? */ - sc = xcsa - sa; /* limit transfer */ - dkp_sta = dkp_sta | STA_XCY; } /* xcyl error */ - bda = sa * DKP_NUMWD * sizeof (short); /* to words, bytes */ - - err = fseek (uptr->fileref, bda, SEEK_SET); /* position drive */ - - if (uptr->FUNC == FCCY_READ) { /* read? */ - for (sx = 0; sx < sc; sx++) { /* loop thru sectors */ - awc = fxread (tbuf, sizeof(uint16), DKP_NUMWD, uptr->fileref); - for ( ; awc < DKP_NUMWD; awc++) tbuf[awc] = 0; - if (err = ferror (uptr->fileref)) break; - for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop thru buffer */ - pa = MapAddr (0, dkp_ma); - if (MEM_ADDR_OK (pa)) M[pa] = tbuf[dx]; - dkp_ma = (dkp_ma + 1) & AMASK; } } } - - if (uptr->FUNC == FCCY_WRITE) { /* write? */ - for (sx = 0; sx < sc; sx++) { /* loop thru sectors */ - for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop into buffer */ - pa = MapAddr (0, dkp_ma); - tbuf[dx] = M[pa]; - dkp_ma = (dkp_ma + 1) & AMASK; } - fxwrite (tbuf, sizeof(int16), DKP_NUMWD, uptr->fileref); - if (err = ferror (uptr->fileref)) break; } } - - if (err != 0) { - perror ("DKP I/O error"); - rval = SCPE_IOERR; } - clearerr (uptr->fileref); - - sa = sa + sc; /* update sector addr */ - newsect = sa % drv_tab[dtype].sect; - newsurf = (sa / drv_tab[dtype].sect) % drv_tab[dtype].surf; - dkp_ussc = (dkp_ussc & USSC_UNIT) | ((dkp_ussc + sc) & USSC_M_COUNT) | - ((drv_tab[dtype].newf)? - ((newsurf << USSC_V_NSURFACE) | (newsect << USSC_V_NSECTOR)): - ((newsurf << USSC_V_OSURFACE) | (newsect << USSC_V_OSECTOR)) ); - dkp_sta = dkp_sta | STA_DONE; } /* set status */ - -dev_busy = dev_busy & ~INT_DKP; /* clear busy */ -dev_done = dev_done | INT_DKP; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -return rval; -} - -/* Reset routine */ - -t_stat dkp_reset (DEVICE *dptr) -{ -int32 u; -UNIT *uptr; - -dev_busy = dev_busy & ~INT_DKP; /* clear busy */ -dev_done = dev_done & ~INT_DKP; /* clear done, int */ -int_req = int_req & ~INT_DKP; -dkp_fccy = dkp_ussc = dkp_ma = dkp_sta = 0; /* clear registers */ -for (u = 0; u < DKP_NUMDR; u++) { /* loop thru units */ - uptr = dkp_dev.units + u; - sim_cancel (uptr); /* cancel activity */ - uptr->CYL = uptr->FUNC = 0; } -return SCPE_OK; -} - -/* Attach routine (with optional autosizing) */ - -t_stat dkp_attach (UNIT *uptr, char *cptr) -{ -int32 i, p; -t_stat r; - -uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size; -r = attach_unit (uptr, cptr); -if ((r != SCPE_OK) || ((uptr->flags & UNIT_AUTO) == 0)) return r; -if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK; -if ((p = ftell (uptr->fileref)) == 0) return SCPE_OK; -for (i = 0; drv_tab[i].sect != 0; i++) { - if (p <= (drv_tab[i].size * (int) sizeof (short))) { - uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); - uptr->capac = drv_tab[i].size; - return SCPE_OK; } } -return SCPE_OK; -} - -/* Set size command validation routine */ - -t_stat dkp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = drv_tab[GET_DTYPE (val)].size; -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define BOOT_START 02000 -#define BOOT_UNIT 02021 -#define BOOT_SEEK 02022 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) - -static const int32 boot_rom[] = { - 060233, /* NIOC 0,DKP ; clear disk */ - 020420, /* LDA 0,USSC ; unit, sfc, sec, cnt */ - 063033, /* DOC 0,DKP ; select disk */ - 020417, /* LDA 0,SEKCMD ; command, cylinder */ - 061333, /* DOAP 0,DKP ; start seek */ - 024415, /* LDA 1,SEKDN */ - 060433, /* DIA 0,DKP ; get status */ - 0123415, /* AND# 1,0,SZR ; skip if done */ - 000776, /* JMP .-2 */ - 0102400, /* SUB 0,0 ; mem addr = 0 */ - 062033, /* DOB 0,DKP */ - 020411, /* LDA 0,REDCMD ; command, cylinder */ - 061133, /* DOAS 0,DKP ; start read */ - 060433, /* DIA 0, DKP ; get status */ - 0101113, /* MOVL# 0,0,SNC ; skip if done */ - 000776, /* JMP .-2 */ - 000377, /* JMP 377 */ - 000016, /* USSC: 0.B1+0.B7+0.B11+16 */ - 0175000, /* SEKCMD: 175000 */ - 074000, /* SEKDN: 074000 */ - 0174000 /* REDCMD: 174000 */ -}; - -t_stat dkp_boot (int32 unitno, DEVICE *dptr) -{ -int32 i, dtype; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -unitno = unitno & USSC_M_UNIT; -dtype = GET_DTYPE (dkp_unit[unitno].flags); -M[BOOT_UNIT] = M[BOOT_UNIT] | (unitno << USSC_V_UNIT); -if (drv_tab[dtype].newf) M[BOOT_SEEK] = 0176000; -saved_PC = BOOT_START; -return SCPE_OK; -} diff --git a/NOVA/nova_doc.txt b/NOVA/nova_doc.txt deleted file mode 100644 index b2bd632e..00000000 --- a/NOVA/nova_doc.txt +++ /dev/null @@ -1,594 +0,0 @@ -To: Users -From: Bob Supnik -Subj: Nova Simulator Usage -Date: 15-Mar-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - Original code published in 1993-2003, written by Robert M Supnik - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - -This memorandum documents the Nova simulator. - - -1. Simulator Files - -sim/ sim_defs.h - sim_rev.h - sim_sock.h - sim_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tape.c - sim_tmxr.c - -sim/nova/ nova_defs.h - nova_cpu.c - nova_clk.c - nova_dkp.c - nova_dsk.c - nova_lp.c - nova_mta.c - nova_plt.c - nova_sys.c - nova_tt.c - nova_tt1.c - -2. Nova Features - -The Nova simulator is configured as follows: - -device simulates -name(s) - -CPU Nova CPU with 32KW of memory -- hardware multiply/divide -PTR,PTP paper tape reader/punch -TTI,TTO console terminal -TTI1,TTO1 second terminal -LPT line printer -PLT plotter -CLK real-time clock -DK head-per-track disk controller -DP moving head disk controller with four drives -MT magnetic tape controller with eight drives - -The Nova simulator implements these unique stop conditions: - - - reference to undefined I/O device, and STOP_DEV is set - - more than INDMAX indirect addresses are detected during - an interrupt - - more than INDMAX indirect addresses are detected during - memory reference address decoding - -The Nova loader supports standard binary format tapes. The DUMP command -is not implemented. - -Most devices can be disabled or enabled, by the commands: - - SET DISABLED - SET ENABLED - -All devices are enabled by default. - -2.1 CPU - -The only CPU options are the presence of the optional instructions -and the size of main memory. - - SET CPU MDV enable multiply/divide - SET CPU NOVA3 enable Nova3 instructions - SET CPU NOVA4 enable Nova4 instructions - SET CPU NONE disable all optional instructions - SET CPU 4K set memory size = 4K - SET CPU 8K set memory size = 8K - SET CPU 12K set memory size = 12K - SET CPU 16K set memory size = 16K - SET CPU 20K set memory size = 20K - SET CPU 24K set memory size = 24K - SET CPU 28K set memory size = 28K - SET CPU 32K set memory size = 32K - -(MDV = unsigned multiply/divide instructions) -(Nova 3 = unsigned multiply/divide, stack, trap instructions) -(Nova 4 = unsigned and signed multiply/divide, stack, byte, trap instructions) - -If memory size is being reduced, and the memory being truncated contains -non-zero data, the simulator asks for confirmation. Data in the truncated -portion of memory is lost. Initial memory size is 32K. - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - PC 15 program counter - AC0..AC3 16 accumulators 0..3 - C 1 carry - SR 16 front panel switches - PI 16 priority interrupt mask - ION 1 interrupt enable - ION_DELAY 1 interrupt enable delay for ION - PWR 1 power fail interrupt - INT 15 interrupt pending flags - BUSY 15 device busy flags - DONE 15 device done flags - DISABLE 15 device interrupt disable flags - STOP_DEV 1 stop on undefined IOT - INDMAX 15 maximum number of nested indirects - PCQ[0:63] 15 PC prior to last JMP, JMS, or interrupt; - most recent PC change first - WRU 8 interrupt character - -2.2 Programmed I/O Devices - -2.2.1 Paper Tape Reader (PTR) - -The paper tape reader (PTR) reads data from a disk file. The POS -register specifies the number of the next data item to be read. Thus, -by changing POS, the user can backspace or advance the reader. - -The paper tape reader implements these registers: - - name size comments - - BUF 8 last data item processed - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - POS 32 position in the input file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape or paper - - end of file 1 report error and stop - 0 out of tape or paper - - OS I/O error x report error and stop - -2.2.2 Paper Tape Punch (PTP) - -The paper tape punch (PTP) writes data to a disk file. The POS -register specifies the number of the next data item to be written. -Thus, by changing POS, the user can backspace or advance the punch. - -The paper tape punch implements these registers: - - name size comments - - BUF 8 last data item processed - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape or paper - - OS I/O error x report error and stop - -2.2.3 Terminal Input (TTI) - -The terminal input polls the console keyboard for input. Terminal -input options include the ability to set ANSI mode or limited Dasher -compatibility mode: - - SET TTI ANSI normal mode - SET TTI DASHER Dasher mode - -Setting either TTI or TTO changes both devices. In Dasher mode, carriage -return is changed to newline on input, and ^X is changed to backspace. - -The terminal input implements these registers: - - name size comments - - BUF 8 last data item processed - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - POS 32 number of characters input - TIME 24 keyboard polling interval - -2.2.4 Terminal Output (TTO) - -The terminal output writes to the simulator console window. Terminal -output options include the the ability to set ANSI mode or limited -Dasher compatibility mode: - - SET TTO ANSI normal mode - SET TTO DASHER Dasher mode - -Setting either TTI or TTO changes both devices. In Dasher mode, carriage -return is changed to newline on input, and ^X is changed to backspace. - -The terminal output implements these registers: - - name size comments - - BUF 8 last data item processed - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - POS 32 number of characters output - TIME 24 time from I/O initiation to interrupt - -2.2.5 Line Printer (LPT) - -The line printer (LPT) writes data to a disk file. The POS register -specifies the number of the next data item to be written. Thus, -by changing POS, the user can backspace or advance the printer. - -The line printer implements these registers: - - name size comments - - BUF 8 last data item processed - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of paper - - OS I/O error x report error and stop - -2.2.6 Real-Time Clock (CLK) - -The real-time clock (CLK) line frequency can be adjusted as follows: - - SET CLK 60HZ set line frequency to 60Hz - SET CLK 50HZ set line frequency to 50Hz - -The default is 60Hz. - -The clock implements these registers: - - name size comments - - SELECT 2 selected clock interval - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - TIME0 24 clock frequency, select = 0 - TIME1 24 clock frequency, select = 1 - TIME2 24 clock frequency, select = 2 - TIME3 24 clock frequency, select = 3 - -The real-time clock autocalibrates; the clock interval is adjusted up -or down so that the clock tracks actual elapsed time. - -2.2.7 Plotter (PTP) - -The plotter (PLT) writes data to a disk file. The POS register -specifies the number of the next data item to be written. Thus, -by changing POS, the user can backspace or advance the plotter. - -The plotter implements these registers: - - name size comments - - BUF 8 last data item processed - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape or paper - - OS I/O error x report error and stop - -2.2.8 Second Terminal (TTI1, TTO1) - -The second terminal consists of two independent devices, TTI1 and TTO1. -The additional terminal performs input and output through a Telnet session -connecting into a user-specified port. The ATTACH command specifies the -port to be used: - - ATTACH TTI1 set up listening port - -where port is a decimal number between 1 and 65535 that is not being used -for other TCP/IP activities. - -Once TTI1 is attached and the simulator is running, the terminal listens -for a connection on the specified port. It assumes that the incoming -connection is a Telnet connection. The connection remain opens until -disconnected by the Telnet client, or by a DETACH TTI1 command. - -The second terminal has two options, recognized on both devices, for -setting limited Dasher-compatibility mode or ANSI mode: - - SET TTI1 ANSI normal mode - SET TTI1 DASHER Dasher mode - SET TTO1 ANSI normal mode - SET TTO1 DASHER Dasher mode - -Setting either TTI1 or TTO1 changes both devices. In Dasher mode, carriage -return is changed to newline on input, and ^X is changed to backspace. - -The SHOW TTI1 CONNECTIONS command displays the current connection to TTI1. -The SHOW TTI1 STATISTICS command displays statistics for the current connection. -The SET TTI1 DISCONNECT{=0} disconnects the current connection. - -The second terminal input implements these registers: - - name size comments - - BUF 8 last data item processed - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - TIME 24 keyboard polling interval - -The second terminal output implements these registers: - - name size comments - - BUF 8 last data item processed - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - TIME 24 time from I/O initiation to interrupt - -2.3 Fixed Head Disk (DK) - -Fixed head disk options include the ability to set the number of platters -to a fixed value between 1 and 8, or to autosize the number of platters -from the attached file: - - SET RF 1P one platter (256K) - SET RF 2P two platters (512K) - SET RF 3P three platters (768K) - SET RF 4P four platters (1024K) - SET RF 5P five platters (1280K) - SET RF 6P six platters (1536K) - SET RF 7P seven platters (1792K) - SET RF 8P eight platters (2048K) - SET RF AUTOSIZE autosized on attach - -The default is 1P (minimum size). - -The fixed head disk controller implements these registers: - - name size comments - - STAT 16 status - DA 16 disk address - MA 16 memory address - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 device disable flag - INT 1 interrupt pending flag - WLK 8 write lock switches - TIME 24 rotational delay, per sector - STOP_IOE 1 stop on I/O error - -The fixed head disk controller supports the BOOT command. - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -Fixed head disk data files are buffered in memory; therefore, end of file -and OS I/O errors cannot occur. - -2.4 Moving Head Disk (DP) - -Moving head disk options include the ability to make units write enabled or -write locked, and to select the type of drive: - - SET DPn LOCKED set unit n write locked - SET DPn WRITEENABLED set unit n write enabled - SET DPn FLOPPY set unit n to floppy disk - SET DPn D31 set unit n to Diablo 31 - SET DPn D44 set unit n to Diablo 44 - SET DPn C111 set unit n to Century 111 - SET DPn C114 set unit n to Century 114 - SET DPn 6225 set unit n to 6225 - SET DPn 6099 set unit n to 6099 - SET DPn 6227 set unit n to 6227 - SET DPn 6070 set unit n to 6070 - SET DPn 6103 set unit n to 6103 - SET DPn 4231 set unit n to 4231 - -Units can also be set ONLINE or OFFLINE. The moving head disk controller -supports the BOOT command. - -All drives have 256 16b words per sector. The other disk parameters are: - - drive cylinders surfaces sectors size (MW) DG models - - floppy 77 1 8 .158 6038 - D31 203 2 12 1.247 4047, 4237, 4238 - D44 408 4 12 5.014 4234, 6045 - C111 203 10 6 3.118 4048 - C114 203 20 12 12.472 4057, 2314 - 6225 245 2 20 2.508 - 6099 192 4 32 6.291 - 6227 245 6 20 7.526 - 6070 408 4 24 10.027 - 6103 192 8 32 12.583 - 4231 411 19 23 45.979 - -The moving head disk controller implements these registers: - - name size comments - - FCCY 16 flags, command, cylinder - USSC 16 unit, surface, sector, count - STAT 16 status - MA 16 memory address - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - -Error handling is as follows: - - error processed as - - not attached disk not ready - - end of file assume rest of disk is zero - - OS I/O error report error and stop - -2.5 Magnetic Tape (MT) - -Magnetic tape options include the ability to make units write enabled or -or write locked. - - SET MTn LOCKED set unit n write locked - SET MTn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFLINE. The magnetic tape controller -supports the BOOT command. - -The magnetic tape controller implements these registers: - - name size comments - - CU 16 command, unit - MA 16 memory address - WC 16 word count - STA1 16 status word 1 - STA2 16 status word 2 - EP 1 extended polling mode (not supported) - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - STOP_IOE 1 stop on I/O error - CTIME 24 controller delay - RTIME 24 record delay - UST[0:7] 32 unit status, units 0-7 - POS[0:7] 31 position, units 0-7 - -Error handling is as follows: - - error processed as - - not attached tape not ready - - end of file bad tape - - OS I/O error report error and stop - -2.6 Symbolic Display and Input - -The Nova simulator implements symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as two character ASCII string - -m display instruction mnemonics - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or -a ASCII character - " or -c two character ASCII string - alphabetic instruction mnemonic - numeric octal number - -Instruction input uses standard Nova assembler syntax. There are three -instruction classes: memory reference, IOT, and operate. - -Memory reference instructions have the format - - memref {ac,}{@}address{,index} - -LDA and STA require an initial register; ISZ, DSZ, JSR, and JMP do not. -The syntax for addresses and indices is as follows: - -syntax mode displacement comments - -0 <= n < 0400 0 n -{+/-}n >= 0400 1 {+/-}n - PC must be in range [-200, 177] - invalid on disk -.+/-n 1 {+/-}n must be in range [-200, 177] -{+/-}n,2 2 {+/-}n must be in range [-200, 177] -{+/-}n,3 3 {+/-}n must be in range [-200, 177] - -IOT instructions have one of four formats - - syntax example - - iot HALT - iot reg INTA - iot device SKPDN - iot reg,device DOAS - -Devices may be specified as mnemonics or as numbers in the range 0 - 077. - -Operate instructions have the format - - opcode{#} reg,reg{,skip} - -In all Nova instructions, blanks may be substituted for commas as field -delimiters. diff --git a/NOVA/nova_dsk.c b/NOVA/nova_dsk.c deleted file mode 100644 index d1fbc04a..00000000 --- a/NOVA/nova_dsk.c +++ /dev/null @@ -1,298 +0,0 @@ -/* nova_dsk.c: 4019 fixed head disk simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - dsk fixed head disk - - 26-Jul-03 RMS Fixed bug in set size routine - 14-Mar-03 RMS Fixed variable capacity interaction with save/restore - 03-Mar-03 RMS Fixed variable capacity and autosizing - 03-Oct-02 RMS Added DIB - 06-Jan-02 RMS Revised enable/disable support - 23-Aug-01 RMS Fixed bug in write watermarking - 26-Apr-01 RMS Added device enable/disable support - 10-Dec-00 RMS Added Eclipse support - 15-Oct-00 RMS Editorial changes - 14-Apr-99 RMS Changed t_addr to unsigned - - The 4019 is a head-per-track disk. To minimize overhead, the entire disk - is buffered in memory. -*/ - -#include "nova_defs.h" -#include - -#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */ -#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */ -#define UNIT_M_PLAT 07 -#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT) -#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT) - -/* Constants */ - -#define DSK_NUMWD 256 /* words/sector */ -#define DSK_NUMSC 8 /* sectors/track */ -#define DSK_NUMTR 128 /* tracks/disk */ -#define DSK_DKSIZE (DSK_NUMTR*DSK_NUMSC*DSK_NUMWD) /* words/disk */ -#define DSK_AMASK ((DSK_NUMDK*DSK_NUMTR*DSK_NUMSC) - 1) /* address mask */ -#define DSK_NUMDK 8 /* disks/controller */ -#define GET_DISK(x) (((x) / (DSK_NUMSC * DSK_NUMTR)) & (DSK_NUMDK - 1)) - -/* Parameters in the unit descriptor */ - -#define FUNC u4 /* function */ - -/* Status register */ - -#define DSKS_WLS 020 /* write lock status */ -#define DSKS_DLT 010 /* data late error */ -#define DSKS_NSD 004 /* non-existent disk */ -#define DSKS_CRC 002 /* parity error */ -#define DSKS_ERR 001 /* error summary */ -#define DSKS_ALLERR (DSKS_WLS | DSKS_DLT | DSKS_NSD | DSKS_CRC | DSKS_ERR) - -/* Map logical sector numbers to physical sector numbers - (indexed by track<2:0>'sector) -*/ - -static const int32 sector_map[] = { - 0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 2, 4, 6, 0, - 2, 4, 6, 0, 3, 5, 7, 1, 3, 5, 7, 1, 4, 6, 0, 2, - 4, 6, 0, 2, 5, 7, 1, 3, 5, 7, 1, 3, 6, 0, 2, 4, - 6, 0, 2, 4, 7, 1, 3, 5, 7, 1, 3, 5, 0, 2, 4, 6 }; - -#define DSK_MMASK 077 -#define GET_SECTOR(x) ((int) fmod (sim_gtime() / ((double) (x)), \ - ((double) DSK_NUMSC))) - -extern uint16 M[]; -extern UNIT cpu_unit; -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 dsk_stat = 0; /* status register */ -int32 dsk_da = 0; /* disk address */ -int32 dsk_ma = 0; /* memory address */ -int32 dsk_wlk = 0; /* wrt lock switches */ -int32 dsk_stopioe = 1; /* stop on error */ -int32 dsk_time = 100; /* time per sector */ - -DEVICE dsk_dev; -int32 dsk (int32 pulse, int32 code, int32 AC); -t_stat dsk_svc (UNIT *uptr); -t_stat dsk_reset (DEVICE *dptr); -t_stat dsk_boot (int32 unitno, DEVICE *dptr); -t_stat dsk_attach (UNIT *uptr, char *cptr); -t_stat dsk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* DSK data structures - - dsk_dev device descriptor - dsk_unit unit descriptor - dsk_reg register list -*/ - -DIB dsk_dib = { DEV_DSK, INT_DSK, PI_DSK, &dsk }; - -UNIT dsk_unit = - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, - DSK_DKSIZE) }; - -REG dsk_reg[] = { - { ORDATA (STAT, dsk_stat, 16) }, - { ORDATA (DA, dsk_da, 16) }, - { ORDATA (MA, dsk_ma, 16) }, - { FLDATA (BUSY, dev_busy, INT_V_DSK) }, - { FLDATA (DONE, dev_done, INT_V_DSK) }, - { FLDATA (DISABLE, dev_disable, INT_V_DSK) }, - { FLDATA (INT, int_req, INT_V_DSK) }, - { ORDATA (WLK, dsk_wlk, 8) }, - { DRDATA (TIME, dsk_time, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, dsk_stopioe, 0) }, - { NULL } }; - -MTAB dsk_mod[] = { - { UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &dsk_set_size }, - { UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &dsk_set_size }, - { UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &dsk_set_size }, - { UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &dsk_set_size }, - { UNIT_PLAT, (4 << UNIT_V_PLAT), NULL, "5P", &dsk_set_size }, - { UNIT_PLAT, (5 << UNIT_V_PLAT), NULL, "6P", &dsk_set_size }, - { UNIT_PLAT, (6 << UNIT_V_PLAT), NULL, "7P", &dsk_set_size }, - { UNIT_PLAT, (7 << UNIT_V_PLAT), NULL, "8P", &dsk_set_size }, - { UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL }, - { 0 } }; - -DEVICE dsk_dev = { - "DK", &dsk_unit, dsk_reg, dsk_mod, - 1, 8, 21, 1, 8, 16, - NULL, NULL, &dsk_reset, - &dsk_boot, &dsk_attach, NULL, - &dsk_dib, DEV_DISABLE }; - -/* IOT routine */ - -int32 dsk (int32 pulse, int32 code, int32 AC) -{ -int32 t, rval; - -rval = 0; -switch (code) { /* decode IR<5:7> */ -case ioDIA: /* DIA */ - rval = dsk_stat & DSKS_ALLERR; /* read status */ - break; -case ioDOA: /* DOA */ - dsk_da = AC & DSK_AMASK; /* save disk addr */ - break; -case ioDIB: /* DIB */ - rval = dsk_ma & AMASK; /* read mem addr */ - break; -case ioDOB: /* DOB */ - dsk_ma = AC & AMASK; /* save mem addr */ - break; } /* end switch code */ - -if (pulse) { /* any pulse? */ - dev_busy = dev_busy & ~INT_DSK; /* clear busy */ - dev_done = dev_done & ~INT_DSK; /* clear done */ - int_req = int_req & ~INT_DSK; /* clear int */ - dsk_stat = 0; /* clear status */ - sim_cancel (&dsk_unit); } /* stop I/O */ - -if ((pulse == iopP) && ((dsk_wlk >> GET_DISK (dsk_da)) & 1)) { /* wrt lock? */ - dev_done = dev_done | INT_DSK; /* set done */ - int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); - dsk_stat = DSKS_ERR + DSKS_WLS; /* set status */ - return rval; } - -if (pulse & 1) { /* read or write? */ - if (((uint32) (dsk_da * DSK_NUMWD)) >= dsk_unit.capac) { /* inv sev? */ - dev_done = dev_done | INT_DSK; /* set done */ - int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); - dsk_stat = DSKS_ERR + DSKS_NSD; /* set status */ - return rval; } /* done */ - dsk_unit.FUNC = pulse; /* save command */ - dev_busy = dev_busy | INT_DSK; /* set busy */ - t = sector_map[dsk_da & DSK_MMASK] - GET_SECTOR (dsk_time); - if (t < 0) t = t + DSK_NUMSC; - sim_activate (&dsk_unit, t * dsk_time); } /* activate */ -return rval; -} - -/* Unit service */ - -t_stat dsk_svc (UNIT *uptr) -{ -int32 i, da, pa; - -dev_busy = dev_busy & ~INT_DSK; /* clear busy */ -dev_done = dev_done | INT_DSK; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); - -if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ - dsk_stat = DSKS_ERR + DSKS_NSD; /* set status */ - return IORETURN (dsk_stopioe, SCPE_UNATT); } - -da = dsk_da * DSK_NUMWD; /* calc disk addr */ -if (uptr->FUNC == iopS) { /* read? */ - for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */ - pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */ - if (MEM_ADDR_OK (pa)) M[pa] = - *(((int16 *) uptr->filebuf) + da + i); } - dsk_ma = (dsk_ma + DSK_NUMWD) & AMASK; } -if (uptr->FUNC == iopP) { /* write? */ - for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */ - pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */ - *(((int16 *) uptr->filebuf) + da + i) = M[pa]; } - if (((uint32) (da + i)) >= uptr->hwmark) /* past end? */ - uptr->hwmark = da + i + 1; /* upd hwmark */ - dsk_ma = (dsk_ma + DSK_NUMWD + 3) & AMASK; } - -dsk_stat = 0; /* set status */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat dsk_reset (DEVICE *dptr) -{ -dsk_stat = dsk_da = dsk_ma = 0; -dev_busy = dev_busy & ~INT_DSK; /* clear busy */ -dev_done = dev_done & ~INT_DSK; /* clear done */ -int_req = int_req & ~INT_DSK; /* clear int */ -sim_cancel (&dsk_unit); -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define BOOT_START 2000 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) - -static const int32 boot_rom[] = { - 060220, /* NIOC DSK ; clear disk */ - 0102400, /* SUB 0,0 ; addr = 0 */ - 061020, /* DOA 0,DSK ; set disk addr */ - 062120, /* DOBS 0,DSK ; set mem addr, rd */ - 063620, /* SKPDN DSK ; done? */ - 000776, /* JMP .-2 */ - 000377, /* JMP 377 */ -}; - -t_stat dsk_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat dsk_attach (UNIT *uptr, char *cptr) -{ -uint32 sz, p; -uint32 ds_bytes = DSK_DKSIZE * sizeof (int16); - -if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) { - p = (sz + ds_bytes - 1) / ds_bytes; - if (p >= DSK_NUMDK) p = DSK_NUMDK - 1; - uptr->flags = (uptr->flags & ~UNIT_PLAT) | - (p << UNIT_V_PLAT); } -uptr->capac = UNIT_GETP (uptr->flags) * DSK_DKSIZE; /* set capacity */ -return attach_unit (uptr, cptr); -} - -/* Change disk size */ - -t_stat dsk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (val < 0) return SCPE_IERR; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = UNIT_GETP (val) * DSK_DKSIZE; -uptr->flags = uptr->flags & ~UNIT_AUTO; -return SCPE_OK; -} diff --git a/NOVA/nova_lp.c b/NOVA/nova_lp.c deleted file mode 100644 index 36817c27..00000000 --- a/NOVA/nova_lp.c +++ /dev/null @@ -1,124 +0,0 @@ -/* nova_lp.c: NOVA line printer simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - lpt line printer - - 25-Apr-03 RMS Revised for extended file support - 30-May-02 RMS Widened POS to 32b -*/ - -#include "nova_defs.h" - -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 lpt_stopioe = 0; /* stop on error */ - -int32 lpt (int32 pulse, int32 code, int32 AC); -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list -*/ - -DIB lpt_dib = { DEV_LPT, INT_LPT, PI_LPT, &lpt }; - -UNIT lpt_unit = { - UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lpt_reg[] = { - { ORDATA (BUF, lpt_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_LPT) }, - { FLDATA (DONE, dev_done, INT_V_LPT) }, - { FLDATA (DISABLE, dev_disable, INT_V_LPT) }, - { FLDATA (INT, int_req, INT_V_LPT) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lpt_stopioe, 0) }, - { NULL } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lpt_reset, - NULL, NULL, NULL, - &lpt_dib, DEV_DISABLE }; - -/* IOT routine */ - -int32 lpt (int32 pulse, int32 code, int32 AC) -{ - -if (code == ioDOA) lpt_unit.buf = AC & 0177; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_LPT; /* set busy */ - dev_done = dev_done & ~INT_LPT; /* clear done, int */ - int_req = int_req & ~INT_LPT; - if ((lpt_unit.buf != 015) && (lpt_unit.buf != 014) && - (lpt_unit.buf != 012)) - return (lpt_svc (&lpt_unit) << IOT_V_REASON); - sim_activate (&lpt_unit, lpt_unit.wait); - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_LPT; /* clear busy */ - dev_done = dev_done & ~INT_LPT; /* clear done, int */ - int_req = int_req & ~INT_LPT; - sim_cancel (&lpt_unit); /* deactivate unit */ - break; } /* end switch */ -return 0; -} - -/* Unit service */ - -t_stat lpt_svc (UNIT *uptr) -{ -dev_busy = dev_busy & ~INT_LPT; /* clear busy */ -dev_done = dev_done | INT_LPT; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); -if (putc (lpt_unit.buf, lpt_unit.fileref) == EOF) { - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } -lpt_unit.pos = lpt_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ -lpt_unit.buf = 0; -dev_busy = dev_busy & ~INT_LPT; /* clear busy */ -dev_done = dev_done & ~INT_LPT; /* clear done, int */ -int_req = int_req & ~INT_LPT; -sim_cancel (&lpt_unit); /* deactivate unit */ -return SCPE_OK; -} diff --git a/NOVA/nova_mta.c b/NOVA/nova_mta.c deleted file mode 100644 index e965da73..00000000 --- a/NOVA/nova_mta.c +++ /dev/null @@ -1,589 +0,0 @@ -/* nova_mta.c: NOVA magnetic tape simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - mta magnetic tape - - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Revised for magtape library - 30-Oct-02 RMS Fixed BOT handling, added error record handling - 08-Oct-02 RMS Added DIB - 30-Sep-02 RMS Revamped error handling - 28-Aug-02 RMS Added end of medium support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Added maximum record length test - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Changed POS, USTAT, FLG to an array - 26-Apr-01 RMS Added device enable/disable support - 18-Apr-01 RMS Changed to rewind tape before boot - 10-Dec-00 RMS Added Eclipse support from Charles Owen - 15-Oct-00 RMS Editorial changes - 11-Nov-98 CEO Removed clear of mta_ma on iopC - 04-Oct-98 RMS V2.4 magtape format - 18-Jan-97 RMS V2.3 magtape format - 29-Jun-96 RMS Added unit enable/disable support - - Magnetic tapes are represented as a series of variable records - of the form: - - 32b byte count byte count is little endian - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32b byte count - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a byte count of 0 and are - not duplicated; end of tape by end of file. -*/ - -#include "nova_defs.h" -#include "sim_tape.h" - -#define MTA_NUMDR 8 /* #drives */ -#define USTAT u3 /* unit status */ -#define MTA_MAXFR (1 << 16) /* max record lnt */ -#define WC_SIZE (1 << 14) /* max word count */ -#define WC_MASK (WC_SIZE - 1) - -/* Command/unit */ - -#define CU_CI 0100000 /* clear interrupt */ -#define CU_EP 0002000 /* poll enable */ -#define CU_DE 0001000 /* disable erase */ -#define CU_DA 0000400 /* disable autoretry */ -#define CU_PE 0000400 /* PE mode */ -#define CU_V_CMD 3 /* command */ -#define CU_M_CMD 027 -#define CU_READ 000 -#define CU_REWIND 001 -#define CU_CMODE 002 -#define CU_SPACEF 003 -#define CU_SPACER 004 -#define CU_WRITE 005 -#define CU_WREOF 006 -#define CU_ERASE 007 -#define CU_READNS 020 -#define CU_UNLOAD 021 -#define CU_DMODE 022 -#define CU_V_UNIT 0 /* unit */ -#define CU_M_UNIT 07 -#define GET_CMD(x) (((x) >> CU_V_CMD) & CU_M_CMD) -#define GET_UNIT(x) (((x) >> CU_V_UNIT) & CU_M_UNIT) - -/* Status 1 - stored in mta_sta<31:16> or (*) uptr->USTAT<31:16> */ - -#define STA_ERR1 (0100000u << 16) /* error */ -#define STA_DLT (0040000 << 16) /* data late */ -#define STA_REW (0020000 << 16) /* *rewinding */ -#define STA_ILL (0010000 << 16) /* illegal */ -#define STA_HDN (0004000 << 16) /* high density */ -#define STA_DAE (0002000 << 16) /* data error */ -#define STA_EOT (0001000 << 16) /* *end of tape */ -#define STA_EOF (0000400 << 16) /* *end of file */ -#define STA_BOT (0000200 << 16) /* *start of tape */ -#define STA_9TK (0000100 << 16) /* nine track */ -#define STA_BAT (0000040 << 16) /* bad tape */ -#define STA_CHG (0000010 << 16) /* status change */ -#define STA_WLK (0000004 << 16) /* *write lock */ -#define STA_ODD (0000002 << 16) /* odd character */ -#define STA_RDY (0000001 << 16) /* *drive ready */ - -/* Status 2 - stored in mta_sta<15:0> or (*) uptr->USTAT<15:0> */ - -#define STA_ERR2 0100000 /* error */ -#define STA_RWY 0040000 /* runaway tape */ -#define STA_FGP 0020000 /* false gap */ -#define STA_CDL 0004000 /* corrected dlt */ -#define STA_V_UNIT 8 -#define STA_M_UNIT 07 /* unit */ -#define STA_WCO 0000200 /* word count ovflo */ -#define STA_BDS 0000100 /* bad signal */ -#define STA_OVS 0000040 /* overskew */ -#define STA_CRC 0000020 /* check error */ -#define STA_STE 0000010 /* single trk error */ -#define STA_FPR 0000004 /* false preamble */ -#define STA_FMT 0000002 /* format error */ -#define STA_PEM 0000001 /* *PE mode */ - -#define STA_EFLGS1 (STA_DLT | STA_ILL | STA_DAE | STA_EOT | \ - STA_EOF | STA_BOT | STA_BAT | STA_ODD) -#define STA_EFLGS2 (STA_FGP | STA_CDL | STA_BDS | STA_OVS | \ - STA_CRC | STA_FPR | STA_FPR) /* set error 2 */ -#define STA_CLR ((020 << 16) | 0010000) /* always clear */ -#define STA_SET (STA_HDN | STA_9TK) /* always set */ -#define STA_DYN (STA_REW | STA_EOT | STA_EOF | STA_BOT | \ - STA_WLK | STA_RDY | STA_PEM) /* kept in USTAT */ -#define STA_MON (STA_REW | STA_BOT | STA_WLK | STA_RDY | \ - STA_PEM) /* set status chg */ - -extern uint16 M[]; -extern UNIT cpu_unit; -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 mta_ma = 0; /* memory address */ -int32 mta_wc = 0; /* word count */ -int32 mta_cu = 0; /* command/unit */ -int32 mta_sta = 0; /* status register */ -int32 mta_ep = 0; /* enable polling */ -int32 mta_cwait = 100; /* command latency */ -int32 mta_rwait = 100; /* record latency */ -uint8 *mtxb = NULL; /* transfer buffer */ - -DEVICE mta_dev; -int32 mta (int32 pulse, int32 code, int32 AC); -t_stat mta_svc (UNIT *uptr); -t_stat mta_reset (DEVICE *dptr); -t_stat mta_boot (int32 unitno, DEVICE *dptr); -t_stat mta_attach (UNIT *uptr, char *cptr); -t_stat mta_detach (UNIT *uptr); -int32 mta_updcsta (UNIT *uptr); -void mta_upddsta (UNIT *uptr, int32 newsta); -t_stat mta_map_err (UNIT *uptr, t_stat st); -t_stat mta_vlock (UNIT *uptr, int32 val, char *cptr, void *desc); - -static const int ctype[32] = { /* c vs r timing */ - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1 }; - -/* MTA data structures - - mta_dev MTA device descriptor - mta_unit MTA unit list - mta_reg MTA register list - mta_mod MTA modifier list -*/ - -DIB mta_dib = { DEV_MTA, INT_MTA, PI_MTA, &mta }; - -UNIT mta_unit[] = { - { UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) } }; - -REG mta_reg[] = { - { ORDATA (CU, mta_cu, 16) }, - { ORDATA (MA, mta_ma, 16) }, - { ORDATA (WC, mta_wc, 16) }, - { GRDATA (STA1, mta_sta, 8, 16, 16) }, - { ORDATA (STA2, mta_sta, 16) }, - { FLDATA (EP, mta_ep, 0) }, - { FLDATA (BUSY, dev_busy, INT_V_MTA) }, - { FLDATA (DONE, dev_done, INT_V_MTA) }, - { FLDATA (DISABLE, dev_disable, INT_V_MTA) }, - { FLDATA (INT, int_req, INT_V_MTA) }, - { DRDATA (CTIME, mta_cwait, 24), PV_LEFT }, - { DRDATA (RTIME, mta_rwait, 24), PV_LEFT }, - { URDATA (UST, mta_unit[0].USTAT, 8, 32, 0, MTA_NUMDR, 0) }, - { URDATA (POS, mta_unit[0].pos, 8, T_ADDR_W, 0, - MTA_NUMDR, REG_RO | PV_LEFT) }, - { NULL } }; - -MTAB mta_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", &mta_vlock }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &mta_vlock }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { 0 } }; - -DEVICE mta_dev = { - "MT", mta_unit, mta_reg, mta_mod, - MTA_NUMDR, 10, 31, 1, 8, 8, - NULL, NULL, &mta_reset, - &mta_boot, &mta_attach, &mta_detach, - &mta_dib, DEV_DISABLE }; - -/* IOT routine */ - -int32 mta (int32 pulse, int32 code, int32 AC) -{ -UNIT *uptr; -int32 u, c, rval; - -rval = 0; -uptr = mta_dev.units + GET_UNIT(mta_cu); /* get unit */ -switch (code) { /* decode IR<5:7> */ -case ioDIA: /* DIA */ - rval = (mta_updcsta (uptr) >> 16) & DMASK; /* return status 1 */ - break; -case ioDOA: /* DOA */ -/* if (AC & CU_CI) ... clear ep int */ - mta_cu = AC; /* save cmd/unit */ - uptr = mta_dev.units + GET_UNIT(mta_cu); /* get unit */ - mta_updcsta (uptr); /* update status */ - break; -case ioDIB: /* DIB */ - rval = mta_ma & AMASK; /* return ma */ - break; -case ioDOB: /* DOB */ - mta_ma = AC & AMASK; /* save ma */ - break; -case ioDIC: /* DIC */ - rval = mta_updcsta (uptr) & DMASK; /* return status 2 */ - break; -case ioDOC: /* DOC */ - mta_wc = ((AC & 040000) << 1) | (AC & 077777); /* save wc */ - break; } /* end switch code */ - -/* IOT, continued */ - -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - c = GET_CMD (mta_cu); /* get command */ - if (dev_busy & INT_MTA) break; /* ignore if busy */ - if ((uptr->USTAT & STA_RDY) == 0) { /* drive not ready? */ - mta_sta = mta_sta | STA_ILL; /* illegal op */ - dev_busy = dev_busy & ~INT_MTA; /* clear busy */ - dev_done = dev_done | INT_MTA; /* set done */ - int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); } - else if ((c == CU_REWIND) || (c == CU_UNLOAD)) { /* rewind, unload? */ - mta_upddsta (uptr, (uptr->USTAT & /* update status */ - ~(STA_BOT | STA_EOF | STA_EOT | STA_RDY)) | STA_REW); - sim_activate (uptr, mta_rwait); /* start IO */ - if (c == CU_UNLOAD) detach_unit (uptr); } - else { - mta_sta = 0; /* clear errors */ - dev_busy = dev_busy | INT_MTA; /* set busy */ - dev_done = dev_done & ~INT_MTA; /* clear done */ - int_req = int_req & ~INT_MTA; /* clear int */ - if (ctype[c]) sim_activate (uptr, mta_cwait); - else { - mta_upddsta (uptr, uptr->USTAT & - ~(STA_BOT | STA_EOF | STA_EOT | STA_RDY)); - sim_activate (uptr, mta_rwait); } } - mta_updcsta (uptr); /* update status */ - break; -case iopC: /* clear */ - for (u = 0; u < MTA_NUMDR; u++) { /* loop thru units */ - uptr = mta_dev.units + u; /* cancel IO */ - if (sim_is_active (uptr) && !(uptr->USTAT & STA_REW)) { - mta_upddsta (uptr, uptr->USTAT | STA_RDY); - sim_cancel (uptr); } } - dev_busy = dev_busy & ~INT_MTA; /* clear busy */ - dev_done = dev_done & ~INT_MTA; /* clear done */ - int_req = int_req & ~INT_MTA; /* clear int */ - mta_sta = mta_cu = 0; /* clear registers */ - mta_updcsta (&mta_unit[0]); /* update status */ - break; } /* end case pulse */ -return rval; -} - -/* Unit service - - If rewind done, reposition to start of tape, set status - else, do operation, clear busy, set done, interrupt -*/ - -t_stat mta_svc (UNIT *uptr) -{ -int32 c, p, pa, u; -t_mtrlnt i, cbc, tbc, wc; -uint16 c1, c2; -t_stat st, r = SCPE_OK; - -u = uptr - mta_dev.units; /* get unit number */ -c = GET_CMD (mta_cu); /* command */ -wc = WC_SIZE - (mta_wc & WC_MASK); /* io wc */ - -if (uptr->USTAT & STA_REW) { /* rewind? */ - sim_tape_rewind (uptr); /* update tape */ - mta_upddsta (uptr, (uptr->USTAT & ~STA_REW) | STA_BOT | STA_RDY); - if (u == GET_UNIT (mta_cu)) mta_updcsta (uptr); - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - mta_upddsta (uptr, 0); /* unit off line */ - mta_sta = mta_sta | STA_ILL; } /* illegal operation */ -else switch (c) { /* case on command */ - -case CU_CMODE: /* controller mode */ - mta_ep = mta_cu & CU_EP; - break; -case CU_DMODE: /* drive mode */ - if (!sim_tape_bot (uptr)) mta_sta = mta_sta | STA_ILL; /* must be BOT */ - else mta_upddsta (uptr, (mta_cu & CU_PE)? /* update drv status */ - uptr->USTAT | STA_PEM: uptr->USTAT & ~ STA_PEM); - break; - -/* Unit service, continued */ - -case CU_READ: /* read */ -case CU_READNS: /* read non-stop */ - st = sim_tape_rdrecf (uptr, mtxb, &tbc, MTA_MAXFR); /* read rec */ - if (st == MTSE_RECE) mta_sta = mta_sta | STA_DAE; /* rec in err? */ - else if (st != MTSE_OK) { /* other error? */ - r = mta_map_err (uptr, st); /* map error */ - break; } - cbc = wc * 2; /* expected bc */ - if (tbc & 1) mta_sta = mta_sta | STA_ODD; /* odd byte count? */ - if (tbc > cbc) mta_sta = mta_sta | STA_WCO; /* too big? */ - else { - cbc = tbc; /* no, use it */ - wc = (cbc + 1) / 2; } /* adjust wc */ - for (i = p = 0; i < wc; i++) { /* copy buf to mem */ - c1 = mtxb[p++]; - c2 = mtxb[p++]; - pa = MapAddr (0, mta_ma); /* map address */ - if (MEM_ADDR_OK (pa)) M[pa] = (c1 << 8) | c2; - mta_ma = (mta_ma + 1) & AMASK; } - mta_wc = (mta_wc + wc) & DMASK; - mta_upddsta (uptr, uptr->USTAT | STA_RDY); - break; - -case CU_WRITE: /* write */ - tbc = wc * 2; /* io byte count */ - for (i = p = 0; i < wc; i++) { /* copy to buffer */ - pa = MapAddr (0, mta_ma); /* map address */ - mtxb[p++] = (M[pa] >> 8) & 0377; - mtxb[p++] = M[pa] & 0377; - mta_ma = (mta_ma + 1) & AMASK; } - if (st = sim_tape_wrrecf (uptr, mtxb, tbc)) { /* write rec, err? */ - r = mta_map_err (uptr, st); /* map error */ - mta_ma = (mta_ma - wc) & AMASK; } /* restore wc */ - else mta_wc = 0; /* clear wc */ - mta_upddsta (uptr, uptr->USTAT | STA_RDY); - break; - -/* Unit service, continued */ - -case CU_WREOF: /* write eof */ - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = mta_map_err (uptr, st); /* map error */ - else mta_upddsta (uptr, uptr->USTAT | STA_EOF | STA_RDY); - break; - -case CU_ERASE: /* erase */ - if (sim_tape_wrp (uptr)) /* write protected? */ - r = mta_map_err (uptr, MTSE_WRP); /* map error */ - else mta_upddsta (uptr, uptr->USTAT | STA_RDY); - break; - -case CU_SPACEF: /* space forward */ - do { - mta_wc = (mta_wc + 1) & DMASK; /* incr wc */ - if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */ - r = mta_map_err (uptr, st); /* map error */ - break; } - } - while (mta_wc != 0); - mta_upddsta (uptr, uptr->USTAT | STA_RDY); - break; - -case CU_SPACER: /* space reverse */ - do { - mta_wc = (mta_wc + 1) & DMASK; /* incr wc */ - if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */ - r = mta_map_err (uptr, st); /* map error */ - break; } - } - while (mta_wc != 0); - mta_upddsta (uptr, uptr->USTAT | STA_RDY); - break; - -default: /* reserved */ - mta_sta = mta_sta | STA_ILL; - mta_upddsta (uptr, uptr->USTAT | STA_RDY); - break; } /* end case */ - -mta_updcsta (uptr); /* update status */ -dev_busy = dev_busy & ~INT_MTA; /* clear busy */ -dev_done = dev_done | INT_MTA; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -return r; -} - -/* Update controller status */ - -int32 mta_updcsta (UNIT *uptr) /* update ctrl */ -{ -mta_sta = (mta_sta & ~(STA_DYN | STA_CLR | STA_ERR1 | STA_ERR2)) | - (uptr->USTAT & STA_DYN) | STA_SET; -if (mta_sta & STA_EFLGS1) mta_sta = mta_sta | STA_ERR1; -if (mta_sta & STA_EFLGS2) mta_sta = mta_sta | STA_ERR2; -return mta_sta; -} - -/* Update drive status */ - -void mta_upddsta (UNIT *uptr, int32 newsta) /* drive status */ -{ -int32 change; - -if ((uptr->flags & UNIT_ATT) == 0) newsta = 0; /* offline? */ -change = (uptr->USTAT ^ newsta) & STA_MON; /* changes? */ -uptr->USTAT = newsta & STA_DYN; /* update status */ -if (change) { -/* if (mta_ep) { /* if polling */ -/* u = uptr - mta_dev.units; /* unit num */ -/* mta_sta = (mta_sta & ~STA_UNIT) | (u << STA_V_UNIT); -/* set polling interupt... } */ - mta_sta = mta_sta | STA_CHG; } /* flag change */ -return; -} - -/* Map tape error status */ - -t_stat mta_map_err (UNIT *uptr, t_stat st) -{ -switch (st) { -case MTSE_FMT: /* illegal fmt */ - mta_upddsta (uptr, uptr->USTAT | STA_WLK | STA_RDY); -case MTSE_UNATT: /* unattached */ - mta_sta = mta_sta | STA_ILL; -case MTSE_OK: /* no error */ - return SCPE_IERR; /* never get here! */ -case MTSE_TMK: /* end of file */ - mta_upddsta (uptr, uptr->USTAT | STA_RDY | STA_EOF); - break; -case MTSE_IOERR: /* IO error */ - mta_sta = mta_sta | STA_DAE; /* data error */ - mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */ - return SCPE_IOERR; -case MTSE_INVRL: /* invalid rec lnt */ - mta_sta = mta_sta | STA_DAE; /* data error */ - mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */ - return SCPE_MTRLNT; -case MTSE_RECE: /* record in error */ - mta_sta = mta_sta | STA_DAE; /* data error */ - mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */ - break; -case MTSE_EOM: /* end of medium */ - mta_sta = mta_sta | STA_BAT; /* bad tape */ - mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */ - break; -case MTSE_BOT: /* reverse into BOT */ - mta_upddsta (uptr, uptr->USTAT | STA_RDY | STA_BOT); - break; -case MTSE_WRP: /* write protect */ - mta_upddsta (uptr, uptr->USTAT | STA_WLK | STA_RDY); - mta_sta = mta_sta | STA_ILL; /* illegal operation */ - break; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat mta_reset (DEVICE *dptr) -{ -int32 u; -UNIT *uptr; - -dev_busy = dev_busy & ~INT_MTA; /* clear busy */ -dev_done = dev_done & ~INT_MTA; /* clear done, int */ -int_req = int_req & ~INT_MTA; -mta_cu = mta_wc = mta_ma = mta_sta = 0; /* clear registers */ -mta_ep = 0; -for (u = 0; u < MTA_NUMDR; u++) { /* loop thru units */ - uptr = mta_dev.units + u; - sim_tape_reset (uptr); /* clear pos flag */ - sim_cancel (uptr); /* cancel activity */ - if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_RDY | - (uptr->USTAT & STA_PEM) | - (sim_tape_wrp (uptr)? STA_WLK: 0) | - (sim_tape_bot (uptr)? STA_BOT: 0); - else uptr->USTAT = 0; } -mta_updcsta (&mta_unit[0]); /* update status */ -if (mtxb == NULL) mtxb = calloc (MTA_MAXFR, sizeof (uint8)); -if (mtxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat mta_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; -if (!sim_is_active (uptr)) mta_upddsta (uptr, STA_RDY | STA_BOT | STA_PEM | - (sim_tape_wrp (uptr)? STA_WLK: 0)); -return r; -} - -/* Detach routine */ - -t_stat mta_detach (UNIT* uptr) -{ -if (!sim_is_active (uptr)) mta_upddsta (uptr, 0); -return sim_tape_detach (uptr); -} - -/* Write lock/unlock validate routine */ - -t_stat mta_vlock (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if ((uptr->flags & UNIT_ATT) && (val || sim_tape_wrp (uptr))) - mta_upddsta (uptr, uptr->USTAT | STA_WLK); -else mta_upddsta (uptr, uptr->USTAT & ~STA_WLK); -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define BOOT_START 02000 -#define BOOT_UNIT 02020 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) - -static const int32 boot_rom[] = { - 060222, /* NIOC 0,MTA ; clear disk */ - 020417, /* LDA 0,UNIT ; unit */ - 024417, /* LDA 1,REWIND ; cmd */ - 0107000, /* ADD 0,1 ; cmd + unit */ - 065122, /* DOAS 1,MTA ; start rewind */ - 070422, /* DIA 2,MTA ; get status */ - 0151213, /* MOVR# 2,2,SNC ; skip if done */ - 000776, /* JMP .-2 */ - 0126400, /* SUB 1,1 ; ma, wc = 0 */ - 066022, /* DOB 1,MTA */ - 067022, /* DOC 1,MTA */ - 061122, /* DOAS 0,MTA ; start read */ - 070422, /* DIA 2,MTA ; get status */ - 0151213, /* MOVR# 2,2,SNC ; skip if done */ - 000776, /* JMP .-2 */ - 000377, /* JMP 377 */ - 000000, /* UNIT: */ - 000010 /* REWIND: 10 */ -}; - -t_stat mta_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -sim_tape_rewind (&mta_unit[unitno]); -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -M[BOOT_UNIT] = (unitno & CU_M_UNIT) << CU_V_UNIT; -saved_PC = BOOT_START; -return SCPE_OK; -} diff --git a/NOVA/nova_plt.c b/NOVA/nova_plt.c deleted file mode 100644 index f954733e..00000000 --- a/NOVA/nova_plt.c +++ /dev/null @@ -1,125 +0,0 @@ -/* nova_plt.c: NOVA plotter simulator - - Copyright (c) 2000-2003, Robert M. Supnik - Written by Bruce Ray and used with his gracious permission. - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - plt plotter - - 25-Apr-03 RMS Revised for extended file support - 03-Oct-02 RMS Added DIB - 30-May-02 RMS Widened POS to 32b - 06-Jan-02 RMS Revised enable/disable support - 26-Apr-01 RMS Added device enable/disable support -*/ - -#include "nova_defs.h" - -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 plt_stopioe = 0; /* stop on error */ - -DEVICE plt_dev; -int32 plt (int32 pulse, int32 code, int32 AC); -t_stat plt_svc (UNIT *uptr); -t_stat plt_reset (DEVICE *dptr); - -/* PLT data structures - - plt_dev PLT device descriptor - plt_unit PLT unit descriptor - plt_reg PLT register list -*/ - -DIB plt_dib = { DEV_PLT, INT_PLT, PI_PLT, &plt }; - -UNIT plt_unit = { - UDATA (&plt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG plt_reg[] = { - { ORDATA (BUF, plt_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_PLT) }, - { FLDATA (DONE, dev_done, INT_V_PLT) }, - { FLDATA (DISABLE, dev_disable, INT_V_PLT) }, - { FLDATA (INT, int_req, INT_V_PLT) }, - { DRDATA (POS, plt_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, plt_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, plt_stopioe, 0) }, - { NULL } }; - -DEVICE plt_dev = { - "PLT", &plt_unit, plt_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &plt_reset, - NULL, NULL, NULL, - &plt_dib, DEV_DISABLE }; - -/* plotter: IOT routine */ - -int32 plt (int32 pulse, int32 code, int32 AC) -{ -if (code == ioDOA) plt_unit.buf = AC & 0377; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_PLT; /* set busy */ - dev_done = dev_done & ~INT_PLT; /* clear done, int */ - int_req = int_req & ~INT_PLT; - sim_activate (&plt_unit, plt_unit.wait); /* activate unit */ - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_PLT; /* clear busy */ - dev_done = dev_done & ~INT_PLT; /* clear done, int */ - int_req = int_req & ~INT_PLT; - sim_cancel (&plt_unit); /* deactivate unit */ - break; } /* end switch */ -return 0; -} - -/* Unit service */ - -t_stat plt_svc (UNIT *uptr) -{ -dev_busy = dev_busy & ~INT_PLT; /* clear busy */ -dev_done = dev_done | INT_PLT; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -if ((plt_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (plt_stopioe, SCPE_UNATT); -if (putc (plt_unit.buf, plt_unit.fileref) == EOF) { - perror ("PLT I/O error"); - clearerr (plt_unit.fileref); - return SCPE_IOERR; } -plt_unit.pos = plt_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat plt_reset (DEVICE *dptr) -{ -plt_unit.buf = 0; -dev_busy = dev_busy & ~INT_PLT; /* clear busy */ -dev_done = dev_done & ~INT_PLT; /* clear done, int */ -int_req = int_req & ~INT_PLT; -sim_cancel (&plt_unit); /* deactivate unit */ -return SCPE_OK; -} diff --git a/NOVA/nova_pt.c b/NOVA/nova_pt.c deleted file mode 100644 index 33333d91..00000000 --- a/NOVA/nova_pt.c +++ /dev/null @@ -1,215 +0,0 @@ -/* nova_pt.c: NOVA paper tape read/punch simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - ptr paper tape reader - ptp paper tape punch - - 25-Apr-03 RMS Revised for extended file support - 03-Oct-02 RMS Added DIBs - 30-May-02 RMS Widened POS to 32b - 29-Nov-01 RMS Added read only unit support -*/ - -#include "nova_defs.h" - -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */ - -int32 ptr (int32 pulse, int32 code, int32 AC); -int32 ptp (int32 pulse, int32 code, int32 AC); -t_stat ptr_svc (UNIT *uptr); -t_stat ptp_svc (UNIT *uptr); -t_stat ptr_reset (DEVICE *dptr); -t_stat ptp_reset (DEVICE *dptr); - -/* PTR data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit descriptor - ptr_reg PTR register list -*/ - -DIB ptr_dib = { DEV_PTR, INT_PTR, PI_PTR, &ptr }; - -UNIT ptr_unit = { - UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), - SERIAL_IN_WAIT }; - -REG ptr_reg[] = { - { ORDATA (BUF, ptr_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_PTR) }, - { FLDATA (DONE, dev_done, INT_V_PTR) }, - { FLDATA (DISABLE, dev_disable, INT_V_PTR) }, - { FLDATA (INT, int_req, INT_V_PTR) }, - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptr_stopioe, 0) }, - { NULL } }; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - NULL, NULL, NULL, - &ptr_dib, 0 }; - -/* PTP data structures - - ptp_dev PTP device descriptor - ptp_unit PTP unit descriptor - ptp_reg PTP register list -*/ - -DIB ptp_dib = { DEV_PTP, INT_PTP, PI_PTP, &ptp }; - -UNIT ptp_unit = { - UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG ptp_reg[] = { - { ORDATA (BUF, ptp_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_PTP) }, - { FLDATA (DONE, dev_done, INT_V_PTP) }, - { FLDATA (DISABLE, dev_disable, INT_V_PTP) }, - { FLDATA (INT, int_req, INT_V_PTP) }, - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptp_stopioe, 0) }, - { NULL } }; - -DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptp_reset, - NULL, NULL, NULL, - &ptp_dib, 0 }; - -/* Paper tape reader: IOT routine */ - -int32 ptr (int32 pulse, int32 code, int32 AC) -{ -int32 iodata; - -iodata = (code == ioDIA)? ptr_unit.buf & 0377: 0; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_PTR; /* set busy */ - dev_done = dev_done & ~INT_PTR; /* clear done, int */ - int_req = int_req & ~INT_PTR; - sim_activate (&ptr_unit, ptr_unit.wait); /* activate unit */ - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_PTR; /* clear busy */ - dev_done = dev_done & ~INT_PTR; /* clear done, int */ - int_req = int_req & ~INT_PTR; - sim_cancel (&ptr_unit); /* deactivate unit */ - break; } /* end switch */ -return iodata; -} - -/* Unit service */ - -t_stat ptr_svc (UNIT *uptr) -{ -int32 temp; - -if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptr_stopioe, SCPE_UNATT); -if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */ - if (feof (ptr_unit.fileref)) { - if (ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } - else perror ("PTR I/O error"); - clearerr (ptr_unit.fileref); - return SCPE_IOERR; } -dev_busy = dev_busy & ~INT_PTR; /* clear busy */ -dev_done = dev_done | INT_PTR; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -ptr_unit.buf = temp & 0377; -ptr_unit.pos = ptr_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptr_reset (DEVICE *dptr) -{ -ptr_unit.buf = 0; -dev_busy = dev_busy & ~INT_PTR; /* clear busy */ -dev_done = dev_done & ~INT_PTR; /* clear done, int */ -int_req = int_req & ~INT_PTR; -sim_cancel (&ptr_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Paper tape punch: IOT routine */ - -int32 ptp (int32 pulse, int32 code, int32 AC) -{ -if (code == ioDOA) ptp_unit.buf = AC & 0377; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_PTP; /* set busy */ - dev_done = dev_done & ~INT_PTP; /* clear done, int */ - int_req = int_req & ~INT_PTP; - sim_activate (&ptp_unit, ptp_unit.wait); /* activate unit */ - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_PTP; /* clear busy */ - dev_done = dev_done & ~INT_PTP; /* clear done, int */ - int_req = int_req & ~INT_PTP; - sim_cancel (&ptp_unit); /* deactivate unit */ - break; } /* end switch */ -return 0; -} - -/* Unit service */ - -t_stat ptp_svc (UNIT *uptr) -{ -dev_busy = dev_busy & ~INT_PTP; /* clear busy */ -dev_done = dev_done | INT_PTP; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -if ((ptp_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptp_stopioe, SCPE_UNATT); -if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { - perror ("PTP I/O error"); - clearerr (ptp_unit.fileref); - return SCPE_IOERR; } -ptp_unit.pos = ptp_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptp_reset (DEVICE *dptr) -{ -ptp_unit.buf = 0; -dev_busy = dev_busy & ~INT_PTP; /* clear busy */ -dev_done = dev_done & ~INT_PTP; /* clear done, int */ -int_req = int_req & ~INT_PTP; -sim_cancel (&ptp_unit); /* deactivate unit */ -return SCPE_OK; -} diff --git a/NOVA/nova_sys.c b/NOVA/nova_sys.c deleted file mode 100644 index 6198ad65..00000000 --- a/NOVA/nova_sys.c +++ /dev/null @@ -1,957 +0,0 @@ -/* nova_sys.c: NOVA simulator interface - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 17-Sep-01 RMS Removed multiconsole support - 31-May-01 RMS Added multiconsole support - 14-Mar-01 RMS Revised load/dump interface (again) - 22-Dec-00 RMS Added second terminal support - 10-Dec-00 RMS Added Eclipse support - 08-Dec-00 BKR Added plotter support - 30-Oct-00 RMS Added support for examine to file - 15-Oct-00 RMS Added stack, byte, trap instructions - 14-Apr-99 RMS Changed t_addr to unsigned - 27-Oct-98 RMS V2.4 load interface - 24-Sep-97 RMS Fixed bug in device name table (found by Charles Owen) -*/ - -#include "nova_defs.h" -#include - -extern DEVICE cpu_dev; -extern UNIT cpu_unit; -#if defined (ECLIPSE) -extern DEVICE map_dev; -#endif -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE plt_dev; -extern DEVICE tti_dev, tto_dev; -extern DEVICE tti1_dev, tto1_dev; -extern DEVICE clk_dev, lpt_dev; -extern DEVICE dkp_dev, dsk_dev; -extern DEVICE mta_dev; -extern UNIT tti_unit, tto_unit; -extern UNIT tti1_unit, tto1_unit; -extern REG cpu_reg[]; -extern uint16 M[]; -extern int32 saved_PC; - -/* SCP data structures - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words needed for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -#if defined (ECLIPSE) -char sim_name[] = "ECLIPSE"; -#else -char sim_name[] = "NOVA"; -#endif - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { - &cpu_dev, -#if defined (ECLIPSE) - &map_dev, -#endif - &ptr_dev, &ptp_dev, - &tti_dev, &tto_dev, - &tti1_dev, &tto1_dev, - &clk_dev, &plt_dev, - &lpt_dev, &dsk_dev, - &dkp_dev, &mta_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unknown I/O instruction", - "HALT instruction", - "Breakpoint", - "Nested indirect address limit exceeded", - "Nested indirect interrupt address limit exceeded", - "Nested indirect trap address limit exceeded", - "Read breakpoint", - "Write breakpoint" }; - -/* Binary loader - - Loader format consists of blocks, optionally preceded, separated, and - followed by zeroes. Each block consists of: - - lo_count - hi_count - lo_origin - hi_origin - lo_checksum - hi_checksum - lo_data byte --- - hi_data byte | - : > -count words - lo_data byte | - hi_data byte --- - - If the word count is [0,-20], then the block is normal data. - If the word count is [-21,-n], then the block is repeated data. - If the word count is 1, the block is the start address. - If the word count is >1, the block is an error block. -*/ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 data, csum, count, state, i; -uint32 origin; - -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; -state = 0; -while ((i = getc (fileref)) != EOF) { - switch (state) { - case 0: /* leader */ - count = i; - state = (count != 0); - break; - case 1: /* high count */ - csum = count = (i << 8) | count; - state = 2; - break; - case 2: /* low origin */ - origin = i; - state = 3; - break; - case 3: /* high origin */ - origin = (i << 8) | origin; - csum = csum + origin; - state = 4; - break; - case 4: /* low checksum */ - csum = csum + i; - state = 5; - break; - case 5: /* high checksum */ - csum = csum + (i << 8); - if (count == 1) saved_PC = origin; /* count = 1? */ - if (count <= 1) { /* count = 0/1? */ - if (csum & 0177777) return SCPE_CSUM; - state = 0; - break; } - if (count < 0100000) { /* count > 1 */ - state = 8; - break; } - count = 0200000 - count; - state = 6; - break; - case 6: /* low data */ - data = i; - state = 7; - break; - case 7: /* high data */ - data = (i << 8) | data; - csum = csum + data; - if (count > 20) { /* large block */ - for (count = count - 1; count == 1; count--) { - if (origin >= MEMSIZE) return SCPE_NXM; - M[origin] = data; - origin = origin + 1; } } - if (origin >= MEMSIZE) return SCPE_NXM; - M[origin] = data; - origin = origin + 1; - count = count - 1; - if (count == 0) { - if (csum & 0177777) return SCPE_CSUM; - state = 0; - break; } - state = 6; - break; - case 8: /* error block */ - if (i == 0377) state = 0; - break; } /* end switch */ - } /* end while */ - -/* Ok to find end of tape between blocks or in error state */ - -return ((state == 0) || (state == 8))? SCPE_OK: SCPE_FMT; -} - -/* Symbol tables */ - -#define I_V_FL 18 /* flag bits */ -#define I_M_FL 037 /* flag width */ -#define I_V_NPN 000 /* no operands */ -#define I_V_R 001 /* reg */ -#define I_V_D 002 /* device */ -#define I_V_RD 003 /* reg,device */ -#define I_V_M 004 /* mem addr */ -#define I_V_RM 005 /* reg,mem addr */ -#define I_V_RR 006 /* operate */ -#define I_V_BY 007 /* Nova byte pointer */ -#define I_V_2AC 010 /* reg,reg */ -#define I_V_RSI 011 /* reg,short imm */ -#define I_V_LI 012 /* long imm */ -#define I_V_RLI 013 /* reg,long imm */ -#define I_V_LM 014 /* long mem addr */ -#define I_V_RLM 015 /* reg,long mem addr */ -#define I_V_FRM 016 /* flt reg,long mem addr */ -#define I_V_FST 017 /* flt long mem, status */ -#define I_V_XP 020 /* XOP */ -#define I_NPN (I_V_NPN << I_V_FL) -#define I_R (I_V_R << I_V_FL) -#define I_D (I_V_D << I_V_FL) -#define I_RD (I_V_RD << I_V_FL) -#define I_M (I_V_M << I_V_FL) -#define I_RM (I_V_RM << I_V_FL) -#define I_RR (I_V_RR << I_V_FL) -#define I_BY (I_V_BY << I_V_FL) -#define I_2AC (I_V_2AC << I_V_FL) -#define I_RSI (I_V_RSI << I_V_FL) -#define I_LI (I_V_LI << I_V_FL) -#define I_RLI (I_V_RLI << I_V_FL) -#define I_LM (I_V_LM << I_V_FL) -#define I_RLM (I_V_RLM << I_V_FL) -#define I_FRM (I_V_FRM << I_V_FL) -#define I_FST (I_V_FST << I_V_FL) -#define I_XP (I_V_XP << I_V_FL) - -static const int32 masks[] = { -0177777, 0163777, 0177700, 0163700, -0174000, 0160000, 0103770, 0163477, -0103777, 0103777, 0177777, 0163777, -0176377, 0162377, 0103777, 0163777, -0100077 }; - -static const char *opcode[] = { - "JMP", "JSR", "ISZ", "DSZ", - "LDA", "STA", -#if defined (ECLIPSE) - "ADI", "SBI", "DAD", "DSB", - "IOR", "XOR", "ANC", "XCH", - "SGT", "SGE", "LSH", "DLSH", - "HXL", "HXR", "DHXL", "DHXR", - "BTO", "BTZ", "SBZ", "SZBO", - "LOB", "LRB", "COB", "LDB", - "STB", "PSH", "POP", - "LMP", "SYSC", - "PSHR", "POPB", "BAM", "POPJ", - "RTN", "BLM", "DIVX", - "MUL", "MULS", "DIV", "DIVS", - "SAVE", "RSTR", - "XOP", - "FAS", "FAD", "FSS", "FSD", - "FMS", "FMD", "FDS", "FDD", - "FAMS", "FAMD", "FSMS", "FSMD", - "FMMS", "FMMD", "FDMS", "FDMD", - "FLDS", "FLDD", "FSTS", "FSTD", - "FLAS", "FLMD", "FFAS", "FFMD", - "FNOM", "FRH", "FAB", "FNEG", - "FSCAL", "FEXP", "FINT", "FHLV", - "FNS", "FSA", "FSEQ", "FSNE", - "FSLT", "FSGE", "FSLE", "FSGT", - "FSNM", "FSND", "FSNU", "FSNUD", - "FSNO", "FSNOD", "FSNUO", "FSNER", - "FSST", "FLST", - "FTE", "FTD", "FCLE", - "FPSH", "FPOP", - "FCMP", "FMOV", - "CMV", "CMP", "CTR", "CMT", - "EJMP", "EJSR", "EISZ", "EDSZ", - "ELDA", "ESTA", "ELEF", - "ELDB", "ESTB", "DSPA", - "PSHJ", "CLM", "SNB", - "MSP", "XCT", "HLV", - "IORI", "XORI", "ANDI", "ADDI", -#endif - "COM", "COMZ", "COMO", "COMC", - "COML", "COMZL", "COMOL", "COMCL", - "COMR", "COMZR", "COMOR", "COMCR", - "COMS", "COMZS", "COMOS", "COMCS", - "COM#", "COMZ#", "COMO#", "COMC#", - "COML#", "COMZL#", "COMOL#", "COMCL#", - "COMR#", "COMZR#", "COMOR#", "COMCR#", - "COMS#", "COMZS#", "COMOS#", "COMCS#", - "NEG", "NEGZ", "NEGO", "NEGC", - "NEGL", "NEGZL", "NEGOL", "NEGCL", - "NEGR", "NEGZR", "NEGOR", "NEGCR", - "NEGS", "NEGZS", "NEGOS", "NEGCS", - "NEG#", "NEGZ#", "NEGO#", "NEGC#", - "NEGL#", "NEGZL#", "NEGOL#", "NEGCL#", - "NEGR#", "NEGZR#", "NEGOR#", "NEGCR#", - "NEGS#", "NEGZS#", "NEGOS#", "NEGCS#", - "MOV", "MOVZ", "MOVO", "MOVC", - "MOVL", "MOVZL", "MOVOL", "MOVCL", - "MOVR", "MOVZR", "MOVOR", "MOVCR", - "MOVS", "MOVZS", "MOVOS", "MOVCS", - "MOV#", "MOVZ#", "MOVO#", "MOVC#", - "MOVL#", "MOVZL#", "MOVOL#", "MOVCL#", - "MOVR#", "MOVZR#", "MOVOR#", "MOVCR#", - "MOVS#", "MOVZS#", "MOVOS#", "MOVCS#", - "INC", "INCZ", "INCO", "INCC", - "INCL", "INCZL", "INCOL", "INCCL", - "INCR", "INCZR", "INCOR", "INCCR", - "INCS", "INCZS", "INCOS", "INCCS", - "INC#", "INCZ#", "INCO#", "INCC#", - "INCL#", "INCZL#", "INCOL#", "INCCL#", - "INCR#", "INCZR#", "INCOR#", "INCCR#", - "INCS#", "INCZS#", "INCOS#", "INCCS#", - "ADC", "ADCZ", "ADCO", "ADCC", - "ADCL", "ADCZL", "ADCOL", "ADCCL", - "ADCR", "ADCZR", "ADCOR", "ADCCR", - "ADCS", "ADCZS", "ADCOS", "ADCCS", - "ADC#", "ADCZ#", "ADCO#", "ADCC#", - "ADCL#", "ADCZL#", "ADCOL#", "ADCCL#", - "ADCR#", "ADCZR#", "ADCOR#", "ADCCR#", - "ADCS#", "ADCZS#", "ADCOS#", "ADCCS#", - "SUB", "SUBZ", "SUBO", "SUBC", - "SUBL", "SUBZL", "SUBOL", "SUBCL", - "SUBR", "SUBZR", "SUBOR", "SUBCR", - "SUBS", "SUBZS", "SUBOS", "SUBCS", - "SUB#", "SUBZ#", "SUBO#", "SUBC#", - "SUBL#", "SUBZL#", "SUBOL#", "SUBCL#", - "SUBR#", "SUBZR#", "SUBOR#", "SUBCR#", - "SUBS#", "SUBZS#", "SUBOS#", "SUBCS#", - "ADD", "ADDZ", "ADDO", "ADDC", - "ADDL", "ADDZL", "ADDOL", "ADDCL", - "ADDR", "ADDZR", "ADDOR", "ADDCR", - "ADDS", "ADDZS", "ADDOS", "ADDCS", - "ADD#", "ADDZ#", "ADDO#", "ADDC#", - "ADDL#", "ADDZL#", "ADDOL#", "ADDCL#", - "ADDR#", "ADDZR#", "ADDOR#", "ADDCR#", - "ADDS#", "ADDZS#", "ADDOS#", "ADDCS#", - "AND", "ANDZ", "ANDO", "ANDC", - "ANDL", "ANDZL", "ANDOL", "ANDCL", - "ANDR", "ANDZR", "ANDOR", "ANDCR", - "ANDS", "ANDZS", "ANDOS", "ANDCS", - "AND#", "ANDZ#", "ANDO#", "ANDC#", - "ANDL#", "ANDZL#", "ANDOL#", "ANDCL#", - "ANDR#", "ANDZR#", "ANDOR#", "ANDCR#", - "ANDS#", "ANDZS#", "ANDOS#", "ANDCS#", - "ION", "IOF", - "RDSW", "INTA", "MSKO", "IORST", "HALT", -#if !defined (ECLIPSE) - "MUL", "DIV", "MULS", "DIVS", - "PSHA", "POPA", "SAV", "RET", - "MTSP", "MTFP", "MFSP", "MFFP", - "LDB", "STB", -#endif - "NIO", "NIOS", "NIOC", "NIOP", - "DIA", "DIAS", "DIAC", "DIAP", - "DOA", "DOAS", "DOAC", "DOAP", - "DIB", "DIBS", "DIBC", "DIBP", - "DOB", "DOBS", "DOBC", "DOBP", - "DIC", "DICS", "DICC", "DICP", - "DOC", "DOCS", "DOCC", "DOCP", - "SKPBN", "SKPBZ", "SKPDN", "SKPDZ", - NULL }; - -static const opc_val[] = { - 0000000+I_M, 0004000+I_M, 0010000+I_M, 0014000+I_M, - 0020000+I_RM, 0040000+I_RM, -#if defined (ECLIPSE) - 0100010+I_RSI, 0100110+I_RSI, 0100210+I_2AC, 0100310+I_2AC, - 0100410+I_2AC, 0100510+I_2AC, 0100610+I_2AC, 0100710+I_2AC, - 0101010+I_2AC, 0101110+I_2AC, 0101210+I_RSI, 0101310+I_RSI, - 0101410+I_RSI, 0101510+I_RSI, 0101610+I_RSI, 0101710+I_RSI, - 0102010+I_2AC, 0102110+I_2AC, 0102210+I_2AC, 0102310+I_2AC, - 0102410+I_2AC, 0102510+I_2AC, 0102610+I_2AC, 0102710+I_2AC, - 0103010+I_2AC, 0103110+I_2AC, 0103210+I_2AC, - 0113410+I_NPN, 0103510+I_RSI, - 0103710+I_NPN, 0107710+I_NPN, 0113710+I_NPN, 0117710+I_NPN, - 0127710+I_NPN, 0133710+I_NPN, 0137710+I_NPN, - 0143710+I_NPN, 0147710+I_NPN, 0153710+I_NPN, 0157710+I_NPN, - 0163710+I_LI, 0167710+I_NPN, - 0100030+I_XP, - 0100050+I_2AC, 0100150+I_2AC, 0100250+I_2AC, 0100350+I_2AC, - 0100450+I_2AC, 0100550+I_2AC, 0100650+I_2AC, 0100750+I_2AC, - 0101050+I_FRM, 0101150+I_FRM, 0101250+I_FRM, 0101350+I_FRM, - 0101450+I_FRM, 0101550+I_FRM, 0101650+I_FRM, 0101750+I_FRM, - 0102050+I_FRM, 0102150+I_FRM, 0102250+I_FRM, 0102350+I_FRM, - 0102450+I_2AC, 0102550+I_FRM, 0102650+I_2AC, 0102750+I_FRM, - 0103050+I_R, 0123050+I_R, 0143050+I_R, 0163050+I_R, - 0103150+I_R, 0123150+I_R, 0143150+I_R, 0163150+I_R, - 0103250+I_NPN, 0107250+I_NPN, 0113250+I_NPN, 0117250+I_NPN, - 0123250+I_NPN, 0127250+I_NPN, 0133250+I_NPN, 0137250+I_NPN, - 0143250+I_NPN, 0147250+I_NPN, 0153250+I_NPN, 0157250+I_NPN, - 0163250+I_NPN, 0167250+I_NPN, 0173250+I_NPN, 0177250+I_NPN, - 0103350+I_FST, 0123350+I_FST, - 0143350+I_NPN, 0147350+I_NPN, 0153350+I_NPN, - 0163350+I_NPN, 0167350+I_NPN, - 0103450+I_2AC, 0103550+I_2AC, - 0153650+I_NPN, 0157650+I_NPN, 0163650+I_NPN, 0167650+I_NPN, - 0102070+I_LM, 0106070+I_LM, 0112070+I_LM, 0116070+I_LM, - 0122070+I_RLM, 0142070+I_RLM, 0162070+I_RLM, - 0102170+I_RLM, 0122170+I_RLM, 0142170+I_RLM, - 0102270+I_LM, 0102370+I_2AC, 0102770+I_2AC, - 0103370+I_R, 0123370+I_R, 0143370+I_R, - 0103770+I_RLI, 0123770+I_RLI, 0143770+I_RLI, 0163770+I_RLI, -#endif - 0100000+I_RR, 0100020+I_RR, 0100040+I_RR, 0100060+I_RR, - 0100100+I_RR, 0100120+I_RR, 0100140+I_RR, 0100160+I_RR, - 0100200+I_RR, 0100220+I_RR, 0100240+I_RR, 0100260+I_RR, - 0100300+I_RR, 0100320+I_RR, 0100340+I_RR, 0100360+I_RR, - 0100010+I_RR, 0100030+I_RR, 0100050+I_RR, 0100070+I_RR, - 0100110+I_RR, 0100130+I_RR, 0100150+I_RR, 0100170+I_RR, - 0100210+I_RR, 0100230+I_RR, 0100250+I_RR, 0100270+I_RR, - 0100310+I_RR, 0100330+I_RR, 0100350+I_RR, 0100370+I_RR, - 0100400+I_RR, 0100420+I_RR, 0100440+I_RR, 0100460+I_RR, - 0100500+I_RR, 0100520+I_RR, 0100540+I_RR, 0100560+I_RR, - 0100600+I_RR, 0100620+I_RR, 0100640+I_RR, 0100660+I_RR, - 0100700+I_RR, 0100720+I_RR, 0100740+I_RR, 0100760+I_RR, - 0100410+I_RR, 0100430+I_RR, 0100450+I_RR, 0100470+I_RR, - 0100510+I_RR, 0100530+I_RR, 0100550+I_RR, 0100570+I_RR, - 0100610+I_RR, 0100630+I_RR, 0100650+I_RR, 0100670+I_RR, - 0100710+I_RR, 0100730+I_RR, 0100750+I_RR, 0100770+I_RR, - 0101000+I_RR, 0101020+I_RR, 0101040+I_RR, 0101060+I_RR, - 0101100+I_RR, 0101120+I_RR, 0101140+I_RR, 0101160+I_RR, - 0101200+I_RR, 0101220+I_RR, 0101240+I_RR, 0101260+I_RR, - 0101300+I_RR, 0101320+I_RR, 0101340+I_RR, 0101360+I_RR, - 0101010+I_RR, 0101030+I_RR, 0101050+I_RR, 0101070+I_RR, - 0101110+I_RR, 0101130+I_RR, 0101150+I_RR, 0101170+I_RR, - 0101210+I_RR, 0101230+I_RR, 0101250+I_RR, 0101270+I_RR, - 0101310+I_RR, 0101330+I_RR, 0101350+I_RR, 0101370+I_RR, - 0101400+I_RR, 0101420+I_RR, 0101440+I_RR, 0101460+I_RR, - 0101500+I_RR, 0101520+I_RR, 0101540+I_RR, 0101560+I_RR, - 0101600+I_RR, 0101620+I_RR, 0101640+I_RR, 0101660+I_RR, - 0101700+I_RR, 0101720+I_RR, 0101740+I_RR, 0101760+I_RR, - 0101410+I_RR, 0101430+I_RR, 0101450+I_RR, 0101470+I_RR, - 0101510+I_RR, 0101530+I_RR, 0101550+I_RR, 0101570+I_RR, - 0101610+I_RR, 0101630+I_RR, 0101650+I_RR, 0101670+I_RR, - 0101710+I_RR, 0101730+I_RR, 0101750+I_RR, 0101770+I_RR, - 0102000+I_RR, 0102020+I_RR, 0102040+I_RR, 0102060+I_RR, - 0102100+I_RR, 0102120+I_RR, 0102140+I_RR, 0102160+I_RR, - 0102200+I_RR, 0102220+I_RR, 0102240+I_RR, 0102260+I_RR, - 0102300+I_RR, 0102320+I_RR, 0102340+I_RR, 0102360+I_RR, - 0102010+I_RR, 0102030+I_RR, 0102050+I_RR, 0102070+I_RR, - 0102110+I_RR, 0102130+I_RR, 0102150+I_RR, 0102170+I_RR, - 0102210+I_RR, 0102230+I_RR, 0102250+I_RR, 0102270+I_RR, - 0102310+I_RR, 0102330+I_RR, 0102350+I_RR, 0102370+I_RR, - 0102400+I_RR, 0102420+I_RR, 0102440+I_RR, 0102460+I_RR, - 0102500+I_RR, 0102520+I_RR, 0102540+I_RR, 0102560+I_RR, - 0102600+I_RR, 0102620+I_RR, 0102640+I_RR, 0102660+I_RR, - 0102700+I_RR, 0102720+I_RR, 0102740+I_RR, 0102760+I_RR, - 0102410+I_RR, 0102430+I_RR, 0102450+I_RR, 0102470+I_RR, - 0102510+I_RR, 0102530+I_RR, 0102550+I_RR, 0102570+I_RR, - 0102610+I_RR, 0102630+I_RR, 0102650+I_RR, 0102670+I_RR, - 0102710+I_RR, 0102730+I_RR, 0102750+I_RR, 0102770+I_RR, - 0103000+I_RR, 0103020+I_RR, 0103040+I_RR, 0103060+I_RR, - 0103100+I_RR, 0103120+I_RR, 0103140+I_RR, 0103160+I_RR, - 0103200+I_RR, 0103220+I_RR, 0103240+I_RR, 0103260+I_RR, - 0103300+I_RR, 0103320+I_RR, 0103340+I_RR, 0103360+I_RR, - 0103010+I_RR, 0103030+I_RR, 0103050+I_RR, 0103070+I_RR, - 0103110+I_RR, 0103130+I_RR, 0103150+I_RR, 0103170+I_RR, - 0103210+I_RR, 0103230+I_RR, 0103250+I_RR, 0103270+I_RR, - 0103310+I_RR, 0103330+I_RR, 0103350+I_RR, 0103370+I_RR, - 0103400+I_RR, 0103420+I_RR, 0103440+I_RR, 0103460+I_RR, - 0103500+I_RR, 0103520+I_RR, 0103540+I_RR, 0103560+I_RR, - 0103600+I_RR, 0103620+I_RR, 0103640+I_RR, 0103660+I_RR, - 0103700+I_RR, 0103720+I_RR, 0103740+I_RR, 0103760+I_RR, - 0103410+I_RR, 0103430+I_RR, 0103450+I_RR, 0103470+I_RR, - 0103510+I_RR, 0103530+I_RR, 0103550+I_RR, 0103570+I_RR, - 0103610+I_RR, 0103630+I_RR, 0103650+I_RR, 0103670+I_RR, - 0103710+I_RR, 0103730+I_RR, 0103750+I_RR, 0103770+I_RR, - 0060177+I_NPN, 0060277+I_NPN, - 0060477+I_R, 0061477+I_R, 0062077+I_R, 0062677+I_NPN, 0063077+I_NPN, -#if !defined (ECLIPSE) - 0073301+I_NPN, 0073101+I_NPN, 0077201+I_NPN, 0077001+I_NPN, - 0061401+I_R, 0061601+I_R, 0062401+I_NPN, 0062601+I_NPN, - 0061001+I_R, 0060001+I_R, 0061201+I_R, 0060201+I_R, - 0060401+I_BY, 0062001+I_BY, -#endif - 0060000+I_D, 0060100+I_D, 0060200+I_D, 0060300+I_D, - 0060400+I_RD, 0060500+I_RD, 0060600+I_RD, 0060700+I_RD, - 0061000+I_RD, 0061100+I_RD, 0061200+I_RD, 0061300+I_RD, - 0061400+I_RD, 0061500+I_RD, 0061600+I_RD, 0061700+I_RD, - 0062000+I_RD, 0062100+I_RD, 0062200+I_RD, 0062300+I_RD, - 0062400+I_RD, 0062500+I_RD, 0062600+I_RD, 0062700+I_RD, - 0063000+I_RD, 0063100+I_RD, 0063200+I_RD, 0063300+I_RD, - 0063400+I_D, 0063500+I_D, 0063600+I_D, 0063700+I_D, - -1 }; - -static const char *skip[] = { - "SKP", "SZC", "SNC", "SZR", "SNR", "SEZ", "SBN", - NULL }; - -static const char *device[] = { -#if defined (ECLIPSE) - "ERCC", "MAP", -#endif - "TTI", "TTO", "PTR", "PTP", "RTC", "PLT", "CDR", "LPT", - "DSK", "MTA", "DCM", "ADCV", "DKP", "CAS", - "TTI1", "TTO1", "CPU", - NULL }; - -static const int32 dev_val[] = { -#if defined (ECLIPSE) - 002, 003, -#endif - 010, 011, 012, 013, 014, 015, 016, 017, - 020, 022, 024, 030, 033, 034, - 050, 051, 077, - -1 }; - -/* Address decode - - Inputs: - *of = output stream - addr = current PC - ind = indirect flag - mode = addressing mode - disp = displacement - ext = true if extended address - cflag = true if decoding for CPU - Outputs: - return = error code -*/ - -t_stat fprint_addr (FILE *of, t_addr addr, int32 ind, int32 mode, - int32 disp, t_bool ext, int32 cflag) -{ -int32 dsign, dmax; - -if (ext) dmax = AMASK + 1; /* get max disp */ -else dmax = I_M_DISP + 1; -dsign = dmax >> 1; /* get disp sign */ -if (ind) fprintf (of, "@"); /* indirect? */ -switch (mode & 03) { /* mode */ -case 0: /* absolute */ - fprintf (of, "%-o", disp); - break; -case 1: /* PC rel */ - if (disp & dsign) { - if (cflag) fprintf (of, "%-o", (addr - (dmax - disp)) & AMASK); - else fprintf (of, ".-%-o", dmax - disp); } - else { - if (cflag) fprintf (of, "%-o", (addr + disp) & AMASK); - else fprintf (of, ".+%-o", disp); } - break; -case 2: /* AC2 rel */ - if (disp & dsign) fprintf (of, "-%-o,2", dmax - disp); - else fprintf (of, "%-o,2", disp); - break; -case 3: /* AC3 rel */ - if (disp & dsign) fprintf (of, "-%-o,3", dmax - disp); - else fprintf (of, "%-o,3", disp); - break; } /* end switch */ -return SCPE_OK; -} - -/* Symbolic output - - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - status = error code -*/ - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, i, j, c1, c2, inst, dv, src, dst, skp; -int32 ind, mode, disp, dev; -int32 byac, extind, extdisp, xop; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -c1 = (val[0] >> 8) & 0177; -c2 = val[0] & 0177; -if (sw & SWMASK ('A')) { /* ASCII? */ - fprintf (of, (c2 < 040)? "<%03o>": "%c", c2); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* character? */ - fprintf (of, (c1 < 040)? "<%03o>": "%c", c1); - fprintf (of, (c2 < 040)? "<%03o>": "%c", c2); - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; /* mnemonic? */ - -/* Instruction decode */ - -inst = val[0]; -for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - if ((opc_val[i] & 0177777) == (inst & masks[j])) { /* match? */ - src = I_GETSRC (inst); /* opr fields */ - dst = I_GETDST (inst); - skp = I_GETSKP (inst); - ind = inst & I_IND; /* mem ref fields */ - mode = I_GETMODE (inst); - disp = I_GETDISP (inst); - dev = I_GETDEV (inst); /* IOT fields */ - byac = I_GETPULSE (inst); /* byte fields */ - xop = I_GETXOP (inst); /* XOP fields */ - extind = val[1] & A_IND; /* extended fields */ - extdisp = val[1] & AMASK; - for (dv = 0; (dev_val[dv] >= 0) && (dev_val[dv] != dev); dv++) ; - - switch (j) { /* switch on class */ - case I_V_NPN: /* no operands */ - fprintf (of, "%s", opcode[i]); /* opcode */ - break; - case I_V_R: /* reg only */ - fprintf (of, "%s %-o", opcode[i], dst); - break; - case I_V_D: /* dev only */ - if (dev_val[dv] >= 0) - fprintf (of, "%s %s", opcode[i], device[dv]); - else fprintf (of, "%s %-o", opcode[i], dev); - break; - case I_V_RD: /* reg, dev */ - if (dev_val[dv] >= 0) - fprintf (of, "%s %-o,%s", opcode[i], dst, device[dv]); - else fprintf (of, "%s %-o,%-o", opcode[i], dst, dev); - break; - case I_V_M: /* addr only */ - fprintf (of, "%s ", opcode[i]); - fprint_addr (of, addr, ind, mode, disp, FALSE, cflag); - break; - case I_V_RM: /* reg, addr */ - fprintf (of, "%s %-o,", opcode[i], dst); - fprint_addr (of, addr, ind, mode, disp, FALSE, cflag); - break; - case I_V_RR: /* operate */ - fprintf (of, "%s %-o,%-o", opcode[i], src, dst); - if (skp) fprintf (of, ",%s", skip[skp-1]); - break; - case I_V_BY: /* byte */ - fprintf (of, "%s %-o,%-o", opcode[i], byac, dst); - break; - case I_V_2AC: /* reg, reg */ - fprintf (of, "%s %-o,%-o", opcode[i], src, dst); - break; - case I_V_RSI: /* reg, short imm */ - fprintf (of, "%s %-o,%-o", opcode[i], src + 1, dst); - break; - case I_V_LI: /* long imm */ - fprintf (of, "%s %-o", opcode[i], val[1]); - return -1; - case I_V_RLI: /* reg, long imm */ - fprintf (of, "%s %-o,%-o", opcode[i], val[1], dst); - return -1; - case I_V_LM: /* long addr */ - fprintf (of, "%s ", opcode[i]); - fprint_addr (of, addr, extind, mode, extdisp, TRUE, cflag); - return -1; - case I_V_RLM: /* reg, long addr */ - fprintf (of, "%s %-o,", opcode[i], dst); - fprint_addr (of, addr, extind, mode, extdisp, TRUE, cflag); - return -1; - case I_V_FRM: /* flt reg, long addr */ - fprintf (of, "%s %-o,", opcode[i], dst); - fprint_addr (of, addr, extind, src, extdisp, TRUE, cflag); - return -1; - case I_V_FST: /* flt status */ - fprintf (of, "%s ", opcode[i]); - fprint_addr (of, addr, extind, dst, extdisp, AMASK + 1, cflag); - return -1; - case I_V_XP: /* XOP */ - fprintf (of, "%s %-o,%-o,%-o", opcode[i], src, dst, xop); - break; } /* end case */ - return SCPE_OK; } /* end if */ - } /* end for */ -return SCPE_ARG; -} - -/* Address parse - - Inputs: - *cptr = pointer to input string - addr = current PC - ext = extended address - cflag = true if parsing for CPU - val[3] = output array - Outputs: - optr = pointer to next char in input string - NULL if error -*/ - -#define A_FL 001 /* CPU flag */ -#define A_NX 002 /* index seen */ -#define A_PER 004 /* period seen */ -#define A_NUM 010 /* number seen */ -#define A_SI 020 /* sign seen */ -#define A_MI 040 /* - seen */ - -char *get_addr (char *cptr, t_addr addr, t_bool ext, int32 cflag, int32 *val) -{ -int32 d, r, x, pflag; -char gbuf[CBUFSIZE]; -int32 dmax, dsign; - -if (ext) dmax = AMASK + 1; /* get max disp */ -else dmax = I_M_DISP + 1; -dsign = dmax >> 1; /* get disp sign */ -val[0] = 0; /* no indirect */ -val[1] = 0; /* PC rel */ -val[2] = 0; /* no addr */ - -pflag = cflag & A_FL; /* isolate flag */ -if (*cptr == '@') { /* indirect? */ - val[0] = 1; - cptr++; } -if (*cptr == '.') { /* relative? */ - pflag = pflag | A_PER; - x = 1; /* "index" is PC */ - cptr++; } -if (*cptr == '+') { /* + sign? */ - pflag = pflag | A_SI; - cptr++; } -else if (*cptr == '-') { /* - sign? */ - pflag = pflag | A_MI | A_SI; - cptr++; } -if (*cptr != 0) { /* number? */ - cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ - d = get_uint (gbuf, 8, AMASK, &r); - if (r != SCPE_OK) return NULL; - pflag = pflag | A_NUM; } -if (*cptr != 0) { /* index? */ - cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ - x = get_uint (gbuf, 8, I_M_DST, &r); - if ((r != SCPE_OK) || (x < 2)) return NULL; - pflag = pflag | A_NX; } - -/* Address parse, continued */ - -switch (pflag) { /* case on flags */ -case A_NUM: case A_NUM+A_SI: /* ~CPU, (+)num */ - if (d < dmax) val[2] = d; - else return NULL; - break; -case A_NUM+A_FL: case A_NUM+A_SI+A_FL: /* CPU, (+)num */ - if (d < dmax) val[2] = d; - else if (((d >= (((int32) addr - dsign) & AMASK)) && - (d < (((int32) addr + dsign) & AMASK))) || - (d >= ((int32) addr + (-dsign & AMASK)))) { - val[1] = 1; /* PC rel */ - val[2] = (d - addr) & (dmax - 1); } - else return NULL; - break; -case A_PER: case A_PER+A_FL: /* . */ -case A_PER+A_SI+A_NUM: case A_PER+A_SI+A_NUM+A_FL: /* . + num */ -case A_PER+A_SI+A_MI+A_NUM: /* . - num */ -case A_PER+A_SI+A_MI+A_NUM+A_FL: -case A_NX+A_NUM: case A_NX+A_NUM+A_FL: /* num, ndx */ -case A_NX+A_SI+A_NUM: case A_NX+A_SI+A_NUM+A_FL: /* +num, ndx */ -case A_NX+A_SI+A_MI+A_NUM: /* -num, ndx */ -case A_NX+A_SI+A_MI+A_NUM+A_FL: - val[1] = x; /* set mode */ - if (((pflag & A_MI) == 0) && (d < dsign)) val[2] = d; - else if ((pflag & A_MI) && (d <= dsign)) val[2] = (dmax - d); - else return NULL; - break; -default: - return NULL; } /* end case */ -return cptr; -} - -/* Parse two registers - - Inputs: - *cptr = input string - term = second terminating character - val = output array - Outputs: - optr = pointer to next char in input string - NULL if error -*/ - -char *get_2reg (char *cptr, char term, int32 *val) -{ -char gbuf[CBUFSIZE]; -t_stat r; - -cptr = get_glyph (cptr, gbuf, ','); /* get register */ -val[0] = get_uint (gbuf, 8, I_M_SRC, &r); -if (r != SCPE_OK) return NULL; -cptr = get_glyph (cptr, gbuf, term); /* get register */ -val[1] = get_uint (gbuf, 8, I_M_DST, &r); -if (r != SCPE_OK) return NULL; -return cptr; -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = error status -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 cflag, d, i, j, amd[3]; -t_stat r, rtn; -char gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ -if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (t_value) cptr[0]; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = ((t_value) cptr[0] << 8) + (t_value) cptr[1]; - return SCPE_OK; } - -/* Instruction parse */ - -rtn = SCPE_OK; /* assume 1 word */ -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; -if (opcode[i] == NULL) return SCPE_ARG; -val[0] = opc_val[i] & 0177777; /* get value */ -j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - -switch (j) { /* case on class */ -case I_V_NPN: /* no operand */ - break; -case I_V_R: /* IOT reg */ - cptr = get_glyph (cptr, gbuf, 0); /* get register */ - d = get_uint (gbuf, 8, I_M_DST, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_DST); /* put in place */ - break; -case I_V_RD: /* IOT reg,dev */ - cptr = get_glyph (cptr, gbuf, ','); /* get register */ - d = get_uint (gbuf, 8, I_M_DST, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_DST); /* put in place */ -case I_V_D: /* IOT dev */ - cptr = get_glyph (cptr, gbuf, 0); /* get device */ - for (i = 0; (device[i] != NULL) && - (strcmp (device[i], gbuf) != 0); i++); - if (device[i] != NULL) val[0] = val[0] | dev_val[i]; - else { - d = get_uint (gbuf, 8, I_M_DEV, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_DEV); } - break; -case I_V_RM: /* reg, addr */ - cptr = get_glyph (cptr, gbuf, ','); /* get register */ - d = get_uint (gbuf, 8, I_M_DST, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_DST); /* put in place */ -case I_V_M: /* addr */ - cptr = get_addr (cptr, addr, FALSE, cflag, amd); - if (cptr == NULL) return SCPE_ARG; - val[0] = val[0] | (amd[0] << I_V_IND) | (amd[1] << I_V_MODE) | amd[2]; - break; -case I_V_RR: /* operate */ - cptr = get_2reg (cptr, ',', amd); /* get 2 reg */ - if (cptr == NULL) return SCPE_ARG; - val[0] = val[0] | (amd[0] << I_V_SRC) | (amd[1] << I_V_DST); - if (*cptr != 0) { /* skip? */ - cptr = get_glyph (cptr, gbuf, 0); /* get skip */ - for (i = 0; (skip[i] != NULL) && - (strcmp (skip[i], gbuf) != 0); i++) ; - if (skip[i] == NULL) return SCPE_ARG; - val[0] = val[0] | (i + 1); } /* end for */ - break; -case I_V_BY: /* byte */ - cptr = get_2reg (cptr, 0, amd); /* get 2 reg */ - if (cptr == NULL) return SCPE_ARG; - val[0] = val[0] | (amd[0] << I_V_PULSE) | (amd[1] << I_V_DST); - break; -case I_V_2AC: /* reg, reg */ - cptr = get_2reg (cptr, 0, amd); /* get 2 reg */ - if (cptr == NULL) return SCPE_ARG; - val[0] = val[0] | (amd[0] << I_V_SRC) | (amd[1] << I_V_DST); - break; -case I_V_RSI: /* reg, short imm */ - cptr = get_glyph (cptr, gbuf, ','); /* get immediate */ - d = get_uint (gbuf, 8, I_M_SRC + 1, &r); - if ((d == 0) || (r != SCPE_OK)) return SCPE_ARG; - val[0] = val[0] | ((d - 1) << I_V_SRC); /* put in place */ - cptr = get_glyph (cptr, gbuf, 0); /* get register */ - d = get_uint (gbuf, 8, I_M_DST, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_DST); /* put in place */ - break; -case I_V_RLI: /* reg, long imm */ - cptr = get_glyph (cptr, gbuf, ','); /* get immediate */ - val[1] = get_uint (gbuf, 8, DMASK, &r); - if (r != SCPE_OK) return SCPE_ARG; - cptr = get_glyph (cptr, gbuf, 0); /* get register */ - d = get_uint (gbuf, 8, I_M_DST, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_DST); /* put in place */ - rtn = -1; - break; -case I_V_LI: /* long imm */ - cptr = get_glyph (cptr, gbuf, 0); /* get immediate */ - val[1] = get_uint (gbuf, 8, DMASK, &r); - if (r != SCPE_OK) return SCPE_ARG; - rtn = -1; - break; -case I_V_RLM: /* reg, long mem */ - cptr = get_glyph (cptr, gbuf, ','); /* get register */ - d = get_uint (gbuf, 8, I_M_DST, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_DST); /* put in place */ -case I_V_LM: /* long mem */ - cptr = get_addr (cptr, addr, TRUE, cflag, amd); - if (cptr == NULL) return SCPE_ARG; - val[0] = val[0] | (amd[1] << I_V_MODE); - val[1] = (amd[0] << A_V_IND) | amd[2]; - rtn = -1; - break; -case I_V_FRM: /* flt reg, long mem */ - cptr = get_glyph (cptr, gbuf, ','); /* get register */ - d = get_uint (gbuf, 8, I_M_DST, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_DST); /* put in place */ - cptr = get_addr (cptr, addr, TRUE, cflag, amd); - if (cptr == NULL) return SCPE_ARG; - val[0] = val[0] | (amd[1] << I_V_SRC); - val[1] = (amd[0] << A_V_IND) | amd[2]; - rtn = -1; - break; -case I_V_FST: /* flt status */ - cptr = get_addr (cptr, addr, TRUE, cflag, amd); - if (cptr == NULL) return SCPE_ARG; - val[0] = val[0] | (amd[1] << I_V_DST); - val[1] = (amd[0] << A_V_IND) | amd[2]; - rtn = -1; - break; -case I_V_XP: /* XOP */ - cptr = get_2reg (cptr, ',', amd); /* get 2 reg */ - if (cptr == NULL) return SCPE_ARG; - val[0] = val[0] | (amd[0] << I_V_SRC) | (amd[1] << I_V_DST); - cptr = get_glyph (cptr, gbuf, 0); /* get argument */ - d = get_uint (gbuf, 8, I_M_XOP, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_XOP); - break; } /* end case */ -if (*cptr != 0) return SCPE_ARG; /* any leftovers? */ -return rtn; -} diff --git a/NOVA/nova_tt.c b/NOVA/nova_tt.c deleted file mode 100644 index f745b08e..00000000 --- a/NOVA/nova_tt.c +++ /dev/null @@ -1,220 +0,0 @@ -/* nova_tt.c: NOVA console terminal simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - tti terminal input - tto terminal output - - 25-Apr-03 RMS Revised for extended file support - 05-Jan-02 RMS Fixed calling sequence for setmod - 03-Oct-02 RMS Added DIBs - 30-May-02 RMS Widened POS to 32b - 30-Nov-01 RMS Added extended SET/SHOW support - 17-Sep-01 RMS Removed multiconsole support - 07-Sep-01 RMS Moved function prototypes - 31-May-01 RMS Added multiconsole support -*/ - -#include "nova_defs.h" - -#define UNIT_V_DASHER (UNIT_V_UF + 0) /* Dasher mode */ -#define UNIT_DASHER (1 << UNIT_V_DASHER) -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 tti (int32 pulse, int32 code, int32 AC); -int32 tto (int32 pulse, int32 code, int32 AC); -t_stat tti_svc (UNIT *uptr); -t_stat tto_svc (UNIT *uptr); -t_stat tti_reset (DEVICE *dptr); -t_stat tto_reset (DEVICE *dptr); -t_stat ttx_setmod (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit descriptor - tti_reg TTI register list - ttx_mod TTI/TTO modifiers list -*/ - -DIB tti_dib = { DEV_TTI, INT_TTI, PI_TTI, &tti }; - -UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }; - -REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_TTI) }, - { FLDATA (DONE, dev_done, INT_V_TTI) }, - { FLDATA (DISABLE, dev_disable, INT_V_TTI) }, - { FLDATA (INT, int_req, INT_V_TTI) }, - { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB ttx_mod[] = { - { UNIT_DASHER, 0, "ANSI", "ANSI", &ttx_setmod }, - { UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx_setmod }, - { 0 } }; - -DEVICE tti_dev = { - "TTI", &tti_unit, tti_reg, ttx_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tti_reset, - NULL, NULL, NULL, - &tti_dib, 0 }; - -/* TTO data structures - - tto_dev TTO device descriptor - tto_unit TTO unit descriptor - tto_reg TTO register list -*/ - -DIB tto_dib = { DEV_TTO, INT_TTO, PI_TTO, &tto }; - -UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT }; - -REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_TTO) }, - { FLDATA (DONE, dev_done, INT_V_TTO) }, - { FLDATA (DISABLE, dev_disable, INT_V_TTO) }, - { FLDATA (INT, int_req, INT_V_TTO) }, - { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -DEVICE tto_dev = { - "TTO", &tto_unit, tto_reg, ttx_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto_reset, - NULL, NULL, NULL, - &tto_dib, 0 }; - -/* Terminal input: IOT routine */ - -int32 tti (int32 pulse, int32 code, int32 AC) -{ -int32 iodata; - -iodata = (code == ioDIA)? tti_unit.buf & 0377: 0; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_TTI; /* set busy */ - dev_done = dev_done & ~INT_TTI; /* clear done, int */ - int_req = int_req & ~INT_TTI; - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_TTI; /* clear busy */ - dev_done = dev_done & ~INT_TTI; /* clear done, int */ - int_req = int_req & ~INT_TTI; - break; } /* end switch */ -return iodata; -} - -/* Unit service */ - -t_stat tti_svc (UNIT *uptr) -{ -int32 temp; - -sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ -if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ -tti_unit.buf = temp & 0177; -if ((tti_unit.flags & UNIT_DASHER) && (tti_unit.buf == '\r')) - tti_unit.buf = '\n'; /* Dasher: cr -> nl */ -dev_busy = dev_busy & ~INT_TTI; /* clear busy */ -dev_done = dev_done | INT_TTI; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -tti_unit.pos = tti_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tti_reset (DEVICE *dptr) -{ -tti_unit.buf = 0; -dev_busy = dev_busy & ~INT_TTI; /* clear busy */ -dev_done = dev_done & ~INT_TTI; /* clear done, int */ -int_req = int_req & ~INT_TTI; -sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ -return SCPE_OK; -} - -/* Terminal output: IOT routine */ - -int32 tto (int32 pulse, int32 code, int32 AC) -{ -if (code == ioDOA) tto_unit.buf = AC & 0377; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_TTO; /* set busy */ - dev_done = dev_done & ~INT_TTO; /* clear done, int */ - int_req = int_req & ~INT_TTO; - sim_activate (&tto_unit, tto_unit.wait); /* activate unit */ - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_TTO; /* clear busy */ - dev_done = dev_done & ~INT_TTO; /* clear done, int */ - int_req = int_req & ~INT_TTO; - sim_cancel (&tto_unit); /* deactivate unit */ - break; } /* end switch */ -return 0; -} - -/* Unit service */ - -t_stat tto_svc (UNIT *uptr) -{ -int32 c, temp; - -dev_busy = dev_busy & ~INT_TTO; /* clear busy */ -dev_done = dev_done | INT_TTO; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -c = tto_unit.buf & 0177; -if ((tto_unit.flags & UNIT_DASHER) && (c == 031)) c = '\b'; -if ((temp = sim_putchar (c)) != SCPE_OK) return temp; -tto_unit.pos = tto_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tto_reset (DEVICE *dptr) -{ -tto_unit.buf = 0; -dev_busy = dev_busy & ~INT_TTO; /* clear busy */ -dev_done = dev_done & ~INT_TTO; /* clear done, int */ -int_req = int_req & ~INT_TTO; -sim_cancel (&tto_unit); /* deactivate unit */ -return SCPE_OK; -} - -t_stat ttx_setmod (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -tti_unit.flags = (tti_unit.flags & ~UNIT_DASHER) | val; -tto_unit.flags = (tto_unit.flags & ~UNIT_DASHER) | val; -return SCPE_OK; -} diff --git a/NOVA/nova_tt1.c b/NOVA/nova_tt1.c deleted file mode 100644 index ea3f1bd3..00000000 --- a/NOVA/nova_tt1.c +++ /dev/null @@ -1,323 +0,0 @@ -/* nova_tt1.c: NOVA second terminal simulator - - Copyright (c) 1993-2003, Robert M. Supnik - Written by Bruce Ray and used with his gracious permission. - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - tti1 second terminal input - tto1 second terminal output - - 09-May-03 RMS Added network device flag - 05-Jan-03 RMS Fixed calling sequence for setmod - 03-Oct-02 RMS Added DIBs - 22-Aug-02 RMS Updated for changes in sim_tmxr - 30-May-02 RMS Widened POS to 32b - 06-Jan-02 RMS Revised enable/disable support - 30-Dec-01 RMS Added show statistics, set disconnect - 30-Nov-01 RMS Added extended SET/SHOW support - 17-Sep-01 RMS Changed to use terminal multiplexor library - 07-Sep-01 RMS Moved function prototypes - 31-May-01 RMS Added multiconsole support - 26-Apr-01 RMS Added device enable/disable support -*/ - -#include "nova_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" - -#define UNIT_V_DASHER (UNIT_V_UF + 0) /* Dasher mode */ -#define UNIT_DASHER (1 << UNIT_V_DASHER) - -extern int32 int_req, dev_busy, dev_done, dev_disable; -extern int32 tmxr_poll; /* calibrated poll */ -TMLN tt1_ldsc = { 0 }; /* line descriptors */ -TMXR tt_desc = { 1, 0, 0, &tt1_ldsc }; /* mux descriptor */ - -DEVICE tti1_dev, tto1_dev; -int32 tti1 (int32 pulse, int32 code, int32 AC); -int32 tto1 (int32 pulse, int32 code, int32 AC); -t_stat tti1_svc (UNIT *uptr); -t_stat tto1_svc (UNIT *uptr); -t_stat tti1_reset (DEVICE *dptr); -t_stat tto1_reset (DEVICE *dptr); -t_stat ttx1_setmod (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat tti1_attach (UNIT *uptr, char *cptr); -t_stat tti1_detach (UNIT *uptr); -t_stat tti1_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat tti1_show (FILE *st, UNIT *uptr, int32 val, void *desc); -void ttx1_enbdis (int32 dis); - -/* TTI1 data structures - - tti1_dev TTI1 device descriptor - tti1_unit TTI1 unit descriptor - tti1_reg TTI1 register list - ttx1_mod TTI1/TTO1 modifiers list -*/ - -DIB tti1_dib = { DEV_TTI1, INT_TTI1, PI_TTI1, &tti1 }; - -UNIT tti1_unit = { UDATA (&tti1_svc, UNIT_ATTABLE, 0), KBD_POLL_WAIT }; - -REG tti1_reg[] = { - { ORDATA (BUF, tti1_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_TTI1) }, - { FLDATA (DONE, dev_done, INT_V_TTI1) }, - { FLDATA (DISABLE, dev_disable, INT_V_TTI1) }, - { FLDATA (INT, int_req, INT_V_TTI1) }, - { DRDATA (POS, tt1_ldsc.rxcnt, 32), PV_LEFT }, - { DRDATA (TIME, tti1_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB tti1_mod[] = { - { UNIT_DASHER, 0, "ANSI", "ANSI", &ttx1_setmod }, - { UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx1_setmod }, - { UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &tti1_summ }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &tt_desc }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &tti1_show, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &tti1_show, NULL }, - { 0 } }; - -DEVICE tti1_dev = { - "TTI1", &tti1_unit, tti1_reg, tti1_mod, - 1, 10, 31, 1, 8, 8, - &tmxr_ex, &tmxr_dep, &tti1_reset, - NULL, &tti1_attach, &tti1_detach, - &tti1_dib, DEV_NET | DEV_DISABLE }; - -/* TTO1 data structures - - tto1_dev TTO1 device descriptor - tto1_unit TTO1 unit descriptor - tto1_reg TTO1 register list -*/ - -DIB tto1_dib = { DEV_TTO1, INT_TTO1, PI_TTO1, &tto1 }; - -UNIT tto1_unit = { UDATA (&tto1_svc, 0, 0), SERIAL_OUT_WAIT }; - -REG tto1_reg[] = { - { ORDATA (BUF, tto1_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_TTO1) }, - { FLDATA (DONE, dev_done, INT_V_TTO1) }, - { FLDATA (DISABLE, dev_disable, INT_V_TTO1) }, - { FLDATA (INT, int_req, INT_V_TTO1) }, - { DRDATA (POS, tt1_ldsc.txcnt, 32), PV_LEFT }, - { DRDATA (TIME, tto1_unit.wait, 24), PV_LEFT }, - { NULL } }; - -MTAB tto1_mod[] = { - { UNIT_DASHER, 0, "ANSI", "ANSI", &ttx1_setmod }, - { UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx1_setmod }, - { 0 } }; - -DEVICE tto1_dev = { - "TTO1", &tto1_unit, tto1_reg, tto1_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto1_reset, - NULL, NULL, NULL, - &tto1_dib, DEV_DISABLE }; - -/* Terminal input: IOT routine */ - -int32 tti1 (int32 pulse, int32 code, int32 AC) -{ -int32 iodata; - -iodata = (code == ioDIA)? tti1_unit.buf & 0377: 0; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_TTI1; /* set busy */ - dev_done = dev_done & ~INT_TTI1; /* clear done, int */ - int_req = int_req & ~INT_TTI1; - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_TTI1; /* clear busy */ - dev_done = dev_done & ~INT_TTI1; /* clear done, int */ - int_req = int_req & ~INT_TTI1; - break; } /* end switch */ -return iodata; -} - -/* Unit service */ - -t_stat tti1_svc (UNIT *uptr) -{ -int32 temp, newln; - -if (tt1_ldsc.conn) { /* connected? */ - tmxr_poll_rx (&tt_desc); /* poll for input */ - if (temp = tmxr_getc_ln (&tt1_ldsc)) { /* get char */ - uptr->buf = temp & 0177; - if ((uptr->flags & UNIT_DASHER) && - (uptr->buf == '\r')) - uptr->buf = '\n'; /* Dasher: cr->nl */ - dev_busy = dev_busy & ~INT_TTI1; /* clear busy */ - dev_done = dev_done | INT_TTI1; /* set done */ - int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); } - sim_activate (uptr, uptr->wait); } /* continue poll */ -if (uptr->flags & UNIT_ATT) { /* attached? */ - newln = tmxr_poll_conn (&tt_desc); /* poll connect */ - if (newln >= 0) { /* got one? */ - sim_activate (&tti1_unit, tti1_unit.wait); - tt1_ldsc.rcve = 1; } /* rcv enabled */ - sim_activate (uptr, tmxr_poll); } /* sched poll */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tti1_reset (DEVICE *dptr) -{ -ttx1_enbdis (dptr->flags & DEV_DIS); /* sync devices */ -tti1_unit.buf = 0; -dev_busy = dev_busy & ~INT_TTI1; /* clear busy */ -dev_done = dev_done & ~INT_TTI1; /* clear done, int */ -int_req = int_req & ~INT_TTI1; -if (tt1_ldsc.conn) { /* if conn, */ - sim_activate (&tti1_unit, tti1_unit.wait); /* activate, */ - tt1_ldsc.rcve = 1; } /* enable */ -else if (tti1_unit.flags & UNIT_ATT) /* if attached, */ - sim_activate (&tti1_unit, tmxr_poll); /* activate */ -else sim_cancel (&tti1_unit); /* else stop */ -return SCPE_OK; -} - -/* Terminal output: IOT routine */ - -int32 tto1 (int32 pulse, int32 code, int32 AC) -{ -if (code == ioDOA) tto1_unit.buf = AC & 0377; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_TTO1; /* set busy */ - dev_done = dev_done & ~INT_TTO1; /* clear done, int */ - int_req = int_req & ~INT_TTO1; - sim_activate (&tto1_unit, tto1_unit.wait); /* activate unit */ - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_TTO1; /* clear busy */ - dev_done = dev_done & ~INT_TTO1; /* clear done, int */ - int_req = int_req & ~INT_TTO1; - sim_cancel (&tto1_unit); /* deactivate unit */ - break; } /* end switch */ -return 0; -} - -/* Unit service */ - -t_stat tto1_svc (UNIT *uptr) -{ -int32 c; - -dev_busy = dev_busy & ~INT_TTO1; /* clear busy */ -dev_done = dev_done | INT_TTO1; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -c = tto1_unit.buf & 0177; -if ((tto1_unit.flags & UNIT_DASHER) && (c == 031)) c = '\b'; -if (tt1_ldsc.conn) { /* connected? */ - if (tt1_ldsc.xmte) { /* tx enabled? */ - tmxr_putc_ln (&tt1_ldsc, c); /* output char */ - tmxr_poll_tx (&tt_desc); } /* poll xmt */ - else { tmxr_poll_tx (&tt_desc); /* poll xmt */ - sim_activate (&tto1_unit, tmxr_poll); /* wait */ - return SCPE_OK; } } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tto1_reset (DEVICE *dptr) -{ -ttx1_enbdis (dptr->flags & DEV_DIS); /* sync devices */ -tto1_unit.buf = 0; -dev_busy = dev_busy & ~INT_TTO1; /* clear busy */ -dev_done = dev_done & ~INT_TTO1; /* clear done, int */ -int_req = int_req & ~INT_TTO1; -sim_cancel (&tto1_unit); /* deactivate unit */ -return SCPE_OK; -} - -t_stat ttx1_setmod (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -tti1_unit.flags = (tti1_unit.flags & ~UNIT_DASHER) | val; -tto1_unit.flags = (tto1_unit.flags & ~UNIT_DASHER) | val; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat tti1_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = tmxr_attach (&tt_desc, uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error */ -sim_activate (uptr, tmxr_poll); /* start poll */ -return SCPE_OK; -} - -/* Detach routine */ - -t_stat tti1_detach (UNIT *uptr) -{ -t_stat r; - -r = tmxr_detach (&tt_desc, uptr); /* detach */ -tt1_ldsc.rcve = 0; /* disable rcv */ -sim_cancel (uptr); /* stop poll */ -return r; -} - -/* Show summary processor */ - -t_stat tti1_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (tt1_ldsc.conn) fprintf (st, "connected"); -else fprintf (st, "disconnected"); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat tti1_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (val) tmxr_fconns (st, &tt1_ldsc, -1); -else tmxr_fstats (st, &tt1_ldsc, -1); -return SCPE_OK; -} - -/* Enable/disable device */ - -void ttx1_enbdis (int32 dis) -{ -if (dis) { - tti1_dev.flags = tto1_dev.flags | DEV_DIS; - tto1_dev.flags = tto1_dev.flags | DEV_DIS; } -else { tti1_dev.flags = tti1_dev.flags & ~DEV_DIS; - tto1_dev.flags = tto1_dev.flags & ~DEV_DIS; } -return; -} diff --git a/PDP1/pdp1_cpu.c b/PDP1/pdp1_cpu.c deleted file mode 100644 index afe90b39..00000000 --- a/PDP1/pdp1_cpu.c +++ /dev/null @@ -1,853 +0,0 @@ -/* pdp1_cpu.c: PDP-1 CPU simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - cpu PDP-1 central processor - - 07-Sep-03 RMS Added additional explanation on I/O simulation - 01-Sep-03 RMS Added address switches for hardware readin - 23-Jul-03 RMS Revised to detect I/O wait hang - 05-Dec-02 RMS Added drum support - 06-Oct-02 RMS Revised for V2.10 - 20-Aug-02 RMS Added DECtape support - 30-Dec-01 RMS Added old PC queue - 07-Dec-01 RMS Revised to use breakpoint package - 30-Nov-01 RMS Added extended SET/SHOW support - 16-Dec-00 RMS Fixed bug in XCT address calculation - 14-Apr-99 RMS Changed t_addr to unsigned - - The PDP-1 was Digital's first computer. Although Digital built four - other 18b computers, the later systems (the PDP-4, PDP-7, PDP-9, and - PDP-15) were similar to each other and quite different from the PDP-1. - Accordingly, the PDP-1 requires a distinct simulator. - - The register state for the PDP-1 is: - - AC<0:17> accumulator - IO<0:17> IO register - OV overflow flag - PC<0:15> program counter - IOSTA I/O status register - SBS<0:2> sequence break flip flops - IOH I/O halt flip flop - IOS I/O syncronizer (completion) flip flop - EXTM extend mode - PF<1:6> program flags - SS<1:6> sense switches - TW<0:17> test word (switch register) - - Questions: - - cks: which bits are line printer print done and space done? - cks: is there a bit for sequence break enabled (yes, according - to the 1963 Handbook) - sbs: do sequence breaks accumulate while the system is disabled - (yes, according to the Maintenance Manual) -*/ - -/* The PDP-1 has six instruction formats: memory reference, skips, - shifts, load immediate, I/O transfer, and operate. The memory - reference format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op |in| address | memory reference - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <0:4> <5> mnemonic action - - 00 - 02 AND AC = AC & M[MA] - 04 IOR AC = AC | M[MA] - 06 XOR AC = AC ^ M[MA] - 10 XCT M[MA] is executed as an instruction - 12 - 14 - 16 0 CAL M[100] = AC, AC = PC, PC = 101 - 16 1 JDA M[MA] = AC, AC = PC, PC = MA + 1 - 20 LAC AC = M[MA] - 22 LIO IO = M[MA] - 24 DAC M[MA] = AC - 26 DAP M[MA]<6:17> = AC<6:17> - 30 DIP M[MA]<0:5> = AC<0:5> - 32 DIO M[MA] = IO - 34 DZM M[MA] = 0 - 36 - 40 ADD AC = AC + M[MA] - 42 SUB AC = AC - M[MA] - 44 IDX AC = M[MA] = M[MA] + 1 - 46 ISP AC = M[MA] = M[MA] + 1, skip if AC >= 0 - 50 SAD skip if AC != M[MA] - 52 SAS skip if AC == M[MA] - 54 MUL AC'IO = AC * M[MA] - 56 DIV AC, IO = AC'IO / M[MA] - 60 JMP PC = MA - 62 JSP AC = PC, PC = MA - - Memory reference instructions can access an address space of 64K words. - The address space is divided into sixteen 4K word fields. An - instruction can directly address, via its 12b address, the entire - current field. If extend mode is off, indirect addresses access - the current field, and indirect addressing is multi-level; if off, - they can access all 64K, and indirect addressing is single level. -*/ - -/* The skip format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 0 1 0| | | | | | | | | | | | | | skip - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | | | \______/ \______/ - | | | | | | | | - | | | | | | | +---- program flags - | | | | | | +------------- sense switches - | | | | | +------------------- AC == 0 - | | | | +---------------------- AC >= 0 - | | | +------------------------- AC < 0 - | | +---------------------------- OV == 0 - | +------------------------------- IO >= 0 - +------------------------------------- invert skip - - The shift format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 0 1 1| subopcode | encoded count | shift - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The load immediate format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 1 0 0| S| immediate | LAW - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <0:4> mnemonic action - - 70 LAW if S = 0, AC = IR<6:17> - else AC = ~IR<6:17> -*/ - -/* The I/O transfer format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 1 0 1| W| C| subopcode | device | I/O transfer - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The IO transfer instruction sends the the specified subopcode to - specified I/O device. The I/O device may take data from the IO or - return data to the IO, initiate or cancel operations, etc. The - W bit specifies whether the CPU waits for completion, the C bit - whether a completion pulse will be returned from the device. - - The operate format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 1 1 1| | | | | | | | | | | | | | operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | | | | \______/ - | | | | | | | | - | | | | | | | +---- PF select - | | | | | | +---------- clear/set PF - | | | | | +------------------- or PC - | | | | +---------------------- clear AC - | | | +------------------------- halt - | | +---------------------------- CMA - | +------------------------------- or TW - +---------------------------------- clear IO - - The operate instruction can be microprogrammed. -*/ - -/* This routine is the instruction decode routine for the PDP-1. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - breakpoint encountered - unimplemented instruction and STOP_INST flag set - XCT loop - indirect address loop - infinite wait state - I/O error in I/O simulator - - 2. Interrupts. With a single channel sequence break system, the - PDP-1 has a single break request (flop b2, here sbs). - If sequence breaks are enabled (flop sbm, here sbs), - and one is not already in progress (flop b4, here sbs), - a sequence break occurs. - - 3. Arithmetic. The PDP-1 is a 1's complement system. In 1's - complement arithmetic, a negative number is represented by the - complement (XOR 0777777) of its absolute value. Addition of 1's - complement numbers requires propagating the carry out of the high - order bit back to the low order bit. - - 4. Adding I/O devices. Three modules must be modified: - - pdp1_defs.h add interrupt request definition - pdp1_cpu.c add IOT dispatch code - pdp1_sys.c add sim_devices table entry -*/ - -#include "pdp1_defs.h" - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC -#define UNIT_V_MDV (UNIT_V_UF + 0) /* mul/div */ -#define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy mask */ -#define UNIT_MDV (1 << UNIT_V_MDV) -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -int32 M[MAXMEMSIZE] = { 0 }; /* memory */ -int32 AC = 0; /* AC */ -int32 IO = 0; /* IO */ -int32 PC = 0; /* PC */ -int32 OV = 0; /* overflow */ -int32 SS = 0; /* sense switches */ -int32 PF = 0; /* program flags */ -int32 TA = 0; /* address switches */ -int32 TW = 0; /* test word */ -int32 iosta = 0; /* status reg */ -int32 sbs = 0; /* sequence break */ -int32 sbs_init = 0; /* seq break startup */ -int32 ioh = 0; /* I/O halt */ -int32 ios = 0; /* I/O syncronizer */ -int32 cpls = 0; /* pending completions */ -int32 extm = 0; /* ext mem mode */ -int32 extm_init = 0; /* ext mem startup */ -int32 stop_inst = 0; /* stop on rsrv inst */ -int32 xct_max = 16; /* nested XCT limit */ -int32 ind_max = 16; /* nested ind limit */ -uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ - -extern UNIT *sim_clock_queue; -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -extern int32 ptr (int32 inst, int32 dev, int32 dat); -extern int32 ptp (int32 inst, int32 dev, int32 dat); -extern int32 tti (int32 inst, int32 dev, int32 dat); -extern int32 tto (int32 inst, int32 dev, int32 dat); -extern int32 lpt (int32 inst, int32 dev, int32 dat); -extern int32 dt (int32 inst, int32 dev, int32 dat); -extern int32 drm (int32 inst, int32 dev, int32 dat); - -int32 sc_map[512] = { - 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, /* 00000xxxx */ - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 00001xxxx */ - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 00010xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 00011xxxx */ - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 00100xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 00101xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 00110xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 00111xxxx */ - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 01000xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 01001xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 01010xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 01011xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 01100xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 01101xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 01110xxxx */ - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, /* 01111xxxx */ - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 10000xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 10001xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 10010xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 10011xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 10100xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 10101xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 10110xxxx */ - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, /* 11011xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 11000xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 11001xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 11010xxxx */ - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, /* 11011xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 11100xxxx */ - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, /* 11101xxxx */ - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, /* 11110xxxx */ - 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9 /* 11111xxxx */ -}; - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit - cpu_reg CPU register list - cpu_mod CPU modifier list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, MAXMEMSIZE) }; - -REG cpu_reg[] = { - { ORDATA (PC, PC, ASIZE) }, - { ORDATA (AC, AC, 18) }, - { ORDATA (IO, IO, 18) }, - { FLDATA (OV, OV, 0) }, - { ORDATA (PF, PF, 6) }, - { ORDATA (SS, SS, 6) }, - { ORDATA (TA, TA, ASIZE) }, - { ORDATA (TW, TW, 18) }, - { FLDATA (EXTM, extm, 0) }, - { ORDATA (IOSTA, iosta, 18), REG_RO }, - { FLDATA (SBON, sbs, SB_V_ON) }, - { FLDATA (SBRQ, sbs, SB_V_RQ) }, - { FLDATA (SBIP, sbs, SB_V_IP) }, - { FLDATA (IOH, ioh, 0) }, - { FLDATA (IOS, ios, 0) }, - { BRDATA (PCQ, pcq, 8, ASIZE, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { FLDATA (STOP_INST, stop_inst, 0) }, - { FLDATA (SBS_INIT, sbs_init, SB_V_ON) }, - { FLDATA (EXTM_INIT, extm_init, 0) }, - { DRDATA (XCT_MAX, xct_max, 8), PV_LEFT + REG_NZ }, - { DRDATA (IND_MAX, ind_max, 8), PV_LEFT + REG_NZ }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_MDV, UNIT_MDV, "multiply/divide", "MDV", NULL }, - { UNIT_MDV, 0, "no multiply/divide", "NOMDV", NULL }, - { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, - { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, - { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size }, - { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, - { UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size }, - { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size }, - { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size }, - { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, - { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size }, - { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, ASIZE, 1, 8, 18, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL, - NULL, 0 }; - -t_stat sim_instr (void) -{ -extern int32 sim_interval; -int32 IR, MA, op, i, t, xct_count; -int32 sign, signd, v; -int32 dev, io_data, sc, skip; -t_stat reason; -static int32 fs_test[8] = { - 0, 040, 020, 010, 04, 02, 01, 077 }; - -#define EPC_WORD ((OV << 17) | (extm << 16) | PC) -#define INCR_ADDR(x) (((x) & EPCMASK) | (((x) + 1) & DAMASK)) -#define DECR_ADDR(x) (((x) & EPCMASK) | (((x) - 1) & DAMASK)) -#define ABS(x) ((x) ^ (((x) & 0400000)? 0777777: 0)) - -/* Main instruction fetch/decode loop: check events and interrupts */ - -reason = 0; -while (reason == 0) { /* loop until halted */ - -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } - -if (sbs == (SB_ON | SB_RQ)) { /* interrupt? */ - sbs = SB_ON | SB_IP; /* set in prog flag */ - PCQ_ENTRY; /* save old PC */ - M[0] = AC; /* save state */ - M[1] = EPC_WORD; - M[2] = IO; - PC = 3; /* fetch next from 3 */ - extm = 0; /* extend off */ - OV = 0; } /* clear overflow */ - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - -/* Fetch, decode instruction */ - -MA = PC; /* PC to MA */ -IR = M[MA]; /* fetch instruction */ -PC = INCR_ADDR (PC); /* increment PC */ -xct_count = 0; /* track nested XCT's */ -sim_interval = sim_interval - 1; - -xct_instr: /* label for XCT */ -if ((IR == (OP_JMP+IA+1)) && ((MA & EPCMASK) == 0) && (sbs & SB_ON)) { - sbs = sbs & ~SB_IP; /* seq debreak */ - PCQ_ENTRY; /* save old PC */ - OV = (M[1] >> 17) & 1; /* restore OV */ - extm = (M[1] >> 16) & 1; /* restore ext mode */ - PC = M[1] & AMASK; /* JMP I 1 */ - continue; } - -op = ((IR >> 13) & 037); /* get opcode */ -if ((op < 032) && (op != 007)) { /* mem ref instr */ - MA = (MA & EPCMASK) | (IR & DAMASK); /* direct address */ - if (IR & IA) { /* indirect addr? */ - if (extm) MA = M[MA] & AMASK; /* if ext, one level */ - else { /* multi-level */ - for (i = 0; i < ind_max; i++) { /* count indirects */ - t = M[MA]; /* get indirect word */ - MA = (MA & EPCMASK) | (t & DAMASK); - if ((t & IA) == 0) break; } - if (i >= ind_max) { /* indirect loop? */ - reason = STOP_IND; - break; } } } } - -switch (op) { /* decode IR<0:4> */ - -/* Logical, load, store instructions */ - -case 001: /* AND */ - AC = AC & M[MA]; - break; - -case 002: /* IOR */ - AC = AC | M[MA]; - break; - -case 003: /* XOR */ - AC = AC ^ M[MA]; - break; - -case 004: /* XCT */ - if (xct_count >= xct_max) { /* too many XCT's? */ - reason = STOP_XCT; - break; } - xct_count = xct_count + 1; /* count XCT's */ - IR = M[MA]; /* get instruction */ - goto xct_instr; /* go execute */ - -case 007: /* CAL, JDA */ - MA = (PC & EPCMASK) | ((IR & IA)? (IR & DAMASK): 0100); - PCQ_ENTRY; - M[MA] = AC; - AC = EPC_WORD; - PC = INCR_ADDR (MA); - break; - -case 010: /* LAC */ - AC = M[MA]; - break; - -case 011: /* LIO */ - IO = M[MA]; - break; - -case 012: /* DAC */ - if (MEM_ADDR_OK (MA)) M[MA] = AC; - break; - -case 013: /* DAP */ - if (MEM_ADDR_OK (MA)) M[MA] = (AC & DAMASK) | (M[MA] & ~DAMASK); - break; - -case 014: /* DIP */ - if (MEM_ADDR_OK (MA)) M[MA] = (AC & ~DAMASK) | (M[MA] & DAMASK); - break; - -case 015: /* DIO */ - if (MEM_ADDR_OK (MA)) M[MA] = IO; - break; - -case 016: /* DZM */ - if (MEM_ADDR_OK (MA)) M[MA] = 0; - break; - -/* Add, subtract, control - - Add is performed in sequential steps, as follows: - 1. add - 2. end around carry propagate - 3. overflow check - 4. -0 cleanup - - Subtract is performed in sequential steps, as follows: - 1. complement AC - 2. add - 3. end around carry propagate - 4. overflow check - 5. complement AC - Because no -0 check is done, (-0) - (+0) yields a result of -0 -*/ - -case 020: /* ADD */ - t = AC; - AC = AC + M[MA]; - if (AC > 0777777) AC = (AC + 1) & 0777777; /* end around carry */ - if (((~t ^ M[MA]) & (t ^ AC)) & 0400000) OV = 1; - if (AC == 0777777) AC = 0; /* minus 0 cleanup */ - break; - -case 021: /* SUB */ - t = AC ^ 0777777; /* complement AC */ - AC = t + M[MA]; /* -AC + MB */ - if (AC > 0777777) AC = (AC + 1) & 0777777; /* end around carry */ - if (((~t ^ M[MA]) & (t ^ AC)) & 0400000) OV = 1; - AC = AC ^ 0777777; /* recomplement AC */ - break; - -case 022: /* IDX */ - AC = M[MA] + 1; - if (AC >= 0777777) AC = (AC + 1) & 0777777; - if (MEM_ADDR_OK (MA)) M[MA] = AC; - break; - -case 023: /* ISP */ - AC = M[MA] + 1; - if (AC >= 0777777) AC = (AC + 1) & 0777777; - if (MEM_ADDR_OK (MA)) M[MA] = AC; - if (AC < 0400000) PC = INCR_ADDR (PC); - break; - -case 024: /* SAD */ - if (AC != M[MA]) PC = INCR_ADDR (PC); - break; - -case 025: /* SAS */ - if (AC == M[MA]) PC = INCR_ADDR (PC); - break; - -case 030: /* JMP */ - PCQ_ENTRY; - PC = MA; - break; - -case 031: /* JSP */ - AC = EPC_WORD; - PCQ_ENTRY; - PC = MA; - break; - -case 034: /* LAW */ - AC = (IR & 07777) ^ ((IR & IA)? 0777777: 0); - break; - -/* Multiply and divide - - Multiply and divide step and hardware multiply are exact implementations. - Hardware divide is a 2's complement analog to the actual hardware. -*/ - -case 026: /* MUL */ - if (cpu_unit.flags & UNIT_MDV) { /* hardware? */ - sign = AC ^ M[MA]; /* result sign */ - IO = ABS (AC); /* IO = |AC| */ - v = ABS (M[MA]); /* v = |mpy| */ - for (i = AC = 0; i < 17; i++) { - if (IO & 1) AC = AC + v; - IO = (IO >> 1) | ((AC & 1) << 17); - AC = AC >> 1; } - if ((sign & 0400000) && (AC | IO)) { /* negative, > 0? */ - AC = AC ^ 0777777; - IO = IO ^ 0777777; } } - else { /* multiply step */ - if (IO & 1) AC = AC + M[MA]; - if (AC > 0777777) AC = (AC + 1) & 0777777; - if (AC == 0777777) AC = 0; - IO = (IO >> 1) | ((AC & 1) << 17); - AC = AC >> 1; } - break; - -case 027: /* DIV */ - if (cpu_unit.flags & UNIT_MDV) { /* hardware */ - sign = AC ^ M[MA]; /* result sign */ - signd = AC; /* remainder sign */ - if (AC & 0400000) { - AC = AC ^ 0777777; /* AC'IO = |AC'IO| */ - IO = IO ^ 0777777; } - v = ABS (M[MA]); /* v = |divr| */ - if (AC >= v) break; /* overflow? */ - for (i = t = 0; i < 18; i++) { - if (t) AC = (AC + v) & 0777777; - else AC = (AC - v) & 0777777; - t = AC >> 17; - if (i != 17) AC = ((AC << 1) | (IO >> 17)) & 0777777; - IO = ((IO << 1) | (t ^ 1)) & 0777777; } - if (t) AC = (AC + v) & 0777777; /* correct remainder */ - t = ((signd & 0400000) && AC)? AC ^ 0777777: AC; - AC = ((sign & 0400000) && IO)? IO ^ 0777777: IO; - IO = t; - PC = INCR_ADDR (PC); } /* skip */ - else { /* divide step */ - t = AC >> 17; - AC = ((AC << 1) | (IO >> 17)) & 0777777; - IO = ((IO << 1) | (t ^ 1)) & 0777777; - if (IO & 1) AC = AC + (M[MA] ^ 0777777); - else AC = AC + M[MA] + 1; - if (AC > 0777777) AC = (AC + 1) & 0777777; - if (AC == 0777777) AC = 0; } - break; - -/* Skip and operate - - Operates execute in the order shown; there are no timing conflicts -*/ - -case 032: /* skip */ - v = (IR >> 3) & 07; /* sense switches */ - t = IR & 07; /* program flags */ - skip = (((IR & 02000) && (IO < 0400000)) || /* SPI */ - ((IR & 01000) && (OV == 0)) || /* SZO */ - ((IR & 00400) && (AC >= 0400000)) || /* SMA */ - ((IR & 00200) && (AC < 0400000)) || /* SPA */ - ((IR & 00100) && (AC == 0)) || /* SZA */ - (v && ((SS & fs_test[v]) == 0)) || /* SZSn */ - (t && ((PF & fs_test[t]) == 0))); /* SZFn */ - if (IR & IA) skip = skip ^ 1; /* invert skip? */ - if (skip) PC = INCR_ADDR (PC); - if (IR & 01000) OV = 0; /* SOV clears OV */ - break; - -case 037: /* operate */ - if (IR & 04000) IO = 0; /* CLI */ - if (IR & 00200) AC = 0; /* CLA */ - if (IR & 02000) AC = AC | TW; /* LAT */ - if (IR & 00100) AC = AC | EPC_WORD; /* LAP */ - if (IR & 01000) AC = AC ^ 0777777; /* CMA */ - if (IR & 00400) reason = STOP_HALT; /* HALT */ - t = IR & 07; /* flag select */ - if (IR & 010) PF = PF | fs_test[t]; /* STFn */ - else PF = PF & ~fs_test[t]; /* CLFn */ - break; - -/* Shifts */ - -case 033: - sc = sc_map[IR & 0777]; /* map shift count */ - switch ((IR >> 9) & 017) { /* case on IR<5:8> */ - case 001: /* RAL */ - AC = ((AC << sc) | (AC >> (18 - sc))) & 0777777; - break; - case 002: /* RIL */ - IO = ((IO << sc) | (IO >> (18 - sc))) & 0777777; - break; - case 003: /* RCL */ - t = AC; - AC = ((AC << sc) | (IO >> (18 - sc))) & 0777777; - IO = ((IO << sc) | (t >> (18 - sc))) & 0777777; - break; - case 005: /* SAL */ - t = (AC & 0400000)? 0777777: 0; - AC = (AC & 0400000) | ((AC << sc) & 0377777) | - (t >> (18 - sc)); - break; - case 006: /* SIL */ - t = (IO & 0400000)? 0777777: 0; - IO = (IO & 0400000) | ((IO << sc) & 0377777) | - (t >> (18 - sc)); - break; - case 007: /* SCL */ - t = (AC & 0400000)? 0777777: 0; - AC = (AC & 0400000) | ((AC << sc) & 0377777) | - (IO >> (18 - sc)); - IO = ((IO << sc) | (t >> (18 - sc))) & 0777777; - break; - case 011: /* RAR */ - AC = ((AC >> sc) | (AC << (18 - sc))) & 0777777; - break; - case 012: /* RIR */ - IO = ((IO >> sc) | (IO << (18 - sc))) & 0777777; - break; - case 013: /* RCR */ - t = IO; - IO = ((IO >> sc) | (AC << (18 - sc))) & 0777777; - AC = ((AC >> sc) | (t << (18 - sc))) & 0777777; - break; - case 015: /* SAR */ - t = (AC & 0400000)? 0777777: 0; - AC = ((AC >> sc) | (t << (18 - sc))) & 0777777; - break; - case 016: /* SIR */ - t = (IO & 0400000)? 0777777: 0; - IO = ((IO >> sc) | (t << (18 - sc))) & 0777777; - break; - case 017: /* SCR */ - t = (AC & 0400000)? 0777777: 0; - IO = ((IO >> sc) | (AC << (18 - sc))) & 0777777; - AC = ((AC >> sc) | (t << (18 - sc))) & 0777777; - break; - default: /* undefined */ - reason = stop_inst; - break; } /* end switch shifts */ - break; - -/* IOT - The simulator behaves functionally like a real PDP-1 but does not - use the same mechanisms or state bits. In particular, - - - If an IOT does not specify IO_WAIT, the IOT will be executed, and the - I/O halt flag (IOH) will not be disturbed. On the real PDP-1, IOH is - stored in IHS, IOH is cleared, the IOT is executed, and then IOH is - restored from IHS. Because IHS is not otherwise used, it is not - explicitly simulated. - - If an IOT does specify IO_WAIT, then IOH specifies whether an I/O halt - (wait) is already in progress. - > If already set, I/O wait is in progress. The simulator looks for - a completion pulse (IOS). If there is a pulse, IOH is cleared. If - not, the IOT is fetched again. In either case, execution of the - IOT is skipped. - > If not set, I/O wait must start. IOH is set, the PC is backed up, - and the IOT is executed. - On a real PDP-1, IOC is the I/O command enable and enables the IOT - pulses. In the simulator, the enabling of IOT pulses is done through - code flow, and IOC is not explicitly simulated. -*/ - -case 035: - if (IR & IO_WAIT) { /* wait? */ - if (ioh) { /* I/O halt? */ - if (ios) ioh = 0; /* comp pulse? done */ - else { /* wait more */ - PC = DECR_ADDR (PC); /* re-execute */ - if (cpls == 0) { /* any pending pulses? */ - reason = STOP_WAIT; /* no, CPU hangs */ - break; } - sim_interval = 0; } /* force event */ - break; } /* skip iot */ - ioh = 1; /* turn on halt */ - PC = DECR_ADDR (PC); } /* re-execute */ - dev = IR & 077; /* get dev addr */ - io_data = IO; /* default data */ - switch (dev) { /* case on dev */ - case 000: /* I/O wait */ - break; - case 001: - if (IR & 003700) io_data = dt (IR, dev, IO); /* DECtape */ - else io_data = ptr (IR, dev, IO); /* paper tape rdr */ - break; - case 002: case 030: /* paper tape rdr */ - io_data = ptr (IR, dev, IO); - break; - case 003: /* typewriter */ - io_data = tto (IR, dev, IO); - break; - case 004: /* keyboard */ - io_data = tti (IR, dev, IO); - break; - case 005: case 006: /* paper tape punch */ - io_data = ptp (IR, dev, IO); - break; - case 033: /* check status */ - io_data = iosta | ((sbs & SB_ON)? IOS_SQB: 0); - break; - case 045: /* line printer */ - io_data = lpt (IR, dev, IO); - break; - case 054: /* seq brk off */ - sbs = sbs & ~SB_ON; - break; - case 055: /* seq brk on */ - sbs = sbs | SB_ON; - break; - case 056: /* clear seq brk */ - sbs = sbs & ~SB_IP; - break; - case 061: case 062: case 063: case 064: /* drum */ - io_data = drm (IR, dev, IO); - break; - case 074: /* extend mode */ - extm = (IR >> 11) & 1; /* set from IR<6> */ - break; - default: /* undefined */ - reason = stop_inst; - break; } /* end switch dev */ - IO = io_data & 0777777; - if (io_data & IOT_SKP) PC = INCR_ADDR (PC); /* skip? */ - if (io_data >= IOT_REASON) reason = io_data >> IOT_V_REASON; - break; - -default: /* undefined */ - reason = STOP_RSRV; /* halt */ - break; } /* end switch opcode */ -} /* end while */ -pcq_r->qptr = pcq_p; /* update pc q ptr */ -return reason; -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -sbs = sbs_init; -extm = extm_init; -ioh = ios = cpls = 0; -OV = 0; -PF = 0; -pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & 0777777; -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -M[addr] = val & 0777777; -return SCPE_OK; -} - -/* Change memory size */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; -if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_OK; -MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; -return SCPE_OK; -} diff --git a/PDP1/pdp1_defs.h b/PDP1/pdp1_defs.h deleted file mode 100644 index e113db12..00000000 --- a/PDP1/pdp1_defs.h +++ /dev/null @@ -1,125 +0,0 @@ -/* pdp1_defs.h: 18b PDP simulator definitions - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 22-Jul-03 RMS Updated for "hardware" RIM loader - Revised to detect I/O wait hang - 05-Dec-02 RMS Added IOT skip support (required by drum) - 14-Apr-99 RMS Changed t_addr to unsigned - - The PDP-1 was Digital's first computer. The system design evolved during - its life, and as a result, specifications are sketchy or contradictory. - This simulator is based on the 1962 maintenance manual. - - This simulator implements the following options: - - Automatic multiply/divide Type 10 - Memory extension control Type 15 - Serial drum Type 24 - Line printer control Type 62 - Microtape (DECtape) control Type 550 -*/ - -#include "sim_defs.h" - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_XCT 4 /* nested XCT's */ -#define STOP_IND 5 /* nested indirects */ -#define STOP_WAIT 6 /* IO wait hang */ - -/* Memory */ - -#define ASIZE 16 /* address bits */ -#define MAXMEMSIZE (1u << ASIZE) /* max mem size */ -#define AMASK (MAXMEMSIZE - 1) /* address mask */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) - -/* Architectural constants */ - -#define DMASK 0777777 /* data mask */ -#define DAMASK 0007777 /* direct addr */ -#define EPCMASK (AMASK & ~DAMASK) /* extended addr */ -#define IA 0010000 /* indirect flag */ -#define IO_WAIT 0010000 /* I/O sync wait */ -#define IO_CPLS 0004000 /* completion pulse */ -#define OP_DAC 0240000 /* DAC */ -#define OP_DIO 0320000 /* DIO */ -#define OP_JMP 0600000 /* JMP */ -#define GEN_CPLS(x) (((x) ^ ((x) << 1)) & IO_WAIT) /* completion pulse? */ - -/* IOT subroutine return codes */ - -#define IOT_V_SKP 18 /* skip */ -#define IOT_SKP (1 << IOT_V_SKP) -#define IOT_V_REASON (IOT_V_SKP + 1) /* reason */ -#define IOT_REASON (1 << IOT_V_REASON) -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ - -/* I/O status flags */ - -#define IOS_V_LPN 17 /* light pen */ -#define IOS_V_PTR 16 /* paper tape reader */ -#define IOS_V_TTO 15 /* typewriter out */ -#define IOS_V_TTI 14 /* typewriter in */ -#define IOS_V_PTP 13 /* paper tape punch */ -#define IOS_V_DRM 12 /* drum */ -#define IOS_V_SQB 11 /* sequence break */ -#define IOS_V_PNT 2 /* print done */ -#define IOS_V_SPC 1 /* space done */ - -#define IOS_LPN (1 << IOS_V_LPN) -#define IOS_PTR (1 << IOS_V_PTR) -#define IOS_TTO (1 << IOS_V_TTO) -#define IOS_TTI (1 << IOS_V_TTI) -#define IOS_PTP (1 << IOS_V_PTP) -#define IOS_DRM (1 << IOS_V_DRM) -#define IOS_SQB (1 << IOS_V_SQB) -#define IOS_PNT (1 << IOS_V_PNT) -#define IOS_SPC (1 << IOS_V_SPC) - -/* Completion pulses */ - -#define CPLS_V_PTR 5 -#define CPLS_V_PTP 4 -#define CPLS_V_TTO 3 -#define CPLS_V_LPT 2 -#define CPLS_PTR (1 << CPLS_V_PTR) -#define CPLS_PTP (1 << CPLS_V_PTP) -#define CPLS_TTO (1 << CPLS_V_TTO) -#define CPLS_LPT (1 << CPLS_V_LPT) - -/* Sequence break flags */ - -#define SB_V_IP 0 /* in progress */ -#define SB_V_RQ 1 /* request */ -#define SB_V_ON 2 /* enabled */ - -#define SB_IP (1 << SB_V_IP) -#define SB_RQ (1 << SB_V_RQ) -#define SB_ON (1 << SB_V_ON) diff --git a/PDP1/pdp1_doc.txt b/PDP1/pdp1_doc.txt deleted file mode 100644 index e0fda843..00000000 --- a/PDP1/pdp1_doc.txt +++ /dev/null @@ -1,516 +0,0 @@ -To: Users -From: Bob Supnik -Subj: PDP-1 Simulator Usage -Date: 15-Sep-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - Original code published in 1993-2003, written by Robert M Supnik - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - -This memorandum documents the PDP-1 simulator. - - -1. Simulator Files - -sim/ sim_defs.h - sim_rev.h - sim_sock.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tmxr.c - -sim/pdp1/ pdp1_defs.h - pdp1_cpu.c - pdp1_drm.c - pdp1_dt.c - pdp1_lp.c - pdp1_stddev.c - pdp1_sys.c - -2. PDP-1 Features - -The PDP-1 is configured as follows: - -device simulates -name(s) - -CPU PDP-1 CPU with up to 64KW of memory -PTR,PTP integral paper tape reader/punch -TTY console typewriter -LPT Type 62 line printer -DRM Type 24 serial drum -DT Type 550 Microtape (DECtape) - -The PDP-1 simulator implements the following unique stop conditions: - - - an unimplemented instruction is decoded, and register - STOP_INST is set - - more than IND_MAX indirect addresses are detected during - memory reference address decoding - - more than XCT_MAX nested executes are detected during - instruction execution - - I/O wait, and no I/O operations outstanding (i.e, no I/O - completion will ever occur) - -The PDP-1 loader supports RIM format tapes and BLK format tapes. If -the file to be loaded has an extension of .BIN, or switch -B is specified, -the file is assumed to be BLK format; otherwise, it defaults to RIM -format. LOAD takes an optional argument which specifies the starting -address of the field to be loaded: - - LOAD lisp.rim -- load RIM format file lisp.rim - LOAD ddt.rim 70000 -- load RIM format file ddt.rim into - the field starting at 70000 - LOAD -B macro.blk -- load BLK format file macro.blk - -The DUMP command is not implemented. - -2.1 CPU - -The only CPU options are the presence of hardware multiply/divide and the -size of main memory. - - SET CPU MDV enable multiply/divide - SET CPU NOMDV disable multiply/divide - SET CPU 4K set memory size = 4K - SET CPU 8K set memory size = 8K - SET CPU 12K set memory size = 12K - SET CPU 16K set memory size = 16K - SET CPU 20K set memory size = 20K - SET CPU 24K set memory size = 24K - SET CPU 28K set memory size = 28K - SET CPU 32K set memory size = 32K - SET CPU 48K set memory size = 48K - SET CPU 64K set memory size = 64K - -If memory size is being reduced, and the memory being truncated contains -non-zero data, the simulator asks for confirmation. Data in the truncated -portion of memory is lost. Initial memory size is 64K. - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - PC 16 program counter - AC 18 accumulator - IO 18 IO register - OV 1 overflow flag - PF 6 program flags<1:6> - SS 6 sense switches<1:6> - TA 16 address switches - TW 18 test word (front panel switches) - EXTM 1 extend mode - IOSTA 18 IO status register - SBON 1 sequence break enable - SBRQ 1 sequence break request - SBIP 1 sequence break in progress - IOH 1 I/O halt in progress - IOS 1 I/O synchronizer (completion) - PCQ[0:63] 16 PC prior to last jump or interrupt; - most recent PC change first - STOP_INST 1 stop on undefined instruction - SBS_INIT 1 initial state of sequence break enable - EXTM_INIT 1 initial state of extend mode - XCT_MAX 8 maximum XCT chain - IND_MAX 8 maximum nested indirect addresses - WRU 8 interrupt character - -2.2 Programmed I/O Devices - -2.2.1 Paper Tape Reader (PTR) - -The paper tape reader (PTR) reads data from or a disk file. The POS -register specifies the number of the next data item to be read. Thus, -by changing POS, the user can backspace or advance the reader. - -The paper tape reader supports the BOOT command. BOOT PTR copies the -RIM loader into memory and starts it running. BOOT PTR loads into the -field selected by TA<0:3> (the high order four bits of the address -switches). - -The paper tape reader implements these registers: - - name size comments - - BUF 8 last data item processed - DONE 1 device done flag - RPLS 1 return restart pulse flag - POS 32 position in the input file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - end of file 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -2.2.2 Paper Tape Punch (PTP) - -The paper tape punch (PTP) writes data to a disk file. The POS -register specifies the number of the next data item to be written. -Thus, by changing POS, the user can backspace or advance the punch. - -The paper tape punch implements these registers: - - name size comments - - BUF 8 last data item processed - DONE 1 device done flag - RPLS 1 return restart pulse flag - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -2.2.3 Console Typewriter (TTY) - -The Typewriter is a half-duplex electric typewriter (originally a -Friden Flexowriter, later a Sorobon-modified IBM B). It has only a -single buffer and a single carriage state but distinct input and -output done and interrupt flags. The typewriter input (TTY unit 0) -polls the console keyboard for input. The typewriter output (TTY -unit 1) writes to the simulator console window. - -The typewriter implements these registers: - - name size comments - - BUF 6 typewriter buffer - UC 1 upper case/lower case state flag - RPLS 1 return restart pulse flag - KDONE 1 input ready flag - KPOS 32 number of characters input - KTIME 24 keyboard polling interval - TDONE 1 output done flag - TPOS 32 number of characters output - TTIME 24 time from I/O initiation to interrupt - -2.2.4 Type 62 Line Printer (LPT) - -The paper line printer (LPT) writes data to a disk file. The POS -register specifies the number of the next data item to be written. -Thus, by changing POS, the user can backspace or advance the printer. - -The line printer can be disabled and enabled with the SET LPT DISABLED -and SET LPT ENABLED commands, respectively. - -The line printer implements these registers: - - name size comments - - BUF 8 last data item processed - PNT 1 printing done flag - SPC 1 spacing done flag - RPLS 1 return restart pulse flag - BPTR 6 print buffer pointer - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - LBUF[0:119] 8 line buffer - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape or paper - - OS I/O error x report error and stop - -2.3 Type 550/555 Microtape (DECtape) (DT) - -The PDP-1 uses the Type 550 Microtape (later renamed DECtape), a programmed -I/O controller. PDP-1 DECtape format has 4 18b words in its block headers -and trailers. - -DECtapes drives are numbered 1-8; in the simulator, drive 8 is unit 0. -DECtape options include the ability to make units write enabled or write -locked. - - SET DTn WRITEENABLED set unit n write enabled - SET DTn LOCKED set unit n write locked - -Units can also be set ONLINE or OFFLINE. - -The DECtape controller can be disabled and enabled with the SET DT DISABLED -and SET DT ENABLED commands, respectively. - -The Type 550 supports PDP-8 format, PDP-11 format, and 18b format DECtape -images. ATTACH tries to determine the tape format from the DECtape image; -the user can force a particular format with switches: - - -r PDP-8 format - -s PDP-11 format - -t 18b format - -The DECtape controller is a data-only simulator; the timing and mark -track, and block header and trailer, are not stored. Thus, the WRITE -TIMING AND MARK TRACK function is not supported; the READ ALL function -always returns the hardware standard block header and trailer; and the -WRITE ALL function dumps non-data words into the bit bucket. - -The DECtape controller implements these registers: - - name size comments - - DTSA 12 status register A - DTSB 12 status register B - DTDB 18 data buffer - DTF 1 DECtape flag - BEF 1 block end flag - ERF 1 error flag - LTIME 31 time between lines - ACTIME 31 time to accelerate to full speed - DCTIME 31 time to decelerate to a full stop - SUBSTATE 2 read/write command substate - POS[0:7] 32 position, in lines, units 0-7 - STATT[0:7] 18 unit state, units 0-7 - -It is critically important to maintain certain timing relationships -among the DECtape parameters, or the DECtape simulator will fail to -operate correctly. - - - LTIME must be at least 6 - - ACTIME must be less than DCTIME, and both need to be at - least 100 times LTIME - -2.4 Type 24 Serial Drum (DRM) - -The serial drum (DRM) implements these registers: - - name size comments - - DA 9 drum address (sector number) - MA 16 current memory address - INT 1 interrupt pending flag - DONE 1 device done flag - ERR 1 error flag - WLK 32 write lock switches - TIME 24 rotational latency, per word - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -Drum data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.5 Symbolic Display and Input - -The PDP-1 simulator implements symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as FIODEC character string - -m display instruction mnemonics - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or -a ASCII character - " or -c three character FIODEC string - alphabetic instruction mnemonic - numeric octal number - -Instruction input uses modified PDP-1 assembler syntax. There are six -instruction classes: memory reference, shift, skip, operate, IOT, and -LAW. - -Memory reference instructions have the format - - memref {I} address - -where I signifies indirect reference. The address is an octal number in -the range 0 - 0177777. - -Shift instructions have the format - - shift shift_count - -The shift count is an octal number in the range 0-9. - -Skip instructions consist of single mnemonics, eg, SZA, SZS4. Skip -instructions may be or'd together - - skip skip skip... - -The sense of a skip can be inverted by including the mnemonic I. - -Operate instructions consist of single mnemonics, eg, CLA, CLI. Operate -instructions may be or'd together - - opr opr opr... - -IOT instructions consist of single mnemonics, eg, TYI, TYO. IOT -instructions may include an octal numeric modifier or the modifier I: - - iot modifier - -The simulator does not check the legality of skip, operate, or IOT -combinations. - -Finally, the LAW instruction has the format - - LAW {I} immediate - -where immediate is in the range 0 to 07777. - -2.6 Character Sets - -The PDP-1's first console was a Frieden Flexowriter; its character encoding -was known as FIODEC. The PDP-1's line printer used a modified Hollerith -character set. The following table provides equivalences between ASCII -characters and the PDP-1's I/O devices. In the console table, UC stands -for upper case. - - PDP-1 PDP-1 -ASCII console line printer - -000 - 007 none none -bs 075 none -tab 036 none -012 - 014 none none -cr 077 none -016 - 037 none none -space 000 000 -! {OR} UC+005 none -" UC+001 none -# {IMPLIES} UC+004 none -$ none none -% none none -& {AND} UC+006 none -' UC+002 none -( 057 057 -) 055 055 -* {TIMES} UC+073 072 -+ UC+054 074 -, 033 033 -- 054 054 -. 073 073 -/ 021 021 -0 020 020 -1 001 001 -2 002 002 -3 003 003 -4 004 004 -5 005 005 -6 006 006 -7 007 007 -8 010 010 -9 011 011 -: none none -; none none -< UC+007 034 -= UC+033 053 -> UC+010 034 -? UC+021 037 -@ {MID DOT} 040 {MID DOT} 040 -A UC+061 061 -B UC+062 062 -C UC+063 063 -D UC+064 064 -E UC+065 065 -F UC+066 066 -G UC+067 067 -H UC+070 070 -I UC+071 071 -J UC+041 041 -K UC+042 042 -L UC+043 043 -M UC+044 044 -N UC+045 045 -O UC+046 046 -P UC+047 047 -Q UC+050 050 -R UC+051 051 -S UC+022 022 -T UC+023 023 -U UC+024 024 -V UC+025 025 -W UC+026 026 -X UC+027 027 -Y UC+030 030 -Z UC+031 031 -[ UC+057 none -\ {OVERLINE} 056 {OVERLINE} 056 -] UC+055 none -^ {UP ARROW} UC+011 {UP ARROW} 035 -_ UC+040 UC+040 -` {RT ARROW} UC+020 036 -a 061 none -b 062 none -c 063 none -d 064 none -e 065 none -f 066 none -g 067 none -h 070 none -i 071 none -j 041 none -k 042 none -l 043 none -m 044 none -n 045 none -o 046 none -p 047 none -q 050 none -r 051 none -s 022 none -t 023 none -u 024 none -v 025 none -w 026 none -x 027 none -y 030 none -z 031 none -{ none none -| UC+056 076 -} none none -~ UC+003 013 -del 075 none diff --git a/PDP1/pdp1_drm.c b/PDP1/pdp1_drm.c deleted file mode 100644 index 1d396723..00000000 --- a/PDP1/pdp1_drm.c +++ /dev/null @@ -1,169 +0,0 @@ -/* pdp1_drm.c: PDP-1 drum simulator - - Copyright (c) 1993-2002, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - drm Type 24 serial drum - - 23-Jul-03 RMS Fixed incorrect logical, missing activate - 05-Dec-02 RMS Cloned from pdp18b_drm.c -*/ - -#include "pdp1_defs.h" -#include - -/* Constants */ - -#define DRM_NUMWDS 256 /* words/sector */ -#define DRM_NUMSC 2 /* sectors/track */ -#define DRM_NUMTR 256 /* tracks/drum */ -#define DRM_NUMDK 1 /* drum/controller */ -#define DRM_NUMWDT (DRM_NUMWDS * DRM_NUMSC) /* words/track */ -#define DRM_SIZE (DRM_NUMDK * DRM_NUMTR * DRM_NUMWDT) /* words/drum */ -#define DRM_SMASK ((DRM_NUMTR * DRM_NUMSC) - 1) /* sector mask */ - -/* Parameters in the unit descriptor */ - -#define FUNC u4 /* function */ -#define DRM_READ 000 /* read */ -#define DRM_WRITE 010 /* write */ - -#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ - ((double) DRM_NUMWDT))) - -extern int32 M[]; -extern int32 iosta, sbs; -extern int32 stop_inst; -extern UNIT cpu_unit; - -int32 drm_da = 0; /* track address */ -int32 drm_ma = 0; /* memory address */ -int32 drm_err = 0; /* error flag */ -int32 drm_wlk = 0; /* write lock */ -int32 drm_time = 10; /* inter-word time */ -int32 drm_stopioe = 1; /* stop on error */ - -t_stat drm_svc (UNIT *uptr); -t_stat drm_reset (DEVICE *dptr); - -/* DRM data structures - - drm_dev DRM device descriptor - drm_unit DRM unit descriptor - drm_reg DRM register list -*/ - -UNIT drm_unit = - { UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, - DRM_SIZE) }; - -REG drm_reg[] = { - { ORDATA (DA, drm_da, 9) }, - { ORDATA (MA, drm_ma, 16) }, - { FLDATA (DONE, iosta, IOS_V_DRM) }, - { FLDATA (ERR, drm_err, 0) }, - { ORDATA (WLK, drm_wlk, 32) }, - { DRDATA (TIME, drm_time, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, drm_stopioe, 0) }, - { NULL } }; - -DEVICE drm_dev = { - "DRM", &drm_unit, drm_reg, NULL, - 1, 8, 20, 1, 8, 18, - NULL, NULL, &drm_reset, - NULL, NULL, NULL, - NULL, DEV_DISABLE }; - -/* IOT routines */ - -int32 drm (int32 IR, int32 dev, int32 dat) -{ -int32 t; -int32 pulse = (IR >> 6) & 037; - -if (drm_dev.flags & DEV_DIS) /* disabled? */ - return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ -if ((pulse != 001) && (pulse != 011)) /* invalid pulse? */ - return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ -switch (dev) { /* switch on device */ -case 061: /* DWR, DRD */ - drm_ma = dat & 0177777; /* load mem addr */ - drm_unit.FUNC = pulse & DRM_WRITE; /* save function */ - break; -case 062: /* DBL, DCN */ - if (pulse & 010) drm_da = dat & DRM_SMASK; /* load sector # */ - iosta = iosta & ~IOS_DRM; /* clear flags */ - drm_err = 0; - t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time); - if (t <= 0) t = t + DRM_NUMWDT; /* wrap around? */ - sim_activate (&drm_unit, t); /* start operation */ - break; -case 063: /* DTD */ - if (pulse == 011) return (stop_inst << IOT_V_REASON) | dat; - if (iosta & IOS_DRM) return (dat | IOT_SKP); /* skip if done */ - break; -case 064: /* DSE, DSP */ - if ((drm_err == 0) || (pulse & 010)) /* no error, par test? */ - return (dat | IOT_SKP); - } -return dat; -} - -/* Unit service - this code assumes the entire drum is buffered */ - -t_stat drm_svc (UNIT *uptr) -{ -uint32 i, da; - -if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ - drm_err = 1; /* set error */ - iosta = iosta | IOS_DRM; /* set done */ - sbs = sbs | SB_RQ; /* req intr */ - return IORETURN (drm_stopioe, SCPE_UNATT); } - -da = drm_da * DRM_NUMWDS; /* compute dev addr */ -for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */ - if (uptr->FUNC == DRM_READ) { - if (MEM_ADDR_OK (drm_ma)) /* read, check nxm */ - M[drm_ma] = *(((int32 *) uptr->filebuf) + da); } - else { - if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1; - else { - *(((int32 *) uptr->filebuf) + da) = M[drm_ma]; - if (da >= uptr->hwmark) uptr->hwmark = da + 1; } } - drm_ma = (drm_ma + 1) & 0177777; } /* incr mem addr */ -drm_da = (drm_da + 1) & DRM_SMASK; /* incr dev addr */ -iosta = iosta | IOS_DRM; /* set done */ -sbs = sbs | SB_RQ; /* req intr */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat drm_reset (DEVICE *dptr) -{ -drm_da = drm_ma = drm_err = 0; -iosta = iosta & ~IOS_DRM; -sim_cancel (&drm_unit); -return SCPE_OK; -} diff --git a/PDP1/pdp1_dt.c b/PDP1/pdp1_dt.c deleted file mode 100644 index bbafc553..00000000 --- a/PDP1/pdp1_dt.c +++ /dev/null @@ -1,983 +0,0 @@ -/* pdp1_dt.c: 18b DECtape simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - dt Type 550/555 DECtape - - 25-Apr-03 RMS Revised for extended file support - 14-Mar-03 RMS Fixed variable size interaction with save/restore - 17-Oct-02 RMS Fixed bug in end of reel logic - 06-Oct-02 RMS Added device disable support - 13-Aug-02 RMS Cloned from pdp18b_dt.c - - 18b DECtapes are represented in memory by fixed length buffer of 32b words. - Three file formats are supported: - - 18b/36b 256 words per block [256 x 18b] - 16b 256 words per block [256 x 16b] - 12b 129 words per block [129 x 12b] - - When a 16b or 12b DECtape file is read in, it is converted to 18b/36b format. - - DECtape motion is measured in 3b lines. Time between lines is 33.33us. - Tape density is nominally 300 lines per inch. The format of a DECtape is - - reverse end zone 36000 lines ~ 10 feet - block 0 - : - block n - forward end zone 36000 lines ~ 10 feet - - A block consists of five 18b header words, a tape-specific number of data - words, and five 18b trailer words. All systems except the PDP-8 use a - standard block length of 256 words; the PDP-8 uses a standard block length - of 86 words (x 18b = 129 words x 12b). [A PDP-1/4/7 DECtape has only four 18b - header words; for consistency, the PDP-1/4/7 uses the same format as the PDP-9/15 - but skips the missing header words.] - - Because a DECtape file only contains data, the simulator cannot support - write timing and mark track and can only do a limited implementation - of read all and write all. Read all assumes that the tape has been - conventionally written forward: - - header word 0 0 - header word 1 block number (for forward reads) - header words 2,3 0 - header word 4 0 - : - trailer word 4 checksum - trailer words 3,2 0 - trailer word 1 block number (for reverse reads) - trailer word 0 0 - - Write all writes only the data words and dumps the interblock words in the - bit bucket. - - The Type 550 controller has a 4b unit select field, for units 1-8; the TC02 - has a 3b unit select field, with unit 8 being represented as 0. The code - assumes that the GETUNIT macro returns a unit number in the range of 0-7, - with 8 represented as 0, and an invalid unit as -1. -*/ - -#include "pdp1_defs.h" - -#define DT_NUMDR 8 /* #drives */ -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_8FMT (UNIT_V_UF + 1) /* 12b format */ -#define UNIT_V_11FMT (UNIT_V_UF + 2) /* 16b format */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_8FMT (1 << UNIT_V_8FMT) -#define UNIT_11FMT (1 << UNIT_V_11FMT) -#define STATE u3 /* unit state */ -#define LASTT u4 /* last time update */ -#define DT_WC 030 /* word count */ -#define DT_CA 031 /* current addr */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -/* System independent DECtape constants */ - -#define DT_EZLIN 36000 /* end zone length */ -#define DT_HTLIN 30 /* header/trailer lines */ -#define DT_BLKLN 6 /* blk no line in h/t */ -#define DT_CSMLN 24 /* checksum line in h/t */ -#define DT_HTWRD (DT_HTLIN / DT_WSIZE) /* header/trailer words */ -#define DT_BLKWD (DT_BLKLN / DT_WSIZE) /* blk no word in h/t */ -#define DT_CSMWD (DT_CSMLN / DT_WSIZE) /* checksum word in h/t */ - -/* 16b, 18b, 36b DECtape constants */ - -#define D18_WSIZE 6 /* word size in lines */ -#define D18_BSIZE 256 /* block size in 18b */ -#define D18_TSIZE 578 /* tape size */ -#define D18_LPERB (DT_HTLIN + (D18_BSIZE * DT_WSIZE) + DT_HTLIN) -#define D18_FWDEZ (DT_EZLIN + (D18_LPERB * D18_TSIZE)) -#define D18_CAPAC (D18_TSIZE * D18_BSIZE) /* tape capacity */ -#define D11_FILSIZ (D18_CAPAC * sizeof (int16)) - -/* 12b DECtape constants */ - -#define D8_WSIZE 4 /* word size in lines */ -#define D8_BSIZE 86 /* block size in 18b */ -#define D8_TSIZE 1474 /* tape size */ -#define D8_LPERB (DT_HTLIN + (D8_BSIZE * DT_WSIZE) + DT_HTLIN) -#define D8_FWDEZ (DT_EZLIN + (D8_LPERB * D8_TSIZE)) -#define D8_CAPAC (D8_TSIZE * D8_BSIZE) /* tape capacity */ - -#define D8_NBSIZE ((D8_BSIZE * D18_WSIZE) / D8_WSIZE) -#define D8_FILSIZ (D8_NBSIZE * D8_TSIZE * sizeof (int16)) - -/* This controller */ - -#define DT_CAPAC D18_CAPAC /* default */ -#define DT_WSIZE D18_WSIZE - -/* Calculated constants, per unit */ - -#define DTU_BSIZE(u) (((u)->flags & UNIT_8FMT)? D8_BSIZE: D18_BSIZE) -#define DTU_TSIZE(u) (((u)->flags & UNIT_8FMT)? D8_TSIZE: D18_TSIZE) -#define DTU_LPERB(u) (((u)->flags & UNIT_8FMT)? D8_LPERB: D18_LPERB) -#define DTU_FWDEZ(u) (((u)->flags & UNIT_8FMT)? D8_FWDEZ: D18_FWDEZ) -#define DTU_CAPAC(u) (((u)->flags & UNIT_8FMT)? D8_CAPAC: D18_CAPAC) - -#define DT_LIN2BL(p,u) (((p) - DT_EZLIN) / DTU_LPERB (u)) -#define DT_LIN2OF(p,u) (((p) - DT_EZLIN) % DTU_LPERB (u)) -#define DT_LIN2WD(p,u) ((DT_LIN2OF (p,u) - DT_HTLIN) / DT_WSIZE) -#define DT_BLK2LN(p,u) (((p) * DTU_LPERB (u)) + DT_EZLIN) -#define DT_QREZ(u) (((u)->pos) < DT_EZLIN) -#define DT_QFEZ(u) (((u)->pos) >= ((uint32) DTU_FWDEZ (u))) -#define DT_QEZ(u) (DT_QREZ (u) || DT_QFEZ (u)) - -/* Status register A */ - -#define DTA_V_UNIT 12 /* unit select */ -#define DTA_M_UNIT 017 -#define DTA_UNIT (DTA_M_UNIT << DTA_V_UNIT) -#define DTA_V_MOT 4 /* motion */ -#define DTA_M_MOT 03 -#define DTA_V_FNC 0 /* function */ -#define DTA_M_FNC 07 -#define FNC_MOVE 00 /* move */ -#define FNC_SRCH 01 /* search */ -#define FNC_READ 02 /* read */ -#define FNC_WRIT 03 /* write */ -#define FNC_RALL 05 /* read all */ -#define FNC_WALL 06 /* write all */ -#define FNC_WMRK 07 /* write timing */ -#define DTA_STSTP (1u << (DTA_V_MOT + 1)) -#define DTA_FWDRV (1u << DTA_V_MOT) -#define DTA_MODE 0 /* not implemented */ -#define DTA_RW 077 -#define DTA_GETUNIT(x) map_unit[(((x) >> DTA_V_UNIT) & DTA_M_UNIT)] -#define DT_UPDINT if (dtsb & (DTB_DTF | DTB_BEF | DTB_ERF)) \ - sbs = sbs | SB_RQ; - -#define DTA_GETMOT(x) (((x) >> DTA_V_MOT) & DTA_M_MOT) -#define DTA_GETFNC(x) (((x) >> DTA_V_FNC) & DTA_M_FNC) - -/* Status register B */ - -#define DTB_V_DTF 17 /* data flag */ -#define DTB_V_BEF 16 /* block end flag */ -#define DTB_V_ERF 15 /* error flag */ -#define DTB_V_END 14 /* end of tape */ -#define DTB_V_TIM 13 /* timing err */ -#define DTB_V_REV 12 /* reverse */ -#define DTB_V_GO 11 /* go */ -#define DTB_V_MRK 10 /* mark trk err */ -#define DTB_V_SEL 9 /* select err */ -#define DTB_DTF (1u << DTB_V_DTF) -#define DTB_BEF (1u << DTB_V_BEF) -#define DTB_ERF (1u << DTB_V_ERF) -#define DTB_END (1u << DTB_V_END) -#define DTB_TIM (1u << DTB_V_TIM) -#define DTB_REV (1u << DTB_V_REV) -#define DTB_GO (1u << DTB_V_GO) -#define DTB_MRK (1u << DTB_V_MRK) -#define DTB_SEL (1u << DTB_V_SEL) -#define DTB_ALLERR (DTB_END | DTB_TIM | DTB_MRK | DTB_SEL) - -/* DECtape state */ - -#define DTS_V_MOT 3 /* motion */ -#define DTS_M_MOT 07 -#define DTS_STOP 0 /* stopped */ -#define DTS_DECF 2 /* decel, fwd */ -#define DTS_DECR 3 /* decel, rev */ -#define DTS_ACCF 4 /* accel, fwd */ -#define DTS_ACCR 5 /* accel, rev */ -#define DTS_ATSF 6 /* @speed, fwd */ -#define DTS_ATSR 7 /* @speed, rev */ -#define DTS_DIR 01 /* dir mask */ -#define DTS_V_FNC 0 /* function */ -#define DTS_M_FNC 07 -#define DTS_OFR 7 /* "off reel" */ -#define DTS_GETMOT(x) (((x) >> DTS_V_MOT) & DTS_M_MOT) -#define DTS_GETFNC(x) (((x) >> DTS_V_FNC) & DTS_M_FNC) -#define DTS_V_2ND 6 /* next state */ -#define DTS_V_3RD (DTS_V_2ND + DTS_V_2ND) /* next next */ -#define DTS_STA(y,z) (((y) << DTS_V_MOT) | ((z) << DTS_V_FNC)) -#define DTS_SETSTA(y,z) uptr->STATE = DTS_STA (y, z) -#define DTS_SET2ND(y,z) uptr->STATE = (uptr->STATE & 077) | \ - ((DTS_STA (y, z)) << DTS_V_2ND) -#define DTS_SET3RD(y,z) uptr->STATE = (uptr->STATE & 07777) | \ - ((DTS_STA (y, z)) << DTS_V_3RD) -#define DTS_NXTSTA(x) (x >> DTS_V_2ND) - -/* Operation substates */ - -#define DTO_WCO 1 /* wc overflow */ -#define DTO_SOB 2 /* start of block */ - -/* Logging */ - -#define LOG_MS 001 /* move, search */ -#define LOG_RW 002 /* read, write */ -#define LOG_RA 004 /* read all */ -#define LOG_BL 010 /* block # lblk */ - -#define ABS(x) (((x) < 0)? (-(x)): (x)) - -extern int32 M[]; -extern int32 sbs; -extern int32 stop_inst; -extern UNIT cpu_unit; -extern int32 sim_switches; -extern int32 sim_is_running; - -int32 dtsa = 0; /* status A */ -int32 dtsb = 0; /* status B */ -int32 dtdb = 0; /* data buffer */ -int32 dt_ltime = 12; /* interline time */ -int32 dt_actime = 54000; /* accel time */ -int32 dt_dctime = 72000; /* decel time */ -int32 dt_substate = 0; -int32 dt_log = 0; -int32 dt_logblk = 0; -static const int32 map_unit[16] = { /* Type 550 unit map */ - -1, 1, 2, 3, 4, 5, 6, 7, - 0, -1, -1, -1, -1, -1, -1, -1 }; - -t_stat dt_svc (UNIT *uptr); -t_stat dt_reset (DEVICE *dptr); -t_stat dt_attach (UNIT *uptr, char *cptr); -t_stat dt_detach (UNIT *uptr); -void dt_deselect (int32 oldf); -void dt_newsa (int32 newf); -void dt_newfnc (UNIT *uptr, int32 newsta); -t_bool dt_setpos (UNIT *uptr); -void dt_schedez (UNIT *uptr, int32 dir); -void dt_seterr (UNIT *uptr, int32 e); -int32 dt_comobv (int32 val); -int32 dt_csum (UNIT *uptr, int32 blk); -int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos); - -/* DT data structures - - dt_dev DT device descriptor - dt_unit DT unit list - dt_reg DT register list - dt_mod DT modifier list -*/ - -UNIT dt_unit[] = { - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) } }; - -REG dt_reg[] = { - { ORDATA (DTSA, dtsa, 18) }, - { ORDATA (DTSB, dtsb, 18) }, - { ORDATA (DTDB, dtdb, 18) }, - { FLDATA (DTF, dtsb, DTB_V_DTF) }, - { FLDATA (BEF, dtsb, DTB_V_BEF) }, - { FLDATA (ERF, dtsb, DTB_V_ERF) }, - { DRDATA (LTIME, dt_ltime, 31), REG_NZ }, - { DRDATA (ACTIME, dt_actime, 31), REG_NZ }, - { DRDATA (DCTIME, dt_dctime, 31), REG_NZ }, - { ORDATA (SUBSTATE, dt_substate, 2) }, - { ORDATA (LOG, dt_log, 4), REG_HIDDEN }, - { DRDATA (LBLK, dt_logblk, 12), REG_HIDDEN }, - { URDATA (POS, dt_unit[0].pos, 10, T_ADDR_W, 0, - DT_NUMDR, PV_LEFT | REG_RO) }, - { URDATA (STATT, dt_unit[0].STATE, 8, 18, 0, - DT_NUMDR, REG_RO) }, - { URDATA (LASTT, dt_unit[0].LASTT, 10, 32, 0, - DT_NUMDR, REG_HRO) }, - { NULL } }; - -MTAB dt_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { UNIT_8FMT + UNIT_11FMT, 0, "18b", NULL, NULL }, - { UNIT_8FMT + UNIT_11FMT, UNIT_8FMT, "12b", NULL, NULL }, - { UNIT_8FMT + UNIT_11FMT, UNIT_11FMT, "16b", NULL, NULL }, - { 0 } }; - -DEVICE dt_dev = { - "DT", dt_unit, dt_reg, dt_mod, - DT_NUMDR, 8, 24, 1, 8, 18, - NULL, NULL, &dt_reset, - NULL, &dt_attach, &dt_detach, - NULL, DEV_DISABLE }; - -int32 dt (int32 IR, int32 dev, int32 dat) -{ -int32 pulse = (IR >> 6) & 037; -int32 fnc, mot, unum; -UNIT *uptr = NULL; - -if (dt_dev.flags & DEV_DIS) /* disabled? */ - return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ -unum = DTA_GETUNIT (dtsa); /* get unit no */ -if (unum >= 0) uptr = dt_dev.units + unum; /* get unit */ - -if (pulse == 003) { /* MSE */ - if ((dtsa ^ dat) & DTA_UNIT) dt_deselect (dtsa); /* new unit? */ - dtsa = (dtsa & ~DTA_UNIT) | (dat & DTA_UNIT); - dtsb = dtsb & ~(DTB_DTF | DTB_BEF | DTB_ERF | DTB_ALLERR); } -if (pulse == 004) { /* MLC */ - dtsa = (dtsa & ~DTA_RW) | (dat & DTA_RW); /* load dtsa */ - dtsb = dtsb & ~(DTB_DTF | DTB_BEF | DTB_ERF | DTB_ALLERR); - fnc = DTA_GETFNC (dtsa); /* get fnc */ - if ((uptr == NULL) || /* invalid? */ - ((uptr->flags) & UNIT_DIS) || /* disabled? */ - (fnc >= FNC_WMRK) || /* write mark? */ - ((fnc == FNC_WRIT) && (uptr->flags & UNIT_WLK)) || - ((fnc == FNC_WALL) && (uptr->flags & UNIT_WLK))) - dt_seterr (uptr, DTB_SEL); /* select err */ - else dt_newsa (dtsa); } -if (pulse == 005) { /* MRD */ - dat = (dat & ~DMASK) | dtdb; - dtsb = dtsb & ~(DTB_DTF | DTB_BEF); } -if (pulse == 006) { /* MWR */ - dtdb = dat & DMASK; - dtsb = dtsb & ~(DTB_DTF | DTB_BEF); } -if (pulse == 007) { /* MRS */ - dtsb = dtsb & ~(DTB_REV | DTB_GO); /* clr rev, go */ - if (uptr) { /* valid unit? */ - mot = DTS_GETMOT (uptr->STATE); /* get motion */ - if (mot & DTS_DIR) dtsb = dtsb | DTB_REV; /* rev? set */ - if ((mot >= DTS_ACCF) || (uptr->STATE & 0777700)) - dtsb = dtsb | DTB_GO; } /* accel? go */ - dat = (dat & ~DMASK) | dtsb; } -DT_UPDINT; -return dat; -} - -/* Unit deselect */ - -void dt_deselect (int32 oldf) -{ -int32 old_unit, old_mot; -UNIT *uptr; - -old_unit = DTA_GETUNIT (oldf); /* get unit no */ -if (old_unit < 0) return; /* invalid? */ -uptr = dt_dev.units + old_unit; /* get unit */ -old_mot = DTS_GETMOT (uptr->STATE); -if (old_mot >= DTS_ATSF) /* at speed? */ - dt_newfnc (uptr, DTS_STA (old_mot, DTS_OFR)); -else if (old_mot >= DTS_ACCF) /* accelerating? */ - DTS_SET2ND (DTS_ATSF | (old_mot & DTS_DIR), DTS_OFR); -return; -} - -/* Command register change - - 1. If change in motion, stop to start - - schedule acceleration - - set function as next state - 2. If change in motion, start to stop - - if not already decelerating (could be reversing), - schedule deceleration - 3. If change in direction, - - if not decelerating, schedule deceleration - - set accelerating (other dir) as next state - - set function as next next state - 4. If not accelerating or at speed, - - schedule acceleration - - set function as next state - 5. If not yet at speed, - - set function as next state - 6. If at speed, - - set function as current state, schedule function -*/ - -void dt_newsa (int32 newf) -{ -int32 new_unit, prev_mot, new_fnc; -int32 prev_mving, new_mving, prev_dir, new_dir; -UNIT *uptr; - -new_unit = DTA_GETUNIT (newf); /* new unit */ -if (new_unit < 0) return; /* invalid? */ -uptr = dt_dev.units + new_unit; -if ((uptr->flags & UNIT_ATT) == 0) { /* new unit attached? */ - dt_seterr (uptr, DTB_SEL); /* no, error */ - return; } -prev_mot = DTS_GETMOT (uptr->STATE); /* previous motion */ -prev_mving = prev_mot != DTS_STOP; /* previous moving? */ -prev_dir = prev_mot & DTS_DIR; /* previous dir? */ -new_mving = (newf & DTA_STSTP) != 0; /* new moving? */ -new_dir = (newf & DTA_FWDRV) != 0; /* new dir? */ -new_fnc = DTA_GETFNC (newf); /* new function? */ - -if ((prev_mving | new_mving) == 0) return; /* stop to stop */ - -if (new_mving & ~prev_mving) { /* start? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_actime); /* schedule accel */ - DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } - -if (prev_mving & ~new_mving) { /* stop? */ - if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_dctime); } /* schedule decel */ - DTS_SETSTA (DTS_DECF | prev_dir, 0); /* state = decel */ - return; } - -if (prev_dir ^ new_dir) { /* dir chg? */ - if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_dctime); } /* schedule decel */ - DTS_SETSTA (DTS_DECF | prev_dir, 0); /* state = decel */ - DTS_SET2ND (DTS_ACCF | new_dir, 0); /* next = accel */ - DTS_SET3RD (DTS_ATSF | new_dir, new_fnc); /* next next = fnc */ - return; } - -if (prev_mot < DTS_ACCF) { /* not accel/at speed? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* cancel cur */ - sim_activate (uptr, dt_actime); /* schedule accel */ - DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } - -if (prev_mot < DTS_ATSF) { /* not at speed? */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } - -dt_newfnc (uptr, DTS_STA (DTS_ATSF | new_dir, new_fnc));/* state = fnc */ -return; -} - -/* Schedule new DECtape function - - This routine is only called if - - the selected unit is attached - - the selected unit is at speed (forward or backward) - - This routine - - updates the selected unit's position - - updates the selected unit's state - - schedules the new operation -*/ - -void dt_newfnc (UNIT *uptr, int32 newsta) -{ -int32 fnc, dir, blk, unum, newpos; -uint32 oldpos; - -oldpos = uptr->pos; /* save old pos */ -if (dt_setpos (uptr)) return; /* update pos */ -uptr->STATE = newsta; /* update state */ -fnc = DTS_GETFNC (uptr->STATE); /* set variables */ -dir = DTS_GETMOT (uptr->STATE) & DTS_DIR; -unum = uptr - dt_dev.units; -if (oldpos == uptr->pos) /* bump pos */ - uptr->pos = uptr->pos + (dir? -1: 1); -blk = DT_LIN2BL (uptr->pos, uptr); - -if (dir? DT_QREZ (uptr): DT_QFEZ (uptr)) { /* wrong ez? */ - dt_seterr (uptr, DTB_END); /* set ez flag, stop */ - return; } -sim_cancel (uptr); /* cancel cur op */ -dt_substate = DTO_SOB; /* substate = block start */ -switch (fnc) { /* case function */ -case DTS_OFR: /* off reel */ - if (dir) newpos = -1000; /* rev? < start */ - else newpos = DTU_FWDEZ (uptr) + DT_EZLIN + 1000; /* fwd? > end */ - break; -case FNC_MOVE: /* move */ - dt_schedez (uptr, dir); /* sched end zone */ - if (dt_log & LOG_MS) printf ("[DT%d: moving %s]\n", unum, (dir? - "backward": "forward")); - return; /* done */ -case FNC_SRCH: /* search */ - if (dir) newpos = DT_BLK2LN ((DT_QFEZ (uptr)? - DTU_TSIZE (uptr): blk), uptr) - DT_BLKLN - DT_WSIZE; - else newpos = DT_BLK2LN ((DT_QREZ (uptr)? - 0: blk + 1), uptr) + DT_BLKLN + (DT_WSIZE - 1); - if (dt_log & LOG_MS) printf ("[DT%d: searching %s]\n", unum, - (dir? "backward": "forward")); - break; -case FNC_WRIT: /* write */ -case FNC_READ: /* read */ -case FNC_RALL: /* read all */ -case FNC_WALL: /* write all */ - if (DT_QEZ (uptr)) { /* in "ok" end zone? */ - if (dir) newpos = DTU_FWDEZ (uptr) - DT_WSIZE; - else newpos = DT_EZLIN + (DT_WSIZE - 1); } - else { - newpos = ((uptr->pos) / DT_WSIZE) * DT_WSIZE; - if (!dir) newpos = newpos + (DT_WSIZE - 1); } - if ((dt_log & LOG_RA) || ((dt_log & LOG_BL) && (blk == dt_logblk))) - printf ("[DT%d: read all block %d %s%s\n", - unum, blk, (dir? "backward": "forward"), - ((dtsa & DTA_MODE)? " continuous]": "]")); - break; -default: - dt_seterr (uptr, DTB_SEL); /* bad state */ - return; } -if ((fnc == FNC_WRIT) || (fnc == FNC_WALL)) { /* write function? */ - dtsb = dtsb | DTB_DTF; /* set data flag */ - DT_UPDINT; } -sim_activate (uptr, ABS (newpos - ((int32) uptr->pos)) * dt_ltime); -return; -} - -/* Update DECtape position - - DECtape motion is modeled as a constant velocity, with linear - acceleration and deceleration. The motion equations are as follows: - - t = time since operation started - tmax = time for operation (accel, decel only) - v = at speed velocity in lines (= 1/dt_ltime) - - Then: - at speed dist = t * v - accel dist = (t^2 * v) / (2 * tmax) - decel dist = (((2 * t * tmax) - t^2) * v) / (2 * tmax) - - This routine uses the relative (integer) time, rather than the absolute - (floating point) time, to allow save and restore of the start times. -*/ - -t_bool dt_setpos (UNIT *uptr) -{ -uint32 new_time, ut, ulin, udelt; -int32 mot = DTS_GETMOT (uptr->STATE); -int32 unum, delta; - -new_time = sim_grtime (); /* current time */ -ut = new_time - uptr->LASTT; /* elapsed time */ -if (ut == 0) return FALSE; /* no time gone? exit */ -uptr->LASTT = new_time; /* update last time */ -switch (mot & ~DTS_DIR) { /* case on motion */ -case DTS_STOP: /* stop */ - delta = 0; - break; -case DTS_DECF: /* slowing */ - ulin = ut / (uint32) dt_ltime; udelt = dt_dctime / dt_ltime; - delta = ((ulin * udelt * 2) - (ulin * ulin)) / (2 * udelt); - break; -case DTS_ACCF: /* accelerating */ - ulin = ut / (uint32) dt_ltime; udelt = dt_actime / dt_ltime; - delta = (ulin * ulin) / (2 * udelt); - break; -case DTS_ATSF: /* at speed */ - delta = ut / (uint32) dt_ltime; - break; } -if (mot & DTS_DIR) uptr->pos = uptr->pos - delta; /* update pos */ -else uptr->pos = uptr->pos + delta; -if (((int32) uptr->pos < 0) || - ((int32) uptr->pos > (DTU_FWDEZ (uptr) + DT_EZLIN))) { - detach_unit (uptr); /* off reel? */ - uptr->STATE = uptr->pos = 0; - unum = uptr - dt_dev.units; - if (unum == DTA_GETUNIT (dtsa)) /* if selected, */ - dt_seterr (uptr, DTB_SEL); /* error */ - return TRUE; } -return FALSE; -} - -/* Unit service - - Unit must be attached, detach cancels operation -*/ - -t_stat dt_svc (UNIT *uptr) -{ -int32 mot = DTS_GETMOT (uptr->STATE); -int32 dir = mot & DTS_DIR; -int32 fnc = DTS_GETFNC (uptr->STATE); -int32 *bptr = uptr->filebuf; -int32 unum = uptr - dt_dev.units; -int32 blk, wrd, ma, relpos; -uint32 ba; - -/* Motion cases - - Decelerating - if next state != stopped, must be accel reverse - Accelerating - next state must be @speed, schedule function - At speed - do functional processing -*/ - -switch (mot) { -case DTS_DECF: case DTS_DECR: /* decelerating */ - if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ - uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ - if (uptr->STATE) /* not stopped? */ - sim_activate (uptr, dt_actime); /* must be reversing */ - return SCPE_OK; -case DTS_ACCF: case DTS_ACCR: /* accelerating */ - dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */ - return SCPE_OK; -case DTS_ATSF: case DTS_ATSR: /* at speed */ - break; /* check function */ -default: /* other */ - dt_seterr (uptr, DTB_SEL); /* state error */ - return SCPE_OK; } - -/* Functional cases - - Move - must be at end zone - Search - transfer block number, schedule next block - Off reel - detach unit (it must be deselected) -*/ - -if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ -if (DT_QEZ (uptr)) { /* in end zone? */ - dt_seterr (uptr, DTB_END); /* end zone error */ - return SCPE_OK; } -blk = DT_LIN2BL (uptr->pos, uptr); /* get block # */ -switch (fnc) { /* at speed, check fnc */ -case FNC_MOVE: /* move */ - dt_seterr (uptr, DTB_END); /* end zone error */ - return SCPE_OK; -case DTS_OFR: /* off reel */ - detach_unit (uptr); /* must be deselected */ - uptr->STATE = uptr->pos = 0; /* no visible action */ - break; - -/* Search */ - -case FNC_SRCH: /* search */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - sim_activate (uptr, DTU_LPERB (uptr) * dt_ltime);/* sched next block */ - dtdb = blk; /* store block # */ - dtsb = dtsb | DTB_DTF; /* set DTF */ - break; - -/* Read and read all */ - -case FNC_READ: case FNC_RALL: - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - sim_activate (uptr, DT_WSIZE * dt_ltime); /* sched next word */ - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - dtdb = bptr[ba]; /* get tape word */ - dtsb = dtsb | DTB_DTF; } /* set flag */ - else { - ma = (2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1; - wrd = relpos / DT_WSIZE; /* hdr start = wd 0 */ - if ((wrd == 0) || /* skip 1st, last */ - (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - 1))) break; - if ((fnc == FNC_READ) && /* read, skip if not */ - (wrd != DT_CSMWD) && /* fwd, rev cksum */ - (wrd != ma)) break; - dtdb = dt_gethdr (uptr, blk, relpos); - if (wrd == (dir? DT_CSMWD: ma)) /* at end csum? */ - dtsb = dtsb | DTB_BEF; /* end block */ - else dtsb = dtsb | DTB_DTF; } /* else next word */ - if (dir) dtdb = dt_comobv (dtdb); - break; - -/* Write and write all */ - -case FNC_WRIT: case FNC_WALL: - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - sim_activate (uptr, DT_WSIZE * dt_ltime); /* sched next word */ - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - if (dir) bptr[ba] = dt_comobv (dtdb); /* get data word */ - else bptr[ba] = dtdb; - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; - if (wrd == (dir? 0: DTU_BSIZE (uptr) - 1)) - dtsb = dtsb | DTB_BEF; /* end block */ - else dtsb = dtsb | DTB_DTF; } /* else next word */ - else { - wrd = relpos / DT_WSIZE; /* hdr start = wd 0 */ - if ((wrd == 0) || /* skip 1st, last */ - (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - 1))) break; - if ((fnc == FNC_WRIT) && /* wr, skip if !csm */ - (wrd != ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1))) - break; - dtsb = dtsb | DTB_DTF; } /* set flag */ - break; - -default: - dt_seterr (uptr, DTB_SEL); /* impossible state */ - break; } -DT_UPDINT; /* update interrupts */ -return SCPE_OK; -} - -/* Utility routines */ - -/* Set error flag */ - -void dt_seterr (UNIT *uptr, int32 e) -{ -int32 mot = DTS_GETMOT (uptr->STATE); - -dtsa = dtsa & ~DTA_STSTP; /* clear go */ -dtsb = dtsb | DTB_ERF | e; /* set error flag */ -if (mot >= DTS_ACCF) { /* ~stopped or stopping? */ - sim_cancel (uptr); /* cancel activity */ - if (dt_setpos (uptr)) return; /* update position */ - sim_activate (uptr, dt_dctime); /* sched decel */ - DTS_SETSTA (DTS_DECF | (mot & DTS_DIR), 0); } /* state = decel */ -DT_UPDINT; -return; -} - -/* Schedule end zone */ - -void dt_schedez (UNIT *uptr, int32 dir) -{ -int32 newpos; - -if (dir) newpos = DT_EZLIN - DT_WSIZE; /* rev? rev ez */ -else newpos = DTU_FWDEZ (uptr) + DT_WSIZE; /* fwd? fwd ez */ -sim_activate (uptr, ABS (newpos - ((int32) uptr->pos)) * dt_ltime); -return; -} - -/* Complement obverse routine */ - -int32 dt_comobv (int32 dat) -{ -dat = dat ^ 0777777; /* compl obverse */ -dat = ((dat >> 15) & 07) | ((dat >> 9) & 070) | - ((dat >> 3) & 0700) | ((dat & 0700) << 3) | - ((dat & 070) << 9) | ((dat & 07) << 15); -return dat; -} - -/* Checksum routine */ - -int32 dt_csum (UNIT *uptr, int32 blk) -{ -int32 *bptr = uptr->filebuf; -int32 ba = blk * DTU_BSIZE (uptr); -int32 i, csum, wrd; - -csum = 0777777; -for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ - wrd = bptr[ba + i]; /* get word */ - csum = csum + wrd; /* 1's comp add */ - if (csum > 0777777) csum = (csum + 1) & 0777777; } -return (csum ^ 0777777); /* 1's comp res */ -} - -/* Get header word */ - -int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos) -{ -int32 wrd = relpos / DT_WSIZE; - -if (wrd == DT_BLKWD) return blk; /* fwd blknum */ -if (wrd == DT_CSMWD) return 0777777; /* rev csum */ -if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */ - return (dt_csum (uptr, blk)); -if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_BLKWD - 1)) /* rev blkno */ - return dt_comobv (blk); -return 0; /* all others */ -} - -/* Reset routine */ - -t_stat dt_reset (DEVICE *dptr) -{ -int32 i, prev_mot; -UNIT *uptr; - -for (i = 0; i < DT_NUMDR; i++) { /* stop all drives */ - uptr = dt_dev.units + i; - if (sim_is_running) { /* CAF? */ - prev_mot = DTS_GETMOT (uptr->STATE); /* get motion */ - if ((prev_mot & ~DTS_DIR) > DTS_DECF) { /* accel or spd? */ - if (dt_setpos (uptr)) continue; /* update pos */ - sim_cancel (uptr); - sim_activate (uptr, dt_dctime); /* sched decel */ - DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); - } } - else { - sim_cancel (uptr); /* sim reset */ - uptr->STATE = 0; - uptr->LASTT = sim_grtime (); } } -dtsa = dtsb = 0; /* clear status */ -DT_UPDINT; /* reset interrupt */ -return SCPE_OK; -} - -/* IORS routine */ - -int32 dt_iors (void) -{ -#if defined IOS_DTA -return ((dtsb & (DTB_ERF | DTB_DTF))? IOS_DTA: 0); -#else -return 0; -#endif -} - -/* Attach routine - - Determine 12b, 16b, or 18b/36b format - Allocate buffer - If 12b, read 12b format and convert to 18b in buffer - If 16b, read 16b format and convert to 18b in buffer - If 18b/36b, read data into buffer -*/ - -t_stat dt_attach (UNIT *uptr, char *cptr) -{ -uint16 pdp8b[D8_NBSIZE]; -uint16 pdp11b[D18_BSIZE]; -uint32 ba, sz, k, *bptr; -int32 u = uptr - dt_dev.units; -t_stat r; - -r = attach_unit (uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error? */ -if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */ - uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); /* default 18b */ - if (sim_switches & SWMASK ('R')) /* att 12b? */ - uptr->flags = uptr->flags | UNIT_8FMT; - else if (sim_switches & SWMASK ('S')) /* att 16b? */ - uptr->flags = uptr->flags | UNIT_11FMT; - else if (!(sim_switches & SWMASK ('T')) && /* autosize? */ - (sz = sim_fsize (cptr))) { - if (sz == D8_FILSIZ) - uptr->flags = uptr->flags | UNIT_8FMT; - else if (sz == D11_FILSIZ) - uptr->flags = uptr->flags | UNIT_11FMT; } } -uptr->capac = DTU_CAPAC (uptr); /* set capacity */ -uptr->filebuf = calloc (uptr->capac, sizeof (int32)); -if (uptr->filebuf == NULL) { /* can't alloc? */ - detach_unit (uptr); - return SCPE_MEM; } -bptr = uptr->filebuf; /* file buffer */ -printf ("%s%d: ", sim_dname (&dt_dev), u); -if (uptr->flags & UNIT_8FMT) printf ("12b format"); -else if (uptr->flags & UNIT_11FMT) printf ("16b format"); -else printf ("18b/36b format"); -printf (", buffering file in memory\n"); -if (uptr->flags & UNIT_8FMT) { /* 12b? */ - for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ - k = fxread (pdp8b, sizeof (int16), D8_NBSIZE, uptr->fileref); - if (k == 0) break; - for ( ; k < D8_NBSIZE; k++) pdp8b[k] = 0; - for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop thru blk */ - bptr[ba] = ((uint32) (pdp8b[k] & 07777) << 6) | - ((uint32) (pdp8b[k + 1] >> 6) & 077); - bptr[ba + 1] = ((uint32) (pdp8b[k + 1] & 077) << 12) | - (pdp8b[k + 2] & 07777); - ba = ba + 2; } /* end blk loop */ - } /* end file loop */ - uptr->hwmark = ba; } /* end if */ -else if (uptr->flags & UNIT_11FMT) { /* 16b? */ - for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ - k = fxread (pdp11b, sizeof (int16), D18_BSIZE, uptr->fileref); - if (k == 0) break; - for ( ; k < D18_BSIZE; k++) pdp11b[k] = 0; - for (k = 0; k < D18_BSIZE; k++) - bptr[ba++] = pdp11b[k]; } - uptr->hwmark = ba; } /* end elif */ -else uptr->hwmark = fxread (uptr->filebuf, sizeof (int32), - uptr->capac, uptr->fileref); -uptr->flags = uptr->flags | UNIT_BUF; /* set buf flag */ -uptr->pos = DT_EZLIN; /* beyond leader */ -uptr->LASTT = sim_grtime (); /* last pos update */ -return SCPE_OK; -} - -/* Detach routine - - Cancel in progress operation - If 12b, convert 18b buffer to 12b and write to file - If 16b, convert 18b buffer to 16b and write to file - If 18b/36b, write buffer to file - Deallocate buffer -*/ - -t_stat dt_detach (UNIT* uptr) -{ -uint16 pdp8b[D8_NBSIZE]; -uint16 pdp11b[D18_BSIZE]; -uint32 ba, k, *bptr; -int32 u = uptr - dt_dev.units; - -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; -if (sim_is_active (uptr)) { - sim_cancel (uptr); - if ((u == DTA_GETUNIT (dtsa)) && (dtsa & DTA_STSTP)) { - dtsb = dtsb | DTB_ERF | DTB_SEL | DTB_DTF; - DT_UPDINT; } - uptr->STATE = uptr->pos = 0; } -bptr = uptr->filebuf; /* file buffer */ -if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */ - printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u); - rewind (uptr->fileref); /* start of file */ - if (uptr->flags & UNIT_8FMT) { /* 12b? */ - for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */ - for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop blk */ - pdp8b[k] = (bptr[ba] >> 6) & 07777; - pdp8b[k + 1] = ((bptr[ba] & 077) << 6) | - ((bptr[ba + 1] >> 12) & 077); - pdp8b[k + 2] = bptr[ba + 1] & 07777; - ba = ba + 2; } /* end loop blk */ - fxwrite (pdp8b, sizeof (int16), D8_NBSIZE, uptr->fileref); - if (ferror (uptr->fileref)) break; } /* end loop file */ - } /* end if 12b */ - else if (uptr->flags & UNIT_11FMT) { /* 16b? */ - for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */ - for (k = 0; k < D18_BSIZE; k++) /* loop blk */ - pdp11b[k] = bptr[ba++] & 0177777; - fxwrite (pdp11b, sizeof (int16), D18_BSIZE, uptr->fileref); - if (ferror (uptr->fileref)) break; } /* end loop file */ - } /* end if 16b */ - else fxwrite (uptr->filebuf, sizeof (int32), /* write file */ - uptr->hwmark, uptr->fileref); - if (ferror (uptr->fileref)) perror ("I/O error"); } /* end if hwmark */ -free (uptr->filebuf); /* release buf */ -uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */ -uptr->filebuf = NULL; /* clear buf ptr */ -uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); /* default fmt */ -uptr->capac = DT_CAPAC; /* default size */ -return detach_unit (uptr); -} diff --git a/PDP1/pdp1_lp.c b/PDP1/pdp1_lp.c deleted file mode 100644 index d2c2fc2e..00000000 --- a/PDP1/pdp1_lp.c +++ /dev/null @@ -1,184 +0,0 @@ -/* pdp1_lp.c: PDP-1 line printer simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - lpt Type 62 line printer for the PDP-1 - - 07-Sep-03 RMS Changed ioc to ios - 23-Jul-03 RMS Fixed bugs in instruction decoding, overprinting - Revised to detect I/O wait hang - 25-Apr-03 RMS Revised for extended file support - 30-May-02 RMS Widened POS to 32b - 13-Apr-01 RMS Revised for register arrays -*/ - -#include "pdp1_defs.h" - -#define BPTR_MAX 40 /* pointer max */ -#define LPT_BSIZE (BPTR_MAX * 3) /* line size */ -#define BPTR_MASK 077 /* buf ptr mask */ - -int32 lpt_spc = 0; /* print (0) vs spc */ -int32 lpt_ovrpr = 0; /* overprint */ -int32 lpt_stopioe = 0; /* stop on error */ -int32 lpt_bptr = 0; /* buffer ptr */ -char lpt_buf[LPT_BSIZE + 1] = { 0 }; -static const unsigned char lpt_trans[64] = { - ' ','1','2','3','4','5','6','7','8','9','\'','~','#','V','^','<', - '0','/','S','T','U','V','W','X','Y','Z','"',',','>','^','-','?', - '@','J','K','L','M','N','O','P','Q','R','$','=','-',')','-','(', - '_','A','B','C','D','E','F','G','H','I','*','.','+',']','|','[' }; - -extern int32 ios, cpls, sbs, iosta; -extern int32 stop_inst; - -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit - lpt_reg LPT register list -*/ - -UNIT lpt_unit = { - UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lpt_reg[] = { - { ORDATA (BUF, lpt_unit.buf, 8) }, - { FLDATA (PNT, iosta, IOS_V_PNT) }, - { FLDATA (SPC, iosta, IOS_V_SPC) }, - { FLDATA (RPLS, cpls, CPLS_V_LPT) }, - { DRDATA (BPTR, lpt_bptr, 6) }, - { ORDATA (LPT_STATE, lpt_spc, 6), REG_HRO }, - { FLDATA (LPT_OVRPR, lpt_ovrpr, 0), REG_HRO }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lpt_stopioe, 0) }, - { BRDATA (LBUF, lpt_buf, 8, 8, LPT_BSIZE) }, - { NULL } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lpt_reset, - NULL, NULL, NULL, - NULL, DEV_DISABLE }; - -/* Line printer IOT routine */ - -int32 lpt (int32 inst, int32 dev, int32 dat) -{ -int32 i; - -if (lpt_dev.flags & DEV_DIS) /* disabled? */ - return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ -if ((inst & 07000) == 01000) { /* fill buf */ - if (lpt_bptr < BPTR_MAX) { /* limit test ptr */ - i = lpt_bptr * 3; /* cvt to chr ptr */ - lpt_buf[i] = lpt_trans[(dat >> 12) & 077]; - lpt_buf[i + 1] = lpt_trans[(dat >> 6) & 077]; - lpt_buf[i + 2] = lpt_trans[dat & 077]; } - lpt_bptr = (lpt_bptr + 1) & BPTR_MASK; - return dat; } -if ((inst & 07000) == 02000) { /* space */ - iosta = iosta & ~IOS_SPC; /* space, clear flag */ - lpt_spc = (inst >> 6) & 077; } /* state = space n */ -else if ((inst & 07000) == 00000) { /* print */ - iosta = iosta & ~IOS_PNT; /* clear flag */ - lpt_spc = 0; } /* state = print */ -else return (stop_inst << IOT_V_REASON) | dat; /* not implemented */ -if (GEN_CPLS (inst)) { /* comp pulse? */ - ios = 0; /* clear flop */ - cpls = cpls | CPLS_LPT; } /* request completion */ -else cpls = cpls & ~CPLS_LPT; -sim_activate (&lpt_unit, lpt_unit.wait); /* activate */ -return dat; -} - -/* Unit service, printer is in one of three states - - lpt_spc = 000 write buffer to file, set overprint - lpt_iot = 02x space command x, clear overprint -*/ - -t_stat lpt_svc (UNIT *uptr) -{ -int32 i; -static const char *lpt_cc[] = { - "\n", - "\n\n", - "\n\n\n", - "\n\n\n\n\n\n", - "\n\n\n\n\n\n\n\n\n\n\n", - "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", - "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", - "\f" }; - -if (cpls & CPLS_LPT) { /* completion pulse? */ - ios = 1; /* restart */ - cpls = cpls & ~CPLS_LPT; } /* clr pulse pending */ -sbs = sbs | SB_RQ; /* req seq break */ -if (lpt_spc) { /* space? */ - iosta = iosta | IOS_SPC; /* set flag */ - if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); - fputs (lpt_cc[lpt_spc & 07], lpt_unit.fileref); /* print cctl */ - if (ferror (lpt_unit.fileref)) { /* error? */ - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } - lpt_ovrpr = 0; } /* dont overprint */ -else { iosta = iosta | IOS_PNT; /* print */ - if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); - if (lpt_ovrpr) fputc ('\r', lpt_unit.fileref); /* overprint? */ - fputs (lpt_buf, lpt_unit.fileref); /* print buffer */ - if (ferror (lpt_unit.fileref)) { /* test error */ - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } - lpt_bptr = 0; - for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */ - lpt_ovrpr = 1; } /* set overprint */ -lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ -int32 i; - -lpt_bptr = 0; /* clear buffer ptr */ -for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */ -lpt_spc = 0; /* clear state */ -lpt_ovrpr = 0; /* clear overprint */ -cpls = cpls & ~CPLS_LPT; -iosta = iosta & ~(IOS_PNT | IOS_SPC); /* clear flags */ -sim_cancel (&lpt_unit); /* deactivate unit */ -return SCPE_OK; -} diff --git a/PDP1/pdp1_stddev.c b/PDP1/pdp1_stddev.c deleted file mode 100644 index 98f95aa8..00000000 --- a/PDP1/pdp1_stddev.c +++ /dev/null @@ -1,455 +0,0 @@ -/* pdp1_stddev.c: PDP-1 standard devices - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - ptr paper tape reader - ptp paper tape punch - tti keyboard - tto teleprinter - - 07-Sep-03 RMS Changed ioc to ios - 30-Aug-03 RMS Revised PTR to conform to Maintenance Manual; - added deadlock prevention on errors - 23-Jul-03 RMS Revised to detect I/O wait hang - 25-Apr-03 RMS Revised for extended file support - 22-Dec-02 RMS Added break support - 29-Nov-02 RMS Fixed output flag initialization (found by Derek Peschel) - 21-Nov-02 RMS Changed typewriter to half duplex (found by Derek Peschel) - 06-Oct-02 RMS Revised for V2.10 - 30-May-02 RMS Widened POS to 32b - 29-Nov-01 RMS Added read only unit support - 07-Sep-01 RMS Moved function prototypes - 10-Jun-01 RMS Fixed comment - 30-Oct-00 RMS Standardized device naming -*/ - -#include "pdp1_defs.h" - -#define FIODEC_UC 074 -#define FIODEC_LC 072 -#define UC_V 6 /* upper case */ -#define UC (1 << UC_V) -#define BOTH (1 << (UC_V + 1)) /* both cases */ -#define CW (1 << (UC_V + 2)) /* char waiting */ -#define TT_WIDTH 077 -#define TTI 0 -#define TTO 1 - -int32 ptr_state = 0; -int32 ptr_wait = 0; -int32 ptr_stopioe = 0; -int32 ptp_stopioe = 0; -int32 tti_hold = 0; /* tti hold buf */ -int32 tty_buf = 0; /* tty buffer */ -int32 tty_uc = 0; /* tty uc/lc */ - -extern int32 sbs, ios, ioh, cpls, iosta; -extern int32 PF, IO, PC, TA; -extern int32 M[]; - -t_stat ptr_svc (UNIT *uptr); -t_stat ptp_svc (UNIT *uptr); -t_stat tti_svc (UNIT *uptr); -t_stat tto_svc (UNIT *uptr); -t_stat ptr_reset (DEVICE *dptr); -t_stat ptp_reset (DEVICE *dptr); -t_stat tty_reset (DEVICE *dptr); -t_stat ptr_boot (int32 unitno, DEVICE *dptr); - -/* Character translation tables */ - -int32 fiodec_to_ascii[128] = { - ' ', '1', '2', '3', '4', '5', '6', '7', /* lower case */ - '8', '9', 0, 0, 0, 0, 0, 0, - '0', '/', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', 0, ',', 0, 0, '\t', 0, - '@', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', 0, 0, '-', ')', '\\', '(', - 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', - 'h', 'i', '{', '.', '}', '\b', 0, '\r', - ' ', '"', '\'', '~', '#', '!', '&', '<', /* upper case */ - '>', '^', 0, 0, 0, 0, 0, 0, - '`', '?', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 0, '=', 0, 0, '\t', 0, - '_', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 0, 0, '+', ']', '|', '[', - 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', '{', '*', '}', '\b', 0, '\r' }; - -int32 ascii_to_fiodec[128] = { - 0, 0, 0, 0, 0, 0, 0, 0, - BOTH+075, BOTH+036, 0, 0, 0, BOTH+077, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - BOTH+0, UC+005, UC+001, UC+004, 0, 0, UC+006, UC+002, - 057, 055, UC+073, UC+054, 033, 054, 073, 021, - 020, 001, 002, 003, 004, 005, 006, 007, - 010, 011, 0, 0, UC+007, UC+033, UC+010, UC+021, - 040, UC+061, UC+062, UC+063, UC+064, UC+065, UC+066, UC+067, - UC+070, UC+071, UC+041, UC+042, UC+043, UC+044, UC+045, UC+046, - UC+047, UC+050, UC+051, UC+022, UC+023, UC+024, UC+025, UC+026, - UC+027, UC+030, UC+031, UC+057, 056, UC+055, UC+011, UC+040, - UC+020, 061, 062, 063, 064, 065, 066, 067, - 070, 071, 041, 042, 043, 044, 045, 046, - 047, 050, 051, 022, 023, 024, 025, 026, - 027, 030, 031, 0, UC+056, 0, UC+003, BOTH+075 }; - -/* PTR data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit - ptr_reg PTR register list -*/ - -UNIT ptr_unit = { - UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), - SERIAL_IN_WAIT }; - -REG ptr_reg[] = { - { ORDATA (BUF, ptr_unit.buf, 18) }, - { FLDATA (DONE, iosta, IOS_V_PTR) }, - { FLDATA (RPLS, cpls, CPLS_V_PTR) }, - { ORDATA (STATE, ptr_state, 5), REG_HRO }, - { FLDATA (WAIT, ptr_wait, 0), REG_HRO }, - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptr_stopioe, 0) }, - { NULL } }; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - &ptr_boot, NULL, NULL, - NULL, 0 }; - -/* PTP data structures - - ptp_dev PTP device descriptor - ptp_unit PTP unit - ptp_reg PTP register list -*/ - -UNIT ptp_unit = { - UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG ptp_reg[] = { - { ORDATA (BUF, ptp_unit.buf, 8) }, - { FLDATA (DONE, iosta, IOS_V_PTP) }, - { FLDATA (RPLS, cpls, CPLS_V_PTP) }, - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptp_stopioe, 0) }, - { NULL } }; - -DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptp_reset, - NULL, NULL, NULL, - NULL, 0 }; - -/* TTY data structures - - tty_dev TTY device descriptor - tty_unit TTY unit - tty_reg TTY register list -*/ - -UNIT tty_unit[] = { - { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }, - { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT } }; - -REG tty_reg[] = { - { ORDATA (BUF, tty_buf, 6) }, - { FLDATA (UC, tty_uc, UC_V) }, - { FLDATA (RPLS, cpls, CPLS_V_TTO) }, - { ORDATA (HOLD, tti_hold, 9), REG_HRO }, - { FLDATA (KDONE, iosta, IOS_V_TTI) }, - { DRDATA (KPOS, tty_unit[TTI].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (KTIME, tty_unit[TTI].wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (TDONE, iosta, IOS_V_TTO) }, - { DRDATA (TPOS, tty_unit[TTO].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TTIME, tty_unit[TTO].wait, 24), PV_LEFT }, - { NULL } }; - -DEVICE tty_dev = { - "TTY", tty_unit, tty_reg, NULL, - 2, 10, 31, 1, 8, 8, - NULL, NULL, &tty_reset, - NULL, NULL, NULL, - NULL, 0 }; - -/* Paper tape reader: IOT routine. Points to note: - - - RPA (but not RPB) complements the reader clutch control. Thus, - if the reader is running, RPA will stop it. - - The status bit indicates data in the reader buffer that has not - been transfered to IO. It is cleared by any RB->IO operation, - including RRB and the completion pulse. - - A reader error on a wait mode operation could hang the simulator. - IOH is set; any retry (without RESET) will be NOP'd. Accordingly, - the PTR service routine clears IOH on any error during a rpa/rpb i. -*/ - -int32 ptr (int32 inst, int32 dev, int32 dat) -{ -if (dev == 0030) { /* RRB */ - iosta = iosta & ~IOS_PTR; /* clear status */ - return ptr_unit.buf; } /* return data */ -if (dev == 0002) ptr_state = 18; /* RPB, mode = binary */ -else if (sim_is_active (&ptr_unit)) { /* RPA, running? */ - sim_cancel (&ptr_unit); /* stop reader */ - return dat; } -else ptr_state = 0; /* mode = alpha */ -ptr_unit.buf = 0; /* clear buffer */ -if (inst & IO_WAIT) ptr_wait = 1; /* set ptr wait */ -else ptr_wait = 0; /* from IR<5> */ -if (GEN_CPLS (inst)) { /* comp pulse? */ - ios = 0; - cpls = cpls | CPLS_PTR; } -else cpls = cpls & ~CPLS_PTR; -sim_activate (&ptr_unit, ptr_unit.wait); /* start reader */ -return dat; -} - -/* Unit service */ - -t_stat ptr_svc (UNIT *uptr) -{ -int32 temp; - -if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */ - if (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */ - if ((cpls & CPLS_PTR) || ptr_stopioe) return SCPE_UNATT; - return SCPE_OK; } -if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */ - if (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */ - if (feof (ptr_unit.fileref)) { - if ((cpls & CPLS_PTR) || ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } - else perror ("PTR I/O error"); - clearerr (ptr_unit.fileref); - return SCPE_IOERR; } -ptr_unit.pos = ptr_unit.pos + 1; -if (ptr_state == 0) ptr_unit.buf = temp & 0377; /* alpha */ -else if (temp & 0200) { /* binary */ - ptr_state = ptr_state - 6; - ptr_unit.buf = ptr_unit.buf | ((temp & 077) << ptr_state); } -if (ptr_state == 0) { /* done? */ - if (cpls & CPLS_PTR) { /* completion pulse? */ - iosta = iosta & ~IOS_PTR; /* clear flag */ - IO = ptr_unit.buf; /* fill IO */ - ios = 1; /* restart */ - cpls = cpls & ~CPLS_PTR; } - else { /* no, interrupt */ - iosta = iosta | IOS_PTR; /* set flag */ - sbs = sbs | SB_RQ; } } /* req seq break */ -else sim_activate (&ptr_unit, ptr_unit.wait); /* get next char */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptr_reset (DEVICE *dptr) -{ -ptr_state = 0; /* clear state */ -ptr_wait = 0; -ptr_unit.buf = 0; -cpls = cpls & ~CPLS_PTR; -iosta = iosta & ~IOS_PTR; /* clear flag */ -sim_cancel (&ptr_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Bootstrap routine */ - -int32 ptr_getw (UNIT *uptr) -{ -int32 i, tmp, word; - -for (i = word = 0; i < 3;) { - if ((tmp = getc (uptr->fileref)) == EOF) return -1; - uptr->pos = uptr->pos + 1; - if (tmp & 0200) { - word = (word << 6) | (tmp & 077); - i++; } } -return word; -} - -t_stat ptr_boot (int32 unitno, DEVICE *dptr) -{ -int32 origin, val; -int32 fld = TA & EPCMASK; - -for (;;) { - if ((val = ptr_getw (&ptr_unit)) < 0) return SCPE_FMT; - if (((val & 0760000) == OP_DIO) || /* DIO? */ - ((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */ - origin = val & DAMASK; - if ((val = ptr_getw (&ptr_unit)) < 0) return SCPE_FMT; - M[fld | origin] = val; } - else if ((val & 0760000) == OP_JMP) { /* JMP? */ - PC = fld | (val & DAMASK); - break; } - else return SCPE_FMT; /* bad instr */ - } -return SCPE_OK; /* done */ -} - -/* Paper tape punch: IOT routine */ - -int32 ptp (int32 inst, int32 dev, int32 dat) -{ -iosta = iosta & ~IOS_PTP; /* clear flag */ -ptp_unit.buf = (dev == 0006)? ((dat >> 12) | 0200): (dat & 0377); -if (GEN_CPLS (inst)) { /* comp pulse? */ - ios = 0; - cpls = cpls | CPLS_PTP; } -else cpls = cpls & ~CPLS_PTP; -sim_activate (&ptp_unit, ptp_unit.wait); /* start unit */ -return dat; -} - -/* Unit service */ - -t_stat ptp_svc (UNIT *uptr) -{ -if (cpls & CPLS_PTP) { /* completion pulse? */ - ios = 1; /* restart */ - cpls = cpls & ~CPLS_PTP; } -iosta = iosta | IOS_PTP; /* set flag */ -sbs = sbs | SB_RQ; /* req seq break */ -if ((ptp_unit.flags & UNIT_ATT) == 0) /* not attached? */ - return IORETURN (ptp_stopioe, SCPE_UNATT); -if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { /* I/O error? */ - perror ("PTP I/O error"); - clearerr (ptp_unit.fileref); - return SCPE_IOERR; } -ptp_unit.pos = ptp_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptp_reset (DEVICE *dptr) -{ -ptp_unit.buf = 0; /* clear state */ -cpls = cpls & ~CPLS_PTP; -iosta = iosta & ~IOS_PTP; /* clear flag */ -sim_cancel (&ptp_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Typewriter IOT routines */ - -int32 tti (int32 inst, int32 dev, int32 dat) -{ -iosta = iosta & ~IOS_TTI; /* clear flag */ -if (inst & (IO_WAIT | IO_CPLS)) /* wait or sync? */ - return (STOP_RSRV << IOT_V_REASON) | (tty_buf & 077); -return tty_buf & 077; -} - -int32 tto (int32 inst, int32 dev, int32 dat) -{ -iosta = iosta & ~IOS_TTO; /* clear flag */ -tty_buf = dat & TT_WIDTH; /* load buffer */ -if (GEN_CPLS (inst)) { /* comp pulse? */ - ios = 0; - cpls = cpls | CPLS_TTO; } -else cpls = cpls & ~CPLS_TTO; -sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); /* activate unit */ -return dat; -} - -/* Unit service routines */ - -t_stat tti_svc (UNIT *uptr) -{ -int32 in, temp; - -sim_activate (uptr, uptr->wait); /* continue poll */ -if (tti_hold & CW) { /* char waiting? */ - tty_buf = tti_hold & TT_WIDTH; /* return char */ - tti_hold = 0; } /* not waiting */ -else { if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; - if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */ - temp = temp & 0177; - if (temp == 0177) temp = '\b'; /* rubout? bs */ - sim_putchar (temp); /* echo */ - if (temp == '\r') sim_putchar ('\n'); /* cr? add nl */ - in = ascii_to_fiodec[temp]; /* translate char */ - if (in == 0) return SCPE_OK; /* no xlation? */ - if ((in & BOTH) || ((in & UC) == (tty_uc & UC))) - tty_buf = in & TT_WIDTH; - else { /* must shift */ - tty_uc = in & UC; /* new case */ - tty_buf = tty_uc? FIODEC_UC: FIODEC_LC; - tti_hold = in | CW; } } /* set 2nd waiting */ -iosta = iosta | IOS_TTI; /* set flag */ -sbs = sbs | SB_RQ; /* req seq break */ -PF = PF | 040; /* set prog flag 1 */ -uptr->pos = uptr->pos + 1; -return SCPE_OK; -} - -t_stat tto_svc (UNIT *uptr) -{ -int32 out; - -if (cpls & CPLS_TTO) { /* completion pulse? */ - ios = 1; /* restart */ - cpls = cpls & ~CPLS_TTO; } -iosta = iosta | IOS_TTO; /* set flag */ -sbs = sbs | SB_RQ; /* req seq break */ -if (tty_buf == FIODEC_UC) { /* upper case? */ - tty_uc = UC; - return SCPE_OK; } -if (tty_buf == FIODEC_LC) { /* lower case? */ - tty_uc = 0; - return SCPE_OK; } -out = fiodec_to_ascii[tty_buf | tty_uc]; /* translate */ -if (out == 0) return SCPE_OK; /* no translation? */ -sim_putchar (out); -uptr->pos = uptr->pos + 1; -if (out == '\r') { /* cr? add lf */ - sim_putchar ('\n'); - uptr->pos = uptr->pos + 1; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tty_reset (DEVICE *dptr) -{ -tty_buf = 0; /* clear buffer */ -tty_uc = 0; /* clear case */ -tti_hold = 0; /* clear hold buf */ -cpls = cpls & ~CPLS_TTO; -iosta = (iosta & ~IOS_TTI) | IOS_TTO; /* clear flag */ -sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate keyboard */ -sim_cancel (&tty_unit[TTO]); /* stop printer */ -return SCPE_OK; -} diff --git a/PDP1/pdp1_sys.c b/PDP1/pdp1_sys.c deleted file mode 100644 index 4a30a798..00000000 --- a/PDP1/pdp1_sys.c +++ /dev/null @@ -1,513 +0,0 @@ -/* pdp1_sys.c: PDP-1 simulator interface - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 01-Sep-03 RMS Added support for loading in multiple fields - 22-Jul-03 RMS Updated for "hardware" RIM loader - 05-Dec-02 RMS Added drum support - 21-Nov-02 RMS Changed typewriter to half duplex - 20-Aug-02 RMS Added DECtape support - 17-Sep-01 RMS Removed multiconsole support - 13-Jul-01 RMS Fixed RIM loader format - 27-May-01 RMS Added multiconsole support - 14-Mar-01 RMS Revised load/dump interface (again) - 30-Oct-00 RMS Added support for examine to file - 27-Oct-98 RMS V2.4 load interface - 20-Oct-97 RMS Fixed endian-dependence in RIM loader - (found by Michael Somos) -*/ - -#include "pdp1_defs.h" -#include - -extern DEVICE cpu_dev; -extern DEVICE ptr_dev; -extern DEVICE ptp_dev; -extern DEVICE tty_dev; -extern DEVICE lpt_dev; -extern DEVICE dt_dev; -extern DEVICE drm_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern int32 M[]; -extern int32 PC; -extern int32 ascii_to_fiodec[], fiodec_to_ascii[]; -extern int32 sc_map[]; -extern int32 sim_switches; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "PDP-1"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 1; - -DEVICE *sim_devices[] = { - &cpu_dev, - &ptr_dev, - &ptp_dev, - &tty_dev, - &lpt_dev, - &dt_dev, - &drm_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Undefined instruction", - "HALT instruction", - "Breakpoint", - "Nested XCT's", - "Nested indirect addresses", - "Infinite I/O wait state" }; - -/* Binary loader - supports both RIM format and Macro block format */ - -int32 getw (FILE *inf) -{ -int32 i, tmp, word; - -word = 0; -for (i = 0; i < 3;) { - if ((tmp = getc (inf)) == EOF) return -1; - if (tmp & 0200) { - word = (word << 6) | (tmp & 077); - i++; } } -return word; -} - -t_stat rim_load (FILE *inf, int32 fld) -{ -int32 origin, val; - -for (;;) { - if ((val = getw (inf)) < 0) return SCPE_FMT; - if (((val & 0760000) == OP_DIO) || /* DIO? */ - ((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */ - origin = val & DAMASK; - if ((val = getw (inf)) < 0) return SCPE_FMT; - M[fld | origin] = val; } - else if ((val & 0760000) == OP_JMP) { /* JMP? */ - PC = fld | (val & DAMASK); - break; } - else return SCPE_FMT; /* bad instr */ - } -return SCPE_OK; /* done */ -} - -t_stat blk_load (FILE *inf, int32 fld) -{ -int32 val, start, count, csum; - -for (;;) { - if ((val = getw (inf)) < 0) return SCPE_FMT; /* get word, EOF? */ - if ((val & 0760000) == OP_DIO) { /* DIO? */ - csum = val; /* init checksum */ - start = val & DAMASK; /* starting addr */ - if ((val = getw (inf)) < 0) return SCPE_FMT; - if ((val & 0760000) != OP_DIO) return SCPE_FMT; - csum = csum + val; - if (csum > 0777777) csum = (csum + 1) & 0777777; - count = (val & DAMASK) - start + 1; /* block count */ - if (count <= 0) return SCPE_FMT; - while (count--) { /* loop on data */ - if ((val = getw (inf)) < 0) return SCPE_FMT; - csum = csum + val; - if (csum > 0777777) csum = (csum + 1) & 0777777; - M[fld | start] = val; - start = (start + 1) & DAMASK; } - if ((val = getw (inf)) < 0) return SCPE_FMT; - if (val != csum) return SCPE_CSUM; } - else if ((val & 0760000) == OP_JMP) { /* JMP? */ - PC = fld | (val & DAMASK); - break; } - else return SCPE_FMT; /* bad instr */ - } -return SCPE_OK; /* done */ -} - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -t_stat sta; -int32 fld; - -if (flag != 0) return SCPE_ARG; -if (cptr) { - fld = get_uint (cptr, 8, AMASK, &sta); - if (sta != SCPE_OK) return sta; - fld = fld & EPCMASK; } -else fld = 0; -sta = rim_load (fileref, fld); -if (sta != SCPE_OK) return sta; -if ((sim_switches & SWMASK ('B')) || match_ext (fnam, "BIN")) - return blk_load (fileref, fld); -return SCPE_OK; -} - -/* Symbol tables */ - -#define I_V_FL 18 /* inst class */ -#define I_M_FL 07 /* class mask */ -#define I_V_NPN 0 /* no operand */ -#define I_V_IOT 1 /* IOT */ -#define I_V_LAW 2 /* LAW */ -#define I_V_MRF 3 /* memory reference */ -#define I_V_MRI 4 /* mem ref no ind */ -#define I_V_OPR 5 /* OPR */ -#define I_V_SKP 6 /* skip */ -#define I_V_SHF 7 /* shift */ -#define I_NPN (I_V_NPN << I_V_FL) /* no operand */ -#define I_IOT (I_V_IOT << I_V_FL) /* IOT */ -#define I_LAW (I_V_LAW << I_V_FL) /* LAW */ -#define I_MRF (I_V_MRF << I_V_FL) /* memory reference */ -#define I_MRI (I_V_MRI << I_V_FL) /* mem ref no ind */ -#define I_OPR (I_V_OPR << I_V_FL) /* OPR */ -#define I_SKP (I_V_SKP << I_V_FL) /* skip */ -#define I_SHF (I_V_SHF << I_V_FL) /* shift */ - -static const int32 masks[] = { - 0777777, 0763777, 0760000, 0760000, - 0770000, 0760017, 0760077, 0777000 }; - -static const char *opcode[] = { - "AND", "IOR", "XOR", "XCT", /* mem refs */ - "LAC", "LIO", "DAC", "DAP", - "DIP", "DIO", "DZM", "ADD", - "SUB", "IDX", "ISP", "SAD", - "SAS", "MUL", "DIV", "JMP", "JSP", - - "CAL", "JDA", /* mem ref no ind */ - - "IOH", "RPA", "RPB", "RRB", /* I/O instructions */ - "PPA", "PPB", "TYO", "TYI", - "LSM", "ESM", "CBS", - "LEM", "EEM", "CKS", - "MSE", "MLC", "MRD", "MWR", "MRS", - - "SKP", "SKP I", "CLO", - "SFT", "LAW", "OPR", - - "RAL", "RIL", "RCL", /* shifts */ - "SAL", "SIL", "SCL", - "RAR", "RIR", "RCR", - "SAR", "SIR", "SCR", - - "SZF1", "SZF2", "SZF3", /* skips */ - "SZF4", "SZF5", "SZF6", "SZF7", - "SZS1", "SZS1 SZF1", "SZS1 SZF2", "SZS1 SZ3", - "SZS1 SZF4", "SZS1 SZF5", "SZS1 SZF6", "SZS1 SZF7", - "SZS2", "SZS2 SZF1", "SZS2 SZF2", "SZS2 SZ3", - "SZS2 SZF4", "SZS2 SZF5", "SZS2 SZF6", "SZS2 SZF7", - "SZS3", "SZS3 SZF1", "SZS3 SZF2", "SZS3 SZ3", - "SZS3 SZF4", "SZS3 SZF5", "SZS3 SZF6", "SZS3 SZF7", - "SZS4", "SZS4 SZF1", "SZS4 SZF2", "SZS4 SZ3", - "SZS4 SZF4", "SZS4 SZF5", "SZS4 SZF6", "SZS4 SZF7", - "SZS5", "SZS5 SZF1", "SZS5 SZF2", "SZS5 SZ3", - "SZS5 SZF4", "SZS5 SZF5", "SZS5 SZF6", "SZS5 SZF7", - "SZS6", "SZS6 SZF1", "SZS6 SZF2", "SZS6 SZ3", - "SZS6 SZF4", "SZS6 SZF5", "SZS6 SZF6", "SZS6 SZF7", - "SZS7", "SZS7 SZF1", "SZS7 SZF2", "SZS7 SZ3", - "SZS7 SZF4", "SZS7 SZF5", "SZS7 SZF6", "SZS7 SZF7", - - "CLF1", "CLF2", "CLF3", /* operates */ - "CLF4", "CLF5", "CLF6", "CLF7", - "STF1", "STF2", "STF3", - "STF4", "STF5", "STF6", "STF7", - - "SZA", "SPA", "SMA", /* encode only */ - "SZO", "SPI", "I", - "LAP", "CLA", "HLT", - "CMA", "LAT", "CLI", - NULL, NULL, /* decode only */ - NULL }; - -static const int32 opc_val[] = { - 0020000+I_MRF, 0040000+I_MRF, 0060000+I_MRF, 0100000+I_MRF, - 0200000+I_MRF, 0220000+I_MRF, 0240000+I_MRF, 0260000+I_MRF, - 0300000+I_MRF, 0320000+I_MRF, 0340000+I_MRF, 0400000+I_MRF, - 0420000+I_MRF, 0440000+I_MRF, 0460000+I_MRF, 0500000+I_MRF, - 0520000+I_MRF, 0540000+I_MRF, 0560000+I_MRF, 0600000+I_MRF, 0620000+I_MRF, - - 0160000+I_MRI, 0170000+I_MRI, - - 0730000+I_NPN, 0720001+I_IOT, 0720002+I_IOT, 0720030+I_IOT, - 0720005+I_IOT, 0720006+I_IOT, 0720003+I_IOT, 0720004+I_IOT, - 0720054+I_NPN, 0720055+I_NPN, 0720056+I_NPN, - 0720074+I_NPN, 0724074+I_NPN, 0720033+I_NPN, - 0720301+I_NPN, 0720401+I_NPN, 0720501+I_NPN, 0720601+I_NPN, 0720701+I_NPN, - - 0640000+I_NPN, 0650000+I_NPN, 0651600+I_NPN, - 0660000+I_NPN, 0700000+I_LAW, 0760000+I_NPN, - - 0661000+I_SHF, 0662000+I_SHF, 0663000+I_SHF, - 0665000+I_SHF, 0666000+I_SHF, 0667000+I_SHF, - 0671000+I_SHF, 0672000+I_SHF, 0673000+I_SHF, - 0675000+I_SHF, 0676000+I_SHF, 0677000+I_SHF, - - 0640001+I_SKP, 0640002+I_SKP, 0640003+I_SKP, - 0640004+I_SKP, 0640005+I_SKP, 0640006+I_SKP, 0640007+I_SKP, - 0640010+I_SKP, 0640011+I_SKP, 0640012+I_SKP, 0640013+I_SKP, - 0640014+I_SKP, 0640015+I_SKP, 0640016+I_SKP, 0640017+I_SKP, - 0640020+I_SKP, 0640021+I_SKP, 0640022+I_SKP, 0640023+I_SKP, - 0640024+I_SKP, 0640025+I_SKP, 0640026+I_SKP, 0640027+I_SKP, - 0640030+I_SKP, 0640031+I_SKP, 0640032+I_SKP, 0640033+I_SKP, - 0640034+I_SKP, 0640035+I_SKP, 0640036+I_SKP, 0640037+I_SKP, - 0640040+I_SKP, 0640041+I_SKP, 0640042+I_SKP, 0640043+I_SKP, - 0640044+I_SKP, 0640045+I_SKP, 0640046+I_SKP, 0640047+I_SKP, - 0640050+I_SKP, 0640051+I_SKP, 0640052+I_SKP, 0640053+I_SKP, - 0640054+I_SKP, 0640055+I_SKP, 0640056+I_SKP, 0640057+I_SKP, - 0640060+I_SKP, 0640061+I_SKP, 0640062+I_SKP, 0640063+I_SKP, - 0640064+I_SKP, 0640065+I_SKP, 0640066+I_SKP, 0640067+I_SKP, - 0640070+I_SKP, 0640071+I_SKP, 0640072+I_SKP, 0640073+I_SKP, - 0640074+I_SKP, 0640075+I_SKP, 0640076+I_SKP, 0640077+I_SKP, - - 0760001+I_OPR, 0760002+I_OPR, 0760003+I_OPR, - 0760004+I_OPR, 0760005+I_OPR, 0760006+I_OPR, 0760007+I_OPR, - 0760011+I_OPR, 0760012+I_OPR, 0760013+I_OPR, - 0760014+I_OPR, 0760015+I_OPR, 0760016+I_OPR, 0760017+I_OPR, - - 0640100+I_SKP, 0640200+I_SKP, 0640400+I_SKP, /* encode only */ - 0641000+I_SKP, 0642000+I_SKP, 0010000+I_SKP, - 0760100+I_OPR, 0760200+I_OPR, 0760400+I_OPR, - 0761000+I_OPR, 0762000+I_OPR, 0764000+I_OPR, - - 0640000+I_SKP, 0760000+I_OPR, /* decode only */ - -1 }; - -/* Operate or skip decode - - Inputs: - *of = output stream - inst = mask bits - class = instruction class code - sp = space needed? - Outputs: - status = space needed? -*/ - -int32 fprint_opr (FILE *of, int32 inst, int32 class, int32 sp) -{ -int32 i, j; - -for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - if ((j == class) && (opc_val[i] & inst)) { /* same class? */ - inst = inst & ~opc_val[i]; /* mask bit set? */ - fprintf (of, (sp? " %s": "%s"), opcode[i]); - sp = 1; } } -return sp; -} - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - return = status code -*/ - -#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) -#define SIXTOASC(x) fiodec_to_ascii[x] -#define ASCTOSIX(x) (ascii_to_fiodec[x] & 077) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, i, j, sp, inst, disp, ma; - -inst = val[0]; -cflag = (uptr == NULL) || (uptr == &cpu_unit); -if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; - fprintf (of, FMTASC (inst & 0177)); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* character? */ - fprintf (of, "%c", SIXTOASC ((inst >> 12) & 077)); - fprintf (of, "%c", SIXTOASC ((inst >> 6) & 077)); - fprintf (of, "%c", SIXTOASC (inst & 077)); - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; - -/* Instruction decode */ - -disp = inst & 007777; -ma = (addr & EPCMASK) | disp; -for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - if ((opc_val[i] & 0777777) == (inst & masks[j])) { /* match? */ - - switch (j) { /* case on class */ - case I_V_NPN: /* no operands */ - fprintf (of, "%s", opcode[i]); /* opcode */ - break; - case I_V_IOT: /* IOT */ - disp = (inst - opc_val[i]) & 017777; - if (disp == IA) fprintf (of, "%s I", opcode[i]); - else if (disp) fprintf (of, "%s %-o", opcode[i], disp); - else fprintf (of, "%s", opcode[i]); - break; - case I_V_LAW: /* LAW */ - cflag = 0; /* fall thru to MRF */ - case I_V_MRF: /* mem ref */ - fprintf (of, "%s%s%-o", opcode[i], - ((inst & IA)? " I ": " "), (cflag? ma: disp)); - break; - case I_V_MRI: /* mem ref no ind */ - fprintf (of, "%s %-o", opcode[i], (cflag? ma: disp)); - break; - case I_V_OPR: /* operates */ - sp = fprint_opr (of, inst & 007700, j, 0); - if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]); - break; - case I_V_SKP: /* skips */ - sp = fprint_opr (of, inst & 007700, j, 0); - if (opcode[i]) sp = fprintf (of, (sp? " %s": "%s"), opcode[i]); - if (inst & IA) fprintf (of, sp? " I": "I"); - break; - case I_V_SHF: /* shifts */ - fprintf (of, "%s %-d", opcode[i], sc_map[inst & 0777]); - break; } /* end case */ - return SCPE_OK; } /* end if */ - } /* end for */ -return SCPE_ARG; -} - -/* Get 18b signed number - - Inputs: - *cptr = pointer to input string - *sign = pointer to sign - *status = pointer to error status - Outputs: - val = output value -*/ - -t_value get_sint (char *cptr, int32 *sign, t_stat *status) -{ -*sign = 1; -if (*cptr == '+') { - *sign = 0; - cptr++; } -else if (*cptr == '-') { - *sign = -1; - cptr++; } -return get_uint (cptr, 8, 0777777, status); -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = error status -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 cflag, d, i, j, k, sign; -t_stat r; -static int32 sc_enc[10] = { 0, 01, 03, 07, 017, 037, 077, 0177, 0377, 0777 }; -char gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; -for (i = 1; (i < 3) && (cptr[i] != 0); i++) - if (cptr[i] == 0) for (j = i + 1; j <= 3; j++) cptr[j] = 0; -if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (t_value) cptr[0]; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (ASCTOSIX (cptr[0] & 077) << 12) | - (ASCTOSIX (cptr[1] & 077) << 6) | - ASCTOSIX (cptr[2] & 077); - return SCPE_OK; } - -/* Symbolic input, continued */ - -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; -if (opcode[i] == NULL) return SCPE_ARG; -val[0] = opc_val[i] & 0777777; /* get value */ -j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - -switch (j) { /* case on class */ -case I_V_LAW: /* LAW */ - cflag = 0; /* fall through */ -case I_V_MRF: case I_V_MRI: /* mem ref */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - if ((j != I_V_MRI) && strcmp (gbuf, "I") == 0) { /* indirect? */ - val[0] = val[0] | IA; - cptr = get_glyph (cptr, gbuf, 0); } - d = get_uint (gbuf, 8, AMASK, &r); - if (r != SCPE_OK) return SCPE_ARG; - if (d <= DAMASK) val[0] = val[0] | d; - else if (cflag && (((addr ^ d) & EPCMASK) == 0)) - val[0] = val[0] | (d & DAMASK); - else return SCPE_ARG; - break; -case I_V_SHF: /* shift */ - cptr = get_glyph (cptr, gbuf, 0); - d = get_uint (gbuf, 10, 9, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | sc_enc[d]; - break; -case I_V_NPN: case I_V_IOT: case I_V_OPR: case I_V_SKP: - for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; - cptr = get_glyph (cptr, gbuf, 0)) { - for (i = 0; (opcode[i] != NULL) && - (strcmp (opcode[i], gbuf) != 0); i++) ; - if (opcode[i] != NULL) { - k = opc_val[i] & 0777777; - if ((k != IA) && (((k ^ val[0]) & 0760000) != 0)) - return SCPE_ARG; - val[0] = val[0] | k; } - else { - d = get_sint (gbuf, &sign, &r); - if (r != SCPE_OK) return SCPE_ARG; - if (sign == 0) val[0] = val[0] + d; - else if (sign < 0) val[0] = val[0] - d; - else val[0] = val[0] | d; } } - break; } /* end case */ -if (*cptr != 0) return SCPE_ARG; /* junk at end? */ -return SCPE_OK; -} diff --git a/PDP10/pdp10_cpu.c b/PDP10/pdp10_cpu.c deleted file mode 100644 index 7ee895d8..00000000 --- a/PDP10/pdp10_cpu.c +++ /dev/null @@ -1,2102 +0,0 @@ -/* pdp10_cpu.c: PDP-10 CPU simulator - - Copyright (c) 1993-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - cpu KS10 central processor - - 08-Oct-02 RMS Revised to build dib_tab dynamically - Added SHOW IOSPACE - 30-Dec-01 RMS Added old PC queue - 25-Dec-01 RMS Cleaned up sim_inst declarations - 07-Dec-01 RMS Revised to use new breakpoint package - 21-Nov-01 RMS Implemented ITS 1-proceed hack - 31-Aug-01 RMS Changed int64 to t_int64 for Windoze - 10-Aug-01 RMS Removed register in declarations - 17-Jul-01 RMS Moved function prototype - 19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug - 29-Apr-01 RMS Fixed modifier naming conflict - Fixed XCTR/XCTRI, UMOVE/UMOVEM, BLTUB/BLTBU for ITS - Added CLRCSH for ITS - - The 36b system family had six different implementions: PDP-6, KA10, KI10, - L10, KL10 extended, and KS10. This simulator implements the KS10. - - The register state for the KS10 is: - - AC[8][16] accumulators - PC program counter - flags<0:11> state flags - pi_enb<1:7> enabled PI levels - pi_act<1:7> active PI levels - pi_prq<1:7> program PI requests - apr_enb<0:7> enabled system flags - apr_flg<0:7> system flags - ebr executive base register - ubr user base register - hsb halt status block address - spt SPT base - cst CST base - pur process use register - cstm CST mask - - The PDP-10 had just two instruction formats: memory reference - and I/O. - - 000000000 0111 1 1111 112222222222333333 - 012345678 9012 3 4567 890123456789012345 - +---------+----+-+----+------------------+ - | opcode | ac |i| idx| address | memory reference - +---------+----+-+----+------------------+ - - 000 0000000 111 1 1111 112222222222333333 - 012 3456789 012 3 4567 890123456789012345 - +---+-------+---+-+----+------------------+ - |111|device |iop|i| idx| address | I/O - +---+-------+---+-+----+------------------+ -*/ - -/* This routine is the instruction decode routine for the PDP-10. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until an abort occurs. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - MUUO instruction in executive mode - pager error in interrupt sequence - invalid vector table in interrupt sequence - illegal instruction in interrupt sequence - breakpoint encountered - nested indirects exceeding limit - nested XCT's exceeding limit - I/O error in I/O simulator - - 2. Interrupts. PDP-10's have a seven level priority interrupt - system. Interrupt requests can come from internal sources, - such as APR program requests, or external sources, such as - I/O devices. The requests are stored in pi_prq for program - requests, pi_apr for other internal flags, and pi_ioq for - I/O device flags. Internal and device (but not program) - interrupts must be enabled on a level by level basis. When - an interrupt is granted on a level, interrupts at that level - and below are masked until the interrupt is dismissed. - - The I/O device interrupt system is taken from the PDP-11. - int_req stores the interrupt requests for Unibus I/O devices. - Routines in the Unibus adapter map requests in int_req to - PDP-10 levels. The Unibus adapter also calculates which - device to get a vector from when a PDP-10 interrupt is granted. - - 3. Arithmetic. The PDP-10 is a 2's complement system. - - 4. Adding I/O devices. These modules must be modified: - - pdp10_defs.h add device address and interrupt definitions - pdp10_sys.c add sim_devices table entry - - A note on ITS 1-proceed. The simulator follows the implementation - on the KS10, keeping 1-proceed as a side flag (its_1pr) rather than - as flags<8>. This simplifies the flag saving instructions, which - don't have to clear flags<8> before saving it. Instead, the page - fail and interrupt code must restore flags<8> from its_1pr. Unlike - the KS10, the simulator will not lose the 1-proceed trap if the - 1-proceeded instructions clears 1-proceed. -*/ - -#include "pdp10_defs.h" -#include - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC -#define UNIT_V_MSIZE (UNIT_V_T20V41 + 1) /* dummy mask */ -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -d10 *M = NULL; /* memory */ -d10 acs[AC_NBLK * AC_NUM] = { 0 }; /* AC blocks */ -d10 *ac_cur, *ac_prv; /* AC cur, prv (dyn) */ -a10 epta, upta; /* proc tbl addr (dyn) */ -a10 saved_PC = 0; /* scp: saved PC */ -d10 pager_word = 0; /* pager: error word */ -a10 pager_PC = 0; /* pager: saved PC */ -int32 pager_flags = 0; /* pager: trap flags */ -t_bool pager_pi = FALSE; /* pager: in pi seq */ -t_bool pager_tc = FALSE; /* pager: trap cycle */ -d10 ebr = 0; /* exec base reg */ -d10 ubr = 0; /* user base reg */ -d10 hsb = 0; /* halt status block */ -d10 spt = 0; /* TOPS20 paging regs */ -d10 cst = 0; -d10 pur = 0; -d10 cstm = 0; -a10 dbr1 = 0; /* ITS paging regs */ -a10 dbr2 = 0; -a10 dbr3 = 0; -a10 dbr4 = 0; -d10 pcst = 0; /* ITS PC sampling */ -int32 pi_on = 0; /* pi system enable */ -int32 pi_enb = 0; /* pi enabled levels */ -int32 pi_act = 0; /* pi active levels */ -int32 pi_ioq = 0; /* pi io requests */ -int32 pi_apr = 0; /* pi apr requests */ -int32 pi_prq = 0; /* pi prog requests */ -int32 apr_enb = 0; /* apr enables */ -int32 apr_flg = 0; /* apr flags */ -int32 apr_lvl = 0; /* apr level */ -int32 qintr = 0; /* interrupt pending */ -int32 flags = 0; /* flags */ -int32 its_1pr = 0; /* ITS 1-proceed */ -int32 stop_op0 = 0; /* stop on 0 */ -int32 rlog = 0; /* extend fixup log */ -int32 ind_max = 32; /* nested ind limit */ -int32 xct_max = 32; /* nested XCT limit */ -a10 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -jmp_buf save_env; - -extern int32 sim_int_char; -extern int32 sim_interval; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern UNIT tim_unit; - -/* Forward and external declarations */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -d10 adjsp (d10 val, a10 ea); -void ibp (a10 ea, int32 pflgs); -d10 ldb (a10 ea, int32 pflgs); -void dpb (d10 val, a10 ea, int32 pflgs); -void adjbp (int32 ac, a10 ea, int32 pflgs); -d10 add (d10 val, d10 mb); -d10 sub (d10 val, d10 mb); -void dadd (int32 ac, d10 *rs); -void dsub (int32 ac, d10 *rs); -int32 jffo (d10 val); -d10 lsh (d10 val, a10 ea); -d10 rot (d10 val, a10 ea); -d10 ash (d10 val, a10 ea); -void lshc (int32 ac, a10 ea); -void rotc (int32 ac, a10 ea); -void ashc (int32 ac, a10 ea); -void circ (int32 ac, a10 ea); -void blt (int32 ac, a10 ea, int32 pflgs); -void bltu (int32 ac, a10 ea, int32 pflgs, int dir); -a10 calc_ea (d10 inst, int32 prv); -a10 calc_ioea (d10 inst, int32 prv); -d10 calc_jrstfea (d10 inst, int32 pflgs); -void pi_dismiss (void); -void set_newflags (d10 fl, t_bool jrst); -extern t_bool aprid (a10 ea, int32 prv); -t_bool wrpi (a10 ea, int32 prv); -t_bool rdpi (a10 ea, int32 prv); -t_bool czpi (a10 ea, int32 prv); -t_bool copi (a10 ea, int32 prv); -t_bool wrapr (a10 ea, int32 prv); -t_bool rdapr (a10 ea, int32 prv); -t_bool czapr (a10 ea, int32 prv); -t_bool coapr (a10 ea, int32 prv); -int32 pi_eval (void); -int32 test_int (void); -void set_ac_display (d10 *acbase); - -extern t_stat build_dib_tab (void); -extern t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc); -extern d10 Read (a10 ea, int32 prv); /* read, read check */ -extern d10 ReadM (a10 ea, int32 prv); /* read, write check */ -extern d10 ReadE (a10 ea); /* read, exec */ -extern d10 ReadP (a10 ea); /* read, physical */ -extern void Write (a10 ea, d10 val, int32 prv); /* write */ -extern void WriteE (a10 ea, d10 val); /* write, exec */ -extern void WriteP (a10 ea, d10 val); /* write, physical */ -extern t_bool AccViol (a10 ea, int32 prv, int32 mode); /* access check */ -extern void set_dyn_ptrs (void); -extern a10 conmap (a10 ea, int32 mode, int32 sw); -extern void fe_intr (); -extern void dfad (int32 ac, d10 *rs, int32 inv); -extern void dfmp (int32 ac, d10 *rs); -extern void dfdv (int32 ac, d10 *rs); -extern void dmul (int32 ac, d10 *rs); -extern void ddiv (int32 ac, d10 *rs); -extern void fix (int32 ac, d10 mb, t_bool rnd); -extern d10 fad (d10 val, d10 mb, t_bool rnd, int32 inv); -extern d10 fmp (d10 val, d10 mb, t_bool rnd); -extern t_bool fdv (d10 val, d10 mb, d10 *rs, t_bool rnd); -extern d10 fsc (d10 val, a10 ea); -extern d10 fltr (d10 mb); -extern int xtend (int32 ac, a10 ea, int32 pflgs); -extern void xtcln (int32 rlog); -extern d10 map (a10 ea, int32 prv); -extern d10 imul (d10 val, d10 mb); -extern t_bool idiv (d10 val, d10 mb, d10 *rs); -extern void mul (d10 val, d10 mb, d10 *rs); -extern t_bool divi (int32 ac, d10 mb, d10 *rs); -extern t_bool io710 (int32 ac, a10 ea); -extern t_bool io711 (int32 ac, a10 ea); -extern d10 io712 (a10 ea); -extern void io713 (d10 val, a10 ea); -extern void io714 (d10 val, a10 ea); -extern void io715 (d10 val, a10 ea); -extern t_bool io720 (int32 ac, a10 ea); -extern t_bool io721 (int32 ac, a10 ea); -extern d10 io722 (a10 ea); -extern void io723 (d10 val, a10 ea); -extern void io724 (d10 val, a10 ea); -extern void io725 (d10 val, a10 ea); -extern t_bool clrcsh (a10 ea, int32 prv); -extern t_bool clrpt (a10 ea, int32 prv); -extern t_bool wrubr (a10 ea, int32 prv); -extern t_bool wrebr (a10 ea, int32 prv); -extern t_bool wrhsb (a10 ea, int32 prv); -extern t_bool wrspb (a10 ea, int32 prv); -extern t_bool wrcsb (a10 ea, int32 prv); -extern t_bool wrpur (a10 ea, int32 prv); -extern t_bool wrcstm (a10 ea, int32 prv); -extern t_bool ldbr1 (a10 ea, int32 prv); -extern t_bool ldbr2 (a10 ea, int32 prv); -extern t_bool ldbr3 (a10 ea, int32 prv); -extern t_bool ldbr4 (a10 ea, int32 prv); -extern t_bool rdubr (a10 ea, int32 prv); -extern t_bool rdebr (a10 ea, int32 prv); -extern t_bool rdhsb (a10 ea, int32 prv); -extern t_bool rdspb (a10 ea, int32 prv); -extern t_bool rdcsb (a10 ea, int32 prv); -extern t_bool rdpur (a10 ea, int32 prv); -extern t_bool rdcstm (a10 ea, int32 prv); -extern t_bool sdbr1 (a10 ea, int32 prv); -extern t_bool sdbr2 (a10 ea, int32 prv); -extern t_bool sdbr3 (a10 ea, int32 prv); -extern t_bool sdbr4 (a10 ea, int32 prv); -extern t_bool rdtim (a10 ea, int32 prv); -extern t_bool rdint (a10 ea, int32 prv); -extern t_bool wrtim (a10 ea, int32 prv); -extern t_bool wrint (a10 ea, int32 prv); -extern t_bool rdpcst (a10 ea, int32 prv); -extern t_bool wrpcst (a10 ea, int32 prv); -extern t_bool spm (a10 ea, int32 prv); -extern t_bool lpmr (a10 ea, int32 prv); -extern int32 pi_ub_vec (int32 lvl, int32 *uba); - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit - cpu_reg CPU register list - cpu_mod CPU modifier list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX, MAXMEMSIZE) }; - -REG cpu_reg[] = { - { ORDATA (PC, saved_PC, VASIZE) }, - { ORDATA (FLAGS, flags, 18) }, - { ORDATA (AC0, acs[0], 36) }, /* addr in memory */ - { ORDATA (AC1, acs[1], 36) }, /* modified at exit */ - { ORDATA (AC2, acs[2], 36) }, /* to SCP */ - { ORDATA (AC3, acs[3], 36) }, - { ORDATA (AC4, acs[4], 36) }, - { ORDATA (AC5, acs[5], 36) }, - { ORDATA (AC6, acs[6], 36) }, - { ORDATA (AC7, acs[7], 36) }, - { ORDATA (AC10, acs[10], 36) }, - { ORDATA (AC11, acs[11], 36) }, - { ORDATA (AC12, acs[12], 36) }, - { ORDATA (AC13, acs[13], 36) }, - { ORDATA (AC14, acs[14], 36) }, - { ORDATA (AC15, acs[15], 36) }, - { ORDATA (AC16, acs[16], 36) }, - { ORDATA (AC17, acs[17], 36) }, - { ORDATA (PFW, pager_word, 36) }, - { ORDATA (EBR, ebr, EBR_N_EBR) }, - { FLDATA (PGON, ebr, EBR_V_PGON) }, - { FLDATA (T20P, ebr, EBR_V_T20P) }, - { ORDATA (UBR, ubr, 36) }, - { GRDATA (CURAC, ubr, 8, 3, UBR_V_CURAC), REG_RO }, - { GRDATA (PRVAC, ubr, 8, 3, UBR_V_PRVAC) }, - { ORDATA (SPT, spt, 36) }, - { ORDATA (CST, cst, 36) }, - { ORDATA (PUR, pur, 36) }, - { ORDATA (CSTM, cstm, 36) }, - { ORDATA (HSB, hsb, 36) }, - { ORDATA (DBR1, dbr1, PASIZE) }, - { ORDATA (DBR2, dbr2, PASIZE) }, - { ORDATA (DBR3, dbr3, PASIZE) }, - { ORDATA (DBR4, dbr4, PASIZE) }, - { ORDATA (PCST, pcst, 36) }, - { ORDATA (PIENB, pi_enb, 7) }, - { FLDATA (PION, pi_on, 0) }, - { ORDATA (PIACT, pi_act, 7) }, - { ORDATA (PIPRQ, pi_prq, 7) }, - { ORDATA (PIIOQ, pi_ioq, 7), REG_RO }, - { ORDATA (PIAPR, pi_apr, 7), REG_RO }, - { ORDATA (APRENB, apr_enb, 8) }, - { ORDATA (APRFLG, apr_flg, 8) }, - { ORDATA (APRLVL, apr_lvl, 3) }, - { ORDATA (RLOG, rlog, 10) }, - { FLDATA (F1PR, its_1pr, 0) }, - { BRDATA (PCQ, pcq, 8, VASIZE, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { DRDATA (INDMAX, ind_max, 8), PV_LEFT + REG_NZ }, - { DRDATA (XCTMAX, xct_max, 8), PV_LEFT + REG_NZ }, - { ORDATA (WRU, sim_int_char, 8) }, - { FLDATA (STOP_ILL, stop_op0, 0) }, - { BRDATA (REG, acs, 8, 36, AC_NUM * AC_NBLK) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_ITS+UNIT_T20V41, 0, "Standard microcode", "STANDARD", NULL }, - { UNIT_ITS+UNIT_T20V41, UNIT_T20V41, "TOPS-20 V4.1", "TOPS20V41", NULL }, - { UNIT_ITS+UNIT_T20V41, UNIT_ITS, "ITS microcode", "ITS", NULL }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL, - NULL, &show_iospace }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, PASIZE, 1, 8, 36, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -/* Data arrays */ - -const int32 pi_l2bit[8] = { - 0, 0100, 0040, 0020, 0010, 0004, 0002, 0001 }; - -const int32 pi_m2lvl[128] = { - 0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - -const d10 bytemask[64] = { 0, - 01, 03, 07, 017, 037, 077, - 0177, 0377, 0777, 01777, 03777, 07777, - 017777, 037777, 077777, - 0177777, 0377777, 0777777, - 01777777, 03777777, 07777777, - 017777777, 037777777, 077777777, - 0177777777, 0377777777, 0777777777, - 01777777777, 03777777777, 07777777777, - 017777777777, 037777777777, 077777777777, - 0177777777777, 0377777777777, 0777777777777, - ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, - ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, - ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES }; - -static t_bool (*io700d[16])() = { - &aprid, NULL, NULL, NULL, &wrapr, &rdapr, &czapr, &coapr, - NULL, NULL, NULL, NULL, &wrpi, &rdpi, &czpi, &copi }; -static t_bool (*io701d[16])() = { - NULL, &rdubr, &clrpt, &wrubr, &wrebr, &rdebr, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -static t_bool (*io702d[16])() = { - &rdspb, &rdcsb, &rdpur, &rdcstm, &rdtim, &rdint, &rdhsb, NULL, - &wrspb, &wrcsb, &wrpur, &wrcstm, &wrtim, &wrint, &wrhsb, NULL }; -#define io700i io700d -static t_bool (*io701i[16])() = { - &clrcsh, &rdubr, &clrpt, &wrubr, &wrebr, &rdebr, NULL, NULL, - NULL, &rdpcst, NULL, &wrpcst, NULL, NULL, NULL, NULL }; -static t_bool (*io702i[16])() = { - &sdbr1, &sdbr2, &sdbr3, &sdbr4, &rdtim, &rdint, &rdhsb, &spm, - &ldbr1, &ldbr2, &ldbr3, &ldbr4, &wrtim, &wrint, &wrhsb, &lpmr }; - -/* JRST classes and validation table */ - -#define JRST_U 1 /* ok anywhere */ -#define JRST_E 2 /* ok exec mode */ -#define JRST_UIO 3 /* ok user I/O mode */ - -static t_stat jrst_tab[16] = { - JRST_U, JRST_U, JRST_U, 0, JRST_E, JRST_U, JRST_E, JRST_E, - JRST_UIO, 0, JRST_UIO, 0, JRST_E, JRST_U, 0, 0 }; - -/* Address operations */ - -#define IM ((d10) ea) -#define IMS (((d10) ea) << 18) -#define JUMP(x) PCQ_ENTRY, PC = ((a10) (x)) & AMASK -#define SUBJ(x) CLRF (F_AFI | F_FPD | F_TR); JUMP (x) -#define INCPC PC = INCA (PC) - -/* AC operations */ - -#define AOBAC AC(ac) = AOB (AC(ac)) -#define SOBAC AC(ac) = SOB (AC(ac)) -#define G2AC rs[0] = AC(ac), rs[1] = AC(P1) -#define S1AC AC(ac) = rs[0] -#define S2AC S1AC, AC(P1) = rs[1] -#define LAC if (ac) AC(ac) = mb - -/* Memory operations */ - -#define RD mb = Read (ea, MM_OPND) -#define RDAC AC(ac) = Read (ea, MM_OPND) -#define RM mb = ReadM (ea, MM_OPND) -#define RMAC AC(ac) = ReadM (ea, MM_OPND) -#define RDP mb = Read (((a10) AC(ac)) & AMASK, MM_BSTK) -#define RD2 rs[0] = Read (ea, MM_OPND); \ - rs[1] = Read (INCA (ea), MM_OPND) -#define WR Write (ea, mb, MM_OPND) -#define WRAC Write (ea, AC(ac), MM_OPND) -#define WRP(x) Write (((a10) INCA (AC(ac))), (x), MM_BSTK) -#define WR1 Write (ea, rs[0], MM_OPND) -#define WR2 ReadM (INCA (ea), MM_OPND); \ - Write (ea, rs[0], MM_OPND); \ - Write (INCA (ea), rs[1], MM_OPND) - -/* Tests and compares */ - -#define TL(a) (TSTS (a) != 0) -#define TE(a) ((a) == 0) -#define TLE(a) (TL (a) || TE (a)) -#define TGE(a) (TSTS (a) == 0) -#define TN(a) ((a) != 0) -#define TG(a) (TGE (a) && TN (a)) -#define CL(a) ((TSTS (AC(ac) ^ a))? (a < AC(ac)): (AC(ac) < a)) -#define CE(a) (AC(ac) == a) -#define CLE(a) (CL (a) || CE (a)) -#define CGE(a) (!CL (a)) -#define CN(a) (AC(ac) != a) -#define CG(a) (CGE (a) && CN (a)) - -/* Word assemblies */ - -#define FLPC XWD (flags, PC) -#define UUOWORD (((d10) op) << INST_V_OP) | (((d10) ac) << INST_V_AC) | ea -#define APRHWORD ((apr_flg << APR_V_FLG) | (apr_lvl & APR_M_LVL) | \ - ((apr_flg & apr_enb)? APR_IRQ: 0)) -#define APRWORD ((apr_enb << (APR_V_FLG + 18)) | APRHWORD) -#define PIHWORD ((pi_act << PI_V_ACT) | (pi_on << PI_V_ON) | \ - (pi_enb << PI_V_ENB)) -#define PIWORD ((pi_prq << PI_V_PRQ) | PIHWORD) - -/* Instruction operations */ - -#define CIBP if (!TSTF (F_FPD)) { ibp (ea, pflgs); SETF (F_FPD); } -#define LDB AC(ac) = ldb (ea, pflgs) -#define DPB dpb (AC(ac), ea, pflgs) -#define FAD(s) fad (AC(ac), s, FALSE, 0) -#define FADR(s) fad (AC(ac), s, TRUE, 0) -#define FSB(s) fad (AC(ac), s, FALSE, 1) -#define FSBR(s) fad (AC(ac), s, TRUE, 1) -#define FMP(s) fmp (AC(ac), s, FALSE) -#define FMPR(s) fmp (AC(ac), s, TRUE) -#define FDV(s) fdv (AC(ac), s, rs, FALSE) -#define FDVR(s) fdv (AC(ac), s, rs, TRUE) -#define MOVN(s) NEG (s); MOVNF(s) -#define MOVM(s) ABS (s); MOVMF(s) -#define ADD(s) add (AC(ac), s) -#define SUB(s) sub (AC(ac), s) -#define IMUL(s) imul (AC(ac), s) -#define IDIV(s) idiv (AC(ac), s, rs) -#define MUL(s) mul (AC(ac), s, rs) -#define DIV(s) divi (ac, s, rs) -#define AOJ AC(ac) = INC (AC(ac)); INCF (AC(ac)) -#define AOS RM; mb = INC (mb); WR; INCF (mb); LAC -#define SOJ AC(ac) = DEC (AC(ac)); DECF (AC(ac)) -#define SOS RM; mb = DEC (mb); WR; DECF (mb); LAC -#define SETCA(s) ~AC(ac) & DMASK -#define SETCM(s) ~(s) & DMASK; -#define AND(s) AC(ac) & (s) -#define ANDCA(s) ~AC(ac) & (s) -#define ANDCM(s) AC(ac) & ~(s) -#define ANDCB(s) (~AC(ac) & ~(s)) & DMASK -#define IOR(s) AC(ac) | (s) -#define ORCA(s) (~AC(ac) | (s)) & DMASK -#define ORCM(s) (AC(ac) | ~(s)) & DMASK -#define ORCB(s) (~AC(ac) | ~(s)) & DMASK -#define XOR(s) AC(ac) ^ (s) -#define EQV(s) (~(AC(ac) ^ (s))) & DMASK -#define LL(s,d) ((s) & LMASK) | ((d) & RMASK) -#define RL(s,d) (((s) << 18) & LMASK) | ((d) & RMASK) -#define RR(s,d) ((s) & RMASK) | ((d) & LMASK) -#define LR(s,d) (((s) >> 18) & RMASK) | ((d) & LMASK) -#define LLO(s) ((s) & LMASK) | RMASK -#define RLO(s) (((s) << 18) & LMASK) | RMASK -#define RRO(s) ((s) & RMASK) | LMASK -#define LRO(s) (((s) >> 18) & RMASK) | LMASK -#define LLE(s) ((s) & LMASK) | (((s) & LSIGN)? RMASK: 0) -#define RLE(s) (((s) << 18) & LMASK) | (((s) & RSIGN)? RMASK: 0) -#define RRE(s) ((s) & RMASK) | (((s) & RSIGN)? LMASK: 0) -#define LRE(s) (((s) >> 18) & RMASK) | (((s) & LSIGN)? LMASK: 0) -#define TD_ RD -#define TS_ RD; mb = SWP (mb) -#define TL_ mb = IMS -#define TR_ mb = IM -#define T_Z AC(ac) = AC(ac) & ~mb -#define T_O AC(ac) = AC(ac) | mb -#define T_C AC(ac) = AC(ac) ^ mb -#define T__E if ((AC(ac) & mb) == 0) INCPC -#define T__N if ((AC(ac) & mb) != 0) INCPC -#define T__A INCPC -#define IOC if (TSTF (F_USR) && !TSTF (F_UIO)) goto MUUO; -#define IO7(x,y) IOC; fptr = ((ITS)? x[ac]: y[ac]); \ - if (fptr == NULL) goto MUUO; \ - if (fptr (ea, MM_OPND)) INCPC; break; -#define IOA IOC; if (!ITS) ea = calc_ioea (inst, pflgs) -#define IOAM IOC; ea = ((ITS)? ((a10) Read (ea, MM_OPND)): \ - calc_ioea (inst, pflgs)) - -/* Flag tests */ - -#define MOVNF(x) if ((x) == MAXNEG) SETF (F_C1 | F_AOV | F_T1); \ - else if ((x) == 0) SETF (F_C0 | F_C1) -#define MOVMF(x) if ((x) == MAXNEG) SETF (F_C1 | F_AOV | F_T1) -#define INCF(x) if ((x) == 0) SETF (F_C0 | F_C1); \ - else if ((x) == MAXNEG) SETF (F_C1 | F_AOV | F_T1) -#define DECF(x) if ((x) == MAXPOS) SETF (F_C0 | F_AOV | F_T1); \ - else if ((x) != ONES) SETF (F_C0 | F_C1) -#define PUSHF if (LRZ (AC(ac)) == 0) SETF (F_T2) -#define POPF if (LRZ (AC(ac)) == RMASK) SETF (F_T2) -#define DMOVNF if (rs[1] == 0) { MOVNF (rs[0]); } - -t_stat sim_instr (void) -{ -a10 PC; /* set by setjmp */ -int abortval = 0; /* abort value */ -t_stat r; - -/* Restore register state */ - -if ((r = build_dib_tab ()) != SCPE_OK) return r; /* build, chk dib_tab */ -pager_PC = PC = saved_PC & AMASK; /* load local PC */ -set_dyn_ptrs (); /* set up local ptrs */ -pager_tc = FALSE; /* not in trap cycle */ -pager_pi = FALSE; /* not in pi sequence */ -rlog = 0; /* not in extend */ -pi_eval (); /* eval pi system */ -sim_rtc_init (tim_unit.wait); /* init calibration */ -if (!ITS) its_1pr = 0; /* ~ITS, clr 1-proc */ - -/* Abort handling - - Aborts may come from within the simulator to stop simulation (values > 0), - for page fails (values < 0), or for an interrupt check (value = 0). -*/ - -abortval = setjmp (save_env); /* set abort hdlr */ -if ((abortval > 0) || pager_pi) { /* stop or pi err? */ - if (pager_pi && (abortval == PAGE_FAIL)) - abortval = STOP_PAGINT; /* stop for pi err */ - saved_PC = pager_PC & AMASK; /* failing instr PC */ - set_ac_display (ac_cur); /* set up AC display */ - pcq_r->qptr = pcq_p; /* update pc q ptr */ - return abortval; } /* return to SCP */ - -/* Page fail - checked against KS10 ucode - All state variables MUST be declared global for GCC optimization to work -*/ - -else if (abortval == PAGE_FAIL) { /* page fail */ - d10 mb; - if (rlog) xtcln (rlog); /* clean up extend */ - rlog = 0; /* clear log */ - if (pager_tc) flags = pager_flags; /* trap? get flags */ - if (T20) { /* TOPS-20 */ - WriteP (upta + UPT_T20_PFL, pager_word); /* write page fail wd */ - WriteP (upta + UPT_T20_OFL, XWD (flags, 0)); - WriteP (upta + UPT_T20_OPC, pager_PC); - mb = ReadP (upta + UPT_T20_NPC); } - else { - a10 ea; /* TOPS-10 or ITS */ - if (ITS) { /* ITS? */ - ea = epta + EPT_ITS_PAG + (pi_m2lvl[pi_act] * 3); - if (its_1pr) flags = flags | F_1PR; /* store 1-proc */ - its_1pr = 0; } /* clear 1-proc */ - else ea = upta + UPT_T10_PAG; - WriteP (ea, pager_word); /* write page fail wd */ - WriteP (ADDA (ea, 1), XWD (flags, pager_PC)); - mb = ReadP (ADDA (ea, 2)); } - JUMP (mb); /* set new PC */ - set_newflags (mb, FALSE); /* set new flags */ - pi_eval (); } /* eval pi system */ -else PC = pager_PC; /* intr, restore PC */ - -/* Main instruction fetch/decode loop: check clock queue, intr, trap, bkpt */ - -for ( ;; ) { /* loop until ABORT */ -int32 op, ac, i, st, xr, xct_cnt, its_2pr, pflgs; -a10 ea; -d10 inst, mb, indrct, rs[2]; -t_bool (*fptr)(); - -pager_PC = PC; /* update pager PC */ -pager_tc = FALSE; /* not in trap cycle */ -pflgs = 0; /* not in PXCT */ -xct_cnt = 0; /* count XCT's */ -if (sim_interval <= 0) { /* check clock queue */ - if (i = sim_process_event ()) ABORT (i); /* error? stop sim */ - pi_eval (); } /* eval pi system */ - -/* PI interrupt (Unibus or system flags). - On the KS10, only JSR and XPCW are allowed as interrupt instructions. - Because of exec mode addressing, and unconditional processing of flags, - they are explicitly emulated here. -*/ - -if (qintr) { - int32 vec, uba; - pager_pi = TRUE; /* flag in pi seq */ - if (vec = pi_ub_vec (qintr, &uba)) { /* Unibus interrupt? */ - mb = ReadP (epta + EPT_UBIT + uba); /* get dispatch table */ - if (mb == 0) ABORT (STOP_ZERINT); /* invalid? stop */ - inst = ReadE ((((a10) mb) + (vec / 4)) & AMASK); - if (inst == 0) ABORT (STOP_ZERINT); } - else inst = ReadP (epta + EPT_PIIT + (2 * qintr)); - op = GET_OP (inst); /* get opcode */ - ac = GET_AC (inst); /* get ac */ - if (its_1pr && ITS) { /* 1-proc set? */ - flags = flags | F_1PR; /* store 1-proc */ - its_1pr = 0; } /* clear 1-proc */ - if (op == OP_JSR) { /* JSR? */ - ea = calc_ea (inst, MM_CUR); /* calc ea, cur mode */ - WriteE (ea, FLPC); /* save flags+PC, exec */ - JUMP (INCA (ea)); /* PC = ea + 1 */ - set_newflags (0, FALSE); } /* set new flags */ - else if ((op == OP_JRST) && (ac == AC_XPCW)) { /* XPCW? */ - ea = calc_ea (inst, MM_CUR); /* calc ea, cur mode */ - WriteE (ea, XWD (flags, 0)); /* write flags, exec */ - WriteE (ADDA (ea, 1), PC); /* write PC, exec */ - rs[0] = ReadE (ADDA (ea, 2)); /* read new flags */ - rs[1] = ReadE (ADDA (ea, 3)); /* read new PC */ - JUMP (rs[1]); /* set new PC */ - set_newflags (rs[0], FALSE); } /* set new flags */ - else ABORT (STOP_ILLINT); /* invalid instr */ - pi_act = pi_act | pi_l2bit[qintr]; /* set level active */ - pi_eval (); /* eval pi system */ - pager_pi = FALSE; /* end of sequence */ - if (sim_interval) sim_interval--; /* charge for instr */ - continue; } /* end if interrupt */ - -/* Traps fetch and execute an instruction from the current mode process table. - On the KS10, the fetch of the next instruction has started, and a page fail - trap on the instruction fetch takes precedence over the trap. During a trap, - flags are cleared before the execute, but if the execute aborts, they must - be restored. Also, the MUUO processor needs to know whether we are in a - trap sequence. Hence, trap in progress is recorded in pflgs, and the - traps for pager restoration are recorded in pager_flags. -*/ - -if (TSTF (F_T1 | F_T2) && PAGING) { - Read (pager_PC = PC, MM_CUR); /* test fetch */ - pager_tc = TRUE; /* in a trap sequence */ - pager_flags = flags; /* save flags */ - ea = (TSTF (F_USR)? upta + UPT_TRBASE: epta + EPT_TRBASE) - + GET_TRAPS (flags); - inst = ReadP (ea); /* get trap instr */ - CLRF (F_T1 | F_T2); } /* clear flags */ - -/* Test for instruction breakpoint */ - -else { if (sim_brk_summ && - sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - ABORT (STOP_IBKPT); } /* stop simulation */ - -/* Ready (at last) to get an instruction */ - - inst = Read (pager_PC = PC, MM_CUR); /* get instruction */ - INCPC; - sim_interval = sim_interval - 1; } - -its_2pr = its_1pr; /* save 1-proc flag */ - -/* Execute instruction. XCT and PXCT also return here. */ - -XCT: -op = GET_OP (inst); /* get opcode */ -ac = GET_AC (inst); /* get AC */ -for (indrct = inst, i = 0; i < ind_max; i++) { /* calc eff addr */ - ea = GET_ADDR (indrct); - xr = GET_XR (indrct); - if (xr) ea = (ea + ((a10) XR (xr, MM_EA))) & AMASK; - if (TST_IND (indrct)) indrct = Read (ea, MM_EA); - else break; } -if (i >= ind_max) - ABORT (STOP_IND); /* too many ind? stop */ -switch (op) { /* case on opcode */ - -/* UUO's (0000 - 0077) - checked against KS10 ucode */ - -case 0000: if (stop_op0) { ABORT (STOP_ILLEG); } - goto MUUO; -case 0001: /* local UUO's */ -case 0002: -case 0003: -case 0004: -case 0005: -case 0006: -case 0007: -case 0010: -case 0011: -case 0012: -case 0013: -case 0014: -case 0015: -case 0016: -case 0017: -case 0020: -case 0021: -case 0022: -case 0023: -case 0024: -case 0025: -case 0026: -case 0027: -case 0030: -case 0031: -case 0032: -case 0033: -case 0034: -case 0035: -case 0036: -case 0037: - Write (040, UUOWORD, MM_CUR); /* store op, ac, ea */ - inst = Read (041, MM_CUR); /* get new instr */ - goto XCT; -/* case 0040 - 0077: MUUO's, handled by default at end of case */ - -/* Floating point, bytes, multiple precision (0100 - 0177) */ - -/* case 0100: MUUO /* UJEN */ -/* case 0101: MUUO /* unassigned */ -case 0102: if (ITS && !TSTF (F_USR)) { /* GFAD (KL), XCTRI (ITS) */ - inst = Read (ea, MM_OPND); - pflgs = pflgs | ac; goto XCT; } - goto MUUO; -case 0103: if (ITS && !TSTF (F_USR)) { /* GFSB (KL), XCTR (ITS) */ - inst = Read (ea, MM_OPND); - pflgs = pflgs | ac; goto XCT; } - goto MUUO; -/* case 0104: MUUO /* JSYS (T20) */ -case 0105: AC(ac) = adjsp (AC(ac), ea); break; /* ADJSP */ -/* case 0106: MUUO /* GFMP (KL)*/ -/* case 0107: MUUO /* GFDV (KL) */ -case 0110: RD2; dfad (ac, rs, 0); break; /* DFAD */ -case 0111: RD2; dfad (ac, rs, 1); break; /* DFSB */ -case 0112: RD2; dfmp (ac, rs); break; /* DFMP */ -case 0113: RD2; dfdv (ac, rs); break; /* DFDV */ -case 0114: RD2; dadd (ac, rs); break; /* DADD */ -case 0115: RD2; dsub (ac, rs); break; /* DSUB */ -case 0116: RD2; dmul (ac, rs); break; /* DMUL */ -case 0117: RD2; ddiv (ac, rs); break; /* DDIV */ -case 0120: RD2; S2AC; break; /* DMOVE */ -case 0121: RD2; DMOVN (rs); S2AC; DMOVNF; break; /* DMOVN */ -case 0122: RD; fix(ac, mb, 0); break; /* FIX */ -case 0123: st = xtend (ac, ea, pflgs); /* EXTEND */ - rlog = 0; switch (st) { /* clear log */ - case XT_SKIP: INCPC; - case XT_NOSK: break; - default: goto MUUO; } - break; -case 0124: G2AC; WR2; break; /* DMOVEM */ -case 0125: G2AC; DMOVN (rs); WR2; DMOVNF; break; /* DMOVNM */ -case 0126: RD; fix (ac, mb, 1); break; /* FIXR */ -case 0127: RD; AC(ac) = fltr (mb); break; /* FLTR */ -/* case 0130: MUUO /* UFA */ -/* case 0131: MUUO /* DFN */ -case 0132: AC(ac) = fsc (AC(ac), ea); break; /* FSC */ -case 0133: if (!ac) ibp (ea, pflgs); /* IBP */ - else adjbp (ac, ea, pflgs); break; -case 0134: CIBP; LDB; CLRF (F_FPD); break; /* ILBP */ -case 0135: LDB; break; /* LDB */ -case 0136: CIBP; DPB; CLRF (F_FPD); break; /* IDBP */ -case 0137: DPB; break; /* DPB */ -case 0140: RD; AC(ac) = FAD (mb); break; /* FAD */ -/* case 0141: MUUO /* FADL */ -case 0142: RM; mb = FAD (mb); WR; break; /* FADM */ -case 0143: RM; AC(ac) = FAD (mb); WRAC; break; /* FADB */ -case 0144: RD; AC(ac) = FADR (mb); break; /* FADR */ -case 0145: AC(ac) = FADR (IMS); break; /* FADRI */ -case 0146: RM; mb = FADR (mb); WR; break; /* FADRM */ -case 0147: RM; AC(ac) = FADR (mb); WRAC; break; /* FADRB */ -case 0150: RD; AC(ac) = FSB (mb); break; /* FSB */ -/* case 0151: MUUO /* FSBL */ -case 0152: RM; mb = FSB (mb); WR; break; /* FSBM */ -case 0153: RM; AC(ac) = FSB (mb); WRAC; break; /* FSBB */ -case 0154: RD; AC(ac) = FSBR (mb); break; /* FSBR */ -case 0155: AC(ac) = FSBR (IMS); break; /* FSBRI */ -case 0156: RM; mb = FSBR (mb); WR; break; /* FSBRM */ -case 0157: RM; AC(ac) = FSBR (mb); WRAC; break; /* FSBRB */ -case 0160: RD; AC(ac) = FMP (mb); break; /* FMP */ -/* case 0161: MUUO /* FMPL */ -case 0162: RM; mb = FMP (mb); WR; break; /* FMPM */ -case 0163: RM; AC(ac) = FMP (mb); WRAC; break; /* FMPB */ -case 0164: RD; AC(ac) = FMPR (mb); break; /* FMPR */ -case 0165: AC(ac) = FMPR (IMS); break; /* FMPRI */ -case 0166: RM; mb = FMPR (mb); WR; break; /* FMPRM */ -case 0167: RM; AC(ac) = FMPR (mb); WRAC; break; /* FMPRB */ -case 0170: RD; if (FDV (mb)) S1AC; break; /* FDV */ -/* case 0171: MUUO /* FDVL */ -case 0172: RM; if (FDV (mb)) WR1; break; /* FDVM */ -case 0173: RM; if (FDV (mb)) { S1AC; WRAC; } break; /* FDVB */ -case 0174: RD; if (FDVR (mb)) S1AC; break; /* FDVR */ -case 0175: if (FDVR (IMS)) S1AC; break; /* FDVRI */ -case 0176: RM; if (FDVR (mb)) WR1; break; /* FDVRM */ -case 0177: RM; if (FDVR (mb)) { S1AC; WRAC; } break; /* FDVRB */ - -/* Move, arithmetic, shift, and jump (0200 - 0277) - - Note that instructions which modify the flags and store a - result in memory must prove the writeability of the result - location before modifying the flags. Also, 0247 and 0257, - if not implemented, are nops, not MUUO's. -*/ - -case 0200: RDAC; break; /* MOVE */ -case 0201: AC(ac) = ea; break; /* MOVEI */ -case 0202: WRAC; break; /* MOVEM */ -case 0203: RM; LAC; break; /* MOVES */ -case 0204: RD; AC(ac) = SWP (mb); break; /* MOVS */ -case 0205: AC(ac) = IMS; break; /* MOVSI */ -case 0206: mb = SWP (AC(ac)); WR; break; /* MOVSM */ -case 0207: RM; mb = SWP (mb); WR; LAC; break; /* MOVSS */ -case 0210: RD; AC(ac) = MOVN (mb); break; /* MOVN */ -case 0211: AC(ac) = MOVN (IM); break; /* MOVNI */ -case 0212: RM; mb = MOVN (AC(ac)); WR; break; /* MOVNM */ -case 0213: RM; mb = MOVN (mb); WR; LAC; break; /* MOVNS */ -case 0214: RD; AC(ac) = MOVM (mb); break; /* MOVM */ -case 0215: AC(ac) = ea; break; /* MOVMI */ -case 0216: RM; mb = MOVM (AC(ac)); WR; break; /* MOVMM */ -case 0217: RM; mb = MOVM (mb); WR; LAC; break; /* MOVMS */ -case 0220: RD; AC(ac) = IMUL (mb); break; /* IMUL */ -case 0221: AC(ac) = IMUL (IM); break; /* IMULI */ -case 0222: RM; mb = IMUL (mb); WR; break; /* IMULM */ -case 0223: RM; AC(ac) = IMUL (mb); WRAC; break; /* IMULB */ -case 0224: RD; MUL (mb); S2AC; break; /* MUL */ -case 0225: MUL (IM); S2AC; break; /* MULI */ -case 0226: RM; MUL (mb); WR1; break; /* MULM */ -case 0227: RM; MUL (mb); WR1; S2AC; break; /* MULB */ -case 0230: RD; if (IDIV (mb)) S2AC; break; /* IDIV */ -case 0231: if (IDIV (IM)) S2AC; break; /* IDIVI */ -case 0232: RM; if (IDIV (mb)) WR1; break; /* IDIVM */ -case 0233: RM; if (IDIV (mb)) { WR1; S2AC; } break; /* IDIVB */ -case 0234: RD; if (DIV (mb)) S2AC; break; /* DIV */ -case 0235: if (DIV (IM)) S2AC; break; /* DIVI */ -case 0236: RM; if (DIV (mb)) WR1; break; /* DIVM */ -case 0237: RM; if (DIV (mb)) { WR1; S2AC; } break; /* DIVB */ -case 0240: AC(ac) = ash (AC(ac), ea); break; /* ASH */ -case 0241: AC(ac) = rot (AC(ac), ea); break; /* ROT */ -case 0242: AC(ac) = lsh (AC(ac), ea); break; /* LSH */ -case 0243: AC(P1) = jffo (AC(ac)); /* JFFO */ - if (AC(ac)) JUMP (ea); break; -case 0244: ashc (ac, ea); break; /* ASHC */ -case 0245: rotc (ac, ea); break; /* ROTC */ -case 0246: lshc (ac, ea); break; /* LSHC */ -case 0247: if (ITS) circ (ac, ea); break; /* (ITS) CIRC */ -case 0250: RM; WRAC; AC(ac) = mb; break; /* EXCH */ -case 0251: blt (ac, ea, pflgs); break; /* BLT */ -case 0252: AOBAC; if (TGE (AC(ac))) JUMP (ea); break; /* AOBJP */ -case 0253: AOBAC; if (TL (AC(ac))) JUMP (ea); break; /* AOBJN */ -/* case 0254: /* shown later /* JRST */ -case 0255: if (flags & (ac << 14)) { /* JFCL */ - JUMP (ea); CLRF (ac << 14); } break; -case 0256: if (xct_cnt++ >= xct_max) /* XCT */ - ABORT (STOP_XCT); - inst = Read (ea, MM_OPND); - if (ac && !TSTF (F_USR) && !ITS) pflgs = pflgs | ac; - goto XCT; -case 0257: if (ITS) goto MUUO; /* MAP */ - AC(ac) = map (ea, MM_OPND); break; -case 0260: WRP (FLPC); AOBAC; /* PUSHJ */ - SUBJ (ea); PUSHF; break; -case 0261: RD; WRP (mb); AOBAC; PUSHF; break; /* PUSH */ -case 0262: RDP; WR; SOBAC; POPF; break; /* POP */ -case 0263: RDP; JUMP (mb); SOBAC; POPF; break; /* POPJ */ -case 0264: Write (ea, FLPC, MM_OPND); /* JSR */ - SUBJ (INCR (ea)); break; -case 0265: AC(ac) = FLPC; SUBJ (ea); break; /* JSP */ -case 0266: WRAC; AC(ac) = XWD (ea, PC); /* JSA */ - JUMP (INCR (ea)); break; -case 0267: AC(ac) = Read ((a10) LRZ (AC(ac)), MM_OPND); /* JRA */ - JUMP (ea); break; -case 0270: RD; AC(ac) = ADD (mb); break; /* ADD */ -case 0271: AC(ac) = ADD (IM); break; /* ADDI */ -case 0272: RM; mb = ADD (mb); WR; break; /* ADDM */ -case 0273: RM; AC(ac) = ADD (mb); WRAC; break; /* ADDB */ -case 0274: RD; AC(ac) = SUB (mb); break; /* SUB */ -case 0275: AC(ac) = SUB (IM); break; /* SUBI */ -case 0276: RM; mb = SUB (mb); WR; break; /* SUBM */ -case 0277: RM; AC(ac) = SUB (mb); WRAC; break; /* SUBB */ - -/* Compare, jump, skip instructions (0300 - 0377) - checked against KS10 ucode */ - -case 0300: break; /* CAI */ -case 0301: if (CL (IM)) INCPC; break; /* CAIL */ -case 0302: if (CE (IM)) INCPC; break; /* CAIE */ -case 0303: if (CLE (IM)) INCPC; break; /* CAILE */ -case 0304: INCPC; break; /* CAIA */ -case 0305: if (CGE (IM)) INCPC; break; /* CAIGE */ -case 0306: if (CN (IM)) INCPC; break; /* CAIN */ -case 0307: if (CG (IM)) INCPC; break; /* CAIG */ -case 0310: RD; break; /* CAM */ -case 0311: RD; if (CL (mb)) INCPC; break; /* CAML */ -case 0312: RD; if (CE (mb)) INCPC; break; /* CAME */ -case 0313: RD; if (CLE (mb)) INCPC; break; /* CAMLE */ -case 0314: RD; INCPC; break; /* CAMA */ -case 0315: RD; if (CGE (mb)) INCPC; break; /* CAMGE */ -case 0316: RD; if (CN (mb)) INCPC; break; /* CAMN */ -case 0317: RD; if (CG (mb)) INCPC; break; /* CAMG */ -case 0320: break; /* JUMP */ -case 0321: if (TL (AC(ac))) JUMP (ea); break; /* JUMPL */ -case 0322: if (TE (AC(ac))) JUMP (ea); break; /* JUMPE */ -case 0323: if (TLE( AC(ac))) JUMP (ea); break; /* JUMPLE */ -case 0324: JUMP (ea); break; /* JUMPA */ -case 0325: if (TGE (AC(ac))) JUMP (ea); break; /* JUMPGE */ -case 0326: if (TN (AC(ac))) JUMP (ea); break; /* JUMPN */ -case 0327: if (TG (AC(ac))) JUMP (ea); break; /* JUMPG */ -case 0330: RD; LAC; break; /* SKIP */ -case 0331: RD; LAC; if (TL (mb)) INCPC; break; /* SKIPL */ -case 0332: RD; LAC; if (TE (mb)) INCPC; break; /* SKIPE */ -case 0333: RD; LAC; if (TLE (mb)) INCPC; break; /* SKIPLE */ -case 0334: RD; LAC; INCPC; break; /* SKIPA */ -case 0335: RD; LAC; if (TGE (mb)) INCPC; break; /* SKIPGE */ -case 0336: RD; LAC; if (TN (mb)) INCPC; break; /* SKIPN */ -case 0337: RD; LAC; if (TG (mb)) INCPC; break; /* SKIPG */ -case 0340: AOJ; break; /* AOJ */ -case 0341: AOJ; if (TL (AC(ac))) JUMP (ea); break; /* AOJL */ -case 0342: AOJ; if (TE (AC(ac))) JUMP (ea); break; /* AOJE */ -case 0343: AOJ; if (TLE (AC(ac))) JUMP (ea); break;/* AOJLE */ -case 0344: AOJ; JUMP(ea); break; /* AOJA */ -case 0345: AOJ; if (TGE (AC(ac))) JUMP (ea); break;/* AOJGE */ -case 0346: AOJ; if (TN (AC(ac))) JUMP (ea); break; /* AOJN */ -case 0347: AOJ; if (TG (AC(ac))) JUMP (ea); break; /* AOJG */ -case 0350: AOS; break; /* AOS */ -case 0351: AOS; if (TL (mb)) INCPC; break; /* AOSL */ -case 0352: AOS; if (TE (mb)) INCPC; break; /* AOSE */ -case 0353: AOS; if (TLE (mb)) INCPC; break; /* AOSLE */ -case 0354: AOS; INCPC; break; /* AOSA */ -case 0355: AOS; if (TGE (mb)) INCPC; break; /* AOSGE */ -case 0356: AOS; if (TN (mb)) INCPC; break; /* AOSN */ -case 0357: AOS; if (TG (mb)) INCPC; break; /* AOSG */ -case 0360: SOJ; break; /* SOJ */ -case 0361: SOJ; if (TL (AC(ac))) JUMP (ea); break; /* SOJL */ -case 0362: SOJ; if (TE (AC(ac))) JUMP (ea); break; /* SOJE */ -case 0363: SOJ; if (TLE (AC(ac))) JUMP (ea); break;/* SOJLE */ -case 0364: SOJ; JUMP(ea); break; /* SOJA */ -case 0365: SOJ; if (TGE (AC(ac))) JUMP (ea); break;/* SOJGE */ -case 0366: SOJ; if (TN (AC(ac))) JUMP (ea); break; /* SOJN */ -case 0367: SOJ; if (TG (AC(ac))) JUMP (ea); break; /* SOJG */ -case 0370: SOS; break; /* SOS */ -case 0371: SOS; if (TL (mb)) INCPC; break; /* SOSL */ -case 0372: SOS; if (TE (mb)) INCPC; break; /* SOSE */ -case 0373: SOS; if (TLE (mb)) INCPC; break; /* SOSLE */ -case 0374: SOS; INCPC; break; /* SOSA */ -case 0375: SOS; if (TGE (mb)) INCPC; break; /* SOSGE */ -case 0376: SOS; if (TN (mb)) INCPC; break; /* SOSN */ -case 0377: SOS; if (TG (mb)) INCPC; break; /* SOSG */ - -/* Boolean instructions (0400 - 0477) - checked against KS10 ucode - - Note that for boolean B, the initial read checks writeability of - the memory operand; hence, it is safe to modify the AC. -*/ - -case 0400: AC(ac) = 0; break; /* SETZ */ -case 0401: AC(ac) = 0; break; /* SETZI */ -case 0402: mb = 0; WR; break; /* SETZM */ -case 0403: mb = 0; WR; AC(ac) = 0; break; /* SETZB */ -case 0404: RD; AC(ac) = AND (mb); break; /* AND */ -case 0405: AC(ac) = AND (IM); break; /* ANDI */ -case 0406: RM; mb = AND (mb); WR; break; /* ANDM */ -case 0407: RM; AC(ac) = AND (mb); WRAC; break; /* ANDB */ -case 0410: RD; AC(ac) = ANDCA (mb); break; /* ANDCA */ -case 0411: AC(ac) = ANDCA (IM); break; /* ANDCAI */ -case 0412: RM; mb = ANDCA (mb); WR; break; /* ANDCAM */ -case 0413: RM; AC(ac) = ANDCA (mb); WRAC; break; /* ANDCAB */ -case 0414: RDAC; break; /* SETM */ -case 0415: AC(ac) = ea; break; /* SETMI */ -case 0416: RM; WR; break; /* SETMM */ -case 0417: RMAC; WRAC; break; /* SETMB */ -case 0420: RD; AC(ac) = ANDCM (mb); break; /* ANDCM */ -case 0421: AC(ac) = ANDCM (IM); break; /* ANDCMI */ -case 0422: RM; mb = ANDCM (mb); WR; break; /* ANDCMM */ -case 0423: RM; AC(ac) = ANDCM (mb); WRAC; break; /* ANDCMB */ -case 0424: break; /* SETA */ -case 0425: break; /* SETAI */ -case 0426: WRAC; break; /* SETAM */ -case 0427: WRAC; break; /* SETAB */ -case 0430: RD; AC(ac) = XOR (mb); break; /* XOR */ -case 0431: AC(ac) = XOR (IM); break; /* XORI */ -case 0432: RM; mb = XOR (mb); WR; break; /* XORM */ -case 0433: RM; AC(ac) = XOR (mb); WRAC; break; /* XORB */ -case 0434: RD; AC(ac) = IOR (mb); break; /* IOR */ -case 0435: AC(ac) = IOR (IM); break; /* IORI */ -case 0436: RM; mb = IOR (mb); WR; break; /* IORM */ -case 0437: RM; AC(ac) = IOR (mb); WRAC; break; /* IORB */ -case 0440: RD; AC(ac) = ANDCB (mb); break; /* ANDCB */ -case 0441: AC(ac) = ANDCB (IM); break; /* ANDCBI */ -case 0442: RM; mb = ANDCB (mb); WR; break; /* ANDCBM */ -case 0443: RM; AC(ac) = ANDCB (mb); WRAC; break; /* ANDCBB */ -case 0444: RD; AC(ac) = EQV (mb); break; /* EQV */ -case 0445: AC(ac) = EQV (IM); break; /* EQVI */ -case 0446: RM; mb = EQV (mb); WR; break; /* EQVM */ -case 0447: RM; AC(ac) = EQV (mb); WRAC; break; /* EQVB */ -case 0450: RD; AC(ac) = SETCA (mb); break; /* SETCA */ -case 0451: AC(ac) = SETCA (IM); break; /* SETCAI */ -case 0452: RM; mb = SETCA (mb); WR; break; /* SETCAM */ -case 0453: RM; AC(ac) = SETCA (mb); WRAC; break; /* SETCAB */ -case 0454: RD; AC(ac) = ORCA (mb); break; /* ORCA */ -case 0455: AC(ac) = ORCA (IM); break; /* ORCAI */ -case 0456: RM; mb = ORCA (mb); WR; break; /* ORCAM */ -case 0457: RM; AC(ac) = ORCA (mb); WRAC; break; /* ORCAB */ -case 0460: RD; AC(ac) = SETCM (mb); break; /* SETCM */ -case 0461: AC(ac) = SETCM (IM); break; /* SETCMI */ -case 0462: RM; mb = SETCM (mb); WR; break; /* SETCMM */ -case 0463: RM; AC(ac) = SETCM (mb); WRAC; break; /* SETCMB */ -case 0464: RD; AC(ac) = ORCM (mb); break; /* ORCM */ -case 0465: AC(ac) = ORCM (IM); break; /* ORCMI */ -case 0466: RM; mb = ORCM (mb); WR; break; /* ORCMM */ -case 0467: RM; AC(ac) = ORCM (mb); WRAC; break; /* ORCMB */ -case 0470: RD; AC(ac) = ORCB (mb); break; /* ORCB */ -case 0471: AC(ac) = ORCB (IM); break; /* ORCBI */ -case 0472: RM; mb = ORCB (mb); WR; break; /* ORCBM */ -case 0473: RM; AC(ac) = ORCB (mb); WRAC; break; /* ORCBB */ -case 0474: AC(ac) = ONES; break; /* SETO */ -case 0475: AC(ac) = ONES; break; /* SETOI */ -case 0476: mb = ONES; WR; break; /* SETOM */ -case 0477: mb = ONES; WR; AC(ac) = ONES; break; /* SETOB */ - -/* Halfword instructions (0500 - 0577) - checked against KS10 ucode */ - -case 0500: RD; AC(ac) = LL (mb, AC(ac)); break; /* HLL */ -case 0501: AC(ac) = LL (IM, AC(ac)); break; /* HLLI */ -case 0502: RM; mb = LL (AC(ac), mb); WR; break; /* HLLM */ -case 0503: RM; mb = LL (mb, mb); WR; LAC; break; /* HLLS */ -case 0504: RD; AC(ac) = RL (mb, AC(ac)); break; /* HRL */ -case 0505: AC(ac) = RL (IM, AC(ac)); break; /* HRLI */ -case 0506: RM; mb = RL (AC(ac), mb); WR; break; /* HRLM */ -case 0507: RM; mb = RL (mb, mb); WR; LAC; break; /* HRLS */ -case 0510: RD; AC(ac) = LLZ (mb); break; /* HLLZ */ -case 0511: AC(ac) = LLZ (IM); break; /* HLLZI */ -case 0512: mb = LLZ (AC(ac)); WR; break; /* HLLZM */ -case 0513: RM; mb = LLZ (mb); WR; LAC; break; /* HLLZS */ -case 0514: RD; AC(ac) = RLZ (mb); break; /* HRLZ */ -case 0515: AC(ac) = RLZ (IM); break; /* HRLZI */ -case 0516: mb = RLZ (AC(ac)); WR; break; /* HRLZM */ -case 0517: RM; mb = RLZ (mb); WR; LAC; break; /* HRLZS */ -case 0520: RD; AC(ac) = LLO (mb); break; /* HLLO */ -case 0521: AC(ac) = LLO (IM); break; /* HLLOI */ -case 0522: mb = LLO (AC(ac)); WR; break; /* HLLOM */ -case 0523: RM; mb = LLO (mb); WR; LAC; break; /* HLLOS */ -case 0524: RD; AC(ac) = RLO (mb); break; /* HRLO */ -case 0525: AC(ac) = RLO (IM); break; /* HRLOI */ -case 0526: mb = RLO (AC(ac)); WR; break; /* HRLOM */ -case 0527: RM; mb = RLO (mb); WR; LAC; break; /* HRLOS */ -case 0530: RD; AC(ac) = LLE (mb); break; /* HLLE */ -case 0531: AC(ac) = LLE (IM); break; /* HLLEI */ -case 0532: mb = LLE (AC(ac)); WR; break; /* HLLEM */ -case 0533: RM; mb = LLE (mb); WR; LAC; break; /* HLLES */ -case 0534: RD; AC(ac) = RLE (mb); break; /* HRLE */ -case 0535: AC(ac) = RLE (IM); break; /* HRLEI */ -case 0536: mb = RLE (AC(ac)); WR; break; /* HRLEM */ -case 0537: RM; mb = RLE (mb); WR; LAC; break; /* HRLES */ -case 0540: RD; AC(ac) = RR (mb, AC(ac)); break; /* HRR */ -case 0541: AC(ac) = RR (IM, AC(ac)); break; /* HRRI */ -case 0542: RM; mb = RR (AC(ac), mb); WR; break; /* HRRM */ -case 0543: RM; mb = RR (mb, mb); WR; LAC; break; /* HRRS */ -case 0544: RD; AC(ac) = LR (mb, AC(ac)); break; /* HLR */ -case 0545: AC(ac) = LR (IM, AC(ac)); break; /* HLRI */ -case 0546: RM; mb = LR (AC(ac), mb); WR; break; /* HLRM */ -case 0547: RM; mb = LR (mb, mb); WR; LAC; break; /* HLRS */ -case 0550: RD; AC(ac) = RRZ (mb); break; /* HRRZ */ -case 0551: AC(ac) = RRZ (IM); break; /* HRRZI */ -case 0552: mb = RRZ (AC(ac)); WR; break; /* HRRZM */ -case 0553: RM; mb = RRZ(mb); WR; LAC; break; /* HRRZS */ -case 0554: RD; AC(ac) = LRZ (mb); break; /* HLRZ */ -case 0555: AC(ac) = LRZ (IM); break; /* HLRZI */ -case 0556: mb = LRZ (AC(ac)); WR; break; /* HLRZM */ -case 0557: RM; mb = LRZ (mb); WR; LAC; break; /* HLRZS */ -case 0560: RD; AC(ac) = RRO (mb); break; /* HRRO */ -case 0561: AC(ac) = RRO (IM); break; /* HRROI */ -case 0562: mb = RRO (AC(ac)); WR; break; /* HRROM */ -case 0563: RM; mb = RRO (mb); WR; LAC; break; /* HRROS */ -case 0564: RD; AC(ac) = LRO (mb); break; /* HLRO */ -case 0565: AC(ac) = LRO (IM); break; /* HLROI */ -case 0566: mb = LRO (AC(ac)); WR; break; /* HLROM */ -case 0567: RM; mb = LRO (mb); WR; LAC; break; /* HLROS */ -case 0570: RD; AC(ac) = RRE (mb); break; /* HRRE */ -case 0571: AC(ac) = RRE (IM); break; /* HRREI */ -case 0572: mb = RRE (AC(ac)); WR; break; /* HRREM */ -case 0573: RM; mb = RRE (mb); WR; LAC; break; /* HRRES */ -case 0574: RD; AC(ac) = LRE (mb); break; /* HLRE */ -case 0575: AC(ac) = LRE (IM); break; /* HLREI */ -case 0576: mb = LRE (AC(ac)); WR; break; /* HLREM */ -case 0577: RM; mb = LRE (mb); WR; LAC; break; /* HLRES */ - -/* Test instructions (0600 - 0677) - checked against KS10 ucode - In the KS10 ucode, TDN and TSN do not fetch an operand; the Processor - Reference Manual describes them as NOPs that reference memory. -*/ - -case 0600: break; /* TRN */ -case 0601: break; /* TLN */ -case 0602: TR_; T__E; break; /* TRNE */ -case 0603: TL_; T__E; break; /* TLNE */ -case 0604: T__A; break; /* TRNA */ -case 0605: T__A; break; /* TLNA */ -case 0606: TR_; T__N; break; /* TRNN */ -case 0607: TL_; T__N; break; /* TLNN */ -case 0610: TD_; break; /* TDN */ -case 0611: TS_; break; /* TSN */ -case 0612: TD_; T__E; break; /* TDNE */ -case 0613: TS_; T__E; break; /* TSNE */ -case 0614: TD_; T__A; break; /* TDNA */ -case 0615: TS_; T__A; break; /* TSNA */ -case 0616: TD_; T__N; break; /* TDNN */ -case 0617: TS_; T__N; break; /* TSNN */ -case 0620: TR_; T_Z; break; /* TRZ */ -case 0621: TL_; T_Z; break; /* TLZ */ -case 0622: TR_; T__E; T_Z; break; /* TRZE */ -case 0623: TL_; T__E; T_Z; break; /* TLZE */ -case 0624: TR_; T__A; T_Z; break; /* TRZA */ -case 0625: TL_; T__A; T_Z; break; /* TLZA */ -case 0626: TR_; T__N; T_Z; break; /* TRZN */ -case 0627: TL_; T__N; T_Z; break; /* TLZN */ -case 0630: TD_; T_Z; break; /* TDZ */ -case 0631: TS_; T_Z; break; /* TSZ */ -case 0632: TD_; T__E; T_Z; break; /* TDZE */ -case 0633: TS_; T__E; T_Z; break; /* TSZE */ -case 0634: TD_; T__A; T_Z; break; /* TDZA */ -case 0635: TS_; T__A; T_Z; break; /* TSZA */ -case 0636: TD_; T__N; T_Z; break; /* TDZN */ -case 0637: TS_; T__N; T_Z; break; /* TSZN */ -case 0640: TR_; T_C; break; /* TRC */ -case 0641: TL_; T_C; break; /* TLC */ -case 0642: TR_; T__E; T_C; break; /* TRCE */ -case 0643: TL_; T__E; T_C; break; /* TLCE */ -case 0644: TR_; T__A; T_C; break; /* TRCA */ -case 0645: TL_; T__A; T_C; break; /* TLCA */ -case 0646: TR_; T__N; T_C; break; /* TRCN */ -case 0647: TL_; T__N; T_C; break; /* TLCN */ -case 0650: TD_; T_C; break; /* TDC */ -case 0651: TS_; T_C; break; /* TSC */ -case 0652: TD_; T__E; T_C; break; /* TDCE */ -case 0653: TS_; T__E; T_C; break; /* TSCE */ -case 0654: TD_; T__A; T_C; break; /* TDCA */ -case 0655: TS_; T__A; T_C; break; /* TSCA */ -case 0656: TD_; T__N; T_C; break; /* TDCN */ -case 0657: TS_; T__N; T_C; break; /* TSCN */ -case 0660: TR_; T_O; break; /* TRO */ -case 0661: TL_; T_O; break; /* TLO */ -case 0662: TR_; T__E; T_O; break; /* TROE */ -case 0663: TL_; T__E; T_O; break; /* TLOE */ -case 0664: TR_; T__A; T_O; break; /* TROA */ -case 0665: TL_; T__A; T_O; break; /* TLOA */ -case 0666: TR_; T__N; T_O; break; /* TRON */ -case 0667: TL_; T__N; T_O; break; /* TLON */ -case 0670: TD_; T_O; break; /* TDO */ -case 0671: TS_; T_O; break; /* TSO */ -case 0672: TD_; T__E; T_O; break; /* TDOE */ -case 0673: TS_; T__E; T_O; break; /* TSOE */ -case 0674: TD_; T__A; T_O; break; /* TDOA */ -case 0675: TS_; T__A; T_O; break; /* TSOA */ -case 0676: TD_; T__N; T_O; break; /* TDON */ -case 0677: TS_; T__N; T_O; break; /* TSON */ - -/* I/O instructions (0700 - 0777) - - Only the defined I/O instructions have explicit case labels; - the rest default to unimplemented (monitor UUO). Note that - 710-715 and 720-725 have different definitions under ITS and - use normal effective addresses instead of the special address - calculation required by TOPS-10 and TOPS-20. -*/ - -case 0700: IO7 (io700i, io700d); break; /* I/O 0 */ -case 0701: IO7 (io701i, io701d); break; /* I/O 1 */ -case 0702: IO7 (io702i, io702d); break; /* I/O 2 */ -case 0704: IOC; AC(ac) = Read (ea, OPND_PXCT); break; /* UMOVE */ -case 0705: IOC; Write (ea, AC(ac), OPND_PXCT); break; /* UMOVEM */ -case 0710: IOA; if (io710 (ac, ea)) INCPC; break; /* TIOE, IORDI */ -case 0711: IOA; if (io711 (ac, ea)) INCPC; break; /* TION, IORDQ */ -case 0712: IOAM; AC(ac) = io712 (ea); break; /* RDIO, IORD */ -case 0713: IOAM; io713 (AC(ac), ea); break; /* WRIO, IOWR */ -case 0714: IOA; io714 (AC(ac), ea); break; /* BSIO, IOWRI */ -case 0715: IOA; io715 (AC(ac), ea); break; /* BCIO, IOWRQ */ -case 0716: IOC; bltu (ac, ea, pflgs, 0); break; /* BLTBU */ -case 0717: IOC; bltu (ac, ea, pflgs, 1); break; /* BLTUB */ -case 0720: IOA; if (io720 (ac, ea)) INCPC; break; /* TIOEB, IORDBI */ -case 0721: IOA; if (io721 (ac, ea)) INCPC; break; /* TIONB, IORDBQ */ -case 0722: IOAM; AC(ac) = io722 (ea); break; /* RDIOB, IORDB */ -case 0723: IOAM; io723 (AC(ac), ea); break; /* WRIOB, IOWRB */ -case 0724: IOA; io724 (AC(ac), ea); break; /* BSIOB, IOWRBI */ -case 0725: IOA; io725 (AC(ac), ea); break; /* BCIOB, IOWRBQ */ - -/* If undefined, monitor UUO - checked against KS10 ucode - The KS10 implements a much more limited version of MUUO flag handling. - In the KS10, the trap ucode checks for opcodes 000-077. If the opcode - is in that range, the trap flags are not cleared. Instead, the MUUO - microcode stores the flags with traps cleared, and uses the trap flags - to determine how to vector. Thus, MUUO's >= 100 will vector incorrectly. -*/ - -default: -MUUO: its_2pr = 0; /* clear trap */ - if (T20) { /* TOPS20? */ - int32 tf = (op << (INST_V_OP - 18)) | (ac << (INST_V_AC - 18)); - WriteP (upta + UPT_MUUO, XWD ( /* store flags,,op+ac */ - flags & ~(F_T2 | F_T1), tf)); /* traps clear */ - WriteP (upta + UPT_MUPC, PC); /* store PC */ - WriteP (upta + UPT_T20_UEA, ea); /* store eff addr */ - WriteP (upta + UPT_T20_CTX, UBRWORD); } /* store context */ - else { /* TOPS10/ITS */ - WriteP (upta + UPT_MUUO, UUOWORD); /* store instr word */ - WriteP (upta + UPT_MUPC, XWD ( /* store flags,,PC */ - flags & ~(F_T2 | F_T1), PC)); /* traps clear */ - WriteP (upta + UPT_T10_CTX, UBRWORD); } /* store context */ - ea = upta + (TSTF (F_USR)? UPT_UNPC: UPT_ENPC) + - (pager_tc? UPT_NPCT: 0); /* calculate vector */ - mb = ReadP (ea); /* new flags, PC */ - JUMP (mb); /* set new PC */ - if (TSTF (F_USR)) mb = mb | XWD (F_UIO, 0); /* set PCU */ - set_newflags (mb, FALSE); /* set new flags */ - break; - -/* JRST - checked against KS10 ucode - Differences from the KS10: the KS10 - - (JRSTF, JEN) refetches the base instruction from PC - 1 - - (XJEN) dismisses interrupt before reading the new flags and PC - - (XPCW) writes the old flags and PC before reading the new - ITS microcode includes extended JRST's, although they are not used -*/ - -case 0254: /* JRST */ - i = jrst_tab[ac]; /* get subop flags */ - if ((i == 0) || ((i == JRST_E) && TSTF (F_USR)) || - ((i == JRST_UIO) && TSTF (F_USR) && !TSTF (F_UIO))) - goto MUUO; /* not legal */ - switch (ac) { /* case on subopcode */ - case 000: /* JRST 0 = jump */ - case 001: /* JRST 1 = portal */ - JUMP (ea); - break; - case 002: /* JRST 2 = JRSTF */ - mb = calc_jrstfea (inst, pflgs); /* recalc addr w flgs */ - JUMP (ea); /* set new PC */ - set_newflags (mb, TRUE); /* set new flags */ - break; - case 004: /* JRST 4 = halt */ - JUMP (ea); /* old_PC = halt + 1 */ - pager_PC = PC; /* force right PC */ - ABORT (STOP_HALT); /* known to be exec */ - break; - case 005: /* JRST 5 = XJRSTF */ - RD2; /* read doubleword */ - JUMP (rs[1]); /* set new PC */ - set_newflags (rs[0], TRUE); /* set new flags */ - break; - case 006: /* JRST 6 = XJEN */ - RD2; /* read doubleword */ - pi_dismiss (); /* page ok, dismiss */ - JUMP (rs[1]); /* set new PC */ - set_newflags (rs[0], FALSE); /* known to be exec */ - break; - case 007: /* JRST 7 = XPCW */ - ea = ADDA (i = ea, 2); /* new flags, PC */ - RD2; /* read, test page fail */ - ReadM (INCA (i), MM_OPND); /* test PC write */ - Write (i, XWD (flags, 0), MM_OPND); /* write flags */ - Write (INCA (i), PC, MM_OPND); /* write PC */ - JUMP (rs[1]); /* set new PC */ - set_newflags (rs[0], FALSE); /* known to be exec */ - break; - case 010: /* JRST 10 = dismiss */ - pi_dismiss (); /* dismiss int */ - JUMP (ea); /* set new PC */ - break; - case 012: /* JRST 12 = JEN */ - mb = calc_jrstfea (inst, pflgs); /* recalc addr w flgs */ - JUMP (ea); /* set new PC */ - set_newflags (mb, TRUE); /* set new flags */ - pi_dismiss (); /* dismiss int */ - break; - case 014: /* JRST 14 = SFM */ - Write (ea, XWD (flags, 0), MM_OPND); - break; - case 015: /* JRST 15 = XJRST */ - if (!T20) goto MUUO; /* only in TOPS20 */ - JUMP (Read (ea, MM_OPND)); /* jump to M[ea] */ - break; } /* end case subop */ - break; } /* end case op */ - -if (its_2pr) { /* 1-proc trap? */ - its_1pr = its_2pr = 0; /* clear trap */ - if (ITS) { /* better be ITS */ - WriteP (upta + UPT_1PO, FLPC); /* wr old flgs, PC */ - mb = ReadP (upta + UPT_1PN); /* rd new flgs, PC */ - JUMP (mb); /* set PC */ - set_newflags (mb, TRUE); } /* set new flags */ - } /* end if 2-proc */ -} /* end for */ - -/* Should never get here */ - -ABORT (STOP_UNKNOWN); -} - -/* Single word integer routines */ - -/* Integer add - - Truth table for integer add - - case a b r flags - 1 + + + none - 2 + + - AOV + C1 - 3 + - + C0 + C1 - 4 + - - - - 5 - + + C0 + C1 - 6 - + - - - 7 - - + AOV + C0 - 8 - - - C0 + C1 -*/ - -d10 add (d10 a, d10 b) -{ -d10 r; - -r = (a + b) & DMASK; -if (TSTS (a & b)) { /* cases 7,8 */ - if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */ - else SETF (F_C0 | F_AOV | F_T1); /* case 7 */ - return r; } -if (!TSTS (a | b)) { /* cases 1,2 */ - if (TSTS (r)) SETF (F_C1 | F_AOV | F_T1); /* case 2 */ - return r; } /* case 1 */ -if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */ -return r; -} - -/* Integer subtract - actually ac + ~op + 1 */ - -d10 sub (d10 a, d10 b) -{ -d10 r; - -r = (a - b) & DMASK; -if (TSTS (a & ~b)) { /* cases 7,8 */ - if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */ - else SETF (F_C0 | F_AOV | F_T1); /* case 7 */ - return r; } -if (!TSTS (a | ~b)) { /* cases 1,2 */ - if (TSTS (r)) SETF (F_C1 | F_AOV | F_T1); /* case 2 */ - return r; } /* case 1 */ -if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */ -return r; -} - - -/* Logical shift */ - -d10 lsh (d10 val, a10 ea) -{ -int32 sc = LIT8 (ea); - -if (sc > 35) return 0; -if (ea & RSIGN) return (val >> sc); -return ((val << sc) & DMASK); -} - -/* Rotate */ - -d10 rot (d10 val, a10 ea) -{ -int32 sc = LIT8 (ea) % 36; - -if (sc == 0) return val; -if (ea & RSIGN) sc = 36 - sc; -return (((val << sc) | (val >> (36 - sc))) & DMASK); -} - -/* Double word integer instructions */ - -/* Double add - see case table for single add */ - -void dadd (int32 ac, d10 *rs) -{ -d10 r; -int32 p1 = ADDAC (ac, 1); - -AC(p1) = CLRS (AC(p1)) + CLRS (rs[1]); /* add lo */ -r = (AC(ac) + rs[0] + (TSTS (AC(p1))? 1: 0)) & DMASK; /* add hi+cry */ -if (TSTS (AC(ac) & rs[0])) { /* cases 7,8 */ - if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */ - else SETF (F_C0 | F_AOV | F_T1); } /* case 7 */ -else if (!TSTS (AC(ac) | rs[0])) { /* cases 1,2 */ - if (TSTS (r)) SETF (F_C1 | F_AOV | F_T1); } /* case 2 */ -else if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */ -AC(ac) = r; -AC(p1) = TSTS (r)? SETS (AC(p1)): CLRS (AC(p1)); -return; -} - -/* Double subtract - see comments for single subtract */ - -void dsub (int32 ac, d10 *rs) -{ -d10 r; -int32 p1 = ADDAC (ac, 1); - -AC(p1) = CLRS (AC(p1)) - CLRS (rs[1]); /* sub lo */ -r = (AC(ac) - rs[0] - (TSTS (AC(p1))? 1: 0)) & DMASK; /* sub hi,borrow */ -if (TSTS (AC(ac) & ~rs[0])) { /* cases 7,8 */ - if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */ - else SETF (F_C0 | F_AOV | F_T1); } /* case 7 */ -else if (!TSTS (AC(ac) | ~rs[0])) { /* cases 1,2 */ - if (TSTS (r)) SETF (F_C1 | F_AOV | F_T1); } /* case 2 */ -else if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */ -AC(ac) = r; -AC(p1) = (TSTS (r)? SETS (AC(p1)): CLRS (AC(p1))) & DMASK; -return; -} - - -/* Logical shift combined */ - -void lshc (int32 ac, a10 ea) -{ -int32 p1 = ADDAC (ac, 1); -int32 sc = LIT8 (ea); - -if (sc > 71) AC(ac) = AC(p1) = 0; -else if (ea & RSIGN) { - if (sc >= 36) { - AC(p1) = AC(ac) >> (sc - 36); - AC(ac) = 0; } - else { - AC(p1) = ((AC(p1) >> sc) | (AC(ac) << (36 - sc))) & DMASK; - AC(ac) = AC(ac) >> sc; } } -else { if (sc >= 36) { - AC(ac) = (AC(p1) << (sc - 36)) & DMASK; - AC(p1) = 0; } - else { - AC(ac) = ((AC(ac) << sc) | (AC(p1) >> (36 - sc))) & DMASK; - AC(p1) = (AC(p1) << sc) & DMASK; } } -return; -} - -/* Rotate combined */ - -void rotc (int32 ac, a10 ea) -{ -int32 p1 = ADDAC (ac, 1); -int32 sc = LIT8 (ea) % 72; -d10 t = AC(ac); - -if (sc == 0) return; -if (ea & RSIGN) sc = 72 - sc; -if (sc >= 36) { - AC(ac) = ((AC(p1) << (sc - 36)) | (t >> (72 - sc))) & DMASK; - AC(p1) = ((t << (sc - 36)) | (AC(p1) >> (72 - sc))) & DMASK; } -else { AC(ac) = ((t << sc) | (AC(p1) >> (36 - sc))) & DMASK; - AC(p1) = ((AC(p1) << sc) | (t >> (36 - sc))) & DMASK; } -return; -} - -/* Arithmetic shifts */ - -d10 ash (d10 val, a10 ea) -{ -int32 sc = LIT8 (ea); -d10 sign = TSTS (val); -d10 fill = sign? ONES: 0; -d10 so; - -if (sc == 0) return val; -if (sc > 35) sc = 35; /* cap sc at 35 */ -if (ea & RSIGN) - return (((val >> sc) | (fill << (36 - sc))) & DMASK); -so = val >> (35 - sc); /* bits lost left + sign */ -if (so != (sign? bytemask[sc + 1]: 0)) SETF (F_AOV | F_T1); -return (sign | ((val << sc) & MMASK)); -} - -void ashc (int32 ac, a10 ea) -{ -int32 sc = LIT8 (ea); -int32 p1 = ADDAC (ac, 1); -d10 sign = TSTS (AC(ac)); -d10 fill = sign? ONES: 0; -d10 so; - -if (sc == 0) return; -if (sc > 70) sc = 70; /* cap sc at 70 */ -AC(ac) = CLRS (AC(ac)); /* clear signs */ -AC(p1) = CLRS (AC(p1)); -if (ea & RSIGN) { - if (sc >= 35) { /* right 36..70 */ - AC(p1) = ((AC(ac) >> (sc - 35)) | (fill << (70 - sc))) & DMASK; - AC(ac) = fill; } - else { - AC(p1) = sign | /* right 1..35 */ - (((AC(p1) >> sc) | (AC(ac) << (35 - sc))) & MMASK); - AC(ac) = ((AC(ac) >> sc) | (fill << (35 - sc))) & DMASK; } } -else { if (sc >= 35) { /* left 36..70 */ - so = AC(p1) >> (70 - sc); /* bits lost left */ - if ((AC(ac) != (sign? MMASK: 0)) || - (so != (sign? bytemask[sc - 35]: 0))) SETF (F_AOV | F_T1); - AC(ac) = sign | ((AC(p1) << (sc - 35)) & MMASK); - AC(p1) = sign; } - else { - so = AC(ac) >> (35 - sc); /* bits lost left */ - if (so != (sign? bytemask[sc]: 0)) SETF (F_AOV | F_T1); - AC(ac) = sign | - (((AC(ac) << sc) | (AC(p1) >> (35 - sc))) & MMASK); - AC(p1) = sign | ((AC(p1) << sc) & MMASK); } } -return; -} - -/* Effective address routines */ - -/* Calculate effective address - used by byte instructions, extended - instructions, and interrupts to get a different mapping context from - the main loop. prv is either EABP_PXCT or MM_CUR. -*/ - -a10 calc_ea (d10 inst, int32 prv) -{ -int32 i, ea, xr; -d10 indrct; - -for (indrct = inst, i = 0; i < ind_max; i++) { - ea = GET_ADDR (indrct); - xr = GET_XR (indrct); - if (xr) ea = (ea + ((a10) XR (xr, prv))) & AMASK; - if (TST_IND (indrct)) indrct = Read (ea, prv); - else break; } -if (i >= ind_max) ABORT (STOP_IND); -return ea; -} - -/* Calculate I/O effective address. Cases: - - No index or indirect, return addr from instruction - - Index only, index >= 0, return 36b sum of addr + index - - Index only, index <= 0, return 18b sum of addr + index - - Indirect, calculate 18b sum of addr + index, return - entire word fetch (single level) -*/ - -a10 calc_ioea (d10 inst, int32 pflgs) -{ -int32 xr; -a10 ea; - -xr = GET_XR (inst); -ea = GET_ADDR (inst); -if (TST_IND (inst)) { /* indirect? */ - if (xr) ea = (ea + ((a10) XR (xr, MM_EA))) & AMASK; - ea = (a10) Read (ea, MM_EA); } -else if (xr) { /* direct + idx? */ - ea = ea + ((a10) XR (xr, MM_EA)); - if (TSTS (XR (xr, MM_EA))) ea = ea & AMASK; } -return ea; -} - -/* Calculate JRSTF effective address. This routine preserves - the left half of the effective address, to be the new flags. -*/ - -d10 calc_jrstfea (d10 inst, int32 pflgs) -{ -int32 i, xr; -d10 mb; - -for (i = 0; i < ind_max; i++) { - mb = inst; - xr = GET_XR (inst); - if (xr) mb = (mb & AMASK) + XR (xr, MM_EA); - if (TST_IND (inst)) inst = Read (((a10) mb) & AMASK, MM_EA); - else break; } -if (i >= ind_max) ABORT (STOP_IND); -return (mb & DMASK); -} - -/* Byte pointer routines */ - -/* Increment byte pointer - checked against KS10 ucode */ - -void ibp (a10 ea, int32 pflgs) -{ -int32 p, s; -d10 bp; - -bp = ReadM (ea, MM_OPND); /* get byte ptr */ -p = GET_P (bp); /* get P and S */ -s = GET_S (bp); -p = p - s; /* adv P */ -if (p < 0) { /* end of word? */ - bp = (bp & LMASK) | (INCR (bp)); /* incr addr */ - p = (36 - s) & 077; } /* reset P */ -bp = PUT_P (bp, p); /* store new P */ -Write (ea, bp, MM_OPND); /* store byte ptr */ -return; -} - -/* Load byte */ - -d10 ldb (a10 ea, int32 pflgs) -{ -a10 ba; -int32 p, s; -d10 bp, wd; - -bp = Read (ea, MM_OPND); /* get byte ptr */ -p = GET_P (bp); /* get P and S */ -s = GET_S (bp); -ba = calc_ea (bp, MM_EABP); /* get addr of byte */ -wd = Read (ba, MM_BSTK); /* read word */ -wd = (wd >> p); /* align byte */ -wd = wd & bytemask[s]; /* mask to size */ -return wd; -} - -/* Deposit byte - must use read and write to get page fail correct */ - -void dpb (d10 val, a10 ea, int32 pflgs) -{ -a10 ba; -int32 p, s; -d10 bp, wd, mask; - -bp = Read (ea, MM_OPND); /* get byte ptr */ -p = GET_P (bp); /* get P and S */ -s = GET_S (bp); -ba = calc_ea (bp, MM_EABP); /* get addr of byte */ -wd = Read (ba, MM_BSTK); /* read word */ -mask = bytemask[s] << p; /* shift mask, val */ -val = val << p; -wd = (wd & ~mask) | (val & mask); /* insert byte */ -Write (ba, wd & DMASK, MM_BSTK); -return; -} - -/* Adjust byte pointer - checked against KS10 ucode - The KS10 divide checks if the bytes per word = 0, which is a simpler - formulation of the processor reference manual check. -*/ - -void adjbp (int32 ac, a10 ea, int32 pflgs) -{ -int32 p, s; -d10 bp, newby, left, byadj, bywrd, val, wdadj; - -val = AC(ac); /* get adjustment */ -bp = Read (ea, MM_OPND); /* get byte pointer */ -p = GET_P (bp); /* get p */ -s = GET_S (bp); /* get s */ -if (s) { - left = (36 - p) / s; /* bytes to left of p */ - bywrd = left + (p / s); /* bytes per word */ - if (bywrd == 0) { /* zero bytes? */ - SETF (F_AOV | F_T1 | F_DCK); /* set flags */ - return; } /* abort operation */ - newby = left + SXT (val); /* adjusted byte # */ - wdadj = newby / bywrd; /* word adjustment */ - byadj = (newby >= 0)? newby % bywrd: -((-newby) % bywrd); - if (byadj <= 0) { - byadj = byadj + bywrd; /* make adj positive */ - wdadj = wdadj - 1; } - p = (36 - ((int32) byadj) * s) - ((36 - p) % s); /* new p */ - bp = (PUT_P (bp, p) & LMASK) | ((bp + wdadj) & RMASK); } -AC(ac) = bp; -return; -} - -/* Block transfer - checked against KS10 ucode - The KS10 uses instruction specific recovery code in page fail - to set the AC properly for restart. Lacking this mechanism, - the simulator must test references in advance. - The clocking test guarantees forward progress under single step. -*/ - -void blt (int32 ac, a10 ea, int32 pflgs) -{ -a10 srca = (a10) LRZ (AC(ac)); -a10 dsta = (a10) RRZ (AC(ac)); -a10 lnt = ea - dsta + 1; -d10 srcv; -int32 flg, t; - -AC(ac) = XWD (srca + lnt, dsta + lnt); -for (flg = 0; dsta <= ea; flg++) { /* loop */ - if (flg && (t = test_int ())) { /* timer event? */ - AC(ac) = XWD (srca, dsta); /* AC for intr */ - ABORT (t); } - if (AccViol (srca & AMASK, MM_BSTK, PTF_RD)) { /* src access viol? */ - AC(ac) = XWD (srca, dsta); /* AC for page fail */ - Read (srca & AMASK, MM_BSTK); } /* force trap */ - if (AccViol (dsta & AMASK, MM_OPND, PTF_WR)) { /* dst access viol? */ - AC(ac) = XWD (srca, dsta); /* AC for page fail */ - ReadM (dsta & AMASK, MM_OPND); } /* force trap */ - srcv = Read (srca & AMASK, MM_BSTK); /* read */ - Write (dsta & AMASK, srcv, MM_OPND); /* write */ - srca = srca + 1; /* incr addr */ - dsta = dsta + 1; } -return; -} - -/* I/O block transfers - byte to Unibus (0) and Unibus to byte (1) */ - -#define BYTE1 0776000000000 -#define BYTE2 0001774000000 -#define BYTE3 0000003770000 -#define BYTE4 0000000007760 -/* unused 0000000000017 */ - -void bltu (int32 ac, a10 ea, int32 pflgs, int dir) -{ -a10 srca = (a10) LRZ (AC(ac)); -a10 dsta = (a10) RRZ (AC(ac)); -a10 lnt = ea - dsta + 1; -d10 srcv, dstv; -int32 flg, t; - -AC(ac) = XWD (srca + lnt, dsta + lnt); -for (flg = 0; dsta <= ea; flg++) { /* loop */ - if (flg && (t = test_int ())) { /* timer event? */ - AC(ac) = XWD (srca, dsta); /* AC for intr */ - ABORT (t); } - if (AccViol (srca & AMASK, MM_BSTK, PTF_RD)) { /* src access viol? */ - AC(ac) = XWD (srca, dsta); /* AC for page fail */ - Read (srca & AMASK, MM_BSTK); } /* force trap */ - if (AccViol (dsta & AMASK, MM_OPND, PTF_WR)) { /* dst access viol? */ - AC(ac) = XWD (srca, dsta); /* AC for page fail */ - ReadM (dsta & AMASK, MM_OPND); } /* force trap */ - srcv = Read (srca & AMASK, MM_BSTK); /* read */ - if (dir) dstv = ((srcv << 10) & BYTE1) | ((srcv >> 6) & BYTE2) | - ((srcv << 12) & BYTE3) | ((srcv >> 4) & BYTE4); - else dstv = ((srcv & BYTE1) >> 10) | ((srcv & BYTE2) << 6) | - ((srcv & BYTE3) >> 12) | ((srcv & BYTE4) << 4); - Write (dsta & AMASK, dstv, MM_OPND); /* write */ - srca = srca + 1; /* incr addr */ - dsta = dsta + 1; } -return; -} - -/* Utility routine to test for I/O event and interrupt */ - -int32 test_int (void) -{ -int32 t; - -if (sim_interval <= 0) { /* check queue */ - if (t = sim_process_event ()) return t; /* IO event? */ - if (pi_eval ()) return (INTERRUPT); } /* interrupt? */ -else sim_interval--; /* count clock */ -return 0; -} - -/* Miscellaneous routines */ - -/* Adjust stack pointer - - The reference manual says to trap on: - 1) E < 0, left changes from + to - - 2) E >= 0, left changes from - to + - This is the same as trap on: - 1) E and left result have same signs - 2) initial value and left result have different signs - */ - -d10 adjsp (d10 val, a10 ea) -{ -d10 imm = ea; -d10 left, right; - -left = ADDL (val, imm); -right = ADDR (val, imm); -if (TSTS ((val ^ left) & (~left ^ RLZ (imm)))) SETF (F_T2); -return (left | right); -} - -/* Jump if find first ones - Takes advantage of 7 bit find first table for priority interrupts. -*/ - -int32 jffo (d10 val) -{ -int32 i, by; - -if ((val & DMASK) == 0) return 0; -for (i = 0; i <= 28; i = i + 7) { /* scan five bytes */ - by = (int32) ((val >> (29 - i)) & 0177); - if (by) return (pi_m2lvl[by] + i - 1); } -return 35; /* must be bit 35 */ -} - -/* Circulate - ITS only instruction - - Bits rotated out of AC are rotated into the opposite end of AC+1 - why? - No attempt is made to optimize this instruction. -*/ - -void circ (int32 ac, int32 ea) -{ -int32 sc = LIT8 (ea) % 72; -int32 p1 = ADDAC (ac,1); -int32 i; -d10 val; - -if (sc == 0) return; /* any shift? */ -if (ea & RSIGN) sc = 72 - sc; /* if right, make left */ -for (i = 0; i < sc; i++) { /* one bit at a time */ - val = TSTS (AC(ac)); /* shift out */ - AC(ac) = ((AC(ac) << 1) | (AC(p1) & 1)) & DMASK; - AC(p1) = (AC(p1) >> 1) | val; } /* shift in */ -return; -} - -/* Arithmetic processor (APR) - - The APR subsystem includes miscellaneous interrupts that are individually - maskable but which interrupt on a single, selectable level - - Instructions for the arithmetic processor: - APRID read system id - WRAPR (CONO APR) write system flags - RDAPR (CONI APR) read system flags - (CONSO APR) test system flags - (CONSZ APR) test system flags -*/ - -t_bool aprid (a10 ea, int32 prv) -{ -Write (ea, (ITS)? UC_AIDITS: UC_AIDDEC, prv); -return FALSE; -} - -/* Checked against KS10 ucode */ - -t_bool wrapr (a10 ea, int32 prv) -{ -int32 bits = APR_GETF (ea); - -apr_lvl = ea & APR_M_LVL; -if (ea & APR_SENB) apr_enb = apr_enb | bits; /* set enables? */ -if (ea & APR_CENB) apr_enb = apr_enb & ~bits; /* clear enables? */ -if (ea & APR_CFLG) apr_flg = apr_flg & ~bits; /* clear flags? */ -if (ea & APR_SFLG) apr_flg = apr_flg | bits; /* set flags? */ -if (apr_flg & APRF_ITC) { /* interrupt console? */ - fe_intr (); /* explicit callout */ - apr_flg = apr_flg & ~APRF_ITC; } /* interrupt clears */ -pi_eval (); /* eval pi system */ -return FALSE; -} - -t_bool rdapr (a10 ea, int32 prv) -{ -Write (ea, (d10) APRWORD, prv); -return FALSE; -} - -t_bool czapr (a10 ea, int32 prv) -{ -return ((APRHWORD & ea)? FALSE: TRUE); -} - -t_bool coapr (a10 ea, int32 prv) -{ -return ((APRHWORD & ea)? TRUE: FALSE); -} - -/* Routine to change the processor flags, called from JRST, MUUO, interrupt. - If jrst is TRUE, must munge flags for executive security. - Because the KS10 lacks the public flag, these checks are simplified. -*/ - -void set_newflags (d10 newf, t_bool jrst) -{ -int32 fl = (int32) LRZ (newf); - -if (jrst && TSTF (F_USR)) { /* if in user now */ - fl = fl | F_USR; /* can't clear user */ - if (!TSTF (F_UIO)) fl = fl & ~F_UIO; } /* if !UIO, can't set */ -if (ITS && (fl & F_1PR)) { /* ITS 1-proceed? */ - its_1pr = 1; /* set flag */ - fl = fl & ~F_1PR; } /* vanish bit */ -flags = fl & F_MASK; /* set new flags */ -set_dyn_ptrs (); /* set new ptrs */ -return; -} - -/* Priority interrupt system (PI) - - The priority interrupt system has three sources of requests - (pi_apr) system flags - synthesized on the fly - (pi_ioq) I/O interrupts - synthesized on the fly - pi_prq program requests - APR and I/O requests are masked with the PI enable mask; the program - requests are not. If priority interrupts are enabled, and there is - a request at a level exceeding the currently active level, then an - interrupt occurs. - - Instructions for the priority interrupt system: - WRPI (CONO PI) write pi system - RDPI (CONI PI) read pi system - (CONSO PI) test pi system - (CONSZ PI) test pi system - - Routines for the priority interrupt system: - pi_eval return level number of highest interrupt - pi_dismiss dismiss highest outstanding interrupt - - Checked against KS10 ucode - KS10 UUO's if <18:21> are non-zero -*/ - -t_bool wrpi (a10 ea, int32 prv) -{ -int32 lvl = ea & PI_M_LVL; - -if (ea & PI_INIT) pi_on = pi_enb = pi_act = pi_prq = 0; -if (ea & PI_CPRQ) pi_prq = pi_prq & ~lvl; /* clear prog reqs? */ -if (ea & PI_SPRQ) pi_prq = pi_prq | lvl; /* set prog reqs? */ -if (ea & PI_SENB) pi_enb = pi_enb | lvl; /* enable levels? */ -if (ea & PI_CENB) pi_enb = pi_enb & ~lvl; /* disable levels? */ -if (ea & PI_SON) pi_on = 1; /* enable pi? */ -if (ea & PI_CON) pi_on = 0; /* disable pi? */ -pi_eval (); /* eval pi system */ -return FALSE; -} - -t_bool rdpi (a10 ea, int32 prv) -{ -Write (ea, (d10) PIWORD, prv); -return FALSE; -} - -t_bool czpi (a10 ea, int32 prv) -{ -return ((PIHWORD & ea)? FALSE: TRUE); -} - -t_bool copi (a10 ea, int32 prv) -{ -return ((PIHWORD & ea)? TRUE: FALSE); -} - -/* Priority interrupt evaluation - - The Processor Reference Manuals says that program interrupt - requests occur whether the corresponding level is enabled or - not. However, the KS10, starting with microcode edit 47, - masked program requests under the enable mask, just like APR - and I/O requests. This is not formally documented but appears - to be necessary for the TOPS20 console port to run correclty. -*/ - -int32 pi_eval (void) -{ -int32 reqlvl, actlvl; -extern int32 pi_ub_eval (); - -qintr = 0; -if (pi_on) { - pi_apr = (apr_flg & apr_enb)? pi_l2bit[apr_lvl]: 0; - pi_ioq = pi_ub_eval (); - reqlvl = pi_m2lvl[((pi_apr | pi_ioq | pi_prq) & pi_enb)]; - actlvl = pi_m2lvl[pi_act]; - if ((actlvl == 0) || (reqlvl < actlvl)) qintr = reqlvl; } -return qintr; -} - -void pi_dismiss (void) -{ -pi_act = pi_act & ~pi_l2bit[pi_m2lvl[pi_act]]; /* clr left most bit */ -pi_eval (); /* eval pi system */ -return; -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -flags = 0; /* clear flags */ -its_1pr = 0; /* clear 1-proceed */ -ebr = ubr = 0; /* clear paging */ -pi_enb = pi_act = pi_prq = 0; /* clear PI */ -apr_enb = apr_flg = apr_lvl = 0; /* clear APR */ -pcst = 0; /* clear PC samp */ -rlog = 0; /* clear reg log */ -hsb = (ITS)? UC_HSBITS: UC_HSBDEC; /* set HSB */ -set_dyn_ptrs (); -set_ac_display (ac_cur); -pi_eval (); -if (M == NULL) M = calloc (MAXMEMSIZE, sizeof (d10)); -if (M == NULL) return SCPE_MEM; -pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr ea, UNIT *uptr, int32 sw) -{ -if (vptr == NULL) return SCPE_ARG; -if (ea < AC_NUM) *vptr = AC(ea) & DMASK; -else { if (sw & SWMASK ('V')) { - ea = conmap (ea, PTF_CON, sw); - if (ea >= MAXMEMSIZE) return SCPE_REL; } - if (ea >= MEMSIZE) return SCPE_NXM; - *vptr = M[ea] & DMASK; } -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr ea, UNIT *uptr, int32 sw) -{ -if (ea < AC_NUM) AC(ea) = val & DMASK; -else { if (sw & SWMASK ('V')) { - ea = conmap (ea, PTF_CON | PTF_WR, sw); - if (ea >= MAXMEMSIZE) return SCPE_REL; } - if (ea >= MEMSIZE) return SCPE_NXM; - M[ea] = val & DMASK; } -return SCPE_OK; -} - -/* Set current AC pointers for SCP */ - -void set_ac_display (d10 *acbase) -{ -extern REG *find_reg (char *cptr, char **optr, DEVICE *dptr); -REG *rptr; -int i; - -rptr = find_reg ("AC0", NULL, &cpu_dev); -if (rptr == NULL) return; -for (i = 0; i < AC_NUM; i++, rptr++) rptr->loc = (void *) (acbase + i); -return; -} diff --git a/PDP10/pdp10_defs.h b/PDP10/pdp10_defs.h deleted file mode 100644 index a92ef0d0..00000000 --- a/PDP10/pdp10_defs.h +++ /dev/null @@ -1,749 +0,0 @@ -/* pdp10_defs.h: PDP-10 simulator definitions - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 19-May-03 RMS Revised for new conditional compilation scheme - 09-Jan-03 RMS Added DEUNA/DELUA support - 29-Sep-02 RMS Added variable vector, RX211 support - 22-Apr-02 RMS Removed magtape record length error - 20-Jan-02 RMS Added multiboard DZ11 support - 23-Oct-01 RMS New IO page address constants - 19-Oct-01 RMS Added DZ11 definitions - 07-Sep-01 RMS Revised for PDP-11 multi-level interrupts - 31-Aug-01 RMS Changed int64 to t_int64 for Windoze - 29-Aug-01 RMS Corrected models and dates (found by Lars Brinkhoff) - 01-Jun-01 RMS Updated DZ11 vector definitions - 19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug -*/ - -#ifndef _PDP10_DEFS_H_ -#define _PDP10_DEFS_H_ 0 - -#ifndef VM_PDP10 -#define VM_PDP10 0 -#endif - -#include "sim_defs.h" /* simulator defns */ - -/* Digital Equipment Corporation's 36b family had six implementations: - - name mips comments - - PDP-6 0.25 Original 36b implementation, 1964 - KA10 0.38 First PDP-10, flip chips, 1967 - KI10 0.72 First paging system, flip chip + MSI, 1972 - KL10 1.8 First ECL system, ECL 10K, 1975 - KL10B 1.8 Expanded addressing, ECL 10K, 1978 - KS10 0.3 Last 36b system, 2901 based, 1979 - - In addition, it ran four major (incompatible) operating systems: - - name company comments - - TOPS-10 DEC Original timesharing system - ITS MIT "Incompatible Timesharing System" - TENEX BBN ARPA-sponsored, became - TOPS-20 DEC Commercial version of TENEX - - All of the implementations differ from one another, in instruction set, - I/O structure, and memory management. Further, each of the operating - systems customized the microcode of the paging systems (KI10, KL10, KS10) - for additional instructions and specialized memory management. As a - result, there is no "reference implementation" for the 36b family that - will run all programs and all operating systems. The conditionalization - and generality needed to support the full matrix of models and operating - systems, and to support 36b hardware on 32b data types, is beyond the - scope of this project. - - Instead, this simulator emulates one model -- the KS10. It has the best - documentation and allows reuse of some of the Unibus peripheral emulators - written for the PDP-11 simulator. Further, the simulator requires that - the underlying compiler support 64b integer data types, allowing 36b data - to be maintained in a single data item. Lastly, the simulator implements - the maximum memory size, so that NXM's never happen. -*/ - -/* Data types */ - -typedef int32 a10; /* PDP-10 addr (30b) */ -typedef t_int64 d10; /* PDP-10 data (36b) */ - -/* Abort codes, used to sort out longjmp's back to the main loop - Codes > 0 are simulator stop codes - Codes < 0 are internal aborts - Code = 0 stops execution for an interrupt check -*/ - -#define STOP_HALT 1 /* halted */ -#define STOP_IBKPT 2 /* breakpoint */ -#define STOP_ILLEG 3 /* illegal instr */ -#define STOP_ILLINT 4 /* illegal intr inst */ -#define STOP_PAGINT 5 /* page fail in intr */ -#define STOP_ZERINT 6 /* zero vec in intr */ -#define STOP_NXMPHY 7 /* nxm on phys ref */ -#define STOP_IND 8 /* indirection loop */ -#define STOP_XCT 9 /* XCT loop */ -#define STOP_ILLIOC 10 /* invalid UBA num */ -#define STOP_ASTOP 11 /* address stop */ -#define STOP_UNKNOWN 12 /* unknown stop */ -#define PAGE_FAIL -1 /* page fail */ -#define INTERRUPT -2 /* interrupt */ -#define ABORT(x) longjmp (save_env, (x)) /* abort */ -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ - -/* Return codes from eXTEND */ - -#define XT_MUUO 0 /* invalid operation */ -#define XT_SKIP 1 /* skip return */ -#define XT_NOSK 2 /* no skip return */ - -/* Operating system flags, kept in cpu_unit.flags */ - -#define UNIT_V_ITS (UNIT_V_UF) /* ITS */ -#define UNIT_ITS (1 << UNIT_V_ITS) -#define UNIT_V_T20V41 (UNIT_V_UF + 1) /* TOPS-20 V4.1 */ -#define UNIT_T20V41 (1 << UNIT_V_T20V41) -#define ITS (cpu_unit.flags & UNIT_ITS) - -/* Architectural constants */ - -#define PASIZE 20 /* phys addr width */ -#define MAXMEMSIZE (1 << PASIZE) /* maximum memory */ -#define PAMASK ((1 << PASIZE) - 1) -#define MEMSIZE MAXMEMSIZE /* fixed, KISS */ -#define MEM_ADDR_NXM(x) ((x) >= MEMSIZE) -#define VASIZE 18 /* virtual addr width */ -#define AMASK ((1 << VASIZE) - 1) /* virtual addr mask */ -#define LMASK 0777777000000 /* left mask */ -#define LSIGN 0400000000000 /* left sign */ -#define RMASK 0000000777777 /* right mask */ -#define RSIGN 0000000400000 /* right sign */ -#define DMASK 0777777777777 /* data mask */ -#define SIGN 0400000000000 /* sign */ -#define MMASK 0377777777777 /* magnitude mask */ -#define ONES 0777777777777 -#define MAXPOS 0377777777777 -#define MAXNEG 0400000000000 - -/* Instruction format */ - -#define INST_V_OP 27 /* opcode */ -#define INST_M_OP 0777 -#define INST_V_DEV 26 -#define INST_M_DEV 0177 /* device */ -#define INST_V_AC 23 /* AC */ -#define INST_M_AC 017 -#define INST_V_IND 22 /* indirect */ -#define INST_IND (1 << INST_V_IND) -#define INST_V_XR 18 /* index */ -#define INST_M_XR 017 -#define OP_JRST 0254 /* JRST */ -#define AC_XPCW 07 /* XPCW */ -#define OP_JSR 0264 /* JSR */ -#define GET_OP(x) ((int32) (((x) >> INST_V_OP) & INST_M_OP)) -#define GET_DEV(x) ((int32) (((x) >> INST_V_DEV) & INST_M_DEV)) -#define GET_AC(x) ((int32) (((x) >> INST_V_AC) & INST_M_AC)) -#define TST_IND(x) ((x) & INST_IND) -#define GET_XR(x) ((int32) (((x) >> INST_V_XR) & INST_M_XR)) -#define GET_ADDR(x) ((a10) ((x) & AMASK)) - -/* Byte pointer format */ - -#define BP_V_P 30 /* position */ -#define BP_M_P 077 -#define BP_P 0770000000000 -#define BP_V_S 24 /* size */ -#define BP_M_S 077 -#define BP_S 0007700000000 -#define GET_P(x) ((int32) (((x) >> BP_V_P) & BP_M_P)) -#define GET_S(x) ((int32) (((x) >> BP_V_S) & BP_M_S)) -#define PUT_P(b,x) (((b) & ~BP_P) | ((((t_int64) (x)) & BP_M_P) << BP_V_P)) - -/* Flags (stored in their own halfword) */ - -#define F_V_AOV 17 /* arithmetic ovflo */ -#define F_V_C0 16 /* carry 0 */ -#define F_V_C1 15 /* carry 1 */ -#define F_V_FOV 14 /* floating ovflo */ -#define F_V_FPD 13 /* first part done */ -#define F_V_USR 12 /* user mode */ -#define F_V_UIO 11 /* user I/O mode */ -#define F_V_PUB 10 /* public mode */ -#define F_V_AFI 9 /* addr fail inhibit */ -#define F_V_T2 8 /* trap 2 */ -#define F_V_T1 7 /* trap 1 */ -#define F_V_FXU 6 /* floating exp unflo */ -#define F_V_DCK 5 /* divide check */ -#define F_AOV (1 << F_V_AOV) -#define F_C0 (1 << F_V_C0) -#define F_C1 (1 << F_V_C1) -#define F_FOV (1 << F_V_FOV) -#define F_FPD (1 << F_V_FPD) -#define F_USR (1 << F_V_USR) -#define F_UIO (1 << F_V_UIO) -#define F_PUB (1 << F_V_PUB) -#define F_AFI (1 << F_V_AFI) -#define F_T2 (1 << F_V_T2) -#define F_T1 (1 << F_V_T1) -#define F_TR (F_T1 | F_T2) -#define F_FXU (1 << F_V_FXU) -#define F_DCK (1 << F_V_DCK) -#define F_1PR (F_AFI) /* ITS: 1-proceed */ -#define F_MASK 0777740 /* all flags */ -#define SETF(x) flags = flags | (x) -#define CLRF(x) flags = flags & ~(x) -#define TSTF(x) (flags & (x)) -#define GET_TRAPS(x) (((x) & (F_T2 | F_T1)) >> F_V_T1) - -/* Priority interrupt system */ - -#define PI_CPRQ 020000 /* drop prog req */ -#define PI_INIT 010000 /* clear pi system */ -#define PI_SPRQ 004000 /* set prog req */ -#define PI_SENB 002000 /* set enables */ -#define PI_CENB 001000 /* clear enables */ -#define PI_CON 000400 /* turn off pi system */ -#define PI_SON 000200 /* turn on pi system */ -#define PI_M_LVL 000177 /* level mask */ -#define PI_V_PRQ 18 /* in CONI */ -#define PI_V_ACT 8 -#define PI_V_ON 7 -#define PI_V_ENB 0 - -/* Arithmetic processor flags */ - -#define APR_SENB 0100000 /* set enable */ -#define APR_CENB 0040000 /* clear enable */ -#define APR_CFLG 0020000 /* clear flag */ -#define APR_SFLG 0010000 /* set flag */ -#define APR_IRQ 0000010 /* int request */ -#define APR_M_LVL 0000007 /* pi level */ -#define APR_V_FLG 4 /* system flags */ -#define APR_M_FLG 0377 -#define APRF_ITC (002000 >> APR_V_FLG) /* int console flag */ -#define APRF_NXM (000400 >> APR_V_FLG) /* nxm flag */ -#define APRF_TIM (000040 >> APR_V_FLG) /* timer request */ -#define APRF_CON (000020 >> APR_V_FLG) /* console int */ -#define APR_GETF(x) (((x) >> APR_V_FLG) & APR_M_FLG) - -/* Virtual address, DEC paging */ - -#define PAG_V_OFF 0 /* offset - must be 0 */ -#define PAG_N_OFF 9 /* page offset width */ -#define PAG_SIZE 01000 /* page offset size */ -#define PAG_M_OFF 0777 /* mask for offset */ -#define PAG_V_PN PAG_N_OFF /* page number */ -#define PAG_N_PPN (PASIZE - PAG_N_OFF) /* phys pageno width */ -#define PAG_M_PPN 03777 /* phys pageno mask */ -#define PAG_PPN 03777000 -#define PAG_N_VPN (VASIZE - PAG_N_OFF) /* virt pageno width */ -#define PAG_M_VPN 0777 /* virt pageno mask */ -#define PAG_VPN 0777000 -#define PAG_GETOFF(x) ((x) & PAG_M_OFF) -#define PAG_GETVPN(x) (((x) >> PAG_V_PN) & PAG_M_VPN) -#define PAG_XPTEPA(p,x) (((p) + PAG_GETOFF (x)) & PAMASK) -#define PAG_PTEPA(p,x) (((((int32) (p)) & PTE_PPMASK) << PAG_V_PN) + PAG_GETOFF (x)) - -/* Page table entry, TOPS-10 paging */ - -#define PTE_T10_A 0400000 /* T10: access */ -#define PTE_T10_P 0200000 /* T10: public */ -#define PTE_T10_W 0100000 /* T10: writeable */ -#define PTE_T10_S 0040000 /* T10: software */ -#define PTE_T10_C 0020000 /* T10: cacheable */ -#define PTE_PPMASK PAG_M_PPN - -/* Page table entry, TOPS-20 paging */ - -#define PTE_T20_V_TYP 33 /* T20: pointer type */ -#define PTE_T20_M_TYP 07 -#define T20_NOA 0 /* no access */ -#define T20_IMM 1 /* immediate */ -#define T20_SHR 2 /* shared */ -#define T20_IND 3 /* indirect */ -#define PTE_T20_W 0020000000000 /* T20: writeable */ -#define PTE_T20_C 0004000000000 /* T20: cacheable */ -#define PTE_T20_STM 0000077000000 /* T20: storage medium */ -#define PTE_T20_V_PMI 18 /* page map index */ -#define PTE_T20_M_PMI 0777 -#define T20_GETTYP(x) ((int32) (((x) >> PTE_T20_V_TYP) & PTE_T20_M_TYP)) -#define T20_GETPMI(x) ((int32) (((x) >> PTE_T20_V_PMI) & PTE_T20_M_PMI)) - -/* CST entry, TOPS-20 paging */ - -#define CST_AGE 0770000000000 /* age field */ -#define CST_M 0000000000001 /* modified */ - -/* Page fail word, DEC paging */ - -#define PF_USER 0400000000000 /* user mode */ -#define PF_HARD 0200000000000 /* nx I/O reg */ -#define PF_NXM 0370000000000 /* nx memory */ -#define PF_T10_A 0100000000000 /* T10: pte A bit */ -#define PF_T10_W 0040000000000 /* T10: pte W bit */ -#define PF_T10_S 0020000000000 /* T10: pte S bit */ -#define PF_T20_DN 0100000000000 /* T20: eval done */ -#define PF_T20_M 0040000000000 /* T20: modified */ -#define PF_T20_W 0020000000000 /* T20: writeable */ -#define PF_WRITE 0010000000000 /* write reference */ -#define PF_PUB 0004000000000 /* pte public bit */ -#define PF_C 0002000000000 /* pte C bit */ -#define PF_VIRT 0001000000000 /* pfl: virt ref */ -#define PF_NXMP 0001000000000 /* nxm: phys ref */ -#define PF_IO 0000200000000 /* I/O reference */ -#define PF_BYTE 0000020000000 /* I/O byte ref */ - -/* Virtual address, ITS paging */ - -#define ITS_V_OFF 0 /* offset - must be 0 */ -#define ITS_N_OFF 10 /* page offset width */ -#define ITS_SIZE 02000 /* page offset size */ -#define ITS_M_OFF 01777 /* mask for offset */ -#define ITS_V_PN ITS_N_OFF /* page number */ -#define ITS_N_PPN (PASIZE- ITS_N_OFF) /* phys pageno width */ -#define ITS_M_PPN 01777 /* phys pageno mask */ -#define ITS_PPN 03776000 -#define ITS_N_VPN (VASIZE - ITS_N_OFF) /* virt pageno width */ -#define ITS_M_VPN 0377 /* virt pageno mask */ -#define ITS_VPN 0776000 -#define ITS_GETVPN(x) (((x) >> ITS_V_PN) & ITS_M_VPN) - -/* Page table entry, ITS paging */ - -#define PTE_ITS_V_ACC 16 /* access field */ -#define PTE_ITS_M_ACC 03 -#define ITS_ACC_NO 0 /* no access */ -#define ITS_ACC_RO 1 /* read only */ -#define ITS_ACC_RWF 2 /* read-write first */ -#define ITS_ACC_RW 3 /* read write */ -#define PTE_ITS_AGE 0020000 /* age */ -#define PTE_ITS_C 0010000 /* cacheable */ -#define PTE_ITS_PPMASK ITS_M_PPN -#define ITS_GETACC(x) (((x) >> PTE_ITS_V_ACC) & PTE_ITS_M_ACC) - -/* Page fail word, ITS paging */ - -#define PF_ITS_WRITE 0010000000000 /* write reference */ -#define PF_ITS_V_ACC 28 /* access from PTE */ - -/* Page table fill operations */ - -#define PTF_RD 0 /* read check */ -#define PTF_WR 1 /* write check */ -#define PTF_MAP 2 /* map instruction */ -#define PTF_CON 4 /* console access */ - -/* User base register */ - -#define UBR_SETACB 0400000000000 /* set AC blocks */ -#define UBR_SETUBR 0100000000000 /* set UBR */ -#define UBR_V_CURAC 27 /* current AC block */ -#define UBR_V_PRVAC 24 /* previous AC block */ -#define UBR_M_AC 07 -#define UBR_ACBMASK 0007700000000 -#define UBR_V_UBR 0 /* user base register */ -#define UBR_N_UBR 11 -#define UBR_M_UBR 03777 -#define UBR_UBRMASK 0000000003777 -#define UBR_GETCURAC(x) ((int32) (((x) >> UBR_V_CURAC) & UBR_M_AC)) -#define UBR_GETPRVAC(x) ((int32) (((x) >> UBR_V_PRVAC) & UBR_M_AC)) -#define UBR_GETUBR(x) ((int32) (((x) >> UBR_V_UBR) & PAG_M_PPN)) -#define UBRWORD (ubr | UBR_SETACB | UBR_SETUBR) - -/* Executive base register */ - -#define EBR_V_T20P 14 /* TOPS20 paging */ -#define EBR_T20P (1u << EBR_V_T20P) -#define EBR_V_PGON 13 /* enable paging */ -#define EBR_PGON (1u << EBR_V_PGON) -#define EBR_V_EBR 0 /* exec base register */ -#define EBR_N_EBR 11 -#define EBR_M_EBR 03777 -#define EBR_MASK (EBR_T20P | EBR_PGON | (EBR_M_EBR << EBR_V_EBR)) -#define EBR_GETEBR(x) ((int32) (((x) >> EBR_V_EBR) & PAG_M_PPN)) -#define PAGING (ebr & EBR_PGON) -#define T20 (ebr & EBR_T20P) - -/* AC and mapping contexts - - There are only two real contexts for selecting the AC block and - the memory map: current and previous. However, PXCT allows the - choice of current versus previous to be made selectively for - various parts of an instruction. The PXCT flags are kept in a - dynamic CPU variable. -*/ - -#define EA_PXCT 010 /* eff addr calc */ -#define OPND_PXCT 004 /* operand, bdst */ -#define EABP_PXCT 002 /* bp eff addr calc */ -#define BSTK_PXCT 001 /* stk, bp op, bsrc */ -#define XSRC_PXCT 002 /* extend source */ -#define XDST_PXCT 001 /* extend destination */ -#define MM_CUR 000 /* current context */ -#define MM_EA (pflgs & EA_PXCT) -#define MM_OPND (pflgs & OPND_PXCT) -#define MM_EABP (pflgs & EABP_PXCT) -#define MM_BSTK (pflgs & BSTK_PXCT) - -/* Accumulator access. The AC blocks are kept in array acs[AC_NBLK * AC_NUM]. - Two pointers are provided to the bases of the current and previous blocks. - Macro AC selects the current AC block; macro XR selects current or previous, - depending on whether the selected bit in the "pxct in progress" flag is set. -*/ - -#define AC_NUM 16 /* # AC's/block */ -#define AC_NBLK 8 /* # AC blocks */ -#define AC(r) (ac_cur[r]) /* AC select current */ -#define XR(r,prv) ((prv)? ac_prv[r]: ac_cur[r]) /* AC select context */ -#define ADDAC(x,i) (((x) + (i)) & INST_M_AC) -#define P1 ADDAC (ac, 1) - -/* User process table entries */ - -#define UPT_T10_UMAP 0000 /* T10: user map */ -#define UPT_T10_X340 0400 /* T10: exec 340-377 */ -#define UPT_TRBASE 0420 /* trap base */ -#define UPT_MUUO 0424 /* MUUO block */ -#define UPT_MUPC 0425 /* caller's PC */ -#define UPT_T10_CTX 0426 /* T10: context */ -#define UPT_T20_UEA 0426 /* T20: address */ -#define UPT_T20_CTX 0427 /* T20: context */ -#define UPT_ENPC 0430 /* MUUO new PC, exec */ -#define UPT_1PO 0432 /* ITS 1-proc: old PC */ -#define UPT_1PN 0433 /* ITS 1-proc: new PC */ -#define UPT_UNPC 0434 /* MUUO new PC, user */ -#define UPT_NPCT 1 /* PC offset if trap */ -#define UPT_T10_PAG 0500 /* T10: page fail blk */ -#define UPT_T20_PFL 0500 /* T20: page fail wd */ -#define UPT_T20_OFL 0501 /* T20: flags */ -#define UPT_T20_OPC 0502 /* T20: old PC */ -#define UPT_T20_NPC 0503 /* T20: new PC */ -#define UPT_T20_SCTN 0540 /* T20: section 0 ptr */ - -/* Exec process table entries */ - -#define EPT_PIIT 0040 /* PI interrupt table */ -#define EPT_UBIT 0100 /* Unibus intr table */ -#define EPT_T10_X400 0200 /* T10: exec 400-777 */ -#define EPT_TRBASE 0420 /* trap base */ -#define EPT_ITS_PAG 0440 /* ITS: page fail blk */ -#define EPT_T20_SCTN 0540 /* T20: section 0 ptr */ -#define EPT_T10_X000 0600 /* T10: exec 0 - 337 */ - -/* Microcode constants */ - -#define UC_INHCST 0400000000000 /* inhibit CST update */ -#define UC_UBABLT 0040000000000 /* BLTBU and BLTUB */ -#define UC_KIPAGE 0020000000000 /* "KI" paging */ -#define UC_KLPAGE 0010000000000 /* "KL" paging */ -#define UC_VERDEC (0130 << 18) /* ucode version */ -#define UC_VERITS (262u << 18) -#define UC_SERDEC 4097 /* serial number */ -#define UC_SERITS 1729 -#define UC_AIDDEC (UC_INHCST | UC_UBABLT | UC_KIPAGE | UC_KLPAGE | \ - UC_VERDEC | UC_SERDEC) -#define UC_AIDITS (UC_KIPAGE | UC_VERITS | UC_SERITS) -#define UC_HSBDEC 0376000 /* DEC initial HSB */ -#define UC_HSBITS 0000500 /* ITS initial HSB */ - -/* Front end communications region */ - -#define FE_SWITCH 030 /* halt switch */ -#define FE_KEEPA 031 /* keep alive */ -#define FE_CTYIN 032 /* console in */ -#define FE_CTYOUT 033 /* console out */ -#define FE_KLININ 034 /* KLINIK in */ -#define FE_KLINOUT 035 /* KLINIK out */ -#define FE_RHBASE 036 /* boot: RH11 addr */ -#define FE_UNIT 037 /* boot: unit num */ -#define FE_MTFMT 040 /* boot: magtape params */ -#define FE_CVALID 0400 /* char valid flag */ - -/* Halfword operations */ - -#define ADDL(x,y) (((x) + ((y) << 18)) & LMASK) -#define ADDR(x,y) (((x) + (y)) & RMASK) -#define INCL(x) ADDL (x, 1) -#define INCR(x) ADDR (x, 1) -#define AOB(x) (INCL (x) | INCR(x)) -#define SUBL(x,y) (((x) - ((y) << 18)) & LMASK) -#define SUBR(x,y) (((x) - (y)) & RMASK) -#define DECL(x) SUBL (x, 1) -#define DECR(x) SUBR (x, 1) -#define SOB(x) (DECL (x) | DECR(x)) -#define LLZ(x) ((x) & LMASK) -#define RLZ(x) (((x) << 18) & LMASK) -#define RRZ(x) ((x) & RMASK) -#define LRZ(x) (((x) >> 18) & RMASK) -#define LIT8(x) (((x) & RSIGN)? \ - (((x) & 0377)? (-(x) & 0377): 0400): ((x) & 0377)) - -/* Fullword operations */ - -#define INC(x) (((x) + 1) & DMASK) -#define DEC(x) (((x) - 1) & DMASK) -#define SWP(x) ((((x) << 18) & LMASK) | (((x) >> 18) & RMASK)) -#define XWD(x,y) (((((d10) (x)) << 18) & LMASK) | (((d10) (y)) & RMASK)) -#define SETS(x) ((x) | SIGN) -#define CLRS(x) ((x) & ~SIGN) -#define TSTS(x) ((x) & SIGN) -#define NEG(x) (-(x) & DMASK) -#define ABS(x) (TSTS (x)? NEG(x): (x)) -#define SXT(x) (TSTS (x)? (x) | ~DMASK: (x)) - -/* Doubleword operations (on 2-word arrays) */ - -#define DMOVN(rs) rs[1] = (-rs[1]) & MMASK; \ - rs[0] = (~rs[0] + (rs[1] == 0)) & DMASK -#define MKDNEG(rs) rs[1] = SETS (-rs[1]) & DMASK; \ - rs[0] = (~rs[0] + (rs[1] == MAXNEG)) & DMASK -#define DCMPGE(a,b) ((a[0] > b[0]) || ((a[0] == b[0]) && (a[1] >= b[1]))) - -/* Address operations */ - -#define ADDA(x,i) (((x) + (i)) & AMASK) -#define INCA(x) ADDA (x, 1) - -/* Unibus adapter control/status register */ - -#define UBCS_TMO 0400000 /* timeout */ -#define UBCS_BMD 0200000 /* bad mem data NI */ -#define UBCS_PAR 0100000 /* parity error NI */ -#define UBCS_NXD 0040000 /* nx device */ -#define UBCS_HI 0004000 /* irq on BR7 or BR6 */ -#define UBCS_LO 0002000 /* irq on BR5 or BR4 */ -#define UBCS_PWR 0001000 /* power low NI */ -#define UBCS_DXF 0000200 /* disable xfer NI*/ -#define UBCS_INI 0000100 /* Unibus init */ -#define UBCS_RDZ 0030500 /* read as zero */ -#define UBCS_RDW 0000277 /* read/write bits */ -#define UBCS_V_LHI 3 /* hi pri irq level */ -#define UBCS_V_LLO 0 /* lo pri irq level */ -#define UBCS_M_PRI 07 -#define UBCS_GET_HI(x) (((x) >> UBCS_V_LHI) & UBCS_M_PRI) -#define UBCS_GET_LO(x) (((x) >> UBCS_V_LLO) & UBCS_M_PRI) - -/* Unibus adapter page map */ - -#define UBANUM 2 /* # of Unibus adapters */ -#define UMAP_ASIZE 6 /* address size */ -#define UMAP_MEMSIZE (1 << UMAP_ASIZE) /* length */ -#define UMAP_AMASK (UMAP_MEMSIZE - 1) -#define UMAP_V_RRV 30 /* read reverse */ -#define UMAP_V_DSB 29 /* 16b on NPR read */ -#define UMAP_V_FST 28 /* fast transfer */ -#define UMAP_V_VLD 27 /* valid flag */ -#define UMAP_RRV (1 << UMAP_V_RRV) -#define UMAP_DSB (1 << UMAP_V_DSB) -#define UMAP_FST (1 << UMAP_V_FST) -#define UMAP_VLD (1 << UMAP_V_VLD) -#define UMAP_V_FLWR 14 /* flags as written */ -#define UMAP_V_FLRD 27 /* flags as stored */ -#define UMAP_M_FL 017 -#define UMAP_V_PNWR 0 /* page num, write */ -#define UMAP_V_PNRD 9 /* page num, read */ -#define UMAP_M_PN 03777 -#define UMAP_MASK ((UMAP_M_FL << UMAP_V_FLRD) | (UMAP_M_PN << UMAP_V_PNRD)) -#define UMAP_POSFL(x) (((x) & (UMAP_M_FL << UMAP_V_FLWR)) \ - << (UMAP_V_FLRD - UMAP_V_FLWR)) -#define UMAP_POSPN(x) (((x) & (UMAP_M_PN << UMAP_V_PNWR)) \ - << (UMAP_V_PNRD - UMAP_V_PNWR)) - -/* Unibus I/O constants */ - -#define READ 0 /* PDP11 compatible */ -/* #define READC 1 /* console read */ -#define WRITE 2 -/* #define WRITEC 3 /* console write */ -#define WRITEB 4 -#define IO_V_UBA 18 /* UBA in I/O addr */ -#define IO_N_UBA 16 /* max num of UBA's */ -#define IO_M_UBA (IO_N_UBA - 1) -#define IO_UBA1 (1 << IO_V_UBA) -#define IO_UBA3 (3 << IO_V_UBA) -#define GET_IOUBA(x) (((x) >> IO_V_UBA) & IO_M_UBA) - -/* Device information block */ - -#define VEC_DEVMAX 8 /* max device vec */ - -struct pdp_dib { - uint32 ba; /* base addr */ - uint32 lnt; /* length */ - t_stat (*rd)(int32 *dat, int32 ad, int32 md); - t_stat (*wr)(int32 dat, int32 ad, int32 md); - int32 vnum; /* vectors: number */ - int32 vloc; /* locator */ - int32 vec; /* value */ - int32 (*ack[VEC_DEVMAX])(void); /* ack routines */ -}; - -typedef struct pdp_dib DIB; - -/* I/O system parameters */ - -#define DZ_MUXES 4 /* max # of muxes */ -#define DZ_LINES 8 /* lines per mux */ -#define DIB_MAX 100 /* max DIBs */ - -#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ -#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */ -#define DEV_V_FLTA (DEV_V_UF + 2) /* float addr */ -#define DEV_UBUS (1u << DEV_V_UBUS) -#define DEV_QBUS (1u << DEV_V_QBUS) -#define DEV_FLTA (1u << DEV_V_FLTA) - -#define UNIBUS TRUE /* 18b only */ - -#define FST 0 /* Unibus 1 */ -#define MAP 1 /* Unibus 3 */ - -#define DEV_RDX 8 /* default device radix */ - -/* I/O page layout */ - -#define IOPAGEBASE 0760000 /* I/O page base */ -#define IOBA_UBMAP 0763000 - -#define IOBA_UBMAP1 (IO_UBA1 + IOBA_UBMAP) /* Unibus 1 map */ -#define IOLN_UBMAP1 0100 -#define IOBA_UBCS1 (IO_UBA1 + 0763100) /* Unibus 1 c/s reg */ -#define IOLN_UBCS1 001 -#define IOBA_UBMNT1 (IO_UBA1 + 0763101) /* Unibus 1 maint reg */ -#define IOLN_UBMNT1 001 -#define IOBA_RP (IO_UBA1 + 0776700) /* RH11/disk */ -#define IOLN_RP 050 - -#define IOBA_DZ (IO_UBA3 + 0760010) /* DZ11 */ -#define IOLN_DZ 010 -#define IOBA_TCU (IO_UBA3 + 0760770) /* TCU150 */ -#define IOLN_TCU 006 -#define IOBA_UBMAP3 (IO_UBA3 + IOBA_UBMAP) /* Unibus 3 map */ -#define IOLN_UBMAP3 0100 -#define IOBA_UBCS3 (IO_UBA3 + 0763100) /* Unibus 3 c/s reg */ -#define IOLN_UBCS3 001 -#define IOBA_UBMNT3 (IO_UBA3 + 0763101) /* Unibus 3 maint reg */ -#define IOLN_UBMNT3 001 -#define IOBA_XU (IO_UBA3 + 0774510) /* DEUNA/DELUA */ -#define IOLN_XU 010 -#define IOBA_RY (IO_UBA3 + 0777170) /* RX211 */ -#define IOLN_RY 004 -#define IOBA_TU (IO_UBA3 + 0772440) /* RH11/tape */ -#define IOLN_TU 034 -#define IOBA_LP20 (IO_UBA3 + 0775400) /* LP20 */ -#define IOLN_LP20 020 -#define IOBA_PTR (IO_UBA3 + 017550) /* PC11 reader */ -#define IOLN_PTR 004 -#define IOBA_PTP (IO_UBA3 + 017554) /* PC11 punch */ -#define IOLN_PTP 004 - -/* Common Unibus CSR flags */ - -#define CSR_V_GO 0 /* go */ -#define CSR_V_IE 6 /* interrupt enable */ -#define CSR_V_DONE 7 /* done */ -#define CSR_V_BUSY 11 /* busy */ -#define CSR_V_ERR 15 /* error */ -#define CSR_GO (1u << CSR_V_GO) -#define CSR_IE (1u << CSR_V_IE) -#define CSR_DONE (1u << CSR_V_DONE) -#define CSR_BUSY (1u << CSR_V_BUSY) -#define CSR_ERR (1u << CSR_V_ERR) - -/* I/O system definitions, lifted from the PDP-11 simulator - Interrupt assignments, priority is right to left - - <3:0> = BR7 - <7:4> = BR6 - <19:8> = BR5 - <30:20> = BR4 -*/ - -#define INT_V_RP 6 /* RH11/RP,RM drives */ -#define INT_V_TU 7 /* RH11/TM03/TU45 */ -#define INT_V_XU 15 /* DEUNA/DELUA */ -#define INT_V_DZRX 16 /* DZ11 */ -#define INT_V_DZTX 17 -#define INT_V_RY 18 /* RX211 */ -#define INT_V_PTR 24 /* PC11 */ -#define INT_V_PTP 25 -#define INT_V_LP20 26 /* LPT20 */ - -#define INT_RP (1u << INT_V_RP) -#define INT_TU (1u << INT_V_TU) -#define INT_XU (1u << INT_V_XU) -#define INT_DZRX (1u << INT_V_DZRX) -#define INT_DZTX (1u << INT_V_DZTX) -#define INT_RY (1u << INT_V_RY) -#define INT_PTR (1u << INT_V_PTR) -#define INT_PTP (1u << INT_V_PTP) -#define INT_LP20 (1u << INT_V_LP20) - -#define IPL_RP 6 /* int levels */ -#define IPL_TU 6 -#define IPL_XU 5 -#define IPL_DZRX 5 -#define IPL_DZTX 5 -#define IPL_RY 5 -#define IPL_PTR 4 -#define IPL_PTP 4 -#define IPL_LP20 4 - -#define INT_UB1 INT_RP /* on Unibus 1 */ -#define INT_UB3 (0xFFFFFFFFu & ~INT_UB1) /* on Unibus 3 */ - -#define INT_IPL7 0x0000000F /* int level masks */ -#define INT_IPL6 0x000000F0 -#define INT_IPL5 0x000FFF00 -#define INT_IPL4 0x3FF00000 - -#define VEC_Q 0000 /* vector base */ -#define VEC_PTR 0070 /* interrupt vectors */ -#define VEC_PTP 0074 -#define VEC_XU 0120 -#define VEC_TU 0224 -#define VEC_RP 0254 -#define VEC_RY 0264 -#define VEC_DZRX 0340 -#define VEC_DZTX 0344 -#define VEC_LP20 0754 - -#define IVCL(dv) (INT_V_##dv) -#define IREQ(dv) int_req -#define SET_INT(dv) IREQ(dv) = IREQ(dv) | (INT_##dv) -#define CLR_INT(dv) IREQ(dv) = IREQ(dv) & ~(INT_##dv) - -/* Function prototypes */ - -int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf, t_bool ub); -int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf, t_bool ub); -int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf, t_bool ub); -int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf, t_bool ub); -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat set_vec (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_vec (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat auto_config (uint32 rank, uint32 num); - -#endif diff --git a/PDP10/pdp10_diag.txt b/PDP10/pdp10_diag.txt deleted file mode 100644 index 3f9a18a6..00000000 --- a/PDP10/pdp10_diag.txt +++ /dev/null @@ -1,25 +0,0 @@ -Bugs Found ----------- - -1. pushj cleared T2 after setting it -2. if timer autoadjust is enabled, timer diagnostic may fail, - depending on host CPU speed -3. DFAD/DFSB should use FP_ONES instead of ONES -4. TLB physical address max = 1MW, tested in diagnostic -5. DPB does read/write, not read-modify/write -6. Fetch error takes priority over traps, due to prefetching - of next instruction -7. HSB is 36b, was 32b -8. CPU and PAG devices had mismatched types -9. non-zero sections in Tops-20 paging section indirect may - cause non-existent memory error, due to microcode "error" -10. PXCT test for user mode was backward -11. Timer interrupts were not implemented in Tops-20 indirect - chains -12. epta/upta hit known bug in VC++ implementation of 64b - data types -13. final W calculation in Tops-20 paging was incorrect -14. Timer representation lost sub msec values -15. UBA initialization reset the UBA itself -16. RHCS1: writing IE cannot trigger an interrupt -17. Tape bootstrap was set to 800bpi instead of 1600bpi diff --git a/PDP10/pdp10_doc.txt b/PDP10/pdp10_doc.txt deleted file mode 100644 index fb31fe4e..00000000 --- a/PDP10/pdp10_doc.txt +++ /dev/null @@ -1,623 +0,0 @@ -To: Users -From: Bob Supnik -Subj: PDP-10 Simulator Usage -Date: 15-May-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - Original code published in 1993-2003, written by Robert M Supnik - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - -This memorandum documents the PDP-10 simulator. - - -1. Simulator Files - -To compile the PDP-10, you must define VM_PDP10 and USE_INT64 as part of the -compilation command line. - -sim/ sim_defs.h - sim_ether.h - sim_rev.h - sim_sock.h - sim_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_ether.c - sim_sock.c - sim_tape.c - sim_tmxr.c - -sim/pdp10/ pdp10_defs.h - pdp10_cpu.c - pdp10_fe.c - pdp10_ksio.c - pdp10_lp20.c - pdp10_mdfp.c - pdp10_pag.c - pdp10_rp.c - pdp10_sys.c - pdp10_tu.c - pdp10_xtnd.c - -sim/pdp11/ pdp11_dz.c - pdp11_pt.c - pdp11_ry.c - pdp11_xu.c - -2. PDP-10 Features - -The PDP-10 simulator is configured as follows: - -device simulates -name(s) - -CPU KS10 CPU with 1MW of memory -PAG paging unit (translation maps) -UBA Unibus adapters (translation maps) -FE console -TIM timer -PTR,PTP PC11 paper tape reader/punch -RY RX211/RX02 floppy disk and two drives -DZ DZ11 8-line terminal multiplexor (up to 4) -LP20 LP20 line printer -RP RH11/RP04/RP05/RP06/RP07/RM03/RM05/RM80 controller with - eight drives -TU RH11/TM02/TU45 controller with eight drives -XU DEUNA/DELUA Ethernet controller - -The PTR, PTP, and RX211 are initially set DISABLED. The DZ11 and LP20 can -also be set DISABLED. Some devices support the SET ADDRESS command, which -allows the I/O page address of the device to be changed, and the SET VECTOR -command, which allows the vector of the device to be changed. All devices -support the SHOW ADDRESS and SHOW VECTOR commands, which display the device -address and vector, respectively. - -The PDP-10 simulator implements several unique stop condition: - - - illegal instruction (000) in kernel mode - - indirect addressing nesting exceeds limit - - execute chaining exceeds limit - - page fail or other error in interrupt sequence - - illegal instruction in interrupt sequence - - invalid vector pointer in interrupt sequence - - invalid Unibus adapter number - - non-existent exec or user page table address - -The PDP-10 loader supports RIM10B format paper tapes, SAV binary files, and -EXE binary files. LOAD switches -r, -s, -e specify RIM10, SAV, EXE format, -respectively. If no switch is specified, the LOAD command checks the file -extension; .RIM, .SAV, .EXE specify RIM10, SAV, EXE format, respectively. -If no switch is specified, and no extension matches, the LOAD command checks -the file format to try to determine the file type. - -2.1 CPU - -The CPU options allow the user to specify standard microcode, standard -microcode with a bug fix for a boostrap problem in TOPS-20 V4.1, or ITS -microcode: - - SET CPU STANDARD Standard microcode - SET CPU TOPS20V41 Standard microcode with TOPS-20 V4.1 bug fix - SET CPU ITS ITS compatible microcode - -The CPU implements a SHOW command to display the I/O space address map: - - SHOW CPU IOSPACE show I/O space address map - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - PC 18 program counter - FLAGS 18 processor flags (<13:17> unused) - AC0..AC17 36 accumulators - IR 36 instruction register - EBR 18 executive base register - PGON 1 paging enabled flag - T20P 1 TOPS-20 paging - UBR 18 user base register - CURAC 3 current AC block - PRVAC 3 previous AC block - SPT 36 shared pointer table - CST 36 core status table - PUR 36 process update register - CSTM 36 CST mask - HSB 18 halt status block address - DBR1 18 descriptor base register 1 (ITS) - DBR2 18 descriptor base register 2 (ITS) - DBR3 18 descriptor base register 3 (ITS) - DBR4 18 descriptor base register 4 (ITS) - PIENB 7 PI levels enabled - PIACT 7 PI levels active - PIPRQ 7 PI levels with program requests - PIIOQ 7 PI levels with IO requests - PIAPR 7 PI levels with APR requests - APRENB 8 APR flags enabled - APRFLG 8 APR flags active - APRLVL 3 PI level for APR interrupt - IND_MAX 8 indirect address nesting limit - XCT_MAX 8 execute chaining limit - PCQ[0:63] 18 PC prior to last jump or interrupt; - most recent PC change first - WRU 8 interrupt character - REG[0:127] 36 fast memory blocks - -2.2 Pager - -The pager contains the page maps for executive and user mode. The -executive page map is the memory space for unit 0, the user page map the -memory space for unit 1. A page map entry is 32 bits wide and has the -following format: - - bit content - --- ------- - 31 page is writeable - 30 entry is valid - 29:19 mbz - 18:9 physical page base address - 8:0 mbz - -The pager has no registers. - -2.3 Unibus Adapters - -The Unibus adapters link the system I/O devices to the CPU. Unibus -adapter 1 (UBA1) is unit 0, and Unibus adapter 3 is unit 1. The -adapter's Unibus map is the memory space of the corresponding unit. - -The Unibus adapter has the following registers: - - name size comments - - INTREQ 32 interrupt requests - UB1CS 16 Unibus adapter 1 control/status - UB3CS 16 Unibus adapter 3 control/status - -2.4 Front End (FE) - -The front end is the system console. The keyboard input is unit 0, -the console output is unit 1. It supports two options: - - SET FE STOP halts the PDP-10 operating system - SET FE CTLC simulates typing ^C - -The front end has the following registers: - - name size comments - - IBUF 8 input buffer - ICOUNT 32 count of input characters - ITIME 24 keyboard polling interval - OBUF 8 output buffer - OCOUNT 32 count of output characters - OTIME 24 console output response time - -2.5 Timer (TIM) - -The timer (TIM) implements the system timer, the interval timer, and -the time of day clock used to get the date and time at system startup. -Because most PDP-10 software is not Y2K compliant, the timer implements -one option: - - SET TIM NOY2K software not Y2K compliant, limit time - of day clock to 1999 (default) - SET TIM Y2K software is Y2K compliant - -The timer has the following registers: - - name size comments - - TIMBASE 59 time base (double precision) - TTG 36 time to go (remaining time) for interval - PERIOD 36 reset value for interval - QUANT 36 quantum timer (ITS only) - TIME 24 tick delay - DIAG 1 use fixed tick delay instead of autocalibration - -Unless the DIAG flag is set, the timer autocalibrates; the tick delay -is adjusted up or down so that the time base tracks actual elapsed time. -This may cause time-dependent diagnostics to report errors. - -2.6 PC11 Paper Tape Reader (PTR) - -The paper tape reader (PTR) reads data from a disk file. The POS -register specifies the number of the next data item to be read. Thus, -by changing POS, the user can backspace or advance the reader. - -The paper tape reader requires an unsupported driver under TOPS-10 -and is not supported under TOPS-20 or ITS. - -The paper tape reader implements these registers: - - name size comments - - BUF 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - BUSY 1 busy flag (CSR<11>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - POS 32 position in the input file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - end of file 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - - -2.7 PC11 Paper Tape Punch (PTP) - -The paper tape punch (PTP) writes data to a disk file. The POS -register specifies the number of the next data item to be written. -Thus, by by changing POS, the user can backspace or advance the punch. - -The paper tape punch requires an unsupported driver under TOPS-10 -and is not supported under TOPS-20 or ITS. - -The paper tape punch implements these registers: - - name size comments - - BUF 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - POS 32 position in the input or output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -2.8 DZ11 Terminal Multiplexor (DZ) - -The DZ11 is an 8-line terminal multiplexor. Up to 4 DZ11's (32 lines) -are supported. The number of lines can be changed with the command - - SET DZ LINES=n set line count to n - -The line count must be a multiple of 8, with a maximum of 32. - -The DZ11 can support 8-bit input and output of characters. 8-bit -output is incompatible with TOPS-20 and is off by default. The command - - SET DZ 8B - -allows output characters to be 8 bits. - -The terminal lines perform input and output through Telnet sessions -connected to a user-specified port. The ATTACH command specifies -the port to be used: - - ATTACH {-am} DZ set up listening port - -where port is a decimal number between 1 and 65535 that is not being used -for other TCP/IP activities. The optional switch -m turns on the DZ11's -modem controls; the optional switch -a turns on active disconnects -(disconnect session if computer clears Data Terminal Ready). Without -modem control, the DZ behaves as though terminals were directly connected; -disconnecting the Telnet session does not cause any operating system- -visible change in line status. - -Once the DZ is attached and the simulator is running, the DZ will listen -for connections on the specified port. It assumes that the incoming -connections are Telnet connections. The connection remains open until -disconnected by the simulated program, the Telnet client, a SET DZ -DISCONNECT command, or a DETACH DZ command. - -The SHOW DZ CONNECTIONS command displays the current connections to the DZ. -The SHOW DZ STATISTICS command displays statistics for active connections. -The SET DZ DISCONNECT=linenumber disconnects the specified line. - -The DZ11 implements these registers: - - name size comments - - CSR[0:3] 16 control/status register, boards 0-3 - RBUF[0:3] 16 receive buffer, boards 0-3 - LPR[0:3] 16 line parameter register, boards 0-3 - TCR[0:3] 16 transmission control register, boards 0-3 - MSR[0:3] 16 modem status register, boards 0-3 - TDR[0:3] 16 transmit data register, boards 0-3 - SAENB[0:3] 1 silo alarm enabled, boards 0-3 - RXINT 4 receive interrupts, boards 3..0 - TXINT 4 transmit interrupts, boards 3..0 - MDMTCL 1 modem control enabled - AUTODS 1 autodisconnect enabled - -The DZ11 does not support save and restore. All open connections are -lost when the simulator shuts down or the DZ is detached. - -2.9 RH11 Adapter, RM02/03/05/80, RP04/05/06/07 drives (RP) - -The RP controller implements the Massbus 18b (RH11) direct interface for -large disk drives. It is more abstract than other device simulators, with -just enough detail to run operating system drivers. In addition, the RP -controller conflates the details of the RM series controllers with the RP -series controllers, although there were detailed differences. - -RP options include the ability to set units write enabled or write locked, -to set the drive type to one of six disk types, or autosize: - - SET RPn LOCKED set unit n write locked - SET RPn WRITEENABLED set unit n write enabled - SET RPn RM03 set type to RM03 - SET RPn RM05 set type to RM05 - SET RPn RM80 set type to RM80 - SET RPn RP04 set type to RP04 - SET RPn RP06 set type to RP06 - SET RPn RP07 set type to RP07 - SET RPn AUTOSIZE set type based on file size at attach - -The type options can be used only when a unit is not attached to a file. -Note that TOPS-10 V7.03 supported only the RP06 and RM03; V7.04 added -support for the RP07. TOPS-20 V4.1 also supported only the RP06 and -RM03. Units can be set ONLINE or OFFLINE. - -The RP controller implements these registers: - - name size comments - - RPCS1 16 control/status 1 - RPWC 16 word count - RPBA 16 bus address - RPDA 16 desired surface, sector - RPCS2 16 control/status 2 - RPDS[0:7] 16 drive status, drives 0-7 - RPER1[0:7] 16 drive errors, drives 0-7 - RPOF 16 offset - RPDC 8 desired cylinder - RPER2 16 error status 2 - RPER3 16 error status 3 - RPEC1 16 ECC syndrome 1 - RPEC2 16 ECC syndrome 2 - RPMR 16 maintenance register - RPDB 16 data buffer - IFF 1 transfer complete interrupt request flop - INT 1 interrupt pending flag - SC 1 special condition (CSR1<15>) - DONE 1 device done flag (CSR1<7>) - IE 1 interrupt enable flag (CSR1<6>) - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - - end of file x assume rest of disk is zero - - OS I/O error x report error and stop - -2.10 RH11 Adapter, TM02 Formatter, TU45 Magnetic Tape (TU) - -The magnetic tape simulator simulates an RH11 Massbus adapter with one -TM02 formatter and up to eight TU45 drives. Magnetic tape options include -the ability to make units write enabled or locked. - - SET TUn LOCKED set unit n write locked - SET TUn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFLINE. - -The magnetic tape controller implements these registers: - - name size comments - - MTCS1 16 control/status 1 - MTBA 16 memory address - MTWC 16 word count - MTFC 16 frame count - MTCS2 16 control/status 2 - MTFS 16 formatter status - MTER 16 error status - MTCC 16 check character - MTDB 16 data buffer - MTMR 16 maintenance register - MTTC 16 tape control register - INT 1 interrupt pending flag - DONE 1 device done flag - IE 1 interrupt enable flag - STOP_IOE 1 stop on I/O error - TIME 24 delay - UST[0:7] 16 unit status, units 0-7 - POS[0:7] 32 position, units 0-7 - -Error handling is as follows: - - error processed as - - not attached tape not ready; if STOP_IOE, stop - - end of file operation incomplete - - OS I/O error parity error; if STOP_IOE, stop - -2.11 LP20 DMA Line Printer (LP20) - -The LP20 is a DMA-based line printer controller. There is one -line printer option to clear the vertical forms unit (VFU): - - SET LP20 VFUCLEAR clear the vertical forms unit - -The LP20 implements these registers: - - name size comments - - LPCSA 16 control/status register A - LPCSB 16 control/status register B - LPBA 16 bus address register - LPBC 12 byte count register - LPPAGC 12 page count register - LPRDAT 12 RAM data register - LPCBUF 8 character buffer register - LPCOLC 8 column counter register - LPPDAT 8 printer data register - LPCSUM 8 checksum register - DVPTR 7 vertical forms unit pointer - DVLNT 7 vertical forms unit length - INT 1 interrupt request - ERR 1 error flag - DONE 1 done flag - IE 1 interrupt enable flag - POS 32 position in output file - TIME 24 response time - STOP_IOE 1 stop on I/O error - TXRAM[0:255] 12 translation RAM - DAVFU[0:142] 12 vertical forms unit array - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of paper - - OS I/O error x report error and stop - -2.12 RX211/RX02 Floppy Disk (RY) - -RX211 options include the ability to set units write enabled or write -locked, single or double density, or autosized: - - SET RYn LOCKED set unit n write locked - SET RYn WRITEENABLED set unit n write enabled - SET RYn SINGLE set unit n single density - SET RYn DOUBLE set unit n double density (default) - SET RYn AUTOSIZE set unit n autosized - -The floppy disk requires an unsupported driver under TOPS-10 and -is not supported under TOPS-20 or ITS. - -The RX211 implements these registers: - - name size comments - - RYCS 16 status - RYBA 16 buffer address - RYWC 8 word count - RYDB 16 data buffer - RYES 12 error status - RYERR 8 error code - RYTA 8 current track - RYSA 8 current sector - STAPTR 4 controller state - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - TR 1 transfer ready flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - DONE 1 device done flag (CSR<5>) - CTIME 24 command completion time - STIME 24 seek time, per track - XTIME 24 transfer ready delay - STOP_IOE 1 stop on I/O error - SBUF[0:255] 8 sector buffer array - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -RX02 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.13 DEUNA/DELUA Ethernet Controller (XU) - -XU simulates the DEUNA/DELUA Ethernet controller. The current implementation -is a stub and is permanently disabled. - -2.14 Symbolic Display and Input - -The PDP-10 simulator implements symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as (sixbit) character string - -p display as packed (seven bit) string - -m display instruction mnemonics - -v interpret address as virtual - -e force executive mode - -u force user mode - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or -a ASCII character - " or -c sixbit string - # or -p packed seven bit string - alphabetic instruction mnemonic - numeric octal number - -Instruction input uses standard PDP-10 assembler syntax. There are three -instruction classes: memory reference, memory reference with AC, and I/O. - -Memory reference instructions have the format - - memref {@}address{(index)} - -memory reference with AC instructions have the format - - memac ac,{@}address{(index)} - -and I/O instructions have the format - - io device,{@}address{(index)} - -where @ signifies indirect. The address is a signed octal number in the -range 0 - 0777777. The ac and index are unsigned octal numbers in the -range 0-17. The device is either a recognized device mnemonic (APR, PI, -TIM) or an octal number in the range 0 - 0177. - -The simulator recognizes the standard MACRO alternate mnemonics (CLEAR -for SETZ, OR for IORI), the individual definitions for JRST and JFCL -variants, and the extended instruction mnemonics. diff --git a/PDP10/pdp10_fe.c b/PDP10/pdp10_fe.c deleted file mode 100644 index e0f9d1cf..00000000 --- a/PDP10/pdp10_fe.c +++ /dev/null @@ -1,168 +0,0 @@ -/* pdp10_fe.c: PDP-10 front end (console terminal) simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - fe KS10 console front end - - 25-Apr-03 RMS Revised for extended file support - 22-Dec-02 RMS Added break support - 30-May-02 RMS Widened COUNT to 32b - 30-Nov-01 RMS Added extended SET/SHOW support - 23-Oct-01 RMS New IO page address constants - 07-Sep-01 RMS Moved function prototypes -*/ - -#include "pdp10_defs.h" -#define UNIT_DUMMY (1 << UNIT_V_UF) - -extern d10 *M; -extern int32 apr_flg; -t_stat fei_svc (UNIT *uptr); -t_stat feo_svc (UNIT *uptr); -t_stat fe_reset (DEVICE *dptr); -t_stat fe_stop_os (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat fe_ctrl_c (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* FE data structures - - fe_dev FE device descriptor - fe_unit FE unit descriptor - fe_reg FE register list -*/ - -#define fei_unit fe_unit[0] -#define feo_unit fe_unit[1] - -UNIT fe_unit[] = { - { UDATA (&fei_svc, 0, 0), KBD_POLL_WAIT }, - { UDATA (&feo_svc, 0, 0), SERIAL_OUT_WAIT } }; - -REG fe_reg[] = { - { ORDATA (IBUF, fei_unit.buf, 8) }, - { DRDATA (ICOUNT, fei_unit.pos, T_ADDR_W), REG_RO + PV_LEFT }, - { DRDATA (ITIME, fei_unit.wait, 24), REG_NZ + PV_LEFT }, - { ORDATA (OBUF, feo_unit.buf, 8) }, - { DRDATA (OCOUNT, feo_unit.pos, T_ADDR_W), REG_RO + PV_LEFT }, - { DRDATA (OTIME, feo_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB fe_mod[] = { - { UNIT_DUMMY, 0, NULL, "STOP", &fe_stop_os }, - { UNIT_DUMMY, 0, NULL, "CTRL-C", &fe_ctrl_c }, - { 0 } }; - -DEVICE fe_dev = { - "FE", fe_unit, fe_reg, fe_mod, - 2, 10, 31, 1, 8, 8, - NULL, NULL, &fe_reset, - NULL, NULL, NULL }; - -/* Front end processor (console terminal) - - Communications between the KS10 and its front end is based on an in-memory - status block and two interrupt lines: interrupt-to-control (APR_ITC) and - interrupt-from-console (APR_CON). When the KS10 wants to print a character - on the terminal, - - 1. It places a character, plus the valid flag, in FE_CTYOUT. - 2. It interrupts the front end processor. - 3. The front end processor types the character and then zeroes FE_CTYOUT. - 4. The front end procesor interrupts the KS10. - - When the front end wants to send an input character to the KS10, - - 1. It places a character, plus the valid flag, in FE_CTYIN. - 2. It interrupts the KS10. - 3. It waits for the KS10 to take the character and clear the valid flag. - 4. It can then send more input (the KS10 may signal this by interrupting - the front end). - - Note that the protocol has both ambiguity (interrupt to the KS10 may mean - character printed, or input character available, or both) and lack of - symmetry (the KS10 does not inform the front end that it has taken an - input character). -*/ - -void fe_intr (void) -{ -if (M[FE_CTYOUT] & FE_CVALID) { /* char to print? */ - feo_unit.buf = (int32) M[FE_CTYOUT] & 0177; /* pick it up */ - sim_putchar (feo_unit.buf); /* type it */ - feo_unit.pos = feo_unit.pos + 1; - sim_activate (&feo_unit, feo_unit.time); } /* sched completion */ -else if ((M[FE_CTYIN] & FE_CVALID) == 0) { /* input char taken? */ - sim_cancel (&fei_unit); /* sched immediate */ - sim_activate (&fei_unit, 0); }; /* keyboard poll */ -return; -} - -t_stat feo_svc (UNIT *uptr) -{ -M[FE_CTYOUT] = 0; /* clear char */ -apr_flg = apr_flg | APRF_CON; /* interrupt KS10 */ -return SCPE_OK; -} - -t_stat fei_svc (UNIT *uptr) -{ -int32 temp; - -sim_activate (&fei_unit, fei_unit.wait); /* continue poll */ -if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ -if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */ -fei_unit.buf = temp & 0177; -fei_unit.pos = fei_unit.pos + 1; -M[FE_CTYIN] = fei_unit.buf | FE_CVALID; /* put char in mem */ -apr_flg = apr_flg | APRF_CON; /* interrupt KS10 */ -return SCPE_OK; -} - -/* Reset */ - -t_stat fe_reset (DEVICE *dptr) -{ -fei_unit.buf = feo_unit.buf = 0; -M[FE_CTYIN] = M[FE_CTYOUT] = 0; -apr_flg = apr_flg & ~(APRF_ITC | APRF_CON); -sim_activate (&fei_unit, fei_unit.wait); /* start input poll */ -return SCPE_OK; -} - -/* Stop operating system */ - -t_stat fe_stop_os (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -M[FE_SWITCH] = IOBA_RP; /* tell OS to stop */ -return SCPE_OK; -} - -/* Enter control-C for Windoze */ - -t_stat fe_ctrl_c (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -fei_unit.buf = 003; /* control-C */ -M[FE_CTYIN] = fei_unit.buf | FE_CVALID; /* put char in mem */ -apr_flg = apr_flg | APRF_CON; /* interrupt KS10 */ -return SCPE_OK; -} diff --git a/PDP10/pdp10_ksio.c b/PDP10/pdp10_ksio.c deleted file mode 100644 index ec54d729..00000000 --- a/PDP10/pdp10_ksio.c +++ /dev/null @@ -1,797 +0,0 @@ -/* pdp10_ksio.c: PDP-10 KS10 I/O subsystem simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - uba Unibus adapters - - 12-Mar-03 RMS Added logical name support - 10-Oct-02 RMS Revised for dynamic table generation - Added SHOW IOSPACE routine - 29-Sep-02 RMS Added variable vector, central map support - 25-Jan-02 RMS Revised for multiple DZ11's - 06-Jan-02 RMS Revised enable/disable support - 23-Sep-01 RMS New IO page address constants - 07-Sep-01 RMS Revised device disable mechanism - 25-Aug-01 RMS Enabled DZ11 - 21-Aug-01 RMS Updated DZ11 disable - 01-Jun-01 RMS Updated DZ11 vectors - 12-May-01 RMS Fixed typo - - The KS10 uses the PDP-11 Unibus for its I/O, via adapters. While - nominally four adapters are supported, in practice only 1 and 3 - are implemented. The disks are placed on adapter 1, the rest of - the I/O devices on adapter 3. - - In theory, we should maintain completely separate Unibuses, with - distinct PI systems. In practice, this simulator has so few devices - that we can get away with a single PI system, masking for which - devices are on adapter 1, and which on adapter 3. The Unibus - implementation is modeled on the Qbus in the PDP-11 simulator and - is described there. - - The I/O subsystem is programmed by I/O instructions which create - Unibus operations (read, read pause, write, write byte). DMA is - the responsibility of the I/O device simulators, which also implement - Unibus to physical memory mapping. - - The priority interrupt subsystem (and other privileged functions) - is programmed by I/O instructions with internal devices codes - (opcodes 700-702). These are dispatched here, although many are - handled in the memory management unit or elsewhere. - - The ITS instructions are significantly different from the TOPS-10/20 - instructions. They do not use the extended address calculation but - instead provide instruction variants (Q for Unibus adapter 1, I for - Unibus adapter 3) which insert the Unibus adapter number into the - effective address. -*/ - -#include "pdp10_defs.h" -#include - -#define XBA_MBZ 0400000 /* ba mbz */ -#define eaRB (ea & ~1) -#define GETBYTE(ea,x) ((((ea) & 1)? (x) >> 8: (x)) & 0377) -#define UBNXM_FAIL(pa,op) \ - n = iocmap[GET_IOUBA (pa)]; \ - if (n >= 0) ubcs[n] = ubcs[n] | UBCS_TMO | UBCS_NXD; \ - pager_word = PF_HARD | PF_VIRT | PF_IO | \ - ((op == WRITEB)? PF_BYTE: 0) | \ - (TSTF (F_USR)? PF_USER: 0) | (pa); \ - ABORT (PAGE_FAIL) - -/* Unibus adapter data */ - -int32 ubcs[UBANUM] = { 0 }; /* status registers */ -int32 ubmap[UBANUM][UMAP_MEMSIZE] = { 0 }; /* Unibus maps */ -int32 int_req = 0; /* interrupt requests */ - -/* Map IO controller numbers to Unibus adapters: -1 = non-existent */ - -static int iocmap[IO_N_UBA] = { /* map I/O ext to UBA # */ - -1, 0, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; - -static const int32 ubabr76[UBANUM] = { - INT_UB1 & (INT_IPL7 | INT_IPL6), INT_UB3 & (INT_IPL7 | INT_IPL6) }; -static const int32 ubabr54[UBANUM] = { - INT_UB1 & (INT_IPL5 | INT_IPL4), INT_UB3 & (INT_IPL5 | INT_IPL4) }; -static const int32 ubashf[4] = { 18, 26, 0, 8 }; - -extern d10 *M; /* main memory */ -extern d10 *ac_cur; -extern d10 pager_word; -extern int32 flags, pi_l2bit[8]; -extern UNIT cpu_unit; -extern FILE *sim_log; -extern jmp_buf save_env; -extern DEVICE *sim_devices[]; - -extern d10 Read (a10 ea); -extern void pi_eval (); -extern int32 rp_inta (void); -extern int32 tu_inta (void); -extern int32 lp20_inta (void); -extern int32 dz_rxinta (void); -extern int32 dz_txinta (void); - -t_stat ubmap_rd (int32 *data, int32 addr, int32 access); -t_stat ubmap_wr (int32 data, int32 addr, int32 access); -t_stat ubs_rd (int32 *data, int32 addr, int32 access); -t_stat ubs_wr (int32 data, int32 addr, int32 access); -t_stat rd_zro (int32 *data, int32 addr, int32 access); -t_stat wr_nop (int32 data, int32 addr, int32 access); -t_stat uba_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat uba_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat uba_reset (DEVICE *dptr); -d10 ReadIO (a10 ea); -void WriteIO (a10 ea, d10 val, int32 mode); - -/* Unibus adapter data structures - - uba_dev UBA device descriptor - uba_unit UBA units - uba_reg UBA register list -*/ - -DIB ubmp1_dib = { IOBA_UBMAP1, IOLN_UBMAP1, &ubmap_rd, &ubmap_wr, 0 }; -DIB ubmp3_dib = { IOBA_UBMAP3, IOLN_UBMAP3, &ubmap_rd, &ubmap_wr, 0 }; -DIB ubcs1_dib = { IOBA_UBCS1, IOLN_UBCS1, &ubs_rd, &ubs_wr, 0 }; -DIB ubcs3_dib = { IOBA_UBCS3, IOLN_UBCS3, &ubs_rd, &ubs_wr, 0 }; -DIB ubmn1_dib = { IOBA_UBMNT1, IOLN_UBMNT1, &rd_zro, &wr_nop, 0 }; -DIB ubmn3_dib = { IOBA_UBMNT3, IOLN_UBMNT3, &rd_zro, &wr_nop, 0 }; -DIB msys_dib = { 00100000, 1, &rd_zro, &wr_nop, 0 }; - -UNIT uba_unit[] = { - { UDATA (NULL, UNIT_FIX, UMAP_MEMSIZE) }, - { UDATA (NULL, UNIT_FIX, UMAP_MEMSIZE) } }; - -REG uba_reg[] = { - { ORDATA (INTREQ, int_req, 32), REG_RO }, - { ORDATA (UB1CS, ubcs[0], 18) }, - { ORDATA (UB3CS, ubcs[1], 18) }, - { NULL } }; - -DEVICE uba_dev = { - "UBA", uba_unit, uba_reg, NULL, - UBANUM, 8, UMAP_ASIZE, 1, 8, 32, - &uba_ex, &uba_dep, &uba_reset, - NULL, NULL, NULL, - NULL, 0 }; - -/* PDP-11 I/O structures */ - -DIB *dib_tab[DIB_MAX]; /* run-time DIBs */ - -int32 (*int_ack[32])(void); /* int ack routines */ - -int32 int_vec[32]; /* int vectors */ - -DIB *std_dib[] = { /* standard DIBs */ - &ubmp1_dib, - &ubmp3_dib, - &ubcs1_dib, - &ubcs3_dib, - &ubmn1_dib, - &ubmn3_dib, - &msys_dib, - NULL }; - -/* IO 710 (DEC) TIOE - test I/O word, skip if zero - (ITS) IORDI - read word from Unibus 3 - returns TRUE if skip, FALSE otherwise -*/ - -t_bool io710 (int32 ac, a10 ea) -{ -d10 val; - -if (ITS) AC(ac) = ReadIO (IO_UBA3 | ea); /* IORDI */ -else { /* TIOE */ - val = ReadIO (ea); /* read word */ - if ((AC(ac) & val) == 0) return TRUE; } -return FALSE; -} - -/* IO 711 (DEC) TION - test I/O word, skip if non-zero - (ITS) IORDQ - read word from Unibus 1 - returns TRUE if skip, FALSE otherwise -*/ - -t_bool io711 (int32 ac, a10 ea) -{ -d10 val; - -if (ITS) AC(ac) = ReadIO (IO_UBA1 | ea); /* IORDQ */ -else { /* TION */ - val = ReadIO (ea); /* read word */ - if ((AC(ac) & val) != 0) return TRUE; } -return FALSE; -} - -/* IO 712 (DEC) RDIO - read I/O word, addr in ea - (ITS) IORD - read I/O word, addr in M[ea] -*/ - -d10 io712 (a10 ea) -{ -return ReadIO (ea); /* RDIO, IORD */ -} - -/* IO 713 (DEC) WRIO - write I/O word, addr in ea - (ITS) IOWR - write I/O word, addr in M[ea] -*/ - -void io713 (d10 val, a10 ea) -{ -WriteIO (ea, val & 0177777, WRITE); /* WRIO, IOWR */ -return; -} - -/* IO 714 (DEC) BSIO - set bit in I/O address - (ITS) IOWRI - write word to Unibus 3 -*/ - -void io714 (d10 val, a10 ea) -{ -d10 temp; - -val = val & 0177777; -if (ITS) WriteIO (IO_UBA3 | ea, val, WRITE); /* IOWRI */ -else { - temp = ReadIO (ea); /* BSIO */ - temp = temp | val; - WriteIO (ea, temp, WRITE); } -return; -} - -/* IO 715 (DEC) BCIO - clear bit in I/O address - (ITS) IOWRQ - write word to Unibus 1 -*/ - -void io715 (d10 val, a10 ea) -{ -d10 temp; - -val = val & 0177777; -if (ITS) WriteIO (IO_UBA1 | ea, val, WRITE); /* IOWRQ */ -else { - temp = ReadIO (ea); /* BCIO */ - temp = temp & ~val; - WriteIO (ea, temp, WRITE); } -return; -} - -/* IO 720 (DEC) TIOEB - test I/O byte, skip if zero - (ITS) IORDBI - read byte from Unibus 3 - returns TRUE if skip, FALSE otherwise -*/ - -t_bool io720 (int32 ac, a10 ea) -{ -d10 val; - -if (ITS) { /* IORDBI */ - val = ReadIO (IO_UBA3 | eaRB); - AC(ac) = GETBYTE (ea, val); } -else { /* TIOEB */ - val = ReadIO (eaRB); - val = GETBYTE (ea, val); - if ((AC(ac) & val) == 0) return TRUE; } -return FALSE; -} - -/* IO 721 (DEC) TIONB - test I/O word, skip if non-zero - (ITS) IORDBQ - read word from Unibus 1 - returns TRUE if skip, FALSE otherwise -*/ - -t_bool io721 (int32 ac, a10 ea) -{ -d10 val; - -if (ITS) { /* IORDBQ */ - val = ReadIO (IO_UBA1 | eaRB); - AC(ac) = GETBYTE (ea, val); } -else { /* TIONB */ - val = ReadIO (eaRB); - val = GETBYTE (ea, val); - if ((AC(ac) & val) != 0) return TRUE; } -return FALSE; -} - -/* IO 722 (DEC) RDIOB - read I/O byte, addr in ea - (ITS) IORDB - read I/O byte, addr in M[ea] -*/ - -d10 io722 (a10 ea) -{ -d10 val; - -val = ReadIO (eaRB); /* RDIOB, IORDB */ -return GETBYTE (ea, val); -} - -/* IO 723 (DEC) WRIOB - write I/O byte, addr in ea - (ITS) IOWRB - write I/O byte, addr in M[ea] -*/ - -void io723 (d10 val, a10 ea) -{ -WriteIO (ea, val & 0377, WRITEB); /* WRIOB, IOWRB */ -return; -} - -/* IO 724 (DEC) BSIOB - set bit in I/O byte address - (ITS) IOWRBI - write byte to Unibus 3 -*/ - -void io724 (d10 val, a10 ea) -{ -d10 temp; - -val = val & 0377; -if (ITS) WriteIO (IO_UBA3 | ea, val, WRITEB); /* IOWRBI */ -else { - temp = ReadIO (eaRB); /* BSIOB */ - temp = GETBYTE (ea, temp); - temp = temp | val; - WriteIO (ea, temp, WRITEB); } -return; -} - -/* IO 725 (DEC) BCIOB - clear bit in I/O byte address - (ITS) IOWRBQ - write byte to Unibus 1 -*/ - -void io725 (d10 val, a10 ea) -{ -d10 temp; - -val = val & 0377; -if (ITS) WriteIO (IO_UBA1 | ea, val, WRITEB); /* IOWRBQ */ -else { - temp = ReadIO (eaRB); /* BCIOB */ - temp = GETBYTE (ea, temp); - temp = temp & ~val; - WriteIO (ea, temp, WRITEB); } -return; -} - -/* Read and write I/O devices. - These routines are the linkage between the 64b world of the main - simulator and the 32b world of the device simulators. -*/ - -d10 ReadIO (a10 ea) -{ -uint32 pa = (uint32) ea; -int32 i, n, val; -DIB *dibp; - -for (i = 0; dibp = dib_tab[i]; i++ ) { - if ((pa >= dibp->ba) && - (pa < (dibp->ba + dibp->lnt))) { - dibp->rd (&val, pa, READ); - pi_eval (); - return ((d10) val); } } -UBNXM_FAIL (pa, READ); -} - -void WriteIO (a10 ea, d10 val, int32 mode) -{ -uint32 pa = (uint32) ea; -int32 i, n; -DIB *dibp; - -for (i = 0; dibp = dib_tab[i]; i++ ) { - if ((pa >= dibp->ba) && - (pa < (dibp->ba + dibp->lnt))) { - dibp->wr ((int32) val, pa, mode); - pi_eval (); - return; } } -UBNXM_FAIL (pa, mode); -} - -/* Mapped read and write routines - used by word-oriented Unibus devices */ - -a10 Map_Addr10 (a10 ba, int32 ub) -{ -a10 pa10; -int32 vpn = PAG_GETVPN (ba >> 2); /* get PDP-10 page number */ - -if ((vpn >= UMAP_MEMSIZE) || (ba & XBA_MBZ) || - ((ubmap[ub][vpn] & UMAP_VLD) == 0)) return -1; /* invalid map? */ -pa10 = (ubmap[ub][vpn] + PAG_GETOFF (ba >> 2)) & PAMASK; -return pa10; -} - -int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf, t_bool ub) -{ -uint32 lim; -a10 pa10; - -lim = ba + bc; -for ( ; ba < lim; ba++) { /* by bytes */ - pa10 = Map_Addr10 (ba, ub); /* map addr */ - if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ - ubcs[ub] = ubcs[ub] | UBCS_TMO; /* UBA times out */ - return (lim - ba); } /* return bc */ - *buf++ = (uint8) ((M[pa10] >> ubashf[ba & 3]) & 0377); - } -return 0; -} - -int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf, t_bool ub) -{ -uint32 lim; -a10 pa10; - -ba = ba & ~01; /* align start */ -lim = ba + (bc & ~01); -for ( ; ba < lim; ba = ba + 2) { /* by words */ - pa10 = Map_Addr10 (ba, ub); /* map addr */ - if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ - ubcs[ub] = ubcs[ub] | UBCS_TMO; /* UBA times out */ - return (lim - ba); } /* return bc */ - *buf++ = (uint16) ((M[pa10] >> ((ba & 2)? 0: 18)) & 0177777); - } -return 0; -} - -int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf, t_bool ub) -{ -uint32 lim; -a10 pa10; -static d10 mask = 0377; - -lim = ba + bc; -for ( ; ba < lim; ba++) { /* by bytes */ - pa10 = Map_Addr10 (ba, ub); /* map addr */ - if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ - ubcs[ub] = ubcs[ub] | UBCS_TMO; /* UBA times out */ - return (lim - ba); } /* return bc */ - M[pa10] = (M[pa10] & ~(mask << ubashf[ba & 3])) | - (((d10) *buf++) << ubashf[ba & 3]); } -return 0; -} - -int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf, t_bool ub) -{ -uint32 lim; -a10 pa10; -d10 val; - -ba = ba & ~01; /* align start */ -lim = ba + (bc & ~01); -for ( ; ba < lim; ba++) { /* by bytes */ - pa10 = Map_Addr10 (ba, ub); /* map addr */ - if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ - ubcs[ub] = ubcs[ub] | UBCS_TMO; /* UBA times out */ - return (lim - ba); } /* return bc */ - val = *buf++; /* get data */ - if (ba & 2) M[pa10] = (M[pa10] & 0777777600000) | val; - else M[pa10] = (M[pa10] & 0600000777777) | (val << 18); - } -return 0; -} - -/* Evaluate Unibus priority interrupts */ - -int32 pi_ub_eval () -{ -int32 i, lvl; - -for (i = lvl = 0; i < UBANUM; i++) { - if (int_req & ubabr76[i]) - lvl = lvl | pi_l2bit[UBCS_GET_HI (ubcs[i])]; - if (int_req & ubabr54[i]) - lvl = lvl | pi_l2bit[UBCS_GET_LO (ubcs[i])]; } -return lvl; -} - -/* Return Unibus device vector - - Takes as input the request level calculated by pi_eval - If there is an interrupting Unibus device at that level, return its vector, - otherwise, returns 0 -*/ - -int32 pi_ub_vec (int32 rlvl, int32 *uba) -{ -int32 i, masked_irq; - -for (i = masked_irq = 0; i < UBANUM; i++) { - if ((rlvl == UBCS_GET_HI (ubcs[i])) && /* req on hi level? */ - (masked_irq = int_req & ubabr76[i])) break; - if ((rlvl == UBCS_GET_LO (ubcs[i])) && /* req on lo level? */ - (masked_irq = int_req & ubabr54[i])) break; } -*uba = (i << 1) + 1; /* store uba # */ -for (i = 0; (i < 32) && masked_irq; i++) { /* find hi pri req */ - if ((masked_irq >> i) & 1) { - int_req = int_req & ~(1u << i); /* clear req */ - if (int_ack[i]) return int_ack[i](); - return int_vec[i]; } } /* return vector */ -return 0; -} - -/* Unibus adapter map routines */ - -t_stat ubmap_rd (int32 *val, int32 pa, int32 mode) -{ -int32 n = iocmap[GET_IOUBA (pa)]; - -if (n < 0) ABORT (STOP_ILLIOC); -*val = ubmap[n][pa & UMAP_AMASK]; -return SCPE_OK; -} - -t_stat ubmap_wr (int32 val, int32 pa, int32 mode) -{ -int32 n = iocmap[GET_IOUBA (pa)]; - -if (n < 0) ABORT (STOP_ILLIOC); -ubmap[n][pa & UMAP_AMASK] = UMAP_POSFL (val) | UMAP_POSPN (val); -return SCPE_OK; -} - -/* Unibus adapter control/status routines */ - -t_stat ubs_rd (int32 *val, int32 pa, int32 mode) -{ -int32 n = iocmap[GET_IOUBA (pa)]; - -if (n < 0) ABORT (STOP_ILLIOC); -if (int_req & ubabr76[n]) ubcs[n] = ubcs[n] | UBCS_HI; -if (int_req & ubabr54[n]) ubcs[n] = ubcs[n] | UBCS_LO; -*val = ubcs[n] = ubcs[n] & ~UBCS_RDZ; -return SCPE_OK; -} - -t_stat ubs_wr (int32 val, int32 pa, int32 mode) -{ -int32 n = iocmap[GET_IOUBA (pa)]; - -if (n < 0) ABORT (STOP_ILLIOC); -if (val & UBCS_INI) { - reset_all (5); /* start after UBA */ - ubcs[n] = val & UBCS_DXF; } -else ubcs[n] = val & UBCS_RDW; -if (int_req & ubabr76[n]) ubcs[n] = ubcs[n] | UBCS_HI; -if (int_req & ubabr54[n]) ubcs[n] = ubcs[n] | UBCS_LO; -return SCPE_OK; -} - -/* Unibus adapter read zero/write ignore routines */ - -t_stat rd_zro (int32 *val, int32 pa, int32 mode) -{ -*val = 0; -return SCPE_OK; -} - -t_stat wr_nop (int32 val, int32 pa, int32 mode) -{ -return SCPE_OK; -} - -t_stat uba_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -int32 uba = uptr - uba_unit; - -if (addr >= UMAP_MEMSIZE) return SCPE_NXM; -*vptr = ubmap[uba][addr]; -return SCPE_OK; -} - -t_stat uba_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -int32 uba = uptr - uba_unit; - -if (addr >= UMAP_MEMSIZE) return SCPE_NXM; -ubmap[uba][addr] = (int32) val & UMAP_MASK; -return SCPE_OK; -} - -t_stat uba_reset (DEVICE *dptr) -{ -int32 i, uba; - -int_req = 0; -for (uba = 0; uba < UBANUM; uba++) { - ubcs[uba] = 0; - for (i = 0; i < UMAP_MEMSIZE; i++) ubmap[uba][i] = 0; } -pi_eval (); -return SCPE_OK; -} - -/* Change device address */ - -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newba; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if ((val == 0) || (uptr == NULL)) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newba = (uint32) get_uint (cptr, 8, PAMASK, &r); /* get new */ -if ((r != SCPE_OK) || (newba == dibp->ba)) return r; -if (GET_IOUBA (newba) != GET_IOUBA (dibp->ba)) return SCPE_ARG; -if (newba % ((uint32) val)) return SCPE_ARG; /* check modulus */ -if (GET_IOUBA (newba) != GET_IOUBA (dibp->ba)) return SCPE_ARG; -dibp->ba = newba; /* store */ -return SCPE_OK; -} - -/* Show device address */ - -t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -DEVICE *dptr; -DIB *dibp; - -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if ((dibp == NULL) || (dibp->ba <= IOPAGEBASE)) return SCPE_IERR; -fprintf (st, "address=%07o", dibp->ba); -if (dibp->lnt > 1) - fprintf (st, "-%07o", dibp->ba + dibp->lnt - 1); -return SCPE_OK; -} - -/* Change device vector */ - -t_stat set_vec (UNIT *uptr, int32 arg, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newvec; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newvec = (uint32) get_uint (cptr, 8, VEC_Q + 01000, &r); -if ((r != SCPE_OK) || (newvec <= VEC_Q) || - ((newvec + (dibp->vnum * 4)) >= (VEC_Q + 01000)) || - (newvec & ((dibp->vnum > 1)? 07: 03))) return SCPE_ARG; -dibp->vec = newvec; -return SCPE_OK; -} - -/* Show device vector */ - -t_stat show_vec (FILE *st, UNIT *uptr, int32 arg, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 vec, numvec; - -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -vec = dibp->vec; -if (arg) numvec = arg; -else numvec = dibp->vnum; -if (vec == 0) fprintf (st, "no vector"); -else { fprintf (st, "vector=%o", vec); - if (numvec > 1) fprintf (st, "-%o", vec + (4 * (numvec - 1))); } -return SCPE_OK; -} - -/* Test for conflict in device addresses */ - -t_bool dev_conflict (DIB *curr) -{ -uint32 i, end; -DEVICE *dptr; -DIB *dibp; - -end = curr->ba + curr->lnt - 1; /* get end */ -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if ((dibp == NULL) || (dibp == curr) || - (dptr->flags & DEV_DIS)) continue; - if (((curr->ba >= dibp->ba) && /* overlap start? */ - (curr->ba < (dibp->ba + dibp->lnt))) || - ((end >= dibp->ba) && /* overlap end? */ - (end < (dibp->ba + dibp->lnt)))) { - printf ("Device %s address conflict at %08o\n", - sim_dname (dptr), dibp->ba); - if (sim_log) fprintf (sim_log, - "Device %s address conflict at %08o\n", - sim_dname (dptr), dibp->ba); - return TRUE; } } -return FALSE; -} - -/* Build interrupt tables */ - -void build_int_vec (int32 vloc, int32 ivec, int32 (*iack)(void) ) -{ -if (iack != NULL) int_ack[vloc] = iack; -else int_vec[vloc] = ivec; -return; -} - -/* Build dib_tab from device list */ - -t_bool build_dib_tab (void) -{ -int32 i, j, k; -DEVICE *dptr; -DIB *dibp; - -for (i = 0; i < 32; i++) { /* clear intr tables */ - int_vec[i] = 0; - int_ack[i] = NULL; } -for (i = j = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if (dibp && !(dptr->flags & DEV_DIS)) { /* defined, enabled? */ - if (dibp->vnum > VEC_DEVMAX) return SCPE_IERR; - for (k = 0; k < dibp->vnum; k++) /* loop thru vec */ - build_int_vec (dibp->vloc + k, /* add vector */ - dibp->vec + (k * 4), dibp->ack[k]); - if (dibp->lnt != 0) { /* I/O addresses? */ - dib_tab[j++] = dibp; /* add DIB to dib_tab */ - if (j >= DIB_MAX) return SCPE_IERR; } /* too many? */ - } /* end if enabled */ - } /* end for */ -for (i = 0; (dibp = std_dib[i]) != NULL; i++) { /* loop thru std */ - dib_tab[j++] = dibp; /* add to dib_tab */ - if (j >= DIB_MAX) return SCPE_IERR; } /* too many? */ -dib_tab[j] = NULL; /* end with NULL */ -for (i = 0; (dibp = dib_tab[i]) != NULL; i++) { /* test built dib_tab */ - if (dev_conflict (dibp)) return SCPE_STOP; } /* for conflicts */ -return SCPE_OK; -} - -/* Show dib_tab */ - -t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, j, done = 0; -DEVICE *dptr; -DIB *dibt; - -build_dib_tab (); /* build table */ -while (done == 0) { /* sort ascending */ - done = 1; /* assume done */ - for (i = 0; dib_tab[i + 1] != NULL; i++) { /* check table */ - if (dib_tab[i]->ba > dib_tab[i + 1]->ba) { /* out of order? */ - dibt = dib_tab[i]; /* interchange */ - dib_tab[i] = dib_tab[i + 1]; - dib_tab[i + 1] = dibt; - done = 0; } } /* not done */ - } /* end while */ -for (i = 0; dib_tab[i] != NULL; i++) { /* print table */ - for (j = 0, dptr = NULL; sim_devices[j] != NULL; j++) { - if (((DIB*) sim_devices[j]->ctxt) == dib_tab[i]) { - dptr = sim_devices[j]; - break; } } - fprintf (st, "%07o - %07o\t%s\n", dib_tab[i]->ba, - dib_tab[i]->ba + dib_tab[i]->lnt - 1, - dptr? sim_dname (dptr): "CPU"); - } -return SCPE_OK; -} - -/* Stub auto-configure */ - -t_stat auto_config (uint32 rank, uint32 num) -{ -return SCPE_OK; -} diff --git a/PDP10/pdp10_lp20.c b/PDP10/pdp10_lp20.c deleted file mode 100644 index 343994ae..00000000 --- a/PDP10/pdp10_lp20.c +++ /dev/null @@ -1,599 +0,0 @@ -/* pdp10_lp20.c: PDP-10 LP20 line printer simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - lp20 line printer - - 25-Apr-03 RMS Revised for extended file support - 29-Sep-02 RMS Added variable vector support - Modified to use common Unibus routines - New data structures - 30-May-02 RMS Widened POS to 32b - 06-Jan-02 RMS Added enable/disable support - 30-Nov-01 RMS Added extended SET/SHOW support -*/ - -#include "pdp10_defs.h" - -#define UNIT_DUMMY (1 << UNIT_V_UF) -#define LP_WIDTH 132 /* printer width */ - -/* DAVFU RAM */ - -#define DV_SIZE 143 /* DAVFU size */ -#define DV_DMASK 077 /* data mask per byte */ -#define DV_TOF 0 /* top of form channel */ -#define DV_MAX 11 /* max channel number */ - -/* Translation RAM */ - -#define TX_SIZE 256 /* translation RAM */ -#define TX_AMASK (TX_SIZE - 1) -#define TX_DMASK 07777 -#define TX_V_FL 8 /* flags */ -#define TX_M_FL 017 -/* define TX_INTR 04000 /* interrupt */ -#define TX_DELH 02000 /* delimiter */ -/* define TX_XLAT 01000 /* translate */ -/* define TX_DVFU 00400 /* DAVFU */ -#define TX_SLEW 00020 /* chan vs slew */ -#define TX_VMASK 00017 /* spacing mask */ -#define TX_CHR 0 /* states: pr char */ -#define TX_RAM 1 /* pr translation */ -#define TX_DVU 2 /* DAVFU action */ -#define TX_INT 3 /* interrupt */ -#define TX_GETFL(x) (((x) >> TX_V_FL) & TX_M_FL) - -/* LPCSRA (765400) */ - -#define CSA_GO 0000001 /* go */ -#define CSA_PAR 0000002 /* parity enable NI */ -#define CSA_V_FNC 2 /* function */ -#define CSA_M_FNC 03 -#define FNC_PR 0 /* print */ -#define FNC_TST 1 /* test */ -#define FNC_DVU 2 /* load DAVFU */ -#define FNC_RAM 3 /* load translation RAM */ -#define FNC_INTERNAL 1 /* internal function */ -#define CSA_FNC (CSA_M_FNC << CSA_V_FNC) -#define CSA_V_UAE 4 /* Unibus addr extension */ -#define CSA_UAE (03 << CSA_V_UAE) -#define CSA_IE 0000100 /* interrupt enable */ -#define CSA_DONE 0000200 /* done */ -#define CSA_INIT 0000400 /* init */ -#define CSA_ECLR 0001000 /* clear errors */ -#define CSA_DELH 0002000 /* delimiter hold */ -#define CSA_ONL 0004000 /* online */ -#define CSA_DVON 0010000 /* DAVFU online */ -#define CSA_UNDF 0020000 /* undefined char */ -#define CSA_PZRO 0040000 /* page counter zero */ -#define CSA_ERR 0100000 /* error */ -#define CSA_RW (CSA_DELH | CSA_IE | CSA_UAE | CSA_FNC | CSA_PAR | CSA_GO) -#define CSA_MBZ (CSA_ECLR | CSA_INIT) -#define CSA_GETUAE(x) (((x) & CSA_UAE) << (16 - CSA_V_UAE)) -#define CSA_GETFNC(x) (((x) >> CSA_V_FNC) & CSA_M_FNC) - -/* LPCSRB (765402) */ - -#define CSB_GOE 0000001 /* go error */ -#define CSB_DTE 0000002 /* DEM timing error NI */ -#define CSB_MTE 0000004 /* MSYN error (Ubus timeout) */ -#define CSB_RPE 0000010 /* RAM parity error NI */ -#define CSB_MPE 0000020 /* MEM parity error NI */ -#define CSB_LPE 0000040 /* LPT parity error NI */ -#define CSB_DVOF 0000100 /* DAVFU not ready */ -#define CSB_OFFL 0000200 /* offline */ -#define CSB_TEST 0003400 /* test mode */ -#define CSB_OVFU 0004000 /* optical VFU NI */ -#define CSB_PBIT 0010000 /* data parity bit NI */ -#define CSB_NRDY 0020000 /* printer error NI */ -#define CSB_LA180 0040000 /* LA180 printer NI */ -#define CSB_VLD 0100000 /* valid data NI */ -#define CSB_ECLR (CSB_GOE | CSB_DTE | CSB_MTE | CSB_RPE | CSB_MPE | CSB_LPE) -#define CSB_ERR (CSB_ECLR | CSB_DVOF | CSB_OFFL) -#define CSB_RW CSB_TEST -#define CSB_MBZ (CSB_DTE | CSB_RPE | CSB_MPE | CSB_LPE | CSB_OVFU |\ - CSB_PBIT | CSB_NRDY | CSB_LA180 | CSB_VLD) - -/* LPBA (765404) */ - -/* LPBC (765506) */ - -#define BC_MASK 0007777 /* <15:12> MBZ */ - -/* LPPAGC (765510) */ - -#define PAGC_MASK 0007777 /* <15:12> MBZ */ - -/* LPRDAT (765512) */ - -#define RDAT_MASK 0007777 /* <15:12> MBZ */ - -/* LPCOLC/LPCBUF (765514) */ - -/* LPCSUM/LPPDAT (765516) */ - -extern d10 *M; /* main memory */ -extern int32 int_req; -extern int32 int_vec[32]; -extern int32 ubcs[UBANUM]; /* UBA csr */ -extern int32 ubmap[UBANUM][UMAP_MEMSIZE]; /* UBA map */ - -int32 lpcsa = 0; /* control/status A */ -int32 lpcsb = 0; /* control/status B */ -int32 lpba = 0; /* bus address */ -int32 lpbc = 0; /* byte count */ -int32 lppagc = 0; /* page count */ -int32 lprdat = 0; /* RAM data */ -int32 lpcbuf = 0; /* character buffer */ -int32 lpcolc = 0; /* column count */ -int32 lppdat = 0; /* printer data */ -int32 lpcsum = 0; /* checksum */ -int32 dvptr = 0; /* davfu pointer */ -int32 dvlnt = 0; /* davfu length */ -int32 lp20_irq = 0; /* int request */ -int32 lp20_stopioe = 0; /* stop on error */ -int16 txram[TX_SIZE] = { 0 }; /* translation RAM */ -int16 davfu[DV_SIZE] = { 0 }; /* DAVFU */ - -DEVICE lp20_dev; -t_stat lp20_rd (int32 *data, int32 pa, int32 access); -t_stat lp20_wr (int32 data, int32 pa, int32 access); -int32 lp20_inta (void); -t_stat lp20_svc (UNIT *uptr); -t_stat lp20_reset (DEVICE *dptr); -t_stat lp20_attach (UNIT *uptr, char *ptr); -t_stat lp20_detach (UNIT *uptr); -t_stat lp20_clear_vfu (UNIT *uptr, int32 val, char *cptr, void *desc); -t_bool lp20_print (int32 c); -t_bool lp20_adv (int32 c, t_bool advdvu); -t_bool lp20_davfu (int32 c); -void update_lpcs (int32 flg); - -/* LP data structures - - lp20_dev LPT device descriptor - lp20_unit LPT unit descriptor - lp20_reg LPT register list -*/ - -DIB lp20_dib = { IOBA_LP20, IOLN_LP20, &lp20_rd, &lp20_wr, - 1, IVCL (LP20), VEC_LP20, { &lp20_inta } }; - -UNIT lp20_unit = { - UDATA (&lp20_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lp20_reg[] = { - { ORDATA (LPCSA, lpcsa, 16) }, - { ORDATA (LPCSB, lpcsb, 16) }, - { ORDATA (LPBA, lpba, 16) }, - { ORDATA (LPBC, lpbc, 12) }, - { ORDATA (LPPAGC, lppagc, 12) }, - { ORDATA (LPRDAT, lprdat, 12) }, - { ORDATA (LPCBUF, lpcbuf, 8) }, - { ORDATA (LPCOLC, lpcolc, 8) }, - { ORDATA (LPPDAT, lppdat, 8) }, - { ORDATA (LPCSUM, lpcsum, 8) }, - { ORDATA (DVPTR, dvptr, 7) }, - { ORDATA (DVLNT, dvlnt, 7), REG_RO + REG_NZ }, - { FLDATA (INT, int_req, INT_V_LP20) }, - { FLDATA (IRQ, lp20_irq, 0) }, - { FLDATA (ERR, lpcsa, CSR_V_ERR) }, - { FLDATA (DONE, lpcsa, CSR_V_DONE) }, - { FLDATA (IE, lpcsa, CSR_V_IE) }, - { DRDATA (POS, lp20_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, lp20_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lp20_stopioe, 0) }, - { BRDATA (TXRAM, txram, 8, 12, TX_SIZE) }, - { BRDATA (DAVFU, davfu, 8, 12, DV_SIZE) }, - { ORDATA (DEVADDR, lp20_dib.ba, 32), REG_HRO }, - { ORDATA (DEVVEC, lp20_dib.vec, 16), REG_HRO }, - { NULL } }; - -MTAB lp20_mod[] = { - { UNIT_DUMMY, 0, NULL, "VFUCLEAR", &lp20_clear_vfu }, - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE lp20_dev = { - "LP20", &lp20_unit, lp20_reg, lp20_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lp20_reset, - NULL, &lp20_attach, &lp20_detach, - &lp20_dib, DEV_DISABLE | DEV_UBUS }; - -/* Line printer routines - - lp20_rd I/O page read - lp20_wr I/O page write - lp20_svc process event (printer ready) - lp20_reset process reset - lp20_attach process attach - lp20_detach process detach -*/ - -t_stat lp20_rd (int32 *data, int32 pa, int32 access) -{ -update_lpcs (0); /* update csr's */ -switch ((pa >> 1) & 07) { /* case on PA<3:1> */ -case 00: /* LPCSA */ - *data = lpcsa = lpcsa & ~CSA_MBZ; - break; -case 01: /* LPCSB */ - *data = lpcsb = lpcsb & ~CSB_MBZ; - break; -case 02: /* LPBA */ - *data = lpba; - break; -case 03: /* LPBC */ - *data = lpbc = lpbc & BC_MASK; - break; -case 04: /* LPPAGC */ - *data = lppagc = lppagc & PAGC_MASK; - break; -case 05: /* LPRDAT */ - *data = lprdat = lprdat & RDAT_MASK; - break; -case 06: /* LPCOLC/LPCBUF */ - *data = (lpcolc << 8) | lpcbuf; - break; -case 07: /* LPCSUM/LPPDAT */ - *data = (lpcsum << 8) | lppdat; - break; } /* end case PA */ -return SCPE_OK; -} - -t_stat lp20_wr (int32 data, int32 pa, int32 access) -{ -update_lpcs (0); /* update csr's */ -switch ((pa >> 1) & 07) { /* case on PA<3:1> */ -case 00: /* LPCSA */ - if (access == WRITEB) data = (pa & 1)? - (lpcsa & 0377) | (data << 8): (lpcsa & ~0377) | data; - if (data & CSA_ECLR) { /* error clear? */ - lpcsa = (lpcsa | CSA_DONE) & ~CSA_GO; /* set done, clr go */ - lpcsb = lpcsb & ~CSB_ECLR; /* clear err */ - sim_cancel (&lp20_unit); } /* cancel I/O */ - if (data & CSA_INIT) lp20_reset (&lp20_dev); /* init? */ - if (data & CSA_GO) { /* go set? */ - if ((lpcsa & CSA_GO) == 0) { /* not set before? */ - if (lpcsb & CSB_ERR) lpcsb = lpcsb | CSB_GOE; - lpcsum = 0; /* clear checksum */ - sim_activate (&lp20_unit, lp20_unit.time); } } - else sim_cancel (&lp20_unit); /* go clr, stop DMA */ - lpcsa = (lpcsa & ~CSA_RW) | (data & CSA_RW); - break; -case 01: /* LPCSB */ - break; /* ignore writes to TEST */ -case 02: /* LPBA */ - if (access == WRITEB) data = (pa & 1)? - (lpba & 0377) | (data << 8): (lpba & ~0377) | data; - lpba = data; - break; -case 03: /* LPBC */ - if (access == WRITEB) data = (pa & 1)? - (lpbc & 0377) | (data << 8): (lpbc & ~0377) | data; - lpbc = data & BC_MASK; - lpcsa = lpcsa & ~CSA_DONE; - break; -case 04: /* LPPAGC */ - if (access == WRITEB) data = (pa & 1)? - (lppagc & 0377) | (data << 8): (lppagc & ~0377) | data; - lppagc = data & PAGC_MASK; - break; -case 05: /* LPRDAT */ - if (access == WRITEB) data = (pa & 1)? - (lprdat & 0377) | (data << 8): (lprdat & ~0377) | data; - lprdat = data & RDAT_MASK; - txram[lpcbuf & TX_AMASK] = lprdat; /* load RAM */ - break; -case 06: /* LPCOLC/LPCBUF */ - if ((access == WRITEB) && (pa & 1)) /* odd byte */ - lpcolc = data & 0377; - else { - lpcbuf = data & 0377; /* even byte, word */ - if (access == WRITE) lpcolc = (data >> 8) & 0377; } - break; -case 07: /* LPCSUM/LPPDAT */ - break; } /* read only */ -update_lpcs (0); -return SCPE_OK; -} - -/* Line printer service - - The translation RAM case table is derived from the LP20 spec and - verified against the LP20 RAM simulator in TOPS10 7.04 LPTSPL. - The equations are: - - flags := inter, delim, xlate, paper, delim_hold (from CSRA) - actions : = print_input, print_xlate, davfu_action, interrupt - - if (inter) { - if (!xlate || delim || delim_hold) interrupt; - else if (paper) davfu_action; - else print_xlate; } - else if (paper) { - if (xlate || delim || delim_hold) davfu_action; - else print_input; } - else { - if (xlate || delim || delim_hold) print_xlate; - else print_input; } -*/ - -t_stat lp20_svc (UNIT *uptr) -{ -int32 fnc, i, tbc, temp, txst; -int32 dvld = -2; /* must be even */ -int32 err = 0; -uint16 wd10; -t_bool cont; -a10 ba; - -static const uint32 txcase[32] = { - TX_CHR, TX_RAM, TX_CHR, TX_DVU, TX_RAM, TX_RAM, TX_DVU, TX_DVU, - TX_RAM, TX_RAM, TX_DVU, TX_DVU, TX_RAM, TX_RAM, TX_DVU, TX_DVU, - TX_INT, TX_INT, TX_INT, TX_INT, TX_RAM, TX_INT, TX_DVU, TX_INT, - TX_INT, TX_INT, TX_INT, TX_INT, TX_INT, TX_INT, TX_INT, TX_INT }; - -lpcsa = lpcsa & ~CSA_GO; -ba = CSA_GETUAE (lpcsa) | lpba; -fnc = CSA_GETFNC (lpcsa); -tbc = 010000 - lpbc; -if (((fnc & FNC_INTERNAL) == 0) && ((lp20_unit.flags & UNIT_ATT) == 0)) { - update_lpcs (CSA_ERR); - IORETURN (lp20_stopioe, SCPE_UNATT); } -if ((fnc == FNC_PR) && (dvlnt == 0)) { - update_lpcs (CSA_ERR); - return SCPE_OK; } - -for (i = 0, cont = TRUE; (i < tbc) && cont; ba++, i++) { - if (Map_ReadW (ba, 2, &wd10, MAP)) { /* get word, err? */ - lpcsb = lpcsb | CSB_MTE; /* set NXM error */ - update_lpcs (CSA_ERR); /* set done */ - break; } - lpcbuf = (wd10 >> ((ba & 1)? 8: 0)) & 0377; /* get character */ - lpcsum = (lpcsum + lpcbuf) & 0377; /* add into checksum */ - switch (fnc) { /* switch on function */ - -/* Translation RAM load */ - - case FNC_RAM: /* RAM load */ - txram[(i >> 1) & TX_AMASK] = wd10 & TX_DMASK; - break; - -/* DAVFU RAM load. The DAVFU RAM is actually loaded in bytes, delimited by - a start (354 to 356) and stop (357) byte pair. If the number of bytes - loaded is odd, or no bytes are loaded, the DAVFU is invalid. -*/ - - case FNC_DVU: /* DVU load */ - if ((lpcbuf >= 0354) && (lpcbuf <= 0356)) /* start DVU load? */ - dvld = dvlnt = 0; /* reset lnt */ - else if (lpcbuf == 0357) { /* stop DVU load? */ - dvptr = 0; /* reset ptr */ - if (dvld & 1) dvlnt = 0; } /* if odd, invalid */ - else if (dvld == 0) { /* even state? */ - temp = lpcbuf & DV_DMASK; - dvld = 1; } - else if (dvld == 1) { /* odd state? */ - if (dvlnt < DV_SIZE) davfu[dvlnt++] = - temp | ((lpcbuf & DV_DMASK) << 6); - dvld = 0; } - break; - -/* Print characters */ - - case FNC_PR: /* print */ - lprdat = txram[lpcbuf]; /* get RAM char */ - txst = (TX_GETFL (lprdat) << 1) | /* get state */ - ((lpcsa & CSA_DELH)? 1: 0); /* plus delim hold */ - if (lprdat & TX_DELH) lpcsa = lpcsa | CSA_DELH; - else lpcsa = lpcsa & ~CSA_DELH; - lpcsa = lpcsa & ~CSA_UNDF; /* assume char ok */ - switch (txcase[txst]) { /* case on state */ - case TX_CHR: /* take char */ - cont = lp20_print (lpcbuf); - break; - case TX_RAM: /* take translation */ - cont = lp20_print (lprdat); - break; - case TX_DVU: /* DAVFU action */ - if (lprdat & TX_SLEW) - cont = lp20_adv (lprdat & TX_VMASK, TRUE); - else cont = lp20_davfu (lprdat & TX_VMASK); - break; - case TX_INT: /* interrupt */ - lpcsa = lpcsa | CSA_UNDF; /* set flag */ - cont = FALSE; /* force stop */ - break; } /* end case char state */ - break; - case FNC_TST: /* test */ - break; } /* end case function */ - } /* end for */ -lpba = ba & 0177777; -lpcsa = (lpcsa & ~CSA_UAE) | ((ba >> (16 - CSA_V_UAE)) & CSA_UAE); -lpbc = (lpbc + i) & BC_MASK; -if (lpbc) update_lpcs (CSA_MBZ); /* intr, but not done */ -else update_lpcs (CSA_DONE); /* intr and done */ -if ((fnc == FNC_PR) && ferror (lp20_unit.fileref)) { - perror ("LP I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -return SCPE_OK; -} - -/* Print routines - - lp20_print print a character - lp20_adv advance n lines - lp20_davfu advance to channel on VFU - - Return TRUE to continue printing, FALSE to stop -*/ - -t_bool lp20_print (int32 c) -{ -t_bool r = TRUE; -int32 i, rpt = 1; - -lppdat = c & 0177; /* mask char to 7b */ -if (lppdat == 000) return TRUE; /* NUL? no op */ -if (lppdat == 012) return lp20_adv (1, TRUE); /* LF? adv carriage */ -if (lppdat == 014) return lp20_davfu (DV_TOF); /* FF? top of form */ -if (lppdat == 015) lpcolc = 0; /* CR? reset col cntr */ -else if (lppdat == 011) { /* TAB? simulate */ - lppdat = ' '; /* with spaces */ - if (lpcolc >= 128) { - r = lp20_adv (1, TRUE); /* eol? adv carriage */ - rpt = 8; } /* adv to col 9 */ - else rpt = 8 - (lpcolc & 07); } /* else adv 1 to 8 */ -else { if (lppdat < 040) lppdat = ' '; /* cvt non-prnt to spc */ - if (lpcolc >= LP_WIDTH) /* line full? */ - r = lp20_adv (1, TRUE); } /* adv carriage */ -for (i = 0; i < rpt; i++) putc (lppdat, lp20_unit.fileref); -lp20_unit.pos = lp20_unit.pos + rpt; -lpcolc = lpcolc + rpt; -return r; -} - -t_bool lp20_adv (int32 cnt, t_bool dvuadv) -{ -int32 i; - -if (cnt == 0) return TRUE; -lpcolc = 0; /* reset col cntr */ -for (i = 0; i < cnt; i++) putc ('\n', lp20_unit.fileref); -lp20_unit.pos = lp20_unit.pos + cnt; /* print 'n' newlines */ -if (dvuadv) dvptr = (dvptr + cnt) % dvlnt; /* update DAVFU ptr */ -if (davfu[dvptr] & (1 << DV_TOF)) { /* at top of form? */ - if (lppagc = (lppagc - 1) & PAGC_MASK) { /* decr page cntr */ - lpcsa = lpcsa & ~CSA_PZRO; /* update status */ - return TRUE; } - else { - lpcsa = lpcsa | CSA_PZRO; /* stop if zero */ - return FALSE; } } -return TRUE; -} - -t_bool lp20_davfu (int32 cnt) -{ -int i; - -if (cnt > DV_MAX) cnt = 7; /* inval chan? */ -for (i = 0; i < dvlnt; i++) { /* search DAVFU */ - dvptr = dvptr + 1; /* adv DAVFU ptr */ - if (dvptr >= dvlnt) dvptr = 0; /* wrap at end */ - if (davfu[dvptr] & (1 << cnt)) { /* channel stop set? */ - if (cnt) return lp20_adv (i + 1, FALSE); /* ~TOF, adv */ - if (lpcolc) lp20_adv (1, FALSE); /* TOF, need newline? */ - putc ('\f', lp20_unit.fileref); /* print form feed */ - lp20_unit.pos = lp20_unit.pos + 1; - if (lppagc = (lppagc - 1) & PAGC_MASK) { /* decr page cntr */ - lpcsa = lpcsa & ~CSA_PZRO; /* update status */ - return TRUE; } - else { - lpcsa = lpcsa | CSA_PZRO; /* stop if zero */ - return FALSE; } } - } /* end for */ -dvlnt = 0; /* DAVFU error */ -return FALSE; -} - -/* Update LPCSA, optionally request interrupt */ - -void update_lpcs (int32 flg) -{ -if (flg) lp20_irq = 1; /* set int req */ -lpcsa = (lpcsa | flg) & ~(CSA_MBZ | CSA_ERR | CSA_ONL | CSA_DVON); -lpcsb = (lpcsb | CSB_OFFL | CSB_DVOF) & ~CSB_MBZ; -if (lp20_unit.flags & UNIT_ATT) { - lpcsa = lpcsa | CSA_ONL; - lpcsb = lpcsb & ~CSB_OFFL; } -else lpcsa = lpcsa & ~CSA_DONE; -if (dvlnt) { - lpcsa = lpcsa | CSA_DVON; - lpcsb = lpcsb & ~CSB_DVOF; } -if (lpcsb & CSB_ERR) lpcsa = lpcsa | CSA_ERR; -if ((lpcsa & CSA_IE) && lp20_irq) int_req = int_req | INT_LP20; -else int_req = int_req & ~INT_LP20; -return; -} - -/* Acknowledge interrupt (clear internal request) */ - -int32 lp20_inta (void) -{ -lp20_irq = 0; /* clear int req */ -return lp20_dib.vec; -} - -t_stat lp20_reset (DEVICE *dptr) -{ -lpcsa = CSA_DONE; -lpcsb = 0; -lpba = lpbc = lppagc = lpcolc = 0; /* clear registers */ -lprdat = lppdat = lpcbuf = lpcsum = 0; -lp20_irq = 0; /* clear int req */ -dvptr = 0; /* reset davfu ptr */ -sim_cancel (&lp20_unit); /* deactivate unit */ -update_lpcs (0); /* update status */ -return SCPE_OK; -} - -t_stat lp20_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); /* attach file */ -if (lpcsa & CSA_ONL) return reason; /* just file chg? */ -if (sim_is_active (&lp20_unit)) update_lpcs (0); /* busy? no int */ -else update_lpcs (CSA_MBZ); /* interrupt */ -return reason; -} - -t_stat lp20_detach (UNIT *uptr) -{ -t_stat reason; - -reason = detach_unit (uptr); -sim_cancel (&lp20_unit); -lpcsa = lpcsa & ~CSA_GO; -update_lpcs (CSA_MBZ); -return reason; -} - -t_stat lp20_clear_vfu (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int i; - -if (!get_yn ("Clear DAVFU? [N]", FALSE)) return SCPE_OK; -for (i = 0; i < DV_SIZE; i++) davfu[i] = 0; -dvlnt = dvptr = 0; -update_lpcs (0); -return SCPE_OK; -} diff --git a/PDP10/pdp10_mdfp.c b/PDP10/pdp10_mdfp.c deleted file mode 100644 index 5c3e1ad9..00000000 --- a/PDP10/pdp10_mdfp.c +++ /dev/null @@ -1,688 +0,0 @@ -/* pdp10_mdfp.c: PDP-10 multiply/divide and floating point simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - Instructions handled in this module: - imul integer multiply - idiv integer divide - mul multiply - div divide - dmul double precision multiply - ddiv double precision divide - fad(r) floating add (and round) - fsb(r) floating subtract (and round) - fmp(r) floating multiply (and round) - fdv(r) floating divide and round - fsc floating scale - fix(r) floating to fixed (and round) - fltr fixed to floating and round - dfad double precision floating add/subtract - dfmp double precision floating multiply - dfdv double precision floating divide - - The PDP-10 stores double (quad) precision integers in sequential - AC's or memory locations. Integers are stored in 2's complement - form. Only the sign of the high order word matters; the signs - in low order words are ignored on input and set to the sign of - the result on output. Quad precision integers exist only in the - AC's as the result of a DMUL or the dividend of a DDIV. - - 0 00000000011111111112222222222333333 - 0 12345678901234567890123456789012345 - +-+-----------------------------------+ - |S| high order integer | AC(n), A - +-+-----------------------------------+ - |S| low order integer | AC(n + 1), A + 1 - +-+-----------------------------------+ - |S| low order integer | AC(n + 2) - +-+-----------------------------------+ - |S| low order integer | AC(n + 3) - +-+-----------------------------------+ - - The PDP-10 supports two floating point formats: single and double - precision. In both, the exponent is 8 bits, stored in excess - 128 notation. The fraction is expected to be normalized. A - single precision floating point number has 27 bits of fraction; - a double precision number has 62 bits of fraction (the sign - bit of the second word is ignored and is set to zero). - - In a negative floating point number, the exponent is stored in - one's complement form, the fraction in two's complement form. - - 0 00000000 011111111112222222222333333 - 0 12345678 901234567890123456789012345 - +-+--------+---------------------------+ - |S|exponent| high order fraction | AC(n), A - +-+--------+---------------------------+ - |0| low order fraction | AC(n + 1), A + 1 - +-+------------------------------------+ - - Note that treatment of the sign is different for double precision - integers and double precision floating point. DMOVN (implemented - as an inline macro) follows floating point conventions. - - The original PDP-10 CPU (KA10) used a different format for double - precision numbers and included certain instructions to make - software support easier. These instructions were phased out in - the KL10 and KS10 and are treated as MUUO's. - - The KL10 added extended precision (11-bit exponent) floating point - format (so-called G floating). These instructions were not - implemented in the KS10 and are treated as MUUO's. - - 31-Aug-01 RMS Changed int64 to t_int64 for Windoze - 10-Aug-01 RMS Removed register in declarations -*/ - -#include "pdp10_defs.h" -#include - -struct ufp { /* unpacked fp number */ - int32 sign; /* sign */ - int32 exp; /* exponent */ - t_uint64 fhi; /* fraction high */ - t_uint64 flo; }; /* for double prec */ - -typedef struct ufp UFP; - -#define MSK32 0xFFFFFFFF -#define FIT27 (DMASK - 0x07FFFFFF) -#define FIT32 (DMASK - MSK32) -#define SFRC TRUE /* frac 2's comp */ -#define AFRC FALSE /* frac abs value */ - -/* In packed floating point number */ - -#define FP_BIAS 0200 /* exponent bias */ -#define FP_N_FHI 27 /* # of hi frac bits */ -#define FP_V_FHI 0 /* must be zero */ -#define FP_M_FHI 0000777777777 -#define FP_N_EXP 8 /* # of exp bits */ -#define FP_V_EXP (FP_V_FHI + FP_N_FHI) -#define FP_M_EXP 0377 -#define FP_V_SIGN (FP_V_EXP + FP_N_EXP) /* sign */ -#define FP_N_FLO 35 /* # of lo frac bits */ -#define FP_V_FLO 0 /* must be zero */ -#define FP_M_FLO 0377777777777 -#define GET_FPSIGN(x) ((int32) (((x) >> FP_V_SIGN) & 1)) -#define GET_FPEXP(x) ((int32) (((x) >> FP_V_EXP) & FP_M_EXP)) -#define GET_FPHI(x) ((x) & FP_M_FHI) -#define GET_FPLO(x) ((x) & FP_M_FLO) - -/* In unpacked floating point number */ - -#define FP_N_GUARD 1 /* # of guard bits */ -#define FP_V_UFLO FP_N_GUARD /* <35:1> */ -#define FP_V_URNDD (FP_V_UFLO - 1) /* dp round bit */ -#define FP_V_UFHI (FP_V_UFLO + FP_N_FLO) /* <62:36> */ -#define FP_V_URNDS (FP_V_UFHI - 1) /* sp round bit */ -#define FP_V_UCRY (FP_V_UFHI + FP_N_FHI) /* <63> */ -#define FP_V_UNORM (FP_V_UCRY - 1) /* normalized bit */ -#define FP_UFHI 0x7FFFFFF000000000 -#define FP_UFLO 0x0000000FFFFFFFFE -#define FP_UFRAC 0x7FFFFFFFFFFFFFFE -#define FP_URNDD 0x0000000000000001 -#define FP_URNDS 0x0000000800000000 -#define FP_UNORM 0x4000000000000000 -#define FP_UCRY 0x8000000000000000 -#define FP_ONES 0xFFFFFFFFFFFFFFFF - -#define UNEG(x) ((~x) + 1) -#define DUNEG(x) x.flo = UNEG (x.flo); x.fhi = ~x.fhi + (x.flo == 0) - -extern d10 *ac_cur; /* current AC block */ -extern int32 flags; /* flags */ -void mul (d10 a, d10 b, d10 *rs); -void funpack (d10 h, d10 l, UFP *r, t_bool sgn); -void fnorm (UFP *r, t_int64 rnd); -d10 fpack (UFP *r, d10 *lo, t_bool fdvneg); - -/* Integer multiply - checked against KS-10 ucode */ - -d10 imul (d10 a, d10 b) -{ -d10 rs[2]; - -if ((a == SIGN) && (b == SIGN)) { /* KS10 hack */ - SETF (F_AOV | F_T1); /* -2**35 squared */ - return SIGN; } -mul (a, b, rs); /* mpy, dprec result */ -if (rs[0] && (rs[0] != ONES)) { /* high not all sign? */ - rs[1] = TSTS (a ^ b)? SETS (rs[1]): CLRS (rs[1]); /* set sign */ - SETF (F_AOV | F_T1); } /* overflow */ -return rs[1]; -} - -/* Integer divide, return quotient, remainder - checked against KS10 ucode - The KS10 does not recognize -2^35/-1 as an error. Instead, it produces - 2^35 (that is, -2^35) as the incorrect result. -*/ - -t_bool idiv (d10 a, d10 b, d10 *rs) -{ -d10 dvd = ABS (a); /* make ops positive */ -d10 dvr = ABS (b); - -if (dvr == 0) { /* divide by 0? */ - SETF (F_DCK | F_AOV | F_T1); /* set flags, return */ - return FALSE; } -rs[0] = dvd / dvr; /* get quotient */ -rs[1] = dvd % dvr; /* get remainder */ -if (TSTS (a ^ b)) rs[0] = NEG (rs[0]); /* sign of result */ -if (TSTS (a)) rs[1] = NEG (rs[1]); /* sign of remainder */ -return TRUE; -} - -/* Multiply, return double precision result - checked against KS10 ucode */ - -void mul (d10 s1, d10 s2, d10 *rs) -{ -t_uint64 a = ABS (s1); -t_uint64 b = ABS (s2); -t_uint64 t, u, r; - -if ((a == 0) || (b == 0)) { /* operand = 0? */ - rs[0] = rs[1] = 0; /* result 0 */ - return; } -if ((a & FIT32) || (b & FIT32)) { /* fit in 64b? */ - t = a >> 18; /* no, split in half */ - a = a & RMASK; /* "dp" multiply */ - u = b >> 18; - b = b & RMASK; - r = (a * b) + (((a * u) + (b * t)) << 18); /* low is only 35b */ - rs[0] = ((t * u) << 1) + (r >> 35); /* so lsh hi 1 */ - rs[1] = r & MMASK; } -else { r = a * b; /* fits, native mpy */ - rs[0] = r >> 35; /* split at bit 35 */ - rs[1] = r & MMASK; } - -if (TSTS (s1 ^ s2)) { MKDNEG (rs); } /* result -? */ -else if (TSTS (rs[0])) { /* result +, 2**70? */ - SETF (F_AOV | F_T1); /* overflow */ - rs[1] = SETS (rs[1]); } /* consistent - */ -return; -} - -/* Divide, return quotient and remainder - checked against KS10 ucode - Note that the initial divide check catches the case -2^70/-2^35; - thus, the quotient can have at most 35 bits. -*/ - -t_bool divi (int32 ac, d10 b, d10 *rs) -{ -int32 p1 = ADDAC (ac, 1); -d10 dvr = ABS (b); /* make divr positive */ -t_int64 t; -int32 i; -d10 dvd[2]; - -dvd[0] = AC(ac); /* divd high */ -dvd[1] = CLRS (AC(p1)); /* divd lo, clr sgn */ -if (TSTS (AC(ac))) { DMOVN (dvd); } /* make divd positive */ -if (dvd[0] >= dvr) { /* divide fail? */ - SETF (F_AOV | F_DCK | F_T1); /* set flags, return */ - return FALSE; } -if (dvd[0] & FIT27) { /* fit in 63b? */ - for (i = 0, rs[0] = 0; i < 35; i++) { /* 35 quotient bits */ - dvd[0] = (dvd[0] << 1) | ((dvd[1] >> 34) & 1); - dvd[1] = (dvd[1] << 1) & MMASK; /* shift dividend */ - rs[0] = rs[0] << 1; /* shift quotient */ - if (dvd[0] >= dvr) { /* subtract work? */ - dvd[0] = dvd[0] - dvr; /* quo bit is 1 */ - rs[0] = rs[0] + 1; } } - rs[1] = dvd[0]; } /* store remainder */ -else { t = (dvd[0] << 35) | dvd[1]; /* concatenate */ - rs[0] = t / dvr; /* quotient */ - rs[1] = t % dvr; } /* remainder */ -if (TSTS (AC(ac) ^ b)) rs[0] = NEG (rs[0]); /* sign of result */ -if (TSTS (AC(ac))) rs[1] = NEG (rs[1]); /* sign of remainder */ -return TRUE; -} - -/* Double precision multiply. This is done the old fashioned way. Cross - product multiplies would be a lot faster but would require more code. -*/ - -void dmul (int32 ac, d10 *mpy) -{ -int32 p1 = ADDAC (ac, 1); -int32 p2 = ADDAC (ac, 2); -int32 p3 = ADDAC (ac, 3); -int32 i; -d10 mpc[2], sign; - -mpc[0] = AC(ac); /* mplcnd hi */ -mpc[1] = CLRS (AC(p1)); /* mplcnd lo, clr sgn */ -sign = mpc[0] ^ mpy[0]; /* sign of result */ -if (TSTS (mpc[0])) { DMOVN (mpc); } /* get abs (mpcnd) */ -if (TSTS (mpy[0])) { DMOVN (mpy); } /* get abs (mpyer) */ -else mpy[1] = CLRS (mpy[1]); /* clear mpy lo sign */ -AC(ac) = AC(p1) = AC(p2) = AC(p3) = 0; /* clear AC's */ -if (((mpy[0] | mpy[1]) == 0) || ((mpc[0] | mpc[1]) == 0)) return; -for (i = 0; i < 71; i++) { /* 71 mpyer bits */ - if (i) { /* shift res, mpy */ - AC(p3) = (AC(p3) >> 1) | ((AC(p2) & 1) << 34); - AC(p2) = (AC(p2) >> 1) | ((AC(p1) & 1) << 34); - AC(p1) = (AC(p1) >> 1) | ((AC(ac) & 1) << 34); - AC(ac) = AC(ac) >> 1; - mpy[1] = (mpy[1] >> 1) | ((mpy[0] & 1) << 34); - mpy[0] = mpy[0] >> 1; } - if (mpy[1] & 1) { /* if mpy lo bit = 1 */ - AC(p1) = AC(p1) + mpc[1]; - AC(ac) = AC(ac) + mpc[0] + (TSTS (AC(p1) != 0)); - AC(p1) = CLRS (AC(p1)); } } -if (TSTS (sign)) { /* result minus? */ - AC(p3) = (-AC(p3)) & MMASK; /* quad negate */ - AC(p2) = (~AC(p2) + (AC(p3) == 0)) & MMASK; - AC(p1) = (~AC(p1) + (AC(p2) == 0)) & MMASK; - AC(ac) = (~AC(ac) + (AC(p1) == 0)) & DMASK; } -else if (TSTS (AC(ac))) SETF (F_AOV | F_T1); /* wrong sign */ -if (TSTS (AC(ac))) { /* if result - */ - AC(p1) = SETS (AC(p1)); /* make signs consistent */ - AC(p2) = SETS (AC(p2)); - AC(p3) = SETS (AC(p3)); } -return; -} - -/* Double precision divide - checked against KS10 ucode */ - -void ddiv (int32 ac, d10 *dvr) -{ -int32 i, cryin; -d10 sign, qu[2], dvd[4]; - -dvd[0] = AC(ac); /* save dividend */ -for (i = 1; i < 4; i++) dvd[i] = CLRS (AC(ADDAC (ac, i))); -sign = AC(ac) ^ dvr[0]; /* sign of result */ -if (TSTS (AC(ac))) { /* get abs (dividend) */ - for (i = 3, cryin = 1; i > 0; i--) { /* negate quad */ - dvd[i] = (~dvd[i] + cryin) & MMASK; /* comp + carry in */ - if (dvd[i]) cryin = 0; } /* next carry in */ - dvd[0] = (~dvd[0] + cryin) & DMASK; } -if (TSTS (dvr[0])) { DMOVN (dvr); } /* get abs (divisor) */ -else dvr[1] = CLRS (dvr[1]); -if (DCMPGE (dvd, dvr)) { /* will divide work? */ - SETF (F_AOV | F_DCK | F_T1); /* no, set flags */ - return; } -qu[0] = qu[1] = 0; /* clear quotient */ -for (i = 0; i < 70; i++) { /* 70 quotient bits */ - dvd[0] = ((dvd[0] << 1) | ((dvd[1] >> 34) & 1)) & DMASK;; - dvd[1] = ((dvd[1] << 1) | ((dvd[2] >> 34) & 1)) & MMASK; - dvd[2] = ((dvd[2] << 1) | ((dvd[3] >> 34) & 1)) & MMASK; - dvd[3] = (dvd[3] << 1) & MMASK; /* shift dividend */ - qu[0] = (qu[0] << 1) | ((qu[1] >> 34) & 1); /* shift quotient */ - qu[1] = (qu[1] << 1) & MMASK; - if (DCMPGE (dvd, dvr)) { /* subtract work? */ - dvd[0] = dvd[0] - dvr[0] - (dvd[1] < dvr[1]); - dvd[1] = (dvd[1] - dvr[1]) & MMASK; /* do subtract */ - qu[1] = qu[1] + 1; } } /* set quotient bit */ -if (TSTS (sign) && (qu[0] | qu[1])) { MKDNEG (qu); } -if (TSTS (AC(ac)) && (dvd[0] | dvd[1])) { MKDNEG (dvd); } -AC(ac) = qu[0]; /* quotient */ -AC(ADDAC(ac, 1)) = qu[1]; -AC(ADDAC(ac, 2)) = dvd[0]; /* remainder */ -AC(ADDAC(ac, 3)) = dvd[1]; -return; -} - -/* Single precision floating add - checked against KS10 ucode - The KS10 shifts the smaller operand regardless of the exponent diff. - This code will not shift more than 63 places; shifts beyond that - cannot change the value of the smaller operand. - - If the signs of the operands are the same, the result sign is the - same as the source sign; the sign of the result fraction is actually - part of the data. If the signs of the operands are different, the - result sign is determined by the fraction sign. -*/ - -d10 fad (d10 op1, d10 op2, t_bool rnd, int32 inv) -{ -int32 ediff; -UFP a, b, t; - -if (inv) op2 = NEG (op2); /* subtract? -b */ -if (op1 == 0) funpack (op2, 0, &a, AFRC); /* a = 0? result is b */ -else if (op2 == 0) funpack (op1, 0, &a, AFRC); /* b = 0? result is a */ -else { funpack (op1, 0, &a, SFRC); /* unpack operands */ - funpack (op2, 0, &b, SFRC); /* fracs are 2's comp */ - ediff = a.exp - b.exp; /* get exp diff */ - if (ediff < 0) { /* a < b? switch */ - t = a; - a = b; - b = t; - ediff = -ediff; } - if (ediff > 63) ediff = 63; /* cap diff at 63 */ - if (ediff) b.fhi = (t_int64) b.fhi >> ediff; /* shift b (signed) */ - a.fhi = a.fhi + b.fhi; /* add fractions */ - if (a.sign ^ b.sign) { /* add or subtract? */ - if (a.fhi & FP_UCRY) { /* subtract, frac -? */ - a.fhi = UNEG (a.fhi); /* complement result */ - a.sign = 1; } /* result is - */ - else a.sign = 0; } /* result is + */ - else { - if (a.sign) a.fhi = UNEG (a.fhi); /* add, src -? comp */ - if (a.fhi & FP_UCRY) { /* check for carry */ - a.fhi = a.fhi >> 1; /* flo won't be used */ - a.exp = a.exp + 1; } } } -fnorm (&a, (rnd? FP_URNDS: 0)); /* normalize, round */ -return fpack (&a, NULL, FALSE); -} - -/* Single precision floating multiply. Because the fractions are 27b, - a 64b multiply can be used for the fraction multiply. The 27b - fractions are positioned 0'frac'0000, resulting in 00'hifrac'0..0. - The extra 0 is accounted for by biasing the result exponent. -*/ - -#define FP_V_SPM (FP_V_UFHI - (32 - FP_N_FHI - 1)) -d10 fmp (d10 op1, d10 op2, t_bool rnd) -{ -UFP a, b; - -funpack (op1, 0, &a, AFRC); /* unpack operands */ -funpack (op2, 0, &b, AFRC); /* fracs are abs val */ -if ((a.fhi == 0) || (b.fhi == 0)) return 0; /* either 0? */ -a.sign = a.sign ^ b.sign; /* result sign */ -a.exp = a.exp + b.exp - FP_BIAS + 1; /* result exponent */ -a.fhi = (a.fhi >> FP_V_SPM) * (b.fhi >> FP_V_SPM); /* high 27b of result */ -fnorm (&a, (rnd? FP_URNDS: 0)); /* normalize, round */ -return fpack (&a, NULL, FALSE); -} - -/* Single precision floating divide. Because the fractions are 27b, a - 64b divide can be used for the fraction divide. Note that 28b-29b - of fraction are developed; the code will do one special normalize to - make sure that the 28th bit is not lost. Also note the special - treatment of negative quotients with non-zero remainders; this - implements the note on p2-23 of the Processor Reference Manual. -*/ - -t_bool fdv (d10 op1, d10 op2, d10 *rs, t_bool rnd) -{ -UFP a, b; -t_uint64 savhi; -t_bool rem = FALSE; - -funpack (op1, 0, &a, AFRC); /* unpack operands */ -funpack (op2, 0, &b, AFRC); /* fracs are abs val */ -if (a.fhi >= 2 * b.fhi) { /* will divide work? */ - SETF (F_AOV | F_DCK | F_FOV | F_T1); - return FALSE; } -if (savhi = a.fhi) { /* dvd = 0? quo = 0 */ - a.sign = a.sign ^ b.sign; /* result sign */ - a.exp = a.exp - b.exp + FP_BIAS + 1; /* result exponent */ - a.fhi = a.fhi / (b.fhi >> (FP_N_FHI + 1)); /* do divide */ - if (a.sign && (savhi != (a.fhi * (b.fhi >> (FP_N_FHI + 1))))) - rem = TRUE; /* KL/KS hack */ - a.fhi = a.fhi << (FP_V_UNORM - FP_N_FHI - 1); /* put quo in place */ - if ((a.fhi & FP_UNORM) == 0) { /* normalize 1b */ - a.fhi = a.fhi << 1; /* before masking */ - a.exp = a.exp - 1; } - a.fhi = a.fhi & (FP_UFHI | FP_URNDS); } /* mask quo to 28b */ -fnorm (&a, (rnd? FP_URNDS: 0)); /* normalize, round */ -*rs = fpack (&a, NULL, rem); /* pack result */ -return TRUE; -} - -/* Single precision floating scale. */ - -d10 fsc (d10 val, a10 ea) -{ -int32 sc = LIT8 (ea); -UFP a; - -if (val == 0) return 0; -funpack (val, 0, &a, AFRC); /* unpack operand */ -if (ea & RSIGN) a.exp = a.exp - sc; /* adjust exponent */ -else a.exp = a.exp + sc; -fnorm (&a, 0); /* renormalize */ -return fpack (&a, NULL, FALSE); /* pack result */ -} - -/* Float integer operand and round */ - -d10 fltr (d10 mb) -{ -UFP a; -d10 val = ABS (mb); - -a.sign = GET_FPSIGN (mb); /* get sign */ -a.exp = FP_BIAS + 36; /* initial exponent */ -a.fhi = val << (FP_V_UNORM - 35); /* left justify op */ -a.flo = 0; -fnorm (&a, FP_URNDS); /* normalize, round */ -return fpack (&a, NULL, FALSE); /* pack result */ -} - -/* Fix and truncate/round floating operand */ - -void fix (int32 ac, d10 mb, t_bool rnd) -{ -int32 sc; -t_uint64 so; -UFP a; - -funpack (mb, 0, &a, AFRC); /* unpack operand */ -if (a.exp > (FP_BIAS + FP_N_FHI + FP_N_EXP)) SETF (F_AOV | F_T1); -else if (a.exp < (FP_BIAS - 1)) AC(ac) = 0; -else { sc = FP_V_UNORM - (a.exp - FP_BIAS) + 1; - AC(ac) = a.fhi >> sc; - if (rnd) { - so = a.fhi << (64 - sc); - if (so >= (0x8000000000000000 + a.sign)) AC(ac) = AC(ac) + 1; } - if (a.sign) AC(ac) = NEG (AC(ac)); } -return; -} - -/* Double precision floating add/subtract - Since a.flo is 0, adding b.flo is just a copy - this is incorporated into - the denormalization step. If there's no denormalization, bflo is zero too. -*/ - -void dfad (int32 ac, d10 *rs, int32 inv) -{ -int32 p1 = ADDAC (ac, 1); -int32 ediff; -UFP a, b, t; - -if (inv) { DMOVN (rs); } /* subtract? -b */ -if ((AC(ac) | AC(p1)) == 0) funpack (rs[0], rs[1], &a, AFRC); - /* a == 0? sum = b */ -else if ((rs[0] | rs[1]) == 0) funpack (AC(ac), AC(p1), &a, AFRC); - /* b == 0? sum = a */ -else { - funpack (AC(ac), AC(p1), &a, SFRC); /* unpack operands */ - funpack (rs[0], rs[1], &b, SFRC); - ediff = a.exp - b.exp; /* get exp diff */ - if (ediff < 0) { /* a < b? switch */ - t = a; - a = b; - b = t; - ediff = -ediff; } - if (ediff > 127) ediff = 127; /* cap diff at 127 */ - if (ediff > 63) { /* diff > 63? */ - a.flo = (t_int64) b.fhi >> (ediff - 64); /* b hi to a lo */ - b.fhi = b.sign? FP_ONES: 0; } /* hi = all sign */ - else if (ediff) { /* diff <= 63 */ - a.flo = (b.flo >> ediff) | (b.fhi << (64 - ediff)); - b.fhi = (t_int64) b.fhi >> ediff; } /* shift b (signed) */ - a.fhi = a.fhi + b.fhi; /* do add */ - if (a.sign ^ b.sign) { /* add or subtract? */ - if (a.fhi & FP_UCRY) { /* subtract, frac -? */ - DUNEG (a); /* complement result */ - a.sign = 1; } /* result is - */ - else a.sign = 0; } /* result is + */ - else { - if (a.sign) { DUNEG (a); }; /* add, src -? comp */ - if (a.fhi & FP_UCRY) { /* check for carry */ - a.fhi = a.fhi >> 1; /* flo won't be used */ - a.exp = a.exp + 1; } } } -fnorm (&a, FP_URNDD); /* normalize, round */ -AC(ac) = fpack (&a, &AC(p1), FALSE); /* pack result */ -return; -} - -/* Double precision floating multiply - The 62b fractions are multiplied, with cross products, to produce a - 124b fraction with two leading and two trailing 0's. Because the - product has 2 leading 0's, instead of the normal 1, an extra - normalization step is needed. Accordingly, the exponent calculation - increments the result exponent, to compensate for normalization. -*/ - -void dfmp (int32 ac, d10 *rs) -{ -int32 p1 = ADDAC (ac, 1); -t_uint64 xh, xl, yh, yl, mid; -UFP a, b; - -funpack (AC(ac), AC(p1), &a, AFRC); /* unpack operands */ -funpack (rs[0], rs[1], &b, AFRC); -if ((a.fhi == 0) || (b.fhi == 0)) { /* either 0? result 0 */ - AC(ac) = AC(p1) = 0; - return; } -a.sign = a.sign ^ b.sign; /* result sign */ -a.exp = a.exp + b.exp - FP_BIAS + 1; /* result exponent */ -xh = a.fhi >> 32; /* split 62b fracs */ -xl = a.fhi & MSK32; /* into 32b halves */ -yh = b.fhi >> 32; -yl = b.fhi & MSK32; -a.fhi = xh * yh; /* hi xproduct */ -a.flo = xl * yl; /* low xproduct */ -mid = (xh * yl) + (yh * xl); /* fits in 64b */ -a.flo = a.flo + (mid << 32); /* add mid lo to lo */ -a.fhi = a.fhi + ((mid >> 32) & MSK32) + (a.flo < (mid << 32)); -fnorm (&a, FP_URNDD); /* normalize, round */ -AC(ac) = fpack (&a, &AC(p1), FALSE); /* pack result */ -return; -} - -/* Double precision floating divide - This algorithm develops a full 62 bits of quotient, plus one rounding - bit, in the low order 63b of a 64b number. To do this, we must assure - that the initial divide step generates a 1. If it would fail, shift - the dividend left and decrement the result exponent accordingly. -*/ - -void dfdv (int32 ac, d10 *rs) -{ -int32 p1 = ADDAC (ac, 1); -int32 i; -t_uint64 qu = 0; -UFP a, b; - -funpack (AC(ac), AC(p1), &a, AFRC); /* unpack operands */ -funpack (rs[0], rs[1], &b, AFRC); -if (a.fhi >= 2 * b.fhi) { /* will divide work? */ - SETF (F_AOV | F_DCK | F_FOV | F_T1); - return; } -if (a.fhi) { /* dvd = 0? quo = 0 */ - a.sign = a.sign ^ b.sign; /* result sign */ - a.exp = a.exp - b.exp + FP_BIAS + 1; /* result exponent */ - if (a.fhi < b.fhi) { /* make sure initial */ - a.fhi = a.fhi << 1; /* divide step will work */ - a.exp = a.exp - 1; } - for (i = 0; i < 63; i++) { /* 63b of quotient */ - qu = qu << 1; /* shift quotient */ - if (a.fhi >= b.fhi) { /* will div work? */ - a.fhi = a.fhi - b.fhi; /* sub, quo = 1 */ - qu = qu + 1; } - a.fhi = a.fhi << 1; } /* shift dividend */ - a.fhi = qu; } -fnorm (&a, FP_URNDD); /* normalize, round */ -AC(ac) = fpack (&a, &AC(p1), FALSE); /* pack result */ -return; -} - -/* Unpack floating point operand */ - -void funpack (d10 h, d10 l, UFP *r, t_bool sgn) -{ -d10 fphi, fplo; - -r->sign = GET_FPSIGN (h); -r->exp = GET_FPEXP (h); -fphi = GET_FPHI (h); -fplo = GET_FPLO (l); -r->fhi = (fphi << FP_V_UFHI) | (fplo << FP_V_UFLO); -r->flo = 0; -if (r->sign) { - r->exp = r->exp ^ FP_M_EXP; - if (sgn) r->fhi = r->fhi | FP_UCRY; /* ext sign */ - else { - if (r->fhi) r->fhi = UNEG (r->fhi) & FP_UFRAC; - else { - r->exp = r->exp + 1; - r->fhi = FP_UNORM; } } } -return; -} - -/* Normalize and optionally round floating point operand */ - -void fnorm (UFP *a, t_int64 rnd) -{ -int32 i; -static t_uint64 normmask[6] = { - 0x6000000000000000, 0x7800000000000000, 0x7F80000000000000, - 0x7FFF800000000000, 0x7FFFFFFF80000000, 0x7FFFFFFFFFFFFFFF }; -static int32 normtab[7] = { 1, 2, 4, 8, 16, 32, 63 }; - -if ((a->fhi | a->flo) == 0) { /* if fraction = 0 */ - a->sign = a->exp = 0; /* result is 0 */ - return; } -while ((a->fhi & FP_UNORM) == 0) { /* normalized? */ - for (i = 0; i < 6; i++) { - if (a->fhi & normmask[i]) break; } - a->fhi = (a->fhi << normtab[i]) | (a->flo >> (64 - normtab[i])); - a->flo = a->flo << normtab[i]; - a->exp = a->exp - normtab[i]; } -if (rnd) { /* rounding? */ - a->fhi = a->fhi + rnd; /* add round const */ - if (a->fhi & FP_UCRY) { /* if carry out, */ - a->fhi = a->fhi >> 1; /* renormalize */ - a->exp = a->exp + 1; } } -return; -} - -/* Pack floating point result */ - -d10 fpack (UFP *r, d10 *lo, t_bool fdvneg) -{ -d10 val[2]; - -if (r->exp < 0) SETF (F_AOV | F_FOV | F_FXU | F_T1); -else if (r->exp > FP_M_EXP) SETF (F_AOV | F_FOV | F_T1); -val[0] = (((((d10) r->exp) & FP_M_EXP) << FP_V_EXP) | - ((r->fhi & FP_UFHI) >> FP_V_UFHI)) & DMASK; -if (lo) val[1] = ((r->fhi & FP_UFLO) >> FP_V_UFLO) & MMASK; -else val[1] = 0; -if (r->sign) { /* negate? */ - if (fdvneg) { /* fdvr special? */ - val[1] = ~val[1] & MMASK; /* 1's comp */ - val[0] = ~val[0] & DMASK; } - else { DMOVN (val); } } /* 2's comp */ -if (lo) *lo = val[1]; -return val[0]; -} diff --git a/PDP10/pdp10_pag.c b/PDP10/pdp10_pag.c deleted file mode 100644 index bcb6d9c8..00000000 --- a/PDP10/pdp10_pag.c +++ /dev/null @@ -1,801 +0,0 @@ -/* pdp10_pag.c: PDP-10 paging subsystem simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - pag KS10 pager - - 02-Dec-01 RMS Fixed bug in ITS LPMR (found by Dave Conroy) - 21-Aug-01 RMS Fixed bug in ITS paging (found by Miriam Lennox) - Removed register from declarations - 19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug - 03-May-01 RMS Fixed bug in indirect page table pointer processing - 29-Apr-01 RMS Added CLRCSH for ITS, fixed LPMR - - The pager consists of a standard hardware part (the translation - tables) and an operating-system specific page table fill routine. - - There are two translation tables, one for executive mode and one - for user mode. Each table consists of 512 page table entries, - one for each page in the 18b virtual address space. Each pte - contains (in the hardware) a valid bit, a writeable bit, an - address space bit (executive or user), and a cacheable bit, plus - the physical page number corresponding to the virtual page. In - the simulator, the pte is expanded for rapid processing of normal - reads and writes. An expanded pte contains a valid bit, a writeable - bit, and the physical page number shifted left by the page size. - - Expanded pte meaning - 0 invalid - >0 read only - <0 read write - - There is a third, physical table, which is used in place of the - executive and user tables if paging is off. Its entries are always - valid and always writeable. - - To translate a virtual to physical address, the simulator uses - the virtual page number to index into the appropriate page table. - If the page table entry (pte) is not valid, the page fill routine - is called to see if the entry is merely not filled or is truly - inaccessible. If the pte is valid but not writeable, and the - reference is a write reference, the page fill routine is also - called to see if the reference can be resolved. - - The page fill routine is operating system dependent. Three styles - of paging are supported: - - TOPS10 known in the KS10 microcode as KI10 paging, - used by earlier versions of TOPS10 - TOPS20 known in the KS10 microcode as KL10 paging, - used by later versions of TOPS10, and TOPS20 - ITS used only by ITS - - TOPS10 vs TOPS20 is selected by a bit in the EBR; ITS paging is - "hardwired" (it required different microcode). -*/ - -#include "pdp10_defs.h" -#include - -/* Page table (contains expanded pte's) */ - -#define PTBL_ASIZE PAG_N_VPN -#define PTBL_MEMSIZE (1 << PTBL_ASIZE) /* page table size */ -#define PTBL_AMASK (PTBL_MEMSIZE - 1) -#define PTBL_M (1u << 31) /* must be sign bit */ -#define PTBL_V (1u << 30) -#define PTBL_MASK (PAG_PPN | PTBL_M | PTBL_V) - -/* NXM processing */ - -#define REF_V 0 /* ref is virt */ -#define REF_P 1 /* ref is phys */ -#define PF_OK 0 /* pfail ok */ -#define PF_TR 1 /* pfail trap */ - -extern d10 *M; -extern d10 acs[AC_NBLK * AC_NUM]; -extern d10 *ac_cur, *ac_prv, *last_pa; -extern a10 epta, upta; -extern int32 flags; -extern d10 pager_word; -extern int32 apr_flg; -extern d10 ebr, ubr, hsb; -extern d10 spt, cst, cstm, pur; -extern a10 dbr1, dbr2, dbr3, dbr4; -extern d10 pcst, quant; -extern t_bool paging; -extern UNIT cpu_unit; -extern jmp_buf save_env; -extern int32 test_int (void); -extern int32 pi_eval (void); - -int32 eptbl[PTBL_MEMSIZE]; /* exec page table */ -int32 uptbl[PTBL_MEMSIZE]; /* user page table */ -int32 physptbl[PTBL_MEMSIZE]; /* phys page table */ -int32 *ptbl_cur, *ptbl_prv; -int32 save_ea; - -int32 ptbl_fill (a10 ea, int32 *ptbl, int32 mode); -t_stat pag_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat pag_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat pag_reset (DEVICE *dptr); -void pag_nxm (a10 pa, int32 phys, int32 trap); - -/* Pager data structures - - pag_dev pager device descriptor - pag_unit pager units - pager_reg pager register list -*/ - -UNIT pag_unit[] = { - { UDATA (NULL, UNIT_FIX, PTBL_MEMSIZE) }, - { UDATA (NULL, UNIT_FIX, PTBL_MEMSIZE) } }; - -REG pag_reg[] = { - { ORDATA (PANIC_EA, save_ea, PASIZE), REG_HRO }, - { NULL } }; - -DEVICE pag_dev = { - "PAG", pag_unit, pag_reg, NULL, - 2, 8, PTBL_ASIZE, 1, 8, 32, - &pag_ex, &pag_dep, &pag_reset, - NULL, NULL, NULL, - NULL, 0 }; - -/* Memory read and write routines - - Read - read current or previous, read checking - ReadM - read current or previous, write checking - ReadE - read exec - ReadP - read physical - Write - write current or previous - WriteE - write exec - WriteP - write physical - AccChk - test accessibility of virtual address -*/ - -d10 Read (a10 ea, int32 prv) -{ -int32 pa, vpn, xpte; - -if (ea < AC_NUM) return (prv? ac_prv[ea]: ac_cur[ea]); /* AC request */ -vpn = PAG_GETVPN (ea); /* get page num */ -xpte = prv? ptbl_prv[vpn]: ptbl_cur[vpn]; /* get exp pte */ -if (xpte == 0) xpte = ptbl_fill (ea, prv? ptbl_prv: ptbl_cur, PTF_RD); -pa = PAG_XPTEPA (xpte, ea); /* calc phys addr */ -if (MEM_ADDR_NXM (pa)) pag_nxm (pa, REF_V, PF_TR); /* process nxm */ -return M[pa]; /* return data */ -} - -d10 ReadM (a10 ea, int32 prv) -{ -int32 pa, vpn, xpte; - -if (ea < AC_NUM) return (prv? ac_prv[ea]: ac_cur[ea]); /* AC request */ -vpn = PAG_GETVPN (ea); /* get page num */ -xpte = prv? ptbl_prv[vpn]: ptbl_cur[vpn]; /* get exp pte */ -if (xpte >= 0) xpte = ptbl_fill (ea, prv? ptbl_prv: ptbl_cur, PTF_WR); -pa = PAG_XPTEPA (xpte, ea); /* calc phys addr */ -if (MEM_ADDR_NXM (pa)) pag_nxm (pa, REF_V, PF_TR); /* process nxm */ -return M[pa]; /* return data */ -} - -d10 ReadE (a10 ea) -{ -int32 pa, vpn, xpte; - -if (ea < AC_NUM) return AC(ea); /* AC? use current */ -if (!PAGING) return M[ea]; /* phys? no mapping */ -vpn = PAG_GETVPN (ea); /* get page num */ -xpte = eptbl[vpn]; /* get exp pte, exec tbl */ -if (xpte == 0) xpte = ptbl_fill (ea, eptbl, PTF_RD); -pa = PAG_XPTEPA (xpte, ea); /* calc phys addr */ -if (MEM_ADDR_NXM (pa)) pag_nxm (pa, REF_V, PF_TR); /* process nxm */ -return M[pa]; /* return data */ -} - -d10 ReadP (a10 ea) -{ -if (ea < AC_NUM) return AC(ea); /* AC request */ -if (MEM_ADDR_NXM (ea)) pag_nxm (ea, REF_P, PF_TR); /* process nxm */ -return M[ea]; /* return data */ -} - -void Write (a10 ea, d10 val, int32 prv) -{ -int32 pa, vpn, xpte; - -if (ea < AC_NUM) { /* AC request */ - if (prv) ac_prv[ea] = val; /* write AC */ - else ac_cur[ea] = val; } -else { vpn = PAG_GETVPN (ea); /* get page num */ - xpte = prv? ptbl_prv[vpn]: ptbl_cur[vpn]; /* get exp pte */ - if (xpte >= 0) xpte = ptbl_fill (ea, prv? ptbl_prv: ptbl_cur, PTF_WR); - pa = PAG_XPTEPA (xpte, ea); /* calc phys addr */ - if (MEM_ADDR_NXM (pa)) pag_nxm (pa, REF_V, PF_TR); /* process nxm */ - else M[pa] = val; } /* write data */ -return; -} - -void WriteE (a10 ea, d10 val) -{ -int32 pa, vpn, xpte; - -if (ea < AC_NUM) AC(ea) = val; /* AC? use current */ -else if (!PAGING) M[ea] = val; /* phys? no mapping */ -else { vpn = PAG_GETVPN (ea); /* get page num */ - xpte = eptbl[vpn]; /* get exp pte, exec tbl */ - if (xpte >= 0) xpte = ptbl_fill (ea, eptbl, PTF_WR); - pa = PAG_XPTEPA (xpte, ea); /* calc phys addr */ - if (MEM_ADDR_NXM (pa)) pag_nxm (pa, REF_V, PF_TR); /* process nxm */ - else M[pa] = val; } /* write data */ -return; -} - -void WriteP (a10 ea, d10 val) -{ -if (ea < AC_NUM) AC(ea) = val; /* AC request */ -else { if (MEM_ADDR_NXM (ea)) pag_nxm (ea, REF_P, PF_TR); /* process nxm */ - M[ea] = val; } /* memory */ -return; -} - -t_bool AccViol (a10 ea, int32 prv, int32 mode) -{ -int32 vpn, xpte; - -if (ea < AC_NUM) return FALSE; /* AC request */ -vpn = PAG_GETVPN (ea); /* get page num */ -xpte = prv? ptbl_prv[vpn]: ptbl_cur[vpn]; /* get exp pte */ -if ((xpte == 0) || ((mode & PTF_WR) && (xpte > 0))) /* not accessible? */ - xpte = ptbl_fill (ea, prv? ptbl_prv: ptbl_cur, mode | PTF_MAP); -if (xpte) return FALSE; /* accessible */ -return TRUE; /* not accessible */ -} - -void pag_nxm (a10 pa, int32 phys, int32 trap) -{ -apr_flg = apr_flg | APRF_NXM; /* set APR flag */ -pi_eval (); /* eval intr */ -pager_word = PF_NXM | (phys? PF_NXMP: 0) | - (TSTF (F_USR)? PF_USER: 0) | ((d10) pa); -if (PAGING && trap) ABORT (PAGE_FAIL); /* trap? */ -return; -} - -/* Page table fill - - This routine is called if the page table is invalid, or on a write - reference if the page table is read only. If the access is allowed - it stores the pte in the page table entry and returns an expanded - pte for use by the caller. Otherwise, it generates a page fail. - - Notes: - - If called from the console, invalid references return a pte - of 0, and the page table entry is not filled. - - If called from MAP, invalid references return a pte of 0. The - page fail word is properly set up. -*/ - -#define PAGE_FAIL_TRAP if (mode & (PTF_CON | PTF_MAP)) return 0; \ - ABORT (PAGE_FAIL) -#define READPT(x,y) if (MEM_ADDR_NXM (y)) { \ - pag_nxm (y, REF_P, PF_OK); \ - PAGE_FAIL_TRAP; } \ - x = ReadP (y) - -int32 ptbl_fill (a10 ea, int32 *tbl, int32 mode) -{ - -/* ITS paging is based on conventional page tables. ITS divides each address - space into a 128K high and low section, and uses different descriptor base - pointers (dbr) for each. ITS pages are twice the size of DEC standard; - therefore, the fill routine fills two page table entries and returns the pte - that maps the correct ITS half page. This allows the DEC paging macros to - be used in the normal path read-write routines. - - ITS has no MAP instruction, therefore, physical NXM traps are ok. -*/ - -if (ITS) { /* ITS paging */ - int32 acc, decvpn, pte, vpn, ptead, xpte; - d10 ptewd; - - vpn = ITS_GETVPN (ea); /* get ITS pagno */ - if (tbl == uptbl) - ptead = ((ea & RSIGN)? dbr2: dbr1) + ((vpn >> 1) & 077); - else ptead = ((ea & RSIGN)? dbr3: dbr4) + ((vpn >> 1) & 077); - ptewd = ReadP (ptead); /* get PTE pair */ - pte = (int32) ((ptewd >> ((vpn & 1)? 0: 18)) & RMASK); - acc = ITS_GETACC (pte); /* get access */ - pager_word = PF_VIRT | ea | ((tbl == uptbl)? PF_USER: 0) | - ((mode & PTF_WR)? PF_ITS_WRITE: 0) | (acc << PF_ITS_V_ACC); - if ((acc != ITS_ACC_NO) && (!(mode & PTF_WR) || (acc == ITS_ACC_RW))) { - pte = pte & ~PTE_ITS_AGE; /* clear age */ - if (vpn & 1) WriteP (ptead, (ptewd & LMASK) | pte); - else WriteP (ptead, (ptewd & RMASK) | (((d10) pte) << 18)); - xpte = ((pte & PTE_ITS_PPMASK) << ITS_V_PN) | PTBL_V | - ((acc == ITS_ACC_RW)? PTBL_M: 0); - decvpn = PAG_GETVPN (ea); /* get tlb idx */ - if (!(mode & PTF_CON)) { - tbl[decvpn & ~1] = xpte; /* map lo ITS page */ - tbl[decvpn | 1] = xpte + PAG_SIZE; } /* map hi */ - return (xpte + ((decvpn & 1)? PAG_SIZE: 0)); } - PAGE_FAIL_TRAP; - } /* end ITS paging */ - -/* TOPS-10 paging - checked against KS10 microcode - - TOPS-10 paging is also based on conventional page tables. The user page - tables are arranged contiguously at the beginning of the user process table; - however, the executive page tables are scattered through the executive and - user process tables. -*/ - -else if (!T20) { /* TOPS-10 paging */ - int32 pte, vpn, ptead, xpte; - d10 ptewd; - - vpn = PAG_GETVPN (ea); /* get virt page num */ - if (tbl == uptbl) ptead = upta + UPT_T10_UMAP + (vpn >> 1); - else if (vpn < 0340) ptead = epta + EPT_T10_X000 + (vpn >> 1); - else if (vpn < 0400) ptead = upta + UPT_T10_X340 + ((vpn - 0340) >> 1); - else ptead = epta + EPT_T10_X400 + ((vpn - 0400) >> 1); - READPT (ptewd, ptead); /* get PTE pair */ - pte = (int32) ((ptewd >> ((vpn & 1)? 0: 18)) & RMASK); - pager_word = PF_VIRT | ea | ((tbl == uptbl)? PF_USER: 0) | - ((mode & PTF_WR)? PF_WRITE: 0) | - ((pte & PTE_T10_A)? PF_T10_A | - ((pte & PTE_T10_S)? PF_T10_S: 0): 0); - if (mode & PTF_MAP) pager_word = pager_word | /* map? add to pf wd */ - ((pte & PTE_T10_W)? PF_T10_W: 0) | /* W, S, C bits */ - ((pte & PTE_T10_S)? PF_T10_S: 0) | - ((pte & PTE_T10_C)? PF_C: 0); - if ((pte & PTE_T10_A) && (!(mode & PTF_WR) || (pte & PTE_T10_W))) { - xpte = ((pte & PTE_PPMASK) << PAG_V_PN) | /* calc exp pte */ - PTBL_V | ((pte & PTE_T10_W)? PTBL_M: 0); - if (!(mode & PTF_CON)) tbl[vpn] = xpte; /* set tbl if ~cons */ - return xpte; } - PAGE_FAIL_TRAP; - } /* end TOPS10 paging */ - -/* TOPS-20 paging - checked against KS10 ucode. - - TOPS-20 paging has three phases: - - 1. Starting at EPT/UPT + 540 + section number, chase section pointers to - get the pointer to the section page table. In the KS10, because there - is only one section, the microcode caches the result of this evaluation. - Also, the evaluation of indirect pointers is simplified, as the section - table index is ignored. - - 2. Starting with the page map pointer, chase page pointers to get the - pointer to the page. The KS10 allows the operating system to inhibit - updating of the CST (base address = 0). - - 3. Use the page pointer to get the CST entry. If a write reference to - a writeable page, set CST_M. If CST_M is set, set M in page table. -*/ - -else { /* TOPS-20 paging */ - int32 pmi, vpn, xpte; - int32 flg, t; - t_bool stop; - a10 pa, csta; - d10 ptr, cste; - d10 acc = PTE_T20_W | PTE_T20_C; /* init access bits */ - - pager_word = PF_VIRT | ea | ((tbl == uptbl)? PF_USER: 0) | - ((mode & PTF_WR)? PF_WRITE: 0); /* set page fail word */ - -/* First phase - evaluate section pointers - returns a ptr to a page map - As a single section machine, the KS10 short circuits this part of the - process. In particular, the indirect pointer calculation assumes that - the section table index will be 0. It adds the full pointer (not just - the right half) to the SPT base. If the section index is > 0, the - result is a physical memory address > 256KW. Depending on the size of - memory, the SPT fetch may or may not generate a NXM page fail. The - KS10 then ignores the section table index in fetching the next pointer. - - The KS10 KL10 memory management diagnostic (dskec.sav) tests for this - behavior with a section index of 3. However, this would be a legal - physical address in a system with 1MW. Accordingly, the simulator - special cases non-zero section indices (which can't work in any case) - to generate the right behavior for the diagnostic. -*/ - - vpn = PAG_GETVPN (ea); /* get virt page num */ - pa = (tbl == uptbl)? upta + UPT_T20_SCTN: epta + EPT_T20_SCTN; - READPT (ptr, pa & PAMASK); /* get section 0 ptr */ - for (stop = FALSE, flg = 0; !stop; flg++) { /* eval section ptrs */ - acc = acc & ptr; /* cascade acc bits */ - switch (T20_GETTYP (ptr)) { /* case on ptr type */ - case T20_NOA: /* no access */ - default: /* undefined type */ - PAGE_FAIL_TRAP; /* page fail */ - case T20_IMM: /* immediate */ - stop = TRUE; /* exit */ - break; - case T20_SHR: /* shared */ - pa = (int32) (spt + (ptr & RMASK)); /* get SPT idx */ - READPT (ptr, pa & PAMASK); /* get SPT entry */ - stop = TRUE; /* exit */ - break; - case T20_IND: /* indirect */ - if (flg && (t = test_int ())) ABORT (t); - pmi = T20_GETPMI (ptr); /* get sect tbl idx */ - pa = (int32) (spt + (ptr & RMASK)); /* get SPT idx */ - if (pmi) { /* for dskec */ - pag_nxm ((pmi << 18) | pa, REF_P, PF_OK); - PAGE_FAIL_TRAP; } - READPT (ptr, pa & PAMASK); /* get SPT entry */ - if (ptr & PTE_T20_STM) { PAGE_FAIL_TRAP; } - pa = PAG_PTEPA (ptr, pmi); /* index off page */ - READPT (ptr, pa & PAMASK); /* get pointer */ - break; /* continue in loop */ - } /* end case */ - } /* end for */ - -/* Second phase - found page map ptr, evaluate page pointers */ - - pa = PAG_PTEPA (ptr, vpn); /* get ptbl address */ - for (stop = FALSE, flg = 0; !stop; flg++) { /* eval page ptrs */ - if (ptr & PTE_T20_STM) { PAGE_FAIL_TRAP; } /* non-res? */ - if (cst) { /* cst really there? */ - csta = (int32) ((cst + (ptr & PTE_PPMASK)) & PAMASK); - READPT (cste, csta); /* get CST entry */ - if ((cste & CST_AGE) == 0) { PAGE_FAIL_TRAP; } - cste = (cste & cstm) | pur; /* update entry */ - WriteP (csta, cste); } /* rewrite */ - READPT (ptr, pa & PAMASK); /* get pointer */ - acc = acc & ptr; /* cascade acc bits */ - switch (T20_GETTYP (ptr)) { /* case on ptr type */ - case T20_NOA: /* no access */ - default: /* undefined type */ - PAGE_FAIL_TRAP; /* page fail */ - case T20_IMM: /* immediate */ - stop = TRUE; /* exit */ - break; - case T20_SHR: /* shared */ - pa = (int32) (spt + (ptr & RMASK)); /* get SPT idx */ - READPT (ptr, pa & PAMASK); /* get SPT entry */ - stop = TRUE; /* exit */ - break; - case T20_IND: /* indirect */ - if (flg && (t = test_int ())) ABORT (t); - pmi = T20_GETPMI (ptr); /* get section index */ - pa = (int32) (spt + (ptr & RMASK)); /* get SPT idx */ - READPT (ptr, pa & PAMASK); /* get SPT entry */ - pa = PAG_PTEPA (ptr, pmi); /* index off page */ - break; /* continue in loop */ - } /* end case */ - } /* end for */ - -/* Last phase - have final page pointer, check modifiability */ - - if (ptr & PTE_T20_STM) { PAGE_FAIL_TRAP; } /* non-resident? */ - if (cst) { /* CST really there? */ - csta = (int32) ((cst + (ptr & PTE_PPMASK)) & PAMASK); - READPT (cste, csta); /* get CST entry */ - if ((cste & CST_AGE) == 0) { PAGE_FAIL_TRAP; } - cste = (cste & cstm) | pur; } /* update entry */ - else cste = 0; /* no, entry = 0 */ - pager_word = pager_word | PF_T20_DN; /* set eval done */ - xpte = ((int32) ((ptr & PTE_PPMASK) << PAG_V_PN)) | PTBL_V; - if (mode & PTF_WR) { /* write? */ - if (acc & PTE_T20_W) { /* writable? */ - xpte = xpte | PTBL_M; /* set PTE M */ - cste = cste | CST_M; } /* set CST M */ - else { PAGE_FAIL_TRAP; } } /* no, trap */ - if (cst) WriteP (csta, cste); /* write CST entry */ - if (mode & PTF_MAP) pager_word = pager_word | /* map? more in pf wd */ - ((xpte & PTBL_M)? PF_T20_M: 0) | /* M, W, C bits */ - ((acc & PTE_T20_W)? PF_T20_W: 0) | - ((acc & PTE_T20_C)? PF_C: 0); - if (!(mode & PTF_CON)) tbl[vpn] = xpte; /* set tbl if ~cons */ - return xpte; - } /* end TOPS20 paging */ -} - -/* Set up pointers for AC, memory, and process table access */ - -void set_dyn_ptrs (void) -{ -int32 t; - -if (PAGING) { - ac_cur = &acs[UBR_GETCURAC (ubr) * AC_NUM]; - ac_prv = &acs[UBR_GETPRVAC (ubr) * AC_NUM]; - if (TSTF (F_USR)) ptbl_cur = ptbl_prv = &uptbl[0]; - else { - ptbl_cur = &eptbl[0]; - ptbl_prv = TSTF (F_UIO)? &uptbl[0]: &eptbl[0]; } } -else { ac_cur = ac_prv = &acs[0]; - ptbl_cur = ptbl_prv = &physptbl[0]; } -t = EBR_GETEBR (ebr); -epta = t << PAG_V_PN; -if (ITS) upta = (int32) ubr & PAMASK; -else { t = UBR_GETUBR (ubr); - upta = t << PAG_V_PN; } -return; -} - -/* MAP instruction, TOPS-10 and TOPS-20 only - - According to the KS-10 ucode, map with paging disabled sets - "accessible, writeable, software", regardless of whether - TOPS-10 or TOPS-20 paging is implemented -*/ - -d10 map (a10 ea, int32 prv) -{ -int32 xpte; -d10 val = (TSTF (F_USR)? PF_USER: 0); - -if (!PAGING) return (val | PF_T10_A | PF_T10_W | PF_T10_S | ea); -xpte = ptbl_fill (ea, prv? ptbl_prv: ptbl_cur, PTF_MAP); /* get exp pte */ -if (xpte) val = (pager_word & ~PAMASK) | PAG_XPTEPA (xpte, ea); -else { if (pager_word & PF_HARD) val = pager_word; /* hard error */ - else val = val | PF_VIRT | ea; } /* inaccessible */ -return val; -} - -/* Mapping routine for console */ - -a10 conmap (a10 ea, int32 mode, int32 sw) -{ -int32 xpte, *tbl; - -if (!PAGING) return ea; -set_dyn_ptrs (); /* in case changed */ -if (sw & SWMASK ('E')) tbl = eptbl; -else if (sw & SWMASK ('U')) tbl = uptbl; -else tbl = ptbl_cur; -xpte = ptbl_fill (ea, tbl, mode); -if (xpte) return PAG_XPTEPA (xpte, ea); -else return MAXMEMSIZE; -} - -/* Common pager instructions */ - -t_bool clrpt (a10 ea, int32 prv) -{ -int32 vpn = PAG_GETVPN (ea); /* get page num */ - -if (ITS) { /* ITS? */ - uptbl[vpn & ~1] = 0; /* clear double size */ - uptbl[vpn | 1] = 0; /* entries in */ - eptbl[vpn & ~1] = 0; /* both page tables */ - eptbl[vpn | 1] = 0; } -else { uptbl[vpn] = 0; /* clear entries in */ - eptbl[vpn] = 0; } /* both page tables */ -return FALSE; -} - -t_bool wrebr (a10 ea, int32 prv) -{ -ebr = ea & EBR_MASK; /* store EBR */ -pag_reset (&pag_dev); /* clear page tables */ -set_dyn_ptrs (); /* set dynamic ptrs */ -return FALSE; -} - -t_bool rdebr (a10 ea, int32 prv) -{ -Write (ea, (ebr & EBR_MASK), prv); -return FALSE; -} - -t_bool wrubr (a10 ea, int32 prv) -{ -d10 val = Read (ea, prv); -d10 ubr_mask = (ITS)? PAMASK: UBR_UBRMASK; /* ITS: ubr is wd addr */ - -if (val & UBR_SETACB) ubr = ubr & ~UBR_ACBMASK; /* set AC's? */ -else val = val & ~UBR_ACBMASK; /* no, keep old val */ -if (val & UBR_SETUBR) { /* set UBR? */ - ubr = ubr & ~ubr_mask; - pag_reset (&pag_dev); } /* yes, clr pg tbls */ -else val = val & ~ubr_mask; /* no, keep old val */ -ubr = (ubr | val) & (UBR_ACBMASK | ubr_mask); -set_dyn_ptrs (); -return FALSE; -} - -t_bool rdubr (a10 ea, int32 prv) -{ -ubr = ubr & (UBR_ACBMASK | (ITS? PAMASK: UBR_UBRMASK)); -Write (ea, UBRWORD, prv); -return FALSE; -} - -t_bool wrhsb (a10 ea, int32 prv) -{ -hsb = Read (ea, prv) & PAMASK; -return FALSE; -} - -t_bool rdhsb (a10 ea, int32 prv) -{ -Write (ea, hsb, prv); -return FALSE; -} - -/* TOPS20 pager instructions */ - -t_bool wrspb (a10 ea, int32 prv) -{ -spt = Read (ea, prv); -return FALSE; -} - -t_bool rdspb (a10 ea, int32 prv) -{ -Write (ea, spt, prv); -return FALSE; -} - -t_bool wrcsb (a10 ea, int32 prv) -{ -cst = Read (ea, prv); -return FALSE; -} - -t_bool rdcsb (a10 ea, int32 prv) -{ -Write (ea, cst, prv); -return FALSE; -} - -t_bool wrpur (a10 ea, int32 prv) -{ -pur = Read (ea, prv); -return FALSE; -} - -t_bool rdpur (a10 ea, int32 prv) -{ -Write (ea, pur, prv); -return FALSE; -} - -t_bool wrcstm (a10 ea, int32 prv) -{ -cstm = Read (ea, prv); -if ((cpu_unit.flags & UNIT_T20V41) && (ea == 040127)) - cstm = 0770000000000; -return FALSE; -} - -t_bool rdcstm (a10 ea, int32 prv) -{ -Write (ea, cstm, prv); -return FALSE; -} - -/* ITS pager instructions - The KS10 does not implement the JPC option. -*/ - -t_bool clrcsh (a10 ea, int32 prv) -{ -return FALSE; -} - -t_bool ldbr1 (a10 ea, int32 prv) -{ -dbr1 = ea; -pag_reset (&pag_dev); -return FALSE; -} - -t_bool sdbr1 (a10 ea, int32 prv) -{ -Write (ea, dbr1, prv); -return FALSE; -} - -t_bool ldbr2 (a10 ea, int32 prv) -{ -dbr2 = ea; -pag_reset (&pag_dev); -return FALSE; -} - -t_bool sdbr2 (a10 ea, int32 prv) -{ -Write (ea, dbr2, prv); -return FALSE; -} - -t_bool ldbr3 (a10 ea, int32 prv) -{ -dbr3 = ea; -pag_reset (&pag_dev); -return FALSE; -} - -t_bool sdbr3 (a10 ea, int32 prv) -{ -Write (ea, dbr3, prv); -return FALSE; -} - -t_bool ldbr4 (a10 ea, int32 prv) -{ -dbr4 = ea; -pag_reset (&pag_dev); -return FALSE; -} - -t_bool sdbr4 (a10 ea, int32 prv) -{ -Write (ea, dbr4, prv); -return FALSE; -} - -t_bool wrpcst (a10 ea, int32 prv) -{ -pcst = Read (ea, prv); -return FALSE; -} - -t_bool rdpcst (a10 ea, int32 prv) -{ -Write (ea, pcst, prv); -return FALSE; -} - -t_bool lpmr (a10 ea, int32 prv) -{ -d10 val; - -val = Read (ADDA (ea, 2), prv); -dbr1 = (a10) (Read (ea, prv) & AMASK); -dbr2 = (a10) (Read (ADDA (ea, 1), prv) & AMASK); -quant = val; -pag_reset (&pag_dev); -return FALSE; -} - -t_bool spm (a10 ea, int32 prv) -{ - -ReadM (ADDA (ea, 2), prv); -Write (ea, dbr1, prv); -Write (ADDA (ea, 1), dbr2, prv); -Write (ADDA (ea, 2), quant, prv); -return FALSE; -} - -t_stat pag_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -int32 tbln = uptr - pag_unit; - -if (addr >= PTBL_MEMSIZE) return SCPE_NXM; -*vptr = tbln? uptbl[addr]: eptbl[addr];; -return SCPE_OK; -} - -t_stat pag_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -int32 tbln = uptr - pag_unit; - -if (addr >= PTBL_MEMSIZE) return SCPE_NXM; -if (tbln) uptbl[addr] = (int32) val & PTBL_MASK; -else eptbl[addr] = (int32) val & PTBL_MASK; -return SCPE_OK; -} - -t_stat pag_reset (DEVICE *dptr) -{ -int32 i; - -for (i = 0; i < PTBL_MEMSIZE; i++) { - eptbl[i] = uptbl[i] = 0; - physptbl[i] = (i << PAG_V_PN) + PTBL_M + PTBL_V; } -return SCPE_OK; -} diff --git a/PDP10/pdp10_rp.c b/PDP10/pdp10_rp.c deleted file mode 100644 index 712a6bbc..00000000 --- a/PDP10/pdp10_rp.c +++ /dev/null @@ -1,1138 +0,0 @@ -/* pdp10_rp.c - RH11/RP04/05/06/07 RM02/03/05/80 "Massbus" disk controller - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - rp RH/RP/RM moving head disks - - 23-Jul-03 RMS Fixed bug in read header stub - 25-Apr-03 RMS Revised for extended file support - 21-Nov-02 RMS Fixed bug in bootstrap (reported by Michael Thompson) - 29-Sep-02 RMS Added variable vector support - New data structures - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support support - 24-Nov-01 RMS Changed RPER, RPDS, FNC, FLG to arrays - 23-Oct-01 RMS Fixed bug in error interrupts - New IO page address constants - 05-Oct-01 RMS Rewrote interrupt handling from schematics - 02-Oct-01 RMS Revised CS1 write code - 30-Sep-01 RMS Moved CS1<5:0> into drives - 28-Sep-01 RMS Fixed interrupt handling for SC/ATA - 23-Aug-01 RMS Added read/write header stubs for ITS - (found by Mirian Crzig Lennox) - 13-Jul-01 RMS Changed fread call to fxread (found by Peter Schorn) - 14-May-01 RMS Added check for unattached drive - - The "Massbus style" disks consisted of several different large - capacity drives interfaced through a reasonably common (but not - 100% compatible) family of interfaces into the KS10 Unibus via - the RH11 disk controller. - - WARNING: The interupt logic of the RH11/RH70 is unusual and must be - simulated with great precision. The RH11 has an internal interrupt - request flop, CSTB INTR, which is controlled as follows: - - Writing IE and DONE simultaneously sets CSTB INTR - - Controller clear, INIT, and interrupt acknowledge clear CSTB INTR - (and also clear IE) - - A transition of DONE from 0 to 1 sets CSTB from INTR - The output of INTR is OR'd with the AND of RPCS1 to - create the interrupt request signal. Thus, - - The DONE interrupt is edge sensitive, but the SC interrupt is - level sensitive. - - The DONE interrupt, once set, is not disabled if IE is cleared, - but the SC interrupt is. -*/ - -#include "pdp10_defs.h" -#include - -#define RP_NUMDR 8 /* #drives */ -#define RP_NUMWD 128 /* 36b words/sector */ -#define RP_MAXFR 32768 /* max transfer */ -#define GET_SECTOR(x,d) ((int) fmod (sim_gtime() / ((double) (x)), \ - ((double) drv_tab[d].sect))) - -/* Flags in the unit flags word */ - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */ -#define UNIT_M_DTYPE 7 -#define UNIT_V_AUTO (UNIT_V_UF + 4) /* autosize */ -#define UNIT_V_DUMMY (UNIT_V_UF + 5) /* dummy flag */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define UNIT_DUMMY (1 << UNIT_V_DUMMY) -#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -/* Parameters in the unit descriptor */ - -#define CYL u3 /* current cylinder */ -#define FUNC u4 /* function */ - -/* RPCS1 - 176700 - control/status 1 */ - -#define CS1_GO CSR_GO /* go */ -#define CS1_V_FNC 1 /* function pos */ -#define CS1_M_FNC 037 /* function mask */ -#define CS1_FNC (CS1_M_FNC << CS1_V_FNC) -#define FNC_NOP 000 /* no operation */ -#define FNC_UNLOAD 001 /* unload */ -#define FNC_SEEK 002 /* seek */ -#define FNC_RECAL 003 /* recalibrate */ -#define FNC_DCLR 004 /* drive clear */ -#define FNC_RELEASE 005 /* port release */ -#define FNC_OFFSET 006 /* offset */ -#define FNC_RETURN 007 /* return to center */ -#define FNC_PRESET 010 /* read-in preset */ -#define FNC_PACK 011 /* pack acknowledge */ -#define FNC_SEARCH 014 /* search */ -#define FNC_XFER 024 /* >=? data xfr */ -#define FNC_WCHK 024 /* write check */ -#define FNC_WRITE 030 /* write */ -#define FNC_WRITEH 031 /* write w/ headers */ -#define FNC_READ 034 /* read */ -#define FNC_READH 035 /* read w/ headers */ -#define CS1_IE CSR_IE /* int enable */ -#define CS1_DONE CSR_DONE /* ready */ -#define CS1_V_UAE 8 /* Unibus addr ext */ -#define CS1_M_UAE 03 -#define CS1_UAE (CS1_M_UAE << CS1_V_UAE) -#define CS1_DVA 0004000 /* drive avail NI */ -#define CS1_MCPE 0020000 /* Mbus par err NI */ -#define CS1_TRE 0040000 /* transfer err */ -#define CS1_SC 0100000 /* special cond */ -#define CS1_MBZ 0012000 -#define CS1_DRV (CS1_FNC | CS1_GO) -#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC) -#define GET_UAE(x) (((x) & CS1_UAE) << (16 - CS1_V_UAE)) - -/* RPWC - 176702 - word count */ - -/* RPBA - 176704 - base address */ - -#define BA_MBZ 0000001 /* must be zero */ - -/* RPDA - 176706 - sector/track */ - -#define DA_V_SC 0 /* sector pos */ -#define DA_M_SC 077 /* sector mask */ -#define DA_V_SF 8 /* track pos */ -#define DA_M_SF 077 /* track mask */ -#define DA_MBZ 0140300 -#define GET_SC(x) (((x) >> DA_V_SC) & DA_M_SC) -#define GET_SF(x) (((x) >> DA_V_SF) & DA_M_SF) - -/* RPCS2 - 176710 - control/status 2 */ - -#define CS2_V_UNIT 0 /* unit pos */ -#define CS2_M_UNIT 07 /* unit mask */ -#define CS2_UNIT (CS2_M_UNIT << CS2_V_UNIT) -#define CS2_UAI 0000010 /* addr inhibit */ -#define CS2_PAT 0000020 /* parity test NI */ -#define CS2_CLR 0000040 /* controller clear */ -#define CS2_IR 0000100 /* input ready */ -#define CS2_OR 0000200 /* output ready */ -#define CS2_MDPE 0000400 /* Mbus par err NI */ -#define CS2_MXF 0001000 /* missed xfer NI */ -#define CS2_PGE 0002000 /* program err */ -#define CS2_NEM 0004000 /* nx mem err */ -#define CS2_NED 0010000 /* nx drive err */ -#define CS2_PE 0020000 /* parity err NI */ -#define CS2_WCE 0040000 /* write check err */ -#define CS2_DLT 0100000 /* data late NI */ -#define CS2_MBZ (CS2_CLR) -#define CS2_RW (CS2_UNIT | CS2_UAI | CS2_PAT | CS2_MXF | CS2_PE) -#define CS2_ERR (CS2_MDPE | CS2_MXF | CS2_PGE | CS2_NEM | \ - CS2_NED | CS2_PE | CS2_WCE | CS2_DLT ) -#define GET_UNIT(x) (((x) >> CS2_V_UNIT) & CS2_M_UNIT) - -/* RPDS - 176712 - drive status */ - -#define DS_OF 0000001 /* offset mode */ -#define DS_VV 0000100 /* volume valid */ -#define DS_RDY 0000200 /* drive ready */ -#define DS_DPR 0000400 /* drive present */ -#define DS_PGM 0001000 /* programable NI */ -#define DS_LST 0002000 /* last sector */ -#define DS_WRL 0004000 /* write locked */ -#define DS_MOL 0010000 /* medium online */ -#define DS_PIP 0020000 /* pos in progress */ -#define DS_ERR 0040000 /* error */ -#define DS_ATA 0100000 /* attention active */ -#define DS_MBZ 0000076 - -/* RPER1 - 176714 - error status 1 */ - -#define ER1_ILF 0000001 /* illegal func */ -#define ER1_ILR 0000002 /* illegal register */ -#define ER1_RMR 0000004 /* reg mod refused */ -#define ER1_PAR 0000010 /* parity err */ -#define ER1_FER 0000020 /* format err NI */ -#define ER1_WCF 0000040 /* write clk fail NI */ -#define ER1_ECH 0000100 /* ECC hard err NI */ -#define ER1_HCE 0000200 /* hdr comp err NI */ -#define ER1_HCR 0000400 /* hdr CRC err NI */ -#define ER1_AOE 0001000 /* addr ovflo err */ -#define ER1_IAE 0002000 /* invalid addr err */ -#define ER1_WLE 0004000 /* write lock err */ -#define ER1_DTE 0010000 /* drive time err NI */ -#define ER1_OPI 0020000 /* op incomplete */ -#define ER1_UNS 0040000 /* drive unsafe */ -#define ER1_DCK 0100000 /* data check NI */ - -/* RPAS - 176716 - attention summary */ - -#define AS_U0 0000001 /* unit 0 flag */ - -/* RPLA - 176720 - look ahead register */ - -#define LA_V_SC 6 /* sector pos */ - -/* RPDB - 176722 - data buffer */ -/* RPMR - 176724 - maintenace register */ -/* RPDT - 176726 - drive type */ -/* RPSN - 176730 - serial number */ - -/* RPOF - 176732 - offset register */ - -#define OF_HCI 0002000 /* hdr cmp inh NI */ -#define OF_ECI 0004000 /* ECC inhibit NI */ -#define OF_F22 0010000 /* format NI */ -#define OF_MBZ 0161400 - -/* RPDC - 176734 - desired cylinder */ - -#define DC_V_CY 0 /* cylinder pos */ -#define DC_M_CY 01777 /* cylinder mask */ -#define DC_MBZ 0176000 -#define GET_CY(x) (((x) >> DC_V_CY) & DC_M_CY) -#define GET_DA(c,fs,d) ((((GET_CY (c) * drv_tab[d].surf) + \ - GET_SF (fs)) * drv_tab[d].sect) + GET_SC (fs)) - -/* RPCC - 176736 - current cylinder */ -/* RPER2 - 176740 - error status 2 - drive unsafe conditions - unimplemented */ -/* RPER3 - 176742 - error status 3 - more unsafe conditions - unimplemented */ -/* RPEC1 - 176744 - ECC status 1 - unimplemented */ -/* RPEC2 - 176746 - ECC status 2 - unimplemented */ - -/* This controller supports many different disk drive types. These drives - are operated in 576 bytes/sector (128 36b words/sector) mode, which gives - them somewhat different geometry from the PDP-11 variants: - - type #sectors/ #surfaces/ #cylinders/ - surface cylinder drive - - RM02/3 30 5 823 =67MB - RP04/5 20 19 411 =88MB - RM80 30 14 559 =124MB - RP06 20 19 815 =176MB - RM05 30 19 823 =256MB - RP07 43 32 630 =516MB - - In theory, each drive can be a different type. The size field in - each unit selects the drive capacity for each drive and thus the - drive type. DISKS MUST BE DECLARED IN ASCENDING SIZE. -*/ - -#define RM03_DTYPE 0 -#define RM03_SECT 30 -#define RM03_SURF 5 -#define RM03_CYL 823 -#define RM03_DEV 020024 -#define RM03_SIZE (RM03_SECT * RM03_SURF * RM03_CYL * RP_NUMWD) - -#define RP04_DTYPE 1 -#define RP04_SECT 20 -#define RP04_SURF 19 -#define RP04_CYL 411 -#define RP04_DEV 020020 -#define RP04_SIZE (RP04_SECT * RP04_SURF * RP04_CYL * RP_NUMWD) - -#define RM80_DTYPE 2 -#define RM80_SECT 30 -#define RM80_SURF 14 -#define RM80_CYL 559 -#define RM80_DEV 020026 -#define RM80_SIZE (RM80_SECT * RM80_SURF * RM80_CYL * RP_NUMWD) - -#define RP06_DTYPE 3 -#define RP06_SECT 20 -#define RP06_SURF 19 -#define RP06_CYL 815 -#define RP06_DEV 020022 -#define RP06_SIZE (RP06_SECT * RP06_SURF * RP06_CYL * RP_NUMWD) - -#define RM05_DTYPE 4 -#define RM05_SECT 30 -#define RM05_SURF 19 -#define RM05_CYL 823 -#define RM05_DEV 020027 -#define RM05_SIZE (RM05_SECT * RM05_SURF * RM05_CYL * RP_NUMWD) - -#define RP07_DTYPE 5 -#define RP07_SECT 43 -#define RP07_SURF 32 -#define RP07_CYL 630 -#define RP07_DEV 020042 -#define RP07_SIZE (RP07_SECT * RP07_SURF * RP07_CYL * RP_NUMWD) - -struct drvtyp { - int sect; /* sectors */ - int surf; /* surfaces */ - int cyl; /* cylinders */ - int size; /* #blocks */ - int devtype; /* device type */ -}; - -struct drvtyp drv_tab[] = { - { RM03_SECT, RM03_SURF, RM03_CYL, RM03_SIZE, RM03_DEV }, - { RP04_SECT, RP04_SURF, RP04_CYL, RP04_SIZE, RP04_DEV }, - { RM80_SECT, RM80_SURF, RM80_CYL, RM80_SIZE, RM80_DEV }, - { RP06_SECT, RP06_SURF, RP06_CYL, RP06_SIZE, RP06_DEV }, - { RM05_SECT, RM05_SURF, RM05_CYL, RM05_SIZE, RM05_DEV }, - { RP07_SECT, RP07_SURF, RP07_CYL, RP07_SIZE, RP07_DEV }, - { 0 } }; - -extern d10 *M; /* memory */ -extern int32 int_req; -extern int32 int_vec[32]; -extern int32 ubmap[UBANUM][UMAP_MEMSIZE]; /* Unibus maps */ -extern int32 ubcs[UBANUM]; -extern UNIT cpu_unit; - -int32 rpcs1 = 0; /* control/status 1 */ -int32 rpwc = 0; /* word count */ -int32 rpba = 0; /* bus address */ -int32 rpda = 0; /* track/sector */ -int32 rpcs2 = 0; /* control/status 2 */ -int32 rpds[RP_NUMDR] = { 0 }; /* drive status */ -int32 rper1[RP_NUMDR] = { 0 }; /* error status 1 */ -int32 rpdb = 0; /* data buffer */ -int32 rpmr = 0; /* maint register */ -int32 rpof = 0; /* offset */ -int32 rpdc = 0; /* cylinder */ -int32 rper2 = 0; /* error status 2 */ -int32 rper3 = 0; /* error status 3 */ -int32 rpec1 = 0; /* ECC correction 1 */ -int32 rpec2 = 0; /* ECC correction 2 */ -int32 rpiff = 0; /* INTR flip/flop */ -int32 rp_stopioe = 1; /* stop on error */ -int32 rp_swait = 10; /* seek time */ -int32 rp_rwait = 10; /* rotate time */ -static int32 reg_in_drive[32] = { - 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -t_stat rp_rd (int32 *data, int32 PA, int32 access); -t_stat rp_wr (int32 data, int32 PA, int32 access); -int32 rp_inta (void); -t_stat rp_svc (UNIT *uptr); -t_stat rp_reset (DEVICE *dptr); -t_stat rp_boot (int32 unitno, DEVICE *dptr); -t_stat rp_attach (UNIT *uptr, char *cptr); -t_stat rp_detach (UNIT *uptr); -void update_rpcs (int32 flags, int32 drv); -void rp_go (int32 drv, int32 fnc); -t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* RP data structures - - rp_dev RP device descriptor - rp_unit RP unit list - rp_reg RP register list - rp_mod RP modifier list -*/ - -DIB rp_dib = { IOBA_RP, IOLN_RP, &rp_rd, &rp_wr, - 1, IVCL (RP), VEC_RP, { &rp_inta } }; - -UNIT rp_unit[] = { - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) } }; - -REG rp_reg[] = { - { ORDATA (RPCS1, rpcs1, 16) }, - { ORDATA (RPWC, rpwc, 16) }, - { ORDATA (RPBA, rpba, 16) }, - { ORDATA (RPDA, rpda, 16) }, - { ORDATA (RPCS2, rpcs2, 16) }, - { BRDATA (RPDS, rpds, 8, 16, RP_NUMDR) }, - { BRDATA (RPER1, rper1, 8, 16, RP_NUMDR) }, - { ORDATA (RPOF, rpof, 16) }, - { ORDATA (RPDC, rpdc, 16) }, - { ORDATA (RPER2, rper2, 16) }, - { ORDATA (RPER3, rper3, 16) }, - { ORDATA (RPEC1, rpec1, 16) }, - { ORDATA (RPEC2, rpec2, 16) }, - { ORDATA (RPMR, rpmr, 16) }, - { ORDATA (RPDB, rpdb, 16) }, - { FLDATA (IFF, rpiff, 0) }, - { FLDATA (INT, int_req, INT_V_RP) }, - { FLDATA (SC, rpcs1, CSR_V_ERR) }, - { FLDATA (DONE, rpcs1, CSR_V_DONE) }, - { FLDATA (IE, rpcs1, CSR_V_IE) }, - { DRDATA (STIME, rp_swait, 24), REG_NZ + PV_LEFT }, - { DRDATA (RTIME, rp_rwait, 24), REG_NZ + PV_LEFT }, - { URDATA (FNC, rp_unit[0].FUNC, 8, 5, 0, RP_NUMDR, REG_HRO) }, - { URDATA (CAPAC, rp_unit[0].capac, 10, T_ADDR_W, 0, - RP_NUMDR, PV_LEFT | REG_HRO) }, - { FLDATA (STOP_IOE, rp_stopioe, 0) }, - { NULL } }; - -MTAB rp_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RM03_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RM03", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RP04_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RP04", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RM80_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RM80", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RP06_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RP06", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RM05_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RM05", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RP07_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RP07", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RM03_DTYPE << UNIT_V_DTYPE), - "RM03", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RP04_DTYPE << UNIT_V_DTYPE), - "RP04", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RM80_DTYPE << UNIT_V_DTYPE), - "RM80", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RP06_DTYPE << UNIT_V_DTYPE), - "RP06", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RM05_DTYPE << UNIT_V_DTYPE), - "RM05", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RP07_DTYPE << UNIT_V_DTYPE), - "RP07", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_DTYPE), (RM03_DTYPE << UNIT_V_DTYPE), - NULL, "RM03", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RP04_DTYPE << UNIT_V_DTYPE), - NULL, "RP04", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RM80_DTYPE << UNIT_V_DTYPE), - NULL, "RM80", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RP06_DTYPE << UNIT_V_DTYPE), - NULL, "RP06", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RM05_DTYPE << UNIT_V_DTYPE), - NULL, "RM05", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RP07_DTYPE << UNIT_V_DTYPE), - NULL, "RP07", &rp_set_size }, - { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; - -DEVICE rp_dev = { - "RP", rp_unit, rp_reg, rp_mod, - RP_NUMDR, 8, 30, 1, 8, 36, - NULL, NULL, &rp_reset, - &rp_boot, &rp_attach, &rp_detach, - &rp_dib, DEV_UBUS }; - -/* I/O dispatch routines, I/O addresses 17776700 - 17776776 */ - -t_stat rp_rd (int32 *data, int32 PA, int32 access) -{ -int32 drv, dtype, i, j; - -drv = GET_UNIT (rpcs2); /* get current unit */ -dtype = GET_DTYPE (rp_unit[drv].flags); /* get drive type */ -j = (PA >> 1) & 037; /* get reg offset */ -if (reg_in_drive[j] && (rp_unit[drv].flags & UNIT_DIS)) { /* nx disk */ - rpcs2 = rpcs2 | CS2_NED; /* set error flag */ - update_rpcs (CS1_SC, drv); /* request intr */ - *data = 0; - return SCPE_OK; } - -update_rpcs (0, drv); /* update status */ -switch (j) { /* decode PA<5:1> */ -case 000: /* RPCS1 */ - *data = rpcs1; - break; -case 001: /* RPWC */ - *data = rpwc; - break; -case 002: /* RPBA */ - *data = rpba = rpba & ~BA_MBZ; - break; -case 003: /* RPDA */ - *data = rpda = rpda & ~DA_MBZ; - break; -case 004: /* RPCS2 */ - *data = rpcs2 = (rpcs2 & ~CS2_MBZ) | CS2_IR | CS2_OR; - break; -case 005: /* RPDS */ - *data = rpds[drv]; - break; -case 006: /* RPER1 */ - *data = rper1[drv]; - break; -case 007: /* RPAS */ - *data = 0; - for (i = 0; i < RP_NUMDR; i++) - if (rpds[i] & DS_ATA) *data = *data | (AS_U0 << i); - break; -case 010: /* RPLA */ - *data = GET_SECTOR (rp_rwait, dtype) << LA_V_SC; - break; -case 011: /* RPDB */ - *data = rpdb; - break; -case 012: /* RPMR */ - *data = rpmr; - break; -case 013: /* RPDT */ - *data = drv_tab[dtype].devtype; - break; -case 014: /* RPSN */ - *data = 020 | (drv + 1); - break; -case 015: /* RPOF */ - *data = rpof = rpof & ~OF_MBZ; - break; -case 016: /* RPDC */ - *data = rpdc = rpdc & ~DC_MBZ; - break; -case 017: /* RPCC, RMHR */ - *data = rp_unit[drv].CYL; - break; -case 020: /* RPER2, RMMR2 */ - *data = rper2; - break; -case 021: /* RPER3, RMER2 */ - *data = rper3; - break; -case 022: /* RPEC1 */ - *data = rpec1; - break; -case 023: /* RPEC2 */ - *data = rpec2; - break; -default: /* all others */ - rper1[drv] = rper1[drv] | ER1_ILR; - update_rpcs (0, drv); - break; } -return SCPE_OK; -} - -t_stat rp_wr (int32 data, int32 PA, int32 access) -{ -int32 cs1f, drv, i, j; -UNIT *uptr; - -cs1f = 0; /* no int on cs1 upd */ -drv = GET_UNIT (rpcs2); /* get current unit */ -uptr = rp_dev.units + drv; /* get unit */ -j = (PA >> 1) & 037; /* get reg offset */ -if (reg_in_drive[j] && (rp_unit[drv].flags & UNIT_DIS)) { /* nx disk */ - rpcs2 = rpcs2 | CS2_NED; /* set error flag */ - update_rpcs (CS1_SC, drv); /* request intr */ - return SCPE_OK; } -if (reg_in_drive[j] && sim_is_active (&rp_unit[drv])) { /* unit busy? */ - rper1[drv] = rper1[drv] | ER1_RMR; /* won't write */ - update_rpcs (0, drv); - return SCPE_OK; } - -switch (j) { /* decode PA<5:1> */ -case 000: /* RPCS1 */ - if ((access == WRITEB) && (PA & 1)) data = data << 8; - if (data & CS1_TRE) { /* error clear? */ - rpcs1 = rpcs1 & ~CS1_TRE; /* clr CS1 */ - rpcs2 = rpcs2 & ~CS2_ERR; } /* clr CS2<15:8> */ - if ((access == WRITE) || (PA & 1)) { /* hi byte write? */ - if (rpcs1 & CS1_DONE) /* done set? */ - rpcs1 = (rpcs1 & ~CS1_UAE) | (data & CS1_UAE); } - if ((access == WRITE) || !(PA & 1)) { /* lo byte write? */ - if ((data & CS1_DONE) && (data & CS1_IE)) /* to DONE+IE? */ - rpiff = 1; /* set CSTB INTR */ - rpcs1 = (rpcs1 & ~CS1_IE) | (data & CS1_IE); - if (uptr->flags & UNIT_DIS) { /* nx disk? */ - rpcs2 = rpcs2 | CS2_NED; /* set error flag */ - cs1f = CS1_SC; } /* req interrupt */ - else if (sim_is_active (uptr)) - rper1[drv] = rper1[drv] | ER1_RMR; /* won't write */ - else if (data & CS1_GO) { /* start op */ - uptr->FUNC = GET_FNC (data); /* set func */ - if ((uptr->FUNC >= FNC_XFER) && /* data xfer and */ - ((rpcs1 & CS1_DONE) == 0)) /* ~rdy? PGE */ - rpcs2 = rpcs2 | CS2_PGE; - else rp_go (drv, uptr->FUNC); } } - break; -case 001: /* RPWC */ - if (access == WRITEB) data = (PA & 1)? - (rpwc & 0377) | (data << 8): (rpwc & ~0377) | data; - rpwc = data; - break; -case 002: /* RPBA */ - if (access == WRITEB) data = (PA & 1)? - (rpba & 0377) | (data << 8): (rpba & ~0377) | data; - rpba = data & ~BA_MBZ; - break; -case 003: /* RPDA */ - if (access == WRITEB) data = (PA & 1)? - (rpda & 0377) | (data << 8): (rpda & ~0377) | data; - rpda = data & ~DA_MBZ; - break; -case 004: /* RPCS2 */ - if ((access == WRITEB) && (PA & 1)) data = data << 8; - if (data & CS2_CLR) rp_reset (&rp_dev); /* init? */ - else { - if ((data & ~rpcs2) & (CS2_PE | CS2_MXF)) - cs1f = CS1_SC; /* diagn intr */ - if (access == WRITEB) data = (rpcs2 & /* merge data */ - ((PA & 1)? 0377: 0177400)) | data; - rpcs2 = (rpcs2 & ~CS2_RW) | (data & CS2_RW) | CS2_IR | CS2_OR; } - drv = GET_UNIT (rpcs2); - break; -case 006: /* RPER1 */ - if (access == WRITEB) break; - rper1[drv] = rper1[drv] & data; - break; -case 007: /* RPAS */ - if ((access == WRITEB) && (PA & 1)) break; - for (i = 0; i < RP_NUMDR; i++) - if (data & (AS_U0 << i)) rpds[i] = rpds[i] & ~DS_ATA; - break; -case 011: /* RPDB */ - if (access == WRITEB) data = (PA & 1)? - (rpdb & 0377) | (data << 8): (rpdb & ~0377) | data; - rpdb = data; - break; -case 012: /* RPMR */ - if (access == WRITEB) data = (PA & 1)? - (rpmr & 0377) | (data << 8): (rpmr & ~0377) | data; - rpmr = data; - break; -case 015: /* RPOF */ - if (access == WRITEB) data = (PA & 1)? - (rpof & 0377) | (data << 8): (rpof & ~0377) | data; - rpof = data & ~OF_MBZ; - break; -case 016: /* RPDC */ - if (access == WRITEB) data = (PA & 1)? - (rpdc & 0377) | (data << 8): (rpdc & ~0377) | data; - rpdc = data & ~DC_MBZ; - break; -case 005: /* RPDS */ -case 010: /* RPLA */ -case 013: /* RPDT */ -case 014: /* RPSN */ -case 017: /* RPDC, RMHR */ -case 020: /* RPER2, RMMN2 */ -case 021: /* RPER3, RMER2 */ -case 022: /* RPEC1 */ -case 023: /* RPEC2 */ - break; /* read only */ -default: /* all others */ - rper1[drv] = rper1[drv] | ER1_ILR; - break; } /* end switch */ -update_rpcs (cs1f, drv); /* update status */ -return SCPE_OK; -} - -/* Initiate operation - unit not busy, function set */ - -void rp_go (int32 drv, int32 fnc) -{ -int32 dc, dtype, t; -UNIT *uptr; - -uptr = rp_dev.units + drv; /* get unit */ -if (uptr->flags & UNIT_DIS) { /* nx unit? */ - rpcs2 = rpcs2 | CS2_NED; /* set error flag */ - update_rpcs (CS1_SC, drv); /* request intr */ - return; } -if ((fnc != FNC_DCLR) && (rpds[drv] & DS_ERR)) { /* err & ~clear? */ - rper1[drv] = rper1[drv] | ER1_ILF; /* not allowed */ - rpds[drv] = rpds[drv] | DS_ATA; /* set attention */ - update_rpcs (CS1_SC, drv); /* request intr */ - return; } -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -rpds[drv] = rpds[drv] & ~DS_ATA; /* clear attention */ -dc = rpdc; /* assume seek, sch */ - -switch (fnc) { /* case on function */ -case FNC_DCLR: /* drive clear */ - rpda = 0; /* clear disk addr */ - rper1[drv] = rper2 = rper3 = 0; /* clear errors */ -case FNC_NOP: /* no operation */ -case FNC_RELEASE: /* port release */ - return; - -case FNC_PRESET: /* read-in preset */ - rpdc = 0; /* clear disk addr */ - rpda = 0; - rpof = 0; /* clear offset */ -case FNC_PACK: /* pack acknowledge */ - rpds[drv] = rpds[drv] | DS_VV; /* set volume valid */ - return; - -case FNC_OFFSET: /* offset mode */ -case FNC_RETURN: - if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ - break; } - rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */ - sim_activate (uptr, rp_swait); /* time operation */ - return; - -case FNC_UNLOAD: /* unload */ -case FNC_RECAL: /* recalibrate */ - dc = 0; /* seek to 0 */ -case FNC_SEEK: /* seek */ -case FNC_SEARCH: /* search */ - if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ - break; } - if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */ - (GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */ - (GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */ - rper1[drv] = rper1[drv] | ER1_IAE; - break; } - rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */ - t = abs (dc - uptr->CYL); /* cyl diff */ - if (t == 0) t = 1; /* min time */ - sim_activate (uptr, rp_swait * t); /* schedule */ - uptr->CYL = dc; /* save cylinder */ - return; - -case FNC_WRITEH: /* write headers */ -case FNC_WRITE: /* write */ -case FNC_WCHK: /* write check */ -case FNC_READ: /* read */ -case FNC_READH: /* read headers */ - if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ - break; } - rpcs2 = rpcs2 & ~CS2_ERR; /* clear errors */ - rpcs1 = rpcs1 & ~(CS1_TRE | CS1_MCPE | CS1_DONE); - if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */ - (GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */ - (GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */ - rper1[drv] = rper1[drv] | ER1_IAE; - break; } - rpds[drv] = rpds[drv] & ~DS_RDY; /* clear drive rdy */ - sim_activate (uptr, rp_rwait + (rp_swait * abs (dc - uptr->CYL))); - uptr->CYL = dc; /* save cylinder */ - return; - -default: /* all others */ - rper1[drv] = rper1[drv] | ER1_ILF; /* not supported */ - break; } -rpds[drv] = rpds[drv] | DS_ATA; /* error, set attn */ -update_rpcs (CS1_SC, drv); /* req intr */ -return; -} - -/* Service unit timeout - - Complete movement or data transfer command - Unit must exist - can't remove an active unit - Unit must be attached - detach cancels in progress operations -*/ - -t_stat rp_svc (UNIT *uptr) -{ -int32 i, dtype, drv, err; -int32 ba, da, vpn; -a10 pa10, mpa10; -int32 wc10, twc10, awc10, fc10; -static d10 dbuf[RP_MAXFR]; - -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -drv = uptr - rp_dev.units; /* get drv number */ -rpds[drv] = (rpds[drv] & ~DS_PIP) | DS_RDY; /* change drive status */ - -switch (uptr->FUNC) { /* case on function */ -case FNC_OFFSET: /* offset */ - rpds[drv] = rpds[drv] | DS_OF | DS_ATA; /* set offset, attention */ - update_rpcs (CS1_SC, drv); - break; -case FNC_RETURN: /* return to centerline */ - rpds[drv] = (rpds[drv] & ~DS_OF) | DS_ATA; /* clear offset, set attn */ - update_rpcs (CS1_SC, drv); - break; -case FNC_UNLOAD: /* unload */ - rp_detach (uptr); /* detach unit */ - break; -case FNC_RECAL: /* recalibrate */ -case FNC_SEARCH: /* search */ -case FNC_SEEK: /* seek */ - rpds[drv] = rpds[drv] | DS_ATA; /* set attention */ - update_rpcs (CS1_SC, drv); - break; - -/* Reads and writes must take into account the complicated relationship - between Unibus addresses and PDP-10 memory addresses, and Unibus - byte and word counts, PDP-10 UBA word counts, and simulator PDP-10 - word counts (due to the fact that the simulator must transfer eight - 8b bytes to do a 36b transfer, whereas the UBA did four 9b bytes). -*/ - -#define XWC_MBZ 0000001 /* wc<0> must be 0 */ -#define XBA_MBZ 0000003 /* addr<1:0> must be 0 */ - -case FNC_WRITE: /* write */ - if (uptr->flags & UNIT_WPRT) { /* write locked? */ - rper1[drv] = rper1[drv] | ER1_WLE; /* set drive error */ - update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */ - break; } -case FNC_WCHK: /* write check */ -case FNC_READ: /* read */ -case FNC_READH: /* read headers */ - ba = GET_UAE (rpcs1) | rpba; /* get byte addr */ - wc10 = (0200000 - rpwc) >> 1; /* get PDP-10 wc */ - da = GET_DA (rpdc, rpda, dtype) * RP_NUMWD; /* get disk addr */ - if ((da + wc10) > drv_tab[dtype].size) { /* disk overrun? */ - rper1[drv] = rper1[drv] | ER1_AOE; - if (wc10 > (drv_tab[dtype].size - da)) - wc10 = drv_tab[dtype].size - da; } - - err = fseek (uptr->fileref, da * sizeof (d10), SEEK_SET); - if (uptr->FUNC == FNC_WRITE) { /* write? */ - for (twc10 = 0; twc10 < wc10; twc10++) { - pa10 = ba >> 2; - vpn = PAG_GETVPN (pa10); /* map addr */ - if ((vpn >= UMAP_MEMSIZE) || (ba & XBA_MBZ) || (rpwc & XWC_MBZ) || - ((ubmap[0][vpn] & (UMAP_VLD | UMAP_DSB | UMAP_RRV)) != UMAP_VLD)) { - rpcs2 = rpcs2 | CS2_NEM; /* set error */ - ubcs[0] = ubcs[0] | UBCS_TMO; /* UBA times out */ - break; } - mpa10 = (ubmap[0][vpn] + PAG_GETOFF (pa10)) & PAMASK; - if (MEM_ADDR_NXM (mpa10)) { /* nx memory? */ - rpcs2 = rpcs2 | CS2_NEM; /* set error */ - ubcs[0] = ubcs[0] | UBCS_TMO; /* UBA times out */ - break; } - dbuf[twc10] = M[mpa10]; /* write to disk */ - if ((rpcs2 & CS2_UAI) == 0) ba = ba + 4; } - if (fc10 = twc10 & (RP_NUMWD - 1)) { /* fill? */ - fc10 = RP_NUMWD - fc10; - for (i = 0; i < fc10; i++) dbuf[twc10 + i] = 0; } - fxwrite (dbuf, sizeof (d10), twc10 + fc10, uptr->fileref); - err = ferror (uptr->fileref); - } /* end if */ - else { /* read, wchk, readh */ - awc10 = fxread (dbuf, sizeof (d10), wc10, uptr->fileref); - err = ferror (uptr->fileref); - for ( ; awc10 < wc10; awc10++) dbuf[awc10] = 0; - for (twc10 = 0; twc10 < wc10; twc10++) { - pa10 = ba >> 2; - vpn = PAG_GETVPN (pa10); /* map addr */ - if ((vpn >= UMAP_MEMSIZE) || (ba & XBA_MBZ) || (rpwc & XWC_MBZ) || - ((ubmap[0][vpn] & (UMAP_VLD | UMAP_DSB | UMAP_RRV)) != UMAP_VLD)) { - rpcs2 = rpcs2 | CS2_NEM; /* set error */ - ubcs[0] = ubcs[0] | UBCS_TMO; /* UBA times out */ - break; } - mpa10 = (ubmap[0][vpn] + PAG_GETOFF (pa10)) & PAMASK; - if (MEM_ADDR_NXM (mpa10)) { /* nx memory? */ - rpcs2 = rpcs2 | CS2_NEM; /* set error */ - ubcs[0] = ubcs[0] | UBCS_TMO; /* UBA times out */ - break; } - if ((uptr->FUNC == FNC_READ) || /* read or */ - (uptr->FUNC == FNC_READH)) /* read header */ - M[mpa10] = dbuf[twc10]; - else if (M[mpa10] != dbuf[twc10]) { /* wchk, mismatch? */ - rpcs2 = rpcs2 | CS2_WCE; /* set error */ - break; } - if ((rpcs2 & CS2_UAI) == 0) ba = ba + 4; } - } /* end else */ - - rpwc = (rpwc + (twc10 << 1)) & 0177777; /* final word count */ - rpba = (ba & 0177777) & ~BA_MBZ; /* lower 16b */ - rpcs1 = (rpcs1 & ~ CS1_UAE) | ((ba >> (16 - CS1_V_UAE)) & CS1_UAE); - da = da + twc10 + (RP_NUMWD - 1); - if (da >= drv_tab[dtype].size) rpds[drv] = rpds[drv] | DS_LST; - da = da / RP_NUMWD; - rpda = da % drv_tab[dtype].sect; - da = da / drv_tab[dtype].sect; - rpda = rpda | ((da % drv_tab[dtype].surf) << DA_V_SF); - rpdc = da / drv_tab[dtype].surf; - - if (err != 0) { /* error? */ - rper1[drv] = rper1[drv] | ER1_PAR; /* set drive error */ - update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */ - perror ("RP I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -case FNC_WRITEH: /* write headers stub */ - update_rpcs (CS1_DONE, drv); /* set done */ - break; } /* end case func */ -return SCPE_OK; -} - -/* Controller status update - - Check for done transition - Update drive status - Update RPCS1 - Update interrupt request -*/ - -void update_rpcs (int32 flag, int32 drv) -{ -int32 i; -UNIT *uptr; - -if ((flag & ~rpcs1) & CS1_DONE) /* DONE 0 to 1? */ - rpiff = (rpcs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */ -uptr = rp_dev.units + drv; /* get unit */ -if (rp_unit[drv].flags & UNIT_DIS) rpds[drv] = rper1[drv] = 0; -else rpds[drv] = (rpds[drv] | DS_DPR) & ~DS_PGM; -if (rp_unit[drv].flags & UNIT_ATT) rpds[drv] = rpds[drv] | DS_MOL; -else rpds[drv] = rpds[drv] & ~(DS_MOL | DS_VV | DS_RDY); -if (rper1[drv] | rper2 | rper3) rpds[drv] = rpds[drv] | DS_ERR | DS_ATA; -else rpds[drv] = rpds[drv] & ~DS_ERR; - -rpcs1 = (rpcs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ | CS1_DRV)) | CS1_DVA | flag; -rpcs1 = rpcs1 | (uptr->FUNC << CS1_V_FNC); -if (sim_is_active (uptr)) rpcs1 = rpcs1 | CS1_GO; -if (rpcs2 & CS2_ERR) rpcs1 = rpcs1 | CS1_TRE | CS1_SC; -else if (rpcs1 & CS1_TRE) rpcs1 = rpcs1 | CS1_SC; -for (i = 0; i < RP_NUMDR; i++) - if (rpds[i] & DS_ATA) rpcs1 = rpcs1 | CS1_SC; -if (rpiff || ((rpcs1 & CS1_SC) && (rpcs1 & CS1_DONE) && (rpcs1 & CS1_IE))) - int_req = int_req | INT_RP; -else int_req = int_req & ~INT_RP; -return; -} - -/* Interrupt acknowledge */ - -int32 rp_inta (void) -{ -rpcs1 = rpcs1 & ~CS1_IE; /* clear int enable */ -rpiff = 0; /* clear CSTB INTR */ -return VEC_RP; /* acknowledge */ -} - -/* Device reset */ - -t_stat rp_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -rpcs1 = CS1_DVA | CS1_DONE; -rpcs2 = CS2_IR | CS2_OR; -rpba = rpda = 0; -rpof = rpdc = 0; -rper2 = rper3 = 0; -rpec1 = rpec2 = 0; -rpiff = 0; /* clear CSTB INTR */ -int_req = int_req & ~INT_RP; /* clear intr req */ -for (i = 0; i < RP_NUMDR; i++) { - uptr = rp_dev.units + i; - sim_cancel (uptr); - uptr->CYL = uptr->FUNC = 0; - if (uptr->flags & UNIT_ATT) rpds[i] = (rpds[i] & DS_VV) | - DS_DPR | DS_RDY | DS_MOL | ((uptr->flags & UNIT_WPRT)? DS_WRL: 0); - else if (uptr->flags & UNIT_DIS) rpds[i] = 0; - else rpds[i] = DS_DPR; - rper1[i] = 0; } -return SCPE_OK; -} - -/* Device attach */ - -t_stat rp_attach (UNIT *uptr, char *cptr) -{ -int32 drv, i, p; -t_stat r; - -uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size; -r = attach_unit (uptr, cptr); -if (r != SCPE_OK) return r; -drv = uptr - rp_dev.units; /* get drv number */ -rpds[drv] = DS_ATA | DS_MOL | DS_RDY | DS_DPR | - ((uptr->flags & UNIT_WPRT)? DS_WRL: 0); -rper1[drv] = 0; -update_rpcs (CS1_SC, drv); - -if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ -if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK; -if ((p = ftell (uptr->fileref)) == 0) return SCPE_OK; -for (i = 0; drv_tab[i].sect != 0; i++) { - if (p <= (drv_tab[i].size * (int) sizeof (d10))) { - uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); - uptr->capac = drv_tab[i].size; - return SCPE_OK; } } -return SCPE_OK; -} - -/* Device detach */ - -t_stat rp_detach (UNIT *uptr) -{ -int32 drv; - -drv = uptr - rp_dev.units; /* get drv number */ -rpds[drv] = (rpds[drv] & ~(DS_MOL | DS_RDY | DS_WRL | DS_VV | DS_OF)) | - DS_ATA; -if (sim_is_active (uptr)) { /* unit active? */ - sim_cancel (uptr); /* cancel operation */ - rper1[drv] = rper1[drv] | ER1_OPI; /* set drive error */ - if (uptr->FUNC >= FNC_WCHK) /* data transfer? */ - rpcs1 = rpcs1 | CS1_DONE | CS1_TRE; } /* set done, err */ -update_rpcs (CS1_SC, drv); /* request intr */ -return detach_unit (uptr); -} - -/* Set size command validation routine */ - -t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = drv_tab[GET_DTYPE (val)].size; -return SCPE_OK; -} - -/* Device bootstrap */ - -#define BOOT_START 0377000 /* start */ -#define BOOT_LEN (sizeof (boot_rom_dec) / sizeof (d10)) - -static const d10 boot_rom_dec[] = { - 0515040000001, /* boot:hrlzi 1,1 ; uba # */ - 0201000140001, /* movei 0,140001 ; vld,fst,pg 1 */ - 0713001000000+(IOBA_UBMAP+1 & RMASK), /* wrio 0,763001(1); set ubmap */ - 0435040000000+(IOBA_RP & RMASK), /* iori 1,776700 ; rh addr */ - 0202040000000+FE_RHBASE, /* movem 1,FE_RHBASE */ - 0201000000040, /* movei 0,40 ; ctrl reset */ - 0713001000010, /* wrio 0,10(1) ; ->RPCS2 */ - 0201000000021, /* movei 0,21 ; preset */ - 0713001000000, /* wrio 0,0(1) ; ->RPCS1 */ - 0201100000001, /* movei 2,1 ; blk #1 */ - 0265740377032, /* jsp 17,rdbl ; read */ - 0204140001000, /* movs 3,1000 ; id word */ - 0306140505755, /* cain 3,sixbit /HOM/ */ - 0254000377023, /* jrst .+6 ; match */ - 0201100000010, /* movei 2,10 ; blk #10 */ - 0265740377032, /* jsp 17,rdbl ; read */ - 0204140001000, /* movs 3,1000 ; id word */ - 0302140505755, /* caie 3,sixbit /HOM/ */ - 0254200377022, /* halt . ; inv home */ - 0336100001103, /* skipn 2,1103 ; pg of ptrs */ - 0254200377024, /* halt . ; inv ptr */ - 0265740377032, /* jsp 17,rdbl ; read */ - 0336100001004, /* skipn 2,1004 ; mon boot */ - 0254200377027, /* halt . ; inv ptr */ - 0265740377032, /* jsp 17,rdbl ; read */ - 0254000001000, /* jrst 1000 ; start */ - 0201140176000, /* rdbl:movei 3,176000 ; wd cnt */ - 0201200004000, /* movei 4,4000 ; addr */ - 0200240000000+FE_UNIT, /* move 5,FE_UNIT ; unit */ - 0200300000002, /* move 6,2 */ - 0242300777750, /* lsh 6,-24. ; cyl */ - 0713141000002, /* wrio 3,2(1) ; ->RPWC */ - 0713201000004, /* wrio 4,4(1) ; ->RPBA */ - 0713101000006, /* wrio 2,6(1) ; ->RPDA */ - 0713241000010, /* wrio 5,10(1) ; ->RPCS2 */ - 0713301000034, /* wrio 6,34(1) ; ->RPDC */ - 0201000000071, /* movei 0,71 ; read+go */ - 0713001000000, /* wrio 0,0(1) ; ->RPCS1 */ - 0712341000000, /* rdio 7,0(1) ; read csr */ - 0606340000200, /* trnn 7,200 ; test rdy */ - 0254000377046, /* jrst .-2 ; loop */ - 0602340100000, /* trne 7,100000 ; test err */ - 0254200377052, /* halt */ - 0254017000000, /* jrst 0(17) ; return */ -}; - -static const d10 boot_rom_its[] = { - 0515040000001, /* boot:hrlzi 1,1 ; uba # */ - 0201000140001, /* movei 0,140001 ; vld,fst,pg 1 */ - 0715000000000+(IOBA_UBMAP+1 & RMASK), /* iowrq 0,763001 ; set ubmap */ - 0435040000000+(IOBA_RP & RMASK), /* iori 1,776700 ; rh addr */ - 0202040000000+FE_RHBASE, /* movem 1,FE_RHBASE */ - 0201000000040, /* movei 0,40 ; ctrl reset */ - 0715001000010, /* iowrq 0,10(1) ; ->RPCS2 */ - 0201000000021, /* movei 0,21 ; preset */ - 0715001000000, /* iowrq 0,0(1) ; ->RPCS1 */ - 0201100000001, /* movei 2,1 ; blk #1 */ - 0265740377032, /* jsp 17,rdbl ; read */ - 0204140001000, /* movs 3,1000 ; id word */ - 0306140505755, /* cain 3,sixbit /HOM/ */ - 0254000377023, /* jrst .+6 ; match */ - 0201100000010, /* movei 2,10 ; blk #10 */ - 0265740377032, /* jsp 17,rdbl ; read */ - 0204140001000, /* movs 3,1000 ; id word */ - 0302140505755, /* caie 3,sixbit /HOM/ */ - 0254200377022, /* halt . ; inv home */ - 0336100001103, /* skipn 2,1103 ; pg of ptrs */ - 0254200377024, /* halt . ; inv ptr */ - 0265740377032, /* jsp 17,rdbl ; read */ - 0336100001004, /* skipn 2,1004 ; mon boot */ - 0254200377027, /* halt . ; inv ptr */ - 0265740377032, /* jsp 17,rdbl ; read */ - 0254000001000, /* jrst 1000 ; start */ - 0201140176000, /* rdbl:movei 3,176000 ; wd cnt */ - 0201200004000, /* movei 4,4000 ; addr */ - 0200240000000+FE_UNIT, /* move 5,FE_UNIT ; unit */ - 0200300000002, /* move 6,2 */ - 0242300777750, /* lsh 6,-24. ; cyl */ - 0715141000002, /* iowrq 3,2(1) ; ->RPWC */ - 0715201000004, /* iowrq 4,4(1) ; ->RPBA */ - 0715101000006, /* iowrq 2,6(1) ; ->RPDA */ - 0715241000010, /* iowrq 5,10(1) ; ->RPCS2 */ - 0715301000034, /* iowrq 6,34(1) ; ->RPDC */ - 0201000000071, /* movei 0,71 ; read+go */ - 0715001000000, /* iowrq 0,0(1) ; ->RPCS1 */ - 0711341000000, /* iordq 7,0(1) ; read csr */ - 0606340000200, /* trnn 7,200 ; test rdy */ - 0254000377046, /* jrst .-2 ; loop */ - 0602340100000, /* trne 7,100000 ; test err */ - 0254200377052, /* halt */ - 0254017000000, /* jrst 0(17) ; return */ -}; - -t_stat rp_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern a10 saved_PC; - -M[FE_UNIT] = unitno & CS2_M_UNIT; -for (i = 0; i < BOOT_LEN; i++) - M[BOOT_START + i] = ITS? boot_rom_its[i]: boot_rom_dec[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} diff --git a/PDP10/pdp10_sys.c b/PDP10/pdp10_sys.c deleted file mode 100644 index 477b5c47..00000000 --- a/PDP10/pdp10_sys.c +++ /dev/null @@ -1,798 +0,0 @@ -/* pdp10_sys.c: PDP-10 simulator interface - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 09-Jan-03 RMS Added DEUNA/DELUA support - 12-Sep-02 RMS Added RX211 support - 22-Apr-02 RMS Removed magtape record length error - 17-Sep-01 RMS Removed multiconsole support - 25-Aug-01 RMS Enabled DZ11 - 27-May-01 RMS Added multiconsole support - 29-Apr-01 RMS Fixed format for RDPCST, WRPCST - Added CLRCSH for ITS - 03-Apr-01 RMS Added support for loading EXE files - 19-Mar-01 RMS Added support for loading SAV files - 30-Oct-00 RMS Added support for examine to file -*/ - -#include "pdp10_defs.h" -#include - -extern DEVICE cpu_dev, pag_dev; -extern DEVICE tim_dev, fe_dev, uba_dev; -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE rp_dev, tu_dev; -extern DEVICE dz_dev, ry_dev; -extern DEVICE lp20_dev; -extern DEVICE xu_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern d10 *M; -extern a10 saved_PC; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "PDP-10"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 1; - -DEVICE *sim_devices[] = { - &cpu_dev, - &pag_dev, - &tim_dev, - &fe_dev, - &uba_dev, - &ptr_dev, - &ptp_dev, - &ry_dev, - &lp20_dev, - &rp_dev, - &tu_dev, - &dz_dev, - &xu_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "HALT instruction", - "Breakpoint", - "Illegal instruction", - "Illegal interrupt instruction", - "Paging error in interrupt", - "Zero vector table", - "NXM on UPT/EPT reference", - "Nested indirect address limit exceeded", - "Nested XCT limit exceeded", - "Invalid I/O controller", - "Address stop", - "Panic stop" }; - -/* Binary loader, supports RIM10, SAV, EXE */ - -#define FMT_R 1 /* RIM10 */ -#define FMT_S 2 /* SAV */ -#define FMT_E 3 /* EXE */ - -#define EXE_DIR 01776 /* EXE directory */ -#define EXE_VEC 01775 /* EXE entry vec */ -#define EXE_PDV 01774 /* EXE ignored */ -#define EXE_END 01777 /* EXE end - -/* RIM10 loader - - RIM10 format is a binary paper tape format (all data frames - are 200 or greater). It consists of blocks containing - - -count,,origin-1 - word - : - word - checksum (includes IOWD) - : - JRST start -*/ - -d10 getrimw (FILE *fileref) -{ -int32 i, tmp; -d10 word; - -word = 0; -for (i = 0; i < 6;) { - if ((tmp = getc (fileref)) == EOF) return -1; - if (tmp & 0200) { - word = (word << 6) | ((d10) tmp & 077); - i++; } } -return word; -} - -t_stat load_rim (FILE *fileref) -{ -d10 count, cksm, data; -a10 pa; -int32 op; - -for ( ;; ) { /* loop until JRST */ - count = cksm = getrimw (fileref); /* get header */ - if (count < 0) return SCPE_FMT; /* read err? */ - if (TSTS (count)) { /* hdr = IOWD? */ - for ( ; TSTS (count); count = AOB (count)) { - data = getrimw (fileref); /* get data wd */ - if (data < 0) return SCPE_FMT; - cksm = cksm + data; /* add to cksm */ - pa = ((a10) count + 1) & AMASK; /* store */ - M[pa] = data; } /* end for */ - data = getrimw (fileref); /* get cksm */ - if (data < 0) return SCPE_FMT; - if ((cksm + data) & DMASK) return SCPE_CSUM;/* test cksm */ - } /* end if count */ - else { - op = GET_OP (count); /* not IOWD */ - if (op != OP_JRST) return SCPE_FMT; /* JRST? */ - saved_PC = (a10) count & AMASK; /* set PC */ - return SCPE_OK; } /* end else */ - } /* end for */ -return SCPE_FMT; -} - -/* SAV file loader - - SAV format is a disk file format (36b words). It consists of - blocks containing: - - -count,,origin-1 - word - : - word - : - JRST start -*/ - -t_stat load_sav (FILE *fileref) -{ -d10 count, data; -a10 pa; -int32 wc, op; - -for ( ;; ) { /* loop */ - wc = fxread (&count, sizeof (d10), 1, fileref); /* read IOWD */ - if (wc == 0) return SCPE_OK; /* done? */ - if (TSTS (count)) { /* IOWD? */ - for ( ; TSTS (count); count = AOB (count)) { - wc = fxread (&data, sizeof (d10), 1, fileref); - if (wc == 0) return SCPE_FMT; - pa = ((a10) count + 1) & AMASK; /* store data */ - M[pa] = data; } /* end for */ - } /* end if count*/ - else { - op = GET_OP (count); /* not IOWD */ - if (op != OP_JRST) return SCPE_FMT; /* JRST? */ - saved_PC = (a10) count & AMASK; /* set PC */ - return SCPE_OK; } /* end else */ - } /* end for */ -return SCPE_FMT; -} - -/* EXE file loader - - EXE format is a disk file format (36b words). It consists of - blocks containing: - - block type,,total words = n - n - 1 data words - - Block types are - - EXE_DIR (1776) directory - EXE_VEC (1775) entry vector - EXE_PDV (1774) optional blocks - EXE_END (1777) end block - - The directory blocks are the most important and contain doubleword - page loading information: - - word0<0:8> = flags - <9:35> = page in file (0 if 0 page) - word1<0:8> = repeat count - 1 - <9:35> = page in memory -*/ - -#define DIRSIZ (2 * PAG_SIZE) - -t_stat load_exe (FILE *fileref) -{ -d10 data, dirbuf[DIRSIZ], pagbuf[PAG_SIZE], entbuf[2]; -int32 ndir, entvec, i, j, k, cont, bsz, bty, rpt, wc; -int32 fpage, mpage; -a10 ma; - -ndir = entvec = 0; /* no dir, entvec */ -cont = 1; -do { wc = fxread (&data, sizeof (d10), 1, fileref); /* read blk hdr */ - if (wc == 0) return SCPE_FMT; /* error? */ - bsz = (int32) ((data & RMASK) - 1); /* get count */ - if (bsz <= 0) return SCPE_FMT; /* zero? */ - bty = (int32) LRZ (data); /* get type */ - switch (bty) { /* case type */ - case EXE_DIR: /* directory */ - if (ndir) return SCPE_FMT; /* got one */ - ndir = fxread (dirbuf, sizeof (d10), bsz, fileref); - if (ndir < bsz) return SCPE_FMT; /* error */ - break; - case EXE_PDV: /* ??? */ - fseek (fileref, bsz * sizeof (d10), SEEK_CUR); - break; - case EXE_VEC: /* entry vec */ - if (bsz != 2) return SCPE_FMT; /* must be 2 wds */ - entvec = fxread (entbuf, sizeof (d10), bsz, fileref); - if (entvec < 2) return SCPE_FMT; /* error? */ - cont = 0; /* stop */ - break; - case EXE_END: /* end */ - if (bsz != 0) return SCPE_FMT; /* must be hdr */ - cont = 0; /* stop */ - break; - default: - return SCPE_FMT; } /* end switch */ - } /* end do */ -while (cont); - -for (i = 0; i < ndir; i = i + 2) { /* loop thru dir */ - fpage = (int32) (dirbuf[i] & RMASK); /* file page */ - mpage = (int32) (dirbuf[i + 1] & RMASK); /* memory page */ - rpt = (int32) ((dirbuf[i + 1] >> 27) + 1); /* repeat count */ - for (j = 0; j < rpt; j++, mpage++) { /* loop thru rpts */ - if (fpage) { /* file pages? */ - fseek (fileref, (fpage << PAG_V_PN) * sizeof (d10), SEEK_SET); - wc = fxread (pagbuf, sizeof (d10), PAG_SIZE, fileref); - if (wc < PAG_SIZE) return SCPE_FMT; - fpage++; } - ma = mpage << PAG_V_PN; /* mem addr */ - for (k = 0; k < PAG_SIZE; k++, ma++) { /* copy buf to mem */ - if (MEM_ADDR_NXM (ma)) return SCPE_NXM; - M[ma] = fpage? (pagbuf[k] & DMASK): 0; - } /* end copy */ - } /* end rpt */ - } /* end directory */ -if (entvec && entbuf[1]) - saved_PC = (int32) entbuf[1] & RMASK; /* start addr */ -return SCPE_OK; -} - -/* Master loader */ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -d10 data; -int32 wc, fmt; -extern int32 sim_switches; - -fmt = 0; /* no fmt */ -if (sim_switches & SWMASK ('R')) fmt = FMT_R; /* -r? */ -else if (sim_switches & SWMASK ('S')) fmt = FMT_S; /* -s? */ -else if (sim_switches & SWMASK ('E')) fmt = FMT_E; /* -e? */ -else if (match_ext (fnam, "RIM")) fmt = FMT_R; /* .RIM? */ -else if (match_ext (fnam, "SAV")) fmt = FMT_S; /* .SAV? */ -else if (match_ext (fnam, "EXE")) fmt = FMT_E; /* .EXE? */ -else { wc = fxread (&data, sizeof (d10), 1, fileref); /* read hdr */ - if (wc == 0) return SCPE_FMT; /* error? */ - if (LRZ (data) == EXE_DIR) fmt = FMT_E; /* EXE magic? */ - else if (TSTS (data)) fmt = FMT_S; /* SAV magic? */ - fseek (fileref, 0, SEEK_SET); } /* rewind */ -switch (fmt) { /* case fmt */ -case FMT_R: /* RIM */ - return load_rim (fileref); -case FMT_S: /* SAV */ - return load_sav (fileref); -case FMT_E: /* EXE */ - return load_exe (fileref); } -printf ("Can't determine load file format\n"); -return SCPE_FMT; -} - -/* Symbol tables */ - -#define I_V_FL 39 /* inst class */ -#define I_M_FL 03 /* class mask */ -#define I_ITS 004000000000000 /* ITS flag */ -#define I_AC 000000000000000 /* AC, address */ -#define I_OP 010000000000000 /* address only */ -#define I_IO 020000000000000 /* classic I/O */ -#define I_V_AC 00 -#define I_V_OP 01 -#define I_V_IO 02 - -static const d10 masks[] = { - 0777000000000, 0777740000000, - 0700340000000, 0777777777777 }; - -static const char *opcode[] = { -"XCTR", "XCTI", /* ITS only */ -"IORDI", "IORDQ", "IORD", "IOWR", "IOWRI", "IOWRQ", -"IORDBI", "IORDBQ", "IORDB", "IOWRB", "IOWRBI", "IOWRBQ", -"CLRCSH", "RDPCST", "WRPCST", -"SDBR1", "SDBR2", "SDBR3", "SDBR4", "SPM", -"LDBR1", "LDBR2", "LDBR3", "LDBR4", "LPMR", - -"PORTAL", "JRSTF", "HALT", /* AC defines op */ -"XJRSTF", "XJEN", "XPCW", -"JEN", "SFM", "XJRST", "IBP", -"JFOV", "JCRY1", "JCRY0", "JCRY", "JOV", - -"APRID", "WRAPR", "RDAPR", "WRPI", "RDPI", "RDUBR", "CLRPT", "WRUBR", -"WREBR", "RDEBR", -"RDSPB", "RDCSB", "RDPUR", "RDCSTM", "RDTIM", "RDINT", "RDHSB", -"WRSPB", "WRCSB", "WRPUR", "WRCSTM", "WRTIM", "WRINT", "WRHSB", - - "LUUO01", "LUUO02", "LUUO03", "LUUO04", "LUUO05", "LUUO06", "LUUO07", -"LUUO10", "LUUO11", "LUUO12", "LUUO13", "LUUO14", "LUUO15", "LUUO16", "LUUO17", -"LUUO20", "LUUO21", "LUUO22", "LUUO23", "LUUO24", "LUUO25", "LUUO26", "LUUO27", -"LUUO30", "LUUO31", "LUUO32", "LUUO33", "LUUO34", "LUUO35", "LUUO36", "LUUO37", -"MUUO40", "MUUO41", "MUUO42", "MUUO43", "MUUO44", "MUUO45", "MUUO46", "MUUO47", -"MUUO50", "MUUO51", "MUUO52", "MUUO53", "MUUO54", "MUUO55", "MUUO56", "MUUO57", -"MUUO60", "MUUO61", "MUUO62", "MUUO63", "MUUO64", "MUUO65", "MUUO66", "MUUO67", -"MUUO70", "MUUO71", "MUUO72", "MUUO73", "MUUO74", "MUUO75", "MUUO76", "MUUO77", - -"UJEN", "GFAD", "GFSB", "JSYS", "ADJSP", "GFMP", "GFDV ", -"DFAD", "DFSB", "DFMP", "DFDV", "DADD", "DSUB", "DMUL", "DDIV", -"DMOVE", "DMOVN", "FIX", "EXTEND", "DMOVEM", "DMOVNM", "FIXR", "FLTR", -"UFA", "DFN", "FSC", "ADJBP", "ILDB", "LDB", "IDPB", "DPB", -"FAD", "FADL", "FADM", "FADB", "FADR", "FADRL", "FADRM", "FADRB", -"FSB", "FSBL", "FSBM", "FSBB", "FSBR", "FSBRL", "FSBRM", "FSBRB", -"FMP", "FMPL", "FMPM", "FMPB", "FMPR", "FMPRL", "FMPRM", "FMPRB", -"FDV", "FDVL", "FDVM", "FDVB", "FDVR", "FDVRL", "FDVRM", "FDVRB", - -"MOVE", "MOVEI", "MOVEM", "MOVES", "MOVS", "MOVSI", "MOVSM", "MOVSS", -"MOVN", "MOVNI", "MOVNM", "MOVNS", "MOVM", "MOVMI", "MOVMM", "MOVMS", -"IMUL", "IMULI", "IMULM", "IMULB", "MUL", "MULI", "MULM", "MULB", -"IDIV", "IDIVI", "IDIVM", "IDIVB", "DIV", "DIVI", "DIVM", "DIVB", -"ASH", "ROT", "LSH", "JFFO", "ASHC", "ROTC", "LSHC", "CIRC", -"EXCH", "BLT", "AOBJP", "AOBJN", "JRST", "JFCL", "XCT", "MAP", -"PUSHJ", "PUSH", "POP", "POPJ", "JSR", "JSP", "JSA", "JRA", -"ADD", "ADDI", "ADDM", "ADDB", "SUB", "SUBI", "SUBM", "SUBB", - -"CAI", "CAIL", "CAIE", "CAILE", "CAIA", "CAIGE", "CAIN", "CAIG", -"CAM", "CAML", "CAME", "CAMLE", "CAMA", "CAMGE", "CAMN", "CAMG", -"JUMP", "JUMPL", "JUMPE", "JUMPLE", "JUMPA", "JUMPGE", "JUMPN", "JUMPG", -"SKIP", "SKIPL", "SKIPE", "SKIPLE", "SKIPA", "SKIPGE", "SKIPN", "SKIPG", -"AOJ", "AOJL", "AOJE", "AOJLE", "AOJA", "AOJGE", "AOJN", "AOJG", -"AOS", "AOSL", "AOSE", "AOSLE", "AOSA", "AOSGE", "AOSN", "AOSG", -"SOJ", "SOJL", "SOJE", "SOJLE", "SOJA", "SOJGE", "SOJN", "SOJG", -"SOS", "SOSL", "SOSE", "SOSLE", "SOSA", "SOSGE", "SOSN", "SOSG", - -"SETZ", "SETZI", "SETZM", "SETZB", "AND", "ANDI", "ANDM", "ANDB", -"ANDCA", "ANDCAI", "ANDCAM", "ANDCAB", "SETM", "SETMI", "SETMM", "SETMB", -"ANDCM", "ANDCMI", "ANDCMM", "ANDCMB", "SETA", "SETAI", "SETAM", "SETAB", -"XOR", "XORI", "XORM", "XORB", "IOR", "IORI", "IORM", "IORB", -"ANDCB", "ANDCBI", "ANDCBM", "ANDCBB", "EQV", "EQVI", "EQVM", "EQVB", -"SETCA", "SETCAI", "SETCAM", "SETCAB", "ORCA", "ORCAI", "ORCAM", "ORCAB", -"SETCM", "SETCMI", "SETCMM", "SETCMB", "ORCM", "ORCMI", "ORCMM", "ORCMB", -"ORCB", "ORCBI", "ORCBM", "ORCBB", "SETO", "SETOI", "SETOM", "SETOB", - -"HLL", "HLLI", "HLLM", "HLLS", "HRL", "HRLI", "HRLM", "HRLS", -"HLLZ", "HLLZI", "HLLZM", "HLLZS", "HRLZ", "HRLZI", "HRLZM", "HRLZS", -"HLLO", "HLLOI", "HLLOM", "HLLOS", "HRLO", "HRLOI", "HRLOM", "HRLOS", -"HLLE", "HLLEI", "HLLEM", "HLLES", "HRLE", "HRLEI", "HRLEM", "HRLES", -"HRR", "HRRI", "HRRM", "HRRS", "HLR", "HLRI", "HLRM", "HLRS", -"HRRZ", "HRRZI", "HRRZM", "HRRZS", "HLRZ", "HLRZI", "HLRZM", "HLRZS", -"HRRO", "HRROI", "HRROM", "HRROS", "HLRO", "HLROI", "HLROM", "HLROS", -"HRRE", "HRREI", "HRREM", "HRRES", "HLRE", "HLREI", "HLREM", "HLRES", - -"TRN", "TLN", "TRNE", "TLNE", "TRNA", "TLNA", "TRNN", "TLNN", -"TDN", "TSN", "TDNE", "TSNE", "TDNA", "TSNA", "TDNN", "TSNN", -"TRZ", "TLZ", "TRZE", "TLZE", "TRZA", "TLZA", "TRZN", "TLZN", -"TDZ", "TSZ", "TDZE", "TSZE", "TDZA", "TSZA", "TDZN", "TSZN", -"TRC", "TLC", "TRCE", "TLCE", "TRCA", "TLCA", "TRCN", "TLCN", -"TDC", "TSC", "TDCE", "TSCE", "TDCA", "TSCA", "TDCN", "TSCN", -"TRO", "TLO", "TROE", "TLOE", "TROA", "TLOA", "TRON", "TLON", -"TDO", "TSO", "TDOE", "TSOE", "TDOA", "TSOA", "TDON", "TSON", - -"UMOVE", "UMOVEM", /* KS10 I/O */ -"TIOE", "TION", "RDIO", "WRIO", -"BSIO", "BCIO", "BLTBU", "BLTUB", -"TIOEB", "TIONB", "RDIOB", "WRIOB", -"BSIOB", "BCIOB", - -"BLKI", "DATAI", "BLKO", "DATAO", /* classic I/O */ -"CONO", "CONI", "CONSZ", "CONSO", - -"CLEAR", "CLEARI", "CLEARM", "CLEARB", -"OR", "ORI", "ORM", "ORB", "XMOVEI", "XHLLI", /* alternate ops */ - - "CMPSL", "CMPSE", "CMPSLE", /* extended ops */ -"EDIT", "CMPSGE", "CMPSN", "CMPSG", -"CVTDBO", "CVTDBT", "CVTBDO", "CVTBDT", -"MOVSO", "MOVST", "MOVSLJ", "MOVSRJ", -"XBLT", "GSNGL", "GDBLE", "GDFIX", -"GFIX", "GDFIXR", "GFIXR", "DGFLTR", -"GFLTR", "GFSC", - -NULL }; - -static const d10 opc_val[] = { - 0102000000000+I_AC+I_ITS, 0103000000000+I_AC+I_ITS, - 0710000000000+I_AC+I_ITS, 0711000000000+I_AC+I_ITS, 0712000000000+I_AC+I_ITS, - 0713000000000+I_AC+I_ITS, 0714000000000+I_AC+I_ITS, 0715000000000+I_AC+I_ITS, - 0720000000000+I_AC+I_ITS, 0721000000000+I_AC+I_ITS, 0722000000000+I_AC+I_ITS, - 0723000000000+I_AC+I_ITS, 0724000000000+I_AC+I_ITS, 0725000000000+I_AC+I_ITS, - 0701000000000+I_OP+I_ITS, 0701440000000+I_OP+I_ITS, 0701540000000+I_OP+I_ITS, - 0702000000000+I_OP+I_ITS, 0702040000000+I_OP+I_ITS, - 0702100000000+I_OP+I_ITS, 0702140000000+I_OP+I_ITS, 0702340000000+I_OP+I_ITS, - 0702400000000+I_OP+I_ITS, 0702440000000+I_OP+I_ITS, - 0702500000000+I_OP+I_ITS, 0702540000000+I_OP+I_ITS, 0702740000000+I_OP+I_ITS, - - 0254040000000+I_OP, 0254100000000+I_OP, - 0254200000000+I_OP, 0254240000000+I_OP, 0254300000000+I_OP, 0254340000000+I_OP, - 0254500000000+I_OP, 0254600000000+I_OP, 0254640000000+I_OP, 0133000000000+I_OP, - 0255040000000+I_OP, 0255100000000+I_OP, 0255200000000+I_OP, 0255300000000+I_OP, - 0255400000000+I_OP, - - 0700000000000+I_OP, 0700200000000+I_OP, 0700240000000+I_OP, 0700600000000+I_OP, - 0700640000000+I_OP, 0701040000000+I_OP, 0701100000000+I_OP, 0701140000000+I_OP, - 0701200000000+I_OP, 0701240000000+I_OP, - 0702000000000+I_OP, 0702040000000+I_OP, 0702100000000+I_OP, 0702140000000+I_OP, - 0702200000000+I_OP, 0702240000000+I_OP, 0702300000000+I_OP, - 0702400000000+I_OP, 0702440000000+I_OP, 0702500000000+I_OP, 0702540000000+I_OP, - 0702600000000+I_OP, 0702640000000+I_OP, 0702700000000+I_OP, - - 0001000000000+I_AC, 0002000000000+I_AC, 0003000000000+I_AC, - 0004000000000+I_AC, 0005000000000+I_AC, 0006000000000+I_AC, 0007000000000+I_AC, - 0010000000000+I_AC, 0011000000000+I_AC, 0012000000000+I_AC, 0013000000000+I_AC, - 0014000000000+I_AC, 0015000000000+I_AC, 0016000000000+I_AC, 0017000000000+I_AC, - 0020000000000+I_AC, 0021000000000+I_AC, 0022000000000+I_AC, 0023000000000+I_AC, - 0024000000000+I_AC, 0025000000000+I_AC, 0026000000000+I_AC, 0027000000000+I_AC, - 0030000000000+I_AC, 0031000000000+I_AC, 0032000000000+I_AC, 0033000000000+I_AC, - 0034000000000+I_AC, 0035000000000+I_AC, 0036000000000+I_AC, 0037000000000+I_AC, - 0040000000000+I_AC, 0041000000000+I_AC, 0042000000000+I_AC, 0043000000000+I_AC, - 0044000000000+I_AC, 0045000000000+I_AC, 0046000000000+I_AC, 0047000000000+I_AC, - 0050000000000+I_AC, 0051000000000+I_AC, 0052000000000+I_AC, 0053000000000+I_AC, - 0054000000000+I_AC, 0055000000000+I_AC, 0056000000000+I_AC, 0057000000000+I_AC, - 0060000000000+I_AC, 0061000000000+I_AC, 0062000000000+I_AC, 0063000000000+I_AC, - 0064000000000+I_AC, 0065000000000+I_AC, 0066000000000+I_AC, 0067000000000+I_AC, - 0070000000000+I_AC, 0071000000000+I_AC, 0072000000000+I_AC, 0073000000000+I_AC, - 0074000000000+I_AC, 0075000000000+I_AC, 0076000000000+I_AC, 0077000000000+I_AC, - - 0100000000000+I_AC, 0102000000000+I_AC, 0103000000000+I_AC, - 0104000000000+I_AC, 0105000000000+I_AC, 0106000000000+I_AC, 0107000000000+I_AC, - 0110000000000+I_AC, 0111000000000+I_AC, 0112000000000+I_AC, 0113000000000+I_AC, - 0114000000000+I_AC, 0115000000000+I_AC, 0116000000000+I_AC, 0117000000000+I_AC, - 0120000000000+I_AC, 0121000000000+I_AC, 0122000000000+I_AC, 0123000000000+I_AC, - 0124000000000+I_AC, 0125000000000+I_AC, 0126000000000+I_AC, 0127000000000+I_AC, - 0130000000000+I_AC, 0131000000000+I_AC, 0132000000000+I_AC, 0133000000000+I_AC, - 0134000000000+I_AC, 0135000000000+I_AC, 0136000000000+I_AC, 0137000000000+I_AC, - 0140000000000+I_AC, 0141000000000+I_AC, 0142000000000+I_AC, 0143000000000+I_AC, - 0144000000000+I_AC, 0145000000000+I_AC, 0146000000000+I_AC, 0147000000000+I_AC, - 0150000000000+I_AC, 0151000000000+I_AC, 0152000000000+I_AC, 0153000000000+I_AC, - 0154000000000+I_AC, 0155000000000+I_AC, 0156000000000+I_AC, 0157000000000+I_AC, - 0160000000000+I_AC, 0161000000000+I_AC, 0162000000000+I_AC, 0163000000000+I_AC, - 0164000000000+I_AC, 0165000000000+I_AC, 0166000000000+I_AC, 0167000000000+I_AC, - 0170000000000+I_AC, 0171000000000+I_AC, 0172000000000+I_AC, 0173000000000+I_AC, - 0174000000000+I_AC, 0175000000000+I_AC, 0176000000000+I_AC, 0177000000000+I_AC, - - 0200000000000+I_AC, 0201000000000+I_AC, 0202000000000+I_AC, 0203000000000+I_AC, - 0204000000000+I_AC, 0205000000000+I_AC, 0206000000000+I_AC, 0207000000000+I_AC, - 0210000000000+I_AC, 0211000000000+I_AC, 0212000000000+I_AC, 0213000000000+I_AC, - 0214000000000+I_AC, 0215000000000+I_AC, 0216000000000+I_AC, 0217000000000+I_AC, - 0220000000000+I_AC, 0221000000000+I_AC, 0222000000000+I_AC, 0223000000000+I_AC, - 0224000000000+I_AC, 0225000000000+I_AC, 0226000000000+I_AC, 0227000000000+I_AC, - 0230000000000+I_AC, 0231000000000+I_AC, 0232000000000+I_AC, 0233000000000+I_AC, - 0234000000000+I_AC, 0235000000000+I_AC, 0236000000000+I_AC, 0237000000000+I_AC, - 0240000000000+I_AC, 0241000000000+I_AC, 0242000000000+I_AC, 0243000000000+I_AC, - 0244000000000+I_AC, 0245000000000+I_AC, 0246000000000+I_AC, 0247000000000+I_AC+I_ITS, - 0250000000000+I_AC, 0251000000000+I_AC, 0252000000000+I_AC, 0253000000000+I_AC, - 0254000000000+I_AC, 0255000000000+I_AC, 0256000000000+I_AC, 0257000000000+I_AC, - 0260000000000+I_AC, 0261000000000+I_AC, 0262000000000+I_AC, 0263000000000+I_AC, - 0264000000000+I_AC, 0265000000000+I_AC, 0266000000000+I_AC, 0267000000000+I_AC, - 0270000000000+I_AC, 0271000000000+I_AC, 0272000000000+I_AC, 0273000000000+I_AC, - 0274000000000+I_AC, 0275000000000+I_AC, 0276000000000+I_AC, 0277000000000+I_AC, - - 0300000000000+I_AC, 0301000000000+I_AC, 0302000000000+I_AC, 0303000000000+I_AC, - 0304000000000+I_AC, 0305000000000+I_AC, 0306000000000+I_AC, 0307000000000+I_AC, - 0310000000000+I_AC, 0311000000000+I_AC, 0312000000000+I_AC, 0313000000000+I_AC, - 0314000000000+I_AC, 0315000000000+I_AC, 0316000000000+I_AC, 0317000000000+I_AC, - 0320000000000+I_AC, 0321000000000+I_AC, 0322000000000+I_AC, 0323000000000+I_AC, - 0324000000000+I_AC, 0325000000000+I_AC, 0326000000000+I_AC, 0327000000000+I_AC, - 0330000000000+I_AC, 0331000000000+I_AC, 0332000000000+I_AC, 0333000000000+I_AC, - 0334000000000+I_AC, 0335000000000+I_AC, 0336000000000+I_AC, 0337000000000+I_AC, - 0340000000000+I_AC, 0341000000000+I_AC, 0342000000000+I_AC, 0343000000000+I_AC, - 0344000000000+I_AC, 0345000000000+I_AC, 0346000000000+I_AC, 0347000000000+I_AC, - 0350000000000+I_AC, 0351000000000+I_AC, 0352000000000+I_AC, 0353000000000+I_AC, - 0354000000000+I_AC, 0355000000000+I_AC, 0356000000000+I_AC, 0357000000000+I_AC, - 0360000000000+I_AC, 0361000000000+I_AC, 0362000000000+I_AC, 0363000000000+I_AC, - 0364000000000+I_AC, 0365000000000+I_AC, 0366000000000+I_AC, 0367000000000+I_AC, - 0370000000000+I_AC, 0371000000000+I_AC, 0372000000000+I_AC, 0373000000000+I_AC, - 0374000000000+I_AC, 0375000000000+I_AC, 0376000000000+I_AC, 0377000000000+I_AC, - - 0400000000000+I_AC, 0401000000000+I_AC, 0402000000000+I_AC, 0403000000000+I_AC, - 0404000000000+I_AC, 0405000000000+I_AC, 0406000000000+I_AC, 0407000000000+I_AC, - 0410000000000+I_AC, 0411000000000+I_AC, 0412000000000+I_AC, 0413000000000+I_AC, - 0414000000000+I_AC, 0415000000000+I_AC, 0416000000000+I_AC, 0417000000000+I_AC, - 0420000000000+I_AC, 0421000000000+I_AC, 0422000000000+I_AC, 0423000000000+I_AC, - 0424000000000+I_AC, 0425000000000+I_AC, 0426000000000+I_AC, 0427000000000+I_AC, - 0430000000000+I_AC, 0431000000000+I_AC, 0432000000000+I_AC, 0433000000000+I_AC, - 0434000000000+I_AC, 0435000000000+I_AC, 0436000000000+I_AC, 0437000000000+I_AC, - 0440000000000+I_AC, 0441000000000+I_AC, 0442000000000+I_AC, 0443000000000+I_AC, - 0444000000000+I_AC, 0445000000000+I_AC, 0446000000000+I_AC, 0447000000000+I_AC, - 0450000000000+I_AC, 0451000000000+I_AC, 0452000000000+I_AC, 0453000000000+I_AC, - 0454000000000+I_AC, 0455000000000+I_AC, 0456000000000+I_AC, 0457000000000+I_AC, - 0460000000000+I_AC, 0461000000000+I_AC, 0462000000000+I_AC, 0463000000000+I_AC, - 0464000000000+I_AC, 0465000000000+I_AC, 0466000000000+I_AC, 0467000000000+I_AC, - 0470000000000+I_AC, 0471000000000+I_AC, 0472000000000+I_AC, 0473000000000+I_AC, - 0474000000000+I_AC, 0475000000000+I_AC, 0476000000000+I_AC, 0477000000000+I_AC, - - 0500000000000+I_AC, 0501000000000+I_AC, 0502000000000+I_AC, 0503000000000+I_AC, - 0504000000000+I_AC, 0505000000000+I_AC, 0506000000000+I_AC, 0507000000000+I_AC, - 0510000000000+I_AC, 0511000000000+I_AC, 0512000000000+I_AC, 0513000000000+I_AC, - 0514000000000+I_AC, 0515000000000+I_AC, 0516000000000+I_AC, 0517000000000+I_AC, - 0520000000000+I_AC, 0521000000000+I_AC, 0522000000000+I_AC, 0523000000000+I_AC, - 0524000000000+I_AC, 0525000000000+I_AC, 0526000000000+I_AC, 0527000000000+I_AC, - 0530000000000+I_AC, 0531000000000+I_AC, 0532000000000+I_AC, 0533000000000+I_AC, - 0534000000000+I_AC, 0535000000000+I_AC, 0536000000000+I_AC, 0537000000000+I_AC, - 0540000000000+I_AC, 0541000000000+I_AC, 0542000000000+I_AC, 0543000000000+I_AC, - 0544000000000+I_AC, 0545000000000+I_AC, 0546000000000+I_AC, 0547000000000+I_AC, - 0550000000000+I_AC, 0551000000000+I_AC, 0552000000000+I_AC, 0553000000000+I_AC, - 0554000000000+I_AC, 0555000000000+I_AC, 0556000000000+I_AC, 0557000000000+I_AC, - 0560000000000+I_AC, 0561000000000+I_AC, 0562000000000+I_AC, 0563000000000+I_AC, - 0564000000000+I_AC, 0565000000000+I_AC, 0566000000000+I_AC, 0567000000000+I_AC, - 0570000000000+I_AC, 0571000000000+I_AC, 0572000000000+I_AC, 0573000000000+I_AC, - 0574000000000+I_AC, 0575000000000+I_AC, 0576000000000+I_AC, 0577000000000+I_AC, - - 0600000000000+I_AC, 0601000000000+I_AC, 0602000000000+I_AC, 0603000000000+I_AC, - 0604000000000+I_AC, 0605000000000+I_AC, 0606000000000+I_AC, 0607000000000+I_AC, - 0610000000000+I_AC, 0611000000000+I_AC, 0612000000000+I_AC, 0613000000000+I_AC, - 0614000000000+I_AC, 0615000000000+I_AC, 0616000000000+I_AC, 0617000000000+I_AC, - 0620000000000+I_AC, 0621000000000+I_AC, 0622000000000+I_AC, 0623000000000+I_AC, - 0624000000000+I_AC, 0625000000000+I_AC, 0626000000000+I_AC, 0627000000000+I_AC, - 0630000000000+I_AC, 0631000000000+I_AC, 0632000000000+I_AC, 0633000000000+I_AC, - 0634000000000+I_AC, 0635000000000+I_AC, 0636000000000+I_AC, 0637000000000+I_AC, - 0640000000000+I_AC, 0641000000000+I_AC, 0642000000000+I_AC, 0643000000000+I_AC, - 0644000000000+I_AC, 0645000000000+I_AC, 0646000000000+I_AC, 0647000000000+I_AC, - 0650000000000+I_AC, 0651000000000+I_AC, 0652000000000+I_AC, 0653000000000+I_AC, - 0654000000000+I_AC, 0655000000000+I_AC, 0656000000000+I_AC, 0657000000000+I_AC, - 0660000000000+I_AC, 0661000000000+I_AC, 0662000000000+I_AC, 0663000000000+I_AC, - 0664000000000+I_AC, 0665000000000+I_AC, 0666000000000+I_AC, 0667000000000+I_AC, - 0670000000000+I_AC, 0671000000000+I_AC, 0672000000000+I_AC, 0673000000000+I_AC, - 0674000000000+I_AC, 0675000000000+I_AC, 0676000000000+I_AC, 0677000000000+I_AC, - - 0704000000000+I_AC, 0705000000000+I_AC, - 0710000000000+I_AC, 0711000000000+I_AC, 0712000000000+I_AC, 0713000000000+I_AC, - 0714000000000+I_AC, 0715000000000+I_AC, 0716000000000+I_AC, 0717000000000+I_AC, - 0720000000000+I_AC, 0721000000000+I_AC, 0722000000000+I_AC, 0723000000000+I_AC, - 0724000000000+I_AC, 0725000000000+I_AC, - - 0700000000000+I_IO, 0700040000000+I_IO, 0700100000000+I_IO, 0700140000000+I_IO, - 0700200000000+I_IO, 0700240000000+I_IO, 0700300000000+I_IO, 0700340000000+I_IO, - - 0400000000000+I_AC, 0401000000000+I_AC, 0402000000000+I_AC, 0403000000000+I_AC, - 0434000000000+I_AC, 0435000000000+I_AC, 0436000000000+I_AC, 0437000000000+I_AC, - 0415000000000+I_AC, 0501000000000+I_AC, - - 0001000000000+I_AC, 0002000000000+I_AC, 0003000000000+I_AC, - 0004000000000+I_AC, 0005000000000+I_AC, 0006000000000+I_AC, 0007000000000+I_AC, - 0010000000000+I_AC, 0011000000000+I_AC, 0012000000000+I_AC, 0013000000000+I_AC, - 0014000000000+I_AC, 0015000000000+I_AC, 0016000000000+I_AC, 0017000000000+I_AC, - 0020000000000+I_AC, 0021000000000+I_AC, 0022000000000+I_AC, 0023000000000+I_AC, - 0024000000000+I_AC, 0025000000000+I_AC, 0026000000000+I_AC, 0027000000000+I_AC, - 0030000000000+I_AC, 0031000000000+I_AC, --1 }; - -#define NUMDEV 6 - -static const char *devnam[NUMDEV] = { - "APR", "PI", "PAG", "CCA", "TIM", "MTR"}; - - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - return = status code -*/ - -#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) -#define SIXTOASC(x) ((x) + 040) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 i, j, c, cflag, ac, xr, y, dev; -d10 inst; - -inst = val[0]; -cflag = (uptr == NULL) || (uptr == &cpu_unit); -if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; - fprintf (of, FMTASC ((int32) (inst & 0177))); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* character? */ - for (i = 30; i >= 0; i = i - 6) { - c = (int32) ((inst >> i) & 077); - fprintf (of, "%c", SIXTOASC (c)); } - return SCPE_OK; } -if (sw & SWMASK ('P')) { /* packed? */ - for (i = 29; i >= 0; i = i - 7) { - c = (int32) ((inst >> i) & 0177); - fprintf (of, FMTASC (c)); } - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; - -/* Instruction decode */ - -ac = GET_AC (inst); -xr = GET_XR (inst); -y = GET_ADDR (inst); -dev = GET_DEV (inst); -for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ - j = (int32) ((opc_val[i] >> I_V_FL) & I_M_FL); /* get class */ - if (((opc_val[i] & DMASK) == (inst & masks[j])) && /* match? */ - (((opc_val[i] & I_ITS) == 0) || ITS)) { - fprintf (of, "%s ", opcode[i]); /* opcode */ - switch (j) { /* case on class */ - case I_V_AC: /* AC + address */ - fprintf (of, "%-o,", ac); /* print AC, fall thru */ - case I_V_OP: /* address only */ - if (inst & INST_IND) fprintf (of, "@"); - if (xr) fprintf (of, "%-o(%-o)", y, xr); - else fprintf (of, "%-o", y); - break; - case I_V_IO: /* I/O */ - if (dev < NUMDEV) fprintf (of, "%s,", devnam[dev]); - else fprintf (of, "%-o,", dev); - if (inst & INST_IND) fprintf (of, "@"); - if (xr) fprintf (of, "%-o(%-o)", y, xr); - else fprintf (of, "%-o", y); - break; } /* end case */ - return SCPE_OK; } /* end if */ - } /* end for */ -return SCPE_ARG; -} - -/* Get operand, including indirect and index - - Inputs: - *cptr = pointer to input string - *status = pointer to error status - Outputs: - val = output value -*/ - -t_value get_opnd (char *cptr, t_stat *status) -{ -int32 sign = 0; -t_value val, xr = 0, ind = 0; -char *tptr; - -*status = SCPE_ARG; /* assume fail */ -if (*cptr == '@') { - ind = INST_IND; - cptr++; } -if (*cptr == '+') cptr++; -else if (*cptr == '-') { - sign = 1; - cptr++; } -val = strtotv (cptr, &tptr, 8); -if (val > 0777777) return 0; -if (sign) val = (~val + 1) & 0777777; -cptr = tptr; -if (*cptr == '(') { - cptr++; - xr = strtotv (cptr, &tptr, 8); - if ((cptr == tptr) || (*tptr != ')') || - (xr > AC_NUM) || (xr == 0)) return 0; - cptr = ++tptr; } -if (*cptr == 0) *status = SCPE_OK; -return (ind | (xr << 18) | val); -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = error status -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 cflag, i, j; -t_value ac, dev; -t_stat r; -char gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; -for (i = 0; i < 6; i++) { - if (cptr[i] == 0) { - for (j = i + 1; j <= 6; j++) cptr[j] = 0; - break; } } -if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (t_value) cptr[0]; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - for (i = 0; i < 6; i++) { - val[0] = (val[0] << 6); - if (cptr[i]) val[0] = val[0] | - ((t_value) ((cptr[i] + 040) & 077)); } - return SCPE_OK; } -if ((sw & SWMASK ('P')) || ((*cptr == '#') && cptr++)) { /* packed string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - for (i = 0; i < 5; i++) val[0] = (val[0] << 7) | ((t_value) cptr[i]); - val[0] = val[0] << 1; - return SCPE_OK; } - -/* Symbolic input, continued */ - -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; -if (opcode[i] == NULL) return SCPE_ARG; -val[0] = opc_val[i] & DMASK; /* get value */ -j = (int32) ((opc_val[i] >> I_V_FL) & I_M_FL); /* get class */ -switch (j) { /* case on class */ -case I_V_AC: /* AC + operand */ - if (strchr (cptr, ',')) { /* AC specified? */ - cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ - if (gbuf[0]) { /* can be omitted */ - ac = get_uint (gbuf, 8, AC_NUM - 1, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (ac << INST_V_AC); } } -case I_V_OP: /* operand */ - cptr = get_glyph (cptr, gbuf, 0); - val[0] = val[0] | get_opnd (gbuf, &r); - if (r != SCPE_OK) return SCPE_ARG; - break; -case I_V_IO: /* I/O */ - cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ - for (dev = 0; (dev < NUMDEV) && (strcmp (devnam[dev], gbuf) != 0); dev++); - if (dev >= NUMDEV) { - dev = get_uint (gbuf, 8, INST_M_DEV, &r); - if (r != SCPE_OK) return SCPE_ARG; } - val[0] = val[0] | (dev << INST_V_DEV); - cptr = get_glyph (cptr, gbuf, 0); - val[0] = val[0] | get_opnd (gbuf, &r); - if (r != SCPE_OK) return SCPE_ARG; - break; } /* end case */ -if (*cptr != 0) return SCPE_ARG; /* junk at end? */ -return SCPE_OK; -} diff --git a/PDP10/pdp10_tim.c b/PDP10/pdp10_tim.c deleted file mode 100644 index e2a0036b..00000000 --- a/PDP10/pdp10_tim.c +++ /dev/null @@ -1,201 +0,0 @@ -/* pdp10_tim.c: PDP-10 tim subsystem simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - tim timer subsystem - - 29-Jan-02 RMS New data structures - 06-Jan-02 RMS Added enable/disable support - 02-Dec-01 RMS Fixed bug in ITS PC sampling (found by Dave Conroy) - 31-Aug-01 RMS Changed int64 to t_int64 for Windoze - 17-Jul-01 RMS Moved function prototype - 04-Jul-01 RMS Added DZ11 support -*/ - -#include "pdp10_defs.h" -#include - -#define TIM_N_HWRE 12 /* hwre bits */ -#define TIM_HWRE 0000000010000 /* hwre incr */ -#define TIM_DELAY 500 -#define TIM_TPS 1001 /* ticks per sec */ -#define DZ_MULT (TIM_TPS / 60) /* DZ poll multiplier */ -#define TB_MASK 037777777777777777777; /* 71 - 12 bits */ -#define UNIT_V_Y2K (UNIT_V_UF) /* Y2K compliant OS */ -#define UNIT_Y2K (1u << UNIT_V_Y2K) - -extern int32 apr_flg, pi_act; -extern UNIT cpu_unit; -extern d10 pcst; -extern a10 pager_PC; -t_int64 timebase = 0; /* 71b timebase */ -d10 ttg = 0; /* time to go */ -d10 period = 0; /* period */ -d10 quant = 0; /* ITS quantum */ -int32 diagflg = 0; /* diagnostics? */ -int32 tmxr_poll = TIM_DELAY * DZ_MULT; /* term mux poll */ - -DEVICE tim_dev; -t_stat tcu_rd (int32 *data, int32 PA, int32 access); -extern t_stat wr_nop (int32 data, int32 PA, int32 access); -t_stat tim_svc (UNIT *uptr); -t_stat tim_reset (DEVICE *dptr); -extern d10 Read (a10 ea, int32 prv); -extern d10 ReadM (a10 ea, int32 prv); -extern void Write (a10 ea, d10 val, int32 prv); -extern void WriteP (a10 ea, d10 val); -extern int32 pi_eval (void); - -/* TIM data structures - - tim_dev TIM device descriptor - tim_unit TIM unit descriptor - tim_reg TIM register list -*/ - -DIB tcu_dib = { IOBA_TCU, IOLN_TCU, &tcu_rd, &wr_nop, 0 }; - -UNIT tim_unit = { UDATA (&tim_svc, 0, 0), TIM_DELAY }; - -REG tim_reg[] = { - { ORDATA (TIMEBASE, timebase, 71 - TIM_N_HWRE) }, - { ORDATA (TTG, ttg, 36) }, - { ORDATA (PERIOD, period, 36) }, - { ORDATA (QUANT, quant, 36) }, - { DRDATA (TIME, tim_unit.wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (DIAG, diagflg, 0) }, - { FLDATA (Y2K, tim_unit.flags, UNIT_V_Y2K), REG_HRO }, - { NULL } }; - -MTAB tim_mod[] = { - { UNIT_Y2K, 0, "non Y2K OS", "NOY2K", NULL }, - { UNIT_Y2K, UNIT_Y2K, "Y2K OS", "Y2K", NULL }, - { MTAB_XTD|MTAB_VDV, 000, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { 0 } }; - -DEVICE tim_dev = { - "TIM", &tim_unit, tim_reg, tim_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &tim_reset, - NULL, NULL, NULL, - &tcu_dib, DEV_DISABLE | DEV_UBUS }; - -/* Timer instructions */ - -t_bool rdtim (a10 ea, int32 prv) -{ -ReadM (INCA (ea), prv); -Write (ea, (timebase >> (35 - TIM_N_HWRE)) & DMASK, prv); -Write (INCA(ea), (timebase << TIM_N_HWRE) & MMASK, prv); -return FALSE; -} - -t_bool wrtim (a10 ea, int32 prv) -{ -timebase = (Read (ea, prv) << (35 - TIM_N_HWRE)) | - (CLRS (Read (INCA (ea), prv)) >> TIM_N_HWRE); -return FALSE; -} - -t_bool rdint (a10 ea, int32 prv) -{ -Write (ea, period, prv); -return FALSE; -} - -t_bool wrint (a10 ea, int32 prv) -{ -period = Read (ea, prv); -ttg = period; -return FALSE; -} - -/* Timer routines - - tim_svc process event (timer tick) - tim_reset process reset -*/ - -t_stat tim_svc (UNIT *uptr) -{ -int32 t; - -t = diagflg? tim_unit.wait: sim_rtc_calb (TIM_TPS); /* calibrate clock */ -sim_activate (&tim_unit, t); /* reactivate unit */ -tmxr_poll = t * DZ_MULT; /* set mux poll */ -timebase = (timebase + 1) & TB_MASK; /* increment timebase */ -ttg = ttg - TIM_HWRE; /* decrement timer */ -if (ttg <= 0) { /* timeout? */ - ttg = period; /* reload */ - apr_flg = apr_flg | APRF_TIM; } /* request interrupt */ -if (ITS) { /* ITS? */ - if (pi_act == 0) quant = (quant + TIM_HWRE) & DMASK; - if (TSTS (pcst)) { /* PC sampling? */ - WriteP ((a10) pcst & AMASK, pager_PC); /* store sample */ - pcst = AOB (pcst); } /* add 1,,1 */ - } /* end ITS */ -return SCPE_OK; -} - -t_stat tim_reset (DEVICE *dptr) -{ -period = ttg = 0; /* clear timer */ -apr_flg = apr_flg & ~APRF_TIM; /* clear interrupt */ -sim_activate (&tim_unit, tim_unit.wait); /* activate unit */ -tmxr_poll = tim_unit.wait * DZ_MULT; /* set mux poll */ -return SCPE_OK; -} - -/* Time of year clock */ - -t_stat tcu_rd (int32 *data, int32 PA, int32 access) -{ -time_t curtim; -struct tm *tptr; - -curtim = time (NULL); /* get time */ -tptr = localtime (&curtim); /* decompose */ -if (tptr == NULL) return SCPE_NXM; /* Y2K prob? */ -if ((tptr->tm_year > 99) && !(tim_unit.flags & UNIT_Y2K)) - tptr->tm_year = 99; - -switch ((PA >> 1) & 03) { /* decode PA<3:1> */ -case 0: /* year/month/day */ - *data = (((tptr->tm_year) & 0177) << 9) | - (((tptr->tm_mon + 1) & 017) << 5) | - ((tptr->tm_mday) & 037); - return SCPE_OK; -case 1: /* hour/minute */ - *data = (((tptr->tm_hour) & 037) << 8) | - ((tptr->tm_min) & 077); - return SCPE_OK; -case 2: /* second */ - *data = (tptr->tm_sec) & 077; - return SCPE_OK; -case 3: /* status */ - *data = CSR_DONE; - return SCPE_OK; } -return SCPE_NXM; /* can't get here */ -} diff --git a/PDP10/pdp10_tu.c b/PDP10/pdp10_tu.c deleted file mode 100644 index f457131a..00000000 --- a/PDP10/pdp10_tu.c +++ /dev/null @@ -1,1058 +0,0 @@ -/* pdp10_tu.c - PDP-10 RH11/TM03/TU45 magnetic tape simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - tu RH11/TM03/TU45 magtape - - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Revised for magtape library - 27-Jan-03 RMS Changed to dynamically allocate buffer - 21-Nov-02 RMS Fixed bug in bootstrap (reported by Michael Thompson) - Fixed bug in read (reported by Harris Newman) - 29-Sep-02 RMS Added variable vector support - New data structures - 28-Aug-02 RMS Added end of medium support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Changed record length error code - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Changed POS, FLG, UST to arrays - 23-Oct-01 RMS Fixed bug in error interrupts - New IO page address constants - 05-Oct-01 RMS Rewrote interrupt handling from schematics - 30-Sep-01 RMS Fixed handling of non-existent formatters - 28-Sep-01 RMS Fixed interrupt handling for SC/ATA - 4-May-01 RMS Fixed bug in odd address test - 3-May-01 RMS Fixed drive reset to clear SSC - - Magnetic tapes are represented as a series of variable 8b records - of the form: - - 32b record length in bytes - exact number, sign = error - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32b record length in bytes - exact number, sign = error - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a single record length of 0. - End of tape is two consecutive end of file marks. - - WARNING: The interupt logic of the RH11/RH70 is unusual and must be - simulated with great precision. The RH11 has an internal interrupt - request flop, CSTB INTR, which is controlled as follows: - - Writing IE and DONE simultaneously sets CSTB INTR - - Controller clear, INIT, and interrupt acknowledge clear CSTB INTR - (and also clear IE) - - A transition of DONE from 0 to 1 sets CSTB from INTR - The output of INTR is OR'd with the AND of RPCS1 to - create the interrupt request signal. Thus, - - The DONE interrupt is edge sensitive, but the SC interrupt is - level sensitive. - - The DONE interrupt, once set, is not disabled if IE is cleared, - but the SC interrupt is. -*/ - -#include "pdp10_defs.h" -#include "sim_tape.h" - -#define TU_NUMFM 1 /* #formatters */ -#define TU_NUMDR 8 /* #drives */ -#define USTAT u3 /* unit status */ -#define UDENS u4 /* unit density */ -#define UD_UNK 0 /* unknown */ -#define MT_MAXFR (1 << 16) /* max data buf */ - -/* MTCS1 - 172440 - control/status 1 */ - -#define CS1_GO CSR_GO /* go */ -#define CS1_V_FNC 1 /* function pos */ -#define CS1_M_FNC 037 /* function mask */ -#define CS1_FNC (CS1_M_FNC << CS1_V_FNC) -#define FNC_NOP 000 /* no operation */ -#define FNC_UNLOAD 001 /* unload */ -#define FNC_REWIND 003 /* rewind */ -#define FNC_FCLR 004 /* formatter clear */ -#define FNC_RIP 010 /* read in preset */ -#define FNC_ERASE 012 /* erase tape */ -#define FNC_WREOF 013 /* write tape mark */ -#define FNC_SPACEF 014 /* space forward */ -#define FNC_SPACER 015 /* space reverse */ -#define FNC_XFER 024 /* >=? data xfr */ -#define FNC_WCHKF 024 /* write check */ -#define FNC_WCHKR 027 /* write check rev */ -#define FNC_WRITE 030 /* write */ -#define FNC_READF 034 /* read forward */ -#define FNC_READR 037 /* read reverse */ -#define CS1_IE CSR_IE /* int enable */ -#define CS1_DONE CSR_DONE /* ready */ -#define CS1_V_UAE 8 /* Unibus addr ext */ -#define CS1_M_UAE 03 -#define CS1_UAE (CS1_M_UAE << CS1_V_UAE) -#define CS1_DVA 0004000 /* drive avail NI */ -#define CS1_MCPE 0020000 /* Mbus par err NI */ -#define CS1_TRE 0040000 /* transfer err */ -#define CS1_SC 0100000 /* special cond */ -#define CS1_MBZ 0012000 -#define CS1_DRV (CS1_FNC | CS1_GO) -#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC) -#define GET_UAE(x) (((x) & CS1_UAE) << (16 - CS1_V_UAE)) - -/* MTWC - 172442 - word count */ - -/* MTBA - 172444 - base address */ - -#define BA_MBZ 0000001 /* must be zero */ - -/* MTFC - 172446 - frame count */ - -/* MTCS2 - 172450 - control/status 2 */ - -#define CS2_V_FMTR 0 /* formatter select */ -#define CS2_M_FMTR 07 -#define CS2_FMTR (CS2_M_FMTR << CS2_V_FMTR) -#define CS2_UAI 0000010 /* addr inhibit NI */ -#define CS2_PAT 0000020 /* parity test NI */ -#define CS2_CLR 0000040 /* controller clear */ -#define CS2_IR 0000100 /* input ready */ -#define CS2_OR 0000200 /* output ready */ -#define CS2_MDPE 0000400 /* Mbus par err NI */ -#define CS2_MXF 0001000 /* missed xfer NI */ -#define CS2_PGE 0002000 /* program err */ -#define CS2_NEM 0004000 /* nx mem err */ -#define CS2_NEF 0010000 /* nx fmter err */ -#define CS2_PE 0020000 /* parity err NI */ -#define CS2_WCE 0040000 /* write chk err NI */ -#define CS2_DLT 0100000 /* data late NI */ -#define CS2_MBZ (CS2_CLR | CS2_WCE) -#define CS2_RW (CS2_FMTR | CS2_UAI | CS2_PAT | CS2_MXF | CS2_PE) -#define CS2_ERR (CS2_MDPE | CS2_MXF | CS2_PGE | CS2_NEM | \ - CS2_NEF | CS2_PE | CS2_DLT ) -#define GET_FMTR(x) (((x) >> CS2_V_FMTR) & CS2_M_FMTR) - -/* MTFS - 172452 - formatter status - + indicates kept in drive status - ^ indicates calculated on the fly -*/ - -#define FS_SAT 0000001 /* slave attention */ -#define FS_BOT 0000002 /* ^beginning of tape */ -#define FS_TMK 0000004 /* end of file */ -#define FS_ID 0000010 /* ID burst detected */ -#define FS_SLOW 0000020 /* slowing down NI */ -#define FS_PE 0000040 /* ^PE status */ -#define FS_SSC 0000100 /* slave stat change */ -#define FS_RDY 0000200 /* ^formatter ready */ -#define FS_FPR 0000400 /* formatter present */ -#define FS_EOT 0002000 /* +end of tape */ -#define FS_WRL 0004000 /* ^write locked */ -#define FS_MOL 0010000 /* ^medium online */ -#define FS_PIP 0020000 /* +pos in progress */ -#define FS_ERR 0040000 /* ^error */ -#define FS_ATA 0100000 /* attention active */ -#define FS_REW 0200000 /* +rewinding */ - -#define FS_DYN (FS_ERR | FS_PIP | FS_MOL | FS_WRL | FS_EOT | \ - FS_RDY | FS_PE | FS_BOT) - -/* MTER - 172454 - error register */ - -#define ER_ILF 0000001 /* illegal func */ -#define ER_ILR 0000002 /* illegal register */ -#define ER_RMR 0000004 /* reg mod refused */ -#define ER_MCP 0000010 /* Mbus cpar err NI */ -#define ER_FER 0000020 /* format sel err */ -#define ER_MDP 0000040 /* Mbus dpar err NI */ -#define ER_VPE 0000100 /* vert parity err */ -#define ER_CRC 0000200 /* CRC err NI */ -#define ER_NSG 0000400 /* non std gap err NI */ -#define ER_FCE 0001000 /* frame count err */ -#define ER_ITM 0002000 /* inv tape mark NI */ -#define ER_NXF 0004000 /* wlock or fnc err */ -#define ER_DTE 0010000 /* time err NI */ -#define ER_OPI 0020000 /* op incomplete */ -#define ER_UNS 0040000 /* drive unsafe */ -#define ER_DCK 0100000 /* data check NI */ - -/* MTAS - 172456 - attention summary */ - -#define AS_U0 0000001 /* unit 0 flag */ - -/* MTCC - 172460 - check character, read only */ - -#define CC_MBZ 0177000 /* must be zero */ - -/* MTDB - 172462 - data buffer */ - -/* MTMR - 172464 - maintenance register */ - -#define MR_RW 0177637 /* read/write */ - -/* MTDT - 172466 - drive type */ - -#define DT_TAPE 0040000 /* tape */ -#define DT_PRES 0002000 /* slave present */ -#define DT_TM03 0000040 /* TM03 formatter */ -#define DT_OFF 0000010 /* drive off */ -#define DT_TE16 0000011 /* TE16 */ -#define DT_TU45 0000012 /* TU45 */ -#define DT_TU77 0000014 /* TU77 */ - -/* MTSN - 172470 - serial number */ - -/* MTTC - 172472 - tape control register */ - -#define TC_V_UNIT 0 /* unit select */ -#define TC_M_UNIT 07 -#define TC_V_EVN 0000010 /* even parity */ -#define TC_V_FMT 4 /* format select */ -#define TC_M_FMT 017 -#define TC_10C 00 /* PDP-10 core dump */ -#define TC_IND 03 /* industry standard */ -#define TC_V_DEN 8 /* density select */ -#define TC_M_DEN 07 -#define TC_800 3 /* 800 bpi */ -#define TC_1600 4 /* 1600 bpi */ -#define TC_AER 0010000 /* abort on error */ -#define TC_SAC 0020000 /* slave addr change */ -#define TC_FCS 0040000 /* frame count status */ -#define TC_ACC 0100000 /* accelerating NI */ -#define TC_RW 0013777 -#define TC_MBZ 0004000 -#define GET_DEN(x) (((x) >> TC_V_DEN) & TC_M_DEN) -#define GET_FMT(x) (((x) >> TC_V_FMT) & TC_M_FMT) -#define GET_DRV(x) (((x) >> TC_V_UNIT) & TC_M_UNIT) - -/* Mapping macros */ - -#define XWC_MBZ 0000001 /* wc<0> mbz */ -#define XBA_MBZ 0000001 /* addr<0> mbz */ -#define XBA_ODD 0000002 /* odd address */ -#define TXFR(b,w,od) if (((b) & XBA_MBZ) || ((w) & XWC_MBZ) || \ - (((b) & XBA_ODD) != ((od) << 1))) { \ - tucs2 = tucs2 | CS2_NEM; \ - ubcs[1] = ubcs[1] | UBCS_TMO; \ - tucs1 = tucs1 & ~CS1_GO; \ - update_tucs (CS1_DONE, drv); \ - return SCPE_OK; } -#define NEWPAGE(v,m) (((v) & PAG_M_OFF) == (m)) -#define MAPM(v,p,f) vpn = PAG_GETVPN (v); \ - if ((vpn >= UMAP_MEMSIZE) || ((ubmap[1][vpn] & \ - (UMAP_VLD | UMAP_DSB | UMAP_RRV)) != \ - (UMAP_VLD | f))) { \ - tucs2 = tucs2 | CS2_NEM; \ - ubcs[1] = ubcs[1] | UBCS_TMO; \ - break; } \ - p = (ubmap[1][vpn] + PAG_GETOFF (v)) & PAMASK; \ - if (MEM_ADDR_NXM (p)) { \ - tucs2 = tucs2 | CS2_NEM; \ - ubcs[1] = ubcs[1] | UBCS_TMO; \ - break; } \ - - -extern d10 *M; /* memory */ -extern int32 int_req; -extern int32 int_vec[32]; -extern int32 ubmap[UBANUM][UMAP_MEMSIZE]; /* Unibus map */ -extern int32 ubcs[UBANUM]; -extern UNIT cpu_unit; - -int32 tucs1 = 0; /* control/status 1 */ -int32 tuwc = 0; /* word count */ -int32 tuba = 0; /* bus address */ -int32 tufc = 0; /* frame count */ -int32 tucs2 = 0; /* control/status 2 */ -int32 tufs = 0; /* formatter status */ -int32 tuer = 0; /* error status */ -int32 tucc = 0; /* check character */ -int32 tudb = 0; /* data buffer */ -int32 tumr = 0; /* maint register */ -int32 tutc = 0; /* tape control */ -int32 tuiff = 0; /* INTR flip/flop */ -int32 tu_time = 10; /* record latency */ -int32 tu_stopioe = 1; /* stop on error */ -int32 tu_log = 0; /* debug */ -int32 reg_in_fmtr[32] = { /* reg in formatter */ - 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; -int32 reg_in_fmtr1[32] = { /* rmr if write + go */ - 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; -int32 fmt_test[16] = { /* fmt bytes/10 wd */ - 5, 0, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -int32 den_test[8] = { /* valid densities */ - 0, 0, 0, 1, 1, 0, 0, 0 }; -static uint8 *xbuf = NULL; /* xfer buffer */ - -t_stat tu_rd (int32 *data, int32 PA, int32 access); -t_stat tu_wr (int32 data, int32 PA, int32 access); -int32 tu_inta (void); -t_stat tu_svc (UNIT *uptr); -t_stat tu_reset (DEVICE *dptr); -t_stat tu_attach (UNIT *uptr, char *cptr); -t_stat tu_detach (UNIT *uptr); -t_stat tu_boot (int32 unitno, DEVICE *dptr); -void tu_go (int32 drv); -void update_tucs (int32 flag, int32 drv); -t_stat tu_map_err (UNIT *uptr, t_stat st); - -/* TU data structures - - tu_dev TU device descriptor - tu_unit TU unit list - tu_reg TU register list - tu_mod TU modifier list -*/ - -DIB tu_dib = { IOBA_TU, IOLN_TU, &tu_rd, &tu_wr, - 1, IVCL (TU), VEC_TU, { &tu_inta } }; - -UNIT tu_unit[] = { - { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) } }; - -REG tu_reg[] = { - { ORDATA (MTCS1, tucs1, 16) }, - { ORDATA (MTWC, tuwc, 16) }, - { ORDATA (MTBA, tuba, 16) }, - { ORDATA (MTFC, tufc, 16) }, - { ORDATA (MTCS2, tucs2, 16) }, - { ORDATA (MTFS, tufs, 16) }, - { ORDATA (MTER, tuer, 16) }, - { ORDATA (MTCC, tucc, 16) }, - { ORDATA (MTDB, tudb, 16) }, - { ORDATA (MTMR, tumr, 16) }, - { ORDATA (MTTC, tutc, 16) }, - { FLDATA (IFF, tuiff, 0) }, - { FLDATA (INT, int_req, INT_V_TU) }, - { FLDATA (DONE, tucs1, CSR_V_DONE) }, - { FLDATA (IE, tucs1, CSR_V_IE) }, - { FLDATA (STOP_IOE, tu_stopioe, 0) }, - { DRDATA (TIME, tu_time, 24), PV_LEFT }, - { URDATA (UST, tu_unit[0].USTAT, 8, 17, 0, TU_NUMDR, 0) }, - { URDATA (POS, tu_unit[0].pos, 10, T_ADDR_W, 0, - TU_NUMDR, PV_LEFT | REG_RO) }, - { ORDATA (LOG, tu_log, 8), REG_HIDDEN }, - { NULL } }; - -MTAB tu_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; - -DEVICE tu_dev = { - "TU", tu_unit, tu_reg, tu_mod, - TU_NUMDR, 10, 31, 1, 8, 8, - NULL, NULL, &tu_reset, - &tu_boot, &tu_attach, &tu_detach, - &tu_dib, DEV_UBUS }; - -/* I/O dispatch routine, I/O addresses 17772440 - 17772472 */ - -t_stat tu_rd (int32 *data, int32 PA, int32 access) -{ -int32 fmtr, drv, j; - -fmtr = GET_FMTR (tucs2); /* get current fmtr */ -drv = GET_DRV (tutc); /* get current drive */ -j = (PA >> 1) & 017; /* get reg offset */ -if (reg_in_fmtr[j] && (fmtr != 0)) { /* nx formatter */ - tucs2 = tucs2 | CS2_NEF; /* set error flag */ - update_tucs (CS1_SC, drv); /* request intr */ - *data = 0; - return SCPE_OK; } - -update_tucs (0, drv); /* update status */ -switch (j) { /* decode PA<4:1> */ -case 000: /* MTCS1 */ - if (fmtr != 0) *data = tucs1 & ~CS1_DRV; - else *data = tucs1; - break; -case 001: /* MTWC */ - *data = tuwc; - break; -case 002: /* MTBA */ - *data = tuba = tuba & ~BA_MBZ; - break; -case 003: /* MTFC */ - *data = tufc; - break; -case 004: /* MTCS2 */ - *data = tucs2 = (tucs2 & ~CS2_MBZ) | CS2_IR | CS2_OR; - break; -case 005: /* MTFS */ - *data = tufs & 0177777; /* mask off rewind */ - break; -case 006: /* MTER */ - *data = tuer; - break; -case 007: /* MTAS */ - *data = (tufs & FS_ATA)? AS_U0: 0; - break; -case 010: /* MTCC */ - *data = tucc = tucc & ~CC_MBZ; - break; -case 011: /* MTDB */ - *data = tudb; - break; -case 012: /* MTMR */ - *data = tumr; - break; -case 013: /* MTDT */ - *data = DT_TAPE | DT_TM03 | ((tu_unit[drv].flags & UNIT_DIS)? - DT_OFF: (DT_PRES | DT_TU45)); - break; -case 014: /* MTSN */ - *data = (tu_unit[drv].flags & UNIT_DIS)? 0: 040 | (drv + 1); - break; -case 015: /* MTTC */ - *data = tutc = tutc & ~TC_MBZ; - break; -default: /* all others */ - tuer = tuer | ER_ILR; - update_tucs (0, drv); - break; } -return SCPE_OK; -} - -t_stat tu_wr (int32 data, int32 PA, int32 access) -{ -int32 cs1f, fmtr, drv, j; - -cs1f = 0; /* no int on cs1 upd */ -fmtr = GET_FMTR (tucs2); /* get formatter */ -drv = GET_DRV (tutc); /* get current unit */ -j = (PA >> 1) & 017; /* get reg offset */ -if (reg_in_fmtr[j] && (fmtr != 0)) { /* nx formatter */ - tucs2 = tucs2 | CS2_NEF; /* set error flag */ - update_tucs (CS1_SC, drv); /* request intr */ - return SCPE_OK; } -if (reg_in_fmtr1[j] && ((tucs1 & CS1_DONE) == 0)) { /* formatter busy? */ - tuer = tuer | ER_RMR; /* won't write */ - update_tucs (0, drv); - return SCPE_OK; } - -switch (j) { /* decode PA<4:1> */ -case 000: /* MTCS1 */ - if ((access == WRITEB) && (PA & 1)) data = data << 8; - if (data & CS1_TRE) { /* error clear? */ - tucs1 = tucs1 & ~CS1_TRE; /* clr CS1 */ - tucs2 = tucs2 & ~CS2_ERR; } /* clr CS2<15:8> */ - if ((access == WRITE) || (PA & 1)) { /* hi byte write? */ - if (tucs1 & CS1_DONE) /* done set? */ - tucs1 = (tucs1 & ~CS1_UAE) | (data & CS1_UAE); } - if ((access == WRITE) || !(PA & 1)) { /* lo byte write? */ - if ((data & CS1_DONE) && (data & CS1_IE)) /* to DONE+IE? */ - tuiff = 1; /* set CSTB INTR */ - tucs1 = (tucs1 & ~CS1_IE) | (data & CS1_IE); - if (fmtr != 0) { /* nx formatter? */ - tucs2 = tucs2 | CS2_NEF; /* set error flag */ - cs1f = CS1_SC; } /* req interrupt */ - else if (tucs1 & CS1_GO) { /* busy? */ - if (tucs1 & CS1_DONE) tuer = tuer | ER_RMR; - else tucs2 = tucs2 | CS2_PGE; } - else { - tucs1 = (tucs1 & ~CS1_DRV) | (data & CS1_DRV); - if (tucs1 & CS1_GO) tu_go (drv); } } - break; -case 001: /* MTWC */ - if (access == WRITEB) data = (PA & 1)? - (tuwc & 0377) | (data << 8): (tuwc & ~0377) | data; - tuwc = data; - break; -case 002: /* MTBA */ - if (access == WRITEB) data = (PA & 1)? - (tuba & 0377) | (data << 8): (tuba & ~0377) | data; - tuba = data & ~BA_MBZ; - break; -case 003: /* MTFC */ - if (access == WRITEB) data = (PA & 1)? - (tufc & 0377) | (data << 8): (tufc & ~0377) | data; - tufc = data; - tutc = tutc | TC_FCS; /* set fc flag */ - break; -case 004: /* MTCS2 */ - if ((access == WRITEB) && (PA & 1)) data = data << 8; - if (data & CS2_CLR) tu_reset (&tu_dev); /* init? */ - else { - if ((data & ~tucs2) & (CS2_PE | CS2_MXF)) - cs1f = CS1_SC; /* diagn intr */ - if (access == WRITEB) data = (tucs2 & /* merge data */ - ((PA & 1)? 0377: 0177400)) | data; - tucs2 = (tucs2 & ~CS2_RW) | (data & CS2_RW) | CS2_IR | CS2_OR; } - break; -case 007: /* MTAS */ - if ((access == WRITEB) && (PA & 1)) break; - if (data & AS_U0) tufs = tufs & ~FS_ATA; - break; -case 011: /* MTDB */ - if (access == WRITEB) data = (PA & 1)? - (tudb & 0377) | (data << 8): (tudb & ~0377) | data; - tudb = data; - break; -case 012: /* MTMR */ - if (access == WRITEB) data = (PA & 1)? - (tumr & 0377) | (data << 8): (tumr & ~0377) | data; - tumr = (tumr & ~MR_RW) | (data & MR_RW); - break; -case 015: /* MTTC */ - if (access == WRITEB) data = (PA & 1)? - (tutc & 0377) | (data << 8): (tutc & ~0377) | data; - tutc = (tutc & ~TC_RW) | (data & TC_RW) | TC_SAC; - drv = GET_DRV (tutc); - break; -case 005: /* MTFS */ -case 006: /* MTER */ -case 010: /* MTCC */ -case 013: /* MTDT */ -case 014: /* MTSN */ - break; /* read only */ -default: /* all others */ - tuer = tuer | ER_ILR; - break; } /* end switch */ -update_tucs (cs1f, drv); /* update status */ -return SCPE_OK; -} - -/* New magtape command */ - -void tu_go (int32 drv) -{ -int32 fnc, den, space_test = FS_BOT; -UNIT *uptr; - -fnc = GET_FNC (tucs1); /* get function */ -den = GET_DEN (tutc); /* get density */ -uptr = tu_dev.units + drv; /* get unit */ -if ((fnc != FNC_FCLR) && /* not clear & err */ - ((tufs & FS_ERR) || sim_is_active (uptr))) { /* or in motion? */ - tuer = tuer | ER_ILF; /* set error flag */ - tufs = tufs | FS_ATA; /* exception */ - tucs1 = tucs1 & ~CS1_GO; /* clear go */ - update_tucs (CS1_SC, drv); /* request intr */ - return; } -tufs = tufs & ~FS_ATA; /* clear attention */ -tutc = tutc & ~TC_SAC; /* clear addr change */ - -switch (fnc) { /* case on function */ -case FNC_FCLR: /* drive clear */ - tuer = 0; /* clear errors */ - tutc = tutc & ~TC_FCS; /* clear fc status */ - tufs = tufs & ~(FS_SAT | FS_SSC | FS_ID | FS_TMK | FS_ERR); - sim_cancel (uptr); /* reset drive */ - uptr->USTAT = 0; -case FNC_NOP: - tucs1 = tucs1 & ~CS1_GO; /* no operation */ - return; -case FNC_RIP: /* read-in preset */ - tutc = TC_800; /* density = 800 */ - sim_tape_rewind (&tu_unit[0]); /* rewind unit 0 */ - tu_unit[0].USTAT = 0; - tucs1 = tucs1 & ~CS1_GO; - return; - -case FNC_UNLOAD: /* unload */ - if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - tuer = tuer | ER_UNS; - break; } - detach_unit (uptr); - uptr->USTAT = FS_REW; - sim_activate (uptr, tu_time); - tucs1 = tucs1 & ~CS1_GO; - return; -case FNC_REWIND: - if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - tuer = tuer | ER_UNS; - break; } - uptr->USTAT = FS_PIP | FS_REW; - sim_activate (uptr, tu_time); - tucs1 = tucs1 & ~CS1_GO; - return; - -case FNC_SPACEF: - space_test = FS_EOT; -case FNC_SPACER: - if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - tuer = tuer | ER_UNS; - break; } - if ((tufs & space_test) || ((tutc & TC_FCS) == 0)) { - tuer = tuer | ER_NXF; - break; } - uptr->USTAT = FS_PIP; - goto GO_XFER; - -case FNC_WCHKR: /* wchk = read */ -case FNC_READR: /* read rev */ - if (tufs & FS_BOT) { /* beginning of tape? */ - tuer = tuer | ER_NXF; - break; } - goto DATA_XFER; - -case FNC_WRITE: /* write */ - if (((tutc & TC_FCS) == 0) || /* frame cnt = 0? */ - ((den == TC_800) && (tufc > 0777765))) { /* NRZI, fc < 13? */ - tuer = tuer | ER_NXF; - break; } -case FNC_WREOF: /* write tape mark */ -case FNC_ERASE: /* erase */ - if (sim_tape_wrp (uptr)) { /* write locked? */ - tuer = tuer | ER_NXF; - break; } -case FNC_WCHKF: /* wchk = read */ -case FNC_READF: /* read */ -DATA_XFER: - if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - tuer = tuer | ER_UNS; - break; } - if (fmt_test[GET_FMT (tutc)] == 0) { /* invalid format? */ - tuer = tuer | ER_FER; - break; } - if (den_test[den] == 0) { /* invalid density? */ - tuer = tuer | ER_NXF; - break; } - if (uptr->UDENS == UD_UNK) uptr->UDENS = den; /* set dens */ -/* else if (uptr->UDENS != den) { /* density mismatch? */ -/* tuer = tuer | ER_NXF; -/* break; } */ - uptr->USTAT = 0; - tucs1 = tucs1 & ~CS1_DONE; /* clear done */ -GO_XFER: - tucs2 = tucs2 & ~CS2_ERR; /* clear errors */ - tucs1 = tucs1 & ~(CS1_TRE | CS1_MCPE); - tufs = tufs & ~(FS_TMK | FS_ID); /* clear eof, id */ - sim_activate (uptr, tu_time); - return; - -default: /* all others */ - tuer = tuer | ER_ILF; /* not supported */ - break; } /* end case function */ -tucs1 = tucs1 & ~CS1_GO; /* clear go */ -tufs = tufs | FS_ATA; /* set attn */ -update_tucs (CS1_SC, drv); /* set intr */ -return; -} - -/* Unit service - - Complete movement or data transfer command - Unit must exist - can't remove an active unit - Unit must be attached - detach cancels in progress operations -*/ - -t_stat tu_svc (UNIT *uptr) -{ -int32 f, fmt, i, j, k, wc10, ba10; -int32 ba, fc, wc, drv, mpa10, vpn; -d10 val, v[4]; -t_mtrlnt tbc; -t_stat st, r = SCPE_OK; - -drv = uptr - tu_dev.units; /* get drive # */ -if (uptr->USTAT & FS_REW) { /* rewind or unload? */ - sim_tape_rewind (uptr); /* rewind tape */ - uptr->USTAT = 0; /* clear status */ - tufs = tufs | FS_ATA | FS_SSC; - update_tucs (CS1_SC, drv); /* update status */ - return SCPE_OK; } - -f = GET_FNC (tucs1); /* get command */ -fmt = GET_FMT (tutc); /* get format */ -ba = GET_UAE (tucs1) | tuba; /* get bus address */ -wc = 0200000 - tuwc; /* get word count */ -fc = 0200000 - tufc; /* get frame count */ -wc10 = wc >> 1; /* 10 word count */ -ba10 = ba >> 2; /* 10 word addr */ -uptr->USTAT = 0; /* clear status */ - -switch (f) { /* case on function */ - -/* Unit service - non-data transfer commands - set ATA when done */ - -case FNC_SPACEF: /* space forward */ - do { - tufc = (tufc + 1) & 0177777; /* incr fc */ - if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */ - r = tu_map_err (uptr, st); /* map error */ - break; } - } - while (tufc != 0); - if (tufc) tuer = tuer | ER_FCE; - else tutc = tutc & ~TC_FCS; - tufs = tufs | FS_ATA; - break; - -case FNC_SPACER: /* space reverse */ - do { - tufc = (tufc + 1) & 0177777; /* incr wc */ - if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */ - r = tu_map_err (uptr, st); /* map error */ - break; } - } - while (tufc != 0); - if (tufc) tuer = tuer | ER_FCE; - else tutc = tutc & ~TC_FCS; - tufs = tufs | FS_ATA; - break; - -case FNC_WREOF: /* write end of file */ - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = tu_map_err (uptr, st); /* map error */ - tufs = tufs | FS_ATA; - break; - -case FNC_ERASE: - if (sim_tape_wrp (uptr)) /* write protected? */ - r = tu_map_err (uptr, MTSE_WRP); /* map error */ - tufs = tufs | FS_ATA; - break; - -/* Unit service - data transfer commands - - These commands must take into account the action of the "bit fiddler", which - converts between PDP-10 format and tape format. Only two tape formats are - supported: - - PDP-10 core dump: write 36b as byte 0/byte 1/byte 2/byte 3/0000'last nibble - industry mode: write hi 32b as byte 0/byte 1/byte 2/byte 3 - - These commands must also take into account the action of the Unibus adapter, - which munges PDP-10 addresses through the Unibus map. -*/ - -case FNC_READF: /* read */ -case FNC_WCHKF: /* wcheck = read */ - tufc = 0; /* clear frame count */ - if ((uptr->UDENS == TC_1600) && sim_tape_bot (uptr)) - tufs = tufs | FS_ID; /* PE BOT? ID burst */ - TXFR (ba, wc, 0); /* validate transfer */ - if (st = sim_tape_rdrecf (uptr, xbuf, &tbc, MT_MAXFR)) { /* read fwd */ - r = tu_map_err (uptr, st); /* map error */ - break; } /* done */ - for (i = j = 0; (i < wc10) && (j < ((int32) tbc)); i++) { - if ((i == 0) || NEWPAGE (ba10 + i, 0)) { /* map new page */ - MAPM (ba10 + i, mpa10, 0); } - for (k = 0; k < 4; k++) v[k] = xbuf[j++]; - val = (v[0] << 28) | (v[1] << 20) | (v[2] << 12) | (v[3] << 4); - if (fmt == TC_10C) val = val | ((d10) xbuf[j++] & 017); - if (f == FNC_READF) M[mpa10] = val; - mpa10 = mpa10 + 1; } /* end for */ - tufc = tbc & 0177777; - tuwc = (tuwc + (i << 1)) & 0177777; - ba = ba + (i << 2); - break; - -case FNC_WRITE: /* write */ - TXFR (ba, wc, 0); /* validate transfer */ - for (i = j = 0; (i < wc10) && (j < fc); i++) { - if ((i == 0) || NEWPAGE (ba10 + i, 0)) { /* map new page */ - MAPM (ba10 + i, mpa10, 0); } - val = M[mpa10]; - xbuf[j++] = (uint8) ((val >> 28) & 0377); - xbuf[j++] = (uint8) ((val >> 20) & 0377); - xbuf[j++] = (uint8) ((val >> 12) & 0377); - xbuf[j++] = (uint8) ((val >> 4) & 0377); - if (fmt == TC_10C) xbuf[j++] = (uint8) (val & 017); - mpa10 = mpa10 + 1; } /* end for */ - if (j < fc) fc = j; /* short record? */ - if (st = sim_tape_wrrecf (uptr, xbuf, fc)) /* write rec, err? */ - r = tu_map_err (uptr, st); /* map error */ - else { - tufc = (tufc + fc) & 0177777; - if (tufc == 0) tutc = tutc & ~TC_FCS; - tuwc = (tuwc + (i << 1)) & 0177777; - ba = ba + (i << 2); } - break; - -case FNC_READR: /* read reverse */ -case FNC_WCHKR: /* wcheck = read */ - tufc = 0; /* clear frame count */ - TXFR (ba, wc, 1); /* validate xfer rev */ - if (st = sim_tape_rdrecr (uptr, xbuf + 4, &tbc, MT_MAXFR)) { /* read rev */ - r = tu_map_err (uptr, st); /* map error */ - break; } /* done */ - for (i = 0; i < 4; i++) xbuf[i] = 0; - for (i = 0, j = tbc + 4; (i < wc10) && (j >= 4); i++) { - if ((i == 0) || NEWPAGE (ba10 - i, PAG_M_OFF)) { /* map page */ - MAPM (ba10 - i, mpa10, UMAP_RRV); } - val = ((fmt == TC_10C)? (((d10) xbuf [--j]) & 017): 0); - for (k = 0; k < 4; i++) v[k] = xbuf[--j]; - val = val | (v[0] << 4) | (v[1] << 12) | (v[2] << 20) | (v[3] << 28); - if (f == FNC_READR) M[mpa10] = val; - mpa10 = mpa10 - 1; } /* end for */ - tufc = tbc & 0177777; - tuwc = (tuwc + (i << 1)) & 0177777; - ba = ba - (i << 2); - break; } /* end case */ - -tucs1 = (tucs1 & ~CS1_UAE) | ((ba >> (16 - CS1_V_UAE)) & CS1_UAE); -tuba = ba & 0177777; /* update mem addr */ -tucs1 = tucs1 & ~CS1_GO; /* clear go */ -update_tucs (CS1_DONE, drv); -return SCPE_OK; -} - -/* Controller status update - - Check for done transition - Update drive status - Update MTCS1 - Update interrupt request -*/ - -void update_tucs (int32 flag, int32 drv) -{ -int32 act = sim_is_active (&tu_unit[drv]); - -if ((flag & ~tucs1) & CS1_DONE) /* DONE 0 to 1? */ - tuiff = (tucs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */ -if (GET_FMTR (tucs2) == 0) { /* formatter present? */ - tufs = (tufs & ~FS_DYN) | FS_FPR; - if (tu_unit[drv].flags & UNIT_ATT) { - tufs = tufs | FS_MOL | tu_unit[drv].USTAT; - if (tu_unit[drv].UDENS == TC_1600) tufs = tufs | FS_PE; - if (sim_tape_wrp (&tu_unit[drv])) tufs = tufs | FS_WRL; - if (sim_tape_bot (&tu_unit[drv]) && !act) tufs = tufs | FS_BOT; } - if (tuer) tufs = tufs | FS_ERR; } -else tufs = 0; -tucs1 = (tucs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ)) | CS1_DVA | flag; -if (tucs2 & CS2_ERR) tucs1 = tucs1 | CS1_TRE | CS1_SC; -else if (tucs1 & CS1_TRE) tucs1 = tucs1 | CS1_SC; -if (tufs & FS_ATA) tucs1 = tucs1 | CS1_SC; -if (tuiff || ((tucs1 & CS1_SC) && (tucs1 & CS1_DONE) && (tucs1 & CS1_IE))) - int_req = int_req | INT_TU; -else int_req = int_req & ~INT_TU; -if ((tucs1 & CS1_DONE) && tufs && !act) tufs = tufs | FS_RDY; -return; -} - -/* Interrupt acknowledge */ - -int32 tu_inta (void) -{ -tucs1 = tucs1 & ~CS1_IE; /* clear int enable */ -tuiff = 0; /* clear CSTB INTR */ -return VEC_TU; /* acknowledge */ -} - -/* Map tape error status */ - -t_stat tu_map_err (UNIT *uptr, t_stat st) -{ -switch (st) { -case MTSE_FMT: /* illegal fmt */ -case MTSE_UNATT: /* not attached */ - tuer = tuer | ER_NXF; /* can't execute */ -case MTSE_OK: /* no error */ - return SCPE_IERR; -case MTSE_TMK: /* end of file */ - tufs = tufs | FS_TMK; - break; -case MTSE_IOERR: /* IO error */ - tuer = tuer | ER_VPE; /* flag error */ - if (tu_stopioe) return SCPE_IOERR; - break; -case MTSE_INVRL: /* invalid rec lnt */ - tuer = tuer | ER_VPE; /* flag error */ - return SCPE_MTRLNT; -case MTSE_RECE: /* record in error */ - tuer = tuer | ER_CRC; /* set crc err */ - break; -case MTSE_EOM: /* end of medium */ - tuer = tuer | ER_OPI; /* incomplete */ - break; -case MTSE_BOT: /* reverse into BOT */ - break; -case MTSE_WRP: /* write protect */ - tuer = tuer | ER_NXF; /* can't execute */ - break; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tu_reset (DEVICE *dptr) -{ -int32 u; -UNIT *uptr; - -tucs1 = CS1_DVA | CS1_DONE; -tucs2 = CS2_IR | CS2_OR; -tuba = tufc = 0; -tutc = tuer = 0; -tufs = FS_FPR | FS_RDY; -tuiff = 0; /* clear CSTB INTR */ -int_req = int_req & ~INT_TU; /* clear interrupt */ -for (u = 0; u < TU_NUMDR; u++) { /* loop thru units */ - uptr = tu_dev.units + u; - sim_tape_reset (uptr); /* clear pos flag */ - sim_cancel (uptr); /* cancel activity */ - uptr->USTAT = 0; } -if (xbuf == NULL) xbuf = calloc (MT_MAXFR + 4, sizeof (uint8)); -if (xbuf == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat tu_attach (UNIT *uptr, char *cptr) -{ -int32 drv = uptr - tu_dev.units; -t_stat r; - -r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; -uptr->USTAT = 0; /* clear unit status */ -uptr->UDENS = UD_UNK; /* unknown density */ -tufs = tufs | FS_ATA | FS_SSC; /* set attention */ -if ((GET_FMTR (tucs2) == 0) && (GET_DRV (tutc) == drv)) /* selected drive? */ - tufs = tufs | FS_SAT; /* set slave attn */ -update_tucs (CS1_SC, drv); /* update status */ -return r; -} - -/* Detach routine */ - -t_stat tu_detach (UNIT* uptr) -{ -int32 drv = uptr - tu_dev.units; - -if (sim_is_active (uptr)) { /* unit active? */ - sim_cancel (uptr); /* cancel operation */ - tuer = tuer | ER_UNS; /* set formatter error */ - if ((uptr->USTAT & FS_REW) == 0) /* data transfer? */ - tucs1 = tucs1 | CS1_DONE | CS1_TRE; } /* set done, err */ -uptr->USTAT = 0; /* clear status flags */ -tufs = tufs | FS_ATA | FS_SSC; /* set attention */ -update_tucs (CS1_SC, drv); /* update status */ -return sim_tape_detach (uptr); -} - -/* Device bootstrap */ - -#define BOOT_START 0377000 /* start */ -#define BOOT_LEN (sizeof (boot_rom_dec) / sizeof (d10)) - -static const d10 boot_rom_dec[] = { - 0515040000003, /* boot:hrlzi 1,3 ; uba # */ - 0201000040001, /* movei 0,40001 ; vld,pg 1 */ - 0713001000000+(IOBA_UBMAP+1 & RMASK), /* wrio 0,763001(1); set ubmap */ - 0435040000000+(IOBA_TU & RMASK), /* iori 1,772440 ; rh addr */ - 0202040000000+FE_RHBASE, /* movem 1,FE_RHBASE */ - 0201000000040, /* movei 0,40 ; ctrl reset */ - 0713001000010, /* wrio 0,10(1) ; ->MTFS */ - 0201100000031, /* movei 2,31 ; space f */ - 0265740377014, /* jsp 17,tpop ; skip ucode */ - 0201100000071, /* movei 2,71 ; read f */ - 0265740377014, /* jsp 17,tpop ; read boot */ - 0254000001000, /* jrst 1000 ; start */ - 0200000000000+FE_MTFMT, /* tpop:move 0,FE_MTFMT ; den,fmt,slv */ - 0713001000032, /* wrio 0,32(1) ; ->MTTC */ - 0201000000011, /* movei 0,11 ; clr+go */ - 0713001000000, /* wrio 0,0(1) ; ->MTCS1 */ - 0201140176000, /* movei 3,176000 ; wd cnt */ - 0201200004000, /* movei 4,4000 ; addr */ - 0200240000000+FE_MTFMT, /* move 5,FE_MTFMT ; unit */ - 0201300000000, /* movei 6,0 ; fmtr */ - 0713141000002, /* wrio 3,2(1) ; ->MTWC */ - 0713201000004, /* wrio 4,4(1) ; ->MTBA */ - 0713301000006, /* wrio 6,6(1) ; ->MTFC */ - 0713301000010, /* wrio 6,10(1) ; ->MTFS */ - 0713241000032, /* wrio 5,32(1) ; ->MTTC */ - 0713101000000, /* wrio 2,0(1) ; ->MTCS1 */ - 0712341000012, /* rdio 7,12(1) ; read FS */ - 0606340000200, /* trnn 7,200 ; test rdy */ - 0254000377032, /* jrst .-2 ; loop */ - 0606340040000, /* trnn 7,40000 ; test err */ - 0254017000000, /* jrst 0(17) ; return */ - 0712341000014, /* rdio 7,14(1) ; read err */ - 0302340001000, /* caie 7,1000 ; fce? */ - 0254200377052, /* halt */ - 0254017000000, /* jrst 0(17) ; return */ -}; - -static const d10 boot_rom_its[] = { - 0515040000003, /* boot:hrlzi 1,3 ; uba # - not used */ - 0201000040001, /* movei 0,40001 ; vld,pg 1 */ - 0714000000000+(IOBA_UBMAP+1 & RMASK), /* iowri 0,763001 ; set ubmap */ - 0435040000000+(IOBA_TU & RMASK), /* iori 1,772440 ; rh addr */ - 0202040000000+FE_RHBASE, /* movem 1,FE_RHBASE */ - 0201000000040, /* movei 0,40 ; ctrl reset */ - 0714001000010, /* iowri 0,10(1) ; ->MTFS */ - 0201100000031, /* movei 2,31 ; space f */ - 0265740377014, /* jsp 17,tpop ; skip ucode */ - 0201100000071, /* movei 2,71 ; read f */ - 0265740377014, /* jsp 17,tpop ; read boot */ - 0254000001000, /* jrst 1000 ; start */ - 0200000000000+FE_MTFMT, /* tpop:move 0,FE_MTFMT ; den,fmt,slv */ - 0714001000032, /* iowri 0,32(1) ; ->MTTC */ - 0201000000011, /* movei 0,11 ; clr+go */ - 0714001000000, /* iowri 0,0(1) ; ->MTCS1 */ - 0201140176000, /* movei 3,176000 ; wd cnt */ - 0201200004000, /* movei 4,4000 ; addr */ - 0200240000000+FE_MTFMT, /* move 5,FE_MTFMT ; unit */ - 0201300000000, /* movei 6,0 ; fmtr */ - 0714141000002, /* iowri 3,2(1) ; ->MTWC */ - 0714201000004, /* iowri 4,4(1) ; ->MTBA */ - 0714301000006, /* iowri 6,6(1) ; ->MTFC */ - 0714301000010, /* iowri 6,10(1) ; ->MTFS */ - 0714241000032, /* iowri 5,32(1) ; ->MTTC */ - 0714101000000, /* iowri 2,0(1) ; ->MTCS1 */ - 0710341000012, /* iordi 7,12(1) ; read FS */ - 0606340000200, /* trnn 7,200 ; test rdy */ - 0254000377032, /* jrst .-2 ; loop */ - 0606340040000, /* trnn 7,40000 ; test err */ - 0254017000000, /* jrst 0(17) ; return */ - 0710341000014, /* iordi 7,14(1) ; read err */ - 0302340001000, /* caie 7,1000 ; fce? */ - 0254200377052, /* halt */ - 0254017000000, /* jrst 0(17) ; return */ -}; -t_stat tu_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern a10 saved_PC; - -M[FE_UNIT] = 0; -M[FE_MTFMT] = (unitno & TC_M_UNIT) | (TC_1600 << TC_V_DEN) | (TC_10C << TC_V_FMT); -tu_unit[unitno].pos = 0; -for (i = 0; i < BOOT_LEN; i++) - M[BOOT_START + i] = ITS? boot_rom_its[i]: boot_rom_dec[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} diff --git a/PDP10/pdp10_xtnd.c b/PDP10/pdp10_xtnd.c deleted file mode 100644 index 3c17e676..00000000 --- a/PDP10/pdp10_xtnd.c +++ /dev/null @@ -1,642 +0,0 @@ -/* pdp10_xtnd.c: PDP-10 extended instruction simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 12-May-01 RMS Fixed compiler warning in xlate - - Instructions handled in this module: - MOVSLJ move string left justified - MOVSO move string offset - MOVST move string translated - MOVSRJ move string right justified - CMPSL compare string, skip on less - CMPSE compare string, skip on equal - CMPSLE compare string, skip on less or equal - CMPSGE compare string, skip on greater or equal - CMPSN compare string, skip on unequal - CMPSG compare string, skip on greater - CVTDBO convert decimal to binary offset - CVTDBT convert decimal to binary translated - CVTBDO convert binary to decimal offset - CVTBDT convert binary to decimal translated - EDIT edit - - The PDP-10 extended instructions deal with non-binary data types, - particularly byte strings and decimal strings. (In the KL10, the - extended instructions include G floating support as well.) They - are very complicated microcoded subroutines that can potentially - run for a very long time. Accordingly, the instructions must test - for interrupts as well as page faults, and be prepared to restart - from either. - - In general, the simulator attempts to keep the AC block up to date, - so that page fails and interrupts can be taken directly at any point. - If the AC block is not up to date, memory accessibility must be tested - before the actual read or write is done. - - The extended instruction routine returns a status code as follows: - XT_NOSK no skip completion - XT_SKIP skip completion - XT_MUUO invalid extended instruction -*/ - -#include "pdp10_defs.h" -#include - -#define MM_XSRC (pflgs & XSRC_PXCT) -#define MM_XDST (pflgs & XDST_PXCT) -#define MM_EA_XSRC ((pflgs & EA_PXCT) && MM_XSRC) -#define MM_EA_XDST ((pflgs & EA_PXCT) && MM_XDST) - -#define XT_CMPSL 001 /* opcodes */ -#define XT_CMPSE 002 -#define XT_CMPSLE 003 -#define XT_EDIT 004 -#define XT_CMPSGE 005 -#define XT_CMPSN 006 -#define XT_CMPSG 007 -#define XT_CVTDBO 010 -#define XT_CVTDBT 011 -#define XT_CVTBDO 012 -#define XT_CVTBDT 013 -#define XT_MOVSO 014 -#define XT_MOVST 015 -#define XT_MOVSLJ 016 -#define XT_MOVSRJ 017 - -/* Translation control */ - -#define XT_LFLG 0400000000000 /* L flag */ -#define XT_SFLG 0400000000000 /* S flag */ -#define XT_NFLG 0200000000000 /* N flag */ -#define XT_MFLG 0100000000000 /* M flag */ - -/* Translation table */ - -#define XT_V_CODE 15 /* translation op */ -#define XT_M_CODE 07 -#define XT_BYMASK 07777 /* byte mask */ -#define XT_DGMASK 017 /* digit mask */ -#define XT_GETCODE(x) ((int32) (((x) >> XT_V_CODE) & XT_M_CODE)) - -/* AC masks */ - -#define XLNTMASK 0000777777777 /* length */ -#define XFLGMASK 0700000000000 /* flags */ -#define XT_MBZ 0777000000000 /* must be zero */ -#define XT_MBZE 0047777000000 /* must be zero, edit */ - -/* Register change log */ - -#define XT_N_RLOG 5 /* entry width */ -#define XT_M_RLOG ((1 << XT_N_RLOG) - 1) /* entry mask */ -#define XT_O_RLOG 1 /* entry offset */ -#define XT_INSRLOG(x,v) v = ((v << XT_N_RLOG) | (((x) + XT_O_RLOG) & XT_M_RLOG)) -#define XT_REMRLOG(x,v) x = (v & XT_M_RLOG) - XT_O_RLOG; \ - v = v >> XT_N_RLOG - -/* Edit */ - -#define ED_V_PBYN 30 /* pattern byte # */ -#define ED_M_PBYN 03 -#define ED_PBYNO 0040000000000 /* overflow bit */ -#define ED_GETPBYN(x) ((int32) (((x) >> ED_V_PBYN) & ED_M_PBYN)) -#define ED_V_POPC 6 /* pattern byte opcode */ -#define ED_M_PAT 0777 /* pattern byte mask */ -#define ED_M_NUM 0077 /* number for msg, etc */ -#define ED_PBYTE(x,y) ((int32) (((x) >> (27 - (ED_GETPBYN (y) * 9))) & ED_M_PAT)) -#define ED_STOP 0000 /* stop */ -#define ED_SELECT 0001 /* select source */ -#define ED_SIGST 0002 /* start significance */ -#define ED_FLDSEP 0003 /* field separator */ -#define ED_EXCHMD 0004 /* exchange mark, dst */ -#define ED_MESSAG 0100 /* message */ -#define ED_SKPM 0500 /* skip if M */ -#define ED_SKPN 0600 /* skip if N */ -#define ED_SKPA 0700 /* skip always */ - -extern d10 *ac_cur; /* current AC block */ -extern d10 bytemask[64]; -extern int32 flags; -extern int32 rlog; -extern jmp_buf save_env; - -extern d10 Read (int32 ea, int32 prv); -extern void Write (int32 ea, d10 val, int32 prv); -extern a10 calc_ea (d10 inst, int32 prv); -extern int32 test_int (void); -d10 incbp (d10 bp); -d10 incloadbp (int32 ac, int32 pflgs); -void incstorebp (d10 val, int32 ac, int32 pflgs); -d10 xlate (d10 by, a10 tblad, d10 *xflgs, int32 pflgs); -void filldst (d10 fill, int32 ac, d10 cnt, int32 pflgs); - -static const d10 pwrs10[23][2] = { - 0, 0, - 0, 1, - 0, 10, - 0, 100, - 0, 1000, - 0, 10000, - 0, 100000, - 0, 1000000, - 0, 10000000, - 0, 100000000, - 0, 1000000000, - 0, 10000000000, - 2, 31280523264, - 29, 3567587328, - 291, 1316134912, - 2910, 13161349120, - 29103, 28534276096, - 291038, 10464854016, - 2910383, 1569325056, - 29103830, 15693250560, - 291038304, 19493552128, - 2910383045, 23136829440, - 29103830456, 25209864192 }; - -int xtend (int32 ac, int32 ea, int32 pflgs) -{ -d10 b1, b2, ppi; -d10 xinst, xoff, digit, f1, f2, rs[2]; -d10 xflgs = 0; -a10 e1, entad; -int32 p1 = ADDAC (ac, 1); -int32 p3 = ADDAC (ac, 3); -int32 p4 = ADDAC (ac, 4); -int32 flg, i, s2, t, pp, pat, xop, xac, ret; - -xinst = Read (ea, MM_OPND); /* get extended instr */ -xop = GET_OP (xinst); /* get opcode */ -xac = GET_AC (xinst); /* get AC */ -if (xac || (xop == 0) || (xop > XT_MOVSRJ)) return XT_MUUO; -rlog = 0; /* clear log */ -switch (xop) { /* case on opcode */ - -/* String compares - checked against KS10 ucode - If both strings are zero length, they are considered equal. - Both source and destination lengths are MBZ checked. - - AC = source1 length - AC + 1 = source1 byte pointer - AC + 3 = source2 length - AC + 4 = source2 byte pointer -*/ - -case XT_CMPSL: /* CMPSL */ -case XT_CMPSE: /* CMPSE */ -case XT_CMPSLE: /* CMPSLE */ -case XT_CMPSGE: /* CMPSGE */ -case XT_CMPSN: /* CMPSN */ -case XT_CMPSG: /* CMPSG */ - if ((AC(ac) | AC(p3)) & XT_MBZ) return XT_MUUO; /* check length MBZ */ - f1 = Read (ADDA (ea, 1), MM_OPND) & bytemask[GET_S (AC(p1))]; - f2 = Read (ADDA (ea, 2), MM_OPND) & bytemask[GET_S (AC(p4))]; - b1 = b2 = 0; - for (flg = 0; (AC(ac) | AC(p3)) && (b1 == b2); flg++) { - if (flg && (t = test_int ())) ABORT (t); - rlog = 0; /* clear log */ - if (AC(ac)) b1 = incloadbp (p1, pflgs); /* src1 */ - else b1 = f1; - if (AC(p3)) b2 = incloadbp (p4, pflgs); /* src2 */ - else b2 = f2; - if (AC(ac)) AC(ac) = (AC(ac) - 1) & XLNTMASK; - if (AC(p3)) AC(p3) = (AC(p3) - 1) & XLNTMASK; } - switch (xop) { - case XT_CMPSL: return (b1 < b2)? XT_SKIP: XT_NOSK; - case XT_CMPSE: return (b1 == b2)? XT_SKIP: XT_NOSK; - case XT_CMPSLE: return (b1 <= b2)? XT_SKIP: XT_NOSK; - case XT_CMPSGE: return (b1 >= b2)? XT_SKIP: XT_NOSK; - case XT_CMPSN: return (b1 != b2)? XT_SKIP: XT_NOSK; - case XT_CMPSG: return (b1 > b2)? XT_SKIP: XT_NOSK; } - return XT_MUUO; - -/* Convert binary to decimal instructions - checked against KS10 ucode - There are no MBZ tests. - - AC'AC + 1 = double precision integer source - AC + 3 = flags and destination length - AC + 4 = destination byte pointer -*/ - -case XT_CVTBDO: /* CVTBDO */ -case XT_CVTBDT: /* CVTBDT */ - e1 = calc_ea (xinst, MM_EA); /* get ext inst addr */ - if (xop == XT_CVTBDO) /* offset? */ - xoff = (e1 & RSIGN)? (e1 | LMASK): e1; /* get offset */ - rs[0] = AC(ac); /* get src opnd */ - rs[1] = CLRS (AC(p1)); - if (!TSTF (F_FPD)) { /* set up done yet? */ - if (TSTS (AC(ac))) { DMOVN (rs); } /* get abs value */ - for (i = 22; i > 1; i--) { /* find field width */ - if (DCMPGE (rs, pwrs10[i])) break; } - if (i > (AC(p3) & XLNTMASK)) return XT_NOSK; - if ((i < (AC(p3) & XLNTMASK)) && (AC(p3) & XT_LFLG)) { - f1 = Read (ADDA (ea, 1), MM_OPND); - filldst (f1, p3, (AC(p3) & XLNTMASK) - i, pflgs); } - else AC(p3) = (AC(p3) & XFLGMASK) | i; - if (TSTS (AC(ac))) AC(p3) = AC(p3) | XT_MFLG; - if (AC(ac) | AC(p1)) AC(p3) = AC(p3) | XT_NFLG; - AC(ac) = rs[0]; /* update state */ - AC(p1) = rs[1]; - SETF (F_FPD); } /* mark set up done */ - -/* Now do actual binary to decimal conversion */ - - for (flg = 0; AC(p3) & XLNTMASK; flg++) { - if (flg && (t = test_int ())) ABORT (t); - rlog = 0; /* clear log */ - i = (int32) AC(p3) & XLNTMASK; /* get length */ - if (i > 22) i = 22; /* put in range */ - for (digit = 0; (digit < 10) && DCMPGE (rs, pwrs10[i]); digit++) { - rs[0] = rs[0] - pwrs10[i][0] - (rs[1] < pwrs10[i][1]); - rs[1] = (rs[1] - pwrs10[i][1]) & MMASK; } - if (xop == XT_CVTBDO) digit = (digit + xoff) & DMASK; - else { - f1 = Read (e1 + (int32) digit, MM_OPND); - if ((i == 1) && (AC(p3) & XT_LFLG)) f1 = f1 >> 18; - digit = f1 & RMASK; } - incstorebp (digit, p4, pflgs); /* store digit */ - AC(ac) = rs[0]; /* mem access ok */ - AC(p1) = rs[1]; /* update state */ - AC(p3) = (AC(p3) & XFLGMASK) | ((AC(p3) - 1) & XLNTMASK); } - CLRF (F_FPD); /* clear FPD */ - return XT_SKIP; - -/* Convert decimal to binary instructions - checked against KS10 ucode - There are no MBZ tests. - - AC = flags and source length - AC + 1 = source byte pointer - AC + 3'AC + 4 = double precision integer result -*/ - -case XT_CVTDBT: /* CVTDBT */ -case XT_CVTDBO: /* CVTDBO */ - e1 = calc_ea (xinst, MM_EA); /* get ext inst addr */ - if ((AC(ac) & XT_SFLG) == 0) AC(p3) = AC(p4) = 0; /* !S? clr res */ - else AC(p4) = CLRS (AC(p4)); /* clear low sign */ - if (xop == XT_CVTDBO) { /* offset? */ - xoff = (e1 & RSIGN)? (e1 | LMASK): e1; /* get offset */ - AC(ac) = AC(ac) | XT_SFLG; } /* set S flag */ - xflgs = AC(ac) & XFLGMASK; /* get xlation flags */ - for (flg = 0; AC(ac) & XLNTMASK; flg++) { - if (flg && (t = test_int ())) ABORT (t); - rlog = 0; /* clear log */ - b1 = incloadbp (p1, pflgs); /* get byte */ - if (xop == XT_CVTDBO) b1 = (b1 + xoff) & DMASK; - else { - b1 = xlate (b1, e1, &xflgs, MM_OPND); - if (b1 < 0) { /* terminated? */ - AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); - if (TSTS (AC(p3))) AC(p4) = SETS (AC(p4)); - return XT_NOSK; } - if (xflgs & XT_SFLG) b1 = b1 & XT_DGMASK; - else b1 = 0; } - AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); - if ((b1 < 0) || (b1 > 9)) { /* bad digit? done */ - if (TSTS (AC(p3))) AC(p4) = SETS (AC(p4)); - return XT_NOSK; } - AC(p4) = (AC(p4) * 10) + b1; /* base * 10 + digit */ - AC(p3) = ((AC(p3) * 10) + (AC(p4) >> 35)) & DMASK; - AC(p4) = AC(p4) & MMASK; } - if (AC(ac) & XT_MFLG) { - AC(p4) = -AC(p4) & MMASK; - AC(p3) = (~AC(p3) + (AC(p4) == 0)) & DMASK; } - if (TSTS (AC(p3))) AC(p4) = SETS (AC(p4)); - return XT_SKIP; - -/* String move instructions - checked against KS10 ucode - Only the destination length is MBZ checked. - - AC = flags (MOVST only) and source length - AC + 1 = source byte pointer - AC + 3 = destination length - AC + 4 = destination byte pointer -*/ - -case XT_MOVSO: /* MOVSO */ -case XT_MOVST: /* MOVST */ -case XT_MOVSRJ: /* MOVSRJ */ -case XT_MOVSLJ: /* MOVSLJ */ - if (AC(p3) & XT_MBZ) return XT_MUUO; /* test dst lnt MBZ */ - f1 = Read (ADDA (ea, 1), MM_OPND); /* get fill */ - switch (xop) { /* case on instr */ - case XT_MOVSO: /* MOVSO */ - AC(ac) = AC(ac) & XLNTMASK; /* trim src length */ - xoff = calc_ea (xinst, MM_EA); /* get offset */ - if (xoff & RSIGN) xoff = xoff | LMASK; /* sign extend 18b */ - s2 = GET_S (AC(p4)); /* get dst byte size */ - break; - case XT_MOVST: /* MOVST */ - e1 = calc_ea (xinst, MM_EA); /* get xlate tbl addr */ - break; - case XT_MOVSRJ: /* MOVSRJ */ - AC(ac) = AC(ac) & XLNTMASK; /* trim src length */ - if (AC(p3) == 0) return (AC(ac)? XT_NOSK: XT_SKIP); - if (AC(ac) > AC(p3)) { /* adv src ptr */ - for (flg = 0; AC(ac) > AC(p3); flg++) { - if (flg && (t = test_int ())) ABORT (t); - AC(p1) = incbp (AC(p1)); - AC(ac) = (AC(ac) - 1) & XLNTMASK; } } - else if (AC(ac) < AC(p3)) - filldst (f1, p3, AC(p3) - AC(ac), pflgs); - break; - case XT_MOVSLJ: /* MOVSLJ */ - AC(ac) = AC(ac) & XLNTMASK; /* trim src length */ - break; } - - xflgs = AC(ac) & XFLGMASK; /* get xlation flags */ - if (AC(p3) == 0) return (AC(ac)? XT_NOSK: XT_SKIP); - for (flg = 0; AC(p3) & XLNTMASK; flg++) { - if (flg && (t = test_int ())) ABORT (t); - rlog = 0; /* clear log */ - if (AC(ac) & XLNTMASK) { /* any source? */ - b1 = incloadbp (p1, pflgs); /* src byte */ - if (xop == XT_MOVSO) { /* offset? */ - b1 = (b1 + xoff) & DMASK; /* test fit */ - if (b1 & ~bytemask[s2]) { - AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); - return XT_NOSK; } } - else if (xop == XT_MOVST) { /* translate? */ - b1 = xlate (b1, e1, &xflgs, MM_OPND); - if (b1 < 0) { /* upd flags in AC */ - AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); - return XT_NOSK; } - if (xflgs & XT_SFLG) b1 = b1 & XT_BYMASK; - else b1 = -1; } } - else b1 = f1; - if (b1 >= 0) { /* valid byte? */ - incstorebp (b1, p4, pflgs); /* store byte */ - AC(p3) = (AC(p3) - 1) & XLNTMASK; } /* update state */ - if (AC(ac) & XLNTMASK) AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); } - return (AC(ac) & XLNTMASK)? XT_NOSK: XT_SKIP; - -/* Edit - checked against KS10 ucode - Only the flags/pattern pointer word is MBZ checked. - - AC = flags, pattern pointer - AC + 1 = source byte pointer - AC + 3 = mark address - AC + 4 = destination byte pointer -*/ - -case XT_EDIT: /* EDIT */ - if (AC(ac) & XT_MBZE) return XT_MUUO; /* check pattern MBZ */ - xflgs = AC(ac) & XFLGMASK; /* get xlation flags */ - e1 = calc_ea (xinst, MM_EA); /* get xlate tbl addr */ - for (ppi = 1, ret = -1, flg = 0; ret < 0; flg++, ppi = 1) { - if (flg && (t = test_int ())) ABORT (t); - rlog = 0; /* clear log */ - pp = (int32) AC(ac) & AMASK; /* get pattern ptr */ - b1 = Read (pp, MM_OPND); /* get pattern word */ - pat = ED_PBYTE (b1, AC(ac)); /* get pattern byte */ - switch ((pat < 0100)? pat: ((pat >> ED_V_POPC) + 0100)) { - case ED_STOP: /* stop */ - ret = XT_SKIP; /* exit loop */ - break; - case ED_SELECT: /* select source */ - b1 = incloadbp (p1, pflgs); /* get src */ - entad = (e1 + ((int32) b1 >> 1)) & AMASK; - f1 = ((Read (entad, MM_OPND) >> ((b1 & 1)? 0: 18)) & RMASK); - i = XT_GETCODE (f1); - if (i & 2) xflgs = - (i & 1)? xflgs | XT_MFLG: xflgs & ~XT_MFLG; - switch (i) { - case 00: case 02: case 03: - if (xflgs & XT_SFLG) f1 = f1 & XT_BYMASK; - else { - f1 = Read (INCA (ea), MM_OPND); - if (f1 == 0) break; } - incstorebp (f1, p4, pflgs); - break; - case 01: - ret = XT_NOSK; /* exit loop */ - break; - case 04: case 06: case 07: - xflgs = xflgs | XT_NFLG; - f1 = f1 & XT_BYMASK; - if ((xflgs & XT_SFLG) == 0) { - f2 = Read (ADDA (ea, 2), MM_OPND); - Write ((a10) AC(p3), AC(p4), MM_OPND); - if (f2) incstorebp (f2, p4, pflgs); - xflgs = xflgs | XT_SFLG; } - incstorebp (f1, p4, pflgs); - break; - case 05: - xflgs = xflgs | XT_NFLG; - ret = XT_NOSK; /* exit loop */ - break; } /* end case xlate op */ - break; - case ED_SIGST: /* start significance */ - if ((xflgs & XT_SFLG) == 0) { - f2 = Read (ADDA (ea, 2), MM_OPND); - Write ((a10) AC(p3), AC(p4), MM_OPND); - if (f2) incstorebp (f2, p4, pflgs); - xflgs = xflgs | XT_SFLG; } - break; - case ED_FLDSEP: /* separate fields */ - xflgs = 0; - break; - case ED_EXCHMD: /* exchange */ - f2 = Read ((int32) (AC(p3) & AMASK), MM_OPND); - Write ((int32) (AC(p3) & AMASK), AC(p4), MM_OPND); - AC(p4) = f2; - break; - case (0100 + (ED_MESSAG >> ED_V_POPC)): /* message */ - if (xflgs & XT_SFLG) - f1 = Read (ea + (pat & ED_M_NUM) + 1, MM_OPND); - else { - f1 = Read (ea + 1, MM_OPND); - if (f1 == 0) break; } - incstorebp (f1, p4, pflgs); - break; - case (0100 + (ED_SKPM >> ED_V_POPC)): /* skip on M */ - if (xflgs & XT_MFLG) ppi = (pat & ED_M_NUM) + 2; - break; - case (0100 + (ED_SKPN >> ED_V_POPC)): /* skip on N */ - if (xflgs & XT_NFLG) ppi = (pat & ED_M_NUM) + 2; - break; - case (0100 + (ED_SKPA >> ED_V_POPC)): /* skip always */ - ppi = (pat & ED_M_NUM) + 2; - break; - default: /* NOP or undefined */ - break; } /* end case pttrn op */ - AC(ac) = AC(ac) + ((ppi & ED_M_PBYN) << ED_V_PBYN); - AC(ac) = AC(ac) + (ppi >> 2) + ((AC(ac) & ED_PBYNO)? 1: 0); - AC(ac) = xflgs | (AC(ac) & ~(XT_MBZE | XFLGMASK)); } - return ret; } /* end case xop */ -return XT_MUUO; -} - -/* Supporting subroutines */ - -/* Increment byte pointer, register version */ - -d10 incbp (d10 bp) -{ -int32 p, s; - -p = GET_P (bp); /* get P and S */ -s = GET_S (bp); -p = p - s; /* adv P */ -if (p < 0) { /* end of word? */ - bp = (bp & LMASK) | (INCR (bp)); /* increment addr */ - p = (36 - s) & 077; } /* reset P */ -bp = PUT_P (bp, p); /* store new P */ -return bp; -} - -/* Increment and load byte, extended version - uses register log */ - -d10 incloadbp (int32 ac, int32 pflgs) -{ -a10 ba; -d10 bp, wd; -int32 p, s; - -bp = AC(ac) = incbp (AC(ac)); /* increment bp */ -XT_INSRLOG (ac, rlog); /* log change */ -p = GET_P (bp); /* get P and S */ -s = GET_S (bp); -ba = calc_ea (bp, MM_EA_XSRC); /* calc bp eff addr */ -wd = Read (ba, MM_XSRC); /* read word */ -wd = (wd >> p) & bytemask[s]; /* get byte */ -return wd; -} - -/* Increment and deposit byte, extended version - uses register log */ - -void incstorebp (d10 val, int32 ac, int32 pflgs) -{ -a10 ba; -d10 bp, wd, mask; -int32 p, s; - -bp = AC(ac) = incbp (AC(ac)); /* increment bp */ -XT_INSRLOG (ac, rlog); /* log change */ -p = GET_P (bp); /* get P and S */ -s = GET_S (bp); -ba = calc_ea (bp, MM_EA_XDST); /* calc bp eff addr */ -wd = Read (ba, MM_XDST); /* read, write test */ -mask = bytemask[s] << p; /* shift mask, val */ -val = val << p; -wd = (wd & ~mask) | (val & mask); /* insert byte */ -Write (ba, wd & DMASK, MM_XDST); -return; -} - -/* Translate byte - - Arguments - by = byte to translate - tblad = virtual address of translation table - *xflgs = pointer to word containing translation flags - prv = previous mode flag for table lookup - Returns - xby = >= 0, translated byte - < 0, terminate translation -*/ - -d10 xlate (d10 by, a10 tblad, d10 *xflgs, int32 prv) -{ -a10 ea; -int32 tcode; -d10 tblent; - -ea = (tblad + ((int32) by >> 1)) & AMASK; -tblent = ((Read (ea, prv) >> ((by & 1)? 0: 18)) & RMASK); -tcode = XT_GETCODE (tblent); /* get xlate code */ -switch (tcode) { -case 00: - return (*xflgs & XT_SFLG)? tblent: by; -case 01: - break; -case 02: - *xflgs = *xflgs & ~XT_MFLG; - return (*xflgs & XT_SFLG)? tblent: by; -case 03: - *xflgs = *xflgs | XT_MFLG; - return (*xflgs & XT_SFLG)? tblent: by; -case 04: - *xflgs = *xflgs | XT_SFLG | XT_NFLG; - return tblent; -case 05: - *xflgs = *xflgs | XT_NFLG; - break; -case 06: - *xflgs = (*xflgs | XT_SFLG | XT_NFLG) & ~XT_MFLG; - return tblent; -case 07: - *xflgs = *xflgs | XT_SFLG | XT_NFLG | XT_MFLG; - return tblent; } /* end case xlate code */ -return -1; -} - -/* Fill out the destination string - - Arguments: - fill = fill - ac = 2 word AC block (length, byte pointer) - cnt = fill count - pflgs = PXCT flags -*/ - -void filldst (d10 fill, int32 ac, d10 cnt, int32 pflgs) -{ -int32 i, t; -int32 p1 = ADDA (ac, 1); - -for (i = 0; i < cnt; i++) { - if (i && (t = test_int ())) ABORT (t); - rlog = 0; /* clear log */ - incstorebp (fill, p1, pflgs); - AC(ac) = (AC(ac) & XFLGMASK) | ((AC(ac) - 1) & XLNTMASK); } - rlog = 0; -return; -} - -/* Clean up after page fault - - Arguments: - logv = register change log - - For each register in logv, decrement the register's contents as - though it were a byte pointer. Note that the KS10 does - do a full decrement calculation but merely adds S to P. -*/ - -void xtcln (int32 logv) -{ -int32 p, reg; - -while (logv) { - XT_REMRLOG (reg, logv); /* get next reg */ - if ((reg >= 0) && (reg < AC_NUM)) { - p = GET_P (AC(reg)) + GET_S (AC(reg)); /* get p + s */ - AC(reg) = PUT_P (AC(reg), p); } /* p <- p + s */ - } -return; -} diff --git a/PDP11/pdp11_cis.c b/PDP11/pdp11_cis.c deleted file mode 100644 index 4190b7be..00000000 --- a/PDP11/pdp11_cis.c +++ /dev/null @@ -1,1265 +0,0 @@ -/* pdp11_cis.c: PDP-11 CIS optional instruction set simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - This module simulates the PDP-11 commercial instruction set (CIS). - - 17-Oct-02 RMS Fixed compiler warning (found by Hans Pufal) - 08-Oct-02 RMS Fixed macro definitions - - The commercial instruction set consists of three instruction formats: - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ register operands - | 0 1 1 1 1 1| 0 0 0 0| opcode | 076030:076057 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 076070:076077 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ inline operands - | 0 1 1 1 1 1| 0 0 0 1| opcode | 076130:076157 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 076170:076177 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ load descriptors - | 0 1 1 1 1 1| 0 0 0 0|op| 1 0| reg | 076020:076027 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 076060:076067 - - The CIS instructions operate on character strings, packed (decimal) - strings, and numeric (decimal) strings. Strings are described by - a two word descriptor: - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | length in bytes | char string - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ descriptor - | starting byte address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | |str type| | length | decimal string - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ descriptor - | starting byte address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - Decimal string types are: - - <14:12> data type bytes occupied by n digits - 0 signed zoned n - 1 unsigned zone n - 2 trailing overpunch n - 3 leading overpunch n - 4 trailing separate n+1 - 5 leading separate n+1 - 6 signed packed n/2 +1 - 7 unsigned packed n/2 +1 - - Zero length character strings occupy no memory; zero length decimal strings - require either zero bytes (zoned, overpunch) or one byte (separate, packed). - - CIS instructions can run for a very long time, so they are interruptible - and restartable. In the simulator, all instructions run to completion. - The code is unoptimized. -*/ - -#include "pdp11_defs.h" - -/* Opcode bits */ - -#define INLINE 0100 /* inline */ -#define PACKED 0020 /* packed */ -#define NUMERIC 0000 /* numeric */ - -/* Operand type definitions */ - -#define R0_DESC 1 /* descr in R0:R1 */ -#define R2_DESC 2 /* descr in R2:R3 */ -#define R4_DESC 3 /* descr in R4:R5 */ -#define R4_ARG 4 /* argument in R4 */ -#define IN_DESC 5 /* inline descriptor */ -#define IN_ARG 6 /* inline argument */ -#define IN_DESC_R0 7 /* inline descr to R0:R1 */ -#define MAXOPN 4 /* max # operands */ - -/* Decimal data type definitions */ - -#define XZ 0 /* signed zoned */ -#define UZ 1 /* unsigned zoned */ -#define TO 2 /* trailing overpunch */ -#define LO 3 /* leading overpunch */ -#define TS 4 /* trailing separate */ -#define LS 5 /* leading separate */ -#define XP 6 /* signed packed */ -#define UP 7 /* unsigned packed */ - -/* Decimal descriptor definitions */ - -#define DTYP_M 07 /* type mask */ -#define DTYP_V 12 /* type position */ -#define DLNT_M 037 /* length mask */ -#define DLNT_V 0 /* length position */ -#define GET_DTYP(x) (((x) >> DTYP_V) & DTYP_M) -#define GET_DLNT(x) (((x) >> DLNT_V) & DLNT_M) - -/* Shift operand definitions */ - -#define ASHRND_M 017 /* round digit mask */ -#define ASHRND_V 8 /* round digit pos */ -#define ASHLNT_M 0377 /* shift count mask */ -#define ASHLNT_V 0 /* shift length pos */ -#define ASHSGN 0200 /* shift sign */ -#define GET_ASHRND(x) (((x) >> ASHRND_V) & ASHRND_M) -#define GET_ASHLNT(x) (((x) >> ASHLNT_V) & ASHLNT_M) - -/* Operand array aliases */ - -#define A1LNT arg[0] -#define A1ADR arg[1] -#define A2LNT arg[2] -#define A2ADR arg[3] -#define A3LNT arg[4] -#define A3ADR arg[5] -#define A1 &arg[0] -#define A2 &arg[2] -#define A3 &arg[4] - -/* Condition code macros */ - -#define GET_BIT(ir,n) (((ir) >> (n)) & 1) -#define GET_SIGN_L(ir) GET_BIT((ir), 31) -#define GET_SIGN_W(ir) GET_BIT((ir), 15) -#define GET_SIGN_B(ir) GET_BIT((ir), 7) -#define GET_Z(ir) ((ir) == 0) - -/* Decimal string structure */ - -#define DSTRLNT 4 -#define DSTRMAX (DSTRLNT - 1) -#define MAXDVAL 429496730 /* 2^32 / 10 */ - -struct dstr { - unsigned int32 sign; - unsigned int32 val[DSTRLNT]; }; - -typedef struct dstr DSTR; - -static DSTR Dstr0 = { 0, 0, 0, 0, 0 }; - -extern int32 isenable, dsenable; -extern int32 N, Z, V, C; -extern int32 R[8], trap_req; -extern int32 ReadW (int32 addr); -extern void WriteW (int32 data, int32 addr); -extern int32 ReadB (int32 addr); -extern void WriteB (int32 data, int32 addr); -int32 ReadDstr (int32 *dscr, DSTR *dec, int32 flag); -void WriteDstr (int32 *dscr, DSTR *dec, int32 flag); -int32 AddDstr (DSTR *src1, DSTR *src2, DSTR *dst, int32 cin); -void SubDstr (DSTR *src1, DSTR *src2, DSTR *dst); -int32 CmpDstr (DSTR *src1, DSTR *src2); -int32 TestDstr (DSTR *dsrc); -int32 LntDstr (DSTR *dsrc, int32 nz); -unsigned int32 NibbleLshift (DSTR *dsrc, int32 sc, unsigned int32 cin); -unsigned int32 NibbleRshift (DSTR *dsrc, int32 sc, unsigned int32 cin); -int32 WordLshift (DSTR *dsrc, int32 sc); -void WordRshift (DSTR *dsrc, int32 sc); -void CreateTable (DSTR *dsrc, DSTR mtable[10]); - -/* Table of instruction operands */ - -static int32 opntab[128][MAXOPN] = { - 0, 0, 0, 0, 0, 0, 0, 0, /* 000 - 007 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* 010 - 017 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* LD2R */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - R0_DESC, R2_DESC, R4_ARG, 0, /* MOVC */ - R0_DESC, R2_DESC, R4_ARG, 0, /* MOVRC */ - R0_DESC, R2_DESC, R4_DESC, 0, /* MOVTC */ - 0, 0, 0, 0, /* 033 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 034 - 037 */ - 0, 0, 0, 0, 0, 0, 0, 0, - R4_ARG, 0, 0, 0, /* LOCC */ - R4_ARG, 0, 0, 0, /* SKPC */ - R4_DESC, 0, 0, 0, /* SCANC */ - R4_DESC, 0, 0, 0, /* SPANC */ - R0_DESC, R2_DESC, R4_ARG, 0, /* CMPC */ - R2_DESC, 0, 0, 0, /* MATC */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 046 - 047 */ - R0_DESC, R2_DESC, R4_DESC, 0, /* ADDN */ - R0_DESC, R2_DESC, R4_DESC, 0, /* SUBN */ - R0_DESC, R2_DESC, 0, 0, /* CMPN */ - R0_DESC, 0, 0, 0, /* CVTNL */ - R0_DESC, R2_DESC, 0, 0, /* CVTPN */ - R0_DESC, R2_DESC, 0, 0, /* CVTNP */ - R0_DESC, R2_DESC, R4_ARG, 0, /* ASHN */ - R0_DESC, 0, 0, 0, /* CVTLN */ - 0, 0, 0, 0, 0, 0, 0, 0, /* LD3R */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - R0_DESC, R2_DESC, R4_DESC, 0, /* ADDP */ - R0_DESC, R2_DESC, R4_DESC, 0, /* SUBP */ - R0_DESC, R2_DESC, 0, 0, /* CMPP */ - R0_DESC, 0, 0, 0, /* CVTPL */ - R0_DESC, R2_DESC, R4_DESC, 0, /* MULP */ - R0_DESC, R2_DESC, R4_DESC, 0, /* DIVP */ - R0_DESC, R2_DESC, R4_ARG, 0, /* ASHP */ - R0_DESC, 0, 0, 0, /* CVTLP */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 100 - 107 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* 110 - 117 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* 120 - 127 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - IN_DESC, IN_DESC, IN_ARG, 0, /* MOVCI */ - IN_DESC, IN_DESC, IN_ARG, 0, /* MOVRCI */ - IN_DESC, IN_DESC, IN_ARG, IN_ARG, /* MOVTCI */ - 0, 0, 0, 0, /* 133 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 134 - 137 */ - 0, 0, 0, 0, 0, 0, 0, 0, - IN_DESC_R0, IN_ARG, 0, 0, /* LOCCI */ - IN_DESC_R0, IN_ARG, 0, 0, /* SKPCI */ - IN_DESC_R0, IN_DESC, 0, 0, /* SCANCI */ - IN_DESC_R0, IN_DESC, 0, 0, /* SPANCI */ - IN_DESC, IN_DESC, IN_ARG, 0, /* CMPCI */ - IN_DESC_R0, IN_DESC, 0, 0, /* MATCI */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 146 - 147 */ - IN_DESC, IN_DESC, IN_DESC, 0, /* ADDNI */ - IN_DESC, IN_DESC, IN_DESC, 0, /* SUBNI */ - IN_DESC, IN_DESC, 0, 0, /* CMPNI */ - IN_DESC, IN_ARG, 0, 0, /* CVTNLI */ - IN_DESC, IN_DESC, 0, 0, /* CVTPNI */ - IN_DESC, IN_DESC, 0, 0, /* CVTNPI */ - IN_DESC, IN_DESC, IN_ARG, 0, /* ASHNI */ - IN_DESC, IN_DESC, 0, 0, /* CVTLNI */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 160 - 167 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - IN_DESC, IN_DESC, IN_DESC, 0, /* ADDPI */ - IN_DESC, IN_DESC, IN_DESC, 0, /* SUBPI */ - IN_DESC, IN_DESC, 0, 0, /* CMPPI */ - IN_DESC, 0, 0, 0, /* CVTPLI */ - IN_DESC, IN_DESC, IN_DESC, 0, /* MULPI */ - IN_DESC, IN_DESC, IN_DESC, 0, /* DIVPI */ - IN_DESC, IN_DESC, IN_ARG, 0, /* ASHPI */ - IN_DESC, IN_DESC, 0, 0 /* CVTLPI */ -}; - -/* ASCII to overpunch table: sign is <7>, digit is <4:0> */ - -static int32 overbin[128] = { - 0, 0, 0, 0, 0, 0, 0, 0, /* 000 - 037 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x80, 0, 0, 0, 0, 0, 0, /* 040 - 077 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 0x80, 0, 0, 0, 0, 0, - 0, 1, 2, 3, 4, 5, 6, 7, /* 100 - 137 */ - 8, 9, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, - 0x87, 0x88, 0x89, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x80, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* 140 - 177 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x80, 0, 0 -}; - -/* Overpunch to ASCII table: indexed by sign and digit */ - -static int32 binover[2][16] = { - '{', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', - '0', '0', '0', '0', '0', '0', - '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', - '0', '0', '0', '0', '0', '0' -}; - -static unsigned char movbuf[65536]; - -/* CIS emulator */ - -void cis11 (int32 IR) -{ -int32 c, i, j, k, t, op, rn, addr; -int32 fill, mask, match, limit, mvlnt, shift; -int32 spc, ldivd, ldivr; -int32 arg[6]; /* operands */ -uint32 nc, digit, result; -static DSTR accum, src1, src2, dst; -static DSTR mptable[10]; -static DSTR Dstr1 = { 0, 0x10, 0, 0, 0 }; - -op = IR & 0177; /* IR <6:0> */ -for (i = j = 0; (i < MAXOPN) && opntab[op][i]; i++) { /* parse operands */ - switch (opntab[op][i]) { /* case on op type */ - case R0_DESC: - arg[j++] = R[0]; - arg[j++] = R[1]; - break; - case R2_DESC: - arg[j++] = R[2]; - arg[j++] = R[3]; - break; - case R4_DESC: - arg[j++] = R[4]; - arg[j++] = R[5]; - break; - case R4_ARG: - arg[j++] = R[4]; - break; - case IN_DESC: - addr = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - arg[j++] = ReadW (addr | dsenable); - arg[j++] = ReadW (((addr + 2) & 0177777) | dsenable); - break; - case IN_DESC_R0: - addr = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - R[0] = ReadW (addr | dsenable); - R[1] = ReadW (((addr + 2) & 0177777) | dsenable); - break; - case IN_ARG: - arg[j++] = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - break; } /* end case */ - } /* end for */ -switch (op) { /* case on opcode */ - -/* MOVC, MOVTC, MOVCI, MOVTCI - - Operands: - A1LNT, A1ADR = source string descriptor - A2LNT, A2ADR = dest string descriptor - A3LNT<7:0> = fill character - A3ADR = translation table address (MOVTC, MOVTCI only) - - Condition codes: - NZVC = set from src.lnt - dst.lnt - - Registers (MOVC, MOVTC only) - R0 = max (0, src.len - dst.len) - R1:R3 = 0 - R4:R5 = unchanged - - Notes: - - To avoid overlap problems, the entire source string is - buffered in movbuf. On a modern microprocessor, for most - string sizes, this will be handled in the on chip cache. - - If either the source or destination lengths are zero, - the move loops exit immediately. - - If the source length does not exceed the destination - length, the fill loop exits immediately. -*/ - -case 030: case 032: case 0130: case 0132: - mvlnt = (A1LNT < A2LNT)? A1LNT: A2LNT; /* calc move lnt */ - for (i = 0; i < mvlnt; i++) { - movbuf[i] = ReadB (((A1ADR + i) & 0177777) | dsenable); } - for (i = 0; i < mvlnt; i++) { - t = movbuf[i]; - if (op & 2) t = ReadB (((A3ADR + t) & 0177777) | dsenable); - WriteB (t, ((A2ADR + i) & 0177777) | dsenable); } - fill = A3LNT & 0377; /* do fill, if any */ - for (i = mvlnt; i < A2LNT; i++) { - WriteB (fill, ((A2ADR + i) & 0177777) | dsenable); } - t = A1LNT - A2LNT; /* src.lnt - dst.lnt */ - N = GET_SIGN_W (t); /* set cc's from diff */ - Z = GET_Z (t); - V = GET_SIGN_W ((A1LNT ^ A2LNT) & (~A2LNT ^ t)); - C = (A1LNT < A2LNT); - if ((op & INLINE) == 0) { /* if reg, set reg */ - R[0] = C? 0: t & 0177777; - R[1] = R[2] = R[3] = 0; - R[4] = R[4] & 0377; } - return; - -/* MOVRC, MOVRCI - - Operands: - A1LNT, A1ADR = source string descriptor - A2LNT, A2ADR = dest string descriptor - A3LNT<7:0> = fill character - - Condition codes: - NZVC = set from src.lnt - dst.lnt - - Registers (MOVRC only) - R0 = max (0, src.len - dst.len) - R1:R3 = 0 - R4:R5 = unchanged - - Notes: see MOVC, MOVCI -*/ - -case 031: case 0131: - mvlnt = (A1LNT < A2LNT)? A1LNT: A2LNT; /* calc move lnt */ - addr = A1ADR + A1LNT - mvlnt; - for (i = 0; i < mvlnt; i++) { - movbuf[i] = ReadB (((addr + i) & 0177777) | dsenable); } - addr = A2ADR + A2LNT - mvlnt; - for (i = 0; i < mvlnt; i++) { - WriteB (movbuf[i], ((addr + i) & 0177777) | dsenable); } - fill = A3LNT & 0377; /* do fill, if any */ - for (i = mvlnt, j = 0; i < A2LNT; i++, j++) { - WriteB (fill, ((A2ADR + j) & 0177777) | dsenable); } - t = A1LNT - A2LNT; /* src.lnt - dst.lnt */ - N = GET_SIGN_W (t); /* set cc's from diff */ - Z = GET_Z (t); - V = GET_SIGN_W ((A1LNT ^ A2LNT) & (~A2LNT ^ t)); - C = (A1LNT < A2LNT); - if ((op & INLINE) == 0) { /* if reg, set reg */ - R[0] = C? 0: t & 0177777; - R[1] = R[2] = R[3] = 0; - R[4] = R[4] & 0377; } - return; - -/* Load descriptors - no operands */ - -case 020: case 021: case 022: case 023: -case 024: case 025: case 026: case 027: -case 060: case 061: case 062: case 063: -case 064: case 065: case 066: case 067: - limit = (op & 040)? 6: 4; - rn = IR & 07; /* get register */ - t = R[rn]; - spc = (rn == 7)? isenable: dsenable; - for (j = 0; j < limit; j = j + 2) { /* loop for 2,3 dscr */ - addr = ReadW (((t + j) & 0177777) | spc); - R[j] = ReadW (addr | dsenable); - R[j + 1] = ReadW (((addr + 2) & 0177777) | dsenable); } - if (rn >= limit) R[rn] = (R[rn] + limit) & 0177777; - return; - -/* LOCC, SKPC, LOCCI, SKPCI - - Operands: - R0, R1 = source string descriptor - A1LNT<7:0> = match character - - Condition codes: - NZ = set from R0 - VC = 0 - - Registers: - R0:R1 = substring descriptor where operation terminated -*/ - -case 040: case 041: case 0140: case 0141: - match = A1LNT & 0377; /* match character */ - for ( ; R[0] != 0; R[0]--) { /* loop */ - c = ReadB (R[1] | dsenable); /* get char */ - if ((c == match) ^ (op & 1)) break; /* = + LOC, != + SKP? */ - R[1] = (R[1] + 1) & 0177777; } - N = GET_SIGN_W (R[0]); - Z = GET_Z (R[0]); - V = C = 0; - if ((op & INLINE) == 0) R[4] = R[4] & 0377; /* if reg, set reg */ - return; - -/* SCANC, SPANC, SCANCI, SPANCI - - Operands: - R0, R1 = source string descriptor - A1LNT<7:0> = mask - A1ADR = table address - - Condition codes: - NZ = set from R0 - VC = 0 - - Registers: - R0:R1 = substring descriptor where operation terminated -*/ - -case 042: case 043: case 0142: case 0143: - mask = A1LNT & 0377; /* mask character */ - for (; R[0] != 0; R[0]--) { /* loop */ - t = ReadB (R[1] | dsenable); /* get char as index */ - c = ReadB (((A1ADR + t) & 0177777) | dsenable); - if (((c & mask) != 0) ^ (op & 1)) break; /* != + SCN, = + SPN? */ - R[1] = (R[1] + 1) & 0177777; } - N = GET_SIGN_W (R[0]); - Z = GET_Z (R[0]); - V = C = 0; - if ((op & INLINE) == 0) R[4] = R[4] & 0377; /* if reg, set reg */ - return; - -/* CMPC, CMPCI - - Operands: - A1LNT, A1ADR = source1 string descriptor - A2LNT, A2ADR = source2 string descriptor - A3LNT<7:0> = fill character - - Condition codes: - NZVC = set from src1 - src2 at mismatch, or - = 0100 if equal - - Registers (CMPC only): - R0:R1 = unmatched source1 substring descriptor - R2:R3 = unmatched source2 substring descriptor -*/ - -case 044: case 0144: - c = t = 0; - for (i = 0; i < ((A1LNT > A2LNT)? A1LNT: A2LNT); i++) { - if (i < A1LNT) c = ReadB (((A1ADR + i) & 0177777) | dsenable); - else c = A3LNT & 0377; - if (i < A2LNT) t = ReadB (((A2ADR + i) & 0177777) | dsenable); - else t = A3LNT & 0377; - if (c != t) break; } - j = c - t; /* last chars read */ - N = GET_SIGN_B (j); /* set cc's */ - Z = GET_Z (j); - V = GET_SIGN_B ((c ^ t) & (~t ^ j)); - C = (c < t); - if ((op & INLINE) == 0) { /* if reg, set reg */ - j = (i > A1LNT)? A1LNT: i; /* #src1 chars used */ - k = (i > A2LNT)? A2LNT: i; /* #src2 chars used */ - R[0] = A1LNT - j; - R[1] = (A1ADR + j) & 0177777; - R[2] = A2LNT - k; - R[3] = (A2ADR + k) & 0177777; - R[4] = R[4] & 0377; } - return; - -/* MATC, MATCI - - Operands: - R0, R1 = source string descriptor - A1LNT, A1ADR = substring descriptor - - Condition codes: - NZ = set from R0 - VC = 0 - - Registers: - R0:R1 = source substring descriptor for match - - Notes: - - If the string is zero length, and the substring is not, - the outer loop exits immediately, and the result is - "no match" - - If the substring is zero length, the inner loop always - exits immediately, and the result is a "match" - - If the string is zero length, and the substring is as - well, the outer loop executes, the inner loop exits - immediately, and the result is a match, but the result - is the length of the string (zero), or "no match" -*/ - -case 0045: case 0145: - for (match = 0; R[0] >= A1LNT; R[0]--) { /* loop thru string */ - for (i = 0, match = 1; match && (i < A1LNT); i++) { - c = ReadB (((R[1] + i) & 0177777) | dsenable); - t = ReadB (((A1ADR + i) & 0177777) | dsenable); - match = (c == t); } /* end for substring */ - if (match) break; /* exit if match */ - R[1] = (R[1] + 1) & 0177777; } /* end for string */ - if (!match) { /* if no match */ - R[1] = (R[1] + R[0]) & 0177777; - R[0] = 0; } - N = GET_SIGN_W (R[0]); - Z = GET_Z (R[0]); - V = C = 0; - return; - -/* ADDN, SUBN, ADDP, SUBP, ADDNI, SUBNI, ADDPI, SUBPI - - Operands: - A1LNT, A1ADR = source1 string descriptor - A2LNT, A2ADR = source2 string descriptor - A3LNT, A3ADR = destination string descriptor - - Condition codes: - NZV = set from result - C = 0 - - Registers (ADDN, ADDP, SUBN, SUBP only): - R0:R3 = 0 -*/ - -case 050: case 051: case 070: case 071: -case 0150: case 0151: case 0170: case 0171: - ReadDstr (A1, &src1, op); /* get source1 */ - ReadDstr (A2, &src2, op); /* get source2 */ - if (op & 1) src1.sign = src1.sign ^ 1; /* sub? invert sign */ - if (src1.sign ^ src2.sign) { /* opp signs? sub */ - if (CmpDstr (&src1, &src2) < 0) { /* src1 < src2? */ - SubDstr (&src1, &src2, &dst); /* src2 - src1 */ - dst.sign = src2.sign; } /* sign = src2 */ - else { - SubDstr (&src2, &src1, &dst); /* src1 - src2 */ - dst.sign = src1.sign; } /* sign = src1 */ - V = 0; } /* can't carry */ - else { /* addition */ - V = AddDstr (&src1, &src2, &dst, 0); /* add magnitudes */ - dst.sign = src1.sign; } /* set result sign */ - C = 0; - WriteDstr (A3, &dst, op); /* store result */ - if ((op & INLINE) == 0) /* if reg, clr reg */ - R[0] = R[1] = R[2] = R[3] = 0; - return; - -/* MULP, MULPI - - Operands: - A1LNT, A1ADR = source1 string descriptor - A2LNT, A2ADR = source2 string descriptor - A3LNT, A3ADR = destination string descriptor - - Condition codes: - NZV = set from result - C = 0 - - Registers (MULP only): - R0:R3 = 0 -*/ - -case 074: case 0174: - dst = Dstr0; /* clear result */ - if (ReadDstr (A1, &src1, op) && ReadDstr (A2, &src2, op)) { - dst.sign = src1.sign ^ src2.sign; /* sign of result */ - accum = Dstr0; /* clear accum */ - NibbleRshift (&src1, 1, 0); /* shift out sign */ - CreateTable (&src1, mptable); /* create *1, *2, ... */ - for (i = 1; i < (DSTRLNT * 8); i++) { /* 31 iterations */ - digit = (src2.val[i / 8] >> ((i % 8) * 4)) & 0xF; - if (digit > 0) /* add in digit*mpcnd */ - AddDstr (&mptable[digit], &accum, &accum, 0); - nc = NibbleRshift (&accum, 1, 0); /* ac right 4 */ - NibbleRshift (&dst, 1, nc); } /* result right 4 */ - V = TestDstr (&accum) != 0; } /* if ovflo, set V */ - else V = 0; /* result = 0 */ - C = 0; /* C = 0 */ - WriteDstr (A3, &dst, op); /* store result */ - if ((op & INLINE) == 0) /* if reg, clr reg */ - R[0] = R[1] = R[2] = R[3] = 0; - return; - -/* DIVP, DIVPI - - Operands: - A1LNT, A1ADR = divisor string descriptor - A2LNT, A2ADR = dividend string descriptor - A3LNT, A3ADR = destination string descriptor - - Condition codes: - NZV = set from result - C = set if divide by zero - - Registers (DIVP only): - R0:R3 = 0 -*/ - -case 075: case 0175: - ldivr = ReadDstr (A1, &src1, op); /* get divisor */ - if (ldivr == 0) { /* divisor = 0? */ - V = C = 1; /* set cc's */ - return; } - ldivr = LntDstr (&src1, ldivr); /* get exact length */ - ldivd = ReadDstr (A2, &src2, op); /* get dividend */ - ldivd = LntDstr (&src2, ldivd); /* get exact length */ - dst = Dstr0; /* clear dest */ - NibbleRshift (&src1, 1, 0); /* right justify ops */ - NibbleRshift (&src2, 1, 0); - if ((t = ldivd - ldivr) >= 0) { /* any divide to do? */ - WordLshift (&src1, t / 8); /* align divr to divd */ - NibbleLshift (&src1, t % 8, 0); - CreateTable (&src1, mptable); /* create *1, *2, ... */ - for (i = 0; i <= t; i++) { /* divide loop */ - for (digit = 9; digit > 0; digit--) { /* find digit */ - if (CmpDstr (&src2, &mptable[digit]) >= 0) { - SubDstr (&mptable[digit], &src2, &src2); - dst.val[0] = dst.val[0] | digit; - break; } } /* end if, for */ - NibbleLshift (&src2, 1, 0); /* shift dividend */ - NibbleLshift (&dst, 1, 0); /* shift quotient */ - } /* end divide loop */ - dst.sign = src1.sign ^ src2.sign; /* calculate sign */ - } /* end if */ - V = C = 0; - WriteDstr (A3, &dst, op); /* store result */ - if ((op & INLINE) == 0) /* if reg, clr reg */ - R[0] = R[1] = R[2] = R[3] = 0; - return; - -/* CMPN, CMPP, CMPNI, CMPPI - - Operands: - A1LNT, A1ADR = source1 string descriptor - A2LNT, A2ADR = source2 string descriptor - - Condition codes: - NZ = set from comparison - VC = 0 - - Registers (CMPN, CMPP only): - R0:R3 = 0 -*/ - -case 052: case 072: case 0152: case 0172: - ReadDstr (A1, &src1, op); /* get source1 */ - ReadDstr (A2, &src2, op); /* get source2 */ - N = Z = V = C = 0; - if (src1.sign != src2.sign) N = src1.sign; - else { - t = CmpDstr (&src1, &src2); /* compare strings */ - if (t < 0) N = 1; - else if (t == 0) Z = 1; } - if ((op & INLINE) == 0) /* if reg, clr reg */ - R[0] = R[1] = R[2] = R[3] = 0; - return; - -/* ASHN, ASHP, ASHNI, ASHPI - - Operands: - A1LNT, A1ADR = source string descriptor - A2LNT, A2ADR = destination string descriptor - A3LNT<11:8> = rounding digit - A3LNT<7:0> = shift count - - Condition codes: - NZV = set from result - C = 0 - - Registers (ASHN, ASHP only): - R0:R1, R4 = 0 -*/ - -case 056: case 076: case 0156: case 0176: - ReadDstr (A1, &src1, op); /* get source */ - V = C = 0; /* init cc's */ - shift = GET_ASHLNT (A3LNT); /* get shift count */ - if (shift & ASHSGN) { /* right shift? */ - shift = (ASHLNT_M + 1 - shift); /* !shift! */ - WordRshift (&src1, shift / 8); /* do word shifts */ - NibbleRshift (&src1, shift % 8, 0); /* do nibble shifts */ - t = GET_ASHRND (A3LNT); /* get rounding digit */ - if ((t + (src1.val[0] & 0xF)) > 9) /* rounding needed? */ - AddDstr (&src1, &Dstr1, &src1, 0); /* round */ - src1.val[0] = src1.val[0] & ~0xF; /* clear sign */ - } /* end right shift */ - else if (shift) { /* left shift? */ - if (WordLshift (&src1, shift / 8)) V = 1; /* do word shifts */ - if (NibbleLshift (&src1, shift % 8, 0)) V = 1; - } /* end left shift */ - WriteDstr (A2, &src1, op); /* store result */ - if ((op & INLINE) == 0) /* if reg, clr reg */ - R[0] = R[1] = R[4] = 0; - return; - -/* CVTPN, CVTPNI - - Operands: - A1LNT, A1ADR = source string descriptor - A2LNT, A2ADR = destination string descriptor - - Condition codes: - NZV = set from result - C = 0 - - Registers (CVTPN only): - R0:R1 = 0 -*/ - -case 054: case 0154: - ReadDstr (A1, &src1, PACKED); /* get source */ - V = C = 0; /* init cc's */ - WriteDstr (A2, &src1, NUMERIC); /* write dest */ - if ((op & INLINE) == 0) R[0] = R[1] = 0; /* if reg, clr reg */ - return; - -/* CVTNP, CVTNPI - - Operands: - A1LNT, A1ADR = source string descriptor - A2LNT, A2ADR = destination string descriptor - - Condition codes: - NZV = set from result - C = 0 - - Registers (CVTNP only): - R0:R1 = 0 -*/ - -case 055: case 0155: - ReadDstr (A1, &src1, NUMERIC); /* get source */ - V = C = 0; /* init cc's */ - WriteDstr (A2, &src1, PACKED); /* write dest */ - if ((op & INLINE) == 0) R[0] = R[1] = 0; /* if reg, clr reg */ - return; - -/* CVTNL, CVTPL, CVTNLI, CVTPLI - - Operands: - A1LNT, A1ADR = source string descriptor - A2LNT = destination address (inline only) - - Condition codes: - NZV = set from result - C = source < 0 and result != 0 - - Registers (CVTNL, CVTPL only): - R0:R1 = 0 - R2:R3 = result -*/ - -case 053: case 073: case 0153: case 0173: - ReadDstr (A1, &src1, op); /* get source */ - V = result = 0; /* clear V, result */ - for (i = (DSTRLNT * 8) - 1; i > 0; i--) { /* loop thru digits */ - digit = (src1.val[i / 8] >> ((i % 8) * 4)) & 0xF; - if (digit || result || V) { /* skip initial 0's */ - if (result >= MAXDVAL) V = 1; - result = (result * 10) + digit; - if (result < digit) V = 1; } /* end if */ - } /* end for */ - if (src1.sign) result = (~result + 1) & 0xFFFFFFFF; - N = GET_SIGN_L (result); - Z = GET_Z (result); - V = V | (N ^ src1.sign); /* overflow if +2**31 */ - C = src1.sign && (Z == 0); /* set C based on std */ - if (op & INLINE) { /* inline? */ - WriteW (result & 0177777, A2LNT | dsenable); - WriteW ((result >> 16) & 0177777, - ((A2LNT + 2) & 0177777) | dsenable); } - else { - R[0] = R[1] = 0; - R[2] = (result >> 16) & 0177777; - R[3] = result & 0177777; } - return; - -/* CVTLN, CVTLP, CVTLNI, CVTLPI - - Operands: - A1LNT, A1ADR = destination string descriptor - A2LNT, A2ADR = source long (CVTLNI, CVTLPI) - VAX format - R2:R3 = source long (CVTLN, CVTLP) - EIS format - - Condition codes: - NZV = set from result - C = 0 - - Registers (CVTLN, CVTLP only) - R2:R3 = 0 -*/ - -case 057: case 077: - result = (R[2] << 16) | R[3]; /* op in EIS format */ - R[2] = R[3] = 0; /* clear registers */ - goto CVTLx; /* join common code */ -case 0157: case 0177: - result = (A2ADR << 16) | A2LNT; /* op in VAX format */ -CVTLx: - dst = Dstr0; /* clear result */ - if (dst.sign = GET_SIGN_L (result)) result = (~result + 1) & 0xFFFFFFFF; - for (i = 1; (i < (DSTRLNT * 8)) && result; i++) { - digit = result % 10; - result = result / 10; - dst.val[i / 8] = dst.val[i / 8] | (digit << ((i % 8) * 4)); } - V = C = 0; - WriteDstr (A1, &dst, op); /* write result */ - return; -default: - setTRAP (TRAP_ILL); - break; } -return; -} /* end cis */ - -/* Get decimal string - - Arguments: - dscr = decimal string descriptor - src = decimal string structure - flag = numeric/packed flag - - The routine returns the length in int32's of the non-zero part of - the string. - - This routine plays fast and loose with operand checking, as did the - original 11/23 microcode (half of which I wrote). In particular, - - - If the flag specifies packed, the type is not checked at all. - The sign of an unsigned string is assumed to be 0xF (an - alternative for +). - - If the flag specifies numeric, packed types will be treated - as unsigned zoned. - - For separate, only the '-' sign is checked, not the '+'. - - However, to simplify the code elsewhere, digits are range checked, - and bad digits are replaced with 0's. -*/ - -int32 ReadDstr (int32 *dscr, DSTR *src, int32 flag) -{ -int32 c, i, end, lnt, type, t; - -*src = Dstr0; /* clear result */ -type = GET_DTYP (dscr[0]); /* get type */ -lnt = GET_DLNT (dscr[0]); /* get string length */ -if (flag & PACKED) { /* packed? */ - end = lnt / 2; /* last byte */ - for (i = 0; i <= end; i++) { /* loop thru string */ - c = ReadB (((dscr[1] + end - i) & 0177777) | dsenable); - if (i == 0) t = c & 0xF; /* save sign */ - if ((i == end) && ((lnt & 1) == 0)) c = c & 0xF; - if (c >= 0xA0) c = c & 0xF; /* check hi digit */ - if ((c & 0xF) >= 0xA) c = c & 0xF0; /* check lo digit */ - src->val[i / 4] = src->val[i / 4] | (c << ((i % 4) * 8)); - } /* end for */ - if ((t == 0xB) || (t == 0xD)) src->sign = 1; /* if -, set sign */ - src->val[0] = src->val[0] & ~0xF; /* clear sign */ - } /* end packed */ -else { /* numeric */ - if (type >= TS) src->sign = (ReadB ((((type == TS)? - dscr[1] + lnt: dscr[1] - 1) & 0177777) | dsenable) == '-'); - for (i = 1; i <= lnt; i++) { /* loop thru string */ - c = ReadB (((dscr[1] + lnt - i) & 0177777) | dsenable); - if ((i == 1) && (type == XZ) && ((c & 0xF0) == 0x70)) - src->sign = 1; /* signed zoned */ - else if (((i == 1) && (type == TO)) || - ((i == lnt) && (type == LO))) { - c = overbin[c & 0177]; /* get sign and digit */ - src->sign = c >> 7; } /* set sign */ - c = c & 0xF; /* get digit */ - if (c > 9) c = 0; /* range check */ - src->val[i / 8] = src->val[i / 8] | (c << ((i % 8) * 4)); - } /* end for */ - } /* end numeric */ -return TestDstr (src); /* clean -0 */ -} - -/* Store decimal string - - Arguments: - dsrc = decimal string descriptor - src = decimal string structure - flag = numeric/packed flag - PSW.NZ are also set to their proper values - PSW.V will be set on overflow; it must be initialized elsewhere - (to allow for external overflow calculations) - - The rules for the stored sign and the PSW sign are: - - Stored sign is negative if input is negative, string type - is signed, and the result is non-zero or there was overflow - - PSW sign is negative if input is negative, string type is - signed, and the result is non-zero - Thus, the stored sign and the PSW sign will differ in one case: - a negative zero generated by overflow is stored with a negative - sign, but PSW.N is clear -*/ - -void WriteDstr (int32 *dscr, DSTR *dst, int32 flag) -{ -int32 c, i, limit, end, type, lnt; -uint32 mask; -static uint32 masktab[8] = { - 0xFFFFFFF0, 0xFFFFFF00, 0xFFFFF000, 0xFFFF0000, - 0xFFF00000, 0xFF000000, 0xF0000000, 0x00000000 }; -static int32 unsignedtab[8] = { 0, 1, 0, 0, 0, 0, 0, 1 }; - -type = GET_DTYP (dscr[0]); /* get type */ -lnt = GET_DLNT (dscr[0]); /* get string length */ -mask = 0; /* can't ovflo */ -Z = 1; /* assume all 0's */ -limit = lnt / 8; /* limit for test */ -for (i = 0; i < DSTRLNT; i++) { /* loop thru value */ - if (i == limit) mask = masktab[lnt % 8]; /* at limit, get mask */ - else if (i > limit) mask = 0xFFFFFFFF; /* beyond, all ovflo */ - if (dst->val[i] & mask) V = 1; /* test for ovflo */ - if (dst->val[i] = dst->val[i] & ~mask) Z = 0; } /* test nz */ -dst->sign = dst->sign & ~unsignedtab[type] & ~(Z & ~V); -N = dst->sign & ~Z; /* N = sign, if ~zero */ - -if (flag & PACKED) { /* packed? */ - end = lnt / 2; /* end of string */ - if (type == UP) dst->val[0] = dst->val[0] | 0xF; - else dst->val[0] = dst->val[0] | 0xC | dst->sign; - for (i = 0; i <= end; i++) { /* store string */ - c = (dst->val[i / 4] >> ((i % 4) * 8)) & 0xFF; - WriteB (c, ((dscr[1] + end - i) & 0177777)); - } /* end for */ - } /* end packed */ -else { - if (type >= TS) WriteB (dst->sign? '-': '+', (((type == TS)? - dscr[1] + lnt: dscr[1] - 1) & 0177777) | dsenable); - for (i = 1; i <= lnt; i++) { /* store string */ - c = (dst->val[i / 8] >> ((i % 8) * 4)) & 0xF; /* get digit */ - if ((i == 1) && (type == XZ) && dst->sign) - c = c | 0x70; /* signed zoned */ - else if (((i == 1) && (type == TO)) || - ((i == lnt) && (type == LO))) - c = binover[dst->sign][c]; /* get sign and digit */ - else c = c | 0x30; /* default */ - WriteB (c, ((dscr[1] + lnt - i) & 0177777)); - } /* end for */ - } /* end numeric */ -return; -} - -/* Add decimal string magnitudes - - Arguments: - s1 = source1 decimal string - s2 = source2 decimal string - ds = destination decimal string - cy = carry in - Output = 1 if carry, 0 if no carry - - This algorithm courtesy Anton Chernoff, circa 1992 or even earlier - - We trace the history of a pair of adjacent digits to see how the - carry is fixed; each parenthesized item is a 4b digit. - - Assume we are adding: - (a)(b) I - + (x)(y) J - - First compute I^J: - (a^x)(b^y) TMP - - Note that the low bit of each digit is the same as the low bit of - the sum of the digits, ignoring the cary, since the low bit of the - sum is the xor of the bits. - - Now compute I+J+66 to get decimal addition with carry forced left - one digit: - (a+x+6+carry mod 16)(b+y+6 mod 16) SUM - - Note that if there was a carry from b+y+6, then the low bit of the - left digit is different from the expected low bit from the xor. - If we xor this SUM into TMP, then the low bit of each digit is 1 - if there was a carry, and 0 if not. We need to subtract 6 from each - digit that did not have a carry, so take ~(SUM ^ TMP) & 0x11, shift - it right 4 to the digits that are affected, and subtract 6*adjustment - (actually, shift it right 3 and subtract 3*adjustment). -*/ - -int32 AddDstr (DSTR *s1, DSTR *s2, DSTR *ds, int32 cy) -{ -int32 i; -unsigned int32 sm1, sm2, tm1, tm2, tm3, tm4; - -for (i = 0; i < DSTRLNT; i++) { /* loop low to high */ - tm1 = s1->val[i] ^ (s2->val[i] + cy); /* xor operands */ - sm1 = s1->val[i] + (s2->val[i] + cy); /* sum operands */ - sm2 = sm1 + 0x66666666; /* force carry out */ - cy = ((sm1 < s1->val[i]) || (sm2 < sm1)); /* check for overflow */ - tm2 = tm1 ^ sm2; /* get carry flags */ - tm3 = (tm2 >> 3) | (cy << 29); /* compute adjustment */ - tm4 = 0x22222222 & ~tm3; /* clear where carry */ - ds->val[i] = sm2 - (3 * tm4); } /* final result */ -return cy; -} - -/* Subtract decimal string magnitudes - - Arguments: - s1 = source1 decimal string - s2 = source2 decimal string - ds = destination decimal string - Outputs: s2 - s1 in ds - - Note: the routine assumes that s1 <= s2 - -*/ - -void SubDstr (DSTR *s1, DSTR *s2, DSTR *ds) -{ -int32 i; -DSTR compl; - -for (i = 0; i < DSTRLNT; i++) compl.val[i] = 0x99999999 - s1->val[i]; -AddDstr (&compl, s2, ds, 1); /* s1 + ~s2 + 1 */ -return; -} - -/* Compare decimal string magnitudes - - Arguments: - s1 = source1 decimal string - s2 = source2 decimal string - Output = 1 if >, 0 if =, -1 if < -*/ - -int32 CmpDstr (DSTR *s1, DSTR *s2) -{ -int32 i; - -for (i = DSTRMAX; i >=0; i--) { - if (s1->val[i] > s2->val[i]) return 1; - if (s1->val[i] < s2->val[i]) return -1; } -return 0; -} - -/* Test decimal string for zero - - Arguments: - dsrc = decimal string structure - Returns the non-zero length of the string, in int32 units - If the string is zero, the sign is cleared -*/ - -int32 TestDstr (DSTR *dsrc) -{ -int32 i; - -for (i = DSTRMAX; i >= 0; i--) if (dsrc->val[i]) return (i + 1); -dsrc->sign = 0; -return 0; -} - -/* Get exact length of decimal string - - Arguments: - dsrc = decimal string structure - nz = result from TestDstr -*/ - -int32 LntDstr (DSTR *dsrc, int32 nz) -{ -int32 i; - -for (i = 7; i > 0; i--) { - if ((dsrc->val[nz - 1] >> (i * 4)) & 0xF) break; } -return ((nz - 1) * 8) + i; -} - -/* Create table of multiples - - Arguments: - dsrc = base decimal string structure - mtable[10] = array of decimal string structures - - Note that dsrc has a high order zero nibble; this - guarantees that the largest multiple won't overflow - Also note that mtable[0] is not filled in -*/ - -void CreateTable (DSTR *dsrc, DSTR mtable[10]) -{ -int32 (i); - -mtable[1] = *dsrc; -for (i = 2; i < 10; i++) AddDstr (&mtable[1], &mtable[i-1], &mtable[i], 0); -return; -} - -/* Word shift right - - Arguments: - dsrc = decimal string structure - sc = shift count -*/ - -void WordRshift (DSTR *dsrc, int32 sc) -{ -int32 i; - -if (sc) { - for (i = 0; i < DSTRLNT; i++) { - if ((i + sc) < DSTRLNT) dsrc->val[i] = dsrc->val[i + sc]; - else dsrc->val[i] = 0; } } -return; -} - -/* Word shift left - - Arguments: - dsrc = decimal string structure - sc = shift count -*/ - -int32 WordLshift (DSTR *dsrc, int32 sc) -{ -int32 i, c; - -c = 0; -if (sc) { - for (i = DSTRMAX; i >= 0; i--) { - if (i > (DSTRMAX - sc)) c = c | dsrc->val[i]; - if ((i - sc) >= 0) dsrc->val[i] = dsrc->val[i - sc]; - else dsrc->val[i] = 0; } } -return c; -} - -/* Nibble shift decimal string right - - Arguments: - dsrc = decimal string structure - sc = shift count - cin = carry in -*/ - -unsigned int32 NibbleRshift (DSTR *dsrc, int32 sc, unsigned int32 cin) -{ -int32 i, s, rs, nc; - -if (s = sc * 4) { - rs = 32 - s; - for (i = DSTRMAX; i >= 0; i--) { - nc = dsrc->val[i]; - dsrc->val[i] = ((dsrc->val[i] >> s) | - (cin << rs)) & 0xFFFFFFFF; - cin = nc; } - return cin; } -return 0; -} - -/* Nibble shift decimal string left - - Arguments: - dsrc = decimal string structure - sc = shift count - cin = carry in -*/ - -unsigned int32 NibbleLshift (DSTR *dsrc, int32 sc, unsigned int32 cin) -{ -int32 i, s, rs, nc; - -if (s = sc * 4) { - rs = 32 - s; - for (i = 0; i < DSTRLNT; i++) { - nc = dsrc->val[i]; - dsrc->val[i] = ((dsrc->val[i] << s) | - (cin >> rs)) & 0xFFFFFFFF; - cin = nc; } - return cin; } -return 0; -} diff --git a/PDP11/pdp11_cpu.c b/PDP11/pdp11_cpu.c deleted file mode 100644 index 5e987a4a..00000000 --- a/PDP11/pdp11_cpu.c +++ /dev/null @@ -1,2506 +0,0 @@ -/* pdp11_cpu.c: PDP-11 CPU simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - cpu PDP-11 CPU (J-11 microprocessor) - - 05-Jun-03 RMS Fixed bugs in memory size table - 12-Mar-03 RMS Added logical name support - 01-Feb-03 RMS Changed R display to follow PSW, added SP display - 19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict - 05-Jan-03 RMS Added memory size restore support - 17-Oct-02 RMS Fixed bug in examine/deposit (found by Hans Pufal) - 08-Oct-02 RMS Revised to build dib_tab dynamically - Added SHOW IOSPACE - 09-Sep-02 RMS Added KW11P support - 14-Jul-02 RMS Fixed bug in MMR0 error status load - 03-Jun-02 RMS Fixed relocation add overflow, added PS<15:12> = 1111 - special case logic to MFPI and removed it from MTPI - (found by John Dundas) - 29-Apr-02 RMS More fixes to DIV and ASH/ASHC (found by John Dundas) - 28-Apr-02 RMS Fixed bugs in illegal instruction 000010 and in - write-only memory pages (found by Wolfgang Helbig) - 21-Apr-02 RMS Fixed bugs in DIV by zero, DIV overflow, TSTSET, RTS, - ASHC -32, and red zone trap (found by John Dundas) - 04-Mar-02 RMS Changed double operand evaluation order for M+ - 23-Feb-02 RMS Fixed bug in MAINT, CPUERR, MEMERR read - 28-Jan-02 RMS Revised for multiple timers; fixed calc_MMR1 macros - 06-Jan-02 RMS Revised enable/disable support - 30-Dec-01 RMS Added old PC queue - 25-Dec-01 RMS Cleaned up sim_inst declarations - 11-Dec-01 RMS Moved interrupt debug code - 07-Dec-01 RMS Revised to use new breakpoint package - 08-Nov-01 RMS Moved I/O to external module - 26-Oct-01 RMS Revised to use symbolic definitions for IO page - 15-Oct-01 RMS Added debug logging - 08-Oct-01 RMS Fixed bug in revised interrupt logic - 07-Sep-01 RMS Revised device disable and interrupt mechanisms - 26-Aug-01 RMS Added DZ11 support - 10-Aug-01 RMS Removed register from declarations - 17-Jul-01 RMS Fixed warning from VC++ 6.0 - 01-Jun-01 RMS Added DZ11 interrupts - 23-Apr-01 RMS Added RK611 support - 05-Apr-01 RMS Added TS11/TSV05 support - 05-Mar-01 RMS Added clock calibration support - 11-Feb-01 RMS Added DECtape support - 25-Jan-01 RMS Fixed 4M memory definition (found by Eric Smith) - 14-Apr-99 RMS Changed t_addr to unsigned - 18-Aug-98 RMS Added CIS support - 09-May-98 RMS Fixed bug in DIV overflow test - 19-Jan-97 RMS Added RP/RM support - 06-Apr-96 RMS Added dynamic memory sizing - 29-Feb-96 RMS Added TM11 support - 17-Jul-94 RMS Corrected updating of MMR1 if MMR0 locked - - The register state for the PDP-11 is: - - REGFILE[0:5][0] general register set - REGFILE[0:5][1] alternate general register set - STACKFILE[4] stack pointers for kernel, supervisor, unused, user - PC program counter - PSW processor status word - <15:14> = CM current processor mode - <13:12> = PM previous processor mode - <11> = RS register set select - <7:5> = IPL interrupt priority level - <4> = TBIT trace trap enable - <3:0> = NZVC condition codes - FR[0:5] floating point accumulators - FPS floating point status register - FEC floating exception code - FEA floating exception address - MMR0,1,2,3 memory management control registers - APRFILE[0:63] memory management relocation registers for - kernel, supervisor, unused, user - <31:16> = PAR processor address registers - <15:0> = PDR processor data registers - PIRQ processor interrupt request register - CPUERR CPU error register - MEMERR memory system error register - CCR cache control register - MAINT maintenance register - HITMISS cache status register - SR switch register - DR display register -*/ - -/* The PDP-11 has many instruction formats: - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ double operand - | opcode | source spec | dest spec | 010000:067777 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 110000:167777 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ register + operand - | opcode | src reg| dest spec | 004000:004777 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 070000:077777 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ single operand - | opcode | dest spec | 000100:000177 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 000300:000377 - 005000:007777 - 105000:107777 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ single register - | opcode |dest reg| 000200:000207 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 000230:000237 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ no operand - | opcode | 000000:000007 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ branch - | opcode | branch displacement | 000400:003477 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 100000:103477 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ EMT/TRAP - | opcode | trap code | 104000:104777 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ cond code operator - | opcode | immediate | 000240:000277 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - An operand specifier consists of an addressing mode and a register. - The addressing modes are: - - 0 register direct R op = R - 1 register deferred (R) op = M[R] - 2 autoincrement (R)+ op = M[R]; R = R + length - 3 autoincrement deferred @(R)+ op = M[M[R]]; R = R + 2 - 4 autodecrement -(R) R = R - length; op = M[R] - 5 autodecrement deferred @-(R) R = R - 2; op = M[M[R]] - 6 displacement d(R) op = M[R + disp] - 7 displacement deferred @d(R) op = M[M[R + disp]] - - There are eight general registers, R0-R7. R6 is the stack pointer, - R7 the PC. The combination of addressing modes with R7 yields: - - 27 immediate #n op = M[PC]; PC = PC + 2 - 37 absolute @#n op = M[M[PC]]; PC = PC + 2 - 67 relative d(PC) op = M[PC + disp] - 77 relative deferred @d(PC) op = M[M[PC + disp]] -*/ - -/* This routine is the instruction decode routine for the PDP-11. It - is called from the simulator control program to execute instructions - in simulated memory, starting at the simulated PC. It runs until an - enabled exception is encountered. - - General notes: - - 1. Virtual address format. PDP-11 memory management uses the 16b - virtual address, the type of reference (instruction or data), and - the current mode, to construct the 22b physical address. To - package this conveniently, the simulator uses a 19b pseudo virtual - address, consisting of the 16b virtual address prefixed with the - current mode and ispace/dspace indicator. These are precalculated - as isenable and dsenable for ispace and dspace, respectively, and - must be recalculated whenever MMR0, MMR3, or PSW changes. - - 2. Traps and interrupts. Variable trap_req bit-encodes all possible - traps. In addition, an interrupt pending bit is encoded as the - lowest priority trap. Traps are processed by trap_vec and trap_clear, - which provide the vector and subordinate traps to clear, respectively. - - Array int_req[0:7] bit encodes all possible interrupts. It is masked - under the interrupt priority level, ipl. If any interrupt request - is not masked, the interrupt bit is set in trap_req. While most - interrupts are handled centrally, a device can supply an interrupt - acknowledge routine. - - 3. PSW handling. The PSW is kept as components, for easier access. - Because the PSW can be explicitly written as address 17777776, - all instructions must update PSW before executing their last write. - - 4. Adding I/O devices. These modules must be modified: - - pdp11_defs.h add device address and interrupt definitions - pdp11_sys.c add to sim_devices table entry -*/ - -/* Definitions */ - -#include "pdp11_defs.h" - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC -#define calc_is(md) ((md) << VA_V_MODE) -#define calc_ds(md) (calc_is((md)) | ((MMR3 & dsmask[(md)])? VA_DS: 0)) -#define calc_MMR1(val) ((MMR1)? (((val) << 8) | MMR1): (val)) -#define GET_SIGN_W(v) ((v) >> 15) -#define GET_SIGN_B(v) ((v) >> 7) -#define GET_Z(v) ((v) == 0) -#define JMP_PC(x) PCQ_ENTRY; PC = (x) -#define BRANCH_F(x) PCQ_ENTRY; PC = (PC + (((x) + (x)) & 0377)) & 0177777 -#define BRANCH_B(x) PCQ_ENTRY; PC = (PC + (((x) + (x)) | 0177400)) & 0177777 -#define last_pa (cpu_unit.u4) /* auto save/rest */ -#define UNIT_V_18B (UNIT_V_UF) /* force 18b addr */ -#define UNIT_V_UBM (UNIT_V_UF + 1) /* bus map present */ -#define UNIT_V_RH11 (UNIT_V_UF + 2) /* RH11 Massbus */ -#define UNIT_V_CIS (UNIT_V_UF + 3) /* CIS present */ -#define UNIT_V_MSIZE (UNIT_V_UF + 4) /* dummy */ -#define UNIT_18B (1u << UNIT_V_18B) -#define UNIT_UBM (1u << UNIT_V_UBM) -#define UNIT_RH11 (1u << UNIT_V_RH11) -#define UNIT_CIS (1u << UNIT_V_CIS) -#define UNIT_MSIZE (1u << UNIT_V_MSIZE) -#define UNIT_MAP (UNIT_18B | UNIT_UBM | UNIT_RH11) - -/* Global state */ - -extern FILE *sim_log; - -uint16 *M = NULL; /* memory */ -int32 REGFILE[6][2] = { 0 }; /* R0-R5, two sets */ -int32 STACKFILE[4] = { 0 }; /* SP, four modes */ -int32 saved_PC = 0; /* program counter */ -int32 R[8] = { 0 }; /* working registers */ -int32 PSW = 0; /* PSW */ - int32 cm = 0; /* current mode */ - int32 pm = 0; /* previous mode */ - int32 rs = 0; /* register set */ - int32 ipl = 0; /* int pri level */ - int32 tbit = 0; /* trace flag */ - int32 N = 0, Z = 0, V = 0, C = 0; /* condition codes */ -int32 wait_state = 0; /* wait state */ -int32 trap_req = 0; /* trap requests */ -int32 int_req[IPL_HLVL] = { 0 }; /* interrupt requests */ -int32 PIRQ = 0; /* programmed int req */ -int32 SR = 0; /* switch register */ -int32 DR = 0; /* display register */ -fpac_t FR[6] = { 0 }; /* fp accumulators */ -int32 FPS = 0; /* fp status */ -int32 FEC = 0; /* fp exception code */ -int32 FEA = 0; /* fp exception addr */ -int32 APRFILE[64] = { 0 }; /* PARs/PDRs */ -int32 MMR0 = 0; /* MMR0 - status */ -int32 MMR1 = 0; /* MMR1 - R+/-R */ -int32 MMR2 = 0; /* MMR2 - saved PC */ -int32 MMR3 = 0; /* MMR3 - 22b status */ -int32 ub_map[UBM_LNT_LW] = { 0 }; /* Unibus map array */ -int32 cpu_bme = 0; /* bus map enable */ -int32 cpu_18b = 0; /* 18b CPU config'd */ -int32 cpu_ubm = 0; /* bus map config'd */ -int32 cpu_rh11 = 0; /* RH11 config'd */ -int32 cpu_astop = 0; /* address stop */ -int32 isenable = 0, dsenable = 0; /* i, d space flags */ -int32 CPUERR = 0; /* CPU error reg */ -int32 MEMERR = 0; /* memory error reg */ -int32 CCR = 0; /* cache control reg */ -int32 HITMISS = 0; /* hit/miss reg */ -int32 MAINT = MAINT_Q | MAINT_NOFPA | MAINT_KDJ | MAINT_BPOK; /* maint reg */ -int32 stop_trap = 1; /* stop on trap */ -int32 stop_vecabort = 1; /* stop on vec abort */ -int32 stop_spabort = 1; /* stop on SP abort */ -int32 wait_enable = 0; /* wait state enable */ -int32 cpu_log = 0; /* logging */ -uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -int32 dev_enb = (-1) & ~INT_TS; /* dev enables */ -jmp_buf save_env; /* abort handler */ -int32 dsmask[4] = { MMR3_KDS, MMR3_SDS, 0, MMR3_UDS }; /* dspace enables */ - -extern int32 sim_interval; -extern UNIT *sim_clock_queue; -extern UNIT clk_unit, pclk_unit; -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern DEVICE *sim_devices[]; - -/* Function declarations */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_bus (UNIT *uptr, int32 val, char *cptr, void *desc); -int32 GeteaB (int32 spec); -int32 GeteaW (int32 spec); -int32 relocR (int32 addr); -int32 relocW (int32 addr); -int32 ReadW (int32 addr); -int32 ReadB (int32 addr); -int32 ReadMW (int32 addr); -int32 ReadMB (int32 addr); -void WriteW (int32 data, int32 addr); -void WriteB (int32 data, int32 addr); -void PWriteW (int32 data, int32 addr); -void PWriteB (int32 data, int32 addr); -t_stat CPU_rd (int32 *data, int32 addr, int32 access); -t_stat CPU_wr (int32 data, int32 addr, int32 access); -t_stat APR_rd (int32 *data, int32 addr, int32 access); -t_stat APR_wr (int32 data, int32 addr, int32 access); -t_stat SR_MMR012_rd (int32 *data, int32 addr, int32 access); -t_stat SR_MMR012_wr (int32 data, int32 addr, int32 access); -t_stat MMR3_rd (int32 *data, int32 addr, int32 access); -t_stat MMR3_wr (int32 data, int32 addr, int32 access); -t_stat ubm_rd (int32 *data, int32 addr, int32 access); -t_stat ubm_wr (int32 data, int32 addr, int32 access); -void set_r_display (int32 rs, int32 cm); - -extern t_stat build_dib_tab (int32 ubm); -extern t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc); -extern t_stat iopageR (int32 *data, uint32 addr, int32 access); -extern t_stat iopageW (int32 data, uint32 addr, int32 access); -extern int32 calc_ints (int32 nipl, int32 trq); -extern int32 get_vector (int32 nipl); - -/* Trap data structures */ - -int32 trap_vec[TRAP_V_MAX] = { /* trap req to vector */ - VEC_RED, VEC_ODD, VEC_MME, VEC_NXM, - VEC_PAR, VEC_PRV, VEC_ILL, VEC_BPT, - VEC_IOT, VEC_EMT, VEC_TRAP, VEC_TRC, - VEC_YEL, VEC_PWRFL, VEC_FPE }; - -int32 trap_clear[TRAP_V_MAX] = { /* trap clears */ - TRAP_RED+TRAP_PAR+TRAP_YEL+TRAP_TRC+TRAP_ODD+TRAP_NXM, - TRAP_ODD+TRAP_PAR+TRAP_YEL+TRAP_TRC, - TRAP_MME+TRAP_PAR+TRAP_YEL+TRAP_TRC, - TRAP_NXM+TRAP_PAR+TRAP_YEL+TRAP_TRC, - TRAP_PAR+TRAP_TRC, TRAP_PRV+TRAP_TRC, - TRAP_ILL+TRAP_TRC, TRAP_BPT+TRAP_TRC, - TRAP_IOT+TRAP_TRC, TRAP_EMT+TRAP_TRC, - TRAP_TRAP+TRAP_TRC, TRAP_TRC, - TRAP_YEL, TRAP_PWRFL, TRAP_FPE }; - -/* Fixed I/O address table entries */ - -DIB cpu0_dib = { IOBA_CPU, IOLN_CPU, &CPU_rd, &CPU_wr, 0 }; -DIB cpu1_dib = { IOBA_APR, IOLN_APR, &APR_rd, &APR_wr, 0 }; -DIB cpu2_dib = { IOBA_APR1, IOLN_APR1, &APR_rd, &APR_wr, 0 }; -DIB cpu3_dib = { IOBA_SRMM, IOLN_SRMM, &SR_MMR012_rd, &SR_MMR012_wr, 0 }; -DIB cpu4_dib = { IOBA_MMR3, IOLN_MMR3, &MMR3_rd, &MMR3_wr, 0 }; -DIB ubm_dib = { IOBA_UBM, IOLN_UBM, &ubm_rd, &ubm_wr, 0 }; - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifier list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, INIMEMSIZE) }; - -REG cpu_reg[] = { - { ORDATA (PC, saved_PC, 16) }, - { ORDATA (R0, REGFILE[0][0], 16) }, - { ORDATA (R1, REGFILE[1][0], 16) }, - { ORDATA (R2, REGFILE[2][0], 16) }, - { ORDATA (R3, REGFILE[3][0], 16) }, - { ORDATA (R4, REGFILE[4][0], 16) }, - { ORDATA (R5, REGFILE[5][0], 16) }, - { ORDATA (SP, STACKFILE[MD_KER], 16) }, - { ORDATA (R00, REGFILE[0][0], 16) }, - { ORDATA (R01, REGFILE[1][0], 16) }, - { ORDATA (R02, REGFILE[2][0], 16) }, - { ORDATA (R03, REGFILE[3][0], 16) }, - { ORDATA (R04, REGFILE[4][0], 16) }, - { ORDATA (R05, REGFILE[5][0], 16) }, - { ORDATA (R10, REGFILE[0][1], 16) }, - { ORDATA (R11, REGFILE[1][1], 16) }, - { ORDATA (R12, REGFILE[2][1], 16) }, - { ORDATA (R13, REGFILE[3][1], 16) }, - { ORDATA (R14, REGFILE[4][1], 16) }, - { ORDATA (R15, REGFILE[5][1], 16) }, - { ORDATA (KSP, STACKFILE[MD_KER], 16) }, - { ORDATA (SSP, STACKFILE[MD_SUP], 16) }, - { ORDATA (USP, STACKFILE[MD_USR], 16) }, - { ORDATA (PSW, PSW, 16) }, - { GRDATA (CM, PSW, 8, 2, PSW_V_CM) }, - { GRDATA (PM, PSW, 8, 2, PSW_V_PM) }, - { FLDATA (RS, PSW, PSW_V_RS) }, - { GRDATA (IPL, PSW, 8, 3, PSW_V_IPL) }, - { FLDATA (T, PSW, PSW_V_TBIT) }, - { FLDATA (N, PSW, PSW_V_N) }, - { FLDATA (Z, PSW, PSW_V_Z) }, - { FLDATA (V, PSW, PSW_V_V) }, - { FLDATA (C, PSW, PSW_V_C) }, - { ORDATA (SR, SR, 16) }, - { ORDATA (DR, DR, 16) }, - { ORDATA (MEMERR, MEMERR, 16) }, - { ORDATA (CCR, CCR, 16) }, - { ORDATA (MAINT, MAINT, 16) }, - { ORDATA (HITMISS, HITMISS, 16) }, - { ORDATA (CPUERR, CPUERR, 16) }, - { BRDATA (IREQ, int_req, 8, 32, IPL_HLVL), REG_RO }, - { ORDATA (TRAPS, trap_req, TRAP_V_MAX) }, - { ORDATA (PIRQ, PIRQ, 16) }, - { FLDATA (WAIT, wait_state, 0) }, - { FLDATA (WAIT_ENABLE, wait_enable, 0) }, - { ORDATA (STOP_TRAPS, stop_trap, TRAP_V_MAX) }, - { FLDATA (STOP_VECA, stop_vecabort, 0) }, - { FLDATA (STOP_SPA, stop_spabort, 0) }, - { HRDATA (DBGLOG, cpu_log, 16), REG_HIDDEN }, - { ORDATA (FAC0H, FR[0].h, 32) }, - { ORDATA (FAC0L, FR[0].l, 32) }, - { ORDATA (FAC1H, FR[1].h, 32) }, - { ORDATA (FAC1L, FR[1].l, 32) }, - { ORDATA (FAC2H, FR[2].h, 32) }, - { ORDATA (FAC2L, FR[2].l, 32) }, - { ORDATA (FAC3H, FR[3].h, 32) }, - { ORDATA (FAC3L, FR[3].l, 32) }, - { ORDATA (FAC4H, FR[4].h, 32) }, - { ORDATA (FAC4L, FR[4].l, 32) }, - { ORDATA (FAC5H, FR[5].h, 32) }, - { ORDATA (FAC5L, FR[5].l, 32) }, - { ORDATA (FPS, FPS, 16) }, - { ORDATA (FEA, FEA, 16) }, - { ORDATA (FEC, FEC, 4) }, - { ORDATA (MMR0, MMR0, 16) }, - { ORDATA (MMR1, MMR1, 16) }, - { ORDATA (MMR2, MMR2, 16) }, - { ORDATA (MMR3, MMR3, 16) }, - { GRDATA (KIPAR0, APRFILE[000], 8, 16, 16) }, - { GRDATA (KIPDR0, APRFILE[000], 8, 16, 0) }, - { GRDATA (KIPAR1, APRFILE[001], 8, 16, 16) }, - { GRDATA (KIPDR1, APRFILE[001], 8, 16, 0) }, - { GRDATA (KIPAR2, APRFILE[002], 8, 16, 16) }, - { GRDATA (KIPDR2, APRFILE[002], 8, 16, 0) }, - { GRDATA (KIPAR3, APRFILE[003], 8, 16, 16) }, - { GRDATA (KIPDR3, APRFILE[003], 8, 16, 0) }, - { GRDATA (KIPAR4, APRFILE[004], 8, 16, 16) }, - { GRDATA (KIPDR4, APRFILE[004], 8, 16, 0) }, - { GRDATA (KIPAR5, APRFILE[005], 8, 16, 16) }, - { GRDATA (KIPDR5, APRFILE[005], 8, 16, 0) }, - { GRDATA (KIPAR6, APRFILE[006], 8, 16, 16) }, - { GRDATA (KIPDR6, APRFILE[006], 8, 16, 0) }, - { GRDATA (KIPAR7, APRFILE[007], 8, 16, 16) }, - { GRDATA (KIPDR7, APRFILE[007], 8, 16, 0) }, - { GRDATA (KDPAR0, APRFILE[010], 8, 16, 16) }, - { GRDATA (KDPDR0, APRFILE[010], 8, 16, 0) }, - { GRDATA (KDPAR1, APRFILE[011], 8, 16, 16) }, - { GRDATA (KDPDR1, APRFILE[011], 8, 16, 0) }, - { GRDATA (KDPAR2, APRFILE[012], 8, 16, 16) }, - { GRDATA (KDPDR2, APRFILE[012], 8, 16, 0) }, - { GRDATA (KDPAR3, APRFILE[013], 8, 16, 16) }, - { GRDATA (KDPDR3, APRFILE[013], 8, 16, 0) }, - { GRDATA (KDPAR4, APRFILE[014], 8, 16, 16) }, - { GRDATA (KDPDR4, APRFILE[014], 8, 16, 0) }, - { GRDATA (KDPAR5, APRFILE[015], 8, 16, 16) }, - { GRDATA (KDPDR5, APRFILE[015], 8, 16, 0) }, - { GRDATA (KDPAR6, APRFILE[016], 8, 16, 16) }, - { GRDATA (KDPDR6, APRFILE[016], 8, 16, 0) }, - { GRDATA (KDPAR7, APRFILE[017], 8, 16, 16) }, - { GRDATA (KDPDR7, APRFILE[017], 8, 16, 0) }, - { GRDATA (SIPAR0, APRFILE[020], 8, 16, 16) }, - { GRDATA (SIPDR0, APRFILE[020], 8, 16, 0) }, - { GRDATA (SIPAR1, APRFILE[021], 8, 16, 16) }, - { GRDATA (SIPDR1, APRFILE[021], 8, 16, 0) }, - { GRDATA (SIPAR2, APRFILE[022], 8, 16, 16) }, - { GRDATA (SIPDR2, APRFILE[022], 8, 16, 0) }, - { GRDATA (SIPAR3, APRFILE[023], 8, 16, 16) }, - { GRDATA (SIPDR3, APRFILE[023], 8, 16, 0) }, - { GRDATA (SIPAR4, APRFILE[024], 8, 16, 16) }, - { GRDATA (SIPDR4, APRFILE[024], 8, 16, 0) }, - { GRDATA (SIPAR5, APRFILE[025], 8, 16, 16) }, - { GRDATA (SIPDR5, APRFILE[025], 8, 16, 0) }, - { GRDATA (SIPAR6, APRFILE[026], 8, 16, 16) }, - { GRDATA (SIPDR6, APRFILE[026], 8, 16, 0) }, - { GRDATA (SIPAR7, APRFILE[027], 8, 16, 16) }, - { GRDATA (SIPDR7, APRFILE[027], 8, 16, 0) }, - { GRDATA (SDPAR0, APRFILE[030], 8, 16, 16) }, - { GRDATA (SDPDR0, APRFILE[030], 8, 16, 0) }, - { GRDATA (SDPAR1, APRFILE[031], 8, 16, 16) }, - { GRDATA (SDPDR1, APRFILE[031], 8, 16, 0) }, - { GRDATA (SDPAR2, APRFILE[032], 8, 16, 16) }, - { GRDATA (SDPDR2, APRFILE[032], 8, 16, 0) }, - { GRDATA (SDPAR3, APRFILE[033], 8, 16, 16) }, - { GRDATA (SDPDR3, APRFILE[033], 8, 16, 0) }, - { GRDATA (SDPAR4, APRFILE[034], 8, 16, 16) }, - { GRDATA (SDPDR4, APRFILE[034], 8, 16, 0) }, - { GRDATA (SDPAR5, APRFILE[035], 8, 16, 16) }, - { GRDATA (SDPDR5, APRFILE[035], 8, 16, 0) }, - { GRDATA (SDPAR6, APRFILE[036], 8, 16, 16) }, - { GRDATA (SDPDR6, APRFILE[036], 8, 16, 0) }, - { GRDATA (SDPAR7, APRFILE[037], 8, 16, 16) }, - { GRDATA (SDPDR7, APRFILE[037], 8, 16, 0) }, - { GRDATA (UIPAR0, APRFILE[060], 8, 16, 16) }, - { GRDATA (UIPDR0, APRFILE[060], 8, 16, 0) }, - { GRDATA (UIPAR1, APRFILE[061], 8, 16, 16) }, - { GRDATA (UIPDR1, APRFILE[061], 8, 16, 0) }, - { GRDATA (UIPAR2, APRFILE[062], 8, 16, 16) }, - { GRDATA (UIPDR2, APRFILE[062], 8, 16, 0) }, - { GRDATA (UIPAR3, APRFILE[063], 8, 16, 16) }, - { GRDATA (UIPDR3, APRFILE[063], 8, 16, 0) }, - { GRDATA (UIPAR4, APRFILE[064], 8, 16, 16) }, - { GRDATA (UIPDR4, APRFILE[064], 8, 16, 0) }, - { GRDATA (UIPAR5, APRFILE[065], 8, 16, 16) }, - { GRDATA (UIPDR5, APRFILE[065], 8, 16, 0) }, - { GRDATA (UIPAR6, APRFILE[066], 8, 16, 16) }, - { GRDATA (UIPDR6, APRFILE[066], 8, 16, 0) }, - { GRDATA (UIPAR7, APRFILE[067], 8, 16, 16) }, - { GRDATA (UIPDR7, APRFILE[067], 8, 16, 0) }, - { GRDATA (UDPAR0, APRFILE[070], 8, 16, 16) }, - { GRDATA (UDPDR0, APRFILE[070], 8, 16, 0) }, - { GRDATA (UDPAR1, APRFILE[071], 8, 16, 16) }, - { GRDATA (UDPDR1, APRFILE[071], 8, 16, 0) }, - { GRDATA (UDPAR2, APRFILE[072], 8, 16, 16) }, - { GRDATA (UDPDR2, APRFILE[072], 8, 16, 0) }, - { GRDATA (UDPAR3, APRFILE[073], 8, 16, 16) }, - { GRDATA (UDPDR3, APRFILE[073], 8, 16, 0) }, - { GRDATA (UDPAR4, APRFILE[074], 8, 16, 16) }, - { GRDATA (UDPDR4, APRFILE[074], 8, 16, 0) }, - { GRDATA (UDPAR5, APRFILE[075], 8, 16, 16) }, - { GRDATA (UDPDR5, APRFILE[075], 8, 16, 0) }, - { GRDATA (UDPAR6, APRFILE[076], 8, 16, 16) }, - { GRDATA (UDPDR6, APRFILE[076], 8, 16, 0) }, - { GRDATA (UDPAR7, APRFILE[077], 8, 16, 16) }, - { GRDATA (UDPDR7, APRFILE[077], 8, 16, 0) }, - { BRDATA (UBMAP, ub_map, 8, 22, UBM_LNT_LW) }, - { BRDATA (PCQ, pcq, 8, 16, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { ORDATA (WRU, sim_int_char, 8) }, - { ORDATA (DEVENB, dev_enb, 32), REG_HRO }, - { NULL} }; - -MTAB cpu_mod[] = { - { UNIT_MAP, UNIT_18B, "18b addressing", "18B", NULL }, - { UNIT_MAP, UNIT_UBM, "22b Unibus + RH70", "URH70", &cpu_set_bus }, - { UNIT_MAP, UNIT_UBM + UNIT_RH11, "22b Unibus + RH11", "URH11", &cpu_set_bus }, - { UNIT_MAP, 0, "22b addressing", "22B", &cpu_set_bus }, - { UNIT_CIS, UNIT_CIS, "CIS", "CIS", NULL }, - { UNIT_CIS, 0, "no CIS", "NOCIS", NULL }, - { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size}, - { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size}, - { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size}, - { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size}, - { UNIT_MSIZE, 98304, NULL, "96K", &cpu_set_size}, - { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size}, - { UNIT_MSIZE, 196608, NULL, "192K", &cpu_set_size}, - { UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size}, - { UNIT_MSIZE, 393216, NULL, "384K", &cpu_set_size}, - { UNIT_MSIZE, 524288, NULL, "512K", &cpu_set_size}, - { UNIT_MSIZE, 786432, NULL, "768K", &cpu_set_size}, - { UNIT_MSIZE, 1048576, NULL, "1024K", &cpu_set_size}, - { UNIT_MSIZE, 2097152, NULL, "2048K", &cpu_set_size}, - { UNIT_MSIZE, 3145728, NULL, "3072K", &cpu_set_size}, - { UNIT_MSIZE, 4186112, NULL, "4096K", &cpu_set_size}, - { UNIT_MSIZE, 1048576, NULL, "1M", &cpu_set_size}, - { UNIT_MSIZE, 2097152, NULL, "2M", &cpu_set_size}, - { UNIT_MSIZE, 3145728, NULL, "3M", &cpu_set_size}, - { UNIT_MSIZE, 4186112, NULL, "4M", &cpu_set_size}, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL, - NULL, &show_iospace }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, 22, 2, 8, 16, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL, - NULL, DEV_DYNM, &cpu_set_size }; - -t_stat sim_instr (void) -{ -int abortval, i; -volatile int32 trapea; /* used by setjmp */ -t_stat reason; -void fp11 (int32 IR); -void cis11 (int32 IR); - -/* Restore register state - - 1. PSW components - 2. Active register file based on PSW - 3. Active stack pointer based on PSW - 4. Memory management control flags - 5. Interrupt system -*/ - -cpu_18b = cpu_unit.flags & UNIT_18B; /* export cnf flgs */ -cpu_ubm = cpu_unit.flags & UNIT_UBM; -cpu_rh11 = cpu_unit.flags & UNIT_RH11; -cpu_bme = (MMR3 & MMR3_BME) && cpu_ubm; -reason = build_dib_tab (cpu_ubm); /* build, chk dib_tab */ -if (reason != SCPE_OK) return reason; -cm = (PSW >> PSW_V_CM) & 03; /* call calc_is,ds */ -pm = (PSW >> PSW_V_PM) & 03; -rs = (PSW >> PSW_V_RS) & 01; -ipl = (PSW >> PSW_V_IPL) & 07; /* call calc_ints */ -tbit = (PSW >> PSW_V_TBIT) & 01; -N = (PSW >> PSW_V_N) & 01; -Z = (PSW >> PSW_V_Z) & 01; -V = (PSW >> PSW_V_V) & 01; -C = (PSW >> PSW_V_C) & 01; - -for (i = 0; i < 6; i++) R[i] = REGFILE[i][rs]; -SP = STACKFILE[cm]; -PC = saved_PC; - -isenable = calc_is (cm); -dsenable = calc_ds (cm); - -CPU_wr (PIRQ, 017777772, WRITE); /* rewrite PIRQ */ -trap_req = calc_ints (ipl, trap_req); /* upd int req */ -trapea = 0; -reason = 0; -sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init line clock */ -sim_rtcn_init (pclk_unit.wait, TMR_PCLK); /* init prog clock */ - -/* Abort handling - - If an abort occurs in memory management or memory access, the lower - level routine executes a longjmp to this area OUTSIDE the main - simulation loop. The longjmp specifies a trap mask which is OR'd - into the trap_req register. Simulation then resumes at the fetch - phase, and the trap is sprung. - - Aborts which occur within a trap sequence (trapea != 0) require - special handling. If the abort occured on the stack pushes, and - the mode (encoded in trapea) is kernel, an "emergency" kernel - stack is created at 4, and a red zone stack trap taken. - - All variables used in setjmp processing, or assumed to be valid - after setjmp, must be volatile or global. -*/ - -abortval = setjmp (save_env); /* set abort hdlr */ -if (abortval != 0) { - trap_req = trap_req | abortval; /* or in trap flag */ - if ((trapea > 0) && (stop_vecabort)) reason = STOP_VECABORT; - if ((trapea < 0) && (stop_spabort)) reason = STOP_SPABORT; - if (trapea == ~MD_KER) { /* kernel stk abort? */ - setTRAP (TRAP_RED); - setCPUERR (CPUE_RED); - STACKFILE[MD_KER] = 4; - if (cm == MD_KER) SP = 4; } } - -/* Main instruction fetch/decode loop - - Check for traps or interrupts. If trap, locate the vector and check - for stop condition. If interrupt, locate the vector. -*/ - -while (reason == 0) { - -int32 IR, srcspec, srcreg, dstspec, dstreg; -int32 src, src2, dst, ea; -int32 i, t, sign, oldrs, trapnum; - -if (cpu_astop) { - cpu_astop = 0; - reason = SCPE_STOP; - break; } - -if (sim_interval <= 0) { /* intv cnt expired? */ - reason = sim_process_event (); /* process events */ - trap_req = calc_ints (ipl, trap_req); /* recalc int req */ - continue; - } /* end if sim_interval */ - -if (trap_req) { /* check traps, ints */ - trapea = 0; /* assume srch fails */ - if (t = trap_req & TRAP_ALL) { /* if a trap */ - for (trapnum = 0; trapnum < TRAP_V_MAX; trapnum++) { - if ((t >> trapnum) & 1) { /* trap set? */ - trapea = trap_vec[trapnum]; /* get vec, clr */ - trap_req = trap_req & ~trap_clear[trapnum]; - if ((stop_trap >> trapnum) & 1) /* stop on trap? */ - reason = trapnum + 1; - break; - } /* end if t & 1 */ - } /* end for */ - } /* end if t */ - else { - trapea = get_vector (ipl); /* get int vector */ - trapnum = TRAP_V_MAX; /* defang stk trap */ - } /* end else t*/ - if (trapea == 0) { /* nothing to do? */ - trap_req = calc_ints (ipl, 0); /* recalculate */ - continue; /* back to fetch */ - } /* end if trapea */ - -/* Process a trap or interrupt - - 1. Exit wait state - 2. Save the current SP and PSW - 3. Read the new PC, new PSW from trapea, kernel data space - 4. Get the mode and stack selected by the new PSW - 5. Push the old PC and PSW on the new stack - 6. Update SP, PSW, and PC - 7. If not stack overflow, check for stack overflow -*/ - - wait_state = 0; /* exit wait state */ - STACKFILE[cm] = SP; - PSW = (cm << PSW_V_CM) | (pm << PSW_V_PM) | (rs << PSW_V_RS) | - (ipl << PSW_V_IPL) | (tbit << PSW_V_TBIT) | - (N << PSW_V_N) | (Z << PSW_V_Z) | - (V << PSW_V_V) | (C << PSW_V_C); - oldrs = rs; - src = ReadW (trapea | calc_ds (MD_KER)); - src2 = ReadW ((trapea + 2) | calc_ds (MD_KER)); - t = (src2 >> PSW_V_CM) & 03; - trapea = ~t; /* flag pushes */ - WriteW (PSW, ((STACKFILE[t] - 2) & 0177777) | calc_ds (t)); - WriteW (PC, ((STACKFILE[t] - 4) & 0177777) | calc_ds (t)); - trapea = 0; /* clear trap flag */ - pm = cm; - cm = t; /* call calc_is,ds */ - rs = (src2 >> PSW_V_RS) & 01; - ipl = (src2 >> PSW_V_IPL) & 07; /* call calc_ints */ - tbit = (src2 >> PSW_V_TBIT) & 01; - N = (src2 >> PSW_V_N) & 01; - Z = (src2 >> PSW_V_Z) & 01; - V = (src2 >> PSW_V_V) & 01; - C = (src2 >> PSW_V_C) & 01; - if (rs != oldrs) { /* if rs chg, swap */ - for (i = 0; i < 6; i++) { - REGFILE[i][oldrs] = R[i]; - R[i] = REGFILE[i][rs]; } } - SP = (STACKFILE[cm] - 4) & 0177777; /* update SP, PC */ - JMP_PC (src); - isenable = calc_is (cm); - dsenable = calc_ds (cm); - trap_req = calc_ints (ipl, trap_req); - if ((SP < STKLIM) && (cm == MD_KER) && - (trapnum != TRAP_V_RED) && (trapnum != TRAP_V_YEL)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } - continue; } /* end if traps */ - -/* Fetch and decode next instruction */ - -if (tbit) setTRAP (TRAP_TRC); -if (wait_state) { /* wait state? */ - if (sim_clock_queue != NULL) sim_interval = 0; /* force check */ - else reason = STOP_WAIT; - continue; } - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - continue; } - -if (update_MM) { /* if mm not frozen */ - MMR1 = 0; - MMR2 = PC; } -IR = ReadW (PC | isenable); /* fetch instruction */ -PC = (PC + 2) & 0177777; /* incr PC, mod 65k */ -sim_interval = sim_interval - 1; -srcspec = (IR >> 6) & 077; /* src, dst specs */ -dstspec = IR & 077; -srcreg = (srcspec <= 07); /* src, dst = rmode? */ -dstreg = (dstspec <= 07); -switch ((IR >> 12) & 017) { /* decode IR<15:12> */ - -/* Opcode 0: no operands, specials, branches, JSR, SOPs */ - -case 000: - switch ((IR >> 6) & 077) { /* decode IR<11:6> */ - case 000: /* no operand */ - if (IR >= 000010) { /* 000010 - 000077 */ - setTRAP (TRAP_ILL); /* illegal */ - break; } - switch (IR) { /* decode IR<2:0> */ - case 0: /* HALT */ - if ((cm == MD_KER) && ((MAINT & MAINT_HTRAP) == 0)) - reason = STOP_HALT; - else { - setTRAP (TRAP_PRV); - setCPUERR (CPUE_HALT); } - break; - case 1: /* WAIT */ - if ((cm == MD_KER) && wait_enable) wait_state = 1; - break; - case 3: /* BPT */ - setTRAP (TRAP_BPT); - break; - case 4: /* IOT */ - setTRAP (TRAP_IOT); - break; - case 5: /* RESET */ - if (cm == MD_KER) { - reset_all (1); - PIRQ = 0; - for (i = 0; i < IPL_HLVL; i++) int_req[i] = 0; - MMR0 = MMR0 & ~(MMR0_MME | MMR0_FREEZE); - MMR3 = 0; - trap_req = trap_req & ~TRAP_INT; - dsenable = calc_ds (cm); } - break; - -/* Opcode 0: specials, continued */ - - case 2: /* RTI */ - case 6: /* RTT */ - src = ReadW (SP | dsenable); - src2 = ReadW (((SP + 2) & 0177777) | dsenable); - STACKFILE[cm] = SP = (SP + 4) & 0177777; - oldrs = rs; - if (cm == MD_KER) { - cm = (src2 >> PSW_V_CM) & 03; - pm = (src2 >> PSW_V_PM) & 03; - rs = (src2 >> PSW_V_RS) & 01; - ipl = (src2 >> PSW_V_IPL) & 07; } - else { - cm = cm | ((src2 >> PSW_V_CM) & 03); - pm = pm | ((src2 >> PSW_V_PM) & 03); - rs = rs | ((src2 >> PSW_V_RS) & 01); } - tbit = (src2 >> PSW_V_TBIT) & 01; - N = (src2 >> PSW_V_N) & 01; - Z = (src2 >> PSW_V_Z) & 01; - V = (src2 >> PSW_V_V) & 01; - C = (src2 >> PSW_V_C) & 01; - trap_req = calc_ints (ipl, trap_req); - isenable = calc_is (cm); - dsenable = calc_ds (cm); - if (rs != oldrs) { - for (i = 0; i < 6; i++) { - REGFILE[i][oldrs] = R[i]; - R[i] = REGFILE[i][rs]; } } - SP = STACKFILE[cm]; - JMP_PC (src); - if ((IR == 000002) && tbit) setTRAP (TRAP_TRC); - break; - case 7: /* MFPT */ - R[0] = 5; /* report J-11 */ - break; } /* end switch no ops */ - break; /* end case no ops */ - -/* Opcode 0: specials, continued */ - - case 001: /* JMP */ - if (dstreg) setTRAP (TRAP_ILL); - else { - JMP_PC (GeteaW (dstspec) & 0177777); } - break; /* end JMP */ - case 002: /* RTS et al*/ - if (IR < 000210) { /* RTS */ - dstspec = dstspec & 07; - JMP_PC (R[dstspec]); - R[dstspec] = ReadW (SP | dsenable); - if (dstspec != 6) SP = (SP + 2) & 0177777; - break; } /* end if RTS */ - if (IR < 000230) { - setTRAP (TRAP_ILL); - break; } - if (IR < 000240) { /* SPL */ - if (cm == MD_KER) ipl = IR & 07; - trap_req = calc_ints (ipl, trap_req); - break; } /* end if SPL */ - if (IR < 000260) { /* clear CC */ - if (IR & 010) N = 0; - if (IR & 004) Z = 0; - if (IR & 002) V = 0; - if (IR & 001) C = 0; - break; } /* end if clear CCs */ - if (IR & 010) N = 1; /* set CC */ - if (IR & 004) Z = 1; - if (IR & 002) V = 1; - if (IR & 001) C = 1; - break; /* end case RTS et al */ - case 003: /* SWAB */ - dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = ((dst & 0377) << 8) | ((dst >> 8) & 0377); - N = GET_SIGN_B (dst & 0377); - Z = GET_Z (dst & 0377); - V = C = 0; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; /* end SWAB */ - -/* Opcode 0: branches, JSR */ - - case 004: case 005: /* BR */ - BRANCH_F (IR); - break; - case 006: case 007: /* BR */ - BRANCH_B (IR); - break; - case 010: case 011: /* BNE */ - if (Z == 0) { BRANCH_F (IR); } - break; - case 012: case 013: /* BNE */ - if (Z == 0) { BRANCH_B (IR); } - break; - case 014: case 015: /* BEQ */ - if (Z) { BRANCH_F (IR); } - break; - case 016: case 017: /* BEQ */ - if (Z) { BRANCH_B (IR); } - break; - case 020: case 021: /* BGE */ - if ((N ^ V) == 0) { BRANCH_F (IR); } - break; - case 022: case 023: /* BGE */ - if ((N ^ V) == 0) { BRANCH_B (IR); } - break; - case 024: case 025: /* BLT */ - if (N ^ V) { BRANCH_F (IR); } - break; - case 026: case 027: /* BLT */ - if (N ^ V) { BRANCH_B (IR); } - break; - case 030: case 031: /* BGT */ - if ((Z | (N ^ V)) == 0) { BRANCH_F (IR); } - break; - case 032: case 033: /* BGT */ - if ((Z | (N ^ V)) == 0) { BRANCH_B (IR); } - break; - case 034: case 035: /* BLE */ - if (Z | (N ^ V)) { BRANCH_F (IR); } - break; - case 036: case 037: /* BLE */ - if (Z | (N ^ V)) { BRANCH_B (IR); } - break; - case 040: case 041: case 042: case 043: /* JSR */ - case 044: case 045: case 046: case 047: - if (dstreg) setTRAP (TRAP_ILL); - else { - srcspec = srcspec & 07; - dst = GeteaW (dstspec); - SP = (SP - 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (0366); - WriteW (R[srcspec], SP | dsenable); - if ((SP < STKLIM) && (cm == MD_KER)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } - R[srcspec] = PC; - JMP_PC (dst & 0177777); } - break; /* end JSR */ - -/* Opcode 0: SOPs */ - - case 050: /* CLR */ - N = V = C = 0; - Z = 1; - if (dstreg) R[dstspec] = 0; - else WriteW (0, GeteaW (dstspec)); - break; - case 051: /* COM */ - dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = dst ^ 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - C = 1; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; - case 052: /* INC */ - dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = (dst + 1) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = (dst == 0100000); - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; - case 053: /* DEC */ - dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = (dst - 1) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = (dst == 077777); - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; - case 054: /* NEG */ - dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = (-dst) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = (dst == 0100000); - C = Z ^ 1; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; - case 055: /* ADC */ - dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = (dst + C) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = (C && (dst == 0100000)); - C = C & Z; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; - -/* Opcode 0: SOPs, continued */ - - case 056: /* SBC */ - dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = (dst - C) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = (C && (dst == 077777)); - C = (C && (dst == 0177777)); - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; - case 057: /* TST */ - dst = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = C = 0; - break; - case 060: /* ROR */ - src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = (src >> 1) | (C << 15); - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - C = (src & 1); - V = N ^ C; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; - case 061: /* ROL */ - src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = ((src << 1) | C) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - C = GET_SIGN_W (src); - V = N ^ C; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; - case 062: /* ASR */ - src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = (src >> 1) | (src & 0100000); - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - C = (src & 1); - V = N ^ C; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; - case 063: /* ASL */ - src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = (src << 1) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - C = GET_SIGN_W (src); - V = N ^ C; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; - -/* Opcode 0: SOPS, continued - - Notes: - - MxPI must mask GeteaW returned address to force ispace - - MxPI must set MMR1 for SP recovery in case of fault -*/ - - case 064: /* MARK */ - i = (PC + dstspec + dstspec) & 0177777; - JMP_PC (R[5]); - R[5] = ReadW (i | dsenable); - SP = (i + 2) & 0177777; - break; - case 065: /* MFPI */ - if (dstreg) { - if ((dstspec == 6) && (cm != pm)) dst = STACKFILE[pm]; - else dst = R[dstspec]; } - else { - i = ((cm == pm) && (cm == MD_USR))? calc_ds (pm): calc_is (pm); - dst = ReadW ((GeteaW (dstspec) & 0177777) | i); } - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - SP = (SP - 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (0366); - WriteW (dst, SP | dsenable); - if ((cm == MD_KER) && (SP < STKLIM)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } - break; - case 066: /* MTPI */ - dst = ReadW (SP | dsenable); - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - SP = (SP + 2) & 0177777; - if (update_MM) MMR1 = 026; - if (dstreg) { - if ((dstspec == 6) && (cm != pm)) STACKFILE[pm] = dst; - else R[dstspec] = dst; } - else WriteW (dst, (GeteaW (dstspec) & 0177777) | calc_is (pm)); - break; - case 067: /* SXT */ - dst = N? 0177777: 0; - Z = N ^ 1; - V = 0; - if (dstreg) R[dstspec] = dst; - else WriteW (dst, GeteaW (dstspec)); - break; - -/* Opcode 0: SOPs, continued */ - - case 070: /* CSM */ - if (((MMR3 & MMR3_CSM) == 0) || (cm == MD_KER)) - setTRAP (TRAP_ILL); - else { - dst = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); - PSW = (cm << PSW_V_CM) | (pm << PSW_V_PM) | - (rs << PSW_V_RS) | (ipl << PSW_V_IPL) | - (tbit << PSW_V_TBIT); - STACKFILE[cm] = SP; - WriteW (PSW, ((SP - 2) & 0177777) | calc_ds (MD_SUP)); - WriteW (PC, ((SP - 4) & 0177777) | calc_ds (MD_SUP)); - WriteW (dst, ((SP - 6) & 0177777) | calc_ds (MD_SUP)); - SP = (SP - 6) & 0177777; - pm = cm; - cm = MD_SUP; - tbit = 0; - isenable = calc_is (cm); - dsenable = calc_ds (cm); - PC = ReadW (010 | isenable); } - break; - case 072: /* TSTSET */ - if (dstreg) setTRAP (TRAP_ILL); - else { - dst = ReadMW (GeteaW (dstspec)); - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - C = (dst & 1); - R[0] = dst; /* R[0] <- dst */ - PWriteW (R[0] | 1, last_pa); } /* dst <- R[0] | 1 */ - break; - case 073: /* WRTLCK */ - if (dstreg) setTRAP (TRAP_ILL); - else { - N = GET_SIGN_W (R[0]); - Z = GET_Z (R[0]); - V = 0; - WriteW (R[0], GeteaW (dstspec)); } - break; - default: - setTRAP (TRAP_ILL); - break; } /* end switch SOPs */ - break; /* end case 000 */ - -/* Opcodes 01 - 06: double operand word instructions - - J-11 (and F-11) optimize away register source operand decoding. - As a result, dop R,+/-(R) use the modified version of R as source. - Most (but not all) other PDP-11's fetch the source operand before - any destination operand decoding. - - Add: v = [sign (src) = sign (src2)] and [sign (src) != sign (result)] - Cmp: v = [sign (src) != sign (src2)] and [sign (src2) = sign (result)] -*/ - -case 001: /* MOV */ - if (srcreg && !dstreg) { /* R,not R */ - ea = GeteaW (dstspec); - dst = R[srcspec]; } - else { - dst = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); - if (!dstreg) ea = GeteaW (dstspec); } - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - if (dstreg) R[dstspec] = dst; - else WriteW (dst, ea); - break; -case 002: /* CMP */ - if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadW (GeteaW (dstspec)); - src = R[srcspec]; } - else { - src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); - src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); } - dst = (src - src2) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = GET_SIGN_W ((src ^ src2) & (~src2 ^ dst)); - C = (src < src2); - break; -case 003: /* BIT */ - if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadW (GeteaW (dstspec)); - src = R[srcspec]; } - else { - src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); - src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); } - dst = src2 & src; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - break; -case 004: /* BIC */ - if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadMW (GeteaW (dstspec)); - src = R[srcspec]; } - else { - src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); - src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); } - dst = src2 & ~src; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; -case 005: /* BIS */ - if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadMW (GeteaW (dstspec)); - src = R[srcspec]; } - else { - src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); - src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); } - dst = src2 | src; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; -case 006: /* ADD */ - if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadMW (GeteaW (dstspec)); - src = R[srcspec]; } - else { - src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); - src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); } - dst = (src2 + src) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = GET_SIGN_W ((~src ^ src2) & (src ^ dst)); - C = (dst < src); - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; - -/* Opcode 07: EIS, FIS (not implemented), CIS - - Notes: - - The code assumes that the host int length is at least 32 bits. - - MUL carry: C is set if the (signed) result doesn't fit in 16 bits. - - Divide has three error cases: - 1. Divide by zero. - 2. Divide largest negative number by -1. - 3. (Signed) quotient doesn't fit in 16 bits. - Cases 1 and 2 must be tested in advance, to avoid C runtime errors. - - ASHx left: overflow if the bits shifted out do not equal the sign - of the result (convert shift out to 1/0, xor against sign). - - ASHx right: if right shift sign extends, then the shift and - conditional or of shifted -1 is redundant. If right shift zero - extends, then the shift and conditional or does sign extension. -*/ - -case 007: - srcspec = srcspec & 07; - switch ((IR >> 9) & 07) { /* decode IR<11:9> */ - case 0: /* MUL */ - src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); - src = R[srcspec]; - if (GET_SIGN_W (src2)) src2 = src2 | ~077777; - if (GET_SIGN_W (src)) src = src | ~077777; - dst = src * src2; - R[srcspec] = (dst >> 16) & 0177777; - R[srcspec | 1] = dst & 0177777; - N = (dst < 0); - Z = GET_Z (dst); - V = 0; - C = ((dst > 077777) || (dst < -0100000)); - break; - case 1: /* DIV */ - src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); - src = (((uint32) R[srcspec]) << 16) | R[srcspec | 1]; - if (src2 == 0) { - N = 0; /* J11,11/70 compat */ - Z = V = C = 1; /* N = 0, Z = 1 */ - break; } - if ((src == 020000000000) && (src2 == 0177777)) { - V = 1; /* J11,11/70 compat */ - N = Z = C = 0; /* N = Z = 0 */ - break; } - if (GET_SIGN_W (src2)) src2 = src2 | ~077777; - if (GET_SIGN_W (R[srcspec])) src = src | ~017777777777; - dst = src / src2; - N = (dst < 0); /* N set on 32b result */ - if ((dst > 077777) || (dst < -0100000)) { - V = 1; /* J11,11/70 compat */ - Z = C = 0; /* Z = C = 0 */ - break; } - R[srcspec] = dst & 0177777; - R[srcspec | 1] = (src - (src2 * dst)) & 0177777; - Z = GET_Z (dst); - V = C = 0; - break; - -/* Opcode 7: EIS, continued */ - - case 2: /* ASH */ - src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); - src2 = src2 & 077; - sign = GET_SIGN_W (R[srcspec]); - src = sign? R[srcspec] | ~077777: R[srcspec]; - if (src2 == 0) { /* [0] */ - dst = src; - V = C = 0; } - else if (src2 <= 15) { /* [1,15] */ - dst = src << src2; - i = (src >> (16 - src2)) & 0177777; - V = (i != ((dst & 0100000)? 0177777: 0)); - C = (i & 1); } - else if (src2 <= 31) { /* [16,31] */ - dst = 0; - V = (src != 0); - C = (src << (src2 - 16)) & 1; } - else if (src2 == 32) { /* [32] = -32 */ - dst = -sign; - V = C = 0; } - else { /* [33,63] = -31,-1 */ - dst = (src >> (64 - src2)) | (-sign << (src2 - 32)); - V = 0; - C = ((src >> (63 - src2)) & 1); } - dst = R[srcspec] = dst & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - break; - case 3: /* ASHC */ - src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); - src2 = src2 & 077; - sign = GET_SIGN_W (R[srcspec]); - src = (((uint32) R[srcspec]) << 16) | R[srcspec | 1]; - if (src2 == 0) { /* [0] */ - dst = src; - V = C = 0; } - else if (src2 <= 31) { /* [1,31] */ - dst = ((uint32) src) << src2; - i = (src >> (32 - src2)) | (-sign << src2); - V = (i != ((dst & 020000000000)? -1: 0)); - C = (i & 1); } - else if (src2 == 32) { /* [32] = -32 */ - dst = -sign; - V = 0; - C = (src >> 31) & 1; } - else { /* [33,63] = -31,-1 */ - dst = (src >> (64 - src2)) | (-sign << (src2 - 32)); - V = 0; - C = ((src >> (63 - src2)) & 1); } - i = R[srcspec] = (dst >> 16) & 0177777; - dst = R[srcspec | 1] = dst & 0177777; - N = GET_SIGN_W (i); - Z = GET_Z (dst | i); - break; - -/* Opcode 7: EIS, continued */ - - case 4: /* XOR */ - dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = dst ^ R[srcspec]; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; - case 5: /* FIS - not impl */ - setTRAP (TRAP_ILL); - break; - case 6: /* CIS */ - if (cpu_unit.flags & UNIT_CIS) cis11 (IR); - else setTRAP (TRAP_ILL); - break; - case 7: /* SOB */ - R[srcspec] = (R[srcspec] - 1) & 0177777; - if (R[srcspec]) { - JMP_PC ((PC - dstspec - dstspec) & 0177777); } - break; } /* end switch EIS */ - break; /* end case 007 */ - -/* Opcode 10: branches, traps, SOPs */ - -case 010: - switch ((IR >> 6) & 077) { /* decode IR<11:6> */ - case 000: case 001: /* BPL */ - if (N == 0) { BRANCH_F (IR); } - break; - case 002: case 003: /* BPL */ - if (N == 0) { BRANCH_B (IR); } - break; - case 004: case 005: /* BMI */ - if (N) { BRANCH_F (IR); } - break; - case 006: case 007: /* BMI */ - if (N) { BRANCH_B (IR); } - break; - case 010: case 011: /* BHI */ - if ((C | Z) == 0) { BRANCH_F (IR); } - break; - case 012: case 013: /* BHI */ - if ((C | Z) == 0) { BRANCH_B (IR); } - break; - case 014: case 015: /* BLOS */ - if (C | Z) { BRANCH_F (IR); } - break; - case 016: case 017: /* BLOS */ - if (C | Z) { BRANCH_B (IR); } - break; - case 020: case 021: /* BVC */ - if (V == 0) { BRANCH_F (IR); } - break; - case 022: case 023: /* BVC */ - if (V == 0) { BRANCH_B (IR); } - break; - case 024: case 025: /* BVS */ - if (V) { BRANCH_F (IR); } - break; - case 026: case 027: /* BVS */ - if (V) { BRANCH_B (IR); } - break; - case 030: case 031: /* BCC */ - if (C == 0) { BRANCH_F (IR); } - break; - case 032: case 033: /* BCC */ - if (C == 0) { BRANCH_B (IR); } - break; - case 034: case 035: /* BCS */ - if (C) { BRANCH_F (IR); } - break; - case 036: case 037: /* BCS */ - if (C) { BRANCH_B (IR); } - break; - case 040: case 041: case 042: case 043: /* EMT */ - setTRAP (TRAP_EMT); - break; - case 044: case 045: case 046: case 047: /* TRAP */ - setTRAP (TRAP_TRAP); - break; - -/* Opcode 10, continued: SOPs */ - - case 050: /* CLRB */ - N = V = C = 0; - Z = 1; - if (dstreg) R[dstspec] = R[dstspec] & 0177400; - else WriteB (0, GeteaB (dstspec)); - break; - case 051: /* COMB */ - dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = (dst ^ 0377) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = 0; - C = 1; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; - case 052: /* INCB */ - dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = (dst + 1) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = (dst == 0200); - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; - case 053: /* DECB */ - dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = (dst - 1) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = (dst == 0177); - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; - case 054: /* NEGB */ - dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = (-dst) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = (dst == 0200); - C = (Z ^ 1); - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; - case 055: /* ADCB */ - dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = (dst + C) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = (C && (dst == 0200)); - C = C & Z; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; - -/* Opcode 10: SOPs, continued */ - - case 056: /* SBCB */ - dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = (dst - C) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = (C && (dst == 0177)); - C = (C && (dst == 0377)); - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; - case 057: /* TSTB */ - dst = dstreg? R[dstspec] & 0377: ReadB (GeteaB (dstspec)); - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = C = 0; - break; - case 060: /* RORB */ - src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = ((src & 0377) >> 1) | (C << 7); - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - C = (src & 1); - V = N ^ C; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; - case 061: /* ROLB */ - src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = ((src << 1) | C) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - C = GET_SIGN_B (src & 0377); - V = N ^ C; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; - case 062: /* ASRB */ - src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = ((src & 0377) >> 1) | (src & 0200); - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - C = (src & 1); - V = N ^ C; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; - case 063: /* ASLB */ - src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = (src << 1) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - C = GET_SIGN_B (src & 0377); - V = N ^ C; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; - -/* Opcode 10: SOPs, continued - - Notes: - - MTPS cannot alter the T bit - - MxPD must mask GeteaW returned address, dspace is from cm not pm - - MxPD must set MMR1 for SP recovery in case of fault -*/ - - case 064: /* MTPS */ - dst = dstreg? R[dstspec]: ReadB (GeteaB (dstspec)); - if (cm == MD_KER) { - ipl = (dst >> PSW_V_IPL) & 07; - trap_req = calc_ints (ipl, trap_req); } - N = (dst >> PSW_V_N) & 01; - Z = (dst >> PSW_V_Z) & 01; - V = (dst >> PSW_V_V) & 01; - C = (dst >> PSW_V_C) & 01; - break; - case 065: /* MFPD */ - if (dstreg) { - if ((dstspec == 6) && (cm != pm)) dst = STACKFILE[pm]; - else dst = R[dstspec]; } - else dst = ReadW ((GeteaW (dstspec) & 0177777) | calc_ds (pm)); - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - SP = (SP - 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (0366); - WriteW (dst, SP | dsenable); - if ((cm == MD_KER) && (SP < STKLIM)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } - break; - case 066: /* MTPD */ - dst = ReadW (SP | dsenable); - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - SP = (SP + 2) & 0177777; - if (update_MM) MMR1 = 026; - if (dstreg) { - if ((dstspec == 6) && (cm != pm)) STACKFILE[pm] = dst; - else R[dstspec] = dst; } - else WriteW (dst, (GeteaW (dstspec) & 0177777) | calc_ds (pm)); - break; - case 067: /* MFPS */ - dst = (ipl << PSW_V_IPL) | (tbit << PSW_V_TBIT) | - (N << PSW_V_N) | (Z << PSW_V_Z) | - (V << PSW_V_V) | (C << PSW_V_C); - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = 0; - if (dstreg) R[dstspec] = (dst & 0200)? 0177400 | dst: dst; - else WriteB (dst, GeteaB (dstspec)); - break; - default: - setTRAP (TRAP_ILL); - break; } /* end switch SOPs */ - break; /* end case 010 */ - -/* Opcodes 11 - 16: double operand byte instructions - - Cmp: v = [sign (src) != sign (src2)] and [sign (src2) = sign (result)] - Sub: v = [sign (src) != sign (src2)] and [sign (src) = sign (result)] -*/ - -case 011: /* MOVB */ - if (srcreg && !dstreg) { /* R,not R */ - ea = GeteaB (dstspec); - dst = R[srcspec] & 0377; } - else { - dst = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec)); - if (!dstreg) ea = GeteaB (dstspec); } - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = 0; - if (dstreg) R[dstspec] = (dst & 0200)? 0177400 | dst: dst; - else WriteB (dst, ea); - break; -case 012: /* CMPB */ - if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadB (GeteaB (dstspec)); - src = R[srcspec] & 0377; } - else { - src = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec)); - src2 = dstreg? R[dstspec] & 0377: ReadB (GeteaB (dstspec)); } - dst = (src - src2) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = GET_SIGN_B ((src ^ src2) & (~src2 ^ dst)); - C = (src < src2); - break; -case 013: /* BITB */ - if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadB (GeteaB (dstspec)); - src = R[srcspec] & 0377; } - else { - src = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec)); - src2 = dstreg? R[dstspec] & 0377: ReadB (GeteaB (dstspec)); } - dst = (src2 & src) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = 0; - break; -case 014: /* BICB */ - if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadMB (GeteaB (dstspec)); - src = R[srcspec]; } - else { - src = srcreg? R[srcspec]: ReadB (GeteaB (srcspec)); - src2 = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); } - dst = (src2 & ~src) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = 0; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; -case 015: /* BISB */ - if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadMB (GeteaB (dstspec)); - src = R[srcspec]; } - else { - src = srcreg? R[srcspec]: ReadB (GeteaB (srcspec)); - src2 = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); } - dst = (src2 | src) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = 0; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; -case 016: /* SUB */ - if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadMW (GeteaW (dstspec)); - src = R[srcspec]; } - else { - src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); - src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); } - dst = (src2 - src) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = GET_SIGN_W ((src ^ src2) & (~src ^ dst)); - C = (src2 < src); - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; - -/* Opcode 17: floating point */ - -case 017: - fp11 (IR); /* floating point */ - break; /* end case 017 */ - } /* end switch op */ -} /* end main loop */ - -/* Simulation halted */ - -PSW = (cm << PSW_V_CM) | (pm << PSW_V_PM) | (rs << PSW_V_RS) | - (ipl << PSW_V_IPL) | (tbit << PSW_V_TBIT) | - (N << PSW_V_N) | (Z << PSW_V_Z) | (V << PSW_V_V) | (C << PSW_V_C); -for (i = 0; i < 6; i++) REGFILE[i][rs] = R[i]; -STACKFILE[cm] = SP; -saved_PC = PC & 0177777; -pcq_r->qptr = pcq_p; /* update pc q ptr */ -set_r_display (rs, cm); -return reason; -} - -/* Effective address calculations - - Inputs: - spec = specifier <5:0> - Outputs: - ea = effective address - <15:0> = virtual address - <16> = instruction/data data space - <18:17> = mode - - Data space calculation: the PDP-11 features both instruction and data - spaces. Instruction space contains the instruction and any sequential - add ons (eg, immediates, absolute addresses). Data space contains all - data operands and indirect addresses. If data space is enabled, then - memory references are directed according to these rules: - - Mode Index ref Indirect ref Direct ref - 10..16 na na data - 17 na na instruction - 20..26 na na data - 27 na na instruction - 30..36 na data data - 37 na instruction (absolute) data - 40..46 na na data - 47 na na instruction - 50..56 na data data - 57 na instruction data - 60..67 instruction na data - 70..77 instruction data data - - According to the PDP-11 Architecture Handbook, MMR1 records all - autoincrement and autodecrement operations, including those which - explicitly reference the PC. For the J-11, this is only true for - autodecrement operands, autodecrement deferred operands, and - autoincrement destination operands that involve a write to memory. - The simulator follows the Handbook, for simplicity. - - Notes: - - - dsenable will direct a reference to data space if data space is enabled - - ds will direct a reference to data space if data space is enabled AND if - the specifier register is not PC; this is used for 17, 27, 37, 47, 57 - - Modes 2x, 3x, 4x, and 5x must update MMR1 if updating enabled - - Modes 46 and 56 must check for stack overflow if kernel mode -*/ - -/* Effective address calculation for words */ - -int32 GeteaW (int32 spec) -{ -int32 adr, reg, ds; - -reg = spec & 07; /* register number */ -ds = (reg == 7)? isenable: dsenable; /* dspace if not PC */ -switch (spec >> 3) { /* decode spec<5:3> */ -default: /* can't get here */ -case 1: /* (R) */ - return (R[reg] | ds); -case 2: /* (R)+ */ - R[reg] = ((adr = R[reg]) + 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (020 | reg); - return (adr | ds); -case 3: /* @(R)+ */ - R[reg] = ((adr = R[reg]) + 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (020 | reg); - adr = ReadW (adr | ds); - return (adr | dsenable); -case 4: /* -(R) */ - adr = R[reg] = (R[reg] - 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (0360 | reg); - if ((adr < STKLIM) && (reg == 6) && (cm == MD_KER)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } - return (adr | ds); -case 5: /* @-(R) */ - adr = R[reg] = (R[reg] - 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (0360 | reg); - if ((adr < STKLIM) && (reg == 6) && (cm == MD_KER)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } - adr = ReadW (adr | ds); - return (adr | dsenable); -case 6: /* d(r) */ - adr = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - return (((R[reg] + adr) & 0177777) | dsenable); -case 7: /* @d(R) */ - adr = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - adr = ReadW (((R[reg] + adr) & 0177777) | dsenable); - return (adr | dsenable); - } /* end switch */ -} - -/* Effective address calculation for bytes */ - -int32 GeteaB (int32 spec) -{ -int32 adr, reg, ds, delta; - -reg = spec & 07; /* reg number */ -ds = (reg == 7)? isenable: dsenable; /* dspace if not PC */ -switch (spec >> 3) { /* decode spec<5:3> */ -default: /* can't get here */ -case 1: /* (R) */ - return (R[reg] | ds); -case 2: /* (R)+ */ - delta = 1 + (reg >= 6); /* 2 if R6, PC */ - R[reg] = ((adr = R[reg]) + delta) & 0177777; - if (update_MM) MMR1 = calc_MMR1 ((delta << 3) | reg); - return (adr | ds); -case 3: /* @(R)+ */ - R[reg] = ((adr = R[reg]) + 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (020 | reg); - adr = ReadW (adr | ds); - return (adr | dsenable); -case 4: /* -(R) */ - delta = 1 + (reg >= 6); /* 2 if R6, PC */ - adr = R[reg] = (R[reg] - delta) & 0177777; - if (update_MM) MMR1 = calc_MMR1 ((((-delta) & 037) << 3) | reg); - if ((adr < STKLIM) && (reg == 6) && (cm == MD_KER)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } - return (adr | ds); -case 5: /* @-(R) */ - adr = R[reg] = (R[reg] - 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (0360 | reg); - if ((adr < STKLIM) && (reg == 6) && (cm == MD_KER)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } - adr = ReadW (adr | ds); - return (adr | dsenable); -case 6: /* d(r) */ - adr = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - return (((R[reg] + adr) & 0177777) | dsenable); -case 7: /* @d(R) */ - adr = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - adr = ReadW (((R[reg] + adr) & 0177777) | dsenable); - return (adr | dsenable); - } /* end switch */ -} - -/* Read byte and word routines, read only and read-modify-write versions - - Inputs: - va = virtual address, <18:16> = mode, I/D space - Outputs: - data = data read from memory or I/O space -*/ - -int32 ReadW (int32 va) -{ -int32 pa, data; - -if (va & 1) { /* odd address? */ - setCPUERR (CPUE_ODD); - ABORT (TRAP_ODD); } -pa = relocR (va); /* relocate */ -if (ADDR_IS_MEM (pa)) return (M[pa >> 1]); /* memory address? */ -if (pa < IOPAGEBASE) { /* I/O address? */ - setCPUERR (CPUE_NXM); - ABORT (TRAP_NXM); } -if (iopageR (&data, pa, READ) != SCPE_OK) { /* invalid I/O addr? */ - setCPUERR (CPUE_TMO); - ABORT (TRAP_NXM); } -return data; -} - -int32 ReadB (int32 va) -{ -int32 pa, data; - -pa = relocR (va); /* relocate */ -if (ADDR_IS_MEM (pa)) return (va & 1? M[pa >> 1] >> 8: M[pa >> 1]) & 0377; -if (pa < IOPAGEBASE) { /* I/O address? */ - setCPUERR (CPUE_NXM); - ABORT (TRAP_NXM); } -if (iopageR (&data, pa, READ) != SCPE_OK) { /* invalid I/O addr? */ - setCPUERR (CPUE_TMO); - ABORT (TRAP_NXM); } -return ((va & 1)? data >> 8: data) & 0377; -} - -int32 ReadMW (int32 va) -{ -int32 data; - -if (va & 1) { /* odd address? */ - setCPUERR (CPUE_ODD); - ABORT (TRAP_ODD); } -last_pa = relocW (va); /* reloc, wrt chk */ -if (ADDR_IS_MEM (last_pa)) return (M[last_pa >> 1]); /* memory address? */ -if (last_pa < IOPAGEBASE) { /* I/O address? */ - setCPUERR (CPUE_NXM); - ABORT (TRAP_NXM); } -if (iopageR (&data, last_pa, READ) != SCPE_OK) { /* invalid I/O addr? */ - setCPUERR (CPUE_TMO); - ABORT (TRAP_NXM); } -return data; -} - -int32 ReadMB (int32 va) -{ -int32 data; - -last_pa = relocW (va); /* reloc, wrt chk */ -if (ADDR_IS_MEM (last_pa)) - return (va & 1? M[last_pa >> 1] >> 8: M[last_pa >> 1]) & 0377; -if (last_pa < IOPAGEBASE) { /* I/O address? */ - setCPUERR (CPUE_NXM); - ABORT (TRAP_NXM); } -if (iopageR (&data, last_pa, READ) != SCPE_OK) { /* invalid I/O addr? */ - setCPUERR (CPUE_TMO); - ABORT (TRAP_NXM); } -return ((va & 1)? data >> 8: data) & 0377; -} - -/* Write byte and word routines - - Inputs: - data = data to be written - va = virtual address, <18:16> = mode, I/D space, or - pa = physical address - Outputs: none -*/ - -void WriteW (int32 data, int32 va) -{ -int32 pa; - -if (va & 1) { /* odd address? */ - setCPUERR (CPUE_ODD); - ABORT (TRAP_ODD); } -pa = relocW (va); /* relocate */ -if (ADDR_IS_MEM (pa)) { /* memory address? */ - M[pa >> 1] = data; - return; } -if (pa < IOPAGEBASE) { /* I/O address? */ - setCPUERR (CPUE_NXM); - ABORT (TRAP_NXM); } -if (iopageW (data, pa, WRITE) != SCPE_OK) { /* invalid I/O addr? */ - setCPUERR (CPUE_TMO); - ABORT (TRAP_NXM); } -return; -} - -void WriteB (int32 data, int32 va) -{ -int32 pa; - -pa = relocW (va); /* relocate */ -if (ADDR_IS_MEM (pa)) { /* memory address? */ - if (va & 1) M[pa >> 1] = (M[pa >> 1] & 0377) | (data << 8); - else M[pa >> 1] = (M[pa >> 1] & ~0377) | data; - return; } -if (pa < IOPAGEBASE) { /* I/O address? */ - setCPUERR (CPUE_NXM); - ABORT (TRAP_NXM); } -if (iopageW (data, pa, WRITEB) != SCPE_OK) { /* invalid I/O addr? */ - setCPUERR (CPUE_TMO); - ABORT (TRAP_NXM); } -return; -} - -void PWriteW (int32 data, int32 pa) -{ -if (ADDR_IS_MEM (pa)) { /* memory address? */ - M[pa >> 1] = data; - return; } -if (pa < IOPAGEBASE) { /* I/O address? */ - setCPUERR (CPUE_NXM); - ABORT (TRAP_NXM); } -if (iopageW (data, pa, WRITE) != SCPE_OK) { /* invalid I/O addr? */ - setCPUERR (CPUE_TMO); - ABORT (TRAP_NXM); } -return; -} - -void PWriteB (int32 data, int32 pa) -{ -if (ADDR_IS_MEM (pa)) { /* memory address? */ - if (pa & 1) M[pa >> 1] = (M[pa >> 1] & 0377) | (data << 8); - else M[pa >> 1] = (M[pa >> 1] & ~0377) | data; - return; } -if (pa < IOPAGEBASE) { /* I/O address? */ - setCPUERR (CPUE_NXM); - ABORT (TRAP_NXM); } -if (iopageW (data, pa, WRITEB) != SCPE_OK) { /* invalid I/O addr? */ - setCPUERR (CPUE_TMO); - ABORT (TRAP_NXM); } -return; -} - -/* Relocate virtual address, read access - - Inputs: - va = virtual address, <18:16> = mode, I/D space - Outputs: - pa = physical address - On aborts, this routine aborts back to the top level simulator - with an appropriate trap code. - - Notes: - - APRFILE[UNUSED] is all zeroes, forcing non-resident abort - - Aborts must update MMR0<15:13,6:1> if updating is enabled -*/ - -int32 relocR (int32 va) -{ -int32 dbn, plf, apridx, apr, pa; - -if (MMR0 & MMR0_MME) { /* if mmgt */ - apridx = (va >> VA_V_APF) & 077; /* index into APR */ - apr = APRFILE[apridx]; /* with va<18:13> */ - dbn = va & VA_BN; /* extr block num */ - plf = (apr & PDR_PLF) >> 2; /* extr page length */ - if ((apr & PDR_PRD) == 0) { /* not readable? */ - if (update_MM) MMR0 = /* update MMR0 */ - (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); - MMR0 = MMR0 | MMR0_NR; /* err non-resident */ - ABORT (TRAP_MME); } /* abort ref */ - if ((apr & PDR_ED)? dbn < plf: dbn > plf) { /* if pg lnt error */ - if (update_MM) MMR0 = /* update MMR0 */ - (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); - MMR0 = MMR0 | MMR0_PL; - ABORT (TRAP_MME); } /* abort ref */ - pa = ((va & VA_DF) + ((apr >> 10) & 017777700)) & PAMASK; - if ((MMR3 & MMR3_M22E) == 0) { - pa = pa & 0777777; - if (pa >= 0760000) pa = 017000000 | pa; } } -else { pa = va & 0177777; /* mmgt off */ - if (pa >= 0160000) pa = 017600000 | pa; } -return pa; -} - -/* Relocate virtual address, write access - - Inputs: - va = virtual address, <18:16> = mode, I/D space - Outputs: - pa = physical address - On aborts, this routine aborts back to the top level simulator - with an appropriate trap code. - - Notes: - - APRFILE[UNUSED] is all zeroes, forcing non-resident abort - - Aborts must update MMR0<15:13,6:1> if updating is enabled -*/ - -int32 relocW (int32 va) -{ -int32 dbn, plf, apridx, apr, pa; - -if (MMR0 & MMR0_MME) { /* if mmgt */ - apridx = (va >> VA_V_APF) & 077; /* index into APR */ - apr = APRFILE[apridx]; /* with va<18:13> */ - dbn = va & VA_BN; /* extr block num */ - plf = (apr & PDR_PLF) >> 2; /* extr page length */ - if ((apr & PDR_PRD) == 0) { /* not readable? */ - if (update_MM) MMR0 = /* update MMR0 */ - (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); - MMR0 = MMR0 | MMR0_NR; /* err non-resident */ - ABORT (TRAP_MME); } /* abort ref */ - if ((apr & PDR_ED)? dbn < plf: dbn > plf) { /* if pg lnt error */ - if (update_MM) MMR0 = /* update MMR0 */ - (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); - MMR0 = MMR0 | MMR0_PL; - ABORT (TRAP_MME); } /* abort ref */ - if ((apr & PDR_PWR) == 0) { /* not writeable? */ - if (update_MM) MMR0 = /* update MMR0 */ - (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); - MMR0 = MMR0 | MMR0_RO; /* err read only */ - ABORT (TRAP_MME); } /* abort ref */ - APRFILE[apridx] = apr | PDR_W; /* set W */ - pa = ((va & VA_DF) + ((apr >> 10) & 017777700)) & PAMASK; - if ((MMR3 & MMR3_M22E) == 0) { - pa = pa & 0777777; - if (pa >= 0760000) pa = 017000000 | pa; } } -else { pa = va & 0177777; /* mmgt off */ - if (pa >= 0160000) pa = 017600000 | pa; } -return pa; -} - -/* Relocate virtual address, console access - - Inputs: - va = virtual address - sw = switches - Outputs: - pa = physical address - On aborts, this routine returns MAXMEMSIZE -*/ - -int32 relocC (int32 va, int32 sw) -{ -int32 mode, dbn, plf, apridx, apr, pa; - -if (MMR0 & MMR0_MME) { /* if mmgt */ - if (sw & SWMASK ('K')) mode = MD_KER; - else if (sw & SWMASK ('S')) mode = MD_SUP; - else if (sw & SWMASK ('U')) mode = MD_USR; - else if (sw & SWMASK ('P')) mode = (PSW >> PSW_V_PM) & 03; - else mode = (PSW >> PSW_V_CM) & 03; - va = va | ((sw & SWMASK ('D'))? calc_ds (mode): calc_is (mode)); - apridx = (va >> VA_V_APF) & 077; /* index into APR */ - apr = APRFILE[apridx]; /* with va<18:13> */ - dbn = va & VA_BN; /* extr block num */ - plf = (apr & PDR_PLF) >> 2; /* extr page length */ - if ((apr & PDR_PRD) == 0) return MAXMEMSIZE; /* not readable? */ - if ((apr & PDR_ED)? dbn < plf: dbn > plf) return MAXMEMSIZE; - pa = ((va & VA_DF) + ((apr >> 10) & 017777700)) & PAMASK; - if ((MMR3 & MMR3_M22E) == 0) { - pa = pa & 0777777; - if (pa >= 0760000) pa = 017000000 | pa; } } -else { pa = va & 0177777; /* mmgt off */ - if (pa >= 0160000) pa = 017600000 | pa; } -return pa; -} - -/* I/O page routines for CPU registers - - Switch register and memory management registers - - SR 17777570 read only - MMR0 17777572 read/write, certain bits unimplemented or read only - MMR1 17777574 read only - MMR2 17777576 read only - MMR3 17777516 read/write, certain bits unimplemented -*/ - -t_stat SR_MMR012_rd (int32 *data, int32 pa, int32 access) -{ -switch ((pa >> 1) & 3) { /* decode pa<2:1> */ -case 0: /* SR */ - *data = SR; - break; -case 1: /* MMR0 */ - *data = MMR0 & MMR0_IMP; - break; -case 2: /* MMR1 */ - *data = MMR1; - break; -case 3: /* MMR2 */ - *data = MMR2; - break; } /* end switch pa */ -return SCPE_OK; -} - -t_stat SR_MMR012_wr (int32 data, int32 pa, int32 access) -{ -switch ((pa >> 1) & 3) { /* decode pa<2:1> */ -case 0: /* DR */ - DR = data; - return SCPE_OK; -case 1: /* MMR0 */ - if (access == WRITEB) data = (pa & 1)? - (MMR0 & 0377) | (data << 8): (MMR0 & ~0377) | data; - MMR0 = (MMR0 & ~MMR0_RW) | (data & MMR0_RW); - return SCPE_OK; -default: /* MMR1, MMR2 */ - return SCPE_OK; } /* end switch pa */ -} - -t_stat MMR3_rd (int32 *data, int32 pa, int32 access) /* MMR3 */ -{ -*data = MMR3 & MMR3_IMP; -return SCPE_OK; -} - -t_stat MMR3_wr (int32 data, int32 pa, int32 access) /* MMR3 */ -{ -if (pa & 1) return SCPE_OK; -MMR3 = data & MMR3_RW; -if (cpu_unit.flags & UNIT_18B) - MMR3 = MMR3 & ~(MMR3_BME + MMR3_M22E); /* for UNIX V6 */ -cpu_bme = (MMR3 & MMR3_BME) && cpu_ubm; -dsenable = calc_ds (cm); -return SCPE_OK; -} - -/* PARs and PDRs. These are grouped in I/O space as follows: - - 17772200 - 17772276 supervisor block - 17772300 - 17772376 kernel block - 17777600 - 17777676 user block - - Within each block, the subblocks are I PDR's, D PDR's, I PAR's, D PAR's - - Thus, the algorithm for converting between I/O space addresses and - APRFILE indices is as follows: - - idx<3:0> = dspace'page = pa<4:1> - par = PDR vs PAR = pa<5> - idx<5:4> = ker/sup/user = pa<8>'~pa<6> - - Note that the W bit is read only; it is cleared by any write to an APR -*/ - -t_stat APR_rd (int32 *data, int32 pa, int32 access) -{ -t_stat left, idx; - -idx = (pa >> 1) & 017; /* dspace'page */ -left = (pa >> 5) & 1; /* PDR vs PAR */ -if ((pa & 0100) == 0) idx = idx | 020; /* 1 for super, user */ -if (pa & 0400) idx = idx | 040; /* 1 for user only */ -*data = left? (APRFILE[idx] >> 16) & 0177777: APRFILE[idx] & PDR_IMP; -return SCPE_OK; -} - -t_stat APR_wr (int32 data, int32 pa, int32 access) -{ -int32 left, idx, curr; - -idx = (pa >> 1) & 017; /* dspace'page */ -left = (pa >> 5) & 1; /* PDR vs PAR */ -if ((pa & 0100) == 0) idx = idx | 020; /* 1 for super, user */ -if (pa & 0400) idx = idx | 040; /* 1 for user only */ -curr = left? (APRFILE[idx] >> 16) & 0177777: APRFILE[idx] & PDR_IMP; -if (access == WRITEB) data = (pa & 1)? - (curr & 0377) | (data << 8): (curr & ~0377) | data; -if (left) APRFILE[idx] = - ((APRFILE[idx] & 0177777) | (((uint32) data) << 16)) & ~PDR_W; -else APRFILE[idx] = - ((APRFILE[idx] & ~PDR_RW) | (data & PDR_RW)) & ~PDR_W; -return SCPE_OK; -} - -/* CPU control registers - - MEMERR 17777744 read only, clear on write - CCR 17777746 read/write - MAINT 17777750 read only - HITMISS 17777752 read only - CPUERR 17777766 read only, clear on write - PIRQ 17777772 read/write, with side effects - PSW 17777776 read/write, with side effects -*/ - -t_stat CPU_rd (int32 *data, int32 pa, int32 access) -{ -switch ((pa >> 1) & 017) { /* decode pa<4:1> */ -case 2: /* MEMERR */ - *data = MEMERR; - return SCPE_OK; -case 3: /* CCR */ - *data = CCR; - return SCPE_OK; -case 4: /* MAINT */ - if (cpu_ubm) *data = MAINT | MAINT_U; - else *data = MAINT & ~MAINT_U; - return SCPE_OK; -case 5: /* Hit/miss */ - *data = HITMISS; - return SCPE_OK; -case 013: /* CPUERR */ - *data = CPUERR & CPUE_IMP; - return SCPE_OK; -case 015: /* PIRQ */ - *data = PIRQ; - return SCPE_OK; -case 017: /* PSW */ - if (access == READC) *data = PSW; - else *data = (cm << PSW_V_CM) | (pm << PSW_V_PM) | (rs << PSW_V_RS) | - (ipl << PSW_V_IPL) | (tbit << PSW_V_TBIT) | - (N << PSW_V_N) | (Z << PSW_V_Z) | - (V << PSW_V_V) | (C << PSW_V_C); - return SCPE_OK; } /* end switch PA */ -return SCPE_NXM; /* unimplemented */ -} - -/* CPU control registers, continued */ - -t_stat CPU_wr (int32 data, int32 pa, int32 access) -{ -int32 i, pl, curr, oldrs; - -switch ((pa >> 1) & 017) { /* decode pa<4:1> */ -case 2: /* MEMERR */ - MEMERR = 0; - return SCPE_OK; -case 3: /* CCR */ - if (access == WRITEB) data = (pa & 1)? - (CCR & 0377) | (data << 8): (CCR & ~0377) | data; - CCR = data; - return SCPE_OK; -case 4: /* MAINT */ - return SCPE_OK; -case 5: /* Hit/miss */ - return SCPE_OK; -case 013: /* CPUERR */ - CPUERR = 0; - return SCPE_OK; -case 015: /* PIRQ */ - if (access == WRITEB) { - if (pa & 1) data = data << 8; - else return SCPE_OK; } - PIRQ = data & PIRQ_RW; - pl = 0; - if (PIRQ & PIRQ_PIR1) { SET_INT (PIR1); pl = 0042; } - else CLR_INT (PIR1); - if (PIRQ & PIRQ_PIR2) { SET_INT (PIR2); pl = 0104; } - else CLR_INT (PIR2); - if (PIRQ & PIRQ_PIR3) { SET_INT (PIR3); pl = 0146; } - else CLR_INT (PIR3); - if (PIRQ & PIRQ_PIR4) { SET_INT (PIR4); pl = 0210; } - else CLR_INT (PIR4); - if (PIRQ & PIRQ_PIR5) { SET_INT (PIR5); pl = 0252; } - else CLR_INT (PIR5); - if (PIRQ & PIRQ_PIR6) { SET_INT (PIR6); pl = 0314; } - else CLR_INT (PIR6); - if (PIRQ & PIRQ_PIR7) { SET_INT (PIR7); pl = 0356; } - else CLR_INT (PIR7); - PIRQ = PIRQ | pl; - return SCPE_OK; - -/* CPU control registers, continued - - Note: Explicit writes to the PSW do not modify the T bit -*/ - -case 017: /* PSW */ - if (access == WRITEC) { /* console access? */ - PSW = data & PSW_RW; - return SCPE_OK; } - curr = (cm << PSW_V_CM) | (pm << PSW_V_PM) | (rs << PSW_V_RS) | - (ipl << PSW_V_IPL) | (tbit << PSW_V_TBIT) | - (N << PSW_V_N) | (Z << PSW_V_Z) | - (V << PSW_V_V) | (C << PSW_V_C); - STACKFILE[cm] = SP; - if (access == WRITEB) data = (pa & 1)? - (curr & 0377) | (data << 8): (curr & ~0377) | data; - curr = (curr & ~PSW_RW) | (data & PSW_RW); - oldrs = rs; - cm = (curr >> PSW_V_CM) & 03; /* call calc_is,ds */ - pm = (curr >> PSW_V_PM) & 03; - rs = (curr >> PSW_V_RS) & 01; - ipl = (curr >> PSW_V_IPL) & 07; - N = (curr >> PSW_V_N) & 01; - Z = (curr >> PSW_V_Z) & 01; - V = (curr >> PSW_V_V) & 01; - C = (curr >> PSW_V_C) & 01; - if (rs != oldrs) { - for (i = 0; i < 6; i++) { - REGFILE[i][oldrs] = R[i]; - R[i] = REGFILE[i][rs]; } } - SP = STACKFILE[cm]; - isenable = calc_is (cm); - dsenable = calc_ds (cm); - return SCPE_OK; } /* end switch pa */ -return SCPE_NXM; /* unimplemented */ -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -int32 i; - -PIRQ = MMR0 = MMR1 = MMR2 = MMR3 = 0; -cpu_bme = 0; -DR = CPUERR = MEMERR = CCR = HITMISS = 0; -PSW = 000340; -trap_req = 0; -wait_state = 0; -if (M == NULL) M = calloc (MEMSIZE >> 1, sizeof (unsigned int16)); -if (M == NULL) return SCPE_MEM; -pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -for (i = 0; i < UBM_LNT_LW; i++) ub_map[i] = 0; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -set_r_display (0, MD_KER); -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -int32 iodata; -t_stat stat; - -if (vptr == NULL) return SCPE_ARG; -if (sw & SWMASK ('V')) { /* -v */ - if (addr >= VASIZE) return SCPE_NXM; - addr = relocC (addr, sw); /* relocate */ - if (addr >= MAXMEMSIZE) return SCPE_REL; } -if (addr < MEMSIZE) { - *vptr = M[addr >> 1] & 0177777; - return SCPE_OK; } -if (addr < IOPAGEBASE) return SCPE_NXM; -stat = iopageR (&iodata, addr, READC); -*vptr = iodata; -return stat; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -if (sw & SWMASK ('V')) { /* -v */ - if (addr >= VASIZE) return SCPE_NXM; - addr = relocC (addr, sw); /* relocate */ - if (addr >= MAXMEMSIZE) return SCPE_REL; } -if (addr < MEMSIZE) { - M[addr >> 1] = val & 0177777; - return SCPE_OK; } -if (addr < IOPAGEBASE) return SCPE_NXM; -return iopageW ((int32) val, addr, WRITEC); -} - -/* Memory allocation */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i, clim; -unsigned int16 *nM; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i = i + 2) mc = mc | M[i >> 1]; -if ((mc != 0) && !get_yn ("Really truncate memory [N]?", FALSE)) - return SCPE_OK; -nM = calloc (val >> 1, sizeof (unsigned int16)); -if (nM == NULL) return SCPE_MEM; -clim = (((t_addr) val) < MEMSIZE)? val: MEMSIZE; -for (i = 0; i < clim; i = i + 2) nM[i >> 1] = M[i >> 1]; -free (M); -M = nM; -MEMSIZE = val; -return cpu_set_bus (uptr, (cpu_unit.flags & UNIT_MAP) | 1, cptr, desc); } - -/* Bus configuration, disable Unibus or Qbus devices */ - -t_stat cpu_set_bus (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; -uint32 i, target; - -if ((MEMSIZE <= UNIMEMSIZE) || (val & UNIT_18B) || - (!(val & 1) && ((uint32) val == (cpu_unit.flags & UNIT_MAP)))) return SCPE_OK; -if (val & UNIT_MAP) target = DEV_QBUS; /* going to Ubus? */ -else target = DEV_UBUS; /* going to Qbus */ -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { - if ((dptr->flags & DEV_DISABLE) && /* disable-able? */ - !(dptr->flags & DEV_DIS) && /* enabled? */ - ((dptr->flags & (DEV_QBUS|DEV_UBUS)) == target)) { - printf ("Disabling %s\n", sim_dname (dptr)); - if (sim_log) fprintf (sim_log, "Disabling %s\n", sim_dname (dptr)); - dptr->flags = dptr->flags | DEV_DIS; } } -return SCPE_OK; -} - -/* Set R, SP register display addresses */ - -void set_r_display (int32 rs, int32 cm) -{ -extern REG *find_reg (char *cptr, char **optr, DEVICE *dptr); -REG *rptr; -int32 i; - -rptr = find_reg ("R0", NULL, &cpu_dev); -if (rptr == NULL) return; -for (i = 0; i < 6; i++, rptr++) rptr->loc = (void *) ®FILE[i][rs]; -rptr->loc = (void *) &STACKFILE[cm]; -return; -} diff --git a/PDP11/pdp11_defs.h b/PDP11/pdp11_defs.h deleted file mode 100644 index 2c460e80..00000000 --- a/PDP11/pdp11_defs.h +++ /dev/null @@ -1,593 +0,0 @@ -/* pdp11_defs.h: PDP-11 simulator definitions - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - The author gratefully acknowledges the help of Max Burnet, Megan Gentry, - and John Wilson in resolving questions about the PDP-11 - - 19-May-03 RMS Revised for new conditional compilation - 05-Apr-03 RMS Fixed bug in MMR1 update (found by Tim Stark) - 28-Feb-03 RMS Added TM logging support - 19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict - 11-Nov-02 RMS Changed log definitions to be VAX compatible - 10-Oct-02 RMS Added vector information to DIB - Changed DZ11 vector to Unibus standard - Added DEQNA/DELQA, DEUNA/DELUA support - Added multiple RQDX3, autoconfigure support - 12-Sep-02 RMS Added TMSCP, KW11P,and RX211 support - 28-Apr-02 RMS Clarified PDF ACF mnemonics - 22-Apr-02 RMS Added HTRAP, BPOK maint register flags, MT_MAXFR - 06-Mar-02 RMS Changed system type to KDJ11A - 20-Jan-02 RMS Added multiboard DZ11 support - 09-Nov-01 RMS Added bus map support - 07-Nov-01 RMS Added RQDX3 support - 26-Oct-01 RMS Added symbolic definitions for IO page - 19-Oct-01 RMS Added DZ definitions - 15-Oct-01 RMS Added logging capabilities - 07-Sep-01 RMS Revised for multilevel interrupts - 01-Jun-01 RMS Added DZ11 support - 23-Apr-01 RMS Added RK611 support - 05-Apr-01 RMS Added TS11/TSV05 support - 10-Feb-01 RMS Added DECtape support -*/ - -#ifndef _PDP11_DEFS_H -#define _PDP11_DEFS_H 0 - -#ifndef VM_PDP11 -#define VM_PDP11 0 -#endif - -#include "sim_defs.h" /* simulator defns */ -#include - -/* Architectural constants */ - -#define STKLIM 0400 /* stack limit */ -#define VASIZE 0200000 /* 2**16 */ -#define VAMASK (VASIZE - 1) /* 2**16 - 1 */ -#define INIMEMSIZE 001000000 /* 2**18 */ -#define UNIMEMSIZE 001000000 /* 2**18 */ -#define UNIMASK (UNIMEMSIZE - 1) /* 2**18 - 1 */ -#define IOPAGEBASE 017760000 /* 2**22 - 2**13 */ -#define MAXMEMSIZE 020000000 /* 2**22 */ -#define PAMASK (MAXMEMSIZE - 1) /* 2**22 - 1 */ -#define MEMSIZE (cpu_unit.capac) -#define ADDR_IS_MEM(x) (((t_addr) (x)) < MEMSIZE) -#define DMASK 0177777 - -/* Protection modes */ - -#define MD_KER 0 -#define MD_SUP 1 -#define MD_UND 2 -#define MD_USR 3 - -/* I/O access modes */ - -#define READ 0 -#define READC 1 /* read console */ -#define WRITE 2 -#define WRITEC 3 /* write console */ -#define WRITEB 4 - -/* PSW */ - -#define PSW_V_C 0 /* condition codes */ -#define PSW_V_V 1 -#define PSW_V_Z 2 -#define PSW_V_N 3 -#define PSW_V_TBIT 4 /* trace trap */ -#define PSW_V_IPL 5 /* int priority */ -#define PSW_V_RS 11 /* register set */ -#define PSW_V_PM 12 /* previous mode */ -#define PSW_V_CM 14 /* current mode */ -#define PSW_RW 0174357 /* read/write bits */ - -/* FPS */ - -#define FPS_V_C 0 /* condition codes */ -#define FPS_V_V 1 -#define FPS_V_Z 2 -#define FPS_V_N 3 -#define FPS_V_T 5 /* truncate */ -#define FPS_V_L 6 /* long */ -#define FPS_V_D 7 /* double */ -#define FPS_V_IC 8 /* ic err int */ -#define FPS_V_IV 9 /* overflo err int */ -#define FPS_V_IU 10 /* underflo err int */ -#define FPS_V_IUV 11 /* undef var err int */ -#define FPS_V_ID 14 /* int disable */ -#define FPS_V_ER 15 /* error */ - -/* PIRQ */ - -#define PIRQ_PIR1 0001000 -#define PIRQ_PIR2 0002000 -#define PIRQ_PIR3 0004000 -#define PIRQ_PIR4 0010000 -#define PIRQ_PIR5 0020000 -#define PIRQ_PIR6 0040000 -#define PIRQ_PIR7 0100000 -#define PIRQ_IMP 0177356 /* implemented bits */ -#define PIRQ_RW 0177000 /* read/write bits */ - -/* MMR0 */ - -#define MMR0_MME 0000001 /* mem mgt enable */ -#define MMR0_V_PAGE 1 /* offset to pageno */ -#define MMR0_M_PAGE 077 /* mask for pageno */ -#define MMR0_PAGE (MMR0_M_PAGE << MMR0_V_PAGE) -#define MMR0_RO 0020000 /* read only error */ -#define MMR0_PL 0040000 /* page lnt error */ -#define MMR0_NR 0100000 /* no access error */ -#define MMR0_FREEZE 0160000 /* if set, no update */ -#define MMR0_IMP 0160177 /* implemented bits */ -#define MMR0_RW 0160001 /* read/write bits */ - -/* MMR3 */ - -#define MMR3_UDS 001 /* user dspace enbl */ -#define MMR3_SDS 002 /* super dspace enbl */ -#define MMR3_KDS 004 /* krnl dspace enbl */ -#define MMR3_CSM 010 /* CSM enable */ -#define MMR3_M22E 020 /* 22b mem mgt enbl */ -#define MMR3_BME 040 /* DMA bus map enbl */ -#define MMR3_IMP 077 /* implemented bits */ -#define MMR3_RW 077 /* read/write bits */ - -/* PDR */ - -#define PDR_PRD 0000002 /* page readable */ -#define PDR_PWR 0000004 /* page writeable */ -#define PDR_ED 0000010 /* expansion dir */ -#define PDR_W 0000100 /* written flag */ -#define PDR_PLF 0077400 /* page lnt field */ -#define PDR_IMP 0177516 /* implemented bits */ -#define PDR_RW 0177416 /* read/write bits */ - -/* Virtual address */ - -#define VA_DF 0017777 /* displacement */ -#define VA_BN 0017700 /* block number */ -#define VA_V_APF 13 /* offset to APF */ -#define VA_V_DS 16 /* offset to space */ -#define VA_V_MODE 17 /* offset to mode */ -#define VA_DS (1u << VA_V_DS) /* data space flag */ - -/* Unibus map (if present) */ - -#define UBM_LNT_LW 32 /* size in LW */ -#define UBM_V_PN 13 /* page number */ -#define UBM_M_PN 037 -#define UBM_V_OFF 0 /* offset */ -#define UBM_M_OFF 017777 -#define UBM_GETPN(x) (((x) >> UBM_V_PN) & UBM_M_PN) -#define UBM_GETOFF(x) ((x) & UBM_M_OFF) - -/* CPUERR */ - -#define CPUE_RED 0004 /* red stack */ -#define CPUE_YEL 0010 /* yellow stack */ -#define CPUE_TMO 0020 /* IO page nxm */ -#define CPUE_NXM 0040 /* memory nxm */ -#define CPUE_ODD 0100 /* odd address */ -#define CPUE_HALT 0200 /* HALT not kernel */ -#define CPUE_IMP 0374 /* implemented bits */ - -/* Maintenance register */ - -#define MAINT_V_UQ 9 /* Q/U flag */ -#define MAINT_Q (0 << MAINT_V_UQ) /* Qbus */ -#define MAINT_U (1 << MAINT_V_UQ) -#define MAINT_V_FPA 8 /* FPA flag */ -#define MAINT_NOFPA (0 << MAINT_V_FPA) -#define MAINT_FPA (1 << MAINT_V_FPA) -#define MAINT_V_TYP 4 /* system type */ -#define MAINT_KDJ (1 << MAINT_V_TYP) /* KDJ11A */ -#define MAINT_V_HTRAP 3 /* trap 4 on HALT */ -#define MAINT_HTRAP (1 << MAINT_V_HTRAP) -#define MAINT_V_BPOK 0 /* power OK */ -#define MAINT_BPOK (1 << MAINT_V_BPOK) - -/* Floating point accumulators */ - -struct fpac { - unsigned int32 l; /* low 32b */ - unsigned int32 h; /* high 32b */ -}; -typedef struct fpac fpac_t; - -/* Device CSRs */ - -#define CSR_V_GO 0 /* go */ -#define CSR_V_IE 6 /* interrupt enable */ -#define CSR_V_DONE 7 /* done */ -#define CSR_V_BUSY 11 /* busy */ -#define CSR_V_ERR 15 /* error */ -#define CSR_GO (1u << CSR_V_GO) -#define CSR_IE (1u << CSR_V_IE) -#define CSR_DONE (1u << CSR_V_DONE) -#define CSR_BUSY (1u << CSR_V_BUSY) -#define CSR_ERR (1u << CSR_V_ERR) - -/* Trap masks, descending priority order, following J-11 - An interrupt summary bit is kept with traps, to minimize overhead -*/ - -#define TRAP_V_RED 0 /* red stk abort 4 */ -#define TRAP_V_ODD 1 /* odd address 4 */ -#define TRAP_V_MME 2 /* mem mgt 250 */ -#define TRAP_V_NXM 3 /* nx memory 4 */ -#define TRAP_V_PAR 4 /* parity err 114 */ -#define TRAP_V_PRV 5 /* priv inst 4 */ -#define TRAP_V_ILL 6 /* illegal inst 10 */ -#define TRAP_V_BPT 7 /* BPT 14 */ -#define TRAP_V_IOT 8 /* IOT 20 */ -#define TRAP_V_EMT 9 /* EMT 30 */ -#define TRAP_V_TRAP 10 /* TRAP 34 */ -#define TRAP_V_TRC 11 /* T bit 14 */ -#define TRAP_V_YEL 12 /* stack 4 */ -#define TRAP_V_PWRFL 13 /* power fail 24 */ -#define TRAP_V_FPE 14 /* fpe 244 */ -#define TRAP_V_MAX 15 /* intr = max trp # */ -#define TRAP_RED (1u << TRAP_V_RED) -#define TRAP_ODD (1u << TRAP_V_ODD) -#define TRAP_MME (1u << TRAP_V_MME) -#define TRAP_NXM (1u << TRAP_V_NXM) -#define TRAP_PAR (1u << TRAP_V_PAR) -#define TRAP_PRV (1u << TRAP_V_PRV) -#define TRAP_ILL (1u << TRAP_V_ILL) -#define TRAP_BPT (1u << TRAP_V_BPT) -#define TRAP_IOT (1u << TRAP_V_IOT) -#define TRAP_EMT (1u << TRAP_V_EMT) -#define TRAP_TRAP (1u << TRAP_V_TRAP) -#define TRAP_TRC (1u << TRAP_V_TRC) -#define TRAP_YEL (1u << TRAP_V_YEL) -#define TRAP_PWRFL (1u << TRAP_V_PWRFL) -#define TRAP_FPE (1u << TRAP_V_FPE) -#define TRAP_INT (1u << TRAP_V_MAX) -#define TRAP_ALL ((1u << TRAP_V_MAX) - 1) /* all traps */ - -#define VEC_RED 0004 /* trap vectors */ -#define VEC_ODD 0004 -#define VEC_MME 0250 -#define VEC_NXM 0004 -#define VEC_PAR 0114 -#define VEC_PRV 0004 -#define VEC_ILL 0010 -#define VEC_BPT 0014 -#define VEC_IOT 0020 -#define VEC_EMT 0030 -#define VEC_TRAP 0034 -#define VEC_TRC 0014 -#define VEC_YEL 0004 -#define VEC_PWRFL 0024 -#define VEC_FPE 0244 - -/* Simulator stop codes; codes 1:TRAP_V_MAX correspond to traps 0:TRAPMAX-1 */ - -#define STOP_HALT (TRAP_V_MAX + 1) /* HALT instruction */ -#define STOP_IBKPT (TRAP_V_MAX + 2) /* instruction bkpt */ -#define STOP_WAIT (TRAP_V_MAX + 3) /* wait, no events */ -#define STOP_VECABORT (TRAP_V_MAX + 4) /* abort vector read */ -#define STOP_SPABORT (TRAP_V_MAX + 5) /* abort trap push */ -#define STOP_RQ (TRAP_V_MAX + 6) /* RQDX3 panic */ -#define STOP_SANITY (TRAP_V_MAX + 7) /* sanity timer exp */ -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ - -/* Timers */ - -#define TMR_CLK 0 /* line clock */ -#define TMR_PCLK 1 /* KW11P */ - -/* IO parameters */ - -#define DZ_MUXES 4 /* max # of muxes */ -#define DZ_LINES 8 /* lines per mux */ -#define MT_MAXFR (1 << 16) /* magtape max rec */ -#define AUTO_LNT 34 /* autoconfig ranks */ -#define DIB_MAX 100 /* max DIBs */ - -#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ -#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */ -#define DEV_V_FLTA (DEV_V_UF + 2) /* flt addr */ -#define DEV_UBUS (1u << DEV_V_UBUS) -#define DEV_QBUS (1u << DEV_V_QBUS) -#define DEV_FLTA (1u << DEV_V_FLTA) - -#define UNIBUS (cpu_18b || cpu_ubm) /* T if 18b */ - -#define MAP 1 /* mapped */ -#define NOMAP 0 /* not mapped */ - -#define DEV_RDX 8 /* default device radix */ - -/* Device information block */ - -#define VEC_DEVMAX 4 /* max device vec */ - -struct pdp_dib { - uint32 ba; /* base addr */ - uint32 lnt; /* length */ - t_stat (*rd)(int32 *dat, int32 ad, int32 md); - t_stat (*wr)(int32 dat, int32 ad, int32 md); - int32 vnum; /* vectors: number */ - int32 vloc; /* locator */ - int32 vec; /* value */ - int32 (*ack[VEC_DEVMAX])(void); /* ack routines */ -}; - -typedef struct pdp_dib DIB; - -/* I/O page layout - RQB,RQC,RQD float based on number of DZ's */ - -#define IOBA_DZ (IOPAGEBASE + 000100) /* DZ11 */ -#define IOLN_DZ 010 -#define IOBA_RQB (IOPAGEBASE + 000334 + (020 * (DZ_MUXES / 2))) -#define IOLN_RQB 004 -#define IOBA_RQC (IOPAGEBASE + IOBA_RQB + IOLN_RQB) -#define IOLN_RQC 004 -#define IOBA_RQD (IOPAGEBASE + IOBA_RQC + IOLN_RQC) -#define IOLN_RQD 004 -#define IOBA_UBM (IOPAGEBASE + 010200) /* Unibus map */ -#define IOLN_UBM (UBM_LNT_LW * sizeof (int32)) -#define IOBA_RQ (IOPAGEBASE + 012150) /* RQDX3 */ -#define IOLN_RQ 004 -#define IOBA_APR (IOPAGEBASE + 012200) /* APRs */ -#define IOLN_APR 0200 -#define IOBA_MMR3 (IOPAGEBASE + 012516) /* MMR3 */ -#define IOLN_MMR3 002 -#define IOBA_TM (IOPAGEBASE + 012520) /* TM11 */ -#define IOLN_TM 014 -#define IOBA_TS (IOPAGEBASE + 012520) /* TS11 */ -#define IOLN_TS 004 -#define IOBA_PCLK (IOPAGEBASE + 012540) /* KW11P */ -#define IOLN_PCLK 006 -#define IOBA_RL (IOPAGEBASE + 014400) /* RL11 */ -#define IOLN_RL 012 -#define IOBA_XQ (IOPAGEBASE + 014440) /* DEQNA/DELQA */ -#define IOLN_XQ 020 -#define IOBA_XQB (IOPAGEBASE + 014460) /* 2nd DEQNA/DELQA */ -#define IOLN_XQB 020 -#define IOBA_TQ (IOPAGEBASE + 014500) /* TMSCP */ -#define IOLN_TQ 004 -#define IOBA_XU (IOPAGEBASE + 014510) /* DEUNA/DELUA */ -#define IOLN_XU 010 -#define IOBA_RP (IOPAGEBASE + 016700) /* RP/RM */ -#define IOLN_RP 054 -#define IOBA_RX (IOPAGEBASE + 017170) /* RX11 */ -#define IOLN_RX 004 -#define IOBA_RY (IOPAGEBASE + 017170) /* RY11 */ -#define IOLN_RY 004 -#define IOBA_TC (IOPAGEBASE + 017340) /* TC11 */ -#define IOLN_TC 012 -#define IOBA_RK (IOPAGEBASE + 017400) /* RK11 */ -#define IOLN_RK 020 -#define IOBA_HK (IOPAGEBASE + 017440) /* RK611 */ -#define IOLN_HK 040 -#define IOBA_LPT (IOPAGEBASE + 017514) /* LP11 */ -#define IOLN_LPT 004 -#define IOBA_CLK (IOPAGEBASE + 017546) /* KW11L */ -#define IOLN_CLK 002 -#define IOBA_PTR (IOPAGEBASE + 017550) /* PC11 reader */ -#define IOLN_PTR 004 -#define IOBA_PTP (IOPAGEBASE + 017554) /* PC11 punch */ -#define IOLN_PTP 004 -#define IOBA_TTI (IOPAGEBASE + 017560) /* DL11 rcv */ -#define IOLN_TTI 004 -#define IOBA_TTO (IOPAGEBASE + 017564) /* DL11 xmt */ -#define IOLN_TTO 004 -#define IOBA_SRMM (IOPAGEBASE + 017570) /* SR, MMR0-2 */ -#define IOLN_SRMM 010 -#define IOBA_APR1 (IOPAGEBASE + 017600) /* APRs */ -#define IOLN_APR1 0100 -#define IOBA_CPU (IOPAGEBASE + 017740) /* CPU reg */ -#define IOLN_CPU 040 - -/* Interrupt assignments; within each level, priority is right to left */ - -#define IPL_HLVL 8 /* # int levels */ - -#define INT_V_PIR7 0 /* BR7 */ - -#define INT_V_CLK 0 /* BR6 */ -#define INT_V_PCLK 1 -#define INT_V_DTA 2 -#define INT_V_PIR6 3 - -#define INT_V_RK 0 /* BR5 */ -#define INT_V_RL 1 -#define INT_V_RX 2 -#define INT_V_TM 3 -#define INT_V_RP 4 -#define INT_V_TS 5 -#define INT_V_HK 6 -#define INT_V_RQ 7 -#define INT_V_DZRX 8 -#define INT_V_DZTX 9 -#define INT_V_TQ 10 -#define INT_V_RY 11 -#define INT_V_XQ 12 -#define INT_V_XU 13 -#define INT_V_PIR5 14 - -#define INT_V_TTI 0 /* BR4 */ -#define INT_V_TTO 1 -#define INT_V_PTR 2 -#define INT_V_PTP 3 -#define INT_V_LPT 4 -#define INT_V_PIR4 5 - -#define INT_V_PIR3 0 /* BR3 */ -#define INT_V_PIR2 0 /* BR2 */ -#define INT_V_PIR1 0 /* BR1 */ - -#define INT_PIR7 (1u << INT_V_PIR7) -#define INT_CLK (1u << INT_V_CLK) -#define INT_PCLK (1u << INT_V_PCLK) -#define INT_DTA (1u << INT_V_DTA) -#define INT_PIR6 (1u << INT_V_PIR6) -#define INT_RK (1u << INT_V_RK) -#define INT_RL (1u << INT_V_RL) -#define INT_RX (1u << INT_V_RX) -#define INT_TM (1u << INT_V_TM) -#define INT_RP (1u << INT_V_RP) -#define INT_TS (1u << INT_V_TS) -#define INT_HK (1u << INT_V_HK) -#define INT_RQ (1u << INT_V_RQ) -#define INT_DZRX (1u << INT_V_DZRX) -#define INT_DZTX (1u << INT_V_DZTX) -#define INT_TQ (1u << INT_V_TQ) -#define INT_RY (1u << INT_V_RY) -#define INT_XQ (1u << INT_V_XQ) -#define INT_XU (1u << INT_V_XU) -#define INT_PIR5 (1u << INT_V_PIR5) -#define INT_PTR (1u << INT_V_PTR) -#define INT_PTP (1u << INT_V_PTP) -#define INT_TTI (1u << INT_V_TTI) -#define INT_TTO (1u << INT_V_TTO) -#define INT_LPT (1u << INT_V_LPT) -#define INT_PIR4 (1u << INT_V_PIR4) -#define INT_PIR3 (1u << INT_V_PIR3) -#define INT_PIR2 (1u << INT_V_PIR2) -#define INT_PIR1 (1u << INT_V_PIR1) - -#define IPL_CLK 6 /* int pri levels */ -#define IPL_PCLK 6 -#define IPL_DTA 6 -#define IPL_RK 5 -#define IPL_RL 5 -#define IPL_RX 5 -#define IPL_TM 5 -#define IPL_RP 5 -#define IPL_TS 5 -#define IPL_HK 5 -#define IPL_RQ 5 -#define IPL_DZRX 5 -#define IPL_DZTX 5 -#define IPL_TQ 5 -#define IPL_RY 5 -#define IPL_XQ 5 -#define IPL_XU 5 -#define IPL_PTR 4 -#define IPL_PTP 4 -#define IPL_TTI 4 -#define IPL_TTO 4 -#define IPL_LPT 4 - -#define IPL_PIR7 7 -#define IPL_PIR6 6 -#define IPL_PIR5 5 -#define IPL_PIR4 4 -#define IPL_PIR3 3 -#define IPL_PIR2 2 -#define IPL_PIR1 1 - -/* Device vectors */ - -#define VEC_Q 0000 /* vector base */ -#define VEC_PIRQ 0240 -#define VEC_TTI 0060 -#define VEC_TTO 0064 -#define VEC_PTR 0070 -#define VEC_PTP 0074 -#define VEC_CLK 0100 -#define VEC_PCLK 0104 -#define VEC_XQ 0120 -#define VEC_XU 0120 -#define VEC_RQ 0154 -#define VEC_RL 0160 -#define VEC_LPT 0200 -#define VEC_HK 0210 -#define VEC_RK 0220 -#define VEC_DTA 0214 -#define VEC_TM 0224 -#define VEC_TS 0224 -#define VEC_RP 0254 -#define VEC_TQ 0260 -#define VEC_RX 0264 -#define VEC_RY 0264 -#define VEC_DZRX 0300 -#define VEC_DZTX 0304 - -/* Autoconfigure ranks */ - -#define RANK_DZ 8 -#define RANK_RL 14 -#define RANK_RX 18 -#define RANK_XU 25 -#define RANK_RQ 26 -#define RANK_TQ 30 - -/* Interrupt macros */ - -#define IVCL(dv) ((IPL_##dv * 32) + INT_V_##dv) -#define IREQ(dv) int_req[IPL_##dv] -#define SET_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] | (INT_##dv) -#define CLR_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] & ~(INT_##dv) - -/* CPU and FPU macros */ - -#define update_MM ((MMR0 & MMR0_FREEZE) == 0) -#define setTRAP(name) trap_req = trap_req | (name) -#define setCPUERR(name) CPUERR = CPUERR | (name) -#define ABORT(val) longjmp (save_env, (val)) -#define SP R[6] -#define PC R[7] - -/* Logging */ - -#define LOG_CPU_I 0x0001 -#define LOG_TM 0x0008 -#define LOG_RP 0x0010 -#define LOG_TS 0x0020 -#define LOG_RQ 0x0040 -#define LOG_TQ 0x0080 -#define LOG_XQ0 0x0100 -#define LOG_XQ1 0x0200 -#define LOG_XQ2 0x0400 -#define LOG_XQ3 0x0800 -#define LOG_TC_MS 0x1000 -#define LOG_TC_RW 0x2000 -#define LOG_TC_BL 0x4000 -#define LOG_HK 0x8000 - -#define DBG_LOG(x) (sim_log && (cpu_log & (x))) - -/* Function prototypes */ - -t_bool Map_Addr (uint32 qa, uint32 *ma); -int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf, t_bool map); -int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf, t_bool map); -int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf, t_bool map); -int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf, t_bool map); -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat set_vec (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_vec (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat auto_config (uint32 rank, uint32 num); - -#endif diff --git a/PDP11/pdp11_doc.txt b/PDP11/pdp11_doc.txt deleted file mode 100644 index 1acebe08..00000000 --- a/PDP11/pdp11_doc.txt +++ /dev/null @@ -1,1330 +0,0 @@ -To: Users -From: Bob Supnik -Subj: PDP-11 Simulator Usage -Date: 15-Sep-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - Original code published in 1993-2003, written by Robert M Supnik - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - -This memorandum documents the PDP-11 simulator. - - -1. Simulator Files - -To compile the PDP-11, you must define VM_PDP11 as part of the compilation -command line. If you want expanded file support, you must also define USE_INT64 -and USE_ADDR64 as part of the compilation command line. - -sim/ sim_defs.h - sim_ether.h - sim_rev.h - sim_sock.h - sim_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_ether.c - sim_sock.c - sim_tape.c - sim_tmxr.c - -sim/pdp11/ pdp11_defs.h - pdp11_mscp.h - pdp11_uqssp.h - pdp11_xq.h - pdp11_xq_bootrom.h - pdp11_cpu.c - pdp11_dz.c - pdp11_fp.c - pdp11_hk.c - pdp11_io.c - pdp11_lp.c - pdp11_pclk.c - pdp11_pt.c - pdp11_rk.c - pdp11_rl.c - pdp11_rp.c - pdp11_rq.c - pdp11_tq.c - pdp11_rx.c - pdp11_ry.c - pdp11_stddev.c - pdp11_sys.c - pdp11_tc.c - pdp11_tm.c - pdp11_ts.c - pdp11_xq.c - pdp11_xu.c - -2. PDP-11 Features - -The PDP-11 simulator is configured as follows: - -device simulates -name(s) - -CPU J-11 CPU with 256KB of memory -- FP11 floating point unit (FPA) -- CIS11 commercial instruction set (CIS, off by default) -PTR,PTP PC11 paper tape reader/punch -TTI,TTO DL11 console terminal -LPT LP11 line printer -CLK line frequency clock -PCLK KW11P programmable clock -DZ DZ11 8-line terminal multiplexor (up to 4) -RK RK11/RK05 cartridge disk controller with eight drives -HK RK611/RK06(7) cartridge disk controller with eight drives -RL RLV12/RL01(2) cartridge disk controller with four drives -RP RM02/03/05/80, RP04/05/06/07 Massbus style controller - with eight drives -RQ RQDX3 MSCP controller with four drives -RQB second RQDX3 MSCP controller with four drives -RQC third RQDX3 MSCP controller with four drives -RQD fourth RQDX3 MSCP controller with four drives -RX RX11/RX01 floppy disk controller with two drives -RY RX211/RX01 floppy disk controller with two drives -TC TC11/TU56 DECtape controller with eight drives -TM TM11/TU10 magnetic tape controller with eight drives -TS TS11/TSV05 magnetic tape controller with one drive -TQ TQK50 TMSCP magnetic tape controller with four drives -XQ DELQA/DEQNA Qbus Ethernet controller -XQB second DELQA/DEQNA Qbus Ethernet controller -XU DEUNA/DELUA Unibus Ethernet controller - -The DZ, RK, HK, RL, RP, RQ, RQB, RQC, RQD, RX, RY, TC, TM, TS, TQ, XQ, XQB, -and XU devices can be set DISABLED. RQB, RQC, RQD, RY, TS, XQB, and XU are -disabled by default. - -The PDP-11 simulator implements several unique stop conditions: - - - abort during exception vector fetch, and register STOP_VEC is set - - abort during exception stack push, and register STOP_SPA is set - - trap condition 'n' occurs, and register STOP_TRAP is set - - wait state entered, and no I/O operations outstanding - (ie, no interrupt can ever occur) - -The PDP-11 loader supports standard binary format tapes. The DUMP command -is not implemented. - -2.1 CPU - -The CPU options include CPU mapping configuration (18b Unibus, 22b Unibus -with RH70-style controllers, 22b Unibus with RH11 style controllers, and -22b Qbus), the CIS instruction set, and the size of main memory. - - SET CPU 18B 18b addressing, no I/O map - SET CPU URH11 22b addresssing, Unibus I/O map, - 18b mapped RH11 controller - SET CPU URH70 22b addressing, Unibus I/O map, - 22b unmapped RH70 controller - SET CPU 22B 22b addressing, no I/O map (Qbus) - SET CPU NOCIS disable CIS instructions (default) - SET CPU CIS enable CIS instructions - SET CPU 16K set memory size = 16KB - SET CPU 32K set memory size = 32KB - SET CPU 48K set memory size = 48KB - SET CPU 64K set memory size = 64KB - SET CPU 96K set memory size = 96KB - SET CPU 128K set memory size = 128KB - SET CPU 192K set memory size = 192KB - SET CPU 256K set memory size = 256KB - SET CPU 384K set memory size = 384KB - SET CPU 512K set memory size = 512KB - SET CPU 768K set memory size = 768KB - SET CPU 1024K (or 1M) set memory size = 1024KB - SET CPU 2048K (or 2M) set memory size = 2048KB - SET CPU 3072K (or 3M) set memory size = 3072KB - SET CPU 4096K (or 4M) set memory size = 4096KB - -The CPU implements a show command to display the I/O address space map: - - SHOW CPU IOSPACE show I/O space address map - -If memory size is being reduced, and the memory being truncated contains -non-zero data, the simulator asks for confirmation. Data in the truncated -portion of memory is lost. Initial memory size is 256KB. If memory size -is being increased to more than 256KB, or the bus structue is being changed, -the simulator asks whether it should disable peripherals that can't run -in the current bus structure. - -DMA peripherals function differently, depending on whether the CPU is -configured for 18B, URH11, URH70, or 22B addressing and I/O: - - peripheral 18B URH11 URH70 22B - - RK 18b 18b 18b won't work, disabled - HK 18b 18b 18b SC02/C 22b, works - only with Ultrix-11 - RL 18b 18b 18b 22b RLV12 - RP 18b 18b 22b 22b third party - RQ 18b 18b 18b 22b RQDX3 - RY 18b 18b 18b won't work, disabled - TC 18b 18b 18b won't work, disabled - TM 18b 18b 18b won't work, disabled - TS 18b 18b 18b 22b TSV05 - TQ 18b 18b 18b 22b TQK50 - XQ 18b won't work, 22b DELQA - disabled - XU 18b 18b 18b won't work, disabled - -Non-DMA peripherals work the same in all configurations. Unibus-only -peripherals should be disabled in a Qbus (22B) configuration with more -than 256KB of memory, and Qbus-only peripherals should be disabled in -a Unibus (URH11 or URH70) configuration with more than 256KB of memory. - -These switches are recognized when examining or depositing in CPU memory: - - -v interpret address as virtual - -d if mem mgt enabled, force data space - -k if mem mgt enabled, force kernel mode - -s if mem mgt enabled, force supervisor mode - -u if mem mgt enabled, force user mode - -p if mem mgt enabled, force previous mode - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - PC 16 program counter - R0..R5 16 R0..R5, current register set - SP 16 stack pointer, current mode - R00..R05 16 R0..R5, register set 0 - R10..R15 16 R0..R5, register set 1 - KSP 16 kernel stack pointer - SSP 16 supervisor stack pointer - USP 16 user stack pointer - PSW 16 processor status word - CM 2 current mode, PSW<15:14> - PM 2 previous mode, PSW<13:12> - RS 2 register set, PSW<11> - IPL 3 interrupt priority level, PSW<7:5> - T 1 trace bit, PSW<4> - N 1 negative flag, PSW<3> - Z 1 zero flag, PSW<2> - V 1 overflow flag, PSW<1> - C 1 carry flag, PSW<0> - SR 16 front panel switches - DR 16 front panel display - MEMERR 16 memory error register - CCR 16 cache control register - MAINT 16 maintenance register - HITMISS 16 hit/miss register - CPUERR 16 CPU error register - PIRQ 16 programmed interrupt requests - FAC0H..FAC5H 32 FAC0..FAC5, high 32 bits - FAC0L..FAC5L 32 FAC0..FAC5, low 32 bits - FPS 16 floating point status - FEA 16 floating exception address - FEC 4 floating exception code - MMR0..3 16 memory management registers 0..3 - {K/S/U}{I/D}{PAR/PDR}{0..7} - 16 memory management registers - UBMAP[0:63] 16 Unibus map registers - INT 32 interrupt pending flags - TRAP 18 trap pending flags - WAIT 0 wait state flag - WAIT_ENABLE 0 wait state enable flag - STOP_TRAPS 18 stop on trap flags - STOP_VECA 1 stop on read abort in trap or interrupt - STOP_SPA 1 stop on stack push abort in trap or interrupt - PCQ[0:63] 16 PC prior to last jump, branch, or interrupt; - most recent PC change first - WRU 8 interrupt character - -2.2 I/O Device Addressing - -PDP-11 I/O space is not large enough to allow all possible devices to be -configured simultaneously at fixed addresses. Instead, many devices have -floating addresses; that is, the assigned device address depends on the -presense of other devices in the configuration: - - DZ11 all instances have floating addresses - RL11 first instance has fixed address, rest floating - RX11/RX211 first instance has fixed address, rest floating - DEUNA/DELUA first instance has fixed address, rest floating - MSCP disk first instance has fixed address, rest floating - TMSCP tape first instance has fixed address, rest floating - -To maintain addressing consistency as the configuration changes, the -simulator implements DEC's standard I/O address and vector autoconfiguration -algorithms for devices DZ, RL, RX, RY, XU, RQ, and TQ. This allows the -user to enable or disable devices without needing to manage I/O addresses -and vectors. For example, if RY is enabled while RX is present, RY is -assigned an I/O address in the floating I/O space range; but if RX is -disabled and then RY is enabled, RY is assigned the fixed "first instance" -I/O address for floppy disks. - -Autoconfiguration cannot solve address conflicts between devices with -overlapping fixed addresses. For example, with default I/O page addressing, -the PDP-11 can support either a TM11 or a TS11, but not both, since they use -the same I/O addresses. - -In addition to autoconfiguration, most devices support the SET ADDRESS -command, which allows the I/O page address of the device to be changed, -and the SET VECTOR command, which allows the vector of the device to be -changed. Explicitly setting the I/O address of a device which normally -uses autoconfiguration DISABLES autoconfiguration for that device. As -a consequence, the user may have to manually configure all other -autoconfigured devices, because the autoconfiguration algorithm no -longer recognizes the explicitly configured device. A device can be -reset to autoconfigure with the SET AUTOCONFIGURE command. - -The current I/O map can be displayed with the SHOW CPU IOSPACE command. -Addresses that have set by autoconfiguration are marked with an asterisk (*). - -All devices support the SHOW ADDRESS and SHOW VECTOR commands, which display -the device address and vector, respectively. - -2.3 Programmed I/O Devices - -2.3.1 PC11 Paper Tape Reader (PTR) - -The paper tape reader (PTR) reads data from a disk file. The POS -register specifies the number of the next data item to be read. Thus, -by changing POS, the user can backspace or advance the reader. - -The paper tape reader implements these registers: - - name size comments - - BUF 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - BUSY 1 busy flag (CSR<11>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - POS 32 position in the input file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - end of file 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -2.3.2 PC11 Paper Tape Punch (PTP) - -The paper tape punch (PTP) writes data to a disk file. The POS -register specifies the number of the next data item to be written. -Thus, by by changing POS, the user can backspace or advance the punch. - -The paper tape punch implements these registers: - - name size comments - - BUF 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -2.3.3 DL11 Terminal Input (TTI) - -The terminal interfaces (TTI, TTO) can be set to one of two modes: -7B or 8B. In 7B mode, input and output characters are masked to 7 -bits. In 8B mode, characters are not modified. Changing the mode -of either interface changes both. The default mode is 8B. - -The terminal input (TTI) polls the console keyboard for input. It -implements these registers: - - name size comments - - BUF 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - POS 32 number of characters input - TIME 24 keyboard polling interval - -If the simulator is compiled under Windows Visual C++, typing ^C to the -terminal input causes a fatal run-time error. Use the following command -to simulate typing ^C: - - SET TTI CTRL-C - -2.3.4 DL11 Terminal Output (TTO) - -The terminal output (TTO) writes to the simulator console window. It -implements these registers: - - name size comments - - BUF 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - POS 32 number of characters input - TIME 24 time from I/O initiation to interrupt - -2.3.5 LP11 Line Printer (LPT) - -The line printer (LPT) writes data to a disk file. The POS register -specifies the number of the next data item to be written. Thus, -by changing POS, the user can backspace or advance the printer. - -The line printer implements these registers: - - name size comments - - BUF 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of paper - - OS I/O error x report error and stop - -2.3.6 Line-Time Clock (CLK) - -The line-time clock (CLK) frequency can be adjusted as follows: - - SET CLK 60HZ set frequency to 60Hz - SET CLK 50HZ set frequency to 50Hz - -The default is 60Hz. - -The line-time clock implements these registers: - - name size comments - - CSR 16 control/status register - INT 1 interrupt pending flag - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - TIME 24 clock interval - -The line-time clock autocalibrates; the clock interval is adjusted up -or down so that the clock tracks actual elapsed time. - -2.3.7 Programmable Clock (PCLK) - -The programmable clock (PCLK) line frequency can be adjusted as follows: - - SET PCLK 60HZ set frequency to 60Hz - SET PCLK 50HZ set frequency to 50Hz - -The default is 60Hz. - -The programmable clock implements these registers: - - name size comments - - CSR 16 control/status register - CSB 16 count set buffer - CNT 16 current count - INT 1 interrupt pending flag - OVFL 1 overflow (error) flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - UPDN 1 up/down count mode (CSR<4>) - MODE 1 single/repeat mode (CSR<3>) - RUN 1 clock run (CSR<0>) - TIME[0..3] 32 clock interval, rates 0..3 - TPS[0..3] 32 ticks per second, rates 0..3 - -The programmable clock autocalibrates; the clock interval is adjusted -up or down so that the clock tracks actual elapsed time. Operation at -the highest clock rate (100Khz) is not recommended. The programmable -clock is disabled by default. - -2.3.8 DZ11 Terminal Multiplexor (DZ) - -The DZ11 is an 8-line terminal multiplexor. Up to 4 DZ11's (32 lines) -are supported. The number of lines can be changed with the command - - SET DZ LINES=n set line count to n - -The line count must be a multiple of 8, with a maximum of 32. - -The DZ11 supports 8-bit input and output of characters. 8-bit output -may be incompatible with certain operating systems. The command - - SET DZ 7B - -forces output characters (only) to be masked to 7 bits. - -The terminal lines perform input and output through Telnet sessions -connected to a user-specified port. The ATTACH command specifies -the port to be used: - - ATTACH {-am} DZ set up listening port - -where port is a decimal number between 1 and 65535 that is not being used -for other TCP/IP activities. The optional switch -m turns on the DZ11's -modem controls; the optional switch -a turns on active disconnects -(disconnect session if computer clears Data Terminal Ready). Without -modem control, the DZ behaves as though terminals were directly connected; -disconnecting the Telnet session does not cause any operating system- -visible change in line status. - -Once the DZ is attached and the simulator is running, the DZ will listen -for connections on the specified port. It assumes that the incoming -connections are Telnet connections. The connection remains open until -disconnected by the simulated program, the Telnet client, a SET DZ -DISCONNECT command, or a DETACH DZ command. - -The SHOW DZ CONNECTIONS command displays the current connections to the DZ. -The SHOW DZ STATISTICS command displays statistics for active connections. -The SET DZ DISCONNECT=linenumber disconnects the specified line. - -The DZ11 implements these registers: - - name size comments - - CSR[0:3] 16 control/status register, boards 0..3 - RBUF[0:3] 16 receive buffer, boards 0..3 - LPR[0:3] 16 line parameter register, boards 0..3 - TCR[0:3] 16 transmission control register, boards 0..3 - MSR[0:3] 16 modem status register, boards 0..3 - TDR[0:3] 16 transmit data register, boards 0..3 - SAENB[0:3] 1 silo alarm enabled, boards 0..3 - RXINT 4 receive interrupts, boards 3..0 - TXINT 4 transmit interrupts, boards 3..0 - MDMTCL 1 modem control enabled - AUTODS 1 autodisconnect enabled - -The DZ11 does not support save and restore. All open connections are -lost when the simulator shuts down or the DZ is detached. - -2.4 Floppy Disk Drives - -2.4.1 RX11/RX01 Floppy Disk (RX) - -RX11 options include the ability to set units write enabled or write locked: - - SET RXn LOCKED set unit n write locked - SET RXn WRITEENABLED set unit n write enabled - -The RX11 supports the BOOT command. - -The RX11 implements these registers: - - name size comments - - RXCS 12 status - RXDB 8 data buffer - RXES 8 error status - RXERR 8 error code - RXTA 8 current track - RXSA 8 current sector - STAPTR 3 controller state - BUFPTR 3 buffer pointer - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - TR 1 transfer ready flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - DONE 1 device done flag (CSR<5>) - CTIME 24 command completion time - STIME 24 seek time, per track - XTIME 24 transfer ready delay - STOP_IOE 1 stop on I/O error - SBUF[0:127] 8 sector buffer array - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -RX01 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.4.2 RX211/RX02 Floppy Disk (RY) - -RX211 options include the ability to set units write enabled or write -locked, single or double density, or autosized: - - SET RYn LOCKED set unit n write locked - SET RYn WRITEENABLED set unit n write enabled - SET RYn SINGLE set unit n single density - SET RYn DOUBLE set unit n double density (default) - SET RYn AUTOSIZE set unit n autosized - -The RX211 supports the BOOT command. The RX211 will not function -properly in a Qbus (22B) system with more than 256KB of memory. - -The RX211 implements these registers: - - name size comments - - RYCS 16 status - RYBA 16 buffer address - RYWC 8 word count - RYDB 16 data buffer - RYES 12 error status - RYERR 8 error code - RYTA 8 current track - RYSA 8 current sector - STAPTR 4 controller state - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - TR 1 transfer ready flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - DONE 1 device done flag (CSR<5>) - CTIME 24 command completion time - STIME 24 seek time, per track - XTIME 24 transfer ready delay - STOP_IOE 1 stop on I/O error - SBUF[0:255] 8 sector buffer array - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -RX02 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.5 Cartridge Disk Drives - -2.5.1 RK11/RK05 Cartridge Disk (RK) - -RK11 options include the ability to make units write enabled or write -locked: - - SET RKn LOCKED set unit n write locked - SET RKn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFLINE. The RK11 supports the BOOT -command. The RK11 will not function properly in a Qbus (22B) system -with more than 256KB of memory. - -The RK11 implements these registers: - - name size comments - - RKCS 16 control/status - RKDA 16 disk address - RKBA 16 memory address - RKWC 16 word count - RKDS 16 drive status - RKER 16 error status - INTQ 9 interrupt queue - DRVN 3 number of last selected drive - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - INT 1 interrupt pending flag - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - - end of file x assume rest of disk is zero - - OS I/O error x report error and stop - -2.5.2 RK611/RK06,RK07 Cartridge Disk (HK) - -RK611 options include the ability to set units write enabled or write -locked, to set the drive size to RK06, RK07, or autosize, and to write -a DEC standard 044 compliant bad block table on the last track: - - SET HKn LOCKED set unit n write locked - SET HKn WRITEENABLED set unit n write enabled - SET HKn RK06 set size to RK06 - SET HKn RK07 set size to RK07 - SET HKn AUTOSIZE set size based on file size at attach - SET HKn BADBLOCK write bad block table on last track - -The size options can be used only when a unit is not attached to a file. -The bad block option can be used only when a unit is attached to a file. -Units can be set ONLINE or OFFLINE. The RK611 supports the BOOT command. -The RK611 will not function properly in a Qbus (22B) system with more -than 256KB of memory using standard DEC software. The simulator implements -a third-party extension of addressing capability to 22b; this is only -supported by Ultrix-11. - -The RK611 implements these registers: - - name size comments - - HKCS1 16 control/status 1 - HKWC 16 word count - HKBA 16 bus address - HKDA 16 desired surface, sector - HKCS2 16 control/status 2 - HKDS[0:7] 16 drive status, drives 0-7 - HKER[0:7] 16 drive errors, drives 0-7 - HKDB[0:2] 16 data buffer silo - HKDC 16 desired cylinder - HKOF 8 offset - HKMR 16 maintenance register - HKSPR 16 spare register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR1<7>) - IE 1 interrupt enable flag (CSR1<6>) - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - - end of file x assume rest of disk is zero - - OS I/O error x report error and stop - -2.5.3 RL11(V12)/RL01,RL02 Cartridge Disk (RL) - -RL11 options include the ability to set units write enabled or write -locked, to set the drive size to RL01, RL02, or autosize, and to write -a DEC standard 044 compliant bad block table on the last track: - - SET RLn LOCKED set unit n write locked - SET RLn WRITEENABLED set unit n write enabled - SET RLn RL01 set size to RL01 - SET RLn RL02 set size to RL02 - SET RLn AUTOSIZE set size based on file size at attach - SET RLn BADBLOCK write bad block table on last track - -The size options can be used only when a unit is not attached to a file. -The bad block option can be used only when a unit is attached to a file. -Units can be set ONLINE or OFFLINE. The RL11 supports the BOOT command. -In an 18B or Unibus system, the RL behaves like an RL11 with 18b -addressing; in a Qbus (22B) system, the RL behaves like the RLV12 with -22b addressing. - -The RL11 implements these registers: - - name size comments - - RLCS 16 control/status - RLDA 16 disk address - RLBA 16 memory address - RLBAE 6 memory address extension (RLV12) - RLMP..RLMP2 16 multipurpose register queue - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - - end of file x assume rest of disk is zero - - OS I/O error x report error and stop - -2.6 RM02/03/05/80, RP04/05/06/07 Disk Pack Drives (RP) - -The RP controller implements a "Massbus style" 22b direct interface -for large disk drives. It is more abstract than other device simulators, -with just enough detail to run operating system drivers. In addition, -the RP controller conflates the details of the RM series controllers -with the RP series controllers, although there were detailed differences. - -RP options include the ability to set units write enabled or write -locked, to set the drive type to one of six disk types, or autosize, -and to write a DEC standard 044 compliant bad block table on the last -track: - - SET RPn LOCKED set unit n write locked - SET RPn WRITEENABLED set unit n write enabled - SET RPn RM03 set type to RM03 - SET RPn RM05 set type to RM05 - SET RPn RM80 set type to RM80 - SET RPn RP04 set type to RP04 - SET RPn RP06 set type to RP06 - SET RPn RP07 set type to RP07 - SET RPn AUTOSIZE set type based on file size at attach - SET RPn BADBLOCK write bad block table on last track - -The type options can be used only when a unit is not attached to a file. -The bad block option can be used only when a unit is attached to a file. -Units can be set ONLINE or OFFLINE. The RP controller supports the -BOOT command. In a Unibus system, the RP can implement either 18b -(RH11) addressing or 22b (RH70) addressing. In a Qbus (22B) system, -the RP always implements 22b addressing. - -The RP controller implements these registers: - - name size comments - - RPCS1 16 control/status 1 - RPWC 16 word count - RPBA 16 bus address - RPDA 16 desired surface, sector - RPCS2 16 control/status 2 - RPDS[0:7] 16 drive status, drives 0-7 - RPER1[0:7] 16 drive errors, drives 0-7 - RPOF 16 offset - RPDC 16 desired cylinder - RPER2 16 error status 2 - RPER3 16 error status 3 - RPEC1 16 ECC syndrome 1 - RPEC2 16 ECC syndrome 2 - RPMR 16 maintenance register - RPDB 16 data buffer - RPBAE 6 bus address extension - RPCS3 16 control/status 3 - IFF 1 transfer complete interrupt request flop - INT 1 interrupt pending flag - SC 1 special condition (CSR1<15>) - DONE 1 device done flag (CSR1<7>) - IE 1 interrupt enable flag (CSR1<6>) - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - - end of file x assume rest of disk is zero - - OS I/O error x report error and stop - -2.7 RQDX3 MSCP Disk Controllers (RQ, RQB, RQC, RQD) - -The simulator implements four MSCP disk controllers, RQ, RQB, RQC, RQD. -Initially, RQB, RQC, and RQD are disabled. Each RQ controller simulates -an RQDX3 MSCP disk controller. RQ options include the ability to set -units write enabled or write locked, and to set the drive type to one -of many disk types: - - SET RQn LOCKED set unit n write locked - SET RQn WRITEENABLED set unit n write enabled - SET RQn RX50 set type to RX50 - SET RQn RX33 set type to RX33 - SET RQn RD51 set type to RD51 - SET RQn RD52 set type to RD52 - SET RQn RD53 set type to RD53 - SET RQn RD54 set type to RD54 - SET RQn RD31 set type to RD31 - SET RQn RA82 set type to RA82 - SET RQn RA72 set type to RA72 - SET RQn RA90 set type to RA90 - SET RQn RA92 set type to RA92 - SET RQn RRD40 set type to RRD40 (CD ROM) - SET RQn RAUSER{=n} set type to RA81 with n LBNs - -The type options can be used only when a unit is not attached to a file. -RAUSER is a "user specified" disk; the user can specify the size of the -disk in logical block numbers (LBN's, 512 bytes each). The minimum size -is 50MB; the maximum size is 2GB. - -Units can also be set ONLINE or OFFLINE. Each RQ controller supports the -BOOT command. In a Unibus system, an RQ supports 18b addressing. In -a Qbus (22B) system, an RQ supports 22b addressing. - -Each RQ controller implements the following special SHOW commands: - - SHOW RQn TYPE show drive type - SHOW RQ RINGS show command and response rings - SHOW RQ FREEQ show packet free queue - SHOW RQ RESPQ show packet response queue - SHOW RQ UNITQ show unit queues - SHOW RQ ALL show all ring and queue state - SHOW RQn UNITQ show unit queues for unit n - -Each RQ controller implements these registers: - - name size comments - - SA 16 status/address register - S1DAT 16 step 1 init host data - CQBA 22 command queue base address - CQLNT 8 command queue length - CQIDX 8 command queue index - RQBA 22 request queue base address - RQLNT 8 request queue length - RQIDX 8 request queue index - FREE 5 head of free packet list - RESP 5 head of response packet list - PBSY 5 number of busy packets - CFLGS 16 controller flags - CSTA 4 controller state - PERR 9 port error number - CRED 5 host credits - HAT 17 host available timer - HTMO 17 host timeout value - CPKT[0:3] 5 current packet, units 0-3 - PKTQ[0:3] 5 packet queue, units 0-3 - UFLG[0:3] 16 unit flags, units 0-3 - INT 1 interrupt request - ITIME 1 response time for initialization steps - (except for step 4) - QTIME 24 response time for 'immediate' packets - XTIME 24 response time for data transfers - PKTS[33*32] 16 packet buffers, 33W each, - 32 entries - -Some DEC operating systems, notably RSX11M/M+, are very sensitive to -the timing parameters. Changing the default values may cause M/M+ to -crash on boot or to hang during operation. - -Error handling is as follows: - - error processed as - - not attached disk not ready - - end of file assume rest of disk is zero - - OS I/O error report error and stop - -2.8 TC11/TU56 DECtape (DT) - -DECtapes drives are numbered 1-8; in the simulator, drive 8 is unit 0. -DECtape options include the ability to make units write enabled or write -locked. - - SET DTn LOCKED set unit n write locked - SET DTn WRITEENABLED set unit n write enabled - -Units can be set ONLINE or OFFLINE. The TC11 supports the BOOT command. -The TC11 will not function properly in a 22B (Qbus) system with more -than 256KB of memory. - -The TC11 supports supports PDP-8 format, PDP-11 format, and 18b format -DECtape images. ATTACH tries to determine the tape format from the DECtape -image; the user can force a particular format with switches: - - -r PDP-8 format - -s PDP-11 format - -t 18b format - -The DECtape controller is a data-only simulator; the timing and mark -track, and block header and trailer, are not stored. Thus, the WRITE -TIMING AND MARK TRACK function is not supported; the READ ALL function -always returns the hardware standard block header and trailer; and the -WRITE ALL function dumps non-data words into the bit bucket. - -The TC controller implements these registers: - - name size comments - - TCST 16 status register - TCCM 16 command register - TCWC 16 word count register - TCBA 16 bus address register - TCDT 16 data register - INT 1 interrupt pending flag - ERR 1 error flag - DONE 1 done flag - IE 1 interrupt enable flag - CTIME 31 time to complete transport stop - LTIME 31 time between lines - ACTIME 31 time to accelerate to full speed - DCTIME 31 time to decelerate to a full stop - SUBSTATE 2 read/write command substate - POS[0:7] 32 position, in lines, units 0-7 - STATT[0-7] 31 unit state, units 0-7 - -It is critically important to maintain certain timing relationships -among the DECtape parameters, or the DECtape simulator will fail to -operate correctly. - - - LTIME must be at least 6 - - ACTIME must be less than DCTIME, and both need to be at - least 100 times LTIME - -2.9 Magnetic Tape Controllers - -2.9.1 TM11 Magnetic Tape (TM) - -TM options include the ability to make units write enabled or write -locked. - - SET TMn LOCKED set unit n write locked - SET TMn WRITEENABLED set unit n write enabled - -Units can be set ONLINE or OFFLINE. - -The TM11 supports the BOOT command. The bootstrap supports both original -and DEC standard boot formats. Originally, a tape bootstrap read and -executed the first record on tape. To allow for ANSI labels, the DEC -standard bootstrap skipped the first record and read and executed the -second. The DEC standard is the default; to bootstrap an original format -tape, use the -o switch. - -The TM11 will not function properly in a Qbus (22B) system with more -than 256KB of memory - -The TM controller implements these registers: - - name size comments - - MTS 16 status - MTC 16 command - MTCMA 16 memory address - MTBRC 16 byte/record count - INT 1 interrupt pending flag - ERR 1 error flag - DONE 1 device done flag - IE 1 interrupt enable flag - STOP_IOE 1 stop on I/O error - TIME 24 delay - UST[0:7] 16 unit status, units 0-7 - POS[0:7] 32 position, units 0-7 - -Error handling is as follows: - - error processed as - - not attached tape not ready; if STOP_IOE, stop - - end of file bad tape - - OS I/O error parity error; if STOP_IOE, stop - -2.9.2 TS11/TSV05 Magnetic Tape (TS) - -The TS actually implements the TSV05, with 22-bit addressing, but will -work with TS11 drivers. TS options include the ability to make the unit -write enabled or write locked. - - SET TS LOCKED set unit write locked - SET TS WRITEENABLED set unit write enabled - -The TS11 supports the BOOT command. The bootstrap supports only DEC -standard boot formats. To allow for ANSI labels, the DEC standard -bootstrap skipped the first record and read and executed the second. -In a Unibus system, the TS behaves like the TS11 and implements 18b -addresses. In a Qbus (22B) system, the TS behaves like the TSV05 -and implements 22b addresses. - -The TS controller implements these registers: - - name size comments - - TSSR 16 status register - TSBA 16 bus address register - TSDBX 16 data buffer extension register - CHDR 16 command packet header - CADL 16 command packet low address or count - CADH 16 command packet high address - CLNT 16 command packet length - MHDR 16 message packet header - MRFC 16 message packet residual frame count - MXS0 16 message packet extended status 0 - MXS1 16 message packet extended status 1 - MXS2 16 message packet extended status 2 - MXS3 16 message packet extended status 3 - MXS4 16 message packet extended status 4 - WADL 16 write char packet low address - WADH 16 write char packet high address - WLNT 16 write char packet length - WOPT 16 write char packet options - WXOPT 16 write char packet extended options - ATTN 1 attention message pending - BOOT 1 boot request pending - OWNC 1 if set, tape owns command buffer - OWNM 1 if set, tape owns message buffer - TIME 24 delay - POS 32 position - -Error handling is as follows: - - error processed as - - not attached tape not ready - - end of file bad tape - - OS I/O error fatal tape error - -2.9.3 TQK50 TMSCP Disk Controller (TQ) - -The TQ controller simulates the TQK50 TMSCP disk controller. TQ options -include the ability to set units write enabled or write locked, and to -specify the controller type and tape length: - - SET TQn LOCKED set unit n write locked - SET TQn WRITEENABLED set unit n write enabled - SET TQ TK50 set controller type to TK50 - SET TQ TK70 set controller type to TK70 - SET TQ TU81 set controller type to TU81 - SET TQ TKUSER{=n} set controller type to TK50 with - tape capacity of n MB - -User-specified capacity must be between 50 and 2000 MB. - -The TQ controller supports the BOOT command. In a Unibus system, the -TQ supports 18b addressing. In a Qbus (22B) system, the TQ supports -22b addressing. - -The TQ controller implements the following special SHOW commands: - - SHOW TQ TYPE show controller type - SHOW TQ RINGS show command and response rings - SHOW TQ FREEQ show packet free queue - SHOW TQ RESPQ show packet response queue - SHOW TQ UNITQ show unit queues - SHOW TQ ALL show all ring and queue state - SHOW TQn UNITQ show unit queues for unit n - -The TQ controller implements these registers: - - name size comments - - SA 16 status/address register - S1DAT 16 step 1 init host data - CQBA 22 command queue base address - CQLNT 8 command queue length - CQIDX 8 command queue index - RQBA 22 request queue base address - RQLNT 8 request queue length - RQIDX 8 request queue index - FREE 5 head of free packet list - RESP 5 head of response packet list - PBSY 5 number of busy packets - CFLGS 16 controller flags - CSTA 4 controller state - PERR 9 port error number - CRED 5 host credits - HAT 17 host available timer - HTMO 17 host timeout value - CPKT[0:3] 5 current packet, units 0-3 - PKTQ[0:3] 5 packet queue, units 0-3 - UFLG[0:3] 16 unit flags, units 0-3 - POS[0:3] 32 tape position, units 0-3 - OBJP[0:3] 32 object position, units 0-3 - INT 1 interrupt request - ITIME 1 response time for initialization steps - (except for step 4) - QTIME 24 response time for 'immediate' packets - XTIME 24 response time for data transfers - PKTS[33*32] 16 packet buffers, 33W each, - 32 entries - -Some DEC operating systems, notably RSX11M/M+, are very sensitive to -the timing parameters. Changing the default values may cause M/M+ to -crash on boot or to hang during operation. - -Error handling is as follows: - - error processed as - - not attached tape not ready - - end of file end of medium - - OS I/O error fatal tape error - -2.10 DELQA/DEQNA Qbus Ethernet Controllers (XQ, XQB) - -The simulator implements two DELQA/DEQNA Qbus Ethernet controllers (XQ, -XQB). Initially, XQ is enabled, and XQB is disabled. Options allow -control of the MAC address, the controller mode, and the sanity timer. - - SET XQ MAC= ex. 08-00-2B-AA-BB-CC - SHOW XQ MAC - -These commands are used to change or display the MAC address. -is a valid ethernet MAC, delimited by dashes or periods. The controller -defaults to 08-00-2B-AA-BB-CC, which should be sufficient if there is -only one SIMH controller on your LAN. Two cards with the same MAC address -will see each other's packets, resulting in a serious mess. - - SET XQ TYPE={DEQNA|[DELQA]} - SHOW XQ TYPE - -These commands are used to change or display the controller mode. DELQA -mode is better and faster but may not be usable by older or non-DEC OS's. -Also, be aware that DEQNA mode is not supported by many modern OS's. The -DEQNA-LOCK mode of the DELQA card is emulated by setting the the controller -to DEQNA - there is no need for a separate mode. DEQNA-LOCK mode behaves -exactly like a DEQNA, except for the operation of the VAR and MOP processing. - - SET XQ SANITY={ON|[OFF]} - SHOW XQ SANITY - -These commands change or display the INITIALIZATION sanity timer (DEQNA -jumper W3/DELQA switch S4). The INITIALIZATION sanity timer has a default -timeout of 4 minutes, and cannot be turned off, just reset. The normal -sanity timer can be set by operating system software regardless of the -state of this switch. Note that only the DEQNA (or the DELQA in DEQNA- -LOCK mode (=DEQNA)) supports the sanity timer - it is ignored by a DELQA -in Normal mode, which uses switch S4 for a different purpose. - -To access the network, the simulated Ethernet controller must be attached -to a real Ethernet interface: - - ATTACH XQ0 {ethX|} ex. eth0 or /dev/era0 - SHOW XQ ETH - -where X in 'ethX' is the number of the ethernet controller to attach, or -the real device name. The X number is system dependant. If you only have -one ethernet controller, the number will probably be 0. To find out what -your system thinks the ethernet numbers are, use the SHOW XQ ETH command. -The device list can be quite cryptic, depending on the host system, but -is probably better than guessing. If you do not attach the device, the -controller will behave as though the ethernet cable were unplugged. - -XQ has the following registers: - - name size comments - - SA0 16 station address word 0 - SA1 16 station address word 1 - SA2 16 station address word 2 - SA3 16 station address word 3 - SA4 16 station address word 4 - SA5 16 station address word 5 - CSR 16 control status register - VAR 16 vector address register - RBDL 32 receive buffer descriptor list - XBDL 32 trans(X)mit buffer descriptorlList - -One final note: because of it's asynchronous nature, the XQ controller is -not limited to the ~1.5Mbit/sec of the real DEQNA/DELQA controllers, -nor the 10Mbit/sec of a standard Ethernet. Attach it to a Fast Ethernet -(100 Mbit/sec) card, and "Feel the Power!" :-) - -2.11 DEUNA/DELUA Unibus Ethernet Controller (XU) - -XU simulates the DEUNA/DELUA Unibus Ethernet controller. THe current -implementation is a stub and is permanently disabled. - -2.12 Symbolic Display and Input - -The PDP-11 simulator implements symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as two character ASCII string - -m display instruction mnemonics - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or -a ASCII character - " or -c two character ASCII string - alphabetic instruction mnemonic - numeric octal number - -Instruction input uses standard PDP-11 assembler syntax. There are sixteen -instruction classes: - -class operands examples comments - -no operands none HALT, RESET -3b literal literal, 0 - 7 SPL -6b literal literal, 0 - 077 MARK -8b literal literal, 0 - 0377 EMT, TRAP -register register RTS -sop specifier SWAB, CLR, ASL -reg-sop register, specifier JSR, XOR, MUL -fop flt specifier ABSf, NEGf -ac-fop flt reg, flt specifier LDf, MULf -ac-sop flt reg, specifier LDEXP, STEXP -ac-moded sop flt reg, specifier LDCif, STCfi -dop specifier, specifier MOV, ADD, BIC -cond branch address BR, BCC, BNE -sob register, address SOB -cc clear cc clear instructions CLC, CLV, CLZ, CLN combinable -cc set cc set instructions SEC, SEV, SEZ, SEN combinable - -For floating point opcodes, F and D variants, and I and L variants, may be -specified regardless of the state of FPS. - -The syntax for specifiers is as follows: - -syntax specifier displacement comments - -Rn 0n - -Fn 0n - only in flt reg classes -(Rn) 1n - -@(Rn) 7n 0 equivalent to @0(Rn) -(Rn)+ 2n - -@(Rn)+ 3n - --(Rn) 4n - -@-(Rn) 5n - -{+/-}d(Rn) 6n {+/-}d -@{+/-}d(Rn) 7n {+/-}d -#n 27 n -@#n 37 n -.+/-n 67 +/-n - 4 -@.+/-n 77 +/-n - 4 -{+/-}n 67 {+/-}n - PC - 4 if on disk, 37 and n -@{+/-}n 77 {+/-}n - PC - 4 if on disk, invalid diff --git a/PDP11/pdp11_dz.c b/PDP11/pdp11_dz.c deleted file mode 100644 index 6b6c33bb..00000000 --- a/PDP11/pdp11_dz.c +++ /dev/null @@ -1,633 +0,0 @@ -/* pdp11_dz.c: DZ11 terminal multiplexor simulator - - Copyright (c) 2001-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - dz DZ11 terminal multiplexor - - 19-May-03 RMS Revised for new conditional compilation scheme - 09-May-03 RMS Added network device flag - 22-Dec-02 RMS Added break (framing error) support - 31-Oct-02 RMS Added 8b support - 12-Oct-02 RMS Added autoconfigure support - 29-Sep-02 RMS Fixed bug in set number of lines routine - Added variable vector support - New data structures - 22-Apr-02 RMS Updated for changes in sim_tmxr - 28-Apr-02 RMS Fixed interrupt acknowledge, fixed SHOW DZ ADDRESS - 14-Jan-02 RMS Added multiboard support - 30-Dec-01 RMS Added show statistics, set disconnect - Removed statistics registers - 03-Dec-01 RMS Modified for extended SET/SHOW - 09-Nov-01 RMS Added VAX support - 20-Oct-01 RMS Moved getchar from sim_tmxr, changed interrupt - logic to use tmxr_rqln - 06-Oct-01 RMS Fixed bug in carrier detect logic - 03-Oct-01 RMS Added support for BSD-style "ringless" modems - 27-Sep-01 RMS Fixed bug in xmte initialization - 17-Sep-01 RMS Added separate autodisconnect switch - 16-Sep-01 RMS Fixed modem control bit offsets -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#include "pdp10_defs.h" -#define RANK_DZ 0 /* no autoconfig */ -#define DZ_8B_DFLT 0 -extern int32 int_req; -extern int32 int_vec[32]; - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -#define DZ_8B_DFLT UNIT_8B -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -#define DZ_8B_DFLT UNIT_8B -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#endif - -#include "sim_sock.h" -#include "sim_tmxr.h" - -#if !defined (DZ_MUXES) -#define DZ_MUXES 1 -#endif -#if !defined (DZ_LINES) -#define DZ_LINES 8 -#endif - -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8b output */ -#define UNIT_8B (1 << UNIT_V_8B) - -#define DZ_MNOMASK (DZ_MUXES - 1) /* mask for mux no */ -#define DZ_LNOMASK (DZ_LINES - 1) /* mask for lineno */ -#define DZ_LMASK ((1 << DZ_LINES) - 1) /* mask of lines */ -#define DZ_SILO_ALM 16 /* silo alarm level */ - -/* DZCSR - 160100 - control/status register */ - -#define CSR_MAINT 0000010 /* maint - NI */ -#define CSR_CLR 0000020 /* clear */ -#define CSR_MSE 0000040 /* master scan enb */ -#define CSR_RIE 0000100 /* rcv int enb */ -#define CSR_RDONE 0000200 /* rcv done - RO */ -#define CSR_V_TLINE 8 /* xmit line - RO */ -#define CSR_TLINE (DZ_LNOMASK << CSR_V_TLINE) -#define CSR_SAE 0010000 /* silo alm enb */ -#define CSR_SA 0020000 /* silo alm - RO */ -#define CSR_TIE 0040000 /* xmit int enb */ -#define CSR_TRDY 0100000 /* xmit rdy - RO */ -#define CSR_RW (CSR_MSE | CSR_RIE | CSR_SAE | CSR_TIE) -#define CSR_MBZ (0004003 | CSR_CLR | CSR_MAINT) - -#define CSR_GETTL(x) (((x) >> CSR_V_TLINE) & DZ_LNOMASK) -#define CSR_PUTTL(x,y) x = ((x) & ~CSR_TLINE) | (((y) & DZ_LNOMASK) << CSR_V_TLINE) - -/* DZRBUF - 160102 - receive buffer, read only */ - -#define RBUF_CHAR 0000377 /* rcv char */ -#define RBUF_V_RLINE 8 /* rcv line */ -#define RBUF_PARE 0010000 /* parity err - NI */ -#define RBUF_FRME 0020000 /* frame err */ -#define RBUF_OVRE 0040000 /* overrun err - NI */ -#define RBUF_VALID 0100000 /* rcv valid */ -#define RBUF_MBZ 0004000 - -/* DZLPR - 160102 - line parameter register, write only, word access only */ - -#define LPR_V_LINE 0 /* line */ -#define LPR_LPAR 0007770 /* line pars - NI */ -#define LPR_RCVE 0010000 /* receive enb */ -#define LPR_GETLN(x) (((x) >> LPR_V_LINE) & DZ_LNOMASK) - -/* DZTCR - 160104 - transmission control register */ - -#define TCR_V_XMTE 0 /* xmit enables */ -#define TCR_V_DTR 8 /* DTRs */ - -/* DZMSR - 160106 - modem status register, read only */ - -#define MSR_V_RI 0 /* ring indicators */ -#define MSR_V_CD 8 /* carrier detect */ - -/* DZTDR - 160106 - transmit data, write only */ - -#define TDR_CHAR 0000377 /* xmit char */ -#define TDR_V_TBR 8 /* xmit break - NI */ - -extern int32 IREQ (HLVL); -extern int32 sim_switches; -extern FILE *sim_log; -extern int32 tmxr_poll; /* calibrated delay */ - -uint16 dz_csr[DZ_MUXES] = { 0 }; /* csr */ -uint16 dz_rbuf[DZ_MUXES] = { 0 }; /* rcv buffer */ -uint16 dz_lpr[DZ_MUXES] = { 0 }; /* line param */ -uint16 dz_tcr[DZ_MUXES] = { 0 }; /* xmit control */ -uint16 dz_msr[DZ_MUXES] = { 0 }; /* modem status */ -uint16 dz_tdr[DZ_MUXES] = { 0 }; /* xmit data */ -uint8 dz_sae[DZ_MUXES] = { 0 }; /* silo alarm enabled */ -uint32 dz_rxi = 0; /* rcv interrupts */ -uint32 dz_txi = 0; /* xmt interrupts */ -int32 dz_mctl = 0; /* modem ctrl enabled */ -int32 dz_auto = 0; /* autodiscon enabled */ -TMLN dz_ldsc[DZ_MUXES * DZ_LINES] = { 0 }; /* line descriptors */ -TMXR dz_desc = { DZ_MUXES * DZ_LINES, 0, 0, NULL }; /* mux descriptor */ - -DEVICE dz_dev; -t_stat dz_rd (int32 *data, int32 PA, int32 access); -t_stat dz_wr (int32 data, int32 PA, int32 access); -int32 dz_rxinta (void); -int32 dz_txinta (void); -t_stat dz_svc (UNIT *uptr); -t_stat dz_reset (DEVICE *dptr); -t_stat dz_attach (UNIT *uptr, char *cptr); -t_stat dz_detach (UNIT *uptr); -t_stat dz_clear (int32 dz, t_bool flag); -int32 dz_getc (int32 dz); -void dz_update_rcvi (void); -void dz_update_xmti (void); -void dz_clr_rxint (int32 dz); -void dz_set_rxint (int32 dz); -void dz_clr_txint (int32 dz); -void dz_set_txint (int32 dz); -t_stat dz_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat dz_show (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat dz_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat dz_setnl (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* DZ data structures - - dz_dev DZ device descriptor - dz_unit DZ unit list - dz_reg DZ register list -*/ - -DIB dz_dib = { IOBA_DZ, IOLN_DZ * DZ_MUXES, &dz_rd, &dz_wr, - 2, IVCL (DZRX), VEC_DZRX, { &dz_rxinta, &dz_txinta } }; - -UNIT dz_unit = { UDATA (&dz_svc, UNIT_ATTABLE + DZ_8B_DFLT, 0) }; - -REG dz_nlreg = { DRDATA (NLINES, dz_desc.lines, 6), PV_LEFT }; - -REG dz_reg[] = { - { BRDATA (CSR, dz_csr, DEV_RDX, 16, DZ_MUXES) }, - { BRDATA (RBUF, dz_rbuf, DEV_RDX, 16, DZ_MUXES) }, - { BRDATA (LPR, dz_lpr, DEV_RDX, 16, DZ_MUXES) }, - { BRDATA (TCR, dz_tcr, DEV_RDX, 16, DZ_MUXES) }, - { BRDATA (MSR, dz_msr, DEV_RDX, 16, DZ_MUXES) }, - { BRDATA (TDR, dz_tdr, DEV_RDX, 16, DZ_MUXES) }, - { BRDATA (SAENB, dz_sae, DEV_RDX, 1, DZ_MUXES) }, - { GRDATA (RXINT, dz_rxi, DEV_RDX, DZ_MUXES, 0) }, - { GRDATA (TXINT, dz_txi, DEV_RDX, DZ_MUXES, 0) }, - { FLDATA (MDMCTL, dz_mctl, 0) }, - { FLDATA (AUTODS, dz_auto, 0) }, - { GRDATA (DEVADDR, dz_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, dz_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -MTAB dz_mod[] = { - { UNIT_8B, 0, "7b", "7B", NULL }, - { UNIT_8B, UNIT_8B, "8b", "8B", NULL }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &dz_desc }, - { UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &dz_summ }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &dz_show, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &dz_show, NULL }, - { MTAB_XTD|MTAB_VDV, 010, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &dz_show_vec, NULL }, -#if !defined (VM_PDP10) - { MTAB_XTD | MTAB_VDV, 0, NULL, "AUTOCONFIGURE", - &set_addr_flt, NULL, NULL }, -#endif - { MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES", - &dz_setnl, NULL, &dz_nlreg }, - { 0 } }; - -DEVICE dz_dev = { - "DZ", &dz_unit, dz_reg, dz_mod, - 1, DEV_RDX, 8, 1, DEV_RDX, 8, - &tmxr_ex, &tmxr_dep, &dz_reset, - NULL, &dz_attach, &dz_detach, - &dz_dib, DEV_FLTA | DEV_DISABLE | DEV_NET | DEV_UBUS | DEV_QBUS }; - -/* IO dispatch routines, I/O addresses 177601x0 - 177601x7 */ - -t_stat dz_rd (int32 *data, int32 PA, int32 access) -{ -int32 dz = ((PA - dz_dib.ba) >> 3) & DZ_MNOMASK; /* get mux num */ - -switch ((PA >> 1) & 03) { /* case on PA<2:1> */ -case 00: /* CSR */ - *data = dz_csr[dz] = dz_csr[dz] & ~CSR_MBZ; - break; -case 01: /* RBUF */ - dz_csr[dz] = dz_csr[dz] & ~CSR_SA; /* clr silo alarm */ - if (dz_csr[dz] & CSR_MSE) { /* scanner on? */ - dz_rbuf[dz] = dz_getc (dz); /* get top of silo */ - if (!dz_rbuf[dz]) dz_sae[dz] = 1; /* empty? re-enable */ - tmxr_poll_rx (&dz_desc); /* poll input */ - dz_update_rcvi (); } /* update rx intr */ - else { - dz_rbuf[dz] = 0; /* no data */ - dz_update_rcvi (); } /* no rx intr */ - *data = dz_rbuf[dz]; - break; -case 02: /* TCR */ - *data = dz_tcr[dz]; - break; -case 03: /* MSR */ - *data = dz_msr[dz]; - break; } -return SCPE_OK; -} - -t_stat dz_wr (int32 data, int32 PA, int32 access) -{ -int32 dz = ((PA - dz_dib.ba) >> 3) & DZ_MNOMASK; /* get mux num */ -int32 i, line; -TMLN *lp; - -switch ((PA >> 1) & 03) { /* case on PA<2:1> */ -case 00: /* CSR */ - if (access == WRITEB) data = (PA & 1)? /* byte? merge */ - (dz_csr[dz] & 0377) | (data << 8): - (dz_csr[dz] & ~0377) | data; - if (data & CSR_CLR) dz_clear (dz, FALSE); /* clr? reset */ - if (data & CSR_MSE) sim_activate (&dz_unit, tmxr_poll); - else dz_csr[dz] &= ~(CSR_SA | CSR_RDONE | CSR_TRDY); - if ((data & CSR_RIE) == 0) dz_clr_rxint (dz); /* RIE = 0? */ - else if (((dz_csr[dz] & CSR_IE) == 0) && /* RIE 0->1? */ - ((dz_csr[dz] & CSR_SAE)? - (dz_csr[dz] & CSR_SA): (dz_csr[dz] & CSR_RDONE))) - dz_set_rxint (dz); - if ((data & CSR_TIE) == 0) dz_clr_txint (dz); /* TIE = 0? */ - else if (((dz_csr[dz] & CSR_TIE) == 0) && (dz_csr[dz] & CSR_TRDY)) - dz_set_txint (dz); - dz_csr[dz] = (dz_csr[dz] & ~CSR_RW) | (data & CSR_RW); - break; -case 01: /* LPR */ - dz_lpr[dz] = data; - line = (dz * DZ_LINES) + LPR_GETLN (data); /* get line num */ - lp = &dz_ldsc[line]; /* get line desc */ - if (dz_lpr[dz] & LPR_RCVE) lp->rcve = 1; /* rcv enb? on */ - else lp->rcve = 0; /* else line off */ - tmxr_poll_rx (&dz_desc); /* poll input */ - dz_update_rcvi (); /* update rx intr */ - break; -case 02: /* TCR */ - if (access == WRITEB) data = (PA & 1)? /* byte? merge */ - (dz_tcr[dz] & 0377) | (data << 8): - (dz_tcr[dz] & ~0377) | data; - if (dz_mctl) { /* modem ctl? */ - dz_msr[dz] |= ((data & 0177400) & /* dcd |= dtr & ring */ - ((dz_msr[dz] & DZ_LMASK) << MSR_V_CD)); - dz_msr[dz] &= ~(data >> TCR_V_DTR); /* ring &= ~dtr */ - if (dz_auto) { /* auto disconnect? */ - int32 drop; - drop = (dz_tcr[dz] & ~data) >> TCR_V_DTR; /* drop = dtr & ~data */ - for (i = 0; i < DZ_LINES; i++) { /* drop hangups */ - line = (dz * DZ_LINES) + i; /* get line num */ - lp = &dz_ldsc[line]; /* get line desc */ - if (lp->conn && (drop & (1 << i))) { - tmxr_msg (lp->conn, "\r\nLine hangup\r\n"); - tmxr_reset_ln (lp); /* reset line, cdet */ - dz_msr[dz] &= ~(1 << (i + MSR_V_CD)); - } /* end if drop */ - } /* end for */ - } /* end if auto */ - } /* end if modem */ - dz_tcr[dz] = data; - tmxr_poll_tx (&dz_desc); /* poll output */ - dz_update_xmti (); /* update int */ - break; -case 03: /* TDR */ - if (PA & 1) { /* odd byte? */ - dz_tdr[dz] = (dz_tdr[dz] & 0377) | (data << 8); /* just save */ - break; } - dz_tdr[dz] = data; - if (dz_csr[dz] & CSR_MSE) { /* enabled? */ - line = (dz * DZ_LINES) + CSR_GETTL (dz_csr[dz]); - lp = &dz_ldsc[line]; /* get line desc */ - tmxr_putc_ln (lp, dz_tdr[dz] & /* store char */ - ((dz_unit.flags & UNIT_8B)? 0377: 0177)); - tmxr_poll_tx (&dz_desc); /* poll output */ - dz_update_xmti (); } /* update int */ - break; } -return SCPE_OK; -} - -/* Unit service routine - - The DZ11 polls to see if asynchronous activity has occurred and now - needs to be processed. The polling interval is controlled by the clock - simulator, so for most environments, it is calibrated to real time. - Typical polling intervals are 50-60 times per second. - - The simulator assumes that software enables all of the multiplexors, - or none of them. -*/ - -t_stat dz_svc (UNIT *uptr) -{ -int32 dz, t, newln; - -for (dz = t = 0; dz < DZ_MUXES; dz++) /* check enabled */ - t = t | (dz_csr[dz] & CSR_MSE); -if (t) { /* any enabled? */ - newln = tmxr_poll_conn (&dz_desc); /* poll connect */ - if ((newln >= 0) && dz_mctl) { /* got a live one? */ - dz = newln / DZ_LINES; /* get mux num */ - if (dz_tcr[dz] & (1 << (newln + TCR_V_DTR))) /* DTR set? */ - dz_msr[dz] |= (1 << (newln + MSR_V_CD)); /* set cdet */ - else dz_msr[dz] |= (1 << newln); } /* set ring */ - tmxr_poll_rx (&dz_desc); /* poll input */ - dz_update_rcvi (); /* upd rcv intr */ - tmxr_poll_tx (&dz_desc); /* poll output */ - dz_update_xmti (); /* upd xmt intr */ - sim_activate (uptr, tmxr_poll); } /* reactivate */ -return SCPE_OK; -} - -/* Get first available character for mux, if any */ - -int32 dz_getc (int32 dz) -{ -uint32 i, line, c; - -for (i = c = 0; (i < DZ_LINES) && (c == 0); i++) { /* loop thru lines */ - line = (dz * DZ_LINES) + i; /* get line num */ - c = tmxr_getc_ln (&dz_ldsc[line]); /* test for input */ - if (c & SCPE_BREAK) c = RBUF_VALID | RBUF_FRME; /* break? frame err */ - if (c) c = c | (i << RBUF_V_RLINE); /* or in line # */ - } /* end for */ -return c; -} - -/* Update receive interrupts */ - -void dz_update_rcvi (void) -{ -int32 i, dz, line, scnt[DZ_MUXES]; -TMLN *lp; - -for (dz = 0; dz < DZ_MUXES; dz++) { /* loop thru muxes */ - scnt[dz] = 0; /* clr input count */ - for (i = 0; i < DZ_LINES; i++) { /* poll lines */ - line = (dz * DZ_LINES) + i; /* get line num */ - lp = &dz_ldsc[line]; /* get line desc */ - scnt[dz] = scnt[dz] + tmxr_rqln (lp); /* sum buffers */ - if (dz_mctl && !lp->conn) /* if disconn */ - dz_msr[dz] &= ~(1 << (i + MSR_V_CD)); /* reset car det */ - } - } -for (dz = 0; dz < DZ_MUXES; dz++) { /* loop thru muxes */ - if (scnt[dz] && (dz_csr[dz] & CSR_MSE)) { /* input & enabled? */ - dz_csr[dz] |= CSR_RDONE; /* set done */ - if (dz_sae[dz] && (scnt[dz] >= DZ_SILO_ALM)) { /* alm enb & cnt hi? */ - dz_csr[dz] |= CSR_SA; /* set status */ - dz_sae[dz] = 0; } } /* disable alarm */ - else dz_csr[dz] &= ~CSR_RDONE; /* no, clear done */ - if ((dz_csr[dz] & CSR_RIE) && /* int enable */ - ((dz_csr[dz] & CSR_SAE)? - (dz_csr[dz] & CSR_SA): (dz_csr[dz] & CSR_RDONE))) - dz_set_rxint (dz); /* and alm/done? */ - else dz_clr_rxint (dz); /* no, clear int */ - } -return; -} - -/* Update transmit interrupts */ - -void dz_update_xmti (void) -{ -int32 dz, linemask, i, j, line; - -for (dz = 0; dz < DZ_MUXES; dz++) { /* loop thru muxes */ - linemask = dz_tcr[dz] & DZ_LMASK; /* enabled lines */ - dz_csr[dz] &= ~CSR_TRDY; /* assume not rdy */ - j = CSR_GETTL (dz_csr[dz]); /* start at current */ - for (i = 0; i < DZ_LINES; i++) { /* loop thru lines */ - j = (j + 1) & DZ_LNOMASK; /* next line */ - line = (dz * DZ_LINES) + j; /* get line num */ - if ((linemask & (1 << j)) && dz_ldsc[line].xmte) { - CSR_PUTTL (dz_csr[dz], j); /* put ln in csr */ - dz_csr[dz] |= CSR_TRDY; /* set xmt rdy */ - break; } } - if ((dz_csr[dz] & CSR_TIE) && (dz_csr[dz] & CSR_TRDY)) /* ready plus int? */ - dz_set_txint (dz); - else dz_clr_txint (dz); /* no int req */ - } -return; -} - -/* Interrupt routines */ - -void dz_clr_rxint (int32 dz) -{ -dz_rxi = dz_rxi & ~(1 << dz); /* clr mux rcv int */ -if (dz_rxi == 0) CLR_INT (DZRX); /* all clr? */ -else SET_INT (DZRX); /* no, set intr */ -return; -} - -void dz_set_rxint (int32 dz) -{ -dz_rxi = dz_rxi | (1 << dz); /* set mux rcv int */ -SET_INT (DZRX); /* set master intr */ -return; -} - -int32 dz_rxinta (void) -{ -int32 dz; - -for (dz = 0; dz < DZ_MUXES; dz++) { /* find 1st mux */ - if (dz_rxi & (1 << dz)) { - dz_clr_rxint (dz); /* clear intr */ - return (dz_dib.vec + (dz * 010)); } } /* return vector */ -return 0; -} - -void dz_clr_txint (int32 dz) -{ -dz_txi = dz_txi & ~(1 << dz); /* clr mux xmt int */ -if (dz_txi == 0) CLR_INT (DZTX); /* all clr? */ -else SET_INT (DZTX); /* no, set intr */ -return; -} - -void dz_set_txint (int32 dz) -{ -dz_txi = dz_txi | (1 << dz); /* set mux xmt int */ -SET_INT (DZTX); /* set master intr */ -return; -} - -int32 dz_txinta (void) -{ -int32 dz; - -for (dz = 0; dz < DZ_MUXES; dz++) { /* find 1st mux */ - if (dz_txi & (1 << dz)) { - dz_clr_txint (dz); /* clear intr */ - return (dz_dib.vec + 4 + (dz * 010)); } } /* return vector */ -return 0; -} - -/* Device reset */ - -t_stat dz_clear (int32 dz, t_bool flag) -{ -int32 i, line; - -dz_csr[dz] = 0; /* clear CSR */ -dz_rbuf[dz] = 0; /* silo empty */ -dz_lpr[dz] = 0; /* no params */ -if (flag) dz_tcr[dz] = 0; /* INIT? clr all */ -else dz_tcr[dz] &= ~0377; /* else save dtr */ -dz_tdr[dz] = 0; -dz_sae[dz] = 1; /* alarm on */ -dz_clr_rxint (dz); /* clear int */ -dz_clr_txint (dz); -for (i = 0; i < DZ_LINES; i++) { /* loop thru lines */ - line = (dz * DZ_LINES) + i; - if (!dz_ldsc[line].conn) dz_ldsc[line].xmte = 1;/* set xmt enb */ - dz_ldsc[line].rcve = 0; } /* clr rcv enb */ -return SCPE_OK; -} - -t_stat dz_reset (DEVICE *dptr) -{ -int32 i, ndev; - -for (i = 0; i < (DZ_MUXES * DZ_LINES); i++) /* init mux desc */ - dz_desc.ldsc[i] = &dz_ldsc[i]; -for (i = 0; i < DZ_MUXES; i++) dz_clear (i, TRUE); /* init muxes */ -dz_rxi = dz_txi = 0; /* clr master int */ -CLR_INT (DZRX); -CLR_INT (DZTX); -sim_cancel (&dz_unit); /* stop poll */ -ndev = ((dptr->flags & DEV_DIS)? 0: (dz_desc.lines / DZ_LINES)); -return auto_config (RANK_DZ, ndev); /* auto config */ -} - -/* Attach */ - -t_stat dz_attach (UNIT *uptr, char *cptr) -{ -t_stat r; -extern int32 sim_switches; - -dz_mctl = dz_auto = 0; /* modem ctl off */ -r = tmxr_attach (&dz_desc, uptr, cptr); /* attach mux */ -if (r != SCPE_OK) return r; /* error? */ -if (sim_switches & SWMASK ('M')) { /* modem control? */ - dz_mctl = 1; - printf ("Modem control activated\n"); - if (sim_log) fprintf (sim_log, "Modem control activated\n"); - if (sim_switches & SWMASK ('A')) { /* autodisconnect? */ - dz_auto = 1; - printf ("Auto disconnect activated\n"); - if (sim_log) fprintf (sim_log, "Auto disconnect activated\n"); - } - } -return SCPE_OK; -} - -/* Detach */ - -t_stat dz_detach (UNIT *uptr) -{ -return tmxr_detach (&dz_desc, uptr); -} - -/* Show summary processor */ - -t_stat dz_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < dz_desc.lines; i++) { /* get num conn */ - if (dz_ldsc[i].conn) t = t + 1; } -if (t == 1) fprintf (st, "1 connection"); -else fprintf (st, "%d connections", t); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat dz_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < dz_desc.lines; i++) { /* loop thru conn */ - if (dz_ldsc[i].conn) { - t = 1; - if (val) tmxr_fconns (st, &dz_ldsc[i], i); - else tmxr_fstats (st, &dz_ldsc[i], i); } } -if (t == 0) fprintf (st, "all disconnected\n"); -return SCPE_OK; -} - -/* SET LINES processor */ - -t_stat dz_setnl (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 newln, i, t, ndev; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -newln = (int32) get_uint (cptr, 10, (DZ_MUXES * DZ_LINES), &r); -if ((r != SCPE_OK) || (newln == dz_desc.lines)) return r; -if ((newln == 0) || (newln % DZ_LINES)) return SCPE_ARG; -if (newln < dz_desc.lines) { - for (i = newln, t = 0; i < dz_desc.lines; i++) t = t | dz_ldsc[i].conn; - if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) - return SCPE_OK; - for (i = newln; i < dz_desc.lines; i++) { - if (dz_ldsc[i].conn) { - tmxr_msg (dz_ldsc[i].conn, "\r\nOperator disconnected line\r\n"); - tmxr_reset_ln (&dz_ldsc[i]); } /* reset line */ - if ((i % DZ_LINES) == (DZ_LINES - 1)) - dz_clear (i / DZ_LINES, TRUE); } /* reset mux */ - } -dz_dib.lnt = (newln / DZ_LINES) * IOLN_DZ; /* set length */ -dz_desc.lines = newln; -ndev = ((dz_dev.flags & DEV_DIS)? 0: (dz_desc.lines / DZ_LINES)); -return auto_config (RANK_DZ, ndev); /* auto config */ -} - -/* SHOW VECTOR processor */ - -t_stat dz_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -return show_vec (st, uptr, ((dz_desc.lines * 2) / DZ_LINES), desc); -} diff --git a/PDP11/pdp11_fp.c b/PDP11/pdp11_fp.c deleted file mode 100644 index 50185330..00000000 --- a/PDP11/pdp11_fp.c +++ /dev/null @@ -1,1008 +0,0 @@ -/* pdp11_fp.c: PDP-11 floating point simulator (32b version) - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict - 08-Oct-02 RMS Fixed macro definitions - 05-Jun-98 RMS Fixed implementation specific shift bugs - 20-Apr-98 RMS Fixed bug in MODf integer truncation - 17-Apr-98 RMS Fixed bug in STCfi range check - 16-Apr-98 RMS Fixed bugs in STEXP, STCfi, round/pack - 09-Apr-98 RMS Fixed bug in LDEXP - 04-Apr-98 RMS Fixed bug in MODf condition codes - - This module simulates the PDP-11 floating point unit (FP11 series). - It is called from the instruction decoder for opcodes 170000:177777. - - The floating point unit recognizes three instruction formats: - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ no operand - | 1 1 1 1| 0 0 0 0 0 0| opcode | 170000: - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 170077 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ one operand - | 1 1 1 1| 0 0 0| opcode | dest spec | 170100: - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 170777 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ register + operand - | 1 1 1 1| opcode | fac | dest spec | 171000: - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 177777 - - The instruction space is further extended through use of the floating - point status register (FPS) mode bits. Three mode bits affect how - instructions are interpreted: - - FPS_D if 0, floating registers are single precision - if 1, floating registers are double precision - - FPS_L if 0, integer operands are word - if 1, integer operands are longword - - FPS_T if 0, floating operations are rounded - if 1, floating operations are truncated - - FPS also contains the condition codes for the floating point unit, - and exception enable bits for individual error conditions. Exceptions - cause a trap through 0244, unless the individual exception, or all - exceptions, are disabled. Illegal address mode, undefined variable, - and divide by zero abort the current instruction; all other exceptions - permit the instruction to complete. (Aborts are implemented as traps - that request an "interrupt" trap. If an interrupt is pending, it is - serviced; if not, trap_req is updated and processing continues.) - - Floating point specifiers are similar to integer specifiers, with - the length of the operand being up to 8 bytes. In two specific cases, - the floating point unit reads or writes only two bytes, rather than - the length specified by the operand type: - - register for integers, only 16b are accessed; if the - operand is 32b, these are the high order 16b - of the operand - - immediate for integers or floating point, only 16b are - accessed; if the operand is 32b or 64b, these - are the high order 16b of the operand -*/ - -#include "pdp11_defs.h" - -/* Floating point status register */ - -#define FPS_ER (1u << FPS_V_ER) /* error */ -#define FPS_ID (1u << FPS_V_ID) /* interrupt disable */ -#define FPS_IUV (1u << FPS_V_IUV) /* int on undef var */ -#define FPS_IU (1u << FPS_V_IU) /* int on underflow */ -#define FPS_IV (1u << FPS_V_IV) /* int on overflow */ -#define FPS_IC (1u << FPS_V_IC) /* int on conv error */ -#define FPS_D (1u << FPS_V_D) /* single/double */ -#define FPS_L (1u << FPS_V_L) /* word/long */ -#define FPS_T (1u << FPS_V_T) /* round/truncate */ -#define FPS_N (1u << FPS_V_N) -#define FPS_Z (1u << FPS_V_Z) -#define FPS_V (1u << FPS_V_V) -#define FPS_C (1u << FPS_V_C) -#define FPS_CC (FPS_N + FPS_Z + FPS_V + FPS_C) -#define FPS_RW (FPS_ER + FPS_ID + FPS_IUV + FPS_IU + FPS_IV + \ - FPS_IC + FPS_D + FPS_L + FPS_T + FPS_CC) - -/* Floating point exception codes */ - -#define FEC_OP 2 /* illegal op/mode */ -#define FEC_DZRO 4 /* divide by zero */ -#define FEC_ICVT 6 /* conversion error */ -#define FEC_OVFLO 8 /* overflow */ -#define FEC_UNFLO 10 /* underflow */ -#define FEC_UNDFV 12 /* undef variable */ - -/* Floating point format, all assignments 32b relative */ - -#define FP_V_SIGN (63 - 32) /* high lw: sign */ -#define FP_V_EXP (55 - 32) /* exponent */ -#define FP_V_HB FP_V_EXP /* hidden bit */ -#define FP_V_F0 (48 - 32) /* fraction 0 */ -#define FP_V_F1 (32 - 32) /* fraction 1 */ -#define FP_V_FROUND (31 - 32) /* f round point */ -#define FP_V_F2 16 /* low lw: fraction 2 */ -#define FP_V_F3 0 /* fraction 3 */ -#define FP_V_DROUND (-1) /* d round point */ -#define FP_M_EXP 0377 -#define FP_SIGN (1u << FP_V_SIGN) -#define FP_EXP (FP_M_EXP << FP_V_EXP) -#define FP_HB (1u << FP_V_HB) -#define FP_FRACH ((1u << FP_V_HB) - 1) -#define FP_FRACL 0xFFFFFFFF -#define FP_BIAS 0200 /* exponent bias */ -#define FP_GUARD 3 /* guard bits */ - -/* Data lengths */ - -#define WORD 2 -#define LONG 4 -#define QUAD 8 - -/* Double precision operations on 64b quantities */ - -#define F_LOAD(qd,ac,ds) ds.h = ac.h; ds.l = (qd)? ac.l: 0 -#define F_LOAD_P(qd,ac,ds) ds->h = ac.h; ds->l = (qd)? ac.l: 0 -#define F_LOAD_FRAC(qd,ac,ds) ds.h = (ac.h & FP_FRACH) | FP_HB; \ - ds.l = (qd)? ac.l: 0 -#define F_STORE(qd,sr,ac) ac.h = sr.h; if ((qd)) ac.l = sr.l -#define F_STORE_P(qd,sr,ac) ac.h = sr->h; if ((qd)) ac.l = sr->l -#define F_GET_FRAC_P(sr,ds) ds.l = sr->l; \ - ds.h = (sr->h & FP_FRACH) | FP_HB -#define F_ADD(s2,s1,ds) ds.l = (s1.l + s2.l) & 0xFFFFFFFF; \ - ds.h = (s1.h + s2.h + (ds.l < s2.l)) & 0xFFFFFFFF -#define F_SUB(s2,s1,ds) ds.h = (s1.h - s2.h - (s1.l < s2.l)) & 0xFFFFFFFF; \ - ds.l = (s1.l - s2.l) & 0xFFFFFFFF -#define F_LT(x,y) ((x.h < y.h) || ((x.h == y.h) && (x.l < y.l))) -#define F_LT_AP(x,y) (((x->h & ~FP_SIGN) < (y->h & ~FP_SIGN)) || \ - (((x->h & ~FP_SIGN) == (y->h & ~FP_SIGN)) && (x->l < y->l))) -#define F_LSH_V(sr,n,ds) \ - ds.h = (((n) >= 32)? (sr.l << ((n) - 32)): \ - (sr.h << (n)) | ((sr.l >> (32 - (n))) & and_mask[n])) \ - & 0xFFFFFFFF; \ - ds.l = ((n) >= 32)? 0: (sr.l << (n)) & 0xFFFFFFFF -#define F_RSH_V(sr,n,ds) \ - ds.l = (((n) >= 32)? (sr.h >> ((n) - 32)) & and_mask[64 - (n)]: \ - ((sr.l >> (n)) & and_mask[32 - (n)]) | \ - (sr.h << (32 - (n)))) & 0xFFFFFFFF; \ - ds.h = ((n) >= 32)? 0: \ - ((sr.h >> (n)) & and_mask[32 - (n)]) & 0xFFFFFFFF - -/* For the constant shift macro, arguments must in the range [2,31] */ - -#define F_LSH_1(ds) ds.h = ((ds.h << 1) | ((ds.l >> 31) & 1)) & 0xFFFFFFFF; \ - ds.l = (ds.l << 1) & 0xFFFFFFFF -#define F_RSH_1(ds) ds.l = ((ds.l >> 1) & 0x7FFFFFFF) | ((ds.h & 1) << 31); \ - ds.h = ((ds.h >> 1) & 0x7FFFFFFF) -#define F_LSH_K(sr,n,ds) \ - ds.h = ((sr.h << (n)) | ((sr.l >> (32 - (n))) & and_mask[n])) \ - & 0xFFFFFFFF; \ - ds.l = (sr.l << (n)) & 0xFFFFFFFF -#define F_RSH_K(sr,n,ds) \ - ds.l = (((sr.l >> (n)) & and_mask[32 - (n)]) | \ - (sr.h << (32 - (n)))) & 0xFFFFFFFF; \ - ds.h = ((sr.h >> (n)) & and_mask[32 - (n)]) & 0xFFFFFFFF -#define F_LSH_GUARD(ds) F_LSH_K(ds,FP_GUARD,ds) -#define F_RSH_GUARD(ds) F_RSH_K(ds,FP_GUARD,ds) - -#define GET_BIT(ir,n) (((ir) >> (n)) & 1) -#define GET_SIGN(ir) GET_BIT((ir), FP_V_SIGN) -#define GET_EXP(ir) (((ir) >> FP_V_EXP) & FP_M_EXP) -#define GET_SIGN_L(ir) GET_BIT((ir), 31) -#define GET_SIGN_W(ir) GET_BIT((ir), 15) - -extern jmp_buf save_env; -extern int32 FEC, FEA, FPS; -extern int32 CPUERR, trap_req; -extern int32 N, Z, V, C; -extern int32 R[8]; -extern fpac_t FR[6]; - -fpac_t zero_fac = { 0, 0 }; -fpac_t one_fac = { 1, 0 }; -fpac_t fround_fac = { (1u << (FP_V_FROUND + 32)), 0 }; -fpac_t fround_guard_fac = { 0, (1u << (FP_V_FROUND + FP_GUARD)) }; -fpac_t dround_guard_fac = { (1u << (FP_V_DROUND + FP_GUARD)), 0 }; -fpac_t fmask_fac = { 0xFFFFFFFF, (1u << (FP_V_HB + FP_GUARD + 1)) - 1 }; -static const uint32 and_mask[33] = { 0, - 0x1, 0x3, 0x7, 0xF, - 0x1F, 0x3F, 0x7F, 0xFF, - 0x1FF, 0x3FF, 0x7FF, 0xFFF, - 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, - 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, - 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF, - 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, - 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF }; -int32 backup_PC; -int32 fpnotrap (int32 code); -int32 GeteaFP (int32 spec, int32 len); - -unsigned int32 ReadI (int32 addr, int32 spec, int32 len); -void ReadFP (fpac_t *fac, int32 addr, int32 spec, int32 len); -void WriteI (int32 data, int32 addr, int32 spec, int32 len); -void WriteFP (fpac_t *data, int32 addr, int32 spec, int32 len); -int32 setfcc (int32 old_status, int32 result_high, int32 newV); -int32 addfp11 (fpac_t *src1, fpac_t *src2); -int32 mulfp11 (fpac_t *src1, fpac_t *src2); -int32 divfp11 (fpac_t *src1, fpac_t *src2); -int32 modfp11 (fpac_t *src1, fpac_t *src2, fpac_t *frac); -void frac_mulfp11 (fpac_t *src1, fpac_t *src2); -int32 roundfp11 (fpac_t *src); -int32 round_and_pack (fpac_t *fac, int32 exp, fpac_t *frac, int r); - -extern int32 GeteaW (int32 spec); -extern int32 ReadW (int32 addr); -extern void WriteW (int32 data, int32 addr); - -/* Set up for instruction decode and execution */ - -void fp11 (int32 IR) -{ -int32 dst, ea, ac, dstspec; -int32 i, qdouble, lenf, leni; -int32 newV, exp, sign; -fpac_t fac, fsrc, modfrac; -static const unsigned int32 i_limit[2][2] = - { { 0x80000000, 0x80010000 }, { 0x80000000, 0x80000001 } }; - -backup_PC = PC; /* save PC for FEA */ -ac = (IR >> 6) & 03; /* fac is IR<7:6> */ -dstspec = IR & 077; -qdouble = FPS & FPS_D; -lenf = qdouble? QUAD: LONG; -switch ((IR >> 8) & 017) { /* decode IR<11:8> */ -case 0: - switch (ac) { /* decode IR<7:6> */ - case 0: /* specials */ - if (IR == 0170000) { /* CFCC */ - N = (FPS >> PSW_V_N) & 1; - Z = (FPS >> PSW_V_Z) & 1; - V = (FPS >> PSW_V_V) & 1; - C = (FPS >> PSW_V_C) & 1; } - else if (IR == 0170001) /* SETF */ - FPS = FPS & ~FPS_D; - else if (IR == 0170002) /* SETI */ - FPS = FPS & ~FPS_L; - else if (IR == 0170011) /* SETD */ - FPS = FPS | FPS_D; - else if (IR == 0170012) /* SETL */ - FPS = FPS | FPS_L; - else fpnotrap (FEC_OP); - break; - case 1: /* LDFPS */ - dst = (dstspec <= 07)? R[dstspec]: ReadW (GeteaW (dstspec)); - FPS = dst & FPS_RW; - break; - case 2: /* STFPS */ - FPS = FPS & FPS_RW; - if (dstspec <= 07) R[dstspec] = FPS; - else WriteW (FPS, GeteaW (dstspec)); - break; - case 3: /* STST */ - if (dstspec <= 07) R[dstspec] = FEC; - else WriteI ((FEC << 16) | FEA, GeteaFP (dstspec, LONG), - dstspec, LONG); - break; } /* end switch <7:6> */ - break; /* end case 0 */ - -/* "Easy" instructions */ - -case 1: - switch (ac) { /* decode IR<7:6> */ - case 0: /* CLRf */ - WriteFP (&zero_fac, GeteaFP (dstspec, lenf), dstspec, lenf); - FPS = (FPS & ~FPS_CC) | FPS_Z; - break; - case 1: /* TSTf */ - ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); - FPS = setfcc (FPS, fsrc.h, 0); - break; - case 2: /* ABSf */ - ReadFP (&fsrc, ea = GeteaFP (dstspec, lenf), dstspec, lenf); - if (GET_EXP (fsrc.h) == 0) fsrc = zero_fac; - else fsrc.h = fsrc.h & ~FP_SIGN; - WriteFP (&fsrc, ea, dstspec, lenf); - FPS = setfcc (FPS, fsrc.h, 0); - break; - case 3: /* NEGf */ - ReadFP (&fsrc, ea = GeteaFP (dstspec, lenf), dstspec, lenf); - if (GET_EXP (fsrc.h) == 0) fsrc = zero_fac; - else fsrc.h = fsrc.h ^ FP_SIGN; - WriteFP (&fsrc, ea, dstspec, lenf); - FPS = setfcc (FPS, fsrc.h, 0); - break; } /* end switch <7:6> */ - break; /* end case 1 */ -case 5: /* LDf */ - ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); - F_STORE (qdouble, fsrc, FR[ac]); - FPS = setfcc (FPS, fsrc.h, 0); - break; -case 010: /* STf */ - F_LOAD (qdouble, FR[ac], fac); - WriteFP (&fac, GeteaFP (dstspec, lenf), dstspec, lenf); - break; -case 017: /* LDCff' */ - ReadFP (&fsrc, GeteaFP (dstspec, 12 - lenf), dstspec, 12 - lenf); - if (GET_EXP (fsrc.h) == 0) fsrc = zero_fac; - if ((FPS & (FPS_D + FPS_T)) == 0) newV = roundfp11 (&fsrc); - else newV = 0; - F_STORE (qdouble, fsrc, FR[ac]); - FPS = setfcc (FPS, fsrc.h, newV); - break; -case 014: /* STCff' */ - F_LOAD (qdouble, FR[ac], fac); - if (GET_EXP (fac.h) == 0) fac = zero_fac; - if ((FPS & (FPS_D + FPS_T)) == FPS_D) newV = roundfp11 (&fac); - else newV = 0; - WriteFP (&fac, GeteaFP (dstspec, 12 - lenf), dstspec, 12 - lenf); - FPS = setfcc (FPS, fac.h, newV); - break; - -/* Compare instruction */ - -case 7: /* CMPf */ - ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); - F_LOAD (qdouble, FR[ac], fac); - if (GET_EXP (fsrc.h) == 0) fsrc = zero_fac; - if (GET_EXP (fac.h) == 0) fac = zero_fac; - if ((fsrc.h == fac.h) && (fsrc.l == fac.l)) { /* equal? */ - FPS = (FPS & ~FPS_CC) | FPS_Z; - if ((fsrc.h | fsrc.l) == 0) { /* zero? */ - F_STORE (qdouble, zero_fac, FR[ac]); } - break; } - FPS = (FPS & ~FPS_CC) | ((fsrc.h >> (FP_V_SIGN - PSW_V_N)) & FPS_N); - if ((GET_SIGN (fsrc.h ^ fac.h) == 0) && (fac.h != 0) && - F_LT (fsrc, fac)) FPS = FPS ^ FPS_N; - break; - -/* Load and store exponent instructions */ - -case 015: /* LDEXP */ - dst = (dstspec <= 07)? R[dstspec]: ReadW (GeteaW (dstspec)); - F_LOAD (qdouble, FR[ac], fac); - fac.h = (fac.h & ~FP_EXP) | (((dst + FP_BIAS) & FP_M_EXP) << FP_V_EXP); - newV = 0; - if ((dst > 0177) && (dst <= 0177600)) { - if (dst < 0100000) { - if (fpnotrap (FEC_OVFLO)) fac = zero_fac; - newV = FPS_V; } - else { - if (fpnotrap (FEC_UNFLO)) fac = zero_fac; } } - F_STORE (qdouble, fac, FR[ac]); - FPS = setfcc (FPS, fac.h, newV); - break; -case 012: /* STEXP */ - dst = (GET_EXP (FR[ac].h) - FP_BIAS) & 0177777; - N = GET_SIGN_W (dst); - Z = (dst == 0); - V = 0; - C = 0; - FPS = (FPS & ~FPS_CC) | (N << PSW_V_N) | (Z << PSW_V_Z); - if (dstspec <= 07) R[dstspec] = dst; - else WriteW (dst, GeteaW (dstspec)); - break; - -/* Integer convert instructions */ - -case 016: /* LDCif */ - leni = FPS & FPS_L? LONG: WORD; - if (dstspec <= 07) fac.l = R[dstspec] << 16; - else fac.l = ReadI (GeteaFP (dstspec, leni), dstspec, leni); - fac.h = 0; - if (fac.l) { - if (sign = GET_SIGN_L (fac.l)) fac.l = (fac.l ^ 0xFFFFFFFF) + 1; - for (i = 0; GET_SIGN_L (fac.l) == 0; i++) fac.l = fac.l << 1; - exp = ((FPS & FPS_L)? FP_BIAS + 32: FP_BIAS + 16) - i; - fac.h = (sign << FP_V_SIGN) | (exp << FP_V_EXP) | - ((fac.l >> (31 - FP_V_HB)) & FP_FRACH); - fac.l = (fac.l << (FP_V_HB + 1)) & FP_FRACL; - if ((FPS & (FPS_D + FPS_T)) == 0) roundfp11 (&fac); } - F_STORE (qdouble, fac, FR[ac]); - FPS = setfcc (FPS, fac.h, 0); - break; -case 013: /* STCfi */ - sign = GET_SIGN (FR[ac].h); /* get sign, */ - exp = GET_EXP (FR[ac].h); /* exponent, */ - F_LOAD_FRAC (qdouble, FR[ac], fac); /* fraction */ - if (FPS & FPS_L) { - leni = LONG; - i = FP_BIAS + 32; } - else { - leni = WORD; - i = FP_BIAS + 16; } - C = 0; - if (exp <= FP_BIAS) dst = 0; - else if (exp > i) { - dst = 0; - C = 1; } - else { - F_RSH_V (fac, FP_V_HB + 1 + i - exp, fsrc); - if (leni == WORD) fsrc.l = fsrc.l & ~0177777; - if (fsrc.l >= i_limit[leni == LONG][sign]) { - dst = 0; - C = 1; } - else { - dst = fsrc.l; - if (sign) dst = -dst; } } - N = GET_SIGN_L (dst); - Z = (dst == 0); - V = 0; - if (C) fpnotrap (FEC_ICVT); - FPS = (FPS & ~FPS_CC) | (N << PSW_V_N) | - (Z << PSW_V_Z) | (C << PSW_V_C); - if (dstspec <= 07) R[dstspec] = (dst >> 16) & 0177777; - else WriteI (dst, GeteaFP (dstspec, leni), dstspec, leni); - break; - -/* Calculation instructions */ - -case 2: /* MULf */ - ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); - F_LOAD (qdouble, FR[ac], fac); - newV = mulfp11 (&fac, &fsrc); - F_STORE (qdouble, fac, FR[ac]); - FPS = setfcc (FPS, fac.h, newV); - break; -case 3: /* MODf */ - ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); - F_LOAD (qdouble, FR[ac], fac); - newV = modfp11 (&fac, &fsrc, &modfrac); - F_STORE (qdouble, fac, FR[ac | 1]); - F_STORE (qdouble, modfrac, FR[ac]); - FPS = setfcc (FPS, modfrac.h, newV); - break; -case 4: /* ADDf */ - ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); - F_LOAD (qdouble, FR[ac], fac); - newV = addfp11 (&fac, &fsrc); - F_STORE (qdouble, fac, FR[ac]); - FPS = setfcc (FPS, fac.h, newV); - break; -case 6: /* SUBf */ - ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); - F_LOAD (qdouble, FR[ac], fac); - if (GET_EXP (fsrc.h) != 0) fsrc.h = fsrc.h ^ FP_SIGN; - newV = addfp11 (&fac, &fsrc); - F_STORE (qdouble, fac, FR[ac]); - FPS = setfcc (FPS, fac.h, newV); - break; -case 011: /* DIVf */ - ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); - F_LOAD (qdouble, FR[ac], fac); - newV = divfp11 (&fac, &fsrc); - F_STORE (qdouble, fac, FR[ac]); - FPS = setfcc (FPS, fac.h, newV); - break; } /* end switch fop */ -return; -} - -/* Effective address calculation for fp operands - - Inputs: - spec = specifier - len = length - Outputs: - VA = virtual address - - Warnings: - - Do not call this routine for integer mode 0 operands - - Do not call this routine more than once per instruction -*/ - -int32 GeteaFP (int32 spec, int32 len) -{ -int32 adr, reg, ds; -extern int32 cm, isenable, dsenable, MMR0, MMR1; - -reg = spec & 07; /* reg number */ -ds = (reg == 7)? isenable: dsenable; /* dspace if not PC */ -switch (spec >> 3) { /* case on spec */ -case 0: /* floating AC */ - if (reg >= 06) { fpnotrap (FEC_OP); ABORT (TRAP_INT); } - return 0; -case 1: /* (R) */ - return (R[reg] | ds); -case 2: /* (R)+ */ - if (reg == 7) len = 2; - R[reg] = ((adr = R[reg]) + len) & 0177777; - if (update_MM) MMR1 = (len << 3) | reg; - return (adr | ds); -case 3: /* @(R)+ */ - R[reg] = ((adr = R[reg]) + 2) & 0177777; - if (update_MM) MMR1 = 020 | reg; - adr = ReadW (adr | ds); - return (adr | dsenable); -case 4: /* -(R) */ - adr = R[reg] = (R[reg] - len) & 0177777; - if (update_MM) MMR1 = (((-len) & 037) << 3) | reg; - if ((adr < STKLIM) && (reg == 6) && (cm == MD_KER)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } - return (adr | ds); -case 5: /* @-(R) */ - adr = R[reg] = (R[reg] - 2) & 0177777; - if (update_MM) MMR1 = 0360 | reg; - if ((adr < STKLIM) && (reg == 6) && (cm == MD_KER)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } - adr = ReadW (adr | ds); - return (adr | dsenable); -case 6: /* d(r) */ - adr = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - return (((R[reg] + adr) & 0177777) | dsenable); -case 7: /* @d(R) */ - adr = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - adr = ReadW (((R[reg] + adr) & 0177777) | dsenable); - return (adr | dsenable); } /* end switch */ -return 0; -} - -/* Read integer operand - - Inputs: - VA = virtual address, VA<18:16> = mode, I/D space - spec = specifier - len = length (2/4 bytes) - Outputs: - data = data read from memory or I/O space -*/ - -unsigned int32 ReadI (int32 VA, int32 spec, int32 len) -{ -if ((len == WORD) || (spec == 027)) return (ReadW (VA) << 16); -return ((ReadW (VA) << 16) | ReadW ((VA & ~0177777) | ((VA + 2) & 0177777))); -} - -/* Read floating operand - - Inputs: - fptr = pointer to output - VA = virtual address, VA<18:16> = mode, I/D space - spec = specifier - len = length (4/8 bytes) -*/ - -void ReadFP (fpac_t *fptr, int32 VA, int32 spec, int32 len) -{ -int32 exta; - -if (spec <= 07) { - F_LOAD_P (len == QUAD, FR[spec], fptr); - return; } -if (spec == 027) { - fptr->h = (ReadW (VA) << FP_V_F0); - fptr->l = 0; } -else { exta = VA & ~0177777; - fptr->h = (ReadW (VA) << FP_V_F0) | - (ReadW (exta | ((VA + 2) & 0177777)) << FP_V_F1); - if (len == QUAD) fptr->l = - (ReadW (exta | ((VA + 4) & 0177777)) << FP_V_F2) | - (ReadW (exta | ((VA + 6) & 0177777)) << FP_V_F3); - else fptr->l = 0; } -if ((GET_SIGN (fptr->h) != 0) && (GET_EXP (fptr->h) == 0) && - (fpnotrap (FEC_UNDFV) == 0)) ABORT (TRAP_INT); -return; -} - -/* Write integer result - - Inputs: - data = data to be written - VA = virtual address, VA<18:16> = mode, I/D space - spec = specifier - len = length - Outputs: none -*/ - -void WriteI (int32 data, int32 VA, int32 spec, int32 len) -{ -WriteW ((data >> 16) & 0177777, VA); -if ((len == WORD) || (spec == 027)) return; -WriteW (data & 0177777, (VA & ~0177777) | ((VA + 2) & 0177777)); -return; -} - -/* Write floating result - - Inputs: - fptr = pointer to data to be written - VA = virtual address, VA<18:16> = mode, I/D space - spec = specifier - len = length - Outputs: none -*/ - -void WriteFP (fpac_t *fptr, int32 VA, int32 spec, int32 len) -{ -int32 exta; - -if (spec <= 07) { - F_STORE_P (len == QUAD, fptr, FR[spec]); - return; } -WriteW ((fptr->h >> FP_V_F0) & 0177777, VA); -if (spec == 027) return; -exta = VA & ~0177777; -WriteW ((fptr->h >> FP_V_F1) & 0177777, exta | ((VA + 2) & 0177777)); -if (len == LONG) return; -WriteW ((fptr->l >> FP_V_F2) & 0177777, exta | ((VA + 4) & 0177777)); -WriteW ((fptr->l >> FP_V_F3) & 0177777, exta | ((VA + 6) & 0177777)); -return; -} - -/* Floating point add - - Inputs: - facp = pointer to src1 (output) - fsrcp = pointer to src2 - Outputs: - ovflo = overflow variable -*/ - -int32 addfp11 (fpac_t *facp, fpac_t *fsrcp) -{ -int32 facexp, fsrcexp, ediff; -fpac_t facfrac, fsrcfrac; - -if (F_LT_AP (facp, fsrcp)) { /* if !fac! < !fsrc! */ - facfrac = *facp; - *facp = *fsrcp; /* swap operands */ - *fsrcp = facfrac; } -facexp = GET_EXP (facp->h); /* get exponents */ -fsrcexp = GET_EXP (fsrcp->h); -if (facexp == 0) { /* fac = 0? */ - *facp = fsrcexp? *fsrcp: zero_fac; /* result fsrc or 0 */ - return 0; } -if (fsrcexp == 0) return 0; /* fsrc = 0? no op */ -ediff = facexp - fsrcexp; /* exponent diff */ -if (ediff >= 60) return 0; /* too big? no op */ -F_GET_FRAC_P (facp, facfrac); /* get fractions */ -F_GET_FRAC_P (fsrcp, fsrcfrac); -F_LSH_GUARD (facfrac); /* guard fractions */ -F_LSH_GUARD (fsrcfrac); -if (GET_SIGN (facp->h) != GET_SIGN (fsrcp->h)) { /* signs different? */ - if (ediff) { F_RSH_V (fsrcfrac, ediff, fsrcfrac); } /* sub, shf fsrc */ - F_SUB (fsrcfrac, facfrac, facfrac); /* sub fsrc from fac */ - if ((facfrac.h | facfrac.l) == 0) { /* result zero? */ - *facp = zero_fac; /* no overflow */ - return 0; } - if (ediff <= 1) { /* big normalize? */ - if ((facfrac.h & (0x00FFFFFF << FP_GUARD)) == 0) { - F_LSH_K (facfrac, 24, facfrac); - facexp = facexp - 24; } - if ((facfrac.h & (0x00FFF000 << FP_GUARD)) == 0) { - F_LSH_K (facfrac, 12, facfrac); - facexp = facexp - 12; } - if ((facfrac.h & (0x00FC0000 << FP_GUARD)) == 0) { - F_LSH_K (facfrac, 6, facfrac); - facexp = facexp - 6; } } - while (GET_BIT (facfrac.h, FP_V_HB + FP_GUARD) == 0) { - F_LSH_1 (facfrac); - facexp = facexp - 1; } } -else { if (ediff) { F_RSH_V (fsrcfrac, ediff, fsrcfrac); } /* add, shf fsrc */ - F_ADD (fsrcfrac, facfrac, facfrac); /* add fsrc to fac */ - if (GET_BIT (facfrac.h, FP_V_HB + FP_GUARD + 1)) { - F_RSH_1 (facfrac); /* carry out, shift */ - facexp = facexp + 1; } } -return round_and_pack (facp, facexp, &facfrac, 1); -} - -/* Floating point multiply - - Inputs: - facp = pointer to src1 (output) - fsrcp = pointer to src2 - Outputs: - ovflo = overflow indicator -*/ - -int32 mulfp11 (fpac_t *facp, fpac_t *fsrcp) -{ -int32 facexp, fsrcexp; -fpac_t facfrac, fsrcfrac; - -facexp = GET_EXP (facp->h); /* get exponents */ -fsrcexp = GET_EXP (fsrcp->h); -if ((facexp == 0) || (fsrcexp == 0)) { /* test for zero */ - *facp = zero_fac; - return 0; } -F_GET_FRAC_P (facp, facfrac); /* get fractions */ -F_GET_FRAC_P (fsrcp, fsrcfrac); -facexp = facexp + fsrcexp - FP_BIAS; /* calculate exp */ -facp->h = facp->h ^ fsrcp->h; /* calculate sign */ -frac_mulfp11 (&facfrac, &fsrcfrac); /* multiply fracs */ - -/* Multiplying two numbers in the range [.5,1) produces a result in the - range [.25,1). Therefore, at most one bit of normalization is required - to bring the result back to the range [.5,1). -*/ - -if (GET_BIT (facfrac.h, FP_V_HB + FP_GUARD) == 0) { - F_LSH_1 (facfrac); - facexp = facexp - 1; } -return round_and_pack (facp, facexp, &facfrac, 1); -} - -/* Floating point mod - - Inputs: - facp = pointer to src1 (integer result) - fsrcp = pointer to src2 - fracp = pointer to fractional result - Outputs: - ovflo = overflow indicator - - See notes on multiply for initial operation -*/ - -int32 modfp11 (fpac_t *facp, fpac_t *fsrcp, fpac_t *fracp) -{ -int32 facexp, fsrcexp; -fpac_t facfrac, fsrcfrac, fmask; - -facexp = GET_EXP (facp->h); /* get exponents */ -fsrcexp = GET_EXP (fsrcp->h); -if ((facexp == 0) || (fsrcexp == 0)) { /* test for zero */ - *fracp = zero_fac; - *facp = zero_fac; - return 0; } -F_GET_FRAC_P (facp, facfrac); /* get fractions */ -F_GET_FRAC_P (fsrcp, fsrcfrac); -facexp = facexp + fsrcexp - FP_BIAS; /* calculate exp */ -fracp->h = facp->h = facp->h ^ fsrcp->h; /* calculate sign */ -frac_mulfp11 (&facfrac, &fsrcfrac); /* multiply fracs */ - -/* Multiplying two numbers in the range [.5,1) produces a result in the - range [.25,1). Therefore, at most one bit of normalization is required - to bring the result back to the range [.5,1). -*/ - -if (GET_BIT (facfrac.h, FP_V_HB + FP_GUARD) == 0) { - F_LSH_1 (facfrac); - facexp = facexp - 1; } - -/* There are three major cases of MODf: - - 1. Exp <= FP_BIAS (all fraction). Return 0 as integer, product as - fraction. Underflow can occur. - 2. Exp > FP_BIAS + #fraction bits (all integer). Return product as - integer, 0 as fraction. Overflow can occur. - 3. FP_BIAS < exp <= FP_BIAS + #fraction bits. Separate integer and - fraction and return both. Neither overflow nor underflow can occur. -*/ - - if (facexp <= FP_BIAS) { /* case 1 */ - *facp = zero_fac; - return round_and_pack (fracp, facexp, &facfrac, 1); } - if (facexp > ((FPS & FPS_D)? FP_BIAS + 56: FP_BIAS + 24)) { - *fracp = zero_fac; /* case 2 */ - return round_and_pack (facp, facexp, &facfrac, 0); } - F_RSH_V (fmask_fac, facexp - FP_BIAS, fmask); /* shift mask */ - fsrcfrac.l = facfrac.l & fmask.l; /* extract fraction */ - fsrcfrac.h = facfrac.h & fmask.h; - if ((fsrcfrac.h | fsrcfrac.l) == 0) *fracp = zero_fac; - else { - F_LSH_V (fsrcfrac, facexp - FP_BIAS, fsrcfrac); - fsrcexp = FP_BIAS; - if ((fsrcfrac.h & (0x00FFFFFF << FP_GUARD)) == 0) { - F_LSH_K (fsrcfrac, 24, fsrcfrac); - fsrcexp = fsrcexp - 24; } - if ((fsrcfrac.h & (0x00FFF000 << FP_GUARD)) == 0) { - F_LSH_K (fsrcfrac, 12, fsrcfrac); - fsrcexp = fsrcexp - 12; } - if ((fsrcfrac.h & (0x00FC0000 << FP_GUARD)) == 0) { - F_LSH_K (fsrcfrac, 6, fsrcfrac); - fsrcexp = fsrcexp - 6; } - while (GET_BIT (fsrcfrac.h, FP_V_HB + FP_GUARD) == 0) { - F_LSH_1 (fsrcfrac); - fsrcexp = fsrcexp - 1; } - round_and_pack (fracp, fsrcexp, &fsrcfrac, 1); } - facfrac.l = facfrac.l & ~fmask.l; - facfrac.h = facfrac.h & ~fmask.h; - return round_and_pack (facp, facexp, &facfrac, 0); -} - -/* Fraction multiply - - Inputs: - f1p = pointer to multiplier (output) - f2p = pointer to multiplicand fraction - - Note: the inputs are unguarded; the output is guarded. - - This routine performs a classic shift-and-add multiply. The low - order bit of the multiplier is tested; if 1, the multiplicand is - added into the high part of the double precision result. The - result and the multiplier are both shifted right 1. - - For the 24b x 24b case, this routine develops 48b of result. - For the 56b x 56b case, this routine only develops the top 64b - of the the result. Because the inputs are normalized fractions, - the interesting part of the result is the high 56+guard bits. - Everything shifted off to the right, beyond 64b, plays no part - in rounding or the result. - - There are many possible optimizations in this routine: scanning - for groups of zeroes, particularly in the 56b x 56b case; using - "extended multiply" capability if available in the hardware. -*/ - -void frac_mulfp11 (fpac_t *f1p, fpac_t *f2p) -{ -fpac_t result, mpy, mpc; -int32 i; - -result = zero_fac; /* clear result */ -mpy = *f1p; /* get operands */ -mpc = *f2p; -F_LSH_GUARD (mpc); /* guard multipicand */ -if ((mpy.l | mpc.l) == 0) { /* 24b x 24b? */ - for (i = 0; i < 24; i++) { - if (mpy.h & 1) result.h = result.h + mpc.h; - F_RSH_1 (result); - mpy.h = mpy.h >> 1; } } -else { if (mpy.l != 0) { /* 24b x 56b? */ - for (i = 0; i < 32; i++) { - if (mpy.l & 1) { F_ADD (mpc, result, result); } - F_RSH_1 (result); - mpy.l = mpy.l >> 1; } } - for (i = 0; i < 24; i++) { - if (mpy.h & 1) { F_ADD (mpc, result, result); } - F_RSH_1 (result); - mpy.h = mpy.h >> 1; } } -*f1p = result; -return; -} - -/* Floating point divide - - Inputs: - facp = pointer to dividend (output) - fsrcp = pointer to divisor - Outputs: - ovflo = overflow indicator -*/ - -int32 divfp11 (fpac_t *facp, fpac_t *fsrcp) -{ -int32 facexp, fsrcexp, i, count, qd; -fpac_t facfrac, fsrcfrac, quo; - -fsrcexp = GET_EXP (fsrcp->h); /* get divisor exp */ -if (fsrcexp == 0) { /* divide by zero? */ - fpnotrap (FEC_DZRO); - ABORT (TRAP_INT); } -facexp = GET_EXP (facp->h); /* get dividend exp */ -if (facexp == 0) { /* test for zero */ - *facp = zero_fac; /* result zero */ - return 0; } -F_GET_FRAC_P (facp, facfrac); /* get fractions */ -F_GET_FRAC_P (fsrcp, fsrcfrac); -F_LSH_GUARD (facfrac); /* guard fractions */ -F_LSH_GUARD (fsrcfrac); -facexp = facexp - fsrcexp + FP_BIAS + 1; /* calculate exp */ -facp->h = facp->h ^ fsrcp->h; /* calculate sign */ -qd = FPS & FPS_D; -count = FP_V_HB + FP_GUARD + (qd? 33: 1); /* count = 56b/24b */ - -quo = zero_fac; -for (i = count; (i > 0) && ((facfrac.h | facfrac.l) != 0); i--) { - F_LSH_1 (quo); /* shift quotient */ - if (!F_LT (facfrac, fsrcfrac)) { /* divd >= divr? */ - F_SUB (fsrcfrac, facfrac, facfrac); /* divd - divr */ - if (qd) quo.l = quo.l | 1; /* double or single? */ - else quo.h = quo.h | 1; } - F_LSH_1 (facfrac); } /* shift divd */ -if (i > 0) { F_LSH_V (quo, i, quo); } /* early exit? */ - -/* Dividing two numbers in the range [.5,1) produces a result in the - range [.5,2). Therefore, at most one bit of normalization is required - to bring the result back to the range [.5,1). The choice of counts - and quotient bit positions makes this work correctly. -*/ - -if (GET_BIT (quo.h, FP_V_HB + FP_GUARD) == 0) { - F_LSH_1 (quo); - facexp = facexp - 1; } -return round_and_pack (facp, facexp, &quo, 1); -} - -/* Update floating condition codes - Note that FC is only set by STCfi via the integer condition codes - - Inputs: - oldst = current status - result = high result - newV = new V - Outputs: - newst = new status -*/ - -int32 setfcc (int32 oldst, int32 result, int32 newV) -{ -oldst = (oldst & ~FPS_CC) | newV; -if (GET_SIGN (result)) oldst = oldst | FPS_N; -if (GET_EXP (result) == 0) oldst = oldst | FPS_Z; -return oldst; -} - -/* Round (in place) floating point number to f_floating - - Inputs: - fptr = pointer to floating number - Outputs: - ovflow = overflow -*/ - -int32 roundfp11 (fpac_t *fptr) -{ -fpac_t outf; - -outf = *fptr; /* get argument */ -F_ADD (fround_fac, outf, outf); /* round */ -if (GET_SIGN (outf.h ^ fptr->h)) { /* flipped sign? */ - outf.h = (outf.h ^ FP_SIGN) & 0xFFFFFFFF; /* restore sign */ - if (fpnotrap (FEC_OVFLO)) *fptr = zero_fac; /* if no int, clear */ - else *fptr = outf; /* return rounded */ - return FPS_V; } /* overflow */ -else { *fptr = outf; /* round was ok */ - return 0; } /* no overflow */ -} - -/* Round result of calculation, test overflow, pack - - Input: - facp = pointer to result, sign in place - exp = result exponent, right justified - fracp = pointer to result fraction, right justified with - guard bits - r = round (1) or truncate (0) - Outputs: - ovflo = overflow indicator -*/ - -int32 round_and_pack (fpac_t *facp, int32 exp, fpac_t *fracp, int r) -{ -fpac_t frac; - -frac = *fracp; /* get fraction */ -if (r && ((FPS & FPS_T) == 0)) { - if (FPS & FPS_D) { F_ADD (dround_guard_fac, frac, frac); } - else { F_ADD (fround_guard_fac, frac, frac); } - if (GET_BIT (frac.h, FP_V_HB + FP_GUARD + 1)) { - F_RSH_1 (frac); - exp = exp + 1; } } -F_RSH_GUARD (frac); -facp->l = frac.l & FP_FRACL; -facp->h = (facp->h & FP_SIGN) | ((exp & FP_M_EXP) << FP_V_EXP) | - (frac.h & FP_FRACH); -if (exp > 0377) { - if (fpnotrap (FEC_OVFLO)) *facp = zero_fac; - return FPS_V; } -if ((exp <= 0) && (fpnotrap (FEC_UNFLO))) *facp = zero_fac; -return 0; -} - -/* Process floating point exception - - Inputs: - code = exception code - Outputs: - int = FALSE if interrupt enabled, TRUE if disabled -*/ - -int32 fpnotrap (int32 code) -{ -static const int32 test_code[] = { 0, 0, 0, FPS_IC, FPS_IV, FPS_IU, FPS_IUV }; - -if ((code >= FEC_ICVT) && (code <= FEC_UNDFV) && - ((FPS & test_code[code >> 1]) == 0)) return TRUE; -FPS = FPS | FPS_ER; -FEC = code; -FEA = (backup_PC - 2) & 0177777; -if ((FPS & FPS_ID) == 0) setTRAP (TRAP_FPE); -return FALSE; -} diff --git a/PDP11/pdp11_hk.c b/PDP11/pdp11_hk.c deleted file mode 100644 index 31f35e52..00000000 --- a/PDP11/pdp11_hk.c +++ /dev/null @@ -1,1134 +0,0 @@ -/* pdp11_hk.c - RK611/RK06/RK07 disk controller - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PUHKOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - hk RK611/RK06/RK07 disk - - 25-Apr-03 RMS Revised for extended file support - - This is a somewhat abstracted implementation of the RK611, more closely - modelled on third party clones than DEC's own implementation. In particular, - the drive-to-controller serial communications system is simulated only at - a level equal to the Emulex SC21. - - The RK611 functions only in 18b Unibus systems with I/O maps. The Emulex - SC02/C was a Qbus work-alike with a unique extension to 22b addressing. It - was only supported in Ultrix-11 and other third party software. - - This module includes ideas from a previous implementation by Fred Van Kempen. -*/ - -#include "pdp11_defs.h" - -#define HK_RDX 8 -#define HK_WID 16 -extern int32 cpu_18b, cpu_ubm; - -extern uint16 *M; - -#define HK_NUMDR 8 /* #drives */ -#define HK_NUMCY6 411 /* cyl/drive */ -#define HK_NUMCY7 815 /* cyl/drive */ -#define HK_NUMSF 3 /* tracks/cyl */ -#define HK_NUMSC 22 /* sectors/track */ -#define HK_NUMWD 256 /* words/sector */ -#define RK06_SIZE (HK_NUMCY6*HK_NUMSF*HK_NUMSC*HK_NUMWD) -#define RK07_SIZE (HK_NUMCY7*HK_NUMSF*HK_NUMSC*HK_NUMWD) -#define HK_SIZE(x) (((x)->flags & UNIT_DTYPE)? RK07_SIZE: RK06_SIZE) -#define HK_CYL(x) (((x)->flags & UNIT_DTYPE)? HK_NUMCY7: HK_NUMCY6) -#define HK_MAXFR (1 << 16) - -/* Flags in the unit flags word */ - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */ -#define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize */ -#define UNIT_V_DUMMY (UNIT_V_UF + 3) /* dummy flag */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_DTYPE (1 << UNIT_V_DTYPE) -#define UNIT_RK06 (0 << UNIT_V_DTYPE) -#define UNIT_RK07 (1 << UNIT_V_DTYPE) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define UNIT_DUMMY (1 << UNIT_V_DUMMY) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */ - -/* Parameters in the unit descriptor */ - -#define CYL u3 /* current cylinder */ -#define FNC u4 /* function */ - -/* HKCS1 - 177440 - control/status 1 */ - -#define CS1_GO CSR_GO /* go */ -#define CS1_V_FNC 1 /* function pos */ -#define CS1_M_FNC 017 /* function mask */ -#define CS1_FNC (CS1_M_FNC << CS1_V_FNC) -#define FNC_NOP 000 /* no operation */ -#define FNC_PACK 001 /* pack acknowledge */ -#define FNC_DCLR 002 /* drive clear */ -#define FNC_UNLOAD 003 /* unload */ -#define FNC_START 004 /* start */ -#define FNC_RECAL 005 /* recalibrate */ -#define FNC_OFFSET 006 /* offset */ -#define FNC_SEEK 007 /* seek */ -#define FNC_XFER 010 -#define FNC_READ 010 /* read */ -#define FNC_WRITE 011 /* write */ -#define FNC_WRITEH 013 /* write w/ headers */ -#define FNC_READH 012 /* read w/ headers */ -#define FNC_WCHK 014 /* write check */ -#define FNC_2ND 020 /* 2nd state flag */ -#define CS1_SPA 0000040 /* spare */ -#define CS1_IE CSR_IE /* int enable */ -#define CS1_DONE CSR_DONE /* ready */ -#define CS1_V_UAE 8 /* Unibus addr ext */ -#define CS1_M_UAE 03 -#define CS1_UAE (CS1_M_UAE << CS1_V_UAE) -#define CS1_DT 0002000 /* drive type */ -#define CS1_CTO 0004000 /* ctrl timeout NI */ -#define CS1_FMT 0010000 /* 16b/18b NI */ -#define CS1_PAR 0020000 /* par err NI */ -#define CS1_DI 0040000 /* drive intr */ -#define CS1_ERR 0100000 /* error */ -#define CS1_CCLR 0100000 /* ctrl clear */ -#define CS1_RW (CS1_DT|CS1_UAE|CS1_IE|CS1_SPA|CS1_FNC|CS1_GO) -#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC) -#define GET_UAE(x) (((x) >> CS1_V_UAE) & CS1_M_UAE) -#define PUT_UAE(x,n) (((x) & ~ CS1_UAE) | (((n) << CS1_V_UAE) & CS1_UAE)) - -/* HKWC - 177442 - word count */ - -/* HKBA - 177444 - base address */ - -#define BA_MBZ 0000001 /* must be zero */ - -/* HKDA - 177446 - sector/track */ - -#define DA_V_SC 0 /* sector pos */ -#define DA_M_SC 037 /* sector mask */ -#define DA_V_SF 8 /* track pos */ -#define DA_M_SF 007 /* track mask */ -#define DA_MBZ 0174340 -#define GET_SC(x) (((x) >> DA_V_SC) & DA_M_SC) -#define GET_SF(x) (((x) >> DA_V_SF) & DA_M_SF) - -/* HKCS2 - 177450 - control/status 2 */ - -#define CS2_V_UNIT 0 /* unit pos */ -#define CS2_M_UNIT 07 /* unit mask */ -#define CS2_UNIT (CS2_M_UNIT << CS2_V_UNIT) -#define CS2_RLS 0000010 /* release NI */ -#define CS2_UAI 0000020 /* addr inhibit */ -#define CS2_CLR 0000040 /* controller clear */ -#define CS2_IR 0000100 /* input ready */ -#define CS2_OR 0000200 /* output ready */ -#define CS2_UFE 0000400 /* unit field err NI */ -#define CS2_MDS 0001000 /* multidrive sel NI */ -#define CS2_PGE 0002000 /* program err */ -#define CS2_NEM 0004000 /* nx mem err */ -#define CS2_NED 0010000 /* nx drive err */ -#define CS2_PE 0020000 /* parity err NI */ -#define CS2_WCE 0040000 /* write check err */ -#define CS2_DLT 0100000 /* data late NI */ -#define CS2_MBZ (CS2_CLR) -#define CS2_RW 0000037 -#define CS2_ERR (CS2_UFE | CS2_MDS | CS2_PGE | CS2_NEM | \ - CS2_NED | CS2_PE | CS2_WCE | CS2_DLT ) -#define GET_UNIT(x) (((x) >> CS2_V_UNIT) & CS2_M_UNIT) - -/* HKDS - 177452 - drive status ^ = calculated dynamically */ - -#define DS_DRA 0000001 /* ^drive avail */ -#define DS_OF 0000004 /* ^offset mode */ -#define DS_ACLO 0000010 /* ^AC LO NI */ -#define DS_SPLS 0000020 /* ^speed loss NI */ -#define DS_DOT 0000040 /* ^off track NI */ -#define DS_VV 0000100 /* volume valid */ -#define DS_RDY 0000200 /* ^drive ready */ -#define DS_DT 0000400 /* ^drive type */ -#define DS_WRL 0004000 /* ^write locked */ -#define DS_PIP 0020000 /* pos in progress */ -#define DS_ATA 0040000 /* attention active */ -#define DS_VLD 0100000 /* ^status valid */ -#define DS_MBZ 0013002 - -/* HKER - 177454 - error status */ - -#define ER_ILF 0000001 /* illegal func */ -#define ER_SKI 0000002 /* seek incomp */ -#define ER_NXF 0000004 /* non-exec func */ -#define ER_PAR 0000010 /* parity err */ -#define ER_FER 0000020 /* format err NI */ -#define ER_DTY 0000040 /* drive type err */ -#define ER_ECH 0000100 /* ECC hard err NI */ -#define ER_BSE 0000200 /* bad sector err NI */ -#define ER_HCR 0000400 /* hdr CRC err NI */ -#define ER_AOE 0001000 /* addr ovflo err */ -#define ER_IAE 0002000 /* invalid addr err */ -#define ER_WLE 0004000 /* write lock err */ -#define ER_DTE 0010000 /* drive time err NI */ -#define ER_OPI 0020000 /* op incomplete */ -#define ER_UNS 0040000 /* drive unsafe */ -#define ER_DCK 0100000 /* data check NI */ - -/* HKAS - 177456 - attention summary/offset */ - -#define AS_U0 0000400 /* unit 0 flag */ -#define AS_OF 0000277 /* offset mask */ - -/* HKDC - 177460 - desired cylinder */ - -#define DC_V_CY 0 /* cylinder pos */ -#define DC_M_CY 0001777 /* cylinder mask */ -#define DC_MBZ 0176000 -#define GET_CY(x) (((x) >> DC_V_CY) & DC_M_CY) -#define GET_DA(c,fs) ((((GET_CY (c) * HK_NUMSF) + \ - GET_SF (fs)) * HK_NUMSC) + GET_SC (fs)) - -/* Spare - 177462 - read/write */ - -#define XM_KMASK 0177700 /* Qbus XM key mask */ -#define XM_KEY 0022000 /* Qbus XM "key" */ -#define XM_MMASK 0000077 /* Qbus XM mask */ -#define SC02C (!UNIBUS && ((hkspr & XM_KMASK) == XM_KEY)) - -/* HKDB - 177464 - read/write */ - -/* HKMR - 177466 - maintenance register 1 */ - -#define MR_V_MS 0 /* message select */ -#define MR_M_MS 03 -#define MR_MS (MR_M_MS << MR_V_MS) -#define GET_MS(x) (((x) >> MR_V_MS) & MR_M_MS) -#define MR_PAR 0000020 /* force even parity */ -#define MR_DMD 0000040 /* diagnostic mode */ -#define MR_RW 0001777 - -/* HKEC1 - 177470 - ECC status 1 - always reads as 0 */ -/* HKEC2 - 177472 - ECC status 2 - always reads as 0 */ - -/* HKMR2 - 177474 - maintenance register 2 */ - -#define AX_V_UNIT 0 /* unit #, all msgs */ -#define AX_PAR 0100000 /* parity, all msgs */ - -#define A0_DRA 0000040 /* drive avail */ -#define A0_VV 0000100 /* vol valid */ -#define A0_RDY 0000200 /* drive ready */ -#define A0_DT 0000400 /* drive type */ -#define A0_FMT 0001000 /* format NI */ -#define A0_OF 0002000 /* offset mode */ -#define A0_WRL 0004000 /* write lock */ -#define A0_SPO 0010000 /* spindle on */ -#define A0_PIP 0020000 /* pos in prog */ -#define A0_ATA 0040000 /* attention */ - -#define A1_SRV 0000020 /* servo */ -#define A1_HHM 0000040 /* heads home */ -#define A1_BHM 0000100 /* brushes home */ -#define A1_DOR 0000200 /* door latched */ -#define A1_CAR 0000400 /* cartridge present */ -#define A1_SPD 0001000 /* speed ok */ -#define A1_FWD 0002000 /* seek fwd */ -#define A1_REV 0004000 /* seek rev */ -#define A1_LDH 0010000 /* loading heads NI */ -#define A1_RTZ 0020000 /* return to zero */ -#define A1_UNL 0040000 /* unloading heads */ - -#define A2_V_DIF 4 /* cyl diff */ -#define A2_M_DIF 0777 - -#define A3_V_SNO 3 /* serial # */ - -/* HKMR3 - 177476 - maintenance register 3 */ - -#define B0_IAE 0000040 /* invalid addr */ -#define B0_ACLO 0000100 /* AC LO NI */ -#define B0_FLT 0000200 /* fault */ -#define B0_NXF 0000400 /* non exec fnc */ -#define B0_CDP 0001000 /* msg parity err */ -#define B0_SKI 0002000 /* seek incomp */ -#define B0_WLE 0004000 /* write lock err */ -#define B0_SLO 0010000 /* speed low NI */ -#define B0_OFT 0020000 /* off track NI */ -#define B0_UNS 0040000 /* rw unsafe NI */ - -#define B1_SCE 0000020 /* sector err NI */ -#define B1_NWC 0000040 /* no write curr NI */ -#define B1_NWT 0000100 /* no write trans NI */ -#define B1_HFL 0000200 /* head fault NI */ -#define B1_MHS 0000400 /* multiselect NI */ -#define B1_IDX 0001000 /* index err NI */ -#define B1_TRI 0002000 /* tribit err NI */ -#define B1_SVE 0004000 /* servo err NI */ -#define B1_SKI 0010000 /* seek no mot */ -#define B1_LIM 0020000 /* seek limit NI */ -#define B1_SVU 0040000 /* servo unsafe NI */ - -#define B2_V_CYL 4 /* cylinder */ - -#define B3_V_SEC 4 /* sector */ -#define B3_V_DHA 9 /* decoded head */ - -/* Read header */ - -#define RDH1_V_CYL 0 /* cylinder */ -#define RDH2_V_SEC 0 /* sector */ -#define RDH2_V_DHA 5 /* decoded head */ -#define RDH2_GOOD 0140000 /* good sector flags */ - -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -extern int32 cpu_log; -extern FILE *sim_log; - -uint16 *hkxb = NULL; /* xfer buffer */ -int32 hkcs1 = 0; /* control/status 1 */ -int32 hkwc = 0; /* word count */ -int32 hkba = 0; /* bus address */ -int32 hkda = 0; /* track/sector */ -int32 hkcs2 = 0; /* control/status 2 */ -int32 hkds[HK_NUMDR] = { 0 }; /* drive status */ -int32 hker[HK_NUMDR] = { 0 }; /* error status */ -int32 hkof = 0; /* offset */ -int32 hkmr = 0; /* maint registers */ -int32 hkmr2 = 0; -int32 hkmr3 = 0; -int32 hkdc = 0; /* cylinder */ -int32 hkspr = 0; /* spare */ -int32 hk_stopioe = 1; /* stop on error */ -int32 hk_cwait = 5; /* command time */ -int32 hk_swait = 10; /* seek time */ -int32 hk_rwait = 10; /* rotate time */ -int16 hkdb[3] = { 0 }; /* data buffer silo */ -int16 hk_off[HK_NUMDR] = { 0 }; /* saved offset */ -int16 hk_dif[HK_NUMDR] = { 0 }; /* cylinder diff */ -static int32 reg_in_drive[16] = { - 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -DEVICE hk_dev; -t_stat hk_rd (int32 *data, int32 PA, int32 access); -t_stat hk_wr (int32 data, int32 PA, int32 access); -t_stat hk_svc (UNIT *uptr); -t_stat hk_reset (DEVICE *dptr); -t_stat hk_boot (int32 unitno, DEVICE *dptr); -t_stat hk_attach (UNIT *uptr, char *cptr); -t_stat hk_detach (UNIT *uptr); -int32 hk_rdmr2 (int32 msg); -int32 hk_rdmr3 (int32 msg); -void update_hkcs (int32 flags, int32 drv); -void update_hkds (int32 drv); -void hk_cmderr (int32 err, int32 drv); -void hk_go (int32 drv); -t_stat hk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat hk_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc); - -extern t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds); - -/* HK data structures - - hk_dev HK device descriptor - hk_unit HK unit list - hk_reg HK register list - hk_mod HK modifier list -*/ - -DIB hk_dib = { IOBA_HK, IOLN_HK, &hk_rd, &hk_wr, - 1, IVCL (HK), VEC_HK, { NULL } }; - -UNIT hk_unit[] = { - { UDATA (&hk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+UNIT_RK06, RK06_SIZE) }, - { UDATA (&hk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+UNIT_RK06, RK06_SIZE) }, - { UDATA (&hk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+UNIT_RK06, RK06_SIZE) }, - { UDATA (&hk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+UNIT_RK06, RK06_SIZE) }, - { UDATA (&hk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+UNIT_RK06, RK06_SIZE) }, - { UDATA (&hk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+UNIT_RK06, RK06_SIZE) }, - { UDATA (&hk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+UNIT_RK06, RK06_SIZE) }, - { UDATA (&hk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+UNIT_RK06, RK06_SIZE) } }; - -REG hk_reg[] = { - { GRDATA (HKCS1, hkcs1, HK_RDX, 16, 0) }, - { GRDATA (HKWC, hkwc, HK_RDX, 16, 0) }, - { GRDATA (HKBA, hkba, HK_RDX, 16, 0) }, - { GRDATA (HKDA, hkda, HK_RDX, 16, 0) }, - { GRDATA (HKCS2, hkcs2, HK_RDX, 16, 0) }, - { BRDATA (HKDS, hkds, HK_RDX, 16, HK_NUMDR) }, - { BRDATA (HKER, hker, HK_RDX, 16, HK_NUMDR) }, - { BRDATA (HKDB, hkdb, HK_RDX, 16, 3) }, - { GRDATA (HKDC, hkdc, HK_RDX, 16, 0) }, - { GRDATA (HKOF, hkof, HK_RDX, 8, 0) }, - { GRDATA (HKMR, hkmr, HK_RDX, 16, 0) }, - { GRDATA (HKMR2, hkmr2, HK_RDX, 16, 0), REG_RO }, - { GRDATA (HKMR3, hkmr3, HK_RDX, 16, 0), REG_RO }, - { GRDATA (HKSPR, hkspr, HK_RDX, 16, 0) }, - { FLDATA (INT, IREQ (HK), INT_V_HK) }, - { FLDATA (ERR, hkcs1, CSR_V_ERR) }, - { FLDATA (DONE, hkcs1, CSR_V_DONE) }, - { FLDATA (IE, hkcs1, CSR_V_IE) }, - { DRDATA (STIME, hk_swait, 24), REG_NZ + PV_LEFT }, - { DRDATA (RTIME, hk_rwait, 24), REG_NZ + PV_LEFT }, - { URDATA (FNC, hk_unit[0].FNC, HK_RDX, 5, 0, - HK_NUMDR, REG_HRO) }, - { URDATA (CYL, hk_unit[0].CYL, HK_RDX, 10, 0, - HK_NUMDR, REG_HRO) }, - { BRDATA (OFFSET, hk_off, HK_RDX, 16, HK_NUMDR), REG_HRO }, - { BRDATA (CYLDIF, hk_dif, HK_RDX, 16, HK_NUMDR), REG_HRO }, - { URDATA (CAPAC, hk_unit[0].capac, 10, T_ADDR_W, 0, - HK_NUMDR, PV_LEFT | REG_HRO) }, - { FLDATA (STOP_IOE, hk_stopioe, 0) }, - { GRDATA (DEVADDR, hk_dib.ba, HK_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, hk_dib.vec, HK_RDX, 16, 0), REG_HRO }, - { NULL } }; - -MTAB hk_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { UNIT_DUMMY, 0, NULL, "BADBLOCK", &hk_set_bad }, - { (UNIT_DTYPE+UNIT_ATT), UNIT_RK06 + UNIT_ATT, - "RK06", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), UNIT_RK07 + UNIT_ATT, - "RK07", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), UNIT_RK06, - "RK06", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), UNIT_RK07, - "RK07", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_DTYPE), UNIT_RK06, - NULL, "RK06", &hk_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), UNIT_RK07, - NULL, "RK07", &hk_set_size }, - { MTAB_XTD|MTAB_VDV, 0040, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE hk_dev = { - "HK", hk_unit, hk_reg, hk_mod, - HK_NUMDR, HK_RDX, 24, 1, HK_RDX, HK_WID, - NULL, NULL, &hk_reset, - &hk_boot, &hk_attach, &hk_detach, - &hk_dib, DEV_DISABLE | DEV_UBUS }; - -/* I/O dispatch routines, I/O addresses 17777440 - 17777476 */ - -t_stat hk_rd (int32 *data, int32 PA, int32 access) -{ -int32 drv, i, j; - -drv = GET_UNIT (hkcs2); /* get current unit */ -j = (PA >> 1) & 017; /* get reg offset */ -if (reg_in_drive[j] && (hk_unit[drv].flags & UNIT_DIS)) { /* nx disk */ - hkcs2 = hkcs2 | CS2_NED; /* set error flag */ - update_hkcs (0, drv); - *data = 0; - return SCPE_OK; } - -update_hkcs (0, drv); /* update status */ -switch (j) { /* decode PA<4:1> */ -case 000: /* HKCS1 */ - *data = hkcs1; - break; -case 001: /* HKWC */ - *data = hkwc; - break; -case 002: /* HKBA */ - *data = hkba = hkba & ~BA_MBZ; - break; -case 003: /* HKDA */ - *data = hkda = hkda & ~DA_MBZ; - break; -case 004: /* HKCS2 */ - *data = hkcs2 = (hkcs2 & ~CS2_MBZ) | CS2_IR | CS2_OR; - break; -case 005: /* HKDS */ - *data = hkds[drv]; - break; -case 006: /* HKER */ - *data = hker[drv]; - break; -case 007: /* HKAS */ - *data = hkof; - for (i = 0; i < HK_NUMDR; i++) - if (hkds[i] & DS_ATA) *data = *data | (AS_U0 << i); - break; -case 010: /* HKDC */ - *data = hkdc = hkdc & ~DC_MBZ; - break; -case 011: /* spare */ - *data = hkspr; - break; -case 012: /* HKDB */ - *data = hkdb[0]; /* top of silo */ - hkdb[0] = hkdb[1]; /* ripple silo */ - hkdb[1] = hkdb[2]; - hkdb[2] = 0; /* just for READH */ - break; -case 013: /* HKMR */ - *data = hkmr; - break; -case 014: /* HKEC1 */ -case 015: /* HKEC2 */ - *data = 0; /* no ECC */ - break; -case 016: /* HKMR2 */ - *data = hkmr2 = hk_rdmr2 (GET_MS (hkmr)); - break; -case 017: /* HKMR3 */ - *data = hkmr3 = hk_rdmr3 (GET_MS (hkmr)); - break; } -return SCPE_OK; -} - -t_stat hk_wr (int32 data, int32 PA, int32 access) -{ -int32 drv, i, j; -UNIT *uptr; - -drv = GET_UNIT (hkcs2); /* get current unit */ -uptr = hk_dev.units + drv; /* get unit */ -j = (PA >> 1) & 017; /* get reg offset */ -if ((hkcs1 & CS1_GO) && /* busy? */ - !(((j == 0) && (data & CS1_CCLR)) || /* not cclr or sclr? */ - ((j == 4) && (data & CS2_CLR)))) { - hkcs2 = hkcs2 | CS2_PGE; /* prog error */ - update_hkcs (0, drv); - return SCPE_OK; } - -switch (j) { /* decode PA<4:1> */ -case 000: /* HKCS1 */ - if (data & CS1_CCLR) { /* controller reset? */ - hkcs1 = CS1_DONE; /* CS1 = done */ - hkcs2 = CS2_IR | CS2_OR; /* CS2 = ready */ - hkmr = hkmr2 = hkmr3 = 0; /* maint = 0 */ - hkda = hkdc = 0; - hkba = hkwc = 0; - hkspr = hkof = 0; - CLR_INT (HK); /* clr int */ - for (i = 0; i < HK_NUMDR; i++) { /* stop data xfr */ - if (sim_is_active (&hk_unit[i]) && - ((uptr->FNC & CS1_M_FNC) >= FNC_XFER)) - sim_cancel (&hk_unit[i]); } - drv = 0; - break; } - if (data & CS1_IE) { /* setting IE? */ - if (data & CS1_DONE) SET_INT (HK); } /* write to DONE+IE? */ - else CLR_INT (HK); /* no, clr intr */ - hkcs1 = (hkcs1 & ~CS1_RW) | (data & CS1_RW); /* merge data */ - if (SC02C) hkspr = (hkspr & ~CS1_M_UAE) | GET_UAE (hkcs1); - if (hkcs1 & CS1_GO) { /* go? */ - if (hkcs1 & CS1_ERR) hkcs1 = hkcs1 & ~CS1_GO; - else hk_go (drv); } - break; -case 001: /* HKWC */ - hkwc = data; - break; -case 002: /* HKBA */ - hkba = data & ~BA_MBZ; - break; -case 003: /* HKDA */ - hkda = data & ~DA_MBZ; - break; -case 004: /* HKCS2 */ - if (data & CS2_CLR) hk_reset (&hk_dev); /* init? */ - else hkcs2 = (hkcs2 & ~CS2_RW) | (data & CS2_RW) | CS2_IR | CS2_OR; - drv = GET_UNIT (hkcs2); - break; -case 007: /* HKAS */ - hkof = data & AS_OF; - break; -case 010: /* HKDC */ - hkdc = data & ~DC_MBZ; - break; -case 011: /* spare */ - hkspr = data; - if (SC02C) hkcs1 = PUT_UAE (hkcs1, hkspr & 03); /* SC02C? upd UAE */ - break; -case 012: /* HKDB */ - hkdb[0] = data; - break; -case 013: /* HKMR */ - hkmr = data & MR_RW; - break; -default: /* all others RO */ - break; } /* end switch */ -update_hkcs (0, drv); /* update status */ -return SCPE_OK; -} - -/* Initiate operation - unit not busy, function set */ - -void hk_go (int32 drv) -{ - -int32 fnc, t; -UNIT *uptr; -static int32 fnc_nxf[16] = { - 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0 }; -static int32 fnc_att[16] = { - 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 }; -static int32 fnc_rdy[16] = { - 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 }; -static int32 fnc_cyl[16] = { - 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0 }; - -fnc = GET_FNC (hkcs1); -if (DBG_LOG (LOG_HK)) fprintf (sim_log, - ">>HK%d: fnc=%o, ds=%o, cyl=%o, da=%o, ba=%o, wc=%o\n", - drv, fnc, hkds[drv], hkdc, hkda, hkba, hkwc); -uptr = hk_dev.units + drv; /* get unit */ -if (fnc != FNC_NOP) hkmr = hkmr & ~MR_MS; /* !nop, clr msg sel */ -if (uptr->flags & UNIT_DIS) { /* nx unit? */ - hkcs2 = hkcs2 | CS2_NED; /* set error flag */ - update_hkcs (CS1_DONE, drv); /* done */ - return; } -if (((hkcs1 & CS1_DT) != 0) != /* dtype mismatch? */ - ((uptr->flags & UNIT_DTYPE) != 0)) { - hk_cmderr (ER_DTY, drv); /* type error */ - return; } -if (fnc_nxf[fnc] && ((hkds[drv] & DS_VV) == 0)) { /* need vol valid? */ - hk_cmderr (ER_NXF, drv); /* non exec func */ - return; } -if (fnc_att[fnc] && ((uptr->flags & UNIT_ATT) == 0)) { /* need attached? */ - hk_cmderr (ER_UNS, drv); /* unsafe */ - return; } -if (fnc_rdy[fnc] && sim_is_active (uptr)) { /* need inactive? */ - hkcs1 = (hkcs1 | CS1_DONE) & ~CS1_GO; /* ignore if busy */ - return; } -if (fnc_cyl[fnc] && /* need valid cyl */ - ((GET_CY (hkdc) >= HK_CYL (uptr)) || /* bad cylinder */ - (GET_SF (hkda) >= HK_NUMSF) || /* bad surface */ - (GET_SC (hkda) >= HK_NUMSC))) { /* or bad sector? */ - hk_cmderr (ER_IAE, drv); /* illegal addr */ - return; } - -hkcs1 = hkcs1 & ~CS1_DONE; /* clear done */ -hkds[drv] = hkds[drv] & ~DS_ATA; /* clear attention */ -uptr->FNC = fnc; /* save function */ -switch (fnc) { /* case on function */ - -/* "Fast functions" finish in less than 15 usec */ - -case FNC_NOP: /* no operation */ -case FNC_DCLR: /* drive clear */ -case FNC_START: /* start spindle */ -case FNC_UNLOAD: /* unload */ -case FNC_PACK: /* pack acknowledge */ - sim_activate (uptr, hk_cwait); /* schedule */ - return; - -/* Positioning functions provide two interrupts - an immediate interrupt - on ctrl done and a second one (if ctrl ready) when the seek is complete */ - -case FNC_OFFSET: /* offset mode */ -case FNC_RECAL: /* recalibrate */ -case FNC_SEEK: /* seek */ - hkds[drv] = hkds[drv] | DS_PIP; /* set positioning */ - sim_activate (uptr, hk_cwait); /* schedule */ - return; - -/* Data transfer functions lock the controller for the duration */ - -case FNC_WRITEH: /* write headers */ -case FNC_WRITE: /* write */ - hk_off[drv] = 0; /* clr offset */ -case FNC_WCHK: /* write check */ -case FNC_READ: /* read */ -case FNC_READH: /* read headers */ - hk_dif[drv] = hkdc - uptr->CYL; /* cyl diff */ - t = abs (hk_dif[drv]); /* |cyl diff| */ - sim_activate (uptr, hk_rwait + (hk_swait * t)); /* Schedule */ - uptr->CYL = hkdc; /* update cyl */ - return; - -default: - hk_cmderr (ER_ILF, drv); /* not supported */ - break; } -return; -} - -/* Service unit timeout - - Complete movement or data transfer command - Unit must exist - can't remove an active unit - Unit must be attached - detach cancels in progress operations -*/ - -t_stat hk_svc (UNIT *uptr) -{ -int32 i, t, dc, drv, fnc, err; -int32 wc, awc, da; -uint32 ba; -uint16 comp; - -drv = uptr - hk_dev.units; /* get drv number */ -fnc = uptr->FNC & CS1_M_FNC; /* get function */ -switch (fnc) { /* case on function */ - -/* Fast commands and other NOPs - start spindle only provides one interrupt - because ATTACH implicitly spins up the drive */ - -case FNC_DCLR: /* drive clear */ - hker[drv] = 0; /* clear errors */ - update_hkcs (CS1_DONE, drv); /* done */ - break; - -case FNC_PACK: /* pack acknowledge */ - hkds[drv] = hkds[drv] | DS_VV; /* set volume valid */ - update_hkcs (CS1_DONE, drv); /* done */ - break; - -case FNC_UNLOAD: /* unload */ - hk_detach (uptr); /* detach unit */ -case FNC_START: /* start spindle */ -case FNC_NOP: /* select */ - update_hkcs (CS1_DONE, drv); /* done */ - break; - -/* Positioning commands provide two interrupts, an immediate controller done - and a delayed drive interrupt */ - -case FNC_OFFSET: /* offset */ - if (uptr->FNC & FNC_2ND) { /* 2nd int? */ - hkds[drv] = (hkds[drv] & ~DS_PIP) | DS_ATA; /* upd sta */ - update_hkcs (CS1_DI, drv); } /* drive intr */ - else { - uptr->FNC = uptr->FNC | FNC_2ND; /* second state */ - hk_off[drv] = hkof & AS_OF; /* save offset */ - sim_activate (uptr, hk_swait * 10); /* wait for compl */ - update_hkcs (CS1_DONE, drv); } /* done */ - break; - -case FNC_RECAL: /* recalibrate */ -case FNC_SEEK: /* seek */ - if (uptr->FNC & FNC_2ND) { /* 2nd int? */ - hkds[drv] = (hkds[drv] & ~DS_PIP) | DS_ATA; /* upd sta */ - update_hkcs (CS1_DI, drv); } /* drive intr */ - else { - uptr->FNC = uptr->FNC | FNC_2ND; /* second state */ - hk_off[drv] = 0; /* clr offset */ - dc = (fnc == FNC_SEEK)? hkdc: 0; /* get cyl */ - hk_dif[drv] = dc - uptr->CYL; /* cyl diff */ - t = abs (hk_dif[drv]); /* |cyl diff| */ - if (t == 0) t = 1; /* min time */ - uptr->CYL = dc; /* save cyl */ - sim_activate (uptr, hk_swait * t); /* schedule */ - update_hkcs (CS1_DONE, drv); } /* done */ - break; - -/* Data transfer commands only generate one interrupt */ - -case FNC_READH: - hkdb[0] = uptr->CYL << RDH1_V_CYL; /* first word */ - hkdb[1] = (GET_SC (hkda) << RDH2_V_SEC) | /* second word */ - (1 << (GET_SF (hkda) + RDH2_V_DHA)) | RDH2_GOOD; - hkdb[2] = hkdb[0] ^ hkdb[1]; /* checksum */ - update_hkcs (CS1_DONE, drv); /* done */ - break; - -case FNC_WRITE: /* write */ - if (uptr->flags & UNIT_WPRT) { /* write locked? */ - hk_cmderr (ER_WLE, drv); /* command error */ - return SCPE_OK; } -case FNC_WCHK: /* write check */ -case FNC_READ: /* read */ - if (SC02C) ba = ((hkspr & XM_MMASK) << 16) | hkba; /* 22b addr? */ - else ba = (GET_UAE (hkcs1) << 16) | hkba; /* no, 18b addr */ - da = GET_DA (hkdc, hkda) * HK_NUMWD; /* get disk addr */ - wc = 0200000 - hkwc; /* get true wc */ - - if ((da + wc) > HK_SIZE (uptr)) { /* disk overrun? */ - hker[drv] = hker[drv] | ER_AOE; /* set err */ - wc = HK_SIZE (uptr) - da; /* trim xfer */ - if (da >= HK_SIZE (uptr)) { /* none left? */ - update_hkcs (CS1_DONE, drv); /* then done */ - break; } } - - err = fseek (uptr->fileref, da * sizeof (int16), SEEK_SET); - if (uptr->FNC == FNC_WRITE) { /* write? */ - if (hkcs2 & CS2_UAI) { /* no addr inc? */ - if (t = Map_ReadW (ba, 2, &comp, MAP)) { /* get 1st wd */ - wc = 0; /* NXM, no xfr */ - hkcs2 = hkcs2 | CS2_NEM; } /* set nxm err */ - for (i = 0; i < wc; i++) hkxb[i] = comp; } - else { /* normal */ - if (t = Map_ReadW (ba, wc << 1, hkxb, MAP)) { /* get buf */ - wc = wc - (t >> 1); /* NXM, adj wc */ - hkcs2 = hkcs2 | CS2_NEM; } /* set nxm err */ - ba = ba + (wc << 1); } /* adv ba */ - awc = (wc + (HK_NUMWD - 1)) & ~(HK_NUMWD - 1); - for (i = wc; i < awc; i++) hkxb[i] = 0; /* fill buf */ - if (wc && !err) { /* write buf */ - fxwrite (hkxb, sizeof (uint16), wc, uptr->fileref); - err = ferror (uptr->fileref); } - } /* end if wr */ - else if (uptr->FNC == FNC_READ) { /* read? */ - i = fxread (hkxb, sizeof (uint16), wc, uptr->fileref); - err = ferror (uptr->fileref); - for ( ; i < wc; i++) hkxb[i] = 0; /* fill buf */ - if (hkcs2 & CS2_UAI) { /* no addr inc? */ - if (t = Map_WriteW (ba, 2, &hkxb[wc - 1], MAP)) { - wc = 0; /* NXM, no xfr */ - hkcs2 = hkcs2 | CS2_NEM; } } /* set nxm err */ - else { /* normal */ - if (t = Map_WriteW (ba, wc << 1, hkxb, MAP)) { /* put buf */ - wc = wc - (t >> 1); /* NXM, adj wc */ - hkcs2 = hkcs2 | CS2_NEM; } /* set nxm err */ - ba = ba + (wc << 1); } /* adv ba */ - } /* end if read */ - else { /* wchk */ - i = fxread (hkxb, sizeof (uint16), wc, uptr->fileref); - err = ferror (uptr->fileref); - for ( ; i < wc; i++) hkxb[i] = 0; /* fill buf */ - awc = wc; - for (wc = 0; wc < awc; wc++) { /* loop thru buf */ - if (Map_ReadW (ba, 2, &comp, MAP)) { /* read word */ - hkcs2 = hkcs2 | CS2_NEM; /* set error */ - break; } - if (comp != hkxb[wc]) { /* compare wd */ - hkcs2 = hkcs2 | CS2_WCE; /* set error */ - break; } - if ((hkcs2 & CS2_UAI) == 0) ba = ba + 2; } - } /* end else wchk */ - - hkwc = (hkwc + wc) & 0177777; /* final word count */ - hkba = (ba & 0177777) & ~BA_MBZ; /* lower 16b */ - hkcs1 = PUT_UAE (hkcs1, ba >> 16); /* upper 2b */ - if (SC02C) /* SC02C? upper 6b */ - hkspr = (hkspr & ~XM_MMASK) | ((ba >> 16) & XM_MMASK); - da = da + wc + (HK_NUMWD - 1); - da = da / HK_NUMWD; - hkda = da % HK_NUMSC; - da = da / HK_NUMSC; - hkda = hkda | ((da % HK_NUMSF) << DA_V_SF); - hkdc = da / HK_NUMSF; - - if (err != 0) { /* error? */ - hk_cmderr (ER_PAR, drv); /* set drive error */ - perror ("HK I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } - -case FNC_WRITEH: /* write headers stub */ - update_hkcs (CS1_DONE, drv); /* set done */ - break; } /* end case func */ -return SCPE_OK; -} - -/* Controller status update - - Check for done transition - Update drive status - Update HKCS1 - Update interrupt request -*/ - -void update_hkcs (int32 flag, int32 drv) -{ -int32 i; - -update_hkds (drv); /* upd drv status */ -if (flag & CS1_DONE) hkcs1 = hkcs1 & ~CS1_GO; /* clear go */ -if (hkcs1 & CS1_IE) { /* intr enable? */ - if (((flag & CS1_DONE) && ((hkcs1 & CS1_DONE) == 0)) || - ((flag & CS1_DI) && (hkcs1 & CS1_DONE))) /* done 0->1 or DI? */ - SET_INT (HK); } -else CLR_INT (HK); -hkcs1 = (hkcs1 & (CS1_DT|CS1_UAE|CS1_DONE|CS1_IE|CS1_SPA|CS1_FNC|CS1_GO)) | flag; -for (i = 0; i < HK_NUMDR; i++) { /* if ATA, set DI */ - if (hkds[i] & DS_ATA) hkcs1 = hkcs1 | CS1_DI; } -if (hker[drv] | (hkcs1 & (CS1_PAR | CS1_CTO)) | /* if err, set ERR */ - (hkcs2 & CS2_ERR)) hkcs1 = hkcs1 | CS1_ERR; -return; -} - -/* Drive status update */ - -void update_hkds (drv) -{ -if (hk_unit[drv].flags & UNIT_DIS) { /* disabled? */ - hkds[drv] = hker[drv] = 0; /* all clear */ - return; } -hkds[drv] = (hkds[drv] & (DS_VV | DS_PIP | DS_ATA)) | DS_VLD | DS_DRA; -if (hk_unit[drv].flags & UNIT_ATT) { /* attached? */ - if (!sim_is_active (&hk_unit[drv])) /* not busy? */ - hkds[drv] = hkds[drv] | DS_RDY; /* set RDY */ - if (hker[drv]) hkds[drv] = hkds[drv] | DS_ATA; /* err? set ATA */ - if (hk_off[drv]) hkds[drv] = hkds[drv] | DS_OF; /* offset? set OF */ - if (hk_unit[drv].flags & UNIT_WPRT) /* write locked? */ - hkds[drv] = hkds[drv] | DS_WRL; } /* set WRL */ -else { hkds[drv] = hkds[drv] & ~(DS_PIP | DS_VV); /* no, clr PIP,VV */ - hker[drv] = 0; } /* no errors */ -if (hk_unit[drv].flags & UNIT_RK07) hkds[drv] = hkds[drv] | DS_DT; -return; -} - -/* Set error and abort command */ - -void hk_cmderr (int32 err, int32 drv) -{ -hker[drv] = hker[drv] | err; /* set error */ -hkds[drv] = hkds[drv] | DS_ATA; /* set attn */ -hkcs1 = hkcs1 & ~CS1_GO; /* clear go */ -update_hkcs (CS1_DONE, drv); /* set done */ -return; -} - -/* Diagnostic registers - - It's unclear whether the drivers actually use these values, but the - Emulex controller bothers to implement them, so we will too */ - -int32 hk_mrpar (int32 v) -{ -int32 bit, wrk; - -wrk = v & 077777; /* par on 15b */ -v = wrk | ((hkmr & MR_PAR)? 0: AX_PAR); /* even/odd */ -while (wrk) { /* while 1's */ - bit = wrk & (-wrk); /* lowest 1 */ - wrk = wrk & ~bit; /* clear */ - v = v ^ AX_PAR; } /* xor parity */ -return v; -} - -int32 hk_rdmr2 (int32 msg) -{ -int32 drv = GET_UNIT (hkcs2); -int32 v = drv << AX_V_UNIT; -UNIT *uptr = hk_dev.units + drv; -int32 fnc = uptr->FNC & CS1_M_FNC; - -switch (msg) { -case 0: /* message A0 */ - v = v | ((hkds[drv] & DS_ATA)? A0_ATA: 0) | - ((hkds[drv] & DS_PIP)? A0_PIP: 0) | - ((uptr->flags & UNIT_WPRT)? A0_WRL: 0) | - ((hk_off[drv])? A0_OF: 0) | - ((uptr->flags & UNIT_RK07)? A0_DT: 0) | - ((hkds[drv] & DS_VV)? A0_VV: 0) | A0_DRA; - if (uptr->flags & UNIT_ATT) v = v | A0_SPO | - (!sim_is_active (uptr)? A0_RDY: 0); - break; -case 1: /* message A1 */ - if (uptr->flags & UNIT_ATT) { - if (sim_is_active (uptr)) { - if (fnc == FNC_UNLOAD) v = v | A1_UNL; - else if (fnc == FNC_RECAL) v = v | A1_RTZ; - else if (fnc == FNC_SEEK) { - if (hk_dif[drv] < 0) v = v | A1_REV; - if (hk_dif[drv] > 0) v = v | A1_FWD; } } - v = v | (A1_SPD|A1_CAR|A1_DOR|A1_HHM|A1_SRV); } - else v = v | A1_HHM; - break; -case 2: /* message A2 */ - if (hkds[drv] & DS_OF) - v = v | ((hk_off[drv] & A2_M_DIF) << A2_V_DIF); - else v = v | ((hk_dif[drv] & A2_M_DIF) << A2_V_DIF); - break; -case 3: /* message A3 */ - v = v | ((012340 + v) << A3_V_SNO); - break; } -return hk_mrpar (v); -} - -int32 hk_rdmr3 (int32 msg) -{ -int32 drv = GET_UNIT (hkcs2); -int32 v = msg & 03; - -switch (msg) { -case 0: /* message B0 */ - v = v | ((hker[drv] & ER_WLE)? (B0_WLE | B0_FLT): 0) | - ((hker[drv] & ER_SKI)? (B0_SKI | B0_FLT): 0) | - ((hker[drv] & ER_NXF)? (B0_NXF | B0_FLT): 0) | - ((hker[drv] & ER_IAE)? (B0_IAE | B0_FLT): 0); - break; -case 1: /* message B1 */ - v = v | ((hker[drv] & ER_SKI)? B1_SKI: 0) | - ((hker[drv] & ER_UNS)? B1_SVE: 0); - break; -case 2: /* message B2 */ - v = v | (hk_unit[drv].CYL << B2_V_CYL); - break; -case 3: /* message B3 */ - v = v | (GET_SC (hkda) << B3_V_SEC) | - (1 << (GET_SF (hkda) + B3_V_DHA)); - break; } -return hk_mrpar (v); -} - -/* Device reset */ - -t_stat hk_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -hkcs1 = CS1_DONE; /* set done */ -hkcs2 = CS2_IR | CS2_OR; /* clear state */ -hkmr = hkmr2 = hkmr3 = 0; -hkda = hkdc = 0; -hkba = hkwc = 0; -hkof = hkspr = 0; -CLR_INT (HK); /* clear intr req */ -for (i = 0; i < HK_NUMDR; i++) { /* stop operations */ - uptr = hk_dev.units + i; - sim_cancel (uptr); - if (uptr->flags & UNIT_ATT) hkds[i] = hkds[i] & DS_VV; - else hkds[i] = 0; - uptr->CYL = uptr->FNC = 0; /* clear state */ - hk_dif[i] = 0; - hk_off[i] = 0; - hker[i] = 0; } /* clear errors */ -if (hkxb == NULL) hkxb = calloc (HK_MAXFR, sizeof (unsigned int16)); -if (hkxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Device attach */ - -t_stat hk_attach (UNIT *uptr, char *cptr) -{ -uint32 drv, p; -t_stat r; - -uptr->capac = HK_SIZE (uptr); -r = attach_unit (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* error? */ -drv = uptr - hk_dev.units; /* get drv number */ -hkds[drv] = DS_ATA | DS_RDY | ((uptr->flags & UNIT_WPRT)? DS_WRL: 0); -hker[drv] = 0; /* upd drv status */ -hk_off[drv] = 0; -hk_dif[drv] = 0; -uptr->CYL = 0; -update_hkcs (CS1_DI, drv); /* upd ctlr status */ - -if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK; /* seek to end */ -if ((p = ftell (uptr->fileref)) == 0) { /* new disk image? */ - if (uptr->flags & UNIT_RO) return SCPE_OK; - return pdp11_bad_block (uptr, HK_NUMSC, HK_NUMWD); } -if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ -if (p > (RK06_SIZE * sizeof (int16))) { - uptr->flags = uptr->flags | UNIT_RK07; - uptr->capac = RK07_SIZE; } -else { uptr->flags = uptr->flags & ~UNIT_RK07; - uptr->capac = RK06_SIZE; } -return SCPE_OK; -} - -/* Device detach */ - -t_stat hk_detach (UNIT *uptr) -{ -int32 drv; - -drv = uptr - hk_dev.units; /* get drv number */ -hkds[drv] = (hkds[drv] & ~(DS_RDY | DS_WRL | DS_VV | DS_OF)) | DS_ATA; -if (sim_is_active (uptr)) { /* unit active? */ - sim_cancel (uptr); /* cancel operation */ - hker[drv] = hker[drv] | ER_OPI; /* set drive error */ - if ((uptr->FNC & CS1_M_FNC) >= FNC_XFER) /* data transfer? */ - hkcs1 = hkcs1 | CS1_DONE | CS1_ERR; } /* set done, err */ -update_hkcs (CS1_DI, drv); /* request intr */ -return detach_unit (uptr); -} - -/* Set size command validation routine */ - -t_stat hk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = val? RK07_SIZE: RK06_SIZE; -return SCPE_OK; -} - -/* Set bad block routine */ - -t_stat hk_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -return pdp11_bad_block (uptr, HK_NUMSC, HK_NUMWD); -} - -/* Device bootstrap - does not clear CSR when done */ - -#define BOOT_START 02000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 014) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 0042115, /* "MD" */ - 0012706, BOOT_START, /* mov #boot_start, sp */ - 0012700, 0000000, /* mov #unit, r0 */ - 0012701, 0177440, /* mov #HKCS1, r1 */ - 0012761, 0000040, 0000010, /* mov #CS2_CLR, 10(r1) ; reset */ - 0010061, 0000010, /* mov r0, 10(r1) ; set unit */ - 0016102, 0000012, /* mov 12(r1), r2 ; drv typ */ - 0100375, /* bpl .-4 ; valid? */ - 0042702, 0177377, /* bic #177377, r2 ; clr rest */ - 0006302, /* asl r2 ; move */ - 0006302, /* asl r2 */ - 0012703, 0000003, /* mov #pack+go, r3 */ - 0050203, /* bis r2, r3 ; merge type */ - 0010311, /* mov r3, (r1); ; pack ack */ - 0105711, /* tstb (r1) ; wait */ - 0100376, /* bpl .-2 */ - 0012761, 0177000, 0000002, /* mov #-512.,2(r1) ; set wc */ - 0005061, 0000004, /* clr 4(r1) ; clr ba */ - 0005061, 0000006, /* clr 6(r1) ; clr da */ - 0005061, 0000020, /* clr 20(r1) ; clr cyl */ - 0012703, 0000021, /* mov #read+go, r3 */ - 0050203, /* bis r2, r3 ; merge type */ - 0010311, /* mov r3, (r1); ; read */ - 0105711, /* tstb (r1) ; wait */ - 0100376, /* bpl .-2 */ - 0005002, /* clr R2 */ - 0005003, /* clr R3 */ - 0012704, BOOT_START+020, /* mov #start+020, r4 */ - 0005005, /* clr R5 */ - 0005007 /* clr PC */ -}; - -t_stat hk_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & CS2_M_UNIT; -M[BOOT_CSR >> 1] = hk_dib.ba & DMASK; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} diff --git a/PDP11/pdp11_io.c b/PDP11/pdp11_io.c deleted file mode 100644 index bae93443..00000000 --- a/PDP11/pdp11_io.c +++ /dev/null @@ -1,603 +0,0 @@ -/* pdp11_io.c: PDP-11 I/O simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 12-Mar-03 RMS Added logical name support - 08-Oct-02 RMS Trimmed I/O bus addresses - Added support for dynamic tables - Added show I/O space, autoconfigure routines - 12-Sep-02 RMS Added support for TMSCP, KW11P, RX211 - 26-Jan-02 RMS Revised for multiple DZ's - 06-Jan-02 RMS Revised I/O access, enable/disable support - 11-Dec-01 RMS Moved interrupt debug code - 08-Nov-01 RMS Cloned from cpu sources -*/ - -#include "pdp11_defs.h" - -extern uint16 *M; -extern int32 int_req[IPL_HLVL]; -extern int32 ub_map[UBM_LNT_LW]; -extern UNIT cpu_unit; -extern int32 cpu_bme, cpu_18b, cpu_ubm; -extern int32 trap_req, ipl; -extern int32 cpu_log; -extern FILE *sim_log; -extern DEVICE *sim_devices[]; - -int32 calc_ints (int32 nipl, int32 trq); - -extern DIB cpu0_dib, cpu1_dib, cpu2_dib; -extern DIB cpu3_dib, cpu4_dib, ubm_dib; - -/* I/O data structures */ - -DIB *dib_tab[DIB_MAX]; /* run time DIBs */ - -int32 int_vec[IPL_HLVL][32]; /* int req to vector */ - -int32 (*int_ack[IPL_HLVL][32])(void); /* int ack routines */ - -static DIB *std_dib[] = { /* standard DIBs */ - &cpu0_dib, - &cpu1_dib, - &cpu2_dib, - &cpu3_dib, - &cpu4_dib, - NULL }; - -static int32 pirq_vloc[7] = { - IVCL (PIR7), IVCL (PIR6), IVCL (PIR5), IVCL (PIR4), - IVCL (PIR3), IVCL (PIR2), IVCL (PIR1) }; - -/* I/O page lookup and linkage routines - - Inputs: - *data = pointer to data to read, if READ - data = data to store, if WRITE or WRITEB - pa = address - access = READ, WRITE, or WRITEB - Outputs: - status = SCPE_OK or SCPE_NXM -*/ - -t_stat iopageR (int32 *data, uint32 pa, int32 access) -{ -int32 i; -DIB *dibp; -t_stat stat; - -for (i = 0; dibp = dib_tab[i]; i++ ) { - if ((pa >= dibp->ba) && - (pa < (dibp->ba + dibp->lnt))) { - stat = dibp->rd (data, pa, access); - trap_req = calc_ints (ipl, trap_req); - return stat; } } -return SCPE_NXM; -} - -t_stat iopageW (int32 data, uint32 pa, int32 access) -{ -int32 i; -DIB *dibp; -t_stat stat; - -for (i = 0; dibp = dib_tab[i]; i++ ) { - if ((pa >= dibp->ba) && - (pa < (dibp->ba + dibp->lnt))) { - stat = dibp->wr (data, pa, access); - trap_req = calc_ints (ipl, trap_req); - return stat; } } -return SCPE_NXM; -} - -/* Calculate interrupt outstanding */ - -int32 calc_ints (int32 nipl, int32 trq) -{ -int32 i; - -for (i = IPL_HLVL - 1; i > nipl; i--) { - if (int_req[i]) return (trq | TRAP_INT); } -return (trq & ~TRAP_INT); -} - -/* Find vector for highest priority interrupt */ - -int32 get_vector (int32 nipl) -{ -int32 i, j, t, vec; - -for (i = IPL_HLVL - 1; i > nipl; i--) { /* loop thru lvls */ - t = int_req[i]; /* get level */ - for (j = 0; t && (j < 32); j++) { /* srch level */ - if ((t >> j) & 1) { /* irq found? */ - int_req[i] = int_req[i] & ~(1u << j); /* clr irq */ - if (int_ack[i][j]) vec = int_ack[i][j](); - else vec = int_vec[i][j]; - if (DBG_LOG (LOG_CPU_I)) fprintf (sim_log, - ">>INT: lvl=%d, flag=%d, vec=%o\n", i, j, vec); - return vec; /* return vector */ - } /* end if t */ - } /* end for j */ - } /* end for i */ -return 0; -} - -/* Read and write Unibus map registers - - In any even/odd pair - even = low 16b, bit <0> clear - odd = high 6b - - The Unibus map is stored as an array of longwords -*/ - -t_stat ubm_rd (int32 *data, int32 addr, int32 access) -{ -if (cpu_ubm) { - int32 pg = (addr >> 2) & UBM_M_PN; - *data = (addr & 2)? ((ub_map[pg] >> 16) & 077): - (ub_map[pg] & 0177776); - return SCPE_OK; } -return SCPE_NXM; -} - -t_stat ubm_wr (int32 data, int32 addr, int32 access) -{ -if (cpu_ubm) { - int32 sc, pg = (addr >> 2) & UBM_M_PN; - if (access == WRITEB) { - sc = (addr & 3) << 3; - ub_map[pg] = (ub_map[pg] & ~(0377 << sc)) | - ((data & 0377) << sc); } - else { - sc = (addr & 2) << 3; - ub_map[pg] = (ub_map[pg] & ~(0177777 << sc)) | - ((data & 0177777) << sc); } - ub_map[pg] = ub_map[pg] & 017777776; - return SCPE_OK; } -return SCPE_NXM; -} - -/* Mapped memory access routines for DMA devices */ - -#define BUSMASK(m) ((cpu_18b || (cpu_ubm && (m)))? UNIMASK: PAMASK) - -/* Map I/O address to memory address */ - -t_bool Map_Addr (uint32 ba, uint32 *ma) -{ -if (cpu_bme) { /* bus map on? */ - int32 pg = UBM_GETPN (ba); /* map entry */ - int32 off = UBM_GETOFF (ba); /* offset */ - if (pg != UBM_M_PN) /* last page? */ - *ma = (ub_map[pg] + off) & PAMASK; /* no, use map */ - else *ma = (IOPAGEBASE + off) & PAMASK; } /* yes, use fixed */ -else *ma = ba; /* else physical */ -return TRUE; -} - -/* I/O buffer routines, aligned access - - Map_ReadB - fetch byte buffer from memory - Map_ReadW - fetch word buffer from memory - Map_WriteB - store byte buffer into memory - Map_WriteW - store word buffer into memory -*/ - -int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf, t_bool map) -{ -uint32 alim, lim, ma; - -ba = ba & BUSMASK (map); /* trim address */ -lim = ba + bc; -if (map && cpu_bme) { /* map req & on? */ - for ( ; ba < lim; ba++) { /* by bytes */ - Map_Addr (ba, &ma); /* map addr */ - if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */ - if (ma & 1) *buf++ = (M[ma >> 1] >> 8) & 0377; /* get byte */ - else *buf++ = M[ma >> 1] & 0377; } - return 0; } -else { /* physical */ - if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */ - else if (ADDR_IS_MEM (ba)) alim = MEMSIZE; /* no, strt ok? */ - else return bc; /* no, err */ - for ( ; ba < alim; ba++) { /* by bytes */ - if (ba & 1) *buf++ = (M[ba >> 1] >> 8) & 0377; /* get byte */ - else *buf++ = M[ba >> 1] & 0377; } - return (lim - alim); } -} - -int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf, t_bool map) -{ -uint32 alim, lim, ma; - -ba = (ba & BUSMASK (map)) & ~01; /* trim, align addr */ -lim = ba + (bc & ~01); -if (map && cpu_bme) { /* map req & on? */ - for (; ba < lim; ba = ba + 2) { /* by words */ - Map_Addr (ba, &ma); /* map addr */ - if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */ - *buf++ = M[ma >> 1]; } - return 0; } -else { /* physical */ - if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */ - else if (ADDR_IS_MEM (ba)) alim = MEMSIZE; /* no, strt ok? */ - else return bc; /* no, err */ - for ( ; ba < alim; ba = ba + 2) { /* by words */ - *buf++ = M[ba >> 1]; } - return (lim - alim); } -} - -int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf, t_bool map) -{ -uint32 alim, lim, ma; - -ba = ba & BUSMASK (map); /* trim address */ -lim = ba + bc; -if (map && cpu_bme) { /* map req & on? */ - for ( ; ba < lim; ba++) { /* by bytes */ - Map_Addr (ba, &ma); /* map addr */ - if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */ - if (ma & 1) M[ma >> 1] = (M[ma >> 1] & 0377) | - ((uint16) *buf++ << 8); - else M[ma >> 1] = (M[ma >> 1] & ~0377) | *buf++; } - return 0; } -else { /* physical */ - if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */ - else if (ADDR_IS_MEM (ba)) alim = MEMSIZE; /* no, strt ok? */ - else return bc; /* no, err */ - for ( ; ba < alim; ba++) { /* by bytes */ - if (ba & 1) M[ba >> 1] = (M[ba >> 1] & 0377) | - ((uint16) *buf++ << 8); - else M[ba >> 1] = (M[ba >> 1] & ~0377) | *buf++; } - return (lim - alim); } -} - -int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf, t_bool map) -{ -uint32 alim, lim, ma; - -ba = (ba & BUSMASK (map)) & ~01; /* trim, align addr */ -lim = ba + (bc & ~01); -if (map && cpu_bme) { /* map req & on? */ - for (; ba < lim; ba = ba + 2) { /* by words */ - Map_Addr (ba, &ma); /* map addr */ - if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */ - M[ma >> 1] = *buf++; } /* store word */ - return 0; } -else { /* physical */ - if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */ - else if (ADDR_IS_MEM (ba)) alim = MEMSIZE; /* no, strt ok? */ - else return bc; /* no, err */ - for ( ; ba < alim; ba = ba + 2) { /* by words */ - M[ba >> 1] = *buf++; } - return (lim - alim); } -} - -/* Change device address */ - -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newba; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if ((val == 0) || (uptr == NULL)) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newba = get_uint (cptr, 8, PAMASK, &r); /* get new */ -if (r != SCPE_OK) return r; /* error? */ -if ((newba <= IOPAGEBASE) || /* > IO page base? */ - (newba % ((uint32) val))) return SCPE_ARG; /* check modulus */ -dibp->ba = newba; /* store */ -dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */ -return auto_config (0, 0); /* autoconfigure */ -} - -/* Show device address */ - -t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -DEVICE *dptr; -DIB *dibp; - -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if ((dibp == NULL) || (dibp->ba <= IOPAGEBASE)) return SCPE_IERR; -fprintf (st, "address=%08o", dibp->ba); -if (dibp->lnt > 1) - fprintf (st, "-%08o", dibp->ba + dibp->lnt - 1); -if (dptr->flags & DEV_FLTA) fprintf (st, "*"); -return SCPE_OK; -} - -/* Set address floating */ - -t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; - -if (cptr != NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dptr->flags = dptr->flags | DEV_FLTA; /* floating */ -return auto_config (0, 0); /* autoconfigure */ -} - -/* Change device vector */ - -t_stat set_vec (UNIT *uptr, int32 arg, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newvec; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newvec = get_uint (cptr, 8, VEC_Q + 01000, &r); -if ((r != SCPE_OK) || (newvec <= VEC_Q) || - ((newvec + (dibp->vnum * 4)) >= (VEC_Q + 01000)) || - (newvec & ((dibp->vnum > 1)? 07: 03))) return SCPE_ARG; -dibp->vec = newvec; -return SCPE_OK; -} - -/* Show device vector */ - -t_stat show_vec (FILE *st, UNIT *uptr, int32 arg, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 vec, numvec; - -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -vec = dibp->vec; -if (arg) numvec = arg; -else numvec = dibp->vnum; -if (vec == 0) fprintf (st, "no vector"); -else { fprintf (st, "vector=%o", vec); - if (numvec > 1) fprintf (st, "-%o", vec + (4 * (numvec - 1))); } -return SCPE_OK; -} - -/* Test for conflict in device addresses */ - -t_bool dev_conflict (DIB *curr) -{ -uint32 i, end; -DEVICE *dptr; -DIB *dibp; - -end = curr->ba + curr->lnt - 1; /* get end */ -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if ((dibp == NULL) || (dibp == curr) || - (dptr->flags & DEV_DIS)) continue; - if (((curr->ba >= dibp->ba) && /* overlap start? */ - (curr->ba < (dibp->ba + dibp->lnt))) || - ((end >= dibp->ba) && /* overlap end? */ - (end < (dibp->ba + dibp->lnt)))) { - printf ("Device %s address conflict at %08o\n", - sim_dname (dptr), dibp->ba); - if (sim_log) fprintf (sim_log, - "Device %s address conflict at %08o\n", - sim_dname (dptr), dibp->ba); - return TRUE; } } -return FALSE; -} - -/* Build interrupt tables */ - -void build_int_vec (int32 vloc, int32 ivec, int32 (*iack)(void) ) -{ -int32 ilvl = vloc / 32; -int32 ibit = vloc % 32; - -if (iack != NULL) int_ack[ilvl][ibit] = iack; -else int_vec[ilvl][ibit] = ivec; -return; -} - -/* Build dib_tab from device list */ - -t_stat build_dib_tab (int32 ubm) -{ -int32 i, j, k; -DEVICE *dptr; -DIB *dibp; - -for (i = 0; i < IPL_HLVL; i++) { /* clear int tables */ - for (j = 0; j < 32; j++) { - int_vec[i][j] = 0; - int_ack[i][j] = NULL; } } -for (i = j = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if (dibp && !(dptr->flags & DEV_DIS)) { /* defined, enabled? */ - if (dibp->vnum > VEC_DEVMAX) return SCPE_IERR; - for (k = 0; k < dibp->vnum; k++) /* loop thru vec */ - build_int_vec (dibp->vloc + k, /* add vector */ - dibp->vec + (k * 4), dibp->ack[k]); - if (dibp->lnt != 0) { /* I/O addresses? */ - dib_tab[j++] = dibp; /* add DIB to dib_tab */ - if (j >= DIB_MAX) return SCPE_IERR; } /* too many? */ - } /* end if enabled */ - } /* end for */ -for (i = 0; (dibp = std_dib[i]) != NULL; i++) { /* loop thru std */ - dib_tab[j++] = dibp; /* add to dib_tab */ - if (j >= DIB_MAX) return SCPE_IERR; } /* too many? */ -if (ubm) { /* Unibus map? */ - dib_tab[j++] = &ubm_dib; /* add to dib_tab */ - if (j >= DIB_MAX) return SCPE_IERR; } /* too many? */ -dib_tab[j] = NULL; /* end with NULL */ -for (i = 0; i < 7; i++) /* add PIRQ intr */ - build_int_vec (pirq_vloc[i], VEC_PIRQ, NULL); -for (i = 0; (dibp = dib_tab[i]) != NULL; i++) { /* test built dib_tab */ - if (dev_conflict (dibp)) { - return SCPE_STOP; } } /* for conflicts */ -return SCPE_OK; -} - -/* Show dib_tab */ - -t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, j, done = 0; -DEVICE *dptr; -DIB *dibt; - -build_dib_tab (cpu_ubm); /* build table */ -while (done == 0) { /* sort ascending */ - done = 1; /* assume done */ - for (i = 0; dib_tab[i + 1] != NULL; i++) { /* check table */ - if (dib_tab[i]->ba > dib_tab[i + 1]->ba) { /* out of order? */ - dibt = dib_tab[i]; /* interchange */ - dib_tab[i] = dib_tab[i + 1]; - dib_tab[i + 1] = dibt; - done = 0; } } /* not done */ - } /* end while */ -for (i = 0; dib_tab[i] != NULL; i++) { /* print table */ - for (j = 0, dptr = NULL; sim_devices[j] != NULL; j++) { - if (((DIB*) sim_devices[j]->ctxt) == dib_tab[i]) { - dptr = sim_devices[j]; - break; } } - fprintf (st, "%08o - %08o%c\t%s\n", dib_tab[i]->ba, - dib_tab[i]->ba + dib_tab[i]->lnt - 1, - (dptr && (dptr->flags & DEV_FLTA))? '*': ' ', - dptr? sim_dname (dptr): "CPU"); - } -return SCPE_OK; -} - -/* Autoconfiguration */ - -#define AUTO_DYN 0001 -#define AUTO_VEC 0002 -#define AUTO_MAXC 4 -#define AUTO_CSRBASE 0010 -#define AUTO_VECBASE 0300 - -struct auto_con { - uint32 amod; - uint32 vmod; - uint32 flags; - uint32 num; - uint32 fix; - char *dnam[AUTO_MAXC]; }; - -struct auto_con auto_tab[AUTO_LNT + 1] = { - { 0x7, 0x7 }, /* DJ11 */ - { 0xf, 0x7 }, /* DH11 */ - { 0x7, 0x7 }, /* DQ11 */ - { 0x7, 0x7 }, /* DU11 */ - { 0x7, 0x7 }, /* DUP11 */ - { 0x7, 0x7 }, /* LK11A */ - { 0x7, 0x7 }, /* DMC11 */ - { 0x7, 0x7, AUTO_VEC, DZ_MUXES, 0, { "DZ" } }, - - { 0x7, 0x7 }, /* KMC11 */ - { 0x7, 0x7 }, /* LPP11 */ - { 0x7, 0x7 }, /* VMV21 */ - { 0xf, 0x7 }, /* VMV31 */ - { 0x7, 0x7 }, /* DWR70 */ - { 0x7, 0x3, AUTO_DYN|AUTO_VEC, 0, IOBA_RL, { "RL", "RLB" } }, - { 0xf, 0x7 }, /* LPA11K */ - { 0x7, 0x7 }, /* KW11C */ - - { 0x7, 0 }, /* reserved */ - { 0x7, 0x3, AUTO_DYN|AUTO_VEC, 0, IOBA_RX, { "RX", "RY" } }, - { 0x7, 0x3 }, /* DR11W */ - { 0x7, 0x3 }, /* DR11B */ - { 0x7, 0x7 }, /* DMP11 */ - { 0x7, 0x7 }, /* DPV11 */ - { 0x7, 0x7 }, /* ISB11 */ - { 0xf, 0x7 }, /* DMV11 */ - - { 0x7, 0x3, AUTO_DYN|AUTO_VEC, 0, IOBA_XU, { "XU", "XUB" } }, - { 0x3, 0x3, AUTO_DYN|AUTO_VEC, 0, IOBA_RQ, { "RQ", "RQB", "RQC", "RQD" } }, - { 0x1f, 0x3 }, /* DMF32 */ - { 0xf, 0x7 }, /* KMS11 */ - { 0xf, 0x3 }, /* VS100 */ - { 0x3, 0x3, AUTO_DYN|AUTO_VEC, 0, IOBA_TQ, { "TQ", "TQB" } }, - { 0xf, 0x7 }, /* KMV11 */ - { 0xf, 0x7 }, /* DHU11/DHQ11 */ - - { 0x1f, 0x7 }, /* DMZ32 */ - { 0x1f, 0x7 }, /* CP132 */ - { 0 }, /* padding */ -}; - -t_stat auto_config (uint32 rank, uint32 nctrl) -{ -uint32 csr = IOPAGEBASE + AUTO_CSRBASE; -uint32 vec = VEC_Q + AUTO_VECBASE; -struct auto_con *autp; -DEVICE *dptr; -DIB *dibp; -int32 i, j, k; -extern DEVICE *find_dev (char *ptr); - -if (rank > AUTO_LNT) return SCPE_IERR; /* legal rank? */ -if (rank) auto_tab[rank - 1].num = nctrl; /* update num? */ -for (i = 0, autp = auto_tab; i < AUTO_LNT; i++) { /* loop thru table */ - for (j = k = 0; (j < AUTO_MAXC) && autp->dnam[j]; j++) { - dptr = find_dev (autp->dnam[j]); /* find ctrl */ - if ((dptr == NULL) || (dptr->flags & DEV_DIS) || - !(dptr->flags & DEV_FLTA)) continue; /* enabled, floating? */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if ((k++ == 0) && autp->fix) /* 1st & fixed? */ - dibp->ba = autp->fix; /* gets fixed CSR */ - else { /* no, float */ - dibp->ba = csr; /* set CSR */ - csr = (csr + autp->amod + 1) & ~autp->amod; /* next CSR */ - if ((autp->flags & AUTO_DYN) == 0) /* static? */ - csr = csr + ((autp->num - 1) * (autp->amod + 1)); - if (autp->flags & AUTO_VEC) { /* vectors too? */ - dibp->vec = (vec + autp->vmod) & ~autp->vmod; - if (autp->flags & AUTO_DYN) vec = vec + autp->vmod + 1; - else vec = vec + (autp->num * (autp->vmod + 1)); } - } /* end else flt */ - } /* end for j */ - autp++; - csr = (csr + autp->amod + 1) & ~autp->amod; /* gap */ - } /* end for i */ -return SCPE_OK; -} diff --git a/PDP11/pdp11_lp.c b/PDP11/pdp11_lp.c deleted file mode 100644 index 022497a9..00000000 --- a/PDP11/pdp11_lp.c +++ /dev/null @@ -1,184 +0,0 @@ -/* pdp11_lp.c: PDP-11 line printer simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - lpt LP11 line printer - - 19-May-03 RMS Revised for new conditional compilation scheme - 25-Apr-03 RMS Revised for extended file support - 29-Sep-02 RMS Added vector change/display support - New data structures - 30-May-02 RMS Widened POS to 32b - 06-Jan-02 RMS Added enable/disable support - 09-Nov-01 RMS Added VAX support - 07-Sep-01 RMS Revised interrupt mechanism - 30-Oct-00 RMS Standardized register naming -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#error "LP11 is not supported on the PDP-10!" - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#endif - -#define LPTCSR_IMP (CSR_ERR + CSR_DONE + CSR_IE) /* implemented */ -#define LPTCSR_RW (CSR_IE) /* read/write */ - -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -int32 lpt_csr = 0; /* control/status */ -int32 lpt_stopioe = 0; /* stop on error */ - -DEVICE lpt_dev; -t_stat lpt_rd (int32 *data, int32 PA, int32 access); -t_stat lpt_wr (int32 data, int32 PA, int32 access); -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); -t_stat lpt_attach (UNIT *uptr, char *ptr); -t_stat lpt_detach (UNIT *uptr); - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list -*/ - -DIB lpt_dib = { IOBA_LPT, IOLN_LPT, &lpt_rd, &lpt_wr, - 1, IVCL (LPT), VEC_LPT, { NULL } }; - -UNIT lpt_unit = { - UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lpt_reg[] = { - { GRDATA (BUF, lpt_unit.buf, DEV_RDX, 8, 0) }, - { GRDATA (CSR, lpt_csr, DEV_RDX, 16, 0) }, - { FLDATA (INT, IREQ (LPT), INT_V_LPT) }, - { FLDATA (ERR, lpt_csr, CSR_V_ERR) }, - { FLDATA (DONE, lpt_csr, CSR_V_DONE) }, - { FLDATA (IE, lpt_csr, CSR_V_IE) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lpt_stopioe, 0) }, - { GRDATA (DEVADDR, lpt_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, lpt_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -MTAB lpt_mod[] = { - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, lpt_mod, - 1, 10, 31, 1, DEV_RDX, 8, - NULL, NULL, &lpt_reset, - NULL, &lpt_attach, &lpt_detach, - &lpt_dib, DEV_DISABLE | DEV_UBUS | DEV_QBUS }; - -/* Line printer routines - - lpt_rd I/O page read - lpt_wr I/O page write - lpt_svc process event (printer ready) - lpt_reset process reset - lpt_attach process attach - lpt_detach process detach -*/ - -t_stat lpt_rd (int32 *data, int32 PA, int32 access) -{ -if ((PA & 02) == 0) *data = lpt_csr & LPTCSR_IMP; /* csr */ -else *data = lpt_unit.buf; /* buffer */ -return SCPE_OK; -} - -t_stat lpt_wr (int32 data, int32 PA, int32 access) -{ -if ((PA & 02) == 0) { /* csr */ - if (PA & 1) return SCPE_OK; - if ((data & CSR_IE) == 0) CLR_INT (LPT); - else if ((lpt_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) - SET_INT (LPT); - lpt_csr = (lpt_csr & ~LPTCSR_RW) | (data & LPTCSR_RW); } -else { if ((PA & 1) == 0) lpt_unit.buf = data & 0177; /* buffer */ - lpt_csr = lpt_csr & ~CSR_DONE; - CLR_INT (LPT); - if ((lpt_unit.buf == 015) || (lpt_unit.buf == 014) || - (lpt_unit.buf == 012)) sim_activate (&lpt_unit, lpt_unit.wait); - else sim_activate (&lpt_unit, 0); } -return SCPE_OK; -} - -t_stat lpt_svc (UNIT *uptr) -{ -lpt_csr = lpt_csr | CSR_ERR | CSR_DONE; -if (lpt_csr & CSR_IE) SET_INT (LPT); -if ((lpt_unit.flags & UNIT_ATT) == 0) - return IORETURN (lpt_stopioe, SCPE_UNATT); -if (putc (lpt_unit.buf & 0177, lpt_unit.fileref) == EOF) { - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } -lpt_csr = lpt_csr & ~CSR_ERR; -lpt_unit.pos = lpt_unit.pos + 1; -return SCPE_OK; -} - -t_stat lpt_reset (DEVICE *dptr) -{ -lpt_unit.buf = 0; -lpt_csr = CSR_DONE; -if ((lpt_unit.flags & UNIT_ATT) == 0) lpt_csr = lpt_csr | CSR_ERR; -CLR_INT (LPT); -sim_cancel (&lpt_unit); /* deactivate unit */ -return SCPE_OK; -} - -t_stat lpt_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -lpt_csr = lpt_csr & ~CSR_ERR; -reason = attach_unit (uptr, cptr); -if ((lpt_unit.flags & UNIT_ATT) == 0) lpt_csr = lpt_csr | CSR_ERR; -return reason; -} - -t_stat lpt_detach (UNIT *uptr) -{ -lpt_csr = lpt_csr | CSR_ERR; -return detach_unit (uptr); -} diff --git a/PDP11/pdp11_mscp.h b/PDP11/pdp11_mscp.h deleted file mode 100644 index cc1fb214..00000000 --- a/PDP11/pdp11_mscp.h +++ /dev/null @@ -1,514 +0,0 @@ -/* pdp11_mscp.h: DEC MSCP and TMSCP definitionsn - - Copyright (c) 2001-2003, Robert M Supnik - Derived from work by Stephen F. Shirron - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 09-Jan-03 RMS Tape read/write end pkt is longer than disk read/write - 20-Sep-02 RMS Merged TMSCP definitions -*/ - -#ifndef _PDP11_MSCP_H_ -#define _PDP11_MSCP_H_ 0 - -/* Misc constants */ - -#define UID_DISK 2 /* disk class */ -#define UID_TAPE 3 /* tape class */ - -/* Opcodes */ - -#define OP_ABO 1 /* b: abort */ -#define OP_GCS 2 /* b: get command status */ -#define OP_GUS 3 /* b: get unit status */ -#define OP_SCC 4 /* b: set controller char */ -#define OP_AVL 8 /* b: available */ -#define OP_ONL 9 /* b: online */ -#define OP_SUC 10 /* b: set unit char */ -#define OP_DAP 11 /* b: det acc paths - nop */ -#define OP_ACC 16 /* b: access */ -#define OP_CCD 17 /* d: compare - nop */ -#define OP_ERS 18 /* b: erase */ -#define OP_FLU 19 /* d: flush - nop */ -#define OP_ERG 22 /* t: erase gap */ -#define OP_CMP 32 /* b: compare */ -#define OP_RD 33 /* b: read */ -#define OP_WR 34 /* b: write */ -#define OP_WTM 36 /* t: write tape mark */ -#define OP_POS 37 /* t: reposition */ -#define OP_FMT 47 /* d: format */ -#define OP_AVA 64 /* b: unit now avail */ -#define OP_END 0x80 /* b: end flag */ - -/* Modifiers */ - -#define MD_EXP 0x8000 /* d: express NI */ -#define MD_CMP 0x4000 /* b: compare NI */ -#define MD_CSE 0x2000 /* b: clr ser err */ -#define MD_ERR 0x1000 /* d: force error NI*/ -#define MD_CDL 0x1000 /* t: clr data lost NI*/ -#define MD_SCH 0x0800 /* t: supr cache NI */ -#define MD_SEC 0x0200 /* b: supr err corr NI */ -#define MD_SER 0x0100 /* b: supr err rec NI */ -#define MD_DLE 0x0080 /* t: detect LEOT */ -#define MD_IMM 0x0040 /* t: immediate NI */ -#define MD_EXA 0x0020 /* b: excl access NI */ -#define MD_SHD 0x0010 /* d: shadow NI */ -#define MD_UNL 0x0010 /* t avl: unload */ -#define MD_ERW 0x0008 /* t wr: enb rewrite */ -#define MD_REV 0x0008 /* t rd, pos: reverse */ -#define MD_SWP 0x0004 /* b suc: enb set wrp */ -#define MD_OBC 0x0004 /* t: pos: obj count */ -#define MD_IMF 0x0002 /* d onl: ign fmte NI */ -#define MD_RWD 0x0002 /* t pos: rewind */ -#define MD_ACL 0x0002 /* t avl: all class NI */ -#define MD_NXU 0x0001 /* b gus: next unit */ -#define MD_RIP 0x0001 /* d onl: allow rip NI */ - -/* End flags */ - -#define EF_LOG 0x0020 /* b: error log */ -#define EF_SXC 0x0010 /* b: serious exc */ -#define EF_EOT 0x0008 /* end of tape */ -#define EF_PLS 0x0004 /* pos lost */ -#define EF_DLS 0x0002 /* cached data lost NI */ - -/* Controller flags */ - -#define CF_RPL 0x8000 /* ctrl bad blk repl */ -#define CF_ATN 0x0080 /* enb attention */ -#define CF_MSC 0x0040 /* enb misc msgs */ -#define CF_OTH 0x0020 /* enb othr host msgs */ -#define CF_THS 0x0010 /* enb this host msgs */ -#define CF_MSK (CF_ATN|CF_MSC|CF_OTH|CF_THS) - -/* Unit flags */ - -#define UF_RPL 0x8000 /* d: ctrl bad blk repl */ -#define UF_CAC 0x8000 /* t: cache write back */ -#define UF_WPH 0x2000 /* b: wr prot hwre */ -#define UF_WPS 0x1000 /* b: wr prot swre */ -#define UF_SCH 0x0800 /* t: supr cache NI */ -#define UF_EXA 0x0400 /* b: exclusive NI */ -#define UF_WPD 0x0100 /* b: wr prot data NI */ -#define UF_RMV 0x0080 /* d: removable */ -#define UF_WBN 0x0040 /* t: write back NI */ -#define UF_VSS 0x0020 /* t: supr var speed NI */ -#define UF_VSU 0x0010 /* t: var speed unit NI */ -#define UF_EWR 0x0008 /* t: enh wr recovery NI */ -#define UF_CMW 0x0002 /* cmp writes NI */ -#define UF_CMR 0x0001 /* cmp reads NI */ - -/* Error log flags */ - -#define LF_SUC 0x0080 /* b: successful */ -#define LF_CON 0x0040 /* b: continuing */ -#define LF_BBR 0x0020 /* d: bad blk repl NI */ -#define LF_RCT 0x0010 /* d: err in repl NI */ -#define LF_SNR 0x0001 /* b: seq # reset */ - -/* Error log formats */ - -#define FM_CNT 0 /* b: port lf err */ -#define FM_BAD 1 /* b: bad host addr */ -#define FM_DSK 2 /* d: disk xfer */ -#define FM_SDI 3 /* d: SDI err */ -#define FM_SDE 4 /* d: sm disk err */ -#define FM_TAP 5 /* t: tape errors */ -#define FM_RPL 9 /* d: bad blk repl */ - -/* Status codes */ - -#define ST_SUC 0 /* b: successful */ -#define ST_CMD 1 /* b: invalid cmd */ -#define ST_ABO 2 /* b: aborted cmd */ -#define ST_OFL 3 /* b: unit offline */ -#define ST_AVL 4 /* b: unit avail */ -#define ST_MFE 5 /* b: media fmt err */ -#define ST_WPR 6 /* b: write prot err */ -#define ST_CMP 7 /* b: compare err */ -#define ST_DAT 8 /* b: data err */ -#define ST_HST 9 /* b: host acc err */ -#define ST_CNT 10 /* b: ctrl err */ -#define ST_DRV 11 /* b: drive err */ -#define ST_FMT 12 /* t: formatter err */ -#define ST_BOT 13 /* t: BOT encountered */ -#define ST_TMK 14 /* t: tape mark */ -#define ST_RDT 16 /* t: record trunc */ -#define ST_POL 17 /* t: pos lost */ -#define ST_SXC 18 /* b: serious exc */ -#define ST_LED 19 /* t: LEOT detect */ -#define ST_BBR 20 /* d: bad block */ -#define ST_DIA 31 /* b: diagnostic */ -#define ST_V_SUB 5 /* subcode */ -#define ST_V_INV 8 /* invalid op */ - -/* Status subcodes */ - -#define SB_SUC_IGN (1 << ST_V_SUB) /* t: unload ignored */ -#define SB_SUC_ON (8 << ST_V_SUB) /* b: already online */ -#define SB_SUC_EOT (32 << ST_V_SUB) /* t: EOT encountered */ -#define SB_SUC_RO (128 << ST_V_SUB) /* t: read only */ -#define SB_OFL_NV (1 << ST_V_SUB) /* b: no volume */ -#define SB_OFL_INOP (2 << ST_V_SUB) /* t: inoperative */ -#define SB_AVL_INU (32 << ST_V_SUB) /* b: in use */ -#define SB_WPR_SW (128 << ST_V_SUB) /* b: swre wlk */ -#define SB_WPR_HW (256 << ST_V_SUB) /* b: hwre wlk */ -#define SB_HST_OA (1 << ST_V_SUB) /* b: odd addr */ -#define SB_HST_OC (2 << ST_V_SUB) /* d: odd count */ -#define SB_HST_NXM (3 << ST_V_SUB) /* b: nx memory */ -#define SB_HST_PAR (4 << ST_V_SUB) /* b: parity err */ -#define SB_HST_PTE (5 << ST_V_SUB) /* b: mapping err */ -#define SB_DAT_RDE (7 << ST_V_SUB) /* t: read err */ - -/* Status invalid command subcodes */ - -#define I_OPCD (8 << ST_V_INV) /* inv opcode */ -#define I_FLAG (9 << ST_V_INV) /* inv flags */ -#define I_MODF (10 << ST_V_INV) /* inv modifier */ -#define I_BCNT (12 << ST_V_INV) /* inv byte cnt */ -#define I_LBN (28 << ST_V_INV) /* inv LBN */ -#define I_VRSN (12 << ST_V_INV) /* inv version */ -#define I_FMTI (28 << ST_V_INV) /* inv format */ - -/* Tape format flags */ - -#define TF_9TK 0x0100 /* 9 track */ -#define TF_9TK_NRZ 0x0001 /* 800 bpi */ -#define TF_9TK_PE 0x0002 /* 1600 bpi */ -#define TF_9TK_GRP 0x0004 /* 6250 bpi */ -#define TF_CTP 0x0200 /* TK50 */ -#define TF_CTP_LO 0x0001 /* low density */ -#define TF_CTP_HI 0x0002 /* hi density */ -#define TF_3480 0x0300 /* 3480 */ -#define TF_WOD 0x0400 /* RV80 */ - -/* Packet formats - note that all packet lengths must be multiples of 4 bytes */ - -/* Command packet header */ - -#define CMD_REFL 2 /* ref # */ -#define CMD_REFH 3 -#define CMD_UN 4 /* unit # */ -/* 5 /* reserved */ -#define CMD_OPC 6 /* opcode */ -#define CMD_MOD 7 /* modifier */ - -#define CMD_OPC_V_OPC 0 /* opcode */ -#define CMD_OPC_M_OPC 0xFF -#define CMD_OPC_V_CAA 8 /* cache NI */ -#define CMD_OPC_M_CAA 0xFF -#define CMD_OPC_V_FLG 8 /* flags */ -#define CMD_OPC_M_FLG 0xFF - -/* Response packet header */ - -#define RSP_LNT 12 -#define RSP_REFL 2 /* ref # */ -#define RSP_REFH 3 -#define RSP_UN 4 /* unit # */ -#define RSP_RSV 5 /* reserved */ -#define RSP_OPF 6 /* opcd,flg */ -#define RSP_STS 7 /* modifiers */ - -#define RSP_OPF_V_OPC 0 /* opcode */ -#define RSP_OPF_V_FLG 8 /* flags */ - -/* Abort packet - 2 W parameter, 2 W status */ - -#define ABO_LNT 16 -#define ABO_REFL 8 /* ref # */ -#define ABO_REFH 9 - -/* Avail packet - min size */ - -#define AVL_LNT 12 - -/* Erase packet - min size */ - -#define ERS_LNT 12 - -/* Erase gap - min size */ - -#define ERG_LNT 12 - -/* Flush - 10 W status (8 undefined) */ - -#define FLU_LNT 32 -/* 8 - 15 /* reserved */ -#define FLU_POSL 16 /* position */ -#define FLU_POSH 17 - -/* Write tape mark - 10W status (8 undefined) */ - -#define WTM_LNT 32 -/* 8 - 15 /* reserved */ -#define WTM_POSL 16 /* position */ -#define WTM_POSH 17 - -/* Get command status packet - 2 W parameter, 4 W status */ - -#define GCS_LNT 20 -#define GCS_REFL 8 /* ref # */ -#define GCS_REFH 9 -#define GCS_STSL 10 /* status */ -#define GCS_STSH 11 - -/* Format packet - 8 W parameters, none returned */ - -#define FMT_LNT 12 -#define FMT_IH 17 /* magic bit */ - -/* Get unit status packet - 18 W status (disk), 16W status (tape) */ - -#define GUS_LNT_D 48 -#define GUS_LNT_T 44 -#define GUS_MLUN 8 /* mlun */ -#define GUS_UFL 9 /* flags */ -#define GUS_RSVL 10 /* reserved */ -#define GUS_RSVH 11 -#define GUS_UIDA 12 /* unit ID */ -#define GUS_UIDB 13 -#define GUS_UIDC 14 -#define GUS_UIDD 15 -#define GUS_MEDL 16 /* media ID */ -#define GUS_MEDH 17 -#define GUS_UVER 23 /* unit version */ - -/* Disk specific status */ - -#define GUS_SHUN 18 /* shadowing */ -#define GUS_SHST 19 -#define GUS_TRK 20 /* track */ -#define GUS_GRP 21 /* group */ -#define GUS_CYL 22 /* cylinder */ -#define GUS_RCTS 24 /* RCT size */ -#define GUS_RBSC 25 /* RBNs, copies */ - -/* Tape specific status */ - -#define GUS_FMT 18 /* format */ -#define GUS_SPEED 19 /* speed */ -#define GUS_MENU 20 /* menu */ -#define GUS_CAP 21 /* capacity */ -#define GUS_FVER 22 /* fmtr version */ - -#define GUS_UIDD_V_MOD 0 /* unit model */ -#define GUS_UIDD_V_CLS 8 /* unit class */ -#define GUS_RB_V_RBNS 0 /* RBNs/track */ -#define GUS_RB_V_RCTC 8 /* RCT copies */ - -/* Unit online - 2 W parameter, 16 W status (disk or tape) */ - -#define ONL_LNT 44 -#define ONL_MLUN 8 /* mlun */ -#define ONL_UFL 9 /* flags */ -#define ONL_RSVL 10 /* reserved */ -#define ONL_RSVH 11 -#define ONL_UIDA 12 /* unit ID */ -#define ONL_UIDB 13 -#define ONL_UIDC 14 -#define ONL_UIDD 15 -#define ONL_MEDL 16 /* media ID */ -#define ONL_MEDH 17 - -/* Disk specific status */ - -#define ONL_SHUN 18 /* shadowing */ -#define ONL_SHST 19 -#define ONL_SIZL 20 /* size */ -#define ONL_SIZH 21 -#define ONL_VSNL 22 /* vol ser # */ -#define ONL_VSNH 23 - -/* Tape specific status */ - -#define ONL_FMT 18 /* format */ -#define ONL_SPD 19 /* speed */ -#define ONL_MAXL 20 /* max rec size */ -#define ONL_MAXH 21 -#define ONL_NREC 22 /* noise rec */ -#define ONL_RSVE 23 /* reserved */ - -#define ONL_UIDD_V_MOD 0 /* unit model */ -#define ONL_UIDD_V_CLS 8 /* unit class */ - -/* Set controller characteristics packet - 8 W parameters, 10 W status */ - -#define SCC_LNT 32 -#define SCC_MSV 8 /* MSCP version */ -#define SCC_CFL 9 /* flags */ -#define SCC_TMO 10 /* timeout */ -#define SCC_VER 11 /* ctrl version */ -#define SCC_CIDA 12 /* ctrl ID */ -#define SCC_CIDB 13 -#define SCC_CIDC 14 -#define SCC_CIDD 15 -#define SCC_MBCL 16 /* max byte count */ -#define SCC_MBCH 17 - -#define SCC_VER_V_SVER 0 /* swre vrsn */ -#define SCC_VER_V_HVER 8 /* hwre vrsn */ -#define SCC_CIDD_V_MOD 0 /* ctrl model */ -#define SCC_CIDD_V_CLS 8 /* ctrl class */ - -/* Set unit characteristics - 2 W parameter, 16 W status - same as ONL */ - -#define SUC_LNT 44 - -/* Reposition - 4 W parameters, 10 W status */ - -#define POS_LNT 32 -#define POS_RCL 8 /* record cnt */ -#define POS_RCH 9 -#define POS_TMCL 10 /* tape mk cnt */ -#define POS_TMCH 11 -/* reserved 12 - 15 */ -#define POS_POSL 16 /* position */ -#define POS_POSH 17 - -/* Data transfer packet - 10 W parameters (disk), 6W parameters (tape), - 10 W status (disk), 12W status (tape) */ - -#define RW_LNT_D 32 -#define RW_LNT_T 36 -#define RW_BCL 8 /* byte count */ -#define RW_BCH 9 -#define RW_BAL 10 /* buff desc */ -#define RW_BAH 11 -#define RW_MAPL 12 /* map table */ -#define RW_MAPH 13 -/* 14 /* reserved */ -/* 15 /* reserved */ - -/* Disk specific parameters */ - -#define RW_LBNL 16 /* LBN */ -#define RW_LBNH 17 -#define RW_WBCL 18 /* working bc */ -#define RW_WBCH 19 -#define RW_WBAL 20 /* working ba */ -#define RW_WBAH 21 -#define RW_WBLL 22 /* working lbn */ -#define RW_WBLH 23 - -/* Tape specific status */ - -#define RW_POSL 16 /* position */ -#define RW_POSH 17 -#define RW_RSZL 18 /* record size */ -#define RW_RSZH 19 - -/* Error log packet header */ - -#define ELP_REFL 2 /* ref # */ -#define ELP_REFH 3 -#define ELP_UN 4 /* unit */ -#define ELP_SEQ 5 -#define ELP_FF 6 /* fmt,flg */ -#define ELP_EVT 7 /* event */ - -#define ELP_EV_V_FMT 0 /* format */ -#define ELP_EV_V_FLG 8 /* flag */ - -/* Port last failure error log packet - 6 W status */ - -#define PLF_LNT 24 /* length */ -#define PLF_CIDA 8 /* ctrl ID */ -#define PLF_CIDB 9 -#define PLF_CIDC 10 -#define PLF_CIDD 11 -#define PLF_VER 12 /* ctrl version */ -#define PLF_ERR 13 /* err */ - -#define PLF_CIDD_V_MOD 0 /* ctrl model */ -#define PLF_CIDD_V_CLS 8 /* ctrl class */ -#define PLF_VER_V_SVER 0 /* swre ver */ -#define PLF_VER_V_HVER 8 /* hwre ver */ - -/* Disk transfer error log packet - 18 W status */ - -#define DTE_LNT 48 -#define DTE_CIDA 8 /* ctrl ID */ -#define DTE_CIDB 9 -#define DTE_CIDC 10 -#define DTE_CIDD 11 -#define DTE_VER 12 /* version */ -#define DTE_MLUN 13 /* mlun */ -#define DTE_UIDA 14 /* unit ID */ -#define DTE_UIDB 15 -#define DTE_UIDC 16 -#define DTE_UIDD 17 -#define DTE_UVER 18 -#define DTE_D2 23 -#define DTE_D3 24 -#define DTE_D4 25 - -/* Disk specific status */ - -#define DTE_SCYL 19 /* cylinder */ -#define DTE_VSNL 20 /* vol ser # */ -#define DTE_VSNH 21 -#define DTE_D1 22 /* dev params */ - -/* Tape specific status */ - -#define DTE_RETR 19 /* retry */ -#define DTE_POSL 20 /* position */ -#define DTE_POSH 21 -#define DTE_FVER 22 /* formatter ver */ - -#define DTE_CIDD_V_MOD 0 /* ctrl model */ -#define DTE_CIDD_V_CLS 8 /* ctrl class */ -#define DTE_VER_V_SVER 0 /* ctrl swre ver */ -#define DTE_VER_V_HVER 8 /* ctrl hwre ver */ -#define DTE_UIDD_V_MOD 0 /* unit model */ -#define DTE_UIDD_V_CLS 8 /* unit class */ -#define DTE_D2_V_SECT 8 -#define DTE_D3_V_SURF 0 -#define DTE_D3_V_CYL 8 - -/* Host bus error log packet - 8 W status */ - -#define HBE_LNT 28 -#define HBE_CIDA 8 /* ctrl ID */ -#define HBE_CIDB 9 -#define HBE_CIDC 10 -#define HBE_CIDD 11 -#define HBE_VER 12 /* ctrl version */ -#define HBE_RSV 13 /* reserved */ -#define HBE_BADL 14 /* bad address */ -#define HBE_BADH 15 - -#define HBE_CIDD_V_MOD 0 /* ctrl model */ -#define HBE_CIDD_V_CLS 8 /* ctrl class */ -#define HBE_VER_V_SVER 0 /* ctrl swre ver */ -#define HBE_VER_V_HVER 8 /* ctrl hwre ver */ - -/* Unit now available attention message - 10 W status, same as - first 10 W of status from get unit status -*/ - -#define UNA_LNT 32 - -#endif diff --git a/PDP11/pdp11_pclk.c b/PDP11/pdp11_pclk.c deleted file mode 100644 index af088679..00000000 --- a/PDP11/pdp11_pclk.c +++ /dev/null @@ -1,293 +0,0 @@ -/* pdp11_pclk.c: KW11P programmable clock simulator - - Copyright (c) 1993-2003, Robert M Supnik - Written by John Dundas, used with his gracious permission - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - pclk KW11P line frequency clock -*/ - -/* KW11-P Programmable Clock - - I/O Page Registers: - - CSR 17 772 540 - CSB 17 772 542 - CNT 17 772 544 - - Vector: 0104 - - Priority: BR6 - - ** Theory of Operation ** - - A real KW11-P is built around the following major components: - - 16-bit up/down counter - - 16-bit count set buffer - - 9-bit control and status register - - clocks: crystal controlled (1) 100 kHz and (2) 10 kHz clocks, - (3) a 50/60 Hz line frequency clock, and (4) an analog signal - input trigger - This software emulator for SIMH implements all of the above with - the exception of the external input trigger, which is arbitrarily - wired to 10Hz. - - Operation of this emulator is rather simplistic as compared to the - actual device. The register read and write routines are responsible - for copying internal state from the simulated device to the operating - program. Clock state variables are altered in the write routine - as well as the desired clock ticking rate. Possible rates are - given in the table below. - - Rate Bit 2 Bit 1 - 100 kHz 0 0 - 10 kHz 0 1 - Line frequency 1 0 - External 1 1 - - I think SIMH would have a hard time actually keeping up with a 100 - kHz ticking rate. I haven't tried this to verify, though. - - The clock service routine (pclk_svc) is responsible for ticking - the clock. The routine does implement up/down, repeat vs. - single-interrupt, and single clocking (maintenance). The routine - updates the internal state according to the options selected and - signals interrupts when appropriate. - - For a complete description of the device, please see DEC-11-HPWB-D - KW11-P Programmable Real-Time Clock Manual. - - ** Notes ** - - 1. The device is disabled by default. - - 2. Use XXDP V2.5 test program ZKWBJ1.BIC; loads at 1000, starts at - 1100? Seems to execute the first few tests correctly then waits - for input from the console. I don't have a description of how this - diagnostic works and thus don't know how to proceed from that point. - - 3. The read and write routines don't do anything with odd address - accesses. The manual says that byte writes don't work. - - 4. RSTS can use this clock in place of the standard KW11-L line - frequency clock. In order to do this, use the DEFAULT response in - the OPTION: dialog. To the Preferred clock prompt answer "P". - Then you have the option of line frequency "L" or some multiple of - 50 between 50 and 1000 to use the programmable portion of the clock. - - 5. This is really a Unibus peripheral and thus doesn't actually make - sense within a J-11 system as there never was a Qbus version of - this to the best of my knowledge. However the OSs I have tried - don't appear to exhibit any dissonance between this option and the - processor/bus emulation. I think the options that would make - somewhat more sense in a Qbus environment the KWV11-C and/or KWV11-S. - I don't know if any of the -11 OSs contained support for using - these as the system clock, though. -*/ - -#include "pdp11_defs.h" - -#define PCLKCSR_RDMASK 0100377 /* readable */ -#define PCLKCSR_WRMASK 0000137 /* writeable */ - -#define UNIT_V_LINE50HZ (UNIT_V_UF + 0) -#define UNIT_LINE50HZ (1 << UNIT_V_LINE50HZ) - -/* CSR - 17772540 */ - -#define CSR_V_FIX 5 /* single tick */ -#define CSR_V_UPDN 4 /* down/up */ -#define CSR_V_MODE 3 /* single/repeat */ -#define CSR_FIX (1u << CSR_V_FIX) -#define CSR_UPDN (1u << CSR_V_UPDN) -#define CSR_MODE (1u << CSR_V_MODE) -#define CSR_V_RATE 1 /* rate */ -#define CSR_M_RATE 03 -#define CSR_GETRATE(x) (((x) >> CSR_V_RATE) & CSR_M_RATE) - -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -uint32 pclk_csr = 0; /* control/status */ -uint32 pclk_csb = 0; /* count set buffer */ -uint32 pclk_ctr = 0; /* counter */ -static uint32 rate[4] = { 100000, 10000, 60, 10 }; /* ticks per second */ -static uint32 xtim[4] = { 10, 100, 16000, 100000 }; /* nominal time delay */ - -DEVICE pclk_dev; -t_stat pclk_rd (int32 *data, int32 PA, int32 access); -t_stat pclk_wr (int32 data, int32 PA, int32 access); -t_stat pclk_svc (UNIT *uptr); -t_stat pclk_reset (DEVICE *dptr); -t_stat pclk_set_line (UNIT *uptr, int32 val, char *cptr, void *desc); -void pclk_tick (void); - -/* PCLK data structures - - pclk_dev PCLK device descriptor - pclk_unit PCLK unit descriptor - pclk_reg PCLK register list -*/ - -DIB pclk_dib = { IOBA_PCLK, IOLN_PCLK, &pclk_rd, &pclk_wr, - 1, IVCL (PCLK), VEC_PCLK, { NULL } }; - -UNIT pclk_unit = { UDATA (&pclk_svc, 0, 0) }; - -REG pclk_reg[] = { - { ORDATA (CSR, pclk_csr, 16) }, - { ORDATA (CSB, pclk_csb, 16) }, - { ORDATA (CNT, pclk_ctr, 16) }, - { FLDATA (INT, IREQ (PCLK), INT_V_PCLK) }, - { FLDATA (OVFL, pclk_csr, CSR_V_ERR) }, - { FLDATA (DONE, pclk_csr, CSR_V_DONE) }, - { FLDATA (IE, pclk_csr, CSR_V_IE) }, - { FLDATA (UPDN, pclk_csr, CSR_V_UPDN) }, - { FLDATA (MODE, pclk_csr, CSR_V_MODE) }, - { FLDATA (RUN, pclk_csr, CSR_V_GO) }, - { BRDATA (TIME, xtim, 10, 32, 4), REG_NZ + PV_LEFT }, - { BRDATA (TPS, rate, 10, 32, 4), REG_NZ + PV_LEFT }, - { DRDATA (CURTIM, pclk_unit.wait, 32), REG_HRO }, - { ORDATA (DEVADDR, pclk_dib.ba, 32), REG_HRO }, - { ORDATA (DEVVEC, pclk_dib.vec, 16), REG_HRO }, - { NULL } }; - -MTAB pclk_mod[] = { - { UNIT_LINE50HZ, UNIT_LINE50HZ, "50 Hz", "50HZ", &pclk_set_line }, - { UNIT_LINE50HZ, 0, "60 Hz", "60HZ", &pclk_set_line }, - { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE pclk_dev = { - "PCLK", &pclk_unit, pclk_reg, pclk_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &pclk_reset, - NULL, NULL, NULL, - &pclk_dib, DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS }; - -/* Clock I/O address routines */ - -t_stat pclk_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 03) { -case 00: /* CSR */ - *data = pclk_csr & PCLKCSR_RDMASK; /* return CSR */ - pclk_csr = pclk_csr & ~(CSR_ERR | CSR_DONE); /* clr err, done */ - CLR_INT (PCLK); /* clr intr */ - break; -case 01: /* buffer */ - *data = 0; /* read only */ - break; -case 02: /* counter */ - *data = pclk_ctr & DMASK; /* return counter */ - break; } -return SCPE_OK; -} - -t_stat pclk_wr (int32 data, int32 PA, int32 access) -{ -int32 old_csr = pclk_csr; -int32 rv; - -switch ((PA >> 1) & 03) { -case 00: /* CSR */ - pclk_csr = data & PCLKCSR_WRMASK; /* clear and write */ - CLR_INT (PCLK); /* clr intr */ - rv = CSR_GETRATE (pclk_csr); /* new rate */ - pclk_unit.wait = xtim[rv]; /* new delay */ - if ((pclk_csr & CSR_GO) == 0) { /* stopped? */ - sim_cancel (&pclk_unit); /* cancel */ - if (data & CSR_FIX) pclk_tick (); } /* fix? tick */ - else if (((old_csr & CSR_GO) == 0) || /* run 0 -> 1? */ - (rv != CSR_GETRATE (old_csr))) { /* rate change? */ - sim_cancel (&pclk_unit); /* cancel */ - sim_activate (&pclk_unit, /* start clock */ - sim_rtcn_init (pclk_unit.wait, TMR_PCLK)); - } - break; -case 01: /* buffer */ - pclk_csb = pclk_ctr = data; /* store ctr */ - pclk_csr = pclk_csr & ~(CSR_ERR | CSR_DONE); /* clr err, done */ - CLR_INT (PCLK); /* clr intr */ - break; -case 02: /* counter */ - break; } /* read only */ -return SCPE_OK; -} - -/* Clock tick (automatic or manual) */ - -void pclk_tick (void) -{ -if (pclk_csr & CSR_UPDN) /* up or down? */ - pclk_ctr = (pclk_ctr + 1) & DMASK; /* 1 = up */ -else pclk_ctr = (pclk_ctr - 1) & DMASK; /* 0 = down */ -if (pclk_ctr == 0) { /* reached zero? */ - if (pclk_csr & CSR_DONE) /* done already set? */ - pclk_csr = pclk_csr | CSR_ERR; /* set error */ - else pclk_csr = pclk_csr | CSR_DONE; /* else set done */ - if (pclk_csr & CSR_IE) SET_INT (PCLK); /* if IE, set int */ - if (pclk_csr & CSR_MODE) pclk_ctr = pclk_csb; /* if rpt, reload */ - else { - pclk_csb = 0; /* else clr ctr */ - pclk_csr = pclk_csr & ~CSR_GO; } } /* and clr go */ -return; -} - -/* Clock service */ - -t_stat pclk_svc (UNIT *uptr) -{ -int32 rv; - -pclk_tick (); /* tick clock */ -if ((pclk_csr & CSR_GO) == 0) return SCPE_OK; /* done? */ -rv = CSR_GETRATE (pclk_csr); /* get rate */ -sim_activate (&pclk_unit, sim_rtcn_calb (rate[rv], TMR_PCLK)); -return SCPE_OK; -} - -/* Clock reset */ - -t_stat pclk_reset (DEVICE *dptr) -{ -pclk_csr = 0; /* clear reg */ -pclk_csb = 0; -pclk_ctr = 0; -CLR_INT (PCLK); /* clear int */ -sim_cancel (&pclk_unit); /* cancel */ -pclk_unit.wait = xtim[0]; /* reset delay */ -return SCPE_OK; -} - -/* Set line frequency */ - -t_stat pclk_set_line (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (val == UNIT_LINE50HZ) rate[2] = 50; -else rate[2] = 60; -return SCPE_OK; -} diff --git a/PDP11/pdp11_pt.c b/PDP11/pdp11_pt.c deleted file mode 100644 index 169c4d4c..00000000 --- a/PDP11/pdp11_pt.c +++ /dev/null @@ -1,324 +0,0 @@ -/* pdp11_pt.c: PC11 paper tape reader/punch simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - ptr paper tape reader - ptp paper tape punch - - 19-May-03 RMS Revised for new conditional compilation scheme - 25-Apr-03 RMS Revised for extended file support - 12-Sep-02 RMS Split off from pdp11_stddev.c -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#include "pdp10_defs.h" -#define PT_DIS DEV_DIS -extern int32 int_req; -extern int32 int_vec[32]; - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -#define PT_DIS DEV_DIS -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -#define PT_DIS 0 -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#endif - -#define PTRCSR_IMP (CSR_ERR+CSR_BUSY+CSR_DONE+CSR_IE) /* paper tape reader */ -#define PTRCSR_RW (CSR_IE) -#define PTPCSR_IMP (CSR_ERR + CSR_DONE + CSR_IE) /* paper tape punch */ -#define PTPCSR_RW (CSR_IE) - -int32 ptr_csr = 0; /* control/status */ -int32 ptr_stopioe = 0; /* stop on error */ -int32 ptp_csr = 0; /* control/status */ -int32 ptp_stopioe = 0; /* stop on error */ - -DEVICE ptr_dev, ptp_dev; -t_stat ptr_rd (int32 *data, int32 PA, int32 access); -t_stat ptr_wr (int32 data, int32 PA, int32 access); -t_stat ptr_svc (UNIT *uptr); -t_stat ptr_reset (DEVICE *dptr); -t_stat ptr_attach (UNIT *uptr, char *ptr); -t_stat ptr_detach (UNIT *uptr); -t_stat ptp_rd (int32 *data, int32 PA, int32 access); -t_stat ptp_wr (int32 data, int32 PA, int32 access); -t_stat ptp_svc (UNIT *uptr); -t_stat ptp_reset (DEVICE *dptr); -t_stat ptp_attach (UNIT *uptr, char *ptr); -t_stat ptp_detach (UNIT *uptr); - -/* PTR data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit descriptor - ptr_reg PTR register list -*/ - -DIB ptr_dib = { IOBA_PTR, IOLN_PTR, &ptr_rd, &ptr_wr, - 1, IVCL (PTR), VEC_PTR, { NULL } }; - -UNIT ptr_unit = { - UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), - SERIAL_IN_WAIT }; - -REG ptr_reg[] = { - { GRDATA (BUF, ptr_unit.buf, DEV_RDX, 8, 0) }, - { GRDATA (CSR, ptr_csr, DEV_RDX, 16, 0) }, - { FLDATA (INT, int_req, INT_V_PTR) }, - { FLDATA (ERR, ptr_csr, CSR_V_ERR) }, - { FLDATA (BUSY, ptr_csr, CSR_V_BUSY) }, - { FLDATA (DONE, ptr_csr, CSR_V_DONE) }, - { FLDATA (IE, ptr_csr, CSR_V_IE) }, - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptr_stopioe, 0) }, - { FLDATA (DEVDIS, ptr_dev.flags, DEV_V_DIS), REG_HRO }, - { NULL } }; - -MTAB ptr_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, ptr_mod, - 1, 10, 31, 1, DEV_RDX, 8, - NULL, NULL, &ptr_reset, - NULL, &ptr_attach, &ptr_detach, - &ptr_dib, DEV_DISABLE | PT_DIS | DEV_UBUS | DEV_QBUS }; - -/* PTP data structures - - ptp_dev PTP device descriptor - ptp_unit PTP unit descriptor - ptp_reg PTP register list -*/ - -DIB ptp_dib = { IOBA_PTP, IOLN_PTP, &ptp_rd, &ptp_wr, - 1, IVCL (PTP), VEC_PTP, { NULL } }; - -UNIT ptp_unit = { - UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG ptp_reg[] = { - { GRDATA (BUF, ptp_unit.buf, DEV_RDX, 8, 0) }, - { GRDATA (CSR, ptp_csr, DEV_RDX, 16, 0) }, - { FLDATA (INT, int_req, INT_V_PTP) }, - { FLDATA (ERR, ptp_csr, CSR_V_ERR) }, - { FLDATA (DONE, ptp_csr, CSR_V_DONE) }, - { FLDATA (IE, ptp_csr, CSR_V_IE) }, - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptp_stopioe, 0) }, - { NULL } }; - -MTAB ptp_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; - -DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, ptp_mod, - 1, 10, 31, 1, DEV_RDX, 8, - NULL, NULL, &ptp_reset, - NULL, &ptp_attach, &ptp_detach, - &ptp_dib, DEV_DISABLE | PT_DIS | DEV_UBUS | DEV_QBUS }; - -/* Paper tape reader I/O address routines */ - -t_stat ptr_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* ptr csr */ - *data = ptr_csr & PTRCSR_IMP; - return SCPE_OK; -case 1: /* ptr buf */ - ptr_csr = ptr_csr & ~CSR_DONE; - CLR_INT (PTR); - *data = ptr_unit.buf & 0377; - return SCPE_OK; } -return SCPE_NXM; /* can't get here */ -} - -t_stat ptr_wr (int32 data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* ptr csr */ - if (PA & 1) return SCPE_OK; - if ((data & CSR_IE) == 0) CLR_INT (PTR); - else if (((ptr_csr & CSR_IE) == 0) && (ptr_csr & (CSR_ERR | CSR_DONE))) - SET_INT (PTR); - if (data & CSR_GO) { - ptr_csr = (ptr_csr & ~CSR_DONE) | CSR_BUSY; - CLR_INT (PTR); - if (ptr_unit.flags & UNIT_ATT) /* data to read? */ - sim_activate (&ptr_unit, ptr_unit.wait); - else sim_activate (&ptr_unit, 0); } /* error if not */ - ptr_csr = (ptr_csr & ~PTRCSR_RW) | (data & PTRCSR_RW); - return SCPE_OK; -case 1: /* ptr buf */ - return SCPE_OK; } /* end switch PA */ -return SCPE_NXM; /* can't get here */ -} - -/* Paper tape reader service */ - -t_stat ptr_svc (UNIT *uptr) -{ -int32 temp; - -ptr_csr = (ptr_csr | CSR_ERR) & ~CSR_BUSY; -if (ptr_csr & CSR_IE) SET_INT (PTR); -if ((ptr_unit.flags & UNIT_ATT) == 0) - return IORETURN (ptr_stopioe, SCPE_UNATT); -if ((temp = getc (ptr_unit.fileref)) == EOF) { - if (feof (ptr_unit.fileref)) { - if (ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } - else perror ("PTR I/O error"); - clearerr (ptr_unit.fileref); - return SCPE_IOERR; } -ptr_csr = (ptr_csr | CSR_DONE) & ~CSR_ERR; -ptr_unit.buf = temp & 0377; -ptr_unit.pos = ptr_unit.pos + 1; -return SCPE_OK; -} - -/* Paper tape reader support routines */ - -t_stat ptr_reset (DEVICE *dptr) -{ -ptr_unit.buf = 0; -ptr_csr = 0; -if ((ptr_unit.flags & UNIT_ATT) == 0) ptr_csr = ptr_csr | CSR_ERR; -CLR_INT (PTR); -sim_cancel (&ptr_unit); -return SCPE_OK; -} - -t_stat ptr_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); -if ((ptr_unit.flags & UNIT_ATT) == 0) ptr_csr = ptr_csr | CSR_ERR; -else ptr_csr = ptr_csr & ~CSR_ERR; -return reason; -} - -t_stat ptr_detach (UNIT *uptr) -{ -ptr_csr = ptr_csr | CSR_ERR; -return detach_unit (uptr); -} - -/* Paper tape punch I/O address routines */ - -t_stat ptp_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* ptp csr */ - *data = ptp_csr & PTPCSR_IMP; - return SCPE_OK; -case 1: /* ptp buf */ - *data = ptp_unit.buf; - return SCPE_OK; } -return SCPE_NXM; /* can't get here */ -} - -t_stat ptp_wr (int32 data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* ptp csr */ - if (PA & 1) return SCPE_OK; - if ((data & CSR_IE) == 0) CLR_INT (PTP); - else if (((ptp_csr & CSR_IE) == 0) && (ptp_csr & (CSR_ERR | CSR_DONE))) - SET_INT (PTP); - ptp_csr = (ptp_csr & ~PTPCSR_RW) | (data & PTPCSR_RW); - return SCPE_OK; -case 1: /* ptp buf */ - if ((PA & 1) == 0) ptp_unit.buf = data & 0377; - ptp_csr = ptp_csr & ~CSR_DONE; - CLR_INT (PTP); - if (ptp_unit.flags & UNIT_ATT) /* file to write? */ - sim_activate (&ptp_unit, ptp_unit.wait); - else sim_activate (&ptp_unit, 0); /* error if not */ - return SCPE_OK; } /* end switch PA */ -return SCPE_NXM; /* can't get here */ -} - -/* Paper tape punch service */ - -t_stat ptp_svc (UNIT *uptr) -{ -ptp_csr = ptp_csr | CSR_ERR | CSR_DONE; -if (ptp_csr & CSR_IE) SET_INT (PTP); -if ((ptp_unit.flags & UNIT_ATT) == 0) - return IORETURN (ptp_stopioe, SCPE_UNATT); -if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { - perror ("PTP I/O error"); - clearerr (ptp_unit.fileref); - return SCPE_IOERR; } -ptp_csr = ptp_csr & ~CSR_ERR; -ptp_unit.pos = ptp_unit.pos + 1; -return SCPE_OK; -} - -/* Paper tape punch support routines */ - -t_stat ptp_reset (DEVICE *dptr) -{ -ptp_unit.buf = 0; -ptp_csr = CSR_DONE; -if ((ptp_unit.flags & UNIT_ATT) == 0) ptp_csr = ptp_csr | CSR_ERR; -CLR_INT (PTP); -sim_cancel (&ptp_unit); /* deactivate unit */ -return SCPE_OK; -} - -t_stat ptp_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); -if ((ptp_unit.flags & UNIT_ATT) == 0) ptp_csr = ptp_csr | CSR_ERR; -else ptp_csr = ptp_csr & ~CSR_ERR; -return reason; -} - -t_stat ptp_detach (UNIT *uptr) -{ -ptp_csr = ptp_csr | CSR_ERR; -return detach_unit (uptr); -} diff --git a/PDP11/pdp11_rk.c b/PDP11/pdp11_rk.c deleted file mode 100644 index 5dc8b1e2..00000000 --- a/PDP11/pdp11_rk.c +++ /dev/null @@ -1,615 +0,0 @@ -/* pdp11_rk.c: RK11 cartridge disk simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - rk RK11/RK05 cartridge disk - - 29-Sep-02 RMS Added variable address support to bootstrap - Added vector change/display support - Revised mapping mnemonics - New data structures - 26-Jan-02 RMS Revised bootstrap to conform to M9312 - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Converted FLG to array - 09-Nov-01 RMS Added bus map support - 07-Sep-01 RMS Revised device disable and interrupt mechanisms - 26-Apr-01 RMS Added device enable/disable support - 25-Mar-01 RMS Fixed block fill calculation - 15-Feb-01 RMS Corrected bootstrap string - 29-Jun-96 RMS Added unit disable support - - The RK11 is an eight drive cartridge disk subsystem. An RK05 drive - consists of 203 cylinders, each with 2 surfaces containing 12 sectors - of 512 bytes. - - The most complicated part of the RK11 controller is the concept of - interrupt "polling". While only one read or write can occur at a - time, the controller supports multiple seeks. When a seek completes, - if done is set the drive attempts to interrupt. If an interrupt is - already pending, the interrupt is "queued" until it can be processed. - When an interrupt occurs, RKDS<15:13> is loaded with the number of the - interrupting drive. - - To implement this structure, and to assure that read/write interrupts - take priority over seek interrupts, the controller contains an - interrupt queue, rkintq, with a bit for a controller interrupt and - then one for each drive. In addition, the drive number of the last - non-seeking drive is recorded in last_drv. -*/ - -#include "pdp11_defs.h" - -/* Constants */ - -#define RK_NUMWD 256 /* words/sector */ -#define RK_NUMSC 12 /* sectors/surface */ -#define RK_NUMSF 2 /* surfaces/cylinder */ -#define RK_NUMCY 203 /* cylinders/drive */ -#define RK_NUMTR (RK_NUMCY * RK_NUMSF) /* tracks/drive */ -#define RK_NUMDR 8 /* drives/controller */ -#define RK_M_NUMDR 07 -#define RK_SIZE (RK_NUMCY * RK_NUMSF * RK_NUMSC * RK_NUMWD) /* words/drive */ -#define RK_CTLI 1 /* controller int */ -#define RK_SCPI(x) (2u << (x)) /* drive int */ -#define RK_MAXFR (1 << 16) /* max transfer */ - -/* Flags in the unit flags word */ - -#define UNIT_V_HWLK (UNIT_V_UF + 0) /* hwre write lock */ -#define UNIT_V_SWLK (UNIT_V_UF + 1) /* swre write lock */ -#define UNIT_HWLK (1u << UNIT_V_HWLK) -#define UNIT_SWLK (1u << UNIT_V_SWLK) -#define UNIT_WPRT (UNIT_HWLK|UNIT_SWLK|UNIT_RO) /* write prot */ - -/* Parameters in the unit descriptor */ - -#define CYL u3 /* current cylinder */ -#define FUNC u4 /* function */ - -/* RKDS */ - -#define RKDS_SC 0000017 /* sector counter */ -#define RKDS_ON_SC 0000020 /* on sector */ -#define RKDS_WLK 0000040 /* write locked */ -#define RKDS_RWS 0000100 /* rd/wr/seek ready */ -#define RKDS_RDY 0000200 /* drive ready */ -#define RKDS_SC_OK 0000400 /* SC valid */ -#define RKDS_INC 0001000 /* seek incomplete */ -#define RKDS_UNSAFE 0002000 /* unsafe */ -#define RKDS_RK05 0004000 /* RK05 */ -#define RKDS_PWR 0010000 /* power low */ -#define RKDS_ID 0160000 /* drive ID */ -#define RKDS_V_ID 13 - -/* RKER */ - -#define RKER_WCE 0000001 /* write check */ -#define RKER_CSE 0000002 /* checksum */ -#define RKER_NXS 0000040 /* nx sector */ -#define RKER_NXC 0000100 /* nx cylinder */ -#define RKER_NXD 0000200 /* nx drive */ -#define RKER_TE 0000400 /* timing error */ -#define RKER_DLT 0001000 /* data late */ -#define RKER_NXM 0002000 /* nx memory */ -#define RKER_PGE 0004000 /* programming error */ -#define RKER_SKE 0010000 /* seek error */ -#define RKER_WLK 0020000 /* write lock */ -#define RKER_OVR 0040000 /* overrun */ -#define RKER_DRE 0100000 /* drive error */ -#define RKER_IMP 0177743 /* implemented */ -#define RKER_SOFT (RKER_WCE+RKER_CSE) /* soft errors */ -#define RKER_HARD 0177740 /* hard errors */ - -/* RKCS */ - -#define RKCS_M_FUNC 0000007 /* function */ -#define RKCS_CTLRESET 0 -#define RKCS_WRITE 1 -#define RKCS_READ 2 -#define RKCS_WCHK 3 -#define RKCS_SEEK 4 -#define RKCS_RCHK 5 -#define RKCS_DRVRESET 6 -#define RKCS_WLK 7 -#define RKCS_V_FUNC 1 -#define RKCS_MEX 0000060 /* memory extension */ -#define RKCS_V_MEX 4 -#define RKCS_SSE 0000400 /* stop on soft err */ -#define RKCS_FMT 0002000 /* format */ -#define RKCS_INH 0004000 /* inhibit increment */ -#define RKCS_SCP 0020000 /* search complete */ -#define RKCS_HERR 0040000 /* hard error */ -#define RKCS_ERR 0100000 /* error */ -#define RKCS_REAL 0026776 /* kept here */ -#define RKCS_RW 0006576 /* read/write */ -#define GET_FUNC(x) (((x) >> RKCS_V_FUNC) & RKCS_M_FUNC) - -/* RKDA */ - -#define RKDA_V_SECT 0 /* sector */ -#define RKDA_M_SECT 017 -#define RKDA_V_TRACK 4 /* track */ -#define RKDA_M_TRACK 0777 -#define RKDA_V_CYL 5 /* cylinder */ -#define RKDA_M_CYL 0377 -#define RKDA_V_DRIVE 13 /* drive */ -#define RKDA_M_DRIVE 07 -#define RKDA_DRIVE (RKDA_M_DRIVE << RKDA_V_DRIVE) -#define GET_SECT(x) (((x) >> RKDA_V_SECT) & RKDA_M_SECT) -#define GET_CYL(x) (((x) >> RKDA_V_CYL) & RKDA_M_CYL) -#define GET_TRACK(x) (((x) >> RKDA_V_TRACK) & RKDA_M_TRACK) -#define GET_DRIVE(x) (((x) >> RKDA_V_DRIVE) & RKDA_M_DRIVE) -#define GET_DA(x) ((GET_TRACK (x) * RK_NUMSC) + GET_SECT (x)) - -/* RKBA */ - -#define RKBA_IMP 0177776 /* implemented */ - -#define RK_MIN 10 -#define MAX(x,y) (((x) > (y))? (x): (y)) - -extern uint16 *M; /* memory */ -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -uint16 *rkxb = NULL; /* xfer buffer */ -int32 rkcs = 0; /* control/status */ -int32 rkds = 0; /* drive status */ -int32 rkba = 0; /* memory address */ -int32 rkda = 0; /* disk address */ -int32 rker = 0; /* error status */ -int32 rkwc = 0; /* word count */ -int32 rkintq = 0; /* interrupt queue */ -int32 last_drv = 0; /* last r/w drive */ -int32 rk_stopioe = 1; /* stop on error */ -int32 rk_swait = 10; /* seek time */ -int32 rk_rwait = 10; /* rotate time */ - -DEVICE rk_dev; -t_stat rk_rd (int32 *data, int32 PA, int32 access); -t_stat rk_wr (int32 data, int32 PA, int32 access); -int32 rk_inta (void); -t_stat rk_svc (UNIT *uptr); -t_stat rk_reset (DEVICE *dptr); -void rk_go (void); -void rk_set_done (int32 error); -void rk_clr_done (void); -t_stat rk_boot (int32 unitno, DEVICE *dptr); - -/* RK11 data structures - - rk_dev RK device descriptor - rk_unit RK unit list - rk_reg RK register list - rk_mod RK modifier list -*/ - -DIB rk_dib = { IOBA_RK, IOLN_RK, &rk_rd, &rk_wr, - 1, IVCL (RK), VEC_RK, { &rk_inta } }; - -UNIT rk_unit[] = { - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) } }; - -REG rk_reg[] = { - { ORDATA (RKCS, rkcs, 16) }, - { ORDATA (RKDA, rkda, 16) }, - { ORDATA (RKBA, rkba, 16) }, - { ORDATA (RKWC, rkwc, 16) }, - { ORDATA (RKDS, rkds, 16) }, - { ORDATA (RKER, rker, 16) }, - { ORDATA (INTQ, rkintq, 9) }, - { ORDATA (DRVN, last_drv, 3) }, - { FLDATA (INT, IREQ (RK), INT_V_RK) }, - { FLDATA (ERR, rkcs, CSR_V_ERR) }, - { FLDATA (DONE, rkcs, CSR_V_DONE) }, - { FLDATA (IE, rkcs, CSR_V_IE) }, - { DRDATA (STIME, rk_swait, 24), PV_LEFT }, - { DRDATA (RTIME, rk_rwait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, rk_stopioe, 0) }, - { ORDATA (DEVADDR, rk_dib.ba, 32), REG_HRO }, - { ORDATA (DEVVEC, rk_dib.vec, 16), REG_HRO }, - { NULL } }; - -MTAB rk_mod[] = { - { UNIT_HWLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_HWLK, UNIT_HWLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VDV, 020, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE rk_dev = { - "RK", rk_unit, rk_reg, rk_mod, - RK_NUMDR, 8, 24, 1, 8, 16, - NULL, NULL, &rk_reset, - &rk_boot, NULL, NULL, - &rk_dib, DEV_DISABLE | DEV_UBUS }; - -/* I/O dispatch routine, I/O addresses 17777400 - 17777416 - - 17777400 RKDS read only, constructed from "id'd drive" - plus current drive status flags - 17777402 RKER read only, set as operations progress, - cleared by INIT or CONTROL RESET - 17777404 RKCS read/write - 17777406 RKWC read/write - 17777410 RKBA read/write - 17777412 RKDA read/write - 17777414 RKMR read/write, unimplemented - 17777416 RKDB read only, unimplemented -*/ - -t_stat rk_rd (int32 *data, int32 PA, int32 access) -{ -UNIT *uptr; - -switch ((PA >> 1) & 07) { /* decode PA<3:1> */ -case 0: /* RKDS: read only */ - rkds = (rkds & RKDS_ID) | RKDS_RK05 | RKDS_SC_OK | - (rand () % RK_NUMSC); /* random sector */ - uptr = rk_dev.units + GET_DRIVE (rkda); /* selected unit */ - if (uptr->flags & UNIT_ATT) rkds = rkds | RKDS_RDY; /* attached? */ - if (!sim_is_active (uptr)) rkds = rkds | RKDS_RWS; /* idle? */ - if (uptr->flags & UNIT_WPRT) rkds = rkds | RKDS_WLK; - if (GET_SECT (rkda) == (rkds & RKDS_SC)) rkds = rkds | RKDS_ON_SC; - *data = rkds; - return SCPE_OK; -case 1: /* RKER: read only */ - *data = rker & RKER_IMP; - return SCPE_OK; -case 2: /* RKCS */ - rkcs = rkcs & RKCS_REAL; - if (rker) rkcs = rkcs | RKCS_ERR; /* update err flags */ - if (rker & RKER_HARD) rkcs = rkcs | RKCS_HERR; - *data = rkcs; - return SCPE_OK; -case 3: /* RKWC */ - *data = rkwc; - return SCPE_OK; -case 4: /* RKBA */ - *data = rkba & RKBA_IMP; - return SCPE_OK; -case 5: /* RKDA */ - *data = rkda; - return SCPE_OK; -default: - *data = 0; - return SCPE_OK; } /* end switch */ -} - -t_stat rk_wr (int32 data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 07) { /* decode PA<3:1> */ -case 0: /* RKDS: read only */ - return SCPE_OK; -case 1: /* RKER: read only */ - return SCPE_OK; -case 2: /* RKCS */ - rkcs = rkcs & RKCS_REAL; - if (access == WRITEB) data = (PA & 1)? - (rkcs & 0377) | (data << 8): (rkcs & ~0377) | data; - if ((data & CSR_IE) == 0) { /* int disable? */ - rkintq = 0; /* clr int queue */ - CLR_INT (RK); } /* clr int request */ - else if ((rkcs & (CSR_DONE + CSR_IE)) == CSR_DONE) { - rkintq = rkintq | RK_CTLI; /* queue ctrl int */ - SET_INT (RK); } /* set int request */ - rkcs = (rkcs & ~RKCS_RW) | (data & RKCS_RW); - if ((rkcs & CSR_DONE) && (data & CSR_GO)) rk_go (); /* new function? */ - return SCPE_OK; -case 3: /* RKWC */ - if (access == WRITEB) data = (PA & 1)? - (rkwc & 0377) | (data << 8): (rkwc & ~0377) | data; - rkwc = data; - return SCPE_OK; -case 4: /* RKBA */ - if (access == WRITEB) data = (PA & 1)? - (rkba & 0377) | (data << 8): (rkba & ~0377) | data; - rkba = data & RKBA_IMP; - return SCPE_OK; -case 5: /* RKDA */ - if ((rkcs & CSR_DONE) == 0) return SCPE_OK; - if (access == WRITEB) data = (PA & 1)? - (rkda & 0377) | (data << 8): (rkda & ~0377) | data; - rkda = data; - return SCPE_OK; -default: - return SCPE_OK; } /* end switch */ -} - -/* Initiate new function */ - -void rk_go (void) -{ -int32 i, sect, cyl, func; -UNIT *uptr; - -func = GET_FUNC (rkcs); /* get function */ -if (func == RKCS_CTLRESET) { /* control reset? */ - rker = 0; /* clear errors */ - rkda = 0; - rkba = 0; - rkcs = CSR_DONE; - rkintq = 0; /* clr int queue */ - CLR_INT (RK); /* clr int request */ - return; } -rker = rker & ~RKER_SOFT; /* clear soft errors */ -if (rker == 0) rkcs = rkcs & ~RKCS_ERR; /* redo summary */ -rkcs = rkcs & ~RKCS_SCP; /* clear sch compl*/ -rk_clr_done (); /* clear done */ -last_drv = GET_DRIVE (rkda); /* get drive no */ -uptr = rk_dev.units + last_drv; /* select unit */ -if (uptr->flags & UNIT_DIS) { /* not present? */ - rk_set_done (RKER_NXD); - return; } -if (((uptr->flags & UNIT_ATT) == 0) || sim_is_active (uptr)) { - rk_set_done (RKER_DRE); /* not att or busy */ - return; } -if (rkcs & (RKCS_INH + RKCS_FMT)) { /* format? */ - rk_set_done (RKER_PGE); - return; } -if ((func == RKCS_WRITE) && (uptr->flags & UNIT_WPRT)) { - rk_set_done (RKER_WLK); /* write and locked? */ - return; } -if (func == RKCS_WLK) { /* write lock? */ - uptr->flags = uptr->flags | UNIT_SWLK; - rk_set_done (0); - return; } -if (func == RKCS_DRVRESET) { /* drive reset? */ - uptr->flags = uptr->flags & ~UNIT_SWLK; - cyl = sect = 0; - func = RKCS_SEEK; } -else { sect = GET_SECT (rkda); - cyl = GET_CYL (rkda); } -if (sect >= RK_NUMSC) { /* bad sector? */ - rk_set_done (RKER_NXS); - return; } -if (cyl >= RK_NUMCY) { /* bad cyl? */ - rk_set_done (RKER_NXC); - return; } -i = abs (cyl - uptr->CYL) * rk_swait; /* seek time */ -if (func == RKCS_SEEK) { /* seek? */ - rk_set_done (0); /* set done */ - sim_activate (uptr, MAX (RK_MIN, i)); } /* schedule */ -else sim_activate (uptr, i + rk_rwait); -uptr->FUNC = func; /* save func */ -uptr->CYL = cyl; /* put on cylinder */ -return; -} - -/* Service unit timeout - - If seek in progress, complete seek command - Else complete data transfer command - - The unit control block contains the function and disk address for - the current command. -*/ - -t_stat rk_svc (UNIT *uptr) -{ -int32 i, drv, err, awc, wc, t; -int32 da, track, sect; -uint32 ma; -uint16 comp; - -drv = uptr - rk_dev.units; /* get drv number */ -if (uptr->FUNC == RKCS_SEEK) { /* seek */ - rkcs = rkcs | RKCS_SCP; /* set seek done */ - if (rkcs & CSR_IE) { /* ints enabled? */ - rkintq = rkintq | RK_SCPI (drv); /* queue request */ - if (rkcs & CSR_DONE) SET_INT (RK); } - else { - rkintq = 0; /* clear queue */ - CLR_INT (RK); } /* clear interrupt */ - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ - rk_set_done (RKER_DRE); - return IORETURN (rk_stopioe, SCPE_UNATT); } -ma = ((rkcs & RKCS_MEX) << (16 - RKCS_V_MEX)) | rkba; /* get mem addr */ -da = GET_DA (rkda) * RK_NUMWD; /* get disk addr */ -wc = 0200000 - rkwc; /* get wd cnt */ - -err = fseek (uptr->fileref, da * sizeof (int16), SEEK_SET); - -if ((uptr->FUNC == RKCS_READ) && (err == 0)) { /* read? */ - i = fxread (rkxb, sizeof (int16), wc, uptr->fileref); - err = ferror (uptr->fileref); - for ( ; i < wc; i++) rkxb[i] = 0; /* fill buf */ - if (t = Map_WriteW (ma, wc << 1, rkxb, MAP)) { /* store buf */ - rker = rker | RKER_NXM; /* NXM? set flg */ - wc = wc - t; } /* adj wd cnt */ - } /* end read */ - -if ((uptr->FUNC == RKCS_WRITE) && (err == 0)) { /* write? */ - if (t = Map_ReadW (ma, wc << 1, rkxb, MAP)) { /* get buf */ - rker = rker | RKER_NXM; /* NXM? set flg */ - wc = wc - t; } /* adj wd cnt */ - if (wc) { /* any xfer? */ - awc = (wc + (RK_NUMWD - 1)) & ~(RK_NUMWD - 1); /* clr to */ - for (i = wc; i < awc; i++) rkxb[i] = 0; /* end of blk */ - fxwrite (rkxb, sizeof (int16), awc, uptr->fileref); - err = ferror (uptr->fileref); } - } /* end write */ - -if ((uptr->FUNC == RKCS_WCHK) && (err == 0)) { /* write check? */ - i = fxread (rkxb, sizeof (int16), wc, uptr->fileref); - err = ferror (uptr->fileref); - for ( ; i < wc; i++) rkxb[i] = 0; /* fill buf */ - awc = wc; /* save wc */ - for (wc = 0; (err == 0) && (wc < awc); wc++) { /* loop thru buf */ - if (Map_ReadW (ma + (wc << 1), 2, &comp, MAP)) { /* mem wd */ - rker = rker | RKER_NXM; /* NXM? set flg */ - break; } - if (comp != rkxb[wc]) { /* match to disk? */ - rker = rker | RKER_WCE; /* no, err */ - if (rkcs & RKCS_SSE) break; } } - } /* end wcheck */ - -rkwc = (rkwc + wc) & 0177777; /* final word count */ -ma = ma + (wc << 1); /* final byte addr */ -rkba = ma & RKBA_IMP; /* lower 16b */ -rkcs = (rkcs & ~RKCS_MEX) | ((ma >> (16 - RKCS_V_MEX)) & RKCS_MEX); -da = da + wc + (RK_NUMWD - 1); -track = (da / RK_NUMWD) / RK_NUMSC; -sect = (da / RK_NUMWD) % RK_NUMSC; -rkda = (rkda & RKDA_DRIVE) | (track << RKDA_V_TRACK) | (sect << RKDA_V_SECT); -rk_set_done (0); - -if (err != 0) { /* error? */ - perror ("RK I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -return SCPE_OK; -} - -/* Interrupt state change routines - - rk_set_done set done and possibly errors - rk_clr_done clear done - rk_inta acknowledge intererupt -*/ - -void rk_set_done (int32 error) -{ -rkcs = rkcs | CSR_DONE; /* set done */ -if (error != 0) { - rker = rker | error; /* update error */ - if (rker) rkcs = rkcs | RKCS_ERR; /* update err flags */ - if (rker & RKER_HARD) rkcs = rkcs | RKCS_HERR; } -if (rkcs & CSR_IE) { /* int enable? */ - rkintq = rkintq | RK_CTLI; /* set ctrl int */ - SET_INT (RK); } /* request int */ -else { rkintq = 0; /* clear queue */ - CLR_INT (RK); } -return; -} - -void rk_clr_done (void) -{ -rkcs = rkcs & ~CSR_DONE; /* clear done */ -rkintq = rkintq & ~RK_CTLI; /* clear ctl int */ -CLR_INT (RK); /* clear int req */ -return; -} - -int32 rk_inta (void) -{ -int32 i; - -for (i = 0; i <= RK_NUMDR; i++) { /* loop thru intq */ - if (rkintq & (1u << i)) { /* bit i set? */ - rkintq = rkintq & ~(1u << i); /* clear bit i */ - if (rkintq) SET_INT (RK); /* queue next */ - rkds = (rkds & ~RKDS_ID) | /* id drive */ - (((i == 0)? last_drv: i - 1) << RKDS_V_ID); - return rk_dib.vec; } } /* return vector */ -rkintq = 0; /* clear queue */ -return 0; /* passive release */ -} - -/* Device reset */ - -t_stat rk_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -rkcs = CSR_DONE; -rkda = rkba = rker = rkds = 0; -rkintq = last_drv = 0; -CLR_INT (RK); -for (i = 0; i < RK_NUMDR; i++) { - uptr = rk_dev.units + i; - sim_cancel (uptr); - uptr->CYL = uptr->FUNC = 0; - uptr->flags = uptr->flags & ~UNIT_SWLK; } -if (rkxb == NULL) rkxb = calloc (RK_MAXFR, sizeof (unsigned int16)); -if (rkxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Device bootstrap */ - -#define BOOT_START 02000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 032) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 0042113, /* "KD" */ - 0012706, BOOT_START, /* MOV #boot_start, SP */ - 0012700, 0000000, /* MOV #unit, R0 ; unit number */ - 0010003, /* MOV R0, R3 */ - 0000303, /* SWAB R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0012701, 0177412, /* MOV #RKDA, R1 ; csr */ - 0010311, /* MOV R3, (R1) ; load da */ - 0005041, /* CLR -(R1) ; clear ba */ - 0012741, 0177000, /* MOV #-256.*2, -(R1) ; load wc */ - 0012741, 0000005, /* MOV #READ+GO, -(R1) ; read & go */ - 0005002, /* CLR R2 */ - 0005003, /* CLR R3 */ - 0012704, BOOT_START+020, /* MOV #START+20, R4 */ - 0005005, /* CLR R5 */ - 0105711, /* TSTB (R1) */ - 0100376, /* BPL .-2 */ - 0105011, /* CLRB (R1) */ - 0005007 /* CLR PC */ -}; - -t_stat rk_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & RK_M_NUMDR; -M[BOOT_CSR >> 1] = (rk_dib.ba & DMASK) + 012; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} diff --git a/PDP11/pdp11_rl.c b/PDP11/pdp11_rl.c deleted file mode 100644 index 67932ae4..00000000 --- a/PDP11/pdp11_rl.c +++ /dev/null @@ -1,653 +0,0 @@ -/* pdp11_rl.c: RL11 (RLV12) cartridge disk simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - rl RL11(RLV12)/RL01/RL02 cartridge disk - - 19-May-03 RMS Revised for new conditional compilation scheme - 25-Apr-03 RMS Revised for extended file support - 29-Sep-02 RMS Added variable address support to bootstrap - Added vector change/display support - Revised mapping nomenclature - New data structures - 26-Jan-02 RMS Revised bootstrap to conform to M9312 - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only, extended SET/SHOW support - 26-Nov-01 RMS Fixed per-drive error handling - 24-Nov-01 RMS Converted FLG, CAPAC to arrays - 19-Nov-01 RMS Fixed signed/unsigned mismatch in write check - 09-Nov-01 RMS Added bus map, VAX support - 07-Sep-01 RMS Revised device disable and interrupt mechanisms - 20-Aug-01 RMS Added bad block option in attach - 17-Jul-01 RMS Fixed warning from VC++ 6.0 - 26-Apr-01 RMS Added device enable/disable support - 25-Mar-01 RMS Fixed block fill calculation - 15-Feb-01 RMS Corrected bootstrap string - 12-Nov-97 RMS Added bad block table command - 25-Nov-96 RMS Default units to autosize - 29-Jun-96 RMS Added unit disable support - - The RL11 is a four drive cartridge disk subsystem. An RL01 drive - consists of 256 cylinders, each with 2 surfaces containing 40 sectors - of 256 bytes. An RL02 drive has 512 cylinders. The RLV12 is a - controller variant which supports 22b direct addressing. - - The most complicated part of the RL11 controller is the way it does - seeks. Seeking is relative to the current disk address; this requires - keeping accurate track of the current cylinder. The RL11 will not - switch heads or cross cylinders during transfers. - - The RL11 functions in three environments: - - - PDP-11 Q22 systems - the I/O map is one for one, so it's safe to - go through the I/O map - - PDP-11 Unibus 22b systems - the RL11 behaves as an 18b Unibus - peripheral and must go through the I/O map - - VAX Q22 systems - the RL11 must go through the I/O map -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#error "RL11 is not supported on the PDP-10!" - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -extern int32 cpu_18b, cpu_ubm; -#endif - -/* Constants */ - -#define RL_NUMWD 128 /* words/sector */ -#define RL_NUMSC 40 /* sectors/surface */ -#define RL_NUMSF 2 /* surfaces/cylinder */ -#define RL_NUMCY 256 /* cylinders/drive */ -#define RL_NUMDR 4 /* drives/controller */ -#define RL_MAXFR (1 << 16) /* max transfer */ -#define RL01_SIZE (RL_NUMCY * RL_NUMSF * RL_NUMSC * RL_NUMWD) /* words/drive */ -#define RL02_SIZE (RL01_SIZE * 2) /* words/drive */ - -/* Flags in the unit flags word */ - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* hwre write lock */ -#define UNIT_V_RL02 (UNIT_V_UF + 1) /* RL01 vs RL02 */ -#define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize enable */ -#define UNIT_V_DUMMY (UNIT_V_UF + 3) /* dummy flag */ -#define UNIT_DUMMY (1 << UNIT_V_DUMMY) -#define UNIT_WLK (1u << UNIT_V_WLK) -#define UNIT_RL02 (1u << UNIT_V_RL02) -#define UNIT_AUTO (1u << UNIT_V_AUTO) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protected */ - -/* Parameters in the unit descriptor */ - -#define TRK u3 /* current track */ -#define STAT u4 /* status */ - -/* RLDS, NI = not implemented, * = kept in STAT, ^ = kept in TRK */ - -#define RLDS_LOAD 0 /* no cartridge */ -#define RLDS_LOCK 5 /* lock on */ -#define RLDS_BHO 0000010 /* brushes home NI */ -#define RLDS_HDO 0000020 /* heads out NI */ -#define RLDS_CVO 0000040 /* cover open NI */ -#define RLDS_HD 0000100 /* head select ^ */ -#define RLDS_RL02 0000200 /* RL02 */ -#define RLDS_DSE 0000400 /* drv sel err NI */ -#define RLDS_VCK 0001000 /* vol check * */ -#define RLDS_WGE 0002000 /* wr gate err * */ -#define RLDS_SPE 0004000 /* spin err * */ -#define RLDS_STO 0010000 /* seek time out NI */ -#define RLDS_WLK 0020000 /* wr locked */ -#define RLDS_HCE 0040000 /* hd curr err NI */ -#define RLDS_WDE 0100000 /* wr data err NI */ -#define RLDS_ATT (RLDS_HDO+RLDS_BHO+RLDS_LOCK) /* att status */ -#define RLDS_UNATT (RLDS_CVO+RLDS_LOAD) /* unatt status */ -#define RLDS_ERR (RLDS_WDE+RLDS_HCE+RLDS_STO+RLDS_SPE+RLDS_WGE+ \ - RLDS_VCK+RLDS_DSE) /* errors bits */ - -/* RLCS */ - -#define RLCS_DRDY 0000001 /* drive ready */ -#define RLCS_M_FUNC 0000007 /* function */ -#define RLCS_NOP 0 -#define RLCS_WCHK 1 -#define RLCS_GSTA 2 -#define RLCS_SEEK 3 -#define RLCS_RHDR 4 -#define RLCS_WRITE 5 -#define RLCS_READ 6 -#define RLCS_RNOHDR 7 -#define RLCS_V_FUNC 1 -#define RLCS_M_MEX 03 /* memory extension */ -#define RLCS_V_MEX 4 -#define RLCS_MEX (RLCS_M_MEX << RLCS_V_MEX) -#define RLCS_M_DRIVE 03 -#define RLCS_V_DRIVE 8 -#define RLCS_INCMP 0002000 /* incomplete */ -#define RLCS_CRC 0004000 /* CRC error */ -#define RLCS_HDE 0010000 /* header error */ -#define RLCS_NXM 0020000 /* non-exist memory */ -#define RLCS_DRE 0040000 /* drive error */ -#define RLCS_ERR 0100000 /* error summary */ -#define RLCS_ALLERR (RLCS_ERR+RLCS_DRE+RLCS_NXM+RLCS_HDE+RLCS_CRC+RLCS_INCMP) -#define RLCS_RW 0001776 /* read/write */ -#define GET_FUNC(x) (((x) >> RLCS_V_FUNC) & RLCS_M_FUNC) -#define GET_DRIVE(x) (((x) >> RLCS_V_DRIVE) & RLCS_M_DRIVE) - -/* RLDA */ - -#define RLDA_SK_DIR 0000004 /* direction */ -#define RLDA_GS_CLR 0000010 /* clear errors */ -#define RLDA_SK_HD 0000020 /* head select */ - -#define RLDA_V_SECT 0 /* sector */ -#define RLDA_M_SECT 077 -#define RLDA_V_TRACK 6 /* track */ -#define RLDA_M_TRACK 01777 -#define RLDA_HD0 (0 << RLDA_V_TRACK) -#define RLDA_HD1 (1u << RLDA_V_TRACK) -#define RLDA_V_CYL 7 /* cylinder */ -#define RLDA_M_CYL 0777 -#define RLDA_TRACK (RLDA_M_TRACK << RLDA_V_TRACK) -#define RLDA_CYL (RLDA_M_CYL << RLDA_V_CYL) -#define GET_SECT(x) (((x) >> RLDA_V_SECT) & RLDA_M_SECT) -#define GET_CYL(x) (((x) >> RLDA_V_CYL) & RLDA_M_CYL) -#define GET_TRACK(x) (((x) >> RLDA_V_TRACK) & RLDA_M_TRACK) -#define GET_DA(x) ((GET_TRACK (x) * RL_NUMSC) + GET_SECT (x)) - -/* RLBA */ - -#define RLBA_IMP 0177776 /* implemented */ - -/* RLBAE */ - -#define RLBAE_IMP 0000077 /* implemented */ - -extern uint16 *M; -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -uint16 *rlxb = NULL; /* xfer buffer */ -int32 rlcs = 0; /* control/status */ -int32 rlba = 0; /* memory address */ -int32 rlbae = 0; /* mem addr extension */ -int32 rlda = 0; /* disk addr */ -int32 rlmp = 0, rlmp1 = 0, rlmp2 = 0; /* mp register queue */ -int32 rl_swait = 10; /* seek wait */ -int32 rl_rwait = 10; /* rotate wait */ -int32 rl_stopioe = 1; /* stop on error */ - -DEVICE rl_dev; -t_stat rl_rd (int32 *data, int32 PA, int32 access); -t_stat rl_wr (int32 data, int32 PA, int32 access); -t_stat rl_svc (UNIT *uptr); -t_stat rl_reset (DEVICE *dptr); -void rl_set_done (int32 error); -t_stat rl_boot (int32 unitno, DEVICE *dptr); -t_stat rl_attach (UNIT *uptr, char *cptr); -t_stat rl_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat rl_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds); - -/* RL11 data structures - - rl_dev RL device descriptor - rl_unit RL unit list - rl_reg RL register list - rl_mod RL modifier list -*/ - -DIB rl_dib = { IOBA_RL, IOLN_RL, &rl_rd, &rl_wr, - 1, IVCL (RL), VEC_RL, { NULL } }; - -UNIT rl_unit[] = { - { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_AUTO, RL01_SIZE) }, - { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_AUTO, RL01_SIZE) }, - { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_AUTO, RL01_SIZE) }, - { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_AUTO, RL01_SIZE) } }; - -REG rl_reg[] = { - { GRDATA (RLCS, rlcs, DEV_RDX, 16, 0) }, - { GRDATA (RLDA, rlda, DEV_RDX, 16, 0) }, - { GRDATA (RLBA, rlba, DEV_RDX, 16, 0) }, - { GRDATA (RLBAE, rlbae, DEV_RDX, 6, 0) }, - { GRDATA (RLMP, rlmp, DEV_RDX, 16, 0) }, - { GRDATA (RLMP1, rlmp1, DEV_RDX, 16, 0) }, - { GRDATA (RLMP2, rlmp2, DEV_RDX, 16, 0) }, - { FLDATA (INT, IREQ (RL), INT_V_RL) }, - { FLDATA (ERR, rlcs, CSR_V_ERR) }, - { FLDATA (DONE, rlcs, CSR_V_DONE) }, - { FLDATA (IE, rlcs, CSR_V_IE) }, - { DRDATA (STIME, rl_swait, 24), PV_LEFT }, - { DRDATA (RTIME, rl_rwait, 24), PV_LEFT }, - { URDATA (CAPAC, rl_unit[0].capac, 10, T_ADDR_W, 0, - RL_NUMDR, PV_LEFT + REG_HRO) }, - { FLDATA (STOP_IOE, rl_stopioe, 0) }, - { GRDATA (DEVADDR, rl_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, rl_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -MTAB rl_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { UNIT_DUMMY, 0, NULL, "BADBLOCK", &rl_set_bad }, - { (UNIT_RL02+UNIT_ATT), UNIT_ATT, "RL01", NULL, NULL }, - { (UNIT_RL02+UNIT_ATT), (UNIT_RL02+UNIT_ATT), "RL02", NULL, NULL }, - { (UNIT_AUTO+UNIT_RL02+UNIT_ATT), 0, "RL01", NULL, NULL }, - { (UNIT_AUTO+UNIT_RL02+UNIT_ATT), UNIT_RL02, "RL02", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_RL02), 0, NULL, "RL01", &rl_set_size }, - { (UNIT_AUTO+UNIT_RL02), UNIT_RL02, NULL, "RL02", &rl_set_size }, - { MTAB_XTD|MTAB_VDV, 010, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE rl_dev = { - "RL", rl_unit, rl_reg, rl_mod, - RL_NUMDR, DEV_RDX, 24, 1, DEV_RDX, 16, - NULL, NULL, &rl_reset, - &rl_boot, &rl_attach, NULL, - &rl_dib, DEV_DISABLE | DEV_UBUS | DEV_QBUS }; - -/* I/O dispatch routine, I/O addresses 17774400 - 17774407 - - 17774400 RLCS read/write - 17774402 RLBA read/write - 17774404 RLDA read/write - 17774406 RLMP read/write - 17774410 RLBAE read/write -*/ - -t_stat rl_rd (int32 *data, int32 PA, int32 access) -{ -UNIT *uptr; - -switch ((PA >> 1) & 07) { /* decode PA<2:1> */ -case 0: /* RLCS */ - rlcs = (rlcs & ~RLCS_MEX) | ((rlbae & RLCS_M_MEX) << RLCS_V_MEX); - if (rlcs & RLCS_ALLERR) rlcs = rlcs | RLCS_ERR; - uptr = rl_dev.units + GET_DRIVE (rlcs); - if (sim_is_active (uptr)) rlcs = rlcs & ~RLCS_DRDY; - else rlcs = rlcs | RLCS_DRDY; /* see if ready */ - *data = rlcs; - break; -case 1: /* RLBA */ - *data = rlba & RLBA_IMP; - break; -case 2: /* RLDA */ - *data = rlda; - break; -case 3: /* RLMP */ - *data = rlmp; - rlmp = rlmp1; /* ripple data */ - rlmp1 = rlmp2; - break; -case 4: /* RLBAE */ - if (UNIBUS) return SCPE_NXM; /* not in RL11 */ - *data = rlbae & RLBAE_IMP; - break; } /* end switch */ -return SCPE_OK; -} - -t_stat rl_wr (int32 data, int32 PA, int32 access) -{ -int32 curr, offs, newc, maxc; -UNIT *uptr; - -switch ((PA >> 1) & 07) { /* decode PA<2:1> */ -case 0: /* RLCS */ - rlcs = (rlcs & ~RLCS_MEX) | ((rlbae & RLCS_M_MEX) << RLCS_V_MEX); - if (rlcs & RLCS_ALLERR) rlcs = rlcs | RLCS_ERR; - uptr = rl_dev.units + GET_DRIVE (data); /* get new drive */ - if (sim_is_active (uptr)) rlcs = rlcs & ~RLCS_DRDY; - else rlcs = rlcs | RLCS_DRDY; /* see if ready */ - - if (access == WRITEB) data = (PA & 1)? - (rlcs & 0377) | (data << 8): (rlcs & ~0377) | data; - rlcs = (rlcs & ~RLCS_RW) | (data & RLCS_RW); - rlbae = (rlbae & ~RLCS_M_MEX) | ((rlcs >> RLCS_V_MEX) & RLCS_M_MEX); - if (data & CSR_DONE) { /* ready set? */ - if ((data & CSR_IE) == 0) CLR_INT (RL); - else if ((rlcs & (CSR_DONE + CSR_IE)) == CSR_DONE) - SET_INT (RL); - return SCPE_OK; } - - CLR_INT (RL); /* clear interrupt */ - rlcs = rlcs & ~RLCS_ALLERR; /* clear errors */ - switch (GET_FUNC (rlcs)) { /* case on RLCS<3:1> */ - case RLCS_NOP: /* nop */ - rl_set_done (0); - break; - case RLCS_SEEK: /* seek */ - curr = GET_CYL (uptr->TRK); /* current cylinder */ - offs = GET_CYL (rlda); /* offset */ - if (rlda & RLDA_SK_DIR) { /* in or out? */ - newc = curr + offs; /* out */ - maxc = (uptr->flags & UNIT_RL02)? - RL_NUMCY * 2: RL_NUMCY; - if (newc >= maxc) newc = maxc - 1; } - else { - newc = curr - offs; /* in */ - if (newc < 0) newc = 0; } - uptr->TRK = (newc << RLDA_V_CYL) | /* put on track */ - ((rlda & RLDA_SK_HD)? RLDA_HD1: RLDA_HD0); - sim_activate (uptr, rl_swait * abs (newc - curr)); - break; - default: /* data transfer */ - sim_activate (uptr, rl_swait); /* activate unit */ - break; } /* end switch func */ - break; /* end case RLCS */ - -case 1: /* RLBA */ - if (access == WRITEB) data = (PA & 1)? - (rlba & 0377) | (data << 8): (rlba & ~0377) | data; - rlba = data & RLBA_IMP; - break; -case 2: /* RLDA */ - if (access == WRITEB) data = (PA & 1)? - (rlda & 0377) | (data << 8): (rlda & ~0377) | data; - rlda = data; - break; -case 3: /* RLMP */ - if (access == WRITEB) data = (PA & 1)? - (rlmp & 0377) | (data << 8): (rlmp & ~0377) | data; - rlmp = rlmp1 = rlmp2 = data; - break; -case 4: /* RLBAE */ - if (UNIBUS) return SCPE_NXM; /* not in RL11 */ - if (PA & 1) return SCPE_OK; - rlbae = data & RLBAE_IMP; - rlcs = (rlcs & ~RLCS_MEX) | ((rlbae & RLCS_M_MEX) << RLCS_V_MEX); - break; } /* end switch */ -return SCPE_OK; -} - -/* Service unit timeout - - If seek in progress, complete seek command - Else complete data transfer command - - The unit control block contains the function and cylinder for - the current command. -*/ - -t_stat rl_svc (UNIT *uptr) -{ -int32 err, wc, maxwc, t; -int32 i, func, da, awc; -uint32 ma; -uint16 comp; - -func = GET_FUNC (rlcs); /* get function */ -if (func == RLCS_GSTA) { /* get status */ - if (rlda & RLDA_GS_CLR) uptr->STAT = uptr->STAT & ~RLDS_ERR; - rlmp = uptr->STAT | (uptr->TRK & RLDS_HD) | - ((uptr->flags & UNIT_ATT)? RLDS_ATT: RLDS_UNATT); - if (uptr->flags & UNIT_RL02) rlmp = rlmp | RLDS_RL02; - if (uptr->flags & UNIT_WPRT) rlmp = rlmp | RLDS_WLK; - rlmp2 = rlmp1 = rlmp; - rl_set_done (0); /* done */ - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ - rlcs = rlcs & ~RLCS_DRDY; /* clear drive ready */ - uptr->STAT = uptr->STAT | RLDS_SPE; /* spin error */ - rl_set_done (RLCS_ERR | RLCS_INCMP); /* flag error */ - return IORETURN (rl_stopioe, SCPE_UNATT); } - -if ((func == RLCS_WRITE) && (uptr->flags & UNIT_WPRT)) { - uptr->STAT = uptr->STAT | RLDS_WGE; /* write and locked */ - rl_set_done (RLCS_ERR | RLCS_DRE); - return SCPE_OK; } - -if (func == RLCS_SEEK) { /* seek? */ - rl_set_done (0); /* done */ - return SCPE_OK; } - -if (func == RLCS_RHDR) { /* read header? */ - rlmp = (uptr->TRK & RLDA_TRACK) | GET_SECT (rlda); - rlmp1 = rlmp2 = 0; - rl_set_done (0); /* done */ - return SCPE_OK; } - -if (((func != RLCS_RNOHDR) && ((uptr->TRK & RLDA_CYL) != (rlda & RLDA_CYL))) - || (GET_SECT (rlda) >= RL_NUMSC)) { /* bad cyl or sector? */ - rl_set_done (RLCS_ERR | RLCS_HDE | RLCS_INCMP); /* wrong cylinder? */ - return SCPE_OK; } - -ma = (rlbae << 16) | rlba; /* get mem addr */ -da = GET_DA (rlda) * RL_NUMWD; /* get disk addr */ -wc = 0200000 - rlmp; /* get true wc */ - -maxwc = (RL_NUMSC - GET_SECT (rlda)) * RL_NUMWD; /* max transfer */ -if (wc > maxwc) wc = maxwc; /* track overrun? */ -err = fseek (uptr->fileref, da * sizeof (int16), SEEK_SET); - -if ((func >= RLCS_READ) && (err == 0)) { /* read (no hdr)? */ - i = fxread (rlxb, sizeof (int16), wc, uptr->fileref); - err = ferror (uptr->fileref); - for ( ; i < wc; i++) rlxb[i] = 0; /* fill buffer */ - if (t = Map_WriteW (ma, wc << 1, rlxb, MAP)) { /* store buffer */ - rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */ - wc = wc - t; } /* adjust wc */ - } /* end read */ - -if ((func == RLCS_WRITE) && (err == 0)) { /* write? */ - if (t = Map_ReadW (ma, wc << 1, rlxb, MAP)) { /* fetch buffer */ - rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */ - wc = wc - t; } /* adj xfer lnt */ - if (wc) { /* any xfer? */ - awc = (wc + (RL_NUMWD - 1)) & ~(RL_NUMWD - 1); /* clr to */ - for (i = wc; i < awc; i++) rlxb[i] = 0; /* end of blk */ - fxwrite (rlxb, sizeof (int16), awc, uptr->fileref); - err = ferror (uptr->fileref); } - } /* end write */ - -if ((func == RLCS_WCHK) && (err == 0)) { /* write check? */ - i = fxread (rlxb, sizeof (int16), wc, uptr->fileref); - err = ferror (uptr->fileref); - for ( ; i < wc; i++) rlxb[i] = 0; /* fill buffer */ - awc = wc; /* save wc */ - for (wc = 0; (err == 0) && (wc < awc); wc++) { /* loop thru buf */ - if (Map_ReadW (ma + (wc << 1), 2, &comp, MAP)) { /* mem wd */ - rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */ - break; } - if (comp != rlxb[wc]) /* check to buf */ - rlcs = rlcs | RLCS_ERR | RLCS_CRC; - } /* end for */ - } /* end wcheck */ - -rlmp = (rlmp + wc) & 0177777; /* final word count */ -if (rlmp != 0) rlcs = rlcs | RLCS_ERR | RLCS_INCMP; /* completed? */ -ma = ma + (wc << 1); /* final byte addr */ -rlbae = (ma >> 16) & RLBAE_IMP; /* upper 6b */ -rlba = ma & RLBA_IMP; /* lower 16b */ -rlcs = (rlcs & ~RLCS_MEX) | ((rlbae & RLCS_M_MEX) << RLCS_V_MEX); -rlda = rlda + ((wc + (RL_NUMWD - 1)) / RL_NUMWD); -rl_set_done (0); - -if (err != 0) { /* error? */ - perror ("RL I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -return SCPE_OK; -} - -/* Set done and possibly errors */ - -void rl_set_done (int32 status) -{ - rlcs = rlcs | status | CSR_DONE; /* set done */ - if (rlcs & CSR_IE) SET_INT (RL); - else CLR_INT (RL); - return; -} - -/* Device reset - - Note that the RL11 does NOT recalibrate its drives on RESET -*/ - -t_stat rl_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -rlcs = CSR_DONE; -rlda = rlba = rlbae = rlmp = rlmp1 = rlmp2 = 0; -CLR_INT (RL); -for (i = 0; i < RL_NUMDR; i++) { - uptr = rl_dev.units + i; - sim_cancel (uptr); - uptr->STAT = 0; } -if (rlxb == NULL) rlxb = calloc (RL_MAXFR, sizeof (unsigned int16)); -if (rlxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat rl_attach (UNIT *uptr, char *cptr) -{ -uint32 p; -t_stat r; - -uptr->capac = (uptr->flags & UNIT_RL02)? RL02_SIZE: RL01_SIZE; -r = attach_unit (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* error? */ -uptr->TRK = 0; /* cylinder 0 */ -uptr->STAT = RLDS_VCK; /* new volume */ -if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK; /* seek to end */ -if ((p = ftell (uptr->fileref)) == 0) { /* new disk image? */ - if (uptr->flags & UNIT_RO) return SCPE_OK; /* if ro, done */ - return pdp11_bad_block (uptr, RL_NUMSC, RL_NUMWD); } -if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ -if (p > (RL01_SIZE * sizeof (int16))) { - uptr->flags = uptr->flags | UNIT_RL02; - uptr->capac = RL02_SIZE; } -else { uptr->flags = uptr->flags & ~UNIT_RL02; - uptr->capac = RL01_SIZE; } -return SCPE_OK; -} - -/* Set size routine */ - -t_stat rl_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = (val & UNIT_RL02)? RL02_SIZE: RL01_SIZE; -return SCPE_OK; -} - -/* Set bad block routine */ - -t_stat rl_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -return pdp11_bad_block (uptr, RL_NUMSC, RL_NUMWD); -} - -/* Device bootstrap */ - -#if defined (VM_PDP11) - -#define BOOT_START 02000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 020) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 0042114, /* "LD" */ - 0012706, BOOT_START, /* MOV #boot_start, SP */ - 0012700, 0000000, /* MOV #unit, R0 */ - 0010003, /* MOV R0, R3 */ - 0000303, /* SWAB R3 */ - 0012701, 0174400, /* MOV #RLCS, R1 ; csr */ - 0012761, 0000013, 0000004, /* MOV #13, 4(R1) ; clr err */ - 0052703, 0000004, /* BIS #4, R3 ; unit+gstat */ - 0010311, /* MOV R3, (R1) ; issue cmd */ - 0105711, /* TSTB (R1) ; wait */ - 0100376, /* BPL .-2 */ - 0105003, /* CLRB R3 */ - 0052703, 0000010, /* BIS #10, R3 ; unit+rdhdr */ - 0010311, /* MOV R3, (R1) ; issue cmd */ - 0105711, /* TSTB (R1) ; wait */ - 0100376, /* BPL .-2 */ - 0016102, 0000006, /* MOV 6(R1), R2 ; get hdr */ - 0042702, 0000077, /* BIC #77, R2 ; clr sector */ - 0005202, /* INC R2 ; magic bit */ - 0010261, 0000004, /* MOV R2, 4(R1) ; seek to 0 */ - 0105003, /* CLRB R3 */ - 0052703, 0000006, /* BIS #6, R3 ; unit+seek */ - 0010311, /* MOV R3, (R1) ; issue cmd */ - 0105711, /* TSTB (R1) ; wait */ - 0100376, /* BPL .-2 */ - 0005061, 0000002, /* CLR 2(R1) ; clr ba */ - 0005061, 0000004, /* CLR 4(R1) ; clr da */ - 0012761, 0177000, 0000006, /* MOV #-512., 6(R1) ; set wc */ - 0105003, /* CLRB R3 */ - 0052703, 0000014, /* BIS #14, R3 ; unit+read */ - 0010311, /* MOV R3, (R1) ; issue cmd */ - 0105711, /* TSTB (R1) ; wait */ - 0100376, /* BPL .-2 */ - 0042711, 0000377, /* BIC #377, (R1) */ - 0005002, /* CLR R2 */ - 0005003, /* CLR R3 */ - 0012704, BOOT_START+020, /* MOV #START+20, R4 */ - 0005005, /* CLR R5 */ - 0005007 /* CLR PC */ -}; - -t_stat rl_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & RLCS_M_DRIVE; -M[BOOT_CSR >> 1] = rl_dib.ba & DMASK; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} - -#else - -t_stat rl_boot (int32 unitno, DEVICE *dptr) -{ -return SCPE_NOFNC; -} -#endif diff --git a/PDP11/pdp11_rp.c b/PDP11/pdp11_rp.c deleted file mode 100644 index d8246211..00000000 --- a/PDP11/pdp11_rp.c +++ /dev/null @@ -1,1182 +0,0 @@ -/* pdp11_rp.c - RP04/05/06/07 RM02/03/05/80 "Massbus style" disk controller - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - rp RH/RP/RM moving head disks - - 19-May-03 RMS Revised for new conditional compilation scheme - 25-Apr-03 RMS Revised for extended file support - 29-Sep-02 RMS Added variable address support to bootstrap - Added vector change/display support - Revised mapping mnemonics - New data structures - 24-Apr-02 RMS Fixed SHOW RP ADDRESS - 26-Jan-02 RMS Revised bootstrap to conform to M9312 - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Changed RPDS, RPER, FLG, CAPAC, RPFN to arrays - 09-Nov-01 RMS Added bus map, VAX support - 23-Oct-01 RMS Fixed bug in error interrupts - 15-Oct-01 RMS Added debug logging - 05-Oct-01 RMS Rewrote interrupt handling from schematics - 02-Oct-01 RMS Revised CS1 write code - 30-Sep-01 RMS Moved CS1<5:0> into drives - 28-Sep-01 RMS Fixed interrupt handling for SC/ATA - 07-Sep-01 RMS Revised device disable and interrupt mechanisms - 20-Aug-01 RMS Added bad block option in attach - 13-Jul-01 RMS Changed fread call to fxread (found by Peter Schorn) - 14-May-01 RMS Added check for unattached drive - 25-Apr-01 RMS Added device enable/disable support - 21-Apr-01 RMS Implemented UAI function - 02-Apr-01 RMS Fixed CS1.TRE error clear function, CS2.MXF/PE writes - 25-Mar-01 RMS Corrected block fill calculation, IE write processing - 15-Feb-01 RMS Corrected bootstrap string - 14-Apr-99 RMS Changed t_addr to unsigned - 05-Oct-98 RMS Fixed bug, failing to interrupt on go error - 04-Oct-98 RMS Changed names to allow coexistence with RH/TU77 - 12-Nov-97 RMS Added bad block table command - 10-Aug-97 RMS Fixed bugs in interrupt handling - - The "Massbus style" disks consisted of several different large - capacity drives interfaced through a reasonably common (but not - 100% compatible) family of interfaces into a 22b direct addressing - port. On the PDP-11/70, this was the Massbus; but on 22b Qbus - systems, this was through many different third party controllers - which emulated the Massbus interface. - - WARNING: The interupt logic of the RH11/RH70 is unusual and must be - simulated with great precision. The RH11 has an internal interrupt - request flop, CSTB INTR, which is controlled as follows: - - Writing IE and DONE simultaneously sets CSTB INTR - - Controller clear, INIT, and interrupt acknowledge clear CSTB INTR - (and also clear IE) - - A transition of DONE from 0 to 1 sets CSTB from INTR - The output of INTR is OR'd with the AND of RPCS1 to - create the interrupt request signal. Thus, - - The DONE interrupt is edge sensitive, but the SC interrupt is - level sensitive. - - The DONE interrupt, once set, is not disabled if IE is cleared, - but the SC interrupt is. - - The RP/RM functions in four environments: - - - PDP-11 Q22 systems - bus map is bypassed - - PDP-11 Unibus systems with native 22b controllers - see above - - PDP-11 Unibus without native 22b controllers - the RP/RM behaves - as an 18b Unibus peripheral and must go through the I/O map - - VAX Q22 systems - the RP/RM must go through the I/O map - - To distinguish the two Unibus cases, the PDP-11 version of the RP/RM - provides an internal mode flag for RH11 vs RH70 -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#error "PDP-10 uses pdp10_rp.c!" - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -#define RP_WID 32 -#define DMASK 0xFFFF -#define RH11 0 /* always 22b */ -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -#define PT_DIS 0 -#define RP_WID 16 -#define RH (cpu_18b || (cpu_ubm && cpu_rh11)) -#define RH11 (RH) -extern uint16 *M; -extern int32 cpu_18b, cpu_ubm, cpu_rh11; -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#endif - -#include - -#define RP_NUMDR 8 /* #drives */ -#define RP_NUMWD 256 /* words/sector */ -#define RP_MAXFR (1 << 16) /* max transfer */ -#define GET_SECTOR(x,d) ((int) fmod (sim_gtime() / ((double) (x)), \ - ((double) drv_tab[d].sect))) - -/* Flags in the unit flags word */ - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */ -#define UNIT_M_DTYPE 7 -#define UNIT_V_AUTO (UNIT_V_UF + 4) /* autosize */ -#define UNIT_V_DUMMY (UNIT_V_UF + 5) /* dummy flag */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define UNIT_DUMMY (1 << UNIT_V_DUMMY) -#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */ - -/* Parameters in the unit descriptor */ - -#define CYL u3 /* current cylinder */ -#define FUNC u4 /* function */ - -/* RPCS1 - 176700 - control/status 1 */ - -#define CS1_GO CSR_GO /* go */ -#define CS1_V_FNC 1 /* function pos */ -#define CS1_M_FNC 037 /* function mask */ -#define CS1_FNC (CS1_M_FNC << CS1_V_FNC) -#define FNC_NOP 000 /* no operation */ -#define FNC_UNLOAD 001 /* unload */ -#define FNC_SEEK 002 /* seek */ -#define FNC_RECAL 003 /* recalibrate */ -#define FNC_DCLR 004 /* drive clear */ -#define FNC_RELEASE 005 /* port release */ -#define FNC_OFFSET 006 /* offset */ -#define FNC_RETURN 007 /* return to center */ -#define FNC_PRESET 010 /* read-in preset */ -#define FNC_PACK 011 /* pack acknowledge */ -#define FNC_SEARCH 014 /* search */ -#define FNC_XFER 024 /* >=? data xfr */ -#define FNC_WCHK 024 /* write check */ -#define FNC_WRITE 030 /* write */ -#define FNC_WRITEH 031 /* write w/ headers */ -#define FNC_READ 034 /* read */ -#define FNC_READH 035 /* read w/ headers */ -#define CS1_IE CSR_IE /* int enable */ -#define CS1_DONE CSR_DONE /* ready */ -#define CS1_V_UAE 8 /* Unibus addr ext */ -#define CS1_M_UAE 03 -#define CS1_UAE (CS1_M_UAE << CS1_V_UAE) -#define CS1_DVA 0004000 /* drive avail NI */ -#define CS1_MCPE 0020000 /* Mbus par err NI */ -#define CS1_TRE 0040000 /* transfer err */ -#define CS1_SC 0100000 /* special cond */ -#define CS1_MBZ 0012000 -#define CS1_DRV (CS1_FNC | CS1_GO) -#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC) - -/* RPWC - 176702 - word count */ - -/* RPBA - 176704 - base address */ - -#define BA_MBZ 0000001 /* must be zero */ - -/* RPDA - 176706 - sector/track */ - -#define DA_V_SC 0 /* sector pos */ -#define DA_M_SC 077 /* sector mask */ -#define DA_V_SF 8 /* track pos */ -#define DA_M_SF 077 /* track mask */ -#define DA_MBZ 0140300 -#define GET_SC(x) (((x) >> DA_V_SC) & DA_M_SC) -#define GET_SF(x) (((x) >> DA_V_SF) & DA_M_SF) - -/* RPCS2 - 176710 - control/status 2 */ - -#define CS2_V_UNIT 0 /* unit pos */ -#define CS2_M_UNIT 07 /* unit mask */ -#define CS2_UNIT (CS2_M_UNIT << CS2_V_UNIT) -#define CS2_UAI 0000010 /* addr inhibit */ -#define CS2_PAT 0000020 /* parity test NI */ -#define CS2_CLR 0000040 /* controller clear */ -#define CS2_IR 0000100 /* input ready */ -#define CS2_OR 0000200 /* output ready */ -#define CS2_MDPE 0000400 /* Mbus par err NI */ -#define CS2_MXF 0001000 /* missed xfer NI */ -#define CS2_PGE 0002000 /* program err */ -#define CS2_NEM 0004000 /* nx mem err */ -#define CS2_NED 0010000 /* nx drive err */ -#define CS2_PE 0020000 /* parity err NI */ -#define CS2_WCE 0040000 /* write check err */ -#define CS2_DLT 0100000 /* data late NI */ -#define CS2_MBZ (CS2_CLR) -#define CS2_RW (CS2_UNIT | CS2_UAI | CS2_PAT | CS2_MXF | CS2_PE) -#define CS2_ERR (CS2_MDPE | CS2_MXF | CS2_PGE | CS2_NEM | \ - CS2_NED | CS2_PE | CS2_WCE | CS2_DLT ) -#define GET_UNIT(x) (((x) >> CS2_V_UNIT) & CS2_M_UNIT) - -/* RPDS - 176712 - drive status */ - -#define DS_OF 0000001 /* offset mode */ -#define DS_VV 0000100 /* volume valid */ -#define DS_RDY 0000200 /* drive ready */ -#define DS_DPR 0000400 /* drive present */ -#define DS_PGM 0001000 /* programable NI */ -#define DS_LST 0002000 /* last sector */ -#define DS_WRL 0004000 /* write locked */ -#define DS_MOL 0010000 /* medium online */ -#define DS_PIP 0020000 /* pos in progress */ -#define DS_ERR 0040000 /* error */ -#define DS_ATA 0100000 /* attention active */ -#define DS_MBZ 0000076 - -/* RPER1 - 176714 - error status 1 */ - -#define ER1_ILF 0000001 /* illegal func */ -#define ER1_ILR 0000002 /* illegal register */ -#define ER1_RMR 0000004 /* reg mod refused */ -#define ER1_PAR 0000010 /* parity err */ -#define ER1_FER 0000020 /* format err NI */ -#define ER1_WCF 0000040 /* write clk fail NI */ -#define ER1_ECH 0000100 /* ECC hard err NI */ -#define ER1_HCE 0000200 /* hdr comp err NI */ -#define ER1_HCR 0000400 /* hdr CRC err NI */ -#define ER1_AOE 0001000 /* addr ovflo err */ -#define ER1_IAE 0002000 /* invalid addr err */ -#define ER1_WLE 0004000 /* write lock err */ -#define ER1_DTE 0010000 /* drive time err NI */ -#define ER1_OPI 0020000 /* op incomplete */ -#define ER1_UNS 0040000 /* drive unsafe */ -#define ER1_DCK 0100000 /* data check NI */ - -/* RPAS - 176716 - attention summary */ - -#define AS_U0 0000001 /* unit 0 flag */ - -/* RPLA - 176720 - look ahead register */ - -#define LA_V_SC 6 /* sector pos */ - -/* RPDB - 176722 - data buffer */ -/* RPMR - 176724 - maintenace register */ -/* RPDT - 176726 - drive type */ -/* RPSN - 176730 - serial number */ - -/* RPOF - 176732 - offset register */ - -#define OF_HCI 0002000 /* hdr cmp inh NI */ -#define OF_ECI 0004000 /* ECC inhibit NI */ -#define OF_F22 0010000 /* format NI */ -#define OF_MBZ 0161400 - -/* RPDC - 176734 - desired cylinder */ - -#define DC_V_CY 0 /* cylinder pos */ -#define DC_M_CY 01777 /* cylinder mask */ -#define DC_MBZ 0176000 -#define GET_CY(x) (((x) >> DC_V_CY) & DC_M_CY) -#define GET_DA(c,fs,d) ((((GET_CY (c) * drv_tab[d].surf) + \ - GET_SF (fs)) * drv_tab[d].sect) + GET_SC (fs)) - -/* RPCC - 176736 - current cylinder */ -/* RPER2 - 176740 - error status 2 - drive unsafe conditions - unimplemented */ -/* RPER3 - 176742 - error status 3 - more unsafe conditions - unimplemented */ -/* RPEC1 - 176744 - ECC status 1 - unimplemented */ -/* RPEC2 - 176746 - ECC status 2 - unimplemented */ - -/* RPBAE - 176750 - bus address extension */ - -#define AE_M_MAE 0 /* addr ext pos */ -#define AE_V_MAE 077 /* addr ext mask */ -#define AE_MBZ 0177700 - -/* RPCS3 - 176752 - control/status 3 - unused except for duplicate IE */ - -#define CS3_MBZ 0177660 - -/* This controller supports many different disk drive types: - - type #sectors/ #surfaces/ #cylinders/ - surface cylinder drive - - RM02/3 32 5 823 =67MB - RP04/5 22 19 411 =88MB - RM80 31 14 559 =124MB - RP06 22 19 815 =176MB - RM05 32 19 823 =256MB - RP07 50 32 630 =516MB - - In theory, each drive can be a different type. The size field in - each unit selects the drive capacity for each drive and thus the - drive type. DISKS MUST BE DECLARED IN ASCENDING SIZE. -*/ - -#define RM03_DTYPE 0 -#define RM03_SECT 32 -#define RM03_SURF 5 -#define RM03_CYL 823 -#define RM03_DEV 020024 -#define RM03_SIZE (RM03_SECT * RM03_SURF * RM03_CYL * RP_NUMWD) - -#define RP04_DTYPE 1 -#define RP04_SECT 22 -#define RP04_SURF 19 -#define RP04_CYL 411 -#define RP04_DEV 020020 -#define RP04_SIZE (RP04_SECT * RP04_SURF * RP04_CYL * RP_NUMWD) - -#define RM80_DTYPE 2 -#define RM80_SECT 31 -#define RM80_SURF 14 -#define RM80_CYL 559 -#define RM80_DEV 020026 -#define RM80_SIZE (RM80_SECT * RM80_SURF * RM80_CYL * RP_NUMWD) - -#define RP06_DTYPE 3 -#define RP06_SECT 22 -#define RP06_SURF 19 -#define RP06_CYL 815 -#define RP06_DEV 020022 -#define RP06_SIZE (RP06_SECT * RP06_SURF * RP06_CYL * RP_NUMWD) - -#define RM05_DTYPE 4 -#define RM05_SECT 32 -#define RM05_SURF 19 -#define RM05_CYL 823 -#define RM05_DEV 020027 -#define RM05_SIZE (RM05_SECT * RM05_SURF * RM05_CYL * RP_NUMWD) - -#define RP07_DTYPE 5 -#define RP07_SECT 50 -#define RP07_SURF 32 -#define RP07_CYL 630 -#define RP07_DEV 020042 -#define RP07_SIZE (RP07_SECT * RP07_SURF * RP07_CYL * RP_NUMWD) - -struct drvtyp { - int32 sect; /* sectors */ - int32 surf; /* surfaces */ - int32 cyl; /* cylinders */ - int32 size; /* #blocks */ - int32 devtype; /* device type */ -}; - -static struct drvtyp drv_tab[] = { - { RM03_SECT, RM03_SURF, RM03_CYL, RM03_SIZE, RM03_DEV }, - { RP04_SECT, RP04_SURF, RP04_CYL, RP04_SIZE, RP04_DEV }, - { RM80_SECT, RM80_SURF, RM80_CYL, RM80_SIZE, RM80_DEV }, - { RP06_SECT, RP06_SURF, RP06_CYL, RP06_SIZE, RP06_DEV }, - { RM05_SECT, RM05_SURF, RM05_CYL, RM05_SIZE, RM05_DEV }, - { RP07_SECT, RP07_SURF, RP07_CYL, RP07_SIZE, RP07_DEV }, - { 0 } }; - -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -extern int32 cpu_log; -extern FILE *sim_log; - -uint16 *rpxb = NULL; /* xfer buffer */ -int32 rpcs1 = 0; /* control/status 1 */ -int32 rpwc = 0; /* word count */ -int32 rpba = 0; /* bus address */ -int32 rpda = 0; /* track/sector */ -int32 rpcs2 = 0; /* control/status 2 */ -int32 rpds[RP_NUMDR] = { 0 }; /* drive status */ -int32 rper1[RP_NUMDR] = { 0 }; /* error status 1 */ -int32 rpdb = 0; /* data buffer */ -int32 rpmr = 0; /* maint register */ -int32 rpof = 0; /* offset */ -int32 rpdc = 0; /* cylinder */ -int32 rper2 = 0; /* error status 2 */ -int32 rper3 = 0; /* error status 3 */ -int32 rpec1 = 0; /* ECC correction 1 */ -int32 rpec2 = 0; /* ECC correction 2 */ -int32 rpbae = 0; /* bus address ext */ -int32 rpcs3 = 0; /* control/status 3 */ -int32 rpiff = 0; /* INTR flip/flop */ -int32 rp_stopioe = 1; /* stop on error */ -int32 rp_swait = 10; /* seek time */ -int32 rp_rwait = 10; /* rotate time */ -static int32 reg_in_drive[32] = { - 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -DEVICE rp_dev; -t_stat rp_rd (int32 *data, int32 PA, int32 access); -t_stat rp_wr (int32 data, int32 PA, int32 access); -int32 rp_inta (void); -t_stat rp_svc (UNIT *uptr); -t_stat rp_reset (DEVICE *dptr); -t_stat rp_boot (int32 unitno, DEVICE *dptr); -t_stat rp_attach (UNIT *uptr, char *cptr); -t_stat rp_detach (UNIT *uptr); -void update_rpcs (int32 flags, int32 drv); -void rp_go (int32 drv, int32 fnc); -t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat rp_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds); - -/* RP data structures - - rp_dev RP device descriptor - rp_unit RP unit list - rp_reg RP register list - rp_mod RP modifier list -*/ - -DIB rp_dib = { IOBA_RP, IOLN_RP, &rp_rd, &rp_wr, - 1, IVCL (RP), VEC_RP, { &rp_inta } }; - -UNIT rp_unit[] = { - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) } }; - -REG rp_reg[] = { - { GRDATA (RPCS1, rpcs1, DEV_RDX, 16, 0) }, - { GRDATA (RPWC, rpwc, DEV_RDX, 16, 0) }, - { GRDATA (RPBA, rpba, DEV_RDX, 16, 0) }, - { GRDATA (RPDA, rpda, DEV_RDX, 16, 0) }, - { GRDATA (RPCS2, rpcs2, DEV_RDX, 16, 0) }, - { BRDATA (RPDS, rpds, DEV_RDX, 16, RP_NUMDR) }, - { BRDATA (RPER1, rper1, DEV_RDX, 16, RP_NUMDR) }, - { GRDATA (RPOF, rpof, DEV_RDX, 16, 0) }, - { GRDATA (RPDC, rpdc, DEV_RDX, 16, 0) }, - { GRDATA (RPER2, rper2, DEV_RDX, 16, 0) }, - { GRDATA (RPER3, rper3, DEV_RDX, 16, 0) }, - { GRDATA (RPEC1, rpec1, DEV_RDX, 16, 0) }, - { GRDATA (RPEC2, rpec2, DEV_RDX, 16, 0) }, - { GRDATA (RPMR, rpmr, DEV_RDX, 16, 0) }, - { GRDATA (RPDB, rpdb, DEV_RDX, 16, 0) }, - { GRDATA (RPBAE, rpbae, DEV_RDX, 6, 0) }, - { GRDATA (RPCS3, rpcs3, DEV_RDX, 16, 0) }, - { FLDATA (IFF, rpiff, 0) }, - { FLDATA (INT, IREQ (RP), INT_V_RP) }, - { FLDATA (SC, rpcs1, CSR_V_ERR) }, - { FLDATA (DONE, rpcs1, CSR_V_DONE) }, - { FLDATA (IE, rpcs1, CSR_V_IE) }, - { DRDATA (STIME, rp_swait, 24), REG_NZ + PV_LEFT }, - { DRDATA (RTIME, rp_rwait, 24), REG_NZ + PV_LEFT }, - { URDATA (FNC, rp_unit[0].FUNC, DEV_RDX, 5, 0, - RP_NUMDR, REG_HRO) }, - { URDATA (CAPAC, rp_unit[0].capac, 10, T_ADDR_W, 0, - RP_NUMDR, PV_LEFT | REG_HRO) }, - { FLDATA (STOP_IOE, rp_stopioe, 0) }, - { GRDATA (DEVADDR, rp_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, rp_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -MTAB rp_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { UNIT_DUMMY, 0, NULL, "BADBLOCK", &rp_set_bad }, - { (UNIT_DTYPE+UNIT_ATT), (RM03_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RM03", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RP04_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RP04", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RM80_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RM80", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RP06_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RP06", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RM05_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RM05", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RP07_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RP07", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RM03_DTYPE << UNIT_V_DTYPE), - "RM03", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RP04_DTYPE << UNIT_V_DTYPE), - "RP04", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RM80_DTYPE << UNIT_V_DTYPE), - "RM80", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RP06_DTYPE << UNIT_V_DTYPE), - "RP06", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RM05_DTYPE << UNIT_V_DTYPE), - "RM05", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RP07_DTYPE << UNIT_V_DTYPE), - "RP07", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_DTYPE), (RM03_DTYPE << UNIT_V_DTYPE), - NULL, "RM03", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RP04_DTYPE << UNIT_V_DTYPE), - NULL, "RP04", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RM80_DTYPE << UNIT_V_DTYPE), - NULL, "RM80", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RP06_DTYPE << UNIT_V_DTYPE), - NULL, "RP06", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RM05_DTYPE << UNIT_V_DTYPE), - NULL, "RM05", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RP07_DTYPE << UNIT_V_DTYPE), - NULL, "RP07", &rp_set_size }, - { MTAB_XTD|MTAB_VDV, 0100, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE rp_dev = { - "RP", rp_unit, rp_reg, rp_mod, - RP_NUMDR, DEV_RDX, 30, 1, DEV_RDX, RP_WID, - NULL, NULL, &rp_reset, - &rp_boot, &rp_attach, &rp_detach, - &rp_dib, DEV_DISABLE | DEV_UBUS | DEV_QBUS }; - -/* I/O dispatch routines, I/O addresses 17776700 - 17776776 */ - -t_stat rp_rd (int32 *data, int32 PA, int32 access) -{ -int32 drv, dtype, i, j; - -drv = GET_UNIT (rpcs2); /* get current unit */ -dtype = GET_DTYPE (rp_unit[drv].flags); /* get drive type */ -j = (PA >> 1) & 037; /* get reg offset */ -if (reg_in_drive[j] && (rp_unit[drv].flags & UNIT_DIS)) { /* nx disk */ - rpcs2 = rpcs2 | CS2_NED; /* set error flag */ - update_rpcs (CS1_SC, drv); /* request intr */ - *data = 0; - return SCPE_OK; } - -update_rpcs (0, drv); /* update status */ -switch (j) { /* decode PA<5:1> */ -case 000: /* RPCS1 */ - *data = rpcs1; - break; -case 001: /* RPWC */ - *data = rpwc; - break; -case 002: /* RPBA */ - *data = rpba = rpba & ~BA_MBZ; - break; -case 003: /* RPDA */ - *data = rpda = rpda & ~DA_MBZ; - break; -case 004: /* RPCS2 */ - *data = rpcs2 = (rpcs2 & ~CS2_MBZ) | CS2_IR | CS2_OR; - break; -case 005: /* RPDS */ - *data = rpds[drv]; - break; -case 006: /* RPER1 */ - *data = rper1[drv]; - break; -case 007: /* RPAS */ - *data = 0; - for (i = 0; i < RP_NUMDR; i++) - if (rpds[i] & DS_ATA) *data = *data | (AS_U0 << i); - break; -case 010: /* RPLA */ - *data = GET_SECTOR (rp_rwait, dtype) << LA_V_SC; - break; -case 011: /* RPDB */ - *data = rpdb; - break; -case 012: /* RPMR */ - *data = rpmr; - break; -case 013: /* RPDT */ - *data = drv_tab[dtype].devtype; - break; -case 014: /* RPSN */ - *data = 020 | (drv + 1); - break; -case 015: /* RPOF */ - *data = rpof = rpof & ~OF_MBZ; - break; -case 016: /* RPDC */ - *data = rpdc = rpdc & ~DC_MBZ; - break; -case 017: /* RPCC, RMHR */ - *data = rp_unit[drv].CYL; - break; -case 020: /* RPER2, RMMR2 */ - *data = rper2; - break; -case 021: /* RPER3, RMER2 */ - *data = rper3; - break; -case 022: /* RPEC1 */ - *data = rpec1; - break; -case 023: /* RPEC2 */ - *data = rpec2; - break; -case 024: /* RPBAE */ - if (RH11) return SCPE_NXM; /* not in RH11 */ - *data = rpbae = rpbae & ~AE_MBZ; - break; -case 025: /* RPCS3 */ - if (RH11) return SCPE_NXM; /* not in RH11 */ - *data = rpcs3 = (rpcs3 & ~(CS1_IE | CS3_MBZ)) | (rpcs1 & CS1_IE); - break; -default: /* all others */ - rper1[drv] = rper1[drv] | ER1_ILR; - update_rpcs (0, drv); - break; } -return SCPE_OK; -} - -t_stat rp_wr (int32 data, int32 PA, int32 access) -{ -int32 cs1f, drv, i, j; -UNIT *uptr; - -cs1f = 0; /* no int on cs1 upd */ -drv = GET_UNIT (rpcs2); /* get current unit */ -uptr = rp_dev.units + drv; /* get unit */ -j = (PA >> 1) & 037; /* get reg offset */ -if (reg_in_drive[j] && (rp_unit[drv].flags & UNIT_DIS)) { /* nx disk */ - rpcs2 = rpcs2 | CS2_NED; /* set error flag */ - update_rpcs (CS1_SC, drv); /* request intr */ - return SCPE_OK; } -if (reg_in_drive[j] && sim_is_active (&rp_unit[drv])) { /* unit busy? */ - rper1[drv] = rper1[drv] | ER1_RMR; /* won't write */ - update_rpcs (0, drv); - return SCPE_OK; } - -switch (j) { /* decode PA<5:1> */ -case 000: /* RPCS1 */ - if ((access == WRITEB) && (PA & 1)) data = data << 8; - if (data & CS1_TRE) { /* error clear? */ - rpcs1 = rpcs1 & ~CS1_TRE; /* clr CS1 */ - rpcs2 = rpcs2 & ~CS2_ERR; } /* clr CS2<15:8> */ - if ((access == WRITE) || (PA & 1)) { /* hi byte write? */ - if (rpcs1 & CS1_DONE) /* done set? */ - rpcs1 = (rpcs1 & ~CS1_UAE) | (data & CS1_UAE); } - if ((access == WRITE) || !(PA & 1)) { /* lo byte write? */ - if ((data & CS1_DONE) && (data & CS1_IE)) /* to DONE+IE? */ - rpiff = 1; /* set CSTB INTR */ - rpcs1 = (rpcs1 & ~CS1_IE) | (data & CS1_IE); - if (uptr->flags & UNIT_DIS) { /* nx disk? */ - rpcs2 = rpcs2 | CS2_NED; /* set error flag */ - cs1f = CS1_SC; } /* req interrupt */ - else if (sim_is_active (uptr)) - rper1[drv] = rper1[drv] | ER1_RMR; /* won't write */ - else if (data & CS1_GO) { /* start op */ - uptr->FUNC = GET_FNC (data); /* set func */ - if ((uptr->FUNC >= FNC_XFER) && /* data xfer and */ - ((rpcs1 & CS1_DONE) == 0)) /* ~rdy? PGE */ - rpcs2 = rpcs2 | CS2_PGE; - else rp_go (drv, uptr->FUNC); } } - rpcs3 = (rpcs3 & ~CS1_IE) | (rpcs1 & CS1_IE); - rpbae = (rpbae & ~CS1_M_UAE) | ((rpcs1 >> CS1_V_UAE) & CS1_M_UAE); - break; -case 001: /* RPWC */ - if (access == WRITEB) data = (PA & 1)? - (rpwc & 0377) | (data << 8): (rpwc & ~0377) | data; - rpwc = data; - break; -case 002: /* RPBA */ - if (access == WRITEB) data = (PA & 1)? - (rpba & 0377) | (data << 8): (rpba & ~0377) | data; - rpba = data & ~BA_MBZ; - break; -case 003: /* RPDA */ - if (access == WRITEB) data = (PA & 1)? - (rpda & 0377) | (data << 8): (rpda & ~0377) | data; - rpda = data & ~DA_MBZ; - break; -case 004: /* RPCS2 */ - if ((access == WRITEB) && (PA & 1)) data = data << 8; - if (data & CS2_CLR) rp_reset (&rp_dev); /* init? */ - else { - if ((data & ~rpcs2) & (CS2_PE | CS2_MXF)) - cs1f = CS1_SC; /* diagn intr */ - if (access == WRITEB) data = (rpcs2 & /* merge data */ - ((PA & 1)? 0377: 0177400)) | data; - rpcs2 = (rpcs2 & ~CS2_RW) | (data & CS2_RW) | CS2_IR | CS2_OR; } - drv = GET_UNIT (rpcs2); - break; -case 006: /* RPER1 */ - if (access == WRITEB) break; - rper1[drv] = rper1[drv] & data; - break; -case 007: /* RPAS */ - if ((access == WRITEB) && (PA & 1)) break; - for (i = 0; i < RP_NUMDR; i++) - if (data & (AS_U0 << i)) rpds[i] = rpds[i] & ~DS_ATA; - break; -case 011: /* RPDB */ - if (access == WRITEB) data = (PA & 1)? - (rpdb & 0377) | (data << 8): (rpdb & ~0377) | data; - rpdb = data; - break; -case 012: /* RPMR */ - if (access == WRITEB) data = (PA & 1)? - (rpmr & 0377) | (data << 8): (rpmr & ~0377) | data; - rpmr = data; - break; -case 015: /* RPOF */ - if (access == WRITEB) data = (PA & 1)? - (rpof & 0377) | (data << 8): (rpof & ~0377) | data; - rpof = data & ~OF_MBZ; - break; -case 016: /* RPDC */ - if (access == WRITEB) data = (PA & 1)? - (rpdc & 0377) | (data << 8): (rpdc & ~0377) | data; - rpdc = data & ~DC_MBZ; - break; -case 024: /* RPBAE */ - if (RH11) return SCPE_NXM; /* not in RH11 */ - if ((access == WRITEB) && (PA & 1)) break; - rpbae = data & ~AE_MBZ; - rpcs1 = (rpcs1 & ~CS1_UAE) | ((rpbae << CS1_V_UAE) & CS1_UAE); - break; -case 025: /* RPCS3 */ - if (RH11) return SCPE_NXM; /* not in RH11 */ - if ((access == WRITEB) && (PA & 1)) break; - rpcs3 = data & ~CS3_MBZ; - rpcs1 = (rpcs1 & ~CS1_IE) | (rpcs3 & CS1_IE); - break; -case 005: /* RPDS */ -case 010: /* RPLA */ -case 013: /* RPDT */ -case 014: /* RPSN */ -case 017: /* RPDC, RMHR */ -case 020: /* RPER2, RMMN2 */ -case 021: /* RPER3, RMER2 */ -case 022: /* RPEC1 */ -case 023: /* RPEC2 */ - break; /* read only */ -default: /* all others */ - rper1[drv] = rper1[drv] | ER1_ILR; - break; } /* end switch */ -update_rpcs (cs1f, drv); /* update status */ -return SCPE_OK; -} - -/* Initiate operation - unit not busy, function set */ - -void rp_go (int32 drv, int32 fnc) -{ - -int32 dc, dtype, t; -UNIT *uptr; - -if (DBG_LOG (LOG_RP)) fprintf (sim_log, - ">>RP%d: fnc=%o, ds=%o, cyl=%o, da=%o, ba=%o, wc=%o\n", - drv, fnc, rpds[drv], rpdc, rpda, (rpbae << 16) | rpba, rpwc); -uptr = rp_dev.units + drv; /* get unit */ -if (uptr->flags & UNIT_DIS) { /* nx unit? */ - rpcs2 = rpcs2 | CS2_NED; /* set error flag */ - update_rpcs (CS1_SC, drv); /* request intr */ - return; } -if ((fnc != FNC_DCLR) && (rpds[drv] & DS_ERR)) { /* err & ~clear? */ - rper1[drv] = rper1[drv] | ER1_ILF; /* not allowed */ - rpds[drv] = rpds[drv] | DS_ATA; /* set attention */ - update_rpcs (CS1_SC, drv); /* request intr */ - return; } -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -rpds[drv] = rpds[drv] & ~DS_ATA; /* clear attention */ -dc = rpdc; /* assume seek, sch */ - -switch (fnc) { /* case on function */ -case FNC_DCLR: /* drive clear */ - rpda = 0; /* clear disk addr */ - rper1[drv] = rper2 = rper3 = 0; /* clear errors */ -case FNC_NOP: /* no operation */ -case FNC_RELEASE: /* port release */ - return; - -case FNC_PRESET: /* read-in preset */ - rpdc = 0; /* clear disk addr */ - rpda = 0; - rpof = 0; /* clear offset */ -case FNC_PACK: /* pack acknowledge */ - rpds[drv] = rpds[drv] | DS_VV; /* set volume valid */ - return; - -case FNC_OFFSET: /* offset mode */ -case FNC_RETURN: - if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ - break; } - rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */ - sim_activate (uptr, rp_swait); /* time operation */ - return; - -case FNC_UNLOAD: /* unload */ -case FNC_RECAL: /* recalibrate */ - dc = 0; /* seek to 0 */ -case FNC_SEEK: /* seek */ -case FNC_SEARCH: /* search */ - if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ - break; } - if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */ - (GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */ - (GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */ - rper1[drv] = rper1[drv] | ER1_IAE; - break; } - rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */ - t = abs (dc - uptr->CYL); /* cyl diff */ - if (t == 0) t = 1; /* min time */ - sim_activate (uptr, rp_swait * t); /* schedule */ - uptr->CYL = dc; /* save cylinder */ - return; - -case FNC_WRITEH: /* write headers */ -case FNC_WRITE: /* write */ -case FNC_WCHK: /* write check */ -case FNC_READ: /* read */ -case FNC_READH: /* read headers */ - if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ - break; } - rpcs2 = rpcs2 & ~CS2_ERR; /* clear errors */ - rpcs1 = rpcs1 & ~(CS1_TRE | CS1_MCPE | CS1_DONE); - if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */ - (GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */ - (GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */ - rper1[drv] = rper1[drv] | ER1_IAE; - break; } - rpds[drv] = rpds[drv] & ~DS_RDY; /* clear drive rdy */ - sim_activate (uptr, rp_rwait + (rp_swait * abs (dc - uptr->CYL))); - uptr->CYL = dc; /* save cylinder */ - return; - -default: /* all others */ - rper1[drv] = rper1[drv] | ER1_ILF; /* not supported */ - rpds[drv] = rpds[drv] | DS_ATA; /* set attention */ - break; } -rpds[drv] = rpds[drv] | DS_ATA; /* error, set attn */ -update_rpcs (CS1_SC, drv); /* req intr */ -return; -} - -/* Service unit timeout - - Complete movement or data transfer command - Unit must exist - can't remove an active unit - Unit must be attached - detach cancels in progress operations -*/ - -t_stat rp_svc (UNIT *uptr) -{ -int32 i, t, dtype, drv, err; -int32 wc, awc, da; -uint32 ba; -uint16 comp; - -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -drv = uptr - rp_dev.units; /* get drv number */ -rpds[drv] = (rpds[drv] & ~DS_PIP) | DS_RDY; /* change drive status */ - -switch (uptr->FUNC) { /* case on function */ -case FNC_OFFSET: /* offset */ - rpds[drv] = rpds[drv] | DS_OF | DS_ATA; /* set offset, attention */ - update_rpcs (CS1_SC, drv); - break; -case FNC_RETURN: /* return to centerline */ - rpds[drv] = (rpds[drv] & ~DS_OF) | DS_ATA; /* clear offset, set attn */ - update_rpcs (CS1_SC, drv); - break; -case FNC_UNLOAD: /* unload */ - rp_detach (uptr); /* detach unit */ - break; -case FNC_RECAL: /* recalibrate */ -case FNC_SEARCH: /* search */ -case FNC_SEEK: /* seek */ - rpds[drv] = rpds[drv] | DS_ATA; /* set attention */ - update_rpcs (CS1_SC, drv); - break; - -case FNC_WRITE: /* write */ - if (uptr->flags & UNIT_WPRT) { /* write locked? */ - rper1[drv] = rper1[drv] | ER1_WLE; /* set drive error */ - update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */ - break; } -case FNC_WCHK: /* write check */ -case FNC_READ: /* read */ -case FNC_READH: /* read headers */ - ba = (rpbae << 16) | rpba; /* get byte addr */ - da = GET_DA (rpdc, rpda, dtype) * RP_NUMWD; /* get disk addr */ - wc = 0200000 - rpwc; /* get true wc */ - - if ((da + wc) > drv_tab[dtype].size) { /* disk overrun? */ - rper1[drv] = rper1[drv] | ER1_AOE; /* set err */ - wc = drv_tab[dtype].size - da; /* trim xfer */ - if (da >= drv_tab[dtype].size) { /* none left? */ - update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */ - break; } } - - err = fseek (uptr->fileref, da * sizeof (int16), SEEK_SET); - if (uptr->FUNC == FNC_WRITE) { /* write? */ - if (rpcs2 & CS2_UAI) { /* no addr inc? */ - if (t = Map_ReadW (ba, 2, &comp, RH)) { /* get 1st wd */ - wc = 0; /* NXM, no xfr */ - rpcs2 = rpcs2 | CS2_NEM; } /* set nxm err */ - for (i = 0; i < wc; i++) rpxb[i] = comp; } - else { /* normal */ - if (t = Map_ReadW (ba, wc << 1, rpxb, RH)) { /* get buf */ - wc = wc - (t >> 1); /* NXM, adj wc */ - rpcs2 = rpcs2 | CS2_NEM; } /* set nxm err */ - ba = ba + (wc << 1); } /* adv ba */ - awc = (wc + (RP_NUMWD - 1)) & ~(RP_NUMWD - 1); - for (i = wc; i < awc; i++) rpxb[i] = 0; /* fill buf */ - if (wc && !err) { /* write buf */ - fxwrite (rpxb, sizeof (uint16), wc, uptr->fileref); - err = ferror (uptr->fileref); } - } /* end if wr */ - else if ((uptr->FUNC == FNC_READ) || /* read? */ - (uptr->FUNC == FNC_READH)) { - i = fxread (rpxb, sizeof (uint16), wc, uptr->fileref); - err = ferror (uptr->fileref); - for ( ; i < wc; i++) rpxb[i] = 0; /* fill buf */ - if (rpcs2 & CS2_UAI) { /* no addr inc? */ - if (t = Map_WriteW (ba, 2, &rpxb[wc - 1], RH)) { - wc = 0; /* NXM, no xfr */ - rpcs2 = rpcs2 | CS2_NEM; } } /* set nxm err */ - else { /* normal */ - if (t = Map_WriteW (ba, wc << 1, rpxb, RH)) { /* put buf */ - wc = wc - (t >> 1); /* NXM, adj wc */ - rpcs2 = rpcs2 | CS2_NEM; } /* set nxm err */ - ba = ba + (wc << 1); } /* adv ba */ - } /* end if read */ - else { /* wchk */ - i = fxread (rpxb, sizeof (uint16), wc, uptr->fileref); - err = ferror (uptr->fileref); - for ( ; i < wc; i++) rpxb[i] = 0; /* fill buf */ - awc = wc; - for (wc = 0; wc < awc; wc++) { /* loop thru buf */ - if (Map_ReadW (ba, 2, &comp, RH)) { /* read word */ - rpcs2 = rpcs2 | CS2_NEM; /* set error */ - break; } - if (comp != rpxb[wc]) { /* compare wd */ - rpcs2 = rpcs2 | CS2_WCE; /* set error */ - break; } - if ((rpcs2 & CS2_UAI) == 0) ba = ba + 2; } - } /* end else wchk */ - - rpwc = (rpwc + wc) & 0177777; /* final word count */ - rpba = (ba & 0177777) & ~BA_MBZ; /* lower 16b */ - rpbae = (ba >> 16) & ~AE_MBZ; /* upper 6b */ - rpcs1 = (rpcs1 & ~ CS1_UAE) | ((rpbae << CS1_V_UAE) & CS1_UAE); - da = da + wc + (RP_NUMWD - 1); - if (da >= drv_tab[dtype].size) rpds[drv] = rpds[drv] | DS_LST; - da = da / RP_NUMWD; - rpda = da % drv_tab[dtype].sect; - da = da / drv_tab[dtype].sect; - rpda = rpda | ((da % drv_tab[dtype].surf) << DA_V_SF); - rpdc = da / drv_tab[dtype].surf; - - if (err != 0) { /* error? */ - rper1[drv] = rper1[drv] | ER1_PAR; /* set drive error */ - update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */ - perror ("RP I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -case FNC_WRITEH: /* write headers stub */ - update_rpcs (CS1_DONE, drv); /* set done */ - break; } /* end case func */ -return SCPE_OK; -} - -/* Controller status update - - Check for done transition - Update drive status - Update RPCS1 - Update interrupt request -*/ - -void update_rpcs (int32 flag, int32 drv) -{ -int32 i; -UNIT *uptr; - -if ((flag & ~rpcs1) & CS1_DONE) /* DONE 0 to 1? */ - rpiff = (rpcs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */ -uptr = rp_dev.units + drv; /* get unit */ -if (rp_unit[drv].flags & UNIT_DIS) rpds[drv] = rper1[drv] = 0; -else rpds[drv] = (rpds[drv] | DS_DPR) & ~DS_PGM; -if (rp_unit[drv].flags & UNIT_ATT) rpds[drv] = rpds[drv] | DS_MOL; -else rpds[drv] = rpds[drv] & ~(DS_MOL | DS_VV | DS_RDY); -if (rper1[drv] | rper2 | rper3) rpds[drv] = rpds[drv] | DS_ERR | DS_ATA; -else rpds[drv] = rpds[drv] & ~DS_ERR; - -rpcs1 = (rpcs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ | CS1_DRV)) | CS1_DVA | flag; -rpcs1 = rpcs1 | (uptr->FUNC << CS1_V_FNC); -if (sim_is_active (uptr)) rpcs1 = rpcs1 | CS1_GO; -if (rpcs2 & CS2_ERR) rpcs1 = rpcs1 | CS1_TRE | CS1_SC; -else if (rpcs1 & CS1_TRE) rpcs1 = rpcs1 | CS1_SC; -for (i = 0; i < RP_NUMDR; i++) - if (rpds[i] & DS_ATA) rpcs1 = rpcs1 | CS1_SC; -if (rpiff || ((rpcs1 & CS1_SC) && (rpcs1 & CS1_DONE) && (rpcs1 & CS1_IE))) - SET_INT (RP); -else CLR_INT (RP); -return; -} - -/* Interrupt acknowledge */ - -int32 rp_inta (void) -{ -rpcs1 = rpcs1 & ~CS1_IE; /* clear int enable */ -rpcs3 = rpcs3 & ~CS1_IE; /* in both registers */ -rpiff = 0; /* clear CSTB INTR */ -return rp_dib.vec; /* acknowledge */ -} - -/* Device reset */ - -t_stat rp_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -rpcs1 = CS1_DVA | CS1_DONE; -rpcs2 = CS2_IR | CS2_OR; -rpba = rpda = 0; -rpof = rpdc = 0; -rper2 = rper3 = 0; -rpec1 = rpec2 = 0; -rpbae = rpcs3 = 0; -rpiff = 0; /* clear CSTB INTR */ -CLR_INT (RP); /* clear intr req */ -for (i = 0; i < RP_NUMDR; i++) { - uptr = rp_dev.units + i; - sim_cancel (uptr); - uptr->CYL = uptr->FUNC = 0; - if (uptr->flags & UNIT_ATT) rpds[i] = (rpds[i] & DS_VV) | - DS_DPR | DS_RDY | DS_MOL | ((uptr->flags & UNIT_WPRT)? DS_WRL: 0); - else if (uptr->flags & UNIT_DIS) rpds[i] = 0; - else rpds[i] = DS_DPR; - rper1[i] = 0; } -if (rpxb == NULL) rpxb = calloc (RP_MAXFR, sizeof (unsigned int16)); -if (rpxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Device attach */ - -t_stat rp_attach (UNIT *uptr, char *cptr) -{ -int32 drv, i, p; -t_stat r; - -uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size; -r = attach_unit (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* error? */ -drv = uptr - rp_dev.units; /* get drv number */ -rpds[drv] = DS_ATA | DS_MOL | DS_RDY | DS_DPR | /* upd drv status */ - ((uptr->flags & UNIT_WPRT)? DS_WRL: 0); -rper1[drv] = 0; -update_rpcs (CS1_SC, drv); /* upd ctlr status */ - -if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK; /* seek to end */ -if ((p = ftell (uptr->fileref)) == 0) { /* new disk image? */ - if (uptr->flags & UNIT_RO) return SCPE_OK; - return pdp11_bad_block (uptr, - drv_tab[GET_DTYPE (uptr->flags)].sect, RP_NUMWD); } -if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ -for (i = 0; drv_tab[i].sect != 0; i++) { - if (p <= (drv_tab[i].size * (int) sizeof (int16))) { - uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); - uptr->capac = drv_tab[i].size; - return SCPE_OK; } } -return SCPE_OK; -} - -/* Device detach */ - -t_stat rp_detach (UNIT *uptr) -{ -int32 drv; - -drv = uptr - rp_dev.units; /* get drv number */ -rpds[drv] = (rpds[drv] & ~(DS_MOL | DS_RDY | DS_WRL | DS_VV | DS_OF)) | - DS_ATA; -if (sim_is_active (uptr)) { /* unit active? */ - sim_cancel (uptr); /* cancel operation */ - rper1[drv] = rper1[drv] | ER1_OPI; /* set drive error */ - if (uptr->FUNC >= FNC_WCHK) /* data transfer? */ - rpcs1 = rpcs1 | CS1_DONE | CS1_TRE; } /* set done, err */ -update_rpcs (CS1_SC, drv); /* request intr */ -return detach_unit (uptr); -} - -/* Set size command validation routine */ - -t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = drv_tab[GET_DTYPE (val)].size; -return SCPE_OK; -} - -/* Set bad block routine */ - -t_stat rp_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -return pdp11_bad_block (uptr, drv_tab[GET_DTYPE (uptr->flags)].sect, RP_NUMWD); -} - -/* Device bootstrap */ - -#if defined (VM_PDP11) - -#define BOOT_START 02000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 014) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 0042102, /* "DB" */ - 0012706, BOOT_START, /* mov #boot_start, sp */ - 0012700, 0000000, /* mov #unit, r0 */ - 0012701, 0176700, /* mov #RPCS1, r1 */ - 0012761, 0000040, 0000010, /* mov #CS2_CLR, 10(r1) ; reset */ - 0010061, 0000010, /* mov r0, 10(r1) ; set unit */ - 0012711, 0000021, /* mov #RIP+GO, (r1) ; pack ack */ - 0012761, 0010000, 0000032, /* mov #FMT16B, 32(r1) ; 16b mode */ - 0012761, 0177000, 0000002, /* mov #-512., 2(r1) ; set wc */ - 0005061, 0000004, /* clr 4(r1) ; clr ba */ - 0005061, 0000006, /* clr 6(r1) ; clr da */ - 0005061, 0000034, /* clr 34(r1) ; clr cyl */ - 0012711, 0000071, /* mov #READ+GO, (r1) ; read */ - 0105711, /* tstb (r1) ; wait */ - 0100376, /* bpl .-2 */ - 0005002, /* clr R2 */ - 0005003, /* clr R3 */ - 0012704, BOOT_START+020, /* mov #start+020, r4 */ - 0005005, /* clr R5 */ - 0105011, /* clrb (r1) */ - 0005007 /* clr PC */ -}; - -t_stat rp_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & CS2_M_UNIT; -M[BOOT_CSR >> 1] = rp_dib.ba & DMASK; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} - -#else - -t_stat rp_boot (int32 unitno, DEVICE *dptr) -{ -return SCPE_NOFNC; -} - -#endif diff --git a/PDP11/pdp11_rq.c b/PDP11/pdp11_rq.c deleted file mode 100644 index 0007e840..00000000 --- a/PDP11/pdp11_rq.c +++ /dev/null @@ -1,2316 +0,0 @@ -/* pdp11_rq.c: MSCP disk controller simulator - - Copyright (c) 2002-2003, Robert M Supnik - Derived from work by Stephen F. Shirron - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - rq RQDX3 disk controller - - 11-Jul-03 RMS Fixed bug in user disk size (found by Chaskiel M Grundman) - 19-May-03 RMS Revised for new conditional compilation scheme - 25-Apr-03 RMS Revised for extended file support - 14-Mar-03 RMS Fixed variable size interaction with save/restore - 27-Feb-03 RMS Added user-defined drive support - 26-Feb-03 RMS Fixed bug in vector calculation for VAXen - 22-Feb-03 RMS Fixed ordering bug in queue process - 12-Oct-02 RMS Added multicontroller support - 29-Sep-02 RMS Changed addressing to 18b in Unibus mode - Added variable address support to bootstrap - Added vector display support - Fixed status code in HBE error log - Consolidated MSCP/TMSCP header file - New data structures - 16-Aug-02 RMS Removed unused variables (found by David Hittner) - 04-May-02 RMS Fixed bug in polling loop for queued operations - 26-Mar-02 RMS Fixed bug, reset routine cleared UF_WPH - 09-Mar-02 RMS Adjusted delays for M+ timing bugs - 04-Mar-02 RMS Added delays to initialization for M+, RSTS/E - 16-Feb-02 RMS Fixed bugs in host timeout logic, boot - 26-Jan-02 RMS Revised bootstrap to conform to M9312 - 06-Jan-02 RMS Revised enable/disable support - 30-Dec-01 RMS Revised show routines - 19-Dec-01 RMS Added bigger drives - 17-Dec-01 RMS Added queue process -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#error "RQDX3 not supported on PDP-10!" - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -#define RQ_AINC 4 -#define RQ_WID 32 -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -#define RQ_AINC 2 -#define RQ_WID 16 -extern int32 cpu_18b, cpu_ubm; -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#endif - -#if !defined (RQ_NUMCT) -#define RQ_NUMCT 4 -#elif (RQ_NUMCT > 4) -#error "Assertion failure: RQ_NUMCT exceeds 4" -#endif - -#include "pdp11_uqssp.h" -#include "pdp11_mscp.h" - -#define UF_MSK (UF_CMR|UF_CMW) /* settable flags */ - -#define RQ_SH_MAX 24 /* max display wds */ -#define RQ_SH_PPL 8 /* wds per line */ -#define RQ_SH_DPL 4 /* desc per line */ -#define RQ_SH_RI 001 /* show rings */ -#define RQ_SH_FR 002 /* show free q */ -#define RQ_SH_RS 004 /* show resp q */ -#define RQ_SH_UN 010 /* show unit q's */ - -#define RQ_CLASS 1 /* RQ class */ -#define RQ_UQPM 19 /* UQ port model */ -#define RQ_MODEL 19 /* MSCP ctrl model */ -#define RQ_HVER 1 /* hardware version */ -#define RQ_SVER 3 /* software version */ -#define RQ_DHTMO 60 /* def host timeout */ -#define RQ_DCTMO 120 /* def ctrl timeout */ -#define RQ_NUMDR 4 /* # drives */ -#define RQ_NUMBY 512 /* bytes per block */ -#define RQ_MAXFR (1 << 16) /* max xfer */ - -#define UNIT_V_ONL (UNIT_V_UF + 0) /* online */ -#define UNIT_V_WLK (UNIT_V_UF + 1) /* hwre write lock */ -#define UNIT_V_ATP (UNIT_V_UF + 2) /* attn pending */ -#define UNIT_V_DTYPE (UNIT_V_UF + 3) /* drive type */ -#define UNIT_M_DTYPE 0xF -#define UNIT_ONL (1 << UNIT_V_ONL) -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_ATP (1 << UNIT_V_ATP) -#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE) -#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) -#define cpkt u3 /* current packet */ -#define pktq u4 /* packet queue */ -#define uf buf /* settable unit flags */ -#define cnum wait /* controller index */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */ -#define RQ_RMV(u) ((drv_tab[GET_DTYPE (u->flags)].flgs & RQDF_RMV)? \ - UF_RMV: 0) -#define RQ_WPH(u) (((drv_tab[GET_DTYPE (u->flags)].flgs & RQDF_RO) || \ - (u->flags & UNIT_WPRT))? UF_WPH: 0) - -#define CST_S1 0 /* init stage 1 */ -#define CST_S1_WR 1 /* stage 1 wrap */ -#define CST_S2 2 /* init stage 2 */ -#define CST_S3 3 /* init stage 3 */ -#define CST_S3_PPA 4 /* stage 3 sa wait */ -#define CST_S3_PPB 5 /* stage 3 ip wait */ -#define CST_S4 6 /* stage 4 */ -#define CST_UP 7 /* online */ -#define CST_DEAD 8 /* fatal error */ - -#define ERR 0 /* must be SCPE_OK! */ -#define OK 1 - -#define RQ_TIMER (RQ_NUMDR) -#define RQ_QUEUE (RQ_TIMER + 1) - -/* Internal packet management. The real RQDX3 manages its packets as true - linked lists. However, use of actual addresses in structures won't work - with save/restore. Accordingly, the packets are an arrayed structure, - and links are actually subscripts. To minimize complexity, packet[0] - is not used (0 = end of list), and the number of packets must be a power - of two. -*/ - -#define RQ_NPKTS 32 /* # packets (pwr of 2) */ -#define RQ_M_NPKTS (RQ_NPKTS - 1) /* mask */ -#define RQ_PKT_SIZE_W 32 /* payload size (wds) */ -#define RQ_PKT_SIZE (RQ_PKT_SIZE_W * sizeof (int16)) - -struct rqpkt { - int16 link; /* link to next */ - uint16 d[RQ_PKT_SIZE_W]; }; /* data */ - -/* Packet payload extraction and insertion; cp defines controller */ - -#define GETP(p,w,f) ((cp->pak[p].d[w] >> w##_V_##f) & w##_M_##f) -#define GETP32(p,w) (((uint32) cp->pak[p].d[w]) | \ - (((uint32) cp->pak[p].d[(w)+1]) << 16)) -#define PUTP32(p,w,x) cp->pak[p].d[w] = (x) & 0xFFFF; \ - cp->pak[p].d[(w)+1] = ((x) >> 16) & 0xFFFF - -/* Disk formats. An RQDX3 consists of the following regions: - - XBNs Extended blocks - contain information about disk format, - also holds track being reformatted during bad block repl. - Size = sectors/track + 1, replicated 3 times. - DBNs Diagnostic blocks - used by diagnostics. Sized to pad - out the XBNs to a cylinder boundary. - LBNs Logical blocks - contain user information. - RCT Replacement control table - first block contains status, - second contains data from block being replaced, remaining - contain information about replaced bad blocks. - Size = RBNs/128 + 3, replicated 4-8 times. - RBNs Replacement blocks - used to replace bad blocks. - - The simulator does not need to perform bad block replacement; the - information below is for simulating RCT reads, if required. - - Note that an RA drive has a different order: LBNs, RCT, XBN, DBN; - the RBNs are spare blocks at the end of every track. -*/ - -#define RCT_OVHD 2 /* #ovhd blks */ -#define RCT_ENTB 128 /* entries/blk */ -#define RCT_END 0x80000000 /* marks RCT end */ - -/* The RQDX3 supports multiple disk drive types: - - type sec surf cyl tpg gpc RCT LBNs - - RX50 10 1 80 5 16 - 800 - RX33 15 2 80 2 1 - 2400 - RD51 18 4 306 4 1 36*4 21600 - RD31 17 4 615 4 1 3*8 41560 - RD52 17 8 512 8 1 4*8 60480 - RD53 17 7 1024 7 1 5*8 138672 - RD54 17 15 1225 15 1 7*8 311200 - - The simulator also supports larger drives that only existed - on SDI controllers. XBN, DBN, RCTS and RCTC are not known - for the SDI drives and are not used by the simulator: - - RA82 57 15 1435 15 1 ?*8 1216665 - RA72 51 20 1921? 20 1 ?*8 1953300 - RA90 69 13 2656 13 1 ?*8 2376153 - RA92 73 13 3101 13 1 ?*8 2940951 - - Each drive can be a different type. The drive field in the - unit flags specified the drive type and thus, indirectly, - the drive size. -*/ - -#define RQDF_RMV 01 /* removable */ -#define RQDF_RO 02 /* read only */ -#define RQDF_SDI 04 /* SDI drive */ - -#define RX50_DTYPE 0 -#define RX50_SECT 10 -#define RX50_SURF 1 -#define RX50_CYL 80 -#define RX50_TPG 5 -#define RX50_GPC 16 -#define RX50_XBN 0 -#define RX50_DBN 0 -#define RX50_LBN 800 -#define RX50_RCTS 0 -#define RX50_RCTC 0 -#define RX50_RBN 0 -#define RX50_MOD 7 -#define RX50_MED 0x25658032 -#define RX50_FLGS RQDF_RMV - -#define RX33_DTYPE 1 -#define RX33_SECT 15 -#define RX33_SURF 2 -#define RX33_CYL 80 -#define RX33_TPG 2 -#define RX33_GPC 1 -#define RX33_XBN 0 -#define RX33_DBN 0 -#define RX33_LBN 2400 -#define RX33_RCTS 0 -#define RX33_RCTC 0 -#define RX33_RBN 0 -#define RX33_MOD 10 -#define RX33_MED 0x25658021 -#define RX33_FLGS RQDF_RMV - -#define RD51_DTYPE 2 -#define RD51_SECT 18 -#define RD51_SURF 4 -#define RD51_CYL 306 -#define RD51_TPG 4 -#define RD51_GPC 1 -#define RD51_XBN 57 -#define RD51_DBN 87 -#define RD51_LBN 21600 -#define RD51_RCTS 36 -#define RD51_RCTC 4 -#define RD51_RBN 144 -#define RD51_MOD 6 -#define RD51_MED 0x25644033 -#define RD51_FLGS 0 - -#define RD31_DTYPE 3 -#define RD31_SECT 17 -#define RD31_SURF 4 -#define RD31_CYL 615 /* last unused */ -#define RD31_TPG RD31_SURF -#define RD31_GPC 1 -#define RD31_XBN 54 -#define RD31_DBN 14 -#define RD31_LBN 41560 -#define RD31_RCTS 3 -#define RD31_RCTC 8 -#define RD31_RBN 100 -#define RD31_MOD 12 -#define RD31_MED 0x2564401F -#define RD31_FLGS 0 - -#define RD52_DTYPE 4 /* Quantum params */ -#define RD52_SECT 17 -#define RD52_SURF 8 -#define RD52_CYL 512 -#define RD52_TPG RD52_SURF -#define RD52_GPC 1 -#define RD52_XBN 54 -#define RD52_DBN 82 -#define RD52_LBN 60480 -#define RD52_RCTS 4 -#define RD52_RCTC 8 -#define RD52_RBN 168 -#define RD52_MOD 8 -#define RD52_MED 0x25644034 -#define RD52_FLGS 0 - -#define RD53_DTYPE 5 -#define RD53_SECT 17 -#define RD53_SURF 8 -#define RD53_CYL 1024 /* last unused */ -#define RD53_TPG RD53_SURF -#define RD53_GPC 1 -#define RD53_XBN 54 -#define RD53_DBN 82 -#define RD53_LBN 138672 -#define RD53_RCTS 5 -#define RD53_RCTC 8 -#define RD53_RBN 280 -#define RD53_MOD 9 -#define RD53_MED 0x25644035 -#define RD53_FLGS 0 - -#define RD54_DTYPE 6 -#define RD54_SECT 17 -#define RD54_SURF 15 -#define RD54_CYL 1225 /* last unused */ -#define RD54_TPG RD54_SURF -#define RD54_GPC 1 -#define RD54_XBN 54 -#define RD54_DBN 201 -#define RD54_LBN 311200 -#define RD54_RCTS 7 -#define RD54_RCTC 8 -#define RD54_RBN 609 -#define RD54_MOD 13 -#define RD54_MED 0x25644036 -#define RD54_FLGS 0 - -#define RA82_DTYPE 7 /* SDI drive */ -#define RA82_SECT 57 /* +1 spare/track */ -#define RA82_SURF 15 -#define RA82_CYL 1435 /* 0-1422 user */ -#define RA82_TPG RA82_SURF -#define RA82_GPC 1 -#define RA82_XBN 3420 /* cyl 1427-1430 */ -#define RA82_DBN 3420 /* cyl 1431-1434 */ -#define RA82_LBN 1216665 /* 57*15*1423 */ -#define RA82_RCTS 400 /* cyl 1423-1426 */ -#define RA82_RCTC 8 -#define RA82_RBN 21345 /* 1 *15*1423 */ -#define RA82_MOD 11 -#define RA82_MED 0x25641052 -#define RA82_FLGS RQDF_SDI - -#define RRD40_DTYPE 8 -#define RRD40_SECT 128 -#define RRD40_SURF 1 -#define RRD40_CYL 10400 -#define RRD40_TPG RRD40_SURF -#define RRD40_GPC 1 -#define RRD40_XBN 0 -#define RRD40_DBN 0 -#define RRD40_LBN 1331200 -#define RRD40_RCTS 0 -#define RRD40_RCTC 0 -#define RRD40_RBN 0 -#define RRD40_MOD 26 -#define RRD40_MED 0x25652228 -#define RRD40_FLGS (RQDF_RMV | RQDF_RO) - -#define RA72_DTYPE 9 /* SDI drive */ -#define RA72_SECT 51 /* +1 spare/trk */ -#define RA72_SURF 20 -#define RA72_CYL 1921 /* 0-1914 user */ -#define RA72_TPG RA72_SURF -#define RA72_GPC 1 -#define RA72_XBN 2040 /* cyl 1917-1918? */ -#define RA72_DBN 2040 /* cyl 1920-1921? */ -#define RA72_LBN 1953300 /* 51*20*1915 */ -#define RA72_RCTS 400 /* cyl 1915-1916? */ -#define RA72_RCTC 5 /* ? */ -#define RA72_RBN 38300 /* 1 *20*1915 */ -#define RA72_MOD 37 -#define RA72_MED 0x25641048 -#define RA72_FLGS RQDF_SDI - -#define RA90_DTYPE 10 /* SDI drive */ -#define RA90_SECT 69 /* +1 spare/trk */ -#define RA90_SURF 13 -#define RA90_CYL 2656 /* 0-2648 user */ -#define RA90_TPG RA90_SURF -#define RA90_GPC 1 -#define RA90_XBN 1794 /* cyl 2651-2652? */ -#define RA90_DBN 1794 /* cyl 2653-2654? */ -#define RA90_LBN 2376153 /* 69*13*2649 */ -#define RA90_RCTS 400 /* cyl 2649-2650? */ -#define RA90_RCTC 6 /* ? */ -#define RA90_RBN 34437 /* 1 *13*2649 */ -#define RA90_MOD 19 -#define RA90_MED 0x2564105A -#define RA90_FLGS RQDF_SDI - -#define RA92_DTYPE 11 /* SDI drive */ -#define RA92_SECT 73 /* +1 spare/trk */ -#define RA92_SURF 13 -#define RA92_CYL 3101 /* 0-3098 user */ -#define RA92_TPG RA92_SURF -#define RA92_GPC 1 -#define RA92_XBN 174 /* cyl 3100? */ -#define RA92_DBN 775 -#define RA92_LBN 2940951 /* 73*13*3099 */ -#define RA92_RCTS 316 /* cyl 3099? */ -#define RA92_RCTC 3 /* ? */ -#define RA92_RBN 40287 /* 1 *13*3099 */ -#define RA92_MOD 29 -#define RA92_MED 0x2564105C -#define RA92_FLGS RQDF_SDI - -#define RA8U_DTYPE 12 /* user defined */ -#define RA8U_SECT 57 /* +1 spare/track */ -#define RA8U_SURF 15 -#define RA8U_CYL 1435 /* 0-1422 user */ -#define RA8U_TPG RA8U_SURF -#define RA8U_GPC 1 -#define RA8U_XBN 3420 /* cyl 1427-1430 */ -#define RA8U_DBN 3420 /* cyl 1431-1434 */ -#define RA8U_LBN 1216665 /* 57*15*1423 */ -#define RA8U_RCTS 400 /* cyl 1423-1426 */ -#define RA8U_RCTC 8 -#define RA8U_RBN 21345 /* 1 *15*1423 */ -#define RA8U_MOD 11 /* RA82 */ -#define RA8U_MED 0x25641052 /* RA82 */ -#define RA8U_FLGS RQDF_SDI -#define RA8U_MINC 5 /* min cap MB */ -#define RA8U_MAXC 2000 /* max cap MB */ -#define RA8U_EMAXC 1000000 /* ext max cap */ - -struct drvtyp { - int32 sect; /* sectors */ - int32 surf; /* surfaces */ - int32 cyl; /* cylinders */ - int32 tpg; /* trk/grp */ - int32 gpc; /* grp/cyl */ - int32 xbn; /* XBN size */ - int32 dbn; /* DBN size */ - uint32 lbn; /* LBN size */ - int32 rcts; /* RCT size */ - int32 rctc; /* RCT copies */ - int32 rbn; /* RBNs */ - int32 mod; /* MSCP model */ - int32 med; /* MSCP media */ - int32 flgs; /* flags */ - char *name; /* name */ -}; - -#define RQ_DRV(d) \ - d##_SECT, d##_SURF, d##_CYL, d##_TPG, \ - d##_GPC, d##_XBN, d##_DBN, d##_LBN, \ - d##_RCTS, d##_RCTC, d##_RBN, d##_MOD, \ - d##_MED, d##_FLGS -#define RQ_SIZE(d) (d##_LBN * RQ_NUMBY) - -static struct drvtyp drv_tab[] = { - { RQ_DRV (RX50), "RX50" }, { RQ_DRV (RX33), "RX33" }, - { RQ_DRV (RD51), "RD51" }, { RQ_DRV (RD31), "RD31" }, - { RQ_DRV (RD52), "RD52" }, { RQ_DRV (RD53), "RD53" }, - { RQ_DRV (RD54), "RD54" }, { RQ_DRV (RA82), "RA82" }, - { RQ_DRV (RRD40), "RRD40" }, { RQ_DRV (RA72), "RA72" }, - { RQ_DRV (RA90), "RA90" }, { RQ_DRV (RA92), "RA92" }, - { RQ_DRV (RA8U), "RAUSER" }, { 0 } }; - -extern int32 int_req[IPL_HLVL]; -extern int32 tmr_poll, clk_tps; -extern int32 cpu_log; -extern UNIT cpu_unit; -extern FILE *sim_log; -extern uint32 sim_taddr_64; - -uint16 *rqxb = NULL; /* xfer buffer */ -int32 rq_itime = 200; /* init time, except */ -int32 rq_itime4 = 10; /* stage 4 */ -int32 rq_qtime = 200; /* queue time */ -int32 rq_xtime = 500; /* transfer time */ - -struct mscp_con { - uint32 cnum; /* ctrl number */ - uint32 ubase; /* unit base */ - uint32 sa; /* status, addr */ - uint32 saw; /* written data */ - uint32 s1dat; /* S1 data */ - uint32 comm; /* comm region */ - uint32 csta; /* ctrl state */ - uint32 perr; /* last error */ - uint32 cflgs; /* ctrl flags */ - uint32 irq; /* intr request */ - uint32 prgi; /* purge int */ - uint32 pip; /* poll in progress */ - int32 freq; /* free list */ - int32 rspq; /* resp list */ - uint32 pbsy; /* #busy pkts */ - uint32 credits; /* credits */ - uint32 hat; /* host timer */ - uint32 htmo; /* host timeout */ - struct uq_ring cq; /* cmd ring */ - struct uq_ring rq; /* rsp ring */ - struct rqpkt pak[RQ_NPKTS]; /* packet queue */ -}; - -#define MSC struct mscp_con /* MSCP ctrl context */ - -DEVICE rq_dev, rqb_dev, rqc_dev,rqd_dev; - -t_stat rq_rd (int32 *data, int32 PA, int32 access); -t_stat rq_wr (int32 data, int32 PA, int32 access); -t_stat rq_svc (UNIT *uptr); -t_stat rq_tmrsvc (UNIT *uptr); -t_stat rq_quesvc (UNIT *uptr); -t_stat rq_reset (DEVICE *dptr); -t_stat rq_attach (UNIT *uptr, char *cptr); -t_stat rq_detach (UNIT *uptr); -t_stat rq_boot (int32 unitno, DEVICE *dptr); -t_stat rq_set_wlk (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat rq_set_type (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat rq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat rq_show_wlk (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat rq_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat rq_show_unitq (FILE *st, UNIT *uptr, int32 val, void *desc); - -t_bool rq_step4 (MSC *cp); -t_bool rq_mscp (MSC *cp, int32 pkt, t_bool q); -t_bool rq_abo (MSC *cp, int32 pkt, t_bool q); -t_bool rq_avl (MSC *cp, int32 pkt, t_bool q); -t_bool rq_fmt (MSC *cp, int32 pkt, t_bool q); -t_bool rq_gcs (MSC *cp, int32 pkt, t_bool q); -t_bool rq_gus (MSC *cp, int32 pkt, t_bool q); -t_bool rq_onl (MSC *cp, int32 pkt, t_bool q); -t_bool rq_rw (MSC *cp, int32 pkt, t_bool q); -t_bool rq_scc (MSC *cp, int32 pkt, t_bool q); -t_bool rq_suc (MSC *cp, int32 pkt, t_bool q); -t_bool rq_plf (MSC *cp, uint32 err); -t_bool rq_dte (MSC *cp, UNIT *uptr, uint32 err); -t_bool rq_hbe (MSC *cp, UNIT *uptr); -t_bool rq_una (MSC *cp, int32 un); -t_bool rq_deqf (MSC *cp, int32 *pkt); -int32 rq_deqh (MSC *cp, int32 *lh); -void rq_enqh (MSC *cp, int32 *lh, int32 pkt); -void rq_enqt (MSC *cp, int32 *lh, int32 pkt); -t_bool rq_getpkt (MSC *cp, int32 *pkt); -t_bool rq_putpkt (MSC *cp, int32 pkt, t_bool qt); -t_bool rq_getdesc (MSC *cp, struct uq_ring *ring, uint32 *desc); -t_bool rq_putdesc (MSC *cp, struct uq_ring *ring, uint32 desc); -int32 rq_rw_valid (MSC *cp, int32 pkt, UNIT *uptr, uint32 cmd); -t_bool rq_rw_end (MSC *cp, UNIT *uptr, uint32 flg, uint32 sts); -void rq_putr (MSC *cp, int32 pkt, uint32 cmd, uint32 flg, - uint32 sts, uint32 lnt, uint32 typ); -void rq_putr_unit (MSC *cp, int32 pkt, UNIT *uptr, uint32 lu, t_bool all); -void rq_setf_unit (MSC *cp, int32 pkt, UNIT *uptr); -void rq_init_int (MSC *cp); -void rq_ring_int (MSC *cp, struct uq_ring *ring); -t_bool rq_fatal (MSC *cp, uint32 err); -UNIT *rq_getucb (MSC *cp, uint32 lu); -int32 rq_map_pa (uint32 pa); -void rq_setint (MSC *cp); -void rq_clrint (MSC *cp); -int32 rq_inta (void); - -/* RQ data structures - - rq_dev RQ device descriptor - rq_unit RQ unit list - rq_reg RQ register list - rq_mod RQ modifier list -*/ - -MSC rq_ctx = { 0 }; - -DIB rq_dib = { IOBA_RQ, IOLN_RQ, &rq_rd, &rq_wr, - 1, IVCL (RQ), 0, { &rq_inta } }; - -UNIT rq_unit[] = { - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RX50_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RX50)) }, - { UDATA (&rq_tmrsvc, UNIT_DIS, 0) }, - { UDATA (&rq_quesvc, UNIT_DIS, 0) } }; - -REG rq_reg[] = { - { GRDATA (SA, rq_ctx.sa, DEV_RDX, 16, 0) }, - { GRDATA (SAW, rq_ctx.saw, DEV_RDX, 16, 0) }, - { GRDATA (S1DAT, rq_ctx.s1dat, DEV_RDX, 16, 0) }, - { GRDATA (COMM, rq_ctx.comm, DEV_RDX, 22, 0) }, - { GRDATA (CQBA, rq_ctx.cq.ba, DEV_RDX, 22, 0) }, - { GRDATA (CQLNT, rq_ctx.cq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (CQIDX, rq_ctx.cq.idx, DEV_RDX, 8, 2) }, - { GRDATA (RQBA, rq_ctx.rq.ba, DEV_RDX, 22, 0) }, - { GRDATA (RQLNT, rq_ctx.rq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (RQIDX, rq_ctx.rq.idx, DEV_RDX, 8, 2) }, - { DRDATA (FREE, rq_ctx.freq, 5) }, - { DRDATA (RESP, rq_ctx.rspq, 5) }, - { DRDATA (PBSY, rq_ctx.pbsy, 5) }, - { GRDATA (CFLGS, rq_ctx.cflgs, DEV_RDX, 16, 0) }, - { GRDATA (CSTA, rq_ctx.csta, DEV_RDX, 4, 0) }, - { GRDATA (PERR, rq_ctx.perr, DEV_RDX, 9, 0) }, - { DRDATA (CRED, rq_ctx.credits, 5) }, - { DRDATA (HAT, rq_ctx.hat, 17) }, - { DRDATA (HTMO, rq_ctx.htmo, 17) }, - { FLDATA (PRGI, rq_ctx.prgi, 0), REG_HIDDEN }, - { FLDATA (PIP, rq_ctx.pip, 0), REG_HIDDEN }, - { FLDATA (INT, rq_ctx.irq, 0) }, - { DRDATA (ITIME, rq_itime, 24), PV_LEFT + REG_NZ }, - { DRDATA (I4TIME, rq_itime4, 24), PV_LEFT + REG_NZ }, - { DRDATA (QTIME, rq_qtime, 24), PV_LEFT + REG_NZ }, - { DRDATA (XTIME, rq_xtime, 24), PV_LEFT + REG_NZ }, - { BRDATA (PKTS, rq_ctx.pak, DEV_RDX, 16, RQ_NPKTS * (RQ_PKT_SIZE_W + 1)) }, - { URDATA (CPKT, rq_unit[0].cpkt, 10, 5, 0, RQ_NUMDR, 0) }, - { URDATA (PKTQ, rq_unit[0].pktq, 10, 5, 0, RQ_NUMDR, 0) }, - { URDATA (UFLG, rq_unit[0].uf, DEV_RDX, 16, 0, RQ_NUMDR, 0) }, - { URDATA (CAPAC, rq_unit[0].capac, 10, T_ADDR_W, 0, RQ_NUMDR, PV_LEFT | REG_HRO) }, - { GRDATA (DEVADDR, rq_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, rq_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { DRDATA (DEVLBN, drv_tab[RA8U_DTYPE].lbn, 22), REG_HRO }, - { NULL } }; - -MTAB rq_mod[] = { - { UNIT_WLK, 0, NULL, "WRITEENABLED", &rq_set_wlk }, - { UNIT_WLK, UNIT_WLK, NULL, "LOCKED", &rq_set_wlk }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, RQ_SH_RI, "RINGS", NULL, - NULL, &rq_show_ctrl, 0 }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, RQ_SH_FR, "FREEQ", NULL, - NULL, &rq_show_ctrl, 0 }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, RQ_SH_RS, "RESPQ", NULL, - NULL, &rq_show_ctrl, 0 }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, RQ_SH_UN, "UNITQ", NULL, - NULL, &rq_show_ctrl, 0 }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, -1, "ALL", NULL, - NULL, &rq_show_ctrl, 0 }, - { MTAB_XTD | MTAB_VUN | MTAB_NMO, 0, "UNITQ", NULL, - NULL, &rq_show_unitq, 0 }, - { MTAB_XTD | MTAB_VUN, 0, "WRITE", NULL, - NULL, &rq_show_wlk, NULL }, - { MTAB_XTD | MTAB_VUN, RX50_DTYPE, NULL, "RX50", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RX33_DTYPE, NULL, "RX33", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RD31_DTYPE, NULL, "RD31", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RD51_DTYPE, NULL, "RD51", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RD52_DTYPE, NULL, "RD52", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RD53_DTYPE, NULL, "RD53", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RD54_DTYPE, NULL, "RD54", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RA82_DTYPE, NULL, "RA82", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RRD40_DTYPE, NULL, "RRD40", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RRD40_DTYPE, NULL, "CDROM", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RA72_DTYPE, NULL, "RA72", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RA90_DTYPE, NULL, "RA90", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RA92_DTYPE, NULL, "RA92", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RA8U_DTYPE, NULL, "RAUSER", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, 0, "TYPE", NULL, - NULL, &rq_show_type, NULL }, -#if defined (VM_PDP11) - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, -#else - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", NULL, - NULL, &show_addr, NULL }, -#endif - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "AUTOCONFIGURE", - &set_addr_flt, NULL, NULL }, - { 0 } }; - -DEVICE rq_dev = { - "RQ", rq_unit, rq_reg, rq_mod, - RQ_NUMDR + 2, DEV_RDX, 31, RQ_AINC, DEV_RDX, RQ_WID, - NULL, NULL, &rq_reset, - &rq_boot, &rq_attach, &rq_detach, - &rq_dib, DEV_FLTA | DEV_DISABLE | DEV_UBUS | DEV_QBUS }; - -/* RQB data structures - - rqb_dev RQB device descriptor - rqb_unit RQB unit list - rqb_reg RQB register list - rqb_mod RQB modifier list -*/ - -MSC rqb_ctx = { 1 }; - -DIB rqb_dib = { IOBA_RQB, IOLN_RQB, &rq_rd, &rq_wr, - 1, IVCL (RQ), 0, { &rq_inta } }; - -UNIT rqb_unit[] = { - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_tmrsvc, UNIT_DIS, 0) }, - { UDATA (&rq_quesvc, UNIT_DIS, 0) } }; - -REG rqb_reg[] = { - { GRDATA (SA, rqb_ctx.sa, DEV_RDX, 16, 0) }, - { GRDATA (SAW, rqb_ctx.saw, DEV_RDX, 16, 0) }, - { GRDATA (S1DAT, rqb_ctx.s1dat, DEV_RDX, 16, 0) }, - { GRDATA (COMM, rqb_ctx.comm, DEV_RDX, 22, 0) }, - { GRDATA (CQBA, rqb_ctx.cq.ba, DEV_RDX, 22, 0) }, - { GRDATA (CQLNT, rqb_ctx.cq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (CQIDX, rqb_ctx.cq.idx, DEV_RDX, 8, 2) }, - { GRDATA (RQBA, rqb_ctx.rq.ba, DEV_RDX, 22, 0) }, - { GRDATA (RQLNT, rqb_ctx.rq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (RQIDX, rqb_ctx.rq.idx, DEV_RDX, 8, 2) }, - { DRDATA (FREE, rqb_ctx.freq, 5) }, - { DRDATA (RESP, rqb_ctx.rspq, 5) }, - { DRDATA (PBSY, rqb_ctx.pbsy, 5) }, - { GRDATA (CFLGS, rqb_ctx.cflgs, DEV_RDX, 16, 0) }, - { GRDATA (CSTA, rqb_ctx.csta, DEV_RDX, 4, 0) }, - { GRDATA (PERR, rqb_ctx.perr, DEV_RDX, 9, 0) }, - { DRDATA (CRED, rqb_ctx.credits, 5) }, - { DRDATA (HAT, rqb_ctx.hat, 17) }, - { DRDATA (HTMO, rqb_ctx.htmo, 17) }, - { FLDATA (PRGI, rqb_ctx.prgi, 0), REG_HIDDEN }, - { FLDATA (PIP, rqb_ctx.pip, 0), REG_HIDDEN }, - { FLDATA (INT, rqb_ctx.irq, 0) }, - { BRDATA (PKTS, rqb_ctx.pak, DEV_RDX, 16, RQ_NPKTS * (RQ_PKT_SIZE_W + 1)) }, - { URDATA (CPKT, rqb_unit[0].cpkt, 10, 5, 0, RQ_NUMDR, 0) }, - { URDATA (PKTQ, rqb_unit[0].pktq, 10, 5, 0, RQ_NUMDR, 0) }, - { URDATA (UFLG, rqb_unit[0].uf, DEV_RDX, 16, 0, RQ_NUMDR, 0) }, - { URDATA (CAPAC, rqb_unit[0].capac, 10, 31, 0, RQ_NUMDR, PV_LEFT | REG_HRO) }, - { GRDATA (DEVADDR, rqb_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, rqb_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -DEVICE rqb_dev = { - "RQB", rqb_unit, rqb_reg, rq_mod, - RQ_NUMDR + 2, DEV_RDX, 31, RQ_AINC, DEV_RDX, RQ_WID, - NULL, NULL, &rq_reset, - &rq_boot, &rq_attach, &rq_detach, - &rqb_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS }; - -/* RQC data structures - - rqc_dev RQC device descriptor - rqc_unit RQC unit list - rqc_reg RQC register list - rqc_mod RQC modifier list -*/ - -MSC rqc_ctx = { 2 }; - -DIB rqc_dib = { IOBA_RQC, IOLN_RQC, &rq_rd, &rq_wr, - 1, IVCL (RQ), 0, { &rq_inta } }; - -UNIT rqc_unit[] = { - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_tmrsvc, UNIT_DIS, 0) }, - { UDATA (&rq_quesvc, UNIT_DIS, 0) } }; - -REG rqc_reg[] = { - { GRDATA (SA, rqc_ctx.sa, DEV_RDX, 16, 0) }, - { GRDATA (SAW, rqc_ctx.saw, DEV_RDX, 16, 0) }, - { GRDATA (S1DAT, rqc_ctx.s1dat, DEV_RDX, 16, 0) }, - { GRDATA (COMM, rqc_ctx.comm, DEV_RDX, 22, 0) }, - { GRDATA (CQBA, rqc_ctx.cq.ba, DEV_RDX, 22, 0) }, - { GRDATA (CQLNT, rqc_ctx.cq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (CQIDX, rqc_ctx.cq.idx, DEV_RDX, 8, 2) }, - { GRDATA (RQBA, rqc_ctx.rq.ba, DEV_RDX, 22, 0) }, - { GRDATA (RQLNT, rqc_ctx.rq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (RQIDX, rqc_ctx.rq.idx, DEV_RDX, 8, 2) }, - { DRDATA (FREE, rqc_ctx.freq, 5) }, - { DRDATA (RESP, rqc_ctx.rspq, 5) }, - { DRDATA (PBSY, rqc_ctx.pbsy, 5) }, - { GRDATA (CFLGS, rqc_ctx.cflgs, DEV_RDX, 16, 0) }, - { GRDATA (CSTA, rqc_ctx.csta, DEV_RDX, 4, 0) }, - { GRDATA (PERR, rqc_ctx.perr, DEV_RDX, 9, 0) }, - { DRDATA (CRED, rqc_ctx.credits, 5) }, - { DRDATA (HAT, rqc_ctx.hat, 17) }, - { DRDATA (HTMO, rqc_ctx.htmo, 17) }, - { FLDATA (PRGI, rqc_ctx.prgi, 0), REG_HIDDEN }, - { FLDATA (PIP, rqc_ctx.pip, 0), REG_HIDDEN }, - { FLDATA (INT, rqc_ctx.irq, 0) }, - { BRDATA (PKTS, rqc_ctx.pak, DEV_RDX, 16, RQ_NPKTS * (RQ_PKT_SIZE_W + 1)) }, - { URDATA (CPKT, rqc_unit[0].cpkt, 10, 5, 0, RQ_NUMDR, 0) }, - { URDATA (PKTQ, rqc_unit[0].pktq, 10, 5, 0, RQ_NUMDR, 0) }, - { URDATA (UFLG, rqc_unit[0].uf, DEV_RDX, 16, 0, RQ_NUMDR, 0) }, - { URDATA (CAPAC, rqc_unit[0].capac, 10, 31, 0, RQ_NUMDR, PV_LEFT | REG_HRO) }, - { GRDATA (DEVADDR, rqc_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, rqc_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -DEVICE rqc_dev = { - "RQC", rqc_unit, rqc_reg, rq_mod, - RQ_NUMDR + 2, DEV_RDX, 31, RQ_AINC, DEV_RDX, RQ_WID, - NULL, NULL, &rq_reset, - &rq_boot, &rq_attach, &rq_detach, - &rqc_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS }; - -/* RQD data structures - - rqd_dev RQ device descriptor - rqd_unit RQ unit list - rqd_reg RQ register list - rqd_mod RQ modifier list -*/ - -MSC rqd_ctx = { 3 }; - -DIB rqd_dib = { IOBA_RQD, IOLN_RQD, &rq_rd, &rq_wr, - 1, IVCL (RQ), 0, { &rq_inta } }; - -UNIT rqd_unit[] = { - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_tmrsvc, UNIT_DIS, 0) }, - { UDATA (&rq_quesvc, UNIT_DIS, 0) } }; - -REG rqd_reg[] = { - { GRDATA (SA, rqd_ctx.sa, DEV_RDX, 16, 0) }, - { GRDATA (SAW, rqd_ctx.saw, DEV_RDX, 16, 0) }, - { GRDATA (S1DAT, rqd_ctx.s1dat, DEV_RDX, 16, 0) }, - { GRDATA (COMM, rqd_ctx.comm, DEV_RDX, 22, 0) }, - { GRDATA (CQBA, rqd_ctx.cq.ba, DEV_RDX, 22, 0) }, - { GRDATA (CQLNT, rqd_ctx.cq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (CQIDX, rqd_ctx.cq.idx, DEV_RDX, 8, 2) }, - { GRDATA (RQBA, rqd_ctx.rq.ba, DEV_RDX, 22, 0) }, - { GRDATA (RQLNT, rqd_ctx.rq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (RQIDX, rqd_ctx.rq.idx, DEV_RDX, 8, 2) }, - { DRDATA (FREE, rqd_ctx.freq, 5) }, - { DRDATA (RESP, rqd_ctx.rspq, 5) }, - { DRDATA (PBSY, rqd_ctx.pbsy, 5) }, - { GRDATA (CFLGS, rqd_ctx.cflgs, DEV_RDX, 16, 0) }, - { GRDATA (CSTA, rqd_ctx.csta, DEV_RDX, 4, 0) }, - { GRDATA (PERR, rqd_ctx.perr, DEV_RDX, 9, 0) }, - { DRDATA (CRED, rqd_ctx.credits, 5) }, - { DRDATA (HAT, rqd_ctx.hat, 17) }, - { DRDATA (HTMO, rqd_ctx.htmo, 17) }, - { FLDATA (PRGI, rqd_ctx.prgi, 0), REG_HIDDEN }, - { FLDATA (PIP, rqd_ctx.pip, 0), REG_HIDDEN }, - { FLDATA (INT, rqd_ctx.irq, 0) }, - { BRDATA (PKTS, rqd_ctx.pak, DEV_RDX, 16, RQ_NPKTS * (RQ_PKT_SIZE_W + 1)) }, - { URDATA (CPKT, rqd_unit[0].cpkt, 10, 5, 0, RQ_NUMDR, 0) }, - { URDATA (PKTQ, rqd_unit[0].pktq, 10, 5, 0, RQ_NUMDR, 0) }, - { URDATA (UFLG, rqd_unit[0].uf, DEV_RDX, 16, 0, RQ_NUMDR, 0) }, - { URDATA (CAPAC, rqd_unit[0].capac, 10, 31, 0, RQ_NUMDR, PV_LEFT | REG_HRO) }, - { GRDATA (DEVADDR, rqd_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, rqd_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -DEVICE rqd_dev = { - "RQD", rqd_unit, rqd_reg, rq_mod, - RQ_NUMDR + 2, DEV_RDX, 31, RQ_AINC, DEV_RDX, RQ_WID, - NULL, NULL, &rq_reset, - &rq_boot, &rq_attach, &rq_detach, - &rqd_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS }; - -static DEVICE *rq_devmap[RQ_NUMCT] = { - &rq_dev, &rqb_dev, &rqc_dev, &rqd_dev }; - -static MSC *rq_ctxmap[RQ_NUMCT] = { - &rq_ctx, &rqb_ctx, &rqc_ctx, &rqd_ctx }; - -/* I/O dispatch routine, I/O addresses 17772150 - 17772152 - - base + 0 IP read/write - base + 2 SA read/write -*/ - -t_stat rq_rd (int32 *data, int32 PA, int32 access) -{ -int32 cidx = rq_map_pa ((uint32) PA); -MSC *cp = rq_ctxmap[cidx]; -DEVICE *dptr = rq_devmap[cidx]; - -if (cidx < 0) return SCPE_IERR; -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* IP */ - *data = 0; /* reads zero */ - if (cp->csta == CST_S3_PPB) rq_step4 (cp); /* waiting for poll? */ - else if (cp->csta == CST_UP) { /* if up */ - cp->pip = 1; /* poll host */ - sim_activate (dptr->units + RQ_QUEUE, rq_qtime); } - break; -case 1: /* SA */ - *data = cp->sa; - break; } -return SCPE_OK; -} - -t_stat rq_wr (int32 data, int32 PA, int32 access) -{ -int32 cidx = rq_map_pa ((uint32) PA); -MSC *cp = rq_ctxmap[cidx]; -DEVICE *dptr = rq_devmap[cidx]; - -if (cidx < 0) return SCPE_IERR; -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* IP */ - rq_reset (rq_devmap[cidx]); /* init device */ - if (DBG_LOG (LOG_RQ)) fprintf (sim_log, - ">>RQ%c: initialization started\n", 'A' + cp->cnum); - break; -case 1: /* SA */ - cp->saw = data; - if (cp->csta < CST_S4) /* stages 1-3 */ - sim_activate (dptr->units + RQ_QUEUE, rq_itime); - else if (cp->csta == CST_S4) /* stage 4 (fast) */ - sim_activate (dptr->units + RQ_QUEUE, rq_itime4); - break; } -return SCPE_OK; -} - -/* Map physical address to device context */ - -int32 rq_map_pa (uint32 pa) -{ -int32 i; -DEVICE *dptr; -DIB *dibp; - -for (i = 0; i < RQ_NUMCT; i++) { /* loop thru ctrls */ - dptr = rq_devmap[i]; /* get device */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if ((pa >= dibp->ba) && /* in range? */ - (pa < (dibp->ba + dibp->lnt))) - return i; } /* return ctrl idx */ -return -1; -} - -/* Transition to step 4 - init communications region */ - -t_bool rq_step4 (MSC *cp) -{ -int32 i, lnt; -uint32 base; -uint16 zero[SA_COMM_MAX >> 1]; - -cp->rq.ioff = SA_COMM_RI; /* set intr offset */ -cp->rq.ba = cp->comm; /* set rsp q base */ -cp->rq.lnt = SA_S1H_RQ (cp->s1dat) << 2; /* get resp q len */ -cp->cq.ioff = SA_COMM_CI; /* set intr offset */ -cp->cq.ba = cp->comm + cp->rq.lnt; /* set cmd q base */ -cp->cq.lnt = SA_S1H_CQ (cp->s1dat) << 2; /* get cmd q len */ -cp->cq.idx = cp->rq.idx = 0; /* clear q idx's */ -if (cp->prgi) base = cp->comm + SA_COMM_QQ; -else base = cp->comm + SA_COMM_CI; -lnt = cp->comm + cp->cq.lnt + cp->rq.lnt - base; /* comm lnt */ -if (lnt > SA_COMM_MAX) lnt = SA_COMM_MAX; /* paranoia */ -for (i = 0; i < (lnt >> 1); i++) zero[i] = 0; /* clr buffer */ -if (Map_WriteW (base, lnt, zero, MAP)) /* zero comm area */ - return rq_fatal (cp, PE_QWE); /* error? */ -cp->sa = SA_S4 | (RQ_UQPM << SA_S4C_V_MOD) | /* send step 4 */ - (RQ_SVER << SA_S4C_V_VER); -cp->csta = CST_S4; /* set step 4 */ -rq_init_int (cp); /* poke host */ -return OK; -} - -/* Queue service - invoked when any of the queues (host queue, unit - queues, response queue) require servicing. Also invoked during - initialization to provide some delay to the next step. - - Process at most one item off each unit queue - If the unit queues were empty, process at most one item off the host queue - Process at most one item off the response queue - - If all queues are idle, terminate thread -*/ - -t_stat rq_quesvc (UNIT *uptr) -{ -int32 i, cnid; -int32 pkt = 0; -UNIT *nuptr; -MSC *cp = rq_ctxmap[uptr->cnum]; -DEVICE *dptr = rq_devmap[uptr->cnum]; -DIB *dibp = (DIB *) dptr->ctxt; - -if (cp->csta < CST_UP) { /* still init? */ - switch (cp->csta) { /* controller state? */ - case CST_S1: /* need S1 reply */ - if (cp->saw & SA_S1H_VL) { /* valid? */ - if (cp->saw & SA_S1H_WR) { /* wrap? */ - cp->sa = cp->saw; /* echo data */ - cp->csta = CST_S1_WR; } /* endless loop */ - else { - cp->s1dat = cp->saw; /* save data */ - dibp->vec = (cp->s1dat & SA_S1H_VEC) << 2; /* get vector */ - if (dibp->vec) dibp->vec = dibp->vec + VEC_Q; /* if nz, bias */ - cp->sa = SA_S2 | SA_S2C_PT | SA_S2C_EC (cp->s1dat); - cp->csta = CST_S2; /* now in step 2 */ - rq_init_int (cp); } /* intr if req */ - } /* end if valid */ - break; - case CST_S1_WR: /* wrap mode */ - cp->sa = cp->saw; /* echo data */ - break; - case CST_S2: /* need S2 reply */ - cp->comm = cp->saw & SA_S2H_CLO; /* get low addr */ - cp->prgi = cp->saw & SA_S2H_PI; /* get purge int */ - cp->sa = SA_S3 | SA_S3C_EC (cp->s1dat); - cp->csta = CST_S3; /* now in step 3 */ - rq_init_int (cp); /* intr if req */ - break; - case CST_S3: /* need S3 reply */ - cp->comm = ((cp->saw & SA_S3H_CHI) << 16) | cp->comm; - if (cp->saw & SA_S3H_PP) { /* purge/poll test? */ - cp->sa = 0; /* put 0 */ - cp->csta = CST_S3_PPA; } /* wait for 0 write */ - else rq_step4 (cp); /* send step 4 */ - break; - case CST_S3_PPA: /* need purge test */ - if (cp->saw) rq_fatal (cp, PE_PPF); /* data not zero? */ - else cp->csta = CST_S3_PPB; /* wait for poll */ - break; - case CST_S4: /* need S4 reply */ - if (cp->saw & SA_S4H_GO) { /* go set? */ - if (DBG_LOG (LOG_RQ)) fprintf (sim_log, - ">>RQ%c: initialization complete\n", 'A' + cp->cnum); - cp->csta = CST_UP; /* we're up */ - cp->sa = 0; /* clear SA */ - sim_activate (dptr->units + RQ_TIMER, tmr_poll * clk_tps); - if ((cp->saw & SA_S4H_LF) && cp->perr) rq_plf (cp, cp->perr); - cp->perr = 0; } - break; } /* end switch */ - return SCPE_OK; } /* end if */ - -for (i = 0; i < RQ_NUMDR; i++) { /* chk unit q's */ - nuptr = dptr->units + i; /* ptr to unit */ - if (nuptr->cpkt || (nuptr->pktq == 0)) continue; - pkt = rq_deqh (cp, &nuptr->pktq); /* get top of q */ - if (!rq_mscp (cp, pkt, FALSE)) return SCPE_OK; } /* process */ -if ((pkt == 0) && cp->pip) { /* polling? */ - if (!rq_getpkt (cp, &pkt)) return SCPE_OK; /* get host pkt */ - if (pkt) { /* got one? */ - if (DBG_LOG (LOG_RQ)) { - fprintf (sim_log, ">>RQ%c: cmd=%04X, mod=%04X, unit=%d, ", - 'A' + cp->cnum, cp->pak[pkt].d[CMD_OPC], - cp->pak[pkt].d[CMD_MOD], cp->pak[pkt].d[CMD_UN]); - fprintf (sim_log, "bc=%04X%04X, ma=%04X%04X, lbn=%04X%04X\n", - cp->pak[pkt].d[RW_BCH], cp->pak[pkt].d[RW_BCL], - cp->pak[pkt].d[RW_BAH], cp->pak[pkt].d[RW_BAL], - cp->pak[pkt].d[RW_LBNH], cp->pak[pkt].d[RW_LBNL]); } - if (GETP (pkt, UQ_HCTC, TYP) != UQ_TYP_SEQ) /* seq packet? */ - return rq_fatal (cp, PE_PIE); /* no, term thread */ - cnid = GETP (pkt, UQ_HCTC, CID); /* get conn ID */ - if (cnid == UQ_CID_MSCP) { /* MSCP packet? */ - if (!rq_mscp (cp, pkt, TRUE)) return SCPE_OK; } /* proc, q non-seq */ - else if (cnid == UQ_CID_DUP) { /* DUP packet? */ - rq_putr (cp, pkt, OP_END, 0, ST_CMD | I_OPCD, RSP_LNT, UQ_TYP_SEQ); - if (!rq_putpkt (cp, pkt, TRUE)) return SCPE_OK; } /* ill cmd */ - else return rq_fatal (cp, PE_ICI); /* no, term thread */ - } /* end if pkt */ - else cp->pip = 0; /* discontinue poll */ - } /* end if pip */ -if (cp->rspq) { /* resp q? */ - pkt = rq_deqh (cp, &cp->rspq); /* get top of q */ - if (!rq_putpkt (cp, pkt, FALSE)) return SCPE_OK; /* send to hst */ - } /* end if resp q */ -if (pkt) sim_activate (uptr, rq_qtime); /* more to do? */ -return SCPE_OK; /* done */ -} - -/* Clock service (roughly once per second) */ - -t_stat rq_tmrsvc (UNIT *uptr) -{ -int32 i; -UNIT *nuptr; -MSC *cp = rq_ctxmap[uptr->cnum]; -DEVICE *dptr = rq_devmap[uptr->cnum]; - -sim_activate (uptr, tmr_poll * clk_tps); /* reactivate */ -for (i = 0; i < RQ_NUMDR; i++) { /* poll */ - nuptr = dptr->units + i; - if ((nuptr->flags & UNIT_ATP) && /* ATN pending? */ - (nuptr->flags & UNIT_ATT) && /* still online? */ - (cp->cflgs & CF_ATN)) { /* wanted? */ - if (!rq_una (cp, i)) return SCPE_OK; } - nuptr->flags = nuptr->flags & ~UNIT_ATP; } -if ((cp->hat > 0) && (--cp->hat == 0)) /* host timeout? */ - rq_fatal (cp, PE_HAT); /* fatal err */ -return SCPE_OK; -} - -/* MSCP packet handling */ - -t_bool rq_mscp (MSC *cp, int32 pkt, t_bool q) -{ -uint32 sts, cmd = GETP (pkt, CMD_OPC, OPC); - -switch (cmd) { -case OP_ABO: /* abort */ - return rq_abo (cp, pkt, q); -case OP_AVL: /* avail */ - return rq_avl (cp, pkt, q); -case OP_FMT: /* format */ - return rq_fmt (cp, pkt, q); -case OP_GCS: /* get cmd status */ - return rq_gcs (cp, pkt, q); -case OP_GUS: /* get unit status */ - return rq_gus (cp, pkt, q); -case OP_ONL: /* online */ - return rq_onl (cp, pkt, q); -case OP_SCC: /* set ctrl char */ - return rq_scc (cp, pkt, q); -case OP_SUC: /* set unit char */ - return rq_suc (cp, pkt, q); -case OP_ACC: /* access */ -case OP_CMP: /* compare */ -case OP_ERS: /* erase */ -case OP_RD: /* read */ -case OP_WR: /* write */ - return rq_rw (cp, pkt, q); -case OP_CCD: /* nops */ -case OP_DAP: -case OP_FLU: - cmd = cmd | OP_END; /* set end flag */ - sts = ST_SUC; /* success */ - break; -default: - cmd = OP_END; /* set end op */ - sts = ST_CMD | I_OPCD; /* ill op */ - break; } -rq_putr (cp, pkt, cmd, 0, sts, RSP_LNT, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Abort a command - 1st parameter is ref # of cmd to abort */ - -t_bool rq_abo (MSC *cp, int32 pkt, t_bool q) -{ -uint32 lu = cp->pak[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 ref = GETP32 (pkt, ABO_REFL); /* cmd ref # */ -int32 tpkt, prv; -UNIT *uptr; -DEVICE *dptr = rq_devmap[cp->cnum]; - -tpkt = 0; /* set no mtch */ -if (uptr = rq_getucb (cp, lu)) { /* get unit */ - if (uptr->cpkt && /* curr pkt? */ - (GETP32 (uptr->cpkt, CMD_REFL) == ref)) { /* match ref? */ - tpkt = uptr->cpkt; /* save match */ - uptr->cpkt = 0; /* gonzo */ - sim_cancel (uptr); /* cancel unit */ - sim_activate (dptr->units + RQ_QUEUE, rq_qtime); } - else if (uptr->pktq && /* head of q? */ - (GETP32 (uptr->pktq, CMD_REFL) == ref)) { /* match ref? */ - tpkt = uptr->pktq; /* save match */ - uptr->pktq = cp->pak[tpkt].link; } /* unlink */ - else if (prv = uptr->pktq) { /* srch pkt q */ - while (tpkt = cp->pak[prv].link) { /* walk list */ - if (GETP32 (tpkt, RSP_REFL) == ref) { /* match? unlink */ - cp->pak[prv].link = cp->pak[tpkt].link; - break; } } } - if (tpkt) { /* found target? */ - uint32 tcmd = GETP (tpkt, CMD_OPC, OPC); /* get opcode */ - rq_putr (cp, tpkt, tcmd | OP_END, 0, ST_ABO, RSP_LNT, UQ_TYP_SEQ); - if (!rq_putpkt (cp, tpkt, TRUE)) return ERR; } - } /* end if unit */ -rq_putr (cp, pkt, cmd | OP_END, 0, ST_SUC, ABO_LNT, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Unit available - set unit status to available - defer if q'd cmds */ - -t_bool rq_avl (MSC *cp, int32 pkt, t_bool q) -{ -uint32 lu = cp->pak[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 sts; -UNIT *uptr; - -if (uptr = rq_getucb (cp, lu)) { /* unit exist? */ - if (q && uptr->cpkt) { /* need to queue? */ - rq_enqt (cp, &uptr->pktq, pkt); /* do later */ - return OK; } - uptr->flags = uptr->flags & ~UNIT_ONL; /* not online */ - uptr->uf = 0; /* clr flags */ - sts = ST_SUC; } /* success */ -else sts = ST_OFL; /* offline */ -rq_putr (cp, pkt, cmd | OP_END, 0, sts, AVL_LNT, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Get command status - only interested in active xfr cmd */ - -t_bool rq_gcs (MSC *cp, int32 pkt, t_bool q) -{ -uint32 lu = cp->pak[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 ref = GETP32 (pkt, GCS_REFL); /* ref # */ -int32 tpkt; -UNIT *uptr; - -if ((uptr = rq_getucb (cp, lu)) && /* valid lu? */ - (tpkt = uptr->cpkt) && /* queued pkt? */ - (GETP32 (tpkt, CMD_REFL) == ref) && /* match ref? */ - (GETP (tpkt, CMD_OPC, OPC) >= OP_ACC)) { /* rd/wr cmd? */ - cp->pak[pkt].d[GCS_STSL] = cp->pak[tpkt].d[RW_WBCL]; - cp->pak[pkt].d[GCS_STSH] = cp->pak[tpkt].d[RW_WBCH]; } -else { - cp->pak[pkt].d[GCS_STSL] = 0; /* return 0 */ - cp->pak[pkt].d[GCS_STSH] = 0; } -rq_putr (cp, pkt, cmd | OP_END, 0, ST_SUC, GCS_LNT, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Get unit status */ - -t_bool rq_gus (MSC *cp, int32 pkt, t_bool q) -{ -uint32 lu = cp->pak[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 dtyp, sts, rbpar; -UNIT *uptr; - -if (cp->pak[pkt].d[CMD_MOD] & MD_NXU) { /* next unit? */ - if (lu >= (cp->ubase + RQ_NUMDR)) { /* end of range? */ - lu = 0; /* reset to 0 */ - cp->pak[pkt].d[RSP_UN] = lu; } } -if (uptr = rq_getucb (cp, lu)) { /* unit exist? */ - if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - sts = ST_OFL | SB_OFL_NV; /* offl no vol */ - else if (uptr->flags & UNIT_ONL) sts = ST_SUC; /* online */ - else sts = ST_AVL; /* avail */ - rq_putr_unit (cp, pkt, uptr, lu, FALSE); /* fill unit fields */ - dtyp = GET_DTYPE (uptr->flags); /* get drive type */ - if (drv_tab[dtyp].rcts) rbpar = 1; /* ctrl bad blk? */ - else rbpar = 0; /* fill geom, bblk */ - cp->pak[pkt].d[GUS_TRK] = drv_tab[dtyp].sect; - cp->pak[pkt].d[GUS_GRP] = drv_tab[dtyp].tpg; - cp->pak[pkt].d[GUS_CYL] = drv_tab[dtyp].gpc; - cp->pak[pkt].d[GUS_UVER] = 0; - cp->pak[pkt].d[GUS_RCTS] = drv_tab[dtyp].rcts; - cp->pak[pkt].d[GUS_RBSC] = - (rbpar << GUS_RB_V_RBNS) | (rbpar << GUS_RB_V_RCTC); } -else sts = ST_OFL; /* offline */ -cp->pak[pkt].d[GUS_SHUN] = lu; /* shadowing */ -cp->pak[pkt].d[GUS_SHST] = 0; -rq_putr (cp, pkt, cmd | OP_END, 0, sts, GUS_LNT_D, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Unit online - defer if q'd commands */ - -t_bool rq_onl (MSC *cp, int32 pkt, t_bool q) -{ -uint32 lu = cp->pak[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 sts; -UNIT *uptr; - -if (uptr = rq_getucb (cp, lu)) { /* unit exist? */ - if (q && uptr->cpkt) { /* need to queue? */ - rq_enqt (cp, &uptr->pktq, pkt); /* do later */ - return OK; } - if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - sts = ST_OFL | SB_OFL_NV; /* offl no vol */ - else if (uptr->flags & UNIT_ONL) /* already online? */ - sts = ST_SUC | SB_SUC_ON; - else { /* mark online */ - sts = ST_SUC; - uptr->flags = uptr->flags | UNIT_ONL; - rq_setf_unit (cp, pkt, uptr); } /* hack flags */ - rq_putr_unit (cp, pkt, uptr, lu, TRUE); } /* set fields */ -else sts = ST_OFL; /* offline */ -cp->pak[pkt].d[ONL_SHUN] = lu; /* shadowing */ -cp->pak[pkt].d[ONL_SHST] = 0; -rq_putr (cp, pkt, cmd | OP_END, 0, sts, ONL_LNT, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Set controller characteristics */ - -t_bool rq_scc (MSC *cp, int32 pkt, t_bool q) -{ -int32 sts, cmd; - -if (cp->pak[pkt].d[SCC_MSV]) { /* MSCP ver = 0? */ - sts = ST_CMD | I_VRSN; /* no, lose */ - cmd = 0; } -else { sts = ST_SUC; /* success */ - cmd = GETP (pkt, CMD_OPC, OPC); /* get opcode */ - cp->cflgs = (cp->cflgs & CF_RPL) | /* hack ctrl flgs */ - cp->pak[pkt].d[SCC_CFL]; - if (cp->htmo = cp->pak[pkt].d[SCC_TMO]) /* set timeout */ - cp->htmo = cp->htmo + 2; /* if nz, round up */ - cp->pak[pkt].d[SCC_CFL] = cp->cflgs; /* return flags */ - cp->pak[pkt].d[SCC_TMO] = RQ_DCTMO; /* ctrl timeout */ - cp->pak[pkt].d[SCC_VER] = (RQ_HVER << SCC_VER_V_HVER) | - (RQ_SVER << SCC_VER_V_SVER); - cp->pak[pkt].d[SCC_CIDA] = 0; /* ctrl ID */ - cp->pak[pkt].d[SCC_CIDB] = 0; - cp->pak[pkt].d[SCC_CIDC] = 0; - cp->pak[pkt].d[SCC_CIDD] = (RQ_CLASS << SCC_CIDD_V_CLS) | - (RQ_MODEL << SCC_CIDD_V_MOD); - cp->pak[pkt].d[SCC_MBCL] = 0; /* max bc */ - cp->pak[pkt].d[SCC_MBCH] = 0; } -rq_putr (cp, pkt, cmd | OP_END, 0, sts, SCC_LNT, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Set unit characteristics - defer if q'd commands */ - -t_bool rq_suc (MSC *cp, int32 pkt, t_bool q) -{ -uint32 lu = cp->pak[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 sts; -UNIT *uptr; - -if (uptr = rq_getucb (cp, lu)) { /* unit exist? */ - if (q && uptr->cpkt) { /* need to queue? */ - rq_enqt (cp, &uptr->pktq, pkt); /* do later */ - return OK; } - if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - sts = ST_OFL | SB_OFL_NV; /* offl no vol */ - else { /* avail or onl */ - sts = ST_SUC; - rq_setf_unit (cp, pkt, uptr); } /* hack flags */ - rq_putr_unit (cp, pkt, uptr, lu, TRUE); } /* set fields */ -else sts = ST_OFL; /* offline */ -cp->pak[pkt].d[ONL_SHUN] = lu; /* shadowing */ -cp->pak[pkt].d[ONL_SHST] = 0; -rq_putr (cp, pkt, cmd | OP_END, 0, sts, SUC_LNT, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Format command - floppies only */ - -t_bool rq_fmt (MSC *cp, int32 pkt, t_bool q) -{ -uint32 lu = cp->pak[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 sts; -UNIT *uptr; - -if (uptr = rq_getucb (cp, lu)) { /* unit exist? */ - if (q && uptr->cpkt) { /* need to queue? */ - rq_enqt (cp, &uptr->pktq, pkt); /* do later */ - return OK; } - if (GET_DTYPE (uptr->flags) != RX33_DTYPE) /* RX33? */ - sts = ST_CMD | I_OPCD; /* no, err */ - else if ((cp->pak[pkt].d[FMT_IH] & 0100000) == 0) /* magic bit set? */ - sts = ST_CMD | I_FMTI; /* no, err */ - else if ((uptr->flags & UNIT_ATT) == 0) /* offline? */ - sts = ST_OFL | SB_OFL_NV; /* no vol */ - else if (uptr->flags & UNIT_ONL) { /* online? */ - uptr->flags = uptr->flags & ~UNIT_ONL; - uptr->uf = 0; /* clear flags */ - sts = ST_AVL | SB_AVL_INU; } /* avail, in use */ - else if (RQ_WPH (uptr)) /* write prot? */ - sts = ST_WPR | SB_WPR_HW; /* can't fmt */ - else sts = ST_SUC; /*** for now ***/ - } -else sts = ST_OFL; /* offline */ -rq_putr (cp, pkt, cmd | OP_END, 0, sts, FMT_LNT, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Data transfer commands */ - -t_bool rq_rw (MSC *cp, int32 pkt, t_bool q) -{ -uint32 lu = cp->pak[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 sts; -UNIT *uptr; - -if (uptr = rq_getucb (cp, lu)) { /* unit exist? */ - if (q && uptr->cpkt) { /* need to queue? */ - rq_enqt (cp, &uptr->pktq, pkt); /* do later */ - return OK; } - sts = rq_rw_valid (cp, pkt, uptr, cmd); /* validity checks */ - if (sts == 0) { /* ok? */ - uptr->cpkt = pkt; /* op in progress */ - cp->pak[pkt].d[RW_WBAL] = cp->pak[pkt].d[RW_BAL]; - cp->pak[pkt].d[RW_WBAH] = cp->pak[pkt].d[RW_BAH]; - cp->pak[pkt].d[RW_WBCL] = cp->pak[pkt].d[RW_BCL]; - cp->pak[pkt].d[RW_WBCH] = cp->pak[pkt].d[RW_BCH]; - cp->pak[pkt].d[RW_WBLL] = cp->pak[pkt].d[RW_LBNL]; - cp->pak[pkt].d[RW_WBLH] = cp->pak[pkt].d[RW_LBNH]; - sim_activate (uptr, rq_xtime); /* activate */ - return OK; } } /* done */ -else sts = ST_OFL; /* offline */ -cp->pak[pkt].d[RW_BCL] = cp->pak[pkt].d[RW_BCH] = 0; /* bad packet */ -rq_putr (cp, pkt, cmd | OP_END, 0, sts, RW_LNT_D, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Validity checks */ - -int32 rq_rw_valid (MSC *cp, int32 pkt, UNIT *uptr, uint32 cmd) -{ -uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */ -uint32 lbn = GETP32 (pkt, RW_LBNL); /* get lbn */ -uint32 bc = GETP32 (pkt, RW_BCL); /* get byte cnt */ -uint32 maxlbn = drv_tab[dtyp].lbn; /* get max lbn */ - -if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - return (ST_OFL | SB_OFL_NV); /* offl no vol */ -if ((uptr->flags & UNIT_ONL) == 0) /* not online? */ - return ST_AVL; /* only avail */ -if ((cmd != OP_ACC) && (cmd != OP_ERS) && /* 'real' xfer */ - (cp->pak[pkt].d[RW_BAL] & 1)) /* odd address? */ - return (ST_HST | SB_HST_OA); /* host buf odd */ -if (bc & 1) return (ST_HST | SB_HST_OC); /* odd byte cnt? */ -if (bc & 0xF0000000) return (ST_CMD | I_BCNT); /* 'reasonable' bc? */ -/* if (lbn & 0xF0000000) return (ST_CMD | I_LBN); /* 'reasonable' lbn? */ -if (lbn >= maxlbn) { /* accessing RCT? */ - if (lbn >= (maxlbn + drv_tab[dtyp].rcts)) /* beyond copy 1? */ - return (ST_CMD | I_LBN); /* lbn err */ - if (bc != RQ_NUMBY) return (ST_CMD | I_BCNT); }/* bc must be 512 */ -else if ((lbn + ((bc + (RQ_NUMBY - 1)) / RQ_NUMBY)) > maxlbn) - return (ST_CMD | I_BCNT); /* spiral to RCT */ -if ((cmd == OP_WR) || (cmd == OP_ERS)) { /* write op? */ - if (lbn >= maxlbn) /* accessing RCT? */ - return (ST_CMD | I_LBN); /* lbn err */ - if (uptr->uf & UF_WPS) /* swre wlk? */ - return (ST_WPR | SB_WPR_SW); - if (RQ_WPH (uptr)) /* hwre wlk? */ - return (ST_WPR | SB_WPR_HW); } -return 0; /* success! */ -} - -/* Unit service for data transfer commands */ - -t_stat rq_svc (UNIT *uptr) -{ -MSC *cp = rq_ctxmap[uptr->cnum]; - -uint32 i, t, err, tbc, abc, wwc; -int32 pkt = uptr->cpkt; /* get packet */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* get cmd */ -uint32 ba = GETP32 (pkt, RW_WBAL); /* buf addr */ -uint32 bc = GETP32 (pkt, RW_WBCL); /* byte count */ -uint32 bl = GETP32 (pkt, RW_WBLL); /* block addr */ -t_addr da = ((t_addr) bl) * RQ_NUMBY; /* disk addr */ - -if ((cp == NULL) || (pkt == 0)) return STOP_RQ; /* what??? */ -tbc = (bc > RQ_MAXFR)? RQ_MAXFR: bc; /* trim cnt to max */ - -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rq_rw_end (cp, uptr, 0, ST_OFL | SB_OFL_NV); /* offl no vol */ - return SCPE_OK; } -if (bc == 0) { /* no xfer? */ - rq_rw_end (cp, uptr, 0, ST_SUC); /* ok by me... */ - return SCPE_OK; } - -if ((cmd == OP_ERS) || (cmd == OP_WR)) { /* write op? */ - if (RQ_WPH (uptr)) { - rq_rw_end (cp, uptr, 0, ST_WPR | SB_WPR_HW); - return SCPE_OK; } - if (uptr->uf & UF_WPS) { - rq_rw_end (cp, uptr, 0, ST_WPR | SB_WPR_SW); - return SCPE_OK; } } - -if (cmd == OP_ERS) { /* erase? */ - wwc = ((tbc + (RQ_NUMBY - 1)) & ~(RQ_NUMBY - 1)) >> 1; - for (i = 0; i < wwc; i++) rqxb[i] = 0; /* clr buf */ - err = fseek_ext (uptr->fileref, da, SEEK_SET); /* set pos */ - if (!err) fxwrite (rqxb, sizeof (int16), wwc, uptr->fileref); - err = ferror (uptr->fileref); } /* end if erase */ - -else if (cmd == OP_WR) { /* write? */ - t = Map_ReadW (ba, tbc, rqxb, MAP); /* fetch buffer */ - if (abc = tbc - t) { /* any xfer? */ - wwc = ((abc + (RQ_NUMBY - 1)) & ~(RQ_NUMBY - 1)) >> 1; - for (i = (abc >> 1); i < wwc; i++) rqxb[i] = 0; - err = fseek_ext (uptr->fileref, da, SEEK_SET); - if (!err) fxwrite (rqxb, sizeof (int16), wwc, uptr->fileref); - err = ferror (uptr->fileref); } - if (t) { /* nxm? */ - PUTP32 (pkt, RW_WBCL, bc - abc); /* adj bc */ - PUTP32 (pkt, RW_WBAL, ba + abc); /* adj ba */ - if (rq_hbe (cp, uptr)) /* post err log */ - rq_rw_end (cp, uptr, EF_LOG, ST_HST | SB_HST_NXM); - return SCPE_OK; } } /* end else wr */ - -else { err = fseek_ext (uptr->fileref, da, SEEK_SET); /* set pos */ - if (!err) { - i = fxread (rqxb, sizeof (int16), tbc >> 1, uptr->fileref); - for ( ; i < (tbc >> 1); i++) rqxb[i] = 0; /* fill */ - err = ferror (uptr->fileref); } - if ((cmd == OP_RD) && !err) { /* read? */ - if (t = Map_WriteW (ba, tbc, rqxb, MAP)) { /* store, nxm? */ - PUTP32 (pkt, RW_WBCL, bc - (tbc - t)); /* adj bc */ - PUTP32 (pkt, RW_WBAL, ba + (tbc - t)); /* adj ba */ - if (rq_hbe (cp, uptr)) /* post err log */ - rq_rw_end (cp, uptr, EF_LOG, ST_HST | SB_HST_NXM); - return SCPE_OK; } - } - else if ((cmd == OP_CMP) && !err) { /* compare? */ - uint8 dby, mby; - for (i = 0; i < tbc; i++) { /* loop */ - if (Map_ReadB (ba + i, 1, &mby, MAP)) { /* fetch, nxm? */ - PUTP32 (pkt, RW_WBCL, bc - i); /* adj bc */ - PUTP32 (pkt, RW_WBAL, bc - i); /* adj ba */ - if (rq_hbe (cp, uptr)) /* post err log */ - rq_rw_end (cp, uptr, EF_LOG, ST_HST | SB_HST_NXM); - return SCPE_OK; } - dby = (rqxb[i >> 1] >> ((i & 1)? 8: 0)) & 0xFF; - if (mby != dby) { /* cmp err? */ - PUTP32 (pkt, RW_WBCL, bc - i); /* adj bc */ - rq_rw_end (cp, uptr, 0, ST_CMP); /* done */ - return SCPE_OK; } /* exit */ - } /* end for */ - } /* end else if */ - } /* end else read */ -if (err != 0) { /* error? */ - if (rq_dte (cp, uptr, ST_DRV)) /* post err log */ - rq_rw_end (cp, uptr, EF_LOG, ST_DRV); /* if ok, report err */ - perror ("RQ I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -ba = ba + tbc; /* incr bus addr */ -bc = bc - tbc; /* decr byte cnt */ -bl = bl + ((tbc + (RQ_NUMBY - 1)) / RQ_NUMBY); /* incr blk # */ -PUTP32 (pkt, RW_WBAL, ba); /* update pkt */ -PUTP32 (pkt, RW_WBCL, bc); -PUTP32 (pkt, RW_WBLL, bl); -if (bc) sim_activate (uptr, rq_xtime); /* more? resched */ -else rq_rw_end (cp, uptr, 0, ST_SUC); /* done! */ -return SCPE_OK; -} - -/* Transfer command complete */ - -t_bool rq_rw_end (MSC *cp, UNIT *uptr, uint32 flg, uint32 sts) -{ -int32 pkt = uptr->cpkt; /* packet */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* get cmd */ -uint32 bc = GETP32 (pkt, RW_BCL); /* init bc */ -uint32 wbc = GETP32 (pkt, RW_WBCL); /* work bc */ -DEVICE *dptr = rq_devmap[uptr->cnum]; - -uptr->cpkt = 0; /* done */ -PUTP32 (pkt, RW_BCL, bc - wbc); /* bytes processed */ -cp->pak[pkt].d[RW_WBAL] = 0; /* clear temps */ -cp->pak[pkt].d[RW_WBAH] = 0; -cp->pak[pkt].d[RW_WBCL] = 0; -cp->pak[pkt].d[RW_WBCH] = 0; -cp->pak[pkt].d[RW_WBLL] = 0; -cp->pak[pkt].d[RW_WBLH] = 0; -rq_putr (cp, pkt, cmd | OP_END, flg, sts, RW_LNT_D, UQ_TYP_SEQ); /* fill pkt */ -if (!rq_putpkt (cp, pkt, TRUE)) return ERR; /* send pkt */ -if (uptr->pktq) /* more to do? */ - sim_activate (dptr->units + RQ_QUEUE, rq_qtime); /* activate thread */ -return OK; -} - -/* Data transfer error log packet */ - -t_bool rq_dte (MSC *cp, UNIT *uptr, uint32 err) -{ -int32 pkt, tpkt; -uint32 lu, dtyp, lbn, ccyl, csurf, csect, t; - -if ((cp->cflgs & CF_THS) == 0) return OK; /* logging? */ -if (!rq_deqf (cp, &pkt)) return ERR; /* get log pkt */ -tpkt = uptr->cpkt; /* rw pkt */ -lu = cp->pak[tpkt].d[CMD_UN]; /* unit # */ -lbn = GETP32 (tpkt, RW_WBLL); /* recent LBN */ -dtyp = GET_DTYPE (uptr->flags); /* drv type */ -if (drv_tab[dtyp].flgs & RQDF_SDI) t = 0; /* SDI? ovhd @ end */ -else t = (drv_tab[dtyp].xbn + drv_tab[dtyp].dbn) / /* ovhd cylinders */ - (drv_tab[dtyp].sect * drv_tab[dtyp].surf); -ccyl = t + (lbn / drv_tab[dtyp].cyl); /* curr real cyl */ -t = lbn % drv_tab[dtyp].cyl; /* trk relative blk */ -csurf = t / drv_tab[dtyp].surf; /* curr surf */ -csect = t % drv_tab[dtyp].surf; /* curr sect */ - -cp->pak[pkt].d[ELP_REFL] = cp->pak[tpkt].d[CMD_REFL]; /* copy cmd ref */ -cp->pak[pkt].d[ELP_REFH] = cp->pak[tpkt].d[CMD_REFH]; -cp->pak[pkt].d[ELP_UN] = lu; /* copy unit */ -cp->pak[pkt].d[ELP_SEQ] = 0; /* clr seq # */ -cp->pak[pkt].d[DTE_CIDA] = 0; /* ctrl ID */ -cp->pak[pkt].d[DTE_CIDB] = 0; -cp->pak[pkt].d[DTE_CIDC] = 0; -cp->pak[pkt].d[DTE_CIDD] = (RQ_CLASS << DTE_CIDD_V_CLS) | - (RQ_MODEL << DTE_CIDD_V_MOD); -cp->pak[pkt].d[DTE_VER] = (RQ_HVER << DTE_VER_V_HVER) | - (RQ_SVER << DTE_VER_V_SVER); -cp->pak[pkt].d[DTE_MLUN] = lu; /* MLUN */ -cp->pak[pkt].d[DTE_UIDA] = lu; /* unit ID */ -cp->pak[pkt].d[DTE_UIDB] = 0; -cp->pak[pkt].d[DTE_UIDC] = 0; -cp->pak[pkt].d[DTE_UIDD] = (UID_DISK << DTE_UIDD_V_CLS) | - (drv_tab[dtyp].mod << DTE_UIDD_V_MOD); -cp->pak[pkt].d[DTE_UVER] = 0; /* unit versn */ -cp->pak[pkt].d[DTE_SCYL] = ccyl; /* cylinder */ -cp->pak[pkt].d[DTE_VSNL] = 01234 + lu; /* vol ser # */ -cp->pak[pkt].d[DTE_VSNH] = 0; -cp->pak[pkt].d[DTE_D1] = 0; -cp->pak[pkt].d[DTE_D2] = csect << DTE_D2_V_SECT; /* geometry */ -cp->pak[pkt].d[DTE_D3] = (ccyl << DTE_D3_V_CYL) | - (csurf << DTE_D3_V_SURF); -rq_putr (cp, pkt, FM_SDE, LF_SNR, err, DTE_LNT, UQ_TYP_DAT); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Host bus error log packet */ - -t_bool rq_hbe (MSC *cp, UNIT *uptr) -{ -int32 pkt, tpkt; - -if ((cp->cflgs & CF_THS) == 0) return OK; /* logging? */ -if (!rq_deqf (cp, &pkt)) return ERR; /* get log pkt */ -tpkt = uptr->cpkt; /* rw pkt */ -cp->pak[pkt].d[ELP_REFL] = cp->pak[tpkt].d[CMD_REFL]; /* copy cmd ref */ -cp->pak[pkt].d[ELP_REFH] = cp->pak[tpkt].d[CMD_REFH]; -cp->pak[pkt].d[ELP_UN] = cp->pak[tpkt].d[CMD_UN]; /* copy unit */ -cp->pak[pkt].d[ELP_SEQ] = 0; /* clr seq # */ -cp->pak[pkt].d[HBE_CIDA] = 0; /* ctrl ID */ -cp->pak[pkt].d[HBE_CIDB] = 0; -cp->pak[pkt].d[HBE_CIDC] = 0; -cp->pak[pkt].d[HBE_CIDD] = (RQ_CLASS << DTE_CIDD_V_CLS) | - (RQ_MODEL << DTE_CIDD_V_MOD); -cp->pak[pkt].d[HBE_VER] = (RQ_HVER << HBE_VER_V_HVER) | /* versions */ - (RQ_SVER << HBE_VER_V_SVER); -cp->pak[pkt].d[HBE_RSV] = 0; -cp->pak[pkt].d[HBE_BADL] = cp->pak[tpkt].d[RW_WBAL]; /* bad addr */ -cp->pak[pkt].d[HBE_BADH] = cp->pak[tpkt].d[RW_WBAH]; -rq_putr (cp, pkt, FM_BAD, LF_SNR, ST_HST | SB_HST_NXM, HBE_LNT, UQ_TYP_DAT); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Port last failure error log packet */ - -t_bool rq_plf (MSC *cp, uint32 err) -{ -int32 pkt; - -if (!rq_deqf (cp, &pkt)) return ERR; /* get log pkt */ -cp->pak[pkt].d[ELP_REFL] = 0; /* ref = 0 */ -cp->pak[pkt].d[ELP_REFH] = 0; -cp->pak[pkt].d[ELP_UN] = 0; /* no unit */ -cp->pak[pkt].d[ELP_SEQ] = 0; /* no seq */ -cp->pak[pkt].d[PLF_CIDA] = 0; /* cntl ID */ -cp->pak[pkt].d[PLF_CIDB] = 0; -cp->pak[pkt].d[PLF_CIDC] = 0; -cp->pak[pkt].d[PLF_CIDD] = (RQ_CLASS << PLF_CIDD_V_CLS) | - (RQ_MODEL << PLF_CIDD_V_MOD); -cp->pak[pkt].d[PLF_VER] = (RQ_SVER << PLF_VER_V_SVER) | - (RQ_HVER << PLF_VER_V_HVER); -cp->pak[pkt].d[PLF_ERR] = err; -rq_putr (cp, pkt, FM_CNT, LF_SNR, ST_CNT, PLF_LNT, UQ_TYP_DAT); -cp->pak[pkt].d[UQ_HCTC] |= (UQ_CID_DIAG << UQ_HCTC_V_CID); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Unit now available attention packet */ - -int32 rq_una (MSC *cp, int32 un) -{ -int32 pkt; -uint32 lu = cp->ubase + un; -UNIT *uptr = rq_getucb (cp, lu); - -if (uptr == NULL) return OK; /* huh? */ -if (!rq_deqf (cp, &pkt)) return ERR; /* get log pkt */ -cp->pak[pkt].d[RSP_REFL] = 0; /* ref = 0 */ -cp->pak[pkt].d[RSP_REFH] = 0; -cp->pak[pkt].d[RSP_UN] = lu; -cp->pak[pkt].d[RSP_RSV] = 0; -rq_putr_unit (cp, pkt, uptr, lu, FALSE); /* fill unit fields */ -rq_putr (cp, pkt, OP_AVA, 0, 0, UNA_LNT, UQ_TYP_SEQ); /* fill std fields */ -return rq_putpkt (cp, pkt, TRUE); -} - -/* List handling - - rq_deqf - dequeue head of free list (fatal err if none) - rq_deqh - dequeue head of list - rq_enqh - enqueue at head of list - rq_enqt - enqueue at tail of list -*/ - -t_bool rq_deqf (MSC *cp, int32 *pkt) -{ -if (cp->freq == 0) return rq_fatal (cp, PE_NSR); /* no free pkts?? */ -cp->pbsy = cp->pbsy + 1; /* cnt busy pkts */ -*pkt = cp->freq; /* head of list */ -cp->freq = cp->pak[cp->freq].link; /* next */ -return OK; -} - -int32 rq_deqh (MSC *cp, int32 *lh) -{ -int32 ptr = *lh; /* head of list */ - -if (ptr) *lh = cp->pak[ptr].link; /* next */ -return ptr; -} - -void rq_enqh (MSC *cp, int32 *lh, int32 pkt) -{ -if (pkt == 0) return; /* any pkt? */ -cp->pak[pkt].link = *lh; /* link is old lh */ -*lh = pkt; /* pkt is new lh */ -return; -} - -void rq_enqt (MSC *cp, int32 *lh, int32 pkt) -{ -if (pkt == 0) return; /* any pkt? */ -cp->pak[pkt].link = 0; /* it will be tail */ -if (*lh == 0) *lh = pkt; /* if empty, enqh */ -else { uint32 ptr = *lh; /* chase to end */ - while (cp->pak[ptr].link) ptr = cp->pak[ptr].link; - cp->pak[ptr].link = pkt; } /* enq at tail */ -return; -} - -/* Packet and descriptor handling */ - -/* Get packet from command ring */ - -t_bool rq_getpkt (MSC *cp, int32 *pkt) -{ -uint32 addr, desc; - -if (!rq_getdesc (cp, &cp->cq, &desc)) return ERR; /* get cmd desc */ -if ((desc & UQ_DESC_OWN) == 0) { /* none */ - *pkt = 0; /* pkt = 0 */ - return OK; } /* no error */ -if (!rq_deqf (cp, pkt)) return ERR; /* get cmd pkt */ -cp->hat = 0; /* dsbl hst timer */ -addr = desc & UQ_ADDR; /* get Q22 addr */ -if (Map_ReadW (addr + UQ_HDR_OFF, RQ_PKT_SIZE, cp->pak[*pkt].d, MAP)) - return rq_fatal (cp, PE_PRE); /* read pkt */ -return rq_putdesc (cp, &cp->cq, desc); /* release desc */ -} - -/* Put packet to response ring - note the clever hack about credits. - The controller sends all its credits to the host. Thereafter, it - supplies one credit for every response packet sent over. Simple! -*/ - -t_bool rq_putpkt (MSC *cp, int32 pkt, t_bool qt) -{ -uint32 addr, desc, lnt, cr; -DEVICE *dptr = rq_devmap[cp->cnum]; - -if (pkt == 0) return OK; /* any packet? */ -if (DBG_LOG (LOG_RQ)) fprintf (sim_log, - ">>RQ%c: rsp=%04X, sts=%04X\n", 'A' + cp->cnum, - cp->pak[pkt].d[RSP_OPF], cp->pak[pkt].d[RSP_STS]); -if (!rq_getdesc (cp, &cp->rq, &desc)) return ERR; /* get rsp desc */ -if ((desc & UQ_DESC_OWN) == 0) { /* not valid? */ - if (qt) rq_enqt (cp, &cp->rspq, pkt); /* normal? q tail */ - else rq_enqh (cp, &cp->rspq, pkt); /* resp q call */ - sim_activate (dptr->units + RQ_QUEUE, rq_qtime); /* activate q thrd */ - return OK; } -addr = desc & UQ_ADDR; /* get Q22 addr */ -lnt = cp->pak[pkt].d[UQ_HLNT] - UQ_HDR_OFF; /* size, with hdr */ -if ((GETP (pkt, UQ_HCTC, TYP) == UQ_TYP_SEQ) && /* seq packet? */ - (GETP (pkt, CMD_OPC, OPC) & OP_END)) { /* end packet? */ - cr = (cp->credits >= 14)? 14: cp->credits; /* max 14 credits */ - cp->credits = cp->credits - cr; /* decr credits */ - cp->pak[pkt].d[UQ_HCTC] |= ((cr + 1) << UQ_HCTC_V_CR); } -if (Map_WriteW (addr + UQ_HDR_OFF, lnt, cp->pak[pkt].d, MAP)) - return rq_fatal (cp, PE_PWE); /* write pkt */ -rq_enqh (cp, &cp->freq, pkt); /* pkt is free */ -cp->pbsy = cp->pbsy - 1; /* decr busy cnt */ -if (cp->pbsy == 0) cp->hat = cp->htmo; /* idle? strt hst tmr */ -return rq_putdesc (cp, &cp->rq, desc); /* release desc */ -} - -/* Get a descriptor from the host */ - -t_bool rq_getdesc (MSC *cp, struct uq_ring *ring, uint32 *desc) -{ -uint32 addr = ring->ba + ring->idx; -uint16 d[2]; - -if (Map_ReadW (addr, 4, d, MAP)) /* fetch desc */ - return rq_fatal (cp, PE_QRE); /* err? dead */ -*desc = ((uint32) d[0]) | (((uint32) d[1]) << 16); -return OK; -} - -/* Return a descriptor to the host, clearing owner bit - If rings transitions from "empty" to "not empty" or "full" to - "not full", and interrupt bit was set, interrupt the host. - Actually, test whether previous ring entry was owned by host. -*/ - -t_bool rq_putdesc (MSC *cp, struct uq_ring *ring, uint32 desc) -{ -uint32 prvd, newd = (desc & ~UQ_DESC_OWN) | UQ_DESC_F; -uint32 prva, addr = ring->ba + ring->idx; -uint16 d[2]; - -d[0] = newd & 0xFFFF; /* 32b to 16b */ -d[1] = (newd >> 16) & 0xFFFF; -if (Map_WriteW (addr, 4, d, MAP)) /* store desc */ - return rq_fatal (cp, PE_QWE); /* err? dead */ -if (desc & UQ_DESC_F) { /* was F set? */ - if (ring->lnt <= 4) rq_ring_int (cp, ring); /* lnt = 1? intr */ - else { /* prv desc */ - prva = ring->ba + ((ring->idx - 4) & (ring->lnt - 1)); - if (Map_ReadW (prva, 4, d, MAP)) /* read prv */ - return rq_fatal (cp, PE_QRE); - prvd = ((uint32) d[0]) | (((uint32) d[1]) << 16); - if (prvd & UQ_DESC_OWN) rq_ring_int (cp, ring); } } -ring->idx = (ring->idx + 4) & (ring->lnt - 1); -return OK; -} - -/* Get unit descriptor for logical unit */ - -UNIT *rq_getucb (MSC *cp, uint32 lu) -{ -DEVICE *dptr = rq_devmap[cp->cnum]; -UNIT *uptr; - -if ((lu < cp->ubase) || (lu >= (cp->ubase + RQ_NUMDR))) - return NULL; -uptr = dptr->units + (lu % RQ_NUMDR); -if (uptr->flags & UNIT_DIS) return NULL; -return uptr; -} - -/* Hack unit flags */ - -void rq_setf_unit (MSC *cp, int32 pkt, UNIT *uptr) -{ -uptr->uf = cp->pak[pkt].d[ONL_UFL] & UF_MSK; /* settable flags */ -if ((cp->pak[pkt].d[CMD_MOD] & MD_SWP) && /* swre wrp enb? */ - (cp->pak[pkt].d[ONL_UFL] & UF_WPS)) /* swre wrp on? */ - uptr->uf = uptr->uf | UF_WPS; /* simon says... */ -return; -} - -/* Unit response fields */ - -void rq_putr_unit (MSC *cp, int32 pkt, UNIT *uptr, uint32 lu, t_bool all) -{ -uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */ - -cp->pak[pkt].d[ONL_MLUN] = lu; /* unit */ -cp->pak[pkt].d[ONL_UFL] = uptr->uf | UF_RPL | RQ_WPH (uptr) | RQ_RMV (uptr); -cp->pak[pkt].d[ONL_RSVL] = 0; /* reserved */ -cp->pak[pkt].d[ONL_RSVH] = 0; -cp->pak[pkt].d[ONL_UIDA] = lu; /* UID low */ -cp->pak[pkt].d[ONL_UIDB] = 0; -cp->pak[pkt].d[ONL_UIDC] = 0; -cp->pak[pkt].d[ONL_UIDD] = (UID_DISK << ONL_UIDD_V_CLS) | - (drv_tab[dtyp].mod << ONL_UIDD_V_MOD); /* UID hi */ -PUTP32 (pkt, ONL_MEDL, drv_tab[dtyp].med); /* media type */ -if (all) { /* if long form */ - PUTP32 (pkt, ONL_SIZL, drv_tab[dtyp].lbn); /* user LBNs */ - cp->pak[pkt].d[ONL_VSNL] = 01234 + lu; /* vol serial # */ - cp->pak[pkt].d[ONL_VSNH] = 0; } -return; -} - -/* UQ_HDR and RSP_OP fields */ - -void rq_putr (MSC *cp, int32 pkt, uint32 cmd, uint32 flg, - uint32 sts, uint32 lnt, uint32 typ) -{ -cp->pak[pkt].d[RSP_OPF] = (cmd << RSP_OPF_V_OPC) | /* set cmd, flg */ - (flg << RSP_OPF_V_FLG); -cp->pak[pkt].d[RSP_STS] = sts; -cp->pak[pkt].d[UQ_HLNT] = lnt; /* length */ -cp->pak[pkt].d[UQ_HCTC] = (typ << UQ_HCTC_V_TYP) | /* type, cid */ - (UQ_CID_MSCP << UQ_HCTC_V_CID); /* clr credits */ -return; -} - -/* Post interrupt during init */ - -void rq_init_int (MSC *cp) -{ -if (cp->s1dat & (SA_S1H_IE | SA_S1H_VEC)) rq_setint (cp); -return; -} - -/* Post interrupt during putpkt - note that NXMs are ignored! */ - -void rq_ring_int (MSC *cp, struct uq_ring *ring) -{ -uint32 iadr = cp->comm + ring->ioff; /* addr intr wd */ -uint16 flag = 1; - -Map_WriteW (iadr, 2, &flag, MAP); /* write flag */ -if (cp->s1dat & SA_S1H_VEC) rq_setint (cp); /* if enb, intr */ -return; -} - -/* Set RQ interrupt */ - -void rq_setint (MSC *cp) -{ -cp->irq = 1; /* set ctrl int */ -SET_INT (RQ); /* set master int */ -return; -} - -/* Clear RQ interrupt */ - -void rq_clrint (MSC *cp) -{ -int32 i; -MSC *ncp; - -cp->irq = 0; /* clr ctrl int */ -for (i = 0; i < RQ_NUMCT; i++) { /* loop thru ctrls */ - ncp = rq_ctxmap[i]; /* get context */ - if (ncp->irq) { /* other interrupt? */ - SET_INT (RQ); /* yes, set master */ - return; } } -CLR_INT (RQ); /* no, clr master */ -return; -} - -/* Return interrupt vector */ - -int32 rq_inta (void) -{ -int32 i; -MSC *ncp; -DEVICE *dptr; -DIB *dibp; - -for (i = 0; i < RQ_NUMCT; i++) { /* loop thru ctrl */ - ncp = rq_ctxmap[i]; /* get context */ - if (ncp->irq) { /* ctrl int set? */ - dptr = rq_devmap[i]; /* get device */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - rq_clrint (ncp); /* clear int req */ - return dibp->vec; } } /* return vector */ -return 0; /* no intr req */ -} - -/* Fatal error */ - -t_bool rq_fatal (MSC *cp, uint32 err) -{ -if (DBG_LOG (LOG_RQ)) - fprintf (sim_log, ">>RQ%c: fatal err=%X\n", 'A' + cp->cnum, err); -rq_reset (rq_devmap[cp->cnum]); /* reset device */ -cp->sa = SA_ER | err; /* SA = dead code */ -cp->csta = CST_DEAD; /* state = dead */ -cp->perr = err; /* save error */ -return ERR; -} - -/* Set/clear hardware write lock */ - -t_stat rq_set_wlk (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */ - -if (drv_tab[dtyp].flgs & RQDF_RO) return SCPE_NOFNC; /* not on read only */ -return SCPE_OK; -} - -/* Show write lock status */ - -t_stat rq_show_wlk (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */ - -if (drv_tab[dtyp].flgs & RQDF_RO) fprintf (st, "read only"); -else if (uptr->flags & UNIT_WPRT) fprintf (st, "write locked"); -else fprintf (st, "write enabled"); -return SCPE_OK; -} - -/* Set unit type (and capacity if user defined) */ - -t_stat rq_set_type (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -uint32 cap; -uint32 max = sim_taddr_64? RA8U_EMAXC: RA8U_MAXC; -t_stat r; - -if ((val < 0) || (val > RA8U_DTYPE) || ((val != RA8U_DTYPE) && cptr)) - return SCPE_ARG; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -if (cptr) { - cap = (int32) get_uint (cptr, 10, max, &r); - if ((r != SCPE_OK) || (cap < RA8U_MINC)) return SCPE_ARG; - drv_tab[val].lbn = cap << (20 - 9); } -uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (val << UNIT_V_DTYPE); -uptr->capac = ((t_addr) drv_tab[val].lbn) * RQ_NUMBY; -return SCPE_OK; -} - -/* Show unit type (and capacity if user defined) */ - -t_stat rq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, "%s", drv_tab[GET_DTYPE (uptr->flags)].name); -return SCPE_OK; -} - -/* Device attach */ - -t_stat rq_attach (UNIT *uptr, char *cptr) -{ -int32 dtyp = GET_DTYPE (uptr->flags); -MSC *cp = rq_ctxmap[uptr->cnum]; -t_stat r; - -uptr->capac = drv_tab[dtyp].lbn * RQ_NUMBY; -r = attach_unit (uptr, cptr); -if (r != SCPE_OK) return r; -if (cp->csta == CST_UP) uptr->flags = uptr->flags | UNIT_ATP; -return SCPE_OK; -} - -/* Device detach */ - -t_stat rq_detach (UNIT *uptr) -{ -t_stat r; - -r = detach_unit (uptr); /* detach unit */ -if (r != SCPE_OK) return r; -uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_ATP); /* clr onl, atn pend */ -uptr->uf = 0; /* clr unit flgs */ -return SCPE_OK; -} - -/* Device reset */ - -t_stat rq_reset (DEVICE *dptr) -{ -int32 i, j, cidx; -UNIT *uptr; -MSC *cp; -DIB *dibp = (DIB *) dptr->ctxt; - -for (i = 0, cidx = -1; i < RQ_NUMCT; i++) { /* find ctrl num */ - if (rq_devmap[i] == dptr) cidx = i; } -if (cidx < 0) return SCPE_IERR; /* not found??? */ -cp = rq_ctxmap[cidx]; /* get context */ -cp->cnum = cidx; /* init index */ -cp->ubase = cidx * RQ_NUMDR; /* init unit base */ -cp->csta = CST_S1; /* init stage 1 */ -cp->s1dat = 0; /* no S1 data */ -dibp->vec = 0; /* no vector */ -cp->comm = 0; /* no comm region */ -cp->sa = SA_S1 | SA_S1C_Q22 | SA_S1C_DI | SA_S1C_MP; /* init SA val */ -cp->cflgs = CF_RPL; /* ctrl flgs off */ -cp->htmo = RQ_DHTMO; /* default timeout */ -cp->hat = cp->htmo; /* default timer */ -cp->cq.ba = cp->cq.lnt = cp->cq.idx = 0; /* clr cmd ring */ -cp->rq.ba = cp->rq.lnt = cp->rq.idx = 0; /* clr rsp ring */ -cp->credits = (RQ_NPKTS / 2) - 1; /* init credits */ -cp->freq = 1; /* init free list */ -for (i = 0; i < RQ_NPKTS; i++) { /* all pkts free */ - if (i) cp->pak[i].link = (i + 1) & RQ_M_NPKTS; - else cp->pak[i].link = 0; - for (j = 0; j < RQ_PKT_SIZE_W; j++) cp->pak[i].d[j] = 0; } -cp->rspq = 0; /* no q'd rsp pkts */ -cp->pbsy = 0; /* all pkts free */ -cp->pip = 0; /* not polling */ -rq_clrint (cp); /* clr intr req */ -for (i = 0; i < (RQ_NUMDR + 2); i++) { /* init units */ - uptr = dptr->units + i; - sim_cancel (uptr); /* clr activity */ - uptr->cnum = cidx; /* set ctrl index */ - uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_ATP); - uptr->uf = 0; /* clr unit flags */ - uptr->cpkt = uptr->pktq = 0; } /* clr pkt q's */ -if (rqxb == NULL) rqxb = calloc (RQ_MAXFR >> 1, sizeof (unsigned int16)); -if (rqxb == NULL) return SCPE_MEM; -return auto_config (0, 0); /* run autoconfig */ -} - -/* Device bootstrap */ - -#if defined (VM_PDP11) - -#define BOOT_START 016000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 014) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - - 0042125, /* st: "UD" */ - - /* Four step init process */ - - 0012706, 0016000, /* mov #st,sp */ - 0012700, 0000000, /* mov #unit,r0 */ - 0012701, 0172150, /* mov #172150, r1 ; ip addr */ - 0012704, 0016162, /* mov #it, r4 */ - 0012705, 0004000, /* mov #4000,r5 ; s1 mask */ - 0010102, /* mov r1,r2 */ - 0005022, /* clr (r2)+ ; init */ - 0005712, /* 10$: tst (r2) ; err? */ - 0100001, /* bpl 20$ */ - 0000000, /* halt */ - 0030512, /* 20$: bit r5,(r2) ; step set? */ - 0001773, /* beq 10$ ; wait */ - 0012412, /* mov (r4)+,(r2) ; send next */ - 0006305, /* asl r5 ; next mask */ - 0100370, /* bpl 10$ ; s4 done? */ - - /* Send ONL, READ commands */ - - 0105714, /* 30$: tstb (r4) ; end tbl? */ - 0001434, /* beq done ; 0 = yes */ - 0012702, 0007000, /* mov #rpkt-4,r2 ; clr pkts */ - 0005022, /* 40$: clr (r2)+ */ - 0020227, 0007204, /* cmp r2,#comm */ - 0103774, /* blo 40$ */ - 0112437, 0007100, /* movb (r4)+,cpkt-4 ; set lnt */ - 0110037, 0007110, /* movb r0,cpkt+4 ; set unit */ - 0112437, 0007114, /* movb (r4)+,cpkt+10 ; set op */ - 0112437, 0007121, /* movb (r4)+,cpkt+15 ; set param */ - 0012722, 0007004, /* mov #rpkt,(r2)+ ; rq desc */ - 0010522, /* mov r5,(r2)+ ; rq own */ - 0012722, 0007104, /* mov #ckpt,(r2)+ ; cq desc */ - 0010512, /* mov r5,(r2) ; cq own */ - 0024242, /* cmp -(r2),-(r2) ; back up */ - 0005711, /* tst (r1) ; wake ctrl */ - 0005712, /* 50$: tst (r2) ; rq own clr? */ - 0100776, /* bmi 50$ ; wait */ - 0005737, 0007016, /* tst rpkt+12 ; stat ok? */ - 0001743, /* beq 30$ ; next cmd */ - 0000000, /* halt */ - - /* Boot block read in, jump to 0 */ - - 0005011, /* done: clr (r1) ; for M+ */ - 0005003, /* clr r3 */ - 0012704, BOOT_START+020, /* mov #st+020,r4 */ - 0005005, /* clr r5 */ - 0005007, /* clr pc */ - - /* Data */ - - 0100000, /* it: no ints, ring sz = 1 */ - 0007204, /* .word comm */ - 0000000, /* .word 0 */ - 0000001, /* .word 1 */ - 0004420, /* .byte 20,11 */ - 0020000, /* .byte 0,40 */ - 0001041, /* .byte 41,2 */ - 0000000 -}; - -t_stat rq_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; -extern uint16 *M; -DIB *dibp = (DIB *) dptr->ctxt; - -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & 3; -M[BOOT_CSR >> 1] = dibp->ba & DMASK; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} - -#else - -t_stat rq_boot (int32 unitno, DEVICE *dptr) -{ -return SCPE_NOFNC; -} -#endif - -/* Special show commands */ - -void rq_show_ring (FILE *st, struct uq_ring *rp) -{ -uint32 i, desc; -uint16 d[2]; - -#if defined (VM_PDP11) -fprintf (st, "ring, base = %o, index = %d, length = %d\n", - rp->ba, rp->idx >> 2, rp->lnt >> 2); -#else -fprintf (st, "ring, base = %x, index = %d, length = %d\n", - rp->ba, rp->idx >> 2, rp->lnt >> 2); -#endif -for (i = 0; i < (rp->lnt >> 2); i++) { - if (Map_ReadW (rp->ba + (i << 2), 4, d, MAP)) { - fprintf (st, " %3d: non-existent memory\n", i); - break; } - desc = ((uint32) d[0]) | (((uint32) d[1]) << 16); -#if defined (VM_PDP11) - fprintf (st, " %3d: %011o\n", i, desc); -#else - fprintf (st, " %3d: %08x\n", i, desc); -#endif - } -return; -} - -void rq_show_pkt (FILE *st, MSC *cp, int32 pkt) -{ -int32 i, j; -uint32 cr = GETP (pkt, UQ_HCTC, CR); -uint32 typ = GETP (pkt, UQ_HCTC, TYP); -uint32 cid = GETP (pkt, UQ_HCTC, CID); - -fprintf (st, "packet %d, credits = %d, type = %d, cid = %d\n", - pkt, cr, typ, cid); -for (i = 0; i < RQ_SH_MAX; i = i + RQ_SH_PPL) { - fprintf (st, " %2d:", i); - for (j = i; j < (i + RQ_SH_PPL); j++) -#if defined (VM_PDP11) - fprintf (st, " %06o", cp->pak[pkt].d[j]); -#else - fprintf (st, " %04x", cp->pak[pkt].d[j]); -#endif - fprintf (st, "\n"); - } -return; -} - -t_stat rq_show_unitq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -MSC *cp = rq_ctxmap[uptr->cnum]; -DEVICE *dptr = rq_devmap[uptr->cnum]; -int32 pkt, u; - -u = uptr - dptr->units; -if (cp->csta != CST_UP) { - fprintf (st, "Controller is not initialized\n"); - return SCPE_OK; } -if ((uptr->flags & UNIT_ONL) == 0) { - if (uptr->flags & UNIT_ATT) - fprintf (st, "Unit %d is available\n", u); - else fprintf (st, "Unit %d is offline\n", u); - return SCPE_OK; } -if (uptr->cpkt) { - fprintf (st, "Unit %d current ", u); - rq_show_pkt (st, cp, uptr->cpkt); - if (pkt = uptr->pktq) { - do { fprintf (st, "Unit %d queued ", u); - rq_show_pkt (st, cp, pkt); } - while (pkt = cp->pak[pkt].link); } } -else fprintf (st, "Unit %d queues are empty\n", u); -return SCPE_OK; -} - -t_stat rq_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -MSC *cp = rq_ctxmap[uptr->cnum]; -DEVICE *dptr = rq_devmap[uptr->cnum]; -int32 i, pkt; - -if (cp->csta != CST_UP) { - fprintf (st, "Controller is not initialized\n"); - return SCPE_OK; } -if (val & RQ_SH_RI) { - if (cp->pip) fprintf (st, "Polling in progress, host timer = %d\n", cp->hat); - else fprintf (st, "Host timer = %d\n", cp->hat); - fprintf (st, "Command "); - rq_show_ring (st, &cp->cq); - fprintf (st, "Response "); - rq_show_ring (st, &cp->rq); - } -if (val & RQ_SH_FR) { - if (pkt = cp->freq) { - for (i = 0; pkt != 0; i++, pkt = cp->pak[pkt].link) { - if (i == 0) fprintf (st, "Free queue = %d", pkt); - else if ((i % 16) == 0) fprintf (st, ",\n %d", pkt); - else fprintf (st, ", %d", pkt); } - fprintf (st, "\n"); } - else fprintf (st, "Free queue is empty\n"); - } -if (val & RQ_SH_RS) { - if (pkt = cp->rspq) { - do { fprintf (st, "Response "); - rq_show_pkt (st, cp, pkt); } - while (pkt = cp->pak[pkt].link); } - else fprintf (st, "Response queue is empty\n"); - } -if (val & RQ_SH_UN) { - for (i = 0; i < RQ_NUMDR; i++) - rq_show_unitq (st, dptr->units + i, 0, desc); - } -return SCPE_OK; -} diff --git a/PDP11/pdp11_rx.c b/PDP11/pdp11_rx.c deleted file mode 100644 index ea10d132..00000000 --- a/PDP11/pdp11_rx.c +++ /dev/null @@ -1,483 +0,0 @@ -/* pdp11_rx.c: RX11/RX01 floppy disk simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - rx RX11/RX01 floppy disk - - 12-Oct-02 RMS Added autoconfigure support - 08-Oct-02 RMS Added variable address support to bootstrap - Added vector change/display support - Revised state machine based on RX211 - New data structures - Fixed reset of disabled device - 26-Jan-02 RMS Revised bootstrap to conform to M9312 - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Converted FLG to array - 07-Sep-01 RMS Revised device disable and interrupt mechanisms - 17-Jul-01 RMS Fixed warning from VC++ 6.0 - 26-Apr-01 RMS Added device enable/disable support - 13-Apr-01 RMS Revised for register arrays - 15-Feb-01 RMS Corrected bootstrap string - 14-Apr-99 RMS Changed t_addr to unsigned - - An RX01 diskette consists of 77 tracks, each with 26 sectors of 128B. - Tracks are numbered 0-76, sectors 1-26. -*/ - -#include "pdp11_defs.h" - -#define RX_NUMTR 77 /* tracks/disk */ -#define RX_M_TRACK 0377 -#define RX_NUMSC 26 /* sectors/track */ -#define RX_M_SECTOR 0177 -#define RX_NUMBY 128 /* bytes/sector */ -#define RX_SIZE (RX_NUMTR * RX_NUMSC * RX_NUMBY) /* bytes/disk */ -#define RX_NUMDR 2 /* drives/controller */ -#define RX_M_NUMDR 01 -#define UNIT_V_WLK (UNIT_V_UF) /* write locked */ -#define UNIT_WLK (1u << UNIT_V_UF) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -#define IDLE 0 /* idle state */ -#define RWDS 1 /* rw, sect next */ -#define RWDT 2 /* rw, track next */ -#define RWXFR 3 /* rw, transfer */ -#define FILL 4 /* fill buffer */ -#define EMPTY 5 /* empty buffer */ -#define CMD_COMPLETE 6 /* set done next */ -#define INIT_COMPLETE 7 /* init compl next */ - -#define RXCS_V_FUNC 1 /* function */ -#define RXCS_M_FUNC 7 -#define RXCS_FILL 0 /* fill buffer */ -#define RXCS_EMPTY 1 /* empty buffer */ -#define RXCS_WRITE 2 /* write sector */ -#define RXCS_READ 3 /* read sector */ -#define RXCS_RXES 5 /* read status */ -#define RXCS_WRDEL 6 /* write del data */ -#define RXCS_ECODE 7 /* read error code */ -#define RXCS_V_DRV 4 /* drive select */ -#define RXCS_V_DONE 5 /* done */ -#define RXCS_V_IE 6 /* intr enable */ -#define RXCS_V_TR 7 /* xfer request */ -#define RXCS_V_INIT 14 /* init */ -#define RXCS_V_ERR 15 /* error */ -#define RXCS_FUNC (RXCS_M_FUNC << RXCS_V_FUNC) -#define RXCS_DRV (1u << RXCS_V_DRV) -#define RXCS_DONE (1u << RXCS_V_DONE) -#define RXCS_IE (1u << RXCS_V_IE) -#define RXCS_TR (1u << RXCS_V_TR) -#define RXCS_INIT (1u << RXCS_V_INIT) -#define RXCS_ERR (1u << RXCS_V_ERR) -#define RXCS_ROUT (RXCS_ERR+RXCS_TR+RXCS_IE+RXCS_DONE) -#define RXCS_IMP (RXCS_ROUT+RXCS_DRV+RXCS_FUNC) -#define RXCS_RW (RXCS_IE) /* read/write */ -#define RXCS_GETFNC(x) (((x) >> RXCS_V_FUNC) & RXCS_M_FUNC) - -#define RXES_CRC 0001 /* CRC error */ -#define RXES_PAR 0002 /* parity error */ -#define RXES_ID 0004 /* init done */ -#define RXES_WLK 0010 /* write protect */ -#define RXES_DD 0100 /* deleted data */ -#define RXES_DRDY 0200 /* drive ready */ - -#define TRACK u3 /* current track */ -#define CALC_DA(t,s) (((t) * RX_NUMSC) + ((s) - 1)) * RX_NUMBY - -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -int32 rx_csr = 0; /* control/status */ -int32 rx_dbr = 0; /* data buffer */ -int32 rx_esr = 0; /* error status */ -int32 rx_ecode = 0; /* error code */ -int32 rx_track = 0; /* desired track */ -int32 rx_sector = 0; /* desired sector */ -int32 rx_state = IDLE; /* controller state */ -int32 rx_stopioe = 1; /* stop on error */ -int32 rx_cwait = 100; /* command time */ -int32 rx_swait = 10; /* seek, per track */ -int32 rx_xwait = 1; /* tr set time */ -uint8 rx_buf[RX_NUMBY] = { 0 }; /* sector buffer */ -static int32 bptr = 0; /* buffer pointer */ -int32 rx_enb = 1; /* device enable */ - -DEVICE rx_dev; -t_stat rx_rd (int32 *data, int32 PA, int32 access); -t_stat rx_wr (int32 data, int32 PA, int32 access); -t_stat rx_svc (UNIT *uptr); -t_stat rx_reset (DEVICE *dptr); -t_stat rx_boot (int32 unitno, DEVICE *dptr); -void rx_done (int esr_flags, int new_ecode); - -/* RX11 data structures - - rx_dev RX device descriptor - rx_unit RX unit list - rx_reg RX register list - rx_mod RX modifier list -*/ - -DIB rx_dib = { IOBA_RX, IOLN_RX, &rx_rd, &rx_wr, - 1, IVCL (RX), VEC_RX, { NULL } }; - -UNIT rx_unit[] = { - { UDATA (&rx_svc, - UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, RX_SIZE) }, - { UDATA (&rx_svc, - UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, RX_SIZE) } }; - -REG rx_reg[] = { - { ORDATA (RXCS, rx_csr, 16) }, - { ORDATA (RXDB, rx_dbr, 8) }, - { ORDATA (RXES, rx_esr, 8) }, - { ORDATA (RXERR, rx_ecode, 8) }, - { ORDATA (RXTA, rx_track, 8) }, - { ORDATA (RXSA, rx_sector, 8) }, - { DRDATA (STAPTR, rx_state, 3), REG_RO }, - { DRDATA (BUFPTR, bptr, 7) }, - { FLDATA (INT, IREQ (RX), INT_V_RX) }, - { FLDATA (ERR, rx_csr, RXCS_V_ERR) }, - { FLDATA (TR, rx_csr, RXCS_V_TR) }, - { FLDATA (IE, rx_csr, RXCS_V_IE) }, - { FLDATA (DONE, rx_csr, RXCS_V_DONE) }, - { DRDATA (CTIME, rx_cwait, 24), PV_LEFT }, - { DRDATA (STIME, rx_swait, 24), PV_LEFT }, - { DRDATA (XTIME, rx_xwait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, rx_stopioe, 0) }, - { BRDATA (SBUF, rx_buf, 8, 8, RX_NUMBY) }, - { ORDATA (DEVADDR, rx_dib.ba, 32), REG_HRO }, - { ORDATA (DEVVEC, rx_dib.vec, 16), REG_HRO }, - { NULL } }; - -MTAB rx_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "AUTOCONFIGURE", - &set_addr_flt, NULL, NULL }, - { 0 } }; - -DEVICE rx_dev = { - "RX", rx_unit, rx_reg, rx_mod, - RX_NUMDR, 8, 20, 1, 8, 8, - NULL, NULL, &rx_reset, - &rx_boot, NULL, NULL, - &rx_dib, DEV_FLTA | DEV_DISABLE | DEV_UBUS | DEV_QBUS }; - -/* I/O dispatch routine, I/O addresses 17777170 - 17777172 - - 17777170 floppy CSR - 17777172 floppy data register -*/ - -t_stat rx_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 1) { /* decode PA<1> */ -case 0: /* RXCS */ - rx_csr = rx_csr & RXCS_IMP; /* clear junk */ - *data = rx_csr & RXCS_ROUT; - break; -case 1: /* RXDB */ - if ((rx_state == EMPTY) && (rx_csr & RXCS_TR)) {/* empty? */ - sim_activate (&rx_unit[0], rx_xwait); - rx_csr = rx_csr & ~RXCS_TR; } /* clear xfer */ - *data = rx_dbr; /* return data */ - break; } /* end switch PA */ -return SCPE_OK; -} - -t_stat rx_wr (int32 data, int32 PA, int32 access) -{ -int32 drv; - -switch ((PA >> 1) & 1) { /* decode PA<1> */ - -/* Writing RXCS, three cases: - 1. Writing INIT, reset device - 2. Idle and writing new function - - clear error, done, transfer ready, int req - - save int enable, function, drive - - start new function - 3. Otherwise, write IE and update interrupts -*/ - -case 0: /* RXCS */ - rx_csr = rx_csr & RXCS_IMP; /* clear junk */ - if (access == WRITEB) data = (PA & 1)? /* write byte? */ - (rx_csr & 0377) | (data << 8): (rx_csr & ~0377) | data; - if (data & RXCS_INIT) { /* initialize? */ - rx_reset (&rx_dev); /* reset device */ - return SCPE_OK; } /* end if init */ - if ((data & CSR_GO) && (rx_state == IDLE)) { /* new function? */ - rx_csr = data & (RXCS_IE + RXCS_DRV + RXCS_FUNC); - drv = ((rx_csr & RXCS_DRV)? 1: 0); /* reselect drive */ - bptr = 0; /* clear buf pointer */ - switch (RXCS_GETFNC (data)) { /* case on func */ - case RXCS_FILL: - rx_state = FILL; /* state = fill */ - rx_csr = rx_csr | RXCS_TR; /* xfer is ready */ - break; - case RXCS_EMPTY: - rx_state = EMPTY; /* state = empty */ - sim_activate (&rx_unit[drv], rx_xwait); - break; - case RXCS_READ: case RXCS_WRITE: case RXCS_WRDEL: - rx_state = RWDS; /* state = get sector */ - rx_csr = rx_csr | RXCS_TR; /* xfer is ready */ - rx_esr = rx_esr & RXES_ID; /* clear errors */ - break; - default: - rx_state = CMD_COMPLETE; /* state = cmd compl */ - sim_activate (&rx_unit[drv], rx_cwait); - break; } /* end switch func */ - return SCPE_OK; } /* end if GO */ - if ((data & RXCS_IE) == 0) CLR_INT (RX); - else if ((rx_csr & (RXCS_DONE + RXCS_IE)) == RXCS_DONE) - SET_INT (RX); - rx_csr = (rx_csr & ~RXCS_RW) | (data & RXCS_RW); - break; /* end case RXCS */ - -/* Accessing RXDB, two cases: - 1. Write idle, write - 2. Write not idle and TR set, state dependent -*/ - -case 1: /* RXDB */ - if ((PA & 1) || ((rx_state != IDLE) && ((rx_csr & RXCS_TR) == 0))) - return SCPE_OK; /* if ~IDLE, need tr */ - rx_dbr = data & 0377; /* save data */ - if ((rx_state != IDLE) && (rx_state != EMPTY)) { - drv = ((rx_csr & RXCS_DRV)? 1: 0); /* select drive */ - sim_activate (&rx_unit[drv], rx_xwait); /* sched event */ - rx_csr = rx_csr & ~RXCS_TR; } /* clear xfer */ - break; /* end case RXDB */ - } /* end switch PA */ -return SCPE_OK; -} - -/* Unit service; the action to be taken depends on the transfer state: - - IDLE Should never get here - RWDS Save sector, set TR, set RWDT - RWDT Save track, set RWXFR - RWXFR Read/write buffer - FILL copy ir to rx_buf[bptr], advance ptr - if bptr > max, finish command, else set tr - EMPTY if bptr > max, finish command, else - copy rx_buf[bptr] to ir, advance ptr, set tr - CMD_COMPLETE copy requested data to ir, finish command - INIT_COMPLETE read drive 0, track 1, sector 1 to buffer, finish command - - For RWDT and CMD_COMPLETE, the input argument is the selected drive; - otherwise, it is drive 0. -*/ - -t_stat rx_svc (UNIT *uptr) -{ -int32 i, func; -uint32 da; - -func = RXCS_GETFNC (rx_csr); /* get function */ -switch (rx_state) { /* case on state */ - -case IDLE: /* idle */ - return SCPE_IERR; /* done */ - -case EMPTY: /* empty buffer */ - if (bptr >= RX_NUMBY) rx_done (0, 0); /* done all? */ - else { - rx_dbr = rx_buf[bptr]; /* get next */ - bptr = bptr + 1; - rx_csr = rx_csr | RXCS_TR; } /* set xfer */ - break; - -case FILL: /* fill buffer */ - rx_buf[bptr] = rx_dbr; /* write next */ - bptr = bptr + 1; - if (bptr < RX_NUMBY) rx_csr = rx_csr | RXCS_TR; /* if more, set xfer */ - else rx_done (0, 0); /* else done */ - break; - -case RWDS: /* wait for sector */ - rx_sector = rx_dbr & RX_M_SECTOR; /* save sector */ - rx_csr = rx_csr | RXCS_TR; /* set xfer */ - rx_state = RWDT; /* advance state */ - return SCPE_OK; -case RWDT: /* wait for track */ - rx_track = rx_dbr & RX_M_TRACK; /* save track */ - rx_state = RWXFR; - sim_activate (uptr, /* sched done */ - rx_swait * abs (rx_track - uptr->TRACK)); - return SCPE_OK; -case RWXFR: - if ((uptr->flags & UNIT_BUF) == 0) { /* not buffered? */ - rx_done (0, 0110); /* done, error */ - return IORETURN (rx_stopioe, SCPE_UNATT); } - if (rx_track >= RX_NUMTR) { /* bad track? */ - rx_done (0, 0040); /* done, error */ - break; } - uptr->TRACK = rx_track; /* now on track */ - if ((rx_sector == 0) || (rx_sector > RX_NUMSC)) { /* bad sect? */ - rx_done (0, 0070); /* done, error */ - break; } - da = CALC_DA (rx_track, rx_sector); /* get disk address */ - if (func == RXCS_WRDEL) rx_esr = rx_esr | RXES_DD; /* del data? */ - if (func == RXCS_READ) { /* read? */ - for (i = 0; i < RX_NUMBY; i++) - rx_buf[i] = *(((int8 *) uptr->filebuf) + da + i); } - else { - if (uptr->flags & UNIT_WPRT) { /* write and locked? */ - rx_done (RXES_WLK, 0100); /* done, error */ - break; } - for (i = 0; i < RX_NUMBY; i++) /* write */ - *(((int8 *) uptr->filebuf) + da + i) = rx_buf[i]; - da = da + RX_NUMBY; - if (da > uptr->hwmark) uptr->hwmark = da; } - rx_done (0, 0); /* done */ - break; - -case CMD_COMPLETE: /* command complete */ - if (func == RXCS_ECODE) { /* read ecode? */ - rx_dbr = rx_ecode; /* set dbr */ - rx_done (0, -1); } /* don't update */ - else rx_done (0, 0); - break; - -case INIT_COMPLETE: /* init complete */ - rx_unit[0].TRACK = 1; /* drive 0 to trk 1 */ - rx_unit[1].TRACK = 0; /* drive 1 to trk 0 */ - if ((rx_unit[0].flags & UNIT_BUF) == 0) { /* not buffered? */ - rx_done (RXES_ID, 0010); /* init done, error */ - break; } - da = CALC_DA (1, 1); /* track 1, sector 1 */ - for (i = 0; i < RX_NUMBY; i++) /* read sector */ - rx_buf[i] = *(((int8 *) uptr->filebuf) + da + i); - rx_done (RXES_ID, 0); /* set done */ - if ((rx_unit[1].flags & UNIT_ATT) == 0) rx_ecode = 0020; - break; } /* end case state */ -return SCPE_OK; -} - -/* Command complete. Set done and put final value in interface register, - request interrupt if needed, return to IDLE state. -*/ - -void rx_done (int32 esr_flags, int32 new_ecode) -{ -int32 drv = (rx_csr & RXCS_DRV)? 1: 0; - -rx_state = IDLE; /* now idle */ -rx_csr = rx_csr | RXCS_DONE; /* set done */ -if (rx_csr & RXCS_IE) SET_INT (RX); /* if ie, intr */ -rx_esr = (rx_esr | esr_flags) & ~RXES_DRDY; -if (rx_unit[drv].flags & UNIT_ATT) - rx_esr = rx_esr | RXES_DRDY; -if (new_ecode > 0) rx_csr = rx_csr | RXCS_ERR; /* test for error */ -if (new_ecode < 0) return; /* don't update? */ -rx_ecode = new_ecode; /* update ecode */ -rx_dbr = rx_esr; /* update RXDB */ -return; -} - -/* Device initialization. The RX is one of the few devices that schedules - an I/O transfer as part of its initialization. -*/ - -t_stat rx_reset (DEVICE *dptr) -{ -rx_csr = rx_dbr = 0; /* clear regs */ -rx_esr = rx_ecode = 0; /* clear error */ -rx_track = rx_sector = 0; /* clear addr */ -rx_state = IDLE; /* ctrl idle */ -CLR_INT (RX); /* clear int req */ -sim_cancel (&rx_unit[1]); /* cancel drive 1 */ -if (dptr->flags & DEV_DIS) sim_cancel (&rx_unit[0]); /* disabled? */ -else if (rx_unit[0].flags & UNIT_BUF) { /* attached? */ - rx_state = INIT_COMPLETE; /* yes, sched init */ - sim_activate (&rx_unit[0], rx_swait * abs (1 - rx_unit[0].TRACK)); } -else rx_done (0, 0010); /* no, error */ -return auto_config (0, 0); /* run autoconfig */ -} - -/* Device bootstrap */ - -#define BOOT_START 02000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 026) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 042130, /* "XD" */ - 0012706, BOOT_START, /* MOV #boot_start, SP */ - 0012700, 0000000, /* MOV #unit, R0 ; unit number */ - 0010003, /* MOV R0, R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0012701, 0177170, /* MOV #RXCS, R1 ; csr */ - 0032711, 0000040, /* BITB #40, (R1) ; ready? */ - 0001775, /* BEQ .-4 */ - 0052703, 0000007, /* BIS #READ+GO, R3 */ - 0010311, /* MOV R3, (R1) ; read & go */ - 0105711, /* TSTB (R1) ; xfr ready? */ - 0100376, /* BPL .-2 */ - 0012761, 0000001, 0000002, /* MOV #1, 2(R1) ; sector */ - 0105711, /* TSTB (R1) ; xfr ready? */ - 0100376, /* BPL .-2 */ - 0012761, 0000001, 0000002, /* MOV #1, 2(R1) ; track */ - 0005003, /* CLR R3 */ - 0032711, 0000040, /* BITB #40, (R1) ; ready? */ - 0001775, /* BEQ .-4 */ - 0012711, 0000003, /* MOV #EMPTY+GO, (R1) ; empty & go */ - 0105711, /* TSTB (R1) ; xfr, done? */ - 0001776, /* BEQ .-2 */ - 0100003, /* BPL .+010 */ - 0116123, 0000002, /* MOVB 2(R1), (R3)+ ; move byte */ - 0000772, /* BR .-012 */ - 0005002, /* CLR R2 */ - 0005003, /* CLR R3 */ - 0012704, BOOT_START+020, /* MOV #START+20, R4 */ - 0005005, /* CLR R5 */ - 0005007 /* CLR R7 */ -}; - -t_stat rx_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; -extern uint16 *M; - -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & RX_M_NUMDR; -M[BOOT_CSR >> 1] = rx_dib.ba & DMASK; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} diff --git a/PDP11/pdp11_ry.c b/PDP11/pdp11_ry.c deleted file mode 100644 index 1a17cd9b..00000000 --- a/PDP11/pdp11_ry.c +++ /dev/null @@ -1,632 +0,0 @@ -/* pdp11_ry.c: RY11/RX02 floppy disk simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - ry RY11/RX02 floppy disk - - 19-May-03 RMS Revised for new conditional compilation scheme - 25-Apr-03 RMS Revised for extended file support - 14-Mar-03 RMS Fixed variable size interaction with save/restore - 03-Mar-03 RMS Fixed autosizing - 12-Oct-02 RMS Added autoconfigure support - - An RX02 diskette consists of 77 tracks, each with 26 sectors of 256B. - Tracks are numbered 0-76, sectors 1-26. -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#include "pdp10_defs.h" -extern int32 int_req; -extern int32 int_vec[32]; - -#elif defined (VM_VAX) /* VAX version */ -#error "RX211 not supported on VAX!" - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#endif - -#define RX_NUMTR 77 /* tracks/disk */ -#define RX_M_TRACK 0377 -#define RX_NUMSC 26 /* sectors/track */ -#define RX_M_SECTOR 0177 -#define RX_NUMBY 128 -#define RX_SIZE (RX_NUMTR * RX_NUMSC * RX_NUMBY) -#define RY_NUMBY 256 /* bytes/sector */ -#define RY_SIZE (RX_NUMTR * RX_NUMSC * RY_NUMBY) -#define RX_NUMDR 2 /* drives/controller */ -#define RX_M_NUMDR 01 -#define UNIT_V_WLK (UNIT_V_UF) /* write locked */ -#define UNIT_V_DEN (UNIT_V_UF + 1) /* double density */ -#define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize */ -#define UNIT_WLK (1u << UNIT_V_WLK) -#define UNIT_DEN (1u << UNIT_V_DEN) -#define UNIT_AUTO (1u << UNIT_V_AUTO) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -#define IDLE 0 /* idle state */ -#define RWDS 1 /* rw, sect next */ -#define RWDT 2 /* rw, track next */ -#define RWXFR 3 /* rw, transfer */ -#define FEWC 4 /* fill empty, wc next */ -#define FEBA 5 /* fill empty, ba next */ -#define FEXFR 6 /* fill empty, transfer */ -#define SDCNF 7 /* set dens, conf next */ -#define SDXFR 8 /* set dens, transfer */ -#define ESBA 9 /* ext sta, ba next */ -#define ESXFR 10 /* ext sta, transfer */ -#define CMD_COMPLETE 11 /* set done next */ -#define INIT_COMPLETE 12 /* init compl next */ - -#define RYCS_V_FUNC 1 /* function */ -#define RYCS_M_FUNC 7 -#define RYCS_FILL 0 /* fill buffer */ -#define RYCS_EMPTY 1 /* empty buffer */ -#define RYCS_WRITE 2 /* write sector */ -#define RYCS_READ 3 /* read sector */ -#define RYCS_SDEN 4 /* set density */ -#define RYCS_RYES 5 /* read status */ -#define RYCS_WRDEL 6 /* write del data */ -#define RYCS_ESTAT 7 /* read ext status */ -#define RYCS_V_DRV 4 /* drive select */ -#define RYCS_V_DONE 5 /* done */ -#define RYCS_V_IE 6 /* int enable */ -#define RYCS_V_TR 7 /* xfer request */ -#define RYCS_V_DEN 8 /* density select */ -#define RYCS_V_RY 11 /* RX02 flag */ -#define RYCS_V_UAE 12 /* addr ext */ -#define RYCS_M_UAE 03 -#define RYCS_V_INIT 14 /* init */ -#define RYCS_V_ERR 15 /* error */ -#define RYCS_FUNC (RYCS_M_FUNC << RYCS_V_FUNC) -#define RYCS_DRV (1u << RYCS_V_DRV) -#define RYCS_DONE (1u << RYCS_V_DONE) -#define RYCS_IE (1u << RYCS_V_IE) -#define RYCS_TR (1u << RYCS_V_TR) -#define RYCS_DEN (1u << RYCS_V_DEN) -#define RYCS_RY (1u << RYCS_V_RY) -#define RYCS_UAE (RYCS_M_UAE << RYCS_V_UAE) -#define RYCS_INIT (1u << RYCS_V_INIT) -#define RYCS_ERR (1u << RYCS_V_ERR) -#define RYCS_IMP (RYCS_ERR+RYCS_UAE+RYCS_DEN+RYCS_TR+RYCS_IE+\ - RYCS_DONE+RYCS_DRV+RYCS_FUNC) -#define RYCS_RW (RYCS_UAE+RYCS_DEN+RYCS_IE+RYCS_DRV+RYCS_FUNC) -#define RYCS_GETFNC(x) (((x) >> RYCS_V_FUNC) & RYCS_M_FUNC) -#define RYCS_GETUAE(x) (((x) >> RYCS_V_UAE) & RYCS_M_UAE) - -#define RYES_CRC 00001 /* CRC error NI */ -#define RYES_ID 00004 /* init done */ -#define RYES_ACLO 00010 /* ACLO NI */ -#define RYES_DERR 00020 /* density err */ -#define RYES_DDEN 00040 /* drive density */ -#define RYES_DD 00100 /* deleted data */ -#define RYES_DRDY 00200 /* drive ready */ -#define RYES_USEL 00400 /* unit selected */ -#define RYES_WCO 02000 /* wc overflow */ -#define RYES_NXM 04000 /* nxm */ -#define RYES_ERR (RYES_NXM|RYES_WCO|RYES_DERR|RYES_ACLO|RYES_CRC) - -#define TRACK u3 /* current track */ -#define CALC_DA(t,s,b) (((t) * RX_NUMSC) + ((s) - 1)) * b - -int32 ry_csr = 0; /* control/status */ -int32 ry_dbr = 0; /* data buffer */ -int32 ry_esr = 0; /* error status */ -int32 ry_ecode = 0; /* error code */ -int32 ry_track = 0; /* desired track */ -int32 ry_sector = 0; /* desired sector */ -int32 ry_ba = 0; /* bus addr */ -int32 ry_wc = 0; /* word count */ -int32 ry_state = IDLE; /* controller state */ -int32 ry_stopioe = 1; /* stop on error */ -int32 ry_cwait = 100; /* command time */ -int32 ry_swait = 10; /* seek, per track */ -int32 ry_xwait = 1; /* tr set time */ -uint8 rx2xb[RY_NUMBY] = { 0 }; /* sector buffer */ -int32 ry_enb = 0; /* device enable */ - -DEVICE ry_dev; -t_stat ry_rd (int32 *data, int32 PA, int32 access); -t_stat ry_wr (int32 data, int32 PA, int32 access); -t_stat ry_svc (UNIT *uptr); -t_stat ry_reset (DEVICE *dptr); -t_stat ry_boot (int32 unitno, DEVICE *dptr); -void ry_done (int esr_flags, int new_ecode); -t_stat ry_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat ry_attach (UNIT *uptr, char *cptr); - -/* RY11 data structures - - ry_dev RY device descriptor - ry_unit RY unit list - ry_reg RY register list - ry_mod RY modifier list -*/ - -DIB ry_dib = { IOBA_RY, IOLN_RY, &ry_rd, &ry_wr, - 1, IVCL (RY), VEC_RY, { NULL } }; - -UNIT ry_unit[] = { - { UDATA (&ry_svc, UNIT_DEN+ - UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, RY_SIZE) }, - { UDATA (&ry_svc, UNIT_DEN+ - UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, RY_SIZE) } }; - -REG ry_reg[] = { - { ORDATA (RYCS, ry_csr, 16) }, - { ORDATA (RYBA, ry_ba, 16) }, - { ORDATA (RYWC, ry_wc, 8) }, - { ORDATA (RYDB, ry_dbr, 16) }, - { ORDATA (RYES, ry_esr, 12) }, - { ORDATA (RYERR, ry_ecode, 8) }, - { ORDATA (RYTA, ry_track, 8) }, - { ORDATA (RYSA, ry_sector, 8) }, - { DRDATA (STAPTR, ry_state, 4), REG_RO }, - { FLDATA (INT, IREQ (RY), INT_V_RY) }, - { FLDATA (ERR, ry_csr, RYCS_V_ERR) }, - { FLDATA (TR, ry_csr, RYCS_V_TR) }, - { FLDATA (IE, ry_csr, RYCS_V_IE) }, - { FLDATA (DONE, ry_csr, RYCS_V_DONE) }, - { DRDATA (CTIME, ry_cwait, 24), PV_LEFT }, - { DRDATA (STIME, ry_swait, 24), PV_LEFT }, - { DRDATA (XTIME, ry_xwait, 24), PV_LEFT }, - { BRDATA (SBUF, rx2xb, 8, 8, RY_NUMBY) }, - { FLDATA (STOP_IOE, ry_stopioe, 0) }, - { URDATA (CAPAC, ry_unit[0].capac, 10, T_ADDR_W, 0, - RX_NUMDR, REG_HRO | PV_LEFT) }, - { ORDATA (DEVADDR, ry_dib.ba, 32), REG_HRO }, - { ORDATA (DEVVEC, ry_dib.vec, 16), REG_HRO }, - { NULL } }; - -MTAB ry_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { (UNIT_DEN+UNIT_ATT), UNIT_ATT, "single density", NULL, NULL }, - { (UNIT_DEN+UNIT_ATT), (UNIT_DEN+UNIT_ATT), "double density", NULL, NULL }, - { (UNIT_AUTO+UNIT_DEN+UNIT_ATT), 0, "single density", NULL, NULL }, - { (UNIT_AUTO+UNIT_DEN+UNIT_ATT), UNIT_DEN, "double density", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_DEN), 0, NULL, "SINGLE", &ry_set_size }, - { (UNIT_AUTO+UNIT_DEN), UNIT_DEN, NULL, "DOUBLE", &ry_set_size }, - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, -#if defined (VM_PDP11) - { MTAB_XTD | MTAB_VDV, 0, NULL, "AUTOCONFIGURE", - &set_addr_flt, NULL, NULL }, -#endif - { 0 } }; - -DEVICE ry_dev = { - "RY", ry_unit, ry_reg, ry_mod, - RX_NUMDR, 8, 20, 1, 8, 8, - NULL, NULL, &ry_reset, - &ry_boot, &ry_attach, NULL, - &ry_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS }; - -/* I/O dispatch routine, I/O addresses 17777170 - 17777172 - - 17777170 floppy CSR - 17777172 floppy data register -*/ - -t_stat ry_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 1) { /* decode PA<1> */ -case 0: /* RYCS */ - ry_csr = (ry_csr & RYCS_IMP) | RYCS_RY; /* clear junk */ - *data = ry_csr; - break; -case 1: /* RYDB */ - *data = ry_dbr; /* return data */ - break; } /* end switch PA */ -return SCPE_OK; -} - -t_stat ry_wr (int32 data, int32 PA, int32 access) -{ -int32 drv; - -switch ((PA >> 1) & 1) { /* decode PA<1> */ - -/* Writing RYCS, three cases: - 1. Writing INIT, reset device - 2. Idle and writing new function - - clear error, done, transfer ready, int req - - save int enable, function, drive - - start new function - 3. Otherwise, write IE and update interrupts -*/ - -case 0: /* RYCS */ - ry_csr = (ry_csr & RYCS_IMP) | RYCS_RY; /* clear junk */ - if (access == WRITEB) data = (PA & 1)? /* write byte? */ - (ry_csr & 0377) | (data << 8): (ry_csr & ~0377) | data; - if (data & RYCS_INIT) { /* initialize? */ - ry_reset (&ry_dev); /* reset device */ - return SCPE_OK; } /* end if init */ - if ((data & CSR_GO) && (ry_state == IDLE)) { /* new function? */ - ry_csr = (data & RYCS_RW) | RYCS_RY; - drv = ((ry_csr & RYCS_DRV)? 1: 0); /* reselect drv */ - switch (RYCS_GETFNC (data)) { - case RYCS_FILL: case RYCS_EMPTY: - ry_state = FEWC; /* state = get wc */ - ry_csr = ry_csr | RYCS_TR; /* xfer is ready */ - break; - case RYCS_SDEN: - ry_state = SDCNF; /* state = get conf */ - ry_csr = ry_csr | RYCS_TR; /* xfer is ready */ - break; - case RYCS_ESTAT: - ry_state = ESBA; /* state = get ba */ - ry_csr = ry_csr | RYCS_TR; /* xfer is ready */ - break; - case RYCS_READ: case RYCS_WRITE: case RYCS_WRDEL: - ry_state = RWDS; /* state = get sector */ - ry_csr = ry_csr | RYCS_TR; /* xfer is ready */ - ry_esr = ry_esr & RYES_ID; /* clear errors */ - ry_ecode = 0; - break; - default: - ry_state = CMD_COMPLETE; /* state = cmd compl */ - sim_activate (&ry_unit[drv], ry_cwait); - break; } /* end switch func */ - return SCPE_OK; } /* end if GO */ - if ((data & RYCS_IE) == 0) CLR_INT (RY); - else if ((ry_csr & (RYCS_DONE + RYCS_IE)) == RYCS_DONE) - SET_INT (RY); - ry_csr = (ry_csr & ~RYCS_RW) | (data & RYCS_RW); - break; /* end case RYCS */ - -/* Accessing RYDB, two cases: - 1. Write idle, write - 2. Write not idle and TR set, state dependent -*/ - -case 1: /* RYDB */ - if ((PA & 1) || ((ry_state != IDLE) && ((ry_csr & RYCS_TR) == 0))) - return SCPE_OK; /* if ~IDLE, need tr */ - ry_dbr = data; /* save data */ - if (ry_state != IDLE) { - drv = ((ry_csr & RYCS_DRV)? 1: 0); /* select drv */ - sim_activate (&ry_unit[drv], ry_xwait); /* sched event */ - ry_csr = ry_csr & ~RYCS_TR; } /* clear xfer */ - break; /* end case RYDB */ - } /* end switch PA */ -return SCPE_OK; -} - -/* Unit service; the action to be taken depends on the transfer state: - - IDLE Should never get here - FEWC Save word count, set TR, set FEBA - FEBA Save bus address, set FEXFR - FEXFR Fill/empty buffer - RWDS Save sector, set TR, set RWDT - RWDT Save track, set RWXFR - RWXFR Read/write buffer - SDCNF Check confirmation, set SDXFR - SDXFR Erase disk - CMD_COMPLETE copy requested data to ir, finish command - INIT_COMPLETE read drive 0, track 1, sector 1 to buffer, finish command -*/ - -t_stat ry_svc (UNIT *uptr) -{ -int32 i, t, func, bps; -static uint8 estat[8]; -uint32 ba, da; - -func = RYCS_GETFNC (ry_csr); /* get function */ -bps = (ry_csr & RYCS_DEN)? RY_NUMBY: RX_NUMBY; /* get sector size */ -ba = (RYCS_GETUAE (ry_csr) << 16) | ry_ba; /* get mem addr */ -switch (ry_state) { /* case on state */ - -case IDLE: /* idle */ - return SCPE_IERR; -case FEWC: /* word count */ - ry_wc = ry_dbr & 0377; /* save WC */ - ry_csr = ry_csr | RYCS_TR; /* set TR */ - ry_state = FEBA; /* next state */ - return SCPE_OK; -case FEBA: /* buffer address */ - ry_ba = ry_dbr; /* save buf addr */ - ry_state = FEXFR; /* next state */ - sim_activate (uptr, ry_cwait); /* schedule xfer */ - return SCPE_OK; -case FEXFR: /* transfer */ - if ((ry_wc << 1) > bps) { /* wc too big? */ - ry_done (RYES_WCO, 0230); /* error */ - break; } - if (func == RYCS_FILL) { /* fill? read */ - for (i = 0; i < RY_NUMBY; i++) rx2xb[i] = 0; - t = Map_ReadB (ba, ry_wc << 1, rx2xb, MAP); } - else t = Map_WriteB (ba, ry_wc << 1, rx2xb, MAP); - ry_wc = t >> 1; /* adjust wc */ - ry_done (t? RYES_NXM: 0, 0); /* done */ - break; - -case RWDS: /* wait for sector */ - ry_sector = ry_dbr & RX_M_SECTOR; /* save sector */ - ry_csr = ry_csr | RYCS_TR; /* set xfer */ - ry_state = RWDT; /* advance state */ - return SCPE_OK; -case RWDT: /* wait for track */ - ry_track = ry_dbr & RX_M_TRACK; /* save track */ - ry_state = RWXFR; /* next state */ - sim_activate (uptr, /* sched xfer */ - ry_swait * abs (ry_track - uptr->TRACK)); - return SCPE_OK; -case RWXFR: /* read/write */ - if ((uptr->flags & UNIT_BUF) == 0) { /* not buffered? */ - ry_done (0, 0110); /* done, error */ - return IORETURN (ry_stopioe, SCPE_UNATT); } - if (ry_track >= RX_NUMTR) { /* bad track? */ - ry_done (0, 0040); /* done, error */ - break; } - uptr->TRACK = ry_track; /* now on track */ - if ((ry_sector == 0) || (ry_sector > RX_NUMSC)) { /* bad sect? */ - ry_done (0, 0070); /* done, error */ - break; } - if (((uptr->flags & UNIT_DEN) != 0) ^ - ((ry_csr & RYCS_DEN) != 0)) { /* densities agree? */ - ry_done (RYES_DERR, 0240); /* no, error */ - break; } - da = CALC_DA (ry_track, ry_sector, bps); /* get disk address */ - if (func == RYCS_WRDEL) ry_esr = ry_esr | RYES_DD; /* del data? */ - if (func == RYCS_READ) { /* read? */ - for (i = 0; i < bps; i++) - rx2xb[i] = *(((int8 *) uptr->filebuf) + da + i); } - else { if (uptr->flags & UNIT_WPRT) { /* write and locked? */ - ry_done (0, 0100); /* done, error */ - break; } - for (i = 0; i < bps; i++) /* write */ - *(((int8 *) uptr->filebuf) + da + i) = rx2xb[i]; - da = da + bps; - if (da > uptr->hwmark) uptr->hwmark = da; } - ry_done (0, 0); /* done */ - break; - -case SDCNF: /* confirm set density */ - if ((ry_dbr & 0377) != 0111) { /* confirmed? */ - ry_done (0, 0250); /* no, error */ - break; } - ry_state = SDXFR; /* next state */ - sim_activate (uptr, ry_cwait * 100); /* schedule operation */ - break; -case SDXFR: /* erase disk */ - for (i = 0; i < (int32) uptr->capac; i++) - *(((int8 *) uptr->filebuf) + i) = 0; - uptr->hwmark = uptr->capac; - if (ry_csr & RYCS_DEN) uptr->flags = uptr->flags | UNIT_DEN; - else uptr->flags = uptr->flags & ~UNIT_DEN; - ry_done (0, 0); - break; - -case ESBA: - ry_ba = ry_dbr; /* save WC */ - ry_state = ESXFR; /* next state */ - sim_activate (uptr, ry_cwait); /* schedule xfer */ - return SCPE_OK; -case ESXFR: - estat[0] = ry_ecode; /* fill 8B status */ - estat[1] = ry_wc; - estat[2] = ry_unit[0].TRACK; - estat[3] = ry_unit[1].TRACK; - estat[4] = ry_track; - estat[5] = ry_sector; - estat[6] = ((ry_csr & RYCS_DRV)? 0200: 0) | - ((ry_unit[1].flags & UNIT_DEN)? 0100: 0) | - ((uptr->flags & UNIT_ATT)? 0040: 0) | - ((ry_unit[0].flags & UNIT_DEN)? 0020: 0) | - ((ry_csr & RYCS_DEN)? 0001: 0); - estat[7] = uptr->TRACK; - t = Map_WriteB (ba, 8, estat, MAP); /* DMA to memory */ - ry_done (t? RYES_NXM: 0, 0); /* done */ - break; - -case CMD_COMPLETE: /* command complete */ - ry_done (0, 0); - break; - -case INIT_COMPLETE: /* init complete */ - ry_unit[0].TRACK = 1; /* drive 0 to trk 1 */ - ry_unit[1].TRACK = 0; /* drive 1 to trk 0 */ - if ((uptr->flags & UNIT_BUF) == 0) { /* not buffered? */ - ry_done (RYES_ID, 0010); /* init done, error */ - break; } - da = CALC_DA (1, 1, bps); /* track 1, sector 1 */ - for (i = 0; i < bps; i++) /* read sector */ - rx2xb[i] = *(((int8 *) uptr->filebuf) + da + i); - ry_done (RYES_ID, 0); /* set done */ - if ((ry_unit[1].flags & UNIT_ATT) == 0) ry_ecode = 0020; - break; } /* end case state */ - -return SCPE_OK; -} - -/* Command complete. Set done and put final value in interface register, - request interrupt if needed, return to IDLE state. -*/ - -void ry_done (int32 esr_flags, int32 new_ecode) -{ -int32 drv = (ry_csr & RYCS_DRV)? 1: 0; - -ry_state = IDLE; /* now idle */ -ry_csr = ry_csr | RYCS_DONE; /* set done */ -if (ry_csr & CSR_IE) SET_INT (RY); /* if ie, intr */ -ry_esr = (ry_esr | esr_flags) & ~(RYES_USEL|RYES_DDEN|RYES_DRDY); -if (drv) ry_esr = ry_esr | RYES_USEL; /* updates RYES */ -if (ry_unit[drv].flags & UNIT_ATT) { - ry_esr = ry_esr | RYES_DRDY; - if (ry_unit[drv].flags & UNIT_DEN) - ry_esr = ry_esr | RYES_DDEN; } -if ((new_ecode > 0) || (ry_esr & RYES_ERR)) /* test for error */ - ry_csr = ry_csr | RYCS_ERR; -ry_ecode = new_ecode; /* update ecode */ -ry_dbr = ry_esr; /* update RYDB */ -return; -} - -/* Device initialization. The RY is one of the few devices that schedules - an I/O transfer as part of its initialization. -*/ - -t_stat ry_reset (DEVICE *dptr) -{ -ry_csr = ry_dbr = 0; /* clear registers */ -ry_esr = ry_ecode = 0; /* clear error */ -ry_ba = ry_wc = 0; /* clear wc, ba */ -ry_track = ry_sector = 0; /* clear trk, sector */ -ry_state = IDLE; /* ctrl idle */ -CLR_INT (RY); /* clear int req */ -sim_cancel (&ry_unit[1]); /* cancel drive 1 */ -if (dptr->flags & UNIT_DIS) sim_cancel (&ry_unit[0]); /* disabled? */ -else if (ry_unit[0].flags & UNIT_BUF) { /* attached? */ - ry_state = INIT_COMPLETE; /* yes, sched init */ - sim_activate (&ry_unit[0], ry_swait * abs (1 - ry_unit[0].TRACK)); } -else ry_done (RYES_ID, 0010); /* no, error */ -return auto_config (0, 0); /* run autoconfig */ -} - -/* Attach routine */ - -t_stat ry_attach (UNIT *uptr, char *cptr) -{ -uint32 sz; - -if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) { - if (sz > RX_SIZE) uptr->flags = uptr->flags | UNIT_DEN; - else uptr->flags = uptr->flags & ~UNIT_DEN; } -uptr->capac = (uptr->flags & UNIT_DEN)? RY_SIZE: RX_SIZE; -return attach_unit (uptr, cptr); -} - -/* Set size routine */ - -t_stat ry_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = val? RY_SIZE: RX_SIZE; -return SCPE_OK; -} - -/* Device bootstrap */ - -#if defined (VM_PDP11) - -#define BOOT_START 02000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 026) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 042131, /* "YD" */ - 0012706, BOOT_START, /* MOV #boot_start, SP */ - 0012700, 0000000, /* MOV #unit, R0 ; unit number */ - 0010003, /* MOV R0, R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0012701, 0177170, /* MOV #RYCS, R1 ; csr */ - 0005002, /* CLR R2 ; ba */ - 0005004, /* CLR R4 ; density */ - 0012705, 0000001, /* MOV #1, R5 ; sector */ - 0005104, /* DN: COM R4 ; compl dens */ - 0042704, 0177377, /* BIC #177377, R4 ; clr rest */ - 0032711, 0000040, /* RD: BIT #40, (R1) ; ready? */ - 0001775, /* BEQ .-4 */ - 0012746, 0000007, /* MOV #READ+GO, -(SP) */ - 0050416, /* BIS R4, (SP) ; or density */ - 0012611, /* MOV (SP)+, (R1) ; read & go */ - 0105711, /* TSTB (R1) ; xfr ready? */ - 0100376, /* BPL .-2 */ - 0010561, 0000002, /* MOV R5, 2(R1) ; sector */ - 0105711, /* TSTB (R1) ; xfr ready? */ - 0100376, /* BPL .-2 */ - 0012761, 0000001, 0000002, /* MOV #1, 2(R1) ; track */ - 0032711, 0000040, /* BIT #40, (R1) ; ready? */ - 0001775, /* BEQ .-4 */ - 0005711, /* TST (R1) ; error? */ - 0100003, /* BEQ OK */ - 0005704, /* TST R4 ; single? */ - 0001346, /* BNE DN ; no, try again */ - 0000000, /* HALT ; dead */ - 0012746, 0000003, /* OK: MOV #EMPTY+GO, -(SP); empty & go */ - 0050416, /* BIS R4, (SP) ; or density */ - 0012611, /* MOV (SP)+, (R1) ; read & go */ - 0105711, /* TSTB (R1) ; xfr, done? */ - 0001776, /* BPL .-2 */ - 0012746, 0000100, /* MOV #100, -(SP) ; assume sd */ - 0005704, /* TST R4 ; test dd */ - 0001401, /* BEQ .+4 */ - 0006316, /* ASL (SP) ; dd, double */ - 0011661, 0000002, /* MOV (SP), 2(R1) ; wc */ - 0105711, /* TSTB (R1) ; xfr, done? */ - 0001776, /* BPL .-2 */ - 0010261, 0000002, /* MOV R2, 2(R1) ; ba */ - 0032711, 0000040, /* BIT #40, (R1) ; ready? */ - 0001775, /* BEQ .-4 */ - 0061602, /* ADD (SP), R2 ; cvt wd to byte */ - 0062602, /* ADD (SP)+, R2 ; adv buf addr */ - 0122525, /* CMPB (R5)+, (R5)+ ; sect += 2 */ - 0020527, 0000007, /* CMP R5, #7 ; end? */ - 0101716, /* BLOS RD ; read next */ - 0005002, /* CLR R2 */ - 0005003, /* CLR R3 */ - 0012704, BOOT_START+020, /* MOV #START+20, R4 */ - 0005005, /* CLR R5 */ - 0005007 /* CLR R7 */ -}; - -t_stat ry_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; -extern uint16 *M; - -if ((ry_unit[unitno & RX_M_NUMDR].flags & UNIT_DEN) == 0) - return SCPE_NOFNC; -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & RX_M_NUMDR; -M[BOOT_CSR >> 1] = ry_dib.ba & DMASK; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} - -#else - -t_stat ry_boot (int32 unitno, DEVICE *dptr) -{ -return SCPE_NOFNC; -} - -#endif diff --git a/PDP11/pdp11_stddev.c b/PDP11/pdp11_stddev.c deleted file mode 100644 index f9c4b24d..00000000 --- a/PDP11/pdp11_stddev.c +++ /dev/null @@ -1,409 +0,0 @@ -/* pdp11_stddev.c: PDP-11 standard I/O devices simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - tti,tto DL11 terminal input/output - clk KW11L line frequency clock - - 25-Apr-03 RMS Revised for extended file support - 01-Mar-03 RMS Added SET/SHOW CLOCK FREQ, SET TTI CTRL-C - 22-Nov-02 RMS Changed terminal default to 7B for UNIX - 01-Nov-02 RMS Added 7B/8B support to terminal - 29-Sep-02 RMS Added vector display support - Split out paper tape - Split DL11 dibs - 30-May-02 RMS Widened POS to 32b - 26-Jan-02 RMS Revised for multiple timers - 09-Jan-02 RMS Fixed bugs in KW11L (found by John Dundas) - 06-Jan-02 RMS Split I/O address routines, revised enable/disable support - 29-Nov-01 RMS Added read only unit support - 09-Nov-01 RMS Added RQDX3 support - 07-Oct-01 RMS Upgraded clock to full KW11L for RSTS/E autoconfigure - 07-Sep-01 RMS Moved function prototypes, revised interrupt mechanism - 17-Jul-01 RMS Moved function prototype - 04-Jul-01 RMS Added DZ11 support - 05-Mar-01 RMS Added clock calibration support - 30-Oct-00 RMS Standardized register order - 25-Jun-98 RMS Fixed bugs in paper tape error handling -*/ - -#include "pdp11_defs.h" - -#define TTICSR_IMP (CSR_DONE + CSR_IE) /* terminal input */ -#define TTICSR_RW (CSR_IE) -#define TTOCSR_IMP (CSR_DONE + CSR_IE) /* terminal output */ -#define TTOCSR_RW (CSR_IE) -#define CLKCSR_IMP (CSR_DONE + CSR_IE) /* real-time clock */ -#define CLKCSR_RW (CSR_IE) -#define CLK_DELAY 8000 - -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_8B (1 << UNIT_V_8B) - -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -int32 tti_csr = 0; /* control/status */ -int32 tto_csr = 0; /* control/status */ -int32 clk_csr = 0; /* control/status */ -int32 clk_tps = 60; /* ticks/second */ -int32 tmxr_poll = CLK_DELAY; /* term mux poll */ -int32 tmr_poll = CLK_DELAY; /* timer poll */ - -t_stat tti_rd (int32 *data, int32 PA, int32 access); -t_stat tti_wr (int32 data, int32 PA, int32 access); -t_stat tti_svc (UNIT *uptr); -t_stat tti_reset (DEVICE *dptr); -t_stat tto_rd (int32 *data, int32 PA, int32 access); -t_stat tto_wr (int32 data, int32 PA, int32 access); -t_stat tto_svc (UNIT *uptr); -t_stat tto_reset (DEVICE *dptr); -t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat clk_rd (int32 *data, int32 PA, int32 access); -t_stat clk_wr (int32 data, int32 PA, int32 access); -t_stat clk_svc (UNIT *uptr); -t_stat clk_reset (DEVICE *dptr); -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc); - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit descriptor - tti_reg TTI register list -*/ - -DIB tti_dib = { IOBA_TTI, IOLN_TTI, &tti_rd, &tti_wr, - 1, IVCL (TTI), VEC_TTI, { NULL } }; - -UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }; - -REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, 8) }, - { ORDATA (CSR, tti_csr, 16) }, - { FLDATA (INT, IREQ (TTI), INT_V_TTI) }, - { FLDATA (ERR, tti_csr, CSR_V_ERR) }, - { FLDATA (DONE, tti_csr, CSR_V_DONE) }, - { FLDATA (IE, tti_csr, CSR_V_IE) }, - { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB tti_mod[] = { - { UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, - { MTAB_XTD|MTAB_VDV|MTAB_VUN, 0, NULL, "CTRL-C", - &tti_set_ctrlc, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; - -DEVICE tti_dev = { - "TTI", &tti_unit, tti_reg, tti_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tti_reset, - NULL, NULL, NULL, - &tti_dib, DEV_UBUS | DEV_QBUS }; - -/* TTO data structures - - tto_dev TTO device descriptor - tto_unit TTO unit descriptor - tto_reg TTO register list -*/ - -DIB tto_dib = { IOBA_TTO, IOLN_TTO, &tto_rd, &tto_wr, - 1, IVCL (TTO), VEC_TTO, { NULL } }; - -UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT }; - -REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, 8) }, - { ORDATA (CSR, tto_csr, 16) }, - { FLDATA (INT, IREQ (TTO), INT_V_TTO) }, - { FLDATA (ERR, tto_csr, CSR_V_ERR) }, - { FLDATA (DONE, tto_csr, CSR_V_DONE) }, - { FLDATA (IE, tto_csr, CSR_V_IE) }, - { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -MTAB tto_mod[] = { - { UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, - { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; - -DEVICE tto_dev = { - "TTO", &tto_unit, tto_reg, tto_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto_reset, - NULL, NULL, NULL, - &tto_dib, DEV_UBUS | DEV_QBUS }; - -/* CLK data structures - - clk_dev CLK device descriptor - clk_unit CLK unit descriptor - clk_reg CLK register list -*/ - -DIB clk_dib = { IOBA_CLK, IOLN_CLK, &clk_rd, &clk_wr, - 1, IVCL (CLK), VEC_CLK, { NULL } }; - -UNIT clk_unit = { UDATA (&clk_svc, 0, 0), 8000 }; - -REG clk_reg[] = { - { ORDATA (CSR, clk_csr, 16) }, - { FLDATA (INT, IREQ (CLK), INT_V_CLK) }, - { FLDATA (DONE, clk_csr, CSR_V_DONE) }, - { FLDATA (IE, clk_csr, CSR_V_IE) }, - { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO }, - { NULL } }; - -MTAB clk_mod[] = { - { MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL, - NULL, &clk_show_freq, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; - -DEVICE clk_dev = { - "CLK", &clk_unit, clk_reg, clk_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &clk_reset, - NULL, NULL, NULL, - &clk_dib, DEV_UBUS | DEV_QBUS }; - -/* Terminal input address routines */ - -t_stat tti_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 00: /* tti csr */ - *data = tti_csr & TTICSR_IMP; - return SCPE_OK; -case 01: /* tti buf */ - tti_csr = tti_csr & ~CSR_DONE; - CLR_INT (TTI); - *data = tti_unit.buf & 0377; - return SCPE_OK; } /* end switch PA */ -return SCPE_NXM; -} - -t_stat tti_wr (int32 data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 00: /* tti csr */ - if (PA & 1) return SCPE_OK; - if ((data & CSR_IE) == 0) CLR_INT (TTI); - else if ((tti_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) - SET_INT (TTI); - tti_csr = (tti_csr & ~TTICSR_RW) | (data & TTICSR_RW); - return SCPE_OK; -case 01: /* tti buf */ - return SCPE_OK; } /* end switch PA */ -return SCPE_NXM; -} - -/* Terminal input service */ - -t_stat tti_svc (UNIT *uptr) -{ -int32 c; - -sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ -if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -if (c & SCPE_BREAK) tti_unit.buf = 0; /* break? */ -else tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177); -tti_unit.pos = tti_unit.pos + 1; -tti_csr = tti_csr | CSR_DONE; -if (tti_csr & CSR_IE) SET_INT (TTI); -return SCPE_OK; -} - -/* Terminal input reset */ - -t_stat tti_reset (DEVICE *dptr) -{ -tti_unit.buf = 0; -tti_csr = 0; -CLR_INT (TTI); -sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ -return SCPE_OK; -} - -/* Set control-C */ - -t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -uptr->buf = 003; -uptr->pos = uptr->pos + 1; -tti_csr = tti_csr | CSR_DONE; -if (tti_csr & CSR_IE) SET_INT (TTI); -return SCPE_OK; -} - -/* Terminal output address routines */ - -t_stat tto_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 00: /* tto csr */ - *data = tto_csr & TTOCSR_IMP; - return SCPE_OK; -case 01: /* tto buf */ - *data = tto_unit.buf; - return SCPE_OK; } /* end switch PA */ -return SCPE_NXM; -} - -t_stat tto_wr (int32 data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 00: /* tto csr */ - if (PA & 1) return SCPE_OK; - if ((data & CSR_IE) == 0) CLR_INT (TTO); - else if ((tto_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) - SET_INT (TTO); - tto_csr = (tto_csr & ~TTOCSR_RW) | (data & TTOCSR_RW); - return SCPE_OK; -case 01: /* tto buf */ - if ((PA & 1) == 0) tto_unit.buf = data & 0377; - tto_csr = tto_csr & ~CSR_DONE; - CLR_INT (TTO); - sim_activate (&tto_unit, tto_unit.wait); - return SCPE_OK; } /* end switch PA */ -return SCPE_NXM; -} - -/* Terminal output service */ - -t_stat tto_svc (UNIT *uptr) -{ -int32 c; -t_stat r; - -tto_csr = tto_csr | CSR_DONE; -if (tto_csr & CSR_IE) SET_INT (TTO); -c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); -if ((r = sim_putchar (c)) != SCPE_OK) return r; -tto_unit.pos = tto_unit.pos + 1; -return SCPE_OK; -} - -/* Terminal output reset */ - -t_stat tto_reset (DEVICE *dptr) -{ -tto_unit.buf = 0; -tto_csr = CSR_DONE; -CLR_INT (TTO); -sim_cancel (&tto_unit); /* deactivate unit */ -return SCPE_OK; -} - -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -tti_unit.flags = (tti_unit.flags & ~UNIT_8B) | val; -tto_unit.flags = (tto_unit.flags & ~UNIT_8B) | val; -return SCPE_OK; -} - -/* Clock I/O address routines */ - -t_stat clk_rd (int32 *data, int32 PA, int32 access) -{ -*data = clk_csr & CLKCSR_IMP; -return SCPE_OK; -} - -t_stat clk_wr (int32 data, int32 PA, int32 access) -{ -if (PA & 1) return SCPE_OK; -clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW); -if ((data & CSR_DONE) == 0) clk_csr = clk_csr & ~CSR_DONE; -if (((clk_csr & CSR_IE) == 0) || /* unless IE+DONE */ - ((clk_csr & CSR_DONE) == 0)) CLR_INT (CLK); /* clr intr */ -return SCPE_OK; -} - -/* Clock service */ - -t_stat clk_svc (UNIT *uptr) -{ -int32 t; - -clk_csr = clk_csr | CSR_DONE; /* set done */ -if (clk_csr & CSR_IE) SET_INT (CLK); -t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */ -sim_activate (&clk_unit, t); /* reactivate unit */ -tmr_poll = t; /* set timer poll */ -tmxr_poll = t; /* set mux poll */ -return SCPE_OK; -} - -/* Clock reset */ - -t_stat clk_reset (DEVICE *dptr) -{ -clk_csr = CSR_DONE; /* set done */ -CLR_INT (CLK); -sim_activate (&clk_unit, clk_unit.wait); /* activate unit */ -tmr_poll = clk_unit.wait; /* set timer poll */ -tmxr_poll = clk_unit.wait; /* set mux poll */ -return SCPE_OK; -} - -/* Set frequency */ - -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; -clk_tps = val; -return SCPE_OK; -} - -/* Show frequency */ - -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, (clk_tps == 50)? "50Hz": "60Hz"); -return SCPE_OK; -} diff --git a/PDP11/pdp11_sys.c b/PDP11/pdp11_sys.c deleted file mode 100644 index 2a140b75..00000000 --- a/PDP11/pdp11_sys.c +++ /dev/null @@ -1,902 +0,0 @@ -/* pdp11_sys.c: PDP-11 simulator interface - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 06-May-03 RMS Added support for second DEQNA/DELQA - 09-Jan-03 RMS Added DELUA support - 17-Oct-02 RMS Fixed bugs in branch, SOB address parsing - 09-Oct-02 RMS Added DELQA support - 12-Sep-02 RMS Added TMSCP, KW11P, RX211 support, RAD50 examine - 29-Nov-01 RMS Added read only unit support - 17-Sep-01 RMS Removed multiconsole support - 26-Aug-01 RMS Added DZ11 - 20-Aug-01 RMS Updated bad block inquiry - 17-Jul-01 RMS Fixed warning from VC++ 6.0 - 27-May-01 RMS Added multiconsole support - 05-Apr-01 RMS Added support for TS11/TSV05 - 14-Mar-01 RMS Revised load/dump interface (again) - 11-Feb-01 RMS Added DECtape support - 30-Oct-00 RMS Added support for examine to file - 14-Apr-99 RMS Changed t_addr to unsigned - 09-Nov-98 RMS Fixed assignments of ROR/ROL (John Wilson) - 27-Oct-98 RMS V2.4 load interface - 08-Oct-98 RMS Fixed bug in bad block routine - 30-Mar-98 RMS Fixed bug in floating point display - 12-Nov-97 RMS Added bad block table routine -*/ - -#include "pdp11_defs.h" -#include - -extern DEVICE cpu_dev; -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE tti_dev, tto_dev; -extern DEVICE lpt_dev; -extern DEVICE clk_dev, pclk_dev; -extern DEVICE dz_dev; -extern DEVICE rk_dev, rl_dev; -extern DEVICE hk_dev; -extern DEVICE rx_dev, ry_dev; -extern DEVICE rp_dev; -extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev; -extern DEVICE dt_dev; -extern DEVICE tm_dev, ts_dev; -extern DEVICE tq_dev; -extern DEVICE xq_dev, xqb_dev; -extern DEVICE xu_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern uint16 *M; -extern int32 saved_PC; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "PDP-11"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { - &cpu_dev, - &ptr_dev, - &ptp_dev, - &tti_dev, - &tto_dev, - &lpt_dev, - &clk_dev, - &pclk_dev, - &dz_dev, - &rk_dev, - &rl_dev, - &hk_dev, - &rx_dev, - &ry_dev, - &rp_dev, - &rq_dev, - &rqb_dev, - &rqc_dev, - &rqd_dev, - &dt_dev, - &tm_dev, - &ts_dev, - &tq_dev, - &xq_dev, - &xqb_dev, - &xu_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Red stack trap", - "Odd address trap", - "Memory management trap", - "Non-existent memory trap", - "Parity error trap", - "Privilege trap", - "Illegal instruction trap", - "BPT trap", - "IOT trap", - "EMT trap", - "TRAP trap", - "Trace trap", - "Yellow stack trap", - "Powerfail trap", - "Floating point exception", - "HALT instruction", - "Breakpoint", - "Wait state", - "Trap vector fetch abort", - "Trap stack push abort", - "RQDX3 consistency error", - "Sanity timer expired" }; - -/* Binary loader. - - Loader format consists of blocks, optionally preceded, separated, and - followed by zeroes. Each block consists of: - - 001 --- - xxx | - lo_count | - hi_count | - lo_origin > count bytes - hi_origin | - data byte | - : | - data byte --- - checksum - - If the byte count is exactly six, the block is the last on the tape, and - there is no checksum. If the origin is not 000001, then the origin is - the PC at which to start the program. -*/ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 csum, count, state, i; -uint32 origin; - -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; -state = csum = 0; -while ((i = getc (fileref)) != EOF) { - csum = csum + i; /* add into chksum */ - switch (state) { - case 0: /* leader */ - if (i == 1) state = 1; - else csum = 0; - break; - case 1: /* ignore after 001 */ - state = 2; - break; - case 2: /* low count */ - count = i; - state = 3; - break; - case 3: /* high count */ - count = (i << 8) | count; - state = 4; - break; - case 4: /* low origin */ - origin = i; - state = 5; - break; - case 5: /* high origin */ - origin = (i << 8) | origin; - if (count == 6) { - if (origin != 1) saved_PC = origin & 0177776; - return SCPE_OK; } - count = count - 6; - state = 6; - break; - case 6: /* data */ - if (origin >= MEMSIZE) return SCPE_NXM; - M[origin >> 1] = (origin & 1)? - (M[origin >> 1] & 0377) | (i << 8): - (M[origin >> 1] & 0177400) | i; - origin = origin + 1; - count = count - 1; - state = state + (count == 0); - break; - case 7: /* checksum */ - if (csum & 0377) return SCPE_CSUM; - csum = state = 0; - break; } /* end switch */ - } /* end while */ -return SCPE_FMT; /* unexpected eof */ -} - -/* Factory bad block table creation routine - - This routine writes a DEC standard 044 compliant bad block table on the - last track of the specified unit. The bad block table consists of 10 - repetitions of the same table, formatted as follows: - - words 0-1 pack id number - words 2-3 cylinder/sector/surface specifications - : - words n-n+1 end of table (-1,-1) - - Inputs: - uptr = pointer to unit - sec = number of sectors per surface - wds = number of words per sector - Outputs: - sta = status code -*/ - -t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds) -{ -int32 i, da; -int16 *buf; - -if ((sec < 2) || (wds < 16)) return SCPE_ARG; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; -if (uptr->flags & UNIT_RO) return SCPE_RO; -if (!get_yn ("Create bad block table on last track? [N]", FALSE)) return SCPE_OK; -da = (uptr->capac - (sec * wds)) * sizeof (int16); -if (fseek (uptr->fileref, da, SEEK_SET)) return SCPE_IOERR; -if ((buf = malloc (wds * sizeof (int16))) == NULL) return SCPE_MEM; -buf[0] = buf[1] = 012345u; -buf[2] = buf[3] = 0; -for (i = 4; i < wds; i++) buf[i] = 0177777u; -for (i = 0; (i < sec) && (i < 10); i++) - fxwrite (buf, sizeof (int16), wds, uptr->fileref); -free (buf); -if (ferror (uptr->fileref)) return SCPE_IOERR; -return SCPE_OK; -} - -/* Symbol tables */ - -#define I_V_L 16 /* long mode */ -#define I_V_D 17 /* double mode */ -#define I_L (1 << I_V_L) -#define I_D (1 << I_V_D) - -/* Warning: for literals, the class number MUST equal the field width!! */ - -#define I_V_CL 18 /* class bits */ -#define I_M_CL 017 /* class mask */ -#define I_V_NPN 0 /* no operands */ -#define I_V_REG 1 /* reg */ -#define I_V_SOP 2 /* operand */ -#define I_V_3B 3 /* 3b literal */ -#define I_V_FOP 4 /* flt operand */ -#define I_V_AFOP 5 /* fac, flt operand */ -#define I_V_6B 6 /* 6b literal */ -#define I_V_BR 7 /* cond branch */ -#define I_V_8B 8 /* 8b literal */ -#define I_V_SOB 9 /* reg, disp */ -#define I_V_RSOP 10 /* reg, operand */ -#define I_V_ASOP 11 /* fac, operand */ -#define I_V_ASMD 12 /* fac, moded int op */ -#define I_V_DOP 13 /* double operand */ -#define I_V_CCC 14 /* CC clear */ -#define I_V_CCS 15 /* CC set */ -#define I_NPN (I_V_NPN << I_V_CL) -#define I_REG (I_V_REG << I_V_CL) -#define I_3B (I_V_3B << I_V_CL) -#define I_SOP (I_V_SOP << I_V_CL) -#define I_FOP (I_V_FOP << I_V_CL) -#define I_6B (I_V_6B << I_V_CL) -#define I_BR (I_V_BR << I_V_CL) -#define I_8B (I_V_8B << I_V_CL) -#define I_AFOP (I_V_AFOP << I_V_CL) -#define I_ASOP (I_V_ASOP << I_V_CL) -#define I_RSOP (I_V_RSOP << I_V_CL) -#define I_SOB (I_V_SOB << I_V_CL) -#define I_ASMD (I_V_ASMD << I_V_CL) -#define I_DOP (I_V_DOP << I_V_CL) -#define I_CCC (I_V_CCC << I_V_CL) -#define I_CCS (I_V_CCS << I_V_CL) - -static const int32 masks[] = { -0177777, 0177770, 0177700, 0177770, -0177700+I_D, 0177400+I_D, 0177700, 0177400, -0177400, 0177000, 0177000, 0177400, -0177400+I_D+I_L, 0170000, 0177777, 0177777 }; - -static const char *opcode[] = { -"HALT","WAIT","RTI","BPT", -"IOT","RESET","RTT","MFPT", -"JMP","RTS","SPL", -"NOP","CLC","CLV","CLV CLC", -"CLZ","CLZ CLC","CLZ CLV","CLZ CLV CLC", -"CLN","CLN CLC","CLN CLV","CLN CLV CLC", -"CLN CLZ","CLN CLZ CLC","CLN CLZ CLC","CCC", -"NOP","SEC","SEV","SEV SEC", -"SEZ","SEZ SEC","SEZ SEV","SEZ SEV SEC", -"SEN","SEN SEC","SEN SEV","SEN SEV SEC", -"SEN SEZ","SEN SEZ SEC","SEN SEZ SEC","SCC", -"SWAB","BR","BNE","BEQ", -"BGE","BLT","BGT","BLE", -"JSR", -"CLR","COM","INC","DEC", -"NEG","ADC","SBC","TST", -"ROR","ROL","ASR","ASL", -"MARK","MFPI","MTPI","SXT", -"CSM", "TSTSET","WRTLCK", -"MOV","CMP","BIT","BIC", -"BIS","ADD", -"MUL","DIV","ASH","ASHC", -"XOR", -"FADD","FSUB","FMUL","FDIV", -"L2DR", -"MOVC","MOVRC","MOVTC", -"LOCC","SKPC","SCANC","SPANC", -"CMPC","MATC", -"ADDN","SUBN","CMPN","CVTNL", -"CVTPN","CVTNP","ASHN","CVTLN", -"L3DR", -"ADDP","SUBP","CMPP","CVTPL", -"MULP","DIVP","ASHP","CVTLP", -"MOVCI","MOVRCI","MOVTCI", -"LOCCI","SKPCI","SCANCI","SPANCI", -"CMPCI","MATCI", -"ADDNI","SUBNI","CMPNI","CVTNLI", -"CVTPNI","CVTNPI","ASHNI","CVTLNI", -"ADDPI","SUBPI","CMPPI","CVTPLI", -"MULPI","DIVPI","ASHPI","CVTLPI", -"SOB", -"BPL","BMI","BHI","BLOS", -"BVC","BVS","BCC","BCS", -"BHIS","BLO", /* encode only */ -"EMT","TRAP", -"CLRB","COMB","INCB","DECB", -"NEGB","ADCB","SBCB","TSTB", -"RORB","ROLB","ASRB","ASLB", -"MTPS","MFPD","MTPD","MFPS", -"MOVB","CMPB","BITB","BICB", -"BISB","SUB", -"CFCC","SETF","SETI","SETD","SETL", -"LDFPS","STFPS","STST", -"CLRF","CLRD","TSTF","TSTD", -"ABSF","ABSD","NEGF","NEGD", -"MULF","MULD","MODF","MODD", -"ADDF","ADDD","LDF","LDD", -"SUBF","SUBD","CMPF","CMPD", -"STF","STD","DIVF","DIVD", -"STEXP", -"STCFI","STCDI","STCFL","STCDL", -"STCFD","STCDF", -"LDEXP", -"LDCIF","LDCID","LDCLF","LDCLD", -"LDCFD","LDCDF", -NULL }; - -static const int32 opc_val[] = { -0000000+I_NPN, 0000001+I_NPN, 0000002+I_NPN, 0000003+I_NPN, -0000004+I_NPN, 0000005+I_NPN, 0000006+I_NPN, 0000007+I_NPN, -0000100+I_SOP, 0000200+I_REG, 0000230+I_3B, -0000240+I_CCC, 0000241+I_CCC, 0000242+I_CCC, 0000243+I_NPN, -0000244+I_CCC, 0000245+I_NPN, 0000246+I_NPN, 0000247+I_NPN, -0000250+I_CCC, 0000251+I_NPN, 0000252+I_NPN, 0000253+I_NPN, -0000254+I_NPN, 0000255+I_NPN, 0000256+I_NPN, 0000257+I_CCC, -0000260+I_CCS, 0000261+I_CCS, 0000262+I_CCS, 0000263+I_NPN, -0000264+I_CCS, 0000265+I_NPN, 0000266+I_NPN, 0000267+I_NPN, -0000270+I_CCS, 0000271+I_NPN, 0000272+I_NPN, 0000273+I_NPN, -0000274+I_NPN, 0000275+I_NPN, 0000276+I_NPN, 0000277+I_CCS, -0000300+I_SOP, 0000400+I_BR, 0001000+I_BR, 0001400+I_BR, -0002000+I_BR, 0002400+I_BR, 0003000+I_BR, 0003400+I_BR, -0004000+I_RSOP, -0005000+I_SOP, 0005100+I_SOP, 0005200+I_SOP, 0005300+I_SOP, -0005400+I_SOP, 0005500+I_SOP, 0005600+I_SOP, 0005700+I_SOP, -0006000+I_SOP, 0006100+I_SOP, 0006200+I_SOP, 0006300+I_SOP, -0006400+I_6B, 0006500+I_SOP, 0006600+I_SOP, 0006700+I_SOP, -0007000+I_SOP, 0007200+I_SOP, 0007300+I_SOP, -0010000+I_DOP, 0020000+I_DOP, 0030000+I_DOP, 0040000+I_DOP, -0050000+I_DOP, 0060000+I_DOP, -0070000+I_RSOP, 0071000+I_RSOP, 0072000+I_RSOP, 0073000+I_RSOP, -0074000+I_RSOP, -0075000+I_REG, 0075010+I_REG, 0075020+I_REG, 0075030+I_REG, -0076020+I_REG, -0076030+I_NPN, 0076031+I_NPN, 0076032+I_NPN, -0076040+I_NPN, 0076041+I_NPN, 0076042+I_NPN, 0076043+I_NPN, -0076044+I_NPN, 0076045+I_NPN, -0076050+I_NPN, 0076051+I_NPN, 0076052+I_NPN, 0076053+I_NPN, -0076054+I_NPN, 0076055+I_NPN, 0076056+I_NPN, 0076057+I_NPN, -0076060+I_REG, -0076070+I_NPN, 0076071+I_NPN, 0076072+I_NPN, 0076073+I_NPN, -0076074+I_NPN, 0076075+I_NPN, 0076076+I_NPN, 0076077+I_NPN, -0076130+I_NPN, 0076131+I_NPN, 0076132+I_NPN, -0076140+I_NPN, 0076141+I_NPN, 0076142+I_NPN, 0076143+I_NPN, -0076144+I_NPN, 0076145+I_NPN, -0076150+I_NPN, 0076151+I_NPN, 0076152+I_NPN, 0076153+I_NPN, -0076154+I_NPN, 0076155+I_NPN, 0076156+I_NPN, 0076157+I_NPN, -0076170+I_NPN, 0076171+I_NPN, 0076172+I_NPN, 0076173+I_NPN, -0076174+I_NPN, 0076175+I_NPN, 0076176+I_NPN, 0076177+I_NPN, -0077000+I_SOB, -0100000+I_BR, 0100400+I_BR, 0101000+I_BR, 0101400+I_BR, -0102000+I_BR, 0102400+I_BR, 0103000+I_BR, 0103400+I_BR, -0103000+I_BR, 0103400+I_BR, -0104000+I_8B, 0104400+I_8B, -0105000+I_SOP, 0105100+I_SOP, 0105200+I_SOP, 0105300+I_SOP, -0105400+I_SOP, 0105500+I_SOP, 0105600+I_SOP, 0105700+I_SOP, -0106000+I_SOP, 0106100+I_SOP, 0106200+I_SOP, 0106300+I_SOP, -0106400+I_SOP, 0106500+I_SOP, 0106600+I_SOP, 0106700+I_SOP, -0110000+I_DOP, 0120000+I_DOP, 0130000+I_DOP, 0140000+I_DOP, -0150000+I_DOP, 0160000+I_DOP, -0170000+I_NPN, 0170001+I_NPN, 0170002+I_NPN, 0170011+I_NPN, 0170012+I_NPN, -0170100+I_SOP, 0170200+I_SOP, 0170300+I_SOP, -0170400+I_FOP, 0170400+I_FOP+I_D, 0170500+I_FOP, 0170500+I_FOP+I_D, -0170600+I_FOP, 0170600+I_FOP+I_D, 0170700+I_FOP, 0170700+I_FOP+I_D, -0171000+I_AFOP, 0171000+I_AFOP+I_D, 0171400+I_AFOP, 0171400+I_AFOP+I_D, -0172000+I_AFOP, 0172000+I_AFOP+I_D, 0172400+I_AFOP, 0172400+I_AFOP+I_D, -0173000+I_AFOP, 0173000+I_AFOP+I_D, 0173400+I_AFOP, 0173400+I_AFOP+I_D, -0174000+I_AFOP, 0174000+I_AFOP+I_D, 0174400+I_AFOP, 0174400+I_AFOP+I_D, -0175000+I_ASOP, -0175400+I_ASMD, 0175400+I_ASMD+I_D, 0175400+I_ASMD+I_L, 0175400+I_ASMD+I_D+I_L, -0176000+I_AFOP, 0176000+I_AFOP+I_D, -0176400+I_ASOP, -0177000+I_ASMD, 0177000+I_ASMD+I_D, 0177000+I_ASMD+I_L, 0177000+I_ASMD+I_D+I_L, -0177400+I_AFOP, 0177400+I_AFOP+I_D, --1 }; - -static const char *rname [] = -{ "R0", "R1", "R2", "R3", "R4", "R5", "SP", "PC" }; - -static const char *fname [] = -{ "F0", "F1", "F2", "F3", "F4", "F5", "?6", "?7" }; - -static const char r50_to_asc[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$._0123456789"; - -/* Specifier decode - - Inputs: - *of = output stream - addr = current PC - spec = specifier - nval = next word - flag = TRUE if decoding for CPU - iflag = TRUE if decoding integer instruction - Outputs: - count = -number of extra words retired -*/ - -int32 fprint_spec (FILE *of, t_addr addr, int32 spec, t_value nval, - int32 flag, int32 iflag) -{ -int32 reg, mode; -static const int32 rgwd[8] = { 0, 0, 0, 0, 0, 0, -1, -1 }; -static const int32 pcwd[8] = { 0, 0, -1, -1, 0, 0, -1, -1 }; - -reg = spec & 07; -mode = ((spec >> 3) & 07); -switch (mode) { -case 0: - if (iflag) fprintf (of, "%s", rname[reg]); - else fprintf (of, "%s", fname[reg]); - break; -case 1: - fprintf (of, "(%s)", rname[reg]); - break; -case 2: - if (reg != 7) fprintf (of, "(%s)+", rname[reg]); - else fprintf (of, "#%-o", nval); - break; -case 3: - if (reg != 7) fprintf (of, "@(%s)+", rname[reg]); - else fprintf (of, "@#%-o", nval); - break; -case 4: - fprintf (of, "-(%s)", rname[reg]); - break; -case 5: - fprintf (of, "@-(%s)", rname[reg]); - break; -case 6: - if ((reg != 7) || !flag) fprintf (of, "%-o(%s)", nval, rname[reg]); - else fprintf (of, "%-o", (nval + addr + 4) & 0177777); - break; -case 7: - if ((reg != 7) || !flag) fprintf (of, "@%-o(%s)", nval, rname[reg]); - else fprintf (of, "@%-o", (nval + addr + 4) & 0177777); - break; } /* end case */ -return ((reg == 07)? pcwd[mode]: rgwd[mode]); -} - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current PC - *val = values to decode - *uptr = pointer to unit - sw = switches - Outputs: - return = if >= 0, error code - if < 0, number of extra words retired -*/ - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, i, j, c1, c2, c3, inst, fac, srcm, srcr, dstm, dstr; -int32 l8b, brdisp, wd1, wd2; -extern int32 FPS; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -c1 = val[0] & 0177; -c2 = (val[0] >> 8) & 0177; -if (sw & SWMASK ('A')) { /* ASCII? */ - fprintf (of, (c1 < 040)? "<%03o>": "%c", c1); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* character? */ - fprintf (of, (c1 < 040)? "<%03o>": "%c", c1); - fprintf (of, (c2 < 040)? "<%03o>": "%c", c2); - return SCPE_OK; } -if (sw & SWMASK ('R')) { /* radix 50? */ - if (val[0] > 0174777) return SCPE_ARG; /* max value */ - c3 = val[0] % 050; - c2 = (val[0] / 050) % 050; - c1 = val[0] / (050 * 050); - fprintf (of, "%c%c%c", r50_to_asc[c1], - r50_to_asc[c2], r50_to_asc[c3]); - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; - -inst = val[0] | ((FPS << (I_V_L - FPS_V_L)) & I_L) | - ((FPS << (I_V_D - FPS_V_D)) & I_D); /* inst + fp mode */ -for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_CL) & I_M_CL; /* get class */ - if ((opc_val[i] & 0777777) == (inst & masks[j])) { /* match? */ - srcm = (inst >> 6) & 077; /* opr fields */ - srcr = srcm & 07; - fac = srcm & 03; - dstm = inst & 077; - dstr = dstm & 07; - l8b = inst & 0377; - -/* Instruction decode */ - - switch (j) { /* case on class */ - case I_V_NPN: case I_V_CCC: case I_V_CCS: /* no operands */ - fprintf (of, "%s", opcode[i]); - return SCPE_OK; - case I_V_REG: /* reg */ - fprintf (of, "%s %-s", opcode[i], rname[dstr]); - return SCPE_OK; - case I_V_SOP: /* sop */ - fprintf (of, "%s ", opcode[i]); - return fprint_spec (of, addr, dstm, val[1], cflag, TRUE); - case I_V_3B: /* 3b */ - fprintf (of, "%s %-o", opcode[i], dstr); - return SCPE_OK; - case I_V_FOP: /* fop */ - fprintf (of, "%s ", opcode[i]); - return fprint_spec (of, addr, dstm, val[1], cflag, FALSE); - case I_V_AFOP: /* afop */ - fprintf (of, "%s %s,", opcode[i], fname[fac]); - return fprint_spec (of, addr, dstm, val[1], cflag, FALSE); - case I_V_6B: /* 6b */ - fprintf (of, "%s %-o", opcode[i], dstm); - return SCPE_OK; - case I_V_BR: /* cond branch */ - fprintf (of, "%s ", opcode[i]); - brdisp = (l8b + l8b + ((l8b & 0200)? 0177002: 2)) & 0177777; - if (cflag) fprintf (of, "%-o", (addr + brdisp) & 0177777); - else if (brdisp < 01000) fprintf (of, ".+%-o", brdisp); - else fprintf (of, ".-%-o", 0200000 - brdisp); - return SCPE_OK; - case I_V_8B: /* 8b */ - fprintf (of, "%s %-o", opcode[i], l8b); - return SCPE_OK; - case I_V_SOB: /* sob */ - fprintf (of, "%s %s,", opcode[i], rname[srcr]); - brdisp = (dstm * 2) - 2; - if (cflag) fprintf (of, "%-o", (addr - brdisp) & 0177777); - else if (brdisp <= 0) fprintf (of, ".+%-o", -brdisp); - else fprintf (of, ".-%-o", brdisp); - return SCPE_OK; - case I_V_RSOP: /* rsop */ - fprintf (of, "%s %s,", opcode[i], rname[srcr]); - return fprint_spec (of, addr, dstm, val[1], cflag, TRUE); - case I_V_ASOP: case I_V_ASMD: /* asop, asmd */ - fprintf (of, "%s %s,", opcode[i], fname[fac]); - return fprint_spec (of, addr, dstm, val[1], cflag, TRUE); - case I_V_DOP: /* dop */ - fprintf (of, "%s ", opcode[i]); - wd1 = fprint_spec (of, addr, srcm, val[1], cflag, TRUE); - fprintf (of, ","); - wd2 = fprint_spec (of, addr - wd1 - wd1, dstm, - val[1 - wd1], cflag, TRUE); - return wd1 + wd2; } /* end case */ - } /* end if */ - } /* end for */ -return SCPE_ARG; /* no match */ -} - -#define A_PND 100 /* # seen */ -#define A_MIN 040 /* -( seen */ -#define A_PAR 020 /* (Rn) seen */ -#define A_REG 010 /* Rn seen */ -#define A_PLS 004 /* + seen */ -#define A_NUM 002 /* number seen */ -#define A_REL 001 /* relative addr seen */ - -/* Register number - - Inputs: - *cptr = pointer to input string - *strings = pointer to register names - mchar = character to match after register name - Outputs: - rnum = 0..7 if a legitimate register - < 0 if error -*/ - -int32 get_reg (char *cptr, const char *strings[], char mchar) -{ -int32 i; - -if (*(cptr + 2) != mchar) return -1; -for (i = 0; i < 8; i++) { - if (strncmp (cptr, strings[i], 2) == 0) return i; } -return -1; -} - -/* Number or memory address - - Inputs: - *cptr = pointer to input string - *dptr = pointer to output displacement - *pflag = pointer to accumulating flags - Outputs: - cptr = pointer to next character in input string - NULL if parsing error - - Flags: 0 (no result), A_NUM (number), A_REL (relative) -*/ - -char *get_addr (char *cptr, int32 *dptr, int32 *pflag) -{ -int32 val, minus; -char *tptr; - -minus = 0; - -if (*cptr == '.') { /* relative? */ - *pflag = *pflag | A_REL; - cptr++; } -if (*cptr == '+') { /* +? */ - *pflag = *pflag | A_NUM; - cptr++; } -if (*cptr == '-') { /* -? */ - *pflag = *pflag | A_NUM; - minus = 1; - cptr++; } -errno = 0; -val = strtoul (cptr, &tptr, 8); -if (cptr == tptr) { /* no number? */ - if (*pflag == (A_REL + A_NUM)) return NULL; /* .+, .-? */ - *dptr = 0; - return cptr; } -if (errno || (*pflag == A_REL)) return NULL; /* .n? */ -*dptr = (minus? -val: val) & 0177777; -*pflag = *pflag | A_NUM; -return tptr; -} - -/* Specifier decode - - Inputs: - *cptr = pointer to input string - addr = current PC - n1 = 0 if no extra word used - -1 if extra word used in prior decode - *sptr = pointer to output specifier - *dptr = pointer to output displacement - cflag = true if parsing for the CPU - iflag = true if integer specifier - Outputs: - status = = -1 extra word decoded - = 0 ok - = +1 error -*/ - -t_stat get_spec (char *cptr, t_addr addr, int32 n1, int32 *sptr, t_value *dptr, - int32 cflag, int32 iflag) -{ -int32 reg, indir, pflag, disp; - -indir = 0; /* no indirect */ -pflag = 0; - -if (*cptr == '@') { /* indirect? */ - indir = 010; - cptr++; } -if (*cptr == '#') { /* literal? */ - pflag = pflag | A_PND; - cptr++; } -if (strncmp (cptr, "-(", 2) == 0) { /* autodecrement? */ - pflag = pflag | A_MIN; - cptr++; } -else if ((cptr = get_addr (cptr, &disp, &pflag)) == NULL) return 1; -if (*cptr == '(') { /* register index? */ - pflag = pflag | A_PAR; - if ((reg = get_reg (cptr + 1, rname, ')')) < 0) return 1; - cptr = cptr + 4; - if (*cptr == '+') { /* autoincrement? */ - pflag = pflag | A_PLS; - cptr++; } } -else if ((reg = get_reg (cptr, iflag? rname: fname, 0)) >= 0) { - pflag = pflag | A_REG; - cptr = cptr + 2; } -if (*cptr != 0) return 1; /* all done? */ - -/* Specifier decode, continued */ - -switch (pflag) { /* case on syntax */ -case A_REG: /* Rn, @Rn */ - *sptr = indir + reg; - return 0; -case A_PAR: /* (Rn), @(Rn) */ - if (indir) { /* @(Rn) = @0(Rn) */ - *sptr = 070 + reg; - *dptr = 0; - return -1; } - else *sptr = 010 + reg; - return 0; -case A_PAR+A_PLS: /* (Rn)+, @(Rn)+ */ - *sptr = 020 + indir + reg; - return 0; -case A_MIN+A_PAR: /* -(Rn), @-(Rn) */ - *sptr = 040 + indir + reg; - return 0; -case A_NUM+A_PAR: /* d(Rn), @d(Rn) */ - *sptr = 060 + indir + reg; - *dptr = disp; - return -1; -case A_PND+A_REL: case A_PND+A_REL+A_NUM: /* #.+n, @#.+n */ - if (!cflag) return 1; - disp = (disp + addr) & 0177777; /* fall through */ -case A_PND+A_NUM: /* #n, @#n */ - *sptr = 027 + indir; - *dptr = disp; - return -1; -case A_REL: case A_REL+A_NUM: /* .+n, @.+n */ - *sptr = 067 + indir; - *dptr = (disp - 4 + (2 * n1)) & 0177777; - return -1; -case A_NUM: /* n, @n */ - if (cflag) { /* CPU - use rel */ - *sptr = 067 + indir; - *dptr = (disp - addr - 4 + (2 * n1)) & 0177777; } - else { if (indir) return 1; /* other - use abs */ - *sptr = 037; - *dptr = disp; } - return -1; -default: - return 1; } /* end case */ -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = > 0 error code - <= 0 -number of extra words -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 cflag, d, i, j, reg, spec, n1, n2, disp, pflag; -t_stat r; -char *tptr, gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ -if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (t_value) cptr[0]; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = ((t_value) cptr[1] << 8) + (t_value) cptr[0]; - return SCPE_OK; } -if (sw & SWMASK ('R')) return SCPE_ARG; /* radix 50 */ - -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -n1 = n2 = pflag = 0; -for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; -if (opcode[i] == NULL) return SCPE_ARG; -val[0] = opc_val[i] & 0177777; /* get value */ -j = (opc_val[i] >> I_V_CL) & I_M_CL; /* get class */ - -switch (j) { /* case on class */ -case I_V_NPN: /* no operand */ - break; -case I_V_REG: /* register */ - cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ - if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG; - val[0] = val[0] | reg; - break; -case I_V_3B: case I_V_6B: case I_V_8B: /* xb literal */ - cptr = get_glyph (cptr, gbuf, 0); /* get literal */ - d = get_uint (gbuf, 8, (1 << j) - 1, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | d; /* put in place */ - break; -case I_V_BR: /* cond br */ - cptr = get_glyph (cptr, gbuf, 0); /* get address */ - tptr = get_addr (gbuf, &disp, &pflag); /* parse */ - if ((tptr == NULL) || (*tptr != 0)) return SCPE_ARG; - if ((pflag & A_REL) == 0) { - if (cflag) disp = (disp - addr) & 0177777; - else return SCPE_ARG; } - if ((disp & 1) || (disp > 0400) && (disp < 0177402)) return SCPE_ARG; - val[0] = val[0] | (((disp - 2) >> 1) & 0377); - break; -case I_V_SOB: /* sob */ - cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ - if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG; - val[0] = val[0] | (reg << 6); - cptr = get_glyph (cptr, gbuf, 0); /* get address */ - tptr = get_addr (gbuf, &disp, &pflag); /* parse */ - if ((tptr == NULL) || (*tptr != 0)) return SCPE_ARG; - if ((pflag & A_REL) == 0) { - if (cflag) disp = (disp - addr) & 0177777; - else return SCPE_ARG; } - if ((disp & 1) || ((disp > 2) && (disp < 0177604))) return SCPE_ARG; - val[0] = val[0] | (((2 - disp) >> 1) & 077); - break; -case I_V_RSOP: /* reg, sop */ - cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ - if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG; - val[0] = val[0] | (reg << 6); /* fall through */ -case I_V_SOP: /* sop */ - cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ - if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0) - return SCPE_ARG; - val[0] = val[0] | spec; - break; -case I_V_AFOP: case I_V_ASOP: case I_V_ASMD: /* fac, (s)fop */ - cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ - if ((reg = get_reg (gbuf, fname, 0)) < 0) return SCPE_ARG; - if (reg > 3) return SCPE_ARG; - val[0] = val[0] | (reg << 6); /* fall through */ -case I_V_FOP: /* fop */ - cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ - if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, - (j == I_V_ASOP) || (j == I_V_ASMD))) > 0) return SCPE_ARG; - val[0] = val[0] | spec; - break; -case I_V_DOP: /* double op */ - cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ - if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0) - return SCPE_ARG; - val[0] = val[0] | (spec << 6); - cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ - if ((n2 = get_spec (gbuf, addr, n1, &spec, &val[1 - n1], - cflag, TRUE)) > 0) return SCPE_ARG; - val[0] = val[0] | spec; - break; -case I_V_CCC: case I_V_CCS: /* cond code oper */ - for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; - cptr = get_glyph (cptr, gbuf, 0)) { - for (i = 0; (opcode[i] != NULL) && - (strcmp (opcode[i], gbuf) != 0) ; i++) ; - if ((((opc_val[i] >> I_V_CL) & I_M_CL) != j) || - (opcode[i] == NULL)) return SCPE_ARG; - val[0] = val[0] | (opc_val[i] & 0177777); } - break; -default: - return SCPE_ARG; } -if (*cptr != 0) return SCPE_ARG; /* junk at end? */ -return n1 + n2; -} diff --git a/PDP11/pdp11_tc.c b/PDP11/pdp11_tc.c deleted file mode 100644 index 414dee28..00000000 --- a/PDP11/pdp11_tc.c +++ /dev/null @@ -1,1182 +0,0 @@ -/* pdp11_tc.c: PDP-11 DECtape simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - tc TC11/TU56 DECtape - - 25-Apr-03 RMS Revised for extended file support - 14-Mar-03 RMS Fixed variable size interaction with save/restore - 29-Sep-02 RMS Added variable address support to bootstrap - Added vector change/display support - Added 16b format support - New data structures - 30-May-02 RMS Widened POS to 32b - 26-Jan-02 RMS Revised bootstrap to conform to M9312 - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Converted POS, STATT, LASTT to arrays - 09-Nov-01 RMS Added bus map support - 15-Sep-01 RMS Integrated debug logging - 27-Sep-01 RMS Fixed interrupt after stop for RSTS/E - 07-Sep-01 RMS Revised device disable and interrupt mechanisms - 29-Aug-01 RMS Added casts to PDP-8 unpack routine - 17-Jul-01 RMS Moved function prototype - 11-May-01 RMS Fixed bug in reset - 26-Apr-01 RMS Added device enable/disable support - 18-Apr-01 RMS Changed to rewind tape before boot - 16-Mar-01 RMS Fixed bug in interrupt after stop - 15-Mar-01 RMS Added 129th word to PDP-8 format - - PDP-11 DECtapes are represented in memory by fixed length buffer of 32b words. - Three file formats are supported: - - 18b/36b 256 words per block [256 x 18b] - 16b 256 words per block [256 x 16b] - 12b 129 words per block [129 x 12b] - - When a 16b or 12b DECtape file is read in, it is converted to 18b/36b format. - - DECtape motion is measured in 3b lines. Time between lines is 33.33us. - Tape density is nominally 300 lines per inch. The format of a DECtape is - - reverse end zone 36000 lines ~ 10 feet - block 0 - : - block n - forward end zone 36000 lines ~ 10 feet - - A block consists of five 18b header words, a tape-specific number of data - words, and five 18b trailer words. All systems except the PDP-8 use a - standard block length of 256 words; the PDP-8 uses a standard block length - of 86 words (x 18b = 129 words x 12b). - - Because a DECtape file only contains data, the simulator cannot support - write timing and mark track and can only do a limited implementation - of read all and write all. Read all assumes that the tape has been - conventionally written forward: - - header word 0 0 - header word 1 block number (for forward reads) - header words 2,3 0 - header word 4 0 - : - trailer word 4 checksum - trailer words 3,2 0 - trailer word 1 block number (for reverse reads) - trailer word 0 0 - - Write all writes only the data words and dumps the interblock words in the - bit bucket. -*/ - -#include "pdp11_defs.h" - -#define DT_NUMDR 8 /* #drives */ -#define DT_M_NUMDR (DT_NUMDR - 1) -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_8FMT (UNIT_V_UF + 1) /* 12b format */ -#define UNIT_V_11FMT (UNIT_V_UF + 2) /* 16b format */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_8FMT (1 << UNIT_V_8FMT) -#define UNIT_11FMT (1 << UNIT_V_11FMT) -#define STATE u3 /* unit state */ -#define LASTT u4 /* last time update */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -/* System independent DECtape constants */ - -#define DT_EZLIN 36000 /* end zone length */ -#define DT_HTLIN 30 /* header/trailer lines */ -#define DT_BLKLN 6 /* blk no line in h/t */ -#define DT_CSMLN 24 /* checksum line in h/t */ -#define DT_HTWRD (DT_HTLIN / DT_WSIZE) /* header/trailer words */ -#define DT_BLKWD (DT_BLKLN / DT_WSIZE) /* blk no word in h/t */ -#define DT_CSMWD (DT_CSMLN / DT_WSIZE) /* checksum word in h/t */ - -/* 16b, 18b, 36b DECtape constants */ - -#define D18_WSIZE 6 /* word size in lines */ -#define D18_BSIZE 256 /* block size in 18b */ -#define D18_TSIZE 578 /* tape size */ -#define D18_LPERB (DT_HTLIN + (D18_BSIZE * DT_WSIZE) + DT_HTLIN) -#define D18_FWDEZ (DT_EZLIN + (D18_LPERB * D18_TSIZE)) -#define D18_CAPAC (D18_TSIZE * D18_BSIZE) /* tape capacity */ -#define D16_FILSIZ (D18_TSIZE * D18_BSIZE * sizeof (int16)) - -/* 12b DECtape constants */ - -#define D8_WSIZE 4 /* word size in lines */ -#define D8_BSIZE 86 /* block size in 18b */ -#define D8_TSIZE 1474 /* tape size */ -#define D8_LPERB (DT_HTLIN + (D8_BSIZE * DT_WSIZE) + DT_HTLIN) -#define D8_FWDEZ (DT_EZLIN + (D8_LPERB * D8_TSIZE)) -#define D8_CAPAC (D8_TSIZE * D8_BSIZE) /* tape capacity */ - -#define D8_NBSIZE ((D8_BSIZE * D18_WSIZE) / D8_WSIZE) -#define D8_FILSIZ (D8_NBSIZE * D8_TSIZE * sizeof (int16)) - -/* This controller */ - -#define DT_CAPAC D18_CAPAC /* default */ -#define DT_WSIZE D18_WSIZE - -/* Calculated constants, per unit */ - -#define DTU_BSIZE(u) (((u)->flags & UNIT_8FMT)? D8_BSIZE: D18_BSIZE) -#define DTU_TSIZE(u) (((u)->flags & UNIT_8FMT)? D8_TSIZE: D18_TSIZE) -#define DTU_LPERB(u) (((u)->flags & UNIT_8FMT)? D8_LPERB: D18_LPERB) -#define DTU_FWDEZ(u) (((u)->flags & UNIT_8FMT)? D8_FWDEZ: D18_FWDEZ) -#define DTU_CAPAC(u) (((u)->flags & UNIT_8FMT)? D8_CAPAC: D18_CAPAC) - -#define DT_LIN2BL(p,u) (((p) - DT_EZLIN) / DTU_LPERB (u)) -#define DT_LIN2OF(p,u) (((p) - DT_EZLIN) % DTU_LPERB (u)) -#define DT_LIN2WD(p,u) ((DT_LIN2OF (p,u) - DT_HTLIN) / DT_WSIZE) -#define DT_BLK2LN(p,u) (((p) * DTU_LPERB (u)) + DT_EZLIN) -#define DT_QREZ(u) (((u)->pos) < DT_EZLIN) -#define DT_QFEZ(u) (((u)->pos) >= ((uint32) DTU_FWDEZ (u))) -#define DT_QEZ(u) (DT_QREZ (u) || DT_QFEZ (u)) - -/* TCST - 177340 - status register */ - -#define STA_END 0100000 /* end zone */ -#define STA_PAR 0040000 /* parity err */ -#define STA_MRK 0020000 /* mark trk err */ -#define STA_ILO 0010000 /* illegal op */ -#define STA_SEL 0004000 /* select err */ -#define STA_BLKM 0002000 /* block miss err */ -#define STA_DATM 0001000 /* data miss err */ -#define STA_NXM 0000400 /* nx mem err */ -#define STA_UPS 0000200 /* up to speed */ -#define STA_V_XD 0 /* extended data */ -#define STA_M_XD 03 -#define STA_ALLERR (STA_END | STA_PAR | STA_MRK | STA_ILO | \ - STA_SEL | STA_BLKM | STA_DATM | STA_NXM ) -#define STA_RWERR (STA_END | STA_PAR | STA_MRK | \ - STA_BLKM | STA_DATM | STA_NXM ) -#define STA_RW 0000003 -#define STA_GETXD(x) (((x) >> STA_V_XD) & STA_M_XD) - -/* TCCM - 177342 - command register */ - -/* #define CSR_ERR 0100000 */ -#define CSR_MNT 0020000 /* maint (unimpl) */ -#define CSR_INH 0010000 /* delay inhibit */ -#define CSR_DIR 0004000 /* reverse */ -#define CSR_V_UNIT 8 /* unit select */ -#define CSR_M_UNIT 07 -#define CSR_UNIT (CSR_M_UNIT << CSR_V_UNIT) -/* #define CSR_DONE 0000200 */ -/* #define CSR_IE 0000100 */ -#define CSR_V_MEX 4 /* mem extension */ -#define CSR_M_MEX 03 -#define CSR_MEX (CSR_M_MEX << CSR_V_MEX) -#define CSR_V_FNC 1 /* function */ -#define CSR_M_FNC 07 -#define FNC_STOP 00 /* stop all */ -#define FNC_SRCH 01 /* search */ -#define FNC_READ 02 /* read */ -#define FNC_RALL 03 /* read all */ -#define FNC_SSEL 04 /* stop selected */ -#define FNC_WMRK 05 /* write */ -#define FNC_WRIT 06 /* write all */ -#define FNC_WALL 07 /* write timing */ -/* define CSR_GO 0000001 */ -#define CSR_RW 0117576 /* read/write */ - -#define CSR_GETUNIT(x) (((x) >> CSR_V_UNIT) & CSR_M_UNIT) -#define CSR_GETMEX(x) (((x) >> CSR_V_MEX) & CSR_M_MEX) -#define CSR_GETFNC(x) (((x) >> CSR_V_FNC) & CSR_M_FNC) -#define CSR_INCMEX(x) (((x) & ~CSR_MEX) | (((x) + (1 << CSR_V_MEX)) & CSR_MEX)) - -/* TCWC - 177344 - word count */ - -/* TCBA - 177346 - bus address */ - -/* TCDT - 177350 - data */ - -/* DECtape state */ - -#define DTS_V_MOT 3 /* motion */ -#define DTS_M_MOT 07 -#define DTS_STOP 0 /* stopped */ -#define DTS_DECF 2 /* decel, fwd */ -#define DTS_DECR 3 /* decel, rev */ -#define DTS_ACCF 4 /* accel, fwd */ -#define DTS_ACCR 5 /* accel, rev */ -#define DTS_ATSF 6 /* @speed, fwd */ -#define DTS_ATSR 7 /* @speed, rev */ -#define DTS_DIR 01 /* dir mask */ -#define DTS_V_FNC 0 /* function */ -#define DTS_M_FNC 07 -#define DTS_OFR FNC_WMRK /* "off reel" */ -#define DTS_GETMOT(x) (((x) >> DTS_V_MOT) & DTS_M_MOT) -#define DTS_GETFNC(x) (((x) >> DTS_V_FNC) & DTS_M_FNC) -#define DTS_V_2ND 6 /* next state */ -#define DTS_V_3RD (DTS_V_2ND + DTS_V_2ND) /* next next */ -#define DTS_STA(y,z) (((y) << DTS_V_MOT) | ((z) << DTS_V_FNC)) -#define DTS_SETSTA(y,z) uptr->STATE = DTS_STA (y, z) -#define DTS_SET2ND(y,z) uptr->STATE = (uptr->STATE & 077) | \ - ((DTS_STA (y, z)) << DTS_V_2ND) -#define DTS_SET3RD(y,z) uptr->STATE = (uptr->STATE & 07777) | \ - ((DTS_STA (y, z)) << DTS_V_3RD) -#define DTS_NXTSTA(x) (x >> DTS_V_2ND) - -/* Logging */ - -#define LOG_MS 001 /* move, search */ -#define LOG_RW 002 /* read, write */ -#define LOG_RA 004 /* read all */ -#define LOG_BL 010 /* block # lblk */ - -#define DT_SETDONE tccm = tccm | CSR_DONE; \ - if (tccm & CSR_IE) SET_INT (DTA) -#define DT_CLRDONE tccm = tccm & ~CSR_DONE; \ - CLR_INT (DTA) -#define ABS(x) (((x) < 0)? (-(x)): (x)) - -extern uint16 *M; /* memory */ -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -extern UNIT cpu_unit; -extern int32 sim_switches; -extern int32 cpu_log; -extern FILE *sim_log; - -int32 tcst = 0; /* status */ -int32 tccm = 0; /* command */ -int32 tcwc = 0; /* word count */ -int32 tcba = 0; /* bus address */ -int32 tcdt = 0; /* data */ -int32 dt_ctime = 100; /* fast cmd time */ -int32 dt_ltime = 12; /* interline time */ -int32 dt_actime = 54000; /* accel time */ -int32 dt_dctime = 72000; /* decel time */ -int32 dt_substate = 0; -int32 dt_logblk = 0; - -DEVICE dt_dev; -t_stat dt_rd (int32 *data, int32 PA, int32 access); -t_stat dt_wr (int32 data, int32 PA, int32 access); -t_stat dt_svc (UNIT *uptr); -t_stat dt_svcdone (UNIT *uptr); -t_stat dt_reset (DEVICE *dptr); -t_stat dt_attach (UNIT *uptr, char *cptr); -t_stat dt_detach (UNIT *uptr); -t_stat dt_boot (int32 unitno, DEVICE *dptr); -void dt_deselect (int32 oldf); -void dt_newsa (int32 newf); -void dt_newfnc (UNIT *uptr, int32 newsta); -t_bool dt_setpos (UNIT *uptr); -void dt_schedez (UNIT *uptr, int32 dir); -void dt_seterr (UNIT *uptr, int32 e); -void dt_stopunit (UNIT *uptr); -int32 dt_comobv (int32 val); -int32 dt_csum (UNIT *uptr, int32 blk); -int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos); -extern int32 sim_is_running; - -/* DT data structures - - dt_dev DT device descriptor - dt_unit DT unit list - dt_reg DT register list - dt_mod DT modifier list -*/ - -DIB dt_dib = { IOBA_TC, IOLN_TC, &dt_rd, &dt_wr, - 1, IVCL (DTA), VEC_DTA, { NULL } }; - -UNIT dt_unit[] = { - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) }, - { UDATA (&dt_svcdone, UNIT_DIS, 0) } }; - -#define DT_TIMER (DT_NUMDR) - -REG dt_reg[] = { - { ORDATA (TCST, tcst, 16) }, - { ORDATA (TCCM, tccm, 16) }, - { ORDATA (TCWC, tcwc, 16) }, - { ORDATA (TCBA, tcba, 16) }, - { ORDATA (TCDT, tcdt, 16) }, - { FLDATA (INT, IREQ (DTA), INT_V_DTA) }, - { FLDATA (ERR, tccm, CSR_V_ERR) }, - { FLDATA (DONE, tccm, CSR_V_DONE) }, - { FLDATA (IE, tccm, CSR_V_DONE) }, - { DRDATA (CTIME, dt_ctime, 31), REG_NZ }, - { DRDATA (LTIME, dt_ltime, 31), REG_NZ }, - { DRDATA (ACTIME, dt_actime, 31), REG_NZ }, - { DRDATA (DCTIME, dt_dctime, 31), REG_NZ }, - { ORDATA (SUBSTATE, dt_substate, 1) }, - { DRDATA (LBLK, dt_logblk, 12), REG_HIDDEN }, - { URDATA (POS, dt_unit[0].pos, 10, T_ADDR_W, 0, - DT_NUMDR, PV_LEFT | REG_RO) }, - { URDATA (STATT, dt_unit[0].STATE, 8, 18, 0, - DT_NUMDR, REG_RO) }, - { URDATA (LASTT, dt_unit[0].LASTT, 10, 32, 0, - DT_NUMDR, REG_HRO) }, - { ORDATA (DEVADDR, dt_dib.ba, 32), REG_HRO }, - { ORDATA (DEVVEC, dt_dib.vec, 16), REG_HRO }, - { NULL } }; - -MTAB dt_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { UNIT_8FMT + UNIT_11FMT, 0, "18b", NULL, NULL }, - { UNIT_8FMT + UNIT_11FMT, UNIT_8FMT, "12b", NULL, NULL }, - { UNIT_8FMT + UNIT_11FMT, UNIT_11FMT, "16b", NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE dt_dev = { - "TC", dt_unit, dt_reg, dt_mod, - DT_NUMDR + 1, 8, 24, 1, 8, 18, - NULL, NULL, &dt_reset, - &dt_boot, &dt_attach, &dt_detach, - &dt_dib, DEV_DISABLE | DEV_UBUS }; - -/* IO dispatch routines, I/O addresses 17777340 - 17777350 */ - -t_stat dt_rd (int32 *data, int32 PA, int32 access) -{ -int32 j, unum, mot, fnc; - -j = (PA >> 1) & 017; /* get reg offset */ -unum = CSR_GETUNIT (tccm); /* get drive */ -switch (j) { -case 000: /* TCST */ - mot = DTS_GETMOT (dt_unit[unum].STATE); /* get motion */ - if (mot >= DTS_ATSF) tcst = tcst | STA_UPS; /* set/clr speed */ - else tcst = tcst & ~STA_UPS; - *data = tcst; - break; -case 001: /* TCCM */ - if (tcst & STA_ALLERR) tccm = tccm | CSR_ERR; /* set/clr error */ - else tccm = tccm & ~CSR_ERR; - *data = tccm; - break; -case 002: /* TCWC */ - *data = tcwc; - break; -case 003: /* TCBA */ - *data = tcba; - break; -case 004: /* TCDT */ - fnc = DTS_GETFNC (dt_unit[unum].STATE); /* get function */ - if (fnc == FNC_RALL) { /* read all? */ - DT_CLRDONE; } /* clear done */ - *data = tcdt; - break; } -return SCPE_OK; -} - -t_stat dt_wr (int32 data, int32 PA, int32 access) -{ -int32 i, j, unum, old_tccm, fnc; -UNIT *uptr; - -j = (PA >> 1) & 017; /* get reg offset */ -switch (j) { -case 000: /* TCST */ - if ((access == WRITEB) && (PA & 1)) break; - tcst = (tcst & ~STA_RW) | (data & STA_RW); - break; -case 001: /* TCCM */ - old_tccm = tccm; /* save prior */ - if (access == WRITEB) data = (PA & 1)? - (tccm & 0377) | (data << 8): (tccm & ~0377) | data; - if ((data & CSR_IE) == 0) CLR_INT (DTA); - else if ((((tccm & CSR_IE) == 0) && (tccm & CSR_DONE)) || - (data & CSR_DONE)) SET_INT (DTA); - tccm = (tccm & ~CSR_RW) | (data & CSR_RW); - if ((data & CSR_GO) && (tccm & CSR_DONE)) { /* new cmd? */ - tcst = tcst & ~STA_ALLERR; /* clear errors */ - tccm = tccm & ~(CSR_ERR | CSR_DONE); /* clear done, err */ - CLR_INT (DTA); /* clear int */ - if ((old_tccm ^ tccm) & CSR_UNIT) dt_deselect (old_tccm); - unum = CSR_GETUNIT (tccm); /* get drive */ - fnc = CSR_GETFNC (tccm); /* get function */ - if (fnc == FNC_STOP) { /* stop all? */ - sim_activate (&dt_dev.units[DT_TIMER], dt_ctime); - for (i = 0; i < DT_NUMDR; i++) - dt_stopunit (dt_dev.units + i); /* stop unit */ - break; } - uptr = dt_dev.units + unum; - if (uptr->flags & UNIT_DIS) /* disabled? */ - dt_seterr (uptr, STA_SEL); /* select err */ - if ((fnc == FNC_WMRK) || /* write mark? */ - ((fnc == FNC_WALL) && (uptr->flags & UNIT_WPRT)) || - ((fnc == FNC_WRIT) && (uptr->flags & UNIT_WPRT))) - dt_seterr (uptr, STA_ILO); /* illegal op */ - if (!(tccm & CSR_ERR)) dt_newsa (tccm); } - else if ((tccm & CSR_ERR) == 0) { /* clear err? */ - tcst = tcst & ~STA_RWERR; - if (tcst & STA_ALLERR) tccm = tccm | CSR_ERR; } - break; -case 002: /* TCWC */ - tcwc = data; /* word write only! */ - break; -case 003: /* TCBA */ - tcba = data; /* word write only! */ - break; -case 004: /* TCDT */ - unum = CSR_GETUNIT (tccm); /* get drive */ - fnc = DTS_GETFNC (dt_unit[unum].STATE); /* get function */ - if (fnc == FNC_WALL) { /* write all? */ - DT_CLRDONE; } /* clear done */ - tcdt = data; /* word write only! */ - break; } -return SCPE_OK; -} - -/* Unit deselect */ - -void dt_deselect (int32 oldf) -{ -int32 old_unit = CSR_GETUNIT (oldf); -UNIT *uptr = dt_dev.units + old_unit; -int32 old_mot = DTS_GETMOT (uptr->STATE); - -if (old_mot >= DTS_ATSF) /* at speed? */ - dt_newfnc (uptr, DTS_STA (old_mot, DTS_OFR)); -else if (old_mot >= DTS_ACCF) /* accelerating? */ - DTS_SET2ND (DTS_ATSF | (old_mot & DTS_DIR), DTS_OFR); -return; } - -/* New operation - - 1. If function = stop - - if not already stopped or decelerating, schedule deceleration - - schedule command completion - 2. If change in direction, - - if not decelerating, schedule deceleration - - set accelerating (other dir) as next state - - set function as next next state - 3. If not accelerating or at speed, - - schedule acceleration - - set function as next state - 4. If not yet at speed, - - set function as next state - 5. If at speed, - - set function as current state, schedule function -*/ - -void dt_newsa (int32 newf) -{ -int32 new_unit, prev_mot, new_fnc; -int32 prev_dir, new_dir; -UNIT *uptr; - -new_unit = CSR_GETUNIT (newf); /* new, old units */ -uptr = dt_dev.units + new_unit; -if ((uptr->flags & UNIT_ATT) == 0) { /* new unit attached? */ - dt_seterr (uptr, STA_SEL); /* no, error */ - return; } -prev_mot = DTS_GETMOT (uptr->STATE); /* previous motion */ -prev_dir = prev_mot & DTS_DIR; /* previous dir */ -new_fnc = CSR_GETFNC (newf); /* new function */ -new_dir = (newf & CSR_DIR) != 0; /* new di? */ - -if (new_fnc == FNC_SSEL) { /* stop unit? */ - sim_activate (&dt_dev.units[DT_TIMER], dt_ctime); /* sched done */ - dt_stopunit (uptr); /* stop unit */ - return; } - -if (prev_mot == DTS_STOP) { /* start? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_actime); /* schedule accel */ - DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } - -if (prev_dir ^ new_dir) { /* dir chg? */ - dt_stopunit (uptr); /* stop unit */ - DTS_SET2ND (DTS_ACCF | new_dir, 0); /* next = accel */ - DTS_SET3RD (DTS_ATSF | new_dir, new_fnc); /* next next = fnc */ - return; } - -if (prev_mot < DTS_ACCF) { /* not accel/at speed? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* cancel cur */ - sim_activate (uptr, dt_actime); /* schedule accel */ - DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } - -if (prev_mot < DTS_ATSF) { /* not at speed? */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } - -dt_newfnc (uptr, DTS_STA (DTS_ATSF | new_dir, new_fnc));/* state = fnc */ -return; -} - -/* Schedule new DECtape function - - This routine is only called if - - the selected unit is attached - - the selected unit is at speed (forward or backward) - - This routine - - updates the selected unit's position - - updates the selected unit's state - - schedules the new operation -*/ - -void dt_newfnc (UNIT *uptr, int32 newsta) -{ -int32 fnc, dir, blk, unum, relpos, newpos; -uint32 oldpos; - -oldpos = uptr->pos; /* save old pos */ -if (dt_setpos (uptr)) return; /* update pos */ -uptr->STATE = newsta; /* update state */ -fnc = DTS_GETFNC (uptr->STATE); /* set variables */ -dir = DTS_GETMOT (uptr->STATE) & DTS_DIR; -unum = uptr - dt_dev.units; -if (oldpos == uptr->pos) - uptr->pos = uptr->pos + (dir? -1: 1); -blk = DT_LIN2BL (uptr->pos, uptr); - -if (dir? DT_QREZ (uptr): DT_QFEZ (uptr)) { /* wrong ez? */ - dt_seterr (uptr, STA_END); /* set ez flag, stop */ - return; } -dt_substate = 0; /* substate = normal */ -sim_cancel (uptr); /* cancel cur op */ -switch (fnc) { /* case function */ -case DTS_OFR: /* off reel */ - if (dir) newpos = -1000; /* rev? < start */ - else newpos = DTU_FWDEZ (uptr) + DT_EZLIN + 1000; /* fwd? > end */ - break; -case FNC_SRCH: /* search */ - if (dir) newpos = DT_BLK2LN ((DT_QFEZ (uptr)? - DTU_TSIZE (uptr): blk), uptr) - DT_BLKLN - DT_WSIZE; - else newpos = DT_BLK2LN ((DT_QREZ (uptr)? - 0: blk + 1), uptr) + DT_BLKLN + (DT_WSIZE - 1); - if (DBG_LOG (LOG_TC_MS)) fprintf (sim_log, ">>DT%d: searching %s\n", - unum, (dir? "backward": "forward")); - break; -case FNC_WRIT: /* write */ -case FNC_READ: /* read */ - if (DT_QEZ (uptr)) { /* in "ok" end zone? */ - if (dir) newpos = DTU_FWDEZ (uptr) - DT_HTLIN - DT_WSIZE; - else newpos = DT_EZLIN + DT_HTLIN + (DT_WSIZE - 1); - break; } - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - dt_seterr (uptr, STA_BLKM); - return; } - if (dir) newpos = DT_BLK2LN (((relpos >= (DTU_LPERB (uptr) - DT_HTLIN))? - blk + 1: blk), uptr) - DT_HTLIN - DT_WSIZE; - else newpos = DT_BLK2LN (((relpos < DT_HTLIN)? - blk: blk + 1), uptr) + DT_HTLIN + (DT_WSIZE - 1); - if (DBG_LOG (LOG_TC_RW) || (DBG_LOG (LOG_TC_BL) && (blk == dt_logblk))) - fprintf (sim_log, ">>DT%d: %s block %d %s\n", - unum, ((fnc == FNC_READ)? "read": "write"), - blk, (dir? "backward": "forward")); - break; -case FNC_RALL: /* read all */ -case FNC_WALL: /* write all */ - if (DT_QEZ (uptr)) { /* in "ok" end zone? */ - if (dir) newpos = DTU_FWDEZ (uptr) - DT_WSIZE; - else newpos = DT_EZLIN + (DT_WSIZE - 1); } - else { - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - if (dir? (relpos < (DTU_LPERB (uptr) - DT_CSMLN)): /* switch in time? */ - (relpos >= DT_CSMLN)) { - dt_seterr (uptr, STA_BLKM); - return; } - if (dir) newpos = DT_BLK2LN (blk + 1, uptr) - DT_CSMLN - DT_WSIZE; - else newpos = DT_BLK2LN (blk, uptr) + DT_CSMLN + (DT_WSIZE - 1); } - if (fnc == FNC_WALL) sim_activate /* write all? */ - (&dt_dev.units[DT_TIMER], dt_ctime); /* sched done */ - if (DBG_LOG (LOG_TC_RW) || (DBG_LOG (LOG_TC_BL) && (blk == dt_logblk))) - fprintf (sim_log, ">>DT%d: read all block %d %s\n", - unum, blk, (dir? "backward": "forward")); - break; -default: - dt_seterr (uptr, STA_SEL); /* bad state */ - return; } -sim_activate (uptr, ABS (newpos - ((int32) uptr->pos)) * dt_ltime); -return; -} - -/* Update DECtape position - - DECtape motion is modeled as a constant velocity, with linear - acceleration and deceleration. The motion equations are as follows: - - t = time since operation started - tmax = time for operation (accel, decel only) - v = at speed velocity in lines (= 1/dt_ltime) - - Then: - at speed dist = t * v - accel dist = (t^2 * v) / (2 * tmax) - decel dist = (((2 * t * tmax) - t^2) * v) / (2 * tmax) - - This routine uses the relative (integer) time, rather than the absolute - (floating point) time, to allow save and restore of the start times. -*/ - -t_bool dt_setpos (UNIT *uptr) -{ -uint32 new_time, ut, ulin, udelt; -int32 mot = DTS_GETMOT (uptr->STATE); -int32 unum, delta; - -new_time = sim_grtime (); /* current time */ -ut = new_time - uptr->LASTT; /* elapsed time */ -if (ut == 0) return FALSE; /* no time gone? exit */ -uptr->LASTT = new_time; /* update last time */ -switch (mot & ~DTS_DIR) { /* case on motion */ -case DTS_STOP: /* stop */ - delta = 0; - break; -case DTS_DECF: /* slowing */ - ulin = ut / (uint32) dt_ltime; udelt = dt_dctime / dt_ltime; - delta = ((ulin * udelt * 2) - (ulin * ulin)) / (2 * udelt); - break; -case DTS_ACCF: /* accelerating */ - ulin = ut / (uint32) dt_ltime; udelt = dt_actime / dt_ltime; - delta = (ulin * ulin) / (2 * udelt); - break; -case DTS_ATSF: /* at speed */ - delta = ut / (uint32) dt_ltime; - break; } -if (mot & DTS_DIR) uptr->pos = uptr->pos - delta; /* update pos */ -else uptr->pos = uptr->pos + delta; -if (((int32) uptr->pos < 0) || - ((int32) uptr->pos > (DTU_FWDEZ (uptr) + DT_EZLIN))) { - detach_unit (uptr); /* off reel? */ - uptr->STATE = uptr->pos = 0; - unum = uptr - dt_dev.units; - if ((unum == CSR_GETUNIT (tccm)) && (CSR_GETFNC (tccm) != FNC_STOP)) - dt_seterr (uptr, STA_SEL); /* error */ - return TRUE; } -return FALSE; -} - -/* Command timer service after stop - set done */ - -t_stat dt_svcdone (UNIT *uptr) -{ -DT_SETDONE; -return SCPE_OK; -} - -/* Unit service - - Unit must be attached, detach cancels operation -*/ - -t_stat dt_svc (UNIT *uptr) -{ -int32 mot = DTS_GETMOT (uptr->STATE); -int32 dir = mot & DTS_DIR; -int32 fnc = DTS_GETFNC (uptr->STATE); -int32 *bptr = uptr->filebuf; -int32 blk, wrd, relpos, dat; -uint32 ba, ma, mma; - -/* Motion cases - - Decelerating - if next state != stopped, must be accel reverse - Accelerating - next state must be @speed, schedule function - At speed - do functional processing -*/ - -switch (mot) { -case DTS_DECF: case DTS_DECR: /* decelerating */ - if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ - uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ - if (uptr->STATE) /* not stopped? */ - sim_activate (uptr, dt_actime); /* must be reversing */ - return SCPE_OK; -case DTS_ACCF: case DTS_ACCR: /* accelerating */ - dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */ - return SCPE_OK; -case DTS_ATSF: case DTS_ATSR: /* at speed */ - break; /* check function */ -default: /* other */ - dt_seterr (uptr, STA_SEL); /* state error */ - return SCPE_OK; } - -/* Functional cases - - Search - transfer block number, schedule next block - Off reel - detach unit (it must be deselected) -*/ - -if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ -if (DT_QEZ (uptr)) { /* in end zone? */ - dt_seterr (uptr, STA_END); /* end zone error */ - return SCPE_OK; } -blk = DT_LIN2BL (uptr->pos, uptr); /* get block # */ - -switch (fnc) { /* at speed, check fnc */ -case FNC_SRCH: /* search */ - tcdt = blk; /* set block # */ - dt_schedez (uptr, dir); /* sched end zone */ - DT_SETDONE; /* set done */ - break; -case DTS_OFR: /* off reel */ - detach_unit (uptr); /* must be deselected */ - uptr->STATE = uptr->pos = 0; /* no visible action */ - break; - -/* Read - - If wc ovf has not occurred, inc ma, wc and copy word from tape to memory - If wc ovf, set flag - If not end of block, schedule next word - If end of block and not wc ovf, schedule next block - If end of block and wc ovf, set done, schedule end zone -*/ - -case FNC_READ: /* read */ - wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */ - if (!dt_substate) { /* !wc ovf? */ - tcwc = tcwc & DMASK; /* incr MA, WC */ - tcba = tcba & DMASK; - ma = (CSR_GETMEX (tccm) << 16) | tcba; /* form 18b addr */ - if (!Map_Addr (ma, &mma) || /* map addr */ - !ADDR_IS_MEM (mma)) { /* nx mem? */ - dt_seterr (uptr, STA_NXM); - break; } - ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - M[mma >> 1] = tcdt = bptr[ba] & DMASK; /* read word */ - tcwc = (tcwc + 1) & DMASK; /* incr MA, WC */ - tcba = (tcba + 2) & DMASK; - if (tcba <= 1) tccm = CSR_INCMEX (tccm); - if (tcwc == 0) dt_substate = 1; } - if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not end blk? */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - else if (dt_substate) { /* wc ovf? */ - dt_schedez (uptr, dir); /* sched end zone */ - DT_SETDONE; } /* set done */ - else sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); - break; - -/* Write - - If wc ovf has not occurred, inc ma, wc - Copy word from memory (or 0, to fill block) to tape - If wc ovf, set flag - If not end of block, schedule next word - If end of block and not wc ovf, schedule next block - If end of block and wc ovf, set done, schedule end zone -*/ - -case FNC_WRIT: /* write */ - wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */ - if (dt_substate) tcdt = 0; /* wc ovf? fill */ - else { - ma = (CSR_GETMEX (tccm) << 16) | tcba; /* form 18b addr */ - if (!Map_Addr (ma, &mma) || /* map addr */ - !ADDR_IS_MEM (mma)) { /* nx mem? */ - dt_seterr (uptr, STA_NXM); - break; } - else tcdt = M[mma >> 1]; /* get word */ - tcwc = (tcwc + 1) & DMASK; /* incr MA, WC */ - tcba = (tcba + 2) & DMASK; - if (tcba <= 1) tccm = CSR_INCMEX (tccm); } - ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - bptr[ba] = tcdt; /* write word */ - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; - if (tcwc == 0) dt_substate = 1; - if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not end blk? */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - else if (dt_substate) { /* wc ovf? */ - dt_schedez (uptr, dir); /* sched end zone */ - DT_SETDONE; } - else sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); - break; - -/* Read all - read current header or data word */ - -case FNC_RALL: - if (tccm & CSR_DONE) { /* done set? */ - dt_seterr (uptr, STA_DATM); /* data miss */ - break; } - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - dat = bptr[ba]; } /* get tape word */ - else dat = dt_gethdr (uptr, blk, relpos); /* get hdr */ - if (dir) dat = dt_comobv (dat); /* rev? comp obv */ - tcdt = dat & DMASK; /* low 16b */ - tcst = (tcst & ~STA_M_XD) | ((dat >> 16) & STA_M_XD); - sim_activate (uptr, DT_WSIZE * dt_ltime); - DT_SETDONE; /* set done */ - break; - -/* Write all - write current header or data word */ - -case FNC_WALL: - if (tccm & CSR_DONE) { /* done set? */ - dt_seterr (uptr, STA_DATM); /* data miss */ - break; } - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - dat = (STA_GETXD (tcst) << 16) | tcdt; /* get data word */ - if (dir) dat = dt_comobv (dat); /* rev? comp obv */ - ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - bptr[ba] = dat; /* write word */ - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; } -/* else /* ignore hdr */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - DT_SETDONE; /* set done */ - break; -default: - dt_seterr (uptr, STA_SEL); /* impossible state */ - break; } -return SCPE_OK; -} - -/* Utility routines */ - -/* Set error flag */ - -void dt_seterr (UNIT *uptr, int32 e) -{ -int32 mot = DTS_GETMOT (uptr->STATE); - -tcst = tcst | e; /* set error flag */ -tccm = tccm | CSR_ERR; -if (!(tccm & CSR_DONE)) { /* not done? */ - DT_SETDONE; } -if (mot >= DTS_ACCF) { /* ~stopped or stopping? */ - sim_cancel (uptr); /* cancel activity */ - if (dt_setpos (uptr)) return; /* update position */ - sim_activate (uptr, dt_dctime); /* sched decel */ - DTS_SETSTA (DTS_DECF | (mot & DTS_DIR), 0); } /* state = decel */ -return; -} - -/* Stop unit */ - -void dt_stopunit (UNIT *uptr) -{ -int32 mot = DTS_GETMOT (uptr->STATE); -int32 dir = mot & DTS_DIR; - -if (mot == DTS_STOP) return; /* already stopped? */ -if ((mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_dctime); } /* schedule decel */ -DTS_SETSTA (DTS_DECF | dir, 0); /* state = decel */ -return; -} - -/* Schedule end zone */ - -void dt_schedez (UNIT *uptr, int32 dir) -{ -int32 newpos; - -if (dir) newpos = DT_EZLIN - DT_WSIZE; /* rev? rev ez */ -else newpos = DTU_FWDEZ (uptr) + DT_WSIZE; /* fwd? fwd ez */ -sim_activate (uptr, ABS (newpos - ((int32) uptr->pos)) * dt_ltime); -return; -} - -/* Complement obverse routine (18b) */ - -int32 dt_comobv (int32 dat) -{ -dat = dat ^ 0777777; /* compl obverse */ -dat = ((dat >> 15) & 07) | ((dat >> 9) & 070) | - ((dat >> 3) & 0700) | ((dat & 0700) << 3) | - ((dat & 070) << 9) | ((dat & 07) << 15); -return dat; -} - -/* Checksum routine */ - -int32 dt_csum (UNIT *uptr, int32 blk) -{ -int32 *bptr = uptr->filebuf; -int32 ba = blk * DTU_BSIZE (uptr); -int32 i, csum, wrd; - -csum = 077; /* init csum */ -for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ - wrd = bptr[ba + i] ^ 0777777; /* get ~word */ - csum = csum ^ (wrd >> 12) ^ (wrd >> 6) ^ wrd; } -return (csum & 077); -} - -/* Get header word (18b) */ - -int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos) -{ -int32 wrd = relpos / DT_WSIZE; - -if (wrd == DT_BLKWD) return blk; /* fwd blknum */ -if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */ - return (dt_csum (uptr, blk) << 12); -if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_BLKWD - 1)) /* rev blkno */ - return dt_comobv (blk); -return 0; /* all others */ -} - -/* Reset routine */ - -t_stat dt_reset (DEVICE *dptr) -{ -int32 i, prev_mot; -UNIT *uptr; - -for (i = 0; i < DT_NUMDR; i++) { /* stop all activity */ - uptr = dt_dev.units + i; - if (sim_is_running) { /* RESET? */ - prev_mot = DTS_GETMOT (uptr->STATE); /* get motion */ - if ((prev_mot & ~DTS_DIR) > DTS_DECF) { /* accel or spd? */ - if (dt_setpos (uptr)) continue; /* update pos */ - sim_cancel (uptr); - sim_activate (uptr, dt_dctime); /* sched decel */ - DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); - } } - else { - sim_cancel (uptr); /* sim reset */ - uptr->STATE = 0; - uptr->LASTT = sim_grtime (); } } -tcst = tcwc = tcba = tcdt = 0; /* clear reg */ -tccm = CSR_DONE; -CLR_INT (DTA); /* clear int req */ -return SCPE_OK; -} - -/* Device bootstrap */ - -#define BOOT_START 02000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 020) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 0042124, /* "TD" */ - 0012706, BOOT_START, /* MOV #boot_start, SP */ - 0012700, 0000000, /* MOV #unit, R0 ; unit number */ - 0010003, /* MOV R0, R3 */ - 0000303, /* SWAB R3 */ - 0012701, 0177342, /* MOV #TCCM, R1 ; csr */ - 0012702, 0004003, /* RW: MOV #4003, R2 ; rev+rnum+go */ - 0050302, /* BIS R3, R2 */ - 0010211, /* MOV R2, (R1) ; load csr */ - 0032711, 0100200, /* BIT #100200, (R1) ; wait */ - 0001775, /* BEQ .-4 */ - 0100370, /* BPL RW ; no err, cont */ - 0005761, 0177776, /* TST -2(R1) ; end zone? */ - 0100036, /* BPL ER ; no, err */ - 0012702, 0000003, /* MOV #3, R2 ; rnum+go */ - 0050302, /* BIS R3, R2 */ - 0010211, /* MOV R2, (R1) ; load csr */ - 0032711, 0100200, /* BIT #100200, (R1) ; wait */ - 0001775, /* BEQ .-4 */ - 0100426, /* BMI ER ; err, die */ - 0005761, 0000006, /* TST 6(R1) ; blk 0? */ - 0001023, /* BNE ER ; no, die */ - 0012761, 0177000, 0000002, /* MOV #-256.*2, 2(R1) ; load wc */ - 0005061, 0000004, /* CLR 4(R1) ; clear ba */ - 0012702, 0000005, /* MOV #READ+GO, R2 ; read & go */ - 0050302, /* BIS R3, R2 */ - 0010211, /* MOV R2, (R1) ; load csr */ - 0005002, /* CLR R2 */ - 0005003, /* CLR R3 */ - 0012704, BOOT_START+020, /* MOV #START+20, R4 */ - 0005005, /* CLR R5 */ - 0032711, 0100200, /* BIT #100200, (R1) ; wait */ - 0001775, /* BEQ .-4 */ - 0100401, /* BMI ER ; err, die */ - 0005007, /* CLR PC */ - 0012711, 0000001, /* ER: MOV #1, (R1) ; stop all */ - 0000000 /* HALT */ -}; - -t_stat dt_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -dt_unit[unitno].pos = DT_EZLIN; -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & DT_M_NUMDR; -M[BOOT_CSR >> 1] = (dt_dib.ba & DMASK) + 02; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} - -/* Attach routine - - Determine 12b, 16b, or 18b/36b format - Allocate buffer - If 12b, read 12b format and convert to 18b in buffer - If 16b, read 16b format and convert to 18b in buffer - If 18b/36b, read data into buffer -*/ - -t_stat dt_attach (UNIT *uptr, char *cptr) -{ -uint16 pdp8b[D8_NBSIZE]; -uint16 pdp11b[D18_BSIZE]; -uint32 ba, sz, k, *bptr; -int32 u = uptr - dt_dev.units; -t_stat r; - -r = attach_unit (uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* fail? */ -if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */ - uptr->flags = (uptr->flags | UNIT_11FMT) & ~UNIT_8FMT; /* default 16b */ - if (sim_switches & SWMASK ('R')) /* att 12b? */ - uptr->flags = (uptr->flags | UNIT_8FMT) & ~UNIT_11FMT; - else if (sim_switches & SWMASK ('T')) /* att 18b? */ - uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); - else if (!(sim_switches & SWMASK ('S')) && /* autosize? */ - ((sz = sim_fsize (cptr)) > D16_FILSIZ)) { - if (sz <= D8_FILSIZ) - uptr->flags = (uptr->flags | UNIT_8FMT) & ~UNIT_11FMT; - else uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); } } -uptr->capac = DTU_CAPAC (uptr); /* set capacity */ -uptr->filebuf = calloc (uptr->capac, sizeof (int32)); -if (uptr->filebuf == NULL) { /* can't alloc? */ - detach_unit (uptr); - return SCPE_MEM; } -bptr = uptr->filebuf; /* file buffer */ -printf ("%s%d: ", sim_dname (&dt_dev), u); -if (uptr->flags & UNIT_8FMT) printf ("12b format"); -else if (uptr->flags & UNIT_11FMT) printf ("16b format"); -else printf ("18b/36b format"); -printf (", buffering file in memory\n"); -if (uptr->flags & UNIT_8FMT) { /* 12b? */ - for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ - k = fxread (pdp8b, sizeof (int16), D8_NBSIZE, uptr->fileref); - if (k == 0) break; - for ( ; k < D8_NBSIZE; k++) pdp8b[k] = 0; - for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop thru blk */ - bptr[ba] = ((uint32) (pdp8b[k] & 07777) << 6) | - ((uint32) (pdp8b[k + 1] >> 6) & 077); - bptr[ba + 1] = ((pdp8b[k + 1] & 077) << 12) | - ((uint32) (pdp8b[k + 2] & 07777)); - ba = ba + 2; } /* end blk loop */ - } /* end file loop */ - uptr->hwmark = ba; } /* end if */ -else if (uptr->flags & UNIT_11FMT) { /* 16b? */ - for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ - k = fxread (pdp11b, sizeof (int16), D18_BSIZE, uptr->fileref); - if (k == 0) break; - for ( ; k < D18_BSIZE; k++) pdp11b[k] = 0; - for (k = 0; k < D18_BSIZE; k++) - bptr[ba++] = pdp11b[k]; } - uptr->hwmark = ba; } /* end elif */ -else uptr->hwmark = fxread (uptr->filebuf, sizeof (int32), - uptr->capac, uptr->fileref); -uptr->flags = uptr->flags | UNIT_BUF; /* set buf flag */ -uptr->pos = DT_EZLIN; /* beyond leader */ -uptr->LASTT = sim_grtime (); /* last pos update */ -return SCPE_OK; -} - -/* Detach routine - - Cancel in progress operation - If 12b, convert 18b buffer to 12b and write to file - If 16b, convert 18b buffer to 16b and write to file - If 18b/36b, write buffer to file - Deallocate buffer -*/ - -t_stat dt_detach (UNIT* uptr) -{ -uint16 pdp8b[D8_NBSIZE]; -uint16 pdp11b[D18_BSIZE]; -uint32 ba, k, *bptr; -int32 u = uptr - dt_dev.units; - -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; -if (sim_is_active (uptr)) { /* active? cancel op */ - sim_cancel (uptr); - if ((u == CSR_GETUNIT (tccm)) && ((tccm & CSR_DONE) == 0)) { - tcst = tcst | STA_SEL; - tccm = tccm | CSR_ERR | CSR_DONE; - if (tccm & CSR_IE) SET_INT (DTA); } - uptr->STATE = uptr->pos = 0; } -bptr = uptr->filebuf; /* file buffer */ -if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */ - printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u); - rewind (uptr->fileref); /* start of file */ - if (uptr->flags & UNIT_8FMT) { /* 12b? */ - for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */ - for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop blk */ - pdp8b[k] = (bptr[ba] >> 6) & 07777; - pdp8b[k + 1] = ((bptr[ba] & 077) << 6) | - ((bptr[ba + 1] >> 12) & 077); - pdp8b[k + 2] = bptr[ba + 1] & 07777; - ba = ba + 2; } /* end loop blk */ - fxwrite (pdp8b, sizeof (int16), D8_NBSIZE, uptr->fileref); - if (ferror (uptr->fileref)) break; } /* end loop file */ - } /* end if 12b */ - else if (uptr->flags & UNIT_11FMT) { /* 16b? */ - for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */ - for (k = 0; k < D18_BSIZE; k++) /* loop blk */ - pdp11b[k] = bptr[ba++] & DMASK; - fxwrite (pdp11b, sizeof (int16), D18_BSIZE, uptr->fileref); - if (ferror (uptr->fileref)) break; } /* end loop file */ - } /* end if 16b */ - else fxwrite (uptr->filebuf, sizeof (int32), /* write file */ - uptr->hwmark, uptr->fileref); - if (ferror (uptr->fileref)) perror ("I/O error"); } /* end if hwmark */ -free (uptr->filebuf); /* release buf */ -uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */ -uptr->filebuf = NULL; /* clear buf ptr */ -uptr->flags = (uptr->flags | UNIT_11FMT) & ~UNIT_8FMT; /* default fmt */ -uptr->capac = DT_CAPAC; /* default size */ -return detach_unit (uptr); -} diff --git a/PDP11/pdp11_tm.c b/PDP11/pdp11_tm.c deleted file mode 100644 index e6872b36..00000000 --- a/PDP11/pdp11_tm.c +++ /dev/null @@ -1,656 +0,0 @@ -/* pdp11_tm.c: PDP-11 magnetic tape simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - tm TM11/TU10 magtape - - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Revised for magtape library, added logging - 30-Oct-02 RMS Revised BOT handling, added error record handling - 30-Sep-02 RMS Added variable address support to bootstrap - Added vector change/display support - Changed mapping mnemonics - New data structures - Updated error handling - 28-Aug-02 RMS Added end of medium support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Fixed max record length, first block bootstrap - (found by Jonathan Engdahl) - 26-Jan-02 RMS Revised bootstrap to conform to M9312 - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Converted UST, POS, FLG to arrays - 09-Nov-01 RMS Added bus map support - 18-Oct-01 RMS Added stub diagnostic register (found by Thord Nilson) - 07-Sep-01 RMS Revised device disable and interrupt mechanisms - 26-Apr-01 RMS Added device enable/disable support - 18-Apr-01 RMS Changed to rewind tape before boot - 14-Apr-99 RMS Changed t_addr to unsigned - 04-Oct-98 RMS V2.4 magtape format - 10-May-98 RMS Fixed bug with non-zero unit operation (from Steven Schultz) - 09-May-98 RMS Fixed problems in bootstrap (from Steven Schultz) - 10-Apr-98 RMS Added 2nd block bootstrap (from John Holden, - University of Sydney) - 31-Jul-97 RMS Added bootstrap (from Ethan Dicks, Ohio State) - 22-Jan-97 RMS V2.3 magtape format - 18-Jan-97 RMS Fixed double interrupt, error flag bugs - 29-Jun-96 RMS Added unit disable support - - Magnetic tapes are represented as a series of variable 8b records - of the form: - - 32b record length in bytes - exact number - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32b record length in bytes - exact number - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a single record length of 0. - End of tape is two consecutive end of file marks. -*/ - -#include "pdp11_defs.h" -#include "sim_tape.h" - -#define TM_NUMDR 8 /* #drives */ -#define USTAT u3 /* unit status */ - -/* Command - tm_cmd */ - -#define MTC_ERR (1 << CSR_V_ERR) /* error */ -#define MTC_V_DEN 13 /* density */ -#define MTC_M_DEN 03 -#define MTC_DEN (MTC_M_DEN << MTC_V_DEN) -#define MTC_INIT 0010000 /* init */ -#define MTC_LPAR 0004000 /* parity select */ -#define MTC_V_UNIT 8 /* unit */ -#define MTC_M_UNIT 07 -#define MTC_UNIT (MTC_M_UNIT << MTC_V_UNIT) -#define MTC_DONE (1 << CSR_V_DONE) /* done */ -#define MTC_IE (1 << CSR_V_IE) /* interrupt enable */ -#define MTC_V_EMA 4 /* ext mem address */ -#define MTC_M_EMA 03 -#define MTC_EMA (MTC_M_EMA << MTC_V_EMA) -#define MTC_V_FNC 1 /* function */ -#define MTC_M_FNC 07 -#define MTC_UNLOAD 00 -#define MTC_READ 01 -#define MTC_WRITE 02 -#define MTC_WREOF 03 -#define MTC_SPACEF 04 -#define MTC_SPACER 05 -#define MTC_WREXT 06 -#define MTC_REWIND 07 -#define MTC_FNC (MTC_M_FNC << MTC_V_FNC) -#define MTC_GO (1 << CSR_V_GO) /* go */ -#define MTC_RW (MTC_DEN | MTC_LPAR | MTC_UNIT | MTC_IE | \ - MTC_EMA | MTC_FNC) -#define GET_EMA(x) (((x) & MTC_EMA) << (16 - MTC_V_EMA)) -#define GET_UNIT(x) (((x) >> MTC_V_UNIT) & MTC_M_UNIT) -#define GET_FNC(x) (((x) >> MTC_V_FNC) & MTC_M_FNC) - -/* Status - stored in tm_sta or (*) uptr->USTAT or (+) calculated */ - -#define STA_ILL 0100000 /* illegal */ -#define STA_EOF 0040000 /* *end of file */ -#define STA_CRC 0020000 /* CRC error */ -#define STA_PAR 0010000 /* parity error */ -#define STA_DLT 0004000 /* data late */ -#define STA_EOT 0002000 /* *end of tape */ -#define STA_RLE 0001000 /* rec lnt error */ -#define STA_BAD 0000400 /* bad tape error */ -#define STA_NXM 0000200 /* non-existent mem */ -#define STA_ONL 0000100 /* *online */ -#define STA_BOT 0000040 /* *start of tape */ -#define STA_7TK 0000020 /* 7 track */ -#define STA_SDN 0000010 /* settle down */ -#define STA_WLK 0000004 /* *write locked */ -#define STA_REW 0000002 /* *rewinding */ -#define STA_TUR 0000001 /* +unit ready */ - -#define STA_CLR (STA_7TK | STA_SDN) /* always clear */ -#define STA_DYN (STA_EOF | STA_EOT | STA_ONL | STA_BOT | \ - STA_WLK | STA_REW | STA_TUR) /* kept in USTAT */ -#define STA_EFLGS (STA_ILL | STA_EOF | STA_CRC | STA_PAR | \ - STA_DLT | STA_EOT | STA_RLE | STA_BAD | STA_NXM) - /* set error */ - -/* Read lines - tm_rdl */ - -#define RDL_CLK 0100000 /* 10 Khz clock */ - -extern uint16 *M; /* memory */ -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -extern int32 cpu_log; -extern FILE *sim_log; - -uint8 *tmxb = NULL; /* xfer buffer */ -int32 tm_sta = 0; /* status register */ -int32 tm_cmd = 0; /* command register */ -int32 tm_ca = 0; /* current address */ -int32 tm_bc = 0; /* byte count */ -int32 tm_db = 0; /* data buffer */ -int32 tm_rdl = 0; /* read lines */ -int32 tm_time = 10; /* record latency */ -int32 tm_stopioe = 1; /* stop on error */ - -DEVICE tm_dev; -t_stat tm_rd (int32 *data, int32 PA, int32 access); -t_stat tm_wr (int32 data, int32 PA, int32 access); -t_stat tm_svc (UNIT *uptr); -t_stat tm_reset (DEVICE *dptr); -t_stat tm_attach (UNIT *uptr, char *cptr); -t_stat tm_detach (UNIT *uptr); -t_stat tm_boot (int32 unitno, DEVICE *dptr); -void tm_go (UNIT *uptr); -int32 tm_updcsta (UNIT *uptr); -void tm_set_done (void); -t_stat tm_map_err (UNIT *uptr, t_stat st); -t_stat tm_vlock (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* MT data structures - - tm_dev MT device descriptor - tm_unit MT unit list - tm_reg MT register list - tm_mod MT modifier list -*/ - -DIB tm_dib = { IOBA_TM, IOLN_TM, &tm_rd, &tm_wr, - 1, IVCL (TM), VEC_TM, { NULL } }; - -UNIT tm_unit[] = { - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) } }; - -REG tm_reg[] = { - { ORDATA (MTS, tm_sta, 16) }, - { ORDATA (MTC, tm_cmd, 16) }, - { ORDATA (MTBRC, tm_bc, 16) }, - { ORDATA (MTCMA, tm_ca, 16) }, - { ORDATA (MTD, tm_db, 8) }, - { ORDATA (MTRD, tm_rdl, 16) }, - { FLDATA (INT, IREQ (TM), INT_V_TM) }, - { FLDATA (ERR, tm_cmd, CSR_V_ERR) }, - { FLDATA (DONE, tm_cmd, CSR_V_DONE) }, - { FLDATA (IE, tm_cmd, CSR_V_IE) }, - { FLDATA (STOP_IOE, tm_stopioe, 0) }, - { DRDATA (TIME, tm_time, 24), PV_LEFT }, - { URDATA (UST, tm_unit[0].USTAT, 8, 16, 0, TM_NUMDR, 0) }, - { URDATA (POS, tm_unit[0].pos, 10, T_ADDR_W, 0, - TM_NUMDR, PV_LEFT | REG_RO) }, - { ORDATA (DEVADDR, tm_dib.ba, 32), REG_HRO }, - { ORDATA (DEVVEC, tm_dib.vec, 16), REG_HRO }, - { NULL } }; - -MTAB tm_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", &tm_vlock }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &tm_vlock }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { MTAB_XTD|MTAB_VDV, 020, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE tm_dev = { - "TM", tm_unit, tm_reg, tm_mod, - TM_NUMDR, 10, 31, 1, 8, 8, - NULL, NULL, &tm_reset, - &tm_boot, &tm_attach, &tm_detach, - &tm_dib, DEV_DISABLE | DEV_UBUS }; - -/* I/O dispatch routine, I/O addresses 17772520 - 17772532 - - 17772520 MTS read only, constructed from tm_sta - plus current drive status flags - 17772522 MTC read/write - 17772524 MTBRC read/write - 17772526 MTCMA read/write - 17772530 MTD read/write - 17772532 MTRD read only -*/ - -t_stat tm_rd (int32 *data, int32 PA, int32 access) -{ -UNIT *uptr; - -uptr = tm_dev.units + GET_UNIT (tm_cmd); /* get unit */ -switch ((PA >> 1) & 07) { /* decode PA<3:1> */ -case 0: /* MTS */ - *data = tm_updcsta (uptr); /* update status */ - break; -case 1: /* MTC */ - tm_updcsta (uptr); /* update status */ - *data = tm_cmd; /* return command */ - break; -case 2: /* MTBRC */ - *data = tm_bc; /* return byte count */ - break; -case 3: /* MTCMA */ - *data = tm_ca; /* return mem addr */ - break; -case 4: /* MTD */ - *data = tm_db; /* return data buffer */ - break; -case 5: /* MTRD */ - tm_rdl = tm_rdl ^ RDL_CLK; /* "clock" ticks */ - *data = tm_rdl; - break; -default: /* unimplemented */ - *data = 0; - break; } -return SCPE_OK; -} - -t_stat tm_wr (int32 data, int32 PA, int32 access) -{ -UNIT *uptr; - -switch ((PA >> 1) & 07) { /* decode PA<3:1> */ -case 0: /* MTS: read only */ - break; -case 1: /* MTC */ - uptr = tm_dev.units + GET_UNIT (tm_cmd); /* select unit */ - if ((tm_cmd & MTC_DONE) == 0) tm_sta = tm_sta | STA_ILL; - else { - if (access == WRITEB) data = (PA & 1)? - (tm_cmd & 0377) | (data << 8): - (tm_cmd & ~0377) | data; - if (data & MTC_INIT) { /* init? */ - tm_reset (&tm_dev); /* reset device */ - return SCPE_OK; } - if ((data & MTC_IE) == 0) /* int disable? */ - CLR_INT (TM); /* clr int request */ - else if ((tm_cmd & (MTC_ERR + MTC_DONE)) && !(tm_cmd & MTC_IE)) - SET_INT (TM); /* set int request */ - tm_cmd = (tm_cmd & ~MTC_RW) | (data & MTC_RW); - uptr = tm_dev.units + GET_UNIT (tm_cmd); /* new unit */ - if (data & MTC_GO) tm_go (uptr); } /* new function? */ - tm_updcsta (uptr); /* update status */ - break; -case 2: /* MTBRC */ - if (access == WRITEB) data = (PA & 1)? - (tm_bc & 0377) | (data << 8): (tm_bc & ~0377) | data; - tm_bc = data; - break; -case 3: /* MTCMA */ - if (access == WRITEB) data = (PA & 1)? - (tm_ca & 0377) | (data << 8): (tm_ca & ~0377) | data; - tm_ca = data; - break; -case 4: /* MTD */ - if ((access == WRITEB) && (PA & 1)) return SCPE_OK; - tm_db = data & 0377; - break; } /* end switch */ -return SCPE_OK; -} - -/* New magtape command */ - -void tm_go (UNIT *uptr) -{ -int32 f; - -f = GET_FNC (tm_cmd); /* get function */ -if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */ - sim_is_active (uptr) || /* busy? */ - (((f == MTC_WRITE) || (f == MTC_WREOF) || (f == MTC_WREXT)) && - sim_tape_wrp (uptr))) { /* write locked? */ - tm_sta = tm_sta | STA_ILL; /* illegal */ - tm_set_done (); /* set done */ - return; } -uptr->USTAT = uptr->USTAT & (STA_WLK | STA_ONL); /* clear status */ -tm_sta = 0; /* clear errors */ -if (f == MTC_UNLOAD) { /* unload? */ - uptr->USTAT = (uptr->USTAT | STA_REW) & ~STA_ONL; - detach_unit (uptr); } /* set offline */ -else if (f == MTC_REWIND) /* rewind */ - uptr->USTAT = uptr->USTAT | STA_REW; /* rewinding */ -/* else /* uncomment this else if rewind/unload don't set done */ -tm_cmd = tm_cmd & ~MTC_DONE; /* clear done */ -CLR_INT (TM); /* clear int */ -sim_activate (uptr, tm_time); /* start io */ -return; -} - -/* Unit service - - If rewind done, reposition to start of tape, set status - else, do operation, set done, interrupt -*/ - -t_stat tm_svc (UNIT *uptr) -{ -int32 f, t, u; -uint32 xma; -t_mtrlnt tbc, cbc; -t_stat st, r = SCPE_OK; - -u = uptr - tm_dev.units; /* get unit number */ -f = GET_FNC (tm_cmd); /* get command */ -xma = GET_EMA (tm_cmd) | tm_ca; /* get mem addr */ -cbc = 0200000 - tm_bc; /* get bc */ - -if (uptr->USTAT & STA_REW) { /* rewind? */ - sim_tape_rewind (uptr); /* update position */ - if (uptr->flags & UNIT_ATT) /* still on line? */ - uptr->USTAT = STA_ONL | STA_BOT | - (sim_tape_wrp (uptr)? STA_WLK: 0); - else uptr->USTAT = 0; - if (u == GET_UNIT (tm_cmd)) { /* selected? */ - tm_set_done (); /* set done */ - tm_updcsta (uptr); } /* update status */ - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */ - uptr->USTAT = 0; /* unit off line */ - tm_sta = tm_sta | STA_ILL; /* illegal operation */ - tm_set_done (); /* set done */ - tm_updcsta (uptr); /* update status */ - return IORETURN (tm_stopioe, SCPE_UNATT); } - -if (DBG_LOG (LOG_TM)) fprintf (sim_log, - ">>TM: op=%o, ma=%o, bc=%o, pos=%d\n", f, xma, cbc, uptr->pos); -switch (f) { /* case on function */ - -/* Unit service, continued */ - -case MTC_READ: /* read */ - st = sim_tape_rdrecf (uptr, tmxb, &tbc, MT_MAXFR); /* read rec */ - if (st == MTSE_RECE) tm_sta = tm_sta | STA_PAR; /* rec in error? */ - else if (st != MTSE_OK) { /* other error? */ - r = tm_map_err (uptr, st); /* map error */ - break; } - if (tbc > cbc) tm_sta = tm_sta | STA_RLE; /* wrong size? */ - if (tbc < cbc) cbc = tbc; /* use smaller */ - if (t = Map_WriteB (xma, cbc, tmxb, MAP)) { /* copy buf to mem */ - tm_sta = tm_sta | STA_NXM; /* NXM, set err */ - cbc = cbc - t; } /* adj byte cnt */ - xma = (xma + cbc) & 0777777; /* inc bus addr */ - tm_bc = (tm_bc + cbc) & 0177777; /* inc byte cnt */ - break; - -case MTC_WRITE: /* write */ -case MTC_WREXT: /* write ext gap */ - if (t = Map_ReadB (xma, cbc, tmxb, MAP)) { /* copy mem to buf */ - tm_sta = tm_sta | STA_NXM; /* NXM, set err */ - cbc = cbc - t; /* adj byte cnt */ - if (cbc == 0) break; } /* no xfr? done */ - if (st = sim_tape_wrrecf (uptr, tmxb, cbc)) /* write rec, err? */ - r = tm_map_err (uptr, st); /* map error */ - else { - xma = (xma + cbc) & 0777777; /* inc bus addr */ - tm_bc = (tm_bc + cbc) & 0177777; } /* inc byte cnt */ - break; - -/* Unit service, continued */ - -case MTC_WREOF: /* write eof */ - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = tm_map_err (uptr, st); /* map error */ - break; - -case MTC_SPACEF: /* space forward */ - do { - tm_bc = (tm_bc + 1) & 0177777; /* incr wc */ - if (st = sim_tape_sprecf (uptr, &tbc)) { /* spc rec fwd, err? */ - r = tm_map_err (uptr, st); /* map error */ - break; } - } - while (tm_bc != 0); - break; - -case MTC_SPACER: /* space reverse */ - do { - tm_bc = (tm_bc + 1) & 0177777; /* incr wc */ - if (st = sim_tape_sprecr (uptr, &tbc)) { /* spc rec rev, err? */ - r = tm_map_err (uptr, st); /* map error */ - break; } - } - while (tm_bc != 0); - break; } /* end case */ - -tm_cmd = (tm_cmd & ~MTC_EMA) | ((xma >> (16 - MTC_V_EMA)) & MTC_EMA); -tm_ca = xma & 0177777; /* update mem addr */ -tm_set_done (); /* set done */ -tm_updcsta (uptr); /* update status */ -if (DBG_LOG (LOG_TM)) fprintf (sim_log, - ">>TM: sta=%o, ma=%o, wc=%o, pos=%d\n", - tm_sta, tm_ca, tm_bc, uptr->pos); -return r; -} - -/* Update controller status */ - -int32 tm_updcsta (UNIT *uptr) -{ -tm_sta = (tm_sta & ~(STA_DYN | STA_CLR)) | (uptr->USTAT & STA_DYN); -if (sim_is_active (uptr)) tm_sta = tm_sta & ~STA_TUR; -else tm_sta = tm_sta | STA_TUR; -if (tm_sta & STA_EFLGS) tm_cmd = tm_cmd | MTC_ERR; -else tm_cmd = tm_cmd & ~MTC_ERR; -if ((tm_cmd & MTC_IE) == 0) CLR_INT (TM); -return tm_sta; -} - -/* Set done */ - -void tm_set_done (void) -{ -tm_cmd = tm_cmd | MTC_DONE; -if (tm_cmd & MTC_IE) SET_INT (TM); -return; -} - -/* Map tape error status */ - -t_stat tm_map_err (UNIT *uptr, t_stat st) -{ -switch (st) { -case MTSE_FMT: /* illegal fmt */ -case MTSE_UNATT: /* not attached */ - tm_sta = tm_sta | STA_ILL; -case MTSE_OK: /* no error */ - return SCPE_IERR; -case MTSE_TMK: /* tape mark */ - uptr->USTAT = uptr->USTAT | STA_EOF; /* end of file */ - break; -case MTSE_IOERR: /* IO error */ - tm_sta = tm_sta | STA_PAR; /* parity error */ - if (tm_stopioe) return SCPE_IOERR; - break; -case MTSE_INVRL: /* invalid rec lnt */ - tm_sta = tm_sta | STA_PAR; /* parity error */ - return SCPE_MTRLNT; -case MTSE_RECE: /* record in error */ - tm_sta = tm_sta | STA_PAR; /* parity error */ - break; -case MTSE_EOM: /* end of medium */ - tm_sta = tm_sta | STA_BAD; /* bad tape */ - break; -case MTSE_BOT: /* reverse into BOT */ - uptr->USTAT = uptr->USTAT | STA_BOT; /* set status */ - break; -case MTSE_WRP: /* write protect */ - tm_sta = tm_sta | STA_ILL; /* illegal operation */ - break; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tm_reset (DEVICE *dptr) -{ -int32 u; -UNIT *uptr; - -tm_cmd = MTC_DONE; /* set done */ -tm_bc = tm_ca = tm_db = tm_sta = tm_rdl = 0; -CLR_INT (TM); /* clear interrupt */ -for (u = 0; u < TM_NUMDR; u++) { /* loop thru units */ - uptr = tm_dev.units + u; - sim_tape_reset (uptr); /* reset tape */ - sim_cancel (uptr); /* cancel activity */ - if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_ONL | - (sim_tape_bot (uptr)? STA_BOT: 0) | - (sim_tape_wrp (uptr)? STA_WLK: 0); - else uptr->USTAT = 0; } -if (tmxb == NULL) tmxb = calloc (MT_MAXFR, sizeof (unsigned int8)); -if (tmxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat tm_attach (UNIT *uptr, char *cptr) -{ -t_stat r; -int32 u = uptr - tm_dev.units; - -r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; -uptr->USTAT = STA_ONL | STA_BOT | (sim_tape_wrp (uptr)? STA_WLK: 0); -if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr); -return r; -} - -/* Detach routine */ - -t_stat tm_detach (UNIT* uptr) -{ -int32 u = uptr - tm_dev.units; - -if (!sim_is_active (uptr)) uptr->USTAT = 0; -if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr); -return sim_tape_detach (uptr); -} - -/* Write lock/enable routine */ - -t_stat tm_vlock (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 u = uptr - tm_dev.units; - -if ((uptr->flags & UNIT_ATT) && - (val || sim_tape_wrp (uptr))) - uptr->USTAT = uptr->USTAT | STA_WLK; -else uptr->USTAT = uptr->USTAT & ~STA_WLK; -if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr); -return SCPE_OK; -} - -/* Device bootstrap - - Magtape boot format changed over time. Originally, a boot tape - contained a boot loader in the first block. Eventually, the first - block was reserved for a tape label, and the second block was - expected to contain a boot loader. BSD and DEC operating systems - use the second block scheme, so it is the default. - - To boot from the first block, use boot -o (old). -*/ - -#define BOOT_START 016000 -#define BOOT_ENTRY (BOOT_START + 2) -#define BOOT_UNIT (BOOT_START + 010) -#define BOOT_CSR (BOOT_START + 014) -#define BOOT1_LEN (sizeof (boot1_rom) / sizeof (int16)) -#define BOOT2_LEN (sizeof (boot2_rom) / sizeof (int16)) - -static const uint16 boot1_rom[] = { - 0046524, /* boot_start: "TM" */ - 0012706, BOOT_START, /* mov #boot_start, sp */ - 0012700, 0000000, /* mov #unit_num, r0 */ - 0012701, 0172526, /* mov #172526, r1 ; mtcma */ - 0005011, /* clr (r1) */ - 0010141, /* mov r1, -(r1) ; mtbrc */ - 0010002, /* mov r0,r2 */ - 0000302, /* swab r2 */ - 0062702, 0060003, /* add #60003, r2 */ - 0010241, /* mov r2, -(r1) ; read + go */ - 0105711, /* tstb (r1) ; mtc */ - 0100376, /* bpl .-2 */ - 0005002, /* clr r2 */ - 0005003, /* clr r3 */ - 0012704, BOOT_START+020, /* mov #boot_start+20, r4 */ - 0005005, /* clr r5 */ - 0005007 /* clr r7 */ -}; - -static const uint16 boot2_rom[] = { - 0046524, /* boot_start: "TM" */ - 0012706, BOOT_START, /* mov #boot_start, sp */ - 0012700, 0000000, /* mov #unit_num, r0 */ - 0012701, 0172526, /* mov #172526, r1 ; mtcma */ - 0005011, /* clr (r1) */ - 0012741, 0177777, /* mov #-1, -(r1) ; mtbrc */ - 0010002, /* mov r0,r2 */ - 0000302, /* swab r2 */ - 0062702, 0060011, /* add #60011, r2 */ - 0010241, /* mov r2, -(r1) ; space + go */ - 0105711, /* tstb (r1) ; mtc */ - 0100376, /* bpl .-2 */ - 0010002, /* mov r0,r2 */ - 0000302, /* swab r2 */ - 0062702, 0060003, /* add #60003, r2 */ - 0010211, /* mov r2, (r1) ; read + go */ - 0105711, /* tstb (r1) ; mtc */ - 0100376, /* bpl .-2 */ - 0005002, /* clr r2 */ - 0005003, /* clr r3 */ - 0012704, BOOT_START+020, /* mov #boot_start+20, r4 */ - 0005005, /* clr r5 */ - 0005007 /* clr r7 */ -}; - -t_stat tm_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; -extern int32 sim_switches; - -sim_tape_rewind (&tm_unit[unitno]); -if (sim_switches & SWMASK ('O')) { - for (i = 0; i < BOOT1_LEN; i++) - M[(BOOT_START >> 1) + i] = boot1_rom[i]; } -else { for (i = 0; i < BOOT2_LEN; i++) - M[(BOOT_START >> 1) + i] = boot2_rom[i]; } -M[BOOT_UNIT >> 1] = unitno; -M[BOOT_CSR >> 1] = (tm_dib.ba & DMASK) + 06; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} diff --git a/PDP11/pdp11_tq.c b/PDP11/pdp11_tq.c deleted file mode 100644 index d310372b..00000000 --- a/PDP11/pdp11_tq.c +++ /dev/null @@ -1,2010 +0,0 @@ -/* pdp11_tq.c: TMSCP tape controller simulator - - Copyright (c) 2002-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - tq TQK50 tape controller - - 19-May-03 RMS Revised for new conditional compilation scheme - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Added variable controller, user-defined drive support - 26-Feb-03 RMS Fixed bug in vector calculation for VAXen - 22-Feb-03 RMS Fixed ordering bug in queue process - Fixed flags table to allow MD_CSE everywhere - 09-Jan-03 RMS Fixed bug in transfer end packet status - 17-Oct-02 RMS Fixed bug in read reverse (found by Hans Pufal) -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#error "TQK50 not supported on PDP-10!" - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -extern int32 cpu_18b, cpu_ubm; -#endif - -#include "pdp11_uqssp.h" -#include "pdp11_mscp.h" -#include "sim_tape.h" - -#define UF_MSK (UF_SCH|UF_VSS|UF_CMR|UF_CMW) /* settable flags */ - -#define TQ_SH_MAX 24 /* max display wds */ -#define TQ_SH_PPL 8 /* wds per line */ -#define TQ_SH_DPL 4 /* desc per line */ -#define TQ_SH_RI 001 /* show rings */ -#define TQ_SH_FR 002 /* show free q */ -#define TQ_SH_RS 004 /* show resp q */ -#define TQ_SH_UN 010 /* show unit q's */ - -#define TQ_CLASS 1 /* TQK50 class */ -#define TQ_DHTMO 0 /* def host timeout */ -#define TQ_DCTMO 120 /* def ctrl timeout */ -#define TQ_NUMDR 4 /* # drives */ -#define TQ_MAXFR (1 << 16) /* max xfer */ - -#define UNIT_V_ONL (MTUF_V_UF + 0) /* online */ -#define UNIT_V_ATP (MTUF_V_UF + 1) /* attn pending */ -#define UNIT_V_SXC (MTUF_V_UF + 2) /* serious exc */ -#define UNIT_V_POL (MTUF_V_UF + 3) /* position lost */ -#define UNIT_V_TMK (MTUF_V_UF + 4) /* tape mark seen */ -#define UNIT_ONL (1 << UNIT_V_ONL) -#define UNIT_ATP (1 << UNIT_V_ATP) -#define UNIT_SXC (1 << UNIT_V_SXC) -#define UNIT_POL (1 << UNIT_V_POL) -#define UNIT_TMK (1 << UNIT_V_TMK) -#define cpkt u3 /* current packet */ -#define pktq u4 /* packet queue */ -#define uf buf /* settable unit flags */ -#define objp wait /* object position */ -#define TQ_WPH(u) (sim_tape_wrp (u)) - -#define CST_S1 0 /* init stage 1 */ -#define CST_S1_WR 1 /* stage 1 wrap */ -#define CST_S2 2 /* init stage 2 */ -#define CST_S3 3 /* init stage 3 */ -#define CST_S3_PPA 4 /* stage 3 sa wait */ -#define CST_S3_PPB 5 /* stage 3 ip wait */ -#define CST_S4 6 /* stage 4 */ -#define CST_UP 7 /* online */ -#define CST_DEAD 8 /* fatal error */ - -#define tq_comm tq_rq.ba - -#define ERR 0 /* must be SCPE_OK! */ -#define OK 1 - -#define CMF_IMM 0x10000 /* immediate */ -#define CMF_SEQ 0x20000 /* sequential */ -#define CMF_WR 0x40000 /* write */ -#define CMF_RW 0x80000 /* resp to GCS */ - -/* Internal packet management */ - -#define TQ_NPKTS 32 /* # packets (pwr of 2) */ -#define TQ_M_NPKTS (TQ_NPKTS - 1) /* mask */ -#define TQ_PKT_SIZE_W 32 /* payload size (wds) */ -#define TQ_PKT_SIZE (TQ_PKT_SIZE_W * sizeof (int16)) - -struct tqpkt { - int16 link; /* link to next */ - uint16 d[TQ_PKT_SIZE_W]; }; /* data */ - -/* Packet payload extraction and insertion */ - -#define GETP(p,w,f) ((tq_pkt[p].d[w] >> w##_V_##f) & w##_M_##f) -#define GETP32(p,w) (((uint32) tq_pkt[p].d[w]) | \ - (((uint32) tq_pkt[p].d[(w)+1]) << 16)) -#define PUTP32(p,w,x) tq_pkt[p].d[w] = (x) & 0xFFFF; \ - tq_pkt[p].d[(w)+1] = ((x) >> 16) & 0xFFFF - -/* Controller and device types - TQK50 must be swre rev 5 or later */ - -#define TQ5_TYPE 0 /* TK50 */ -#define TQ5_UQPM 3 /* UQ port ID */ -#define TQ5_CMOD 9 /* ctrl ID */ -#define TQ5_UMOD 3 /* unit ID */ -#define TQ5_MED 0x6D68B032 /* media ID */ -#define TQ5_CREV ((1 << 8) | 5) /* ctrl revs */ -#define TQ5_FREV 0 /* formatter revs */ -#define TQ5_UREV 0 /* unit revs */ -#define TQ5_CAP (94 * (1 << 20)) /* capacity */ -#define TQ5_FMT (TF_CTP|TF_CTP_LO) /* menu */ - -#define TQ7_TYPE 1 /* TK70 */ -#define TQ7_UQPM 14 /* UQ port ID */ -#define TQ7_CMOD 14 /* ctrl ID */ -#define TQ7_UMOD 11 /* unit ID */ -#define TQ7_MED 0x6A68B046 /* media ID */ -#define TQ7_CREV ((1 << 8) | 5) /* ctrl revs */ -#define TQ7_FREV 0 /* formatter revs */ -#define TQ7_UREV 0 /* unit revs */ -#define TQ7_CAP (300 * (1 << 20)) /* capacity */ -#define TQ7_FMT (TF_CTP|TF_CTP_LO) /* menu */ - -#define TQ8_TYPE 2 /* TU81 */ -#define TQ8_UQPM 5 /* UQ port ID */ -#define TQ8_CMOD 5 /* ctrl ID */ -#define TQ8_UMOD 2 /* unit ID */ -#define TQ8_MED 0x6D695051 /* media ID */ -#define TQ8_CREV ((1 << 8) | 5) /* ctrl revs */ -#define TQ8_FREV 0 /* formatter revs */ -#define TQ8_UREV 0 /* unit revs */ -#define TQ8_CAP (180 * (1 << 20)) /* capacity */ -#define TQ8_FMT (TF_9TK|TF_9TK_GRP) /* menu */ - -#define TQU_TYPE 3 /* TKuser defined */ -#define TQU_UQPM 3 /* UQ port ID */ -#define TQU_CMOD 9 /* ctrl ID */ -#define TQU_UMOD 3 /* unit ID */ -#define TQU_MED 0x6D68B032 /* media ID */ -#define TQU_CREV ((1 << 8) | 5) /* ctrl revs */ -#define TQU_FREV 0 /* formatter revs */ -#define TQU_UREV 0 /* unit revs */ -#define TQU_CAP (94 * (1 << 20)) /* capacity */ -#define TQU_FMT (TF_CTP|TF_CTP_LO) /* menu */ -#define TQU_MINC 30 /* min cap MB */ -#define TQU_MAXC 2000 /* max cap MB */ -#define TQU_EMAXC 2000000000 /* ext max cap MB */ - -#define TQ_DRV(d) \ - d##_UQPM, \ - d##_CMOD, d##_MED, d##_FMT, d##_CAP, \ - d##_UMOD, d##_CREV, d##_FREV, d##_UREV - -#define TEST_EOT(u) (sim_tape_eot (u, drv_tab[tq_typ].cap)) - -struct drvtyp { - uint32 uqpm; /* UQ port model */ - uint32 cmod; /* ctrl model */ - uint32 med; /* MSCP media */ - uint32 fmt; /* flags */ - t_addr cap; /* capacity */ - uint32 umod; /* unit model */ - uint32 cver; - uint32 fver; - uint32 uver; - char *name; -}; - -static struct drvtyp drv_tab[] = { - { TQ_DRV (TQ5), "TK50" }, - { TQ_DRV (TQ7), "TK70" }, - { TQ_DRV (TQ8), "TU81" }, - { TQ_DRV (TQU), "TKUSER" }, -}; - -/* Data */ - -extern int32 int_req[IPL_HLVL]; -extern int32 tmr_poll, clk_tps; -extern int32 cpu_log; -extern UNIT cpu_unit; -extern FILE *sim_log; -extern uint32 sim_taddr_64; - -uint8 *tqxb = NULL; /* xfer buffer */ -uint32 tq_sa = 0; /* status, addr */ -uint32 tq_saw = 0; /* written data */ -uint32 tq_s1dat = 0; /* S1 data */ -uint32 tq_csta = 0; /* ctrl state */ -uint32 tq_perr = 0; /* last error */ -uint32 tq_cflgs = 0; /* ctrl flags */ -uint32 tq_prgi = 0; /* purge int */ -uint32 tq_pip = 0; /* poll in progress */ -struct uq_ring tq_cq = { 0 }; /* cmd ring */ -struct uq_ring tq_rq = { 0 }; /* rsp ring */ -struct tqpkt tq_pkt[TQ_NPKTS]; /* packet queue */ -int32 tq_freq = 0; /* free list */ -int32 tq_rspq = 0; /* resp list */ -uint32 tq_pbsy = 0; /* #busy pkts */ -uint32 tq_credits = 0; /* credits */ -uint32 tq_hat = 0; /* host timer */ -uint32 tq_htmo = TQ_DHTMO; /* host timeout */ -int32 tq_itime = 200; /* init time, except */ -int32 tq_itime4 = 10; /* stage 4 */ -int32 tq_qtime = 200; /* queue time */ -int32 tq_xtime = 500; /* transfer time */ -int32 tq_typ = TQ5_TYPE; /* device type */ - -/* Command table - legal modifiers (low 16b) and flags (high 16b) */ - -static uint32 tq_cmf[64] = { - 0, /* 0 */ - CMF_IMM, /* abort */ - CMF_IMM|MD_CSE, /* get cmd status */ - CMF_IMM|MD_CSE|MD_NXU, /* get unit status */ - CMF_IMM|MD_CSE, /* set ctrl char */ - 0, 0, 0, /* 5-7 */ - CMF_SEQ|MD_ACL|MD_CDL|MD_CSE|MD_EXA|MD_UNL, /* available */ - CMF_SEQ|MD_CDL|MD_CSE|MD_SWP|MD_EXA, /* online */ - CMF_SEQ|MD_CDL|MD_CSE|MD_SWP|MD_EXA, /* set unit char */ - CMF_IMM, /* define acc paths */ - 0, 0, 0, 0, /* 12-15 */ - CMF_SEQ|CMF_RW|MD_CDL|MD_CSE|MD_REV| /* access */ - MD_SCH|MD_SEC|MD_SER, - 0, /* 17 */ - CMF_SEQ|CMF_WR|MD_CDL|MD_CSE|MD_IMM, /* erase */ - CMF_SEQ|CMF_WR|MD_CDL|MD_CSE, /* flush */ - 0, 0, /* 20-21 */ - CMF_SEQ|CMF_WR|MD_CDL|MD_CSE|MD_IMM, /* erase gap */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 22-31 */ - CMF_SEQ|CMF_RW|MD_CDL|MD_CSE|MD_REV| /* compare */ - MD_SCH|MD_SEC|MD_SER, - CMF_SEQ|CMF_RW|MD_CDL|MD_CSE|MD_REV|MD_CMP| /* read */ - MD_SCH|MD_SEC|MD_SER, - CMF_SEQ|CMF_RW|CMF_WR|MD_CDL|MD_CSE|MD_IMM| /* write */ - MD_CMP|MD_ERW|MD_SEC|MD_SER, - 0, /* 35 */ - CMF_SEQ|MD_CDL|MD_CSE|MD_IMM, /* wr tape mark */ - CMF_SEQ|MD_CDL|MD_CSE|MD_IMM|MD_OBC| /* reposition */ - MD_REV|MD_RWD|MD_DLE| - MD_SCH|MD_SEC|MD_SER, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 38-47 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }; - -/* Forward references */ - -DEVICE tq_dev; - -t_stat tq_rd (int32 *data, int32 PA, int32 access); -t_stat tq_wr (int32 data, int32 PA, int32 access); -t_stat tq_inta (void); -t_stat tq_svc (UNIT *uptr); -t_stat tq_tmrsvc (UNIT *uptr); -t_stat tq_quesvc (UNIT *uptr); -t_stat tq_reset (DEVICE *dptr); -t_stat tq_attach (UNIT *uptr, char *cptr); -t_stat tq_detach (UNIT *uptr); -t_stat tq_boot (int32 unitno, DEVICE *dptr); -t_stat tq_set_wlk (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat tq_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat tq_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat tq_show_unitq (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat tq_set_type (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat tq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc); - -t_bool tq_step4 (void); -t_bool tq_mscp (int32 pkt, t_bool q); -t_bool tq_abo (int32 pkt); -t_bool tq_avl (int32 pkt); -t_bool tq_erase (int32 pkt); -t_bool tq_flu (int32 pkt); -t_bool tq_gcs (int32 pkt); -t_bool tq_gus (int32 pkt); -t_bool tq_onl (int32 pkt); -t_bool tq_pos (int32 pkt); -t_bool tq_rw (int32 pkt); -t_bool tq_scc (int32 pkt); -t_bool tq_suc (int32 pkt); -t_bool tq_wtm (int32 pkt); -t_bool tq_plf (uint32 err); -t_bool tq_dte (UNIT *uptr, uint32 err); -t_bool tq_hbe (UNIT *uptr, uint32 ba); -t_bool tq_una (UNIT *uptr); -uint32 tq_map_status (UNIT *uptr, t_stat st); -uint32 tq_spacef (UNIT *uptr, uint32 cnt, uint32 *skipped, t_bool qrec); -uint32 tq_skipff (UNIT *uptr, uint32 cnt, uint32 *skipped); -uint32 tq_rdbuff (UNIT *uptr, t_mtrlnt *tbc); -uint32 tq_spacer (UNIT *uptr, uint32 cnt, uint32 *skipped, t_bool qrec); -uint32 tq_skipfr (UNIT *uptr, uint32 cnt, uint32 *skipped); -uint32 tq_rdbufr (UNIT *uptr, t_mtrlnt *tbc); -t_bool tq_deqf (int32 *pkt); -int32 tq_deqh (int32 *lh); -void tq_enqh (int32 *lh, int32 pkt); -void tq_enqt (int32 *lh, int32 pkt); -t_bool tq_getpkt (int32 *pkt); -t_bool tq_putpkt (int32 pkt, t_bool qt); -t_bool tq_getdesc (struct uq_ring *ring, uint32 *desc); -t_bool tq_putdesc (struct uq_ring *ring, uint32 desc); -int32 tq_mot_valid (UNIT *uptr, uint32 cmd); -t_stat tq_mot_err (UNIT *uptr, uint32 rsiz); -t_bool tq_mot_end (UNIT *uptr, uint32 flg, uint32 sts, uint32 rsiz); -void tq_putr (int32 pkt, uint32 cmd, uint32 flg, uint32 sts, uint32 lnt, uint32 typ); -void tq_putr_unit (int32 pkt, UNIT *uptr, uint32 lu, t_bool all); -void tq_setf_unit (int32 pkt, UNIT *uptr); -uint32 tq_efl (UNIT *uptr); -void tq_init_int (void); -void tq_ring_int (struct uq_ring *ring); -t_bool tq_fatal (uint32 err); -UNIT *tq_getucb (uint32 lu); - -/* TQ data structures - - tq_dev TQ device descriptor - tq_unit TQ unit list - tq_reg TQ register list - tq_mod TQ modifier list -*/ - -DIB tq_dib = { IOBA_TQ, IOLN_TQ, &tq_rd, &tq_wr, - 1, IVCL (TQ), 0, { &tq_inta } }; - -UNIT tq_unit[] = { - { UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), 0 }, - { UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), 0 }, - { UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), 0 }, - { UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), 0 }, - { UDATA (&tq_tmrsvc, UNIT_DIS, 0) }, - { UDATA (&tq_quesvc, UNIT_DIS, 0) } }; - -#define TQ_TIMER (TQ_NUMDR) -#define TQ_QUEUE (TQ_TIMER + 1) - -REG tq_reg[] = { - { GRDATA (SA, tq_sa, DEV_RDX, 16, 0) }, - { GRDATA (SAW, tq_saw, DEV_RDX, 16, 0) }, - { GRDATA (S1DAT, tq_s1dat, DEV_RDX, 16, 0) }, - { GRDATA (CQBA, tq_cq.ba, DEV_RDX, 22, 0) }, - { GRDATA (CQLNT, tq_cq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (CQIDX, tq_cq.idx, DEV_RDX, 8, 2) }, - { GRDATA (TQBA, tq_rq.ba, DEV_RDX, 22, 0) }, - { GRDATA (TQLNT, tq_rq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (TQIDX, tq_rq.idx, DEV_RDX, 8, 2) }, - { DRDATA (FREE, tq_freq, 5) }, - { DRDATA (RESP, tq_rspq, 5) }, - { DRDATA (PBSY, tq_pbsy, 5) }, - { GRDATA (CFLGS, tq_cflgs, DEV_RDX, 16, 0) }, - { GRDATA (CSTA, tq_csta, DEV_RDX, 4, 0) }, - { GRDATA (PERR, tq_perr, DEV_RDX, 9, 0) }, - { DRDATA (CRED, tq_credits, 5) }, - { DRDATA (HAT, tq_hat, 17) }, - { DRDATA (HTMO, tq_htmo, 17) }, - { URDATA (CPKT, tq_unit[0].cpkt, 10, 5, 0, TQ_NUMDR, 0) }, - { URDATA (PKTQ, tq_unit[0].pktq, 10, 5, 0, TQ_NUMDR, 0) }, - { URDATA (UFLG, tq_unit[0].uf, DEV_RDX, 16, 0, TQ_NUMDR, 0) }, - { URDATA (POS, tq_unit[0].pos, 10, T_ADDR_W, 0, TQ_NUMDR, 0) }, - { URDATA (OBJP, tq_unit[0].objp, 10, 32, 0, TQ_NUMDR, 0) }, - { FLDATA (PRGI, tq_prgi, 0), REG_HIDDEN }, - { FLDATA (PIP, tq_pip, 0), REG_HIDDEN }, - { FLDATA (INT, IREQ (TQ), INT_V_TQ) }, - { DRDATA (ITIME, tq_itime, 24), PV_LEFT + REG_NZ }, - { DRDATA (I4TIME, tq_itime4, 24), PV_LEFT + REG_NZ }, - { DRDATA (QTIME, tq_qtime, 24), PV_LEFT + REG_NZ }, - { DRDATA (XTIME, tq_xtime, 24), PV_LEFT + REG_NZ }, - { BRDATA (PKTS, tq_pkt, DEV_RDX, 16, TQ_NPKTS * (TQ_PKT_SIZE_W + 1)) }, - { DRDATA (DEVTYPE, tq_typ, 2), REG_HRO }, - { DRDATA (DEVCAP, drv_tab[TQU_TYPE].cap, T_ADDR_W), PV_LEFT | REG_HRO }, - { GRDATA (DEVADDR, tq_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, tq_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -MTAB tq_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD | MTAB_VDV, TQ5_TYPE, NULL, "TK50", - &tq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, TQ7_TYPE, NULL, "TK70", - &tq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, TQ8_TYPE, NULL, "TU81", - &tq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, TQU_TYPE, NULL, "TKUSER", - &tq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL, - NULL, &tq_show_type, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, TQ_SH_RI, "RINGS", NULL, - NULL, &tq_show_ctrl, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, TQ_SH_FR, "FREEQ", NULL, - NULL, &tq_show_ctrl, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, TQ_SH_RS, "RESPQ", NULL, - NULL, &tq_show_ctrl, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, TQ_SH_UN, "UNITQ", NULL, - NULL, &tq_show_ctrl, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, -1, "ALL", NULL, - NULL, &tq_show_ctrl, NULL }, - { MTAB_XTD | MTAB_VUN | MTAB_NMO, 0, "UNITQ", NULL, - NULL, &tq_show_unitq, NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, -#if defined (VM_PDP11) - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, -#else - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", NULL, - NULL, &show_addr, NULL }, -#endif - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; - -DEVICE tq_dev = { - "TQ", tq_unit, tq_reg, tq_mod, - TQ_NUMDR + 2, 10, 31, 1, DEV_RDX, 8, - NULL, NULL, &tq_reset, - &tq_boot, &tq_attach, &tq_detach, - &tq_dib, DEV_DISABLE | DEV_UBUS | DEV_QBUS }; - -/* I/O dispatch routine, I/O addresses 17772150 - 17772152 - - 17772150 IP read/write - 17772152 SA read/write -*/ - -t_stat tq_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* IP */ - *data = 0; /* reads zero */ - if (tq_csta == CST_S3_PPB) tq_step4 (); /* waiting for poll? */ - else if (tq_csta == CST_UP) { /* if up */ - tq_pip = 1; /* poll host */ - sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); } - break; -case 1: /* SA */ - *data = tq_sa; - break; } -return SCPE_OK; -} - -t_stat tq_wr (int32 data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* IP */ - tq_reset (&tq_dev); /* init device */ - if (DBG_LOG (LOG_TQ)) fprintf (sim_log, - ">>TQ: initialization started, time=%.0f\n", sim_gtime ()); - break; -case 1: /* SA */ - tq_saw = data; - if (tq_csta < CST_S4) /* stages 1-3 */ - sim_activate (&tq_unit[TQ_QUEUE], tq_itime); - else if (tq_csta == CST_S4) /* stage 4 (fast) */ - sim_activate (&tq_unit[TQ_QUEUE], tq_itime4); - break; } -return SCPE_OK; -} - -/* Transition to step 4 - init communications region */ - -t_bool tq_step4 (void) -{ -int32 i, lnt; -uint32 base; -uint16 zero[SA_COMM_MAX >> 1]; - -tq_rq.ioff = SA_COMM_RI; /* set intr offset */ -tq_rq.ba = tq_comm; /* set rsp q base */ -tq_rq.lnt = SA_S1H_RQ (tq_s1dat) << 2; /* get resp q len */ -tq_cq.ioff = SA_COMM_CI; /* set intr offset */ -tq_cq.ba = tq_comm + tq_rq.lnt; /* set cmd q base */ -tq_cq.lnt = SA_S1H_CQ (tq_s1dat) << 2; /* get cmd q len */ -tq_cq.idx = tq_rq.idx = 0; /* clear q idx's */ -if (tq_prgi) base = tq_comm + SA_COMM_QQ; -else base = tq_comm + SA_COMM_CI; -lnt = tq_comm + tq_cq.lnt + tq_rq.lnt - base; /* comm lnt */ -if (lnt > SA_COMM_MAX) lnt = SA_COMM_MAX; /* paranoia */ -for (i = 0; i < (lnt >> 1); i++) zero[i] = 0; /* clr buffer */ -if (Map_WriteW (base, lnt, zero, MAP)) /* zero comm area */ - return tq_fatal (PE_QWE); /* error? */ -tq_sa = SA_S4 | (drv_tab[tq_typ].uqpm << SA_S4C_V_MOD) |/* send step 4 */ - ((drv_tab[tq_typ].cver & 0xFF) << SA_S4C_V_VER); -tq_csta = CST_S4; /* set step 4 */ -tq_init_int (); /* poke host */ -return OK; -} - -/* Queue service - invoked when any of the queues (host queue, unit - queues, response queue) require servicing. Also invoked during - initialization to provide some delay to the next step. - - Process at most one item off each unit queue - If the unit queues were empty, process at most one item off the host queue - Process at most one item off the response queue - - If all queues are idle, terminate thread -*/ - -t_stat tq_quesvc (UNIT *uptr) -{ -int32 i, cnid; -int32 pkt = 0; -UNIT *nuptr; - -if (tq_csta < CST_UP) { /* still init? */ - switch (tq_csta) { /* controller state? */ - case CST_S1: /* need S1 reply */ - if (tq_saw & SA_S1H_VL) { /* valid? */ - if (tq_saw & SA_S1H_WR) { /* wrap? */ - tq_sa = tq_saw; /* echo data */ - tq_csta = CST_S1_WR; } /* endless loop */ - else { - tq_s1dat = tq_saw; /* save data */ - tq_dib.vec = (tq_s1dat & SA_S1H_VEC) << 2; /* get vector */ - if (tq_dib.vec) tq_dib.vec = tq_dib.vec + VEC_Q; /* if nz, bias */ - tq_sa = SA_S2 | SA_S2C_PT | SA_S2C_EC (tq_s1dat); - tq_csta = CST_S2; /* now in step 2 */ - tq_init_int (); } /* intr if req */ - } /* end if valid */ - break; - case CST_S1_WR: /* wrap mode */ - tq_sa = tq_saw; /* echo data */ - break; - case CST_S2: /* need S2 reply */ - tq_comm = tq_saw & SA_S2H_CLO; /* get low addr */ - tq_prgi = tq_saw & SA_S2H_PI; /* get purge int */ - tq_sa = SA_S3 | SA_S3C_EC (tq_s1dat); - tq_csta = CST_S3; /* now in step 3 */ - tq_init_int (); /* intr if req */ - break; - case CST_S3: /* need S3 reply */ - tq_comm = ((tq_saw & SA_S3H_CHI) << 16) | tq_comm; - if (tq_saw & SA_S3H_PP) { /* purge/poll test? */ - tq_sa = 0; /* put 0 */ - tq_csta = CST_S3_PPA; } /* wait for 0 write */ - else tq_step4 (); /* send step 4 */ - break; - case CST_S3_PPA: /* need purge test */ - if (tq_saw) tq_fatal (PE_PPF); /* data not zero? */ - else tq_csta = CST_S3_PPB; /* wait for poll */ - break; - case CST_S4: /* need S4 reply */ - if (tq_saw & SA_S4H_GO) { /* go set? */ - if (DBG_LOG (LOG_TQ)) fprintf (sim_log, - ">>TQ: initialization complete\n"); - tq_csta = CST_UP; /* we're up */ - tq_sa = 0; /* clear SA */ - sim_activate (&tq_unit[TQ_TIMER], tmr_poll * clk_tps); - if ((tq_saw & SA_S4H_LF) && tq_perr) tq_plf (tq_perr); - tq_perr = 0; } - break; } /* end switch */ - return SCPE_OK; } /* end if */ - -for (i = 0; i < TQ_NUMDR; i++) { /* chk unit q's */ - nuptr = tq_dev.units + i; /* ptr to unit */ - if (nuptr->cpkt || (nuptr->pktq == 0)) continue; - pkt = tq_deqh (&nuptr->pktq); /* get top of q */ - if (!tq_mscp (pkt, FALSE)) return SCPE_OK; } /* process */ -if ((pkt == 0) && tq_pip) { /* polling? */ - if (!tq_getpkt (&pkt)) return SCPE_OK; /* get host pkt */ - if (pkt) { /* got one? */ - if (DBG_LOG (LOG_TQ)) { - UNIT *up = tq_getucb (tq_pkt[pkt].d[CMD_UN]); - fprintf (sim_log, ">>TQ: cmd=%04X, mod=%04X, unit=%d, ", - tq_pkt[pkt].d[CMD_OPC], tq_pkt[pkt].d[CMD_MOD], tq_pkt[pkt].d[CMD_UN]); - fprintf (sim_log, "bc=%04X%04X, ma=%04X%04X", - tq_pkt[pkt].d[RW_BCH], tq_pkt[pkt].d[RW_BCL], - tq_pkt[pkt].d[RW_BAH], tq_pkt[pkt].d[RW_BAL]); - if (up) fprintf (sim_log, ", pos=%d, obj=%d\n", up->pos, up->objp); - else fprintf (sim_log, "\n"); - fflush (sim_log); } - if (GETP (pkt, UQ_HCTC, TYP) != UQ_TYP_SEQ) /* seq packet? */ - return tq_fatal (PE_PIE); /* no, term thread */ - cnid = GETP (pkt, UQ_HCTC, CID); /* get conn ID */ - if (cnid == UQ_CID_TMSCP) { /* TMSCP packet? */ - if (!tq_mscp (pkt, TRUE)) return SCPE_OK; } /* proc, q non-seq */ - else if (cnid == UQ_CID_DUP) { /* DUP packet? */ - tq_putr (pkt, OP_END, 0, ST_CMD | I_OPCD, RSP_LNT, UQ_TYP_SEQ); - if (!tq_putpkt (pkt, TRUE)) return SCPE_OK; } /* ill cmd */ - else return tq_fatal (PE_ICI); /* no, term thread */ - } /* end if pkt */ - else tq_pip = 0; /* discontinue poll */ - } /* end if pip */ -if (tq_rspq) { /* resp q? */ - pkt = tq_deqh (&tq_rspq); /* get top of q */ - if (!tq_putpkt (pkt, FALSE)) return SCPE_OK; /* send to hst */ - } /* end if resp q */ -if (pkt) sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); /* more to do? */ -return SCPE_OK; /* done */ -} - -/* Clock service (roughly once per second) */ - -t_stat tq_tmrsvc (UNIT *uptr) -{ -int32 i; -UNIT *nuptr; - -sim_activate (uptr, tmr_poll * clk_tps); /* reactivate */ -for (i = 0; i < TQ_NUMDR; i++) { /* poll */ - nuptr = tq_dev.units + i; - if ((nuptr->flags & UNIT_ATP) && /* ATN pending? */ - (nuptr->flags & UNIT_ATT) && /* still online? */ - (tq_cflgs & CF_ATN)) { /* wanted? */ - if (!tq_una (nuptr)) return SCPE_OK; } - nuptr->flags = nuptr->flags & ~UNIT_ATP; } -if ((tq_hat > 0) && (--tq_hat == 0)) /* host timeout? */ - tq_fatal (PE_HAT); /* fatal err */ -return SCPE_OK; -} - -/* MSCP packet handling */ - -t_bool tq_mscp (int32 pkt, t_bool q) -{ -uint32 sts; -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* command */ -uint32 flg = GETP (pkt, CMD_OPC, FLG); /* flags */ -uint32 mdf = tq_pkt[pkt].d[CMD_MOD]; /* modifier */ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -UNIT *uptr; - -if ((cmd >= 64) || (tq_cmf[cmd] == 0)) { /* invalid cmd? */ - cmd = OP_END; /* set end op */ - sts = ST_CMD | I_OPCD; } /* ill op */ -else if (flg) { /* flags? */ - cmd = cmd | OP_END; /* set end flag */ - sts = ST_CMD | I_FLAG; } /* ill flags */ -else if (mdf & ~tq_cmf[cmd]) { /* invalid mod? */ - cmd = cmd | OP_END; /* set end flag */ - sts = ST_CMD | I_MODF; } /* ill mods */ -else { /* valid cmd */ - if (uptr = tq_getucb (lu)) { /* valid unit? */ - if (q && (tq_cmf[cmd] & CMF_SEQ) && /* queueing, seq, */ - (uptr->cpkt || uptr->pktq)) { /* and active? */ - tq_enqt (&uptr->pktq, pkt); /* do later */ - return OK; } -/* if (tq_cmf[cmd] & MD_CDL) /* clr cch lost? */ -/* uptr->flags = uptr->flags & ~UNIT_CDL; */ - if (tq_cmf[cmd] & MD_CSE) /* clr ser exc? */ - uptr->flags = uptr->flags & ~UNIT_SXC; } - switch (cmd) { - case OP_ABO: /* abort */ - return tq_abo (pkt); - case OP_AVL: /* avail */ - return tq_avl (pkt); - case OP_GCS: /* get cmd status */ - return tq_gcs (pkt); - case OP_GUS: /* get unit status */ - return tq_gus (pkt); - case OP_ONL: /* online */ - return tq_onl (pkt); - case OP_SCC: /* set ctrl char */ - return tq_scc (pkt); - case OP_SUC: /* set unit char */ - return tq_suc (pkt); - case OP_ERS: /* erase */ - case OP_ERG: /* erase gap */ - return tq_erase (pkt); - case OP_FLU: /* flush */ - return tq_flu (pkt); - case OP_POS: /* position */ - return tq_pos (pkt); - case OP_WTM: /* write tape mark */ - return tq_wtm (pkt); - case OP_ACC: /* access */ - case OP_CMP: /* compare */ - case OP_RD: /* read */ - case OP_WR: /* write */ - return tq_rw (pkt); - case OP_DAP: - cmd = cmd | OP_END; /* set end flag */ - sts = ST_SUC; /* success */ - break; - default: - cmd = OP_END; /* set end op */ - sts = ST_CMD | I_OPCD; /* ill op */ - break; - } /* end switch */ - } /* end else */ -tq_putr (pkt, cmd, 0, sts, RSP_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Abort a command - 1st parameter is ref # of cmd to abort */ - -t_bool tq_abo (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 ref = GETP32 (pkt, ABO_REFL); /* cmd ref # */ -int32 tpkt, prv; -UNIT *uptr; - -tpkt = 0; /* set no mtch */ -if (uptr = tq_getucb (lu)) { /* get unit */ - if (uptr->cpkt && /* curr pkt? */ - (GETP32 (uptr->cpkt, CMD_REFL) == ref)) { /* match ref? */ - tpkt = uptr->cpkt; /* save match */ - uptr->cpkt = 0; /* gonzo */ - sim_cancel (uptr); /* cancel unit */ - sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); } - else if (uptr->pktq && /* head of q? */ - (GETP32 (uptr->pktq, CMD_REFL) == ref)) { /* match ref? */ - tpkt = uptr->pktq; /* save match */ - uptr->pktq = tq_pkt[tpkt].link; } /* unlink */ - else if (prv = uptr->pktq) { /* srch pkt q */ - while (tpkt = tq_pkt[prv].link) { /* walk list */ - if (GETP32 (tpkt, RSP_REFL) == ref) { /* match ref? */ - tq_pkt[prv].link = tq_pkt[tpkt].link; /* unlink */ - break; } } } - if (tpkt) { /* found target? */ - uint32 tcmd = GETP (tpkt, CMD_OPC, OPC); /* get opcode */ - tq_putr (tpkt, tcmd | OP_END, 0, ST_ABO, RSP_LNT, UQ_TYP_SEQ); - if (!tq_putpkt (tpkt, TRUE)) return ERR; } - } /* end if unit */ -tq_putr (pkt, OP_ABO | OP_END, 0, ST_SUC, ABO_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Unit available - set unit status to available - Deferred if q'd cmds, bypassed if ser exc */ - -t_bool tq_avl (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 mdf = tq_pkt[pkt].d[CMD_MOD]; /* modifiers */ -uint32 sts; -UNIT *uptr; - -if (uptr = tq_getucb (lu)) { /* unit exist? */ - if (uptr->flags & UNIT_SXC) sts = ST_SXC; /* ser exc pending? */ - else { - uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_TMK | UNIT_POL); - sim_tape_rewind (uptr); /* rewind */ - uptr->uf = uptr->objp = 0; /* clr flags */ - if (uptr->flags & UNIT_ATT) { /* attached? */ - sts = ST_SUC; /* success */ - if (mdf & MD_UNL) tq_detach (uptr); } /* unload? */ - else sts = ST_OFL | SB_OFL_NV; } } /* no, offline */ -else sts = ST_OFL; /* offline */ -tq_putr (pkt, OP_AVL | OP_END, tq_efl (uptr), sts, AVL_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Get command status - only interested in active xfr cmd */ - -t_bool tq_gcs (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 ref = GETP32 (pkt, GCS_REFL); /* ref # */ -int32 tpkt; -UNIT *uptr; - -if ((uptr = tq_getucb (lu)) && /* valid lu? */ - (tpkt = uptr->cpkt) && /* queued pkt? */ - (GETP32 (tpkt, CMD_REFL) == ref) && /* match ref? */ - (tq_cmf[GETP (tpkt, CMD_OPC, OPC)] & CMF_RW)) { /* rd/wr cmd? */ - tq_pkt[pkt].d[GCS_STSL] = tq_pkt[tpkt].d[RW_BCL]; - tq_pkt[pkt].d[GCS_STSH] = tq_pkt[tpkt].d[RW_BCH]; } -else tq_pkt[pkt].d[GCS_STSL] = tq_pkt[pkt].d[GCS_STSH] = 0; -tq_putr (pkt, OP_GCS | OP_END, 0, ST_SUC, GCS_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Get unit status */ - -t_bool tq_gus (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 sts; -UNIT *uptr; - -if (tq_pkt[pkt].d[CMD_MOD] & MD_NXU) { /* next unit? */ - if (lu >= TQ_NUMDR) { /* end of range? */ - lu = 0; /* reset to 0 */ - tq_pkt[pkt].d[RSP_UN] = lu; } } -if (uptr = tq_getucb (lu)) { /* unit exist? */ - if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - sts = ST_OFL | SB_OFL_NV; /* offl no vol */ - else if (uptr->flags & UNIT_ONL) sts = ST_SUC; /* online */ - else sts = ST_AVL; /* avail */ - tq_putr_unit (pkt, uptr, lu, FALSE); /* fill unit fields */ - tq_pkt[pkt].d[GUS_MENU] = drv_tab[tq_typ].fmt; /* format menu */ - tq_pkt[pkt].d[GUS_CAP] = 0; /* free capacity */ - tq_pkt[pkt].d[GUS_FVER] = drv_tab[tq_typ].fver; /* formatter version */ - tq_pkt[pkt].d[GUS_UVER] = drv_tab[tq_typ].uver; /* unit version */ - } -else sts = ST_OFL; /* offline */ -tq_putr (pkt, OP_GUS | OP_END, tq_efl (uptr), sts, GUS_LNT_T, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Unit online - deferred if q'd commands */ - -t_bool tq_onl (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 sts; -UNIT *uptr; - -if (uptr = tq_getucb (lu)) { /* unit exist? */ - if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - sts = ST_OFL | SB_OFL_NV; /* offl no vol */ - else if (uptr->flags & UNIT_ONL) /* already online? */ - sts = ST_SUC | SB_SUC_ON; - else { sts = ST_SUC; /* mark online */ - sim_tape_rewind (uptr); /* rewind */ - uptr->objp = 0; /* clear flags */ - uptr->flags = (uptr->flags | UNIT_ONL) & - ~(UNIT_TMK | UNIT_POL); /* onl, pos ok */ - tq_setf_unit (pkt, uptr); } /* hack flags */ - tq_putr_unit (pkt, uptr, lu, TRUE); } /* set fields */ -else sts = ST_OFL; /* offline */ -tq_putr (pkt, OP_ONL | OP_END, tq_efl (uptr), sts, ONL_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Set controller characteristics */ - -t_bool tq_scc (int32 pkt) -{ -if (tq_pkt[pkt].d[SCC_MSV]) /* MSCP ver = 0? */ - tq_putr (pkt, 0, 0, ST_CMD | I_VRSN, SCC_LNT, UQ_TYP_SEQ); -else { tq_cflgs = (tq_cflgs & CF_RPL) | /* hack ctrl flgs */ - tq_pkt[pkt].d[SCC_CFL]; - if (tq_htmo = tq_pkt[pkt].d[SCC_TMO]) /* set timeout */ - tq_htmo = tq_htmo + 2; /* if nz, round up */ - tq_pkt[pkt].d[SCC_CFL] = tq_cflgs; /* return flags */ - tq_pkt[pkt].d[SCC_TMO] = TQ_DCTMO; /* ctrl timeout */ - tq_pkt[pkt].d[SCC_VER] = drv_tab[tq_typ].cver; /* ctrl version */ - tq_pkt[pkt].d[SCC_CIDA] = 0; /* ctrl ID */ - tq_pkt[pkt].d[SCC_CIDB] = 0; - tq_pkt[pkt].d[SCC_CIDC] = 0; - tq_pkt[pkt].d[SCC_CIDD] = (TQ_CLASS << SCC_CIDD_V_CLS) | - (drv_tab[tq_typ].cmod << SCC_CIDD_V_MOD); - PUTP32 (pkt, SCC_MBCL, TQ_MAXFR); /* max bc */ - tq_putr (pkt, OP_SCC | OP_END, 0, ST_SUC, SCC_LNT, UQ_TYP_SEQ); - } -return tq_putpkt (pkt, TRUE); -} - -/* Set unit characteristics - defer if q'd commands */ - -t_bool tq_suc (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 sts; -UNIT *uptr; - -if (uptr = tq_getucb (lu)) { /* unit exist? */ - if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - sts = ST_OFL | SB_OFL_NV; /* offl no vol */ - else { sts = ST_SUC; /* avail or onl */ - tq_setf_unit (pkt, uptr); } /* hack flags */ - tq_putr_unit (pkt, uptr, lu, TRUE); } /* set fields */ -else sts = ST_OFL; /* offline */ -tq_putr (pkt, OP_SUC | OP_END, 0, sts, SUC_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Flush - sequential nop - deferred if q'd cmds, bypassed if ser exc */ - -t_bool tq_flu (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 sts; -UNIT *uptr; - -if (uptr = tq_getucb (lu)) { /* unit exist? */ - sts = tq_mot_valid (uptr, OP_FLU); } /* validate req */ -else sts = ST_OFL; /* offline */ -tq_putr (pkt, OP_FLU | OP_END, tq_efl (uptr), sts, FLU_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Erase, erase gap - deferred if q'd cmds, bypassed if ser exc */ - -t_bool tq_erase (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 sts; -UNIT *uptr; - -if (uptr = tq_getucb (lu)) { /* unit exist? */ - sts = tq_mot_valid (uptr, cmd); /* validity checks */ - if (sts == ST_SUC) { /* ok? */ - uptr->cpkt = pkt; /* op in progress */ - sim_activate (uptr, tq_xtime); /* activate */ - return OK; } } /* done */ -else sts = ST_OFL; /* offline */ -tq_putr (pkt, cmd | OP_END, tq_efl (uptr), sts, ERS_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Write tape mark - deferred if q'd cmds, bypassed if ser exc */ - -t_bool tq_wtm (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 sts, objp = 0; -UNIT *uptr; - -if (uptr = tq_getucb (lu)) { /* unit exist? */ - objp = uptr->objp; /* position op */ - sts = tq_mot_valid (uptr, OP_WTM); /* validity checks */ - if (sts == ST_SUC) { /* ok? */ - uptr->cpkt = pkt; /* op in progress */ - sim_activate (uptr, tq_xtime); /* activate */ - return OK; } } /* done */ -else sts = ST_OFL; /* offline */ -PUTP32 (pkt, WTM_POSL, objp); /* set obj pos */ -tq_putr (pkt, OP_WTM | OP_END, tq_efl (uptr), sts, WTM_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Position - deferred if q'd cmds, bypassed if ser exc */ - -t_bool tq_pos (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 sts, objp = 0; -UNIT *uptr; - -if (uptr = tq_getucb (lu)) { /* unit exist? */ - objp = uptr->objp; /* position op */ - sts = tq_mot_valid (uptr, OP_POS); /* validity checks */ - if (sts == ST_SUC) { /* ok? */ - uptr->cpkt = pkt; /* op in progress */ - sim_activate (uptr, tq_xtime); /* activate */ - return OK; } } /* done */ -else sts = ST_OFL; /* offline */ -PUTP32 (pkt, POS_RCL, 0); /* clear #skipped */ -PUTP32 (pkt, POS_TMCL, 0); -PUTP32 (pkt, POS_POSL, objp); /* set obj pos */ -tq_putr (pkt, OP_POS | OP_END, tq_efl (uptr), sts, POS_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Data transfer commands - deferred if q'd commands, bypassed if ser exc */ - -t_bool tq_rw (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 bc = GETP32 (pkt, RW_BCL); /* byte count */ -uint32 sts, objp = 0; -UNIT *uptr; - -if (uptr = tq_getucb (lu)) { /* unit exist? */ - objp = uptr->objp; /* position op */ - sts = tq_mot_valid (uptr, cmd); /* validity checks */ - if (sts == ST_SUC) { /* ok? */ - if ((bc == 0) || (bc > TQ_MAXFR)) { /* invalid? */ - uptr->flags = uptr->flags | UNIT_SXC; /* set ser exc */ - sts = ST_CMD | I_BCNT; } - else { - uptr->cpkt = pkt; /* op in progress */ - sim_activate (uptr, tq_xtime); /* activate */ - return OK; } } } /* done */ -else sts = ST_OFL; /* offline */ -PUTP32 (pkt, RW_BCL, 0); /* no bytes processed */ -PUTP32 (pkt, RW_POSL, objp); /* set obj pos */ -PUTP32 (pkt, RW_RSZL, 0); /* clr rec size */ -tq_putr (pkt, cmd | OP_END, tq_efl (uptr), sts, RW_LNT_T, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Validity checks */ - -int32 tq_mot_valid (UNIT *uptr, uint32 cmd) -{ -if (uptr->flags & UNIT_SXC) return ST_SXC; /* ser exc pend? */ -if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - return (ST_OFL | SB_OFL_NV); /* offl no vol */ -if ((uptr->flags & UNIT_ONL) == 0) /* not online? */ - return ST_AVL; /* only avail */ -if (tq_cmf[cmd] & CMF_WR) { /* write op? */ - if (uptr->uf & UF_WPS) { /* swre wlk? */ - uptr->flags = uptr->flags | UNIT_SXC; /* set ser exc */ - return (ST_WPR | SB_WPR_SW); } - if (TQ_WPH (uptr)) { /* hwre wlk? */ - uptr->flags = uptr->flags | UNIT_SXC; /* set ser exc */ - return (ST_WPR | SB_WPR_HW); } } -return ST_SUC; /* success! */ -} - -/* Unit service for motion commands */ - -t_stat tq_svc (UNIT *uptr) -{ -uint32 t, sts, sktmk, skrec; -t_mtrlnt i, tbc, wbc; -int32 pkt = uptr->cpkt; /* get packet */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* get cmd */ -uint32 mdf = tq_pkt[pkt].d[CMD_MOD]; /* modifier */ -uint32 ba = GETP32 (pkt, RW_BAL); /* buf addr */ -t_mtrlnt bc = GETP32 (pkt, RW_BCL); /* byte count */ -uint32 nrec = GETP32 (pkt, POS_RCL); /* #rec to skip */ -uint32 ntmk = GETP32 (pkt, POS_TMCL); /* #tmk to skp */ - -if (pkt == 0) return SCPE_IERR; /* what??? */ -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - tq_mot_end (uptr, 0, ST_OFL | SB_OFL_NV, 0); /* offl no vol */ - return SCPE_OK; } - -if (tq_cmf[cmd] & CMF_WR) { /* write op? */ - if (TQ_WPH (uptr)) { /* hwre write prot? */ - uptr->flags = uptr->flags | UNIT_SXC; /* set ser exc */ - tq_mot_end (uptr, 0, ST_WPR | SB_WPR_HW, 0); - return SCPE_OK; } - if (uptr->uf & UF_WPS) { /* swre write prot? */ - uptr->flags = uptr->flags | UNIT_SXC; /* set ser exc */ - tq_mot_end (uptr, 0, ST_WPR | SB_WPR_SW, 0); - return SCPE_OK; } } -sts = ST_SUC; /* assume success */ -tbc = 0; /* assume zero rec */ -switch (cmd) { /* case on command */ - -case OP_RD:case OP_ACC:case OP_CMP: /* read-like op */ - if (mdf & MD_REV) sts = tq_rdbufr (uptr, &tbc); /* read record */ - else sts = tq_rdbuff (uptr, &tbc); - if (sts == ST_DRV) { /* read error? */ - PUTP32 (pkt, RW_BCL, 0); /* no bytes processed */ - return tq_mot_err (uptr, tbc); } /* log, done */ - if ((sts != ST_SUC) || (cmd == OP_ACC)) { /* error or access? */ - PUTP32 (pkt, RW_BCL, 0); /* no bytes processed */ - break; } - if (tbc > bc) { /* tape rec > buf? */ - uptr->flags = uptr->flags | UNIT_SXC; /* serious exc */ - sts = ST_RDT; /* data truncated */ - wbc = bc; } /* set working bc */ - else wbc = tbc; - if (cmd == OP_RD) { /* read? */ - if (t = Map_WriteB (ba, wbc, tqxb, MAP)) { /* store, nxm? */ - PUTP32 (pkt, RW_BCL, wbc - t); /* adj bc */ - if (tq_hbe (uptr, ba + wbc - t)) /* post err log */ - tq_mot_end (uptr, EF_LOG, ST_HST | SB_HST_NXM, tbc); - return SCPE_OK; } /* end if nxm */ - } /* end if read */ - else { /* compare */ - uint8 mby, dby; - uint32 mba; - for (i = 0; i < wbc; i++) { /* loop */ - if (mdf & MD_REV) { /* reverse? */ - mba = ba + bc - 1 - i; /* mem addr */ - dby = tqxb[tbc - 1 - i]; } /* byte */ - else { - mba = ba + i; - dby = tqxb[i]; } - if (Map_ReadB (mba, 1, &mby, MAP)) { /* fetch, nxm? */ - PUTP32 (pkt, RW_BCL, i); /* adj bc */ - if (tq_hbe (uptr, mba)) /* post err log */ - tq_mot_end (uptr, EF_LOG, ST_HST | SB_HST_NXM, tbc); - return SCPE_OK; } - if (mby != dby) { /* cmp err? */ - uptr->flags = uptr->flags | UNIT_SXC; /* ser exc */ - PUTP32 (pkt, RW_BCL, i); /* adj bc */ - tq_mot_end (uptr, 0, ST_CMP, tbc); - return SCPE_OK; } /* exit */ - } /* end for */ - } /* end if compare */ - PUTP32 (pkt, RW_BCL, wbc); /* bytes read/cmp'd */ - break; - -case OP_WR: /* write */ - if (t = Map_ReadB (ba, bc, tqxb, MAP)) { /* fetch buf, nxm? */ - PUTP32 (pkt, RW_BCL, 0); /* no bytes xfer'd */ - if (tq_hbe (uptr, ba + bc - t)) /* post err log */ - tq_mot_end (uptr, EF_LOG, ST_HST | SB_HST_NXM, bc); - return SCPE_OK; } /* end else wr */ - if (sim_tape_wrrecf (uptr, tqxb, bc)) /* write rec fwd, err? */ - return tq_mot_err (uptr, bc); /* log, end */ - uptr->objp = uptr->objp + 1; /* upd obj pos */ - if (TEST_EOT (uptr)) /* EOT on write? */ - uptr->flags = uptr->flags | UNIT_SXC; - uptr->flags = uptr->flags & ~UNIT_TMK; /* disable LEOT */ - tbc = bc; /* RW_BC is ok */ - break; - -case OP_WTM: /* write tape mark */ - if (sim_tape_wrtmk (uptr)) /* write tmk, err? */ - return tq_mot_err (uptr, 0); /* log, end */ - uptr->objp = uptr->objp + 1; /* incr obj cnt */ -case OP_ERG: /* erase gap */ - if (TEST_EOT (uptr)) /* EOT on write? */ - uptr->flags = uptr->flags | UNIT_SXC; - uptr->flags = uptr->flags & ~UNIT_TMK; /* disable LEOT */ - break; - -case OP_ERS: /* erase */ - if (sim_tape_wreom (uptr)) /* write eom, err? */ - return tq_mot_err (uptr, 0); /* log, end */ - sim_tape_rewind (uptr); /* rewind */ - uptr->objp = 0; - uptr->flags = uptr->flags & ~(UNIT_TMK | UNIT_POL); - break; - -case OP_POS: /* position */ - sktmk = skrec = 0; /* clr skipped */ - if (mdf & MD_RWD) { /* rewind? */ - sim_tape_rewind (uptr); - uptr->objp = 0; /* clr flags */ - uptr->flags = uptr->flags & ~(UNIT_TMK | UNIT_POL); } - if (mdf & MD_OBC) { /* skip obj? */ - if (mdf & MD_REV) /* reverse? */ - sts = tq_spacer (uptr, nrec, &skrec, FALSE); - else sts = tq_spacef (uptr, nrec, &skrec, FALSE); - } - else { /* skip tmk, rec */ - if (mdf & MD_REV) sts = tq_skipfr (uptr, ntmk, &sktmk); - else sts = tq_skipff (uptr, ntmk, &sktmk); - if (sts == ST_SUC) { /* tmk succeed? */ - if (mdf & MD_REV) /* reverse? */ - sts = tq_spacer (uptr, nrec, &skrec, TRUE); - else sts = tq_spacef (uptr, nrec, &skrec, TRUE); - if (sts == ST_TMK) sktmk = sktmk + 1; } - } - PUTP32 (pkt, POS_RCL, skrec); /* #rec skipped */ - PUTP32 (pkt, POS_TMCL, sktmk); /* #tmk skipped */ - break; - -default: - return SCPE_IERR; } -tq_mot_end (uptr, 0, sts, tbc); /* done */ -return SCPE_OK; -} - -/* Motion command drive error */ - -t_stat tq_mot_err (UNIT *uptr, uint32 rsiz) -{ -uptr->flags = (uptr->flags | UNIT_SXC) & ~UNIT_TMK; /* serious exception */ -if (tq_dte (uptr, ST_DRV)) /* post err log */ - tq_mot_end (uptr, EF_LOG, ST_DRV, rsiz); /* if ok, report err */ -perror ("TQ I/O error"); -clearerr (uptr->fileref); -return SCPE_IOERR; -} - -/* Motion command complete */ - -t_bool tq_mot_end (UNIT *uptr, uint32 flg, uint32 sts, uint32 rsiz) -{ -int32 pkt = uptr->cpkt; /* packet */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* get cmd */ -uint32 lnt = RW_LNT_T; /* assume rw */ - -if (cmd == OP_ERG) lnt = ERG_LNT; /* set pkt lnt */ -else if (cmd == OP_ERS) lnt = ERS_LNT; -else if (cmd == OP_WTM) lnt = WTM_LNT; -else if (cmd == OP_POS) lnt = POS_LNT; - -uptr->cpkt = 0; /* done */ -if (lnt > ERG_LNT) { /* xfer cmd? */ - PUTP32 (pkt, RW_POSL, uptr->objp); /* position */ - PUTP32 (pkt, RW_RSZL, rsiz); } /* record size */ -tq_putr (pkt, cmd | OP_END, flg | tq_efl (uptr), sts, lnt, UQ_TYP_SEQ); -if (!tq_putpkt (pkt, TRUE)) return ERR; /* send pkt */ -if (uptr->pktq) /* more to do? */ - sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); /* activate thread */ -return OK; -} - -/* Tape motion routines */ - -uint32 tq_map_status (UNIT *uptr, t_stat st) -{ -switch (st) -{ -case MTSE_OK: - break; -case MTSE_UNATT: - uptr->flags = uptr->flags | UNIT_SXC; - return (ST_OFL | SB_OFL_NV); -case MTSE_FMT: - uptr->flags = uptr->flags | UNIT_SXC; - return ST_MFE; -case MTSE_TMK: - uptr->flags = uptr->flags | UNIT_SXC; - return ST_TMK; -case MTSE_INVRL: - uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL; - return ST_FMT; -case MTSE_RECE: -case MTSE_IOERR: - uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL; - return ST_DRV; -case MTSE_EOM: - uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL; - return ST_DAT; -case MTSE_BOT: - uptr->flags = (uptr->flags | UNIT_SXC) & ~UNIT_POL; - return ST_BOT; -case MTSE_WRP: - uptr->flags = uptr->flags | UNIT_SXC; - return ST_WPR; } -return ST_SUC; -} - -uint32 tq_spacef (UNIT *uptr, uint32 cnt, uint32 *skipped, t_bool qrec) -{ -t_stat st; -t_mtrlnt tbc; - -*skipped = 0; -while (*skipped < cnt) { /* loop */ - st = sim_tape_sprecf (uptr, &tbc); /* space rec fwd */ - if ((st != MTSE_OK) && (st != MTSE_TMK)) /* real error? */ - return tq_map_status (uptr, st); /* map status */ - uptr->objp = uptr->objp + 1; /* upd obj cnt */ - if (st == MTSE_TMK) { /* tape mark? */ - int32 pkt = uptr->cpkt; /* get pkt */ - if ((tq_pkt[pkt].d[CMD_MOD] & MD_DLE) && /* LEOT? */ - (uptr->flags & UNIT_TMK)) { - sim_tape_sprecr (uptr, &tbc); /* rev over tmk */ - uptr->flags = uptr->flags | UNIT_SXC; /* serious exc */ - return ST_LED; } - uptr->flags = uptr->flags | UNIT_TMK; /* set TM seen */ - if (qrec) return ST_TMK; } /* rec spc? stop */ - else uptr->flags = uptr->flags & ~UNIT_TMK; /* clr TM seen */ - *skipped = *skipped + 1; } /* # obj skipped */ -return ST_SUC; -} - -uint32 tq_skipff (UNIT *uptr, uint32 cnt, uint32 *skipped) -{ -uint32 st, skrec; - -*skipped = 0; -while (*skipped < cnt) { /* loop */ - st = tq_spacef (uptr, 0x7FFFFFFF, &skrec, TRUE);/* rec spc fwd */ - if (st == ST_TMK) *skipped = *skipped + 1; /* count files */ - else if (st != ST_SUC) return st; } -return ST_SUC; -} - -uint32 tq_spacer (UNIT *uptr, uint32 cnt, uint32 *skipped, t_bool qrec) -{ -t_stat st; -t_mtrlnt tbc; - -*skipped = 0; -while (*skipped < cnt) { /* loop */ - st = sim_tape_sprecr (uptr, &tbc); /* spc rec rev */ - if ((st != MTSE_OK) && (st != MTSE_TMK)) /* real error? */ - return tq_map_status (uptr, st); /* map status */ - uptr->objp = uptr->objp - 1; /* upd obj cnt */ - if ((st == MTSE_TMK) && qrec) return ST_TMK; /* tape mark, stop? */ - *skipped = *skipped + 1; } /* # obj skipped */ -return ST_SUC; -} - -uint32 tq_skipfr (UNIT *uptr, uint32 cnt, uint32 *skipped) -{ -uint32 st, skrec; - -*skipped = 0; -while (*skipped < cnt) { /* loopo */ - st = tq_spacer (uptr, 0x7FFFFFFF, &skrec, TRUE);/* rec spc rev */ - if (st == ST_TMK) *skipped = *skipped + 1; /* tape mark? */ - else if (st != 0) return st; } /* error? */ -return ST_SUC; -} - -/* Read buffer - can return ST_TMK, ST_FMT, or ST_DRV */ - -uint32 tq_rdbuff (UNIT *uptr, t_mtrlnt *tbc) -{ -t_stat st; - -st = sim_tape_rdrecf (uptr, tqxb, tbc, MT_MAXFR); /* read rec fwd */ -if (st == MTSE_TMK) { /* tape mark? */ - uptr->flags = uptr->flags | UNIT_SXC | UNIT_TMK;/* serious exc */ - uptr->objp = uptr->objp + 1; /* update obj cnt */ - return ST_TMK; } -if (st != MTSE_OK) return tq_map_status (uptr, st); /* other error? */ -uptr->flags = uptr->flags & ~UNIT_TMK; /* clr tape mark */ -uptr->objp = uptr->objp + 1; /* upd obj cnt */ -return ST_SUC; -} - -uint32 tq_rdbufr (UNIT *uptr, t_mtrlnt *tbc) -{ -t_stat st; - -st = sim_tape_rdrecr (uptr, tqxb, tbc, MT_MAXFR); /* read rec rev */ -if (st == MTSE_TMK) { /* tape mark? */ - uptr->flags = uptr->flags | UNIT_SXC; /* serious exc */ - uptr->objp = uptr->objp - 1; /* update obj cnt */ - return ST_TMK; } -if (st != MTSE_OK) return tq_map_status (uptr, st); /* other error? */ -uptr->objp = uptr->objp - 1; /* upd obj cnt */ -return ST_SUC; -} - -/* Data transfer error log packet */ - -t_bool tq_dte (UNIT *uptr, uint32 err) -{ -int32 pkt, tpkt; -uint32 lu; - -if ((tq_cflgs & CF_THS) == 0) return OK; /* logging? */ -if (!tq_deqf (&pkt)) return ERR; /* get log pkt */ -tpkt = uptr->cpkt; /* rw pkt */ -lu = tq_pkt[tpkt].d[CMD_UN]; /* unit # */ - -tq_pkt[pkt].d[ELP_REFL] = tq_pkt[tpkt].d[CMD_REFL]; /* copy cmd ref */ -tq_pkt[pkt].d[ELP_REFH] = tq_pkt[tpkt].d[CMD_REFH]; /* copy cmd ref */ -tq_pkt[pkt].d[ELP_UN] = lu; /* copy unit */ -tq_pkt[pkt].d[ELP_SEQ] = 0; /* clr seq # */ -tq_pkt[pkt].d[DTE_CIDA] = 0; /* ctrl ID */ -tq_pkt[pkt].d[DTE_CIDB] = 0; -tq_pkt[pkt].d[DTE_CIDC] = 0; -tq_pkt[pkt].d[DTE_CIDD] = (TQ_CLASS << DTE_CIDD_V_CLS) | - (drv_tab[tq_typ].cmod << DTE_CIDD_V_MOD); -tq_pkt[pkt].d[DTE_VER] = drv_tab[tq_typ].cver; /* ctrl ver */ -tq_pkt[pkt].d[DTE_MLUN] = lu; /* MLUN */ -tq_pkt[pkt].d[DTE_UIDA] = lu; /* unit ID */ -tq_pkt[pkt].d[DTE_UIDB] = 0; -tq_pkt[pkt].d[DTE_UIDC] = 0; -tq_pkt[pkt].d[DTE_UIDD] = (UID_TAPE << DTE_UIDD_V_CLS) | - (drv_tab[tq_typ].umod << DTE_UIDD_V_MOD); -tq_pkt[pkt].d[DTE_UVER] = drv_tab[tq_typ].uver; /* unit ver */ -PUTP32 (pkt, DTE_POSL, uptr->objp); /* position */ -tq_pkt[pkt].d[DTE_FVER] = drv_tab[tq_typ].fver; /* fmtr ver */ -tq_putr (pkt, FM_TAP, LF_SNR, err, DTE_LNT, UQ_TYP_DAT); -return tq_putpkt (pkt, TRUE); -} - -/* Host bus error log packet */ - -t_bool tq_hbe (UNIT *uptr, uint32 ba) -{ -int32 pkt, tpkt; - -if ((tq_cflgs & CF_THS) == 0) return OK; /* logging? */ -if (!tq_deqf (&pkt)) return ERR; /* get log pkt */ -tpkt = uptr->cpkt; /* rw pkt */ -tq_pkt[pkt].d[ELP_REFL] = tq_pkt[tpkt].d[CMD_REFL]; /* copy cmd ref */ -tq_pkt[pkt].d[ELP_REFH] = tq_pkt[tpkt].d[CMD_REFH]; /* copy cmd ref */ -tq_pkt[pkt].d[ELP_UN] = tq_pkt[tpkt].d[CMD_UN]; /* copy unit */ -tq_pkt[pkt].d[ELP_SEQ] = 0; /* clr seq # */ -tq_pkt[pkt].d[HBE_CIDA] = 0; /* ctrl ID */ -tq_pkt[pkt].d[HBE_CIDB] = 0; -tq_pkt[pkt].d[HBE_CIDC] = 0; -tq_pkt[pkt].d[DTE_CIDD] = (TQ_CLASS << DTE_CIDD_V_CLS) | - (drv_tab[tq_typ].cmod << DTE_CIDD_V_MOD); -tq_pkt[pkt].d[HBE_VER] = drv_tab[tq_typ].cver; /* ctrl ver */ -tq_pkt[pkt].d[HBE_RSV] = 0; -PUTP32 (pkt, HBE_BADL, ba); /* bad addr */ -tq_putr (pkt, FM_BAD, LF_SNR, ST_HST | SB_HST_NXM, HBE_LNT, UQ_TYP_DAT); -return tq_putpkt (pkt, TRUE); -} - -/* Port last failure error log packet */ - -t_bool tq_plf (uint32 err) -{ -int32 pkt; - -if (!tq_deqf (&pkt)) return ERR; /* get log pkt */ -tq_pkt[pkt].d[ELP_REFL] = tq_pkt[pkt].d[ELP_REFH] = 0; /* ref = 0 */ -tq_pkt[pkt].d[ELP_UN] = tq_pkt[pkt].d[ELP_SEQ] = 0; /* no unit, seq */ -tq_pkt[pkt].d[PLF_CIDA] = 0; /* cntl ID */ -tq_pkt[pkt].d[PLF_CIDB] = 0; -tq_pkt[pkt].d[PLF_CIDC] = 0; -tq_pkt[pkt].d[PLF_CIDD] = (TQ_CLASS << PLF_CIDD_V_CLS) | - (drv_tab[tq_typ].cmod << PLF_CIDD_V_MOD); -tq_pkt[pkt].d[PLF_VER] = drv_tab[tq_typ].cver; -tq_pkt[pkt].d[PLF_ERR] = err; -tq_putr (pkt, FM_CNT, LF_SNR, ST_CNT, PLF_LNT, UQ_TYP_DAT); -tq_pkt[pkt].d[UQ_HCTC] |= (UQ_CID_DIAG << UQ_HCTC_V_CID); -return tq_putpkt (pkt, TRUE); -} - -/* Unit now available attention packet */ - -int32 tq_una (UNIT *uptr) -{ -int32 pkt; -uint32 lu; - -if (!tq_deqf (&pkt)) return ERR; /* get log pkt */ -lu = uptr - tq_dev.units; /* get unit */ -tq_pkt[pkt].d[RSP_REFL] = tq_pkt[pkt].d[RSP_REFH] = 0; /* ref = 0 */ -tq_pkt[pkt].d[RSP_UN] = lu; -tq_pkt[pkt].d[RSP_RSV] = 0; -tq_putr_unit (pkt, uptr, lu, FALSE); /* fill unit fields */ -tq_putr (pkt, OP_AVA, 0, 0, UNA_LNT, UQ_TYP_SEQ); /* fill std fields */ -return tq_putpkt (pkt, TRUE); -} - -/* List handling - - tq_deqf - dequeue head of free list (fatal err if none) - tq_deqh - dequeue head of list - tq_enqh - enqueue at head of list - tq_enqt - enqueue at tail of list -*/ - -t_bool tq_deqf (int32 *pkt) -{ -if (tq_freq == 0) return tq_fatal (PE_NSR); /* no free pkts?? */ -tq_pbsy = tq_pbsy + 1; /* cnt busy pkts */ -*pkt = tq_freq; /* head of list */ -tq_freq = tq_pkt[tq_freq].link; /* next */ -return OK; -} - -int32 tq_deqh (int32 *lh) -{ -int32 ptr = *lh; /* head of list */ - -if (ptr) *lh = tq_pkt[ptr].link; /* next */ -return ptr; -} - -void tq_enqh (int32 *lh, int32 pkt) -{ -if (pkt == 0) return; /* any pkt? */ -tq_pkt[pkt].link = *lh; /* link is old lh */ -*lh = pkt; /* pkt is new lh */ -return; -} - -void tq_enqt (int32 *lh, int32 pkt) -{ -if (pkt == 0) return; /* any pkt? */ -tq_pkt[pkt].link = 0; /* it will be tail */ -if (*lh == 0) *lh = pkt; /* if empty, enqh */ -else { uint32 ptr = *lh; /* chase to end */ - while (tq_pkt[ptr].link) ptr = tq_pkt[ptr].link; - tq_pkt[ptr].link = pkt; } /* enq at tail */ -return; -} - -/* Packet and descriptor handling */ - -/* Get packet from command ring */ - -t_bool tq_getpkt (int32 *pkt) -{ -uint32 addr, desc; - -if (!tq_getdesc (&tq_cq, &desc)) return ERR; /* get cmd desc */ -if ((desc & UQ_DESC_OWN) == 0) { /* none */ - *pkt = 0; /* pkt = 0 */ - return OK; } /* no error */ -if (!tq_deqf (pkt)) return ERR; /* get cmd pkt */ -tq_hat = 0; /* dsbl hst timer */ -addr = desc & UQ_ADDR; /* get Q22 addr */ -if (Map_ReadW (addr + UQ_HDR_OFF, TQ_PKT_SIZE, tq_pkt[*pkt].d, MAP)) - return tq_fatal (PE_PRE); /* read pkt */ -return tq_putdesc (&tq_cq, desc); /* release desc */ -} - -/* Put packet to response ring - note the clever hack about credits. - The controller sends all its credits to the host. Thereafter, it - supplies one credit for every response packet sent over. Simple! -*/ - -t_bool tq_putpkt (int32 pkt, t_bool qt) -{ -uint32 addr, desc, lnt, cr; - -if (pkt == 0) return OK; /* any packet? */ -if (DBG_LOG (LOG_TQ)) { - UNIT *up = tq_getucb (tq_pkt[pkt].d[CMD_UN]); - fprintf (sim_log, ">>TQ: rsp=%04X, sts=%04X", - tq_pkt[pkt].d[RSP_OPF], tq_pkt[pkt].d[RSP_STS]); - if (up) fprintf (sim_log, ", pos=%d, obj=%d\n", up->pos, up->objp); - else fprintf (sim_log, "\n"); - fflush (sim_log); } -if (!tq_getdesc (&tq_rq, &desc)) return ERR; /* get rsp desc */ -if ((desc & UQ_DESC_OWN) == 0) { /* not valid? */ - if (qt) tq_enqt (&tq_rspq, pkt); /* normal? q tail */ - else tq_enqh (&tq_rspq, pkt); /* resp q call */ - sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); /* activate q thrd */ - return OK; } -addr = desc & UQ_ADDR; /* get Q22 addr */ -lnt = tq_pkt[pkt].d[UQ_HLNT] - UQ_HDR_OFF; /* size, with hdr */ -if ((GETP (pkt, UQ_HCTC, TYP) == UQ_TYP_SEQ) && /* seq packet? */ - (GETP (pkt, CMD_OPC, OPC) & OP_END)) { /* end packet? */ - cr = (tq_credits >= 14)? 14: tq_credits; /* max 14 credits */ - tq_credits = tq_credits - cr; /* decr credits */ - tq_pkt[pkt].d[UQ_HCTC] |= ((cr + 1) << UQ_HCTC_V_CR); } -if (Map_WriteW (addr + UQ_HDR_OFF, lnt, tq_pkt[pkt].d, MAP)) - return tq_fatal (PE_PWE); /* write pkt */ -tq_enqh (&tq_freq, pkt); /* pkt is free */ -tq_pbsy = tq_pbsy - 1; /* decr busy cnt */ -if (tq_pbsy == 0) tq_hat = tq_htmo; /* idle? strt hst tmr */ -return tq_putdesc (&tq_rq, desc); /* release desc */ -} - -/* Get a descriptor from the host */ - -t_bool tq_getdesc (struct uq_ring *ring, uint32 *desc) -{ -uint32 addr = ring->ba + ring->idx; -uint16 d[2]; - -if (Map_ReadW (addr, 4, d, MAP)) /* fetch desc */ - return tq_fatal (PE_QRE); /* err? dead */ -*desc = ((uint32) d[0]) | (((uint32) d[1]) << 16); -return OK; -} - -/* Return a descriptor to the host, clearing owner bit - If rings transitions from "empty" to "not empty" or "full" to - "not full", and interrupt bit was set, interrupt the host. - Actually, test whether previous ring entry was owned by host. -*/ - -t_bool tq_putdesc (struct uq_ring *ring, uint32 desc) -{ -uint32 prvd, newd = (desc & ~UQ_DESC_OWN) | UQ_DESC_F; -uint32 prva, addr = ring->ba + ring->idx; -uint16 d[2]; - -d[0] = newd & 0xFFFF; /* 32b to 16b */ -d[1] = (newd >> 16) & 0xFFFF; -if (Map_WriteW (addr, 4, d, MAP)) /* store desc */ - return tq_fatal (PE_QWE); /* err? dead */ -if (desc & UQ_DESC_F) { /* was F set? */ - if (ring->lnt <= 4) tq_ring_int (ring); /* lnt = 1? intr */ - else { prva = ring->ba + /* prv desc */ - ((ring->idx - 4) & (ring->lnt - 1)); - if (Map_ReadW (prva, 4, d, MAP)) /* read prv */ - return tq_fatal (PE_QRE); - prvd = ((uint32) d[0]) | (((uint32) d[1]) << 16); - if (prvd & UQ_DESC_OWN) tq_ring_int (ring); } } -ring->idx = (ring->idx + 4) & (ring->lnt - 1); -return OK; -} - -/* Get unit descriptor for logical unit - trivial now, - but eventually, hide multiboard complexities here */ - -UNIT *tq_getucb (uint32 lu) -{ -UNIT *uptr; - -if (lu >= TQ_NUMDR) return NULL; -uptr = tq_dev.units + lu; -if (uptr->flags & UNIT_DIS) return NULL; -return uptr; -} - -/* Hack unit flags */ - -void tq_setf_unit (int32 pkt, UNIT *uptr) -{ -uptr->uf = tq_pkt[pkt].d[ONL_UFL] & UF_MSK; /* settable flags */ -if ((tq_pkt[pkt].d[CMD_MOD] & MD_SWP) && /* swre wrp enb? */ - (tq_pkt[pkt].d[ONL_UFL] & UF_WPS)) /* swre wrp on? */ - uptr->uf = uptr->uf | UF_WPS; /* simon says... */ -return; -} - -/* Hack end flags */ - -uint32 tq_efl (UNIT *uptr) -{ -uint32 t = 0; - -if (uptr) { /* any unit? */ - if (uptr->flags & UNIT_POL) t = t | EF_PLS; /* note pos lost */ - if (uptr->flags & UNIT_SXC) t = t | EF_SXC; /* note ser exc */ - if (TEST_EOT (uptr)) t = t | EF_EOT; } /* note EOT */ -return t; -} - -/* Unit response fields */ - -void tq_putr_unit (int32 pkt, UNIT *uptr, uint32 lu, t_bool all) -{ -tq_pkt[pkt].d[ONL_MLUN] = lu; /* multi-unit */ -tq_pkt[pkt].d[ONL_UFL] = uptr->uf | TQ_WPH (uptr); /* unit flags */ -tq_pkt[pkt].d[ONL_RSVL] = tq_pkt[pkt].d[ONL_RSVH] = 0; /* reserved */ -tq_pkt[pkt].d[ONL_UIDA] = lu; /* UID low */ -tq_pkt[pkt].d[ONL_UIDB] = 0; -tq_pkt[pkt].d[ONL_UIDC] = 0; -tq_pkt[pkt].d[ONL_UIDD] = (UID_TAPE << ONL_UIDD_V_CLS) | - (drv_tab[tq_typ].umod << ONL_UIDD_V_MOD); /* UID hi */ -PUTP32 (pkt, ONL_MEDL, drv_tab[tq_typ].med); /* media type */ -if (all) { /* if long form */ - tq_pkt[pkt].d[ONL_FMT] = drv_tab[tq_typ].fmt; /* format */ - tq_pkt[pkt].d[ONL_SPD] = 0; /* speed */ - PUTP32 (pkt, ONL_MAXL, TQ_MAXFR); /* max xfr */ - tq_pkt[pkt].d[ONL_NREC] = 0; /* noise rec */ - tq_pkt[pkt].d[ONL_RSVE] = 0; } /* reserved */ -return; -} - -/* UQ_HDR and RSP_OP fields */ - -void tq_putr (int32 pkt, uint32 cmd, uint32 flg, uint32 sts, uint32 lnt, uint32 typ) -{ -tq_pkt[pkt].d[RSP_OPF] = (cmd << RSP_OPF_V_OPC) | /* set cmd, flg */ - (flg << RSP_OPF_V_FLG); -tq_pkt[pkt].d[RSP_STS] = sts; -tq_pkt[pkt].d[UQ_HLNT] = lnt; /* length */ -tq_pkt[pkt].d[UQ_HCTC] = (typ << UQ_HCTC_V_TYP) | /* type, cid */ - (UQ_CID_TMSCP << UQ_HCTC_V_CID); /* clr credits */ -return; -} - -/* Post interrupt during init */ - -void tq_init_int (void) -{ -if ((tq_s1dat & SA_S1H_IE) && tq_dib.vec) SET_INT (TQ); -return; -} - -/* Post interrupt during putpkt - note that NXMs are ignored! */ - -void tq_ring_int (struct uq_ring *ring) -{ -uint32 iadr = tq_comm + ring->ioff; /* addr intr wd */ -uint16 flag = 1; - -Map_WriteW (iadr, 2, &flag, MAP); /* write flag */ -if (tq_dib.vec) SET_INT (TQ); /* if enb, intr */ -return; -} - -/* Return interrupt vector */ - -int32 tq_inta (void) -{ -return tq_dib.vec; /* prog vector */ -} - -/* Fatal error */ - -t_bool tq_fatal (uint32 err) -{ -if (DBG_LOG (LOG_TQ)) fprintf (sim_log, ">>TQ: fatal err=%X\n", err); -tq_reset (&tq_dev); /* reset device */ -tq_sa = SA_ER | err; /* SA = dead code */ -tq_csta = CST_DEAD; /* state = dead */ -tq_perr = err; /* save error */ -return ERR; -} - -/* Device attach */ - -t_stat tq_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; -if (tq_csta == CST_UP) uptr->flags = (uptr->flags | UNIT_ATP) & - ~(UNIT_SXC | UNIT_POL | UNIT_TMK); -return SCPE_OK; -} - -/* Device detach */ - -t_stat tq_detach (UNIT *uptr) -{ -t_stat r; - -r = sim_tape_detach (uptr); /* detach unit */ -if (r != SCPE_OK) return r; -uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_ATP | UNIT_SXC | UNIT_POL | UNIT_TMK); -uptr->uf = 0; /* clr unit flgs */ -return SCPE_OK; -} - -/* Device reset */ - -t_stat tq_reset (DEVICE *dptr) -{ -int32 i, j; -UNIT *uptr; - -tq_csta = CST_S1; /* init stage 1 */ -tq_s1dat = 0; /* no S1 data */ -tq_dib.vec = 0; /* no vector */ -tq_sa = SA_S1 | SA_S1C_Q22 | SA_S1C_DI | SA_S1C_MP; /* init SA val */ -tq_cflgs = CF_RPL; /* ctrl flgs off */ -tq_htmo = TQ_DHTMO; /* default timeout */ -tq_hat = tq_htmo; /* default timer */ -tq_cq.ba = tq_cq.lnt = tq_cq.idx = 0; /* clr cmd ring */ -tq_rq.ba = tq_rq.lnt = tq_rq.idx = 0; /* clr rsp ring */ -tq_credits = (TQ_NPKTS / 2) - 1; /* init credits */ -tq_freq = 1; /* init free list */ -for (i = 0; i < TQ_NPKTS; i++) { /* all pkts free */ - if (i) tq_pkt[i].link = (i + 1) & TQ_M_NPKTS; - else tq_pkt[i].link = 0; - for (j = 0; j < TQ_PKT_SIZE_W; j++) tq_pkt[i].d[j] = 0; } -tq_rspq = 0; /* no q'd rsp pkts */ -tq_pbsy = 0; /* all pkts free */ -tq_pip = 0; /* not polling */ -CLR_INT (TQ); /* clr intr req */ -for (i = 0; i < TQ_NUMDR + 2; i++) { /* init units */ - uptr = tq_dev.units + i; - sim_cancel (uptr); /* clr activity */ - sim_tape_reset (uptr); - uptr->flags = uptr->flags & /* not online */ - ~(UNIT_ONL|UNIT_ATP|UNIT_SXC|UNIT_POL|UNIT_TMK); - uptr->uf = 0; /* clr unit flags */ - uptr->cpkt = uptr->pktq = 0; } /* clr pkt q's */ -if (tqxb == NULL) tqxb = calloc (TQ_MAXFR, sizeof (uint8)); -if (tqxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Device bootstrap */ - -#if defined (VM_PDP11) - -#define BOOT_START 016000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 014) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - - -/* Data structure definitions */ - -#define B_CMDINT (BOOT_START - 01000) /* cmd int */ -#define B_RSPINT (B_CMDINT + 002) /* rsp int */ -#define B_RING (B_RSPINT + 002) /* ring base */ -#define B_RSPH (B_RING + 010) /* resp pkt hdr */ -#define B_TKRSP (B_RSPH + 004) /* resp pkt */ -#define B_CMDH (B_TKRSP + 060) /* cmd pkt hdr */ -#define B_TKCMD (B_CMDH + 004) /* cmd pkt */ -#define B_UNIT (B_TKCMD + 004) /* unit # */ - -static const uint16 boot_rom[] = { - - 0046525, /* ST: "UM" */ - - 0012706, 0016000, /* mov #st,sp */ - 0012700, 0000000, /* mov #unitno,r0 */ - 0012701, 0174500, /* mov #174500,r1 ; ip addr */ - 0005021, /* clr (r1)+ ; init */ - 0012704, 0004000, /* mov #4000,r4 ; s1 mask */ - 0005002, /* clr r2 */ - 0005022, /* 10$: clr (r2)+ ; clr up to boot */ - 0020237, BOOT_START - 2, /* cmp r2,#st-2 */ - 0103774, /* blo 10$ */ - 0012705, BOOT_START+0312, /* mov #cmdtbl,r5 ; addr of tbl */ - - /* Four step init process */ - - 0005711, /* 20$: tst (r1) ; err? */ - 0100001, /* bpl 30$ */ - 0000000, /* halt */ - 0030411, /* 30$: bit r4,(r1) ; step set? */ - 0001773, /* beq 20$ ; wait */ - 0012511, /* mov (r5)+,(r1) ; send next */ - 0006304, /* asl r4 ; next mask */ - 0100370, /* bpl 20$ ; s4 done? */ - - /* Set up rings, issue ONLINE, REWIND, READ */ - - 0012737, 0000400, B_CMDH + 2, /* mov #400,cmdh+2 ; VCID = 1 */ - 0012737, 0000044, B_CMDH, /* mov #36.,cmdh ; cmd pkt lnt */ - 0010037, B_UNIT, /* mov r0,unit ; unit # */ - 0012737, 0000011, B_TKCMD + 8, /* mov #11,tkcmd+8. ; online op */ - 0012737, 0020000, B_TKCMD + 10, /* mov #20000,tkcmd+10. ; clr ser ex */ - 0012702, B_RING, /* mov #ring,r2 ; init rings */ - 0012722, B_TKRSP, /* mov #tkrsp,(r2)+ ; rsp pkt addr */ - 0010203, /* mov r2,r3 ; save ring+2 */ - 0010423, /* mov r4,(r3)+ ; set TK own */ - 0012723, B_TKCMD, /* mov #tkcmd,(r3)+ ; cmd pkt addr */ - 0010423, /* mov r4,(r3)+ ; set TK own */ - 0005741, /* tst -(r1) ; start poll */ - 0005712, /* 40$: tst (r2) ; wait for resp */ - 0100776, /* bmi 40$ */ - 0105737, B_TKRSP + 10, /* tstb tkrsp+10. ; check stat */ - 0001401, /* beq 50$ */ - 0000000, /* halt */ - 0012703, B_TKCMD + 8, /* 50$: mov #tkcmd+8.,r3 */ - 0012723, 0000045, /* mov #45,(r3)+ ; reposition */ - 0012723, 0020002, /* mov #20002,(r3)+ ; rew, clr exc */ - 0012723, 0000001, /* mov #1,(r3)+ ; lo rec skp */ - 0005023, /* clr (r3)+ ; hi rec skp */ - 0005023, /* clr (r3)+ ; lo tmk skp */ - 0005023, /* clr (r3)+ ; hi tmk skp */ - 0010412, /* mov r4,(r2) ; TK own rsp */ - 0010437, B_RING + 6, /* mov r4,ring+6 ; TK own cmd */ - 0005711, /* tst (r1) ; start poll */ - 0005712, /* 60$: tst (r2) ; wait for resp */ - 0100776, /* bmi 60$ */ - 0105737, B_TKRSP + 10, /* tstb tkrsp+10. ; check stat */ - 0001401, /* beq 70$ */ - 0000000, /* halt */ - 0012703, B_TKCMD + 8, /* 70$: mov #tkcmd+8.,r3 */ - 0012723, 0000041, /* mov #41,(r3)+ ; read */ - 0012723, 0020000, /* mov #20000,(r3)+ ; clr exc */ - 0012723, 0001000, /* mov #512.,(r3)+ ; bc = 512 */ - 0005023, /* clr (r3)+ ; clr args */ - 0005023, /* clr (r3)+ ; ba = 0 */ - 0010412, /* mov r4,(r2) ; TK own rsp */ - 0010437, B_RING + 6, /* mov r4,ring+6 ; TK own cmd */ - 0005711, /* tst (r1) ; start poll */ - 0005712, /* 80$: tst (r2) ; wait for resp */ - 0100776, /* bmi 80$ */ - 0105737, B_TKRSP + 10, /* tstb tkrsp+10. ; check stat */ - 0001401, /* beq 90$ */ - 0000000, /* halt */ - - /* Boot block read in, jump to 0 - leave controller init'd */ - - 0005003, /* clr r3 */ - 0012704, BOOT_START+020, /* mov #st+020,r4 */ - 0005005, /* clr r5 */ - 0005007, /* clr pc */ - - 0100000, /* cmdtbl: init step 1 */ - B_RING, /* ring base */ - 0000000, /* high ring base */ - 0000001 /* go */ -}; - -t_stat tq_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; -extern uint16 *M; - -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & 3; -M[BOOT_CSR >> 1] = tq_dib.ba & DMASK; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} - -#else - -t_stat tq_boot (int32 unitno, DEVICE *dptr) -{ -return SCPE_NOFNC; -} -#endif - -/* Special show commands */ - -void tq_show_ring (FILE *st, struct uq_ring *rp) -{ -uint32 i, desc; -uint16 d[2]; - -#if defined (VM_PDP11) -fprintf (st, "ring, base = %o, index = %d, length = %d\n", - rp->ba, rp->idx >> 2, rp->lnt >> 2); -#else -fprintf (st, "ring, base = %x, index = %d, length = %d\n", - rp->ba, rp->idx >> 2, rp->lnt >> 2); -#endif -for (i = 0; i < (rp->lnt >> 2); i++) { - if (Map_ReadW (rp->ba + (i << 2), 4, d, MAP)) { - fprintf (st, " %3d: non-existent memory\n", i); - break; } - desc = ((uint32) d[0]) | (((uint32) d[1]) << 16); -#if defined (VM_PDP11) - fprintf (st, " %3d: %011o\n", i, desc); -#else - fprintf (st, " %3d: %08x\n", i, desc); -#endif - } -return; -} - -void tq_show_pkt (FILE *st, int32 pkt) -{ -int32 i, j; -uint32 cr = GETP (pkt, UQ_HCTC, CR); -uint32 typ = GETP (pkt, UQ_HCTC, TYP); -uint32 cid = GETP (pkt, UQ_HCTC, CID); - -fprintf (st, "packet %d, credits = %d, type = %d, cid = %d\n", - pkt, cr, typ, cid); -for (i = 0; i < TQ_SH_MAX; i = i + TQ_SH_PPL) { - fprintf (st, " %2d:", i); - for (j = i; j < (i + TQ_SH_PPL); j++) -#if defined (VM_PDP11) - fprintf (st, " %06o", tq_pkt[pkt].d[j]); -#else - fprintf (st, " %04x", tq_pkt[pkt].d[j]); -#endif - fprintf (st, "\n"); - } -return; -} - -t_stat tq_show_unitq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 pkt, u = uptr - tq_dev.units; - -if (tq_csta != CST_UP) { - fprintf (st, "Controller is not initialized\n"); - return SCPE_OK; } -if ((uptr->flags & UNIT_ONL) == 0) { - if (uptr->flags & UNIT_ATT) - fprintf (st, "Unit %d is available\n", u); - else fprintf (st, "Unit %d is offline\n", u); - return SCPE_OK; } -if (uptr->cpkt) { - fprintf (st, "Unit %d current ", u); - tq_show_pkt (st, uptr->cpkt); - if (pkt = uptr->pktq) { - do { fprintf (st, "Unit %d queued ", u); - tq_show_pkt (st, pkt); } - while (pkt = tq_pkt[pkt].link); } } -else fprintf (st, "Unit %d queues are empty\n", u); -return SCPE_OK; -} - -t_stat tq_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, pkt; - -if (tq_csta != CST_UP) { - fprintf (st, "Controller is not initialized\n"); - return SCPE_OK; } -if (val & TQ_SH_RI) { - if (tq_pip) fprintf (st, "Polling in progress, host timer = %d\n", tq_hat); - else fprintf (st, "Host timer = %d\n", tq_hat); - fprintf (st, "Command "); - tq_show_ring (st, &tq_cq); - fprintf (st, "Response "); - tq_show_ring (st, &tq_rq); - } -if (val & TQ_SH_FR) { - if (pkt = tq_freq) { - for (i = 0; pkt != 0; i++, pkt = tq_pkt[pkt].link) { - if (i == 0) fprintf (st, "Free queue = %d", pkt); - else if ((i % 16) == 0) fprintf (st, ",\n %d", pkt); - else fprintf (st, ", %d", pkt); } - fprintf (st, "\n"); } - else fprintf (st, "Free queue is empty\n"); - } -if (val & TQ_SH_RS) { - if (pkt = tq_rspq) { - do { fprintf (st, "Response "); - tq_show_pkt (st, pkt); } - while (pkt = tq_pkt[pkt].link); } - else fprintf (st, "Response queue is empty\n"); - } -if (val & TQ_SH_UN) { - for (i = 0; i < TQ_NUMDR; i++) - tq_show_unitq (st, &tq_unit[i], 0, NULL); - } -return SCPE_OK; -} - -/* Set controller type (and capacity for user-defined type) */ - -tq_set_type (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -uint32 i, cap; -uint32 max = sim_taddr_64? TQU_EMAXC: TQU_MAXC; -t_stat r; - -if ((val < 0) || (val > TQU_TYPE) || ((val != TQU_TYPE) && cptr)) - return SCPE_ARG; -for (i = 0; i < TQ_NUMDR; i++) { - if (tq_unit[i].flags & UNIT_ATT) return SCPE_ALATT; } -if (cptr) { - cap = (uint32) get_uint (cptr, 10, max, &r); - if ((r != SCPE_OK) || (cap < TQU_MINC)) return SCPE_ARG; - drv_tab[TQU_TYPE].cap = ((t_addr) cap) << 20; } -tq_typ = val; -return SCPE_OK; -} - -/* Show controller type (and capacity for user-defined type) */ - -tq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, "%s", drv_tab[tq_typ].name); -if (tq_typ == TQU_TYPE) fprintf (st, " (%dMB)", drv_tab[tq_typ].cap >> 20); -return SCPE_OK; -} diff --git a/PDP11/pdp11_ts.c b/PDP11/pdp11_ts.c deleted file mode 100644 index caa95439..00000000 --- a/PDP11/pdp11_ts.c +++ /dev/null @@ -1,1011 +0,0 @@ -/* pdp11_ts.c: TS11/TSV05 magnetic tape simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - ts TS11/TSV05 magtape - - 19-May-03 RMS Revised for new conditional compilation scheme - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Revised to use magtape library - 30-Sep-02 RMS Added variable address support to bootstrap - Added vector change/display support - Fixed CTL unload/clean decode - Implemented XS0_MOT in extended status - New data structures, revamped error recovery - 28-Aug-02 RMS Added end of medium support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Added maximum record length protection - 04-Apr-02 RMS Fixed bug in residual frame count after space operation - 16-Feb-02 RMS Fixed bug in message header logic - 26-Jan-02 RMS Revised bootstrap to conform to M9312 - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 09-Nov-01 RMS Added bus map, VAX support - 15-Oct-01 RMS Integrated debug logging across simulator - 27-Sep-01 RMS Implemented extended characteristics and status - Fixed bug in write characteristics status return - 19-Sep-01 RMS Fixed bug in bootstrap - 15-Sep-01 RMS Fixed bug in NXM test - 07-Sep-01 RMS Revised device disable and interrupt mechanism - 13-Jul-01 RMS Fixed bug in space reverse (found by Peter Schorn) - - Magnetic tapes are represented as a series of variable 8b records - of the form: - - 32b record length in bytes - exact number - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32b record length in bytes - exact number - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a single record length of 0. - End of tape is two consecutive end of file marks. - - The TS11 functions in three environments: - - - PDP-11 Q22 systems - the I/O map is one for one, so it's safe to - go through the I/O map - - PDP-11 Unibus 22b systems - the TS11 behaves as an 18b Unibus - peripheral and must go through the I/O map - - VAX Q22 systems - the TS11 must go through the I/O map -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#error "TS11 not supported on PDP10!" - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -#define TS_DIS 0 /* on by default */ -#define ADDRTEST 0177700 -#define DMASK 0xFFFF -extern int32 ReadB (uint32 pa); -extern void WriteB (uint32 pa, int32 val); -extern int32 ReadW (uint32 pa); -extern void WriteW (uint32 pa, int32 val); -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -#define TS_DIS DEV_DIS /* off by default */ -#define ADDRTEST (UNIBUS? 0177774: 0177700) -extern uint16 *M; -extern int32 cpu_18b, cpu_ubm; -#define ReadB(p) ((M[(p) >> 1] >> (((p) & 1)? 8: 0)) & 0377) -#define WriteB(p,v) M[(p) >> 1] = ((p) & 1)? \ - ((M[(p) >> 1] & 0377) | ((v) << 8)): \ - ((M[(p) >> 1] & ~0377) | (v)) -#define ReadW(p) M[(p) >> 1] -#define WriteW(p,v) M[(p) >> 1] = (v) -#endif - -#include "sim_tape.h" - -/* TSBA/TSDB - 17772520: base address/data buffer register - - read: most recent memory address - write word: initiate command - write byte: diagnostic use -*/ - -/* TSSR - 17772522: subsystem status register - TSDBX - 17772523: extended address register - - read: return status - write word: initialize - write byte: if odd, set extended packet address register -*/ - -#define TSSR_SC 0100000 /* special condition */ -#define TSSR_RMR 0010000 /* reg mod refused */ -#define TSSR_NXM 0004000 /* nxm */ -#define TSSR_NBA 0002000 /* need buf addr */ -#define TSSR_V_EMA 8 /* mem addr<17:16> */ -#define TSSR_EMA 0001400 -#define TSSR_SSR 0000200 /* subsystem ready */ -#define TSSR_OFL 0000100 /* offline */ -#define TSSR_V_TC 1 /* term class */ -#define TSSR_M_TC 07 -#define TSSR_TC (TSSR_M_TC << TSSR_V_TC) -#define TC0 (0 << TSSR_V_TC) /* ok */ -#define TC1 (1 << TSSR_V_TC) /* attention */ -#define TC2 (2 << TSSR_V_TC) /* status alert */ -#define TC3 (3 << TSSR_V_TC) /* func reject */ -#define TC4 (4 << TSSR_V_TC) /* retry, moved */ -#define TC5 (5 << TSSR_V_TC) /* retry */ -#define TC6 (6 << TSSR_V_TC) /* pos lost */ -#define TC7 (7 << TSSR_V_TC) /* fatal err */ -#define TSSR_MBZ 0060060 -#define GET_TC(x) (((x) >> TSSR_V_TC) & TSSR_M_TC) - -#define TSDBX_M_XA 017 /* ext addr */ -#define TSDBX_BOOT 0000200 /* boot */ - -/* Command packet offsets */ - -#define CMD_PLNT 4 /* cmd pkt length */ -#define cmdhdr tscmdp[0] /* header */ -#define cmdadl tscmdp[1] /* address low */ -#define cmdadh tscmdp[2] /* address high */ -#define cmdlnt tscmdp[3] /* length */ - -/* Command packet header */ - -#define CMD_ACK 0100000 /* acknowledge */ -#define CMD_CVC 0040000 /* clear vol chk */ -#define CMD_OPP 0020000 /* opposite */ -#define CMD_SWP 0010000 /* swap bytes */ -#define CMD_V_MODE 8 /* mode */ -#define CMD_M_MODE 017 -#define CMD_IE 0000200 /* int enable */ -#define CMD_V_FNC 0 /* function */ -#define CMD_M_FNC 037 /* function */ -#define CMD_N_FNC (CMD_M_FNC + 1) -#define FNC_READ 001 /* read */ -#define FNC_WCHR 004 /* write char */ -#define FNC_WRIT 005 /* write */ -#define FNC_WSSM 006 /* write mem */ -#define FNC_POS 010 /* position */ -#define FNC_FMT 011 /* format */ -#define FNC_CTL 012 /* control */ -#define FNC_INIT 013 /* init */ -#define FNC_GSTA 017 /* get status */ -#define CMD_MBZ 0000140 -#define GET_FNC(x) (((x) >> CMD_V_FNC) & CMD_M_FNC) -#define GET_MOD(x) (((x) >> CMD_V_MODE) & CMD_M_MODE) - -/* Function test flags */ - -#define FLG_MO 001 /* motion */ -#define FLG_WR 002 /* write */ -#define FLG_AD 004 /* addr mem */ - -/* Message packet offsets */ - -#define MSG_PLNT 8 /* packet length */ -#define msghdr tsmsgp[0] /* header */ -#define msglnt tsmsgp[1] /* length */ -#define msgrfc tsmsgp[2] /* residual frame */ -#define msgxs0 tsmsgp[3] /* ext status 0 */ -#define msgxs1 tsmsgp[4] /* ext status 1 */ -#define msgxs2 tsmsgp[5] /* ext status 2 */ -#define msgxs3 tsmsgp[6] /* ext status 3 */ -#define msgxs4 tsmsgp[7] /* ext status 4 */ - -/* Message packet header */ - -#define MSG_ACK 0100000 /* acknowledge */ -#define MSG_MATN 0000000 /* attention */ -#define MSG_MILL 0000400 /* illegal */ -#define MSG_MNEF 0001000 /* non exec fnc */ -#define MSG_CEND 0000020 /* end */ -#define MSG_CFAIL 0000021 /* fail */ -#define MSG_CERR 0000022 /* error */ -#define MSG_CATN 0000023 /* attention */ - -/* Extended status register 0 */ - -#define XS0_TMK 0100000 /* tape mark */ -#define XS0_RLS 0040000 /* rec lnt short */ -#define XS0_LET 0020000 /* log end tape */ -#define XS0_RLL 0010000 /* rec lnt long */ -#define XS0_WLE 0004000 /* write lock err */ -#define XS0_NEF 0002000 /* non exec fnc */ -#define XS0_ILC 0001000 /* illegal cmd */ -#define XS0_ILA 0000400 /* illegal addr */ -#define XS0_MOT 0000200 /* tape has moved */ -#define XS0_ONL 0000100 /* online */ -#define XS0_IE 0000040 /* int enb */ -#define XS0_VCK 0000020 /* volume check */ -#define XS0_PET 0000010 /* 1600 bpi */ -#define XS0_WLK 0000004 /* write lock */ -#define XS0_BOT 0000002 /* BOT */ -#define XS0_EOT 0000001 /* EOT */ -#define XS0_ALLCLR 0177600 /* clear at start */ - -/* Extended status register 1 */ - -#define XS1_UCOR 0000002 /* uncorrectable */ - -/* Extended status register 2 */ - -#define XS2_XTF 0000200 /* ext features */ - -/* Extended status register 3 */ - -#define XS3_OPI 0000100 /* op incomplete */ -#define XS3_REV 0000040 /* reverse */ -#define XS3_RIB 0000001 /* reverse to BOT */ - -/* Extended status register 4 */ - -#define XS4_HDS 0100000 /* high density */ - -/* Write characteristics packet offsets */ - -#define WCH_PLNT 5 /* packet length */ -#define wchadl tswchp[0] /* address low */ -#define wchadh tswchp[1] /* address high */ -#define wchlnt tswchp[2] /* length */ -#define wchopt tswchp[3] /* options */ -#define wchxopt tswchp[4] /* ext options */ - -/* Write characteristics options */ - -#define WCH_ESS 0000200 /* stop dbl tmk */ -#define WCH_ENB 0000100 /* BOT = tmk */ -#define WCH_EAI 0000040 /* enb attn int */ -#define WCH_ERI 0000020 /* enb mrls int */ - -/* Write characteristics extended options */ - -#define WCHX_HDS 0000040 /* high density */ - -#define MAX(a,b) (((a) >= (b))? (a): (b)) - -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -extern UNIT cpu_unit; -extern int32 cpu_log; -extern FILE *sim_log; -uint8 *tsxb = NULL; /* xfer buffer */ -int32 tssr = 0; /* status register */ -int32 tsba = 0; /* mem addr */ -int32 tsdbx = 0; /* data buf ext */ -int32 tscmdp[CMD_PLNT] = { 0 }; /* command packet */ -int32 tsmsgp[MSG_PLNT] = { 0 }; /* message packet */ -int32 tswchp[WCH_PLNT] = { 0 }; /* wr char packet */ -int32 ts_ownc = 0; /* tape owns cmd */ -int32 ts_ownm = 0; /* tape owns msg */ -int32 ts_qatn = 0; /* queued attn */ -int32 ts_bcmd = 0; /* boot cmd */ -int32 ts_time = 10; /* record latency */ - -DEVICE ts_dev; -t_stat ts_rd (int32 *data, int32 PA, int32 access); -t_stat ts_wr (int32 data, int32 PA, int32 access); -t_stat ts_svc (UNIT *uptr); -t_stat ts_reset (DEVICE *dptr); -t_stat ts_attach (UNIT *uptr, char *cptr); -t_stat ts_detach (UNIT *uptr); -t_stat ts_boot (int32 unitno, DEVICE *dptr); -int32 ts_updtssr (int32 t); -int32 ts_updxs0 (int32 t); -void ts_cmpendcmd (int32 s0, int32 s1); -void ts_endcmd (int32 ssf, int32 xs0f, int32 msg); -int32 ts_map_status (t_stat st); - -/* TS data structures - - ts_dev TS device descriptor - ts_unit TS unit list - ts_reg TS register list - ts_mod TS modifier list -*/ - -DIB ts_dib = { IOBA_TS, IOLN_TS, &ts_rd, &ts_wr, - 1, IVCL (TS), VEC_TS, { NULL } }; - -UNIT ts_unit = { UDATA (&ts_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }; - -REG ts_reg[] = { - { GRDATA (TSSR, tssr, DEV_RDX, 16, 0) }, - { GRDATA (TSBA, tsba, DEV_RDX, 22, 0) }, - { GRDATA (TSDBX, tsdbx, DEV_RDX, 8, 0) }, - { GRDATA (CHDR, cmdhdr, DEV_RDX, 16, 0) }, - { GRDATA (CADL, cmdadl, DEV_RDX, 16, 0) }, - { GRDATA (CADH, cmdadh, DEV_RDX, 16, 0) }, - { GRDATA (CLNT, cmdlnt, DEV_RDX, 16, 0) }, - { GRDATA (MHDR, msghdr, DEV_RDX, 16, 0) }, - { GRDATA (MRFC, msgrfc, DEV_RDX, 16, 0) }, - { GRDATA (MXS0, msgxs0, DEV_RDX, 16, 0) }, - { GRDATA (MXS1, msgxs1, DEV_RDX, 16, 0) }, - { GRDATA (MXS2, msgxs2, DEV_RDX, 16, 0) }, - { GRDATA (MXS3, msgxs3, DEV_RDX, 16, 0) }, - { GRDATA (MSX4, msgxs4, DEV_RDX, 16, 0) }, - { GRDATA (WADL, wchadl, DEV_RDX, 16, 0) }, - { GRDATA (WADH, wchadh, DEV_RDX, 16, 0) }, - { GRDATA (WLNT, wchlnt, DEV_RDX, 16, 0) }, - { GRDATA (WOPT, wchopt, DEV_RDX, 16, 0) }, - { GRDATA (WXOPT, wchxopt, DEV_RDX, 16, 0) }, - { FLDATA (INT, IREQ (TS), INT_V_TS) }, - { FLDATA (ATTN, ts_qatn, 0) }, - { FLDATA (BOOT, ts_bcmd, 0) }, - { FLDATA (OWNC, ts_ownc, 0) }, - { FLDATA (OWNM, ts_ownm, 0) }, - { DRDATA (TIME, ts_time, 24), PV_LEFT + REG_NZ }, - { DRDATA (POS, ts_unit.pos, T_ADDR_W), PV_LEFT + REG_RO }, - { GRDATA (DEVADDR, ts_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, ts_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -MTAB ts_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE ts_dev = { - "TS", &ts_unit, ts_reg, ts_mod, - 1, 10, 31, 1, DEV_RDX, 8, - NULL, NULL, &ts_reset, - &ts_boot, &ts_attach, &ts_detach, - &ts_dib, DEV_DISABLE | TS_DIS | DEV_UBUS | DEV_QBUS }; - -/* I/O dispatch routine, I/O addresses 17772520 - 17772522 - - 17772520 TSBA read/write - 17772522 TSSR read/write -*/ - -t_stat ts_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* TSBA */ - *data = tsba & DMASK; /* low 16b of ba */ - break; -case 1: /* TSSR */ - *data = tssr = ts_updtssr (tssr); /* update tssr */ - break; } -return SCPE_OK; -} - -t_stat ts_wr (int32 data, int32 PA, int32 access) -{ -int32 i; -uint32 pa; - -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* TSDB */ - if ((tssr & TSSR_SSR) == 0) { /* ready? */ - tssr = tssr | TSSR_RMR; /* no, refuse */ - break; } - tsba = ((tsdbx & TSDBX_M_XA) << 18) | /* form pkt addr */ - ((data & 03) << 16) | (data & 0177774); - tsdbx = 0; /* clr tsdbx */ - tssr = ts_updtssr (tssr & TSSR_NBA); /* clr ssr, err */ - msgxs0 = ts_updxs0 (msgxs0 & ~XS0_ALLCLR); /* clr, upd xs0 */ - msgrfc = msgxs1 = msgxs2 = msgxs3 = msgxs4 = 0; /* clr status */ - CLR_INT (TS); /* clr int req */ - for (i = 0; i < CMD_PLNT; i++) { /* get cmd pkt */ - if (Map_Addr (tsba, &pa) && ADDR_IS_MEM (pa)) - tscmdp[i] = ReadW (pa); - else { - ts_endcmd (TSSR_NXM + TC5, 0, MSG_ACK|MSG_MNEF|MSG_CFAIL); - return SCPE_OK; } - tsba = tsba + 2; } /* incr tsba */ - ts_ownc = ts_ownm = 1; /* tape owns all */ - sim_activate (&ts_unit, ts_time); /* activate */ - break; -case 1: /* TSSR */ - if (PA & 1) { /* TSDBX */ - if (UNIBUS) return SCPE_OK; /* not in TS11 */ - if (tssr & TSSR_SSR) { /* ready? */ - tsdbx = data; /* save */ - if (data & TSDBX_BOOT) { - ts_bcmd = 1; - sim_activate (&ts_unit, ts_time); } } - else tssr = tssr | TSSR_RMR; } /* no, err */ - else if (access == WRITE) ts_reset (&ts_dev); /* reset */ - break; } -return SCPE_OK; -} - -/* Tape motion routines */ - -#define XTC(x,t) (((unsigned) (x) << 16) | (t)) -#define GET_X(x) (((x) >> 16) & 0177777) -#define GET_T(x) ((x) & 0177777) - -int32 ts_map_status (t_stat st) -{ -switch (st) { -case MTSE_OK: - break; -case MTSE_TMK: - msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ - return (XTC (XS0_TMK | XS0_RLS, TC2)); -case MTSE_RECE: /* record in error */ - msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ -case MTSE_INVRL: /* invalid rec lnt */ -case MTSE_IOERR: /* IO error */ - msgxs1 = msgxs1 | XS1_UCOR; /* uncorrectable */ - return (XTC (XS0_RLS, TC6)); /* pos lost */ -case MTSE_FMT: -case MTSE_UNATT: -case MTSE_EOM: /* end of medium */ - msgxs3 = msgxs3 | XS3_OPI; /* incomplete */ - return (XTC (XS0_RLS, TC6)); /* pos lost */ -case MTSE_BOT: /* reverse into BOT */ - msgxs3 = msgxs3 | XS3_RIB; /* set status */ - return (XTC (XS0_BOT | XS0_RLS, TC2)); /* tape alert */ -case MTSE_WRP: /* write protect */ - msgxs0 = msgxs0 | XS0_WLE | XS0_NEF; /* can't execute */ - return (XTC (XS0_WLE | XS0_NEF, TC3)); } -return 0; -} - -int32 ts_spacef (UNIT *uptr, int32 fc, t_bool upd) -{ -t_stat st; -t_mtrlnt tbc; - -do { fc = (fc - 1) & DMASK; /* decr wc */ - if (upd) msgrfc = fc; - if (st = sim_tape_sprecf (uptr, &tbc)) /* space rec fwd, err? */ - return ts_map_status (st); /* map status */ - msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ - } -while (fc != 0); -return 0; -} - -int32 ts_skipf (UNIT *uptr, int32 fc) -{ -t_stat st; -t_mtrlnt tbc; -t_bool tmkprv = FALSE; - -msgrfc = fc; -if (sim_tape_bot (uptr) && (wchopt & WCH_ENB)) tmkprv = TRUE; -do { st = sim_tape_sprecf (uptr, &tbc); /* space rec fwd */ - if (st == MTSE_TMK) { /* tape mark? */ - msgrfc = (msgrfc - 1) & DMASK; /* decr count */ - msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ - if (tmkprv && (wchopt & WCH_ESS)) /* 2nd tmk & ESS? */ - return (XTC ((msgrfc? XS0_RLS: 0) | - XS0_TMK | XS0_LET, TC2)); - tmkprv = TRUE; } /* flag tmk */ - else if (st != MTSE_OK) return ts_map_status (st); - else tmkprv = FALSE; /* not a tmk */ - msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ - } -while (msgrfc != 0); -return 0; -} - -int32 ts_spacer (UNIT *uptr, int32 fc, t_bool upd) -{ -int32 st; -t_mtrlnt tbc; - -do { fc = (fc - 1) & DMASK; /* decr wc */ - if (upd) msgrfc = fc; - if (st = sim_tape_sprecr (uptr, &tbc)) /* space rec rev, err? */ - return ts_map_status (st); /* map status */ - msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ - } -while (fc != 0); -return 0; -} - -int32 ts_skipr (UNIT *uptr, int32 fc) -{ -t_stat st; -t_mtrlnt tbc; -t_bool tmkprv = FALSE; - -msgrfc = fc; -do { st = sim_tape_sprecr (uptr, &tbc); /* space rec rev */ - if (st == MTSE_TMK) { /* tape mark? */ - msgrfc = (msgrfc - 1) & DMASK; /* decr count */ - msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ - if (tmkprv && (wchopt & WCH_ESS)) /* 2nd tmk & ESS? */ - return (XTC ((msgrfc? XS0_RLS: 0) | - XS0_TMK | XS0_LET, TC2)); - tmkprv = TRUE; } /* flag tmk */ - else if (st != MTSE_OK) return ts_map_status (st); - else tmkprv = FALSE; /* not a tmk */ - msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ - } -while (msgrfc != 0); -return 0; -} - -int32 ts_readf (UNIT *uptr, uint32 fc) -{ -t_stat st; -t_mtrlnt i, tbc, wbc; -uint32 wa, pa; - -msgrfc = fc; -st = sim_tape_rdrecf (uptr, tsxb, &tbc, MT_MAXFR); /* read rec fwd */ -if (st != MTSE_OK) return ts_map_status (st); /* error? */ -if (fc == 0) fc = 0200000; /* byte count */ -tsba = (cmdadh << 16) | cmdadl; /* buf addr */ -wbc = (tbc > fc)? fc: tbc; /* cap buf size */ -msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ -for (i = 0; i < wbc; i++) { /* copy buffer */ - wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply OPP */ - if (Map_Addr (wa, &pa) && ADDR_IS_MEM (pa)) /* map addr, nxm? */ - WriteB (pa, tsxb[i]); /* no, store */ - else { - tssr = ts_updtssr (tssr | TSSR_NXM); /* set error */ - return (XTC (XS0_RLS, TC4)); } - tsba = tsba + 1; - msgrfc = (msgrfc - 1) & DMASK; } -if (msgrfc) return (XTC (XS0_RLS, TC2)); /* buf too big? */ -if (tbc > wbc) return (XTC (XS0_RLL, TC2)); /* rec too big? */ -return 0; -} - -int32 ts_readr (UNIT *uptr, uint32 fc) -{ -t_stat st; -t_mtrlnt i, tbc, wbc; -uint32 wa, pa; - -msgrfc = fc; -st = sim_tape_rdrecr (uptr, tsxb, &tbc, MT_MAXFR); /* read rec rev */ -if (st != MTSE_OK) return ts_map_status (st); /* error? */ -if (fc == 0) fc = 0200000; /* byte count */ -tsba = (cmdadh << 16) | cmdadl + fc; /* buf addr */ -wbc = (tbc > fc)? fc: tbc; /* cap buf size */ -msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ -for (i = wbc; i > 0; i--) { /* copy buffer */ - tsba = tsba - 1; - wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply OPP */ - if (Map_Addr (wa, &pa) && ADDR_IS_MEM (pa)) /* map addr, nxm? */ - WriteB (pa, tsxb[i - 1]); /* no, store */ - else { - tssr = ts_updtssr (tssr | TSSR_NXM); - return (XTC (XS0_RLS, TC4)); } - msgrfc = (msgrfc - 1) & DMASK; } -if (msgrfc) return (XTC (XS0_RLS, TC2)); /* buf too big? */ -if (tbc > wbc) return (XTC (XS0_RLL, TC2)); /* rec too big? */ -return 0; -} - -int32 ts_write (UNIT *uptr, int32 fc) -{ -int32 i; -uint32 wa, pa; -t_stat st; - -msgrfc = fc; -if (fc == 0) fc = 0200000; /* byte count */ -tsba = (cmdadh << 16) | cmdadl; /* buf addr */ -for (i = 0; i < fc; i++) { /* copy mem to buf */ - wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply OPP */ - if (Map_Addr (wa, &pa) && ADDR_IS_MEM (pa)) /* map addr, nxm? */ - tsxb[i] = ReadB (pa); /* no, store */ - else { - tssr = ts_updtssr (tssr | TSSR_NXM); - return TC5; } - tsba = tsba + 1; } -if (st = sim_tape_wrrecf (uptr, tsxb, fc)) /* write rec, err? */ - return ts_map_status (st); /* return status */ -msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ -msgrfc = 0; -return 0; -} - -int32 ts_wtmk (UNIT *uptr) -{ -t_stat st; - -if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - return ts_map_status (st); /* return status */ -msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ -return XTC (XS0_TMK, TC0); -} - -/* Unit service */ - -t_stat ts_svc (UNIT *uptr) -{ -int32 i, fnc, mod, st0, st1; -uint32 pa; - -static const int32 fnc_mod[CMD_N_FNC] = { /* max mod+1 0 ill */ - 0, 4, 0, 0, 1, 2, 1, 0, /* 00 - 07 */ - 5, 3, 5, 1, 0, 0, 0, 1, /* 10 - 17 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 27 */ - 0, 0, 0, 0, 0, 0, 0, 0 }; /* 30 - 37 */ -static const int32 fnc_flg[CMD_N_FNC] = { - 0, FLG_MO+FLG_AD, 0, 0, 0, FLG_MO+FLG_WR+FLG_AD, FLG_AD, 0, - FLG_MO, FLG_MO+FLG_WR, FLG_MO, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 27 */ - 0, 0, 0, 0, 0, 0, 0, 0 }; /* 30 - 37 */ - -if (ts_bcmd) { /* boot? */ - ts_bcmd = 0; /* clear flag */ - sim_tape_rewind (uptr); /* rewind */ - if (uptr->flags & UNIT_ATT) { /* attached? */ - cmdlnt = cmdadh = cmdadl = 0; /* defang rd */ - ts_spacef (uptr, 1, FALSE); /* space fwd */ - ts_readf (uptr, 512); /* read blk */ - tssr = ts_updtssr (tssr | TSSR_SSR); } - else tssr = ts_updtssr (tssr | TSSR_SSR | TC3); - if (cmdhdr & CMD_IE) SET_INT (TS); - return SCPE_OK; } - -if (!(cmdhdr & CMD_ACK)) { /* no acknowledge? */ - tssr = ts_updtssr (tssr | TSSR_SSR); /* set rdy, int */ - if (cmdhdr & CMD_IE) SET_INT (TS); - ts_ownc = ts_ownm = 0; /* CPU owns all */ - return SCPE_OK; } -fnc = GET_FNC (cmdhdr); /* get fnc+mode */ -mod = GET_MOD (cmdhdr); -if (DBG_LOG (LOG_TS)) - fprintf (sim_log, ">>TS: cmd=%o, mod=%o, buf=%o, lnt=%d, pos=%d\n", - fnc, mod, cmdadl, cmdlnt, ts_unit.pos); -if ((fnc != FNC_WCHR) && (tssr & TSSR_NBA)) { /* ~wr chr & nba? */ - ts_endcmd (TC3, 0, 0); /* error */ - return SCPE_OK; } -if (ts_qatn && (wchopt & WCH_EAI)) { /* attn pending? */ - ts_endcmd (TC1, 0, MSG_MATN | MSG_CATN); /* send attn msg */ - SET_INT (TS); /* set interrupt */ - ts_qatn = 0; /* not pending */ - return SCPE_OK; } -if (cmdhdr & CMD_CVC) /* cvc? clr vck */ - msgxs0 = msgxs0 & ~XS0_VCK; -if ((cmdhdr & CMD_MBZ) || (mod >= fnc_mod[fnc])) { /* test mbz */ - ts_endcmd (TC3, XS0_ILC, MSG_ACK | MSG_MILL | MSG_CFAIL); - return SCPE_OK; } -if ((fnc_flg[fnc] & FLG_MO) && /* mot+(vck|!att)? */ - ((msgxs0 & XS0_VCK) || !(uptr->flags & UNIT_ATT))) { - ts_endcmd (TC3, XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL); - return SCPE_OK; } -if ((fnc_flg[fnc] & FLG_WR) && /* write? */ - sim_tape_wrp (uptr)) { /* write lck? */ - ts_endcmd (TC3, XS0_WLE | XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL); - return SCPE_OK; } -if ((((fnc == FNC_READ) && (mod == 1)) || /* read rev */ - ((fnc == FNC_POS) && (mod & 1))) && /* space rev */ - sim_tape_bot (uptr)) { /* BOT? */ - ts_endcmd (TC3, XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL); - return SCPE_OK; } -if ((fnc_flg[fnc] & FLG_AD) && (cmdadh & ADDRTEST)) { /* buf addr > 22b? */ - ts_endcmd (TC3, XS0_ILA, MSG_ACK | MSG_MILL | MSG_CFAIL); - return SCPE_OK; } - -st0 = st1 = 0; -switch (fnc) { /* case on func */ -case FNC_INIT: /* init */ - if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* set if tape moves */ - sim_tape_rewind (uptr); /* rewind */ -case FNC_WSSM: /* write mem */ -case FNC_GSTA: /* get status */ - ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); /* send end packet */ - return SCPE_OK; -case FNC_WCHR: /* write char */ - if ((cmdadh & ADDRTEST) || (cmdadl & 1) || (cmdlnt < 6)) { - ts_endcmd (TSSR_NBA | TC3, XS0_ILA, 0); - break; } - tsba = (cmdadh << 16) | cmdadl; - for (i = 0; (i < WCH_PLNT) && (i < (cmdlnt / 2)); i++) { - if (Map_Addr (tsba, &pa) && ADDR_IS_MEM (pa)) - tswchp[i] = ReadW (pa); - else { - ts_endcmd (TSSR_NBA | TSSR_NXM | TC5, 0, 0); - return SCPE_OK; } - tsba = tsba + 2; } - if ((wchlnt < ((MSG_PLNT - 1) * 2)) || (wchadh & 0177700) || - (wchadl & 1)) ts_endcmd (TSSR_NBA | TC3, 0, 0); - else { - msgxs2 = msgxs2 | XS2_XTF | 1; - tssr = ts_updtssr (tssr & ~TSSR_NBA); - ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); } - return SCPE_OK; -case FNC_CTL: /* control */ - switch (mod) { /* case mode */ - case 00: /* msg buf rls */ - tssr = ts_updtssr (tssr | TSSR_SSR); /* set SSR */ - if (wchopt & WCH_ERI) SET_INT (TS); - ts_ownc = 0; ts_ownm = 1; /* keep msg */ - break; - case 01: /* rewind and unload */ - if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */ - sim_tape_detach (uptr); /* unload */ - ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); - break; - case 02: /* clean */ - ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); /* nop */ - break; - case 03: /* undefined */ - ts_endcmd (TC3, XS0_ILC, MSG_ACK | MSG_MILL | MSG_CFAIL); - return SCPE_OK; - case 04: /* rewind */ - if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */ - sim_tape_rewind (uptr); - ts_endcmd (TC0, XS0_BOT, MSG_ACK | MSG_CEND); - break; } - break; - -case FNC_READ: /* read */ - switch (mod) { /* case mode */ - case 00: /* fwd */ - st0 = ts_readf (uptr, cmdlnt); /* read */ - break; - case 01: /* back */ - st0 = ts_readr (uptr, cmdlnt); /* read */ - break; - case 02: /* reread fwd */ - if (cmdhdr & CMD_OPP) { /* opposite? */ - st0 = ts_readr (uptr, cmdlnt); - st1 = ts_spacef (uptr, 1, FALSE); } - else { - st0 = ts_spacer (uptr, 1, FALSE); - st1 = ts_readf (uptr, cmdlnt); } - break; - case 03: /* reread back */ - if (cmdhdr & CMD_OPP) { /* opposite */ - st0 = ts_readf (uptr, cmdlnt); - st1 = ts_spacer (uptr, 1, FALSE); } - else { - st0 = ts_spacef (uptr, 1, FALSE); - st1 = ts_readr (uptr, cmdlnt); } - break; } - ts_cmpendcmd (st0, st1); - break; -case FNC_WRIT: /* write */ - switch (mod) { /* case mode */ - case 00: /* write */ - st0 = ts_write (uptr, cmdlnt); - break; - case 01: /* rewrite */ - st0 = ts_spacer (uptr, 1, FALSE); - st1 = ts_write (uptr, cmdlnt); - break; } - ts_cmpendcmd (st0, st1); - break; -case FNC_FMT: /* format */ - switch (mod) { /* case mode */ - case 00: /* write tmk */ - st0 = ts_wtmk (uptr); - break; - case 01: /* erase */ - break; - case 02: /* retry tmk */ - st0 = ts_spacer (uptr, 1, FALSE); - st1 = ts_wtmk (uptr); - break; } - ts_cmpendcmd (st0, st1); - break; -case FNC_POS: - switch (mod) { /* case mode */ - case 00: /* space fwd */ - st0 = ts_spacef (uptr, cmdadl, TRUE); - break; - case 01: /* space rev */ - st0 = ts_spacer (uptr, cmdadl, TRUE); - break; - case 02: /* space ffwd */ - st0 = ts_skipf (uptr, cmdadl); - break; - case 03: /* space frev */ - st0 = ts_skipr (uptr, cmdadl); - break; - case 04: /* rewind */ - if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */ - sim_tape_rewind (uptr); - break; } - ts_cmpendcmd (st0, 0); - break; } -return SCPE_OK; -} - -/* Utility routines */ - -int32 ts_updtssr (int32 t) -{ -t = (t & ~TSSR_EMA) | ((tsba >> (16 - TSSR_V_EMA)) & TSSR_EMA); -if (ts_unit.flags & UNIT_ATT) t = t & ~TSSR_OFL; -else t = t | TSSR_OFL; -return (t & ~TSSR_MBZ); -} - -int32 ts_updxs0 (int32 t) -{ -t = (t & ~(XS0_ONL | XS0_WLK | XS0_BOT | XS0_IE)) | XS0_PET; -if (ts_unit.flags & UNIT_ATT) { - t = t | XS0_ONL; - if (sim_tape_wrp (&ts_unit)) t = t | XS0_WLK; - if (sim_tape_bot (&ts_unit)) t = (t | XS0_BOT) & ~XS0_EOT; } -else t = t & ~XS0_EOT; -if (cmdhdr & CMD_IE) t = t | XS0_IE; -return t; -} - -void ts_cmpendcmd (int32 s0, int32 s1) -{ -int32 xs0, ssr, tc; -static const int32 msg[8] = { - MSG_ACK | MSG_CEND, MSG_ACK | MSG_MATN | MSG_CATN, - MSG_ACK | MSG_CEND, MSG_ACK | MSG_CFAIL, - MSG_ACK | MSG_CERR, MSG_ACK | MSG_CERR, - MSG_ACK | MSG_CERR, MSG_ACK | MSG_CERR }; - -xs0 = GET_X (s0) | GET_X (s1); /* or XS0 errs */ -s0 = GET_T (s0); /* get SSR errs */ -s1 = GET_T (s1); -ssr = (s0 | s1) & ~TSSR_TC; /* or SSR errs */ -tc = MAX (GET_TC (s0), GET_TC (s1)); /* max term code */ -ts_endcmd (ssr | (tc << TSSR_V_TC), xs0, msg[tc]); /* end cmd */ -return; -} - -void ts_endcmd (int32 tc, int32 xs0, int32 msg) -{ -int32 i; -uint32 pa; - -msgxs0 = ts_updxs0 (msgxs0 | xs0); /* update XS0 */ -if (wchxopt & WCHX_HDS) msgxs4 = msgxs4 | XS4_HDS; /* update XS4 */ -if (msg && !(tssr & TSSR_NBA)) { /* send end pkt */ - msghdr = msg; - msglnt = wchlnt - 4; /* exclude hdr, bc */ - tsba = (wchadh << 16) | wchadl; - for (i = 0; (i < MSG_PLNT) && (i < (wchlnt / 2)); i++) { - if (Map_Addr (tsba, &pa) && ADDR_IS_MEM (pa)) - WriteW (pa, tsmsgp[i]); - else { - tssr = tssr | TSSR_NXM; - tc = (tc & ~TSSR_TC) | TC4; - break; } - tsba = tsba + 2; } } -tssr = ts_updtssr (tssr | tc | TSSR_SSR | (tc? TSSR_SC: 0)); -if (cmdhdr & CMD_IE) SET_INT (TS); -ts_ownm = 0; ts_ownc = 0; -if (DBG_LOG (LOG_TS)) - fprintf (sim_log, ">>TS: sta=%o, tc=%o, rfc=%d, pos=%d\n", - msgxs0, GET_TC (tssr), msgrfc, ts_unit.pos); -return; -} - -/* Device reset */ - -t_stat ts_reset (DEVICE *dptr) -{ -int32 i; - -sim_tape_rewind (&ts_unit); -tsba = tsdbx = 0; -ts_ownc = ts_ownm = 0; -ts_bcmd = 0; -ts_qatn = 0; -tssr = ts_updtssr (TSSR_NBA | TSSR_SSR); -for (i = 0; i < CMD_PLNT; i++) tscmdp[i] = 0; -for (i = 0; i < WCH_PLNT; i++) tswchp[i] = 0; -for (i = 0; i < MSG_PLNT; i++) tsmsgp[i] = 0; -msgxs0 = ts_updxs0 (XS0_VCK); -CLR_INT (TS); -if (tsxb == NULL) tsxb = calloc (MT_MAXFR, sizeof (unsigned int8)); -if (tsxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Attach */ - -t_stat ts_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = sim_tape_attach (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* error? */ -tssr = tssr & ~TSSR_OFL; /* clr offline */ -if ((tssr & TSSR_NBA) || !(wchopt & WCH_EAI)) return r; /* attn msg? */ -if (ts_ownm) { /* own msg buf? */ - ts_endcmd (TC1, 0, MSG_MATN | MSG_CATN); /* send attn */ - SET_INT (TS); /* set interrupt */ - ts_qatn = 0; } /* don't queue */ -else ts_qatn = 1; /* else queue */ -return r; -} - -/* Detach routine */ - -t_stat ts_detach (UNIT* uptr) -{ -t_stat r; - -r = sim_tape_detach (uptr); /* detach unit */ -if (r != SCPE_OK) return r; /* error? */ -tssr = tssr | TSSR_OFL; /* set offline */ -if ((tssr & TSSR_NBA) || !(wchopt & WCH_EAI)) return r; /* attn msg? */ -if (ts_ownm) { /* own msg buf? */ - ts_endcmd (TC1, 0, MSG_MATN | MSG_CATN); /* send attn */ - SET_INT (TS); /* set interrupt */ - ts_qatn = 0; } /* don't queue */ -else ts_qatn = 1; /* else queue */ -return r; -} - -/* Boot */ - -#if defined (VM_PDP11) -#define BOOT_START 01000 -#define BOOT_CSR0 (BOOT_START + 006) -#define BOOT_CSR1 (BOOT_START + 012) -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 0012706, 0001000, /* mov #boot_start, sp */ - 0012700, 0172520, /* mov #tsba, r0 */ - 0012701, 0172522, /* mov #tssr, r1 */ - 0005011, /* clr (r1) ; init, rew */ - 0105711, /* tstb (r1) ; wait */ - 0100376, /* bpl .-2 */ - 0012710, 0001070, /* mov #pkt1, (r0) ; set char */ - 0105711, /* tstb (r1) ; wait */ - 0100376, /* bpl .-2 */ - 0012710, 0001110, /* mov #pkt2, (r0) ; read, skip */ - 0105711, /* tstb (r1) ; wait */ - 0100376, /* bpl .-2 */ - 0012710, 0001110, /* mov #pkt2, (r0) ; read */ - 0105711, /* tstb (r1) ; wait */ - 0100376, /* bpl .-2 */ - 0005711, /* tst (r1) ; err? */ - 0100421, /* bmi hlt */ - 0005000, /* clr r0 */ - 0012704, 0001066+020, /* mov #sgnt+20, r4 */ - 0005007, /* clr r7 */ - 0046523, /* sgnt: "SM" */ - 0140004, /* pkt1: 140004, wcpk, 0, 8. */ - 0001100, - 0000000, - 0000010, - 0001122, /* wcpk: msg, 0, 14., 0 */ - 0000000, - 0000016, - 0000000, - 0140001, /* pkt2: 140001, 0, 0, 512. */ - 0000000, - 0000000, - 0001000, - 0000000 /* hlt: halt */ - /* msg: .blk 4 */ -}; - -t_stat ts_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -sim_tape_rewind (&ts_unit); -for (i = 0; i < BOOT_LEN; i++) - M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_CSR0 >> 1] = ts_dib.ba & DMASK; -M[BOOT_CSR1 >> 1] = (ts_dib.ba & DMASK) + 02; -saved_PC = BOOT_START; -return SCPE_OK; -} -#else - -t_stat ts_boot (int32 unitno, DEVICE *dptr) -{ -return SCPE_NOFNC; -} -#endif diff --git a/PDP11/pdp11_uqssp.h b/PDP11/pdp11_uqssp.h deleted file mode 100644 index 257d41bc..00000000 --- a/PDP11/pdp11_uqssp.h +++ /dev/null @@ -1,169 +0,0 @@ -/* pdp11_uqssp.h: Unibus/Qbus storage systems port definitions file - - Copyright (c) 2001-2003, Robert M Supnik - Derived from work by Stephen F. Shirron - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 30-Aug-02 RMS Added TMSCP support -*/ - -#ifndef _PDP11_UQSSP_H_ -#define _PDP11_UQSSP_H_ 0 - -/* IP register - initialization and polling - - read - controller polls command queue - write - controller re-initializes -*/ - -/* SA register - status, address, and purge - - read - data and error information - write - host startup information, purge complete -*/ - -#define SA_ER 0x8000 /* error */ -#define SA_S4 0x4000 /* init step 4 */ -#define SA_S3 0x2000 /* init step 3 */ -#define SA_S2 0x1000 /* init step 2 */ -#define SA_S1 0x0800 /* init step 1 */ - -/* Init step 1, controller to host */ - -#define SA_S1C_NV 0x0400 /* fixed vec NI */ -#define SA_S1C_Q22 0x0200 /* Q22 device */ -#define SA_S1C_DI 0x0100 /* ext diags */ -#define SA_S1C_OD 0x0080 /* odd addrs NI */ -#define SA_S1C_MP 0x0040 /* mapping */ -#define SA_S1C_SM 0x0020 /* spec fncs NI */ -#define SA_S1C_CN 0x0010 /* node name NI */ - -/* Init step 1, host to controller */ - -#define SA_S1H_VL 0x8000 /* valid */ -#define SA_S1H_WR 0x4000 /* wrap mode */ -#define SA_S1H_V_CQ 11 /* cmd q len */ -#define SA_S1H_M_CQ 0x7 -#define SA_S1H_V_RQ 8 /* resp q len */ -#define SA_S1H_M_RQ 0x7 -#define SA_S1H_IE 0x0080 /* int enb */ -#define SA_S1H_VEC 0x007F /* vector */ -#define SA_S1H_CQ(x) (1 << (((x) >> SA_S1H_V_CQ) & SA_S1H_M_CQ)) -#define SA_S1H_RQ(x) (1 << (((x) >> SA_S1H_V_RQ) & SA_S1H_M_RQ)) - -/* Init step 2, controller to host */ - -#define SA_S2C_PT 0x0000 /* port type */ -#define SA_S2C_V_EC 8 /* info to echo */ -#define SA_S2C_M_EC 0xFF -#define SA_S2C_EC(x) (((x) >> SA_S2C_V_EC) & SA_S2C_M_EC) - -/* Init step 2, host to controller */ - -#define SA_S2H_CLO 0xFFFE /* comm addr lo */ -#define SA_S2H_PI 0x0001 /* adp prg int */ - -/* Init step 3, controller to host */ - -#define SA_S3C_V_EC 0 /* info to echo */ -#define SA_S3C_M_EC 0xFF -#define SA_S3C_EC(x) (((x) >> SA_S3C_V_EC) & SA_S3C_M_EC) - -/* Init step 3, host to controller */ - -#define SA_S3H_PP 0x8000 /* purge, poll test */ -#define SA_S3H_CHI 0x7FFF /* comm addr hi */ - -/* Init step 4, controller to host */ - -#define SA_S4C_V_MOD 4 /* adapter # */ -#define SA_S4C_V_VER 0 /* version # */ - -/* Init step 4, host to controller */ - -#define SA_S4H_CS 0x0400 /* host scrpad NI */ -#define SA_S4H_NN 0x0200 /* snd node name NI */ -#define SA_S4H_SF 0x0100 /* spec fnc NI */ -#define SA_S4H_LF 0x0002 /* send last fail */ -#define SA_S4H_GO 0x0001 /* go */ - -/* Fatal error codes (generic through 32) */ - -#define PE_PRE 1 /* packet read err */ -#define PE_PWE 2 /* packet write err */ -#define PE_QRE 6 /* queue read err */ -#define PE_QWE 7 /* queue write err */ -#define PE_HAT 9 /* host access tmo */ -#define PE_ICI 14 /* inv conn ident */ -#define PE_PIE 20 /* prot incompat */ -#define PE_PPF 21 /* prg/poll err */ -#define PE_MRE 22 /* map reg rd err */ -#define PE_T11 475 /* T11 err NI */ -#define PE_SND 476 /* SND err NI */ -#define PE_RCV 477 /* RCV err NI */ -#define PE_NSR 478 /* no such rsrc */ - -/* Comm region offsets */ - -#define SA_COMM_QQ -8 /* unused */ -#define SA_COMM_PI -6 /* purge int */ -#define SA_COMM_CI -4 /* cmd int */ -#define SA_COMM_RI -2 /* resp int */ -#define SA_COMM_MAX ((4 << SA_S1H_M_CQ) + (4 << SA_S1H_M_RQ) - SA_COMM_QQ) - -/* Command/response rings */ - -struct uq_ring { - int32 ioff; /* intr offset */ - uint32 ba; /* base addr */ - uint32 lnt; /* size in bytes */ - uint32 idx; /* current index */ - }; - -/* Ring descriptor entry */ - -#define UQ_DESC_OWN 0x80000000 /* ownership */ -#define UQ_DESC_F 0x40000000 /* flag */ -#define UQ_ADDR 0x003FFFFE /* addr, word aligned */ - -/* Packet header */ - -#define UQ_HDR_OFF -4 /* offset */ - -#define UQ_HLNT 0 /* length */ -#define UQ_HCTC 1 /* credits, type, CID */ - -#define UQ_HCTC_V_CR 0 /* credits */ -#define UQ_HCTC_M_CR 0xF -#define UQ_HCTC_V_TYP 4 /* type */ -#define UQ_HCTC_M_TYP 0xF -#define UQ_TYP_SEQ 0 /* sequential */ -#define UQ_TYP_DAT 1 /* datagram */ -#define UQ_HCTC_V_CID 8 /* conn ID */ -#define UQ_HCTC_M_CID 0xFF -#define UQ_CID_MSCP 0 /* MSCP */ -#define UQ_CID_TMSCP 1 /* TMSCP */ -#define UQ_CID_DUP 2 /* DUP */ -#define UQ_CID_DIAG 0xFF /* diagnostic */ - -#endif diff --git a/PDP11/pdp11_xq.c b/PDP11/pdp11_xq.c deleted file mode 100644 index 8b3e96a9..00000000 --- a/PDP11/pdp11_xq.c +++ /dev/null @@ -1,2240 +0,0 @@ -/* pdp11_xq.c: DEQNA/DELQA ethernet controller simulator - ------------------------------------------------------------------------------ - - Copyright (c) 2002-2003, David T. Hittner - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of the author shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from the author. - - ------------------------------------------------------------------------------ - - This DEQNA/DELQA simulation is based on: - Digital DELQA Users Guide, Part# EK-DELQA-UG-002 - Digital DEQNA Users Guide, Part# EK-DEQNA-UG-001 - These manuals can be found online at: - http://www.spies.com/~aek/pdf/dec/qbus - - Certain adaptations have been made because this is an emulation: - Ethernet transceiver power flag CSR<12> is ON when attached. - External Loopback does not go out to the physical adapter, it is - implemented more like an extended Internal Loopback - Time Domain Reflectometry (TDR) numbers are faked - The 10-second approx. hardware/software reset delay does not exist - Some physical ethernet receive events like Runts, Overruns, etc. are - never reported back, since the packet-level driver never sees them - - Certain advantages are derived from this emulation: - If the real ethernet controller is faster than 10Mbit/sec, the speed is - seen by the simulated cpu since there are no minimum response times. - - Known Bugs or Unsupported features, in priority order: - 1) PDP11 (modified) bootrom loader [done! 10-Apr-03] - 2) Second controller [done! 05-May-03] - 3) Cannot split inbound packet into multiple buffers [done! 05-Jun-03] - 4) PDP11 bootstrap - 5) MOP functionality not implemented - 6) Local packet processing not implemented - - Regression Tests used by the Author: - VAX: - 1. Console SHOW DEVICE - 2. VMS v7.2 boots/initializes/shows device - 3. VMS DECNET - SET HOST and COPY tests - 4. VMS MultiNet - SET HOST/TELNET and FTP tests - 5. VMS LAT - SET HOST/LAT tests - 6. VMS Cluster - SHOW CLUSTER, SHOW DEVICE, and cluster disk COPY tests - 7. Console boot into VMSCluster (>>>B XQAO) - PDP11: - 1. RT-11 v5.3 - FTPSB copy test - - ------------------------------------------------------------------------------ - - Modification history: - - 05-Jun-03 DTH Added receive packet splitting - 03-Jun-03 DTH Added SHOW XQ FILTERS - 02-Jun-03 DTH Added SET/SHOW XQ STATS (packet statistics), runt & giant processing - 28-May-03 DTH Modified message queue for dynamic size to shrink executable - 28-May-03 MP Fixed bug in xq_setmac - 06-May-03 DTH Changed 32-bit t_addr to uint32 for v3.0 - Removed SET ADDRESS functionality - 05-May-03 DTH Added second controller - 26-Mar-03 DTH Added PDP11 bootrom loader - Adjusted xq_ex and xq_dev to allow pdp11 to look at bootrom - Patched bootrom to allow "pass" of diagnostics on RSTS/E - 06-Mar-03 DTH Corrected interrupts on IE state transition (code by Tom Evans) - Added interrupt clear on soft reset (first noted by Bob Supnik) - Removed interrupt when setting XL or RL (multiple people) - 16-Jan-03 DTH Merged Mark Pizzolato's enhancements with main source - Corrected PDP11 XQ_DEBUG compilation - 15-Jan-03 MP Fixed the number of units in the xq device structure. - 13-Jan-03 MP Reworked the timer management logic which initiated - the system id broadcast messages. The original - implementation triggered this on the CSR transition - of Receiver Enabled. This was an issue since the - it seems that at least VMS's XQ driver makes this - transition often and the resulting overhead reduces - the simulated CPU instruction execution thruput by - about 40%. I start the system id timer on device - reset and it fires once a second so that it can - leverage the reasonably recalibrated tmr_poll value. - 13-Jan-03 MP Changed the scheduling of xq_svc to leverage the - dynamically computed clock values to achieve an - approximate interval of 100 per second. This is - more than sufficient for normal system behaviour - expecially since we service recieves with every - transmit. The previous fixed value of 2500 - attempted to get 200/sec but it was a guess that - didn't adapt. On faster host systems (possibly - most of them) the 2500 number spends too much time - polling. - 10-Jan-03 DTH Removed XQ_DEBUG dependency from Borland #pragmas - Added SET XQ BOOTROM command for PDP11s - 07-Jan-03 DTH Added pointer to online manuals - 02-Jan-03 DTH Added local packet processing - 30-Dec-02 DTH Added automatic system id broadcast - 27-Dec-02 DTH Merged Mark Pizzolato's enhancements with main source - 20-Dec-02 MP Fix bug that caused VMS system crashes when attempting cluster - operations. Added additional conditionally compiled debug - info needed to track down the issue. - 17-Dec-02 MP Added SIMH "registers" describing the Ethernet state - so this information can be recorded in a "saved" snapshot. - 05-Dec-02 MP Adjusted the rtime value from 100 to 2500 which increased the - available CPU cycles for Instruction execution by almost 100%. - This made sense after the below enhancements which, in general - caused the draining of the received data stream much more - agressively with less overhead. - 05-Dec-02 MP Added a call to xq_svc after all successful calls to eth_write - to allow receive processing to happen before the next event - service time. - 05-Dec-02 MP Restructured the flow of processing in xq_svc so that eth_read - is called repeatedly until either a packet isn't found or - there is no room for another one in the queue. Once that has - been done, xq_processrdbl is called to pass the queued packets - into the simulated system as space is available there. - xq_process_rdbl is also called at the beginning of xq_svc to - drain the queue into the simulated system, making more room - available in the queue. No processing is done at all in - xq_svc if the receiver is disabled. - 04-Dec-02 MP Changed interface and usage to xq_insert_queue to pass - the packet to be inserted by reference. This avoids 3K bytes - of buffer copy operations for each packet received. Now only - copy actual received packet data. - 31-Oct-02 DTH Cleaned up pointer warnings (found by Federico Schwindt) - Corrected unattached and no network behavior - Added message when SHOW XQ ETH finds no devices - 23-Oct-02 DTH Beta 5 released - 22-Oct-02 DTH Added all_multicast and promiscuous support - 21-Oct-02 DTH Added write buffer max size check (code by Jason Thorpe) - Corrected copyright again - Implemented NXM testing and recovery - 16-Oct-02 DTH Beta 4 released - Added and debugged Sanity Timer code - Corrected copyright - 15-Oct-02 DTH Rollback to known good Beta3 and roll forward; TCP broken - 12-Oct-02 DTH Fixed VAX network bootstrap; setup packets must return TDR > 0 - 11-Oct-02 DTH Added SET/SHOW XQ TYPE and SET/SHOW XQ SANITY commands - 10-Oct-02 DTH Beta 3 released; Integrated with 2.10-0b1 - Fixed off-by-1 bug on xq->setup.macs[7..13] - Added xq_make_checksum - Added rejection of multicast addresses in SET XQ MAC - 08-Oct-02 DTH Beta 2 released; Integrated with 2.10-0p4 - Added variable vector (fixes PDP11) and copyrights - 03-Oct-02 DTH Beta version of xq/sim_ether released for SIMH 2.09-11 - 24-Sep-02 DTH Moved more code to Sim_Ether module, added SHOW ETH command - 23-Sep-02 DTH Added SET/SHOW MAC command - 22-Sep-02 DTH Multinet TCP/IP loaded, tests OK via SET HOST/TELNET - 20-Sep-02 DTH Cleaned up code fragments, fixed non-DECNET MAC use - 19-Sep-02 DTH DECNET finally stays up; successful SET HOST to another node - 15-Sep-02 DTH Added ethernet packet read/write - 13-Sep-02 DTH DECNET starts, but circuit keeps going up & down - 26-Aug-02 DTH DECNET loaded, returns device timeout - 22-Aug-02 DTH VMS 7.2 recognizes device as XQA0 - 18-Aug-02 DTH VAX sees device as XQA0; shows hardcoded MAC correctly - 15-Aug-02 DTH Started XQ simulation - - ------------------------------------------------------------------------------ -*/ - -/* compiler directives to help the Author keep the code clean :-) */ -#if defined (__BORLANDC__) -#pragma warn +8070 /* function should return value */ -/* #pragma warn +8071 *//* conversion may lose significant digits */ -#pragma warn +8075 /* suspicious pointer conversion */ -#pragma warn +8079 /* mixing different char pointers */ -#pragma warn +8080 /* variable declared but not used */ -#endif /* __BORLANDC__ */ - -#include -#include "pdp11_xq.h" -#include "pdp11_xq_bootrom.h" - -#define XQ_MAX_CONTROLLERS 2 /* maximum controllers allowed */ - -extern int32 int_req[IPL_HLVL]; -extern int32 tmr_poll, clk_tps; -extern FILE *sim_log; - -/* forward declarations */ -t_stat xq_rd(int32* data, int32 PA, int32 access); -t_stat xq_wr(int32 data, int32 PA, int32 access); -t_stat xq_svc(UNIT * uptr); -t_stat xq_sansvc(UNIT * uptr); -t_stat xq_idsvc(UNIT * uptr); -t_stat xq_reset (DEVICE * dptr); -t_stat xq_attach (UNIT * uptr, char * cptr); -t_stat xq_detach (UNIT * uptr); -t_stat xq_showmac (FILE* st, UNIT* uptr, int32 val, void* desc); -t_stat xq_setmac (UNIT* uptr, int32 val, char* cptr, void* desc); -t_stat xq_show_filters (FILE* st, UNIT* uptr, int32 val, void* desc); -t_stat xq_show_stats (FILE* st, UNIT* uptr, int32 val, void* desc); -t_stat xq_set_stats (UNIT* uptr, int32 val, char* cptr, void* desc); -t_stat xq_show_type (FILE* st, UNIT* uptr, int32 val, void* desc); -t_stat xq_set_type (UNIT* uptr, int32 val, char* cptr, void* desc); -t_stat xq_show_sanity (FILE* st, UNIT* uptr, int32 val, void* desc); -t_stat xq_set_sanity (UNIT* uptr, int32 val, char* cptr, void* desc); -t_stat xq_showeth (FILE* st, UNIT* uptr, int32 val, void* desc); -t_stat xq_process_xbdl(CTLR* xq); -t_stat xq_dispatch_xbdl(CTLR* xq); -void xq_start_receiver(void); -void xq_sw_reset(CTLR* xq); -int32 xq_inta (void); -int32 xq_intb (void); -t_stat xq_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat xq_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -void xq_start_santmr(CTLR* xq); -void xq_cancel_santmr(CTLR* xq); -void xq_reset_santmr(CTLR* xq); -t_stat xq_boot_host(void); -void xq_start_idtmr(CTLR* xq); -t_stat xq_system_id(CTLR* xq, const ETH_MAC dst, uint16 receipt_id); -void xqa_read_callback(int status); -void xqb_read_callback(int status); -void xqa_write_callback(int status); -void xqb_write_callback(int status); - -struct xq_device xqa = { - xqa_read_callback, /* read callback routine */ - xqa_write_callback, /* write callback routine */ - {0x08, 0x00, 0x2B, 0xAA, 0xBB, 0xCC}, /* mac */ - XQ_T_DELQA, /* type */ - {0} /* sanity */ - }; - -struct xq_device xqb = { - xqb_read_callback, /* read callback routine */ - xqb_write_callback, /* write callback routine */ - {0x08, 0x00, 0x2B, 0xBB, 0xCC, 0xDD}, /* mac */ - XQ_T_DELQA, /* type */ - {0} /* sanity */ - }; - -/* SIMH device structures */ -DIB xqa_dib = { IOBA_XQ, IOLN_XQ, &xq_rd, &xq_wr, - 1, IVCL (XQ), 0, { &xq_inta } }; - -UNIT xqa_unit[] = { - { UDATA (&xq_svc, UNIT_ATTABLE + UNIT_DISABLE, 2047) }, /* receive timer */ - { UDATA (&xq_sansvc, UNIT_DIS, 0) }, /* sanity timer */ - { UDATA (&xq_idsvc, UNIT_DIS, 0) } /* system id timer */ -}; - -REG xqa_reg[] = { - { GRDATA ( SA0, xqa.addr[0], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA1, xqa.addr[1], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA2, xqa.addr[2], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA3, xqa.addr[3], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA4, xqa.addr[4], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA5, xqa.addr[5], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( RBDL, xqa.rbdl, XQ_RDX, 32, 0) }, - { GRDATA ( XBDL, xqa.xbdl, XQ_RDX, 32, 0) }, - { GRDATA ( VAR, xqa.var, XQ_RDX, 16, 0) }, - { GRDATA ( CSR, xqa.csr, XQ_RDX, 16, 0) }, - { GRDATA ( SETUP_PRM, xqa.setup.promiscuous, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_MLT, xqa.setup.multicast, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_L1, xqa.setup.l1, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_L2, xqa.setup.l2, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_L3, xqa.setup.l3, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_SAN, xqa.setup.sanity_timer, XQ_RDX, 32, 0), REG_HRO}, - { BRDATA ( SETUP_MACS, &xqa.setup.macs, XQ_RDX, 8, sizeof(xqa.setup.macs)), REG_HRO}, - { NULL }, -}; - -DIB xqb_dib = { IOBA_XQB, IOLN_XQB, &xq_rd, &xq_wr, - 1, IVCL (XQ), 0, { &xq_intb } }; - -UNIT xqb_unit[] = { - { UDATA (&xq_svc, UNIT_ATTABLE + UNIT_DISABLE, 2047) }, /* receive timer */ - { UDATA (&xq_sansvc, UNIT_DIS, 0) }, /* sanity timer */ - { UDATA (&xq_idsvc, UNIT_DIS, 0) } /* system id timer */ -}; - -REG xqb_reg[] = { - { GRDATA ( SA0, xqb.addr[0], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA1, xqb.addr[1], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA2, xqb.addr[2], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA3, xqb.addr[3], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA4, xqb.addr[4], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA5, xqb.addr[5], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( RBDL, xqb.rbdl, XQ_RDX, 32, 0) }, - { GRDATA ( XBDL, xqb.xbdl, XQ_RDX, 32, 0) }, - { GRDATA ( VAR, xqb.var, XQ_RDX, 16, 0) }, - { GRDATA ( CSR, xqb.csr, XQ_RDX, 16, 0) }, - { GRDATA ( SETUP_PRM, xqb.setup.promiscuous, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_MLT, xqb.setup.multicast, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_L1, xqb.setup.l1, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_L2, xqb.setup.l2, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_L3, xqb.setup.l3, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_SAN, xqb.setup.sanity_timer, XQ_RDX, 32, 0), REG_HRO}, - { BRDATA ( SETUP_MACS, &xqb.setup.macs, XQ_RDX, 8, sizeof(xqb.setup.macs)), REG_HRO}, - { NULL }, -}; - -MTAB xq_mod[] = { - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "MAC", "MAC", - &xq_setmac, &xq_showmac, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "ETH", NULL, - NULL, &xq_showeth, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "FILTERS", NULL, - NULL, &xq_show_filters, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATS", "STATS", - &xq_set_stats, &xq_show_stats, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "TYPE", "TYPE", - &xq_set_type, &xq_show_type, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "SANITY", "SANITY", - &xq_set_sanity, &xq_show_sanity, NULL }, - { 0 }, -}; - -DEVICE xq_dev = { - "XQ", xqa_unit, xqa_reg, xq_mod, - 3, XQ_RDX, 11, 1, XQ_RDX, 16, - &xq_ex, &xq_dep, &xq_reset, - NULL, &xq_attach, &xq_detach, - &xqa_dib, DEV_DISABLE | DEV_QBUS -}; - -DEVICE xqb_dev = { - "XQB", xqb_unit, xqb_reg, xq_mod, - 3, XQ_RDX, 11, 1, XQ_RDX, 16, - &xq_ex, &xq_dep, &xq_reset, - NULL, &xq_attach, &xq_detach, - &xqb_dib, DEV_DISABLE | DEV_DIS | DEV_QBUS -}; - -CTLR xq_ctrl[] = { - {&xq_dev, xqa_unit, &xqa_dib, &xqa}, /* XQA controller */ - {&xqb_dev, xqb_unit, &xqb_dib, &xqb} /* XQB controller */ -}; - -#ifdef XQ_DEBUG - -const char* const xq_recv_regnames[] = { - "MAC0", "MAC1", "MAC2", "MAC3", "MAC4", "MAC5", "VAR", "CSR" -}; - -const char* const xq_xmit_regnames[] = { - "", "", "RBDL-Lo", "RBDL-Hi", "XBDL-Lo", "XBDL-Hi", "VAR", "CSR" -}; - -const char* const xq_csr_bits[] = { - "RE ", "SR ", "NI ", "BD ", "XL ", "RL ", "IE ", "XI ", - "IL ", "EL ", "SE ", "RR ", "OK ", "CA ", "PE ", "RI" -}; - -/* internal debugging routines */ -void xq_debug_setup(CTLR* xq); -void xq_dump_csr(CTLR* xq); -void xq_dump_var(CTLR* xq); -void xq_csr_changes(CTLR* xq, uint16 data); -void xq_var_changes(CTLR* xq, uint16 data); - -/* sanity timer debugging */ -#include -struct timeb start, finish; - -#endif /* XQ_DEBUG */ - -/* -================================================================================ - Queue Management -================================================================================ -*/ - -t_stat xq_init_queue(CTLR* xq, struct xq_msg_que* que) -{ - /* create dynamic queue if it does not exist */ - if (!que->item) { - size_t size = sizeof(struct xq_msg_itm) * XQ_QUE_MAX; - que->item = malloc(size); - if (que->item) { - /* init dynamic memory */ - memset(que->item, 0, size); - } else { - /* failed to allocate memory */ - printf("%s: failed to allocate dynamic queue\n", xq->dev->name); - if (sim_log) fprintf(sim_log, "%s: failed to allocate dynamic queue\n", xq->dev->name); - return SCPE_MEM; - }; - }; - return SCPE_OK; -} - -void xq_clear_queue(struct xq_msg_que* que) -{ - int i; - struct xq_msg_itm* item; - - for (i = 0; i < XQ_QUE_MAX; i++) { - item = &que->item[i]; - item->type = 0; - item->packet.len = 0; - item->packet.used = 0; - item->status = 0; - }; - que->count = que->head = que->tail = que->loss = 0; -} - -void xq_remove_queue(struct xq_msg_que* que) -{ - struct xq_msg_itm* item = &que->item[que->head]; - - if (que->count) { - item->type = 0; - item->packet.len = 0; - item->packet.used = 0; - item->status = 0; - if (++que->head == XQ_QUE_MAX) - que->head = 0; - que->count--; - } -} - -void xq_insert_queue(struct xq_msg_que* que, int32 type, ETH_PACK* packet, int32 status) -{ - struct xq_msg_itm* item; - - /* if queue empty, set pointers to beginning */ - if (!que->count) { - que->head = 0; - que->tail = -1; - } - - /* find new tail of the circular queue */ - if (++que->tail == XQ_QUE_MAX) - que->tail = 0; - if (++que->count > XQ_QUE_MAX) { - que->count = XQ_QUE_MAX; - /* lose oldest packet */ - if (++que->head == XQ_QUE_MAX) - que->head = 0; - que->loss++; -#ifdef XQ_DEBUG - fprintf(stderr, "Packet Lost\n"); -#endif - } - if (que->count > que->high) - que->high = que->count; - - /* set information in (new) tail item */ - item = &que->item[que->tail]; - item->type = type; - item->packet.len = packet->len; - item->packet.used = 0; - memcpy(item->packet.msg, packet->msg, packet->len); - item->status = status; -} - -/* -================================================================================ -*/ - -/*============================================================================*/ - -/* Multicontroller support */ - -CTLR* xq_unit2ctlr(UNIT* uptr) -{ - unsigned int i,j; - for (i=0; inumunits; j++) - if (&xq_ctrl[i].unit[j] == uptr) return &xq_ctrl[i]; - /* not found */ - return 0; -} - -CTLR* xq_dev2ctlr(DEVICE* dptr) -{ - int i; - for (i=0; i= xq_ctrl[i].dib->ba) && (PA < (xq_ctrl[i].dib->ba + xq_ctrl[i].dib->lnt))) - return &xq_ctrl[i]; - /* not found */ - return 0; -} - -/*============================================================================*/ - -/* stop simh from reading non-existant unit data stream */ -t_stat xq_ex (t_value* vptr, t_addr addr, UNIT* uptr, int32 sw) -{ - /* on PDP-11, allow EX command to look at bootrom */ -#ifdef VM_PDP11 - if (addr <= sizeof(xq_bootrom)/2) - *vptr = xq_bootrom[addr]; - else - *vptr = 0; - return SCPE_OK; -#else - return SCPE_NOFNC; -#endif -} - -/* stop simh from writing non-existant unit data stream */ -t_stat xq_dep (t_value val, t_addr addr, UNIT* uptr, int32 sw) -{ - return SCPE_NOFNC; -} - -t_stat xq_showmac (FILE* st, UNIT* uptr, int32 val, void* desc) -{ - CTLR* xq = xq_unit2ctlr(uptr); - char buffer[20]; - - eth_mac_fmt((ETH_MAC*)xq->var->mac, buffer); - fprintf(st, "MAC=%s", buffer); - return SCPE_OK; -} - -void xq_make_checksum(CTLR* xq) -{ - /* checksum calculation routine detailed in vaxboot.zip/xqbtdrivr.mar */ - uint32 checksum = 0; - const uint32 wmask = 0xFFFF; - int i; - - for (i = 0; i < sizeof(ETH_MAC); i += 2) { - checksum <<= 1; - if (checksum > wmask) - checksum -= wmask; - checksum += (xq->var->mac[i] << 8) | xq->var->mac[i+1]; - if (checksum > wmask) - checksum -= wmask; - } - if (checksum == wmask) - checksum = 0; - - /* set checksum bytes */ - xq->var->mac_checksum[0] = checksum & 0xFF; - xq->var->mac_checksum[1] = checksum >> 8; -} - -t_stat xq_setmac (UNIT* uptr, int32 val, char* cptr, void* desc) -{ - int i, j, len; - short int num; - ETH_MAC newmac = {0,0,0,0,0,0}; - const ETH_MAC zeros = {0,0,0,0,0,0}; - const ETH_MAC ones = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - CTLR* xq = xq_unit2ctlr(uptr); - - if (!cptr) return SCPE_IERR; - /* parse new mac and validate */ - len = strlen(cptr); - if (len != 17) return SCPE_ARG; - /* make sure byte separators are OK */ - for (i=2; ivar->mac, newmac, sizeof(ETH_MAC)); - /* calculate MAC checksum */ - xq_make_checksum(xq); - return SCPE_OK; -} - -t_stat xq_showeth (FILE* st, UNIT* uptr, int32 val, void* desc) -{ -#define XQ_MAX_LIST 10 - int i; - ETH_LIST list[XQ_MAX_LIST]; - int number = eth_devices(XQ_MAX_LIST, list); - - fprintf(st, "ETH devices:\n"); - if (number) - for (i=0; ivar->stats; - int elements = sizeof(struct xq_stats)/sizeof(int); - int i; - for (i=0; ivar->stats, 0, sizeof(struct xq_stats)); -#endif - return SCPE_OK; -} - -t_stat xq_show_stats (FILE* st, UNIT* uptr, int32 val, void* desc) -{ - char* fmt = " %-15s%d\n"; - CTLR* xq = xq_unit2ctlr(uptr); - - fprintf(st, "Ethernet statistics:\n"); - fprintf(st, fmt, "Recv:", xq->var->stats.recv); - fprintf(st, fmt, "Filtered:", xq->var->stats.filter); - fprintf(st, fmt, "Xmit:", xq->var->stats.xmit); - fprintf(st, fmt, "Xmit Fail:", xq->var->stats.fail); - fprintf(st, fmt, "Runts:", xq->var->stats.runt); - fprintf(st, fmt, "Oversize:", xq->var->stats.giant); - fprintf(st, fmt, "Setup:", xq->var->stats.setup); - fprintf(st, fmt, "Loopback:", xq->var->stats.loop); - fprintf(st, fmt, "ReadQ high:", xq->var->ReadQ.high); - return SCPE_OK; -} - -t_stat xq_show_filters (FILE* st, UNIT* uptr, int32 val, void* desc) -{ - CTLR* xq = xq_unit2ctlr(uptr); - char buffer[20]; - int i; - - fprintf(st, "Filters:\n"); - for (i=0; ivar->setup.macs[i], buffer); - fprintf(st, " [%2d]: %s\n", i, buffer); - }; - return SCPE_OK; -} - -t_stat xq_show_type (FILE* st, UNIT* uptr, int32 val, void* desc) -{ - CTLR* xq = xq_unit2ctlr(uptr); - fprintf(st, "type="); - switch (xq->var->type) { - case XQ_T_DEQNA: fprintf(st, "DEQNA"); break; - case XQ_T_DELQA: fprintf(st, "DELQA"); break; - } - return SCPE_OK; -} - -t_stat xq_set_type (UNIT* uptr, int32 val, char* cptr, void* desc) -{ - CTLR* xq = xq_unit2ctlr(uptr); - if (!cptr) return SCPE_IERR; - - /* this assumes that the parameter has already been upcased */ - if (!strcmp(cptr, "DEQNA")) xq->var->type = XQ_T_DEQNA; - else if (!strcmp(cptr, "DELQA")) xq->var->type = XQ_T_DELQA; - else return SCPE_ARG; - - return SCPE_OK; -} - -t_stat xq_show_sanity (FILE* st, UNIT* uptr, int32 val, void* desc) -{ - CTLR* xq = xq_unit2ctlr(uptr); - - fprintf(st, "sanity="); - switch (xq->var->sanity.enabled) { - case 0: fprintf(st, "OFF"); break; - case 1: fprintf(st, "ON"); break; - } - return SCPE_OK; -} - -t_stat xq_set_sanity (UNIT* uptr, int32 val, char* cptr, void* desc) -{ - CTLR* xq = xq_unit2ctlr(uptr); - if (!cptr) return SCPE_IERR; - - /* this assumes that the parameter has already been upcased */ - if (!strcmp(cptr, "ON")) xq->var->sanity.enabled = 1; - else if (!strcmp(cptr, "OFF")) xq->var->sanity.enabled = 0; - else return SCPE_ARG; - - return SCPE_OK; -} - -t_stat xq_nxm_error(CTLR* xq) -{ -#ifdef XQ_DEBUG - fprintf(stderr,"%s: Non Existent Memory Error\n", xq->dev->name); -#endif - /* set NXM and associated bits in CSR */ - xq->var->csr |= (XQ_CSR_NI | XQ_CSR_XI | XQ_CSR_XL | XQ_CSR_RL); - - /* interrupt if required */ - if (xq->var->csr & XQ_CSR_IE) - SET_INT(XQ); - - return SCPE_OK; -} - -/* -** write callback -*/ -void xq_write_callback (CTLR* xq, int status) -{ - t_stat rstatus; - int32 wstatus; - const uint16 TDR = 100 + xq->var->write_buffer.len * 8; /* arbitrary value */ - uint16 write_success[2] = {0}; - uint16 write_failure[2] = {XQ_DSC_C}; - write_success[1] = TDR & 0x03FF; /* Does TDR get set on successful packets ?? */ - write_failure[1] = TDR & 0x03FF; /* TSW2<09:00> */ - - xq->var->stats.xmit += 1; - /* update write status words */ - if (status == 0) { /* success */ - wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, write_success, NOMAP); - } else { /* failure */ -#ifdef XQ_DEBUG - fprintf(stderr, "%s: Packet Write Error\n", xq->dev->name); -#endif - xq->var->stats.fail += 1; - wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, write_failure, NOMAP); - } - if (wstatus) { - xq_nxm_error(xq); - return; - } - - /* update csr */ - xq->var->csr |= XQ_CSR_XI; - if (xq->var->csr & XQ_CSR_IE) - SET_INT(XQ); - - /* reset sanity timer */ - xq_reset_santmr(xq); - - /* clear write buffer */ - xq->var->write_buffer.len = 0; - - /* next descriptor (implicit) */ - xq->var->xbdl_ba += 12; - - /* finish processing xbdl */ - rstatus = xq_process_xbdl(xq); -} - -void xqa_write_callback (int status) -{ - xq_write_callback(&xq_ctrl[0], status); -} - -void xqb_write_callback (int status) -{ - xq_write_callback(&xq_ctrl[1], status); -} - -/* read registers: */ -t_stat xq_rd(int32* data, int32 PA, int32 access) -{ - CTLR* xq = xq_pa2ctlr(PA); - int index = (PA >> 1) & 07; /* word index */ - -#ifdef XQ_DEBUG - if (index != 7) -#if defined(VM_VAX) - fprintf (stderr,"%s: %s %08X %08X read: %X\n", - xq->dev->name, xq_recv_regnames[index], fault_PC, PSL, *data); -#else - fprintf (stderr,"%s: %s read: %X\n", - xq->dev->name, xq_recv_regnames[index], *data); -#endif /* VM_VAX */ -#endif - - switch (index) { - case 0: - case 1: - /* return checksum in external loopback mode */ - if (xq->var->csr & XQ_CSR_EL) - *data = 0xFF00 | xq->var->mac_checksum[index]; - else - *data = 0xFF00 | xq->var->mac[index]; - break; - case 2: - case 3: - case 4: - case 5: - *data = 0xFF00 | xq->var->mac[index]; - break; - case 6: -#if 0 -#ifdef XQ_DEBUG - xq_dump_var(xq); -#endif -#endif - *data = xq->var->var; - break; - case 7: -#ifdef XQ_DEBUG - xq_dump_csr(xq); -#endif - *data = xq->var->csr; - break; - } - return SCPE_OK; -} - - -/* dispatch ethernet read request - procedure documented in sec. 3.2.2 */ - -t_stat xq_process_rbdl(CTLR* xq) -{ - int32 rstatus, wstatus; - uint16 b_length, w_length, rbl; - uint32 address; - struct xq_msg_itm* item; - char* rbuf; - -#ifdef XQ_DEBUG - fprintf(stderr,"%s: CSR - Processing read\n", xq->dev->name); -#endif - /* process buffer descriptors */ - while(1) { - - /* get receive bdl from memory */ - xq->var->rbdl_buf[0] = 0xFFFF; - wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0], NOMAP); - rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1], NOMAP); - if (rstatus || wstatus) return xq_nxm_error(xq); - - /* invalid buffer? */ - if (~xq->var->rbdl_buf[1] & XQ_DSC_V) { - xq->var->csr |= XQ_CSR_RL; - return SCPE_OK; - } - - /* explicit chain buffer? */ - if (xq->var->rbdl_buf[1] & XQ_DSC_C) { - xq->var->rbdl_ba = ((xq->var->rbdl_buf[1] & 0x3F) << 16) | xq->var->rbdl_buf[2]; - continue; - } - - /* stop processing if nothing in read queue */ - if (!xq->var->ReadQ.count) break; - - /* get status words */ - rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP); - if (rstatus) return xq_nxm_error(xq); - - /* get host memory address */ - address = ((xq->var->rbdl_buf[1] & 0x3F) << 16) | xq->var->rbdl_buf[2]; - - /* decode buffer length - two's complement (in words) */ - w_length = ~xq->var->rbdl_buf[3] + 1; - b_length = w_length * 2; - if (xq->var->rbdl_buf[1] & XQ_DSC_H) b_length -= 1; - if (xq->var->rbdl_buf[1] & XQ_DSC_L) b_length -= 1; - - item = &xq->var->ReadQ.item[xq->var->ReadQ.head]; - rbl = item->packet.len; - rbuf = item->packet.msg; - - /* see if packet must be size-adjusted or is splitting */ - if (item->packet.used) { - int used = item->packet.used; - rbl -= used; - rbuf = &item->packet.msg[used]; - } else { - /* adjust runt packets */ - if (rbl < ETH_MIN_PACKET) { - xq->var->stats.runt += 1; -#ifdef XQ_DEBUG - printf("%s: Runt detected, size = %d\n", xq->dev->name, rbl); -#endif - /* pad runts with zeros up to minimum size - this allows "legal" (size - 60) - processing of those weird short ARP packets that seem to occur occasionally */ - memset(&item->packet.msg[rbl], 0, ETH_MIN_PACKET); - rbl = ETH_MIN_PACKET; - }; - - /* adjust oversized packets */ - if (rbl > ETH_MAX_PACKET) { - xq->var->stats.giant += 1; -#ifdef XQ_DEBUG - printf("%s: Giant detected, size = %d\n", xq->dev->name, rbl); -#endif - /* trim giants down to maximum size - no documentation on how to handle the data loss */ - item->packet.len = ETH_MAX_PACKET; - rbl = ETH_MAX_PACKET; - }; - }; - - /* make sure entire packet fits in buffer - if not, will need to split into multiple buffers */ - /* assert(rbl <= b_length); */ /* abort if packet won't fit into single buffer */ - if (rbl > b_length) - rbl = b_length; - item->packet.used += rbl; - - /* send data to host */ - wstatus = Map_WriteB(address, rbl, rbuf, NOMAP); - if (wstatus) return xq_nxm_error(xq); - - /* set receive size into RBL - RBL<10:8> maps into Status1<10:8>, - RBL<7:0> maps into Status2<7:0>, and Status2<15:8> (copy) */ - - xq->var->rbdl_buf[4] = 0; - switch (item->type) { - case 0: /* setup packet */ - xq->var->stats.setup += 1; - xq->var->rbdl_buf[4] = 0x2700; /* set esetup and RBL 10:8 */ - break; - case 1: /* loopback packet */ - xq->var->stats.loop += 1; - xq->var->rbdl_buf[4] = 0x2000; /* loopback flag */ - xq->var->rbdl_buf[4] |= (rbl & 0x0700); /* high bits of rbl */ - break; - case 2: /* normal packet */ - rbl -= 60; /* keeps max packet size in 11 bits */ - xq->var->rbdl_buf[4] = (rbl & 0x0700); /* high bits of rbl */ - break; - } - if (item->packet.used < item->packet.len) - xq->var->rbdl_buf[4] |= 0xC000; /* not last segment */ - xq->var->rbdl_buf[5] = ((rbl & 0x00FF) << 8) | (rbl & 0x00FF); - if (xq->var->ReadQ.loss) { -#ifdef XQ_DEBUG - fprintf(stderr, "%s: ReadQ overflow\n", xq->dev->name); -#endif - xq->var->rbdl_buf[4] |= 0x0001; /* set overflow bit */ - xq->var->ReadQ.loss = 0; /* reset loss counter */ - } - - /* update read status words*/ - wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP); - if (wstatus) return xq_nxm_error(xq); - - /* remove packet from queue */ - if (item->packet.used >= item->packet.len) - xq_remove_queue(&xq->var->ReadQ); - - /* reset sanity timer */ - xq_reset_santmr(xq); - - /* mark transmission complete */ - xq->var->csr |= XQ_CSR_RI; - if (xq->var->csr & XQ_CSR_IE) - SET_INT(XQ); - - /* set to next bdl (implicit chain) */ - xq->var->rbdl_ba += 12; - - } /* while */ - - return SCPE_OK; -} - -t_stat xq_process_mop(CTLR* xq) -{ - uint32 address; - uint16 size; - int32 wstatus; - struct xq_meb* meb = (struct xq_meb*) &xq->var->write_buffer.msg[0200]; - const struct xq_meb* limit = (struct xq_meb*) &xq->var->write_buffer.msg[0400]; - -#ifdef XQ_DEBUG - fprintf(stderr, "%s: Processing MOP data\n", xq->dev->name); -#endif - if (xq->var->type == XQ_T_DEQNA) /* DEQNA's don't MOP */ - return SCPE_NOFNC; - - while ((meb->type != 0) && (meb < limit)) { - address = (meb->add_hi << 16) || (meb->add_mi << 8) || meb->add_lo; - size = (meb->siz_hi << 8) || meb->siz_lo; - - /* MOP stuff here - NOT YET FULLY IMPLEMENTED */ - -#ifdef XQ_DEBUG - printf("%s: Processing MEB type: %d\n", xq->dev->name, meb->type); -#endif - switch (meb->type) { - case 0: /* MOP Termination */ - break; - case 1: /* MOP Read Ethernet Address */ - wstatus = Map_WriteB(address, sizeof(ETH_MAC), (uint8*) &xq->var->setup.macs[0], NOMAP); - if (wstatus) return xq_nxm_error(xq); - break; - case 2: /* MOP Reset System ID */ - break; - case 3: /* MOP Read Last MOP Boot */ - break; - case 4: /* MOP Read Boot Password */ - break; - case 5: /* MOP Write Boot Password */ - break; - case 6: /* MOP Read System ID */ - break; - case 7: /* MOP Write System ID */ - break; - case 8: /* MOP Read Counters */ - break; - case 9: /* Mop Read/Clear Counters */ - break; - } /* switch */ - - /* process next meb */ - meb += sizeof(struct xq_meb); - - } /* while */ - return SCPE_OK; -} - -t_stat xq_process_setup(CTLR* xq) -{ - int i,j; - int count = 0; - float secs; - t_stat status; - ETH_MAC zeros = {0, 0, 0, 0, 0, 0}; - ETH_MAC filters[XQ_FILTER_MAX + 1]; - - /* extract filter addresses from setup packet */ - memset(xq->var->setup.macs, '\0', sizeof(xq->var->setup.macs)); - for (i = 0; i < 7; i++) - for (j = 0; j < 6; j++) { - xq->var->setup.macs[i] [j] = xq->var->write_buffer.msg[(i + 01) + (j * 8)]; - if (xq->var->write_buffer.len > 112) - xq->var->setup.macs[i+7][j] = xq->var->write_buffer.msg[(i + 0101) + (j * 8)]; - } - - /* process high byte count */ - if (xq->var->write_buffer.len > 128) { - uint16 len = xq->var->write_buffer.len; - uint16 led, san; - - if (len & XQ_SETUP_MC) - xq->var->setup.multicast = 1; - if (len & XQ_SETUP_PM) - xq->var->setup.promiscuous = 1; - if (led = (len & XQ_SETUP_LD) >> 2) { - switch (led) { - case 1: xq->var->setup.l1 = 0; break; - case 2: xq->var->setup.l2 = 0; break; - case 3: xq->var->setup.l3 = 0; break; - } /* switch */ - } /* if led */ - /* set sanity timer timeout */ - san = (len & XQ_SETUP_ST) >> 4; - switch(san) { - case 0: secs = 0.25; break; /* 1/4 second */ - case 1: secs = 1; break; /* 1 second */ - case 2: secs = 4; break; /* 4 seconds */ - case 3: secs = 16; break; /* 16 seconds */ - case 4: secs = 1 * 60; break; /* 1 minute */ - case 5: secs = 4 * 60; break; /* 4 minutes */ - case 6: secs = 16 * 60; break; /* 16 minutes */ - case 7: secs = 64 * 60; break; /* 64 minutes */ - } - xq->var->sanity.quarter_secs = (int) (secs * 4); - - /* if sanity timer enabled, start sanity timer */ - if (xq->var->csr & XQ_CSR_SE || xq->var->sanity.enabled) - xq_start_santmr(xq); - else - xq_cancel_santmr(xq); - } - - /* set ethernet filter */ - /* memcpy (filters[count++], xq->mac, sizeof(ETH_MAC)); */ - for (i = 0; i < XQ_FILTER_MAX; i++) - if (memcmp(zeros, &xq->var->setup.macs[i], sizeof(ETH_MAC))) - memcpy (filters[count++], xq->var->setup.macs[i], sizeof(ETH_MAC)); - status = eth_filter (xq->var->etherface, count, filters, xq->var->setup.multicast, xq->var->setup.promiscuous); - - /* process MOP information */ - if (xq->var->write_buffer.msg[0]) - status = xq_process_mop(xq); - - /* mark setup block valid */ - xq->var->setup.valid = 1; - -#ifdef XQ_DEBUG - xq_debug_setup(xq); -#endif - return SCPE_OK; -} - -/* - Dispatch Write Operation - - The DELQA manual does not explicitly state whether or not multiple packets - can be written in one transmit operation, so a maximum of 1 packet is assumed. - -*/ -t_stat xq_process_xbdl(CTLR* xq) -{ - const uint16 implicit_chain_status[2] = {XQ_DSC_V | XQ_DSC_C, 1}; - const uint16 write_success[2] = {0, 1 /*Non-Zero TDR*/}; - - uint16 b_length, w_length; - int32 rstatus, wstatus; - uint32 address; - t_stat status; - -#ifdef XQ_DEBUG - fprintf(stderr,"%s: xq_process_xbdl - Processing write\n", xq->dev->name); -#endif - /* clear write buffer */ - xq->var->write_buffer.len = 0; - - /* process buffer descriptors until not valid */ - while (1) { - - /* Get transmit bdl from memory */ - rstatus = Map_ReadW (xq->var->xbdl_ba, 12, &xq->var->xbdl_buf[0], NOMAP); - xq->var->xbdl_buf[0] = 0xFFFF; - wstatus = Map_WriteW(xq->var->xbdl_ba, 2, &xq->var->xbdl_buf[0], NOMAP); - if (rstatus || wstatus) return xq_nxm_error(xq); - - /* invalid buffer? */ - if (~xq->var->xbdl_buf[1] & XQ_DSC_V) { - xq->var->csr |= XQ_CSR_XL; -#ifdef XQ_DEBUG - fprintf(stderr,"%s: xq_process_xbdl - List Empty - Done Processing write\n", xq->dev->name); -#endif - return SCPE_OK; - } - -#ifdef XQ_DEBUG - fprintf(stderr,"%s: xq_process_xbdl: Buffer Descriptor Information: %04X %04X %04X %04X %04X \n", - xq->dev->name, xq->var->xbdl_buf[1], xq->var->xbdl_buf[2], - xq->var->xbdl_buf[3], xq->var->xbdl_buf[4], xq->var->xbdl_buf[5]); -#endif - /* compute host memory address */ - address = ((xq->var->xbdl_buf[1] & 0x3F) << 16) | xq->var->xbdl_buf[2]; - - /* decode buffer length - two's complement (in words) */ - w_length = ~xq->var->xbdl_buf[3] + 1; - b_length = w_length * 2; - if (xq->var->xbdl_buf[1] & XQ_DSC_H) b_length -= 1; - if (xq->var->xbdl_buf[1] & XQ_DSC_L) b_length -= 1; - - /* explicit chain buffer? */ - if (xq->var->xbdl_buf[1] & XQ_DSC_C) { - xq->var->xbdl_ba = address; -#ifdef XQ_DEBUG - fprintf(stderr,"%s: xq_process_xbdl: Chained Buffer Encountered: %d\n", xq->dev->name, b_length); -#endif - continue; - } - - /* add to transmit buffer, making sure it's not too big */ - if ((xq->var->write_buffer.len + b_length) > sizeof(xq->var->write_buffer.msg)) - b_length = sizeof(xq->var->write_buffer.msg) - xq->var->write_buffer.len; - rstatus = Map_ReadB(address, b_length, &xq->var->write_buffer.msg[xq->var->write_buffer.len], NOMAP); - if (rstatus) return xq_nxm_error(xq); - xq->var->write_buffer.len += b_length; - - /* end of message? */ - if (xq->var->xbdl_buf[1] & XQ_DSC_E) { - if (((~xq->var->csr & XQ_CSR_RE) && ((~xq->var->csr & XQ_CSR_IL) || (xq->var->csr & XQ_CSR_EL))) || /* loopback */ - (xq->var->xbdl_buf[1] & XQ_DSC_S)) { /* or setup packet (forces loopback regardless of state) */ - if (xq->var->xbdl_buf[1] & XQ_DSC_S) { /* setup packet */ - status = xq_process_setup(xq); - - /* put packet in read buffer */ - xq_insert_queue (&xq->var->ReadQ, 0, &xq->var->write_buffer, status); - } else { /* loopback */ - /* put packet in read buffer */ - xq_insert_queue (&xq->var->ReadQ, 1, &xq->var->write_buffer, 0); - } - - /* update write status */ - wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, (uint16*) write_success, NOMAP); - if (wstatus) return xq_nxm_error(xq); - - /* clear write buffer */ - xq->var->write_buffer.len = 0; - - /* reset sanity timer */ - xq_reset_santmr(xq); - - /* mark transmission complete */ - xq->var->csr |= XQ_CSR_XI; - if (xq->var->csr & XQ_CSR_IE) - SET_INT(XQ); - - /* now trigger "read" of setup or loopback packet */ - if (~xq->var->csr & XQ_CSR_RL) - status = xq_process_rbdl(xq); - - } else { /* not loopback */ - - status = eth_write(xq->var->etherface, &xq->var->write_buffer, xq->var->wcallback); - if (status != SCPE_OK) /* not implemented or unattached */ - xq_write_callback(xq, 1); /* fake failure */ - else - xq_svc(&xq->unit[0]); /* service any received data */ -#ifdef XQ_DEBUG - fprintf(stderr,"%s: xq_process_xbdl: Completed Processing write\n", xq->dev->name); -#endif - return SCPE_OK; - - } /* loopback/non-loopback */ - } else { /* not at end-of-message */ - -#ifdef XQ_DEBUG - fprintf(stderr,"%s: xq_process_xbdl: Processing Implicit Chained Buffer Segment\n", xq->dev->name); -#endif - /* update bdl status words */ - wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, (uint16*) implicit_chain_status, NOMAP); - if(wstatus) return xq_nxm_error(xq); - } - - /* set to next bdl (implicit chain) */ - xq->var->xbdl_ba += 12; - - } /* while */ -} - -t_stat xq_dispatch_rbdl(CTLR* xq) -{ - int i; - int32 rstatus, wstatus; - t_stat status; - -#ifdef XQ_DEBUG - fprintf(stderr,"%s: CSR - Dispatching read\n", xq->dev->name); -#endif - - /* mark receive bdl valid */ - xq->var->csr &= ~XQ_CSR_RL; - - /* init receive bdl buffer */ - for (i=0; i<6; i++) - xq->var->rbdl_buf[i] = 0; - - /* get address of first receive buffer */ - xq->var->rbdl_ba = ((xq->var->rbdl[1] & 0x3F) << 16) | (xq->var->rbdl[0] & ~01); - - /* get first receive buffer */ - xq->var->rbdl_buf[0] = 0xFFFF; - wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0], NOMAP); - rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1], NOMAP); - if (rstatus || wstatus) return xq_nxm_error(xq); - - /* is buffer valid? */ - if (~xq->var->rbdl_buf[1] & XQ_DSC_V) { - xq->var->csr |= XQ_CSR_RL; - return SCPE_OK; - } - - /* process any waiting packets in receive queue */ - if (xq->var->ReadQ.count) - status = xq_process_rbdl(xq); - - return SCPE_OK; -} - -t_stat xq_dispatch_xbdl(CTLR* xq) -{ - int i; - t_stat status; -#ifdef XQ_DEBUG - fprintf(stderr,"%s: CSR - Dispatching write\n", xq->dev->name); -#endif - /* mark transmit bdl valid */ - xq->var->csr &= ~XQ_CSR_XL; - - /* initialize transmit bdl buffers */ - for (i=0; i<6; i++) - xq->var->xbdl_buf[i] = 0; - - /* clear transmit buffer */ - xq->var->write_buffer.len = 0; - - /* get base address of first transmit descriptor */ - xq->var->xbdl_ba = ((xq->var->xbdl[1] & 0x3F) << 16) | (xq->var->xbdl[0] & ~01); - - /* process xbdl */ - status = xq_process_xbdl(xq); - - return status; -} - -t_stat xq_process_loopback(CTLR* xq, ETH_PACK* pack) -{ - ETH_PACK reply; - ETH_MAC physical_address; - t_stat status; - int offset = pack->msg[14] | (pack->msg[15] << 8); - int function = pack->msg[offset] | (pack->msg[offset+1] << 8); - - if (function != 2 /*forward*/) - return SCPE_NOFNC; - - /* create reply packet */ - memcpy (&reply, pack, sizeof(ETH_PACK)); - memcpy (physical_address, xq->var->setup.valid ? xq->var->setup.macs[0] : xq->var->mac, sizeof(ETH_MAC)); - memcpy (&reply.msg[0], &reply.msg[offset+2], sizeof(ETH_MAC)); - memcpy (&reply.msg[6], physical_address, sizeof(ETH_MAC)); - memcpy (&reply.msg[offset+2], physical_address, sizeof(ETH_MAC)); - reply.msg[offset] = 0x01; - offset += 8; - reply.msg[14] = offset & 0xFF; - reply.msg[15] = (offset >> 8) & 0xFF; - - /* send reply packet */ - status = eth_write(xq->var->etherface, &reply, NULL); - - return status; -} - -t_stat xq_process_remote_console (CTLR* xq, ETH_PACK* pack) -{ - t_stat status; - ETH_MAC source; - uint16 receipt; - int code = pack->msg[16]; - - switch (code) { - case 0x05: /* request id */ - receipt = pack->msg[18] | (pack->msg[19] << 8); - memcpy(source, &pack->msg[6], sizeof(ETH_MAC)); - - /* send system id to requestor */ - status = xq_system_id (xq, source, receipt); - return status; - break; - case 0x06: /* boot */ - /* - NOTE: the verification field should be checked here against the - verification value established in the setup packet. If they match the - reboot should occur, otherwise nothing happens, and the packet - is passed on to the host. - - Verification is not implemented, since the setup packet processing code - isn't complete yet. - - Various values are also passed: processor, control, and software id. - These control the various boot parameters, however SIMH does not - have a mechanism to pass these to the host, so just reboot. - */ - - status = xq_boot_host(); - return status; - break; - } /* switch */ - - return SCPE_NOFNC; -} - -t_stat xq_process_local (CTLR* xq, ETH_PACK* pack) -{ - /* returns SCPE_OK if local processing occurred, - otherwise returns SCPE_NOFNC or some other code */ - int protocol; - - /* DEQNA's have no local processing capability */ - if (xq->var->type == XQ_T_DEQNA) - return SCPE_NOFNC; - - protocol = pack->msg[12] | (pack->msg[13] << 8); - switch (protocol) { - case 0x0090: /* ethernet loopback */ - return xq_process_loopback(xq, pack); - break; - case 0x0260: /* MOP remote console */ - return xq_process_remote_console(xq, pack); - break; - } - return SCPE_NOFNC; -} - -void xq_read_callback(CTLR* xq, int status) -{ - xq->var->stats.recv += 1; - if (xq->var->csr & XQ_CSR_RE) { /* receiver enabled */ - - /* process any packets locally that can be */ - t_stat status = xq_process_local (xq, &xq->var->read_buffer); - - /* add packet to read queue */ - if (status != SCPE_OK) - xq_insert_queue(&xq->var->ReadQ, 2, &xq->var->read_buffer, status); - } -#ifdef XQ_DEBUG - else - fprintf(stderr, "%s: packet received with receiver disabled\n", xq->dev->name); -#endif -} - -void xqa_read_callback(int status) -{ - xq_read_callback(&xq_ctrl[0], status); -} - -void xqb_read_callback(int status) -{ - xq_read_callback(&xq_ctrl[1], status); -} - -void xq_sw_reset(CTLR* xq) -{ - int i; - - /* cancel all timers (ethernet, sanity, system_id) */ - for (i=0; i<3; i++) - sim_cancel(&xq->unit[i]); - - /* reset csr bits */ - xq->var->csr = XQ_CSR_XL | XQ_CSR_RL; - - if (xq->var->etherface) - xq->var->csr |= XQ_CSR_OK; - - /* clear CPU interrupts */ - CLR_INT(XQ); - - /* flush read queue */ - xq_clear_queue(&xq->var->ReadQ); - - /* clear setup info */ - memset (&xq->var->setup, 0, sizeof(xq->var->setup)); -} - -/* write registers: */ - -t_stat xq_wr_var(CTLR* xq, int32 data) -{ - -#ifdef XQ_DEBUG - xq_var_changes(xq, data); -#endif - - switch (xq->var->type) { - case XQ_T_DEQNA: - xq->var->var = (data & XQ_VEC_IV); - break; - case XQ_T_DELQA: - xq->var->var = (xq->var->var & XQ_VEC_RO) | (data & XQ_VEC_RW); - - /* if switching to DEQNA-LOCK mode clear VAR<14:10> */ - if (~xq->var->var & XQ_VEC_MS) - xq->var->var &= ~(XQ_VEC_OS | XQ_VEC_RS | XQ_VEC_ST); - break; - } - - /* set vector of SIMH device */ - if (data & XQ_VEC_IV) - xq->dib->vec = (data & XQ_VEC_IV) + VEC_Q; - else - xq->dib->vec = 0; - - return SCPE_OK; -} - -#ifdef VM_PDP11 -t_stat xq_process_bootrom (CTLR* xq) -{ - /* - NOTE: BOOT ROMs are a PDP-11ism, since they contain PDP-11 binary code. - the host is responsible for creating two *2KB* receive buffers. - - RSTS/E v10.1 source (INIONE.MAR/XHLOOK:) indicates that both the DEQNA and - DELQA will set receive status word 1 bits 15 & 14 on both packets. It also - states that a hardware bug in the DEQNA will set receive status word 1 bit 15 - (only) in the *third* receive buffer (oops!). - - RSTS/E v10.1 will run the Citizenship test from the bootrom after loading it. - Documentation on the Boot ROM can be found in INIQNA.MAR. - */ - - int32 rstatus, wstatus; - uint16 b_length, w_length; - uint32 address; - uint8* bootrom = (uint8*) xq_bootrom; - int i, checksum; - -#ifdef XQ_DEBUG - fprintf(stderr,"%s: CSR - Processing boot rom load\n", xq->dev->name); -#endif - - /* - RSTS/E v10.1 invokes the Citizenship tests in the Bootrom. For some - reason, the current state of the XQ emulator cannot pass these. So, - to get moving on RSTE/E support, we will replace the following line in - INIQNA.MAR/CITQNA:: - 70$: MOV (R2),R0 ;get the status word - with - 70$: CLR R0 ;force success - to cause the Citizenship test to return success to RSTS/E. - - At some point, the real problem (failure to pass citizenship diagnostics) - does need to be corrected to find incompatibilities in the emulation, and to - ultimately allow it to pass Digital hardware diagnostic tests. - */ - for (i=0; ivar->rbdl_buf[0] = 0xFFFF; - wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0], NOMAP); - rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1], NOMAP); - if (rstatus || wstatus) return xq_nxm_error(xq); - - /* invalid buffer? */ - if (~xq->var->rbdl_buf[1] & XQ_DSC_V) { - xq->var->csr |= XQ_CSR_RL; - return SCPE_OK; - } - - /* get status words */ - rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP); - if (rstatus) return xq_nxm_error(xq); - - /* get host memory address */ - address = ((xq->var->rbdl_buf[1] & 0x3F) << 16) | xq->var->rbdl_buf[2]; - -#ifdef XQ_DEBUG - fprintf(stderr,"%s: BootRom1 load address: 0%o\n", xq->dev->name, address); -#endif - - /* decode buffer length - two's complement (in words) */ - w_length = ~xq->var->rbdl_buf[3] + 1; - b_length = w_length * 2; - if (xq->var->rbdl_buf[1] & XQ_DSC_H) b_length -= 1; - if (xq->var->rbdl_buf[1] & XQ_DSC_L) b_length -= 1; - - /* make sure entire packet fits in buffer */ - assert(b_length >= sizeof(xq_bootrom)/2); - - /* send data to host */ - wstatus = Map_WriteB(address, sizeof(xq_bootrom)/2, bootrom, NOMAP); - if (wstatus) return xq_nxm_error(xq); - - /* update read status words */ - xq->var->rbdl_buf[4] = XQ_DSC_V | XQ_DSC_C; /* valid, chain */ - xq->var->rbdl_buf[5] = 0; - - /* update read status words*/ - wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP); - if (wstatus) return xq_nxm_error(xq); - - /* set to next bdl (implicit chain) */ - xq->var->rbdl_ba += 12; - - /* --------------------------- bootrom part 2 -----------------------------*/ - - /* get receive bdl from memory */ - xq->var->rbdl_buf[0] = 0xFFFF; - wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0], NOMAP); - rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1], NOMAP); - if (rstatus || wstatus) return xq_nxm_error(xq); - - /* invalid buffer? */ - if (~xq->var->rbdl_buf[1] & XQ_DSC_V) { - xq->var->csr |= XQ_CSR_RL; - return SCPE_OK; - } - - /* get status words */ - rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP); - if (rstatus) return xq_nxm_error(xq); - - /* get host memory address */ - address = ((xq->var->rbdl_buf[1] & 0x3F) << 16) | xq->var->rbdl_buf[2]; - -#ifdef XQ_DEBUG - fprintf(stderr,"%s: BootRom2 load address: 0%o\n", xq->dev->name, address); -#endif - - /* decode buffer length - two's complement (in words) */ - w_length = ~xq->var->rbdl_buf[3] + 1; - b_length = w_length * 2; - if (xq->var->rbdl_buf[1] & XQ_DSC_H) b_length -= 1; - if (xq->var->rbdl_buf[1] & XQ_DSC_L) b_length -= 1; - - /* make sure entire packet fits in buffer */ - assert(b_length >= sizeof(xq_bootrom)/2); - - /* send data to host */ - wstatus = Map_WriteB(address, sizeof(xq_bootrom)/2, &bootrom[2048], NOMAP); - if (wstatus) return xq_nxm_error(xq); - - /* update read status words */ - xq->var->rbdl_buf[4] = XQ_DSC_V | XQ_DSC_C; /* valid, chain */ - xq->var->rbdl_buf[5] = 0; - - /* update read status words*/ - wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP); - if (wstatus) return xq_nxm_error(xq); - - /* set to next bdl (implicit chain) */ - xq->var->rbdl_ba += 12; - - /* --------------------------- bootrom part 3 -----------------------------*/ - - switch (xq->var->type) { - case XQ_T_DEQNA: - - /* get receive bdl from memory */ - xq->var->rbdl_buf[0] = 0xFFFF; - wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0], NOMAP); - rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1], NOMAP); - if (rstatus || wstatus) return xq_nxm_error(xq); - - /* invalid buffer? */ - if (~xq->var->rbdl_buf[1] & XQ_DSC_V) { - xq->var->csr |= XQ_CSR_RL; - return SCPE_OK; - } - - /* get status words */ - rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP); - if (rstatus) return xq_nxm_error(xq); - - /* update read status words */ - xq->var->rbdl_buf[4] = XQ_DSC_V; /* valid */ - xq->var->rbdl_buf[5] = 0; - - /* update read status words*/ - wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP); - if (wstatus) return xq_nxm_error(xq); - - /* set to next bdl (implicit chain) */ - xq->var->rbdl_ba += 12; - break; - } /* switch */ - - /* --------------------------- Done, finish up -----------------------------*/ - - /* mark transmission complete */ - xq->var->csr |= XQ_CSR_RI; - if (xq->var->csr & XQ_CSR_IE) - SET_INT(XQ); - - /* reset sanity timer */ - xq_reset_santmr(xq); - - return SCPE_OK; -} -#endif /* ifdef VM_PDP11 */ - -t_stat xq_wr_csr(CTLR* xq, int32 data) -{ -#ifdef VM_PDP11 - static const uint16 bd_bits_on = XQ_CSR_BD | XQ_CSR_EL; -#endif - int old_int_state, new_int_state; - const uint16 saved_csr = xq->var->csr; - -#ifdef XQ_DEBUG - xq_csr_changes(xq, data); -#endif - - /* reset controller when SR transitions to cleared */ - if (xq->var->csr & XQ_CSR_SR & ~data) { - xq_sw_reset(xq); - return SCPE_OK; - } - - /* write the writeable bits */ - xq->var->csr = (xq->var->csr & XQ_CSR_RO) | (data & XQ_CSR_RW); - - /* clear write-one-to-clear bits */ - xq->var->csr &= ~(data & XQ_CSR_W1); - if (data & XQ_CSR_XI) /* clearing XI clears NI too */ - xq->var->csr &= ~XQ_CSR_NI; - - /* start receiver timer when RE transitions to set */ - if (~saved_csr & XQ_CSR_RE & data) { - sim_activate(&xq->unit[0], (clk_tps * tmr_poll)/100); - } - - /* stop receiver timer when RE transitions to clear */ - if (saved_csr & XQ_CSR_RE & ~data) { - sim_cancel(&xq->unit[0]); - } - - /* check and correct CPU interrupt state */ - old_int_state = (saved_csr & XQ_CSR_IE) && (saved_csr & (XQ_CSR_XI | XQ_CSR_RI)); - new_int_state = (xq->var->csr & XQ_CSR_IE) && (xq->var->csr & (XQ_CSR_XI | XQ_CSR_RI)); - if ( old_int_state && !new_int_state) CLR_INT(XQ); - if (!old_int_state && new_int_state) SET_INT(XQ); - -#ifdef VM_PDP11 - /* request boot/diagnostic rom? [PDP-11 only] */ - if ((bd_bits_on & data) == bd_bits_on) /* all bits must be on */ - xq_process_bootrom(xq); -#endif - - return SCPE_OK; -} - -t_stat xq_wr(int32 data, int32 PA, int32 access) -{ - t_stat status; - CTLR* xq = xq_pa2ctlr(PA); - int index = (PA >> 1) & 07; /* word index */ - -#ifdef XQ_DEBUG - if (index != 7) - fprintf (stderr,"%s: %s", xq->dev->name, xq_xmit_regnames[index]); -#if defined(VM_VAX) - fprintf (stderr," %08X %08X", fault_PC, PSL); -#endif /* VM_VAX */ - fprintf (stderr," write: %X\n", data); -#endif - - switch (index) { - case 0: /* these should not be written */ - case 1: - break; - case 2: /* receive bdl low bits */ - xq->var->rbdl[0] = data; - break; - case 3: /* receive bdl high bits */ - xq->var->rbdl[1] = data; - status = xq_dispatch_rbdl(xq); /* start receive operation */ - break; - case 4: /* transmit bdl low bits */ - xq->var->xbdl[0] = data; - break; - case 5: /* transmit bdl high bits */ - xq->var->xbdl[1] = data; - status = xq_dispatch_xbdl(xq); /* start transmit operation */ - break; - case 6: /* vector address register */ - status = xq_wr_var(xq, data); - break; - case 7: /* control and status register */ - status = xq_wr_csr(xq, data); - break; - } - return SCPE_OK; -} - - -/* reset device */ -t_stat xq_reset(DEVICE* dptr) -{ - t_stat status; - CTLR* xq = xq_dev2ctlr(dptr); - - /* calculate MAC checksum */ - xq_make_checksum(xq); - - /* init vector address register */ - switch (xq->var->type) { - case XQ_T_DEQNA: - xq->var->var = 0; - break; - case XQ_T_DELQA: - xq->var->var = XQ_VEC_MS | XQ_VEC_OS; - break; - } - xq->dib->vec = 0; - - /* init control status register */ - xq->var->csr = XQ_CSR_RL | XQ_CSR_XL; - - /* reset ethernet interface */ - if (xq->var->etherface) { - status = eth_filter (xq->var->etherface, 1, &xq->var->mac, 0, 0); - xq->var->csr |= XQ_CSR_OK; - } - - /* init read queue (first time only) */ - status = xq_init_queue (xq, &xq->var->ReadQ); - if (status != SCPE_OK) - return status; - - /* clear read queue */ - xq_clear_queue(&xq->var->ReadQ); - - /* start sanity timer if power-on SANITY is set */ - switch (xq->var->type) { - case XQ_T_DEQNA: - if (xq->var->sanity.enabled) { - xq->var->sanity.quarter_secs = 4 * (4 * 60); /* default is 4 minutes */; - xq_start_santmr(xq); - } - break; - case XQ_T_DELQA: - /* note that the DELQA in NORMAL mode has no power-on SANITY state! */ - xq_start_idtmr(xq); - break; - }; - - return SCPE_OK; -} - -void xq_start_santmr(CTLR* xq) -{ - UNIT* xq_santmr = &xq->unit[1]; /* sanity timer uses unit 1 */ - - /* must be recalculated each time since tmr_poll is a dynamic number */ - const int32 quarter_sec = (clk_tps * tmr_poll) / 4; - -#if 0 -#ifdef XQ_DEBUG - fprintf(stderr,"%s: SANITY TIMER ENABLED, qsecs: %d, poll:%d\n", - xq->dev->name, xq->var->sanity.quarter_secs, tmr_poll); -#endif -#endif - if (sim_is_active(xq_santmr)) /* cancel timer, just in case */ - sim_cancel(xq_santmr); - xq_reset_santmr(xq); - sim_activate(xq_santmr, quarter_sec); -} - -void xq_cancel_santmr(CTLR* xq) -{ - UNIT* xq_santmr = &xq->unit[1]; /* sanity timer uses unit 1 */ - - /* can't cancel hardware switch sanity timer */ - if (sim_is_active(xq_santmr) && !xq->var->sanity.enabled) { -#if 0 -#ifdef XQ_DEBUG - fprintf(stderr,"%s: SANITY TIMER CANCELLED, qsecs: %d\n", - xq->dev->name, xq->var->sanity.quarter_secs); -#endif -#endif - sim_cancel(xq_santmr); - } -} - -void xq_reset_santmr(CTLR* xq) -{ -#if 0 -#ifdef XQ_DEBUG - ftime(&start); - fprintf(stderr,"%s: SANITY TIMER RESETTING, qsecs: %d\n", - xq->dev->name, xq->var->sanity.quarter_secs); -#endif -#endif - xq->var->sanity.countdown = xq->var->sanity.quarter_secs; -} - -t_stat xq_sansvc(UNIT* uptr) -{ - CTLR* xq = xq_unit2ctlr(uptr); - UNIT* xq_santmr = &xq->unit[1]; /* sanity timer uses unit 1 */ - - if (--xq->var->sanity.countdown) { - /* must be recalculated each time since tmr_poll is a dynamic number */ - const int32 quarter_sec = (clk_tps * tmr_poll) / 4; - - /* haven't hit the end of the countdown timer yet, resubmit */ - sim_activate(xq_santmr, quarter_sec); - } else { - /* - If this section is entered, it means that the sanity timer has expired - without being reset, and the controller must reboot the processor. - */ -#if 0 -#ifdef XQ_DEBUG - ftime(&finish); - fprintf(stderr,"%s: SANITY TIMER EXPIRED, qsecs: %d, poll: %d, elapsed: %d\n", - xq->dev->name, xq->var->sanity.quarter_secs, tmr_poll, finish.time - start.time); -#endif -#endif - xq_boot_host(); - } - return SCPE_OK; -} - -t_stat xq_boot_host(void) -{ - /* - The manual says the hardware should force the Qbus BDCOK low for - 3.6 microseconds, which will cause the host to reboot. - - Since the SIMH Qbus emulator does not have this functionality, we call - a special STOP_ code, and let the CPU stop dispatch routine decide - what the appropriate cpu-specific behavior should be. - */ - return STOP_SANITY; -} - -void xq_start_idtmr(CTLR* xq) -{ - UNIT* xq_idtmr = &xq->unit[2]; /* system id timer uses unit 2 */ - - /* must be recalculated each time since tmr_poll is a dynamic number */ - const int32 one_sec = clk_tps * tmr_poll; - - if (sim_is_active(xq_idtmr)) /* cancel timer, just in case */ - sim_cancel(xq_idtmr); - xq->var->id.enabled = 1; - /* every 8-10 minutes (9 in this case) the DELQA broadcasts a system id message */ - xq->var->id.countdown = 9 * 60; - sim_activate(xq_idtmr, one_sec); -} - -t_stat xq_system_id (CTLR* xq, const ETH_MAC dest, uint16 receipt_id) -{ - static uint16 receipt = 0; - ETH_PACK system_id; - uint8* const msg = &system_id.msg[0]; - t_stat status; - - memset (&system_id, 0, sizeof(system_id)); - memcpy (&msg[0], dest, sizeof(ETH_MAC)); - memcpy (&msg[6], xq->var->setup.valid ? xq->var->setup.macs[0] : xq->var->mac, sizeof(ETH_MAC)); - msg[12] = 0x60; /* type */ - msg[13] = 0x02; /* type */ - msg[14] = 0x1C; /* character count */ - msg[15] = 0x00; /* character count */ - msg[16] = 0x07; /* code */ - msg[17] = 0x00; /* zero pad */ - if (receipt_id) { - msg[18] = receipt_id & 0xFF; /* receipt number */ - msg[19] = (receipt_id >> 8) & 0xFF; /* receipt number */ - } else { - msg[18] = receipt & 0xFF; /* receipt number */ - msg[19] = (receipt++ >> 8) & 0xFF; /* receipt number */ - } - - /* MOP VERSION */ - msg[20] = 0x01; /* type */ - msg[21] = 0x00; /* type */ - msg[22] = 0x03; /* length */ - msg[23] = 0x03; /* version */ - msg[24] = 0x01; /* eco */ - msg[25] = 0x00; /* user eco */ - - /* FUNCTION */ - msg[26] = 0x02; /* type */ - msg[27] = 0x00; /* type */ - msg[28] = 0x02; /* length */ - msg[29] = 0x00; /* value 1 ??? */ - msg[30] = 0x00; /* value 2 */ - - /* HARDWARE ADDRESS */ - msg[31] = 0x07; /* type */ - msg[32] = 0x00; /* type */ - msg[33] = 0x06; /* length */ - memcpy (&msg[34], xq->var->mac, sizeof(ETH_MAC)); /* ROM address */ - - /* DEVICE TYPE */ - msg[40] = 37; /* type */ - msg[41] = 0x00; /* type */ - msg[42] = 0x01; /* length */ - msg[43] = 0x11; /* value (0x11=DELQA) */ - - /* write system id */ - system_id.len = 60; - status = eth_write(xq->var->etherface, &system_id, NULL); - - return status; -} - -t_stat xq_idsvc(UNIT* uptr) -{ - CTLR* xq = xq_unit2ctlr(uptr); - UNIT* xq_idtmr = &xq->unit[2]; /* system id timer uses unit 2 */ - - /* must be recalculated each time since tmr_poll is a dynamic number */ - const int32 one_sec = clk_tps * tmr_poll; - const ETH_MAC mop_multicast = {0xAB, 0x00, 0x00, 0x02, 0x00, 0x00}; - - /* DEQNAs don't issue system id messages */ - if (xq->var->type == XQ_T_DEQNA) - return SCPE_NOFNC; - - if (--xq->var->id.countdown <= 0) { - /* - If this section is entered, it means that the 9 minute interval has elapsed - so broadcast system id to MOP multicast address - */ - xq_system_id(xq, mop_multicast, 0); - /* every 8-10 minutes (9 in this case) the DELQA broadcasts a system id message */ - xq->var->id.countdown = 9 * 60; - } - - /* resubmit - for one second to get a well calibrated value of tmr_poll */ - sim_activate(xq_idtmr, one_sec); - return SCPE_OK; -} - -/* -** service routine - used for ethernet reading loop -*/ -t_stat xq_svc(UNIT* uptr) -{ - t_stat status; - int queue_size; - CTLR* xq = xq_unit2ctlr(uptr); - UNIT* xq_svctmr = &xq->unit[0]; - - /* Don't try a read if the receiver is disabled */ - if (!(xq->var->csr & XQ_CSR_RE)) return SCPE_OK; - - /* First pump any queued packets into the system */ - if ((xq->var->ReadQ.count > 0) && (~xq->var->csr & XQ_CSR_RL)) - status = xq_process_rbdl(xq); - - /* Now read and queue packets that have arrived */ - /* This is repeated as long as they are available and we have room */ - do - { - queue_size = xq->var->ReadQ.count; - /* read a packet from the ethernet - processing is via the callback */ - status = eth_read (xq->var->etherface, &xq->var->read_buffer, xq->var->rcallback); - } while (queue_size != xq->var->ReadQ.count); - - /* Now pump any still queued packets into the system */ - if ((xq->var->ReadQ.count > 0) && (~xq->var->csr & XQ_CSR_RL)) - status = xq_process_rbdl(xq); - - /* resubmit if still receive enabled */ - if (xq->var->csr & XQ_CSR_RE) - sim_activate(xq_svctmr, (clk_tps * tmr_poll)/100); - - return SCPE_OK; -} - - - -/* attach device: */ -t_stat xq_attach(UNIT* uptr, char* cptr) -{ - t_stat status; - char* tptr; - CTLR* xq = xq_unit2ctlr(uptr); - - tptr = malloc(strlen(cptr) + 1); - if (tptr == NULL) return SCPE_MEM; - strcpy(tptr, cptr); - - xq->var->etherface = malloc(sizeof(ETH_DEV)); - if (!xq->var->etherface) return SCPE_MEM; - - status = eth_open(xq->var->etherface, cptr); - if (status != SCPE_OK) { - free(tptr); - free(xq->var->etherface); - xq->var->etherface = 0; - return status; - } - uptr->filename = tptr; - uptr->flags |= UNIT_ATT; - - /* turn on transceiver power indicator */ - xq->var->csr |= XQ_CSR_OK; - - return SCPE_OK; -} - -/* detach device: */ - -t_stat xq_detach(UNIT* uptr) -{ - t_stat status; - CTLR* xq = xq_unit2ctlr(uptr); - - if (uptr->flags & UNIT_ATT) { - status = eth_close (xq->var->etherface); - free(xq->var->etherface); - xq->var->etherface = 0; - free(uptr->filename); - uptr->filename = NULL; - uptr->flags &= ~UNIT_ATT; - } - - /* turn off transceiver power indicator */ - xq->var->csr &= ~XQ_CSR_OK; - - return SCPE_OK; -} - -int32 xq_inta (void) -{ - return xqa_dib.vec; -} - -int32 xq_intb (void) -{ - return xqb_dib.vec; -} - -/*============================================================================== -/ debugging routines -/=============================================================================*/ - -#ifdef XQ_DEBUG - -void xq_dump_csr (CTLR* xq) -{ - static int cnt = 0; - /* tell user what is changing in register */ - int i; - int mask = 1; - uint16 csr = xq->var->csr; - char hi[256] = "Set: "; - char lo[256] = "Reset: "; - for (i=0; i<16; i++, mask <<= 1) { - if ((csr & mask)) strcat (hi, xq_csr_bits[i]); - if ((~csr & mask)) strcat (lo, xq_csr_bits[i]); - } -#if defined (VM_VAX) - printf ("%s: CSR %08X %08X read: %s %s\n", xq->dev->name, fault_PC, PSL, hi, lo); -#else -if (cnt < 20) - printf ("%s: CSR read[%d]: %s %s\n", xq->dev->name, cnt++, hi, lo); -#endif /* VM_VAX */ -} - -void xq_dump_var (CTLR* xq) -{ - /* tell user what is changing in register */ - uint16 var = xq->var->var; - char hi[256] = "Set: "; - char lo[256] = "Reset: "; - int vec = (var & XQ_VEC_IV) >> 2; - strcat((var & XQ_VEC_MS) ? hi : lo, "MS "); - strcat((var & XQ_VEC_OS) ? hi : lo, "OS "); - strcat((var & XQ_VEC_RS) ? hi : lo, "RS "); - strcat((var & XQ_VEC_S3) ? hi : lo, "S3 "); - strcat((var & XQ_VEC_S2) ? hi : lo, "S2 "); - strcat((var & XQ_VEC_S1) ? hi : lo, "S1 "); - strcat((var & XQ_VEC_RR) ? hi : lo, "RR "); - strcat((var & XQ_VEC_ID) ? hi : lo, "ID "); - printf ("%s: VAR read: %s %s - Vec: %d \n", xq->dev->name, hi, lo, vec); -} - -void xq_csr_changes (CTLR* xq, uint16 data) -{ - /* tell user what is changing in register */ - int i; - int mask = 1; - uint16 csr = xq->var->csr; - char hi[256] = "Setting: "; - char lo[256] = "Resetting: "; - for (i=0; i<16; i++, mask <<= 1) { - if ((csr & mask) && (~data & mask)) strcat (lo, xq_csr_bits[i]); - if ((~csr & mask) && (data & mask)) strcat (hi, xq_csr_bits[i]); - } - /* write-one-to-clear bits*/ - if (data & XQ_CSR_RI) strcat(lo, "RI "); - if (data & XQ_CSR_XI) strcat(lo, "XI "); -#if defined(VM_VAX) - printf ("%s: CSR %08X %08X write: %s %s\n", xq->dev->name, fault_PC, PSL, hi, lo); -#else - printf ("%s: CSR write: %s %s\n", xq->dev->name, hi, lo); -#endif /* VM_VAX */ -} - -void xq_var_changes (CTLR* xq, uint16 data) -{ - /* tell user what is changing in register */ - uint16 vec; - uint16 var = xq->var->var; - char hi[256] = "Setting: "; - char lo[256] = "Resetting: "; - if (~var & XQ_VEC_MS & data) strcat (hi, "MS "); - if (var & XQ_VEC_MS & ~data) strcat (lo, "MS "); - if (~var & XQ_VEC_OS & data) strcat (hi, "OS "); - if (var & XQ_VEC_OS & ~data) strcat (lo, "OS "); - if (~var & XQ_VEC_RS & data) strcat (hi, "RS "); - if (var & XQ_VEC_RS & ~data) strcat (lo, "RS "); - if (~var & XQ_VEC_ID & data) strcat (hi, "ID "); - if (var & XQ_VEC_ID & ~data) strcat (lo, "ID "); - - if ((var & XQ_VEC_IV) != (data & XQ_VEC_IV)) { - vec = (data & XQ_VEC_IV) >> 2; - printf ("%s: VAR write: %s %s - Vec: %d\n", xq->dev->name, hi, lo, vec); - } else - printf ("%s: VAR write: %s %s\n", xq->dev->name, hi, lo); -} - -void xq_debug_setup(CTLR* xq) -{ - int i; - char buffer[20]; - if (xq->var->write_buffer.msg[0]) - printf ("%s: Setup: MOP info present!\n", xq->dev->name); - - for (i = 0; i < XQ_FILTER_MAX; i++) { - eth_mac_fmt(&xq->var->setup.macs[i], buffer); - printf ("%s: Setup: set addr[%d]: %s\n", xq->dev->name, i, buffer); - } - - if (xq->var->write_buffer.len > 128) { - char buffer[20] = {0}; - uint16 len = xq->var->write_buffer.len; - if (len & XQ_SETUP_MC) strcat(buffer, "MC "); - if (len & XQ_SETUP_PM) strcat(buffer, "PM "); - if (len & XQ_SETUP_LD) strcat(buffer, "LD "); - if (len & XQ_SETUP_ST) strcat(buffer, "ST "); - printf ("%s: Setup: Length [%d =0x%X, LD:%d, ST:%d] info: %s\n", - xq->dev->name, len, len, (len & XQ_SETUP_LD) >> 2, (len & XQ_SETUP_ST) >> 4, buffer); - } -} -#endif diff --git a/PDP11/pdp11_xq.h b/PDP11/pdp11_xq.h deleted file mode 100644 index 6f174ceb..00000000 --- a/PDP11/pdp11_xq.h +++ /dev/null @@ -1,230 +0,0 @@ -/* pdp11_xq.h: DEQNA/DELQA ethernet controller information - ------------------------------------------------------------------------------ - - Copyright (c) 2002-2003, David T. Hittner - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of the author shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from the author. - - ------------------------------------------------------------------------------ - - Modification history: - - 02-Jun-03 DTH Added struct xq_stats - 28-May-03 DTH Made xq_msg_que.item dynamic - 28-May-03 MP Optimized structures, removed rtime variable - 06-May-03 DTH Changed 32-bit t_addr to uint32 for v3.0 - 28-Apr-03 DTH Added callbacks for multicontroller identification - 25-Mar-03 DTH Removed bootrom field - no longer needed; Updated copyright - 15-Jan-03 DTH Merged Mark Pizzolato's changes into main source - 13-Jan-03 MP Added countdown for System Id multicast packets - 10-Jan-03 DTH Added bootrom field - 30-Dec-02 DTH Added setup valid field - 21-Oct-02 DTH Corrected copyright again - 15-Oct-02 DTH Fixed copyright, added sanity timer support - 10-Oct-02 DTH Added more setup fields and bitmasks - 08-Oct-02 DTH Integrated with 2.10-0p4, added variable vector and copyrights - 03-Oct-02 DTH Beta version of xq/sim_ether released for SIMH 2.09-11 - 15-Aug-02 DTH Started XQ simulation - - ------------------------------------------------------------------------------ -*/ - -#ifndef _PDP11_XQ_H -#define _PDP11_XQ_H - -#if defined (VM_PDP10) /* PDP10 version */ -#error "DEQNA/DELQA not supported on PDP10!" - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -#define XQ_RDX 16 -#define XQ_WID 32 -extern int32 PSL; /* PSL */ -extern int32 fault_PC; /* fault PC */ -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -#define XQ_RDX 8 -#define XQ_WID 16 -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#endif - -#include "sim_ether.h" - -/* message queue arrays */ -#define XQ_QUE_MAX 500 -#define XQ_FILTER_MAX 14 - -enum xq_type {XQ_T_DEQNA, XQ_T_DELQA}; - -struct xq_sanity { - int enabled; /* sanity timer enabled ? */ - int quarter_secs; /* sanity timer value in 1/4 seconds */ - int countdown; /* sanity timer countdown in 1/4 seconds */ -}; - -struct xq_id { - int enabled; /* System ID timer enabled ? */ - int countdown; /* System ID timer countdown in seconds */ -}; - -struct xq_msg_itm { - int type; /* receive (0=setup, 1=loopback, 2=normal) */ - int32 status; /* message size */ - ETH_PACK packet; /* packet */ -}; - -struct xq_msg_que { - int count; - int head; - int tail; - int loss; - int high; - struct xq_msg_itm* item; -}; - -struct xq_setup { - int valid; /* is the setup block valid? */ - int promiscuous; /* promiscuous mode enabled */ - int multicast; /* enable all multicast addresses */ - int l1; /* first diagnostic led state */ - int l2; /* second diagnostic led state */ - int l3; /* third diagnostic led state */ - int sanity_timer; /* sanity timer value (encoded) */ - ETH_MAC macs[XQ_FILTER_MAX]; /* MAC addresses to respond to */ -}; - -struct xq_stats { - int recv; /* received packets */ - int filter; /* filtered packets */ - int xmit; /* transmitted packets */ - int fail; /* transmit failed */ - int runt; /* runts */ - int giant; /* oversize packets */ - int setup; /* setup packets */ - int loop; /* loopback packets */ -}; - -struct xq_meb { /* MEB block */ - uint8 type; - uint8 add_lo; - uint8 add_mi; - uint8 add_hi; - uint8 siz_lo; - uint8 siz_hi; -}; - -struct xq_device { - /*+ initialized values - DO NOT MOVE */ - ETH_PCALLBACK rcallback; /* read callback routine */ - ETH_PCALLBACK wcallback; /* write callback routine */ - ETH_MAC mac; /* MAC address */ - enum xq_type type; /* controller type */ - struct xq_sanity sanity; /* sanity timer information */ - struct xq_id id; /* System ID timer information */ - /*- initialized values - DO NOT MOVE */ - - /* I/O register storage */ - uint16 addr[6]; - uint16 rbdl[2]; - uint16 xbdl[2]; - uint16 var; - uint16 csr; - - /* buffers, etc. */ - struct xq_setup setup; - struct xq_stats stats; - uint8 mac_checksum[2]; - uint16 rbdl_buf[6]; - uint16 xbdl_buf[6]; - uint32 rbdl_ba; - uint32 xbdl_ba; - ETH_DEV* etherface; - int receiving; - ETH_PACK read_buffer; - ETH_PACK write_buffer; - struct xq_msg_que ReadQ; -}; - -struct xq_controller { - DEVICE* dev; /* device block */ - UNIT* unit; /* unit block */ - DIB* dib; /* device interface block */ - struct xq_device* var; /* controller-specific variables */ -}; - -typedef struct xq_controller CTLR; - - -#define XQ_CSR_RI 0x8000 /* Receive Interrupt Request (RI) [RO/W1] */ -#define XQ_CSR_PE 0x4000 /* Parity Error in Host Memory (PE) [RO] */ -#define XQ_CSR_CA 0x2000 /* Carrier from Receiver Enabled (CA) [RO] */ -#define XQ_CSR_OK 0x1000 /* Ethernet Transceiver Power (OK) [RO] */ -#define XQ_CSR_RR 0x0800 /* Reserved : Set to Zero (RR) [RO] */ -#define XQ_CSR_SE 0x0400 /* Sanity Timer Enable (SE) [RW] */ -#define XQ_CSR_EL 0x0200 /* External Loopback (EL) [RW] */ -#define XQ_CSR_IL 0x0100 /* Internal Loopback (IL) [RW] */ -#define XQ_CSR_XI 0x0080 /* Transmit Interrupt Request (XI) [RO/W1] */ -#define XQ_CSR_IE 0x0040 /* Interrupt Enable (IE) [RW] */ -#define XQ_CSR_RL 0x0020 /* Receive List Invalid/Empty (RL) [RO] */ -#define XQ_CSR_XL 0x0010 /* Transmit List Invalid/Empty (XL) [RO] */ -#define XQ_CSR_BD 0x0008 /* Boot/Diagnostic ROM Load (BD) [RW] */ -#define XQ_CSR_NI 0x0004 /* NonExistant Memory Timeout (NXM) [RO] */ -#define XQ_CSR_SR 0x0002 /* Software Reset (SR) [RW] */ -#define XQ_CSR_RE 0x0001 /* Receiver Enable (RE) [RW] */ - -/* special access bitmaps */ -#define XQ_CSR_RO 0xF8B4 /* Read-Only bits */ -#define XQ_CSR_RW 0x074B /* Read/Write bits */ -#define XQ_CSR_W1 0x8080 /* Write-one-to-clear bits */ - -#define XQ_VEC_MS 0x8000 /* Mode Select (MO) [RW] */ -#define XQ_VEC_OS 0x4000 /* Option Switch Setting (OS) [RO] */ -#define XQ_VEC_RS 0x2000 /* Request Self-Test (RS) [RW] */ -#define XQ_VEC_S3 0x1000 /* Self-Test Status (S3) [RO] */ -#define XQ_VEC_S2 0x0800 /* Self-Test Status (S2) [RO] */ -#define XQ_VEC_S1 0x0400 /* Self-Test Status (S1) [RO] */ -#define XQ_VEC_ST 0x1C00 /* Self-Test (S1 + S2 + S3) [RO] */ -#define XQ_VEC_IV 0x03FC /* Interrupt Vector (IV) [RW] */ -#define XQ_VEC_RR 0x0002 /* Reserved (RR) [RO] */ -#define XQ_VEC_ID 0x0001 /* Identity Test Bit (ID) [RW] */ - -/* special access bitmaps */ -#define XQ_VEC_RO 0x5C02 /* Read-Only bits */ -#define XQ_VEC_RW 0xA3FD /* Read/Write bits */ - -#define XQ_DSC_V 0x8000 /* Valid bit */ -#define XQ_DSC_C 0x4000 /* Chain bit */ -#define XQ_DSC_E 0x2000 /* End of Message bit [Transmit only] */ -#define XQ_DSC_S 0x1000 /* Setup bit [Transmit only] */ -#define XQ_DSC_L 0x0080 /* Low Byte Termination bit [Transmit only] */ -#define XQ_DSC_H 0x0040 /* High Byte Start bit [Transmit only] */ - -#define XQ_SETUP_MC 0x0001 /* multicast bit */ -#define XQ_SETUP_PM 0x0002 /* promiscuous bit */ -#define XQ_SETUP_LD 0x000C /* led bits */ -#define XQ_SETUP_ST 0x0070 /* sanity timer bits */ - -#endif /* _PDP11_XQ_H */ diff --git a/PDP11/pdp11_xq_bootrom.h b/PDP11/pdp11_xq_bootrom.h deleted file mode 100644 index 9a0b954c..00000000 --- a/PDP11/pdp11_xq_bootrom.h +++ /dev/null @@ -1,312 +0,0 @@ -/* pdp11_xq_bootrom.h: DEQNA/DELQA bootrom data - ------------------------------------------------------------------------------ - - Copyright (c) 2003, David T. Hittner - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of the author shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from the author. - - ------------------------------------------------------------------------------ - - Modification history: - - 26-Mar-03 DTH Removed 'static' declaration - 23-Mar-03 DTH Created by extracting from merged DEQNA bootrom dumps - - ------------------------------------------------------------------------------ -*/ - -#ifndef _PDP11_XQ_BOOTROM_H -#define _PDP11_XQ_BOOTROM_H - -#ifdef VM_PDP11 - /* - Bootrom code is from merged file 23-334e5.bin, offset 050000, for 4096. bytes. - - Word 0: NOP - Word 1: Branch to extended primary boot - Word 2: Branch/Vector to Citizenship tests - Word 3: Offset from beginning to checksum word - - See INIQNA.MAR for further information on format and contents. - */ - - uint16 xq_bootrom[] = { - 0000240,0000423,0000546,0007776,0000520,0000000,0100000,0100000, - 0002000,0176000,0000000,0000000,0100000,0100000,0006000,0176000, - 0000000,0000000,0100000,0020000,0140000,0012706,0001776,0010046, - 0012761,0000014,0000004,0005061,0000006,0012761,0001010,0000016, - 0005000,0005300,0001376,0005061,0000016,0005000,0005300,0001376, - 0012761,0000002,0000016,0005061,0000016,0042767,0037777,0177664, - 0026767,0177660,0177702,0001057,0042767,0037777,0177652,0026767, - 0177646,0177664,0001050,0042767,0037777,0177650,0026767,0177644, - 0177646,0001041,0012704,0007776,0005003,0005002,0116200,0002000, - 0005202,0042700,0177400,0060003,0005304,0001370,0013700,0000006, - 0026003,0002000,0001020,0000137,0002010,0012702,0012000,0004767, - 0000040,0005700,0001010,0011602,0001002,0000167,0004530,0022702, - 0000777,0103001,0000112,0013703,0000012,0001401,0000113,0000000, - 0000776,0010637,0000764,0062701,0000016,0032761,0100000,0177776, - 0001421,0052761,0020000,0177776,0012703,0000777,0005000,0005300, - 0001376,0032761,0016000,0177776,0001405,0005303,0001370,0012700, - 0000200,0000454,0004767,0000136,0052711,0000002,0042711,0000002, - 0012703,0017777,0005303,0001376,0004567,0003514,0177700,0001014, - 0005712,0001014,0032762,0002000,0000050,0001402,0052711,0002000, - 0004567,0003464,0177622,0001402,0052712,0000100,0012711,0000002, - 0005011,0012703,0017777,0005303,0001376,0011100,0042700,0064000, - 0022700,0010060,0001402,0052712,0000100,0011200,0162701,0000016, - 0000207,0052400,0177652,0013746,0000034,0013746,0000036,0010703, - 0062703,0000210,0010337,0000034,0012737,0000340,0000036,0104400, - 0012637,0000036,0012637,0000034,0013700,0000762,0052700,0000340, - 0062703,0000010,0010337,0000004,0010037,0000006,0010637,0000766, - 0010137,0000772,0010237,0000770,0062703,0000012,0010337,0000024, - 0010037,0000026,0062703,0000022,0012761,0000774,0177776,0052761, - 0100000,0177776,0010337,0000774,0010037,0000776,0005062,0000002, - 0005012,0012700,0000162,0060200,0012704,0000112,0005020,0005304, - 0001375,0004567,0003202,0177666,0001434,0005262,0000002,0022762, - 0000002,0000002,0003355,0000207,0016637,0000002,0000762,0000006, - 0052712,0002000,0013706,0000764,0000207,0052712,0020000,0013706, - 0000766,0013701,0000772,0013702,0000770,0000207,0052712,0004000, - 0000002,0106427,0000000,0010103,0162703,0000016,0010204,0062704, - 0000012,0012705,0000006,0012300,0110024,0005305,0001374,0010204, - 0062704,0000012,0010405,0005724,0001004,0005724,0001002,0005714, - 0001421,0010504,0012700,0177777,0020024,0001016,0020024,0001014, - 0020014,0001410,0001011,0010504,0022724,0000252,0001003,0122714, - 0000004,0103002,0052712,0000001,0012700,0177777,0004767,0003314, - 0013705,0000774,0010703,0062703,0000044,0010337,0000774,0052711, - 0000100,0010461,0177772,0005000,0010061,0177774,0012703,0010000, - 0005303,0001376,0052712,0004000,0000207,0062706,0000004,0010537, - 0000774,0005200,0001767,0011100,0032700,0000200,0001763,0011400, - 0042700,0037777,0022700,0140000,0001355,0005764,0000010,0001752, - 0005764,0000012,0001747,0052711,0000002,0042711,0000002,0012711, - 0002000,0106437,0000762,0004567,0002576,0177666,0001402,0000207, - 0010703,0062703,0177160,0010362,0000002,0010362,0000006,0062703, - 0000005,0010362,0000004,0005062,0000010,0010203,0062703,0000162, - 0012700,0000002,0012705,0000006,0105023,0012704,0000007,0026262, - 0000004,0000006,0003003,0016262,0000002,0000006,0117223,0000006, - 0005262,0000006,0005304,0001363,0005305,0001356,0012704,0000020, - 0105023,0005304,0001375,0005300,0001345,0004567,0002432,0177705, - 0001403,0052712,0000002,0000207,0005262,0000010,0022762,0000764, - 0000010,0003323,0042761,0100000,0177776,0005062,0000006,0010204, - 0062704,0000163,0010462,0000010,0005304,0012703,0000060,0105024, - 0005303,0001375,0062762,0000010,0000002,0016262,0000010,0000002, - 0012762,0000060,0000004,0105062,0000012,0000261,0106162,0000012, - 0103041,0106162,0000012,0062762,0000010,0000002,0000433,0016204, - 0000010,0005304,0012703,0000060,0112724,0000377,0005303,0001374, - 0012762,0000060,0000004,0016262,0000010,0000002,0112762,0000377, - 0000012,0000241,0106162,0000012,0103405,0106162,0000012,0062762, - 0000010,0000002,0016204,0000002,0012703,0000007,0105064,0177770, - 0116224,0000012,0005303,0001372,0004567,0002154,0177750,0001402, - 0000167,0000414,0005762,0000006,0001011,0000241,0106172,0000002, - 0103010,0106072,0000002,0106072,0000002,0000403,0000261,0106172, - 0000002,0016204,0000010,0010203,0062703,0004362,0012700,0000006, - 0111423,0062704,0000010,0005300,0001373,0012711,0000001,0012700, - 0177775,0004767,0002352,0010461,0177766,0005061,0177770,0004767, - 0002372,0010461,0177772,0005061,0177774,0012700,0077777,0032711, - 0100000,0001003,0005300,0001373,0000523,0005000,0004567,0002412, - 0000000,0040000,0001115,0016204,0000010,0005204,0010203,0062703, - 0004362,0012700,0000006,0111423,0062704,0000010,0005300,0001373, - 0042711,0100200,0012700,0177775,0004767,0002224,0010461,0177766, - 0005061,0177770,0012700,0177775,0004767,0002240,0010461,0177772, - 0005061,0177774,0012700,0077777,0032711,0100000,0001003,0005300, - 0001373,0000454,0005000,0004567,0002260,0000000,0000000,0001040, - 0042711,0000001,0010204,0062704,0001362,0010205,0062705,0004362, - 0012700,0000006,0122425,0001024,0005300,0001374,0005362,0000004, - 0001007,0005762,0000006,0001034,0005262,0000006,0000167,0177256, - 0005762,0000006,0001002,0000167,0177222,0000261,0000167,0177304, - 0052712,0000004,0000405,0052712,0004000,0000402,0052712,0001004, - 0052761,0100000,0177776,0000207,0000074,0001422,0002752,0177777, - 0052761,0100000,0177776,0052711,0001000,0010703,0062703,0176046, - 0010362,0000002,0010362,0000006,0062703,0000004,0010362,0000004, - 0010703,0062703,0177726,0010362,0000010,0010203,0062703,0004362, - 0017205,0000010,0026262,0000004,0000006,0003003,0016262,0000002, - 0000006,0117223,0000006,0005262,0000006,0005305,0001363,0017200, - 0000010,0004567,0001536,0103425,0017200,0000010,0004567,0001752, - 0000000,0020000,0001401,0000003,0010204,0062704,0001362,0010205, - 0062705,0004362,0017200,0000010,0122425,0001003,0005300,0001374, - 0000403,0052712,0000010,0000207,0062762,0000002,0000010,0022772, - 0177777,0000010,0001402,0000167,0177620,0012700,0177770,0004767, - 0001536,0010461,0177766,0005061,0177770,0010203,0062703,0000040, - 0010304,0012700,0000010,0012723,0100000,0012723,0100000,0010213, - 0062723,0000012,0012723,0177777,0005023,0005023,0005300,0001363, - 0010403,0052763,0000200,0000002,0052763,0000300,0000016,0012763, - 0177776,0000022,0052763,0000100,0000032,0062763,0000002,0000034, - 0062763,0000004,0000050,0012763,0040000,0000062,0010363,0000064, - 0062763,0000074,0000064,0010363,0000100,0062763,0000070,0000100, - 0012763,0177776,0000102,0012763,0120000,0000112,0012763,0177775, - 0000116,0012763,0020000,0000126,0010461,0177772,0005061,0177774, - 0012700,0077777,0032711,0100000,0001005,0005300,0001373,0052712, - 0001000,0000411,0012700,0000020,0004567,0001376,0100000,0020000, - 0001405,0052712,0040000,0052712,0000020,0000207,0010203,0062703, - 0000040,0012700,0000010,0016305,0000000,0042705,0037777,0022705, - 0140000,0001357,0022700,0000004,0001403,0022700,0000001,0001007, - 0005763,0000010,0001346,0005763,0000012,0001343,0000424,0022700, - 0000002,0001405,0032763,0100000,0000010,0001733,0000414,0016305, - 0000010,0042705,0026417,0022705,0000000,0001323,0016305,0000012, - 0042705,0176000,0001716,0062703,0000014,0005300,0001324,0010203, - 0062703,0000012,0010204,0062704,0001362,0010405,0022324,0001303, - 0022324,0001301,0022324,0001277,0005724,0001275,0005724,0001273, - 0022524,0001271,0022524,0001267,0022524,0001265,0010203,0062703, - 0000162,0010305,0012700,0000113,0005023,0005300,0001375,0010204, - 0062704,0000012,0004767,0000046,0062705,0000020,0004767,0000036, - 0004567,0000444,0177674,0001401,0000207,0012700,0177777,0032711, - 0020000,0001423,0005300,0001373,0052712,0100000,0000207,0010446, - 0012700,0000006,0005205,0012703,0000007,0111425,0005303,0001375, - 0005204,0005300,0001367,0012604,0000207,0005712,0001017,0052711, - 0001400,0012700,0000056,0004767,0000132,0012700,0000074,0004567, - 0000522,0103005,0042712,0001000,0052712,0100000,0000207,0012700, - 0000074,0004767,0000156,0001761,0001403,0052712,0000040,0000207, - 0012700,0000074,0004767,0000232,0001370,0012700,0002734,0004767, - 0000042,0012700,0002752,0004567,0000432,0103757,0012700,0002752, - 0004767,0000100,0001766,0001351,0012700,0002752,0004767,0000162, - 0001344,0000207,0010203,0062703,0004362,0010204,0062704,0000012, - 0010405,0012423,0012423,0012423,0012523,0012523,0012523,0012723, - 0000220,0005023,0012723,0000001,0110023,0005300,0001375,0005062, - 0000002,0000207,0004567,0000542,0000000,0020000,0001004,0062716, - 0000002,0005712,0000207,0016200,0000050,0042700,0137777,0001010, - 0016200,0000030,0032700,0137777,0001003,0042712,0040000,0000757, - 0005262,0000002,0022762,0000144,0000002,0003751,0042712,0040000, - 0000750,0010204,0062704,0001362,0010205,0062705,0004362,0122425, - 0001002,0005300,0001374,0000207,0010200,0062700,0000162,0010046, - 0011500,0005300,0004767,0000270,0010461,0177766,0005061,0177770, - 0012500,0004767,0000306,0012764,0130000,0000002,0011664,0000004, - 0010461,0177772,0005061,0177774,0012704,0017777,0032711,0100000, - 0001010,0005304,0001373,0052712,0001000,0005726,0052712,0010000, - 0000430,0016500,0177776,0006300,0005400,0004567,0000274,0000000, - 0020000,0001363,0016500,0177776,0006300,0005400,0010204,0062704, - 0001362,0012603,0122423,0001352,0005300,0001374,0022714,0051343, - 0001345,0000205,0005046,0006000,0005516,0061600,0005400,0004767, - 0000076,0010461,0177766,0005061,0177770,0004767,0000116,0005726, - 0001403,0052764,0000200,0000002,0010461,0177772,0005061,0177774, - 0012703,0000777,0005000,0032711,0100000,0001010,0005300,0001376, - 0005303,0001371,0052712,0001000,0000261,0000401,0000241,0000205, - 0010203,0062703,0001362,0012704,0000200,0012723,0051343,0005304, - 0001374,0004567,0000020,0000020,0001362,0000207,0004567,0000006, - 0000040,0004362,0000207,0012503,0060203,0010304,0012723,0100000, - 0012723,0120000,0012513,0060223,0010023,0012723,0100000,0012723, - 0100000,0012723,0100000,0005023,0000205,0010046,0005000,0011104, - 0052711,0100200,0042704,0077401,0022704,0100260,0001401,0010700, - 0016204,0000040,0042704,0037777,0022704,0140000,0001401,0010700, - 0016204,0000050,0100002,0042704,0077777,0042704,0076417,0022504, - 0001401,0010700,0016204,0000052,0042704,0176000,0001001,0010700, - 0016204,0000020,0042704,0037777,0022704,0140000,0001401,0010700, - 0016204,0000030,0010446,0042704,0007777,0022504,0001401,0010700, - 0012604,0042704,0174377,0022762,0177775,0000046,0001002,0005726, - 0000415,0032762,0010000,0000042,0001401,0005004,0016203,0000032, - 0042703,0177400,0060304,0022604,0001401,0010700,0010003,0001402, - 0052712,0040000,0000205,0000005,0012706,0017776,0010616,0011646, - 0162716,0003056,0010703,0062703,0000014,0010337,0000004,0011100, - 0000401,0000000,0004767,0000230,0011605,0012725,0022410,0012725, - 0000401,0105025,0105025,0012725,0000621,0112725,0000002,0012702, - 0002752,0110225,0000302,0110225,0012702,0000013,0005000,0004767, - 0000452,0001350,0012702,0002756,0004767,0000660,0001046,0011603, - 0112304,0005302,0120427,0000002,0001404,0105704,0001335,0162702, - 0000004,0105713,0001402,0121300,0001030,0112300,0105200,0005302, - 0003410,0012305,0005723,0162702,0000004,0003403,0112325,0005302, - 0003375,0105704,0001417,0005003,0011605,0112725,0000012,0110025, - 0110325,0005005,0012702,0000003,0000722,0105700,0001673,0012703, - 0000001,0000762,0004767,0001232,0112346,0112366,0000001,0000207, - 0042761,0000002,0000016,0016605,0000002,0010504,0062704,0177720, - 0010466,0000004,0012702,0000020,0005024,0077202,0010504,0062704, - 0177760,0005065,0177722,0010465,0177724,0005065,0177742,0010465, - 0177744,0052765,0100000,0177722,0012702,0002756,0006202,0005402, - 0010265,0177726,0052765,0120000,0177742,0016604,0000004,0010467, - 0001324,0005067,0001322,0062704,0000020,0010467,0001314,0005067, - 0001312,0116167,0000000,0001262,0116167,0000002,0001255,0116167, - 0000004,0001250,0116167,0000006,0001243,0116167,0000010,0001236, - 0116167,0000012,0001231,0105267,0001232,0042761,0000002,0000016, - 0052761,0000400,0000016,0004767,0001104,0005065,0000002,0016744, - 0001174,0016744,0001166,0016744,0001160,0012744,0000000,0012744, - 0001000,0012744,0000253,0004767,0000046,0000207,0016605,0000002, - 0010504,0010244,0012744,0000540,0016744,0001122,0016744,0001114, - 0016744,0001106,0016744,0001060,0016744,0001052,0016744,0001044, - 0062705,0177740,0062702,0000016,0020227,0000074,0002003,0012702, - 0000074,0000407,0032702,0000001,0001404,0052765,0000200,0000002, - 0005202,0006202,0005402,0010265,0000006,0005065,0000010,0005065, - 0000012,0016761,0001024,0000010,0016761,0001020,0000012,0012704, - 0000204,0004767,0000610,0103012,0001404,0032765,0001000,0000010, - 0001354,0042765,0000200,0000002,0000244,0000207,0042765,0000200, - 0000002,0032702,0040004,0001401,0000000,0000207,0016605,0000002, - 0062705,0177720,0005065,0000010,0005065,0000012,0016761,0000706, - 0000004,0016761,0000702,0000006,0052761,0000001,0000016,0012704, - 0100004,0004767,0000470,0103030,0001355,0052761,0000002,0000016, - 0012767,0000253,0000576,0012767,0000400,0000572,0012767,0000000, - 0000566,0105267,0000616,0005000,0042761,0000002,0000016,0052761, - 0000400,0000016,0000244,0000207,0042761,0000001,0000016,0052761, - 0000002,0000016,0016605,0000002,0016502,0177776,0042761,0000002, - 0000016,0052761,0000400,0000016,0022765,0000540,0177774,0001041, - 0105767,0000520,0001015,0026765,0000456,0177772,0001267,0026765, - 0000444,0177770,0001263,0026765,0000432,0177766,0001257,0000207, - 0122715,0000003,0001253,0016567,0177766,0000410,0016567,0177770, - 0000404,0016567,0177772,0000400,0105067,0000430,0000244,0005000, - 0000207,0022765,0000220,0177774,0001423,0022765,0001140,0177774, - 0001225,0122715,0000005,0001222,0004767,0000262,0016464,0177776, - 0177770,0016464,0177774,0177766,0016464,0177772,0177764,0000437, - 0010504,0060204,0010503,0062703,0177720,0016302,0000010,0042702, - 0174377,0156302,0000012,0062702,0000056,0022724,0000002,0001027, - 0062765,0000010,0177776,0032714,0000001,0001021,0010503,0062703, - 0177760,0012423,0012423,0012423,0010504,0062704,0177774,0016744, - 0000234,0016744,0000226,0016744,0000220,0004767,0177122,0000167, - 0177272,0016737,0000156,0000030,0016737,0000152,0000032,0016737, - 0000146,0000034,0052761,0000002,0000016,0000264,0000207,0012703, - 0037777,0000241,0012702,0000220,0030461,0000016,0001006,0005303, - 0001376,0005302,0001371,0000261,0000207,0016102,0000016,0010261, - 0000016,0032765,0040000,0000010,0001401,0000261,0000207,0010546, - 0010703,0062703,0000050,0012702,0000030,0012325,0005725,0112325, - 0005302,0001375,0012605,0010504,0012702,0000034,0010244,0012744, - 0001140,0000207,0000253,0000400,0000000,0000007,0000001,0001403, - 0000000,0000002,0000402,0003400,0003000,0000000,0000000,0000000, - 0000144,0022401,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0102206 - }; -#endif /* VM_PDP11 */ - -#endif /* _PDP11_XQ_BOOTROM_H */ diff --git a/PDP11/pdp11_xu.c b/PDP11/pdp11_xu.c deleted file mode 100644 index 02867c65..00000000 --- a/PDP11/pdp11_xu.c +++ /dev/null @@ -1,63 +0,0 @@ -/* pdp11_xu.c: DEUNA/DELUA Unibus Ethernet interface (stub) - - Copyright (c) 2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - xu DEUNA/DELUNA Ethernet interface (stub) -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#include "pdp10_defs.h" -extern int32 int_req; -extern int32 int_vec[32]; - -#elif defined (VM_VAX) /* VAX version */ -#error "DEUNA/DELUA not supported on VAX!" - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#endif - -/* XU data structures - - xu_dev XU device descriptor - xu_unit XU unit list - xu_reg XU register list -*/ - -DIB xu_dib = { IOBA_XU, IOLN_XU, NULL, NULL, - 1, IVCL (XU), VEC_XU, { NULL } }; - -UNIT xu_unit = { UDATA (NULL, 0, 0) }; - -REG xu_reg[] = { - { NULL } }; - -DEVICE xu_dev = { - "XU", &xu_unit, xu_reg, NULL, - 1, 8, 8, 1, 8, 8, - NULL, NULL, NULL, - NULL, NULL, NULL, - &xu_dib, DEV_DIS | DEV_UBUS }; diff --git a/PDP18B/pdp18b_cpu.c b/PDP18B/pdp18b_cpu.c deleted file mode 100644 index 96c3ff16..00000000 --- a/PDP18B/pdp18b_cpu.c +++ /dev/null @@ -1,2006 +0,0 @@ -/* pdp18b_cpu.c: 18b PDP CPU simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - cpu PDP-4/7/9/15 central processor - - 31-Aug-03 RMS Added instruction history - Fixed PDP-15-specific implementation of API priorities - 16-Aug-03 RMS Fixed PDP-15-specific handling of EAE unsigned mul/div - 27-Jul-03 RMS Added FP15 support - Added XVM support - Added EAE option to PDP-4 - Added PDP-15 "re-entrancy ECO" - Fixed memory protect/skip interaction - Fixed CAF not to reset CPU - 12-Mar-03 RMS Added logical name support - 18-Feb-03 RMS Fixed three EAE bugs (found by Hans Pufal) - 05-Oct-02 RMS Added DIBs, device number support - 25-Jul-02 RMS Added DECtape support for PDP-4 - 06-Jan-02 RMS Revised enable/disable support - 30-Dec-01 RMS Added old PC queue - 30-Nov-01 RMS Added extended SET/SHOW support - 25-Nov-01 RMS Revised interrupt structure - 19-Sep-01 RMS Fixed bug in EAE (found by Dave Conroy) - 17-Sep-01 RMS Fixed typo in conditional - 10-Aug-01 RMS Removed register from declarations - 17-Jul-01 RMS Moved function prototype - 27-May-01 RMS Added second Teletype support, fixed bug in API - 18-May-01 RMS Added PDP-9,-15 API option - 16-May-01 RMS Fixed bugs in protection checks - 26-Apr-01 RMS Added device enable/disable support - 25-Jan-01 RMS Added DECtape support - 18-Dec-00 RMS Added PDP-9,-15 memm init register - 30-Nov-00 RMS Fixed numerous PDP-15 bugs - 14-Apr-99 RMS Changed t_addr to unsigned - - The 18b PDP family has five distinct architectural variants: PDP-1, - PDP-4, PDP-7, PDP-9, and PDP-15. Of these, the PDP-1 is so unique - as to require a different simulator. The PDP-4, PDP-7, PDP-9, and - PDP-15 are "upward compatible", with each new variant adding - distinct architectural features and incompatibilities. - - The register state for the 18b PDP's is: - - all AC<0:17> accumulator - all MQ<0:17> multiplier-quotient - all L link flag - all PC<0:x> program counter - all IORS I/O status register - PDP-7, PDP-9 EXTM extend mode - PDP-15 BANKM bank mode - PDP-7 USMD trap mode - PDP-9, PDP-15 USMD user mode - PDP-9, PDP-15 BR bounds register - PDP-15 RR relocation register - PDP-15 XVM MMR memory management register - PDP-15 XR index register - PDP-15 LR limit register -*/ - -/* The PDP-4, PDP-7, and PDP-9 have five instruction formats: memory - reference, load immediate, I/O transfer, EAE, and operate. The PDP-15 - adds a sixth, index operate, and a seventh, floating point. The memory - reference format for the PDP-4, PDP-7, and PDP-9, and for the PDP-15 - in bank mode, is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op |in| address | memory reference - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The PDP-15 in page mode trades an address bit for indexing capability: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op |in| X| address | memory reference - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <0:3> mnemonic action - - 00 CAL JMS with MA = 20 - 04 DAC M[MA] = AC - 10 JMS M[MA] = L'mem'user'PC, PC = MA + 1 - 14 DZM M[MA] = 0 - 20 LAC AC = M[MA] - 24 XOR AC = AC ^ M[MA] - 30 ADD L'AC = AC + M[MA] one's complement - 34 TAD L'AC = AC + M[MA] - 40 XCT M[MA] is executed as an instruction - 44 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0 - 50 AND AC = AC & M[MA] - 54 SAD skip if AC != M[MA] - 60 JMP PC = MA - - On the PDP-4, PDP-7, and PDP-9, and the PDP-15 in bank mode, memory - reference instructions can access an address space of 32K words. The - address space is divided into four 8K word fields. An instruction can - directly address, via its 13b address, the entire current field. On the - PDP-4, PDP-7, and PDP-9, if extend mode is off, indirect addresses access - the current field; if on (or a PDP-15), they can access all 32K. - - On the PDP-15 in page mode, memory reference instructions can access - an address space of 128K words. The address is divided into four 32K - word blocks, each of which consists of eight 4K pages. An instruction - can directly address, via its 12b address, the current page. Indirect - addresses can access the current block. Indexed and autoincrement - addresses can access all 128K. - - On the PDP-4 and PDP-7, if an indirect address in in locations 00010- - 00017 of any field, the indirect address is incremented and rewritten - to memory before use. On the PDP-9 and PDP-15, only locations 00010- - 00017 of field zero autoincrement; special logic will redirect indirect - references to 00010-00017 to field zero, even if (on the PDP-9) extend - mode is off. -*/ - -/* The EAE format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 0 1| | | | | | | | | | | | | | | EAE - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | | | | | | | | | | | - | | | | | | | | | | | | | +- or SC (3) - | | | | | | | | | | | | +---- or MQ (3) - | | | | | | | | | | | +------- compl MQ (3) - | | | | | | | | \______________/ - | | | | | | | | | - | | | | | \_____/ +--------- shift count - | | | | | | - | | | | | +---------------------- EAE command (3) - | | | | +---------------------------- clear AC (2) - | | | +------------------------------- or AC (2) - | | +---------------------------------- load EAE sign (1) - | +------------------------------------- clear MQ (1) - +---------------------------------------- load link (1) - - The I/O transfer format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 1 0 0 0| device | sdv |cl| pulse | I/O transfer - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The IO transfer instruction sends the the specified pulse to the - specified I/O device and sub-device. The I/O device may take data - from the AC, return data to the AC, initiate or cancel operations, - or skip on status. On the PDP-4, PDP-7, and PDP-9, bits <4:5> - were designated as subdevice bits but were never used; the PDP-15 - requires them to be zero. - - On the PDP-15, the floating point format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 1 0 0 1| subopcode | floating point - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - Indirection is always single level. -*/ - -/* On the PDP-15, the index operate format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 1 0 1| subopcode | immediate | index operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The index operate instructions provide various operations on the - index and limit registers. - - The operate format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 1 1 0| | | | | | | | | | | | | | operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | | | | | | | | | | - | | | | | | | | | | | | +- CMA (3) - | | | | | | | | | | | +---- CML (3) - | | | | | | | | | | +------- OAS (3) - | | | | | | | | | +---------- RAL (3) - | | | | | | | | +------------- RAR (3) - | | | | | | | +---------------- HLT (4) - | | | | | | +------------------- SMA (1) - | | | | | +---------------------- SZA (1) - | | | | +------------------------- SNL (1) - | | | +---------------------------- invert skip (1) - | | +------------------------------- rotate twice (2) - | +---------------------------------- CLL (2) - +------------------------------------- CLA (2) - - The operate instruction can be microprogrammed to perform operations - on the AC and link. - - The load immediate format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 1 1 1| immediate | LAW - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <0:4> mnemonic action - - 76 LAW AC = IR -*/ - -/* This routine is the instruction decode routine for the 18b PDP's. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - breakpoint encountered - unimplemented instruction and STOP_INST flag set - nested XCT's - I/O error in I/O simulator - - 2. Interrupts. Interrupt requests are maintained in the int_hwre - array. int_hwre[0:3] corresponds to API levels 0-3; int_hwre[4] - holds PI requests. - - 3. Arithmetic. The 18b PDP's implements both 1's and 2's complement - arithmetic for signed numbers. In 1's complement arithmetic, a - negative number is represented by the complement (XOR 0777777) of - its absolute value. Addition of 1's complement numbers requires - propagating the carry out of the high order bit back to the low - order bit. - - 4. Adding I/O devices. Three modules must be modified: - - pdp18b_defs.h add interrupt request definition - pdp18b_sys.c add sim_devices table entry -*/ - -#include "pdp18b_defs.h" - -#define SEXT(x) ((int32) (((x) & SIGN)? (x) | ~DMASK: (x) & DMASK)) - -#define UNIT_V_NOEAE (UNIT_V_UF + 0) /* EAE absent */ -#define UNIT_V_NOAPI (UNIT_V_UF + 1) /* API absent */ -#define UNIT_V_PROT (UNIT_V_UF + 2) /* protection */ -#define UNIT_V_RELOC (UNIT_V_UF + 3) /* relocation */ -#define UNIT_V_XVM (UNIT_V_UF + 4) /* XVM */ -#define UNIT_V_MSIZE (UNIT_V_UF + 5) /* dummy mask */ -#define UNIT_NOEAE (1 << UNIT_V_NOEAE) -#define UNIT_NOAPI (1 << UNIT_V_NOAPI) -#define UNIT_PROT (1 << UNIT_V_PROT) -#define UNIT_RELOC (1 << UNIT_V_RELOC) -#define UNIT_XVM (1 << UNIT_V_XVM) -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -#define HIST_SIZE 4096 -#define HIST_API 0x40000000 -#define HIST_PI 0x20000000 -#define HIST_M_LVL 0x3F -#define HIST_V_LVL 6 -struct InstHistory { - int32 pc; - int32 ir; - int32 ir1; - int32 lac; - int32 mq; }; - -#define XVM (cpu_unit.flags & UNIT_XVM) -#define RELOC (cpu_unit.flags & UNIT_RELOC) -#define PROT (cpu_unit.flags & UNIT_PROT) - -#if defined (PDP4) -#define EAE_DFLT UNIT_NOEAE -#else -#define EAE_DFLT 0 -#endif -#if defined (PDP4) || defined (PDP7) -#define API_DFLT UNIT_NOAPI -#define PROT_DFLT 0 -#define ASW_DFLT 017763 -#else -#define API_DFLT UNIT_NOAPI /* for now */ -#define PROT_DFLT UNIT_PROT -#define ASW_DFLT 017720 -#endif - -int32 M[MAXMEMSIZE] = { 0 }; /* memory */ -int32 LAC = 0; /* link'AC */ -int32 MQ = 0; /* MQ */ -int32 PC = 0; /* PC */ -int32 iors = 0; /* IORS */ -int32 ion = 0; /* int on */ -int32 ion_defer = 0; /* int defer */ -int32 ion_inh = 0; /* int inhibit */ -int32 int_pend = 0; /* int pending */ -int32 int_hwre[API_HLVL+1] = { 0 }; /* int requests */ -int32 api_enb = 0; /* API enable */ -int32 api_req = 0; /* API requests */ -int32 api_act = 0; /* API active */ -int32 memm = 0; /* mem mode */ -#if defined (PDP15) -int32 memm_init = 1; /* mem init */ -#else -int32 memm_init = 0; -#endif -int32 usmd = 0; /* user mode */ -int32 usmd_buf = 0; /* user mode buffer */ -int32 usmd_defer = 0; /* user mode defer */ -int32 trap_pending = 0; /* trap pending */ -int32 emir_pending = 0; /* emir pending */ -int32 rest_pending = 0; /* restore pending */ -int32 BR = 0; /* mem mgt bounds */ -int32 RR = 0; /* mem mgt reloc */ -int32 MMR = 0; /* XVM mem mgt */ -int32 nexm = 0; /* nx mem flag */ -int32 prvn = 0; /* priv viol flag */ -int32 SC = 0; /* shift count */ -int32 eae_ac_sign = 0; /* EAE AC sign */ -int32 SR = 0; /* switch register */ -int32 ASW = ASW_DFLT; /* address switches */ -int32 XR = 0; /* index register */ -int32 LR = 0; /* limit register */ -int32 stop_inst = 0; /* stop on rsrv inst */ -int32 xct_max = 16; /* nested XCT limit */ -#if defined (PDP15) -int32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -#else -int16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -#endif -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -int32 hst_p = 0; /* history pointer */ -int32 hst_lnt = 0; /* history length */ -static struct InstHistory hst[HIST_SIZE] = { { 0 } }; /* instruction history */ - -extern int32 sim_int_char; -extern int32 sim_interval; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern DEVICE *sim_devices[]; -extern FILE *sim_log; - -t_bool build_dev_tab (void); -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc); -void cpu_inst_hist (int32 addr, int32 inst); -void cpu_intr_hist (int32 flag, int32 lvl); -int32 upd_iors (void); -int32 api_eval (int32 *pend); -t_stat Read (int32 ma, int32 *dat, int32 cyc); -t_stat Write (int32 ma, int32 dat, int32 cyc); -t_stat Ia (int32 ma, int32 *ea, t_bool jmp); -int32 Incr_addr (int32 addr); -int32 Jms_word (int32 t); -#if defined (PDP15) -#define INDEX(i,x) if (!memm && ((i) & I_IDX)) x = ((x) + XR) & AMASK -int32 Prot15 (int32 ma, t_bool bndchk); -int32 Reloc15 (int32 ma, int32 acc); -int32 RelocXVM (int32 ma, int32 acc); -extern t_stat fp15 (int32 ir); -#else -#define INDEX(i,x) -#endif - -extern clk (int32 pulse, int32 AC); - -int32 (*dev_tab[DEV_MAX])(int32 pulse, int32 AC); /* device dispatch */ - -int32 (*dev_iors[DEV_MAX])(void); /* IORS dispatch */ - -static const int32 api_ffo[256] = { - 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -static const int32 api_vec[API_HLVL][32] = { - { ACH_PWRFL }, /* API 0 */ - { ACH_DTA, ACH_MTA, ACH_DRM, ACH_RF, ACH_RP, ACH_RB }, /* API 1 */ - { ACH_PTR, ACH_LPT, ACH_LPT }, /* API 2 */ - { ACH_CLK, ACH_TTI1, ACH_TTO1 } }; /* API 3 */ - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit - cpu_reg CPU register list - cpu_mod CPU modifier list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX+UNIT_BINK+EAE_DFLT+API_DFLT+PROT_DFLT, - MAXMEMSIZE) }; - -REG cpu_reg[] = { - { ORDATA (PC, PC, ADDRSIZE) }, - { ORDATA (AC, LAC, 18) }, - { FLDATA (L, LAC, 18) }, - { ORDATA (MQ, MQ, 18) }, - { ORDATA (SC, SC, 6) }, - { FLDATA (EAE_AC_SIGN, eae_ac_sign, 18) }, - { ORDATA (SR, SR, 18) }, - { ORDATA (ASW, ASW, ADDRSIZE) }, - { ORDATA (IORS, iors, 18), REG_RO }, - { BRDATA (INT, int_hwre, 8, 32, API_HLVL+1), REG_RO }, - { FLDATA (INT_PEND, int_pend, 0), REG_RO }, - { FLDATA (ION, ion, 0) }, - { ORDATA (ION_DELAY, ion_defer, 2) }, -#if defined (PDP7) - { FLDATA (TRAPM, usmd, 0) }, - { FLDATA (TRAPP, trap_pending, 0) }, - { FLDATA (EXTM, memm, 0) }, - { FLDATA (EXTM_INIT, memm_init, 0) }, - { FLDATA (EMIRP, emir_pending, 0) }, -#endif -#if defined (PDP9) - { FLDATA (APIENB, api_enb, 0) }, - { ORDATA (APIREQ, api_req, 8) }, - { ORDATA (APIACT, api_act, 8) }, - { ORDATA (BR, BR, ADDRSIZE) }, - { FLDATA (USMD, usmd, 0) }, - { FLDATA (USMDBUF, usmd_buf, 0) }, - { FLDATA (USMDDEF, usmd_defer, 0) }, - { FLDATA (NEXM, nexm, 0) }, - { FLDATA (PRVN, prvn, 0) }, - { FLDATA (TRAPP, trap_pending, 0) }, - { FLDATA (EXTM, memm, 0) }, - { FLDATA (EXTM_INIT, memm_init, 0) }, - { FLDATA (EMIRP, emir_pending, 0) }, - { FLDATA (RESTP, rest_pending, 0) }, - { FLDATA (PWRFL, int_hwre[API_PWRFL], INT_V_PWRFL) }, -#endif -#if defined (PDP15) - { FLDATA (ION_INH, ion_inh, 0) }, - { FLDATA (APIENB, api_enb, 0) }, - { ORDATA (APIREQ, api_req, 8) }, - { ORDATA (APIACT, api_act, 8) }, - { ORDATA (XR, XR, 18) }, - { ORDATA (LR, LR, 18) }, - { ORDATA (BR, BR, 18) }, - { ORDATA (RR, RR, 18) }, - { ORDATA (MMR, MMR, 18) }, - { FLDATA (USMD, usmd, 0) }, - { FLDATA (USMDBUF, usmd_buf, 0) }, - { FLDATA (USMDDEF, usmd_defer, 0) }, - { FLDATA (NEXM, nexm, 0) }, - { FLDATA (PRVN, prvn, 0) }, - { FLDATA (TRAPP, trap_pending, 0) }, - { FLDATA (BANKM, memm, 0) }, - { FLDATA (BANKM_INIT, memm_init, 0) }, - { FLDATA (RESTP, rest_pending, 0) }, - { FLDATA (PWRFL, int_hwre[API_PWRFL], INT_V_PWRFL) }, -#endif - { BRDATA (PCQ, pcq, 8, ADDRSIZE, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { FLDATA (STOP_INST, stop_inst, 0) }, - { DRDATA (XCT_MAX, xct_max, 8), PV_LEFT + REG_NZ }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_NOEAE, UNIT_NOEAE, "no EAE", "NOEAE", NULL }, - { UNIT_NOEAE, 0, "EAE", "EAE", NULL }, -#if defined (PDP9) || defined (PDP15) - { UNIT_NOAPI, UNIT_NOAPI, "no API", "NOAPI", NULL }, - { UNIT_NOAPI, 0, "API", "API", NULL }, - { UNIT_PROT+UNIT_RELOC+UNIT_XVM, 0, "no memory protect", - "NOPROTECT", NULL }, - { UNIT_PROT+UNIT_RELOC+UNIT_XVM, UNIT_PROT, "memory protect", - "PROTECT", NULL }, -#endif -#if defined (PDP15) - { UNIT_PROT+UNIT_RELOC+UNIT_XVM, UNIT_PROT+UNIT_RELOC, - "memory relocation", "RELOCATION", NULL }, - { UNIT_PROT+UNIT_RELOC+UNIT_XVM, UNIT_PROT+UNIT_RELOC+UNIT_XVM, - "XVM", "XVM", NULL }, -#endif -#if defined (PDP4) - { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, -#endif - { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, -#if (MAXMEMSIZE > 8192) - { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size }, - { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, - { UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size }, - { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size }, - { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size }, - { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, -#endif -#if (MAXMEMSIZE > 32768) - { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size }, - { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size }, - { UNIT_MSIZE, 81920, NULL, "80K", &cpu_set_size }, - { UNIT_MSIZE, 98304, NULL, "96K", &cpu_set_size }, - { UNIT_MSIZE, 114688, NULL, "112K", &cpu_set_size }, - { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size }, -#endif - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", "HISTORY", - &cpu_set_hist, &cpu_show_hist }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, ADDRSIZE, 1, 8, 18, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -t_stat sim_instr (void) -{ -int32 api_int, api_usmd, skp; -int32 iot_data, device, pulse; -t_stat reason; -extern UNIT clk_unit; - -if (build_dev_tab ()) return SCPE_STOP; /* build, chk tables */ -PC = PC & AMASK; /* clean variables */ -LAC = LAC & LACMASK; -MQ = MQ & DMASK; -reason = 0; -sim_rtc_init (clk_unit.wait); /* init calibration */ -if (cpu_unit.flags & UNIT_NOAPI) api_enb = api_req = api_act = 0; -api_int = api_eval (&int_pend); /* eval API */ -api_usmd = 0; /* not API user cycle */ - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ -int32 IR, MA, MB, esc, t, xct_count; -int32 link_init, fill; - -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; - api_int = api_eval (&int_pend); } /* eval API */ - -/* PDP-4 and PDP-7 traps and interrupts - - PDP-4 no trap - PDP-7 trap: extend mode forced on, M[0] = PC, PC = 2 - PDP-4, PDP-7 programmable interrupts only */ - -#if defined (PDP4) || defined (PDP7) -#if defined (PDP7) -if (trap_pending) { /* trap pending? */ - PCQ_ENTRY; /* save old PC */ - MB = Jms_word (1); /* save state */ - ion = 0; /* interrupts off */ - memm = 1; /* extend on */ - emir_pending = trap_pending = 0; /* emir, trap off */ - usmd = usmd_buf = 0; /* user mode off */ - Write (0, MB, WR); /* save in 0 */ - PC = 2; } /* fetch next from 2 */ -#endif -if (int_pend && ion && !ion_defer) { /* interrupt? */ - PCQ_ENTRY; /* save old PC */ - MB = Jms_word (usmd); /* save state */ - ion = 0; /* interrupts off */ - memm = 0; /* extend off */ - emir_pending = rest_pending = 0; /* emir, restore off */ - usmd = usmd_buf = 0; /* user mode off */ - Write (0, MB, WR); /* physical write */ - PC = 1; } /* fetch next from 1 */ - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - -#endif /* end PDP-4/PDP-7 */ - -/* PDP-9 and PDP-15 traps and interrupts - - PDP-9 trap: extend mode ???, M[0/20] = PC, PC = 0/21 - PDP-15 trap: bank mode unchanged, M[0/20] = PC, PC = 0/21 - PDP-9, PDP-15 API and program interrupts */ - -#if defined (PDP9) || defined (PDP15) -if (trap_pending) { /* trap pending? */ - PCQ_ENTRY; /* save old PC */ - MB = Jms_word (1); /* save state */ - MA = ion? 0: 020; /* save in 0/20 */ - ion = 0; /* interrupts off */ - emir_pending = rest_pending = trap_pending = 0; /* emir,rest,trap off */ - usmd = usmd_buf = 0; /* user mode off */ - Write (MA, MB, WR); /* physical write */ - PC = MA + 1; } /* fetch next */ - -if (api_int && !ion_defer) { /* API intr? */ - int32 i, lvl = api_int - 1; /* get req level */ - if (hst_lnt) cpu_intr_hist (HIST_API, lvl); /* record */ - api_act = api_act | (API_ML0 >> lvl); /* set level active */ - if (lvl >= API_HLVL) { /* software req? */ - MA = ACH_SWRE + lvl - API_HLVL; /* vec = 40:43 */ - api_req = api_req & ~(API_ML0 >> lvl); } /* remove request */ - else { - MA = 0; /* assume fails */ - for (i = 0; i < 32; i++) { /* loop hi to lo */ - if ((int_hwre[lvl] >> i) & 1) { /* int req set? */ - MA = api_vec[lvl][i]; /* get vector */ - break; } } } /* and stop */ - if (MA == 0) { /* bad channel? */ - reason = STOP_API; /* API error */ - break; } - api_int = api_eval (&int_pend); /* no API int */ - api_usmd = usmd; /* API user mode cycle */ - usmd = usmd_buf = 0; /* user mode off */ - emir_pending = rest_pending = 0; /* emir, restore off */ - xct_count = 0; - goto xct_instr; } - -if (int_pend && ion && !ion_defer && /* int pending, enabled? */ - !(api_enb && (api_act & API_MASKPI))) { /* API off or not masking PI? */ - PCQ_ENTRY; /* save old PC */ - if (hst_lnt) cpu_intr_hist (HIST_PI, 0); /* record */ - MB = Jms_word (usmd); /* save state */ - ion = 0; /* interrupts off */ -#if defined (PDP9) /* PDP-9, */ - memm = 0; /* extend off */ -#else /* PDP-15 */ - ion_defer = 2; /* free instruction */ - if (!(cpu_unit.flags & UNIT_NOAPI)) { /* API? */ - api_act = api_act | API_ML3; /* set lev 3 active */ - api_int = api_eval (&int_pend); } /* re-evaluate */ -#endif - emir_pending = rest_pending = 0; /* emir, restore off */ - usmd = usmd_buf = 0; /* user mode off */ - Write (0, MB, WR); /* physical write */ - PC = 1; } /* fetch next from 1 */ - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } -if (!usmd_defer) usmd = usmd_buf; /* no IOT? load usmd */ -else usmd_defer = 0; /* cancel defer */ - -#endif /* PDP-9/PDP-15 */ - -/* Instruction fetch and address decode */ - -xct_count = 0; /* track nested XCT's */ -MA = PC; /* fetch at PC */ -PC = Incr_addr (PC); /* increment PC */ - -xct_instr: /* label for XCT */ -if (Read (MA, &IR, FE)) continue; /* fetch instruction */ -if (hst_lnt) cpu_inst_hist (MA, IR); /* history? */ -if (ion_defer) ion_defer = ion_defer - 1; /* count down defer */ -if (sim_interval) sim_interval = sim_interval - 1; - -#if defined (PDP15) /* PDP15 */ -if (memm) MA = (MA & B_EPCMASK) | (IR & B_DAMASK); /* bank mode dir addr */ -else MA = (MA & P_EPCMASK) | (IR & P_DAMASK); /* page mode dir addr */ -#else /* others */ -MA = (MA & B_EPCMASK) | (IR & B_DAMASK); /* bank mode only */ -#endif -switch ((IR >> 13) & 037) { /* decode IR<0:4> */ - -/* LAC: opcode 20 */ - -case 011: /* LAC, indir */ - if (Ia (MA, &MA, 0)) break; -case 010: /* LAC, dir */ - INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; - LAC = (LAC & LINK) | MB; - break; - -/* DAC: opcode 04 */ - -case 003: /* DAC, indir */ - if (Ia (MA, &MA, 0)) break; -case 002: /* DAC, dir */ - INDEX (IR, MA); - Write (MA, LAC & DMASK, WR); - break; - -/* DZM: opcode 14 */ - -case 007: /* DZM, indir */ - if (Ia (MA, &MA, 0)) break; -case 006: /* DZM, direct */ - INDEX (IR, MA); - Write (MA, 0, WR); - break; - -/* AND: opcode 50 */ - -case 025: /* AND, ind */ - if (Ia (MA, &MA, 0)) break; -case 024: /* AND, dir */ - INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; - LAC = LAC & (MB | LINK); - break; - -/* XOR: opcode 24 */ - -case 013: /* XOR, ind */ - if (Ia (MA, &MA, 0)) break; -case 012: /* XOR, dir */ - INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; - LAC = LAC ^ MB; - break; - -/* ADD: opcode 30 */ - -case 015: /* ADD, indir */ - if (Ia (MA, &MA, 0)) break; -case 014: /* ADD, dir */ - INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; - t = (LAC & DMASK) + MB; - if (t > DMASK) t = (t + 1) & DMASK; /* end around carry */ - if (((~LAC ^ MB) & (LAC ^ t)) & SIGN) /* overflow? */ - LAC = LINK | t; /* set link */ - else LAC = (LAC & LINK) | t; - break; - -/* TAD: opcode 34 */ - -case 017: /* TAD, indir */ - if (Ia (MA, &MA, 0)) break; -case 016: /* TAD, dir */ - INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; - LAC = (LAC + MB) & LACMASK; - break; - -/* ISZ: opcode 44 */ - -case 023: /* ISZ, indir */ - if (Ia (MA, &MA, 0)) break; -case 022: /* ISZ, dir */ - INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; - MB = (MB + 1) & DMASK; - if (Write (MA, MB, WR)) break; - if (MB == 0) PC = Incr_addr (PC); - break; - -/* SAD: opcode 54 */ - -case 027: /* SAD, indir */ - if (Ia (MA, &MA, 0)) break; -case 026: /* SAD, dir */ - INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; - if ((LAC & DMASK) != MB) PC = Incr_addr (PC); - break; - -/* XCT: opcode 40 */ - -case 021: /* XCT, indir */ - if (Ia (MA, &MA, 0)) break; -case 020: /* XCT, dir */ - INDEX (IR, MA); - if ((api_usmd | usmd) && (xct_count != 0)) { /* chained and usmd? */ - if (usmd) prvn = trap_pending = 1; /* trap if usmd */ - break; } /* nop if api_usmd */ - if (xct_count >= xct_max) { /* too many XCT's? */ - reason = STOP_XCT; - break; } - xct_count = xct_count + 1; /* count XCT's */ -#if defined (PDP9) - ion_defer = 1; /* defer intr */ -#endif - goto xct_instr; /* go execute */ - -/* CAL: opcode 00 - api_usmd records whether usmd = 1 at start of API cycle - - On the PDP-4 and PDP-7, CAL (I) is exactly the same as JMS (I) 20 - On the PDP-9 and PDP-15, CAL clears user mode - On the PDP-9 and PDP-15 with API, CAL activates level 4 - On the PDP-15, CAL goes to absolute 20, regardless of mode */ - -case 001: case 000: /* CAL */ - t = usmd; /* save user mode */ -#if defined (PDP15) /* PDP15 */ - MA = 020; /* MA = abs 20 */ - ion_defer = 1; /* "free instruction" */ -#else /* others */ - if (memm) MA = 020; /* if ext, abs 20 */ - else MA = (PC & B_EPCMASK) | 020; /* else bank-rel 20 */ -#endif -#if defined (PDP9) || defined (PDP15) - usmd = usmd_buf = 0; /* clear user mode */ - if ((cpu_unit.flags & UNIT_NOAPI) == 0) { /* if API, act lvl 4 */ - api_act = api_act | 010; - api_int = api_eval (&int_pend); } -#endif - if (IR & I_IND) { /* indirect? */ - if (Ia (MA, &MA, 0)) break; } - PCQ_ENTRY; - MB = Jms_word (api_usmd | t); /* save state */ - Write (MA, MB, WR); - PC = Incr_addr (MA); - break; - -/* JMS: opcode 010 - api_usmd records whether usmd = 1 at start of API cycle */ - -case 005: /* JMS, indir */ - if (Ia (MA, &MA, 0)) break; -case 004: /* JMS, dir */ - INDEX (IR, MA); - PCQ_ENTRY; -#if defined (PDP15) /* PDP15 */ - if (!usmd) ion_defer = 1; /* "free instruction" */ -#endif - MB = Jms_word (api_usmd | usmd); /* save state */ - if (Write (MA, MB, WR)) break; - PC = Incr_addr (MA); - break; - -/* JMP: opcode 60 */ - -case 031: /* JMP, indir */ - if (Ia (MA, &MA, 1)) break; -case 030: /* JMP, dir */ - INDEX (IR, MA); - PCQ_ENTRY; /* save old PC */ - PC = MA; - break; - -/* OPR: opcode 74 */ - -case 037: /* OPR, indir */ - LAC = (LAC & LINK) | IR; /* LAW */ - break; - -case 036: /* OPR, dir */ - skp = 0; /* assume no skip */ - switch ((IR >> 6) & 017) { /* decode IR<8:11> */ - case 0: /* nop */ - break; - case 1: /* SMA */ - if ((LAC & SIGN) != 0) skp = 1; - break; - case 2: /* SZA */ - if ((LAC & DMASK) == 0) skp = 1; - break; - case 3: /* SZA | SMA */ - if (((LAC & DMASK) == 0) || ((LAC & SIGN) != 0)) - skp = 1; - break; - case 4: /* SNL */ - if (LAC >= LINK) skp = 1; - break; - case 5: /* SNL | SMA */ - if (LAC >= SIGN) skp = 1; - break; - case 6: /* SNL | SZA */ - if ((LAC >= LINK) || (LAC == 0)) skp = 1; - break; - case 7: /* SNL | SZA | SMA */ - if ((LAC >= SIGN) || (LAC == 0)) skp = 1; - break; - case 010: /* SKP */ - skp = 1; - break; - case 011: /* SPA */ - if ((LAC & SIGN) == 0) skp = 1; - break; - case 012: /* SNA */ - if ((LAC & DMASK) != 0) skp = 1; - break; - case 013: /* SNA & SPA */ - if (((LAC & DMASK) != 0) && ((LAC & SIGN) == 0)) - skp = 1; - break; - case 014: /* SZL */ - if (LAC < LINK) skp = 1; - break; - case 015: /* SZL & SPA */ - if (LAC < SIGN) skp = 1; - break; - case 016: /* SZL & SNA */ - if ((LAC < LINK) && (LAC != 0)) skp = 1; - break; - case 017: /* SZL & SNA & SPA */ - if ((LAC < SIGN) && (LAC != 0)) skp = 1; - break; } /* end switch skips */ - -/* OPR, continued */ - - switch (((IR >> 9) & 014) | (IR & 03)) { /* IR<5:6,16:17> */ - case 0: /* NOP */ - break; - case 1: /* CMA */ - LAC = LAC ^ DMASK; - break; - case 2: /* CML */ - LAC = LAC ^ LINK; - break; - case 3: /* CML CMA */ - LAC = LAC ^ LACMASK; - break; - case 4: /* CLL */ - LAC = LAC & DMASK; - break; - case 5: /* CLL CMA */ - LAC = (LAC & DMASK) ^ DMASK; - break; - case 6: /* CLL CML = STL */ - LAC = LAC | LINK; - break; - case 7: /* CLL CML CMA */ - LAC = (LAC | LINK) ^ DMASK; - break; - case 010: /* CLA */ - LAC = LAC & LINK; - break; - case 011: /* CLA CMA = STA */ - LAC = LAC | DMASK; - break; - case 012: /* CLA CML */ - LAC = (LAC & LINK) ^ LINK; - break; - case 013: /* CLA CML CMA */ - LAC = (LAC | DMASK) ^ LINK; - break; - case 014: /* CLA CLL */ - LAC = 0; - break; - case 015: /* CLA CLL CMA */ - LAC = DMASK; - break; - case 016: /* CLA CLL CML */ - LAC = LINK; - break; - case 017: /* CLA CLL CML CMA */ - LAC = LACMASK; - break; } /* end decode */ - -/* OPR, continued */ - - if (IR & 0000004) { /* OAS */ -#if defined (PDP9) || defined (PDP15) - if (usmd) prvn = trap_pending = 1; /* trap if usmd */ - else if (!api_usmd) /* nop if api_usmd */ -#endif - LAC = LAC | SR; } - - switch (((IR >> 8) & 04) | ((IR >> 3) & 03)) { /* decode IR<7,13:14> */ - case 1: /* RAL */ - LAC = ((LAC << 1) | (LAC >> 18)) & LACMASK; - break; - case 2: /* RAR */ - LAC = ((LAC >> 1) | (LAC << 18)) & LACMASK; - break; - case 3: /* RAL RAR */ -#if defined (PDP15) /* PDP-15 */ - LAC = (LAC + 1) & LACMASK; /* IAC */ -#else /* PDP-4,-7,-9 */ - reason = stop_inst; /* undefined */ -#endif - break; - case 5: /* RTL */ - LAC = ((LAC << 2) | (LAC >> 17)) & LACMASK; - break; - case 6: /* RTR */ - LAC = ((LAC >> 2) | (LAC << 17)) & LACMASK; - break; - case 7: /* RTL RTR */ -#if defined (PDP15) /* PDP-15 */ - LAC = ((LAC >> 9) & 0777) | ((LAC & 0777) << 9) | - (LAC & LINK); /* BSW */ -#else /* PDP-4,-7,-9 */ - reason = stop_inst; /* undefined */ -#endif - break; } /* end switch rotate */ - - if (IR & 0000040) { /* HLT */ - if (usmd) prvn = trap_pending = 1; /* trap if usmd */ - else if (!api_usmd) reason = STOP_HALT; } /* nop if api_usmd */ - if (skp) PC = Incr_addr (PC); /* if skip, inc PC */ - break; /* end OPR */ - -/* EAE: opcode 64 - - The EAE is microprogrammed to execute variable length signed and - unsigned shift, multiply, divide, and normalize. Most commands are - controlled by a six bit step counter (SC). In the hardware, the step - counter is complemented on load and then counted up to zero; timing - guarantees an initial increment, which completes the two's complement - load. In the simulator, the SC is loaded normally and then counted - down to zero; the read SC command compensates. */ - -case 033: case 032: /* EAE */ - if (cpu_unit.flags & UNIT_NOEAE) break; /* disabled? */ - if (IR & 0020000) /* IR<4>? AC0 to L */ - LAC = ((LAC << 1) & LINK) | (LAC & DMASK); - if (IR & 0010000) MQ = 0; /* IR<5>? clear MQ */ - if ((IR & 0004000) && (LAC & SIGN)) /* IR<6> and minus? */ - eae_ac_sign = LINK; /* set eae_ac_sign */ - else eae_ac_sign = 0; /* if not, unsigned */ - if (IR & 0002000) MQ = (MQ | LAC) & DMASK; /* IR<7>? or AC */ - else if (eae_ac_sign) LAC = LAC ^ DMASK; /* if not, |AC| */ - if (IR & 0001000) LAC = LAC & LINK; /* IR<8>? clear AC */ - link_init = LAC & LINK; /* link temporary */ - fill = link_init? DMASK: 0; /* fill = link */ - esc = IR & 077; /* get eff SC */ - - switch ((IR >> 6) & 07) { /* case on IR<9:11> */ - case 0: /* setup */ - if (IR & 04) MQ = MQ ^ DMASK; /* IR<15>? ~MQ */ - if (IR & 02) LAC = LAC | MQ; /* IR<16>? or MQ */ - if (IR & 01) LAC = LAC | ((-SC) & 077); /* IR<17>? or SC */ - break; - -/* EAE, continued - - Multiply uses a shift and add algorithm. The PDP-15, unlike prior - implementations, factors IR<6> (signed multiply) into the calculation - of the result sign. */ - - case 1: /* multiply */ - if (Read (PC, &MB, FE)) break; /* get next word */ - PC = Incr_addr (PC); /* increment PC */ - if (eae_ac_sign) MQ = MQ ^ DMASK; /* EAE AC sign? ~MQ */ - LAC = LAC & DMASK; /* clear link */ - SC = esc; /* init SC */ - do { /* loop */ - if (MQ & 1) LAC = LAC + MB; /* MQ<17>? add */ - MQ = (MQ >> 1) | ((LAC & 1) << 17); - LAC = LAC >> 1; /* shift AC'MQ right */ - SC = (SC - 1) & 077; } /* decrement SC */ - while (SC != 0); /* until SC = 0 */ -#if defined (PDP15) - if ((IR & 0004000) && (eae_ac_sign ^ link_init)) { -#else - if (eae_ac_sign ^ link_init) { /* result negative? */ -#endif - LAC = LAC ^ DMASK; - MQ = MQ ^ DMASK; } - break; - -/* Divide uses a non-restoring divide. Divide uses a subtract and shift - algorithm. The quotient is generated in true form. The PDP-15, unlike - prior implementations, factors IR<6> (signed multiply) into the calculation - of the result sign.*/ - - case 3: /* divide */ - if (Read (PC, &MB, FE)) break; /* get next word */ - PC = Incr_addr (PC); /* increment PC */ - if (eae_ac_sign) MQ = MQ ^ DMASK; /* EAE AC sign? ~MQ */ - if ((LAC & DMASK) >= MB) { /* overflow? */ - LAC = (LAC - MB) | LINK; /* set link */ - break; } - LAC = LAC & DMASK; /* clear link */ - t = 0; /* init loop */ - SC = esc; /* init SC */ - do { /* loop */ - if (t) LAC = (LAC + MB) & LACMASK; - else LAC = (LAC - MB) & LACMASK; - t = (LAC >> 18) & 1; /* quotient bit */ - if (SC > 1) LAC = /* skip if last */ - ((LAC << 1) | (MQ >> 17)) & LACMASK; - MQ = ((MQ << 1) | (t ^ 1)) & DMASK; /* shift in quo bit */ - SC = (SC - 1) & 077; } /* decrement SC */ - while (SC != 0); /* until SC = 0 */ - if (t) LAC = (LAC + MB) & LACMASK; - if (eae_ac_sign) LAC = LAC ^ DMASK; /* sgn rem = sgn divd */ -#if defined (PDP15) - if ((IR & 0004000) && (eae_ac_sign ^ link_init)) -#else - if (eae_ac_sign ^ link_init) /* result negative? */ -#endif - MQ = MQ ^ DMASK; - break; - -/* EAE, continued - - EAE shifts, whether left or right, fill from the link. If the - operand sign has been copied to the link, this provides correct - sign extension for one's complement numbers. */ - - case 4: /* normalize */ -#if defined (PDP15) - if (!usmd) ion_defer = 2; /* free instructions */ -#endif - for (SC = esc; ((LAC & SIGN) == ((LAC << 1) & SIGN)); ) { - LAC = (LAC << 1) | ((MQ >> 17) & 1); - MQ = (MQ << 1) | (link_init >> 18); - SC = (SC - 1) & 077; - if (SC == 0) break; } - LAC = link_init | (LAC & DMASK); /* trim AC, restore L */ - MQ = MQ & DMASK; /* trim MQ */ - SC = SC & 077; /* trim SC */ - break; - - case 5: /* long right shift */ - if (esc < 18) { - MQ = ((LAC << (18 - esc)) | (MQ >> esc)) & DMASK; - LAC = ((fill << (18 - esc)) | (LAC >> esc)) & LACMASK; } - else { - if (esc < 36) MQ = - ((fill << (36 - esc)) | (LAC >> (esc - 18))) & DMASK; - else MQ = fill; - LAC = link_init | fill; } - SC = 0; /* clear step count */ - break; - - case 6: /* long left shift */ - if (esc < 18) { - LAC = link_init | - (((LAC << esc) | (MQ >> (18 - esc))) & DMASK); - MQ = ((MQ << esc) | (fill >> (18 - esc))) & DMASK; } - else { - if (esc < 36) LAC = link_init | - (((MQ << (esc - 18)) | (fill >> (36 - esc))) & DMASK); - else LAC = link_init | fill; - MQ = fill; } - SC = 0; /* clear step count */ - break; - - case 7: /* AC left shift */ - if (esc < 18) LAC = link_init | - (((LAC << esc) | (fill >> (18 - esc))) & DMASK); - else LAC = link_init | fill; - SC = 0; /* clear step count */ - break; } /* end switch IR */ - break; /* end case EAE */ - -/* PDP-15 index operates: opcode 72 */ - -case 035: /* index operates */ -#if defined (PDP15) - t = (IR & 0400)? IR | 0777000: IR & 0377; /* sext immediate */ - switch ((IR >> 9) & 017) { /* case on IR<5:8> */ - case 000: /* AAS */ - LAC = (LAC & LINK) | ((LAC + t) & DMASK); - if (SEXT (LAC & DMASK) >= SEXT (LR)) - PC = Incr_addr (PC); - case 001: /* PAX */ - XR = LAC & DMASK; - break; - case 002: /* PAL */ - LR = LAC & DMASK; - break; - case 003: /* AAC */ - LAC = (LAC & LINK) | ((LAC + t) & DMASK); - break; - case 004: /* PXA */ - LAC = (LAC & LINK) | XR; - break; - case 005: /* AXS */ - XR = (XR + t) & DMASK; - if (SEXT (XR) >= SEXT (LR)) PC = Incr_addr (PC); - break; - case 006: /* PXL */ - LR = XR; - break; - case 010: /* PLA */ - LAC = (LAC & LINK) | LR; - break; - case 011: /* PLX */ - XR = LR; - break; - case 014: /* CLAC */ - LAC = LAC & LINK; - break; - case 015: /* CLX */ - XR = 0; - break; - case 016: /* CLLR */ - LR = 0; - break; - case 017: /* AXR */ - XR = (XR + t) & DMASK; - break; } /* end switch IR */ - break; /* end case */ -#endif - -/* IOT: opcode 70 - - The 18b PDP's have different definitions of various control IOT's. - - IOT PDP-4 PDP-7 PDP-9 PDP-15 - - 700002 IOF IOF IOF IOF - 700022 undefined undefined undefined ORMM (XVM) - 700042 ION ION ION ION - 700024 undefined undefined undefined LDMM (XVM) - 700062 undefined ITON undefined undefined - 701701 undefined undefined MPSK MPSK - 701741 undefined undefined MPSNE MPSNE - 701702 undefined undefined MPCV MPCV - 701722 undefined undefined undefined MPRC (XVM) - 701742 undefined undefined MPEU MPEU - 701704 undefined undefined MPLD MPLD - 701724 undefined undefined undefined MPLR (KT15, XVM) - 701744 undefined undefined MPCNE MPCNE - 701764 undefined undefined undefined IPFH (XVM) - 703201 undefined undefined PFSF PFSF - 703301 undefined TTS TTS TTS - 703341 undefined SKP7 SKP7 SPCO - 703302 undefined CAF CAF CAF - 703304 undefined undefined DBK DBK - 703344 undefined undefined DBR DBR - 705501 undefined undefined SPI SPI - 705521 undefined undefined undefined ENB - 705502 undefined undefined RPL RPL - 705522 undefined undefined undefined INH - 705504 undefined undefined ISA ISA - 707701 undefined SEM SEM undefined - 707741 undefined undefined undefined SKP15 - 707761 undefined undefined undefined SBA - 707702 undefined EEM EEM undefined - 707742 undefined EMIR EMIR RES - 707762 undefined undefined undefined DBA - 707704 undefined LEM LEM undefined - 707764 undefined undefined undefined EBA */ - -case 034: /* IOT */ -#if defined (PDP15) - if (IR & 0010000) { /* floating point? */ - reason = fp15 (IR); /* process */ - break; } -#endif - if ((api_usmd | usmd) && /* user, not XVM UIOT? */ - (!XVM || !(MMR & MM_UIOT))) { - if (usmd) prvn = trap_pending = 1; /* trap if user */ - break; } /* nop if api_usmd */ - device = (IR >> 6) & 077; /* device = IR<6:11> */ - pulse = IR & 067; /* pulse = IR<12:17> */ - if (IR & 0000010) LAC = LAC & LINK; /* clear AC? */ - iot_data = LAC & DMASK; /* AC unchanged */ - -/* PDP-4 system IOT's */ - -#if defined (PDP4) - switch (device) { /* decode IR<6:11> */ - case 0: /* CPU and clock */ - if (pulse == 002) ion = 0; /* IOF */ - else if (pulse == 042) ion = ion_defer = 1; /* ION */ - else iot_data = clk (pulse, iot_data); - break; -#endif - -/* PDP-7 system IOT's */ - -#if defined (PDP7) - switch (device) { /* decode IR<6:11> */ - case 0: /* CPU and clock */ - if (pulse == 002) ion = 0; /* IOF */ - else if (pulse == 042) ion = ion_defer = 1; /* ION */ - else if (pulse == 062) /* ITON */ - usmd = usmd_buf = ion = ion_defer = 1; - else iot_data = clk (pulse, iot_data); - break; - case 033: /* CPU control */ - if ((pulse == 001) || (pulse == 041)) PC = Incr_addr (PC); - else if (pulse == 002) reset_all (1); /* CAF - skip CPU */ - break; - case 077: /* extended memory */ - if ((pulse == 001) && memm) PC = Incr_addr (PC); - else if (pulse == 002) memm = 1; /* EEM */ - else if (pulse == 042) /* EMIR */ - memm = emir_pending = 1; /* ext on, restore */ - else if (pulse == 004) memm = 0; /* LEM */ - break; -#endif - -/* PDP-9 system IOT's */ - -#if defined (PDP9) - ion_defer = 1; /* delay interrupts */ - usmd_defer = 1; /* defer load user */ - switch (device) { /* decode IR<6:11> */ - case 000: /* CPU and clock */ - if (pulse == 002) ion = 0; /* IOF */ - else if (pulse == 042) ion = 1; /* ION */ - else iot_data = clk (pulse, iot_data); - break; - case 017: /* mem protection */ - if (PROT) { /* enabled? */ - if ((pulse == 001) && prvn) PC = Incr_addr (PC); - else if ((pulse == 041) && nexm) PC = Incr_addr (PC); - else if (pulse == 002) prvn = 0; - else if (pulse == 042) usmd_buf = 1; - else if (pulse == 004) BR = LAC & BRMASK; - else if (pulse == 044) nexm = 0; } - else reason = stop_inst; - break; - case 032: /* power fail */ - if ((pulse == 001) && (TST_INT (PWRFL))) - PC = Incr_addr (PC); - break; - case 033: /* CPU control */ - if ((pulse == 001) || (pulse == 041)) PC = Incr_addr (PC); - else if (pulse == 002) { /* CAF */ - reset_all (1); /* reset all exc CPU */ - api_enb = api_req = api_act = 0; } /* reset API system */ - else if (pulse == 044) rest_pending = 1; /* DBR */ - if (((cpu_unit.flags & UNIT_NOAPI) == 0) && (pulse & 004)) { - int32 t = api_ffo[api_act & 0377]; - api_act = api_act & ~(API_ML0 >> t); } - break; - case 055: /* API control */ - if (cpu_unit.flags & UNIT_NOAPI) reason = stop_inst; - else if (pulse == 001) { /* SPI */ - if (((LAC & SIGN) && api_enb) || - ((LAC & 0377) > api_act)) - iot_data = iot_data | IOT_SKP; } - else if (pulse == 002) { /* RPL */ - iot_data = iot_data | (api_enb << 17) | - (api_req << 8) | api_act; } - else if (pulse == 004) { /* ISA */ - api_enb = (iot_data & SIGN)? 1: 0; - api_req = api_req | ((LAC >> 8) & 017); - api_act = api_act | (LAC & 0377); } - break; - case 077: /* extended memory */ - if ((pulse == 001) && memm) PC = Incr_addr (PC); - else if (pulse == 002) memm = 1; /* EEM */ - else if (pulse == 042) /* EMIR */ - memm = emir_pending = 1; /* ext on, restore */ - else if (pulse == 004) memm = 0; /* LEM */ - break; -#endif - -/* PDP-15 system IOT's - includes "re-entrancy ECO" ENB/INH as standard */ - -#if defined (PDP15) - ion_defer = 1; /* delay interrupts */ - usmd_defer = 1; /* defer load user */ - switch (device) { /* decode IR<6:11> */ - case 000: /* CPU and clock */ - if (pulse == 002) ion = 0; /* IOF */ - else if (pulse == 042) ion = 1; /* ION */ - else if (XVM && (pulse == 022)) /* ORMM/RDMM */ - iot_data = MMR; - else if (XVM && (pulse == 024)) /* LDMM */ - MMR = iot_data; - else iot_data = clk (pulse, iot_data); - break; - case 017: /* mem protection */ - if (PROT) { /* enabled? */ - t = XVM? BRMASK_XVM: BRMASK; - if ((pulse == 001) && prvn) PC = Incr_addr (PC); - else if ((pulse == 041) && nexm) PC = Incr_addr (PC); - else if (pulse == 002) prvn = 0; - else if (pulse == 042) usmd_buf = 1; - else if (pulse == 004) BR = LAC & t; - else if (RELOC && (pulse == 024)) RR = LAC & t; - else if (pulse == 044) nexm = 0; } - else reason = stop_inst; - break; - case 032: /* power fail */ - if ((pulse == 001) && (TST_INT (PWRFL))) - PC = Incr_addr (PC); - break; - case 033: /* CPU control */ - if ((pulse == 001) || (pulse == 041)) PC = Incr_addr (PC); - else if (pulse == 002) { /* CAF */ - reset_all (2); /* reset all exc CPU, FP15 */ - api_enb = api_req = api_act = 0; } /* reset API system */ - else if (pulse == 044) rest_pending = 1; /* DBR */ - if (((cpu_unit.flags & UNIT_NOAPI) == 0) && (pulse & 004)) { - int32 t = api_ffo[api_act & 0377]; - api_act = api_act & ~(API_ML0 >> t); } - break; - case 055: /* API control */ - if (cpu_unit.flags & UNIT_NOAPI) reason = stop_inst; - else if (pulse == 001) { /* SPI */ - if (((LAC & SIGN) && api_enb) || - ((LAC & 0377) > api_act)) - iot_data = iot_data | IOT_SKP; } - else if (pulse == 002) { /* RPL */ - iot_data = iot_data | (api_enb << 17) | - (api_req << 8) | api_act; } - else if (pulse == 004) { /* ISA */ - api_enb = (iot_data & SIGN)? 1: 0; - api_req = api_req | ((LAC >> 8) & 017); - api_act = api_act | (LAC & 0377); } - else if (pulse == 021) ion_inh = 0; /* ENB */ - else if (pulse == 022) ion_inh = 1; /* INH */ - break; - case 077: /* bank addressing */ - if ((pulse == 041) || ((pulse == 061) && memm)) - PC = Incr_addr (PC); /* SKP15, SBA */ - else if (pulse == 042) rest_pending = 1; /* RES */ - else if (pulse == 062) memm = 0; /* DBA */ - else if (pulse == 064) memm = 1; /* EBA */ - break; -#endif - -/* IOT, continued */ - - default: /* devices */ - if (dev_tab[device]) /* defined? */ - iot_data = dev_tab[device] (pulse, iot_data); - else reason = stop_inst; /* stop on flag */ - break; } /* end switch device */ - LAC = LAC | (iot_data & DMASK); - if (iot_data & IOT_SKP) PC = Incr_addr (PC); - if (iot_data >= IOT_REASON) reason = iot_data >> IOT_V_REASON; - api_int = api_eval (&int_pend); /* eval API */ - break; /* end case IOT */ - } /* end switch opcode */ -api_usmd = 0; /* API cycle over */ -} /* end while */ - -/* Simulation halted */ - -iors = upd_iors (); /* get IORS */ -pcq_r->qptr = pcq_p; /* update pc q ptr */ -return reason; -} - -/* Evaluate API */ - -int32 api_eval (int32 *pend) -{ -int32 i, hi; - -*pend = 0; /* assume no intr */ -#if defined (PDP15) /* PDP15 only */ -if (ion_inh) return 0; /* inhibited? */ -#endif -for (i = 0; i < API_HLVL+1; i++) { /* any intr? */ - if (int_hwre[i]) *pend = 1; } -if (api_enb == 0) return 0; /* off? no req */ -api_req = api_req & ~(API_ML0|API_ML1|API_ML2|API_ML3); /* clr req<0:3> */ -for (i = 0; i < API_HLVL; i++) { /* loop thru levels */ - if (int_hwre[i]) /* req on level? */ - api_req = api_req | (API_ML0 >> i); } /* set api req */ -hi = api_ffo[api_req & 0377]; /* find hi req */ -if (hi < api_ffo[api_act & 0377]) return (hi + 1); -return 0; -} - -/* Process IORS instruction */ - -int32 upd_iors (void) -{ -int32 d, p; - -d = (ion? IOS_ION: 0); /* ION */ -for (p = 0; dev_iors[p] != NULL; p++) { /* loop thru table */ - d = d | dev_iors[p](); } /* OR in results */ -return d; -} - -#if defined (PDP4) || defined (PDP7) - -/* Read, write, indirect, increment routines - On the PDP-4 and PDP-7, - There are autoincrement locations in every field. If a field - does not exist, it is impossible to generate an - autoincrement reference (all instructions are CAL). - Indirect addressing range is determined by extend mode. - JMP I with EMIR pending can only clear extend - There is no memory protection, nxm reads zero and ignores writes. */ - -t_stat Read (int32 ma, int32 *dat, int32 cyc) -{ -ma = ma & AMASK; -if (MEM_ADDR_OK (ma)) *dat = M[ma] & DMASK; -else *dat = 0; -return MM_OK; -} - -t_stat Write (int32 ma, int32 dat, int32 cyc) -{ -ma = ma & AMASK; -if (MEM_ADDR_OK (ma)) M[ma] = dat & DMASK; -return MM_OK; -} - -t_stat Ia (int32 ma, int32 *ea, t_bool jmp) -{ -int32 t; -t_stat sta = MM_OK; - -if ((ma & B_DAMASK) == 010) { /* autoindex? */ - Read (ma, &t, DF); /* add 1 before use */ - t = (t + 1) & DMASK; - sta = Write (ma, t, DF); } -else sta = Read (ma, &t, DF); /* fetch indirect */ -if (jmp) { /* jmp i? */ - if (emir_pending && (((t >> 16) & 1) == 0)) memm = 0; - emir_pending = rest_pending = 0; } -if (memm) *ea = t & IAMASK; /* extend? 15b ia */ -else *ea = (ma & B_EPCMASK) | (t & B_DAMASK); /* bank-rel ia */ -return sta; -} - -int32 Incr_addr (int32 ma) -{ -return ((ma & B_EPCMASK) | ((ma + 1) & B_DAMASK)); -} - -int32 Jms_word (int32 t) -{ -return (((LAC & LINK) >> 1) | ((memm & 1) << 16) | - ((t & 1) << 15) | (PC & IAMASK)); -} - -#endif - -#if defined (PDP9) - -/* Read, write, indirect, increment routines - On the PDP-9, - The autoincrement registers are in field zero only. Regardless - of extend mode, indirect addressing through 00010-00017 - will access absolute locations 00010-00017. - Indirect addressing range is determined by extend mode. If - extend mode is off, and autoincrementing is used, the - resolved address is in bank 0 (KG09B maintenance manual). - JMP I with EMIR pending can only clear extend - JMP I with DBK pending restores L, user mode, extend mode - Memory protection is implemented for foreground/background operation. */ - -t_stat Read (int32 ma, int32 *dat, int32 cyc) -{ -ma = ma & AMASK; -if (usmd) { /* user mode? */ - if (!MEM_ADDR_OK (ma)) { /* nxm? */ - nexm = prvn = trap_pending = 1; /* set flags, trap */ - *dat = 0; - return MM_ERR; } - if ((cyc != DF) && (ma < BR)) { /* boundary viol? */ - prvn = trap_pending = 1; /* set flag, trap */ - *dat = 0; - return MM_ERR; } } -if (MEM_ADDR_OK (ma)) *dat = M[ma] & DMASK; /* valid mem? ok */ -else { *dat = 0; /* set flag, no trap */ - nexm = 1; } -return MM_OK; -} - -t_stat Write (int32 ma, int32 dat, int32 cyc) -{ -ma = ma & AMASK; -if (usmd) { - if (!MEM_ADDR_OK (ma)) { /* nxm? */ - nexm = prvn = trap_pending = 1; /* set flags, trap */ - return MM_ERR; } - if ((cyc != DF) && (ma < BR)) { /* boundary viol? */ - prvn = trap_pending = 1; /* set flag, trap */ - return MM_ERR; } } -if (MEM_ADDR_OK (ma)) M[ma] = dat & DMASK; /* valid mem? ok */ -else nexm = 1; /* set flag, no trap */ -return MM_OK; -} - -t_stat Ia (int32 ma, int32 *ea, t_bool jmp) -{ -int32 t; -t_stat sta = MM_OK; - -if ((ma & B_DAMASK) == 010) { /* autoindex? */ - ma = ma & 017; /* always in bank 0 */ - Read (ma, &t, DF); /* +1 before use */ - t = (t + 1) & DMASK; - sta = Write (ma, t, DF); } -else sta = Read (ma, &t, DF); -if (jmp) { /* jmp i? */ - if (emir_pending && (((t >> 16) & 1) == 0)) memm = 0; - if (rest_pending) { /* restore pending? */ - LAC = ((t << 1) & LINK) | (LAC & DMASK); /* restore L */ - memm = (t >> 16) & 1; /* restore extend */ - usmd = usmd_buf = (t >> 15) & 1; } /* restore user */ - emir_pending = rest_pending = 0; } -if (memm) *ea = t & IAMASK; /* extend? 15b ia */ -else *ea = (ma & B_EPCMASK) | (t & B_DAMASK); /* bank-rel ia */ -return sta; -} - -int32 Incr_addr (int32 ma) -{ -return ((ma & B_EPCMASK) | ((ma + 1) & B_DAMASK)); -} - -int32 Jms_word (int32 t) -{ -return (((LAC & LINK) >> 1) | ((memm & 1) << 16) | - ((t & 1) << 15) | (PC & IAMASK)); -} - -#endif - -#if defined (PDP15) - -/* Read, write, indirect, increment routines - On the PDP-15, - The autoincrement registers are in page zero only. Regardless - of bank mode, indirect addressing through 00010-00017 - will access absolute locations 00010-00017. - Indirect addressing range is determined by autoincrementing. - Any indirect can trigger a restore. - Memory protection is implemented for foreground/background operation. */ - -t_stat Read (int32 ma, int32 *dat, int32 cyc) -{ -int32 pa; - -if (usmd) { /* user mode? */ - if (XVM) pa = RelocXVM (ma, REL_R); /* XVM relocation? */ - else if (RELOC) pa = Reloc15 (ma, REL_R); /* PDP-15 relocation? */ - else pa = Prot15 (ma, cyc == FE); /* just protection */ - if (pa < 0) { /* error? */ - *dat = 0; - return MM_ERR; } } -else pa = ma & AMASK; /* no prot or reloc */ -if (MEM_ADDR_OK (pa)) *dat = M[pa] & DMASK; /* valid mem? ok */ -else { nexm = 1; /* set flag, no trap */ - *dat = 0; } -return MM_OK; -} - -t_stat Write (int32 ma, int32 dat, int32 cyc) -{ -int32 pa; - -if (usmd) { /* user mode? */ - if (XVM) pa = RelocXVM (ma, REL_W); /* XVM relocation? */ - else if (RELOC) pa = Reloc15 (ma, REL_W); /* PDP-15 relocation? */ - else pa = Prot15 (ma, cyc != DF); /* just protection */ - if (pa < 0) return MM_ERR; } /* error? */ -else pa = ma & AMASK; /* no prot or reloc */ -if (MEM_ADDR_OK (pa)) M[pa] = dat & DMASK; /* valid mem? ok */ -else nexm = 1; /* set flag, no trap */ -return MM_OK; -} - -/* XVM will do 18b defers if user_mode and G_Mode != 0 */ - -t_stat Ia (int32 ma, int32 *ea, t_bool jmp) -{ -int32 t; -int32 damask = memm? B_DAMASK: P_DAMASK; -t_stat sta = MM_OK; - -if ((ma & damask & ~07) == 010) { /* autoincrement? */ - ma = ma & 017; /* always in bank 0 */ - Read (ma, &t, DF); /* +1 before use */ - t = (t + 1) & DMASK; - sta = Write (ma, t, DF); } -else sta = Read (ma, &t, DF); -if (rest_pending) { /* restore pending? */ - LAC = ((t << 1) & LINK) | (LAC & DMASK); /* restore L */ - memm = (t >> 16) & 1; /* restore bank */ - usmd = usmd_buf = (t >> 15) & 1; /* restore user */ - emir_pending = rest_pending = 0; } -if (usmd && XVM && (MMR & MM_GM)) *ea = t; /* XVM G_mode? */ -else if ((ma & damask & ~07) == 010) *ea = t & AMASK; /* autoindex? */ -else *ea = (PC & BLKMASK) | (t & IAMASK); /* within 32K */ -return sta; -} - -t_stat Incr_addr (int32 ma) -{ -if (memm) return ((ma & B_EPCMASK) | ((ma + 1) & B_DAMASK)); -return ((ma & P_EPCMASK) | ((ma + 1) & P_DAMASK)); -} - -/* XVM will store all 18b of PC if user mode and G_mode != 0 */ - -int32 Jms_word (int32 t) -{ -if (usmd && XVM && (MMR & MM_GM)) return PC; -return (((LAC & LINK) >> 1) | ((memm & 1) << 16) | - ((t & 1) << 15) | (PC & IAMASK)); -} - -/* PDP-15 protection (KM15 option) */ - -int32 Prot15 (int32 ma, t_bool bndchk) -{ -ma = ma & AMASK; /* 17b addressing */ -if (!MEM_ADDR_OK (ma)) { /* nxm? */ - nexm = prvn = trap_pending = 1; /* set flags, trap */ - return -1; } -if (bndchk && (ma < BR)) { /* boundary viol? */ - prvn = trap_pending = 1; /* set flag, trap */ - return -1; } -return ma; /* no relocation */ -} - -/* PDP-15 relocation and protection (KT15 option) */ - -int32 Reloc15 (int32 ma, int32 rc) -{ -int32 pa; - -ma = ma & AMASK; /* 17b addressing */ -if (ma >= (BR | 0377)) { /* boundary viol? */ - if (rc != REL_C) prvn = trap_pending = 1; /* set flag, trap */ - return -1; } -pa = (ma + RR) & AMASK; /* relocate address */ -if (!MEM_ADDR_OK (pa)) { /* nxm? */ - if (rc != REL_C) nexm = prvn = trap_pending = 1; /* set flags, trap */ - return -1; } -return pa; -} - -/* XVM relocation and protection option */ - -int32 RelocXVM (int32 ma, int32 rc) -{ -int32 pa, gmode, slr; -static const int32 g_mask[4] = { MM_G_W0, MM_G_W1, MM_G_W2, MM_G_W3 }; -static const int32 g_base[4] = { MM_G_B0, MM_G_B1, MM_G_B2, MM_G_B3 }; -static const int32 slr_lnt[4] = { MM_SLR_L0, MM_SLR_L1, MM_SLR_L2, MM_SLR_L3 }; - -gmode = MM_GETGM (MMR); /* get G_mode */ -slr = MM_GETSLR (MMR); /* get segment length */ -ma = ma & g_mask[gmode]; /* mask address */ -if (MMR & MM_RDIS) pa = ma; /* reloc disabled? */ -else if ((MMR & MM_SH) && /* shared enabled and */ - (ma >= g_base[gmode]) && /* >= shared base and */ - (ma < (g_base[gmode] + slr_lnt[slr]))) { /* < shared end? */ - if (ma & 017400) { /* ESAS? */ - if ((rc == REL_W) && (MMR & MM_WP)) { /* write and protected? */ - prvn = trap_pending = 1; /* set flag, trap */ - return -1; } - pa = (((MMR & MM_SBR_MASK) << 8) + ma) & DMASK; } /* ESAS reloc */ - else pa = RR + (ma & 0377); } /* no, ISAS reloc */ -else { if (ma >= (BR | 0377)) { /* normal reloc, viol? */ - if (rc != REL_C) prvn = trap_pending = 1; /* set flag, trap */ - return -1; } - pa = (RR + ma) & DMASK; } /* relocate address */ -if (!MEM_ADDR_OK (pa)) { /* nxm? */ - if (rc != REL_C) nexm = prvn = trap_pending = 1; /* set flags, trap */ - return -1; } -return pa; -} - -#endif - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -SC = 0; -eae_ac_sign = 0; -ion = ion_defer = ion_inh = 0; -CLR_INT (PWRFL); -api_enb = api_req = api_act = 0; -BR = 0; -RR = 0; -MMR = 0; -usmd = usmd_buf = usmd_defer = 0; -memm = memm_init; -nexm = prvn = trap_pending = 0; -emir_pending = rest_pending = 0; -pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -#if defined (PDP15) -if (usmd && (sw & SWMASK ('V'))) { - if (XVM) addr = RelocXVM (addr, REL_C); - else if (RELOC) addr = Reloc15 (addr, REL_C); - if (addr < 0) return STOP_MME; } -#endif -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & DMASK; -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -#if defined (PDP15) -if (usmd && (sw & SWMASK ('V'))) { - if (XVM) addr = RelocXVM (addr, REL_C); - else if (RELOC) addr = Reloc15 (addr, REL_C); - if (addr < 0) return STOP_MME; } -#endif -if (addr >= MEMSIZE) return SCPE_NXM; -M[addr] = val & DMASK; -return SCPE_OK; -} - -/* Change memory size */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; -if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_OK; -MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; -return SCPE_OK; -} - -/* Change device number for a device */ - -t_stat set_devno (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newdev; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newdev = get_uint (cptr, 8, DEV_MAX - 1, &r); /* get new */ -if ((r != SCPE_OK) || (newdev == dibp->dev)) return r; -dibp->dev = newdev; /* store */ -return SCPE_OK; -} - -/* Show device number for a device */ - -t_stat show_devno (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -DEVICE *dptr; -DIB *dibp; - -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -fprintf (st, "devno=%02o", dibp->dev); -if (dibp->num > 1) fprintf (st, "-%2o", dibp->dev + dibp->num - 1); -return SCPE_OK; -} - -/* CPU device handler - should never get here! */ - -int32 bad_dev (int32 pulse, int32 AC) -{ -return (SCPE_IERR << IOT_V_REASON) | AC; /* broken! */ -} - -/* Build device dispatch table */ - -t_bool build_dev_tab (void) -{ -DEVICE *dptr; -DIB *dibp; -uint32 i, j, p; -static const uint8 std_dev[] = -#if defined (PDP4) - { 000 }; -#elif defined (PDP7) - { 000, 033, 077 }; -#else - { 000, 017, 033, 055, 077 }; -#endif - -for (i = 0; i < DEV_MAX; i++) { /* clr tables */ - dev_tab[i] = NULL; - dev_iors[i] = NULL; } -for (i = 0; i < ((uint32) sizeof (std_dev)); i++) /* std entries */ - dev_tab[std_dev[i]] = &bad_dev; -for (i = p = 0; (dptr = sim_devices[i]) != NULL; i++) { /* add devices */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if (dibp && !(dptr->flags & DEV_DIS)) { /* enabled? */ - if (dibp->iors) dev_iors[p++] = dibp->iors; /* if IORS, add */ - for (j = 0; j < dibp->num; j++) { /* loop thru disp */ - if (dibp->dsp[j]) { /* any dispatch? */ - if (dev_tab[dibp->dev + j]) { /* already filled? */ - printf ("%s device number conflict at %02o\n", - sim_dname (dptr), dibp->dev + j); - if (sim_log) fprintf (sim_log, - "%s device number conflict at %02o\n", - sim_dname (dptr), dibp->dev + j); - return TRUE; } - dev_tab[dibp->dev + j] = dibp->dsp[j]; /* fill */ - } /* end if dsp */ - } /* end for j */ - } /* end if enb */ - } /* end for i */ -return FALSE; -} - -/* Set history */ - -t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 i, lnt; -t_stat r; - -if (cptr == NULL) { - for (i = 0; i < HIST_SIZE; i++) hst[i].pc = 0; - return SCPE_OK; } -lnt = (int32) get_uint (cptr, 10, HIST_SIZE, &r); -if (r != SCPE_OK) return SCPE_ARG; -hst_lnt = lnt; -return SCPE_OK; -} - -/* Show history */ - -t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 l, j, k, di; -t_value sim_eval[2]; -struct InstHistory *h; -extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); - -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ -di = hst_p + HIST_SIZE - hst_lnt; /* work forward */ -for (k = 0; k < hst_lnt; k++) { /* print specified */ - h = &hst[(di++) % HIST_SIZE]; /* entry pointer */ - if (h->pc == 0) continue; /* filled in? */ - if (h->pc & (HIST_API | HIST_PI)) { /* interrupt event? */ - if (h->pc & HIST_PI) /* PI? */ - fprintf (st, "%06o PI LVL 0-4 =", h->pc & AMASK); - else fprintf (st, "%06o API %d LVL 0-4 =", h->pc & AMASK, h->mq); - for (j = API_HLVL; j >= 0; j--) - fprintf (st, " %02o", (h->ir >> (j * HIST_V_LVL)) & HIST_M_LVL); - } - else { /* instruction */ - l = (h->lac >> 18) & 1; /* link */ - fprintf (st, "%06o %o %06o %06o ", h->pc, l, h->lac & DMASK, h->mq); - sim_eval[0] = h->ir; - sim_eval[1] = h->ir1; - if ((fprint_sym (st, h->pc, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) - fprintf (st, "(undefined) %06o", h->ir); - } /* end else instruction */ - fputc ('\n', st); /* end line */ - } /* end for */ -return SCPE_OK; -} - -/* Record events in history table */ - -void cpu_inst_hist (int32 addr, int32 inst) -{ -hst[hst_p].pc = addr; -hst[hst_p].ir = inst; -if (cpu_ex (&hst[hst_p].ir1, (addr + 1) & AMASK, &cpu_unit, SWMASK ('V'))) - hst[hst_p].ir1 = 0; -hst[hst_p].lac = LAC; -hst[hst_p].mq = MQ; -hst_p = (hst_p + 1) % HIST_SIZE; -return; -} - -void cpu_intr_hist (int32 flag, int32 lvl) -{ -int32 j; - -hst[hst_p].pc = PC | flag; -hst[hst_p].ir = 0; -for (j = 0; j < API_HLVL+1; j++) hst[hst_p].ir = - (hst[hst_p].ir << HIST_V_LVL) | (int_hwre[j] & HIST_M_LVL); -hst[hst_p].ir1 = 0; -hst[hst_p].lac = 0; -hst[hst_p].mq = lvl; -hst_p = (hst_p + 1) % HIST_SIZE; -return; -} diff --git a/PDP18B/pdp18b_defs.h b/PDP18B/pdp18b_defs.h deleted file mode 100644 index 12798f3c..00000000 --- a/PDP18B/pdp18b_defs.h +++ /dev/null @@ -1,488 +0,0 @@ -/* pdp18b_defs.h: 18b PDP simulator definitions - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 18-Jul-03 RMS Added FP15 support - Added XVM support - Added EAE option for PDP-4 - 25-Apr-03 RMS Revised for extended file support - 04-Feb-03 RMS Added RB09, LP09 support - 22-Nov-02 RMS Added PDP-4 drum support - 05-Oct-02 RMS Added DIB structure - 25-Jul-02 RMS Added PDP-4 DECtape support - 10-Feb-02 RMS Added PDP-7 DECtape support - 25-Nov-01 RMS Revised interrupt structure - 27-May-01 RMS Added second Teletype support - 21-Jan-01 RMS Added DECtape support - 14-Apr-99 RMS Changed t_addr to unsigned - 02-Jan-96 RMS Added fixed head and moving head disks - 31-Dec-95 RMS Added memory management - 19-Mar-95 RMS Added dynamic memory size - - The author gratefully acknowledges the help of Craig St. Clair and - Deb Tevonian in locating archival material about the 18b PDP's, and of - Al Kossow and Max Burnet in making documentation and software available. -*/ - -#ifndef _PDP18B_DEFS_H_ -#define _PDP18B_DEFS_H_ 0 - -#include "sim_defs.h" /* simulator defns */ - -/* Models: only one should be defined - - model memory CPU options I/O options - - PDP4 8K Type 18 EAE Type 65 KSR-28 Teletype (Baudot) - ??Type 16 mem extension integral paper tape reader - Type 75 paper tape punch - integral real time clock - Type 62 line printer (Hollerith) - Type 550/555 DECtape - Type 24 serial drum - - PDP7 32K Type 177 EAE Type 649 KSR-33 Teletype - Type 148 mem extension Type 444 paper tape reader - Type 75 paper tape punch - integral real time clock - Type 647B line printer (sixbit) - Type 550/555 DECtape - Type 24 serial drum - - PDP9 32K KE09A EAE KSR-33 Teletype - KF09A auto pri intr PC09A paper tape reader and punch - KG09B mem extension integral real time clock - KP09A power detection Type 647D/E line printer (sixbit) - KX09A mem protection LP09 line printer (ASCII) - RF09/RS09 fixed head disk - RB09 fixed head disk - TC59 magnetic tape - TC02/TU55 DECtape - LT09A second Teletype - - PDP15 128K KE15 EAE KSR-35 Teletype - KA15 auto pri intr PC15 paper tape reader and punch - KF15 power detection KW15 real time clock - KM15 mem protection LP09 line printer - KT15 mem relocation LP15 line printer - FP15 floating point RP15 disk pack - XVM option RF15/RF09 fixed head disk - TC59D magnetic tape - TC15/TU56 DECtape - LT15 second Teletype - - ??Indicates not implemented. The PDP-4 manual refers to a memory - ??extension control; there is no documentation on it. -*/ - -#if !defined (PDP4) && !defined (PDP7) && !defined (PDP9) && !defined (PDP15) -#define PDP15 0 /* default to PDP-15 */ -#endif - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_XCT 4 /* nested XCT's */ -#define STOP_API 5 /* invalid API int */ -#define STOP_NONSTD 6 /* non-std dev num */ -#define STOP_MME 7 /* mem mgt error */ -#define STOP_FPDIS 8 /* fp inst, fpp disabled */ - -/* Peripheral configuration */ - -#if defined (PDP4) -#define ADDRSIZE 13 -#define KSR28 0 /* Baudot terminal */ -#define TYPE62 0 /* Hollerith printer */ -#define TYPE550 0 /* DECtape */ -#define DRM 0 /* drum */ -#elif defined (PDP7) -#define ADDRSIZE 15 -#define TYPE647 0 /* sixbit printer */ -#define TYPE550 0 /* DECtape */ -#define DRM 0 /* drum */ -#elif defined (PDP9) -#define ADDRSIZE 15 -#define TYPE647 0 /* sixbit printer */ -#define LP09 0 /* ASCII printer */ -#define RB 0 /* fixed head disk */ -#define RF 0 /* fixed head disk */ -#define MTA 0 /* magtape */ -#define TC02 0 /* DECtape */ -#define TTY1 0 /* second Teletype */ -#define BRMASK 0076000 /* bounds mask */ -#elif defined (PDP15) -#define ADDRSIZE 17 -#define LP09 0 /* ASCII printer */ -#define LP15 0 /* DMA printer */ -#define RF 0 /* fixed head disk */ -#define RP 0 /* disk pack */ -#define MTA 0 /* magtape */ -#define TC02 0 /* DECtape */ -#define TTY1 0 /* second Teletype */ -#define BRMASK 0377400 /* bounds mask */ -#define BRMASK_XVM 0777400 /* bounds mask, XVM */ -#endif - -/* Memory */ - -#define AMASK ((1 << ADDRSIZE) - 1) /* address mask */ -#define IAMASK 077777 /* ind address mask */ -#define BLKMASK (AMASK & (~IAMASK)) /* block mask */ -#define MAXMEMSIZE (1 << ADDRSIZE) /* max memory size */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) - -/* Instructions */ - -#define I_V_OP 14 /* opcode */ -#define I_M_OP 017 -#define I_V_IND 13 /* indirect */ -#define I_V_IDX 12 /* index */ -#define I_IND (1 << I_V_IND) -#define I_IDX (1 << I_V_IDX) -#define B_DAMASK 017777 /* bank mode address */ -#define B_EPCMASK (AMASK & ~B_DAMASK) -#define P_DAMASK 007777 /* page mode address */ -#define P_EPCMASK (AMASK & ~P_DAMASK) - -/* Memory cycles */ - -#define FE 0 -#define DF 1 -#define RD 2 -#define WR 3 - -/* Memory status codes */ - -#define MM_OK 0 -#define MM_ERR 1 - -/* Memory management relocation checks (PDP-15 KT15 and XVM only) */ - -#define REL_C -1 /* console */ -#define REL_R 0 /* read */ -#define REL_W 1 /* write */ - -/* Architectural constants */ - -#define DMASK 0777777 /* data mask */ -#define LINK (DMASK + 1) /* link */ -#define LACMASK (LINK | DMASK) /* link + data */ -#define SIGN 0400000 /* sign bit */ -#define OP_JMS 0100000 /* JMS */ -#define OP_JMP 0600000 /* JMP */ -#define OP_HLT 0740040 /* HLT */ - -/* IOT subroutine return codes */ - -#define IOT_V_SKP 18 /* skip */ -#define IOT_V_REASON 19 /* reason */ -#define IOT_SKP (1 << IOT_V_SKP) -#define IOT_REASON (1 << IOT_V_REASON) - -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ - -/* PC change queue */ - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC - -/* XVM memory management registers */ - -#define MM_RDIS 0400000 /* reloc disabled */ -#define MM_V_GM 15 /* G mode */ -#define MM_M_GM 03 -#define MM_GM (MM_M_GM << MM_V_GM) -#define MM_G_W0 0077777 /* virt addr width */ -#define MM_G_W1 0177777 -#define MM_G_W2 0777777 -#define MM_G_W3 0377777 -#define MM_G_B0 0060000 /* SAS base */ -#define MM_G_B1 0160000 -#define MM_G_B2 0760000 -#define MM_G_B3 0360000 -#define MM_UIOT 0040000 /* user mode IOT's */ -#define MM_WP 0020000 /* share write prot */ -#define MM_SH 0010000 /* share enabled */ -#define MM_V_SLR 10 /* segment length reg */ -#define MM_M_SLR 03 -#define MM_SLR_L0 001000 /* SAS length */ -#define MM_SLR_L1 002000 -#define MM_SLR_L2 010000 -#define MM_SLR_L3 020000 -#define MM_SBR_MASK 01777 /* share base reg */ -#define MM_GETGM(x) (((x) >> MM_V_GM) & MM_M_GM) -#define MM_GETSLR(x) (((x) >> MM_V_SLR) & MM_M_SLR) - -/* Device information block */ - -#define DEV_MAXBLK 8 /* max dev block */ -#define DEV_MAX 64 /* total devices */ - -struct pdp18b_dib { - uint32 dev; /* base dev number */ - uint32 num; /* number of slots */ - int32 (*iors)(void); /* IORS responder */ - int32 (*dsp[DEV_MAXBLK])(int32 pulse, int32 dat); -}; - -typedef struct pdp18b_dib DIB; - -/* Standard device numbers */ - -#define DEV_PTR 001 /* paper tape reader */ -#define DEV_PTP 002 /* paper tape punch */ -#define DEV_TTI 003 /* console input */ -#define DEV_TTO 004 /* console output */ -#define DEV_TTI1 041 /* extra terminals */ -#define DEV_TTO1 040 -#define DEV_DRM 060 /* drum */ -#define DEV_RP 063 /* RP15 */ -#define DEV_LPT 065 /* line printer */ -#define DEV_RF 070 /* RF09 */ -#define DEV_RB 071 /* RB09 */ -#define DEV_MT 073 /* magtape */ -#define DEV_DTA 075 /* dectape */ - -/* Interrupt system - - The interrupt system can be modelled on either the flag driven system - of the PDP-4 and PDP-7 or the API driven system of the PDP-9 and PDP-15. - If flag based, API is hard to implement; if API based, IORS requires - extra code for implementation. I've chosen an API based model. - - API channel Device API priority Notes - - 00 software 4 4 - 01 software 5 5 - 02 software 6 6 - 03 software 7 7 - 04 TC02/TC15 1 - 05 TC59D 1 - 06 drum 1 PDP-9 only - 07 RB09 1 PDP-9 only - 10 paper tape reader 2 - 11 real time clock 3 - 12 power fail 0 - 13 memory parity 0 - 14 display 2 - 15 card reader 2 - 16 line printer 2 - 17 A/D converter 0 - 20 interprocessor buffer 3 - 21 360 link 3 PDP-9 only - 22 data phone 2 PDP-15 only - 23 RF09/RF15 1 - 24 RP15 1 PDP-15 only - 25 plotter 1 PDP-15 only - 26 - - 27 - - 30 - - 31 - - 32 - - 33 - - 34 LT15 TTO 3 PDP-15 only - 35 LT15 TTI 3 PDP-15 only - 36 - - 37 - -*/ - -#define API_ML0 0200 /* API masks: level 0 */ -#define API_ML1 0100 -#define API_ML2 0040 -#define API_ML3 0020 -#define API_ML4 0010 -#define API_ML5 0004 -#define API_ML6 0002 -#define API_ML7 0001 /* level 7 */ - -#if defined (PDP9) /* levels which mask PI */ -#define API_MASKPI (API_ML0|API_ML1|API_ML2|API_ML3|API_ML4|API_ML5|API_ML6|API_ML7) -#else -#define API_MASKPI (API_ML0|API_ML1|API_ML2|API_ML3) -#endif - -#define API_HLVL 4 /* hwre levels */ -#define ACH_SWRE 040 /* swre int vec */ - -/* API level 0 */ - -#define INT_V_PWRFL 0 /* powerfail */ - -#define INT_PWRFL (1 << INT_V_PWRFL) - -#define API_PWRFL 0 - -#define ACH_PWRFL 052 - -/* API level 1 */ - -#define INT_V_DTA 0 /* DECtape */ -#define INT_V_MTA 1 /* magtape */ -#define INT_V_DRM 2 /* drum */ -#define INT_V_RF 3 /* fixed head disk */ -#define INT_V_RP 4 /* disk pack */ -#define INT_V_RB 5 /* RB disk */ - -#define INT_DTA (1 << INT_V_DTA) -#define INT_MTA (1 << INT_V_MTA) -#define INT_DRM (1 << INT_V_DRM) -#define INT_RF (1 << INT_V_RF) -#define INT_RP (1 << INT_V_RP) -#define INT_RB (1 << INT_V_RB) - -#define API_DTA 1 -#define API_MTA 1 -#define API_DRM 1 -#define API_RF 1 -#define API_RP 1 -#define API_RB 1 - -#define ACH_DTA 044 -#define ACH_MTA 045 -#define ACH_DRM 046 -#define ACH_RB 047 -#define ACH_RF 063 -#define ACH_RP 064 - -/* API level 2 */ - -#define INT_V_PTR 0 /* paper tape reader */ -#define INT_V_LPT 1 /* line printer */ -#define INT_V_LPTSPC 2 /* line printer spc */ - -#define INT_PTR (1 << INT_V_PTR) -#define INT_LPT (1 << INT_V_LPT) -#define INT_LPTSPC (1 << INT_V_LPTSPC) - -#define API_PTR 2 -#define API_LPT 2 -#define API_LPTSPC 2 - -#define ACH_PTR 050 -#define ACH_LPT 056 - -/* API level 3 */ - -#define INT_V_CLK 0 /* clock */ -#define INT_V_TTI1 1 /* LT15 keyboard */ -#define INT_V_TTO1 2 /* LT15 output */ - -#define INT_CLK (1 << INT_V_CLK) -#define INT_TTI1 (1 << INT_V_TTI1) -#define INT_TTO1 (1 << INT_V_TTO1) - -#define API_CLK 3 -#define API_TTI1 3 -#define API_TTO1 3 - -#define ACH_CLK 051 -#define ACH_TTI1 075 -#define ACH_TTO1 074 - -/* PI level */ - -#define INT_V_TTI 0 /* console keyboard */ -#define INT_V_TTO 1 /* console output */ -#define INT_V_PTP 2 /* paper tape punch */ - -#define INT_TTI (1 << INT_V_TTI) -#define INT_TTO (1 << INT_V_TTO) -#define INT_PTP (1 << INT_V_PTP) - -#define API_TTI 4 /* PI level */ -#define API_TTO 4 -#define API_PTP 4 - -/* Interrupt macros */ - -#define SET_INT(dv) int_hwre[API_##dv] = int_hwre[API_##dv] | INT_##dv -#define CLR_INT(dv) int_hwre[API_##dv] = int_hwre[API_##dv] & ~INT_##dv -#define TST_INT(dv) (int_hwre[API_##dv] & INT_##dv) - -/* I/O status flags for the IORS instruction - - bit PDP-4 PDP-7 PDP-9 PDP-15 - - 0 intr on intr on intr on intr on - 1 tape rdr flag* tape rdr flag* tape rdr flag* tape rdr flag* - 2 tape pun flag* tape pun flag* tape pun flag* tape pun flag* - 3 keyboard flag* keyboard flag* keyboard flag* keyboard flag* - 4 type out flag* type out flag* type out flag* type out flag* - 5 display flag* display flag* light pen flag* light pen flag* - 6 clk ovflo flag* clk ovflo flag* clk ovflo flag* clk ovflo flag* - 7 clk enable flag clk enable flag clk enable flag clk enable flag - 8 mag tape flag* mag tape flag* tape rdr empty* tape rdr empty* - 9 card rdr col* * tape pun empty tape pun empty - 10 card rdr ~busy DECtape flag* DECtape flag* - 11 card rdr error magtape flag* magtape flag* - 12 card rdr EOF disk pack flag* - 13 card pun row* DECdisk flag* DECdisk flag* - 14 card pun error lpt flag* - 15 lpt flag* lpt flag* lpt flag* - 16 lpt space flag* lpt error flag lpt error flag - 17 drum flag* drum flag* -*/ - -#define IOS_ION 0400000 /* interrupts on */ -#define IOS_PTR 0200000 /* tape reader */ -#define IOS_PTP 0100000 /* tape punch */ -#define IOS_TTI 0040000 /* keyboard */ -#define IOS_TTO 0020000 /* terminal */ -#define IOS_LPEN 0010000 /* light pen */ -#define IOS_CLK 0004000 /* clock */ -#define IOS_CLKON 0002000 /* clock enable */ -#define IOS_DTA 0000200 /* DECtape */ -#define IOS_RP 0000040 /* disk pack */ -#define IOS_RF 0000020 /* fixed head disk */ -#define IOS_DRM 0000001 /* drum */ -#if defined (PDP4) || defined (PDP7) -#define IOS_MTA 0001000 /* magtape */ -#define IOS_LPT 0000004 /* line printer */ -#define IOS_LPT1 0000002 /* line printer stat */ -#elif defined (PDP9) -#define IOS_PTRERR 0001000 /* reader empty */ -#define IOS_PTPERR 0000400 /* punch empty */ -#define IOS_MTA 0000100 /* magtape */ -#define IOS_LPT 0000004 /* line printer */ -#define IOS_LPT1 0000002 /* line printer stat */ -#elif defined (PDP15) -#define IOS_PTRERR 0001000 /* reader empty */ -#define IOS_PTPERR 0000400 /* punch empty */ -#define IOS_MTA 0000100 /* magtape */ -#define IOS_LPT 0000010 /* line printer */ -#define IOS_LPT1 0000000 /* not used */ -#endif - -/* Function prototypes */ - -t_stat set_devno (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_devno (FILE *st, UNIT *uptr, int32 val, void *desc); - -#endif - diff --git a/PDP18B/pdp18b_doc.txt b/PDP18B/pdp18b_doc.txt deleted file mode 100644 index 881c75f9..00000000 --- a/PDP18B/pdp18b_doc.txt +++ /dev/null @@ -1,993 +0,0 @@ -To: Users -From: Bob Supnik -Subj: 18b PDP Simulator Usage -Date: 25-Aug-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - Original code published in 1993-2003, written by Robert M Supnik - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - -This memorandum documents the PDP-4, PDP-7, PDP-9, and PDP-15 simulators. - - -1. Simulator Files - -To compile a particular model in the 18b family, you must include the appropriate -switch in the compilation command line: - -PDP-4/ PDP4 -PDP-7/ PDP7 -PDP-9/ PDP9 -PDP-15/ PDP15 - -If no model is specified, the default is the PDP-15. - - PDP-4 PDP-7 PDP-9 PDP-15 -sim/ sim_defs.h x x x x - sim_rev.h x x x x - sim_sock.h x x x x - sim_tape.h x x - sim_tmxr.h x x x x - scp.c x x x x - scp_tty.c x x x x - sim_sock.c x x x x - sim_tape.c x x - sim_tmxr.c x x x x - -sim/pdp18b/ pdp18b_defs.h x x x x - pdp18b_cpu.c x x x x - pdp18b_drm.c x x - pdp18b_dt.c x x x x - pdp18b_fpp.c x - pdp18b_lp.c x x x x - pdp18b_mt.c x x - pdp18b_rb.c x - pdp18b_rf.c x x - pdp18b_rp.c x - pdp18b_stddev.c x x x x - pdp18b_sys.c x x x x - pdp18b_tt1.c x x - -2. 18b PDP Features - -The other four 18b PDP's (PDP-4, PDP-7, PDP-9, PDP-15) are very similar -and are configured as follows: - -system device simulates - name(s) - -PDP-4 CPU PDP-4 CPU with 8KW of memory - - Type 18 extended arithmetic element (EAE) - PTR,PTP integral paper tape/Type 75 punch - TTI,TTO KSR28 console terminal (Baudot code) - LPT Type 62 line printer (Hollerith code) - CLK integral real-time clock - DT Type 550/555 DECtape - DRM Type 24 serial drum - -PDP-7 CPU PDP-7 CPU with 32KW of memory - - Type 177 extended arithmetic element (EAE) - - Type 148 memory extension - PTR,PTP Type 444 paper tape reader/Type 75 punch - TTI,TTO KSR 33 console terminal - LPT Type 647 line printer - CLK integral real-time clock - DT Type 550/555 DECtape - DRM Type 24 serial drum - -PDP-9 CPU PDP-9 CPU with 32KW of memory - - KE09A extended arithmetic element (EAE) - - KF09A automatic priority interrupt (API) - - KG09B memory extension - - KP09A power detection - - KX09A memory protection - PTR,PTP PC09A paper tape reader/punch - TTI,TTO KSR 33 console terminal - TTI1,TTO1 LT09A second console terminal - LP9 LP09 line printer - LPT Type 647E line printer - CLK integral real-time clock - RB RB09 fixed-head disk - RF RF09/RS09 fixed-head disk - DT TC02/TU55 DECtape - MT TC59/TU10 magnetic tape - -PDP-15 CPU PDP-15 CPU with 32KW of memory - - KE15 extended arithmetic element (EAE) - - KA15 automatic priority interrupt (API) - - KF15 power detection - - KM15 memory protection - - KT15 memory relocation and protection - - XVM memory relocation and protection - FPP FP15 floating point processor - PTR,PTP PC15 paper tape reader/punch - TTI,TTO KSR 35 console terminal - TTI1,TTO1 LT15 second console terminal - LP9 LP09 line printer - LPT LP15 line printer - CLK integral real-time clock - RP RP15/RP02 disk pack - RF RF15/RS09 fixed-head disk - DT TC15/TU56 DECtape - MT TC59/TU10 magnetic tape - -Most devices can be disabled or enabled, by the commands: - - SET DISABLED - SET ENABLED - -The simulator allows most device numbers to be changed, by the command: - - SET DEV= - -However, devices can only be BOOTed with their default device numbers. - -The 18b PDP simulators implement several unique stop conditions: - - - an unimplemented instruction is decoded, and register - STOP_INST is set - - more than XCT_MAX nested executes are detected during - instruction execution - - an FP15 instruction is decoded, the FP15 is disabled, - and register STOP_FPP is set - -The PDP-4 and PDP-7 LOAD command supports only "second stage" RIM format -files (alternating DAC address instructions and data): - - LOAD file load PDP-4/PDP-7 RIM format file - -The PDP-9 and PDP-15 LOAD commands support hardware RIM format (data only), -PDP-4/PDP-7 RIM loader format (for compatability with Macro7), and BIN -loader format: - - LOAD -S file load PDP-4/PDP-7 RIM format file - LOAD -R file address load PDP-9/PDP-15 RIM format - file starting at address - LOAD file.RIM address assume file is PDP-9/PDP-15 - RIM format - LOAD -B file load PDP-9/PDP-15 BIN format file - LOAD file.BIN assume file is PDP-9/PDP-15 - BIN format - -If no address is given for a RIM format load, a starting address of 200 -(octal) is assumed. If no switch is specified, and the file extension is -neither RIM nor BIN, the file format is assumed to be BIN. - -2.1 CPU - -The CPU options are the presence of the EAE, the presense of the API and -memory protection (for the PDP-9 and PDP-15), the presense of relocation -or XVM (PDP-15 only), and the size of main memory. - - system option comment - - all SET CPU EAE enable EAE - all SET CPU NOEAE disable EAE - 9,15 SET CPU API enable API - 9,15 SET CPU NOAPI disable API - 9,15 SET CPU PROT enable memory protection - 15 SET CPU RELOC enable memory relocation - 15 SET CPU XVM enable XVM relocation - 9,15 SET CPU NOPROT disable protection, relocation, XVM - 4 SET CPU 4K set memory size = 4K - all SET CPU 8K set memory size = 8K - all SET CPU 12K set memory size = 12K - all SET CPU 16K set memory size = 16K - all SET CPU 20K set memory size = 20K - all SET CPU 24K set memory size = 24K - all SET CPU 28K set memory size = 28K - all SET CPU 32K set memory size = 32K - 15 SET CPU 48K set memory size = 48K - 15 SET CPU 64K set memory size = 64K - 15 SET CPU 80K set memory size = 80K - 15 SET CPU 96K set memory size = 96K - 15 SET CPU 112K set memory size = 112K - 15 SET CPU 128K set memory size = 128K - -Memory sizes greater than 8K are only available on the PDP-7, PDP-9, and -PDP-15; memory sizes greater than 32KW are only available on the PDP-15. -If memory size is being reduced, and the memory being truncated contains -non-zero data, the simulator asks for confirmation. Data in the truncated -portion of memory is lost. Initial memory size is 8K for the PDP-4, 32K -for the PDP-7 and PDP-9, and 128K for the PDP-15. - -The PROT option corresponds to the KX09A on the PDP-9 and the KM15 for the -PDP-15. The PROT option is required to run the Foreground/Background -Monitor. The RELOC option corresponds to the KT15 on the PDP-15, and the -XVM option corresponds to the XM15 on the PDP-15. ADSS-15, ADSS-15 Foreground/ -Background, and standard DOS-15 will run if these options are enabled. - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - system name size comments - - all PC addr program counter - all AC 18 accumulator - all L 1 link - all MQ 18 multiplier-quotient - all SC 6 shift counter - all EAE_AC_SIGN 1 EAE AC sign - all SR 18 front panel switches - all ASW addr address switches for RIM load - all INT[0:4] 32 interrupt requests, - 0:3 = API levels 0-3 - 4 = PI level - all IORS 18 IORS register - all ION 1 interrupt enable - all ION_DELAY 2 interrupt enable delay - 15 ION_INH 1 interrupt inhibit - 9,15 APIENB 1 API enable - 9,15 APIREQ 8 API requesting levels - 9,15 APIACT 8 API active levels - 9,15 BR 18 memory protection bounds - 15 XR 18 index register - 15 LR 18 limit register - 9,15 BR 18 memory protection bounds - 15 RR 18 memory protection relocation - 15 MMR 18 memory protection control - 9,15 USMD 1 user mode - 9,15 USMDBUF 1 user mode buffer - 9,15 USMDDEF 1 user mode load defer - 9,15 NEXM 1 non-existent memory violation - 9,15 PRVN 1 privilege violation - 7,9 EXTM 1 extend mode - 7,9 EXTM_INIT 1 extend mode value after reset - 15 BANKM 1 bank mode - 15 BANKM_INIT 1 bank mode value after reset - 7 TRAPM 1 trap mode - 7,9,15 TRAPP 1 trap pending - 7,9 EMIRP 1 EMIR instruction pending - 9,15 RESTP 1 DBR or RES instruction pending - 9,15 PWRFL 1 power fail flag - all PCQ[0:63] addr PC prior to last JMP, JMS, CAL, or - interrupt; most recent PC change first - all STOP_INST 1 stop on undefined instruction - all XCT_MAX 8 maximum number of chained XCT's allowed - all WRU 8 interrupt character - -"addr" signifies the address width of the system (13b for the PDP-4, 15b for -the PDP-7 and PDP-9, 17b for the PDP-15). - -2.2 Floating Point Processor (FPP) - -The PDP-15 features an optional floating point processor, the FP15 (FPP). -The FPP can be enabled and disabled; by default it is disabled. - -The FPP implements these registers: - - name size comments - - FIR 12 floating instruction register - EPA 18 EPA (A exponent) - FMAS 1 FMA sign - FMAH 17 FMA<1:17> - FMAL 18 FMA<18:35> - EPB 18 EPB (B exponent) - FMBS 1 FMB sign - FMBH 17 FMB<1:17> - FMBL 18 FMB<18:35> - FGUARD 1 guard bit - FMQH 17 FMQ<1:17> - FMQL 18 FMQ<18:35> - JEA 18 exception address register - STOP_FPP 1 stop if FP15 instruction decoded - while FP15 is disabled - -2.3 Programmed I/O Devices - -2.3.1 Paper Tape Reader (PTR) - -The paper tape reader (PTR) reads data from a disk file. The POS -register specifies the number of the next data item to be read. Thus, -by changing POS, the user can backspace or advance the reader. - -The paper tape reader supports the BOOT command. The specific forms -recognized vary from system to system: - - BOOT PTR PDP-4, PDP-7: load RIM loader and start it running - BOOT -F PTR PDP-4, PDP-7: load funny format loader and start - it running - BOOT -H PTR PDP-7: start hardware RIM load at address given - by address switches (ASW) - BOOT {-H} PTR PDP-9, PDP-15: start hardware RIM load at address - given by address switches (ASW) - -The PDP-4 did not have a hardware read-in mode load capability. - -The PTR ATTACH command recognizes one switch, -A for ASCII mode. In -ASCII mode, data returned by the read alphabetic command has even parity. -This allows normal text files to be used as input to the paper tape reader. - -The paper tape reader implements these registers: - - name size comments - - BUF 8 last data item processed - INT 1 interrupt pending flag - DONE 1 device done flag - ERR 1 error flag (PDP-9, PDP-15 only) - POS 32 position in the input file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - end of file 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -2.3.2 Paper Tape Punch (PTP) - -The paper tape punch (PTP) writes data to a disk file. The POS -register specifies the number of the next data item to be written. -Thus, by changing POS, the user can backspace or advance the punch. - -The PTP ATTACH command recognizes one switch, -A for ASCII mode. In -ASCII mode, data is punched with the high order bit clear, and NULL and -DEL characters are supressed. This allows punch output to be processed -with normal text editing utilities. - -The paper tape punch implements these registers: - - name size comments - - BUF 8 last data item processed - INT 1 interrupt pending flag - DONE 1 device done flag - ERR 1 error flag (PDP-9, PDP-15 only) - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape or paper - - OS I/O error x report error and stop - -2.3.3 Terminal Input (TTI) - -On the PDP-7, PDP-9, and PDP-15, the terminal interfaces (TTI, TTO) -can be set to one of three modes: KSR, 7B, or 8B. In KSR mode, lower -case input and output characters are automatically converted to upper -case, the high order bit is forced to one on input, and printing of -ALTmode characters is supressed. In 7B mode, input and output characters -are masked to 7 bits. In 8B mode, characters are not modified. Changing -the mode of either interface changes both. The default mode is KSR. - -On the PDP-9 and PDP-15, the console terminal operates, by default, -with local echo. For backward compatibility, the terminal input can -be set to FDX (full duplex), which supresses local echo. - -The terminal input (TTI) polls the console keyboard for input. It -implements these registers: - - name size comments - - BUF 8 last data item processed - INT 1 interrupt pending flag - DONE 1 device done flag - POS 32 number of characters input - TIME 24 keyboard polling interval - -If the simulator is debugged under Windows Visual C++, typing ^C to the -terminal input causes a fatal run-time error. Use the following command -to simulate typing ^C: - - SET TTI CTRL-C - -2.3.4 Terminal Output (TTO) - -The terminal output (TTO) writes to the simulator console window. It -implements these registers: - - name size comments - - BUF 8 last data item processed - INT 1 interrupt pending flag - DONE 1 device done flag - POS 32 number of chararacters output - TIME 24 time from I/O initiation to interrupt - -2.3.5 Line Printers (LPT, LP9) - -The line printers (LPT, LP9) write data to a disk file. The POS -register specifies the number of the next data item to be written. -Thus, by changing POS, the user can backspace or advance the printer. - -LPT is the "default" line printer for a CPU: Type 62 for the PDP-4, -Type 647 for the PDP-7 and PDP-9, and LP15 for the PDP-15. LP9 is -the LP09 line printer controller for the PDP-9. It may be needed -on the PDP-15 to run certain software packages. LP9 is disabled by -default. - -The Type 62 printer controller implements these registers: - - name size comments - - BUF 8 last data item processed - INT 1 interrupt pending flag - DONE 1 device done flag - SPC 1 spacing done flag - BPTR 6 print buffer pointer - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - LBUF[0:119] 8 line buffer - -The Type 647 printer controller implements these registers: - - name size comments - - BUF 8 last data item processed - INT 1 interrupt pending flag - DONE 1 device done flag - ENABLE 1 interrupt enable (PDP-9 only) - ERR 1 error flag - BPTR 7 print buffer pointer - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - LBUF[0:119] 8 line buffer - -The LP09 printer controller implements these registers: - - name size comments - - BUF 7 output character - INT 1 interrupt pending flag - DONE 1 device done flag - ENABLE 1 interrupt enable - ERR 1 error flag - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - -The LP15 printer controller implements these registers: - - name size comments - - STA 18 status register - MA 18 DMA memory address - INT 1 interrupt pending flag - ENABLE 1 interrupt enable - LCNT 8 line counter - BPTR 7 print buffer pointer - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - LBUF[0:131] 8 line buffer - -For all printers, error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape or paper - - OS I/O error x report error and stop - -2.3.6 Real-Time Clock (CLK) - -The real-time clock (CLK) frequency can be adjusted as follows: - - SET CLK 60HZ set frequency to 60Hz - SET CLK 50HZ set frequency to 50Hz - -The default is 60Hz. - -The clock implements these registers: - - name size comments - - INT 1 interrupt pending flag - DONE 1 device done flag - ENABLE 1 clock enable - TIME 24 clock frequency - -The real-time clock autocalibrates; the clock interval is adjusted up or -down so that the clock tracks actual elapsed time. - -2.3.7 Second Terminal (TTI1, TTO1) - -The second terminal consists of two independent devices, TTI1 and TTO1. -The second terminal performs input and output through a Telnet session -connected to a user-specified port. The ATTACH command specifies the -port to be used: - - ATTACH TTI1 set up listening port - -where port is a decimal number between 1 and 65535 that is not being used -for other TCP/IP activities. - -Once TTI1 is attached and the simulator is running, the terminal listens -for a connection on the specified port. It assumes that the incoming -connection is a Telnet connection. The connection remain opens until -disconnected by the Telnet client, or by a DETACH TTI1 command. - -The second terminal (TTI1,TTO1) can be set to one of three modes: KSR, 7B, -or 8B. In KSR mode, lower case input and output characters are converted -automatically to upper case, the high order bit is forced to one on input, -and printing of ALTmode characters is supressed. In 7B mode, input and -output characters are masked to 7 bits. In 8B mode, characters are not -modified. Changing the mode of either device changes both. The default -mode is KSR. - -The SHOW TTI1 CONNECTIONS command displays the current connection to TTI1. -The SHOW TTI1 STATISTICS command displays statistics for the current connection. -The SET TTI1 DISCONNECT{=0} disconnects the current connection. - -The second terminal input implements these registers: - - name size comments - - BUF 8 last data item processed - INT 1 interrupt pending flag - DONE 1 device done flag - TIME 24 keyboard polling interval - -The second terminal output implements these registers: - - name size comments - - BUF 8 last data item processed - INT 1 interrupt pending flag - DONE 1 device done flag - TIME 24 time from I/O initiation to interrupt - -2.4 RP15/RP02 Disk Pack (RP) - -RP15 options include the ability to make units write enabled or write locked: - - SET RPn LOCKED set unit n write locked - SET RPn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFLINE. - -The RP15 implements these registers: - - name size comments - - STA 18 status A - STB 18 status B - DA 18 disk address - MA 18 current memory address - WC 18 word count - INT 1 interrupt pending flag - BUSY 1 control busy flag - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - - end of file x assume rest of disk is zero - - OS I/O error x report error and stop - -2.5 Type 24 Serial Drum (DRM) - -The serial drum (DRM) implements these registers: - - name size comments - - DA 9 drum address (sector number) - MA 16 current memory address - INT 1 interrupt pending flag - DONE 1 device done flag - ERR 1 error flag - WLK 32 write lock switches - TIME 24 rotational latency, per word - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -Drum data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.6 RB09 Fixed Head Disk (RB) - -The RB09 was an early fixed-head disk for the PDP-9. It was superceded -by the RF09/RS09. It is disabled by default. - -The RB09 implements these registers: - - name size comments - - STA 18 status - DA 20 current disk address - WC 16 word count - MA 15 memory address - INT 1 interrupt pending flag - WLK 20 write lock switches for track groups, - 10 tracks per group - TIME 24 rotational delay, per word - BURST 1 burst flag - STOP_IOE 1 stop on I/O error - -The RB09 is a data break device. If BURST = 0, word transfers are -scheduled individually; if BURST = 1, the entire transfer occurs in -a single data break. - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -RB09 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.7 RF09/RF15/RS09 Fixed Head Disk (RF) - -RF09/RF15 options include the ability to set the number of platters -to a fixed value between 1 and 8, or to autosize the number of platters -from the attached file: - - SET RF 1P one platter (256K) - SET RF 2P two platters (512K) - SET RF 3P three platters (768K) - SET RF 4P four platters (1024K) - SET RF 5P five platters (1280K) - SET RF 6P six platters (1536K) - SET RF 7P seven platters (1792K) - SET RF 8P eight platters (2048K) - SET RF AUTOSIZE autosize on attach - -The default is AUTOSIZE. - -The RF09/RF15 implements these registers: - - name size comments - - STA 18 status - DA 21 current disk address - WC 18 word count (in memory) - CA 18 memory address (in memory) - BUF 18 data buffer (diagnostic only) - INT 1 interrupt pending flag - WLK[0:7] 16 write lock switches for disks 0-7 - TIME 24 rotational delay, per word - BURST 1 burst flag - STOP_IOE 1 stop on I/O error - -The RF09/RF15 is a three-cycle data break device. If BURST = 0, word -transfers are scheduled individually; if BURST = 1, the entire transfer -occurs in a single data break. - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -RF15/RF09 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.8 Type 550/555, TC02/TU55, and TC15/TU56 DECtape (DT) - -The PDP-4 and PDP-7 use the Type 550 DECtape, a programmed I/O controller. -The PDP-9 uses the TC02, and the PDP-15 uses the TC15. The TC02 and TC15 -are DMA controllers and programmatically identical. PDP-4/7 DECtape format -had 4 18b words in its block headers and trailers; PDP-9/15 DECtape format -had 5 18b words. - -DECtapes drives are numbered 1-8; in the simulator, drive 8 is unit 0. -DECtape options include the ability to make units write enabled or write -locked. - - SET DTn WRITEENABLED set unit n write enabled - SET DTn LOCKED set unit n write locked - -Units can also be set ONLINE or OFFLINE. - -The Type 550, TC02, and TC15 support PDP-8 format, PDP-11 format, and -18b format DECtape images. ATTACH tries to determine the tape format -from the DECtape image; the user can force a particular format with -switches: - - -r PDP-8 format - -s PDP-11 format - -t 18b format - -The DECtape controller is a data-only simulator; the timing and mark -track, and block header and trailer, are not stored. Thus, the WRITE -TIMING AND MARK TRACK function is not supported; the READ ALL function -always returns the hardware standard block header and trailer; and the -WRITE ALL function dumps non-data words into the bit bucket. - -The DECtape controller implements these registers: - - system name size comments - - all DTSA 12 status register A - all DTSB 12 status register B - all DTDB 18 data buffer - all INT 1 interrupt pending flag - 9,15 ENB 1 interrupt enable flag - all DTF 1 DECtape flag - 7 BEF 1 block end flag - all ERF 1 error flag - 9,15 CA 18 current address (memory location 30) - 9,15 WC 18 word count (memory location 31) - all LTIME 31 time between lines - all ACTIME 31 time to accelerate to full speed - all DCTIME 31 time to decelerate to a full stop - all SUBSTATE 2 read/write command substate - all POS[0:7] 32 position, in lines, units 0-7 - all STATT[0:7] 18 unit state, units 0-7 - -It is critically important to maintain certain timing relationships -among the DECtape parameters, or the DECtape simulator will fail to -operate correctly. - - - LTIME must be at least 6 - - ACTIME must be less than DCTIME, and both need to be at - least 100 times LTIME - -2.9 TC59/TU10 Magnetic Tape (MT) - -Magnetic tape options include the ability to make units write enabled or -or write locked. - - SET MTn LOCKED set unit n write locked - SET MTn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFLINE. - -The magnetic tape controller implements these registers: - - name size comments - - CMD 18 command - STA 18 main status - CA 18 memory address (in memory) - WC 18 word count (in memory) - INT 1 interrupt pending flag - STOP_IOE 1 stop on I/O error - TIME 24 record delay - UST[0:7] 24 unit status, units 0-7 - POS[0:7] 32 position, units 0-7 - -Error handling is as follows: - - error processed as - - not attached tape not ready; if STOP_IOE, stop - - end of file bad tape - - OS I/O error parity error; if STOP_IOE, stop - -2.10 Symbolic Display and Input - -The 18b PDP simulators implement symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as (sixbit) character string - -m display instruction mnemonics - -The PDP-15 also recognizes an additional switch: - - -p display as packed ASCII (five 7b ASCII - characters in two 18b words) - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or -a ASCII character - " or -c three character sixbit string - alphabetic instruction mnemonic - numeric octal number - -The PDP-15 also recognizes an additional input mode: - - # or -p five character packed ASCII string in - two 18b words - -Instruction input uses standard 18b PDP assembler syntax. There are eight -instruction classes: memory reference, EAE, index (PDP-15 only), IOT, -operate, LAW, FP15 memory reference (PDP-15 only), and FP15 no operand -(PDP-15 only). - -Memory reference instructions have the format - - PDP-4, PDP-7: memref {I} address - PDP-9: memref{*} address - PDP-15: memref{*} address{,X} - -where I (PDP-4, PDP-7) /* (PDP-9, PDP-15) signifies indirect reference, -and X signifies indexing (PDP-15 in page mode only). The address is an -octal number in the range 0 - 017777 (PDP-4, PDP-7, PDP-9, and PDP-15 in -bank mode) or 0 - 07777 (PDP-15 in page mode). - -IOT instructions consist of single mnemonics, eg, KRB, TLS. IOT instructions -may be or'd together - - iot iot iot... - -IOT's may also include the number 10, signifying clear the accumulator - - iot 10 - -The simulator does not check the legality of IOT combinations. IOT's for -which there is no opcode may be specified as IOT n, where n is an octal -number in the range 0 - 07777. - -EAE instructions have the format - - eae {+/- shift count} - -EAE instructions may be or'd together - - eae eae eae... - -The simulator does not check the legality of EAE combinations. EAE's for -which there is no opcode may be specified as EAE n, where n is an octal -number in the range 0 - 037777. - -Index instructions (PDP-15 only) have the format - - index {immediate} - -The immediate, if allowed, must be in the range of -0400 to +0377. - -Operate instructions have the format - - opr opr opr... - -The simulator does not check the legality of the proposed combination. The -operands for MUY and DVI must be deposited explicitly. - -The LAW instruction has the format - - LAW immediate - -where immediate is in the range of 0 to 017777. - -FP15 memory reference instructions occupy two successive words and have -the format - - fpmem{*} address - -where * signifies indirect addressing. The address is a number in the range -0 - 0377777. - -FP15 no operand instructions occupy two successive words and have the format - - fpop - -The second word is ignored on output and set to 0 on input. - -2.11 Character Sets - -The PDP-4's console was an ASR-28 Teletype; its character encoding was -Baudot. The PDP-4's line printer used a modified Hollerith character -set. The PDP-7's and PDP-9's consoles were KSR-33 Teletypes; their -character sets were basically ASCII. The PDP-7's and PDP-9's line -printers used sixbit encoding (ASCII codes 040 - 0137 masked to six -bits). The PDP-15's I/O devices were all ASCII. The following table -provides equivalences between ASCII characters and the PDP-4's I/O devices. -In the console table, FG stands for figures (upper case). - - PDP-4 PDP-4 -ASCII console line printer - -000 - 006 none none -bell FG+024 none -010 - 011 none none -lf 010 none -013 - 014 none none -cr 002 none -016 - 037 none none -space 004 000 -! FG+026 none -" FG+021 none -# FG+005 none -$ FG+062 none -% none none -& FG+013 none -' FG+032 none -( FG+036 057 -) FG+011 055 -* none 072 -+ none 074 -, FG+006 033 -- FG+030 054 -. FG+007 073 -/ FG+027 021 -0 FG+015 020 -1 FG+035 001 -2 FG+031 002 -3 FG+020 003 -4 FG+012 004 -5 FG+001 005 -6 FG+025 006 -7 FG+034 007 -8 FG+014 010 -9 FG+003 011 -: FG+016 none -; FG+017 none -< none 034 -= none 053 -> none 034 -? FG+023 037 -@ none {MID DOT} 040 -A 030 061 -B 023 062 -C 016 063 -D 022 064 -E 020 065 -F 026 066 -G 013 067 -H 005 070 -I 014 071 -J 032 041 -K 036 042 -L 011 043 -M 007 044 -N 006 045 -O 003 046 -P 015 047 -Q 035 050 -R 012 051 -S 024 022 -T 001 023 -U 034 024 -V 017 025 -W 031 026 -X 027 027 -Y 025 030 -Z 021 031 -[ none none -\ none {OVERLINE} 056 -] none none -^ none {UP ARROW} 035 -_ none UC+040 -0140 - 0177 none none diff --git a/PDP18B/pdp18b_drm.c b/PDP18B/pdp18b_drm.c deleted file mode 100644 index 4c3b917f..00000000 --- a/PDP18B/pdp18b_drm.c +++ /dev/null @@ -1,230 +0,0 @@ -/* pdp18b_drm.c: drum/fixed head disk simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - drm (PDP-4,PDP-7) Type 24 serial drum - - 05-Dec-02 RMS Updated from Type 24 documentation - 22-Nov-02 RMS Added PDP-4 support - 05-Feb-02 RMS Added DIB, device number support - 03-Feb-02 RMS Fixed bug in reset routine (found by Robert Alan Byer) - 06-Jan-02 RMS Revised enable/disable support - 25-Nov-01 RMS Revised interrupt structure - 10-Jun-01 RMS Cleaned up IOT decoding to reflect hardware - 26-Apr-01 RMS Added device enable/disable support - 14-Apr-99 RMS Changed t_addr to unsigned -*/ - -#include "pdp18b_defs.h" -#include - -/* Constants */ - -#define DRM_NUMWDS 256 /* words/sector */ -#define DRM_NUMSC 2 /* sectors/track */ -#define DRM_NUMTR 256 /* tracks/drum */ -#define DRM_NUMDK 1 /* drum/controller */ -#define DRM_NUMWDT (DRM_NUMWDS * DRM_NUMSC) /* words/track */ -#define DRM_SIZE (DRM_NUMDK * DRM_NUMTR * DRM_NUMWDT) /* words/drum */ -#define DRM_SMASK ((DRM_NUMTR * DRM_NUMSC) - 1) /* sector mask */ - -/* Parameters in the unit descriptor */ - -#define FUNC u4 /* function */ -#define DRM_READ 000 /* read */ -#define DRM_WRITE 040 /* write */ - -#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ - ((double) DRM_NUMWDT))) - -extern int32 M[]; -extern int32 int_hwre[API_HLVL+1]; -extern UNIT cpu_unit; - -int32 drm_da = 0; /* track address */ -int32 drm_ma = 0; /* memory address */ -int32 drm_err = 0; /* error flag */ -int32 drm_wlk = 0; /* write lock */ -int32 drm_time = 10; /* inter-word time */ -int32 drm_stopioe = 1; /* stop on error */ - -DEVICE drm_dev; -int32 drm60 (int32 pulse, int32 AC); -int32 drm61 (int32 pulse, int32 AC); -int32 drm62 (int32 pulse, int32 AC); -int32 drm_iors (void); -t_stat drm_svc (UNIT *uptr); -t_stat drm_reset (DEVICE *dptr); -t_stat drm_boot (int32 unitno, DEVICE *dptr); - -/* DRM data structures - - drm_dev DRM device descriptor - drm_unit DRM unit descriptor - drm_reg DRM register list -*/ - -DIB drm_dib = { DEV_DRM, 3 ,&drm_iors, { &drm60, &drm61, &drm62 } }; - -UNIT drm_unit = - { UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, - DRM_SIZE) }; - -REG drm_reg[] = { - { ORDATA (DA, drm_da, 9) }, - { ORDATA (MA, drm_ma, 16) }, - { FLDATA (INT, int_hwre[API_DRM], INT_V_DRM) }, - { FLDATA (DONE, int_hwre[API_DRM], INT_V_DRM) }, - { FLDATA (ERR, drm_err, 0) }, - { ORDATA (WLK, drm_wlk, 32) }, - { DRDATA (TIME, drm_time, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, drm_stopioe, 0) }, - { ORDATA (DEVNO, drm_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB drm_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE drm_dev = { - "DRM", &drm_unit, drm_reg, drm_mod, - 1, 8, 20, 1, 8, 18, - NULL, NULL, &drm_reset, - &drm_boot, NULL, NULL, - &drm_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 drm60 (int32 pulse, int32 AC) -{ -if ((pulse & 027) == 06) { /* DRLR, DRLW */ - drm_ma = AC & 0177777; /* load mem addr */ - drm_unit.FUNC = pulse & DRM_WRITE; } /* save function */ -return AC; -} - -int32 drm61 (int32 pulse, int32 AC) -{ -int32 t; - -if (pulse & 001) { /* DRSF */ - if (TST_INT (DRM)) AC = AC | IOT_SKP; } -if (pulse & 002) { /* DRCF */ - CLR_INT (DRM); /* clear done */ - drm_err = 0; } /* clear error */ -if (pulse & 004) { /* DRSS */ - drm_da = AC & DRM_SMASK; /* load sector # */ - t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time); - if (t <= 0) t = t + DRM_NUMWDT; /* wrap around? */ - sim_activate (&drm_unit, t * drm_time); } /* schedule op */ -return AC; -} - -int32 drm62 (int32 pulse, int32 AC) -{ -int32 t; - -if (pulse & 001) { /* DRSN */ - if (drm_err == 0) AC = AC | IOT_SKP; } -if (pulse & 004) { /* DRCS */ - CLR_INT (DRM); /* clear done */ - drm_err = 0; /* clear error */ - t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time); - if (t <= 0) t = t + DRM_NUMWDT; /* wrap around? */ - sim_activate (&drm_unit, t * drm_time); } /* schedule op */ -return AC; -} - -/* Unit service - - This code assumes the entire drum is buffered. -*/ - -t_stat drm_svc (UNIT *uptr) -{ -int32 i; -uint32 da; - -if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ - drm_err = 1; /* set error */ - SET_INT (DRM); /* set done */ - return IORETURN (drm_stopioe, SCPE_UNATT); } - -da = drm_da * DRM_NUMWDS; /* compute dev addr */ -for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */ - if (uptr->FUNC == DRM_READ) { - if (MEM_ADDR_OK (drm_ma)) /* read, check nxm */ - M[drm_ma] = *(((int32 *) uptr->filebuf) + da); } - else { - if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1; - else { - *(((int32 *) uptr->filebuf) + da) = M[drm_ma]; - if (da >= uptr->hwmark) uptr->hwmark = da + 1; } } - drm_ma = (drm_ma + 1) & 0177777; } /* incr mem addr */ -drm_da = (drm_da + 1) & DRM_SMASK; /* incr dev addr */ -SET_INT (DRM); /* set done */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat drm_reset (DEVICE *dptr) -{ -drm_da = drm_ma = drm_err = 0; -CLR_INT (DRM); /* clear done */ -sim_cancel (&drm_unit); -return SCPE_OK; -} - -/* IORS routine */ - -int32 drm_iors (void) -{ -return (TST_INT (DRM)? IOS_DRM: 0); -} - -/* Bootstrap routine */ - -#define BOOT_START 02000 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) - -static const int32 boot_rom[] = { - 0750000, /* CLA ; dev, mem addr */ - 0706006, /* DRLR ; load ma */ - 0706106, /* DRSS ; load da, start */ - 0706101, /* DRSF ; wait for done */ - 0602003, /* JMP .-1 */ - 0600000 /* JMP 0 ; enter boot */ -}; - -t_stat drm_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 PC; - -if (drm_dib.dev != DEV_DRM) return STOP_NONSTD; /* non-std addr? */ -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -PC = BOOT_START; -return SCPE_OK; -} diff --git a/PDP18B/pdp18b_dt.c b/PDP18B/pdp18b_dt.c deleted file mode 100644 index 1a5620ae..00000000 --- a/PDP18B/pdp18b_dt.c +++ /dev/null @@ -1,1338 +0,0 @@ -/* pdp18b_dt.c: 18b DECtape simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - dt (PDP-4, PDP-7) Type 550/555 DECtape - (PDP-9) TC02/TU55 DECtape - (PDP-15) TC15/TU56 DECtape - - 25-Apr-03 RMS Revised for extended file support - 14-Mar-03 RMS Fixed variable size interaction with save/restore - 17-Oct-02 RMS Fixed bug in end of reel logic - 05-Oct-02 RMS Added DIB, device number support - 12-Sep-02 RMS Added 16b format support - 13-Aug-02 RMS Corrected Type 550 unit select logic - 25-Jul-02 RMS Added PDP-4 support - 30-May-02 RMS Widened POS to 32b - 10-Feb-02 RMS Added PDP-7 support - 06-Jan-02 RMS Revised enable/disable support - 29-Nov-01 RMS Added read only unit support - 25-Nov-01 RMS Revised interrupt structure - Changed POS, STATT, LASTT, FLG to arrays - 29-Aug-01 RMS Added casts to PDP-8 unpack routine - 17-Jul-01 RMS Moved function prototype - 11-May-01 RMS Fixed bug in reset - 26-Apr-01 RMS Added device enable/disable support - 15-Mar-01 RMS Added 129th word to PDP-8 format - - 18b DECtapes are represented in memory by fixed length buffer of 32b words. - Three file formats are supported: - - 18b/36b 256 words per block [256 x 18b] - 16b 256 words per block [256 x 16b] - 12b 129 words per block [129 x 12b] - - When a 16b or 12b DECtape file is read in, it is converted to 18b/36b format. - - DECtape motion is measured in 3b lines. Time between lines is 33.33us. - Tape density is nominally 300 lines per inch. The format of a DECtape is - - reverse end zone 36000 lines ~ 10 feet - block 0 - : - block n - forward end zone 36000 lines ~ 10 feet - - A block consists of five 18b header words, a tape-specific number of data - words, and five 18b trailer words. All systems except the PDP-8 use a - standard block length of 256 words; the PDP-8 uses a standard block length - of 86 words (x 18b = 129 words x 12b). [A PDP-4/7 DECtape has only four 18b - header words; for consistency, the PDP-4/7 uses the same format as the PDP-9/15 - but skips the missing header words.] - - Because a DECtape file only contains data, the simulator cannot support - write timing and mark track and can only do a limited implementation - of read all and write all. Read all assumes that the tape has been - conventionally written forward: - - header word 0 0 - header word 1 block number (for forward reads) - header words 2,3 0 - header word 4 0 - : - trailer word 4 checksum - trailer words 3,2 0 - trailer word 1 block number (for reverse reads) - trailer word 0 0 - - Write all writes only the data words and dumps the interblock words in the - bit bucket. - - The Type 550 controller has a 4b unit select field, for units 1-8; the TC02 - has a 3b unit select field, with unit 8 being represented as 0. The code - assumes that the GETUNIT macro returns a unit number in the range of 0-7, - with 8 represented as 0, and an invalid unit as -1. -*/ - -#include "pdp18b_defs.h" - -#define DT_NUMDR 8 /* #drives */ -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_8FMT (UNIT_V_UF + 1) /* 12b format */ -#define UNIT_V_11FMT (UNIT_V_UF + 2) /* 16b format */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_8FMT (1 << UNIT_V_8FMT) -#define UNIT_11FMT (1 << UNIT_V_11FMT) -#define STATE u3 /* unit state */ -#define LASTT u4 /* last time update */ -#define DT_WC 030 /* word count */ -#define DT_CA 031 /* current addr */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -/* System independent DECtape constants */ - -#define DT_EZLIN 36000 /* end zone length */ -#define DT_HTLIN 30 /* header/trailer lines */ -#define DT_BLKLN 6 /* blk no line in h/t */ -#define DT_CSMLN 24 /* checksum line in h/t */ -#define DT_HTWRD (DT_HTLIN / DT_WSIZE) /* header/trailer words */ -#define DT_BLKWD (DT_BLKLN / DT_WSIZE) /* blk no word in h/t */ -#define DT_CSMWD (DT_CSMLN / DT_WSIZE) /* checksum word in h/t */ - -/* 16b, 18b, 36b DECtape constants */ - -#define D18_WSIZE 6 /* word size in lines */ -#define D18_BSIZE 256 /* block size in 18b */ -#define D18_TSIZE 578 /* tape size */ -#define D18_LPERB (DT_HTLIN + (D18_BSIZE * DT_WSIZE) + DT_HTLIN) -#define D18_FWDEZ (DT_EZLIN + (D18_LPERB * D18_TSIZE)) -#define D18_CAPAC (D18_TSIZE * D18_BSIZE) /* tape capacity */ -#define D11_FILSIZ (D18_CAPAC * sizeof (int16)) - -/* 12b DECtape constants */ - -#define D8_WSIZE 4 /* word size in lines */ -#define D8_BSIZE 86 /* block size in 18b */ -#define D8_TSIZE 1474 /* tape size */ -#define D8_LPERB (DT_HTLIN + (D8_BSIZE * DT_WSIZE) + DT_HTLIN) -#define D8_FWDEZ (DT_EZLIN + (D8_LPERB * D8_TSIZE)) -#define D8_CAPAC (D8_TSIZE * D8_BSIZE) /* tape capacity */ - -#define D8_NBSIZE ((D8_BSIZE * D18_WSIZE) / D8_WSIZE) -#define D8_FILSIZ (D8_NBSIZE * D8_TSIZE * sizeof (int16)) - -/* This controller */ - -#define DT_CAPAC D18_CAPAC /* default */ -#define DT_WSIZE D18_WSIZE - -/* Calculated constants, per unit */ - -#define DTU_BSIZE(u) (((u)->flags & UNIT_8FMT)? D8_BSIZE: D18_BSIZE) -#define DTU_TSIZE(u) (((u)->flags & UNIT_8FMT)? D8_TSIZE: D18_TSIZE) -#define DTU_LPERB(u) (((u)->flags & UNIT_8FMT)? D8_LPERB: D18_LPERB) -#define DTU_FWDEZ(u) (((u)->flags & UNIT_8FMT)? D8_FWDEZ: D18_FWDEZ) -#define DTU_CAPAC(u) (((u)->flags & UNIT_8FMT)? D8_CAPAC: D18_CAPAC) - -#define DT_LIN2BL(p,u) (((p) - DT_EZLIN) / DTU_LPERB (u)) -#define DT_LIN2OF(p,u) (((p) - DT_EZLIN) % DTU_LPERB (u)) -#define DT_LIN2WD(p,u) ((DT_LIN2OF (p,u) - DT_HTLIN) / DT_WSIZE) -#define DT_BLK2LN(p,u) (((p) * DTU_LPERB (u)) + DT_EZLIN) -#define DT_QREZ(u) (((u)->pos) < DT_EZLIN) -#define DT_QFEZ(u) (((u)->pos) >= ((uint32) DTU_FWDEZ (u))) -#define DT_QEZ(u) (DT_QREZ (u) || DT_QFEZ (u)) - -/* Status register A */ - -#if defined (TC02) /* TC02/TC15 */ -#define DTA_V_UNIT 15 /* unit select */ -#define DTA_M_UNIT 07 -#define DTA_UNIT (DTA_M_UNIT << DTA_V_UNIT) -#define DTA_V_MOT 13 /* motion */ -#define DTA_M_MOT 03 -#define DTA_V_MODE 12 /* mode */ -#define DTA_V_FNC 9 /* function */ -#define DTA_M_FNC 07 -#define FNC_MOVE 00 /* move */ -#define FNC_SRCH 01 /* search */ -#define FNC_READ 02 /* read */ -#define FNC_RALL 03 /* read all */ -#define FNC_WRIT 04 /* write */ -#define FNC_WALL 05 /* write all */ -#define FNC_WMRK 06 /* write timing */ -#define DTA_V_ENB 8 /* int enable */ -#define DTA_V_CERF 7 /* clr error flag */ -#define DTA_V_CDTF 6 /* clr DECtape flag */ -#define DTA_FWDRV (1u << (DTA_V_MOT + 1)) -#define DTA_STSTP (1u << DTA_V_MOT) -#define DTA_MODE (1u << DTA_V_MODE) -#define DTA_ENB (1u << DTA_V_ENB) -#define DTA_CERF (1u << DTA_V_CERF) -#define DTA_CDTF (1u << DTA_V_CDTF) -#define DTA_RW (0777700 & ~(DTA_CERF | DTA_CDTF)) -#define DTA_GETUNIT(x) (((x) >> DTA_V_UNIT) & DTA_M_UNIT) -#define DT_UPDINT if ((dtsa & DTA_ENB) && (dtsb & (DTB_ERF | DTB_DTF))) \ - SET_INT (DTA); \ - else CLR_INT (DTA); - -#else /* Type 550 */ -#define DTA_V_UNIT 12 /* unit select */ -#define DTA_M_UNIT 017 -#define DTA_UNIT (DTA_M_UNIT << DTA_V_UNIT) -#define DTA_V_MOT 4 /* motion */ -#define DTA_M_MOT 03 -#define DTA_V_FNC 0 /* function */ -#define DTA_M_FNC 07 -#define FNC_MOVE 00 /* move */ -#define FNC_SRCH 01 /* search */ -#define FNC_READ 02 /* read */ -#define FNC_WRIT 03 /* write */ -#define FNC_RALL 05 /* read all */ -#define FNC_WALL 06 /* write all */ -#define FNC_WMRK 07 /* write timing */ -#define DTA_STSTP (1u << (DTA_V_MOT + 1)) -#define DTA_FWDRV (1u << DTA_V_MOT) -#define DTA_MODE 0 /* not implemented */ -#define DTA_RW 077 -#define DTA_GETUNIT(x) map_unit[(((x) >> DTA_V_UNIT) & DTA_M_UNIT)] -#define DT_UPDINT if (dtsb & (DTB_DTF | DTB_BEF | DTB_ERF)) \ - SET_INT (DTA); \ - else CLR_INT (DTA); -#endif - -#define DTA_GETMOT(x) (((x) >> DTA_V_MOT) & DTA_M_MOT) -#define DTA_GETFNC(x) (((x) >> DTA_V_FNC) & DTA_M_FNC) - -/* Status register B */ - -#if defined (TC02) /* TC02/TC15 */ -#define DTB_V_ERF 17 /* error flag */ -#define DTB_V_MRK 16 /* mark trk err */ -#define DTB_V_END 15 /* end zone err */ -#define DTB_V_SEL 14 /* select err */ -#define DTB_V_PAR 13 /* parity err */ -#define DTB_V_TIM 12 /* timing err */ -#define DTB_V_DTF 6 /* DECtape flag */ -#define DTB_ERF (1u << DTB_V_ERF) -#define DTB_MRK (1u << DTB_V_MRK) -#define DTB_END (1u << DTB_V_END) -#define DTB_SEL (1u << DTB_V_SEL) -#define DTB_PAR (1u << DTB_V_PAR) -#define DTB_TIM (1u << DTB_V_TIM) -#define DTB_DTF (1u << DTB_V_DTF) -#define DTB_ALLERR (DTB_ERF | DTB_MRK | DTB_END | DTB_SEL | \ - DTB_PAR | DTB_TIM) - -#else /* Type 550 */ -#define DTB_V_DTF 17 /* data flag */ -#define DTB_V_BEF 16 /* block end flag */ -#define DTB_V_ERF 15 /* error flag */ -#define DTB_V_END 14 /* end of tape */ -#define DTB_V_TIM 13 /* timing err */ -#define DTB_V_REV 12 /* reverse */ -#define DTB_V_GO 11 /* go */ -#define DTB_V_MRK 10 /* mark trk err */ -#define DTB_V_SEL 9 /* select err */ -#define DTB_DTF (1u << DTB_V_DTF) -#define DTB_BEF (1u << DTB_V_BEF) -#define DTB_ERF (1u << DTB_V_ERF) -#define DTB_END (1u << DTB_V_END) -#define DTB_TIM (1u << DTB_V_TIM) -#define DTB_REV (1u << DTB_V_REV) -#define DTB_GO (1u << DTB_V_GO) -#define DTB_MRK (1u << DTB_V_MRK) -#define DTB_SEL (1u << DTB_V_SEL) -#define DTB_ALLERR (DTB_END | DTB_TIM | DTB_MRK | DTB_SEL) -#endif - -/* DECtape state */ - -#define DTS_V_MOT 3 /* motion */ -#define DTS_M_MOT 07 -#define DTS_STOP 0 /* stopped */ -#define DTS_DECF 2 /* decel, fwd */ -#define DTS_DECR 3 /* decel, rev */ -#define DTS_ACCF 4 /* accel, fwd */ -#define DTS_ACCR 5 /* accel, rev */ -#define DTS_ATSF 6 /* @speed, fwd */ -#define DTS_ATSR 7 /* @speed, rev */ -#define DTS_DIR 01 /* dir mask */ -#define DTS_V_FNC 0 /* function */ -#define DTS_M_FNC 07 -#define DTS_OFR 7 /* "off reel" */ -#define DTS_GETMOT(x) (((x) >> DTS_V_MOT) & DTS_M_MOT) -#define DTS_GETFNC(x) (((x) >> DTS_V_FNC) & DTS_M_FNC) -#define DTS_V_2ND 6 /* next state */ -#define DTS_V_3RD (DTS_V_2ND + DTS_V_2ND) /* next next */ -#define DTS_STA(y,z) (((y) << DTS_V_MOT) | ((z) << DTS_V_FNC)) -#define DTS_SETSTA(y,z) uptr->STATE = DTS_STA (y, z) -#define DTS_SET2ND(y,z) uptr->STATE = (uptr->STATE & 077) | \ - ((DTS_STA (y, z)) << DTS_V_2ND) -#define DTS_SET3RD(y,z) uptr->STATE = (uptr->STATE & 07777) | \ - ((DTS_STA (y, z)) << DTS_V_3RD) -#define DTS_NXTSTA(x) (x >> DTS_V_2ND) - -/* Operation substates */ - -#define DTO_WCO 1 /* wc overflow */ -#define DTO_SOB 2 /* start of block */ - -/* Logging */ - -#define LOG_MS 001 /* move, search */ -#define LOG_RW 002 /* read, write */ -#define LOG_RA 004 /* read all */ -#define LOG_BL 010 /* block # lblk */ - -#define ABS(x) (((x) < 0)? (-(x)): (x)) - -extern int32 M[]; -extern int32 int_hwre[API_HLVL+1], dev_enb; -extern UNIT cpu_unit; -extern int32 sim_switches; -extern int32 sim_is_running; - -int32 dtsa = 0; /* status A */ -int32 dtsb = 0; /* status B */ -int32 dtdb = 0; /* data buffer */ -int32 dt_ltime = 12; /* interline time */ -int32 dt_actime = 54000; /* accel time */ -int32 dt_dctime = 72000; /* decel time */ -int32 dt_substate = 0; -int32 dt_log = 0; -int32 dt_logblk = 0; -static const int32 map_unit[16] = { /* Type 550 unit map */ - -1, 1, 2, 3, 4, 5, 6, 7, - 0, -1, -1, -1, -1, -1, -1, -1 }; - -DEVICE dt_dev; -int32 dt75 (int32 pulse, int32 dat); -int32 dt76 (int32 pulse, int32 dat); -int32 dt_iors (void); -t_stat dt_svc (UNIT *uptr); -t_stat dt_reset (DEVICE *dptr); -t_stat dt_attach (UNIT *uptr, char *cptr); -t_stat dt_detach (UNIT *uptr); -void dt_deselect (int32 oldf); -void dt_newsa (int32 newf); -void dt_newfnc (UNIT *uptr, int32 newsta); -t_bool dt_setpos (UNIT *uptr); -void dt_schedez (UNIT *uptr, int32 dir); -void dt_seterr (UNIT *uptr, int32 e); -int32 dt_comobv (int32 val); -int32 dt_csum (UNIT *uptr, int32 blk); -int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos); - -/* DT data structures - - dt_dev DT device descriptor - dt_unit DT unit list - dt_reg DT register list - dt_mod DT modifier list -*/ - -DIB dt_dib = { DEV_DTA, 2, &dt_iors, { &dt75, &dt76 } }; - -UNIT dt_unit[] = { - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) } }; - -REG dt_reg[] = { - { ORDATA (DTSA, dtsa, 18) }, - { ORDATA (DTSB, dtsb, 18) }, - { ORDATA (DTDB, dtdb, 18) }, - { FLDATA (INT, int_hwre[API_DTA], INT_V_DTA) }, -#if defined (DTA_V_ENB) - { FLDATA (ENB, dtsa, DTA_V_ENB) }, -#endif - { FLDATA (DTF, dtsb, DTB_V_DTF) }, -#if defined (DTB_V_BEF) - { FLDATA (BEF, dtsb, DTB_V_BEF) }, -#endif - { FLDATA (ERF, dtsb, DTB_V_ERF) }, -#if defined (TC02) /* TC02/TC15 */ - { ORDATA (WC, M[DT_WC], 18) }, - { ORDATA (CA, M[DT_CA], 18) }, -#endif - { DRDATA (LTIME, dt_ltime, 31), REG_NZ }, - { DRDATA (ACTIME, dt_actime, 31), REG_NZ }, - { DRDATA (DCTIME, dt_dctime, 31), REG_NZ }, - { ORDATA (SUBSTATE, dt_substate, 2) }, - { ORDATA (LOG, dt_log, 4), REG_HIDDEN }, - { DRDATA (LBLK, dt_logblk, 12), REG_HIDDEN }, - { URDATA (POS, dt_unit[0].pos, 10, T_ADDR_W, 0, - DT_NUMDR, PV_LEFT | REG_RO) }, - { URDATA (STATT, dt_unit[0].STATE, 8, 18, 0, - DT_NUMDR, REG_RO) }, - { URDATA (LASTT, dt_unit[0].LASTT, 10, T_ADDR_W, 0, - DT_NUMDR, REG_HRO) }, - { ORDATA (DEVNO, dt_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB dt_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { UNIT_8FMT + UNIT_11FMT, 0, "18b", NULL, NULL }, - { UNIT_8FMT + UNIT_11FMT, UNIT_8FMT, "12b", NULL, NULL }, - { UNIT_8FMT + UNIT_11FMT, UNIT_11FMT, "16b", NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE dt_dev = { - "DT", dt_unit, dt_reg, dt_mod, - DT_NUMDR, 8, 24, 1, 8, 18, - NULL, NULL, &dt_reset, - NULL, &dt_attach, &dt_detach, - &dt_dib, DEV_DISABLE }; - -/* IOT routines */ - -#if defined (TC02) /* TC02/TC15 */ -int32 dt75 (int32 pulse, int32 dat) -{ -int32 old_dtsa = dtsa, fnc; -UNIT *uptr; - -if (((pulse & 060) == 040) && (pulse & 05)) { /* select */ - if (pulse & 01) dtsa = 0; /* DTCA */ - if (pulse & 02) dat = dtsa; /* DTRA!... */ - if (pulse & 04) { /* DTXA */ - if ((dat & DTA_CERF) == 0) dtsb = dtsb & ~DTB_ALLERR; - if ((dat & DTA_CDTF) == 0) dtsb = dtsb & ~DTB_DTF; - dtsa = dtsa ^ (dat & DTA_RW); } - if ((old_dtsa ^ dtsa) & DTA_UNIT) dt_deselect (old_dtsa); - uptr = dt_dev.units + DTA_GETUNIT (dtsa); /* get unit */ - fnc = DTA_GETFNC (dtsa); /* get fnc */ - if (((uptr->flags) & UNIT_DIS) || /* disabled? */ - (fnc >= FNC_WMRK) || /* write mark? */ - ((fnc == FNC_WRIT) && (uptr->flags & UNIT_WPRT)) || - ((fnc == FNC_WALL) && (uptr->flags & UNIT_WPRT))) - dt_seterr (uptr, DTB_SEL); /* select err */ - else dt_newsa (dtsa); /* new func */ - DT_UPDINT; - return dat; } -if ((pulse & 067) == 042) return dtsa; /* DTRA */ -if ((pulse & 067) == 061) /* DTEF */ - return ((dtsb & DTB_ERF)? IOT_SKP + dat: dat); -if ((pulse & 067) == 062) return dtsb; /* DTRB */ -if ((pulse & 067) == 063) /* DTEF!DTRB */ - return ((dtsb & DTB_ERF)? IOT_SKP + dtsb: dtsb); -return dat; -} - -int32 dt76 (int32 pulse, int32 dat) -{ -if ((pulse & 01) && (dtsb & DTB_DTF)) /* DTDF */ - return IOT_SKP + dat; -return dat; -} - -#else /* Type 550 */ -int32 dt75 (int32 pulse, int32 dat) -{ -if (((pulse & 041) == 001) && (dtsb & DTB_DTF)) /* MMDF */ - dat = dat | IOT_SKP; -else if (((pulse & 041) == 041) && (dtsb & DTB_ERF)) /* MMEF */ - dat = dat | IOT_SKP; -if (pulse & 002) { /* MMRD */ - dat = (dat & ~DMASK) | dtdb; - dtsb = dtsb & ~(DTB_DTF | DTB_BEF); } -if (pulse & 004) { /* MMWR */ - dtdb = dat & DMASK; - dtsb = dtsb & ~(DTB_DTF | DTB_BEF); } -DT_UPDINT; -return dat; -} - -int32 dt76 (int32 pulse, int32 dat) -{ -int32 fnc, mot, unum; -UNIT *uptr = NULL; - -unum = DTA_GETUNIT (dtsa); /* get unit no */ -if (unum >= 0) uptr = dt_dev.units + unum; /* get unit */ -if ((pulse & 001) && (dtsb & DTB_BEF)) /* MMBF */ - dat = dat | IOT_SKP; -if (pulse & 002) { /* MMRS */ - dtsb = dtsb & ~(DTB_REV | DTB_GO); /* clr rev, go */ - if (uptr) { /* valid unit? */ - mot = DTS_GETMOT (uptr->STATE); /* get motion */ - if (mot & DTS_DIR) dtsb = dtsb | DTB_REV; /* rev? set */ - if ((mot >= DTS_ACCF) || (uptr->STATE & 0777700)) - dtsb = dtsb | DTB_GO; } /* accel? go */ - dat = (dat & ~DMASK) | dtsb; } -if ((pulse & 044) == 044) { /* MMSE */ - if ((dtsa ^ dat) & DTA_UNIT) dt_deselect (dtsa); /* new unit? */ - dtsa = (dtsa & ~DTA_UNIT) | (dat & DTA_UNIT); - dtsb = dtsb & ~(DTB_DTF | DTB_BEF | DTB_ERF | DTB_ALLERR); } -else if ((pulse & 044) == 004) { /* MMLC */ - dtsa = (dtsa & ~DTA_RW) | (dat & DTA_RW); /* load dtsa */ - dtsb = dtsb & ~(DTB_DTF | DTB_BEF | DTB_ERF | DTB_ALLERR); - fnc = DTA_GETFNC (dtsa); /* get fnc */ - if ((uptr == NULL) || /* invalid? */ - ((uptr->flags) & UNIT_DIS) || /* disabled? */ - (fnc >= FNC_WMRK) || /* write mark? */ - ((fnc == FNC_WRIT) && (uptr->flags & UNIT_WLK)) || - ((fnc == FNC_WALL) && (uptr->flags & UNIT_WLK))) - dt_seterr (uptr, DTB_SEL); /* select err */ - else dt_newsa (dtsa); } -DT_UPDINT; -return dat; -} -#endif - -/* Unit deselect */ - -void dt_deselect (int32 oldf) -{ -int32 old_unit, old_mot; -UNIT *uptr; - -old_unit = DTA_GETUNIT (oldf); /* get unit no */ -if (old_unit < 0) return; /* invalid? */ -uptr = dt_dev.units + old_unit; /* get unit */ -old_mot = DTS_GETMOT (uptr->STATE); -if (old_mot >= DTS_ATSF) /* at speed? */ - dt_newfnc (uptr, DTS_STA (old_mot, DTS_OFR)); -else if (old_mot >= DTS_ACCF) /* accelerating? */ - DTS_SET2ND (DTS_ATSF | (old_mot & DTS_DIR), DTS_OFR); -return; -} - -/* Command register change - - 1. If change in motion, stop to start - - schedule acceleration - - set function as next state - 2. If change in motion, start to stop - - if not already decelerating (could be reversing), - schedule deceleration - 3. If change in direction, - - if not decelerating, schedule deceleration - - set accelerating (other dir) as next state - - set function as next next state - 4. If not accelerating or at speed, - - schedule acceleration - - set function as next state - 5. If not yet at speed, - - set function as next state - 6. If at speed, - - set function as current state, schedule function -*/ - -void dt_newsa (int32 newf) -{ -int32 new_unit, prev_mot, new_fnc; -int32 prev_mving, new_mving, prev_dir, new_dir; -UNIT *uptr; - -new_unit = DTA_GETUNIT (newf); /* new unit */ -if (new_unit < 0) return; /* invalid? */ -uptr = dt_dev.units + new_unit; -if ((uptr->flags & UNIT_ATT) == 0) { /* new unit attached? */ - dt_seterr (uptr, DTB_SEL); /* no, error */ - return; } -prev_mot = DTS_GETMOT (uptr->STATE); /* previous motion */ -prev_mving = prev_mot != DTS_STOP; /* previous moving? */ -prev_dir = prev_mot & DTS_DIR; /* previous dir? */ -new_mving = (newf & DTA_STSTP) != 0; /* new moving? */ -new_dir = (newf & DTA_FWDRV) != 0; /* new dir? */ -new_fnc = DTA_GETFNC (newf); /* new function? */ - -if ((prev_mving | new_mving) == 0) return; /* stop to stop */ - -if (new_mving & ~prev_mving) { /* start? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_actime); /* schedule accel */ - DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } - -if (prev_mving & ~new_mving) { /* stop? */ - if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_dctime); } /* schedule decel */ - DTS_SETSTA (DTS_DECF | prev_dir, 0); /* state = decel */ - return; } - -if (prev_dir ^ new_dir) { /* dir chg? */ - if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_dctime); } /* schedule decel */ - DTS_SETSTA (DTS_DECF | prev_dir, 0); /* state = decel */ - DTS_SET2ND (DTS_ACCF | new_dir, 0); /* next = accel */ - DTS_SET3RD (DTS_ATSF | new_dir, new_fnc); /* next next = fnc */ - return; } - -if (prev_mot < DTS_ACCF) { /* not accel/at speed? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* cancel cur */ - sim_activate (uptr, dt_actime); /* schedule accel */ - DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } - -if (prev_mot < DTS_ATSF) { /* not at speed? */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } - -dt_newfnc (uptr, DTS_STA (DTS_ATSF | new_dir, new_fnc));/* state = fnc */ -return; -} - -/* Schedule new DECtape function - - This routine is only called if - - the selected unit is attached - - the selected unit is at speed (forward or backward) - - This routine - - updates the selected unit's position - - updates the selected unit's state - - schedules the new operation -*/ - -void dt_newfnc (UNIT *uptr, int32 newsta) -{ -int32 fnc, dir, blk, unum, relpos, newpos; -uint32 oldpos; - -oldpos = uptr->pos; /* save old pos */ -if (dt_setpos (uptr)) return; /* update pos */ -uptr->STATE = newsta; /* update state */ -fnc = DTS_GETFNC (uptr->STATE); /* set variables */ -dir = DTS_GETMOT (uptr->STATE) & DTS_DIR; -unum = uptr - dt_dev.units; -if (oldpos == uptr->pos) /* bump pos */ - uptr->pos = uptr->pos + (dir? -1: 1); -blk = DT_LIN2BL (uptr->pos, uptr); - -if (dir? DT_QREZ (uptr): DT_QFEZ (uptr)) { /* wrong ez? */ - dt_seterr (uptr, DTB_END); /* set ez flag, stop */ - return; } -sim_cancel (uptr); /* cancel cur op */ -dt_substate = DTO_SOB; /* substate = block start */ -switch (fnc) { /* case function */ -case DTS_OFR: /* off reel */ - if (dir) newpos = -1000; /* rev? < start */ - else newpos = DTU_FWDEZ (uptr) + DT_EZLIN + 1000; /* fwd? > end */ - break; -case FNC_MOVE: /* move */ - dt_schedez (uptr, dir); /* sched end zone */ - if (dt_log & LOG_MS) printf ("[DT%d: moving %s]\n", unum, (dir? - "backward": "forward")); - return; /* done */ -case FNC_SRCH: /* search */ - if (dir) newpos = DT_BLK2LN ((DT_QFEZ (uptr)? - DTU_TSIZE (uptr): blk), uptr) - DT_BLKLN - DT_WSIZE; - else newpos = DT_BLK2LN ((DT_QREZ (uptr)? - 0: blk + 1), uptr) + DT_BLKLN + (DT_WSIZE - 1); - if (dt_log & LOG_MS) printf ("[DT%d: searching %s]\n", unum, - (dir? "backward": "forward")); - break; -case FNC_WRIT: /* write */ -case FNC_READ: /* read */ -#if defined (TC02) /* TC02/TC15 */ - if (DT_QEZ (uptr)) { /* in "ok" end zone? */ - if (dir) newpos = DTU_FWDEZ (uptr) - DT_HTLIN - DT_WSIZE; - else newpos = DT_EZLIN + DT_HTLIN + (DT_WSIZE - 1); - break; } - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - dt_seterr (uptr, DTB_SEL); - return; } - if (dir) newpos = DT_BLK2LN (((relpos >= (DTU_LPERB (uptr) - DT_HTLIN))? - blk + 1: blk), uptr) - DT_HTLIN - DT_WSIZE; - else newpos = DT_BLK2LN (((relpos < DT_HTLIN)? - blk: blk + 1), uptr) + DT_HTLIN + (DT_WSIZE - 1); - break; -#endif -case FNC_RALL: /* read all */ -case FNC_WALL: /* write all */ - if (DT_QEZ (uptr)) { /* in "ok" end zone? */ - if (dir) newpos = DTU_FWDEZ (uptr) - DT_WSIZE; - else newpos = DT_EZLIN + (DT_WSIZE - 1); } - else { - newpos = ((uptr->pos) / DT_WSIZE) * DT_WSIZE; - if (!dir) newpos = newpos + (DT_WSIZE - 1); } - if ((dt_log & LOG_RA) || ((dt_log & LOG_BL) && (blk == dt_logblk))) - printf ("[DT%d: read all block %d %s%s\n", - unum, blk, (dir? "backward": "forward"), - ((dtsa & DTA_MODE)? " continuous]": "]")); - break; -default: - dt_seterr (uptr, DTB_SEL); /* bad state */ - return; } -#if defined (TYPE550) /* Type 550 */ -if ((fnc == FNC_WRIT) || (fnc == FNC_WALL)) { /* write function? */ - dtsb = dtsb | DTB_DTF; /* set data flag */ - DT_UPDINT; } -#endif -sim_activate (uptr, ABS (newpos - ((int32) uptr->pos)) * dt_ltime); -return; -} - -/* Update DECtape position - - DECtape motion is modeled as a constant velocity, with linear - acceleration and deceleration. The motion equations are as follows: - - t = time since operation started - tmax = time for operation (accel, decel only) - v = at speed velocity in lines (= 1/dt_ltime) - - Then: - at speed dist = t * v - accel dist = (t^2 * v) / (2 * tmax) - decel dist = (((2 * t * tmax) - t^2) * v) / (2 * tmax) - - This routine uses the relative (integer) time, rather than the absolute - (floating point) time, to allow save and restore of the start times. -*/ - -t_bool dt_setpos (UNIT *uptr) -{ -uint32 new_time, ut, ulin, udelt; -int32 mot = DTS_GETMOT (uptr->STATE); -int32 unum, delta; - -new_time = sim_grtime (); /* current time */ -ut = new_time - uptr->LASTT; /* elapsed time */ -if (ut == 0) return FALSE; /* no time gone? exit */ -uptr->LASTT = new_time; /* update last time */ -switch (mot & ~DTS_DIR) { /* case on motion */ -case DTS_STOP: /* stop */ - delta = 0; - break; -case DTS_DECF: /* slowing */ - ulin = ut / (uint32) dt_ltime; udelt = dt_dctime / dt_ltime; - delta = ((ulin * udelt * 2) - (ulin * ulin)) / (2 * udelt); - break; -case DTS_ACCF: /* accelerating */ - ulin = ut / (uint32) dt_ltime; udelt = dt_actime / dt_ltime; - delta = (ulin * ulin) / (2 * udelt); - break; -case DTS_ATSF: /* at speed */ - delta = ut / (uint32) dt_ltime; - break; } -if (mot & DTS_DIR) uptr->pos = uptr->pos - delta; /* update pos */ -else uptr->pos = uptr->pos + delta; -if (((int32) uptr->pos < 0) || - ((int32) uptr->pos > (DTU_FWDEZ (uptr) + DT_EZLIN))) { - detach_unit (uptr); /* off reel? */ - uptr->STATE = uptr->pos = 0; - unum = uptr - dt_dev.units; - if (unum == DTA_GETUNIT (dtsa)) /* if selected, */ - dt_seterr (uptr, DTB_SEL); /* error */ - return TRUE; } -return FALSE; -} - -/* Unit service - - Unit must be attached, detach cancels operation -*/ - -t_stat dt_svc (UNIT *uptr) -{ -int32 mot = DTS_GETMOT (uptr->STATE); -int32 dir = mot & DTS_DIR; -int32 fnc = DTS_GETFNC (uptr->STATE); -int32 *bptr = uptr->filebuf; -int32 unum = uptr - dt_dev.units; -int32 blk, wrd, ma, relpos; -uint32 ba; - -/* Motion cases - - Decelerating - if next state != stopped, must be accel reverse - Accelerating - next state must be @speed, schedule function - At speed - do functional processing -*/ - -switch (mot) { -case DTS_DECF: case DTS_DECR: /* decelerating */ - if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ - uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ - if (uptr->STATE) /* not stopped? */ - sim_activate (uptr, dt_actime); /* must be reversing */ - return SCPE_OK; -case DTS_ACCF: case DTS_ACCR: /* accelerating */ - dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */ - return SCPE_OK; -case DTS_ATSF: case DTS_ATSR: /* at speed */ - break; /* check function */ -default: /* other */ - dt_seterr (uptr, DTB_SEL); /* state error */ - return SCPE_OK; } - -/* Functional cases - - Move - must be at end zone - Search - transfer block number, schedule next block - Off reel - detach unit (it must be deselected) -*/ - -if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ -if (DT_QEZ (uptr)) { /* in end zone? */ - dt_seterr (uptr, DTB_END); /* end zone error */ - return SCPE_OK; } -blk = DT_LIN2BL (uptr->pos, uptr); /* get block # */ -switch (fnc) { /* at speed, check fnc */ -case FNC_MOVE: /* move */ - dt_seterr (uptr, DTB_END); /* end zone error */ - return SCPE_OK; -case DTS_OFR: /* off reel */ - detach_unit (uptr); /* must be deselected */ - uptr->STATE = uptr->pos = 0; /* no visible action */ - break; - -/* TC02/TC15 service */ -/* Search */ - -#if defined (TC02) /* TC02/TC15 */ -case FNC_SRCH: /* search */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - sim_activate (uptr, DTU_LPERB (uptr) * dt_ltime);/* sched next block */ - M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* inc WC */ - ma = M[DT_CA] & AMASK; /* get mem addr */ - if (MEM_ADDR_OK (ma)) M[ma] = blk; /* store block # */ - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; /* set DTF */ - break; - -/* Read has four subcases - - Start of block, not wc ovf - check that DTF is clear, otherwise normal - Normal - increment MA, WC, copy word from tape to memory - if read dir != write dir, bits must be scrambled - if wc overflow, next state is wc overflow - if end of block, possibly set DTF, next state is start of block - Wc ovf, not start of block - - if end of block, possibly set DTF, next state is start of block - Wc ovf, start of block - if end of block reached, timing error, - otherwise, continue to next word -*/ - -case FNC_READ: /* read */ - wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */ - switch (dt_substate) { /* case on substate */ - case DTO_SOB: /* start of block */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - if ((dt_log & LOG_RW) || ((dt_log & LOG_BL) && (blk == dt_logblk))) - printf ("[DT%d: reading block %d %s%s\n", - unum, blk, (dir? "backward": "forward"), - ((dtsa & DTA_MODE)? " continuous]": "]")); - dt_substate = 0; /* fall through */ - case 0: /* normal read */ - M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */ - M[DT_CA] = (M[DT_CA] + 1) & DMASK; - ma = M[DT_CA] & AMASK; /* mem addr */ - ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - dtdb = bptr[ba]; /* get tape word */ - if (dir) dtdb = dt_comobv (dtdb); /* rev? comp obv */ - if (MEM_ADDR_OK (ma)) M[ma] = dtdb; /* mem addr legal? */ - if (M[DT_WC] == 0) dt_substate = DTO_WCO; /* wc ovf? */ - case DTO_WCO: /* wc ovf, not sob */ - if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not last? */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - else { - dt_substate = dt_substate | DTO_SOB; - sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; } /* set DTF */ - break; - case DTO_WCO | DTO_SOB: /* next block */ - if (wrd == (dir? 0: DTU_BSIZE (uptr))) /* end of block? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - else sim_activate (uptr, DT_WSIZE * dt_ltime); - break; } - break; - -/* Write has four subcases - - Start of block, not wc ovf - check that DTF is clear, set block direction - Normal - increment MA, WC, copy word from memory to tape - if wc overflow, next state is wc overflow - if end of block, possibly set DTF, next state is start of block - Wc ovf, not start of block - - copy 0 to tape - if end of block, possibly set DTF, next state is start of block - Wc ovf, start of block - schedule end zone -*/ - -case FNC_WRIT: /* write */ - wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */ - switch (dt_substate) { /* case on substate */ - case DTO_SOB: /* start block */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - if ((dt_log & LOG_RW) || ((dt_log & LOG_BL) && (blk == dt_logblk))) - printf ("[DT%d: writing block %d %s%s\n", unum, blk, - (dir? "backward": "forward"), - ((dtsa & DTA_MODE)? " continuous]": "]")); - dt_substate = 0; /* fall through */ - case 0: /* normal write */ - M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */ - M[DT_CA] = (M[DT_CA] + 1) & DMASK; - case DTO_WCO: /* wc ovflo */ - ma = M[DT_CA] & AMASK; /* mem addr */ - ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - dtdb = dt_substate? 0: M[ma]; /* get word */ - if (dir) dtdb = dt_comobv (dtdb); /* rev? comp obv */ - bptr[ba] = dtdb; /* write word */ - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; - if (M[DT_WC] == 0) dt_substate = DTO_WCO; - if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not last? */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - else { - dt_substate = dt_substate | DTO_SOB; - sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; } /* set DTF */ - break; - case DTO_WCO | DTO_SOB: /* all done */ - dt_schedez (uptr, dir); /* sched end zone */ - break; } - break; - -/* Read all has two subcases - - Not word count overflow - increment MA, WC, copy word from tape to memory - Word count overflow - schedule end zone -*/ - -case FNC_RALL: - switch (dt_substate) { /* case on substate */ - case 0: case DTO_SOB: /* read in progress */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */ - M[DT_CA] = (M[DT_CA] + 1) & DMASK; - ma = M[DT_CA] & AMASK; /* mem addr */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - dtdb = bptr[ba]; } /* get tape word */ - else dtdb = dt_gethdr (uptr, blk, relpos); /* get hdr */ - if (dir) dtdb = dt_comobv (dtdb); /* rev? comp obv */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - if (MEM_ADDR_OK (ma)) M[ma] = dtdb; /* mem addr legal? */ - if (M[DT_WC] == 0) dt_substate = DTO_WCO; - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; /* set DTF */ - break; - case DTO_WCO: case DTO_WCO | DTO_SOB: /* all done */ - dt_schedez (uptr, dir); /* sched end zone */ - break; } /* end case substate */ - break; - -/* Write all has two subcases - - Not word count overflow - increment MA, WC, copy word from memory to tape - Word count overflow - schedule end zone -*/ - -case FNC_WALL: - switch (dt_substate) { /* case on substate */ - case 0: case DTO_SOB: /* read in progress */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */ - M[DT_CA] = (M[DT_CA] + 1) & DMASK; - ma = M[DT_CA] & AMASK; /* mem addr */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - dtdb = M[ma]; /* get mem word */ - if (dir) dtdb = dt_comobv (dtdb); - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - bptr[ba] = dtdb; /* write word */ - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; } -/* /* ignore hdr */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - if (M[DT_WC] == 0) dt_substate = DTO_WCO; - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; /* set DTF */ - break; - case DTO_WCO: case DTO_WCO | DTO_SOB: /* all done */ - dt_schedez (uptr, dir); /* sched end zone */ - break; } /* end case substate */ - break; - -/* Type 550 service */ -/* Search */ - -#else /* Type 550 */ -case FNC_SRCH: /* search */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - sim_activate (uptr, DTU_LPERB (uptr) * dt_ltime);/* sched next block */ - dtdb = blk; /* store block # */ - dtsb = dtsb | DTB_DTF; /* set DTF */ - break; - -/* Read and read all */ - -case FNC_READ: case FNC_RALL: - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - sim_activate (uptr, DT_WSIZE * dt_ltime); /* sched next word */ - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - dtdb = bptr[ba]; /* get tape word */ - dtsb = dtsb | DTB_DTF; } /* set flag */ - else { - ma = (2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1; - wrd = relpos / DT_WSIZE; /* hdr start = wd 0 */ - if ((wrd == 0) || /* skip 1st, last */ - (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - 1))) break; - if ((fnc == FNC_READ) && /* read, skip if not */ - (wrd != DT_CSMWD) && /* fwd, rev cksum */ - (wrd != ma)) break; - dtdb = dt_gethdr (uptr, blk, relpos); - if (wrd == (dir? DT_CSMWD: ma)) /* at end csum? */ - dtsb = dtsb | DTB_BEF; /* end block */ - else dtsb = dtsb | DTB_DTF; } /* else next word */ - if (dir) dtdb = dt_comobv (dtdb); - break; - -/* Write and write all */ - -case FNC_WRIT: case FNC_WALL: - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - sim_activate (uptr, DT_WSIZE * dt_ltime); /* sched next word */ - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - if (dir) bptr[ba] = dt_comobv (dtdb); /* get data word */ - else bptr[ba] = dtdb; - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; - if (wrd == (dir? 0: DTU_BSIZE (uptr) - 1)) - dtsb = dtsb | DTB_BEF; /* end block */ - else dtsb = dtsb | DTB_DTF; } /* else next word */ - else { - wrd = relpos / DT_WSIZE; /* hdr start = wd 0 */ - if ((wrd == 0) || /* skip 1st, last */ - (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - 1))) break; - if ((fnc == FNC_WRIT) && /* wr, skip if !csm */ - (wrd != ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1))) - break; - dtsb = dtsb | DTB_DTF; } /* set flag */ - break; -#endif - -default: - dt_seterr (uptr, DTB_SEL); /* impossible state */ - break; } -DT_UPDINT; /* update interrupts */ -return SCPE_OK; -} - -/* Utility routines */ - -/* Set error flag */ - -void dt_seterr (UNIT *uptr, int32 e) -{ -int32 mot = DTS_GETMOT (uptr->STATE); - -dtsa = dtsa & ~DTA_STSTP; /* clear go */ -dtsb = dtsb | DTB_ERF | e; /* set error flag */ -if (mot >= DTS_ACCF) { /* ~stopped or stopping? */ - sim_cancel (uptr); /* cancel activity */ - if (dt_setpos (uptr)) return; /* update position */ - sim_activate (uptr, dt_dctime); /* sched decel */ - DTS_SETSTA (DTS_DECF | (mot & DTS_DIR), 0); } /* state = decel */ -DT_UPDINT; -return; -} - -/* Schedule end zone */ - -void dt_schedez (UNIT *uptr, int32 dir) -{ -int32 newpos; - -if (dir) newpos = DT_EZLIN - DT_WSIZE; /* rev? rev ez */ -else newpos = DTU_FWDEZ (uptr) + DT_WSIZE; /* fwd? fwd ez */ -sim_activate (uptr, ABS (newpos - ((int32) uptr->pos)) * dt_ltime); -return; -} - -/* Complement obverse routine */ - -int32 dt_comobv (int32 dat) -{ -dat = dat ^ DMASK; /* compl obverse */ -dat = ((dat >> 15) & 07) | ((dat >> 9) & 070) | - ((dat >> 3) & 0700) | ((dat & 0700) << 3) | - ((dat & 070) << 9) | ((dat & 07) << 15); -return dat; -} - -/* Checksum routine */ - -int32 dt_csum (UNIT *uptr, int32 blk) -{ -int32 *bptr = uptr->filebuf; -int32 ba = blk * DTU_BSIZE (uptr); -int32 i, csum, wrd; - -#if defined (TC02) /* TC02/TC15 */ -csum = 077; /* init csum */ -for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ - wrd = bptr[ba + i] ^ DMASK; /* get ~word */ - csum = csum ^ (wrd >> 12) ^ (wrd >> 6) ^ wrd; } -return (csum & 077); -#else /* Type 550 */ -csum = DMASK; -for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ - wrd = bptr[ba + i]; /* get word */ - csum = csum + wrd; /* 1's comp add */ - if (csum > DMASK) csum = (csum + 1) & DMASK; } -return (csum ^ DMASK); /* 1's comp res */ -#endif -} - -/* Get header word */ - -int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos) -{ -int32 wrd = relpos / DT_WSIZE; - -if (wrd == DT_BLKWD) return blk; /* fwd blknum */ -#if defined (TC02) /* TC02/TC15 */ -if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */ - return (dt_csum (uptr, blk) << 12); -#else -if (wrd == DT_CSMWD) return DMASK; /* rev csum */ -if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */ - return (dt_csum (uptr, blk)); -#endif /* Type 550 */ -if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_BLKWD - 1)) /* rev blkno */ - return dt_comobv (blk); -return 0; /* all others */ -} - -/* Reset routine */ - -t_stat dt_reset (DEVICE *dptr) -{ -int32 i, prev_mot; -UNIT *uptr; - -for (i = 0; i < DT_NUMDR; i++) { /* stop all drives */ - uptr = dt_dev.units + i; - if (sim_is_running) { /* CAF? */ - prev_mot = DTS_GETMOT (uptr->STATE); /* get motion */ - if ((prev_mot & ~DTS_DIR) > DTS_DECF) { /* accel or spd? */ - if (dt_setpos (uptr)) continue; /* update pos */ - sim_cancel (uptr); - sim_activate (uptr, dt_dctime); /* sched decel */ - DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); - } } - else { - sim_cancel (uptr); /* sim reset */ - uptr->STATE = 0; - uptr->LASTT = sim_grtime (); } } -dtsa = dtsb = 0; /* clear status */ -DT_UPDINT; /* reset interrupt */ -return SCPE_OK; -} - -/* IORS routine */ - -int32 dt_iors (void) -{ -#if defined IOS_DTA -return ((dtsb & (DTB_ERF | DTB_DTF))? IOS_DTA: 0); -#else -return 0; -#endif -} - -/* Attach routine - - Determine 12b, 16b, or 18b/36b format - Allocate buffer - If 12b, read 12b format and convert to 18b in buffer - If 16b, read 16b format and convert to 18b in buffer - If 18b/36b, read data into buffer -*/ - -t_stat dt_attach (UNIT *uptr, char *cptr) -{ -uint16 pdp8b[D8_NBSIZE]; -uint16 pdp11b[D18_BSIZE]; -uint32 ba, sz, k, *bptr; -int32 u = uptr - dt_dev.units; -t_stat r; - -r = attach_unit (uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error? */ -if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */ - uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); /* default 18b */ - if (sim_switches & SWMASK ('R')) /* att 12b? */ - uptr->flags = uptr->flags | UNIT_8FMT; - else if (sim_switches & SWMASK ('S')) /* att 16b? */ - uptr->flags = uptr->flags | UNIT_11FMT; - else if (!(sim_switches & SWMASK ('T')) && /* autosize? */ - (sz = sim_fsize (cptr))) { - if (sz == D8_FILSIZ) - uptr->flags = uptr->flags | UNIT_8FMT; - else if (sz == D11_FILSIZ) - uptr->flags = uptr->flags | UNIT_11FMT; } } -uptr->capac = DTU_CAPAC (uptr); /* set capacity */ -uptr->filebuf = calloc (uptr->capac, sizeof (int32)); -if (uptr->filebuf == NULL) { /* can't alloc? */ - detach_unit (uptr); - return SCPE_MEM; } -bptr = uptr->filebuf; /* file buffer */ -printf ("%s%d: ", sim_dname (&dt_dev), u); -if (uptr->flags & UNIT_8FMT) printf ("12b format"); -else if (uptr->flags & UNIT_11FMT) printf ("16b format"); -else printf ("18b/36b format"); -printf (", buffering file in memory\n"); -if (uptr->flags & UNIT_8FMT) { /* 12b? */ - for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ - k = fxread (pdp8b, sizeof (int16), D8_NBSIZE, uptr->fileref); - if (k == 0) break; - for ( ; k < D8_NBSIZE; k++) pdp8b[k] = 0; - for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop thru blk */ - bptr[ba] = ((uint32) (pdp8b[k] & 07777) << 6) | - ((uint32) (pdp8b[k + 1] >> 6) & 077); - bptr[ba + 1] = ((uint32) (pdp8b[k + 1] & 077) << 12) | - (pdp8b[k + 2] & 07777); - ba = ba + 2; } /* end blk loop */ - } /* end file loop */ - uptr->hwmark = ba; } /* end if */ -else if (uptr->flags & UNIT_11FMT) { /* 16b? */ - for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ - k = fxread (pdp11b, sizeof (int16), D18_BSIZE, uptr->fileref); - if (k == 0) break; - for ( ; k < D18_BSIZE; k++) pdp11b[k] = 0; - for (k = 0; k < D18_BSIZE; k++) - bptr[ba++] = pdp11b[k]; } - uptr->hwmark = ba; } /* end elif */ -else uptr->hwmark = fxread (uptr->filebuf, sizeof (int32), - uptr->capac, uptr->fileref); -uptr->flags = uptr->flags | UNIT_BUF; /* set buf flag */ -uptr->pos = DT_EZLIN; /* beyond leader */ -uptr->LASTT = sim_grtime (); /* last pos update */ -return SCPE_OK; -} - -/* Detach routine - - Cancel in progress operation - If 12b, convert 18b buffer to 12b and write to file - If 16b, convert 18b buffer to 16b and write to file - If 18b/36b, write buffer to file - Deallocate buffer -*/ - -t_stat dt_detach (UNIT* uptr) -{ -uint16 pdp8b[D8_NBSIZE]; -uint16 pdp11b[D18_BSIZE]; -uint32 ba, k, *bptr; -int32 u = uptr - dt_dev.units; - -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; -if (sim_is_active (uptr)) { - sim_cancel (uptr); - if ((u == DTA_GETUNIT (dtsa)) && (dtsa & DTA_STSTP)) { - dtsb = dtsb | DTB_ERF | DTB_SEL | DTB_DTF; - DT_UPDINT; } - uptr->STATE = uptr->pos = 0; } -bptr = uptr->filebuf; /* file buffer */ -if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */ - printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u); - rewind (uptr->fileref); /* start of file */ - if (uptr->flags & UNIT_8FMT) { /* 12b? */ - for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */ - for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop blk */ - pdp8b[k] = (bptr[ba] >> 6) & 07777; - pdp8b[k + 1] = ((bptr[ba] & 077) << 6) | - ((bptr[ba + 1] >> 12) & 077); - pdp8b[k + 2] = bptr[ba + 1] & 07777; - ba = ba + 2; } /* end loop blk */ - fxwrite (pdp8b, sizeof (int16), D8_NBSIZE, uptr->fileref); - if (ferror (uptr->fileref)) break; } /* end loop file */ - } /* end if 12b */ - else if (uptr->flags & UNIT_11FMT) { /* 16b? */ - for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */ - for (k = 0; k < D18_BSIZE; k++) /* loop blk */ - pdp11b[k] = bptr[ba++] & 0177777; - fxwrite (pdp11b, sizeof (int16), D18_BSIZE, uptr->fileref); - if (ferror (uptr->fileref)) break; } /* end loop file */ - } /* end if 16b */ - else fxwrite (uptr->filebuf, sizeof (int32), /* write file */ - uptr->hwmark, uptr->fileref); - if (ferror (uptr->fileref)) perror ("I/O error"); } /* end if hwmark */ -free (uptr->filebuf); /* release buf */ -uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */ -uptr->filebuf = NULL; /* clear buf ptr */ -uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); /* default fmt */ -uptr->capac = DT_CAPAC; /* default size */ -return detach_unit (uptr); -} diff --git a/PDP18B/pdp18b_fpp.c b/PDP18B/pdp18b_fpp.c deleted file mode 100644 index 4b8eb99d..00000000 --- a/PDP18B/pdp18b_fpp.c +++ /dev/null @@ -1,781 +0,0 @@ -/* pdp18b_fpp.c: FP15 floating point processor simulator - - Copyright (c) 2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - fpp PDP-15 floating point processor - - The FP15 instruction format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 1 0 0 1| subop | microcoded modifiers | floating point - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - Indirection is always single level. - - The FP15 supports four data formats: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | S| 2's complement integer | A: integer - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | S| 2's complement integer (high) | A: extended integer - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 2's complement integer (low) | A+1 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | fraction (low) |SE|2's complement exponent| A: single floating - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |SF| fraction (high) | A+1 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |SE| 2's complement exponent | A: double floating - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |SF| fraction (high) | A+1 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | fraction (low) | A+2 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - -*/ - -#include "pdp18b_defs.h" - -/* Instruction */ - -#define FI_V_OP 8 /* subopcode */ -#define FI_M_OP 017 -#define FI_GETOP(x) (((x) >> FI_V_OP) & FI_M_OP) -#define FI_NOLOAD 0200 /* don't load */ -#define FI_DP 0100 /* single/double */ -#define FI_FP 0040 /* int/flt point */ -#define FI_NONORM 0020 /* don't normalize */ -#define FI_NORND 0010 /* don't round */ -#define FI_V_SGNOP 0 /* A sign change */ -#define FI_M_SGNOP 03 -#define FI_GETSGNOP(x) (((x) >> FI_V_SGNOP) & FI_M_SGNOP) - -/* Exception register */ - -#define JEA_V_SIGN 17 /* A sign */ -#define JEA_V_GUARD 16 /* guard */ -#define JEA_EAMASK 077777 /* exc address */ -#define JEA_OFF_OVF 0 /* ovf offset */ -#define JEA_OFF_UNF 2 /* unf offset */ -#define JEA_OFF_DIV 4 /* div offset */ -#define JEA_OFF_MM 6 /* mem mgt offset */ - -/* Status codes - must relate directly to JEA offsets */ - -#define FP_OK 0 /* no error - mbz */ -#define FP_OVF (JEA_OFF_OVF + 1) /* overflow */ -#define FP_UNF (JEA_OFF_UNF + 1) /* underflow */ -#define FP_DIV (JEA_OFF_DIV + 1) /* divide exception */ -#define FP_MM (JEA_OFF_MM + 1) /* mem mgt error */ - -/* Unpacked floating point fraction */ - -#define UFP_FH_CARRY 0400000 /* carry out */ -#define UFP_FH_NORM 0200000 /* normalized */ -#define UFP_FH_MASK 0377777 /* hi mask */ -#define UFP_FL_MASK 0777777 /* low mask */ -#define UFP_FL_SMASK 0777000 /* low mask, single */ -#define UFP_FL_SRND 0000400 /* round bit, single */ - -#define GET_SIGN(x) (((x) >> 17) & 1) -#define SEXT18(x) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK)) -#define SEXT9(x) (((x) & 0400)? ((x) | ~0377): ((x) & 0377)) - -enum fop { - FOP_TST, FOP_SUB, FOP_RSUB, FOP_MUL, - FOP_DIV, FOP_RDIV, FOP_LD, FOP_ST, - FOP_FLT, FOP_FIX, FOP_LFMQ, FOP_JEA, - FOP_ADD, FOP_BR, FOP_DIAG, FOP_UND }; - -struct ufp { - int32 exp; /* exponent */ - int32 sign; /* sign */ - int32 hi; /* hi frac, 17b */ - int32 lo; }; /* lo frac, 18b */ - -typedef struct ufp UFP; - -static int32 fir; /* instruction */ -static int32 jea; /* exc address */ -static int32 fguard; /* guard bit */ -static int32 stop_fpp = STOP_RSRV; /* stop if fp dis */ -static UFP fma; /* FMA */ -static UFP fmb; /* FMB */ -static UFP fmq; /* FMQ - hi,lo only */ - -extern int32 M[MAXMEMSIZE]; -extern int32 pcq[PCQ_SIZE]; -extern int32 pcq_p; -extern int32 PC; -extern int32 trap_pending, usmd; - -t_stat fp15_reset (DEVICE *dptr); -t_stat fp15_opnd (int32 ir, int32 addr, UFP *a); -t_stat fp15_store (int32 ir, int32 addr, UFP *a); -t_stat fp15_iadd (int32 ir, UFP *a, UFP *b, t_bool sub); -t_stat fp15_imul (int32 ir, UFP *a, UFP *b); -t_stat fp15_idiv (int32 ir, UFP *a, UFP *b); -t_stat fp15_fadd (int32 ir, UFP *a, UFP *b, t_bool sub); -t_stat fp15_fmul (int32 ir, UFP *a, UFP *b); -t_stat fp15_fdiv (int32 ir, UFP *a, UFP *b); -t_stat fp15_fix (int32 ir, UFP *a); -t_stat fp15_norm (int32 ir, UFP *a, UFP *b, t_bool rnd); -t_stat fp15_exc (int32 sta); -void fp15_asign (int32 ir, UFP *a); -void dp_add (UFP *a, UFP *b); -void dp_sub (UFP *a, UFP *b); -void dp_inc (UFP *a); -int32 dp_cmp (UFP *a, UFP *b); -void dp_mul (UFP *a, UFP *b); -void dp_lsh_1 (UFP *a, UFP *b); -void dp_rsh_1 (UFP *a, UFP *b); -void dp_dnrm_r (int32 ir, UFP *a, int32 sc); -void dp_swap (UFP *a, UFP *b); - -extern t_stat Read (int32 ma, int32 *dat, int32 cyc); -extern t_stat Write (int32 ma, int32 dat, int32 cyc); -extern t_stat Ia (int32 ma, int32 *ea, t_bool jmp); -extern int32 Incr_addr (int32 addr); -extern int32 Jms_word (int32 t); - -/* FPP data structures - - fpp_dev FPP device descriptor - fpp_unit FPP unit - fpp_reg FPP register list - fpp_mod FPP modifier list -*/ - -UNIT fpp_unit = { UDATA (NULL, 0, 0) }; - -REG fpp_reg[] = { - { ORDATA (FIR, fir, 12) }, - { ORDATA (EPA, fma.exp, 18) }, - { FLDATA (FMAS, fma.sign, 0) }, - { ORDATA (FMAH, fma.hi, 17) }, - { ORDATA (FMAL, fma.lo, 18) }, - { ORDATA (EPB, fmb.exp, 18) }, - { FLDATA (FMBS, fmb.sign, 0) }, - { ORDATA (FMBH, fmb.hi, 17) }, - { ORDATA (FMBL, fmb.lo, 18) }, - { FLDATA (FGUARD, fguard, 0) }, - { ORDATA (FMQH, fmq.hi, 17) }, - { ORDATA (FMQL, fmq.lo, 18) }, - { ORDATA (JEA, jea, 18) }, - { FLDATA (STOP_FPP, stop_fpp, 0) }, - { NULL } }; - -DEVICE fpp_dev = { - "FPP", &fpp_unit, fpp_reg, NULL, - 1, 8, 1, 1, 8, 18, - NULL, NULL, &fp15_reset, - NULL, NULL, NULL, - NULL, DEV_DISABLE | DEV_DIS }; - -/* Instruction decode for FP15 - - The CPU actually fetches the instruction and the word after. If the - instruction is 71XXXX, the CPU executes it as a NOP, and the FP15 fools - the CPU into thinking that the second word is also a NOP. - - Indirect addresses are resolved during fetch, unless the NOLOAD modifier - is set and the instruction is not a store. */ - -t_stat fp15 (int32 ir) -{ -int32 ar, ma, fop, dat; -t_stat sta = FP_OK; - -if (fpp_dev.flags & DEV_DIS) /* disabled? */ - return (stop_fpp? STOP_FPDIS: SCPE_OK); -fir = ir & 07777; /* save subop + mods */ -ma = PC; /* fetch next word */ -PC = Incr_addr (PC); -if (Read (ma, &ar, RD)) return fp15_exc (FP_MM); /* error? MM exc */ -fop = FI_GETOP (fir); /* get subopcode */ -if ((ar & SIGN) && /* indirect? */ - ((fop == FOP_ST) || !(ir & FI_NOLOAD))) { /* store or load? */ - ma = ar & AMASK; /* fetch indirect */ - if (Read (ma, &ar, RD)) return fp15_exc (FP_MM); } -fma.exp = SEXT18 (fma.exp); /* sext exponents */ -fmb.exp = SEXT18 (fmb.exp); -switch (fop) { /* case on subop */ - -case FOP_TST: /* NOP */ - break; - -case FOP_SUB: /* subtract */ - if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */ - if (fir & FI_FP) /* fp? */ - sta = fp15_fadd (fir, &fma, &fmb, 1); /* yes, fp sub */ - else sta = fp15_iadd (fir, &fma, &fmb, 1); /* no, int sub */ - break; - -case FOP_RSUB: /* reverse sub */ - fmb = fma; /* FMB <- FMA */ - if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ - if (fir & FI_FP) /* fp? */ - sta = fp15_fadd (fir, &fma, &fmb, 1); /* yes, fp sub */ - else sta = fp15_iadd (fir, &fma, &fmb, 1); /* no, int sub */ - break; - -case FOP_MUL: /* multiply */ - if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */ - if (fir & FI_FP) /* fp? */ - sta = fp15_fmul (fir, &fma, &fmb); /* yes, fp mul */ - else sta = fp15_imul (fir, &fma, &fmb); /* no, int mul */ - break; - -case FOP_DIV: /* divide */ - if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */ - if (fir & FI_FP) /* fp? */ - sta = fp15_fadd (fir, &fma, &fmb, 1); /* yes, fp sub */ - else sta = fp15_idiv (fir, &fma, &fmb); /* no, int div */ - break; - -case FOP_RDIV: /* reverse divide */ - fmb = fma; /* FMB <- FMA */ - if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ - if (fir & FI_FP) /* fp? */ - sta = fp15_fadd (fir, &fma, &fmb, 1); /* yes, fp sub */ - else sta = fp15_idiv (fir, &fma, &fmb); /* no, int div */ - break; - -case FOP_LD: /* load */ - if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ - fp15_asign (fir, &fma); /* modify A sign */ - if (fir & FI_FP) /* fp? */ - sta = fp15_norm (ir, &fma, NULL, 0); /* norm, no round */ - break; - -case FOP_ST: /* store */ - fp15_asign (fir, &fma); /* modify A sign */ - sta = fp15_store (fir, ar, &fma); /* store result */ - break; - -case FOP_FLT: /* float */ - if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ - fma.exp = 35; - fp15_asign (fir, &fma); /* adjust A sign */ - sta = fp15_norm (ir, &fma, NULL, 0); /* norm, no found */ - break; - -case FOP_FIX: /* fix */ - if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ - sta = fp15_fix (fir, &fma); /* fix */ - break; - -case FOP_LFMQ: /* load FMQ */ - if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ - dp_swap (&fma, &fmq); /* swap FMA, FMQ */ - fp15_asign (fir, &fma); /* adjust A sign */ - if (fir & FI_FP) /* fp? */ - sta = fp15_norm (ir, &fma, &fmq, 0); /* yes, norm, no rnd */ - break; - -case FOP_JEA: /* JEA */ - if (ir & 0200) { /* store? */ - dat = jea | (fma.sign << JEA_V_SIGN) | (fguard << JEA_V_GUARD); - sta = Write (ar, dat, WR); } - else { /* no, load */ - if (sta = Read (ar, &dat, RD)) break; - fguard = (dat >> JEA_V_GUARD) & 1; - jea = dat; } - break; - -case FOP_ADD: /* add */ - if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */ - if (fir & FI_FP) /* fp? */ - sta = fp15_fadd (fir, &fma, &fmb, 0); /* yes, fp add */ - else sta = fp15_iadd (fir, &fma, &fmb, 0); /* no, int add */ - break; - -case FOP_BR: /* branch */ - if (((fir & 001) && ((fma.hi | fma.lo) == 0)) || - ((fir & 002) && fma.sign) || - ((fir & 004) && !fma.sign) || - ((fir & 010) && ((fma.hi | fma.lo) != 0)) || - ((fir & 020) && fguard)) { /* cond met? */ - PCQ_ENTRY; /* save current PC */ - PC = (PC & BLKMASK) | (ar & IAMASK); } /* branch within 32K */ - break; - -default: - break; } - -fma.exp = fma.exp & DMASK; /* mask exp to 18b */ -fmb.exp = fmb.exp & DMASK; -if (sta != FP_OK) return fp15_exc (sta); /* error? */ -return SCPE_OK; -} - -/* Operand load and store */ - -t_stat fp15_opnd (int32 ir, int32 addr, UFP *fpn) -{ -int32 i, numwd, wd[3]; - -fguard = 0; /* clear guard */ -if (ir & FI_NOLOAD) return FP_OK; /* no load? */ -if (ir & FI_FP) numwd = 2; /* fp? at least 2 */ -else numwd = 1; /* else at least 1 */ -if (ir & FI_DP) numwd = numwd + 1; /* dp? 1 more */ -for (i = 0; i < numwd; i++) { /* fetch words */ - if (Read (addr, &wd[i], RD)) return FP_MM; - addr = (addr + 1) & AMASK; } -if (ir & FI_FP) { /* fp? */ - fpn->sign = GET_SIGN (wd[1]); /* frac sign */ - fpn->hi = wd[1] & UFP_FH_MASK; /* frac high */ - if (ir & FI_DP) { /* dp? */ - fpn->exp = SEXT18 (wd[0]); /* exponent */ - fpn->lo = wd[2]; } /* frac low */ - else { /* sp */ - fpn->exp = SEXT9 (wd[0]); /* exponent */ - fpn->lo = wd[0] & UFP_FL_SMASK; } /* frac low */ - } -else { fpn->sign = GET_SIGN (wd[0]); /* int, get sign */ - if (ir & FI_DP) { /* dp? */ - fpn->lo = wd[1]; /* 2 words */ - fpn->hi = wd[0]; } - else { /* single */ - fpn->lo = wd[0]; /* 1 word */ - fpn->hi = fpn->sign? DMASK: 0; } /* sign extended */ - if (fpn->sign) { /* negative? */ - fpn->lo = (-fpn->lo) & UFP_FL_MASK; /* take abs val */ - fpn->hi = (~fpn->hi + (fpn->lo == 0)) & UFP_FH_MASK; } - } -return FP_OK; -} - -t_stat fp15_store (int32 ir, int32 addr, UFP *a) -{ -int32 i, numwd, wd[3]; -t_stat sta; - -fguard = 0; /* clear guard */ -if (ir & FI_FP) { /* fp? */ - if (sta = fp15_norm (ir, a, NULL, 0)) return sta; /* normalize */ - wd[1] = (a->sign << 17) | a->hi; /* hi frac */ - if (ir & FI_DP) { /* dp? */ - numwd = 3; /* 3 words */ - wd[0] = a->exp & DMASK; /* exponent */ - wd[2] = a->lo; } /* low frac */ - else { /* single */ - if (!(ir & FI_NORND) && (a->lo & UFP_FL_SRND)) { /* round? */ - a->lo = (a->lo + UFP_FL_SRND) & UFP_FL_SMASK; - a->hi = (a->hi + (a->lo == 0)) & UFP_FH_MASK; - if ((a->hi | a->lo) == 0) { /* carry out? */ - a->hi = UFP_FH_NORM; /* shift back */ - a->exp = a->exp + 1; } } - if (a->exp > 0377) return FP_OVF; /* sp ovf? */ - if (a->exp < -0400) return FP_UNF; /* sp unf? */ - numwd = 2; /* 2 words */ - wd[0] = (a->exp & 0777) | a->lo; } /* low frac'exp */ - } -else { fmb.lo = (-a->lo) & UFP_FL_MASK; /* 2's complement */ - fmb.hi = (~a->hi + (fmb.lo == 0)) & UFP_FH_MASK;/* to FMB */ - if (ir & FI_DP) { /* dp? */ - numwd = 2; /* 2 words */ - if (a->sign) { /* negative? */ - wd[0] = fmb.hi | SIGN; /* store FMB */ - wd[1] = fmb.lo; } - else { /* pos, store FMA */ - wd[0] = a->hi; - wd[1] = a->lo; } } - else { /* single */ - if (a->hi || (a->lo & SIGN)) return FP_OVF; /* check int ovf */ - numwd = 1; /* 1 word */ - if (a->sign) wd[0] = fmb.lo; /* neg? store FMB */ - else wd[0] = a->lo; } /* pos, store FMA */ - } -for (i = 0; i < numwd; i++) { /* store words */ - if (Write (addr, wd[i], WR)) return FP_MM; - addr = (addr + 1) & AMASK; } -return FP_OK; -} - -/* Integer arithmetic routines */ - -/* Integer add - overflow only on add, if carry out of high fraction */ - -t_stat fp15_iadd (int32 ir, UFP *a, UFP *b, t_bool sub) -{ -fmq.hi = fmq.lo = 0; /* clear FMQ */ -if (a->sign ^ b->sign ^ sub) dp_sub (a, b); /* eff subtract? */ -else { dp_add (a, b); /* no, add */ - if (a->hi & UFP_FH_CARRY) { /* carry out? */ - a->hi = a->hi & UFP_FH_MASK; /* mask to 35b */ - return FP_OVF; } } /* overflow */ -fp15_asign (ir, a); /* adjust A sign */ -return FP_OK; -} - -/* Integer multiply - overflow if high result (FMQ after swap) non-zero */ - -t_stat fp15_imul (int32 ir, UFP *a, UFP *b) -{ -a->sign = a->sign ^ b->sign; /* sign of result */ -dp_mul (a, b); /* a'FMQ <- a * b */ -dp_swap (a, &fmq); /* swap a, FMQ */ -if (fmq.hi | fmq.lo) return FP_OVF; /* FMQ != 0? ovf */ -fp15_asign (ir, a); /* adjust A sign */ -return FP_OK; -} - -/* Integer divide - actually done as fraction divide - - - If divisor zero, error - - If dividend zero, done - - Normalize dividend and divisor together - - If divisor normalized but dividend not, result is zero - - If divisor not normalized, normalize and count shifts - - Do fraction divide for number of shifts, +1, steps - - Note that dp_lsh_1 returns a 72b result; the last right shift - guarantees a 71b remainder. The quotient cannot exceed 71b */ - -t_stat fp15_idiv (int32 ir, UFP *a, UFP *b) -{ -int32 i, sc; - -a->sign = a->sign ^ b->sign; /* sign of result */ -fmq.hi = fmq.lo = 0; /* clear quotient */ -a->exp = 0; /* clear a exp */ -if ((b->hi | b->lo) == 0) return FP_DIV; /* div by 0? */ -if ((a->hi | a->lo) == 0) return FP_OK; /* div into 0? */ -while (((a->hi & UFP_FH_NORM) == 0) && /* normalize divd */ - ((b->hi & UFP_FH_NORM) == 0)) { /* and divr */ - dp_lsh_1 (a, NULL); /* lsh divd, divr */ - dp_lsh_1 (b, NULL); } /* can't carry out */ -if (!(a->hi & UFP_FH_NORM) && (b->hi & UFP_FH_NORM)) { /* divr norm, divd not? */ - a->hi = a->lo = 0; /* result is 0 */ - return FP_OK; } -while ((b->hi & UFP_FH_NORM) == 0) { /* normalize divr */ - dp_lsh_1 (b, NULL); /* can't carry out */ - a->exp = a->exp + 1; } /* count steps */ -sc = a->exp; -for (i = 0; i <= sc; i++) { /* n+1 steps */ - dp_lsh_1 (&fmq, NULL); /* left shift quo */ - if (dp_cmp (a, b) >= 0) { /* sub work? */ - dp_sub (a, b); /* a -= b */ - if (i == 0) a->exp = a->exp + 1; /* first step? */ - fmq.lo = fmq.lo | 1; } /* set quo bit */ - dp_lsh_1 (a, NULL); } /* left shift divd */ -dp_rsh_1 (a, NULL); /* shift back */ -dp_swap (a, &fmq); /* swap a, FMQ */ -fp15_asign (ir, a); /* adjust A sign */ -return FP_OK; -} - -/* Floating point arithmetic routines */ - -/* Floating add - - Special add case, overflow if carry out increments exp out of range - - All cases, overflow/underflow detected in normalize */ - -t_stat fp15_fadd (int32 ir, UFP *a, UFP *b, t_bool sub) -{ -int32 ediff; - -fmq.hi = fmq.lo = 0; /* clear FMQ */ -ediff = a->exp - b->exp; /* exp diff */ -if (((a->hi | a->lo) == 0) || (ediff < -35)) { /* a = 0 or "small"? */ - *a = *b; /* rslt is b */ - a->sign = a->sign ^ sub; } /* or -b if sub */ -else if (((b->hi | b->lo) != 0) && (ediff <= 35)) { /* b!=0 && ~"small"? */ - if (ediff > 0) dp_dnrm_r (ir, b, ediff); /* |a| > |b|? dnorm b */ - else if (ediff < 0) { /* |a| < |b|? */ - a->exp = b->exp; /* b exp is rslt */ - dp_dnrm_r (ir, a, -ediff); } /* denorm A */ - if (a->sign ^ b->sign ^ sub) dp_sub (a, b); /* eff sub? */ - else { /* eff add */ - dp_add (a, b); /* add */ - if (a->hi & UFP_FH_CARRY) { /* carry out? */ - fguard = a->lo & 1; /* set guard */ - dp_rsh_1 (a, NULL); /* right shift */ - a->exp = a->exp + 1; /* incr exponent */ - if (!(ir & FI_NORND) && fguard) /* rounding? */ - dp_inc (a); - if (a->exp > 0377777) return FP_OVF; } } - } /* end if b != 0 */ -fp15_asign (ir, a); /* adjust A sign */ -return fp15_norm (ir, a, NULL, 0); /* norm, no round */ -} - -/* Floating multiply - overflow/underflow detected in normalize */ - -t_stat fp15_fmul (int32 ir, UFP *a, UFP *b) -{ -a->sign = a->sign ^ b->sign; /* sign of result */ -a->exp = a->exp + b->exp; /* exp of result */ -dp_mul (a, b); /* mul fractions */ -fp15_asign (ir, a); /* adjust A sign */ -return fp15_norm (ir, a, &fmq, 1); /* norm and round */ -} - -/* Floating divide - overflow/underflow detected in normalize */ - -t_stat fp15_fdiv (int32 ir, UFP *a, UFP *b) -{ -int32 i; - -a->sign = a->sign ^ b->sign; /* sign of result */ -a->exp = a->exp - b->exp; /* exp of result */ -fmq.hi = fmq.lo = 0; /* clear quotient */ -if (!(b->hi & UFP_FH_NORM)) return FP_DIV; /* divr not norm? */ -if (a->hi | a->lo) { /* divd non-zero? */ - fp15_norm (0, a, NULL, 0); /* normalize divd */ - for (i = 0; (fmq.hi & UFP_FH_NORM) == 0; i++) { /* until quo */ - dp_lsh_1 (&fmq, NULL); /* left shift quo */ - if (dp_cmp (a, b) >= 0) { /* sub work? */ - dp_sub (a, b); /* a -= b */ - if (i == 0) a->exp = a->exp + 1; - fmq.lo = fmq.lo | 1; } /* set quo bit */ - dp_lsh_1 (a, NULL); } /* left shift divd */ - dp_rsh_1 (a, NULL); /* shift back */ - dp_swap (a, &fmq); } /* swap a, FMQ */ -fp15_asign (ir, a); /* adjust A sign */ -return fp15_norm (ir, a, &fmq, 1); /* norm and round */ -} - -/* Floating to integer - overflow only if exponent out of range */ - -t_stat fp15_fix (int32 ir, UFP *a) -{ -int32 i; - -fmq.hi = fmq.lo = 0; /* clear FMQ */ -if (a->exp > 35) return FP_OVF; /* exp > 35? ovf */ -if (a->exp < 0) a->hi = a->lo = 0; /* exp <0 ? rslt 0 */ -else { for (i = a->exp; i < 35; i++) /* denorm frac */ - dp_rsh_1 (a, &fmq); - if (fmq.hi & UFP_FH_NORM) { /* last out = 1? */ - fguard = 1; /* set guard */ - if (!(ir & FI_NORND)) dp_inc (a); } } /* round */ -fp15_asign (ir, a); /* adjust A sign */ -return FP_OK; -} - -/* Double precision routines */ - -/* Double precision add - returns 72b result (including carry) */ - -void dp_add (UFP *a, UFP *b) -{ -a->lo = (a->lo + b->lo) & UFP_FL_MASK; /* add low */ -a->hi = a->hi + b->hi + (a->lo < b->lo); /* add hi + carry */ -return; -} - -/* Double precision increment - returns 72b result (including carry) */ - -void dp_inc (UFP *a) -{ -a->lo = (a->lo + 1) & UFP_FL_MASK; /* inc low */ -a->hi = a->hi + (a->lo == 0); /* propagate carry */ -return; -} - -/* Double precision subtract - result always fits in 71b */ - -void dp_sub (UFP *a, UFP *b) -{ -if (dp_cmp (a,b) >= 0) { /* |a| >= |b|? */ - a->hi = (a->hi - b->hi - (a->lo < b->lo)) & UFP_FH_MASK; - a->lo = (a->lo - b->lo) & UFP_FL_MASK; } /* a - b */ -else { a->hi = (b->hi - a->hi - (b->lo < a->lo)) & UFP_FH_MASK; - a->lo = (b->lo - a->lo) & UFP_FL_MASK; /* b - a */ - a->sign = a->sign ^ 1; } /* change a sign */ -return; -} - -/* Double precision compare - returns +1 (>), 0 (=), -1 (<) */ - -int32 dp_cmp (UFP *a, UFP *b) -{ -if (a->hi < b->hi) return -1; -if (a->hi > b->hi) return +1; -if (a->lo < b->lo) return -1; -if (a->lo > b->lo) return +1; -return 0; -} - -/* Double precision multiply - returns 70b result */ - -void dp_mul (UFP *a, UFP *b) -{ -int32 i; - -fmq.hi = a->hi; /* FMQ <- a */ -fmq.lo = a->lo; -a->hi = a->lo = 0; /* a <- 0 */ -if (((fmq.hi | fmq.lo) == 0) || ((b->hi | b->lo) == 0)) return; -for (i = 0; i < 35; i++) { /* 35 iterations */ - if (fmq.lo & 1) dp_add (a, b); /* FMQ<35>? a += b */ - dp_rsh_1 (a, &fmq); } /* rsh a'FMQ */ -return; -} - -/* Double (quad) precision left shift - returns 72b (143b) result */ - -void dp_lsh_1 (UFP *a, UFP *b) -{ -int32 t = b? b->lo: 0; - -a->hi = (a->hi << 1) | (a->lo >> 17); -a->lo = ((a->lo << 1) | (t >> 16)) & UFP_FL_MASK; -if (b) { - b->hi = ((b->hi << 1) | (b->lo >> 17)) & UFP_FH_MASK; - b->lo = (b->lo << 1) & UFP_FL_MASK; } -return; -} - -/* Double (quad) precision right shift - returns 71b (142b) result */ - -void dp_rsh_1 (UFP *a, UFP *b) -{ -if (b) { - b->lo = (b->lo >> 1) | ((b->hi & 1) << 17); - b->hi = (b->hi >> 1) | ((a->lo & 1) << 16); } -a->lo = (a->lo >> 1) | ((a->hi & 1) << 17); -a->hi = a->hi >> 1; -return; -} - -/* Double precision denormalize and round - returns 71b result */ - -void dp_dnrm_r (int32 ir, UFP *a, int32 sc) -{ -int32 i; - -if (sc <= 0) return; /* legit? */ -for (i = 0; i < sc; i++) dp_rsh_1 (a, &fmq); /* dnorm to fmq */ -if (!(ir & FI_NORND) && (fmq.hi & UFP_FH_NORM)) /* round & fmq<1>? */ - dp_inc (a); /* incr a */ -return; -} - -/* Double precision swap */ - -void dp_swap (UFP *a, UFP *b) -{ -int32 t; - -t = a->hi; /* swap fractions */ -a->hi = b->hi; -b->hi = t; -t = a->lo; -a->lo = b->lo; -b->lo = t; -return; -} - -/* Support routines */ - -void fp15_asign (int32 fir, UFP *a) -{ -int32 sgnop = FI_GETSGNOP (fir); - -switch (sgnop) { /* modify FMA sign */ -case 1: - a->sign = 0; - break; -case 2: - a->sign = 1; - break; -case 3: - a->sign = a->sign ^ 1; - break; -default: - break; } -return; -} - -/* FP15 normalization and rounding - - - Do normalization if enabled (NOR phase, part 1) - Normalization also does zero detect - - Do rounding if enabled (NOR phase, part 2) */ - -t_stat fp15_norm (int32 ir, UFP *a, UFP *b, t_bool rnd) -{ -if (!(ir & FI_NONORM)) { /* norm enabled? */ - if ((a->hi | a->lo) || (b && (b->hi | b->lo))) { /* frac != 0? */ - while ((a->hi & UFP_FH_NORM) == 0) { /* until norm */ - dp_lsh_1 (a, b); /* lsh a'b, no cry */ - a->exp = a->exp - 1; } } /* decr exp */ - else a->sign = a->exp = 0; } /* true zero */ -if (rnd && b && (b->hi & UFP_FH_NORM)) { /* rounding? */ - fguard = 1; /* set guard */ - if (!(ir & FI_NORND)) { /* round enabled? */ - dp_inc (a); /* add 1 */ - if (a->hi & UFP_FH_CARRY) { /* carry out? */ - a->hi = UFP_FH_NORM; /* set hi bit */ - a->exp = a->exp + 1; } } } /* incr exp */ -if (a->exp > 0377777) return FP_OVF; /* overflow? */ -if (a->exp < -0400000) return FP_UNF; /* underflow? */ -return FP_OK; -} - -/* Exception */ - -t_stat fp15_exc (t_stat sta) -{ -int32 ma, mb; - -if (sta == FP_MM) trap_pending = 0; /* if mm, kill trap */ -ma = (jea & JEA_EAMASK) + sta - 1; /* JEA address */ -PCQ_ENTRY; /* record branch */ -PC = Incr_addr (PC); /* PC+1 for "JMS" */ -mb = Jms_word (usmd); /* form JMS word */ -if (Write (ma, mb, WR)) return SCPE_OK; /* store */ -PC = (jea + 1) & IAMASK; /* new PC */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat fp15_reset (DEVICE *dptr) -{ -jea = 0; -fir = 0; -fguard = 0; -fma.exp = fma.hi = fma.lo = fma.sign = 0; -fmb.exp = fmb.hi = fmb.lo = fmb.sign = 0; -fmq.exp = fmq.hi = fmq.lo = fmq.sign = 0; -return SCPE_OK; -} diff --git a/PDP18B/pdp18b_lp.c b/PDP18B/pdp18b_lp.c deleted file mode 100644 index 3ef218a6..00000000 --- a/PDP18B/pdp18b_lp.c +++ /dev/null @@ -1,783 +0,0 @@ -/* pdp18b_lp.c: 18b PDP's line printer simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - lp62 (PDP-4) Type 62 line printer - lp647 (PDP-7,9) Type 647 line printer - lp09 (PDP-9,15) LP09 line printer - lp15 (PDP-15) LP15 line printer - - 23-Jul-03 RMS Fixed overprint bug in Type 62 - 25-Apr-03 RMS Revised for extended file support - 05-Feb-03 RMS Added LP09, fixed conditionalization - 05-Oct-02 RMS Added DIB, device number support - 30-May-02 RMS Widened POS to 32b - 03-Feb-02 RMS Fixed typo (found by Robert Alan Byer) - 25-Nov-01 RMS Revised interrupt structure - 19-Sep-01 RMS Fixed bug in 647 - 13-Feb-01 RMS Revised for register arrays - 15-Feb-01 RMS Fixed 3 cycle data break sequence - 30-Oct-00 RMS Standardized register naming - 20-Aug-98 RMS Fixed compilation problem in BeOS - 03-Jan-97 RMS Fixed bug in Type 62 state handling -*/ - -#include "pdp18b_defs.h" -extern int32 int_hwre[API_HLVL+1]; - -#if defined (TYPE62) - -/* Type 62 line printer */ - -#define LP62_BSIZE 120 /* line size */ -#define BPTR_MAX 40 /* pointer max */ -#define BPTR_MASK 077 /* buf ptr max */ - -int32 lp62_spc = 0; /* print vs spc */ -int32 lp62_ovrpr = 0; /* overprint */ -int32 lp62_stopioe = 0; -int32 lp62_bp = 0; /* buffer ptr */ -char lp62_buf[LP62_BSIZE + 1] = { 0 }; -static const char lp62_trans[64] = { - ' ','1','2','3','4','5','6','7','8','9','\'','~','#','V','^','<', - '0','/','S','T','U','V','W','X','Y','Z','"',',','>','^','-','?', - 'o','J','K','L','M','N','O','P','Q','R','$','=','-',')','-','(', - '_','A','B','C','D','E','F','G','H','I','*','.','+',']','|','[' }; -static const char *lp62_cc[] = { - "\n", - "\n\n", - "\n\n\n", - "\n\n\n\n\n\n", - "\n\n\n\n\n\n\n\n\n\n\n", - "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", - "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", - "\f" }; - -DEVICE lp62_dev; -int32 lp62_65 (int32 pulse, int32 dat); -int32 lp62_66 (int32 pulse, int32 dat); -int32 lp62_iors (void); -t_stat lp62_svc (UNIT *uptr); -t_stat lp62_reset (DEVICE *dptr); - -/* Type 62 LPT data structures - - lp62_dev LPT device descriptor - lp62_unit LPT unit - lp62_reg LPT register list -*/ - -DIB lp62_dib = { DEV_LPT, 2, &lp62_iors, { &lp62_65, &lp62_66 } }; - -UNIT lp62_unit = { - UDATA (&lp62_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lp62_reg[] = { - { ORDATA (BUF, lp62_unit.buf, 8) }, - { FLDATA (INT, int_hwre[API_LPT], INT_V_LPT) }, - { FLDATA (DONE, int_hwre[API_LPT], INT_V_LPT) }, - { FLDATA (SPC, int_hwre[API_LPTSPC], INT_V_LPTSPC) }, - { DRDATA (BPTR, lp62_bp, 6) }, - { ORDATA (STATE, lp62_spc, 6), REG_HRO }, - { FLDATA (OVRPR, lp62_ovrpr, 0), REG_HRO }, - { DRDATA (POS, lp62_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, lp62_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lp62_stopioe, 0) }, - { BRDATA (LBUF, lp62_buf, 8, 8, LP62_BSIZE) }, - { ORDATA (DEVNO, lp62_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB lp62_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE lp62_dev = { - "LPT", &lp62_unit, lp62_reg, lp62_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lp62_reset, - NULL, NULL, NULL, - &lp62_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 lp62_65 (int32 pulse, int32 dat) -{ -int32 i; - -if ((pulse & 01) && TST_INT (LPT)) dat = IOT_SKP | dat; /* LPSF */ -if (pulse & 02) { - int32 sb = pulse & 060; /* subopcode */ - if (sb == 000) CLR_INT (LPT); /* LPCF */ - if ((sb == 040) && (lp62_bp < BPTR_MAX)) { /* LPLD */ - i = lp62_bp * 3; /* cvt to chr ptr */ - lp62_buf[i] = lp62_trans[(dat >> 12) & 077]; - lp62_buf[i + 1] = lp62_trans[(dat >> 6) & 077]; - lp62_buf[i + 2] = lp62_trans[dat & 077]; - lp62_bp = (lp62_bp + 1) & BPTR_MASK; } - } -if (pulse & 04) { /* LPSE */ - lp62_spc = 0; /* print */ - sim_activate (&lp62_unit, lp62_unit.wait); } /* activate */ -return dat; -} - -int32 lp62_66 (int32 pulse, int32 dat) -{ -if ((pulse & 01) && TST_INT (LPTSPC)) /* LSSF */ - dat = IOT_SKP | dat; -if (pulse & 02) CLR_INT (LPTSPC); /* LSCF */ -if (pulse & 04) { /* LSPR */ - lp62_spc = 020 | (dat & 07); /* space */ - sim_activate (&lp62_unit, lp62_unit.wait); } /* activate */ -return dat; -} - -/* Unit service, action based on lp62_spc - - lp62_spc = 0 write buffer to file, set overprint - lp62_spc = 2x space command x, clear overprint -*/ - -t_stat lp62_svc (UNIT *uptr) -{ -int32 i; - -if (lp62_spc) { /* space? */ - SET_INT (LPTSPC); /* set flag */ - if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lp62_stopioe, SCPE_UNATT); - fputs (lp62_cc[lp62_spc & 07], uptr->fileref); /* print cctl */ - if (ferror (uptr->fileref)) { /* error? */ - perror ("LPT I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } - lp62_ovrpr = 0; } /* clear overprint */ -else { SET_INT (LPT); /* print */ - if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lp62_stopioe, SCPE_UNATT); - if (lp62_ovrpr) fputc ('\r', uptr->fileref); /* overprint? */ - fputs (lp62_buf, uptr->fileref); /* print buffer */ - if (ferror (uptr->fileref)) { /* test error */ - perror ("LPT I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } - lp62_bp = 0; - for (i = 0; i <= LP62_BSIZE; i++) lp62_buf[i] = 0; /* clear buffer */ - lp62_ovrpr = 1; } /* set overprint */ -uptr->pos = ftell (uptr->fileref); /* update position */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lp62_reset (DEVICE *dptr) -{ -int32 i; - -CLR_INT (LPT); /* clear intrs */ -CLR_INT (LPTSPC); -sim_cancel (&lp62_unit); /* deactivate unit */ -lp62_bp = 0; /* clear buffer ptr */ -for (i = 0; i <= LP62_BSIZE; i++) lp62_buf[i] = 0; /* clear buffer */ -lp62_spc = 0; /* clear state */ -lp62_ovrpr = 0; /* clear overprint */ -return SCPE_OK; -} - -/* IORS routine */ - -int32 lp62_iors (void) -{ -return (TST_INT (LPT)? IOS_LPT: 0) | - (TST_INT (LPTSPC)? IOS_LPT1: 0); -} - -#endif - -#if defined (TYPE647) - -/* Type 647 line printer */ - -#define LP647_BSIZE 120 /* line size */ - -int32 lp647_don = 0; /* ready */ -int32 lp647_ie = 1; /* int enable */ -int32 lp647_err = 0; /* error */ -int32 lp647_iot = 0; /* saved state */ -int32 lp647_stopioe = 0; -int32 lp647_bp = 0; /* buffer ptr */ -char lp647_buf[LP647_BSIZE] = { 0 }; -static const char *lp647_cc[] = { - "\n", - "\n\n", - "\n\n\n", - "\n\n\n\n\n\n", - "\n\n\n\n\n\n\n\n\n\n\n", - "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", - "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", - "\f" }; - -DEVICE lp647_dev; -int32 lp647_65 (int32 pulse, int32 dat); -int32 lp647_66 (int32 pulse, int32 dat); -int32 lp647_iors (void); -t_stat lp647_svc (UNIT *uptr); -t_stat lp647_reset (DEVICE *dptr); -t_stat lp647_attach (UNIT *uptr, char *cptr); -t_stat lp647_detach (UNIT *uptr); - -/* Type 647 LPT data structures - - lp647_dev LPT device descriptor - lp647_unit LPT unit - lp647_reg LPT register list -*/ - -DIB lp647_dib = { DEV_LPT, 2, &lp647_iors, { &lp647_65, &lp647_66 } }; - -UNIT lp647_unit = { - UDATA (&lp647_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lp647_reg[] = { - { ORDATA (BUF, lp647_unit.buf, 8) }, - { FLDATA (INT, int_hwre[API_LPT], INT_V_LPT) }, - { FLDATA (DONE, lp647_don, 0) }, -#if defined (PDP9) - { FLDATA (ENABLE, lp647_ie, 0) }, -#endif - { FLDATA (ERR, lp647_err, 0) }, - { DRDATA (BPTR, lp647_bp, 7) }, - { ORDATA (SCMD, lp647_iot, 6), REG_HRO }, - { DRDATA (POS, lp647_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, lp647_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lp647_stopioe, 0) }, - { BRDATA (LBUF, lp647_buf, 8, 8, LP647_BSIZE) }, - { ORDATA (DEVNO, lp647_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB lp647_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE lp647_dev = { - "LPT", &lp647_unit, lp647_reg, lp647_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lp647_reset, - NULL, &lp647_attach, &lp647_detach, - &lp647_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 lp647_65 (int32 pulse, int32 dat) -{ -int32 i, sb; - -sb = pulse & 060; /* subcode */ -if ((pulse & 01) && lp647_don) dat = IOT_SKP | dat; /* LPSF */ -if (pulse & 02) { /* pulse 02 */ - lp647_don = 0; /* clear done */ - CLR_INT (LPT); /* clear int req */ - if (sb == 000) { /* LPCB */ - for (i = 0; i < LP647_BSIZE; i++) lp647_buf[i] = 0; - lp647_bp = 0; /* reset buf ptr */ - lp647_don = 1; /* set done */ - if (lp647_ie) SET_INT (LPT); } /* set int */ - } -if (pulse & 004) { /* LPDI */ - switch (sb) { /* case on subcode */ - case 000: /* LPDI */ -#if defined (PDP9) - lp647_ie = 0; /* clear int enable */ - CLR_INT (LPT); /* clear int req */ -#endif - break; - case 040: /* LPB3 */ - if (lp647_bp < LP647_BSIZE) { - lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | ((dat >> 12) & 077); - lp647_bp = lp647_bp + 1; } - case 020: /* LPB2 */ - if (lp647_bp < LP647_BSIZE) { - lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | ((dat >> 6) & 077); - lp647_bp = lp647_bp + 1; } - case 060: /* LPB1 */ - if (lp647_bp < LP647_BSIZE) { - lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | (dat & 077); - lp647_bp = lp647_bp + 1; } - lp647_don = 1; /* set done */ - if (lp647_ie) SET_INT (LPT); /* set int */ - break; } /* end case */ - } -return dat; -} - -int32 lp647_66 (int32 pulse, int32 dat) -{ -if ((pulse & 01) && lp647_err) dat = IOT_SKP | dat; /* LPSE */ -if (pulse & 02) { /* LPCF */ - lp647_don = 0; /* clear done, int */ - CLR_INT (LPT); } -if (pulse & 04) { - if ((pulse & 060) < 060) { /* LPLS, LPPB, LPPS */ - lp647_iot = (pulse & 060) | (dat & 07); /* save parameters */ - sim_activate (&lp647_unit, lp647_unit.wait); } /* activate */ -#if defined (PDP9) - else { /* LPEI */ - lp647_ie = 1; /* set int enable */ - if (lp647_don) SET_INT (LPT); } -#endif - } -return dat; -} - -/* Unit service. lp647_iot specifies the action to be taken - - lp647_iot = 0x print only - lp647_iot = 2x space only, x is spacing command - lp647_iot = 4x print then space, x is spacing command -*/ - -t_stat lp647_svc (UNIT *uptr) -{ -int32 i; -char pbuf[LP647_BSIZE + 1]; - -lp647_don = 1; -if (lp647_ie) SET_INT (LPT); /* set flag */ -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - lp647_err = 1; /* set error */ - return IORETURN (lp647_stopioe, SCPE_UNATT); } -if ((lp647_iot & 020) == 0) { /* print? */ - for (i = 0; i < lp647_bp; i++) /* translate buffer */ - pbuf[i] = lp647_buf[i] | ((lp647_buf[i] >= 040)? 0: 0100); - if ((lp647_iot & 060) == 0) pbuf[lp647_bp++] = '\r'; - for (i = 0; i < LP647_BSIZE; i++) lp647_buf[i] = 0; /* clear buffer */ - fwrite (pbuf, 1, lp647_bp, uptr->fileref); /* print buffer */ - if (ferror (uptr->fileref)) { /* error? */ - perror ("LPT I/O error"); - clearerr (uptr->fileref); - lp647_bp = 0; - return SCPE_IOERR; } - lp647_bp = 0; } /* clear buffer ptr */ -if (lp647_iot & 060) { /* space? */ - fputs (lp647_cc[lp647_iot & 07], uptr->fileref); /* write cctl */ - if (ferror (uptr->fileref)) { /* error? */ - perror ("LPT I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } } -uptr->pos = ftell (uptr->fileref); /* update position */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lp647_reset (DEVICE *dptr) -{ -int32 i; - -lp647_don = 0; /* clear done */ -lp647_err = (lp647_unit.flags & UNIT_ATT)? 0: 1; /* clr/set error */ -lp647_ie = 1; /* set enable */ -CLR_INT (LPT); /* clear int */ -sim_cancel (&lp647_unit); /* deactivate unit */ -lp647_bp = 0; /* clear buffer ptr */ -lp647_iot = 0; /* clear state */ -for (i = 0; i < LP647_BSIZE; i++) lp647_buf[i] = 0; /* clear buffer */ -return SCPE_OK; -} - -/* IORS routine */ - -int32 lp647_iors (void) -{ -return (lp647_don? IOS_LPT: 0) | (lp647_err? IOS_LPT1: 0); -} - -/* Attach routine */ - -t_stat lp647_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); -lp647_err = (lp647_unit.flags & UNIT_ATT)? 0: 1; /* clr/set error */ -return reason; -} - -/* Detach routine */ - -t_stat lp647_detach (UNIT *uptr) -{ -lp647_err = 1; -return detach_unit (uptr); -} - -#endif - -#if defined (LP09) - -/* LP09 line printer */ - -#define LP09_BSIZE 132 /* line size */ - -int32 lp09_don = 0; /* ready */ -int32 lp09_err = 0; /* error */ -int32 lp09_ie = 1; /* int enable */ -int32 lp09_stopioe = 0; -DEVICE lp09_dev; - -int32 lp09_66 (int32 pulse, int32 dat); -int32 lp09_iors (void); -t_stat lp09_svc (UNIT *uptr); -t_stat lp09_reset (DEVICE *dptr); -t_stat lp09_attach (UNIT *uptr, char *cptr); -t_stat lp09_detach (UNIT *uptr); - -/* LP09 LPT data structures - - lp09_dev LPT device descriptor - lp09_unit LPT unit - lp09_reg LPT register list -*/ - -DIB lp09_dib = { DEV_LPT, 2, &lp09_iors, { NULL, &lp09_66 } }; - -UNIT lp09_unit = { - UDATA (&lp09_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lp09_reg[] = { - { ORDATA (BUF, lp09_unit.buf, 7) }, - { FLDATA (INT, int_hwre[API_LPT], INT_V_LPT) }, - { FLDATA (DONE, lp09_don, 0) }, - { FLDATA (ENABLE, lp09_ie, 0) }, - { FLDATA (ERR, lp09_err, 0) }, - { DRDATA (POS, lp09_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, lp09_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lp09_stopioe, 0) }, - { ORDATA (DEVNO, lp09_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB lp09_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE lp09_dev = { - "LP9", &lp09_unit, lp09_reg, lp09_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lp09_reset, - NULL, &lp09_attach, &lp09_detach, - &lp09_dib, DEV_DISABLE | DEV_DIS }; - -/* IOT routines */ - -int32 lp09_66 (int32 pulse, int32 dat) -{ -int32 sb = pulse & 060; /* subopcode */ - -if (pulse & 001) { - if ((sb == 000) && lp09_don) dat = IOT_SKP | dat; /* LSDF */ - if ((sb == 020) && lp09_err) dat = IOT_SKP | dat; /* LSEF */ - } -if (pulse & 002) { - if (sb == 000) { /* LSCF */ - lp09_don = 0; /* clear done, int */ - CLR_INT (LPT); } - else if (sb == 020) { /* LPLD */ - lp09_don = 0; /* clear done, int */ - CLR_INT (LPT); - lp09_unit.buf = dat & 0177; /* load char */ - if ((lp09_unit.buf == 015) || (lp09_unit.buf == 014) || - (lp09_unit.buf == 012)) - sim_activate (&lp09_unit, lp09_unit.wait); - else dat = dat | (lp09_svc (&lp09_unit) << IOT_V_REASON); } - } -if (pulse & 004) { - if (sb == 000) { /* LIOF */ - lp09_ie = 0; /* clear int enab */ - CLR_INT (LPT); } /* clear int */ - else if (sb == 040) { /* LION */ - lp09_ie = 1; /* set int enab */ - if (lp09_don) SET_INT (LPT); } /* if done, set int */ - } -return dat; -} - -/* Unit service */ - -t_stat lp09_svc (UNIT *uptr) -{ -int32 c; - -lp09_don = 1; /* set done */ -if (lp09_ie) SET_INT (LPT); /* int enb? req int */ -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - lp09_err = 1; /* set error */ - return IORETURN (lp09_stopioe, SCPE_UNATT); } -c = uptr->buf & 0177; /* get char */ -if ((c == 0) || (c == 0177)) return SCPE_OK; /* skip NULL, DEL */ -if (fputc (c, uptr->fileref) == EOF) { /* print char */ - perror ("LPT I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -uptr->pos = uptr->pos + 1; /* update position */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lp09_reset (DEVICE *dptr) -{ -lp09_don = 0; /* clear done */ -lp09_err = (lp09_unit.flags & UNIT_ATT)? 0: 1; /* compute error */ -lp09_ie = 1; /* set enable */ -CLR_INT (LPT); /* clear int */ -return SCPE_OK; -} - -/* IORS routine */ - -int32 lp09_iors (void) -{ -return (lp09_don? IOS_LPT: 0); -} - -/* Attach routine */ - -t_stat lp09_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); -lp09_err = (lp09_unit.flags & UNIT_ATT)? 0: 1; /* clr/set error */ -return reason; -} - -/* Detach routine */ - -t_stat lp09_detach (UNIT *uptr) -{ -lp09_err = 1; -return detach_unit (uptr); -} - -#endif - -#if defined (LP15) - -/* LP15 line printer */ - -#define LP15_BSIZE 132 /* line size */ -#define LPT_WC 034 /* word count */ -#define LPT_CA 035 /* current addr */ - -/* Status register */ - -#define STA_ERR 0400000 /* error */ -#define STA_ALM 0200000 /* alarm */ -#define STA_OVF 0100000 /* line overflow */ -#define STA_IHT 0040000 /* illegal HT */ -#define STA_BUSY 0020000 /* busy */ -#define STA_DON 0010000 /* done */ -#define STA_ILK 0004000 /* interlock */ -#define STA_EFLGS (STA_ALM | STA_OVF | STA_IHT | STA_ILK) -#define STA_CLR 0003777 /* always clear */ - -extern int32 M[]; -int32 lp15_sta = 0; -int32 lp15_ie = 1; -int32 lp15_stopioe = 0; -int32 lp15_mode = 0; -int32 lp15_lc = 0; -int32 lp15_bp = 0; -char lp15_buf[LP15_BSIZE] = { 0 }; - -DEVICE lp15_dev; -int32 lp15_65 (int32 pulse, int32 dat); -int32 lp15_66 (int32 pulse, int32 dat); -int32 lp15_iors (void); -t_stat lp15_svc (UNIT *uptr); -t_stat lp15_reset (DEVICE *dptr); - -int32 lp15_updsta (int32 new); - -/* LP15 LPT data structures - - lp15_dev LPT device descriptor - lp15_unit LPT unit - lp15_reg LPT register list -*/ - -DIB lp15_dib = { DEV_LPT, 2, &lp15_iors, { &lp15_65, &lp15_66 } }; - -UNIT lp15_unit = { - UDATA (&lp15_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lp15_reg[] = { - { ORDATA (STA, lp15_sta, 18) }, - { ORDATA (CA, M[LPT_CA], 18) }, - { FLDATA (INT, int_hwre[API_LPT], INT_V_LPT) }, - { FLDATA (ENABLE, lp15_ie, 0) }, - { DRDATA (LCNT, lp15_lc, 9) }, - { DRDATA (BPTR, lp15_bp, 8) }, - { FLDATA (MODE, lp15_mode, 0) }, - { DRDATA (POS, lp15_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, lp15_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lp15_stopioe, 0) }, - { BRDATA (LBUF, lp15_buf, 8, 8, LP15_BSIZE) }, - { ORDATA (DEVNO, lp15_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB lp15_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE lp15_dev = { - "LPT", &lp15_unit, lp15_reg, lp15_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lp15_reset, - NULL, NULL, NULL, - &lp15_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 lp15_65 (int32 pulse, int32 dat) -{ -int32 header, sb; - -sb = pulse & 060; /* subopcode */ -if (pulse & 01) { - if ((sb == 000) && (lp15_sta & (STA_ERR | STA_DON))) /* LPSF */ - dat = IOT_SKP | dat; - else if ((sb == 020) || (sb == 040)) { /* LPP1, LPPM */ - sim_activate (&lp15_unit, lp15_unit.wait); /* activate */ - header = M[(M[LPT_CA] + 1) & AMASK]; /* get first word */ - M[LPT_CA] = (M[LPT_CA] + 2) & DMASK; - lp15_mode = header & 1; /* mode */ - if (sb == 040) lp15_lc = 1; /* line count */ - else lp15_lc = (header >> 9) & 0377; - if (lp15_lc == 0) lp15_lc = 256; - lp15_bp = 0; } /* reset buf ptr */ - else if (sb == 060) lp15_ie = 0; /* LPDI */ - } -if ((pulse & 02) && (sb == 040)) dat = dat | lp15_updsta (0); /* LPOS, LPRS */ -if ((pulse & 04) && (sb == 040)) lp15_ie = 1; /* LPEI */ -lp15_updsta (0); /* update status */ -return dat; -} - -int32 lp15_66 (int32 pulse, int32 dat) -{ -if (pulse == 021) lp15_sta = lp15_sta & ~STA_DON; /* LPCD */ -if (pulse == 041) lp15_sta = 0; /* LPCF */ -lp15_updsta (0); /* update status */ -return dat; -} - -/* Unit service */ - -t_stat lp15_svc (UNIT *uptr) -{ -int32 i, ccnt, more, w0, w1; -char c[5]; -static const char *ctrl[040] = { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, "\n", "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", - "\f", "\r", NULL, NULL, - "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", - "\n\n", "\n\n\n", "\n", - "\n\n\n\n\n\n\n\n\n\n", NULL, NULL, NULL, - NULL, NULL, NULL, "\r", NULL, NULL, NULL, NULL }; - -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - lp15_updsta (STA_DON | STA_ALM); /* set done, err */ - return IORETURN (lp15_stopioe, SCPE_UNATT); } - -for (more = 1; more != 0; ) { /* loop until ctrl */ - w0 = M[(M[LPT_CA] + 1) & AMASK]; /* get first word */ - w1 = M[(M[LPT_CA] + 2) & AMASK]; /* get second word */ - M[LPT_CA] = (M[LPT_CA] + 2) & DMASK; /* advance mem addr */ - if (lp15_mode) { /* unpacked? */ - c[0] = w0 & 0177; - c[1] = w1 & 0177; - ccnt = 2; } - else { - c[0] = (w0 >> 11) & 0177; /* packed */ - c[1] = (w0 >> 4) & 0177; - c[2] = (((w0 << 3) | (w1 >> 15))) & 0177; - c[3] = (w1 >> 8) & 0177; - c[4] = (w1 >> 1) & 0177; - ccnt = 5; } - for (i = 0; i < ccnt; i++) { /* loop through */ - if ((c[i] <= 037) && ctrl[c[i]]) { /* control char? */ - fwrite (lp15_buf, 1, lp15_bp, uptr->fileref); - fputs (ctrl[c[i]], uptr->fileref); - if (ferror (uptr->fileref)) { /* error? */ - perror ("LPT I/O error"); - clearerr (uptr->fileref); - lp15_bp = 0; - lp15_updsta (STA_DON | STA_ALM); - return SCPE_IOERR; } - uptr->pos = ftell (uptr->fileref); - lp15_bp = more = 0; } - else { - if (lp15_bp < LP15_BSIZE) lp15_buf[lp15_bp++] = c[i]; - else lp15_sta = lp15_sta | STA_OVF; } } } - -lp15_lc = lp15_lc - 1; /* decr line count */ -if (lp15_lc) sim_activate (&lp15_unit, uptr->wait); /* more to do? */ -else lp15_updsta (STA_DON); /* no, set done */ -return SCPE_OK; -} - -/* Update status */ - -int32 lp15_updsta (int32 new) -{ -lp15_sta = (lp15_sta | new) & ~(STA_CLR | STA_ERR | STA_BUSY); -if (lp15_sta & STA_EFLGS) lp15_sta = lp15_sta | STA_ERR; /* update errors */ -if (sim_is_active (&lp15_unit)) lp15_sta = lp15_sta | STA_BUSY; -if (lp15_ie && (lp15_sta & STA_DON)) SET_INT (LPT); -else CLR_INT (LPT); /* update int */ -return lp15_sta; -} - -/* Reset routine */ - -t_stat lp15_reset (DEVICE *dptr) -{ -lp15_mode = lp15_lc = lp15_bp = 0; /* clear controls */ -sim_cancel (&lp15_unit); /* deactivate unit */ -lp15_sta = 0; /* clear status */ -lp15_ie = 1; /* enable interrupts */ -lp15_updsta (0); /* update status */ -return SCPE_OK; -} - -/* IORS routine */ - -int32 lp15_iors (void) -{ -return ((lp15_sta & STA_DON)? IOS_LPT: 0); -} - -#endif diff --git a/PDP18B/pdp18b_mt.c b/PDP18B/pdp18b_mt.c deleted file mode 100644 index 0796035d..00000000 --- a/PDP18B/pdp18b_mt.c +++ /dev/null @@ -1,476 +0,0 @@ -/* pdp18b_mt.c: 18b PDP magnetic tape simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - mt (PDP-9) TC59 magtape - (PDP-15) TC59D magtape - - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 04-Mar-03 RMS Fixed bug in MTTR - 01-Mar-03 RMS Fixed bug in interrupt handling - Revised for magtape library - 02-Feb-03 RMS Revised IOT decoding - 30-Oct-02 RMS Revised BOT handling, added error record handling - 05-Oct-02 RMS Added DIB, device number support - Revamped error recovery - 28-Aug-02 RMS Added end of medium support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Added maximum record length test - 06-Jan-02 RMS Revised enabled/disable support - 29-Nov-01 RMS Added read only unit support - 25-Nov-01 RMS Revised interrupt structure - Changed UST, POS, FLG to arrays - 26-Apr-01 RMS Added device enable/disable support - 15-Feb-01 RMS Fixed 3-cycle data break sequence - 04-Oct-98 RMS V2.4 magtape format - 22-Jan-97 RMS V2.3 magtape format - 29-Jun-96 RMS Added unit enable/disable support - - Magnetic tapes are represented as a series of variable records - of the form: - - 32b byte count - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32 byte count - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a byte count of 0. -*/ - -#include "pdp18b_defs.h" -#include "sim_tape.h" - -#define MT_NUMDR 8 /* #drives */ -#define USTAT u3 /* unit status */ -#define MT_MAXFR (1 << 16) /* max record length */ -#define MT_WC 032 /* word count */ -#define MT_CA 033 /* current addr */ -#define WC_SIZE (1 << 12) /* max word count */ -#define WC_MASK (WC_SIZE - 1) - -/* Command/unit - mt_cu */ - -#define CU_V_UNIT 15 /* unit */ -#define CU_M_UNIT 07 -#define CU_PARITY 0040000 /* parity select */ -#define CU_DUMP 0020000 /* dump mode */ -#define CU_ERASE 0010000 /* ext rec gap */ -#define CU_V_CMD 9 /* command */ -#define CU_M_CMD 07 -#define FN_NOP 00 -#define FN_REWIND 01 -#define FN_READ 02 -#define FN_CMPARE 03 -#define FN_WRITE 04 -#define FN_WREOF 05 -#define FN_SPACEF 06 -#define FN_SPACER 07 -#define CU_IE 0000400 /* interrupt enable */ -#define CU_V_TYPE 6 /* drive type */ -#define CU_M_TYPE 03 -#define TY_9TK 3 -#define GET_UNIT(x) (((x) >> CU_V_UNIT) & CU_M_UNIT) -#define GET_CMD(x) (((x) >> CU_V_CMD) & CU_M_CMD) -#define GET_TYPE(x) (((x) >> CU_V_TYPE) & CU_M_TYPE) -#define PACKED(x) (((x) & CU_DUMP) || (GET_TYPE (x) != TY_9TK)) - -/* Status - stored in mt_sta or (*) uptr->USTAT */ - -#define STA_ERR 0400000 /* error */ -#define STA_REW 0200000 /* *rewinding */ -#define STA_BOT 0100000 /* *start of tape */ -#define STA_ILL 0040000 /* illegal cmd */ -#define STA_PAR 0020000 /* parity error */ -#define STA_EOF 0010000 /* *end of file */ -#define STA_EOT 0004000 /* *end of tape */ -#define STA_CPE 0002000 /* compare error */ -#define STA_RLE 0001000 /* rec lnt error */ -#define STA_DLT 0000400 /* data late */ -#define STA_BAD 0000200 /* bad tape */ -#define STA_DON 0000100 /* done */ - -#define STA_CLR 0000077 /* always clear */ -#define STA_DYN (STA_REW | STA_BOT | STA_EOF | STA_EOT) - /* kept in USTAT */ - -extern int32 M[]; -extern int32 int_hwre[API_HLVL+1]; -extern UNIT cpu_unit; - -int32 mt_cu = 0; /* command/unit */ -int32 mt_sta = 0; /* status register */ -int32 mt_time = 10; /* record latency */ -int32 mt_stopioe = 1; /* stop on error */ -int32 mt_log = 0; -uint8 *mtxb = NULL; /* transfer buffer */ - -DEVICE mt_dev; -int32 mt (int32 pulse, int32 dat); -int32 mt_iors (void); -t_stat mt_svc (UNIT *uptr); -t_stat mt_reset (DEVICE *dptr); -t_stat mt_attach (UNIT *uptr, char *cptr); -t_stat mt_detach (UNIT *uptr); -int32 mt_updcsta (UNIT *uptr, int32 val); -t_stat mt_map_err (UNIT *uptr, t_stat st); -UNIT *mt_busy (void); - -/* MT data structures - - mt_dev MT device descriptor - mt_unit MT unit list - mt_reg MT register list - mt_mod MT modifier list -*/ - -DIB mt_dib = { DEV_MT, 1, &mt_iors, { &mt } }; - -UNIT mt_unit[] = { - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) } }; - -REG mt_reg[] = { - { ORDATA (STA, mt_sta, 18) }, - { ORDATA (CMD, mt_cu, 18) }, - { ORDATA (WC, M[MT_WC], 18) }, - { ORDATA (CA, M[MT_CA], 18) }, - { FLDATA (INT, int_hwre[API_MTA], INT_V_MTA) }, - { FLDATA (STOP_IOE, mt_stopioe, 0) }, - { DRDATA (TIME, mt_time, 24), PV_LEFT }, - { URDATA (UST, mt_unit[0].USTAT, 8, 16, 0, MT_NUMDR, 0) }, - { URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0, - MT_NUMDR, PV_LEFT | REG_RO) }, - { FLDATA (LOG, mt_log, 0), REG_HIDDEN }, - { ORDATA (DEVNO, mt_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB mt_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_devno, &show_devno, NULL }, - { 0 } }; - -DEVICE mt_dev = { - "MT", mt_unit, mt_reg, mt_mod, - MT_NUMDR, 10, 31, 1, 8, 8, - NULL, NULL, &mt_reset, - NULL, &mt_attach, &mt_detach, - &mt_dib, DEV_DISABLE }; - -/* IOT routine */ - -int32 mt (int32 pulse, int32 dat) -{ -int32 f, sb; -UNIT *uptr; - -uptr = mt_dev.units + GET_UNIT (mt_cu); /* get unit */ -mt_updcsta (uptr, 0); /* update status */ -sb = pulse & 060; /* subop */ -if (pulse & 01) { - if ((sb == 000) && (uptr->flags & UNIT_ATT) && /* MTTR */ - !sim_is_active (uptr)) - dat = IOT_SKP | dat; - else if ((sb == 020) && !mt_busy ()) /* MTCR */ - dat = IOT_SKP | dat; - else if ((sb == 040) && (mt_sta & (STA_ERR | STA_DON))) /* MTSF */ - dat = IOT_SKP | dat; - } -if ((pulse & 06) && mt_log) - printf ("[MT%d: IOT=%o, AC=%o, sta=%o]\n", - GET_UNIT (mt_cu), 0707300 + pulse, dat, mt_sta); -if (pulse & 02) { - if (sb == 000) dat = dat | (mt_cu & 0777700); /* MTRC */ - else if (sb == 020) { /* MTAF, MTLC */ - if (!mt_busy ()) mt_cu = mt_sta = 0; /* if not busy, clr */ - mt_sta = mt_sta & ~(STA_ERR | STA_DON); } /* clear flags */ - else if (sb == 040) dat = dat | mt_sta; /* MTRS */ - } -if (pulse & 04) { - if (sb == 000) { /* MTGO */ - f = GET_CMD (mt_cu); /* get function */ - if (mt_busy () || - sim_is_active (uptr) || - (f == FN_NOP) || - (((f == FN_SPACER) || (f == FN_REWIND)) && (uptr->USTAT & STA_BOT)) || - (((f == FN_WRITE) || (f == FN_WREOF)) && sim_tape_wrp (uptr)) || - ((uptr->flags & UNIT_ATT) == 0)) - mt_sta = mt_sta | STA_ILL | STA_ERR; /* set illegal op */ - else { - if (f == FN_REWIND) uptr->USTAT = STA_REW; /* rewind? */ - else mt_sta = uptr->USTAT = 0; /* no, clear status */ - sim_activate (uptr, mt_time); } } /* start io */ - if (sb == 020) /* MTCM, MTLC */ - mt_cu = (mt_cu & 0770700) | (dat & 0777700); /* load status */ - } -mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */ -return dat; -} - -/* Unit service - - If rewind done, reposition to start of tape, set status - else, do operation, set done, interrupt -*/ - -t_stat mt_svc (UNIT *uptr) -{ -int32 c, c1, c2, c3, f, i, p, u; -int32 wc, xma; -t_mtrlnt tbc, cbc; -t_stat st, r = SCPE_OK; - -u = uptr - mt_dev.units; /* get unit number */ -f = GET_CMD (mt_cu); /* get command */ -wc = WC_SIZE - (M[MT_WC] & WC_MASK); /* word count is 12b */ - -if (uptr->USTAT & STA_REW) { /* rewind? */ - sim_tape_rewind (uptr); /* rewind tape */ - if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_BOT; - else uptr->USTAT = 0; - if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr, STA_DON); - if (mt_log) printf ("[MT%d: rewind complete, sta=%o]\n", u, mt_sta); - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */ - mt_updcsta (uptr, STA_ILL); /* illegal operation */ - return IORETURN (mt_stopioe, SCPE_UNATT); } - -switch (f) { /* case on function */ - -/* Unit service, continued */ - -case FN_READ: /* read */ -case FN_CMPARE: /* read/compare */ - st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */ - if (st == MTSE_RECE) mt_sta = mt_sta | STA_PAR | STA_ERR; /* rec in err? */ - else if (st != MTSE_OK) { /* other error? */ - mt_sta = mt_sta | STA_RLE | STA_ERR; /* set RLE flag */ - r = mt_map_err (uptr, st); /* map error */ - break; } - cbc = PACKED (mt_cu)? wc * 3: wc * 2; /* expected bc */ - if (tbc != cbc) mt_sta = mt_sta | STA_RLE | STA_ERR; /* wrong size? */ - if (tbc < cbc) { /* record small? */ - cbc = tbc; /* use smaller */ - wc = PACKED (mt_cu)? ((tbc + 2) / 3): ((tbc + 1) / 2); } - for (i = p = 0; i < wc; i++) { /* copy buffer */ - M[MT_WC] = (M[MT_WC] + 1) & DMASK; /* inc WC, CA */ - M[MT_CA] = (M[MT_CA] + 1) & DMASK; - xma = M[MT_CA] & AMASK; - if (PACKED (mt_cu)) { /* packed? */ - c1 = mtxb[p++] & 077; - c2 = mtxb[p++] & 077; - c3 = mtxb[p++] & 077; - c = (c1 << 12) | (c2 << 6) | c3; } - else { - c1 = mtxb[p++]; - c2 = mtxb[p++]; - c = (c1 << 8) | c2; } - if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c; - else if ((f == FN_CMPARE) && (c != (M[xma] & - (PACKED (mt_cu)? DMASK: 0177777)))) { - mt_updcsta (uptr, STA_CPE); - break; } } - break; - -case FN_WRITE: /* write */ - tbc = PACKED (mt_cu)? wc * 3: wc * 2; - xma = M[MT_CA] & AMASK; /* get mem addr */ - for (i = p = 0; i < wc; i++) { /* copy buf to tape */ - xma = (xma + 1) & AMASK; /* incr mem addr */ - if (PACKED (mt_cu)) { /* packed? */ - mtxb[p++] = (M[xma] >> 12) & 077; - mtxb[p++] = (M[xma] >> 6) & 077; - mtxb[p++] = M[xma] & 077; } - else { - mtxb[p++] = (M[xma] >> 8) & 0377; - mtxb[p++] = M[xma] & 0377; } } - if (st = sim_tape_wrrecf (uptr, mtxb, tbc)) /* write rec, err? */ - r = mt_map_err (uptr, st); /* map error */ - else { - M[MT_CA] = (M[MT_CA] + wc) & DMASK; /* advance mem addr */ - M[MT_WC] = 0; } /* clear word cnt */ - mt_cu = mt_cu & ~CU_ERASE; /* clear erase flag */ - break; - -/* Unit service, continued */ - -case FN_WREOF: - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = mt_map_err (uptr, st); /* map error */ - else uptr->USTAT = STA_EOF; - mt_cu = mt_cu & ~CU_ERASE; /* clear erase flag */ - break; - -case FN_SPACEF: /* space forward */ - do { - M[MT_WC] = (M[MT_WC] + 1) & DMASK; /* inc WC */ - if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; } - } - while (M[MT_WC] != 0); - break; - -case FN_SPACER: /* space reverse */ - do { - M[MT_WC] = (M[MT_WC] + 1) & DMASK; /* inc WC */ - if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; } - } - while (M[MT_WC] != 0); - break; } /* end case */ - -mt_updcsta (uptr, STA_DON); /* set done */ -if (mt_log) printf ("MT%d: fnc=%d done, ma=%o, wc=%o, sta=%o]\n", - u, f, M[MT_CA], M[MT_WC], mt_sta); -return r; -} - -/* Update controller status */ - -int32 mt_updcsta (UNIT *uptr, int32 news) -{ -mt_sta = (mt_sta & ~(STA_DYN | STA_CLR)) | - (uptr->USTAT & STA_DYN) | news; -if ((mt_sta & (STA_ERR | STA_DON)) && (mt_cu & CU_IE)) - SET_INT (MTA); -else CLR_INT (MTA); /* int request */ -return mt_sta; -} - -/* Test if controller busy */ - -UNIT *mt_busy (void) -{ -int32 u; -UNIT *uptr; - -for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */ - uptr = mt_dev.units + u; - if (sim_is_active (uptr) && ((uptr->USTAT & STA_REW) == 0)) - return uptr; } -return NULL; -} - -/* Map tape error status */ - -t_stat mt_map_err (UNIT *uptr, t_stat st) -{ -switch (st) { -case MTSE_FMT: /* illegal fmt */ -case MTSE_UNATT: /* not attached */ - mt_sta = mt_sta | STA_ILL | STA_ERR; -case MTSE_OK: /* no error */ - return SCPE_IERR; -case MTSE_TMK: /* end of file */ - uptr->USTAT = uptr->USTAT | STA_EOF; /* set EOF */ - mt_sta = mt_sta | STA_ERR; - break; -case MTSE_IOERR: /* IO error */ - mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */ - if (mt_stopioe) return SCPE_IOERR; - break; -case MTSE_INVRL: /* invalid rec lnt */ - mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */ - return SCPE_MTRLNT; -case MTSE_RECE: /* record in error */ - mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */ - break; -case MTSE_EOM: /* end of medium */ - mt_sta = mt_sta | STA_BAD | STA_ERR; /* set end tape */ - break; -case MTSE_BOT: /* reverse into BOT */ - uptr->USTAT = uptr->USTAT | STA_BOT; /* set status */ - mt_sta = mt_sta | STA_ERR; - break; -case MTSE_WRP: /* write protect */ - mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */ - break; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat mt_reset (DEVICE *dptr) -{ -int32 u; -UNIT *uptr; - -mt_cu = mt_sta = 0; -for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */ - uptr = mt_dev.units + u; - sim_tape_reset (uptr); /* reset tape */ - sim_cancel (uptr); /* cancel activity */ - if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_BOT; - else uptr->USTAT = 0; } -mt_updcsta (&mt_unit[0], 0); /* update status */ -if (mtxb == NULL) mtxb = calloc (MT_MAXFR, sizeof (uint8)); -if (mtxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* IORS routine */ - -int32 mt_iors (void) -{ -return (mt_sta & (STA_ERR | STA_DON))? IOS_MTA: 0; -} - -/* Attach routine */ - -t_stat mt_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; -uptr->USTAT = STA_BOT; -mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */ -return r; -} - -/* Detach routine */ - -t_stat mt_detach (UNIT* uptr) -{ -if (!sim_is_active (uptr)) uptr->USTAT = 0; -mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */ -return sim_tape_detach (uptr); -} diff --git a/PDP18B/pdp18b_rb.c b/PDP18B/pdp18b_rb.c deleted file mode 100644 index e3423225..00000000 --- a/PDP18B/pdp18b_rb.c +++ /dev/null @@ -1,273 +0,0 @@ -/* pdp18b_rb.c: RB09 fixed head disk simulator - - Copyright (c) 2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - rb RB09 fixed head disk - - The RB09 is a head-per-track disk. It uses the single cycle data break - facility. To minimize overhead, the entire RB09 is buffered in memory. - - Two timing parameters are provided: - - rb_time Interword timing. Must be non-zero. - rb_burst Burst mode. If 0, DMA occurs cycle by cycle; otherwise, - DMA occurs in a burst. -*/ - -#include "pdp18b_defs.h" -#include - -/* Constants */ - -#define RB_NUMWD 64 /* words/sector */ -#define RB_NUMSC 80 /* sectors/track */ -#define RB_NUMTR 200 /* tracks/disk */ -#define RB_WLKTR 10 /* tracks/wlock switch */ -#define RB_SIZE (RB_NUMTR * RB_NUMSC * RB_NUMWD) /* words/drive */ - -/* Function/status register */ - -#define RBS_ERR 0400000 /* error */ -#define RBS_PAR 0200000 /* parity error */ -#define RBS_ILA 0100000 /* ill addr error */ -#define RBS_TIM 0040000 /* timing transfer */ -#define RBS_NRY 0020000 /* not ready error */ -#define RBS_DON 0010000 /* done */ -#define RBS_IE 0004000 /* int enable */ -#define RBS_BSY 0002000 /* busy */ -#define RBS_WR 0001000 /* read/write */ -#define RBS_XOR (RBS_IE|RBS_BSY|RBS_WR) /* set by XOR */ -#define RBS_MBZ 0000777 /* always clear */ -#define RBS_EFLGS (RBS_PAR|RBS_ILA|RBS_TIM|RBS_NRY) /* error flags */ - -/* BCD disk address */ - -#define RBA_V_TR 8 -#define RBA_M_TR 0x1FF -#define RBA_V_SC 0 -#define RBA_M_SC 0xFF -#define RBA_GETTR(x) (((x) >> RBA_V_TR) & RBA_M_TR) -#define RBA_GETSC(x) (((x) >> RBA_V_SC) & RBA_M_SC) - -#define GET_POS(x) ((int) fmod (sim_gtime () / ((double) (x)), \ - ((double) (RB_NUMSC * RB_NUMWD)))) - -extern int32 M[]; -extern int32 int_hwre[API_HLVL+1]; -extern UNIT cpu_unit; - -int32 rb_sta = 0; /* status register */ -int32 rb_da = 0; /* disk address */ -int32 rb_ma = 0; /* current addr */ -int32 rb_wc = 0; /* word count */ -int32 rb_wlk = 0; /* write lock */ -int32 rb_time = 10; /* inter-word time */ -int32 rb_burst = 1; /* burst mode flag */ -int32 rb_stopioe = 1; /* stop on error */ - -DEVICE rb_dev; -int32 rb71 (int32 pulse, int32 AC); -t_stat rb_svc (UNIT *uptr); -t_stat rb_reset (DEVICE *dptr); -int32 rb_updsta (int32 new); -int32 rb_make_da (int32 dat); -int32 rb_make_bcd (int32 dat); -int32 rb_set_da (int32 dat, int32 old); -int32 rb_set_bcd (int32 dat); - -/* RB data structures - - rb_dev RF device descriptor - rb_unit RF unit descriptor - rb_reg RF register list -*/ - -DIB rb_dib = { DEV_RB, 1, NULL, { &rb71 } }; - -UNIT rb_unit = - { UDATA (&rb_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, - RB_SIZE) }; - -REG rb_reg[] = { - { ORDATA (STA, rb_sta, 18) }, - { ORDATA (DA, rb_da, 20) }, - { ORDATA (WC, rb_wc, 16) }, - { ORDATA (MA, rb_ma, ADDRSIZE) }, - { FLDATA (INT, int_hwre[API_RB], INT_V_RB) }, - { ORDATA (WLK, rb_wlk, RB_NUMTR / RB_WLKTR) }, - { DRDATA (TIME, rb_time, 24), PV_LEFT + REG_NZ }, - { FLDATA (BURST, rb_burst, 0) }, - { FLDATA (STOP_IOE, rb_stopioe, 0) }, - { ORDATA (DEVNO, rb_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB rb_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE rb_dev = { - "RB", &rb_unit, rb_reg, rb_mod, - 1, 8, 21, 1, 8, 18, - NULL, NULL, &rb_reset, - NULL, NULL, NULL, - &rb_dib, DEV_DIS | DEV_DISABLE }; - -/* IOT routines */ - -int32 rb71 (int32 pulse, int32 AC) -{ -int32 tow, t, sb = pulse & 060; - -if (pulse & 001) { - if (sb == 000) rb_sta = rb_sta & /* DBCF */ - ~(RBS_ERR | RBS_EFLGS | RBS_DON); - if ((sb == 020) && (rb_sta & (RBS_ERR | RBS_DON))) - AC = AC | IOT_SKP; /* DBSF */ - if (sb == 040) rb_sta = 0; /* DBCS */ - } -if (pulse & 002) { - if (sb == 000) AC = AC | rb_make_da (rb_da); /* DBRD */ - if (sb == 020) AC = AC | rb_sta; /* DBRS */ - if (sb == 040) rb_ma = AC & AMASK; /* DBLM */ - } -if (pulse & 004) { - if (sb == 000) rb_da = rb_set_da (AC, rb_da); /* DBLD */ - if (sb == 020) rb_wc = AC & 0177777; /* DBLW */ - if (sb == 040) { /* DBLS */ - rb_sta = (rb_sta & RBS_XOR) ^ (AC & ~RBS_MBZ); - if (rb_sta & RBS_BSY) { /* busy set? */ - if (!sim_is_active (&rb_unit)) { /* schedule */ - tow = rb_da % (RB_NUMSC * RB_NUMWD); - t = tow - GET_POS (rb_time); - if (t < 0) t = t + (RB_NUMSC * RB_NUMWD); - sim_activate (&rb_unit, t * rb_time); } } - else sim_cancel (&rb_unit); } /* no, stop */ - } -rb_updsta (0); /* update status */ -return AC; -} - -int32 rb_make_da (int32 da) -{ -int32 t = da / (RB_NUMSC * RB_NUMWD); /* bin track */ -int32 s = (da % (RB_NUMSC * RB_NUMWD)) / RB_NUMWD; /* bin sector */ -int32 bcd_t = rb_make_bcd (t); /* bcd track */ -int32 bcd_s = rb_make_bcd (s); /* bcd sector */ -return (bcd_t << RBA_V_TR) | (bcd_s << RBA_V_SC); -} - -int32 rb_set_da (int32 bcda, int32 old_da) -{ -int32 bcd_t = RBA_GETTR (bcda); /* bcd track */ -int32 bcd_s = RBA_GETSC (bcda); /* bcd sector */ -int32 t = rb_set_bcd (bcd_t); /* bin track */ -int32 s = rb_set_bcd (bcd_s); /* bin sector */ - -if ((t >= RB_NUMTR) || (t < 0) || /* invalid? */ - (s >= RB_NUMSC) || (s < 0)) { - rb_updsta (RBS_ILA); /* error */ - return old_da; } /* don't change */ -else return (((t * RB_NUMSC) + s) * RB_NUMWD); /* new da */ -} - -int32 rb_make_bcd (int32 bin) -{ -int32 d, i, r; - -for (r = i = 0; bin != 0; bin = bin / 10) { /* while nz */ - d = bin % 10; /* dec digit */ - r = r | (d << i); /* insert bcd */ - i = i + 4; } -return r; -} - -int32 rb_set_bcd (int32 bcd) -{ -int32 d, i, r; - -for (r = 0, i = 1; bcd != 0; bcd = bcd >> 4) { /* while nz */ - d = bcd & 0xF; /* bcd digit */ - if (d >= 10) return -1; /* invalid? */ - r = r + (d * i); /* insert bin */ - i = i * 10; } -return r; -} - -/* Unit service - disk is buffered in memory */ - -t_stat rb_svc (UNIT *uptr) -{ -int32 t, sw; - -if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ - rb_updsta (RBS_NRY | RBS_DON); /* set nxd, done */ - return IORETURN (rb_stopioe, SCPE_UNATT); } - -do { if (rb_sta & RBS_WR) { /* write? */ - t = rb_da / (RB_NUMSC * RB_NUMWD); /* track */ - sw = t / RB_WLKTR; /* switch */ - if ((rb_wlk >> sw) & 1) { /* write locked? */ - rb_updsta (RBS_ILA | RBS_DON); - break; } - else { - *(((int32 *) uptr->filebuf) + rb_da) = M[rb_ma]; - if (((t_addr) rb_da) >= uptr->hwmark) uptr->hwmark = rb_da + 1; } } - else if (MEM_ADDR_OK (rb_ma)) /* read, valid addr? */ - M[rb_ma] = *(((int32 *) uptr->filebuf) + rb_da); - rb_wc = (rb_wc + 1) & 0177777; /* incr word count */ - rb_ma = (rb_ma + 1) & AMASK; /* incr mem addr */ - rb_da = rb_da + 1; /* incr disk addr */ - if (rb_da > RB_SIZE) rb_da = 0; /* disk wraparound? */ - } -while ((rb_wc != 0) && (rb_burst != 0)); /* brk if wc, no brst */ - -if ((rb_wc != 0) && ((rb_sta & RBS_ERR) == 0)) /* more to do? */ - sim_activate (&rb_unit, rb_time); /* sched next */ -else rb_updsta (RBS_DON); /* set done */ -return SCPE_OK; -} - -/* Update status */ - -int32 rb_updsta (int32 new) -{ -rb_sta = (rb_sta | new) & ~(RBS_ERR | RBS_MBZ); /* clear err, mbz */ -if (rb_sta & RBS_EFLGS) rb_sta = rb_sta | RBS_ERR; /* error? */ -if (rb_sta & RBS_DON) rb_sta = rb_sta & ~RBS_BSY; /* done? clear busy */ -if ((rb_sta & (RBS_ERR | RBS_DON)) && (rb_sta & RBS_IE)) - SET_INT (RB); /* set or clr intr */ -else CLR_INT (RB); -return rb_sta; -} - -/* Reset routine */ - -t_stat rb_reset (DEVICE *dptr) -{ -rb_sta = rb_da = 0; -rb_wc = rb_ma = 0; -rb_updsta (0); -sim_cancel (&rb_unit); -return SCPE_OK; -} diff --git a/PDP18B/pdp18b_rf.c b/PDP18B/pdp18b_rf.c deleted file mode 100644 index 86c2e60c..00000000 --- a/PDP18B/pdp18b_rf.c +++ /dev/null @@ -1,332 +0,0 @@ -/* pdp18b_rf.c: fixed head disk simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - rf (PDP-9) RF09/RF09 - (PDP-15) RF15/RS09 - - 26-Jul-03 RMS Fixed bug in set size routine - 14-Mar-03 RMS Fixed variable platter interaction with save/restore - 03-Mar-03 RMS Fixed autosizing - 12-Feb-03 RMS Removed 8 platter sizing hack - 05-Feb-03 RMS Fixed decode bugs, added variable and autosizing - 05-Oct-02 RMS Added DIB, dev number support - 06-Jan-02 RMS Revised enable/disable support - 25-Nov-01 RMS Revised interrupt structure - 24-Nov-01 RMS Changed WLK to array - 26-Apr-01 RMS Added device enable/disable support - 15-Feb-01 RMS Fixed 3 cycle data break sequencing - 30-Nov-99 RMS Added non-zero requirement to rf_time - 14-Apr-99 RMS Changed t_addr to unsigned - - The RFxx is a head-per-track disk. It uses the multicycle data break - facility. To minimize overhead, the entire RFxx is buffered in memory. - - Two timing parameters are provided: - - rf_time Interword timing. Must be non-zero. - rf_burst Burst mode. If 0, DMA occurs cycle by cycle; otherwise, - DMA occurs in a burst. -*/ - -#include "pdp18b_defs.h" -#include - -#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */ -#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */ -#define UNIT_M_PLAT 07 -#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT) -#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT) - -/* Constants */ - -#define RF_NUMWD 2048 /* words/track */ -#define RF_NUMTR 128 /* tracks/disk */ -#define RF_DKSIZE (RF_NUMTR * RF_NUMWD) /* words/disk */ -#define RF_NUMDK 8 /* disks/controller */ -#define RF_WMASK (RF_NUMWD - 1) /* word mask */ -#define RF_WC 036 /* word count */ -#define RF_CA 037 /* current addr */ - -/* Function/status register */ - -#define RFS_ERR 0400000 /* error */ -#define RFS_HDW 0200000 /* hardware error */ -#define RFS_APE 0100000 /* addr parity error */ -#define RFS_MXF 0040000 /* missed transfer */ -#define RFS_WCE 0020000 /* write check error */ -#define RFS_DPE 0010000 /* data parity error */ -#define RFS_WLO 0004000 /* write lock error */ -#define RFS_NED 0002000 /* non-existent disk */ -#define RFS_DCH 0001000 /* data chan timing */ -#define RFS_PGE 0000400 /* programming error */ -#define RFS_DON 0000200 /* transfer complete */ -#define RFS_V_FNC 1 /* function */ -#define RFS_M_FNC 03 -#define RFS_FNC (RFS_M_FNC << RFS_V_FNC) -#define FN_NOP 0 -#define FN_READ 1 -#define FN_WRITE 2 -#define FN_WCHK 3 -#define RFS_IE 0000001 /* interrupt enable */ - -#define RFS_CLR 0000170 /* always clear */ -#define RFS_EFLGS (RFS_HDW | RFS_APE | RFS_MXF | RFS_WCE | \ - RFS_DPE | RFS_WLO | RFS_NED ) /* error flags */ -#define GET_FNC(x) (((x) >> RFS_V_FNC) & RFS_M_FNC) -#define GET_POS(x) ((int) fmod (sim_gtime () / ((double) (x)), \ - ((double) RF_NUMWD))) -#define RF_BUSY (sim_is_active (&rf_unit)) - -extern int32 M[]; -extern int32 int_hwre[API_HLVL+1]; -extern UNIT cpu_unit; - -int32 rf_sta = 0; /* status register */ -int32 rf_da = 0; /* disk address */ -int32 rf_dbuf = 0; /* data buffer */ -int32 rf_wlk[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; /* write lock */ -int32 rf_time = 10; /* inter-word time */ -int32 rf_burst = 1; /* burst mode flag */ -int32 rf_stopioe = 1; /* stop on error */ - -DEVICE rf_dev; -int32 rf70 (int32 pulse, int32 dat); -int32 rf72 (int32 pulse, int32 dat); -int32 rf_iors (void); -t_stat rf_svc (UNIT *uptr); -t_stat rf_reset (DEVICE *dptr); -int32 rf_updsta (int32 new); -t_stat rf_attach (UNIT *uptr, char *cptr); -t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* RF data structures - - rf_dev RF device descriptor - rf_unit RF unit descriptor - rf_reg RF register list -*/ - -DIB rf_dib = { DEV_RF, 3, &rf_iors, { &rf70, NULL, &rf72 } }; - -UNIT rf_unit = - { UDATA (&rf_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_AUTO, - RF_DKSIZE) }; - -REG rf_reg[] = { - { ORDATA (STA, rf_sta, 18) }, - { ORDATA (DA, rf_da, 22) }, - { ORDATA (WC, M[RF_WC], 18) }, - { ORDATA (CA, M[RF_CA], 18) }, - { ORDATA (BUF, rf_dbuf, 18) }, - { FLDATA (INT, int_hwre[API_RF], INT_V_RF) }, - { BRDATA (WLK, rf_wlk, 8, 16, RF_NUMDK) }, - { DRDATA (TIME, rf_time, 24), PV_LEFT + REG_NZ }, - { FLDATA (BURST, rf_burst, 0) }, - { FLDATA (STOP_IOE, rf_stopioe, 0) }, - { DRDATA (CAPAC, rf_unit.capac, 31), PV_LEFT + REG_HRO }, - { ORDATA (DEVNO, rf_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB rf_mod[] = { - { UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &rf_set_size }, - { UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &rf_set_size }, - { UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &rf_set_size }, - { UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &rf_set_size }, - { UNIT_PLAT, (4 << UNIT_V_PLAT), NULL, "5P", &rf_set_size }, - { UNIT_PLAT, (5 << UNIT_V_PLAT), NULL, "6P", &rf_set_size }, - { UNIT_PLAT, (6 << UNIT_V_PLAT), NULL, "7P", &rf_set_size }, - { UNIT_PLAT, (7 << UNIT_V_PLAT), NULL, "8P", &rf_set_size }, - { UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE rf_dev = { - "RF", &rf_unit, rf_reg, rf_mod, - 1, 8, 21, 1, 8, 18, - NULL, NULL, &rf_reset, - NULL, &rf_attach, NULL, - &rf_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 rf70 (int32 pulse, int32 dat) -{ -int32 t, sb; - -sb = pulse & 060; /* subopcode */ -if (pulse & 01) { - if ((sb == 000) && (rf_sta & (RFS_ERR | RFS_DON))) - dat = IOT_SKP | dat; /* DSSF */ - else if (sb == 020) rf_reset (&rf_dev); /* DSCC */ - else if (sb == 040) { /* DSCF */ - if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */ - else rf_sta = rf_sta & ~(RFS_FNC | RFS_IE); } /* clear func */ - } -if (pulse & 02) { - if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */ - else if (sb == 000) dat = dat | rf_dbuf; /* DRBR */ - else if (sb == 020) /* DRAL */ - dat = dat | (rf_da & DMASK); - else if (sb == 040) /* DSFX */ - rf_sta = rf_sta ^ (dat & (RFS_FNC | RFS_IE)); /* xor func */ - else if (sb == 060) /* DRAH */ - dat = dat | (rf_da >> 18) | ((rf_sta & RFS_NED)? 010: 0); - } -if (pulse & 04) { - if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */ - else if (sb == 000) rf_dbuf = dat & DMASK; /* DLBR */ - else if (sb == 020) /* DLAL */ - rf_da = (rf_da & ~DMASK) | (dat & DMASK); - else if (sb == 040) { /* DSCN */ - rf_sta = rf_sta & ~RFS_DON; /* clear done */ - if (GET_FNC (rf_sta) != FN_NOP) { - t = (rf_da & RF_WMASK) - GET_POS (rf_time); /* delta to new */ - if (t < 0) t = t + RF_NUMWD; /* wrap around? */ - sim_activate (&rf_unit, t * rf_time); } } /* schedule op */ - else if (sb == 060) { /* DLAH */ - rf_da = (rf_da & DMASK) | ((dat & 07) << 18); - if ((uint32) rf_da >= rf_unit.capac) /* for sizing */ - rf_updsta (RFS_NED); } - } -rf_updsta (0); /* update status */ -return dat; -} - -int32 rf72 (int32 pulse, int32 dat) -{ -int32 sb = pulse & 060; - -if (pulse & 02) { - if (sb == 000) dat = dat | GET_POS (rf_time) | /* DLOK */ - (sim_is_active (&rf_unit)? 0400000: 0); - else if (sb == 040) { /* DSCD */ - if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */ - else rf_sta = 0; - rf_updsta (0); } - else if (sb == 060) { /* DSRS */ - if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */ - dat = dat | rf_updsta (0); } - } -return dat; -} - -/* Unit service - assumes the entire disk is buffered */ - -t_stat rf_svc (UNIT *uptr) -{ -int32 f, pa, d, t; - -if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ - rf_updsta (RFS_NED | RFS_DON); /* set nxd, done */ - return IORETURN (rf_stopioe, SCPE_UNATT); } - -f = GET_FNC (rf_sta); /* get function */ -do { if ((uint32) rf_da >= uptr->capac) { /* disk overflow? */ - rf_updsta (RFS_NED); /* nx disk error */ - break; } - M[RF_WC] = (M[RF_WC] + 1) & DMASK; /* incr word count */ - pa = M[RF_CA] = (M[RF_CA] + 1) & AMASK; /* incr mem addr */ - if ((f == FN_READ) && MEM_ADDR_OK (pa)) /* read? */ - M[pa] = *(((int32 *) uptr->filebuf) + rf_da); - if ((f == FN_WCHK) && /* write check? */ - (M[pa] != *(((int32 *) uptr->filebuf) + rf_da))) { - rf_updsta (RFS_WCE); /* flag error */ - break; } - if (f == FN_WRITE) { /* write? */ - d = (rf_da >> 18) & 07; /* disk */ - t = (rf_da >> 14) & 017; /* track groups */ - if ((rf_wlk[d] >> t) & 1) { /* write locked? */ - rf_updsta (RFS_WLO); - break; } - else { - *(((int32 *) uptr->filebuf) + rf_da) = M[pa]; - if (((uint32) rf_da) >= uptr->hwmark) uptr->hwmark = rf_da + 1; } } - rf_da = rf_da + 1; /* incr disk addr */ - } -while ((M[RF_WC] != 0) && (rf_burst != 0)); /* brk if wc, no brst */ - -if ((M[RF_WC] != 0) && ((rf_sta & RFS_ERR) == 0)) /* more to do? */ - sim_activate (&rf_unit, rf_time); /* sched next */ -else rf_updsta (RFS_DON); -return SCPE_OK; -} - -/* Update status */ - -int32 rf_updsta (int32 new) -{ -rf_sta = (rf_sta | new) & ~(RFS_ERR | RFS_CLR); -if (rf_sta & RFS_EFLGS) rf_sta = rf_sta | RFS_ERR; -if ((rf_sta & (RFS_ERR | RFS_DON)) && (rf_sta & RFS_IE)) - SET_INT (RF); -else CLR_INT (RF); -return rf_sta; -} - -/* Reset routine */ - -t_stat rf_reset (DEVICE *dptr) -{ -rf_sta = rf_da = rf_dbuf = 0; -rf_updsta (0); -sim_cancel (&rf_unit); -return SCPE_OK; -} - -/* IORS routine */ - -int32 rf_iors (void) -{ -return ((rf_sta & (RFS_ERR | RFS_DON))? IOS_RF: 0); -} - -/* Attach routine */ - -t_stat rf_attach (UNIT *uptr, char *cptr) -{ -uint32 p, sz; -uint32 ds_bytes = RF_DKSIZE * sizeof (int32); - -if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) { - p = (sz + ds_bytes - 1) / ds_bytes; - if (p >= RF_NUMDK) p = RF_NUMDK - 1; - uptr->flags = (uptr->flags & ~UNIT_PLAT) | - (p << UNIT_V_PLAT); } -uptr->capac = UNIT_GETP (uptr->flags) * RF_DKSIZE; -return attach_unit (uptr, cptr); -} - -/* Change disk size */ - -t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (val < 0) return SCPE_IERR; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = UNIT_GETP (val) * RF_DKSIZE; -uptr->flags = uptr->flags & ~UNIT_AUTO; -return SCPE_OK; -} diff --git a/PDP18B/pdp18b_rp.c b/PDP18B/pdp18b_rp.c deleted file mode 100644 index b4d739c9..00000000 --- a/PDP18B/pdp18b_rp.c +++ /dev/null @@ -1,461 +0,0 @@ -/* pdp18b_rp.c: RP15/RP02 disk pack simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - rp RP15/RP02 disk pack - - 06-Feb-03 RMS Revised IOT decoding, fixed bug in initiation - 05-Oct-02 RMS Added DIB, device number support - 06-Jan-02 RMS Revised enable/disable support - 29-Nov-01 RMS Added read only unit support - 25-Nov-01 RMS Revised interrupt structure - Changed FLG to array - 26-Apr-01 RMS Added device enable/disable support - 14-Apr-99 RMS Changed t_addr to unsigned - 29-Jun-96 RMS Added unit enable/disable support -*/ - -#include "pdp18b_defs.h" - -/* Constants */ - -#define RP_NUMWD 256 /* words/sector */ -#define RP_NUMSC 10 /* sectors/surface */ -#define RP_NUMSF 20 /* surfaces/cylinder */ -#define RP_NUMCY 203 /* cylinders/drive */ -#define RP_NUMDR 8 /* drives/controller */ -#define RP_SIZE (RP_NUMCY * RP_NUMSF * RP_NUMSC * RP_NUMWD) /* words/drive */ - -/* Unit specific flags */ - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* hwre write lock */ -#define UNIT_WLK (1u << UNIT_V_WLK) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -/* Parameters in the unit descriptor */ - -#define CYL u3 /* current cylinder */ -#define FUNC u4 /* function */ - -/* Status register A */ - -#define STA_V_UNIT 15 /* unit select */ -#define STA_M_UNIT 07 -#define STA_V_FUNC 12 /* function */ -#define STA_M_FUNC 07 -#define FN_IDLE 0 -#define FN_READ 1 -#define FN_WRITE 2 -#define FN_RECAL 3 -#define FN_SEEK 4 -#define FN_RDALL 5 -#define FN_WRALL 6 -#define FN_WRCHK 7 -#define FN_2ND 010 /* second state flag */ -#define STA_IED 0004000 /* int enable done */ -#define STA_IEA 0002000 /* int enable attn */ -#define STA_GO 0001000 /* go */ -#define STA_WPE 0000400 /* write lock error */ -#define STA_NXC 0000200 /* nx cyl error */ -#define STA_NXF 0000100 /* nx surface error */ -#define STA_NXS 0000040 /* nx sector error */ -#define STA_HNF 0000020 /* hdr not found */ -#define STA_SUWP 0000010 /* sel unit wrt lock */ -#define STA_SUSI 0000004 /* sel unit seek inc */ -#define STA_DON 0000002 /* done */ -#define STA_ERR 0000001 /* error */ - -#define STA_RW 0777000 /* read/write */ -#define STA_EFLGS (STA_WPE | STA_NXC | STA_NXF | STA_NXS | \ - STA_HNF | STA_SUSI) /* error flags */ -#define STA_DYN (STA_SUWP | STA_SUSI) /* per unit status */ -#define GET_UNIT(x) (((x) >> STA_V_UNIT) & STA_M_UNIT) -#define GET_FUNC(x) (((x) >> STA_V_FUNC) & STA_M_FUNC) - -/* Status register B */ - -#define STB_V_ATT0 17 /* unit 0 attention */ -#define STB_ATTN 0776000 /* attention flags */ -#define STB_SUFU 0001000 /* sel unit unsafe */ -#define STB_PGE 0000400 /* programming error */ -#define STB_EOP 0000200 /* end of pack */ -#define STB_TME 0000100 /* timing error */ -#define STB_FME 0000040 /* format error */ -#define STB_WCE 0000020 /* write check error */ -#define STB_WPE 0000010 /* word parity error */ -#define STB_LON 0000004 /* long parity error */ -#define STB_SUSU 0000002 /* sel unit seeking */ -#define STB_SUNR 0000001 /* sel unit not rdy */ - -#define STB_EFLGS (STB_SUFU | STB_PGE | STB_EOP | STB_TME | STB_FME | \ - STB_WCE | STB_WPE | STB_LON ) /* error flags */ -#define STB_DYN (STB_SUFU | STB_SUSU | STB_SUNR) /* per unit */ - -/* Disk address */ - -#define DA_V_SECT 0 /* sector */ -#define DA_M_SECT 017 -#define DA_V_SURF 5 -#define DA_M_SURF 037 -#define DA_V_CYL 10 /* cylinder */ -#define DA_M_CYL 0377 -#define GET_SECT(x) (((x) >> DA_V_SECT) & DA_M_SECT) -#define GET_SURF(x) (((x) >> DA_V_SURF) & DA_M_SURF) -#define GET_CYL(x) (((x) >> DA_V_CYL) & DA_M_CYL) -#define GET_DA(x) ((((GET_CYL (x) * RP_NUMSF) + GET_SURF (x)) * \ - RP_NUMSC) + GET_SECT (x)) - -#define RP_MIN 2 -#define MAX(x,y) (((x) > (y))? (x): (y)) - -extern int32 M[]; -extern int32 int_hwre[API_HLVL+1], nexm; -extern UNIT cpu_unit; - -int32 rp_sta = 0; /* status A */ -int32 rp_stb = 0; /* status B */ -int32 rp_ma = 0; /* memory address */ -int32 rp_da = 0; /* disk address */ -int32 rp_wc = 0; /* word count */ -int32 rp_busy = 0; /* busy */ -int32 rp_stopioe = 1; /* stop on error */ -int32 rp_swait = 10; /* seek time */ -int32 rp_rwait = 10; /* rotate time */ - -DEVICE rp_dev; -int32 rp63 (int32 pulse, int32 dat); -int32 rp64 (int32 pulse, int32 dat); -int32 rp_iors (void); -t_stat rp_svc (UNIT *uptr); -void rp_updsta (int32 newa, int32 newb); -t_stat rp_reset (DEVICE *dptr); -t_stat rp_attach (UNIT *uptr, char *cptr); -t_stat rp_detach (UNIT *uptr); - -/* RP15 data structures - - rp_dev RP device descriptor - rp_unit RP unit list - rp_reg RP register list - rp_mod RP modifier list -*/ - -DIB rp_dib = { DEV_RP, 2, &rp_iors, { &rp63, &rp64 } }; - -UNIT rp_unit[] = { - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) } }; - -REG rp_reg[] = { - { ORDATA (STA, rp_sta, 18) }, - { ORDATA (STB, rp_stb, 18) }, - { ORDATA (DA, rp_da, 18) }, - { ORDATA (MA, rp_ma, 18) }, - { ORDATA (WC, rp_wc, 18) }, - { FLDATA (INT, int_hwre[API_RP], INT_V_RP) }, - { FLDATA (BUSY, rp_busy, 0) }, - { FLDATA (STOP_IOE, rp_stopioe, 0) }, - { DRDATA (STIME, rp_swait, 24), PV_LEFT }, - { DRDATA (RTIME, rp_rwait, 24), PV_LEFT }, - { ORDATA (DEVNO, rp_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB rp_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE rp_dev = { - "RP", rp_unit, rp_reg, rp_mod, - RP_NUMDR, 8, 24, 1, 8, 18, - NULL, NULL, &rp_reset, - NULL, &rp_attach, &rp_detach, - &rp_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 rp63 (int32 pulse, int32 dat) -{ -int32 sb = pulse & 060; /* subopcode */ - -rp_updsta (0, 0); -if (pulse & 01) { - if ((sb == 000) && /* DPSF */ - ((rp_sta & (STA_DON | STA_ERR)) || (rp_stb & STB_ATTN))) - dat = IOT_SKP | dat; - else if ((sb == 020) && (rp_stb & STB_ATTN)) /* DPSA */ - dat = IOT_SKP | dat; - else if ((sb == 040) && (rp_sta & STA_DON)) /* DPSJ */ - dat = IOT_SKP | dat; - else if ((sb == 060) && (rp_sta & STA_ERR)) /* DPSE */ - dat = IOT_SKP | dat; - } -if (pulse & 02) { - if (sb == 000) dat = dat | rp_sta; /* DPOSA */ - else if (sb == 020) dat = dat | rp_stb; /* DPOSB */ - } -if (pulse & 04) { - if (rp_busy) { /* busy? */ - rp_updsta (0, STB_PGE); - return dat; } - else if (sb == 000) { /* DPLA */ - rp_da = dat & DMASK; - if (GET_SECT (rp_da) >= RP_NUMSC) rp_updsta (STA_NXS, 0); - if (GET_SURF (rp_da) >= RP_NUMSF) rp_updsta (STA_NXF, 0); - if (GET_CYL (rp_da) >= RP_NUMCY) rp_updsta (STA_NXC, 0); } - else if (sb == 020) { /* DPCS */ - rp_sta = rp_sta & ~(STA_HNF | STA_DON); - rp_stb = rp_stb & ~(STB_FME | STB_WPE | STB_LON | STB_WCE | - STB_TME | STB_PGE | STB_EOP); - rp_updsta (0, 0); } - else if (sb == 040) rp_ma = dat & DMASK; /* DPCA */ - else if (sb == 060) rp_wc = dat & DMASK; /* DPWC */ - } -return dat; -} - -/* IOT 64 */ - -int32 rp64 (int32 pulse, int32 dat) -{ -int32 u, f, c, sb; -UNIT *uptr; - -sb = pulse & 060; -if (pulse & 01) { - if (sb == 020) dat = IOT_SKP | dat; /* DPSN */ - } -if (pulse & 02) { - if (sb == 000) dat = dat | rp_unit[GET_UNIT (rp_sta)].CYL; /* DPOU */ - else if (sb == 020) dat = dat | rp_da; /* DPOA */ - else if (sb == 040) dat = dat | rp_ma; /* DPOC */ - else if (sb == 060) dat = dat | rp_wc; /* DPOW */ - } -if (pulse & 04) { - if (rp_busy) { /* busy? */ - rp_updsta (0, STB_PGE); - return dat; } - if (sb == 000) rp_sta = rp_sta & ~STA_RW; /* DPCF */ - else if (sb == 020) rp_sta = rp_sta & (dat | ~STA_RW); /* DPLZ */ - else if (sb == 040) rp_sta = rp_sta | (dat & STA_RW); /* DPLO */ - else if (sb == 060) /* DPLF */ - rp_sta = (rp_sta & ~STA_RW) | (dat & STA_RW); - rp_sta = rp_sta & ~STA_DON; /* clear done */ - u = GET_UNIT (rp_sta); /* get unit num */ - uptr = rp_dev.units + u; /* select unit */ - if ((rp_sta & STA_GO) && !sim_is_active (uptr)) { - f = uptr->FUNC = GET_FUNC (rp_sta); /* get function */ - rp_busy = 1; /* set ctrl busy */ - rp_sta = rp_sta & ~(STA_HNF | STA_DON); /* clear flags */ - rp_stb = rp_stb & ~(STB_FME | STB_WPE | STB_LON | STB_WCE | - STB_TME | STB_PGE | STB_EOP | (1 << (STB_V_ATT0 - u))); - if (((uptr->flags & UNIT_ATT) == 0) || (f == FN_IDLE) || - (f == FN_SEEK) || (f == FN_RECAL)) - sim_activate (uptr, RP_MIN); /* short delay */ - else { - c = GET_CYL (rp_da); - c = abs (c - uptr->CYL) * rp_swait; /* seek time */ - sim_activate (uptr, MAX (RP_MIN, c + rp_rwait)); } } - } -rp_updsta (0, 0); -return dat; -} - -/* Unit service - - If function = idle, clear busy - If seek or recal initial state, clear attention line, compute seek time, - put on cylinder, set second state - If unit not attached, give error - If seek or recal second state, set attention line, compute errors - Else complete data transfer command - - The unit control block contains the function and cylinder for - the current command. -*/ - -static int32 fill[RP_NUMWD] = { 0 }; -t_stat rp_svc (UNIT *uptr) -{ -int32 f, u, comp, cyl, sect, surf; -int32 err, pa, da, wc, awc, i; - -u = uptr - rp_dev.units; /* get drv number */ -f = uptr->FUNC; /* get function */ -if (f == FN_IDLE) { /* idle? */ - rp_busy = 0; /* clear busy */ - return SCPE_OK; } - -if ((f == FN_SEEK) || (f == FN_RECAL)) { /* seek or recal? */ - rp_busy = 0; /* not busy */ - cyl = (f == FN_SEEK)? GET_CYL (rp_da): 0; /* get cylinder */ - sim_activate (uptr, MAX (RP_MIN, abs (cyl - uptr->CYL) * rp_swait)); - uptr->CYL = cyl; /* on cylinder */ - uptr->FUNC = FN_SEEK | FN_2ND; /* set second state */ - rp_updsta (0, 0); /* update status */ - return SCPE_OK; } - -if (f == (FN_SEEK | FN_2ND)) { /* seek done? */ - rp_updsta (0, rp_stb | (1 << (STB_V_ATT0 - u))); /* set attention */ - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rp_updsta (STA_DON, STB_SUFU); /* done, unsafe */ - return IORETURN (rp_stopioe, SCPE_UNATT); } - -if ((f == FN_WRITE) && (uptr->flags & UNIT_WPRT)) { /* write locked? */ - rp_updsta (STA_DON | STA_WPE, 0); /* error */ - return SCPE_OK; } - -if (GET_SECT (rp_da) >= RP_NUMSC) rp_updsta (STA_NXS, 0); -if (GET_SURF (rp_da) >= RP_NUMSF) rp_updsta (STA_NXF, 0); -if (GET_CYL (rp_da) >= RP_NUMCY) rp_updsta (STA_NXC, 0); -if (rp_sta & (STA_NXS | STA_NXF | STA_NXC)) { /* or bad disk addr? */ - rp_updsta (STA_DON, STB_SUFU); /* done, unsafe */ - return SCPE_OK; } - -pa = rp_ma & AMASK; /* get mem addr */ -da = GET_DA (rp_da) * RP_NUMWD; /* get disk addr */ -wc = 01000000 - rp_wc; /* get true wc */ -if (((uint32) (pa + wc)) > MEMSIZE) { /* memory overrun? */ - nexm = 1; /* set nexm flag */ - wc = MEMSIZE - pa; } /* limit xfer */ -if ((da + wc) > RP_SIZE) { /* disk overrun? */ - rp_updsta (0, STB_EOP); /* error */ - wc = RP_SIZE - da; } /* limit xfer */ - -err = fseek (uptr->fileref, da * sizeof (int), SEEK_SET); - -if ((f == FN_READ) && (err == 0)) { /* read? */ - awc = fxread (&M[pa], sizeof (int32), wc, uptr->fileref); - for ( ; awc < wc; awc++) M[pa + awc] = 0; - err = ferror (uptr->fileref); } - -if ((f == FN_WRITE) && (err == 0)) { /* write? */ - fxwrite (&M[pa], sizeof (int32), wc, uptr->fileref); - err = ferror (uptr->fileref); - if ((err == 0) && (i = (wc & (RP_NUMWD - 1)))) { - fxwrite (fill, sizeof (int), i, uptr->fileref); - err = ferror (uptr->fileref); } } - -if ((f == FN_WRCHK) && (err == 0)) { /* write check? */ - for (i = 0; (err == 0) && (i < wc); i++) { - awc = fxread (&comp, sizeof (int32), 1, uptr->fileref); - if (awc == 0) comp = 0; - if (comp != M[pa + i]) rp_updsta (0, STB_WCE); } - err = ferror (uptr->fileref); } - -rp_wc = (rp_wc + wc) & DMASK; /* final word count */ -rp_ma = (rp_ma + wc) & DMASK; /* final mem addr */ -da = (da + wc + (RP_NUMWD - 1)) / RP_NUMWD; /* final sector num */ -cyl = da / (RP_NUMSC * RP_NUMSF); /* get cyl */ -if (cyl >= RP_NUMCY) cyl = RP_NUMCY - 1; -surf = (da % (RP_NUMSC * RP_NUMSF)) / RP_NUMSC; /* get surface */ -sect = (da % (RP_NUMSC * RP_NUMSF)) % RP_NUMSC; /* get sector */ -rp_da = (cyl << DA_V_CYL) | (surf << DA_V_SURF) | (sect << DA_V_SECT); -rp_busy = 0; /* clear busy */ -rp_updsta (STA_DON, 0); /* set done */ - -if (err != 0) { /* error? */ - perror ("RP I/O error"); - clearerr (uptr->fileref); - return IORETURN (rp_stopioe, SCPE_IOERR); } -return SCPE_OK; -} - -/* Update status */ - -void rp_updsta (int32 newa, int32 newb) -{ -int32 f; -UNIT *uptr; - -uptr = rp_dev.units + GET_UNIT (rp_sta); -rp_sta = (rp_sta & ~(STA_DYN | STA_ERR)) | newa; -rp_stb = (rp_stb & ~STB_DYN) | newb; -if (uptr->flags & UNIT_WPRT) rp_sta = rp_sta | STA_SUWP; -if ((uptr->flags & UNIT_ATT) == 0) rp_stb = rp_stb | STB_SUFU | STB_SUNR; -else if (sim_is_active (uptr)) { - f = (uptr->FUNC) & STA_M_FUNC; - if ((f == FN_SEEK) || (f == FN_RECAL)) - rp_stb = rp_stb | STB_SUSU | STB_SUNR; } -else if (uptr->CYL >= RP_NUMCY) rp_sta = rp_sta | STA_SUSI; -if ((rp_sta & STA_EFLGS) || (rp_stb & STB_EFLGS)) rp_sta = rp_sta | STA_ERR; -if (((rp_sta & (STA_ERR | STA_DON)) && (rp_sta & STA_IED)) || - ((rp_stb & STB_ATTN) && (rp_sta & STA_IEA))) SET_INT (RP); -else CLR_INT (RP); -return; -} - -/* Reset routine */ - -t_stat rp_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -rp_sta = rp_stb = rp_da = rp_wc = rp_ma = rp_busy = 0; -CLR_INT (RP); -for (i = 0; i < RP_NUMDR; i++) { - uptr = rp_dev.units + i; - sim_cancel (uptr); - uptr->CYL = uptr->FUNC = 0; } -return SCPE_OK; -} - -/* IORS routine */ - -int32 rp_iors (void) -{ -return ((rp_sta & (STA_ERR | STA_DON)) || (rp_stb & STB_ATTN))? IOS_RP: 0; -} - -/* Attach unit */ - -t_stat rp_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); -rp_updsta (0, 0); -return reason; -} - -/* Detach unit */ - -t_stat rp_detach (UNIT *uptr) -{ -t_stat reason; - -reason = detach_unit (uptr); -rp_updsta (0, 0); -return reason; -} diff --git a/PDP18B/pdp18b_stddev.c b/PDP18B/pdp18b_stddev.c deleted file mode 100644 index dc36133b..00000000 --- a/PDP18B/pdp18b_stddev.c +++ /dev/null @@ -1,975 +0,0 @@ -/* pdp18b_stddev.c: 18b PDP's standard devices - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - ptr paper tape reader - ptp paper tape punch - tti keyboard - tto teleprinter - clk clock - - 26-Jul-03 RMS Increased PTP, TTO timeouts for PDP-15 operating systems - Added hardware read-in mode support for PDP-7/9/15 - 25-Apr-03 RMS Revised for extended file support - 14-Mar-03 RMS Clean up flags on detach - 01-Mar-03 RMS Added SET/SHOW CLK FREQ support, SET TTI CTRL-C support - 22-Dec-02 RMS Added break support - 01-Nov-02 RMS Added 7B/8B support to terminal - 05-Oct-02 RMS Added DIBs, device number support, IORS call - 14-Jul-02 RMS Added ASCII reader/punch support (from Hans Pufal) - 30-May-02 RMS Widened POS to 32b - 29-Nov-01 RMS Added read only unit support - 25-Nov-01 RMS Revised interrupt structure - 17-Sep-01 RMS Removed multiconsole support - 07-Sep-01 RMS Added terminal multiplexor support - 17-Jul-01 RMS Moved function prototype - 10-Jun-01 RMS Cleaned up IOT decoding to reflect hardware - 27-May-01 RMS Added multiconsole support - 10-Mar-01 RMS Added funny format loader support - 05-Mar-01 RMS Added clock calibration support - 22-Dec-00 RMS Added PDP-9/15 half duplex support - 30-Nov-00 RMS Fixed PDP-4/7 bootstrap loader for 4K systems - 30-Oct-00 RMS Standardized register naming - 06-Jan-97 RMS Fixed PDP-4 console input - 16-Dec-96 RMS Fixed bug in binary ptr service -*/ - -#include "pdp18b_defs.h" -#include - -#define UNIT_V_RASCII (UNIT_V_UF + 0) /* reader ASCII */ -#define UNIT_RASCII (1 << UNIT_V_RASCII) -#define UNIT_V_PASCII (UNIT_V_UF + 0) /* punch ASCII */ -#define UNIT_PASCII (1 << UNIT_V_PASCII) - -extern int32 M[]; -extern int32 int_hwre[API_HLVL+1], PC, ASW; -extern int32 sim_switches; -extern UNIT cpu_unit; - -int32 clk_state = 0; -int32 ptr_err = 0, ptr_stopioe = 0, ptr_state = 0; -int32 ptp_err = 0, ptp_stopioe = 0; -int32 tti_state = 0; -int32 tto_state = 0; -int32 clk_tps = 60; /* ticks/second */ -int32 tmxr_poll = 16000; /* term mux poll */ - -int32 ptr (int32 pulse, int32 dat); -int32 ptp (int32 pulse, int32 dat); -int32 tti (int32 pulse, int32 dat); -int32 tto (int32 pulse, int32 dat); -int32 clk_iors (void); -int32 ptr_iors (void); -int32 ptp_iors (void); -int32 tti_iors (void); -int32 tto_iors (void); -t_stat clk_svc (UNIT *uptr); -t_stat ptr_svc (UNIT *uptr); -t_stat ptp_svc (UNIT *uptr); -t_stat tti_svc (UNIT *uptr); -t_stat tto_svc (UNIT *uptr); -t_stat clk_reset (DEVICE *dptr); -t_stat ptr_reset (DEVICE *dptr); -t_stat ptp_reset (DEVICE *dptr); -t_stat tti_reset (DEVICE *dptr); -t_stat tto_reset (DEVICE *dptr); -t_stat ptr_attach (UNIT *uptr, char *cptr); -t_stat ptp_attach (UNIT *uptr, char *cptr); -t_stat ptr_detach (UNIT *uptr); -t_stat ptp_detach (UNIT *uptr); -t_stat ptr_boot (int32 unitno, DEVICE *dptr); -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc); - -extern int32 upd_iors (void); - -/* CLK data structures - - clk_dev CLK device descriptor - clk_unit CLK unit - clk_reg CLK register list -*/ - -DIB clk_dib = { 0, 0, &clk_iors, { NULL } }; - -UNIT clk_unit = { UDATA (&clk_svc, 0, 0), 16000 }; - -REG clk_reg[] = { - { FLDATA (INT, int_hwre[API_CLK], INT_V_CLK) }, - { FLDATA (DONE, int_hwre[API_CLK], INT_V_CLK) }, - { FLDATA (ENABLE, clk_state, 0) }, - { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO }, - { NULL } }; - -MTAB clk_mod[] = { - { MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL, - NULL, &clk_show_freq, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno }, - { 0 } }; - -DEVICE clk_dev = { - "CLK", &clk_unit, clk_reg, clk_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &clk_reset, - NULL, NULL, NULL, - &clk_dib, 0 }; - -/* PTR data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit - ptr_reg PTR register list -*/ - -DIB ptr_dib = { DEV_PTR, 1, &ptr_iors, { &ptr } }; - -UNIT ptr_unit = { - UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), - SERIAL_IN_WAIT }; - -REG ptr_reg[] = { - { ORDATA (BUF, ptr_unit.buf, 18) }, - { FLDATA (INT, int_hwre[API_PTR], INT_V_PTR) }, - { FLDATA (DONE, int_hwre[API_PTR], INT_V_PTR) }, -#if defined (IOS_PTRERR) - { FLDATA (ERR, ptr_err, 0) }, -#endif - { ORDATA (STATE, ptr_state, 5), REG_HRO }, - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptr_stopioe, 0) }, - { NULL } }; - -MTAB ptr_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno }, - { 0 } }; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, ptr_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - &ptr_boot, &ptr_attach, &ptr_detach, - &ptr_dib, 0 }; - -/* PTP data structures - - ptp_dev PTP device descriptor - ptp_unit PTP unit - ptp_reg PTP register list -*/ - -DIB ptp_dib = { DEV_PTP, 1, &ptp_iors, { &ptp } }; - -UNIT ptp_unit = { - UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), 1000 }; - -REG ptp_reg[] = { - { ORDATA (BUF, ptp_unit.buf, 8) }, - { FLDATA (INT, int_hwre[API_PTP], INT_V_PTP) }, - { FLDATA (DONE, int_hwre[API_PTP], INT_V_PTP) }, -#if defined (IOS_PTPERR) - { FLDATA (ERR, ptp_err, 0) }, -#endif - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptp_stopioe, 0) }, - { NULL } }; - -MTAB ptp_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno }, - { 0 } }; - -DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, ptp_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptp_reset, - NULL, &ptp_attach, &ptp_detach, - &ptp_dib, 0 }; - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit - tti_reg TTI register list - tti_trans ASCII to Baudot table -*/ - -#if defined (KSR28) -#define TTI_WIDTH 5 -#define TTI_FIGURES (1 << TTI_WIDTH) -#define TTI_2ND (1 << (TTI_WIDTH + 1)) -#define TTI_BOTH (1 << (TTI_WIDTH + 2)) -#define BAUDOT_LETTERS 033 -#define BAUDOT_FIGURES 037 - -static const int32 tti_trans[128] = { - 000,000,000,000,000,000,000,064, /* bell */ - 000,000,0210,000,000,0202,000,000, /* lf, cr */ - 000,000,000,000,000,000,000,000, - 000,000,000,000,000,000,000,000, - 0204,066,061,045,062,000,053,072, /* space - ' */ - 076,051,000,000,046,070,047,067, /* ( - / */ - 055,075,071,060,052,041,065,074, /* 0 - 7 */ - 054,043,056,057,000,000,000,063, /* 8 - ? */ - 000,030,023,016,022,020,026,013, /* @ - G */ - 005,014,032,036,011,007,006,003, /* H - O */ - 015,035,012,024,001,034,017,031, /* P - W */ - 027,025,021,000,000,000,000,000, /* X - _ */ - 000,030,023,016,022,020,026,013, /* ` - g */ - 005,014,032,036,011,007,006,003, /* h - o */ - 015,035,012,024,001,034,017,031, /* p - w */ - 027,025,021,000,000,000,000,000 }; /* x - DEL */ -#else - -#define TTI_WIDTH 8 -#endif - -#define TTI_MASK ((1 << TTI_WIDTH) - 1) -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */ -#define UNIT_V_HDX (UNIT_V_UF + 2) /* half duplex */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_KSR (1 << UNIT_V_KSR) -#define UNIT_HDX (1 << UNIT_V_HDX) - -DIB tti_dib = { DEV_TTI, 1, &tti_iors, { &tti } }; - -#if defined (PDP4) || defined (PDP7) -UNIT tti_unit = { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }; -#else -UNIT tti_unit = { UDATA (&tti_svc, UNIT_KSR+UNIT_HDX, 0), KBD_POLL_WAIT }; -#endif - -REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, TTI_WIDTH) }, - { FLDATA (INT, int_hwre[API_TTI], INT_V_TTI) }, - { FLDATA (DONE, int_hwre[API_TTI], INT_V_TTI) }, -#if defined (KSR28) - { ORDATA (TTI_STATE, tti_state, (TTI_WIDTH + 3)), REG_HRO }, -#endif - { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB tti_mod[] = { -#if !defined (KSR28) - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, - { UNIT_HDX, 0 , "full duplex", "FDX", NULL }, - { UNIT_HDX, UNIT_HDX, "half duplex", "HDX", NULL }, - { MTAB_XTD|MTAB_VDV|MTAB_VUN, 0, NULL, "CTRL-C", &tti_set_ctrlc, NULL, NULL }, -#endif - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno, NULL }, - { 0 } }; - -DEVICE tti_dev = { - "TTI", &tti_unit, tti_reg, tti_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tti_reset, - NULL, NULL, NULL, - &tti_dib, 0 }; - -/* TTO data structures - - tto_dev TTO device descriptor - tto_unit TTO unit - tto_reg TTO register list - tto_trans Baudot to ASCII table -*/ - -#if defined (KSR28) -#define TTO_WIDTH 5 -#define TTO_FIGURES (1 << TTO_WIDTH) - -static const char tto_trans[64] = { - 0 ,'T',015,'O',' ','H','N','M', - 012,'L','R','G','I','P','C','V', - 'E','Z','D','B','S','Y','F','X', - 'A','W','J', 0 ,'U','Q','K', 0, - 0 ,'5','\r','9',' ','#',',','.', - 012,')','4','&','8','0',':',';', - '3','"','$','?','\a','6','!','/', - '-','2','\'',0 ,'7','1','(', 0 }; -#else - -#define TTO_WIDTH 8 -#endif - -#define TTO_MASK ((1 << TTO_WIDTH) - 1) - -DIB tto_dib = { DEV_TTO, 1, &tto_iors, { &tto } }; - -UNIT tto_unit = { UDATA (&tto_svc, UNIT_KSR, 0), 1000 }; - -REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, TTO_WIDTH) }, - { FLDATA (INT, int_hwre[API_TTO], INT_V_TTO) }, - { FLDATA (DONE, int_hwre[API_TTO], INT_V_TTO) }, -#if defined (KSR28) - { FLDATA (TTO_STATE, tto_state, 0), REG_HRO }, -#endif - { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -MTAB tto_mod[] = { -#if !defined (KSR28) - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, -#endif - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno }, - { 0 } }; - -DEVICE tto_dev = { - "TTO", &tto_unit, tto_reg, tto_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto_reset, - NULL, NULL, NULL, - &tto_dib, 0 }; - -/* Clock: IOT routine */ - -int32 clk (int32 pulse, int32 dat) -{ -if (pulse & 001) { /* CLSF */ - if (TST_INT (CLK)) dat = dat | IOT_SKP; } -if (pulse & 004) { /* CLON/CLOF */ - if (pulse & 040) { /* CLON */ - CLR_INT (CLK); /* clear flag */ - clk_state = 1; /* clock on */ - if (!sim_is_active (&clk_unit)) /* already on? */ - sim_activate (&clk_unit, /* start, calibr */ - sim_rtc_init (clk_unit.wait)); } - else clk_reset (&clk_dev); } /* CLOF */ -return dat; -} - -/* Unit service */ - -t_stat clk_svc (UNIT *uptr) -{ -int32 t; - -if (clk_state) { /* clock on? */ - M[7] = (M[7] + 1) & DMASK; /* incr counter */ - if (M[7] == 0) SET_INT (CLK); /* ovrflo? set flag */ - t = sim_rtc_calb (clk_tps); /* calibrate clock */ - sim_activate (&clk_unit, t); /* reactivate unit */ - tmxr_poll = t; } /* set mux poll */ -return SCPE_OK; -} - -/* IORS service */ - -int32 clk_iors (void) -{ -return (TST_INT (CLK)? IOS_CLK: 0); -} - -/* Reset routine */ - -t_stat clk_reset (DEVICE *dptr) -{ -CLR_INT (CLK); /* clear flag */ -clk_state = 0; /* clock off */ -sim_cancel (&clk_unit); /* stop clock */ -tmxr_poll = clk_unit.wait; /* set mux poll */ -return SCPE_OK; -} - -/* Set frequency */ - -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; -clk_tps = val; -return SCPE_OK; -} - -/* Show frequency */ - -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, (clk_tps == 50)? "50Hz": "60Hz"); -return SCPE_OK; -} - -/* Paper tape reader: IOT routine */ - -int32 ptr (int32 pulse, int32 dat) -{ -if (pulse & 001) { /* RSF */ - if (TST_INT (PTR)) dat = dat | IOT_SKP; } -if (pulse & 002) { /* RRB, RCF */ - CLR_INT (PTR); /* clear done */ - dat = dat | ptr_unit.buf; } /* return buffer */ -if (pulse & 004) { /* RSA, RSB */ - ptr_state = (pulse & 040)? 18: 0; /* set mode */ - CLR_INT (PTR); /* clear done */ - ptr_unit.buf = 0; /* clear buffer */ - sim_activate (&ptr_unit, ptr_unit.wait); } -return dat; -} - -/* Unit service */ - -t_stat ptr_svc (UNIT *uptr) -{ -int32 temp; - -if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */ -#if defined (IOS_PTRERR) - SET_INT (PTR); /* if err, set int */ - ptr_err = 1; -#endif - return IORETURN (ptr_stopioe, SCPE_UNATT); } -if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */ -#if defined (IOS_PTRERR) - SET_INT (PTR); /* if err, set done */ - ptr_err = 1; -#endif - if (feof (ptr_unit.fileref)) { - if (ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } - else perror ("PTR I/O error"); - clearerr (ptr_unit.fileref); - return SCPE_IOERR; } -if (ptr_state == 0) { /* ASCII */ - if (ptr_unit.flags & UNIT_RASCII) { /* want parity? */ - ptr_unit.buf = temp = temp & 0177; /* parity off */ - while (temp = temp & (temp - 1)) - ptr_unit.buf = ptr_unit.buf ^ 0200; /* count bits */ - ptr_unit.buf = ptr_unit.buf ^ 0200; } /* set even parity */ - else ptr_unit.buf = temp & 0377; } -else if (temp & 0200) { /* binary */ - ptr_state = ptr_state - 6; - ptr_unit.buf = ptr_unit.buf | ((temp & 077) << ptr_state); } -if (ptr_state == 0) SET_INT (PTR); /* if done, set flag */ -else sim_activate (&ptr_unit, ptr_unit.wait); /* else restart */ -ptr_unit.pos = ptr_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptr_reset (DEVICE *dptr) -{ -ptr_state = 0; /* clear state */ -ptr_unit.buf = 0; -CLR_INT (PTR); /* clear flag */ -ptr_err = (ptr_unit.flags & UNIT_ATT)? 0: 1; -sim_cancel (&ptr_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* IORS service */ - -int32 ptr_iors (void) -{ -return ((TST_INT (PTR)? IOS_PTR: 0) -#if defined (IOS_PTRERR) - | (ptr_err? IOS_PTRERR: 0) -#endif - ); -} - -/* Attach routine */ - -t_stat ptr_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); -ptr_err = (ptr_unit.flags & UNIT_ATT)? 0: 1; -ptr_unit.flags = ptr_unit.flags & ~UNIT_RASCII; -if (sim_switches & SWMASK ('A')) - ptr_unit.flags = ptr_unit.flags | UNIT_RASCII; -return reason; -} - -/* Detach routine */ - -t_stat ptr_detach (UNIT *uptr) -{ -ptr_err = 1; -ptr_unit.flags = ptr_unit.flags & ~UNIT_RASCII; -return detach_unit (uptr); -} - -/* Hardware RIM loader routines, PDP-7/9/15 */ - -int32 ptr_getw (FILE *fileref, int32 *hi) -{ -int32 word, bits, st, ch; - -word = st = bits = 0; -do { if ((ch = getc (fileref)) == EOF) return -1; - if (ch & 0200) { - word = (word << 6) | (ch & 077); - bits = (bits << 1) | ((ch >> 6) & 1); - st++; } } -while (st < 3); -if (hi != NULL) *hi = bits; -return word; -} - -t_stat ptr_rim_load (FILE *fileref, int32 origin) -{ -int32 bits, val; - -for (;;) { /* word loop */ - if ((val = ptr_getw (fileref, &bits)) < 0) return SCPE_FMT; - if (bits & 1) { /* end of tape? */ - if ((val & 0760000) == OP_JMP) { - PC = ((origin - 1) & 060000) | (val & 017777); - return SCPE_OK; } - else if (val == OP_HLT) return STOP_HALT; - break; } - else if (MEM_ADDR_OK (origin)) M[origin++] = val; } -return SCPE_FMT; -} - -#if defined (PDP4) || defined (PDP7) - -/* Bootstrap routine, PDP-4 and PDP-7 - - In a 4K system, the boostrap resides at 7762-7776. - In an 8K or greater system, the bootstrap resides at 17762-17776. - Because the program is so small, simple masking can be - used to remove addr<5> for a 4K system. */ - -#define BOOT_START 017577 -#define BOOT_FPC 017577 /* funny format loader */ -#define BOOT_RPC 017770 /* RIM loader */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) - -static const int32 boot_rom[] = { - 0700144, /* rsb */ - 0117762, /* ff, jsb r1b */ - 0057666, /* dac done 1 */ - 0117762, /* jms r1b */ - 0057667, /* dac done 2 */ - 0117762, /* jms r1b */ - 0040007, /* dac conend */ - 0057731, /* dac conbeg */ - 0440007, /* isz conend */ - 0117762, /* blk, jms r1b */ - 0057673, /* dac cai */ - 0741100, /* spa */ - 0617665, /* jmp done */ - 0117762, /* jms r1b */ - 0057777, /* dac tem1 */ - 0317673, /* add cai */ - 0057775, /* dac cks */ - 0117713, /* jms r1a */ - 0140010, /* dzm word */ - 0457777, /* cont, isz tem1 */ - 0617632, /* jmp cont1 */ - 0217775, /* lac cks */ - 0740001, /* cma */ - 0740200, /* sza */ - 0740040, /* hlt */ - 0700144, /* rsb */ - 0617610, /* jmp blk */ - 0117713, /* cont1, jms r1a */ - 0057762, /* dac tem2 */ - 0117713, /* jms r1a */ - 0742010, /* rtl */ - 0742010, /* rtl */ - 0742010, /* rtl */ - 0742010, /* rtl */ - 0317762, /* add tem2 */ - 0057762, /* dac tem2 */ - 0117713, /* jms r1a */ - 0742020, /* rtr */ - 0317726, /* add cdsp */ - 0057713, /* dac r1a */ - 0517701, /* and ccma */ - 0740020, /* rar */ - 0317762, /* add tem2 */ - 0437713, /* xct i r1a */ - 0617622, /* jmp cont */ - 0617672, /* dsptch, jmp code0 */ - 0617670, /* jmp code1 */ - 0617700, /* jmp code2 */ - 0617706, /* jmp code3 */ - 0417711, /* xct code4 */ - 0617732, /* jmp const */ - 0740000, /* nop */ - 0740000, /* nop */ - 0740000, /* nop */ - 0200007, /* done, lac conend */ - 0740040, /* xx */ - 0740040, /* xx */ - 0517727, /* code1, and imsk */ - 0337762, /* add i tem2 */ - 0300010, /* code0, add word */ - 0740040, /* cai, xx */ - 0750001, /* clc */ - 0357673, /* tad cai */ - 0057673, /* dac cai */ - 0617621, /* jmp cont-1 */ - 0711101, /* code2, spa cla */ - 0740001, /* ccma, cma */ - 0277762, /* xor i tem2 */ - 0300010, /* add word */ - 0040010, /* code2a, dac word */ - 0617622, /* jmp cont */ - 0057711, /* code3, dac code4 */ - 0217673, /* lac cai */ - 0357701, /* tad ccma */ - 0740040, /* code4, xx */ - 0617622, /* jmp cont */ - 0000000, /* r1a, 0 */ - 0700101, /* rsf */ - 0617714, /* jmp .-1 */ - 0700112, /* rrb */ - 0700104, /* rsa */ - 0057730, /* dac tem */ - 0317775, /* add cks */ - 0057775, /* dac cks */ - 0217730, /* lac tem */ - 0744000, /* cll */ - 0637713, /* jmp i r1a */ - 0017654, /* cdsp, dsptch */ - 0760000, /* imsk, 760000 */ - 0000000, /* tem, 0 */ - 0000000, /* conbeg, 0 */ - 0300010, /* const, add word */ - 0060007, /* dac i conend */ - 0217731, /* lac conbeg */ - 0040010, /* dac index */ - 0220007, /* lac i conend */ - 0560010, /* con1, sad i index */ - 0617752, /* jmp find */ - 0560010, /* sad i index */ - 0617752, /* jmp find */ - 0560010, /* sad i index */ - 0617752, /* jmp find */ - 0560010, /* sad i index */ - 0617752, /* jmp find */ - 0560010, /* sad i index */ - 0617752, /* jmp find */ - 0617737, /* jmp con1 */ - 0200010, /* find, lac index */ - 0540007, /* sad conend */ - 0440007, /* isz conend */ - 0617704, /* jmp code2a */ - 0000000, - 0000000, - 0000000, - 0000000, - 0000000, /* r1b, 0 */ - 0700101, /* rsf */ - 0617763, /* jmp .-1 */ - 0700112, /* rrb */ - 0700144, /* rsb */ - 0637762, /* jmp i r1b */ - 0700144, /* go, rsb */ - 0117762, /* g, jms r1b */ - 0057775, /* dac cks */ - 0417775, /* xct cks */ - 0117762, /* jms r1b */ - 0000000, /* cks, 0 */ - 0617771 /* jmp g */ -}; - -t_stat ptr_boot (int32 unitno, DEVICE *dptr) -{ -int32 i, mask, wd; -extern int32 sim_switches; - -#if defined (PDP7) -if (sim_switches & SWMASK ('H')) /* hardware RIM load? */ - return ptr_rim_load (ptr_unit.fileref, ASW); -#endif -if (ptr_dib.dev != DEV_PTR) return STOP_NONSTD; /* non-std addr? */ -if (MEMSIZE < 8192) mask = 0767777; /* 4k? */ -else mask = 0777777; -for (i = 0; i < BOOT_LEN; i++) { - wd = boot_rom[i]; - if ((wd >= 0040000) && (wd < 0640000)) wd = wd & mask; - M[(BOOT_START & mask) + i] = wd; } -PC = ((sim_switches & SWMASK ('F'))? BOOT_FPC: BOOT_RPC) & mask; -return SCPE_OK; -} - -#else - -/* PDP-9 and PDP-15 have built-in hardware RIM loaders */ - -t_stat ptr_boot (int32 unitno, DEVICE *dptr) -{ -return ptr_rim_load (ptr_unit.fileref, ASW); -} - -#endif - -/* Paper tape punch: IOT routine */ - -int32 ptp (int32 pulse, int32 dat) -{ -if (pulse & 001) { /* PSF */ - if (TST_INT (PTP)) dat = dat | IOT_SKP; } -if (pulse & 002) CLR_INT (PTP); /* PCF */ -if (pulse & 004) { /* PSA, PSB, PLS */ - CLR_INT (PTP); /* clear flag */ - ptp_unit.buf = (pulse & 040)? /* load punch buf */ - (dat & 077) | 0200: dat & 0377; /* bin or alpha */ - sim_activate (&ptp_unit, ptp_unit.wait); } /* activate unit */ -return dat; -} - -/* Unit service */ - -t_stat ptp_svc (UNIT *uptr) -{ -SET_INT (PTP); /* set done flag */ -if ((ptp_unit.flags & UNIT_ATT) == 0) { /* not attached? */ - ptp_err = 1; /* set error */ - return IORETURN (ptp_stopioe, SCPE_UNATT); } -if (ptp_unit.flags & UNIT_PASCII) { /* ASCII mode? */ - ptp_unit.buf = ptp_unit.buf & 0177; /* force 7b */ - if ((ptp_unit.buf == 0) || (ptp_unit.buf == 0177)) - return SCPE_OK; } /* skip null, del */ -if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { /* I/O error? */ - ptp_err = 1; /* set error */ - perror ("PTP I/O error"); - clearerr (ptp_unit.fileref); - return SCPE_IOERR; } -ptp_unit.pos = ptp_unit.pos + 1; -return SCPE_OK; -} - -/* IORS service */ - -int32 ptp_iors (void) -{ -return ((TST_INT (PTP)? IOS_PTP: 0) -#if defined (IOS_PTPERR) - | (ptp_err? IOS_PTPERR: 0) -#endif - ); -} - -/* Reset routine */ - -t_stat ptp_reset (DEVICE *dptr) -{ -ptp_unit.buf = 0; -CLR_INT (PTP); /* clear flag */ -ptp_err = (ptp_unit.flags & UNIT_ATT)? 0: 1; -sim_cancel (&ptp_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Attach routine */ - -t_stat ptp_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); -ptp_err = (ptp_unit.flags & UNIT_ATT)? 0: 1; -ptp_unit.flags = ptp_unit.flags & ~UNIT_PASCII; -if (sim_switches & SWMASK ('A')) - ptp_unit.flags = ptp_unit.flags | UNIT_PASCII; -return reason; -} - -/* Detach routine */ - -t_stat ptp_detach (UNIT *uptr) -{ -ptp_err = 1; -ptp_unit.flags = ptp_unit.flags & ~UNIT_PASCII; -return detach_unit (uptr); -} - -/* Terminal input: IOT routine */ - -int32 tti (int32 pulse, int32 dat) -{ -if (pulse & 001) { /* KSF */ - if (TST_INT (TTI)) dat = dat | IOT_SKP; } -if (pulse & 002) { /* KRB */ - CLR_INT (TTI); /* clear flag */ - dat = dat | tti_unit.buf & TTI_MASK; } /* return buffer */ -if (pulse & 004) { /* IORS */ - dat = dat | upd_iors (); } -return dat; -} - -/* Unit service */ - -t_stat tti_svc (UNIT *uptr) -{ -#if defined (KSR28) /* Baudot... */ -int32 c; - -sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ -if (tti_state & TTI_2ND) { /* char waiting? */ - tti_unit.buf = tti_state & TTI_MASK; /* return char */ - tti_state = tti_state & ~TTI_2ND; } /* not waiting */ -else { if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; - c = tti_trans[c & 0177]; /* translate char */ - if (c == 0) return SCPE_OK; /* untranslatable? */ - if (((c & TTI_FIGURES) == (tti_state & TTI_FIGURES)) || - (c & TTI_BOTH)) tti_unit.buf = c & TTI_MASK; - else { - tti_unit.buf = (c & TTI_FIGURES)? - BAUDOT_FIGURES: BAUDOT_LETTERS; - tti_state = c | TTI_2ND; } } /* set 2nd waiting */ - -#else /* ASCII... */ -int32 c, out; - -sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ -if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -out = c & 0177; /* mask echo to 7b */ -if (c & SCPE_BREAK) c = 0; /* break? */ -else if (tti_unit.flags & UNIT_KSR) { /* KSR? */ - if (islower (out)) out = toupper (out); /* convert to UC */ - c = out | 0200; } /* set TTY bit */ -else c = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177); /* no, 7b/8b */ -if ((tti_unit.flags & UNIT_HDX) && out && /* half duplex and */ - (!(tto_unit.flags & UNIT_KSR) || /* 7b/8b or */ - ((out >= 007) && (out <= 0137)))) { /* in range? */ - sim_putchar (out); /* echo */ - tto_unit.pos = tto_unit.pos + 1; } -tti_unit.buf = c; /* got char */ - -#endif -tti_unit.pos = tti_unit.pos + 1; -SET_INT (TTI); /* set flag */ -return SCPE_OK; -} - -/* IORS service */ - -int32 tti_iors (void) -{ -return (TST_INT (TTI)? IOS_TTI: 0); -} - -/* Reset routine */ - -t_stat tti_reset (DEVICE *dptr) -{ -tti_unit.buf = 0; /* clear buffer */ -tti_state = 0; /* clear state */ -CLR_INT (TTI); /* clear flag */ -sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ -return SCPE_OK; -} - -/* Set control-C */ - -t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -uptr->buf = (uptr->flags & UNIT_KSR)? 0203: 0003; -uptr->pos = uptr->pos + 1; -SET_INT (TTI); -return SCPE_OK; -} - -/* Terminal output: IOT routine */ - -int32 tto (int32 pulse, int32 dat) -{ -if (pulse & 001) { /* TSF */ - if (TST_INT (TTO)) dat = dat | IOT_SKP; } -if (pulse & 002) CLR_INT (TTO); /* clear flag */ -if (pulse & 004) { /* load buffer */ - sim_activate (&tto_unit, tto_unit.wait); /* activate unit */ - tto_unit.buf = dat & TTO_MASK; } /* load buffer */ -return dat; -} - -/* Unit service */ - -t_stat tto_svc (UNIT *uptr) -{ -int32 c; -t_stat r; - -SET_INT (TTO); /* set flag */ -#if defined (KSR28) /* Baudot... */ -if (tto_unit.buf == BAUDOT_FIGURES) { /* set figures? */ - tto_state = TTO_FIGURES; - return SCPE_OK; } -if (tto_unit.buf == BAUDOT_LETTERS) { /* set letters? */ - tto_state = 0; - return SCPE_OK; } -c = tto_trans[tto_unit.buf + tto_state]; /* translate */ -#else -if (tto_unit.flags & UNIT_KSR) { /* KSR? */ - c = tto_unit.buf & 0177; - if (islower (c)) c = toupper (c); - if ((c < 007) || (c > 0137)) return SCPE_OK; } -else c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); -#endif -if ((r = sim_putchar (c)) != SCPE_OK) return r; -tto_unit.pos = tto_unit.pos + 1; -return SCPE_OK; -} - -/* IORS service */ - -int32 tto_iors (void) -{ -return (TST_INT (TTO)? IOS_TTO: 0); -} - -/* Reset routine */ - -t_stat tto_reset (DEVICE *dptr) -{ -tto_unit.buf = 0; /* clear buffer */ -tto_state = 0; /* clear state */ -CLR_INT (TTO); /* clear flag */ -sim_cancel (&tto_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Set mode */ - -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -tti_unit.flags = (tti_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; -tto_unit.flags = (tto_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; -return SCPE_OK; -} diff --git a/PDP18B/pdp18b_sys.c b/PDP18B/pdp18b_sys.c deleted file mode 100644 index 583de1b0..00000000 --- a/PDP18B/pdp18b_sys.c +++ /dev/null @@ -1,1119 +0,0 @@ -/* pdp18b_sys.c: 18b PDP's simulator interface - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 30-Jul-03 RMS Fixed FPM class mask - 18-Jul-03 RMS Added FP15 support - 02-Mar-03 RMS Split loaders apart for greater flexibility - 09-Feb-03 RMS Fixed bug in FMTASC (found by Hans Pufal) - 31-Jan-03 RMS Added support for RB09 - 05-Oct-02 RMS Added variable device number support - 25-Jul-02 RMS Added PDP-4 DECtape support - 10-Feb-02 RMS Added PDP-7 DECtape IOT's - 03-Feb-02 RMS Fixed typo (found by Robert Alan Byer) - 17-Sep-01 RMS Removed multiconsole support - 27-May-01 RMS Added second Teletype support - 18-May-01 RMS Added PDP-9,-15 API IOT's - 12-May-01 RMS Fixed bug in RIM loaders - 14-Mar-01 RMS Added extension detection of RIM format tapes - 21-Jan-01 RMS Added DECtape support - 30-Nov-00 RMS Added PDP-9,-15 RIM/BIN loader format - 30-Oct-00 RMS Added support for examine to file - 27-Oct-98 RMS V2.4 load interface - 20-Oct-97 RMS Fixed endian dependence in RIM loader - (found by Michael Somos) -*/ - -#include "pdp18b_defs.h" -#include - -extern DEVICE cpu_dev; -#if defined (PDP15) -extern DEVICE fpp_dev; -#endif -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE tti_dev, tto_dev; -extern UNIT tti_unit, tto_unit; -extern DEVICE clk_dev; -#if defined (TYPE62) -extern DEVICE lp62_dev; -#endif -#if defined (TYPE647) -extern DEVICE lp647_dev; -#endif -#if defined (LP09) -extern DEVICE lp09_dev; -#endif -#if defined (LP15) -extern DEVICE lp15_dev; -#endif -extern DEVICE dt_dev; -#if defined (DRM) -extern DEVICE drm_dev; -#endif -#if defined (RB) -extern DEVICE rb_dev; -#endif -#if defined (RF) -extern DEVICE rf_dev; -#endif -#if defined (RP) -extern DEVICE rp_dev; -#endif -#if defined (MTA) -extern DEVICE mt_dev; -#endif -#if defined (TTY1) -extern DEVICE tti1_dev, tto1_dev; -extern UNIT tti1_unit, tto1_unit; -#endif -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern int32 M[]; -extern int32 memm; -extern int32 PC; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -#if defined (PDP4) -char sim_name[] = "PDP-4"; -#elif defined (PDP7) -char sim_name[] = "PDP-7"; -#elif defined (PDP9) -char sim_name[] = "PDP-9"; -#elif defined (PDP15) -char sim_name[] = "PDP-15"; -#endif - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 2; - -DEVICE *sim_devices[] = { - &cpu_dev, -#if defined (PDP15) - &fpp_dev, -#endif - &ptr_dev, - &ptp_dev, - &tti_dev, - &tto_dev, - &clk_dev, -#if defined (TYPE62) - &lp62_dev, -#endif -#if defined (TYPE647) - &lp647_dev, -#endif -#if defined (LP09) - &lp09_dev, -#endif -#if defined (LP15) - &lp15_dev, -#endif -#if defined (DRM) - &drm_dev, -#endif -#if defined (RB) - &rb_dev, -#endif -#if defined (RF) - &rf_dev, -#endif -#if defined (RP) - &rp_dev, -#endif - &dt_dev, -#if defined (MTA) - &mt_dev, -#endif -#if defined (TTY1) - &tti1_dev, &tto1_dev, -#endif - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Undefined instruction", - "HALT instruction", - "Breakpoint", - "Nested XCT's", - "Invalid API interrupt", - "Non-standard device number", - "Memory management error", - "FP15 instruction disabled" }; - -/* Binary loaders */ - -int32 getword (FILE *fileref, int32 *hi) -{ -int32 word, bits, st, ch; - -word = st = bits = 0; -do { if ((ch = getc (fileref)) == EOF) return -1; - if (ch & 0200) { - word = (word << 6) | (ch & 077); - bits = (bits << 1) | ((ch >> 6) & 1); - st++; } } -while (st < 3); -if (hi != NULL) *hi = bits; -return word; -} - -/* PDP-4/PDP-7 RIM format loader - - Tape format - dac addr - data - : - dac addr - data - jmp addr or hlt -*/ - -t_stat rim_load_47 (FILE *fileref, char *cptr) -{ -int32 origin, val; - -if (*cptr != 0) return SCPE_2MARG; -origin = 0200; -for (;;) { - if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; - if ((val & 0760000) == 0040000) { /* DAC? */ - origin = val & 017777; - if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; - if (MEM_ADDR_OK (origin)) M[origin++] = val; } - else if ((val & 0760000) == OP_JMP) { /* JMP? */ - PC = ((origin - 1) & 060000) | (val & 017777); - return SCPE_OK; } - else if (val == OP_HLT) return SCPE_OK; /* HLT? */ - else return SCPE_FMT; } /* error */ -return SCPE_FMT; /* error */ -} - -/* PDP-9/15 RIM format loader - - Tape format (read in address specified externally) - data - : - data - word to execute (bit 1 of last character set) -*/ - -t_stat rim_load_915 (FILE *fileref, char *cptr) -{ -int32 bits, origin, val; -char gbuf[CBUFSIZE]; -t_stat r; - -if (*cptr != 0) { /* more input? */ - cptr = get_glyph (cptr, gbuf, 0); /* get origin */ - origin = get_uint (gbuf, 8, AMASK, &r); - if (r != SCPE_OK) return r; - if (*cptr != 0) return SCPE_ARG; } /* no more */ -else origin = 0200; /* default 200 */ - -for (;;) { /* word loop */ - if ((val = getword (fileref, &bits)) < 0) return SCPE_FMT; - if (bits & 1) { /* end of tape? */ - if ((val & 0760000) == OP_JMP) PC = - ((origin - 1) & 060000) | (val & 017777); - else if (val != OP_HLT) return SCPE_FMT; - break; } - else if (MEM_ADDR_OK (origin)) M[origin++] = val; } -return SCPE_OK; -} - -/* PDP-9/15 BIN format loader - - BIN format (starts after RIM bootstrap) - block/ origin (>= 0) - count - checksum - data - : - data - block/ - : - endblock/ origin (< 0) -*/ - -t_stat bin_load_915 (FILE *fileref, char *cptr) -{ -int32 i, val, bits, origin, count, cksum; - -if (*cptr != 0) return SCPE_2MARG; /* no arguments */ -do { val = getword (fileref, & bits); } /* find end RIM */ -while ((val >= 0) && ((bits & 1) == 0)); -if (val < 0) rewind (fileref); /* no RIM? rewind */ -for (;;) { /* block loop */ - if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; - if (val & SIGN) { - if (val != DMASK) PC = val & 077777; - break; } - cksum = origin = val; /* save origin */ - if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; - cksum = cksum + val; /* add to cksum */ - count = (-val) & DMASK; /* save count */ - if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; - cksum = cksum + val; /* add to cksum */ - for (i = 0; i < count; i++) { - if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; - cksum = cksum + val; - if (MEM_ADDR_OK (origin)) M[origin++] = val; } - if ((cksum & DMASK) != 0) return SCPE_CSUM; } -return SCPE_OK; -} - -#if defined (PDP4) || defined (PDP7) - -/* PDP-4/PDP-7: RIM format only */ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -if (flag != 0) return SCPE_NOFNC; -return rim_load_47 (fileref, cptr); -} - -#else - -/* PDP-9/PDP-15: all formats */ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -extern int32 sim_switches; - -if (flag != 0) return SCPE_NOFNC; -if (sim_switches & SWMASK ('S')) /* PDP-4/7 format? */ - return rim_load_47 (fileref, cptr); -if ((sim_switches & SWMASK ('R')) || /* RIM format? */ - (match_ext (fnam, "RIM") && !(sim_switches & SWMASK ('B')))) - return rim_load_915 (fileref, cptr); -return bin_load_915 (fileref, cptr); /* must be BIN */ -} - -#endif - -/* Symbol tables */ - -#define I_V_FL 18 /* inst class */ -#define I_M_FL 017 /* class mask */ -#define I_V_DC 22 /* default count */ -#define I_V_NPN 0 /* no operand */ -#define I_V_NPI 1 /* no operand IOT */ -#define I_V_IOT 2 /* IOT */ -#define I_V_MRF 3 /* memory reference */ -#define I_V_OPR 4 /* OPR */ -#define I_V_LAW 5 /* LAW */ -#define I_V_XR 6 /* index */ -#define I_V_XR9 7 /* index literal */ -#define I_V_EST 8 /* EAE setup */ -#define I_V_ESH 9 /* EAE shift */ -#define I_V_EMD 10 /* EAE mul-div */ -#define I_V_FPM 11 /* FP15 mem ref */ -#define I_V_FPI 12 /* FP15 indirect */ -#define I_V_FPN 13 /* FP15 no operand */ -#define I_NPN (I_V_NPN << I_V_FL) -#define I_NPI (I_V_NPI << I_V_FL) -#define I_IOT (I_V_IOT << I_V_FL) -#define I_MRF (I_V_MRF << I_V_FL) -#define I_OPR (I_V_OPR << I_V_FL) -#define I_LAW (I_V_LAW << I_V_FL) -#define I_XR (I_V_XR << I_V_FL) -#define I_XR9 (I_V_XR9 << I_V_FL) -#define I_EST (I_V_EST << I_V_FL) -#define I_ESH (I_V_ESH << I_V_FL) -#define I_EMD (I_V_EMD << I_V_FL) -#define I_FPM (I_V_FPM << I_V_FL) -#define I_FPI (I_V_FPI << I_V_FL) -#define I_FPN (I_V_FPN << I_V_FL) -#define MD(x) ((I_EMD) + ((x) << I_V_DC)) - -static const int32 masks[] = { - 0777777, 0777767, 0770000, 0760000, - 0763730, 0760000, 0777000, 0777000, - 0740700, 0760700, 0777700, 0777777, - 0777777, 0777777 }; - -static const char *opcode[] = { - "CAL", "DAC", "JMS", "DZM", /* mem refs */ - "LAC", "XOR", "ADD", "TAD", - "XCT", "ISZ", "AND", "SAD", - "JMP", - -#if defined (PDP9) || defined (PDP15) /* mem ref ind */ - "CAL*", "DAC*", "JMS*", "DZM*", /* normal */ - "LAC*", "XOR*", "ADD*", "TAD*", - "XCT*", "ISZ*", "AND*", "SAD*", - "JMP*", -#else - "CAL I", "DAC I", "JMS I", "DZM I", /* decode only */ - "LAC I", "XOR I", "ADD I", "TAD I", - "XCT I", "ISZ I", "AND I", "SAD I", - "JMP I", -#endif - - "LAW", /* LAW */ - - "LACQ", "LACS", "ABS", "GSM", "LMQ", /* EAE */ - "MUL", "MULS", "DIV", "DIVS", - "IDIV", "IDIVS", "FRDIV", "FRDIVS", - "NORM", "NORMS", - "MUY", "LLK MUY", "DVI", "LLK DVI", - "NMI", "NMIS", "LRS", "LRSS", - "LLS", "LLSS", "ALS", "ALSS", - "EAE-setup", "EAE", /* setup, general */ - - "CLSF", "IOF", "ION", "CLOF", "CLON", /* standard IO devs */ - "RSF", "RRB", "RCF", "RSA", "RSB", - "PSF", "PCF", "PSA", "PSB", "PLS", - "KSF", "KRB", "KCF", "IORS", "IOOS", - "TSF", "TCF", "TPC", "TLS", -#if defined (TYPE62) /* Type 62 */ - "LPSF", "LPCF", "LPLD", "LPSE", - "LSSF", "LSCF", "LSPR", -#endif -#if defined (TYPE647) /* Type 647 */ - "LPSF", "LPCB", "LPCD", "LPCD", "LPCD", - "LPL2", "LPLD", "LPL1", - "LPEF", "LPCF", "LPCF", "LPCF", "LPCF", - "LPPB", "LPLS", "LPPS", -#endif -#if defined (LP09) - "LSDF", "LSEF", "LSCF", "LPLD", - "LIOF", "LION", -#endif -#if defined (LP15) /* LP15 */ - "LPSF", "LPPM", "LPP1", "LPDI", - "LPRS", "LPOS", "LPEI", "LPCD", "LPCF", -#endif -#if defined (DRM) /* drum */ - "DRLR", "DRLW", "DRSS", "DRCS", - "DRSF", "DRSN", "DRCF", - "DRLCRD", "DRLCWR", "DRLBLK", "DRCONT", - "DRSF", "DRSOK", "DRCF", -#endif -#if defined (RB) /* RB09 */ - "DBCF", "DBRD", "DBLD", - "DBSF", "DBRS", "DBLW", - "DBCS", "DBLM", "DBLS", -#endif -#if defined (RF) /* RF09 */ - "DSSF", "DSCC", "DSCF", - "DRBR", "DRAL", "DSFX", "DRAH", - "DLBR", "DLAL", "DSCN", "DLAH", - "DLOK", "DSCD", "DSRS", - "DGHS", "DGSS", -#endif -#if defined (RP) - "DPSF", "DPSA", "DPSJ", "DPSE", - "DPRSA", "DPOSA", "DPRSB", "DPOSB", - "DPRM", "DPOM", - "DPLA", "DPCS", "DPCA", "DPWC", - "DPLM", "DPEM", "DPSN", - "DPRU", "DPOU", "DPRA", "DPOA", - "DPRC", "DPOC", "DPRW", "DPOW", - "DPCF", "DPLZ", "DPCN", "DPLO", "DPLF", -#endif -#if defined (MTA) /* TC59 */ - "MTTR", "MTCR", "MTSF", "MTRC", "MTAF", - "MTRS", "MTGO", "MTCM", "MTLC", -#endif -#if defined (TYPE550) /* Type 550 */ - "MMDF", "MMEF", "MMRD", "MMWR", - "MMBF", "MMRS", "MMLC", "MMSE", -#elif defined (TC02) /* TC02/TC15 */ - "DTCA", "DTRA", "DTXA", "DTLA", - "DTEF", "DTRB", "DTDF", -#endif -#if defined (TTY1) - "KSF1", "KRB1", - "TSF1", "TCF1", "TLS1", "TCF1!TLS1", -#endif -#if defined (PDP7) - "ITON", "TTS", "SKP7", "CAF", - "SEM", "EEM", "EMIR", "LEM", -#endif -#if defined (PDP9) - "SKP7", "SEM", "EEM", "LEM", - "LPDI", "LPEI", -#endif -#if defined (PDP15) - "SPCO", "SKP15", "RES", - "SBA", "DBA", "EBA", - "ORMM", "RDMM", "LDMM", "MPLR", - "ENB", "INH", "MPRC", "IPFH", - "AAS", "PAX", "PAL", "AAC", - "PXA", "AXS", "PXL", "PLA", - "PLX", "CLAC","CLX", "CLLR", "AXR", - - "FPT", /* FP15 */ - "ISB", "ESB", /* mem ref */ - "FSB", "URFSB", "UNFSB", "UUFSB", - "DSB", "URDSB", "UNDSB", "UUDSB", - "IRS", "ERS", - "FRS", "URFRS", "UNFRS", "UUFRS", - "DRS", "URDRS", "UNDRS", "UUDRS", - "IMP", "EMP", - "FMP", "URFMP", "UNFMP", "UUFMP", - "DMP", "URDMP", "UNDMP", "UUDMP", - "IDV", "EDV", - "FDV", "URFDV", "UNFDV", "UUFDV", - "DDV", "URDDV", "UNDDV", "UUDDV", - "IRD", "ERD", - "FRD", "URFRD", "UNFRD", "UUFRD", - "DRD", "URDRD", "UNDRD", "UUDRD", - "ILD", "ELD", - "FLD", "UNFLD", "DLD", "UNDLD", - "IST", "EST", - "FST", "URFST", "UNFST", "UUFST", - "DST", "UNDST", - "ILF", "UNILF", "ELF", "UNELF", - "FLX", "URFLX", "DLX", "URDLX", - "ILQ", "ELQ", - "FLQ", "UNFLQ", "DLQ", "UNDLQ", - "LJE", "SJE", - "IAD", "EAD", - "FAD", "URFAD", "UNFAD", "UUFAD", - "DAD", "URDAD", "UNDAD", "UUDAD", - "BZA", "BMA", "BLE", "BPA", - "BRU", "BNA", "BAC", - "ISB*", "ESB*", /* indirect */ - "FSB*", "URFSB*", "UNFSB*", "UUFSB*", - "DSB*", "URDSB*", "UNDSB*", "UUDSB*", - "IRS*", "ERS*", - "FRS*", "URFRS*", "UNFRS*", "UUFRS*", - "DRS*", "URDRS*", "UNDRS*", "UUDRS*", - "IMP*", "EMP*", - "FMP*", "URFMP*", "UNFMP*", "UUFMP*", - "DMP*", "URDMP*", "UNDMP*", "UUDMP*", - "IDV*", "EDV*", - "FDV*", "URFDV*", "UNFDV*", "UUFDV*", - "DDV*", "URDDV*", "UNDDV*", "UUDDV*", - "IRD*", "ERD", - "FRD*", "URFRD*", "UNFRD*", "UUFRD*", - "DRD*", "URDRD*", "UNDRD*", "UUDRD*", - "ILD*", "ELD", - "FLD*", "UNFLD*", "DLD*", "UNDLD*", - "IST*", "EST", - "FST*", "URFST*", "UNFST*", "UUFST*", - "DST*", "UNDST*", - "ILF*", "UNILF*", "ELF*", "UNELF*", - "FLX*", "URFLX*", "DLX*", "URDLX*", - "ILQ*", "ELQ*", - "FLQ*", "UNFLQ*", "DLQ*", "UNDLQ*", - "LJE*", "SJE*", - "IAD*", "EAD*", - "FAD*", "URFAD*", "UNFAD*", "UUFAD*", - "DAD*", "URDAD*", "UNDAD*", "UUDAD*", - - "FLA", "UNFLA", "FXA", "URFXA", /* no operand */ - "SWQ", "UNSWQ", "FZR", - "FAB", "FNG", "FCM", "FNM", -#endif -#if defined (PDP9) || defined (PDP15) - "MPSK", "MPSNE", "MPCV", "MPEU", - "MPLD", "MPCNE", "PFSF", - "TTS", "CAF", "DBK", "DBR", - "SPI", "RPL", "ISA", -#endif - "IOT", /* general */ - - "NOP", "STL", "RCL", "RCR", - "CLC", "LAS", "GLK", - "OPR", "SMA", "SZA", "SZA SMA", - "SNL", "SNL SMA", "SNL SZA", "SNL SZA SMA", - "SKP", "SPA", "SNA", "SNA SPA", - "SZL", "SZL SPA", "SZL SNA", "SZL SZA SPA", - "RAL", "SMA RAL", "SZA RAL", "SZA SMA RAL", - "SNL RAL", "SNL SMA RAL", "SNL SZA RAL", "SNL SZA SMA RAL", - "SKP RAL", "SPA RAL", "SNA RAL", "SNA SPA RAL", - "SZL RAL", "SZL SPA RAL", "SZL SNA RAL", "SZL SZA SPA RAL", - "RAR", "SMA RAR", "SZA RAR", "SZA SMA RAR", - "SNL RAR", "SNL SMA RAR", "SNL SZA RAR", "SNL SZA SMA RAR", - "SKP RAR", "SPA RAR", "SNA RAR", "SNA SPA RAR", - "SZL RAR", "SZL SPA RAR", "SZL SNA RAR", "SZL SZA SPA RAR", -#if defined (PDP15) - "IAC", "SMA IAC", "SZA IAC", "SZA SMA IAC", - "SNL IAC", "SNL SMA IAC", "SNL SZA IAC", "SNL SZA SMA IAC", - "SKP IAC", "SPA IAC", "SNA IAC", "SNA SPA IAC", - "SZL IAC", "SZL SPA IAC", "SZL SNA IAC", "SZL SZA SPA IAC", -#else - "RAL RAR", "SMA RAL RAR", "SZA RAL RAR", "SZA SMA RAL RAR", - "SNL RAL RAR", "SNL SMA RAL RAR", "SNL SZA RAL RAR", "SNL SZA SMA RAL RAR", - "SKP RAL RAR", "SPA RAL RAR", "SNA RAL RAR", "SNA SPA RAL RAR", - "SZL RAL RAR", "SZL SPA RAL RAR", "SZL SNA RAL RAR", "SZL SZA SPA RAL RAR", -#endif - "RTWO", "SMA RTWO", "SZA RTWO", "SZA SMA RTWO", - "SNL RTWO", "SNL SMA RTWO", "SNL SZA RTWO", "SNL SZA SMA RTWO", - "SKP RTWO", "SPA RTWO", "SNA RTWO", "SNA SPA RTWO", - "SZL RTWO", "SZL SPA RTWO", "SZL SNA RTWO", "SZL SZA SPA RTWO", - "RTL", "SMA RTL", "SZA RTL", "SZA SMA RTL", - "SNL RTL", "SNL SMA RTL", "SNL SZA RTL", "SNL SZA SMA RTL", - "SKP RTL", "SPA RTL", "SNA RTL", "SNA SPA RTL", - "SZL RTL", "SZL SPA RTL", "SZL SNA RTL", "SZL SZA SPA RTL", - "RTR", "SMA RTR", "SZA RTR", "SZA SMA RTR", - "SNL RTR", "SNL SMA RTR", "SNL SZA RTR", "SNL SZA SMA RTR", - "SKP RTR", "SPA RTR", "SNA RTR", "SNA SPA RTR", - "SZL RTR", "SZL SPA RTR", "SZL SNA RTR", "SZL SZA SPA RTR", -#if defined (PDP15) - "BSW", "SMA BSW", "SZA BSW", "SZA SMA BSW", - "SNL BSW", "SNL SMA BSW", "SNL SZA BSW", "SNL SZA SMA BSW", - "SKP BSW", "SPA BSW", "SNA BSW", "SNA SPA BSW", - "SZL BSW", "SZL SPA BSW", "SZL SNA BSW", "SZL SZA SPA BSW", -#else - "RTL RTR", "SMA RTL RTR", "SZA RTL RTR", "SZA SMA RTL RTR", - "SNL RTL RTR", "SNL SMA RTL RTR", "SNL SZA RTL RTR", "SNL SZA SMA RTL RTR", - "SKP RTL RTR", "SPA RTL RTR", "SNA RTL RTR", "SNA SPA RTL RTR", - "SZL RTL RTR", "SZL SPA RTL RTR", "SZL SNA RTL RTR", "SZL SZA SPA RTL RTR", -#endif - - "LLK", "CLQ", "LSN", "OACQ", "ECLA", /* encode only masks */ - "CMQ", "OMQ", "OSC", - "CLA", "CLL", "CML", "CMA", - "OAS", "HLT", - NULL }; - -static const int32 opc_val[] = { - 0000000+I_MRF, 0040000+I_MRF, 0100000+I_MRF, 0140000+I_MRF, - 0200000+I_MRF, 0240000+I_MRF, 0300000+I_MRF, 0340000+I_MRF, - 0400000+I_MRF, 0440000+I_MRF, 0500000+I_MRF, 0540000+I_MRF, - 0600000+I_MRF, - 0020000+I_MRF, 0060000+I_MRF, 0120000+I_MRF, 0160000+I_MRF, - 0220000+I_MRF, 0260000+I_MRF, 0320000+I_MRF, 0360000+I_MRF, - 0420000+I_MRF, 0460000+I_MRF, 0520000+I_MRF, 0560000+I_MRF, - 0620000+I_MRF, - - 0760000+I_LAW, - - 0641002+I_NPN, 0641001+I_NPN, 0644000+I_NPN, 0664000+I_NPN, 0652000+I_NPN, - 0653100+MD(022), 0657100+MD(022), 0640300+MD(023), 0644300+MD(023), - 0653300+MD(023), 0657300+MD(023), 0650300+MD(023), 0654300+MD(023), - 0640400+MD(044), 0660400+MD(044), - 0640100+I_ESH, 0660100+I_ESH, 0640300+I_ESH, 0660300+I_ESH, - 0640400+I_ESH, 0660400+I_ESH, 0640500+I_ESH, 0660500+I_ESH, - 0640600+I_ESH, 0660600+I_ESH, 0640700+I_ESH, 0660700+I_ESH, - 0640000+I_EST, 0640000+I_IOT, - - 0700001+I_NPI, 0700002+I_NPI, 0700042+I_NPI, 0700004+I_NPI, 0700044+I_NPI, - 0700101+I_NPI, 0700112+I_NPN, 0700102+I_NPI, 0700104+I_NPI, 0700144+I_NPI, - 0700201+I_NPI, 0700202+I_NPI, 0700204+I_NPI, 0700244+I_NPI, 0700206+I_NPI, - 0700301+I_NPI, 0700312+I_NPN, 0700302+I_NPI, 0700314+I_NPN, 0700304+I_NPI, - 0700401+I_NPI, 0700402+I_NPI, 0700404+I_NPI, 0700406+I_NPI, -#if defined (TYPE62) - 0706501+I_NPI, 0706502+I_NPI, 0706542+I_NPI, 0706506+I_NPI, - 0706601+I_NPI, 0706602+I_NPI, 0706606+I_NPI, -#endif -#if defined (TYPE647) - 0706501+I_NPI, 0706502+I_NPI, 0706522+I_NPI, 0706542+I_NPI, 0706562+I_NPI, - 0706526+I_NPI, 0706546+I_NPI, 0706566+I_NPI, - 0706601+I_NPI, 0706602+I_NPI, 0706622+I_NPI, 0706642+I_NPI, 0706662+I_NPI, - 0706606+I_NPI, 0706626+I_NPI, 0706646+I_NPI, -#endif -#if defined (LP09) - 0706601+I_NPI, 0706621+I_NPI, 0706602+I_NPI, 0706622+I_NPI, - 0706604+I_NPI, 0706644+I_NPI, -#endif -#if defined (LP15) - 0706501+I_NPI, 0706521+I_NPI, 0706541+I_NPI, 0706561+I_NPI, - 0706552+I_NPN, 0706542+I_NPI, 0706544+I_NPI, 0706621+I_NPI, 0706641+I_NPI, -#endif -#if defined (DRM) - 0706006+I_NPI, 0706046+I_NPI, 0706106+I_NPI, 0706204+I_NPI, - 0706101+I_NPI, 0706201+I_NPI, 0706102+I_NPI, - 0706006+I_NPI, 0706046+I_NPI, 0706106+I_NPI, 0706204+I_NPI, - 0706101+I_NPI, 0706201+I_NPI, 0706102+I_NPI, -#endif -#if defined (RB) - 0707101+I_NPI, 0707112+I_NPN, 0707104+I_NPI, - 0707121+I_NPI, 0707132+I_NPN, 0707124+I_NPI, - 0707141+I_NPI, 0707142+I_NPI, 0707144+I_NPI, -#endif -#if defined (RF) - 0707001+I_NPI, 0707021+I_NPI, 0707041+I_NPI, - 0707002+I_NPI, 0707022+I_NPI, 0707042+I_NPI, 0707062+I_NPI, - 0707004+I_NPI, 0707024+I_NPI, 0707044+I_NPI, 0707064+I_NPI, - 0707202+I_NPI, 0707242+I_NPI, 0707262+I_NPI, - 0707204+I_NPI, 0707224+I_NPI, -#endif -#if defined (RP) - 0706301+I_NPI, 0706321+I_NPI, 0706341+I_NPI, 0706361+I_NPI, - 0706312+I_NPN, 0706302+I_NPI, 0706332+I_NPN, 0706322+I_NPI, - 0706342+I_NPN, 0706352+I_NPI, - 0706304+I_NPI, 0706324+I_NPI, 0706344+I_NPI, 0706364+I_NPI, - 0706411+I_NPN, 0706401+I_NPI, 0706421+I_NPI, - 0706412+I_NPN, 0706402+I_NPI, 0706432+I_NPN, 0706422+I_NPI, - 0706452+I_NPN, 0706442+I_NPI, 0706472+I_NPN, 0706462+I_NPI, - 0706404+I_NPI, 0706424+I_NPI, 0706454+I_NPN, 0706444+I_NPI, 0706464+I_NPI, -#endif -#if defined (MTA) - 0707301+I_NPI, 0707321+I_NPI, 0707341+I_NPI, 0707312+I_NPN, 0707322+I_NPI, - 0707352+I_NPN, 0707304+I_NPI, 0707324+I_NPI, 0707326+I_NPI, -#endif -#if defined (TYPE550) /* Type 550 */ - 0707501+I_NPI, 0707541+I_NPI, 0707512+I_NPN, 0707504+I_NPI, - 0707601+I_NPI, 0707612+I_NPN, 0707604+I_NPI, 0707644+I_NPI, -#elif defined (TC02) /* TC02/TC15 */ - 0707541+I_NPI, 0707552+I_NPN, 0707544+I_NPI, 0707545+I_NPI, - 0707561+I_NPI, 0707572+I_NPN, 0707601+I_NPI, -#endif -#if defined (TTY1) - 0704101+I_NPI, 0704112+I_NPN, - 0704001+I_NPI, 0704002+I_NPI, 0704004+I_NPI, 0704006+I_NPI, -#endif -#if defined (PDP7) - 0703201+I_NPI, 0703301+I_NPI, 0703341+I_NPI, 0703302+I_NPI, - 0707701+I_NPI, 0707702+I_NPI, 0707742+I_NPI, 0707704+I_NPI, -#endif -#if defined (PDP9) - 0703341+I_NPI, 0707701+I_NPI, 0707702+I_NPI, 0707704+I_NPI, - 0706504+I_NPI, 0706604+I_NPI, -#endif -#if defined (PDP15) - 0703341+I_NPI, 0707741+I_NPI, 0707742+I_NPI, - 0707761+I_NPI, 0707762+I_NPI, 0707764+I_NPI, - 0700022+I_NPI, 0700032+I_NPN, 0700024+I_NPI, 0701724+I_NPI, - 0705521+I_NPI, 0705522+I_NPI, 0701722+I_NPI, 0701764+I_NPI, - 0720000+I_XR9, 0721000+I_XR, 0722000+I_XR, 0723000+I_XR9, - 0724000+I_XR, 0725000+I_XR9, 0726000+I_XR, 0730000+I_XR, - 0731000+I_XR, 0734000+I_XR, 0735000+I_XR, 0736000+I_XR, 0737000+I_XR9, - - 0710314+I_FPN, - 0710400+I_FPM, 0710500+I_FPM, - 0710440+I_FPM, 0710450+I_FPM, 0710460+I_FPM, 0710470+I_FPM, - 0710540+I_FPM, 0710550+I_FPM, 0710560+I_FPM, 0710570+I_FPM, - 0711000+I_FPM, 0711100+I_FPM, - 0711040+I_FPM, 0711050+I_FPM, 0711060+I_FPM, 0711070+I_FPM, - 0711140+I_FPM, 0711150+I_FPM, 0711160+I_FPM, 0711170+I_FPM, - 0711400+I_FPM, 0711500+I_FPM, - 0711440+I_FPM, 0711450+I_FPM, 0711460+I_FPM, 0711470+I_FPM, - 0711540+I_FPM, 0711550+I_FPM, 0711560+I_FPM, 0711570+I_FPM, - 0712000+I_FPM, 0712100+I_FPM, - 0712040+I_FPM, 0712050+I_FPM, 0712060+I_FPM, 0712070+I_FPM, - 0712140+I_FPM, 0712150+I_FPM, 0712160+I_FPM, 0712170+I_FPM, - 0712400+I_FPM, 0712500+I_FPM, - 0712440+I_FPM, 0712450+I_FPM, 0712460+I_FPM, 0712470+I_FPM, - 0712540+I_FPM, 0712550+I_FPM, 0712560+I_FPM, 0712570+I_FPM, - 0713000+I_FPM, 0713100+I_FPM, - 0713050+I_FPM, 0713070+I_FPM, 0713150+I_FPM, 0713170+I_FPM, - 0713600+I_FPM, 0713700+I_FPM, - 0713640+I_FPM, 0713650+I_FPM, 0713660+I_FPM, 0713670+I_FPM, - 0713750+I_FPM, 0713770+I_FPM, - 0714010+I_FPM, 0714030+I_FPM, 0714110+I_FPM, 0714130+I_FPM, - 0714460+I_FPM, 0714470+I_FPM, 0714560+I_FPM, 0714570+I_FPM, - 0715000+I_FPM, 0715100+I_FPM, - 0715050+I_FPM, 0715070+I_FPM, 0715150+I_FPM, 0715170+I_FPM, - 0715400+I_FPM, 0715600+I_FPM, - 0716000+I_FPM, 0716100+I_FPM, - 0716040+I_FPM, 0716050+I_FPM, 0716060+I_FPM, 0716070+I_FPM, - 0716140+I_FPM, 0716150+I_FPM, 0716160+I_FPM, 0716170+I_FPM, - 0716601+I_FPM, 0716602+I_FPM, 0716603+I_FPM, - 0716604+I_FPM, 0716606+I_FPM, 0716610+I_FPM, 0716620+I_FPM, - 0710400+I_FPI, 0710500+I_FPI, /* indirect */ - 0710440+I_FPI, 0710450+I_FPI, 0710460+I_FPI, 0710470+I_FPI, - 0710540+I_FPI, 0710550+I_FPI, 0710560+I_FPI, 0710570+I_FPI, - 0711000+I_FPI, 0711100+I_FPI, - 0711040+I_FPI, 0711050+I_FPI, 0711060+I_FPI, 0711070+I_FPI, - 0711140+I_FPI, 0711150+I_FPI, 0711160+I_FPI, 0711170+I_FPI, - 0711400+I_FPI, 0711500+I_FPI, - 0711440+I_FPI, 0711450+I_FPI, 0711460+I_FPI, 0711470+I_FPI, - 0711540+I_FPI, 0711550+I_FPI, 0711560+I_FPI, 0711570+I_FPI, - 0712000+I_FPI, 0712100+I_FPI, - 0712040+I_FPI, 0712050+I_FPI, 0712060+I_FPI, 0712070+I_FPI, - 0712140+I_FPI, 0712150+I_FPI, 0712160+I_FPI, 0712170+I_FPI, - 0712400+I_FPI, 0712500+I_FPI, - 0712440+I_FPI, 0712450+I_FPI, 0712460+I_FPI, 0712470+I_FPI, - 0712540+I_FPI, 0712550+I_FPI, 0712560+I_FPI, 0712570+I_FPI, - 0713000+I_FPI, 0713100+I_FPI, - 0713050+I_FPI, 0713070+I_FPI, 0713150+I_FPI, 0713170+I_FPI, - 0713600+I_FPI, 0713700+I_FPI, - 0713640+I_FPI, 0713650+I_FPI, 0713660+I_FPI, 0713670+I_FPI, - 0713750+I_FPI, 0713770+I_FPI, - 0714010+I_FPI, 0714030+I_FPI, 0714110+I_FPI, 0714130+I_FPI, - 0714460+I_FPI, 0714470+I_FPI, 0714560+I_FPI, 0714570+I_FPI, - 0715000+I_FPI, 0715100+I_FPI, - 0715050+I_FPI, 0715070+I_FPI, 0715150+I_FPI, 0715170+I_FPI, - 0715400+I_FPI, 0715600+I_FPI, - 0716000+I_FPI, 0716100+I_FPI, - 0716040+I_FPI, 0716050+I_FPI, 0716060+I_FPI, 0716070+I_FPI, - 0716140+I_FPI, 0716150+I_FPI, 0716160+I_FPI, 0716170+I_FPI, - 0714210+I_FPN, 0714230+I_FPN, 0714660+I_FPN, 0714670+I_FPN, - 0715250+I_FPN, 0715270+I_FPN, 0711200+I_FPN, - 0713271+I_FPN, 0713272+I_FPN, 0713273+I_FPN, 0713250+I_FPN, -#endif -#if defined (PDP9) || defined (PDP15) - 0701701+I_NPI, 0701741+I_NPI, 0701702+I_NPI, 0701742+I_NPI, - 0701704+I_NPI, 0701744+I_NPI, 0703201+I_NPI, - 0703301+I_NPI, 0703302+I_NPI, 0703304+I_NPI, 0703344+I_NPI, - 0705501+I_NPI, 0705512+I_NPN, 0705504+I_NPI, -#endif - 0700000+I_IOT, - - 0740000+I_NPN, 0744002+I_NPN, 0744010+I_NPN, 0744020+I_NPN, - 0750001+I_NPN, 0750004+I_NPN, 0750010+I_NPN, - 0740000+I_OPR, 0740100+I_OPR, 0740200+I_OPR, 0740300+I_OPR, - 0740400+I_OPR, 0740500+I_OPR, 0740600+I_OPR, 0740700+I_OPR, - 0741000+I_OPR, 0741100+I_OPR, 0741200+I_OPR, 0741300+I_OPR, - 0741400+I_OPR, 0741500+I_OPR, 0741600+I_OPR, 0741700+I_OPR, - 0740010+I_OPR, 0740110+I_OPR, 0740210+I_OPR, 0740310+I_OPR, - 0740410+I_OPR, 0740510+I_OPR, 0740610+I_OPR, 0740710+I_OPR, - 0741010+I_OPR, 0741110+I_OPR, 0741210+I_OPR, 0741310+I_OPR, - 0741410+I_OPR, 0741510+I_OPR, 0741610+I_OPR, 0741710+I_OPR, - 0740020+I_OPR, 0740120+I_OPR, 0740220+I_OPR, 0740320+I_OPR, - 0740420+I_OPR, 0740520+I_OPR, 0740620+I_OPR, 0740720+I_OPR, - 0741020+I_OPR, 0741120+I_OPR, 0741220+I_OPR, 0741320+I_OPR, - 0741420+I_OPR, 0741520+I_OPR, 0741620+I_OPR, 0741720+I_OPR, - 0740030+I_OPR, 0740130+I_OPR, 0740230+I_OPR, 0740330+I_OPR, - 0740430+I_OPR, 0740530+I_OPR, 0740630+I_OPR, 0740730+I_OPR, - 0741030+I_OPR, 0741130+I_OPR, 0741230+I_OPR, 0741330+I_OPR, - 0741430+I_OPR, 0741530+I_OPR, 0741630+I_OPR, 0741730+I_OPR, - 0742000+I_OPR, 0742100+I_OPR, 0742200+I_OPR, 0742300+I_OPR, - 0742400+I_OPR, 0742500+I_OPR, 0742600+I_OPR, 0742700+I_OPR, - 0743000+I_OPR, 0743100+I_OPR, 0743200+I_OPR, 0743300+I_OPR, - 0743400+I_OPR, 0743500+I_OPR, 0743600+I_OPR, 0743700+I_OPR, - 0742010+I_OPR, 0742110+I_OPR, 0742210+I_OPR, 0742310+I_OPR, - 0742410+I_OPR, 0742510+I_OPR, 0742610+I_OPR, 0742710+I_OPR, - 0743010+I_OPR, 0743110+I_OPR, 0743210+I_OPR, 0743310+I_OPR, - 0743410+I_OPR, 0743510+I_OPR, 0743610+I_OPR, 0743710+I_OPR, - 0742020+I_OPR, 0742120+I_OPR, 0742220+I_OPR, 0742320+I_OPR, - 0742420+I_OPR, 0742520+I_OPR, 0742620+I_OPR, 0742720+I_OPR, - 0743020+I_OPR, 0743120+I_OPR, 0743220+I_OPR, 0743320+I_OPR, - 0743420+I_OPR, 0743520+I_OPR, 0743620+I_OPR, 0743720+I_OPR, - 0742030+I_OPR, 0742130+I_OPR, 0742230+I_OPR, 0742330+I_OPR, - 0742430+I_OPR, 0742530+I_OPR, 0742630+I_OPR, 0742730+I_OPR, - 0743030+I_OPR, 0743130+I_OPR, 0743230+I_OPR, 0743330+I_OPR, - 0743430+I_OPR, 0743530+I_OPR, 0743630+I_OPR, 0743730+I_OPR, - - 0660000+I_EST, 0650000+I_EST, 0644000+I_EST, 0642000+I_EST, 0641000+I_EST, - 0640004+I_EST, 0640002+I_EST, 0640001+I_EST, - 0750000+I_OPR, 0744000+I_OPR, 0740002+I_OPR, 0740001+I_OPR, - 0740004+I_OPR, 0740040+I_OPR, - -1 }; - -/* Operate or EAE decode - - Inputs: - *of = output stream - inst = mask bits - class = instruction class code - sp = space needed? - Outputs: - status = space needed? -*/ - -int32 fprint_opr (FILE *of, int32 inst, int32 class, int32 sp) -{ -int32 i, j; - -for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - if ((j == class) && (opc_val[i] & inst)) { /* same class? */ - inst = inst & ~opc_val[i]; /* mask bit set? */ - fprintf (of, (sp? " %s": "%s"), opcode[i]); - sp = 1; } } -return sp; -} - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - return = status code -*/ - -#define FMTASC(x) (((x) < 040)? "<%03o>": "%c"), (x) -#define SIXTOASC(x) (((x) >= 040)? (x): ((x) + 0100)) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, i, j, k, sp, inst, disp, ma; - -inst = val[0]; -cflag = (uptr == NULL) || (uptr == &cpu_unit); -if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; - fprintf (of, FMTASC (inst & 0177)); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* character? */ - fprintf (of, "%c", SIXTOASC ((inst >> 12) & 077)); - fprintf (of, "%c", SIXTOASC ((inst >> 6) & 077)); - fprintf (of, "%c", SIXTOASC (inst & 077)); - return SCPE_OK; } -#if defined (PDP15) -if (sw & SWMASK ('P')) { /* packed ASCII? */ - i = val[1]; - fprintf (of, FMTASC ((inst >> 11) & 0177)); - fprintf (of, FMTASC ((inst >> 4) & 0177)); - fprintf (of, FMTASC (((inst << 3) | (i >> 15)) & 0177)); - fprintf (of, FMTASC ((i >> 8) & 0177)); - fprintf (of, FMTASC ((i >> 1) & 0177)); - return -1; } -#endif -if (!(sw & SWMASK ('M'))) return SCPE_ARG; - -/* Instruction decode */ - -for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */ - - switch (j) { /* case on class */ - case I_V_NPN: /* no operands */ - case I_V_XR: /* index no opers */ - fprintf (of, "%s", opcode[i]); /* opcode */ - break; - case I_V_NPI: /* IOT no operand */ - fprintf (of, "%s", opcode[i]); /* opcode */ - if (inst & 010) fprintf (of, " +10"); - break; - case I_V_IOT: /* IOT or EAE */ - fprintf (of, "%s %-o", opcode[i], inst & 037777); - break; - case I_V_MRF: /* mem ref */ -#if defined (PDP15) - if (memm) { - disp = inst & B_DAMASK; - ma = (addr & (AMASK & ~B_DAMASK)) | disp; } - else { - disp = inst & P_DAMASK; - ma = (addr & (AMASK & ~P_DAMASK)) | disp; } - fprintf (of, "%s %-o", opcode[i], (cflag? ma & AMASK: disp)); - if (!memm && (inst & I_IDX)) fprintf (of, ",X"); -#else - disp = inst & B_DAMASK; - ma = (addr & (AMASK & ~B_DAMASK)) | disp; - fprintf (of, "%s %-o", opcode[i], (cflag? ma & AMASK: disp)); -#endif - break; - case I_V_OPR: /* operate */ - if (sp = (inst & 03730)) fprintf (of, "%s", opcode[i]); - fprint_opr (of, inst & 014047, I_V_OPR, sp); - break; - case I_V_LAW: /* LAW */ - fprintf (of, "%s %-o", opcode[i], inst & 017777); - break; - case I_V_XR9: /* index with lit */ - disp = inst & 0777; - if (disp & 0400) fprintf (of, "%s -%-o", opcode[i], 01000 - disp); - else fprintf (of, "%s %-o", opcode[i], disp); - break; - case I_V_EST: /* EAE setup */ - fprint_opr (of, inst & 037007, I_V_EST, 0); - break; - case I_V_ESH: /* EAE shift */ - sp = fprint_opr (of, inst & 017000, I_V_EST, 0); - fprintf (of, (sp? " %s %-o": "%s %-o"), opcode[i], inst & 077); - break; - case I_V_EMD: /* EAE mul-div */ - disp = inst & 077; /* get actual val */ - k = (opc_val[i] >> I_V_DC) & 077; /* get default val */ - if (disp == k) fprintf (of, "%s", opcode[i]); - else if (disp < k) fprintf (of, "%s -%-o", opcode[i], k - disp); - else fprintf (of, "%s +%-o", opcode[i], disp - k); - break; - case I_V_FPM: case I_V_FPI: /* FP15 mem ref */ - fprintf (of, "%s", opcode[i]); - if (val[1] & SIGN) fputc ('*', of); - fprintf (of, " %-o", val[1] & ~SIGN); - return -1; - case I_V_FPN: /* FP15 no operand */ - fprintf (of, "%s", opcode[i]); - return -1; } /* end case */ - return SCPE_OK; } /* end if */ - } /* end for */ -return SCPE_ARG; -} - -/* Get 18b signed number - - Inputs: - *cptr = pointer to input string - *sign = pointer to sign - *status = pointer to error status - Outputs: - val = output value -*/ - -t_value get_sint (char *cptr, int32 *sign, t_stat *status) -{ -*sign = 0; -if (*cptr == '+') { - *sign = 1; - cptr++; } -else if (*cptr == '-') { - *sign = -1; - cptr++; } -return get_uint (cptr, 8, 0777777, status); -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = error status -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 cflag, d, i, j, k, sign, damask, epcmask; -t_stat r, sta = SCPE_OK; -char gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; -for (i = 1; (i < 5) && (cptr[i] != 0); i++) - if (cptr[i] == 0) for (j = i + 1; j <= 5; j++) cptr[j] = 0; -if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (t_value) cptr[0] | 0200; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (((t_value) cptr[0] & 077) << 12) | - (((t_value) cptr[1] & 077) << 6) | - ((t_value) cptr[2] & 077); - return SCPE_OK; } -#if defined (PDP15) -if ((sw & SWMASK ('P')) || ((*cptr == '#') && cptr++)) { /* packed string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (((t_value) cptr[0] & 0177) << 11) | - (((t_value) cptr[1] & 0177) << 4) | - (((t_value) cptr[2] & 0170) >> 3); - val[1] = (((t_value) cptr[2] & 0007) << 15) | - (((t_value) cptr[3] & 0177) << 8) | - (((t_value) cptr[4] & 0177) << 1); - return -1; } -#endif - -/* Symbolic input, continued */ - -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; -if (opcode[i] == NULL) return SCPE_ARG; -val[0] = opc_val[i] & DMASK; /* get value */ -j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - -switch (j) { /* case on class */ -case I_V_XR: /* index */ - break; -case I_V_XR9: /* index literal */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - d = get_sint (gbuf, &sign, &r); - if (r != SCPE_OK) return SCPE_ARG; - if (((sign >= 0) && (d > 0377)) || ((sign < 0) && (d > 0400))) - return SCPE_ARG; - val[0] = val[0] | ((sign >= 0)? d: (01000 - d)); - break; -case I_V_LAW: /* law */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - d = get_uint (gbuf, 8, 017777, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | d; - break; -case I_V_MRF: /* mem ref */ -#if defined (PDP15) - if (memm) damask = B_DAMASK; - else damask = P_DAMASK; - cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ -#else - damask = B_DAMASK; - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ -#endif -#if defined (PDP4) || defined (PDP7) - if (strcmp (gbuf, "I") == 0) { /* indirect? */ - val[0] = val[0] | I_IND; - cptr = get_glyph (cptr, gbuf, 0); } -#endif - epcmask = AMASK & ~damask; /* get ePC */ - d = get_uint (gbuf, 8, AMASK, &r); /* get addr */ - if (r != SCPE_OK) return SCPE_ARG; - if (d <= damask) val[0] = val[0] | d; /* fit in 12/13b? */ - else if (cflag && (((addr ^ d) & epcmask) == 0)) - val[0] = val[0] | (d & damask); /* hi bits = ePC? */ - else return SCPE_ARG; -#if defined (PDP15) - if (!memm) { - cptr = get_glyph (cptr, gbuf, 0); - if (gbuf[0] != 0) { - if (strcmp (gbuf, "X") != 0) return SCPE_ARG; - val[0] = val[0] | I_IDX; } } -#endif - break; -case I_V_EMD: /* or'able */ - val[0] = val[0] | ((opc_val[i] >> I_V_DC) & 077); /* default shift */ -case I_V_EST: case I_V_ESH: -case I_V_NPN: case I_V_NPI: case I_V_IOT: case I_V_OPR: - for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; - cptr = get_glyph (cptr, gbuf, 0)) { - for (i = 0; (opcode[i] != NULL) && - (strcmp (opcode[i], gbuf) != 0) ; i++) ; - if (opcode[i] != NULL) { - k = opc_val[i] & DMASK; - if (((k ^ val[0]) & 0740000) != 0) return SCPE_ARG; - val[0] = val[0] | k; } - else { - d = get_sint (gbuf, & sign, &r); - if (r != SCPE_OK) return SCPE_ARG; - if (sign > 0) val[0] = val[0] + d; - else if (sign < 0) val[0] = val[0] - d; - else val[0] = val[0] | d; } } - break; -case I_V_FPM: /* FP15 mem ref */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - val[1] = get_uint (gbuf, 8, AMASK, &r); /* get addr */ - if (r != SCPE_OK) return SCPE_ARG; - sta = -1; - break; -case I_V_FPI: /* FP15 ind mem ref */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - val[1] = get_uint (gbuf, 8, AMASK, &r) | SIGN; /* get @addr */ - if (r != SCPE_OK) return SCPE_ARG; - sta = -1; - break; -case I_V_FPN: /* FP15 no operand */ - val[1] = 0; - sta = -1; - break; } /* end case */ -if (*cptr != 0) return SCPE_ARG; /* junk at end? */ -return sta; -} diff --git a/PDP18B/pdp18b_tt1.c b/PDP18B/pdp18b_tt1.c deleted file mode 100644 index 9229bc3d..00000000 --- a/PDP18B/pdp18b_tt1.c +++ /dev/null @@ -1,312 +0,0 @@ -/* pdp18b_tt1.c: 18b PDP's second Teletype - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - tti1 keyboard - tto1 teleprinter - - 09-May-03 RMS Added network device flag - 22-Dec-02 RMS Added break support - 02-Nov-02 RMS Added 7B/8B support - 05-Oct-02 RMS Added DIB, device number support - 22-Aug-02 RMS Updated for changes to sim_tmxr - 30-May-02 RMS Widened POS to 32b - 06-Jan-02 RMS Added enable/disable support - 30-Dec-01 RMS Added show statistics, set disconnect - 30-Nov-01 RMS Added extended SET/SHOW support - 25-Nov-01 RMS Revised interrupt structure - 19-Sep-01 RMS Fixed typo - 17-Sep-01 RMS Changed to use terminal multiplexor library - 07-Sep-01 RMS Moved function prototypes - 10-Jun-01 RMS Cleaned up IOT decoding to reflect hardware -*/ - -#include "pdp18b_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" -#include - -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_KSR (1 << UNIT_V_KSR) - -extern int32 int_hwre[API_HLVL+1], dev_enb; -extern int32 tmxr_poll; /* calibrated poll */ -TMLN tt1_ldsc = { 0 }; /* line descriptors */ -TMXR tt_desc = { 1, 0, 0, &tt1_ldsc }; /* mux descriptor */ - -DEVICE tti1_dev, tto1_dev; -int32 tti1 (int32 pulse, int32 dat); -int32 tto1 (int32 pulse, int32 dat); -t_stat tti1_svc (UNIT *uptr); -t_stat tto1_svc (UNIT *uptr); -t_stat tti1_reset (DEVICE *dptr); -t_stat tto1_reset (DEVICE *dptr); -t_stat tti1_attach (UNIT *uptr, char *cptr); -t_stat tti1_detach (UNIT *uptr); -t_stat tti1_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat tti1_show (FILE *st, UNIT *uptr, int32 val, void *desc); -void tt1_enbdis (int32 dis); -t_stat tt1_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* TTI1 data structures - - tti1_dev TTI1 device descriptor - tti1_unit TTI1 unit - tto1_mod TTI1 modifier list - tti1_reg TTI1 register list -*/ - -DIB tti1_dib = { DEV_TTI1, 1, NULL, { &tti1 } }; - -UNIT tti1_unit = { UDATA (&tti1_svc, UNIT_ATTABLE+UNIT_KSR, 0), KBD_POLL_WAIT }; - -REG tti1_reg[] = { - { ORDATA (BUF, tti1_unit.buf, 8) }, - { FLDATA (INT, int_hwre[API_TTI1], INT_V_TTI1) }, - { FLDATA (DONE, int_hwre[API_TTI1], INT_V_TTI1) }, - { DRDATA (POS, tt1_ldsc.rxcnt, 32), PV_LEFT }, - { DRDATA (TIME, tti1_unit.wait, 24), REG_NZ + PV_LEFT }, - { ORDATA (DEVNO, tti1_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB tti1_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tt1_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tt1_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tt1_set_mode }, - { UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &tti1_summ }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &tt_desc }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &tti1_show, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &tti1_show, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE tti1_dev = { - "TTI1", &tti1_unit, tti1_reg, tti1_mod, - 1, 10, 31, 1, 8, 8, - &tmxr_ex, &tmxr_dep, &tti1_reset, - NULL, &tti1_attach, &tti1_detach, - &tti1_dib, DEV_NET | DEV_DISABLE }; - -/* TTO1 data structures - - tto1_dev TTO1 device descriptor - tto1_unit TTO1 unit - tto1_mod TTO1 modifier list - tto1_reg TTO1 register list -*/ - -DIB tto1_dib = { DEV_TTO1, 1, NULL, { &tto1 } }; - -UNIT tto1_unit = { UDATA (&tto1_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }; - -REG tto1_reg[] = { - { ORDATA (BUF, tto1_unit.buf, 8) }, - { FLDATA (INT, int_hwre[API_TTO1], INT_V_TTO1) }, - { FLDATA (DONE, int_hwre[API_TTO1], INT_V_TTO1) }, - { DRDATA (POS, tt1_ldsc.txcnt, 32), PV_LEFT }, - { DRDATA (TIME, tto1_unit.wait, 24), PV_LEFT }, - { ORDATA (DEVNO, tto1_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB tto1_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tt1_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tt1_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tt1_set_mode }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE tto1_dev = { - "TTO1", &tto1_unit, tto1_reg, tto1_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto1_reset, - NULL, NULL, NULL, - &tto1_dib, DEV_DISABLE }; - -/* Terminal input: IOT routine */ - -int32 tti1 (int32 pulse, int32 dat) -{ -if (pulse & 001) { /* KSF1 */ - if (TST_INT (TTI1)) dat = dat | IOT_SKP; } -if (pulse & 002) { /* KRB1 */ - CLR_INT (TTI1); /* clear flag */ - dat= dat | tti1_unit.buf; } /* return buffer */ -return dat; -} - -/* Unit service */ - -t_stat tti1_svc (UNIT *uptr) -{ -int32 c, newln; - -if (tt1_ldsc.conn) { /* connected? */ - tmxr_poll_rx (&tt_desc); /* poll for input */ - if (c = tmxr_getc_ln (&tt1_ldsc)) { /* get char */ - if (c & SCPE_BREAK) uptr->buf = 0; /* break? */ - else if (uptr->flags & UNIT_KSR) { /* KSR? */ - c = c & 0177; - if (islower (c)) c = toupper (c); - uptr->buf = c | 0200; } /* got char */ - else uptr->buf = c & ((tti1_unit.flags & UNIT_8B)? 0377: 0177); - SET_INT (TTI1); } /* set flag */ - sim_activate (uptr, uptr->wait); } /* continue poll */ -if (uptr->flags & UNIT_ATT) { /* attached? */ - newln = tmxr_poll_conn (&tt_desc); /* poll connect */ - if (newln >= 0) { /* got one? */ - sim_activate (&tti1_unit, tti1_unit.wait); - tt1_ldsc.rcve = 1; } /* rcv enabled */ - sim_activate (uptr, tmxr_poll); } /* sched poll */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tti1_reset (DEVICE *dptr) -{ -tt1_enbdis (dptr->flags & DEV_DIS); /* sync enables */ -tti1_unit.buf = 0; /* clear buffer */ -CLR_INT (TTI1); /* clear flag */ -if (tt1_ldsc.conn) { /* if conn, */ - sim_activate (&tti1_unit, tti1_unit.wait); /* activate, */ - tt1_ldsc.rcve = 1; } /* enable */ -else if (tti1_unit.flags & UNIT_ATT) /* if attached, */ - sim_activate (&tti1_unit, tmxr_poll); /* activate */ -else sim_cancel (&tti1_unit); /* else stop */ -return SCPE_OK; -} - -/* Terminal output: IOT routine */ - -int32 tto1 (int32 pulse, int32 dat) -{ -if (pulse & 001) { /* TSF */ - if (TST_INT (TTO1)) dat = dat | IOT_SKP; } -if (pulse & 002) CLR_INT (TTO1); /* clear flag */ -if (pulse & 004) { /* load buffer */ - sim_activate (&tto1_unit, tto1_unit.wait); /* activate unit */ - tto1_unit.buf = dat & 0377; } /* load buffer */ -return dat; -} - -/* Unit service */ - -t_stat tto1_svc (UNIT *uptr) -{ -int32 c; - -SET_INT (TTO1); /* set flag */ -c = tto1_unit.buf & 0177; -if (tt1_ldsc.conn) { /* connected? */ - if (tt1_ldsc.xmte) { /* tx enabled? */ - if (tto1_unit.flags & UNIT_KSR) { /* KSR? */ - c = c & 0177; - if (islower (c)) c = toupper (c); - if ((c < 007) || (c > 0137)) c = 0; } - else c = c & ((tto1_unit.flags & UNIT_8B)? 0377: 0177); - if (c) tmxr_putc_ln (&tt1_ldsc, c); /* output char */ - tmxr_poll_tx (&tt_desc); } /* poll xmt */ - else { - tmxr_poll_tx (&tt_desc); /* poll xmt */ - sim_activate (&tto1_unit, tmxr_poll); /* wait */ - return SCPE_OK; } } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tto1_reset (DEVICE *dptr) -{ -tt1_enbdis (dptr->flags & DEV_DIS); /* sync enables */ -tto1_unit.buf = 0; /* clear buffer */ -CLR_INT (TTO1); /* clear flag */ -sim_cancel (&tto1_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Attach routine */ - -t_stat tti1_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = tmxr_attach (&tt_desc, uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error */ -sim_activate (uptr, tmxr_poll); /* start poll */ -return SCPE_OK; -} - -/* Detach routine */ - -t_stat tti1_detach (UNIT *uptr) -{ -t_stat r; - -r = tmxr_detach (&tt_desc, uptr); /* detach */ -tt1_ldsc.rcve = 0; /* disable rcv */ -sim_cancel (uptr); /* stop poll */ -return r; -} - -/* Show summary processor */ - -t_stat tti1_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (tt1_ldsc.conn) fprintf (st, "connected"); -else fprintf (st, "disconnected"); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat tti1_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (val) tmxr_fconns (st, &tt1_ldsc, -1); -else tmxr_fstats (st, &tt1_ldsc, -1); -return SCPE_OK; -} - -/* Enable/disable device */ - -void tt1_enbdis (int32 dis) -{ -if (dis) { - tti1_dev.flags = tto1_dev.flags | DEV_DIS; - tto1_dev.flags = tto1_dev.flags | DEV_DIS; } -else { tti1_dev.flags = tti1_dev.flags & ~DEV_DIS; - tto1_dev.flags = tto1_dev.flags & ~DEV_DIS; } -return; -} - -t_stat tt1_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -tti1_unit.flags = (tti1_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; -tto1_unit.flags = (tto1_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; -return SCPE_OK; -} diff --git a/PDP8/pdp8_clk.c b/PDP8/pdp8_clk.c deleted file mode 100644 index 462de909..00000000 --- a/PDP8/pdp8_clk.c +++ /dev/null @@ -1,166 +0,0 @@ -/* pdp8_clk.c: PDP-8 real-time clock simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - clk real time clock - - 01-Mar-03 RMS Aded SET/SHOW CLK FREQ support - 04-Oct-02 RMS Added DIB, device number support - 30-Dec-01 RMS Removed for generalized timers - 05-Sep-01 RMS Added terminal multiplexor support - 17-Jul-01 RMS Moved function prototype - 05-Mar-01 RMS Added clock calibration support - - Note: includes the IOT's for both the PDP-8/E and PDP-8/A clocks -*/ - -#include "pdp8_defs.h" - -extern int32 int_req, int_enable, dev_done, stop_inst; - -int32 clk_tps = 60; /* ticks/second */ -int32 tmxr_poll = 16000; /* term mux poll */ - -int32 clk (int32 IR, int32 AC); -t_stat clk_svc (UNIT *uptr); -t_stat clk_reset (DEVICE *dptr); -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc); - -/* CLK data structures - - clk_dev CLK device descriptor - clk_unit CLK unit descriptor - clk_reg CLK register list -*/ - -DIB clk_dib = { DEV_CLK, 1, { &clk } }; - -UNIT clk_unit = { UDATA (&clk_svc, 0, 0), 16000 }; - -REG clk_reg[] = { - { FLDATA (DONE, dev_done, INT_V_CLK) }, - { FLDATA (ENABLE, int_enable, INT_V_CLK) }, - { FLDATA (INT, int_req, INT_V_CLK) }, - { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO }, - { NULL } }; - -MTAB clk_mod[] = { - { MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL, - NULL, &clk_show_freq, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev }, - { 0 } }; - -DEVICE clk_dev = { - "CLK", &clk_unit, clk_reg, clk_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &clk_reset, - NULL, NULL, NULL, - &clk_dib, 0 }; - -/* IOT routine - - IOT's 6131-6133 are the PDP-8/E clock - IOT's 6135-6137 are the PDP-8/A clock -*/ - -int32 clk (int32 IR, int32 AC) -{ -switch (IR & 07) { /* decode IR<9:11> */ -case 1: /* CLEI */ - int_enable = int_enable | INT_CLK; /* enable clk ints */ - int_req = INT_UPDATE; /* update interrupts */ - return AC; -case 2: /* CLDI */ - int_enable = int_enable & ~INT_CLK; /* disable clk ints */ - int_req = int_req & ~INT_CLK; /* update interrupts */ - return AC; -case 3: /* CLSC */ - if (dev_done & INT_CLK) { /* flag set? */ - dev_done = dev_done & ~INT_CLK; /* clear flag */ - int_req = int_req & ~INT_CLK; /* clear int req */ - return IOT_SKP + AC; } - return AC; -case 5: /* CLLE */ - if (AC & 1) int_enable = int_enable | INT_CLK; /* test AC<11> */ - else int_enable = int_enable & ~INT_CLK; - int_req = INT_UPDATE; /* update interrupts */ - return AC; -case 6: /* CLCL */ - dev_done = dev_done & ~INT_CLK; /* clear flag */ - int_req = int_req & ~INT_CLK; /* clear int req */ - return AC; -case 7: /* CLSK */ - return (dev_done & INT_CLK)? IOT_SKP + AC: AC; -default: - return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ -} - -/* Unit service */ - -t_stat clk_svc (UNIT *uptr) -{ -int32 t; - -dev_done = dev_done | INT_CLK; /* set done */ -int_req = INT_UPDATE; /* update interrupts */ -t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */ -sim_activate (&clk_unit, t); /* reactivate unit */ -tmxr_poll = t; /* set mux poll */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat clk_reset (DEVICE *dptr) -{ -dev_done = dev_done & ~INT_CLK; /* clear done, int */ -int_req = int_req & ~INT_CLK; -int_enable = int_enable & ~INT_CLK; /* clear enable */ -sim_activate (&clk_unit, clk_unit.wait); /* activate unit */ -return SCPE_OK; -} - -/* Set frequency */ - -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; -clk_tps = val; -return SCPE_OK; -} - -/* Show frequency */ - -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, (clk_tps == 50)? "50Hz": "60Hz"); -return SCPE_OK; -} diff --git a/PDP8/pdp8_cpu.c b/PDP8/pdp8_cpu.c deleted file mode 100644 index dbada524..00000000 --- a/PDP8/pdp8_cpu.c +++ /dev/null @@ -1,1145 +0,0 @@ -/* pdp8_cpu.c: PDP-8 CPU simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - cpu central processor - - 12-Mar-03 RMS Added logical name support - 04-Oct-02 RMS Revamped device dispatching, added device number support - 06-Jan-02 RMS Added device enable/disable routines - 30-Dec-01 RMS Added old PC queue - 16-Dec-01 RMS Fixed bugs in EAE - 07-Dec-01 RMS Revised to use new breakpoint package - 30-Nov-01 RMS Added RL8A, extended SET/SHOW support - 16-Sep-01 RMS Fixed bug in reset routine, added KL8A support - 10-Aug-01 RMS Removed register from declarations - 17-Jul-01 RMS Moved function prototype - 07-Jun-01 RMS Fixed bug in JMS to non-existent memory - 25-Apr-01 RMS Added device enable/disable support - 18-Mar-01 RMS Added DF32 support - 05-Mar-01 RMS Added clock calibration support - 15-Feb-01 RMS Added DECtape support - 14-Apr-99 RMS Changed t_addr to unsigned - - The register state for the PDP-8 is: - - AC<0:11> accumulator - MQ<0:11> multiplier-quotient - L link flag - PC<0:11> program counter - IF<0:2> instruction field - IB<0:2> instruction buffer - DF<0:2> data field - UF user flag - UB user buffer - SF<0:6> interrupt save field - - The PDP-8 has three instruction formats: memory reference, I/O transfer, - and operate. The memory reference format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 - +--+--+--+--+--+--+--+--+--+--+--+--+ - | op |in|zr| page offset | memory reference - +--+--+--+--+--+--+--+--+--+--+--+--+ - - <0:2> mnemonic action - - 000 AND AC = AC & M[MA] - 001 TAD L'AC = AC + M[MA] - 010 DCA M[MA] = AC, AC = 0 - 011 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0 - 100 JMS M[MA] = PC, PC = MA + 1 - 101 JMP PC = MA - - <3:4> mode action - 00 page zero MA = IF'0'IR<5:11> - 01 current page MA = IF'PC<0:4>'IR<5:11> - 10 indirect page zero MA = xF'M[IF'0'IR<5:11>] - 11 indirect current page MA = xF'M[IF'PC<0:4>'IR<5:11>] - - where x is D for AND, TAD, ISZ, DCA, and I for JMS, JMP. - - Memory reference instructions can access an address space of 32K words. - The address space is divided into eight 4K word fields; each field is - divided into thirty-two 128 word pages. An instruction can directly - address, via its 7b offset, locations 0-127 on page zero or on the current - page. All 32k words can be accessed via indirect addressing and the - instruction and data field registers. If an indirect address is in - locations 0010-0017 of any field, the indirect address is incremented - and rewritten to memory before use. -*/ - -/* The I/O transfer format is as follows: - - 0 1 2 3 4 5 6 7 8 9 10 11 - +--+--+--+--+--+--+--+--+--+--+--+--+ - | op | device | pulse | I/O transfer - +--+--+--+--+--+--+--+--+--+--+--+--+ - - The IO transfer instruction sends the the specified pulse to the - specified I/O device. The I/O device may take data from the AC, - return data to the AC, initiate or cancel operations, or skip on - status. - - The operate format is as follows: - - +--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 1| 1| 0| | | | | | | | | operate group 1 - +--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | | | | | - | | | | | | | +--- increment AC 3 - | | | | | | +--- rotate 1 or 2 4 - | | | | | +--- rotate left 4 - | | | | +--- rotate right 4 - | | | +--- complement L 2 - | | +--- complement AC 2 - | +--- clear L 1 - +-- clear AC 1 - - +--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 1| 1| 1| | | | | | | | 0| operate group 2 - +--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | | | | - | | | | | | +--- halt 3 - | | | | | +--- or switch register 3 - | | | | +--- reverse skip sense 1 - | | | +--- skip on L != 0 1 - | | +--- skip on AC == 0 1 - | +--- skip on AC < 0 1 - +-- clear AC 2 - - +--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 1| 1| 1| | | | | | | | 1| operate group 3 - +--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | \______/ - | | | | | - | | +--|-----+--- EAE command 3 - | | +--- AC -> MQ, 0 -> AC 2 - | +--- MQ v AC --> AC 2 - +-- clear AC 1 - - The operate instruction can be microprogrammed to perform operations - on the AC, MQ, and link. -*/ - -/* This routine is the instruction decode routine for the PDP-8. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - breakpoint encountered - unimplemented instruction and stop_inst flag set - I/O error in I/O simulator - - 2. Interrupts. Interrupts are maintained by three parallel variables: - - dev_done device done flags - int_enable interrupt enable flags - int_req interrupt requests - - In addition, int_req contains the interrupt enable flag, the - CIF not pending flag, and the ION not pending flag. If all - three of these flags are set, and at least one interrupt request - is set, then an interrupt occurs. - - 3. Non-existent memory. On the PDP-8, reads to non-existent memory - return zero, and writes are ignored. In the simulator, the - largest possible memory is instantiated and initialized to zero. - Thus, only writes outside the current field (indirect writes) need - be checked against actual memory size. - - 3. Adding I/O devices. These modules must be modified: - - pdp8_defs.h add device number and interrupt definitions - pdp8_sys.c add sim_devices table entry -*/ - -#include "pdp8_defs.h" - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC -#define UNIT_V_NOEAE (UNIT_V_UF) /* EAE absent */ -#define UNIT_NOEAE (1 << UNIT_V_NOEAE) -#define UNIT_V_MSIZE (UNIT_V_UF+1) /* dummy mask */ -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -uint16 M[MAXMEMSIZE] = { 0 }; /* main memory */ -int32 saved_LAC = 0; /* saved L'AC */ -int32 saved_MQ = 0; /* saved MQ */ -int32 saved_PC = 0; /* saved IF'PC */ -int32 saved_DF = 0; /* saved Data Field */ -int32 IB = 0; /* Instruction Buffer */ -int32 SF = 0; /* Save Field */ -int32 emode = 0; /* EAE mode */ -int32 gtf = 0; /* EAE gtf flag */ -int32 SC = 0; /* EAE shift count */ -int32 UB = 0; /* User mode Buffer */ -int32 UF = 0; /* User mode Flag */ -int32 OSR = 0; /* Switch Register */ -int16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -int32 dev_done = 0; /* dev done flags */ -int32 int_enable = INT_INIT_ENABLE; /* intr enables */ -int32 int_req = 0; /* intr requests */ -int32 stop_inst = 0; /* trap on ill inst */ -int32 (*dev_tab[DEV_MAX])(int32 IR, int32 dat); /* device dispatch */ - -extern int32 sim_interval; -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern DEVICE *sim_devices[]; -extern FILE *sim_log; -extern UNIT clk_unit, ttix_unit; - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_bool build_dev_tab (void); - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifier list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, MAXMEMSIZE) }; - -REG cpu_reg[] = { - { ORDATA (PC, saved_PC, 15) }, - { ORDATA (AC, saved_LAC, 12) }, - { FLDATA (L, saved_LAC, 12) }, - { ORDATA (MQ, saved_MQ, 12) }, - { ORDATA (SR, OSR, 12) }, - { GRDATA (IF, saved_PC, 8, 3, 12) }, - { GRDATA (DF, saved_DF, 8, 3, 12) }, - { GRDATA (IB, IB, 8, 3, 12) }, - { ORDATA (SF, SF, 7) }, - { FLDATA (UB, UB, 0) }, - { FLDATA (UF, UF, 0) }, - { ORDATA (SC, SC, 5) }, - { FLDATA (GTF, gtf, 0) }, - { FLDATA (EMODE, emode, 0) }, - { FLDATA (ION, int_req, INT_V_ION) }, - { FLDATA (ION_DELAY, int_req, INT_V_NO_ION_PENDING) }, - { FLDATA (CIF_DELAY, int_req, INT_V_NO_CIF_PENDING) }, - { FLDATA (PWR_INT, int_req, INT_V_PWR) }, - { FLDATA (UF_INT, int_req, INT_V_UF) }, - { ORDATA (INT, int_req, INT_V_ION+1), REG_RO }, - { ORDATA (DONE, dev_done, INT_V_DIRECT), REG_RO }, - { ORDATA (ENABLE, int_enable, INT_V_DIRECT), REG_RO }, - { BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { FLDATA (STOP_INST, stop_inst, 0) }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_NOEAE, UNIT_NOEAE, "no EAE", "NOEAE", NULL }, - { UNIT_NOEAE, 0, "EAE", "EAE", NULL }, - { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, - { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, - { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size }, - { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, - { UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size }, - { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size }, - { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size }, - { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, 15, 1, 8, 12, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL, - NULL, 0 }; - -t_stat sim_instr (void) -{ -int32 IR, MB, IF, DF, LAC, MQ; -uint32 PC, MA; -int32 device, pulse, temp, iot_data; -t_stat reason; - -/* Restore register state */ - -if (build_dev_tab ()) return SCPE_STOP; /* build dev_tab */ -PC = saved_PC & 007777; /* load local copies */ -IF = saved_PC & 070000; -DF = saved_DF & 070000; -LAC = saved_LAC & 017777; -MQ = saved_MQ & 07777; -int_req = INT_UPDATE; -reason = 0; -sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init clk calib */ -sim_rtcn_init (ttix_unit.wait, TMR_TTX); /* init ttx calib */ - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } - -if (int_req > INT_PENDING) { /* interrupt? */ - int_req = int_req & ~INT_ION; /* interrupts off */ - SF = (UF << 6) | (IF >> 9) | (DF >> 12); /* form save field */ - IF = IB = DF = UF = UB = 0; /* clear mem ext */ - PCQ_ENTRY; /* save old PC */ - M[0] = PC; /* save PC in 0 */ - PC = 1; } /* fetch next from 1 */ - -MA = IF | PC; /* form PC */ -if (sim_brk_summ && sim_brk_test (MA, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - -IR = M[MA]; /* fetch instruction */ -PC = (PC + 1) & 07777; /* increment PC */ -int_req = int_req | INT_NO_ION_PENDING; /* clear ION delay */ -sim_interval = sim_interval - 1; - -/* Instruction decoding. - - The opcode (IR<0:2>), indirect flag (IR<3>), and page flag (IR<4>) - are decoded together. This produces 32 decode points, four per - major opcode. For IOT, the extra decode points are not useful; - for OPR, only the group flag (IR<3>) is used. - - The following macros define the address calculations for data and - jump calculations. Data calculations return a full 15b extended - address, jump calculations a 12b field-relative address. - - Autoindex calculations always occur within the same field as the - instruction fetch. The field must exist; otherwise, the instruction - fetched would be 0000, and indirect addressing could not occur. - - Note that MA contains IF'PC. -*/ - -#define ZERO_PAGE MA = IF | (IR & 0177) -#define CURR_PAGE MA = (MA & 077600) | (IR & 0177) -#define INDIRECT if ((MA & 07770) != 00010) MA = DF | M[MA]; \ - else MA = DF | (M[MA] = (M[MA] + 1) & 07777) - -#define ZERO_PAGE_J MA = IR & 0177 -#define CURR_PAGE_J MA = (MA & 007600) | (IR & 0177) -#define INDIRECT_J if ((MA & 07770) != 00010) MA = M[MA]; \ - else MA = (M[MA] = (M[MA] + 1) & 07777) -#define CHANGE_FIELD IF = IB; UF = UB; \ - int_req = int_req | INT_NO_CIF_PENDING - -switch ((IR >> 7) & 037) { /* decode IR<0:4> */ - -/* Opcode 0, AND */ - -case 000: /* AND, dir, zero */ - ZERO_PAGE; - LAC = LAC & (M[MA] | 010000); - break; -case 001: /* AND, dir, curr */ - CURR_PAGE; - LAC = LAC & (M[MA] | 010000); - break; -case 002: /* AND, indir, zero */ - ZERO_PAGE; - INDIRECT; - LAC = LAC & (M[MA] | 010000); - break; -case 003: /* AND, indir, curr */ - CURR_PAGE; - INDIRECT; - LAC = LAC & (M[MA] | 010000); - break; - -/* Opcode 1, TAD */ - -case 004: /* TAD, dir, zero */ - ZERO_PAGE; - LAC = (LAC + M[MA]) & 017777; - break; -case 005: /* TAD, dir, curr */ - CURR_PAGE; - LAC = (LAC + M[MA]) & 017777; - break; -case 006: /* TAD, indir, zero */ - ZERO_PAGE; - INDIRECT; - LAC = (LAC + M[MA]) & 017777; - break; -case 007: /* TAD, indir, curr */ - CURR_PAGE; - INDIRECT; - LAC = (LAC + M[MA]) & 017777; - break; - -/* Opcode 2, ISZ */ - -case 010: /* ISZ, dir, zero */ - ZERO_PAGE; - M[MA] = MB = (M[MA] + 1) & 07777; /* field must exist */ - if (MB == 0) PC = (PC + 1) & 07777; - break; -case 011: /* ISZ, dir, curr */ - CURR_PAGE; - M[MA] = MB = (M[MA] + 1) & 07777; /* field must exist */ - if (MB == 0) PC = (PC + 1) & 07777; - break; -case 012: /* ISZ, indir, zero */ - ZERO_PAGE; - INDIRECT; - MB = (M[MA] + 1) & 07777; - if (MEM_ADDR_OK (MA)) M[MA] = MB; - if (MB == 0) PC = (PC + 1) & 07777; - break; -case 013: /* ISZ, indir, curr */ - CURR_PAGE; - INDIRECT; - MB = (M[MA] + 1) & 07777; - if (MEM_ADDR_OK (MA)) M[MA] = MB; - if (MB == 0) PC = (PC + 1) & 07777; - break; - -/* Opcode 3, DCA */ - -case 014: /* DCA, dir, zero */ - ZERO_PAGE; - M[MA] = LAC & 07777; - LAC = LAC & 010000; - break; -case 015: /* DCA, dir, curr */ - CURR_PAGE; - M[MA] = LAC & 07777; - LAC = LAC & 010000; - break; -case 016: /* DCA, indir, zero */ - ZERO_PAGE; - INDIRECT; - if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; - LAC = LAC & 010000; - break; -case 017: /* DCA, indir, curr */ - CURR_PAGE; - INDIRECT; - if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; - LAC = LAC & 010000; - break; - -/* Opcode 4, JMS */ - -case 020: /* JMS, dir, zero */ - ZERO_PAGE_J; - CHANGE_FIELD; - MA = IF | MA; - PCQ_ENTRY; - if (MEM_ADDR_OK (MA)) M[MA] = PC; - PC = (MA + 1) & 07777; - break; -case 021: /* JMS, dir, curr */ - CURR_PAGE_J; - CHANGE_FIELD; - MA = IF | MA; - PCQ_ENTRY; - if (MEM_ADDR_OK (MA)) M[MA] = PC; - PC = (MA + 1) & 07777; - break; -case 022: /* JMS, indir, zero */ - ZERO_PAGE; - INDIRECT_J; - CHANGE_FIELD; - MA = IF | MA; - PCQ_ENTRY; - if (MEM_ADDR_OK (MA)) M[MA] = PC; - PC = (MA + 1) & 07777; - break; -case 023: /* JMS, indir, curr */ - CURR_PAGE; - INDIRECT_J; - CHANGE_FIELD; - MA = IF | MA; - PCQ_ENTRY; - if (MEM_ADDR_OK (MA)) M[MA] = PC; - PC = (MA + 1) & 07777; - break; - -/* Opcode 5, JMP */ - -case 024: /* JMP, dir, zero */ - ZERO_PAGE_J; - CHANGE_FIELD; - PCQ_ENTRY; - PC = MA; - break; -case 025: /* JMP, dir, curr */ - CURR_PAGE_J; - CHANGE_FIELD; - PCQ_ENTRY; - PC = MA; - break; -case 026: /* JMP, indir, zero */ - ZERO_PAGE; - INDIRECT_J; - CHANGE_FIELD; - PCQ_ENTRY; - PC = MA; - break; -case 027: /* JMP, indir, curr */ - CURR_PAGE; - INDIRECT_J; - CHANGE_FIELD; - PCQ_ENTRY; - PC = MA; - break; - -/* Opcode 7, OPR group 1 */ - -case 034:case 035: /* OPR, group 1 */ - switch ((IR >> 4) & 017) { /* decode IR<4:7> */ - case 0: /* nop */ - break; - case 1: /* CML */ - LAC = LAC ^ 010000; - break; - case 2: /* CMA */ - LAC = LAC ^ 07777; - break; - case 3: /* CMA CML */ - LAC = LAC ^ 017777; - break; - case 4: /* CLL */ - LAC = LAC & 07777; - break; - case 5: /* CLL CML = STL */ - LAC = LAC | 010000; - break; - case 6: /* CLL CMA */ - LAC = (LAC ^ 07777) & 07777; - break; - case 7: /* CLL CMA CML */ - LAC = (LAC ^ 07777) | 010000; - break; - case 010: /* CLA */ - LAC = LAC & 010000; - break; - case 011: /* CLA CML */ - LAC = (LAC & 010000) ^ 010000; - break; - case 012: /* CLA CMA = STA */ - LAC = LAC | 07777; - break; - case 013: /* CLA CMA CML */ - LAC = (LAC | 07777) ^ 010000; - break; - case 014: /* CLA CLL */ - LAC = 0; - break; - case 015: /* CLA CLL CML */ - LAC = 010000; - break; - case 016: /* CLA CLL CMA */ - LAC = 07777; - break; - case 017: /* CLA CLL CMA CML */ - LAC = 017777; - break; } /* end switch opers */ - -/* OPR group 1, continued */ - - if (IR & 01) LAC = (LAC + 1) & 017777; /* IAC */ - switch ((IR >> 1) & 07) { /* decode IR<8:10> */ - case 0: /* nop */ - break; - case 1: /* BSW */ - LAC = (LAC & 010000) | ((LAC >> 6) & 077) | ((LAC & 077) << 6); - break; - case 2: /* RAL */ - LAC = ((LAC << 1) | (LAC >> 12)) & 017777; - break; - case 3: /* RTL */ - LAC = ((LAC << 2) | (LAC >> 11)) & 017777; - break; - case 4: /* RAR */ - LAC = ((LAC >> 1) | (LAC << 12)) & 017777; - break; - case 5: /* RTR */ - LAC = ((LAC >> 2) | (LAC << 11)) & 017777; - break; - case 6: /* RAL RAR - undef */ - LAC = LAC & (IR | 010000); /* uses AND path */ - break; - case 7: /* RTL RTR - undef */ - LAC = (LAC & 010000) | (MA & 07600) | (IR & 0177); - break; } /* uses address path */ - break; /* end group 1 */ - -/* OPR group 2 */ - -case 036:case 037: /* OPR, groups 2, 3 */ - if ((IR & 01) == 0) { /* group 2 */ - switch ((IR >> 3) & 017) { /* decode IR<6:8> */ - case 0: /* nop */ - break; - case 1: /* SKP */ - PC = (PC + 1) & 07777; - break; - case 2: /* SNL */ - if (LAC >= 010000) PC = (PC + 1) & 07777; - break; - case 3: /* SZL */ - if (LAC < 010000) PC = (PC + 1) & 07777; - break; - case 4: /* SZA */ - if ((LAC & 07777) == 0) PC = (PC + 1) & 07777; - break; - case 5: /* SNA */ - if ((LAC & 07777) != 0) PC = (PC + 1) & 07777; - break; - case 6: /* SZA | SNL */ - if ((LAC == 0) || (LAC >= 010000)) - PC = (PC + 1) & 07777; - break; - case 7: /* SNA & SZL */ - if ((LAC != 0) && (LAC < 010000)) PC = (PC + 1) & 07777; - break; - case 010: /* SMA */ - if ((LAC & 04000) != 0) PC = (PC + 1) & 07777; - break; - case 011: /* SPA */ - if ((LAC & 04000) == 0) PC = (PC + 1) & 07777; - break; - case 012: /* SMA | SNL */ - if (LAC >= 04000) PC = (PC + 1) & 07777; - break; - case 013: /* SPA & SZL */ - if (LAC < 04000) PC = (PC + 1) & 07777; - break; - case 014: /* SMA | SZA */ - if (((LAC & 04000) != 0) || ((LAC & 07777) == 0)) - PC = (PC + 1) & 07777; - break; - case 015: /* SPA & SNA */ - if (((LAC & 04000) == 0) && ((LAC & 07777) != 0)) - PC = (PC + 1) & 07777; - break; - case 016: /* SMA | SZA | SNL */ - if ((LAC >= 04000) || (LAC == 0)) PC = (PC + 1) & 07777; - break; - case 017: /* SPA & SNA & SZL */ - if ((LAC < 04000) && (LAC != 0)) PC = (PC + 1) & 07777; - break; } /* end switch skips */ - if (IR & 0200) LAC = LAC & 010000; /* CLA */ - if ((IR & 06) && UF) int_req = int_req | INT_UF; - else { - if (IR & 04) LAC = LAC | OSR; /* OSR */ - if (IR & 02) reason = STOP_HALT; } /* HLT */ - break; } /* end group 2 */ - -/* OPR group 3 standard - - MQA!MQL exchanges AC and MQ, as follows: - - temp = MQ; - MQ = LAC & 07777; - LAC = LAC & 010000 | temp; -*/ - - temp = MQ; /* group 3 */ - if (IR & 0200) LAC = LAC & 010000; /* CLA */ - if (IR & 0020) { /* MQL */ - MQ = LAC & 07777; - LAC = LAC & 010000; } - if (IR & 0100) LAC = LAC | temp; /* MQA */ - if ((IR & 0056) && (cpu_unit.flags & UNIT_NOEAE)) { - reason = stop_inst; /* EAE not present */ - break; } - -/* OPR group 3 EAE - - The EAE operates in two modes: - - Mode A, PDP-8/I compatible - Mode B, extended capability - - Mode B provides eight additional subfunctions; in addition, some - of the Mode A functions operate differently in Mode B. - - The mode switch instructions are decoded explicitly and cannot be - microprogrammed with other EAE functions (SWAB performs an MQL as - part of standard group 3 decoding). If mode switching is decoded, - all other EAE timing is suppressed. -*/ - - if (IR == 07431) { /* SWAB */ - emode = 1; /* set mode flag */ - break; } - if (IR == 07447) { /* SWBA */ - emode = gtf = 0; /* clear mode, gtf */ - break; } - -/* If not switching modes, the EAE operation is determined by the mode - and IR<6,8:10>: - - <6:10> mode A mode B comments - - 0x000 NOP NOP - 0x001 SCL ACS - 0x010 MUY MUY if mode B, next = address - 0x011 DVI DVI if mode B, next = address - 0x100 NMI NMI if mode B, clear AC if - result = 4000'0000 - 0x101 SHL SHL if mode A, extra shift - 0x110 ASR ASR if mode A, extra shift - 0x111 LSR LSR if mode A, extra shift - 1x000 SCA SCA - 1x001 SCA + SCL DAD - 1x010 SCA + MUY DST - 1x011 SCA + DVI SWBA NOP if not detected earlier - 1x100 SCA + NMI DPSZ - 1x101 SCA + SHL DPIC must be combined with MQA!MQL - 1x110 SCA + ASR DCM must be combined with MQA!MQL - 1x111 SCA + LSR SAM - - EAE instructions which fetch memory operands use the CPU's DEFER - state to read the first word; if the address operand is in locations - x0010 - x0017, it is autoincremented. -*/ - -/* EAE continued */ - - if (emode == 0) gtf = 0; /* mode A? clr gtf */ - switch ((IR >> 1) & 027) { /* decode IR<6,8:10> */ - case 020: /* mode A, B: SCA */ - LAC = LAC | SC; - break; - case 000: /* mode A, B: NOP */ - break; - case 021: /* mode B: DAD */ - if (emode) { - MA = IF | PC; - INDIRECT; /* defer state */ - MQ = MQ + M[MA]; - MA = DF | ((MA + 1) & 07777); - LAC = (LAC & 07777) + M[MA] + (MQ >> 12); - MQ = MQ & 07777; - PC = (PC + 1) & 07777; - break; } - LAC = LAC | SC; /* mode A: SCA then */ - case 001: /* mode B: ACS */ - if (emode) { - SC = LAC & 037; - LAC = LAC & 010000; } - else { /* mode A: SCL */ - SC = (~M[IF | PC]) & 037; - PC = (PC + 1) & 07777; } - break; - case 022: /* mode B: DST */ - if (emode) { - MA = IF | PC; - INDIRECT; /* defer state */ - if (MEM_ADDR_OK (MA)) M[MA] = MQ & 07777; - MA = DF | ((MA + 1) & 07777); - if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; - PC = (PC + 1) & 07777; - break; } - LAC = LAC | SC; /* mode A: SCA then */ - case 002: /* MUY */ - MA = IF | PC; - if (emode) { INDIRECT; } /* mode B: defer */ - temp = (MQ * M[MA]) + (LAC & 07777); - LAC = (temp >> 12) & 07777; - MQ = temp & 07777; - PC = (PC + 1) & 07777; - SC = 014; /* 12 shifts */ - break; - -/* EAE continued */ - - case 023: /* mode B: SWBA */ - if (emode) break; - LAC = LAC | SC; /* mode A: SCA then */ - case 003: /* DVI */ - MA = IF | PC; - if (emode) { INDIRECT; } /* mode B: defer */ - if ((LAC & 07777) >= M[MA]) { /* overflow? */ - LAC = LAC | 010000; /* set link */ - MQ = ((MQ << 1) + 1) & 07777; /* rotate MQ */ - SC = 01; } /* 1 shift */ - else { - temp = ((LAC & 07777) << 12) | MQ; - MQ = temp / M[MA]; - LAC = temp % M[MA]; - SC = 015; } /* 13 shifts */ - PC = (PC + 1) & 07777; - break; - case 024: /* mode B: DPSZ */ - if (emode) { - if (((LAC | MQ) & 07777) == 0) PC = (PC + 1) & 07777; - break; } - LAC = LAC | SC; /* mode A: SCA then */ - case 004: /* NMI */ - temp = (LAC << 12) | MQ; /* preserve link */ - for (SC = 0; ((temp & 017777777) != 0) && - (temp & 040000000) == ((temp << 1) & 040000000); SC++) - temp = temp << 1; - LAC = (temp >> 12) & 017777; - MQ = temp & 07777; - if (emode && ((LAC & 07777) == 04000) && (MQ == 0)) - LAC = LAC & 010000; /* clr if 4000'0000 */ - break; - case 025: /* mode B: DPIC */ - if (emode) { - temp = (LAC + 1) & 07777; /* SWP already done! */ - LAC = MQ + (temp == 0); - MQ = temp; - break; } - LAC = LAC | SC; /* mode A: SCA then */ - case 5: /* SHL */ - SC = (M[IF | PC] & 037) + (emode ^ 1); /* shift+1 if mode A */ - if (SC > 25) temp = 0; /* >25? result = 0 */ - else temp = ((LAC << 12) | MQ) << SC; /* <=25? shift LAC:MQ */ - LAC = (temp >> 12) & 017777; - MQ = temp & 07777; - PC = (PC + 1) & 07777; - SC = emode? 037: 0; /* SC = 0 if mode A */ - break; - -/* EAE continued */ - - case 026: /* mode B: DCM */ - if (emode) { - temp = (-LAC) & 07777; /* SWP already done! */ - LAC = (MQ ^ 07777) + (temp == 0); - MQ = temp; - break; } - LAC = LAC | SC; /* mode A: SCA then */ - case 6: /* ASR */ - SC = (M[IF | PC] & 037) + (emode ^ 1); /* shift+1 if mode A */ - temp = ((LAC & 07777) << 12) | MQ; /* sext from AC0 */ - if (LAC & 04000) temp = temp | ~037777777; - if (emode && (SC != 0)) gtf = (temp >> (SC - 1)) & 1; - if (SC > 25) temp = (LAC & 04000)? -1: 0; - else temp = temp >> SC; - LAC = (temp >> 12) & 017777; - MQ = temp & 07777; - PC = (PC + 1) & 07777; - SC = emode? 037: 0; /* SC = 0 if mode A */ - break; - case 027: /* mode B: SAM */ - if (emode) { - temp = LAC & 07777; - LAC = MQ + (temp ^ 07777) + 1; /* L'AC = MQ - AC */ - gtf = (temp <= MQ) ^ ((temp ^ MQ) >> 11); - break; } - LAC = LAC | SC; /* mode A: SCA then */ - case 7: /* LSR */ - SC = (M[IF | PC] & 037) + (emode ^ 1); /* shift+1 if mode A */ - temp = ((LAC & 07777) << 12) | MQ; /* clear link */ - if (emode && (SC != 0)) gtf = (temp >> (SC - 1)) & 1; - if (SC > 24) temp = 0; /* >24? result = 0 */ - else temp = temp >> SC; /* <=24? shift AC:MQ */ - LAC = (temp >> 12) & 07777; - MQ = temp & 07777; - PC = (PC + 1) & 07777; - SC = emode? 037: 0; /* SC = 0 if mode A */ - break; } /* end switch */ - break; /* end case 7 */ - -/* Opcode 6, IOT */ - -case 030:case 031:case 032:case 033: /* IOT */ - if (UF) { /* privileged? */ - int_req = int_req | INT_UF; - break; } - device = (IR >> 3) & 077; /* device = IR<3:8> */ - pulse = IR & 07; /* pulse = IR<9:11> */ - iot_data = LAC & 07777; /* AC unchanged */ - switch (device) { /* decode IR<3:8> */ - case 0: /* CPU control */ - switch (pulse) { /* decode IR<9:11> */ - case 0: /* SKON */ - if (int_req & INT_ION) PC = (PC + 1) & 07777; - int_req = int_req & ~INT_ION; - break; - case 1: /* ION */ - int_req = (int_req | INT_ION) & ~INT_NO_ION_PENDING; - break; - case 2: /* IOF */ - int_req = int_req & ~INT_ION; - break; - case 3: /* SRQ */ - if (int_req & INT_ALL) PC = (PC + 1) & 07777; - break; - case 4: /* GTF */ - LAC = (LAC & 010000) | - ((LAC & 010000) >> 1) | (gtf << 10) | - (((int_req & INT_ALL) != 0) << 9) | - (((int_req & INT_ION) != 0) << 7) | SF; - break; - case 5: /* RTF */ - gtf = ((LAC & 02000) >> 10); - UB = (LAC & 0100) >> 6; - IB = (LAC & 0070) << 9; - DF = (LAC & 0007) << 12; - LAC = ((LAC & 04000) << 1) | iot_data; - int_req = (int_req | INT_ION) & ~INT_NO_CIF_PENDING; - break; - case 6: /* SGT */ - if (gtf) PC = (PC + 1) & 07777; - break; - case 7: /* CAF */ - gtf = 0; - emode = 0; - int_req = int_req & INT_NO_CIF_PENDING; - dev_done = 0; - int_enable = INT_INIT_ENABLE; - LAC = 0; - break; } /* end switch pulse */ - break; /* end case 0 */ - -/* IOT, continued: memory extension */ - - case 020:case 021:case 022:case 023: - case 024:case 025:case 026:case 027: /* memory extension */ - switch (pulse) { /* decode IR<9:11> */ - case 1: /* CDF */ - DF = (IR & 0070) << 9; - break; - case 2: /* CIF */ - IB = (IR & 0070) << 9; - int_req = int_req & ~INT_NO_CIF_PENDING; - break; - case 3: /* CDF CIF */ - DF = IB = (IR & 0070) << 9; - int_req = int_req & ~INT_NO_CIF_PENDING; - break; - case 4: - switch (device & 07) { /* decode IR<6:8> */ - case 0: /* CINT */ - int_req = int_req & ~INT_UF; - break; - case 1: /* RDF */ - LAC = LAC | (DF >> 9); - break; - case 2: /* RIF */ - LAC = LAC | (IF >> 9); - break; - case 3: /* RIB */ - LAC = LAC | SF; - break; - case 4: /* RMF */ - UB = (SF & 0100) >> 6; - IB = (SF & 0070) << 9; - DF = (SF & 0007) << 12; - int_req = int_req & ~INT_NO_CIF_PENDING; - break; - case 5: /* SINT */ - if (int_req & INT_UF) PC = (PC + 1) & 07777; - break; - case 6: /* CUF */ - UB = 0; - int_req = int_req & ~INT_NO_CIF_PENDING; - break; - case 7: /* SUF */ - UB = 1; - int_req = int_req & ~INT_NO_CIF_PENDING; - break; } /* end switch device */ - break; - default: - reason = stop_inst; - break; } /* end switch pulse */ - break; /* end case 20-27 */ - -/* IOT, continued: other special cases */ - - case 010: /* power fail */ - switch (pulse) { /* decode IR<9:11> */ - case 1: /* SBE */ - break; - case 2: /* SPL */ - if (int_req & INT_PWR) PC = (PC + 1) & 07777; - break; - case 3: /* CAL */ - int_req = int_req & ~INT_PWR; - break; - default: - reason = stop_inst; - break; } /* end switch pulse */ - break; /* end case 10 */ - default: /* I/O device */ - if (dev_tab[device]) { /* dev present? */ - iot_data = dev_tab[device] (IR, iot_data); - LAC = (LAC & 010000) | (iot_data & 07777); - if (iot_data & IOT_SKP) PC = (PC + 1) & 07777; - if (iot_data >= IOT_REASON) - reason = iot_data >> IOT_V_REASON; } - else reason = stop_inst; /* stop on flag */ - break; } /* end switch device */ - break; /* end case IOT */ - } /* end switch opcode */ -} /* end while */ - -/* Simulation halted */ - -saved_PC = IF | (PC & 07777); /* save copies */ -saved_DF = DF & 070000; -saved_LAC = LAC & 017777; -saved_MQ = MQ & 07777; -pcq_r->qptr = pcq_p; /* update pc q ptr */ -return reason; -} /* end sim_instr */ - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -int_req = (int_req & ~INT_ION) | INT_NO_CIF_PENDING; -saved_DF = IB = saved_PC & 070000; -UF = UB = gtf = emode = 0; -pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & 07777; -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -M[addr] = val & 07777; -return SCPE_OK; -} - -/* Memory size change */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; -if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_OK; -MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; -return SCPE_OK; -} - -/* Change device number for a device */ - -t_stat set_dev (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newdev; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newdev = get_uint (cptr, 8, DEV_MAX - 1, &r); /* get new */ -if ((r != SCPE_OK) || (newdev == dibp->dev)) return r; -dibp->dev = newdev; /* store */ -return SCPE_OK; -} - -/* Show device number for a device */ - -t_stat show_dev (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -DEVICE *dptr; -DIB *dibp; - -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -fprintf (st, "devno=%02o", dibp->dev); -if (dibp->num > 1) fprintf (st, "-%2o", dibp->dev + dibp->num - 1); -return SCPE_OK; -} - -/* CPU device handler - should never get here! */ - -int32 bad_dev (int32 IR, int32 AC) -{ -return (SCPE_IERR << IOT_V_REASON) | AC; /* broken! */ -} - -/* Build device dispatch table */ - -t_bool build_dev_tab (void) -{ -DEVICE *dptr; -DIB *dibp; -uint32 i, j; -static const uint8 std_dev[] = - { 000, 010, 020, 021, 022, 023, 024, 025, 026, 027 }; - -for (i = 0; i < DEV_MAX; i++) dev_tab[i] = NULL; /* clr table */ -for (i = 0; i < ((uint32) sizeof (std_dev)); i++) /* std entries */ - dev_tab[std_dev[i]] = &bad_dev; -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* add devices */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if (dibp && !(dptr->flags & DEV_DIS)) { /* enabled? */ - for (j = 0; j < dibp->num; j++) { /* loop thru disp */ - if (dibp->dsp[j]) { /* any dispatch? */ - if (dev_tab[dibp->dev + j]) { /* already filled? */ - printf ("%s device number conflict at %02o\n", - sim_dname (dptr), dibp->dev + j); - if (sim_log) fprintf (sim_log, - "%s device number conflict at %02o\n", - sim_dname (dptr), dibp->dev + j); - return TRUE; } - dev_tab[dibp->dev + j] = dibp->dsp[j]; /* fill */ - } /* end if dsp */ - } /* end for j */ - } /* end if enb */ - } /* end for i */ -return FALSE; -} diff --git a/PDP8/pdp8_defs.h b/PDP8/pdp8_defs.h deleted file mode 100644 index 74c9fed7..00000000 --- a/PDP8/pdp8_defs.h +++ /dev/null @@ -1,188 +0,0 @@ -/* pdp8_defs.h: PDP-8 simulator definitions - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 04-Oct-02 RMS Added variable device number support - 20-Jan-02 RMS Fixed bug in TTx interrupt enable initialization - 25-Nov-01 RMS Added RL8A support - 16-Sep-01 RMS Added multiple KL support - 18-Mar-01 RMS Added DF32 support - 15-Feb-01 RMS Added DECtape support - 14-Apr-99 RMS Changed t_addr to unsigned - 19-Mar-95 RMS Added dynamic memory size - 02-May-94 RMS Added non-existent memory handling - - The author gratefully acknowledges the help of Max Burnet, Richie Lary, - and Bill Haygood in resolving questions about the PDP-8 -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_NOTSTD 4 /* non-std devno */ - -/* Memory */ - -#define MAXMEMSIZE 32768 /* max memory size */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define ADDRMASK (MAXMEMSIZE - 1) /* address mask */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) - -/* IOT subroutine return codes */ - -#define IOT_V_SKP 12 /* skip */ -#define IOT_V_REASON 13 /* reason */ -#define IOT_SKP (1 << IOT_V_SKP) -#define IOT_REASON (1 << IOT_V_REASON) -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ - -/* Timers */ - -#define TMR_CLK 0 /* timer 0 = clock */ -#define TMR_TTX 1 /* timer 1 = TTx */ - -/* Device information block */ - -#define DEV_MAXBLK 8 /* max dev block */ -#define DEV_MAX 64 /* total devices */ - -struct pdp8_dib { - uint32 dev; /* base dev number */ - uint32 num; /* number of slots */ - int32 (*dsp[DEV_MAXBLK])(int32 IR, int32 dat); -}; - -typedef struct pdp8_dib DIB; - -/* Standard device numbers */ - -#define DEV_PTR 001 /* paper tape reader */ -#define DEV_PTP 002 /* paper tape punch */ -#define DEV_TTI 003 /* console input */ -#define DEV_TTO 004 /* console output */ -#define DEV_CLK 013 /* clock */ -#define DEV_KJ8 040 /* extra terminals */ -#define DEV_DF 060 /* DF32 */ -#define DEV_RF 060 /* RF08 */ -#define DEV_RL 060 /* RL8A */ -#define DEV_LPT 066 /* line printer */ -#define DEV_MT 070 /* TM8E */ -#define DEV_RK 074 /* RK8E */ -#define DEV_RX 075 /* RX8E/RX28 */ -#define DEV_DTA 076 /* TC08 */ - -/* Interrupt flags - - The interrupt flags consist of three groups: - - 1. Devices with individual interrupt enables. These record - their interrupt requests in device_done and their enables - in device_enable, and must occupy the low bit positions. - - 2. Devices without interrupt enables. These record their - interrupt requests directly in int_req, and must occupy - the middle bit positions. - - 3. Overhead. These exist only in int_req and must occupy the - high bit positions. - - Because the PDP-8 does not have priority interrupts, the order - of devices within groups does not matter. - - Note: all extra KL input and output interrupts must be assigned - to contiguous bits. -*/ - -#define INT_V_START 0 /* enable start */ -#define INT_V_LPT (INT_V_START+0) /* line printer */ -#define INT_V_PTP (INT_V_START+1) /* tape punch */ -#define INT_V_PTR (INT_V_START+2) /* tape reader */ -#define INT_V_TTO (INT_V_START+3) /* terminal */ -#define INT_V_TTI (INT_V_START+4) /* keyboard */ -#define INT_V_CLK (INT_V_START+5) /* clock */ -#define INT_V_TTO1 (INT_V_START+6) /* tto1 */ -#define INT_V_TTO2 (INT_V_START+7) /* tto2 */ -#define INT_V_TTO3 (INT_V_START+8) /* tto3 */ -#define INT_V_TTO4 (INT_V_START+9) /* tto4 */ -#define INT_V_TTI1 (INT_V_START+10) /* tti1 */ -#define INT_V_TTI2 (INT_V_START+11) /* tti2 */ -#define INT_V_TTI3 (INT_V_START+12) /* tti3 */ -#define INT_V_TTI4 (INT_V_START+13) /* tti4 */ -#define INT_V_DIRECT (INT_V_START+14) /* direct start */ -#define INT_V_RX (INT_V_DIRECT+0) /* RX8E */ -#define INT_V_RK (INT_V_DIRECT+1) /* RK8E */ -#define INT_V_RF (INT_V_DIRECT+2) /* RF08 */ -#define INT_V_DF (INT_V_DIRECT+3) /* DF32 */ -#define INT_V_MT (INT_V_DIRECT+4) /* TM8E */ -#define INT_V_DTA (INT_V_DIRECT+5) /* TC08 */ -#define INT_V_RL (INT_V_DIRECT+6) /* RL8A */ -#define INT_V_PWR (INT_V_DIRECT+7) /* power int */ -#define INT_V_UF (INT_V_DIRECT+8) /* user int */ -#define INT_V_OVHD (INT_V_DIRECT+9) /* overhead start */ -#define INT_V_NO_ION_PENDING (INT_V_OVHD+0) /* ion pending */ -#define INT_V_NO_CIF_PENDING (INT_V_OVHD+1) /* cif pending */ -#define INT_V_ION (INT_V_OVHD+2) /* interrupts on */ - -#define INT_LPT (1 << INT_V_LPT) -#define INT_PTP (1 << INT_V_PTP) -#define INT_PTR (1 << INT_V_PTR) -#define INT_TTO (1 << INT_V_TTO) -#define INT_TTI (1 << INT_V_TTI) -#define INT_CLK (1 << INT_V_CLK) -#define INT_TTO1 (1 << INT_V_TTO1) -#define INT_TTO2 (1 << INT_V_TTO2) -#define INT_TTO3 (1 << INT_V_TTO3) -#define INT_TTO4 (1 << INT_V_TTO4) -#define INT_TTI1 (1 << INT_V_TTI1) -#define INT_TTI2 (1 << INT_V_TTI2) -#define INT_TTI3 (1 << INT_V_TTI3) -#define INT_TTI4 (1 << INT_V_TTI4) -#define INT_RX (1 << INT_V_RX) -#define INT_RK (1 << INT_V_RK) -#define INT_RF (1 << INT_V_RF) -#define INT_DF (1 << INT_V_DF) -#define INT_MT (1 << INT_V_MT) -#define INT_DTA (1 << INT_V_DTA) -#define INT_RL (1 << INT_V_RL) -#define INT_PWR (1 << INT_V_PWR) -#define INT_UF (1 << INT_V_UF) -#define INT_NO_ION_PENDING (1 << INT_V_NO_ION_PENDING) -#define INT_NO_CIF_PENDING (1 << INT_V_NO_CIF_PENDING) -#define INT_ION (1 << INT_V_ION) -#define INT_DEV_ENABLE ((1 << INT_V_DIRECT) - 1) /* devices w/enables */ -#define INT_ALL ((1 << INT_V_OVHD) - 1) /* all interrupts */ -#define INT_INIT_ENABLE (INT_TTI+INT_TTO+INT_PTR+INT_PTP+INT_LPT) | \ - (INT_TTI1+INT_TTI2+INT_TTI3+INT_TTI4) | \ - (INT_TTO1+INT_TTO2+INT_TTO3+INT_TTO4) -#define INT_PENDING (INT_ION+INT_NO_CIF_PENDING+INT_NO_ION_PENDING) -#define INT_UPDATE ((int_req & ~INT_DEV_ENABLE) | (dev_done & int_enable)) - -/* Function prototypes */ - -t_stat set_dev (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_dev (FILE *st, UNIT *uptr, int32 val, void *desc); diff --git a/PDP8/pdp8_df.c b/PDP8/pdp8_df.c deleted file mode 100644 index 3e28847c..00000000 --- a/PDP8/pdp8_df.c +++ /dev/null @@ -1,347 +0,0 @@ -/* pdp8_df.c: DF32 fixed head disk simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - df DF32 fixed head disk - - 26-Jul-03 RMS Fixed bug in set size routine - 14-Mar-03 RMS Fixed variable platter interaction with save/restore - 03-Mar-03 RMS Fixed autosizing - 02-Feb-03 RMS Added variable platter and autosizing support - 04-Oct-02 RMS Added DIBs, device number support - 28-Nov-01 RMS Added RL8A support - 25-Apr-01 RMS Added device enable/disable support - - The DF32 is a head-per-track disk. It uses the three cycle data break - facility. To minimize overhead, the entire DF32 is buffered in memory. - - Two timing parameters are provided: - - df_time Interword timing, must be non-zero - df_burst Burst mode, if 0, DMA occurs cycle by cycle; otherwise, - DMA occurs in a burst -*/ - -#include "pdp8_defs.h" -#include - -#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */ -#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */ -#define UNIT_M_PLAT 03 -#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT) -#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT) - -/* Constants */ - -#define DF_NUMWD 2048 /* words/track */ -#define DF_NUMTR 16 /* tracks/disk */ -#define DF_DKSIZE (DF_NUMTR * DF_NUMWD) /* words/disk */ -#define DF_NUMDK 4 /* disks/controller */ -#define DF_WC 07750 /* word count */ -#define DF_MA 07751 /* mem address */ -#define DF_WMASK (DF_NUMWD - 1) /* word mask */ - -/* Parameters in the unit descriptor */ - -#define FUNC u4 /* function */ -#define DF_READ 2 /* read */ -#define DF_WRITE 4 /* write */ - -/* Status register */ - -#define DFS_PCA 04000 /* photocell status */ -#define DFS_DEX 03700 /* disk addr extension */ -#define DFS_MEX 00070 /* mem addr extension */ -#define DFS_DRL 00004 /* data late error */ -#define DFS_WLS 00002 /* write lock error */ -#define DFS_NXD 00002 /* non-existent disk */ -#define DFS_PER 00001 /* parity error */ -#define DFS_ERR (DFS_DRL | DFS_WLS | DFS_PER) -#define DFS_V_DEX 6 -#define DFS_V_MEX 3 - -#define GET_MEX(x) (((x) & DFS_MEX) << (12 - DFS_V_MEX)) -#define GET_DEX(x) (((x) & DFS_DEX) << (12 - DFS_V_DEX)) -#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ - ((double) DF_NUMWD))) -#define UPDATE_PCELL if (GET_POS (df_time) < 6) df_sta = df_sta | DFS_PCA; \ - else df_sta = df_sta & ~DFS_PCA - -extern uint16 M[]; -extern int32 int_req, stop_inst; -extern UNIT cpu_unit; - -int32 df_sta = 0; /* status register */ -int32 df_da = 0; /* disk address */ -int32 df_done = 0; /* done flag */ -int32 df_wlk = 0; /* write lock */ -int32 df_time = 10; /* inter-word time */ -int32 df_burst = 1; /* burst mode flag */ -int32 df_stopioe = 1; /* stop on error */ - -DEVICE df_dev; -int32 df60 (int32 IR, int32 AC); -int32 df61 (int32 IR, int32 AC); -int32 df62 (int32 IR, int32 AC); -t_stat df_svc (UNIT *uptr); -t_stat pcell_svc (UNIT *uptr); -t_stat df_reset (DEVICE *dptr); -t_stat df_boot (int32 unitno, DEVICE *dptr); -t_stat df_attach (UNIT *uptr, char *cptr); -t_stat df_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* DF32 data structures - - df_dev RF device descriptor - df_unit RF unit descriptor - pcell_unit photocell timing unit (orphan) - df_reg RF register list -*/ - -DIB df_dib = { DEV_DF, 3, { &df60, &df61, &df62 } }; - -UNIT df_unit = - { UDATA (&df_svc, UNIT_FIX+UNIT_ATTABLE+ - UNIT_BUFABLE+UNIT_MUSTBUF, DF_DKSIZE) }; - -REG df_reg[] = { - { ORDATA (STA, df_sta, 12) }, - { ORDATA (DA, df_da, 12) }, - { ORDATA (WC, M[DF_WC], 12) }, - { ORDATA (MA, M[DF_MA], 12) }, - { FLDATA (DONE, df_done, 0) }, - { FLDATA (INT, int_req, INT_V_DF) }, - { ORDATA (WLS, df_wlk, 8) }, - { DRDATA (TIME, df_time, 24), REG_NZ + PV_LEFT }, - { FLDATA (BURST, df_burst, 0) }, - { FLDATA (STOP_IOE, df_stopioe, 0) }, - { DRDATA (CAPAC, df_unit.capac, 18), REG_HRO }, - { ORDATA (DEVNUM, df_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB df_mod[] = { - { UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &df_set_size }, - { UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &df_set_size }, - { UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &df_set_size }, - { UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &df_set_size }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE df_dev = { - "DF", &df_unit, df_reg, df_mod, - 1, 8, 17, 1, 8, 12, - NULL, NULL, &df_reset, - &df_boot, &df_attach, NULL, - &df_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 df60 (int32 IR, int32 AC) -{ -int32 t; -int32 pulse = IR & 07; - -UPDATE_PCELL; /* update photocell */ -if (pulse & 1) { /* DCMA */ - df_da = 0; /* clear disk addr */ - df_done = 0; /* clear done */ - df_sta = df_sta & ~DFS_ERR; /* clear errors */ - int_req = int_req & ~INT_DF; } /* clear int req */ -if (pulse & 6) { /* DMAR, DMAW */ - df_da = df_da | AC; /* disk addr |= AC */ - df_unit.FUNC = pulse & ~1; /* save function */ - t = (df_da & DF_WMASK) - GET_POS (df_time); /* delta to new loc */ - if (t < 0) t = t + DF_NUMWD; /* wrap around? */ - sim_activate (&df_unit, t * df_time); /* schedule op */ - AC = 0; } /* clear AC */ -return AC; -} - -/* Based on the hardware implementation. DEAL and DEAC work as follows: - - 6615 pulse 1 = clear df_sta - pulse 4 = df_sta = df_sta | AC - AC = AC | old_df_sta - 6616 pulse 2 = clear AC, skip if address confirmed - pulse 4 = df_sta = df_sta | AC = 0 (nop) - AC = AC | old_df_sta -*/ - -int32 df61 (int32 IR, int32 AC) -{ -int32 old_df_sta = df_sta; -int32 pulse = IR & 07; - -UPDATE_PCELL; /* update photocell */ -if (pulse & 1) /* DCEA */ - df_sta = df_sta & ~(DFS_DEX | DFS_MEX); /* clear dex, mex */ -if (pulse & 2) /* DSAC */ - AC = ((df_da & DF_WMASK) == GET_POS (df_time))? IOT_SKP: 0; -if (pulse & 4) { - df_sta = df_sta | (AC & (DFS_DEX | DFS_MEX)); /* DEAL */ - AC = AC | old_df_sta; } /* DEAC */ -return AC; -} - -int32 df62 (int32 IR, int32 AC) -{ -int32 pulse = IR & 07; - -UPDATE_PCELL; /* update photocell */ -if (pulse & 1) { /* DFSE */ - if ((df_sta & DFS_ERR) == 0) AC = AC | IOT_SKP; } -if (pulse & 2) { /* DFSC */ - if (pulse & 4) AC = AC & ~07777; /* for DMAC */ - else if (df_done) AC = AC | IOT_SKP; } -if (pulse & 4) AC = AC | df_da; /* DMAC */ -return AC; -} - -/* Unit service - - Note that for reads and writes, memory addresses wrap around in the - current field. This code assumes the entire disk is buffered. -*/ - -t_stat df_svc (UNIT *uptr) -{ -int32 pa, t, mex; -uint32 da; - -UPDATE_PCELL; /* update photocell */ -if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ - df_done = 1; - int_req = int_req | INT_DF; /* update int req */ - return IORETURN (df_stopioe, SCPE_UNATT); } - -mex = GET_MEX (df_sta); -da = GET_DEX (df_sta) | df_da; /* form disk addr */ -do { if (da >= uptr->capac) { /* nx disk addr? */ - df_sta = df_sta | DFS_NXD; - break; } - M[DF_WC] = (M[DF_WC] + 1) & 07777; /* incr word count */ - M[DF_MA] = (M[DF_MA] + 1) & 07777; /* incr mem addr */ - pa = mex | M[DF_MA]; /* add extension */ - if (uptr->FUNC == DF_READ) { /* read? */ - if (MEM_ADDR_OK (pa)) /* check nxm */ - M[pa] = *(((int16 *) uptr->filebuf) + da); } - else { /* write */ - t = (da >> 14) & 07; /* check wr lock */ - if ((df_wlk >> t) & 1) df_sta = df_sta | DFS_WLS; - else { /* not locked */ - *(((int16 *) uptr->filebuf) + da) = M[pa]; - if (da >= uptr->hwmark) uptr->hwmark = da + 1; } } - da = (da + 1) & 0377777; } /* incr disk addr */ -while ((M[DF_WC] != 0) && (df_burst != 0)); /* brk if wc, no brst */ - -if ((M[DF_WC] != 0) && ((df_sta & DFS_ERR) == 0)) /* more to do? */ - sim_activate (&df_unit, df_time); /* sched next */ -else { if (uptr->FUNC != DF_READ) da = (da - 1) & 0377777; - df_done = 1; /* done */ - int_req = int_req | INT_DF; } /* update int req */ -df_sta = (df_sta & ~DFS_DEX) | ((da >> (12 - DFS_V_DEX)) & DFS_DEX); -df_da = da & 07777; /* separate disk addr */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat df_reset (DEVICE *dptr) -{ -df_sta = df_da = 0; -df_done = 1; -int_req = int_req & ~INT_DF; /* clear interrupt */ -sim_cancel (&df_unit); -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define OS8_START 07750 -#define OS8_LEN (sizeof (os8_rom) / sizeof (int16)) -#define DM4_START 00200 -#define DM4_LEN (sizeof (dm4_rom) / sizeof (int16)) - -static const uint16 os8_rom[] = { - 07600, /* 7750, CLA CLL ; also word count */ - 06603, /* 7751, DMAR ; also address */ - 06622, /* 7752, DFSC ; done? */ - 05352, /* 7753, JMP .-1 ; no */ - 05752 /* 7754, JMP @.-2 ; enter boot */ -}; - -static const uint16 dm4_rom[] = { - 00200, 07600, /* 0200, CLA CLL */ - 00201, 06603, /* 0201, DMAR ; read */ - 00202, 06622, /* 0202, DFSC ; done? */ - 00203, 05202, /* 0203, JMP .-1 ; no */ - 00204, 05600, /* 0204, JMP @.-4 ; enter boot */ - 07750, 07576, /* 7750, 7576 ; word count */ - 07751, 07576 /* 7751, 7576 ; address */ -}; - -t_stat df_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 sim_switches, saved_PC; - -if (sim_switches & SWMASK ('D')) { - for (i = 0; i < DM4_LEN; i = i + 2) - M[dm4_rom[i]] = dm4_rom[i + 1]; - saved_PC = DM4_START; } -else { for (i = 0; i < OS8_LEN; i++) - M[OS8_START + i] = os8_rom[i]; - saved_PC = OS8_START; } -return SCPE_OK; -} - -/* Attach routine */ - -t_stat df_attach (UNIT *uptr, char *cptr) -{ -uint32 p, sz; -uint32 ds_bytes = DF_DKSIZE * sizeof (int16); - -if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) { - p = (sz + ds_bytes - 1) / ds_bytes; - if (p >= DF_NUMDK) p = DF_NUMDK - 1; - uptr->flags = (uptr->flags & ~UNIT_PLAT) | - (p << UNIT_V_PLAT); } -uptr->capac = UNIT_GETP (uptr->flags) * DF_DKSIZE; -return attach_unit (uptr, cptr); -} - -/* Change disk size */ - -t_stat df_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (val < 0) return SCPE_IERR; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = UNIT_GETP (val) * DF_DKSIZE; -uptr->flags = uptr->flags & ~UNIT_AUTO; -return SCPE_OK; -} diff --git a/PDP8/pdp8_doc.txt b/PDP8/pdp8_doc.txt deleted file mode 100644 index 08f8a218..00000000 --- a/PDP8/pdp8_doc.txt +++ /dev/null @@ -1,758 +0,0 @@ -To: Users -From: Bob Supnik -Subj: PDP-8 Simulator Usage -Date: 1-Feb-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - Original code published in 1993-2003, written by Robert M Supnik - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - -This memorandum documents the PDP-8 simulator. - - -1. Simulator Files - -sim/ sim_defs.h - sim_rev.h - sim_sock.h - sim_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tape.c - sim_tmxr.c - -sim/pdp8/ pdp8_defs.h - pdp8_cpu.c - pdp8_df.c - pdp8_dt.c - pdp8_lp.c - pdp8_mt.c - pdp8_pt.c - pdp8_rf.c - pdp8_rk.c - pdp8_rl.c - pdp8_rx.c - pdp8_sys.c - pdp8_tt.c - pdp8_ttx.c - -2. PDP-8 Features - -The PDP-8 simulator is configured as follows: - -device simulates -name(s) - -CPU PDP-8/E CPU with 4KW-32KW of memory -- KE8E extended arithmetic element (EAE) -- KM8E memory management and timeshare control -PTR,PTP PC8E paper tape reader/punch -TTI,TTO KL8E console terminal -TTIX,TTOX KL8JA additional terminals -LPT LE8E line printer -CLK DK8E line frequency clock (also PDP-8/A compatible) -RK RK8E/RK05 cartridge disk controller with four drives -RF RF08/RS08 fixed head disk controller with 1-4 platters, or -DF DF32/DS32 fixed head disk controller with 1-4 platters -RL RL8A/RL01 cartridge disk controller with four drives -RX RX8E/RX01, RX28/RX02 floppy disk controller with two drives -DT TC08/TU56 DECtape controller with eight drives -MT TM8E/TU10 magnetic tape controller with eight drives - -Most devices can be disabled or enabled, by the commands: - - SET DISABLED - SET ENABLED - -The simulator allows most device numbers to be changed, by the command: - - SET DEV= - -The PDP-8 can support only one of the set {DF32, RF08, RL8A} using the -default device numbers, since they all use device numbers 60-61. The -default is the RF08. To change the disk at device numbers 60-61: - - sim> SET RF DISABLED disable RF08 - sim> SET DF ENABLED, or enable DF32 - sim> SET RL ENABLED enable RL8A - -Alternately, the device conflict can be eliminated by changing device -numbers: - - sim> SET RL DEV=50 - sim> SET RL ENA - -However, devices can only be BOOTed with their default device numbers. - -The PDP-8 simulator implements one unique stop condition: if an undefined -instruction (unimplemented IOT or OPR) is decoded, and register STOP_INST -is set, the simulator halts. - -The PDP-8 loader supports both RIM format and BIN format tapes. If the file -extension is .RIM, or the -r switch is specified with LOAD, the file is -assumed to be RIM format; if the file extension is not .RIM, or if the -b -switch is specified, the file is assumed to be BIN format. - -2.1 CPU - -The only CPU options are the presence of the EAE and the size of main -memory; the memory extension and time-share control is always included, -even if memory size is 4K. - - SET CPU EAE enable EAE - SET CPU NOEAE disable EAE - SET CPU 4K set memory size = 4K - SET CPU 8K set memory size = 8K - SET CPU 12K set memory size = 12K - SET CPU 16K set memory size = 16K - SET CPU 20K set memory size = 20K - SET CPU 24K set memory size = 24K - SET CPU 28K set memory size = 28K - SET CPU 32K set memory size = 32K - -If memory size is being reduced, and the memory being truncated contains -non-zero data, the simulator asks for confirmation. Data in the truncated -portion of memory is lost. Initial memory size is 32K. - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - PC 15 program counter, including IF as high 3 bits - AC 12 accumulator - MQ 12 multiplier-quotient - L 1 link - SR 12 front panel switches - IF 3 instruction field - DF 3 data field - IB 3 instruction field buffer - SF 7 save field - UF 1 user mode flag - UB 1 user mode buffer - SC 5 EAE shift counter - GTF 1 EAE greater than flag - EMODE 1 EAE mode (0 = A, 1 = B) - ION 1 interrupt enable - ION_DELAY 1 interrupt enable delay for ION - CIF_DELAY 1 interrupt enable delay for CIF - PWR_INT 1 power fail interrupt - UF_INT 1 user mode violation interrupt - INT 15 interrupt pending flags - DONE 15 device done flags - ENABLE 15 device interrupt enable flags - PCQ[0:63] 15 PC prior to last JMP, JMS, or interrupt; - most recent PC change first - STOP_INST 1 stop on undefined instruction - WRU 8 interrupt character - -2.2 Programmed I/O Devices - -2.2.1 PC8E Paper Tape Reader (PTR) - -The paper tape reader (PTR) reads data from a disk file. The POS -register specifies the number of the next data item to be read. Thus, -by changing POS, the user can backspace or advance the reader. - -The paper tape reader supports the BOOT command. BOOT PTR copies the -RIM loader into memory and starts it running. - -The paper tape reader implements these registers: - - name size comments - - BUF 8 last data item processed - DONE 1 device done flag - ENABLE 1 interrupt enable flag - INT 1 interrupt pending flag - POS 32 position in the input file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - end of file 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -2.2.2 PC8E Paper Tape Punch (PTP) - -The paper tape punch (PTP) writes data to a disk file. The POS register -specifies the number of the next data item to bewritten. Thus, by -changing POS, the user can backspace or advance the punch. - -The paper tape punch implements these registers: - - name size comments - - BUF 8 last data item processed - DONE 1 device done flag - ENABLE 1 interrupt enable flag - INT 1 interrupt pending flag - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -2.2.3 KL8E Terminal Input (TTI) - -The terminal interfaces (TTI, TTO) can be set to one of three modes: -KSR, 7B, or 8B. In KSR mode, lower case input and output characters -are automatically converted to upper case, and the high order bit is -forced to one on input. In 7B mode, input and output characters are -masked to 7 bits. In 8B mode, characters are not modified. Changing -the mode of either interface changes both. The default mode is KSR. - -The terminal input (TTI) polls the console keyboard for input. It -implements these registers: - - name size comments - - BUF 8 last data item processed - DONE 1 device done flag - ENABLE 1 interrupt enable flag - INT 1 interrupt pending flag - POS 32 number of characters input - TIME 24 keyboard polling interval - -If the simulator is compiled under Windows Visual C++, typing ^C to the -terminal input causes a fatal run-time error. Use the following command -to simulate typing ^C: - - SET TTI CTRL-C - -2.2.4 KL8E Terminal Output (TTO) - -The terminal output (TTO) writes to the simulator console window. It -implements these registers: - - name size comments - - BUF 8 last data item processed - DONE 1 device done flag - ENABLE 1 interrupt enable flag - INT 1 interrupt pending flag - POS 32 number of characters output - TIME 24 time from I/O initiation to interrupt - -2.2.5 LE8E Line Printer (LPT) - -The line printer (LPT) writes data to a disk file. The POS register -specifies the number of the next data item to be read or written. Thus, -by changing POS, the user can backspace or advance the printer. - -The line printer implements these registers: - - name size comments - - BUF 8 last data item processed - ERR 1 error status flag - DONE 1 device done flag - ENABLE 1 interrupt enable flag - INT 1 interrupt pending flag - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 set error flag - - OS I/O error x report error and stop - -2.2.6 DK8E Line-Frequency Clock (CLK) - -The real-time clock (CLK) frequency can be adjusted as follows: - - SET CLK 60HZ set frequency to 60Hz - SET CLK 50HZ set frequency to 50Hz - -The default is 60Hz. - -The clock implements these registers: - - name size comments - - DONE 1 device done flag - ENABLE 1 interrupt enable flag - INT 1 interrupt pending flag - TIME 24 clock interval - -The real-time clock autocalibrates; the clock interval is adjusted up or -down so that the clock tracks actual elapsed time. - -2.2.7 KL8JA Additional Terminals (TTIX, TTOX) - -The additional terminals consist of two independent devices, TTIX and -TTOX. The entire set is modelled as a terminal multiplexor, with TTIX -as the master unit. The additional terminals perform input and output -through Telnet sessions connected to a user-specified port. The ATTACH -command specifies the port to be used: - - ATTACH TTIX set up listening port - -where port is a decimal number between 1 and 65535 that is not being used -for other TCP/IP activities. - -The additional terminals can be set to one of three modes: UC, 7B, or -8B. In KSR mode, lower case input and output characters are converted -automatically to upper case. In 7B mode, input and output characters -are masked to 7 bits. In 8B mode, characters are not modified. The -default mode is UC. - -Once TTIX is attached and the simulator is running, the terminals listen -for connections on the specified port. They assume that the incoming -connections are Telnet connections. The connections remain open until -disconnected either by the Telnet client, a SET TTIX DISCONNECT command, -or a DETACH TTIX command. - -The SHOW TTIX CONNECTIONS command displays the current connections to the -extra terminals. The SHOW TTIX STATISTICS command displays statistics for -active connections. The SET TTIX DISCONNECT=linenumber disconnects the -specified line. - -The input device (TTIX) implements these registers: - - name size comments - - BUF[0:3] 8 input buffer, lines 0-3 - DONE 4 device done flags (line 0 rightmost) - ENABLE 4 interrupt enable flag - INT 4 interrupt pending flag - TIME 24 initial polling interval - TPS 10 polls per second after calibration - -The output device (TTOX) implements these registers: - - name size comments - - BUF[0:3] 8 last data item processed, lines 0-3 - DONE 4 device done flag (line 0 rightmost) - ENABLE 4 interrupt enable flag - INT 4 interrupt pending flag - TIME[0:3] 24 time from I/O initiation to interrupt, - lines 0-3 - -The additional terminals do not support save and restore. All open -connections are lost when the simulator shuts down or TTIX is detached. - -2.3 Moving Head Disks - -2.3.1 RK8E Cartridge Disk (RK) - -RK8E options include the ability to make units write enabled or write locked: - - SET RKn LOCKED set unit n write locked - SET RKn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFLINE. The RK8E supports the BOOT command. - -The RK8E implements these registers: - - name size comments - - RKSTA 12 status - RKCMD 12 disk command - RKDA 12 disk address - RKMA 12 current memory address - BUSY 1 control busy flag - INT 1 interrupt pending flag - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - - end of file x assume rest of disk is zero - - OS I/O error x report error and stop - -2.3.2 RL8A Cartridge Disk (RL) - -RL8A options include the ability to make units write enabled or write locked: - - SET RLn LOCKED set unit n write locked - SET RLn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFILE. The RL8A supports the BOOT command. - -The RL8A implements these registers: - - name size comments - - RLCSA 12 control/status A - RLCSB 12 control/status B - RLMA 12 memory address - RLWC 12 word count - RLSA 6 sector address - RLER 12 error flags - RLSI 16 silo top word - RLSI1 16 silo second word - RLSI2 16 silo third word - RLSIL 1 silo read left/right flag - INT 1 interrupt request - DONE 1 done flag - ERR 1 composite error flag - STIME 1 seek time, per cylinder - RTIME 1 rotational delay - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - - end of file x assume rest of disk is zero - - OS I/O error x report error and stop - -2.4 RX8E/RX01, RX28/RX02 Floppy Disk (RX) - -The RX can be configured as an RX8E with two RX01 drives, or an RX28 with -two RX02 drives: - - SET RX RX8E set controller to RX8E/RX01 - SET RX RX28 set controller to RX28/RX02 - -The controller is set to the RX8E by default. The RX28 is not backwards- -compatible with the RX8E and will not work with the standard OS/8 V3D floppy -disk driver. - -RX8E options include the ability to set units write enabled or write locked: - - SET RXn LOCKED set unit n write locked - SET RXn WRITEENABLED set unit n write enabled - -RX28 options include, in addition, the ability to set the unit density to -single density, double density, or autosized; autosizing is the default: - - SET RXn SINGLE set unit n single density - SET RXn DOUBLE set unit n double density - SET RXn AUTOSIZE set unit n autosize - -The RX8E and RX28 support the BOOT command. - -The RX8E and RX28 implement these registers: - - name size comments - - RXCS 12 status - RXDB 12 data buffer - RXES 12 error status - RXTA 8 current track - RXSA 8 current sector - STAPTR 4 controller state - BUFPTR 8 buffer pointer - INT 1 interrupt pending flag - DONE 1 device done flag - ENABLE 1 interrupt enable flag - TR 1 transfer ready flag - ERR 1 error flag - CTIME 24 command completion time - STIME 24 seek time, per track - XTIME 24 transfer ready delay - STOP_IOE 1 stop on I/O error - SBUF[0:255] 8 sector buffer array - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -RX01 and RX02 data files are buffered in memory; therefore, end of file -and OS I/O errors cannot occur. - -2.5 Fixed Head Disks - -Either the RF08 or the DF32 can be present in a configuration, but -not both, with default device addressing. - -2.5.1 RF08/RS08 Fixed Head Disk (RF) - -RF08 options include the ability to set the number of platters to a -fixed value between 1 and 4, or to autosize the number of platters -from the attached file: - - SET RF 1P one platter (256K) - SET RF 2P two platters (512K) - SET RF 3P three platters (768K) - SET RF 4P four platters (1024K) - SET RF AUTOSIZE autosized on attach - -The default is one platter. - -The RF08 implements these registers: - - name size comments - - STA 12 status - DA 20 current disk address - MA 12 memory address (in memory) - WC 12 word count (in memory) - WLK 32 write lock switches - INT 1 interrupt pending flag - DONE 1 device done flag - TIME 24 rotational delay, per word - BURST 1 burst flag - STOP_IOE 1 stop on I/O error - -The RF08 supports the BOOT command. The default bootstrap is for OS/8. To -bootstrap the 4K Disk Monitor, use the BOOT -D RF command. - -The RF08 is a three-cycle data break device. If BURST = 0, word transfers -are scheduled individually; if BURST = 1, the entire transfer occurs in -a single data break. - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -RF08 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.5.2 DF32/DS32 Fixed Head Disk (RF) - -DF32 options include the ability to set the number of platters to a -fixed value between 1 and 4, or to autosize the number of platters -from the attached file: - - SET DF 1P one platter (32K) - SET DF 2P two platters (64K) - SET DF 3P three platters (98K) - SET DF 4P four platters (128K) - SET DF AUTOSIZE autosized on attach - -The default is one platter. - -The DF32 implements these registers: - - name size comments - - STA 12 status, disk and memory address extension - DA 12 low order disk address - MA 12 memory address (in memory) - WC 12 word count (in memory) - WLK 16 write lock switches - INT 1 interrupt pending flag - DONE 1 device done flag - TIME 24 rotational delay, per word - BURST 1 burst flag - STOP_IOE 1 stop on I/O error - -The DF32 supports the BOOT command. The default bootstrap is for OS/8. To -bootstrap the 4K Disk Monitor, use the BOOT -D DF command. - -The DF32 is a three-cycle data break device. If BURST = 0, word transfers -are scheduled individually; if BURST = 1, the entire transfer occurs in -a single data break. - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -DF32 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.6 TC08/TU56 DECtape (DT) - -DECtapes drives are numbered 1-8; in the simulator, drive 8 is unit 0. -DECtape options include the ability to make units write enabled or write -locked. - - SET DTn LOCKED set unit n write locked - SET DTn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFLINE. The TC08 supports the BOOT command. - -The TC08 supports supports PDP-8 format, PDP-11 format, and 18b format -DECtape images. ATTACH tries to determine the tape format from the DECtape -image; the user can force a particular format with switches: - - -r PDP-8 format - -s PDP-11 format - -t 18b format - -The DECtape controller is a data-only simulator; the timing and mark -track, and block header and trailer, are not stored. Thus, the WRITE -TIMING AND MARK TRACK function is not supported; the READ ALL function -always returns the hardware standard block header and trailer; and the -WRITE ALL function dumps non-data words into the bit bucket. - -The DECtape controller implements these registers: - - name size comments - - DTSA 12 status register A - DTSB 12 status register B - INT 1 interrupt pending flag - ENB 1 interrupt enable flag - DTF 1 DECtape flag - ERF 1 error flag - CA 12 current address (memory location 7754) - WC 12 word count (memory location 7755) - LTIME 31 time between lines - ACTIME 31 time to accelerate to full speed - DCTIME 31 time to decelerate to a full stop - SUBSTATE 2 read/write command substate - POS[0:7] 32 position, in lines, units 0-7 - STATT[0:7] 31 unit state, units 0-7 - -It is critically important to maintain certain timing relationships -among the DECtape parameters, or the DECtape simulator will fail to -operate correctly. - - - LTIME must be at least 6 - - ACTIME must be less than DCTIME, and both need to be at - least 100 times LTIME - -2.7 TM8E Magnetic Tape (MT) - -Magnetic tape options include the ability to make units write enabled or -or write locked. - - SET MTn LOCKED set unit n write locked - SET MTn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFLINE. - -The magnetic tape controller implements these registers: - - name size comments - - CMD 12 command - FNC 12 function - CA 12 memory address - WC 12 word count - DB 12 data buffer - STA 12 main status - STA2 6 secondary status - DONE 1 device done flag - INT 1 interrupt pending flag - STOP_IOE 1 stop on I/O error - TIME 24 record delay - UST[0:7] 24 unit status, units 0-7 - POS[0:7] 32 position, units 0-7 - -Error handling is as follows: - - error processed as - - not attached tape not ready; if STOP_IOE, stop - - end of file bad tape - - OS I/O error parity error; if STOP_IOE, stop - -2.8 Symbolic Display and Input - -The PDP-8 simulator implements symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as (sixbit) character string - -t display as (TSS/8 sixbit) character string - -m display instruction mnemonics - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or -a ASCII character - " or -c two character sixbit string - # or -t two character TSS/8 sixbit string - alphabetic instruction mnemonic - numeric octal number - -Instruction input uses standard PDP-8 assembler syntax. There are four -instruction classes: memory reference, IOT, field change, and operate. - -Memory reference instructions have the format - - memref {I} {C/Z} address - -where I signifies indirect, C a current page reference, and Z a zero page -reference. The address is an octal number in the range 0 - 07777; if C or -Z is specified, the address is a page offset in the range 0 - 177. Normally, -C is not needed; the simulator figures out from the address what mode to use. -However, when referencing memory outside the CPU (eg, disks), there is no -valid PC, and C must be used to specify current page addressing. - -IOT instructions consist of single mnemonics, eg, KRB, TLS. IOT instructions -may be or'd together - - iot iot iot... - -The simulator does not check the legality of the proposed combination. IOT's -for which there is no opcode may be specified as IOT n, where n is an octal -number in the range 0 - 0777. - -Field change instructions (CIF, CDF) have the format - - fldchg field - -where field is an octal number in the range 0 - 7. Field change instructions -may be or'd together. - -Operate instructions have the format - - opr opr opr... - -The simulator does not check the legality of the proposed combination. EAE -mode A and B mnemonics may be specified regardless of the EAE mode. The -operands for MUY and DVI must be deposited explicitly. diff --git a/PDP8/pdp8_dt.c b/PDP8/pdp8_dt.c deleted file mode 100644 index f2c62316..00000000 --- a/PDP8/pdp8_dt.c +++ /dev/null @@ -1,1174 +0,0 @@ -/* pdp8_dt.c: PDP-8 DECtape simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - dt TC08/TU56 DECtape - - 25-Apr-03 RMS Revised for extended file support - 14-Mar-03 RMS Fixed sizing interaction with save/restore - 17-Oct-02 RMS Fixed bug in end of reel logic - 04-Oct-02 RMS Added DIB, device number support - 12-Sep-02 RMS Added support for 16b format - 30-May-02 RMS Widened POS to 32b - 06-Jan-02 RMS Changed enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Changed POS, STATT, LASTT, FLG to arrays - 29-Aug-01 RMS Added casts to PDP-18b packup routine - 17-Jul-01 RMS Moved function prototype - 11-May-01 RMS Fixed bug in reset - 25-Apr-01 RMS Added device enable/disable support - 18-Apr-01 RMS Changed to rewind tape before boot - 19-Mar-01 RMS Changed bootstrap to support 4k disk monitor - 15-Mar-01 RMS Added 129th word to PDP-8 format - - PDP-8 DECtapes are represented in memory by fixed length buffer of 16b words. - Three file formats are supported: - - 18b/36b 256 words per block [256 x 18b] - 16b 256 words per block [256 x 16b] - 12b 129 words per block [129 x 12b] - - When a 16b or 18/36bb DECtape file is read in, it is converted to 12b format. - - DECtape motion is measured in 3b lines. Time between lines is 33.33us. - Tape density is nominally 300 lines per inch. The format of a DECtape is - - reverse end zone 36000 lines ~ 10 feet - block 0 - : - block n - forward end zone 36000 lines ~ 10 feet - - A block consists of five 18b header words, a tape-specific number of data - words, and five 18b trailer words. All systems except the PDP-8 use a - standard block length of 256 words; the PDP-8 uses a standard block length - of 86 words (x 18b = 129 words x 12b). - - Because a DECtape file only contains data, the simulator cannot support - write timing and mark track and can only do a limited implementation - of read all and write all. Read all assumes that the tape has been - conventionally written forward: - - header word 0 0 - header word 1 block number (for forward reads) - header words 2,3 0 - header word 4 0 - : - trailer word 4 checksum - trailer words 3,2 0 - trailer word 1 block number (for reverse reads) - trailer word 0 0 - - Write all writes only the data words and dumps the interblock words in the - bit bucket. -*/ - -#include "pdp8_defs.h" - -#define DT_NUMDR 8 /* #drives */ -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_8FMT (UNIT_V_UF + 1) /* 12b format */ -#define UNIT_V_11FMT (UNIT_V_UF + 2) /* 16b format */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_8FMT (1 << UNIT_V_8FMT) -#define UNIT_11FMT (1 << UNIT_V_11FMT) -#define STATE u3 /* unit state */ -#define LASTT u4 /* last time update */ -#define DT_WC 07754 /* word count */ -#define DT_CA 07755 /* current addr */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -/* System independent DECtape constants */ - -#define DT_EZLIN 36000 /* end zone length */ -#define DT_HTLIN 30 /* header/trailer lines */ -#define DT_BLKLN 6 /* blk no line in h/t */ -#define DT_CSMLN 24 /* checksum line in h/t */ - -/* 16b, 18b, 36b DECtape constants */ - -#define D18_WSIZE 6 /* word size in lines */ -#define D18_BSIZE 384 /* block size in 12b */ -#define D18_TSIZE 578 /* tape size */ -#define D18_LPERB (DT_HTLIN + (D18_BSIZE * DT_WSIZE) + DT_HTLIN) -#define D18_FWDEZ (DT_EZLIN + (D18_LPERB * D18_TSIZE)) -#define D18_CAPAC (D18_TSIZE * D18_BSIZE) /* tape capacity */ - -#define D18_NBSIZE ((D18_BSIZE * D8_WSIZE) / D18_WSIZE) -#define D18_FILSIZ (D18_NBSIZE * D18_TSIZE * sizeof (int32)) -#define D11_FILSIZ (D18_NBSIZE * D18_TSIZE * sizeof (int16)) - -/* 12b DECtape constants */ - -#define D8_WSIZE 4 /* word size in lines */ -#define D8_BSIZE 129 /* block size in 12b */ -#define D8_TSIZE 1474 /* tape size */ -#define D8_LPERB (DT_HTLIN + (D8_BSIZE * DT_WSIZE) + DT_HTLIN) -#define D8_FWDEZ (DT_EZLIN + (D8_LPERB * D8_TSIZE)) -#define D8_CAPAC (D8_TSIZE * D8_BSIZE) /* tape capacity */ -#define D8_FILSIZ (D8_CAPAC * sizeof (int16)) - -/* This controller */ - -#define DT_CAPAC D8_CAPAC /* default */ -#define DT_WSIZE D8_WSIZE - -/* Calculated constants, per unit */ - -#define DTU_BSIZE(u) (((u)->flags & UNIT_8FMT)? D8_BSIZE: D18_BSIZE) -#define DTU_TSIZE(u) (((u)->flags & UNIT_8FMT)? D8_TSIZE: D18_TSIZE) -#define DTU_LPERB(u) (((u)->flags & UNIT_8FMT)? D8_LPERB: D18_LPERB) -#define DTU_FWDEZ(u) (((u)->flags & UNIT_8FMT)? D8_FWDEZ: D18_FWDEZ) -#define DTU_CAPAC(u) (((u)->flags & UNIT_8FMT)? D8_CAPAC: D18_CAPAC) - -#define DT_LIN2BL(p,u) (((p) - DT_EZLIN) / DTU_LPERB (u)) -#define DT_LIN2OF(p,u) (((p) - DT_EZLIN) % DTU_LPERB (u)) -#define DT_LIN2WD(p,u) ((DT_LIN2OF (p,u) - DT_HTLIN) / DT_WSIZE) -#define DT_BLK2LN(p,u) (((p) * DTU_LPERB (u)) + DT_EZLIN) -#define DT_QREZ(u) (((u)->pos) < DT_EZLIN) -#define DT_QFEZ(u) (((u)->pos) >= ((uint32) DTU_FWDEZ (u))) -#define DT_QEZ(u) (DT_QREZ (u) || DT_QFEZ (u)) - -/* Status register A */ - -#define DTA_V_UNIT 9 /* unit select */ -#define DTA_M_UNIT 07 -#define DTA_UNIT (DTA_M_UNIT << DTA_V_UNIT) -#define DTA_V_MOT 7 /* motion */ -#define DTA_M_MOT 03 -#define DTA_V_MODE 6 /* mode */ -#define DTA_V_FNC 3 /* function */ -#define DTA_M_FNC 07 -#define FNC_MOVE 00 /* move */ -#define FNC_SRCH 01 /* search */ -#define FNC_READ 02 /* read */ -#define FNC_RALL 03 /* read all */ -#define FNC_WRIT 04 /* write */ -#define FNC_WALL 05 /* write all */ -#define FNC_WMRK 06 /* write timing */ -#define DTA_V_ENB 2 /* int enable */ -#define DTA_V_CERF 1 /* clr error flag */ -#define DTA_V_CDTF 0 /* clr DECtape flag */ -#define DTA_FWDRV (1u << (DTA_V_MOT + 1)) -#define DTA_STSTP (1u << DTA_V_MOT) -#define DTA_MODE (1u << DTA_V_MODE) -#define DTA_ENB (1u << DTA_V_ENB) -#define DTA_CERF (1u << DTA_V_CERF) -#define DTA_CDTF (1u << DTA_V_CDTF) -#define DTA_RW (07777 & ~(DTA_CERF | DTA_CDTF)) - -#define DTA_GETUNIT(x) (((x) >> DTA_V_UNIT) & DTA_M_UNIT) -#define DTA_GETMOT(x) (((x) >> DTA_V_MOT) & DTA_M_MOT) -#define DTA_GETFNC(x) (((x) >> DTA_V_FNC) & DTA_M_FNC) - -/* Status register B */ - -#define DTB_V_ERF 11 /* error flag */ -#define DTB_V_MRK 10 /* mark trk err */ -#define DTB_V_END 9 /* end zone err */ -#define DTB_V_SEL 8 /* select err */ -#define DTB_V_PAR 7 /* parity err */ -#define DTB_V_TIM 6 /* timing err */ -#define DTB_V_MEX 3 /* memory extension */ -#define DTB_M_MEX 07 -#define DTB_MEX (DTB_M_MEX << DTB_V_MEX) -#define DTB_V_DTF 0 /* DECtape flag */ -#define DTB_ERF (1u << DTB_V_ERF) -#define DTB_MRK (1u << DTB_V_MRK) -#define DTB_END (1u << DTB_V_END) -#define DTB_SEL (1u << DTB_V_SEL) -#define DTB_PAR (1u << DTB_V_PAR) -#define DTB_TIM (1u << DTB_V_TIM) -#define DTB_DTF (1u << DTB_V_DTF) -#define DTB_ALLERR (DTB_ERF | DTB_MRK | DTB_END | DTB_SEL | \ - DTB_PAR | DTB_TIM) -#define DTB_GETMEX(x) (((x) & DTB_MEX) << (12 - DTB_V_MEX)) - -/* DECtape state */ - -#define DTS_V_MOT 3 /* motion */ -#define DTS_M_MOT 07 -#define DTS_STOP 0 /* stopped */ -#define DTS_DECF 2 /* decel, fwd */ -#define DTS_DECR 3 /* decel, rev */ -#define DTS_ACCF 4 /* accel, fwd */ -#define DTS_ACCR 5 /* accel, rev */ -#define DTS_ATSF 6 /* @speed, fwd */ -#define DTS_ATSR 7 /* @speed, rev */ -#define DTS_DIR 01 /* dir mask */ -#define DTS_V_FNC 0 /* function */ -#define DTS_M_FNC 07 -#define DTS_OFR 7 /* "off reel" */ -#define DTS_GETMOT(x) (((x) >> DTS_V_MOT) & DTS_M_MOT) -#define DTS_GETFNC(x) (((x) >> DTS_V_FNC) & DTS_M_FNC) -#define DTS_V_2ND 6 /* next state */ -#define DTS_V_3RD (DTS_V_2ND + DTS_V_2ND) /* next next */ -#define DTS_STA(y,z) (((y) << DTS_V_MOT) | ((z) << DTS_V_FNC)) -#define DTS_SETSTA(y,z) uptr->STATE = DTS_STA (y, z) -#define DTS_SET2ND(y,z) uptr->STATE = (uptr->STATE & 077) | \ - ((DTS_STA (y, z)) << DTS_V_2ND) -#define DTS_SET3RD(y,z) uptr->STATE = (uptr->STATE & 07777) | \ - ((DTS_STA (y, z)) << DTS_V_3RD) -#define DTS_NXTSTA(x) (x >> DTS_V_2ND) - -/* Operation substates */ - -#define DTO_WCO 1 /* wc overflow */ -#define DTO_SOB 2 /* start of block */ - -/* Logging */ - -#define LOG_MS 001 /* move, search */ -#define LOG_RW 002 /* read, write */ -#define LOG_RA 004 /* read all */ -#define LOG_BL 010 /* block # lblk */ - -#define DT_UPDINT if ((dtsa & DTA_ENB) && (dtsb & (DTB_ERF | DTB_DTF))) \ - int_req = int_req | INT_DTA; \ - else int_req = int_req & ~INT_DTA; -#define ABS(x) (((x) < 0)? (-(x)): (x)) - -extern uint16 M[]; -extern int32 int_req; -extern UNIT cpu_unit; -extern int32 sim_switches; - -int32 dtsa = 0; /* status A */ -int32 dtsb = 0; /* status B */ -int32 dt_ltime = 12; /* interline time */ -int32 dt_actime = 54000; /* accel time */ -int32 dt_dctime = 72000; /* decel time */ -int32 dt_substate = 0; -int32 dt_log = 0; /* debug */ -int32 dt_logblk = 0; - -DEVICE dt_dev; -int32 dt76 (int32 IR, int32 AC); -int32 dt77 (int32 IR, int32 AC); -t_stat dt_svc (UNIT *uptr); -t_stat dt_reset (DEVICE *dptr); -t_stat dt_attach (UNIT *uptr, char *cptr); -t_stat dt_detach (UNIT *uptr); -t_stat dt_boot (int32 unitno, DEVICE *dptr); -void dt_deselect (int32 oldf); -void dt_newsa (int32 newf); -void dt_newfnc (UNIT *uptr, int32 newsta); -t_bool dt_setpos (UNIT *uptr); -void dt_schedez (UNIT *uptr, int32 dir); -void dt_seterr (UNIT *uptr, int32 e); -int32 dt_comobv (int32 val); -int32 dt_csum (UNIT *uptr, int32 blk); -int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos, int32 dir); -extern int32 sim_is_running; - -/* DT data structures - - dt_dev DT device descriptor - dt_unit DT unit list - dt_reg DT register list - dt_mod DT modifier list -*/ - -DIB dt_dib = { DEV_DTA, 2, { &dt76, &dt77 } }; - -UNIT dt_unit[] = { - { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) } }; - -REG dt_reg[] = { - { ORDATA (DTSA, dtsa, 12) }, - { ORDATA (DTSB, dtsb, 12) }, - { FLDATA (INT, int_req, INT_V_DTA) }, - { FLDATA (ENB, dtsa, DTA_V_ENB) }, - { FLDATA (DTF, dtsb, DTB_V_DTF) }, - { FLDATA (ERF, dtsb, DTB_V_ERF) }, - { ORDATA (WC, M[DT_WC], 18) }, - { ORDATA (CA, M[DT_CA], 18) }, - { DRDATA (LTIME, dt_ltime, 31), REG_NZ }, - { DRDATA (ACTIME, dt_actime, 31), REG_NZ }, - { DRDATA (DCTIME, dt_dctime, 31), REG_NZ }, - { ORDATA (SUBSTATE, dt_substate, 2) }, - { ORDATA (LOG, dt_log, 4), REG_HIDDEN }, - { DRDATA (LBLK, dt_logblk, 12), REG_HIDDEN }, - { URDATA (POS, dt_unit[0].pos, 10, T_ADDR_W, 0, - DT_NUMDR, PV_LEFT | REG_RO) }, - { URDATA (STATT, dt_unit[0].STATE, 8, 18, 0, - DT_NUMDR, REG_RO) }, - { URDATA (LASTT, dt_unit[0].LASTT, 10, 32, 0, - DT_NUMDR, REG_HRO) }, - { ORDATA (DEVNUM, dt_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB dt_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { UNIT_8FMT + UNIT_11FMT, 0, "18b", NULL, NULL }, - { UNIT_8FMT + UNIT_11FMT, UNIT_8FMT, "12b", NULL, NULL }, - { UNIT_8FMT + UNIT_11FMT, UNIT_11FMT, "16b", NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE dt_dev = { - "DT", dt_unit, dt_reg, dt_mod, - DT_NUMDR, 8, 24, 1, 8, 12, - NULL, NULL, &dt_reset, - &dt_boot, &dt_attach, &dt_detach, - &dt_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 dt76 (int32 IR, int32 AC) -{ -int32 pulse = IR & 07; -int32 old_dtsa = dtsa, fnc; -UNIT *uptr; - -if (pulse & 01) AC = AC | dtsa; /* DTRA */ -if (pulse & 06) { /* select */ - if (pulse & 02) dtsa = 0; /* DTCA */ - if (pulse & 04) { /* DTXA */ - if ((AC & DTA_CERF) == 0) dtsb = dtsb & ~DTB_ALLERR; - if ((AC & DTA_CDTF) == 0) dtsb = dtsb & ~DTB_DTF; - dtsa = dtsa ^ (AC & DTA_RW); - AC = 0; } /* clr AC */ - if ((old_dtsa ^ dtsa) & DTA_UNIT) dt_deselect (old_dtsa); - uptr = dt_dev.units + DTA_GETUNIT (dtsa); /* get unit */ - fnc = DTA_GETFNC (dtsa); /* get fnc */ - if (((uptr->flags) & UNIT_DIS) || /* disabled? */ - (fnc >= FNC_WMRK) || /* write mark? */ - ((fnc == FNC_WALL) && (uptr->flags & UNIT_WPRT)) || - ((fnc == FNC_WRIT) && (uptr->flags & UNIT_WPRT))) - dt_seterr (uptr, DTB_SEL); /* select err */ - else dt_newsa (dtsa); - DT_UPDINT; } -return AC; -} - -int32 dt77 (int32 IR, int32 AC) -{ -int32 pulse = IR & 07; - -if ((pulse & 01) && (dtsb & (DTB_ERF |DTB_DTF))) /* DTSF */ - AC = IOT_SKP | AC; -if (pulse & 02) AC = AC | dtsb; /* DTRB */ -if (pulse & 04) { /* DTLB */ - dtsb = (dtsb & ~DTB_MEX) | (AC & DTB_MEX); - AC = AC & ~07777; } /* clear AC */ -return AC; -} - -/* Unit deselect */ - -void dt_deselect (int32 oldf) -{ -int32 old_unit = DTA_GETUNIT (oldf); -UNIT *uptr = dt_dev.units + old_unit; -int32 old_mot = DTS_GETMOT (uptr->STATE); - -if (old_mot >= DTS_ATSF) /* at speed? */ - dt_newfnc (uptr, DTS_STA (old_mot, DTS_OFR)); -else if (old_mot >= DTS_ACCF) /* accelerating? */ - DTS_SET2ND (DTS_ATSF | (old_mot & DTS_DIR), DTS_OFR); -return; } - -/* Command register change - - 1. If change in motion, stop to start - - schedule acceleration - - set function as next state - 2. If change in motion, start to stop - - if not already decelerating (could be reversing), - schedule deceleration - 3. If change in direction, - - if not decelerating, schedule deceleration - - set accelerating (other dir) as next state - - set function as next next state - 4. If not accelerating or at speed, - - schedule acceleration - - set function as next state - 5. If not yet at speed, - - set function as next state - 6. If at speed, - - set function as current state, schedule function -*/ - -void dt_newsa (int32 newf) -{ -int32 new_unit, prev_mot, new_fnc; -int32 prev_mving, new_mving, prev_dir, new_dir; -UNIT *uptr; - -new_unit = DTA_GETUNIT (newf); /* new, old units */ -uptr = dt_dev.units + new_unit; -if ((uptr->flags & UNIT_ATT) == 0) { /* new unit attached? */ - dt_seterr (uptr, DTB_SEL); /* no, error */ - return; } -prev_mot = DTS_GETMOT (uptr->STATE); /* previous motion */ -prev_mving = prev_mot != DTS_STOP; /* previous moving? */ -prev_dir = prev_mot & DTS_DIR; /* previous dir? */ -new_mving = (newf & DTA_STSTP) != 0; /* new moving? */ -new_dir = (newf & DTA_FWDRV) != 0; /* new dir? */ -new_fnc = DTA_GETFNC (newf); /* new function? */ - -if ((prev_mving | new_mving) == 0) return; /* stop to stop */ - -if (new_mving & ~prev_mving) { /* start? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_actime); /* schedule accel */ - DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } - -if (prev_mving & ~new_mving) { /* stop? */ - if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_dctime); } /* schedule decel */ - DTS_SETSTA (DTS_DECF | prev_dir, 0); /* state = decel */ - return; } - -if (prev_dir ^ new_dir) { /* dir chg? */ - if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_dctime); } /* schedule decel */ - DTS_SETSTA (DTS_DECF | prev_dir, 0); /* state = decel */ - DTS_SET2ND (DTS_ACCF | new_dir, 0); /* next = accel */ - DTS_SET3RD (DTS_ATSF | new_dir, new_fnc); /* next next = fnc */ - return; } - -if (prev_mot < DTS_ACCF) { /* not accel/at speed? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* cancel cur */ - sim_activate (uptr, dt_actime); /* schedule accel */ - DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } - -if (prev_mot < DTS_ATSF) { /* not at speed? */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } - -dt_newfnc (uptr, DTS_STA (DTS_ATSF | new_dir, new_fnc));/* state = fnc */ -return; -} - -/* Schedule new DECtape function - - This routine is only called if - - the selected unit is attached - - the selected unit is at speed (forward or backward) - - This routine - - updates the selected unit's position - - updates the selected unit's state - - schedules the new operation -*/ - -void dt_newfnc (UNIT *uptr, int32 newsta) -{ -int32 fnc, dir, blk, unum, relpos, newpos; -uint32 oldpos; - -oldpos = uptr->pos; /* save old pos */ -if (dt_setpos (uptr)) return; /* update pos */ -uptr->STATE = newsta; /* update state */ -fnc = DTS_GETFNC (uptr->STATE); /* set variables */ -dir = DTS_GETMOT (uptr->STATE) & DTS_DIR; -unum = uptr - dt_dev.units; -if (oldpos == uptr->pos) /* bump pos */ - uptr->pos = uptr->pos + (dir? -1: 1); -blk = DT_LIN2BL (uptr->pos, uptr); - -if (dir? DT_QREZ (uptr): DT_QFEZ (uptr)) { /* wrong ez? */ - dt_seterr (uptr, DTB_END); /* set ez flag, stop */ - return; } -sim_cancel (uptr); /* cancel cur op */ -dt_substate = DTO_SOB; /* substate = block start */ -switch (fnc) { /* case function */ -case DTS_OFR: /* off reel */ - if (dir) newpos = -1000; /* rev? < start */ - else newpos = DTU_FWDEZ (uptr) + DT_EZLIN + 1000; /* fwd? > end */ - break; -case FNC_MOVE: /* move */ - dt_schedez (uptr, dir); /* sched end zone */ - if (dt_log & LOG_MS) printf ("[DT%d: moving %s]\n", unum, (dir? - "backward": "forward")); - return; /* done */ -case FNC_SRCH: /* search */ - if (dir) newpos = DT_BLK2LN ((DT_QFEZ (uptr)? - DTU_TSIZE (uptr): blk), uptr) - DT_BLKLN - DT_WSIZE; - else newpos = DT_BLK2LN ((DT_QREZ (uptr)? - 0: blk + 1), uptr) + DT_BLKLN + (DT_WSIZE - 1); - if (dt_log & LOG_MS) printf ("[DT%d: searching %s]\n", unum, - (dir? "backward": "forward")); - break; -case FNC_WRIT: /* write */ -case FNC_READ: /* read */ -case FNC_RALL: /* read all */ -case FNC_WALL: /* write all */ - if (DT_QEZ (uptr)) { /* in "ok" end zone? */ - if (dir) newpos = DTU_FWDEZ (uptr) - DT_HTLIN - DT_WSIZE; - else newpos = DT_EZLIN + DT_HTLIN + (DT_WSIZE - 1); - break; } - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - dt_seterr (uptr, DTB_SEL); - return; } - if (dir) newpos = DT_BLK2LN (((relpos >= (DTU_LPERB (uptr) - DT_HTLIN))? - blk + 1: blk), uptr) - DT_HTLIN - DT_WSIZE; - else newpos = DT_BLK2LN (((relpos < DT_HTLIN)? - blk: blk + 1), uptr) + DT_HTLIN + (DT_WSIZE - 1); - break; -default: - dt_seterr (uptr, DTB_SEL); /* bad state */ - return; } -sim_activate (uptr, ABS (newpos - ((int32) uptr->pos)) * dt_ltime); -return; -} - -/* Update DECtape position - - DECtape motion is modeled as a constant velocity, with linear - acceleration and deceleration. The motion equations are as follows: - - t = time since operation started - tmax = time for operation (accel, decel only) - v = at speed velocity in lines (= 1/dt_ltime) - - Then: - at speed dist = t * v - accel dist = (t^2 * v) / (2 * tmax) - decel dist = (((2 * t * tmax) - t^2) * v) / (2 * tmax) - - This routine uses the relative (integer) time, rather than the absolute - (floating point) time, to allow save and restore of the start times. -*/ - -t_bool dt_setpos (UNIT *uptr) -{ -uint32 new_time, ut, ulin, udelt; -int32 mot = DTS_GETMOT (uptr->STATE); -int32 unum, delta; - -new_time = sim_grtime (); /* current time */ -ut = new_time - uptr->LASTT; /* elapsed time */ -if (ut == 0) return FALSE; /* no time gone? exit */ -uptr->LASTT = new_time; /* update last time */ -switch (mot & ~DTS_DIR) { /* case on motion */ -case DTS_STOP: /* stop */ - delta = 0; - break; -case DTS_DECF: /* slowing */ - ulin = ut / (uint32) dt_ltime; udelt = dt_dctime / dt_ltime; - delta = ((ulin * udelt * 2) - (ulin * ulin)) / (2 * udelt); - break; -case DTS_ACCF: /* accelerating */ - ulin = ut / (uint32) dt_ltime; udelt = dt_actime / dt_ltime; - delta = (ulin * ulin) / (2 * udelt); - break; -case DTS_ATSF: /* at speed */ - delta = ut / (uint32) dt_ltime; - break; } -if (mot & DTS_DIR) uptr->pos = uptr->pos - delta; /* update pos */ -else uptr->pos = uptr->pos + delta; -if (((int32) uptr->pos < 0) || - ((int32) uptr->pos > (DTU_FWDEZ (uptr) + DT_EZLIN))) { - detach_unit (uptr); /* off reel? */ - uptr->STATE = uptr->pos = 0; - unum = uptr - dt_dev.units; - if (unum == DTA_GETUNIT (dtsa)) /* if selected, */ - dt_seterr (uptr, DTB_SEL); /* error */ - return TRUE; } -return FALSE; -} - -/* Unit service - - Unit must be attached, detach cancels operation -*/ - -t_stat dt_svc (UNIT *uptr) -{ -int32 mot = DTS_GETMOT (uptr->STATE); -int32 dir = mot & DTS_DIR; -int32 fnc = DTS_GETFNC (uptr->STATE); -int16 *bptr = uptr->filebuf; -int32 unum = uptr - dt_dev.units; -int32 blk, wrd, ma, relpos, dat; -uint32 ba; - -/* Motion cases - - Decelerating - if next state != stopped, must be accel reverse - Accelerating - next state must be @speed, schedule function - At speed - do functional processing -*/ - -switch (mot) { -case DTS_DECF: case DTS_DECR: /* decelerating */ - if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ - uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ - if (uptr->STATE) /* not stopped? */ - sim_activate (uptr, dt_actime); /* must be reversing */ - return SCPE_OK; -case DTS_ACCF: case DTS_ACCR: /* accelerating */ - dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */ - return SCPE_OK; -case DTS_ATSF: case DTS_ATSR: /* at speed */ - break; /* check function */ -default: /* other */ - dt_seterr (uptr, DTB_SEL); /* state error */ - return SCPE_OK; } - -/* Functional cases - - Move - must be at end zone - Search - transfer block number, schedule next block - Off reel - detach unit (it must be deselected) -*/ - -if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ -if (DT_QEZ (uptr)) { /* in end zone? */ - dt_seterr (uptr, DTB_END); /* end zone error */ - return SCPE_OK; } -blk = DT_LIN2BL (uptr->pos, uptr); /* get block # */ -switch (fnc) { /* at speed, check fnc */ -case FNC_MOVE: /* move */ - dt_seterr (uptr, DTB_END); /* end zone error */ - return SCPE_OK; -case FNC_SRCH: /* search */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - sim_activate (uptr, DTU_LPERB (uptr) * dt_ltime);/* sched next block */ - M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr word cnt */ - ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ - if (MEM_ADDR_OK (ma)) M[ma] = blk & 07777; /* store block # */ - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; /* set DTF */ - break; -case DTS_OFR: /* off reel */ - detach_unit (uptr); /* must be deselected */ - uptr->STATE = uptr->pos = 0; /* no visible action */ - break; - -/* Read has four subcases - - Start of block, not wc ovf - check that DTF is clear, otherwise normal - Normal - increment MA, WC, copy word from tape to memory - if read dir != write dir, bits must be scrambled - if wc overflow, next state is wc overflow - if end of block, possibly set DTF, next state is start of block - Wc ovf, not start of block - - if end of block, possibly set DTF, next state is start of block - Wc ovf, start of block - if end of block reached, timing error, - otherwise, continue to next word -*/ - -case FNC_READ: /* read */ - wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */ - switch (dt_substate) { /* case on substate */ - case DTO_SOB: /* start of block */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - if ((dt_log & LOG_RW) || ((dt_log & LOG_BL) && (blk == dt_logblk))) - printf ("[DT%d: reading block %d %s%s\n", - unum, blk, (dir? "backward": "forward"), - ((dtsa & DTA_MODE)? " continuous]": "]")); - dt_substate = 0; /* fall through */ - case 0: /* normal read */ - M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr WC, CA */ - M[DT_CA] = (M[DT_CA] + 1) & 07777; - ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ - ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - dat = bptr[ba]; /* get tape word */ - if (dir) dat = dt_comobv (dat); /* rev? comp obv */ - if (MEM_ADDR_OK (ma)) M[ma] = dat; /* mem addr legal? */ - if (M[DT_WC] == 0) dt_substate = DTO_WCO; /* wc ovf? */ - case DTO_WCO: /* wc ovf, not sob */ - if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not last? */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - else { - dt_substate = dt_substate | DTO_SOB; - sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; } /* set DTF */ - break; - case DTO_WCO | DTO_SOB: /* next block */ - if (wrd == (dir? 0: DTU_BSIZE (uptr))) /* end of block? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - else sim_activate (uptr, DT_WSIZE * dt_ltime); - break; } - break; - -/* Write has four subcases - - Start of block, not wc ovf - check that DTF is clear, set block direction - Normal - increment MA, WC, copy word from memory to tape - if wc overflow, next state is wc overflow - if end of block, possibly set DTF, next state is start of block - Wc ovf, not start of block - - copy 0 to tape - if end of block, possibly set DTF, next state is start of block - Wc ovf, start of block - schedule end zone -*/ - -case FNC_WRIT: /* write */ - wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */ - switch (dt_substate) { /* case on substate */ - case DTO_SOB: /* start block */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - if ((dt_log & LOG_RW) || ((dt_log & LOG_BL) && (blk == dt_logblk))) - printf ("[DT%d: writing block %d %s%s\n", unum, blk, - (dir? "backward": "forward"), - ((dtsa & DTA_MODE)? " continuous]": "]")); - dt_substate = 0; /* fall through */ - case 0: /* normal write */ - M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr WC, CA */ - M[DT_CA] = (M[DT_CA] + 1) & 07777; - case DTO_WCO: /* wc ovflo */ - ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ - ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - dat = dt_substate? 0: M[ma]; /* get word */ - if (dir) dat = dt_comobv (dat); /* rev? comp obv */ - bptr[ba] = dat; /* write word */ - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; - if (M[DT_WC] == 0) dt_substate = DTO_WCO; - if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not last? */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - else { - dt_substate = dt_substate | DTO_SOB; - sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; } /* set DTF */ - break; - case DTO_WCO | DTO_SOB: /* all done */ - dt_schedez (uptr, dir); /* sched end zone */ - break; } - break; - -/* Read all has two subcases - - Not word count overflow - increment MA, WC, copy word from tape to memory - Word count overflow - schedule end zone -*/ - -case FNC_RALL: - switch (dt_substate) { /* case on substate */ - case 0: case DTO_SOB: /* read in progress */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr WC, CA */ - M[DT_CA] = (M[DT_CA] + 1) & 07777; - ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - dat = bptr[ba]; /* get tape word */ - if (dir) dat = dt_comobv (dat); } /* rev? comp obv */ - else dat = dt_gethdr (uptr, blk, relpos, dir); /* get hdr */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - if (MEM_ADDR_OK (ma)) M[ma] = dat; /* mem addr legal? */ - if (M[DT_WC] == 0) dt_substate = DTO_WCO; - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; /* set DTF */ - break; - case DTO_WCO: case DTO_WCO | DTO_SOB: /* all done */ - dt_schedez (uptr, dir); /* sched end zone */ - break; } /* end case substate */ - break; - -/* Write all has two subcases - - Not word count overflow - increment MA, WC, copy word from memory to tape - Word count overflow - schedule end zone -*/ - -case FNC_WALL: - switch (dt_substate) { /* case on substate */ - case 0: case DTO_SOB: /* read in progress */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr WC, CA */ - M[DT_CA] = (M[DT_CA] + 1) & 07777; - ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - dat = M[ma]; /* get mem word */ - if (dir) dat = dt_comobv (dat); - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - bptr[ba] = dat; /* write word */ - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; } -/* /* ignore hdr */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - if (M[DT_WC] == 0) dt_substate = DTO_WCO; - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; /* set DTF */ - break; - case DTO_WCO: case DTO_WCO | DTO_SOB: /* all done */ - dt_schedez (uptr, dir); /* sched end zone */ - break; } /* end case substate */ - break; -default: - dt_seterr (uptr, DTB_SEL); /* impossible state */ - break; } -DT_UPDINT; /* update interrupts */ -return SCPE_OK; -} - -/* Reading the header is complicated, because 18b words are being parsed - out 12b at a time. The sequence of word numbers is directionally - sensitive - - Forward Reverse - Word Word Content Word Word Content - (abs) (rel) (abs) (rel) - - 137 8 rev csm'00 6 6 fwd csm'00 - 138 9 0000 5 5 0000 - 139 10 0000 4 4 0000 - 140 11 0000 3 3 0000 - 141 12 00'lo rev blk 2 2 00'lo fwd blk - 142 13 hi rev blk 1 1 hi fwd blk - 143 14 0000 0 0 0000 - 0 0 0000 143 14 0000 - 1 1 0000 142 13 0000 - 2 2 hi fwd blk 141 12 hi rev blk - 3 3 lo fwd blk'00 140 11 lo rev blk'00 - 4 4 0000 139 10 0000 - 5 5 0000 138 9 0000 - 6 6 0000 137 8 0000 - 7 7 00'fwd csm 136 7 00'rev csm -*/ - -int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos, int32 dir) -{ -if (relpos >= DT_HTLIN) relpos = relpos - (DT_WSIZE * DTU_BSIZE (uptr)); -if (dir) { /* reverse */ - switch (relpos / DT_WSIZE) { - case 6: /* fwd csum */ - return (dt_comobv (dt_csum (uptr, blk))); - case 2: /* lo fwd blk */ - return dt_comobv ((blk & 077) << 6); - case 1: /* hi fwd blk */ - return dt_comobv (blk >> 6); - case 12: /* hi rev blk */ - return (blk >> 6) & 07777; - case 11: /* lo rev blk */ - return ((blk & 077) << 6); - default: /* others */ - return 077; } } -else { /* forward */ - switch (relpos / DT_WSIZE) { - case 8: /* rev csum */ - return (dt_csum (uptr, blk) << 6); - case 12: /* lo rev blk */ - return dt_comobv ((blk & 077) << 6); - case 13: /* hi rev blk */ - return dt_comobv (blk >> 6); - case 2: /* hi fwd blk */ - return ((blk >> 6) & 07777); - case 3: /* lo fwd blk */ - return ((blk & 077) << 6); - default: /* others */ - break; } } -return 0; -} - -/* Utility routines */ - -/* Set error flag */ - -void dt_seterr (UNIT *uptr, int32 e) -{ -int32 mot = DTS_GETMOT (uptr->STATE); - -dtsa = dtsa & ~DTA_STSTP; /* clear go */ -dtsb = dtsb | DTB_ERF | e; /* set error flag */ -if (mot >= DTS_ACCF) { /* ~stopped or stopping? */ - sim_cancel (uptr); /* cancel activity */ - if (dt_setpos (uptr)) return; /* update position */ - sim_activate (uptr, dt_dctime); /* sched decel */ - DTS_SETSTA (DTS_DECF | (mot & DTS_DIR), 0); } /* state = decel */ -DT_UPDINT; -return; -} - -/* Schedule end zone */ - -void dt_schedez (UNIT *uptr, int32 dir) -{ -int32 newpos; - -if (dir) newpos = DT_EZLIN - DT_WSIZE; /* rev? rev ez */ -else newpos = DTU_FWDEZ (uptr) + DT_WSIZE; /* fwd? fwd ez */ -sim_activate (uptr, ABS (newpos - ((int32) uptr->pos)) * dt_ltime); -return; -} - -/* Complement obverse routine */ - -int32 dt_comobv (int32 dat) -{ -dat = dat ^ 07777; /* compl obverse */ -dat = ((dat >> 9) & 07) | ((dat >> 3) & 070) | - ((dat & 070) << 3) | ((dat & 07) << 9); -return dat; -} - -/* Checksum routine */ - -int32 dt_csum (UNIT *uptr, int32 blk) -{ -int16 *bptr = uptr->filebuf; -int32 ba = blk * DTU_BSIZE (uptr); -int32 i, csum, wrd; - -csum = 077; /* init csum */ -for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ - wrd = bptr[ba + i] ^ 07777; /* get ~word */ - csum = csum ^ (wrd >> 6) ^ wrd; } -return (csum & 077); -} - -/* Reset routine */ - -t_stat dt_reset (DEVICE *dptr) -{ -int32 i, prev_mot; -UNIT *uptr; - -for (i = 0; i < DT_NUMDR; i++) { /* stop all activity */ - uptr = dt_dev.units + i; - if (sim_is_running) { /* CAF? */ - prev_mot = DTS_GETMOT (uptr->STATE); /* get motion */ - if ((prev_mot & ~DTS_DIR) > DTS_DECF) { /* accel or spd? */ - if (dt_setpos (uptr)) continue; /* update pos */ - sim_cancel (uptr); - sim_activate (uptr, dt_dctime); /* sched decel */ - DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); - } } - else { - sim_cancel (uptr); /* sim reset */ - uptr->STATE = 0; - uptr->LASTT = sim_grtime (); } } -dtsa = dtsb = 0; /* clear status */ -DT_UPDINT; /* reset interrupt */ -return SCPE_OK; -} - -/* Bootstrap routine - - This is actually the 4K disk monitor bootstrap, which also - works with OS/8. The reverse is not true - the OS/8 bootstrap - doesn't work with the disk monitor. -*/ - -#define BOOT_START 0200 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 07600, /* 200, CLA CLL */ - 01216, /* TAD MVB ; move back */ - 04210, /* JMS DO ; action */ - 01217, /* TAD K7577 ; addr */ - 03620, /* DCA I CA */ - 01222, /* TAD RDF ; read fwd */ - 04210, /* JMS DO ; action */ - 05600, /* JMP I 200 ; enter boot */ - 00000, /* DO, 0 */ - 06766, /* DTCA!DTXA ; start tape */ - 03621, /* DCA I WC ; clear wc */ - 06771, /* DTSF ; wait */ - 05213, /* JMP .-1 */ - 05610, /* JMP I DO */ - 00600, /* MVB, 0600 */ - 07577, /* K7577, 7757 */ - 07755, /* CA, 7755 */ - 07754, /* WC, 7754 */ - 00220 /* RF, 0220 */ -}; - -t_stat dt_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -if (unitno) return SCPE_ARG; /* only unit 0 */ -if (dt_dib.dev != DEV_DTA) return STOP_NOTSTD; /* only std devno */ -dt_unit[unitno].pos = DT_EZLIN; -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} - -/* Attach routine - - Determine 12b, 16b, or 18b/36b format - Allocate buffer - If 16b or 18b, read 16b or 18b format and convert to 12b in buffer - If 12b, read data into buffer -*/ - -t_stat dt_attach (UNIT *uptr, char *cptr) -{ -uint32 pdp18b[D18_NBSIZE]; -uint16 pdp11b[D18_NBSIZE], *bptr; -int32 i, k; -int32 u = uptr - dt_dev.units; -t_stat r; -uint32 ba, sz; - -r = attach_unit (uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* fail? */ -if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */ - uptr->flags = (uptr->flags | UNIT_8FMT) & ~UNIT_11FMT; - if (sim_switches & SWMASK ('T')) /* att 18b? */ - uptr->flags = uptr->flags & ~UNIT_8FMT; - else if (sim_switches & SWMASK ('S')) /* att 16b? */ - uptr->flags = (uptr->flags | UNIT_11FMT) & ~UNIT_8FMT; - else if (!(sim_switches & SWMASK ('R')) && /* autosize? */ - (sz = sim_fsize (cptr))) { - if (sz == D11_FILSIZ) - uptr->flags = (uptr->flags | UNIT_11FMT) & ~UNIT_8FMT; - else if (sz > D8_FILSIZ) - uptr->flags = uptr->flags & ~UNIT_8FMT; } } -uptr->capac = DTU_CAPAC (uptr); /* set capacity */ -uptr->filebuf = calloc (uptr->capac, sizeof (int16)); -if (uptr->filebuf == NULL) { /* can't alloc? */ - detach_unit (uptr); - return SCPE_MEM; } -bptr = uptr->filebuf; /* file buffer */ -printf ("%s%d: ", sim_dname (&dt_dev), u); -if (uptr->flags & UNIT_8FMT) printf ("12b format"); -else if (uptr->flags & UNIT_11FMT) printf ("16b format"); -else printf ("18b/36b format"); -printf (", buffering file in memory\n"); -if (uptr->flags & UNIT_8FMT) /* 12b? */ - uptr->hwmark = fxread (uptr->filebuf, sizeof (int16), - uptr->capac, uptr->fileref); -else { /* 16b/18b */ - for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ - if (uptr->flags & UNIT_11FMT) { - k = fxread (pdp11b, sizeof (int16), D18_NBSIZE, uptr->fileref); - for (i = 0; i < k; i++) pdp18b[i] = pdp11b[i]; } - else k = fxread (pdp18b, sizeof (int32), D18_NBSIZE, uptr->fileref); - if (k == 0) break; - for ( ; k < D18_NBSIZE; k++) pdp18b[k] = 0; - for (k = 0; k < D18_NBSIZE; k = k + 2) { /* loop thru blk */ - bptr[ba] = (pdp18b[k] >> 6) & 07777; - bptr[ba + 1] = ((pdp18b[k] & 077) << 6) | - ((pdp18b[k + 1] >> 12) & 077); - bptr[ba + 2] = pdp18b[k + 1] & 07777; - ba = ba + 3; } /* end blk loop */ - } /* end file loop */ - uptr->hwmark = ba; } /* end else */ -uptr->flags = uptr->flags | UNIT_BUF; /* set buf flag */ -uptr->pos = DT_EZLIN; /* beyond leader */ -uptr->LASTT = sim_grtime (); /* last pos update */ -return SCPE_OK; -} - -/* Detach routine - - Cancel in progress operation - If 12b, write buffer to file - If 16b or 18b, convert 12b buffer to 16b or 18b and write to file - Deallocate buffer -*/ - -t_stat dt_detach (UNIT* uptr) -{ -uint32 pdp18b[D18_NBSIZE]; -uint16 pdp11b[D18_NBSIZE], *bptr; -int32 i, k; -int32 u = uptr - dt_dev.units; -uint32 ba; - -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; -if (sim_is_active (uptr)) { - sim_cancel (uptr); - if ((u == DTA_GETUNIT (dtsa)) && (dtsa & DTA_STSTP)) { - dtsb = dtsb | DTB_ERF | DTB_SEL | DTB_DTF; - DT_UPDINT; } - uptr->STATE = uptr->pos = 0; } -bptr = uptr->filebuf; /* file buffer */ -if (uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */ - printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u); - rewind (uptr->fileref); /* start of file */ - if (uptr->flags & UNIT_8FMT) /* PDP8? */ - fxwrite (uptr->filebuf, sizeof (int16), /* write file */ - uptr->hwmark, uptr->fileref); - else { /* 16b/18b */ - for (ba = 0; ba < uptr->hwmark; ) { /* loop thru buf */ - for (k = 0; k < D18_NBSIZE; k = k + 2) { - pdp18b[k] = ((uint32) (bptr[ba] & 07777) << 6) | - ((uint32) (bptr[ba + 1] >> 6) & 077); - pdp18b[k + 1] = ((uint32) (bptr[ba + 1] & 077) << 12) | - ((uint32) (bptr[ba + 2] & 07777)); - ba = ba + 3; } /* end loop blk */ - if (uptr->flags & UNIT_11FMT) { /* 16b? */ - for (i = 0; i < D18_NBSIZE; i++) pdp11b[i] = pdp18b[i]; - fxwrite (pdp11b, sizeof (int16), - D18_NBSIZE, uptr->fileref); } - else fxwrite (pdp18b, sizeof (int32), - D18_NBSIZE, uptr->fileref); - } /* end loop buf */ - } /* end else */ - if (ferror (uptr->fileref)) perror ("I/O error"); - } /* end if hwmark */ -free (uptr->filebuf); /* release buf */ -uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */ -uptr->filebuf = NULL; /* clear buf ptr */ -uptr->flags = (uptr->flags | UNIT_8FMT) & ~UNIT_11FMT; /* default fmt */ -uptr->capac = DT_CAPAC; /* default size */ -return detach_unit (uptr); -} diff --git a/PDP8/pdp8_lp.c b/PDP8/pdp8_lp.c deleted file mode 100644 index 48bda59f..00000000 --- a/PDP8/pdp8_lp.c +++ /dev/null @@ -1,165 +0,0 @@ -/* pdp8_lp.c: PDP-8 line printer simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - lpt LP8E line printer - - 25-Apr-03 RMS Revised for extended file support - 04-Oct-02 RMS Added DIB, enable/disable, device number support - 30-May-02 RMS Widened POS to 32b -*/ - -#include "pdp8_defs.h" - -extern int32 int_req, int_enable, dev_done, stop_inst; - -int32 lpt_err = 0; /* error flag */ -int32 lpt_stopioe = 0; /* stop on error */ - -DEVICE lpt_dev; -int32 lpt (int32 IR, int32 AC); -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); -t_stat lpt_attach (UNIT *uptr, char *cptr); -t_stat lpt_detach (UNIT *uptr); - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list -*/ - -DIB lpt_dib = { DEV_LPT, 1, { &lpt } }; - -UNIT lpt_unit = { - UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lpt_reg[] = { - { ORDATA (BUF, lpt_unit.buf, 8) }, - { FLDATA (ERR, lpt_err, 0) }, - { FLDATA (DONE, dev_done, INT_V_LPT) }, - { FLDATA (ENABLE, int_enable, INT_V_LPT) }, - { FLDATA (INT, int_req, INT_V_LPT) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lpt_stopioe, 0) }, - { ORDATA (DEVNUM, lpt_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB lpt_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, lpt_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lpt_reset, - NULL, &lpt_attach, &lpt_detach, - &lpt_dib, DEV_DISABLE }; - -/* IOT routine */ - -int32 lpt (int32 IR, int32 AC) -{ -switch (IR & 07) { /* decode IR<9:11> */ -case 1: /* PSKF */ - return (dev_done & INT_LPT)? IOT_SKP + AC: AC; -case 2: /* PCLF */ - dev_done = dev_done & ~INT_LPT; /* clear flag */ - int_req = int_req & ~INT_LPT; /* clear int req */ - return AC; -case 3: /* PSKE */ - return (lpt_err)? IOT_SKP + AC: AC; -case 6: /* PCLF!PSTB */ - dev_done = dev_done & ~INT_LPT; /* clear flag */ - int_req = int_req & ~INT_LPT; /* clear int req */ -case 4: /* PSTB */ - lpt_unit.buf = AC & 0177; /* load buffer */ - if ((lpt_unit.buf == 015) || (lpt_unit.buf == 014) || - (lpt_unit.buf == 012)) { - sim_activate (&lpt_unit, lpt_unit.wait); - return AC; } - return (lpt_svc (&lpt_unit) << IOT_V_REASON) + AC; -case 5: /* PSIE */ - int_enable = int_enable | INT_LPT; /* set enable */ - int_req = INT_UPDATE; /* update interrupts */ - return AC; -case 7: /* PCIE */ - int_enable = int_enable & ~INT_LPT; /* clear enable */ - int_req = int_req & ~INT_LPT; /* clear int req */ - return AC; -default: - return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ -} - -/* Unit service */ - -t_stat lpt_svc (UNIT *uptr) -{ -dev_done = dev_done | INT_LPT; /* set done */ -int_req = INT_UPDATE; /* update interrupts */ -if ((lpt_unit.flags & UNIT_ATT) == 0) { - lpt_err = 1; - return IORETURN (lpt_stopioe, SCPE_UNATT); } -if (putc (lpt_unit.buf, lpt_unit.fileref) == EOF) { - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } -lpt_unit.pos = lpt_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ -lpt_unit.buf = 0; -dev_done = dev_done & ~INT_LPT; /* clear done, int */ -int_req = int_req & ~INT_LPT; -int_enable = int_enable | INT_LPT; /* set enable */ -lpt_err = (lpt_unit.flags & UNIT_ATT) == 0; -sim_cancel (&lpt_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Attach routine */ - -t_stat lpt_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); -lpt_err = (lpt_unit.flags & UNIT_ATT) == 0; -return reason; -} - -/* Detach routine */ - -t_stat lpt_detach (UNIT *uptr) -{ -lpt_err = 1; -return detach_unit (uptr); -} diff --git a/PDP8/pdp8_mt.c b/PDP8/pdp8_mt.c deleted file mode 100644 index 315105b8..00000000 --- a/PDP8/pdp8_mt.c +++ /dev/null @@ -1,582 +0,0 @@ -/* pdp8_mt.c: PDP-8 magnetic tape simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - mt TM8E/TU10 magtape - - 25-Apr-03 RMS Revised for extended file support - 29-Mar-03 RMS Added multiformat support - 04-Mar-03 RMS Fixed bug in SKTR - 01-Mar-03 RMS Fixed interrupt handling - Revised for magtape library - 30-Oct-02 RMS Revised BOT handling, added error record handling - 04-Oct-02 RMS Added DIBs, device number support - 30-Aug-02 RMS Revamped error handling - 28-Aug-02 RMS Added end of medium support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Added maximum record length test - 06-Jan-02 RMS Changed enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Changed UST, POS, FLG to arrays - 25-Apr-01 RMS Added device enable/disable support - 04-Oct-98 RMS V2.4 magtape format - 22-Jan-97 RMS V2.3 magtape format - 01-Jan-96 RMS Rewritten from TM8-E Maintenance Manual - - Magnetic tapes are represented as a series of variable records - of the form: - - 32b byte count - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32b byte count - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a byte count of 0. -*/ - -#include "pdp8_defs.h" -#include "sim_tape.h" - -#define MT_NUMDR 8 /* #drives */ -#define USTAT u3 /* unit status */ -#define MT_MAXFR (1 << 16) /* max record lnt */ -#define WC_SIZE (1 << 12) /* max word count */ -#define WC_MASK (WC_SIZE - 1) - -/* Command/unit - mt_cu */ - -#define CU_V_UNIT 9 /* unit */ -#define CU_M_UNIT 07 -#define CU_PARITY 00400 /* parity select */ -#define CU_IEE 00200 /* error int enable */ -#define CU_IED 00100 /* done int enable */ -#define CU_V_EMA 3 /* ext mem address */ -#define CU_M_EMA 07 -#define CU_EMA (CU_M_EMA << CU_V_EMA) -#define CU_DTY 00002 /* drive type */ -#define CU_UNPAK 00001 /* 6b vs 8b mode */ -#define GET_UNIT(x) (((x) >> CU_V_UNIT) & CU_M_UNIT) -#define GET_EMA(x) (((x) & CU_EMA) << (12 - CU_V_EMA)) - -/* Function - mt_fn */ - -#define FN_V_FNC 9 /* function */ -#define FN_M_FNC 07 -#define FN_UNLOAD 00 -#define FN_REWIND 01 -#define FN_READ 02 -#define FN_CMPARE 03 -#define FN_WRITE 04 -#define FN_WREOF 05 -#define FN_SPACEF 06 -#define FN_SPACER 07 -#define FN_ERASE 00400 /* erase */ -#define FN_CRC 00200 /* read CRC */ -#define FN_GO 00100 /* go */ -#define FN_INC 00040 /* incr mode */ -#define FN_RMASK 07700 /* readable bits */ -#define GET_FNC(x) (((x) >> FN_V_FNC) & FN_M_FNC) - -/* Status - stored in mt_sta or (*) uptr->USTAT */ - -#define STA_ERR (04000 << 12) /* error */ -#define STA_REW (02000 << 12) /* *rewinding */ -#define STA_BOT (01000 << 12) /* *start of tape */ -#define STA_REM (00400 << 12) /* *offline */ -#define STA_PAR (00200 << 12) /* parity error */ -#define STA_EOF (00100 << 12) /* *end of file */ -#define STA_RLE (00040 << 12) /* rec lnt error */ -#define STA_DLT (00020 << 12) /* data late */ -#define STA_EOT (00010 << 12) /* *end of tape */ -#define STA_WLK (00004 << 12) /* *write locked */ -#define STA_CPE (00002 << 12) /* compare error */ -#define STA_ILL (00001 << 12) /* illegal */ -#define STA_9TK 00040 /* 9 track */ -/* #define STA_BAD 00020 /* bad tape?? */ -#define STA_INC 00010 /* increment error */ -#define STA_LAT 00004 /* lateral par error */ -#define STA_CRC 00002 /* CRC error */ -#define STA_LON 00001 /* long par error */ - -#define STA_CLR (FN_RMASK | 00020) /* always clear */ -#define STA_DYN (STA_REW | STA_BOT | STA_REM | STA_EOF | \ - STA_EOT | STA_WLK) /* kept in USTAT */ - -extern uint16 M[]; -extern int32 int_req, stop_inst; -extern UNIT cpu_unit; - -int32 mt_cu = 0; /* command/unit */ -int32 mt_fn = 0; /* function */ -int32 mt_ca = 0; /* current address */ -int32 mt_wc = 0; /* word count */ -int32 mt_sta = 0; /* status register */ -int32 mt_db = 0; /* data buffer */ -int32 mt_done = 0; /* mag tape flag */ -int32 mt_time = 10; /* record latency */ -int32 mt_stopioe = 1; /* stop on error */ -uint8 *mtxb = NULL; /* transfer buffer */ - -DEVICE mt_dev; -int32 mt70 (int32 IR, int32 AC); -int32 mt71 (int32 IR, int32 AC); -int32 mt72 (int32 IR, int32 AC); -t_stat mt_svc (UNIT *uptr); -t_stat mt_reset (DEVICE *dptr); -t_stat mt_attach (UNIT *uptr, char *cptr); -t_stat mt_detach (UNIT *uptr); -int32 mt_updcsta (UNIT *uptr); -int32 mt_ixma (int32 xma); -t_stat mt_map_err (UNIT *uptr, t_stat st); -t_stat mt_vlock (UNIT *uptr, int32 val, char *cptr, void *desc); -UNIT *mt_busy (void); -void mt_set_done (void); - -/* MT data structures - - mt_dev MT device descriptor - mt_unit MT unit list - mt_reg MT register list - mt_mod MT modifier list -*/ - -DIB mt_dib = { DEV_MT, 3, { &mt70, &mt71, &mt72 } }; - -UNIT mt_unit[] = { - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) } }; - -REG mt_reg[] = { - { ORDATA (CMD, mt_cu, 12) }, - { ORDATA (FNC, mt_fn, 12) }, - { ORDATA (CA, mt_ca, 12) }, - { ORDATA (WC, mt_wc, 12) }, - { ORDATA (DB, mt_db, 12) }, - { GRDATA (STA, mt_sta, 8, 12, 12) }, - { ORDATA (STA2, mt_sta, 6) }, - { FLDATA (DONE, mt_done, 0) }, - { FLDATA (INT, int_req, INT_V_MT) }, - { FLDATA (STOP_IOE, mt_stopioe, 0) }, - { DRDATA (TIME, mt_time, 24), PV_LEFT }, - { URDATA (UST, mt_unit[0].USTAT, 8, 16, 0, MT_NUMDR, 0) }, - { URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0, - MT_NUMDR, PV_LEFT | REG_RO) }, - { FLDATA (DEVNUM, mt_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB mt_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", &mt_vlock }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &mt_vlock }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE mt_dev = { - "MT", mt_unit, mt_reg, mt_mod, - MT_NUMDR, 10, 31, 1, 8, 8, - NULL, NULL, &mt_reset, - NULL, &mt_attach, &mt_detach, - &mt_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 mt70 (int32 IR, int32 AC) -{ -int32 f; -UNIT *uptr; - -uptr = mt_dev.units + GET_UNIT (mt_cu); /* get unit */ -switch (IR & 07) { /* decode IR<9:11> */ -case 1: /* LWCR */ - mt_wc = AC; /* load word count */ - return 0; -case 2: /* CWCR */ - mt_wc = 0; /* clear word count */ - return AC; -case 3: /* LCAR */ - mt_ca = AC; /* load mem address */ - return 0; -case 4: /* CCAR */ - mt_ca = 0; /* clear mem address */ - return AC; -case 5: /* LCMR */ - if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */ - mt_cu = AC; /* load command reg */ - mt_updcsta (mt_dev.units + GET_UNIT (mt_cu)); - return 0; -case 6: /* LFGR */ - if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */ - mt_fn = AC; /* load function */ - if ((mt_fn & FN_GO) == 0) { /* go set? */ - mt_updcsta (uptr); /* update status */ - return 0; } - f = GET_FNC (mt_fn); /* get function */ - if (((uptr->flags & UNIT_ATT) == 0) || - sim_is_active (uptr) || - (((f == FN_WRITE) || (f == FN_WREOF)) && sim_tape_wrp (uptr)) - || (((f == FN_SPACER) || (f == FN_REWIND)) && sim_tape_bot (uptr))) { - mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal op error */ - mt_set_done (); /* set done */ - mt_updcsta (uptr); /* update status */ - return 0; } - uptr->USTAT = uptr->USTAT & STA_WLK; /* clear status */ - if (f == FN_UNLOAD) { /* unload? */ - detach_unit (uptr); /* set offline */ - uptr->USTAT = STA_REW | STA_REM; /* rewinding, off */ - mt_set_done (); } /* set done */ - else if (f == FN_REWIND) { /* rewind */ - uptr->USTAT = uptr->USTAT | STA_REW; /* rewinding */ - mt_set_done (); } /* set done */ - else mt_done = 0; /* clear done */ - mt_updcsta (uptr); /* update status */ - sim_activate (uptr, mt_time); /* start io */ - return 0; -case 7: /* LDBR */ - if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */ - mt_db = AC; /* load buffer */ - mt_set_done (); /* set done */ - mt_updcsta (uptr); /* update status */ - return 0; } /* end switch */ -return (stop_inst << IOT_V_REASON) + AC; /* ill inst */ -} - -/* IOTs, continued */ - -int32 mt71 (int32 IR, int32 AC) -{ -UNIT *uptr; - -uptr = mt_dev.units + GET_UNIT (mt_cu); -switch (IR & 07) { /* decode IR<9:11> */ -case 1: /* RWCR */ - return mt_wc; /* read word count */ -case 2: /* CLT */ - mt_reset (&mt_dev); /* reset everything */ - return AC; -case 3: /* RCAR */ - return mt_ca; /* read mem address */ -case 4: /* RMSR */ - return ((mt_updcsta (uptr) >> 12) & 07777); /* read status */ -case 5: /* RCMR */ - return mt_cu; /* read command */ -case 6: /* RFSR */ - return (((mt_fn & FN_RMASK) | (mt_updcsta (uptr) & ~FN_RMASK)) - & 07777); /* read function */ -case 7: /* RDBR */ - return mt_db; } /* read data buffer */ -return (stop_inst << IOT_V_REASON) + AC; /* ill inst */ -} - -int32 mt72 (int32 IR, int32 AC) -{ -UNIT *uptr; - -uptr = mt_dev.units + GET_UNIT (mt_cu); /* get unit */ -switch (IR & 07) { /* decode IR<9:11> */ -case 1: /* SKEF */ - return (mt_sta & STA_ERR)? IOT_SKP + AC: AC; -case 2: /* SKCB */ - return (!mt_busy ())? IOT_SKP + AC: AC; -case 3: /* SKJD */ - return mt_done? IOT_SKP + AC: AC; -case 4: /* SKTR */ - return (!sim_is_active (uptr) && - (uptr->flags & UNIT_ATT))? IOT_SKP + AC: AC; -case 5: /* CLF */ - if (!sim_is_active (uptr)) mt_reset (&mt_dev); /* if TUR, zap */ - else { /* just ctrl zap */ - mt_sta = 0; /* clear status */ - mt_done = 0; /* clear done */ - mt_updcsta (uptr); } /* update status */ - return AC; } /* end switch */ -return (stop_inst << IOT_V_REASON) + AC; /* ill inst */ -} - -/* Unit service - - If rewind done, reposition to start of tape, set status - else, do operation, set done, interrupt -*/ - -t_stat mt_svc (UNIT *uptr) -{ -int32 f, i, p, u, wc, xma; -t_mtrlnt tbc, cbc; -uint16 c, c1, c2; -t_stat st, r = SCPE_OK; - -u = uptr - mt_dev.units; /* get unit number */ -f = GET_FNC (mt_fn); /* get command */ -xma = GET_EMA (mt_cu) + mt_ca; /* get mem addr */ -wc = WC_SIZE - mt_wc; /* get wc */ - -if (uptr->USTAT & STA_REW) { /* rewind? */ - sim_tape_rewind (uptr); /* update position */ - if (uptr->flags & UNIT_ATT) /* still on line? */ - uptr->USTAT = (uptr->USTAT & STA_WLK) | STA_BOT; - else uptr->USTAT = STA_REM; - if (u == GET_UNIT (mt_cu)) { /* selected? */ - mt_set_done (); /* set done */ - mt_updcsta (uptr); } /* update status */ - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */ - uptr->USTAT = STA_REM; /* unit off line */ - mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */ - mt_set_done (); /* set done */ - mt_updcsta (uptr); /* update status */ - return IORETURN (mt_stopioe, SCPE_UNATT); } - -switch (f) { /* case on function */ - -/* Unit service, continued */ - -case FN_READ: /* read */ -case FN_CMPARE: /* read/compare */ - st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */ - if (st == MTSE_RECE) mt_sta = mt_sta | STA_PAR | STA_ERR; /* rec in err? */ - else if (st != MTSE_OK) { /* other error? */ - r = mt_map_err (uptr, st); /* map error */ - mt_sta = mt_sta | STA_RLE | STA_ERR; /* err, eof/eom, tmk */ - break; } - cbc = (mt_cu & CU_UNPAK)? wc: wc * 2; /* expected bc */ - if (tbc != cbc) mt_sta = mt_sta | STA_RLE | STA_ERR; /* wrong size? */ - if (tbc < cbc) { /* record small? */ - cbc = tbc; /* use smaller */ - wc = (mt_cu & CU_UNPAK)? cbc: (cbc + 1) / 2; } - for (i = p = 0; i < wc; i++) { /* copy buffer */ - xma = mt_ixma (xma); /* increment xma */ - mt_wc = (mt_wc + 1) & 07777; /* incr word cnt */ - if (mt_cu & CU_UNPAK) c = mtxb[p++]; - else { - c1 = mtxb[p++] & 077; - c2 = mtxb[p++] & 077; - c = (c1 << 6) | c2; } - if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c; - else if ((f == FN_CMPARE) && (M[xma] != c)) { - mt_sta = mt_sta | STA_CPE | STA_ERR; - break; } } - break; - -case FN_WRITE: /* write */ - tbc = (mt_cu & CU_UNPAK)? wc: wc * 2; - for (i = p = 0; i < wc; i++) { /* copy buf to tape */ - xma = mt_ixma (xma); /* incr mem addr */ - if (mt_cu & CU_UNPAK) mtxb[p++] = M[xma] & 0377; - else { - mtxb[p++] = (M[xma] >> 6) & 077; - mtxb[p++] = M[xma] & 077; } } - if (st = sim_tape_wrrecf (uptr, mtxb, tbc)) { /* write rec, err? */ - r = mt_map_err (uptr, st); /* map error */ - xma = GET_EMA (mt_cu) + mt_ca; } /* restore xma */ - else mt_wc = 0; /* ok, clear wc */ - break; - -/* Unit service, continued */ - -case FN_WREOF: - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; - -case FN_SPACEF: /* space forward */ - do { - mt_wc = (mt_wc + 1) & 07777; /* incr wc */ - if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; } /* stop */ - } - while (mt_wc != 0); - break; - -case FN_SPACER: /* space reverse */ - do { - mt_wc = (mt_wc + 1) & 07777; /* incr wc */ - if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; } /* stop */ - } - while (mt_wc != 0); - break; } /* end case */ - -mt_cu = (mt_cu & ~CU_EMA) | ((xma >> (12 - CU_V_EMA)) & CU_EMA); -mt_ca = xma & 07777; /* update mem addr */ -mt_set_done (); /* set done */ -mt_updcsta (uptr); /* update status */ -return r; -} - -/* Update controller status */ - -int32 mt_updcsta (UNIT *uptr) -{ -mt_sta = (mt_sta & ~(STA_DYN | STA_CLR)) | (uptr->USTAT & STA_DYN); -if (((mt_sta & STA_ERR) && (mt_cu & CU_IEE)) || - (mt_done && (mt_cu & CU_IED))) int_req = int_req | INT_MT; -else int_req = int_req & ~INT_MT; -return mt_sta; -} - -/* Test if controller busy */ - -UNIT *mt_busy (void) -{ -int32 u; -UNIT *uptr; - -for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */ - uptr = mt_dev.units + u; - if (sim_is_active (uptr) && ((uptr->USTAT & STA_REW) == 0)) - return uptr; } -return NULL; -} - -/* Increment extended memory address */ - -int32 mt_ixma (int32 xma) /* incr extended ma */ -{ -int32 v; - -v = ((xma + 1) & 07777) | (xma & 070000); /* wrapped incr */ -if (mt_fn & FN_INC) { /* increment mode? */ - if (xma == 077777) mt_sta = mt_sta | STA_INC | STA_ERR; /* at limit? error */ - else v = xma + 1; } /* else 15b incr */ -return v; -} - -/* Set done */ - -void mt_set_done (void) -{ -mt_done = 1; /* set done */ -mt_fn = mt_fn & ~(FN_CRC | FN_GO | FN_INC); /* clear func<4:6> */ -return; -} - -/* Map tape error status */ - -t_stat mt_map_err (UNIT *uptr, t_stat st) -{ -switch (st) { -case MTSE_FMT: /* illegal fmt */ -case MTSE_UNATT: /* unattached */ - mt_sta = mt_sta | STA_ILL | STA_ERR; -case MTSE_OK: /* no error */ - return SCPE_IERR; /* never get here! */ -case MTSE_TMK: /* end of file */ - uptr->USTAT = uptr->USTAT | STA_EOF; /* set EOF */ - mt_sta = mt_sta | STA_ERR; - break; -case MTSE_IOERR: /* IO error */ - mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */ - if (mt_stopioe) return SCPE_IOERR; - break; -case MTSE_INVRL: /* invalid rec lnt */ - mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */ - return SCPE_MTRLNT; -case MTSE_RECE: /* record in error */ -case MTSE_EOM: /* end of medium */ - mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */ - break; -case MTSE_BOT: /* reverse into BOT */ - uptr->USTAT = uptr->USTAT | STA_BOT; /* set status */ - mt_sta = mt_sta | STA_ERR; - break; -case MTSE_WRP: /* write protect */ - mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */ - break; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat mt_reset (DEVICE *dptr) -{ -int32 u; -UNIT *uptr; - -mt_cu = mt_fn = mt_wc = mt_ca = mt_db = mt_sta = mt_done = 0; -int_req = int_req & ~INT_MT; /* clear interrupt */ -for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */ - uptr = mt_dev.units + u; - sim_cancel (uptr); /* cancel activity */ - sim_tape_reset (uptr); /* reset tape */ - if (uptr->flags & UNIT_ATT) uptr->USTAT = - (sim_tape_bot (uptr)? STA_BOT: 0) | - (sim_tape_wrp (uptr)? STA_WLK: 0); - else uptr->USTAT = STA_REM; } -if (mtxb == NULL) mtxb = calloc (MT_MAXFR, sizeof (uint8)); -if (mtxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat mt_attach (UNIT *uptr, char *cptr) -{ -t_stat r; -int32 u = uptr - mt_dev.units; /* get unit number */ - -r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; -uptr->USTAT = STA_BOT | (sim_tape_wrp (uptr)? STA_WLK: 0); -if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr); -return r; -} - -/* Detach routine */ - -t_stat mt_detach (UNIT* uptr) -{ -int32 u = uptr - mt_dev.units; /* get unit number */ - -if (!sim_is_active (uptr)) uptr->USTAT = STA_REM; -if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr); -return sim_tape_detach (uptr); -} - -/* Write lock/enable routine */ - -t_stat mt_vlock (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 u = uptr - mt_dev.units; /* get unit number */ - -if ((uptr->flags & UNIT_ATT) && (val || sim_tape_wrp (uptr))) - uptr->USTAT = uptr->USTAT | STA_WLK; -else uptr->USTAT = uptr->USTAT & ~STA_WLK; -if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr); -return SCPE_OK; -} diff --git a/PDP8/pdp8_pt.c b/PDP8/pdp8_pt.c deleted file mode 100644 index 92a39858..00000000 --- a/PDP8/pdp8_pt.c +++ /dev/null @@ -1,266 +0,0 @@ -/* pdp8_pt.c: PDP-8 paper tape reader/punch simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - ptr,ptp PC8E paper tape reader/punch - - 25-Apr-03 RMS Revised for extended file support - 04-Oct-02 RMS Added DIBs - 30-May-02 RMS Widened POS to 32b - 30-Nov-01 RMS Added read only unit support - 30-Mar-98 RMS Added RIM loader as PTR bootstrap -*/ - -#include "pdp8_defs.h" - -extern int32 int_req, int_enable, dev_done, stop_inst; - -int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */ - -int32 ptr (int32 IR, int32 AC); -int32 ptp (int32 IR, int32 AC); -t_stat ptr_svc (UNIT *uptr); -t_stat ptp_svc (UNIT *uptr); -t_stat ptr_reset (DEVICE *dptr); -t_stat ptp_reset (DEVICE *dptr); -t_stat ptr_boot (int32 unitno, DEVICE *dptr); - -/* PTR data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit descriptor - ptr_reg PTR register list -*/ - -DIB ptr_dib = { DEV_PTR, 1, { &ptr } }; - -UNIT ptr_unit = { - UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), - SERIAL_IN_WAIT }; - -REG ptr_reg[] = { - { ORDATA (BUF, ptr_unit.buf, 8) }, - { FLDATA (DONE, dev_done, INT_V_PTR) }, - { FLDATA (ENABLE, int_enable, INT_V_PTR) }, - { FLDATA (INT, int_req, INT_V_PTR) }, - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptr_stopioe, 0) }, - { NULL } }; - -MTAB ptr_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev }, - { 0 } }; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, ptr_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - &ptr_boot, NULL, NULL, - &ptr_dib, 0 }; - -/* PTP data structures - - ptp_dev PTP device descriptor - ptp_unit PTP unit descriptor - ptp_reg PTP register list -*/ - -DIB ptp_dib = { DEV_PTP, 1, { &ptp } }; - -UNIT ptp_unit = { - UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG ptp_reg[] = { - { ORDATA (BUF, ptp_unit.buf, 8) }, - { FLDATA (DONE, dev_done, INT_V_PTP) }, - { FLDATA (ENABLE, int_enable, INT_V_PTP) }, - { FLDATA (INT, int_req, INT_V_PTP) }, - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptp_stopioe, 0) }, - { NULL } }; - -MTAB ptp_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev }, - { 0 } }; - -DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, ptp_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptp_reset, - NULL, NULL, NULL, - &ptp_dib, 0 }; - -/* Paper tape reader: IOT routine */ - -int32 ptr (int32 IR, int32 AC) -{ -switch (IR & 07) { /* decode IR<9:11> */ -case 0: /* RPE */ - int_enable = int_enable | (INT_PTR+INT_PTP); /* set enable */ - int_req = INT_UPDATE; /* update interrupts */ - return AC; -case 1: /* RSF */ - return (dev_done & INT_PTR)? IOT_SKP + AC: AC; -case 6: /* RFC!RRB */ - sim_activate (&ptr_unit, ptr_unit.wait); -case 2: /* RRB */ - dev_done = dev_done & ~INT_PTR; /* clear flag */ - int_req = int_req & ~INT_PTR; /* clear int req */ - return (AC | ptr_unit.buf); /* or data to AC */ -case 4: /* RFC */ - sim_activate (&ptr_unit, ptr_unit.wait); - dev_done = dev_done & ~INT_PTR; /* clear flag */ - int_req = int_req & ~INT_PTR; /* clear int req */ - return AC; -default: - return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ -} - -/* Unit service */ - -t_stat ptr_svc (UNIT *uptr) -{ -int32 temp; - -if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptr_stopioe, SCPE_UNATT); -if ((temp = getc (ptr_unit.fileref)) == EOF) { - if (feof (ptr_unit.fileref)) { - if (ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } - else perror ("PTR I/O error"); - clearerr (ptr_unit.fileref); - return SCPE_IOERR; } -dev_done = dev_done | INT_PTR; /* set done */ -int_req = INT_UPDATE; /* update interrupts */ -ptr_unit.buf = temp & 0377; -ptr_unit.pos = ptr_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptr_reset (DEVICE *dptr) -{ -ptr_unit.buf = 0; -dev_done = dev_done & ~INT_PTR; /* clear done, int */ -int_req = int_req & ~INT_PTR; -int_enable = int_enable | INT_PTR; /* set enable */ -sim_cancel (&ptr_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Paper tape punch: IOT routine */ - -int32 ptp (int32 IR, int32 AC) -{ -switch (IR & 07) { /* decode IR<9:11> */ -case 0: /* PCE */ - int_enable = int_enable & ~(INT_PTR+INT_PTP); /* clear enables */ - int_req = INT_UPDATE; /* update interrupts */ - return AC; -case 1: /* PSF */ - return (dev_done & INT_PTP)? IOT_SKP + AC: AC; -case 2: /* PCF */ - dev_done = dev_done & ~INT_PTP; /* clear flag */ - int_req = int_req & ~INT_PTP; /* clear int req */ - return AC; -case 6: /* PLS */ - dev_done = dev_done & ~INT_PTP; /* clear flag */ - int_req = int_req & ~INT_PTP; /* clear int req */ -case 4: /* PPC */ - ptp_unit.buf = AC & 0377; /* load punch buf */ - sim_activate (&ptp_unit, ptp_unit.wait); /* activate unit */ - return AC; -default: - return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ -} - -/* Unit service */ - -t_stat ptp_svc (UNIT *uptr) -{ -dev_done = dev_done | INT_PTP; /* set done */ -int_req = INT_UPDATE; /* update interrupts */ -if ((ptp_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptp_stopioe, SCPE_UNATT); -if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { - perror ("PTP I/O error"); - clearerr (ptp_unit.fileref); - return SCPE_IOERR; } -ptp_unit.pos = ptp_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptp_reset (DEVICE *dptr) -{ -ptp_unit.buf = 0; -dev_done = dev_done & ~INT_PTP; /* clear done, int */ -int_req = int_req & ~INT_PTP; -int_enable = int_enable | INT_PTP; /* set enable */ -sim_cancel (&ptp_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define BOOT_START 07756 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 06014, /* 7756, RFC */ - 06011, /* 7757, LOOP, RSF */ - 05357, /* JMP .-1 */ - 06016, /* RFC RRB */ - 07106, /* CLL RTL*/ - 07006, /* RTL */ - 07510, /* SPA*/ - 05374, /* JMP 7774 */ - 07006, /* RTL */ - 06011, /* RSF */ - 05367, /* JMP .-1 */ - 06016, /* RFC RRB */ - 07420, /* SNL */ - 03776, /* DCA I 7776 */ - 03376, /* 7774, DCA 7776 */ - 05357, /* JMP 7757 */ - 00000, /* 7776, 0 */ - 05301 /* 7777, JMP 7701 */ -}; - -t_stat ptr_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; -extern uint16 M[]; - -if (ptr_dib.dev != DEV_PTR) return STOP_NOTSTD; /* only std devno */ -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} diff --git a/PDP8/pdp8_rf.c b/PDP8/pdp8_rf.c deleted file mode 100644 index c8441147..00000000 --- a/PDP8/pdp8_rf.c +++ /dev/null @@ -1,400 +0,0 @@ -/* pdp8_rf.c: RF08 fixed head disk simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - rf RF08 fixed head disk - - 26-Jul-03 RMS Fixed bug in set size routine - 14-Mar-03 RMS Fixed variable platter interaction with save/restore - 03-Mar-03 RMS Fixed autosizing - 02-Feb-03 RMS Added variable platter and autosizing support - 04-Oct-02 RMS Added DIB, device number support - 28-Nov-01 RMS Added RL8A support - 25-Apr-01 RMS Added device enable/disable support - 19-Mar-01 RMS Added disk monitor bootstrap, fixed IOT decoding - 15-Feb-01 RMS Fixed 3 cycle data break sequence - 14-Apr-99 RMS Changed t_addr to unsigned - 30-Mar-98 RMS Fixed bug in RF bootstrap - - The RF08 is a head-per-track disk. It uses the three cycle data break - facility. To minimize overhead, the entire RF08 is buffered in memory. - - Two timing parameters are provided: - - rf_time Interword timing, must be non-zero - rf_burst Burst mode, if 0, DMA occurs cycle by cycle; otherwise, - DMA occurs in a burst -*/ - -#include "pdp8_defs.h" -#include - -#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */ -#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */ -#define UNIT_M_PLAT 03 -#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT) - -/* Constants */ - -#define RF_NUMWD 2048 /* words/track */ -#define RF_NUMTR 128 /* tracks/disk */ -#define RF_DKSIZE (RF_NUMTR * RF_NUMWD) /* words/disk */ -#define RF_NUMDK 4 /* disks/controller */ -#define RF_WC 07750 /* word count */ -#define RF_MA 07751 /* mem address */ -#define RF_WMASK (RF_NUMWD - 1) /* word mask */ - -/* Parameters in the unit descriptor */ - -#define FUNC u4 /* function */ -#define RF_READ 2 /* read */ -#define RF_WRITE 4 /* write */ - -/* Status register */ - -#define RFS_PCA 04000 /* photocell status */ -#define RFS_DRE 02000 /* data req enable */ -#define RFS_WLS 01000 /* write lock status */ -#define RFS_EIE 00400 /* error int enable */ -#define RFS_PIE 00200 /* photocell int enb */ -#define RFS_CIE 00100 /* done int enable */ -#define RFS_MEX 00070 /* memory extension */ -#define RFS_DRL 00004 /* data late error */ -#define RFS_NXD 00002 /* non-existent disk */ -#define RFS_PER 00001 /* parity error */ -#define RFS_ERR (RFS_WLS + RFS_DRL + RFS_NXD + RFS_PER) -#define RFS_V_MEX 3 - -#define GET_MEX(x) (((x) & RFS_MEX) << (12 - RFS_V_MEX)) -#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ - ((double) RF_NUMWD))) -#define UPDATE_PCELL if (GET_POS(rf_time) < 6) rf_sta = rf_sta | RFS_PCA; \ - else rf_sta = rf_sta & ~RFS_PCA -#define RF_INT_UPDATE if ((rf_done && (rf_sta & RFS_CIE)) || \ - ((rf_sta & RFS_ERR) && (rf_sta & RFS_EIE)) || \ - ((rf_sta & RFS_PCA) && (rf_sta & RFS_PIE))) \ - int_req = int_req | INT_RF; \ - else int_req = int_req & ~INT_RF - -extern uint16 M[]; -extern int32 int_req, stop_inst; -extern UNIT cpu_unit; - -int32 rf_sta = 0; /* status register */ -int32 rf_da = 0; /* disk address */ -int32 rf_done = 0; /* done flag */ -int32 rf_wlk = 0; /* write lock */ -int32 rf_time = 10; /* inter-word time */ -int32 rf_burst = 1; /* burst mode flag */ -int32 rf_stopioe = 1; /* stop on error */ - -DEVICE rf_dev; -int32 rf60 (int32 IR, int32 AC); -int32 rf61 (int32 IR, int32 AC); -int32 rf62 (int32 IR, int32 AC); -int32 rf64 (int32 IR, int32 AC); -t_stat rf_svc (UNIT *uptr); -t_stat pcell_svc (UNIT *uptr); -t_stat rf_reset (DEVICE *dptr); -t_stat rf_boot (int32 unitno, DEVICE *dptr); -t_stat rf_attach (UNIT *uptr, char *cptr); -t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* RF08 data structures - - rf_dev RF device descriptor - rf_unit RF unit descriptor - pcell_unit photocell timing unit (orphan) - rf_reg RF register list -*/ - -DIB rf_dib = { DEV_RF, 5, { &rf60, &rf61, &rf62, NULL, &rf64 } }; - -UNIT rf_unit = - { UDATA (&rf_svc, UNIT_FIX+UNIT_ATTABLE+ - UNIT_BUFABLE+UNIT_MUSTBUF, RF_DKSIZE) }; - -UNIT pcell_unit = { UDATA (&pcell_svc, 0, 0) }; - -REG rf_reg[] = { - { ORDATA (STA, rf_sta, 12) }, - { ORDATA (DA, rf_da, 20) }, - { ORDATA (WC, M[RF_WC], 12) }, - { ORDATA (MA, M[RF_MA], 12) }, - { FLDATA (DONE, rf_done, 0) }, - { FLDATA (INT, int_req, INT_V_RF) }, - { ORDATA (WLK, rf_wlk, 32) }, - { DRDATA (TIME, rf_time, 24), REG_NZ + PV_LEFT }, - { FLDATA (BURST, rf_burst, 0) }, - { FLDATA (STOP_IOE, rf_stopioe, 0) }, - { DRDATA (CAPAC, rf_unit.capac, 21), REG_HRO }, - { ORDATA (DEVNUM, rf_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB rf_mod[] = { - { UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &rf_set_size }, - { UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &rf_set_size }, - { UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &rf_set_size }, - { UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &rf_set_size }, - { UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE rf_dev = { - "RF", &rf_unit, rf_reg, rf_mod, - 1, 8, 20, 1, 8, 12, - NULL, NULL, &rf_reset, - &rf_boot, &rf_attach, NULL, - &rf_dib, DEV_DISABLE | DEV_DIS }; - -/* IOT routines */ - -int32 rf60 (int32 IR, int32 AC) -{ -int32 t; -int32 pulse = IR & 07; - -UPDATE_PCELL; /* update photocell */ -if (pulse & 1) { /* DCMA */ - rf_da = rf_da & ~07777; /* clear DAR<8:19> */ - rf_done = 0; /* clear done */ - rf_sta = rf_sta & ~RFS_ERR; /* clear errors */ - RF_INT_UPDATE; } /* update int req */ -if (pulse & 6) { /* DMAR, DMAW */ - rf_da = rf_da | AC; /* DAR<8:19> |= AC */ - rf_unit.FUNC = pulse & ~1; /* save function */ - t = (rf_da & RF_WMASK) - GET_POS (rf_time); /* delta to new loc */ - if (t < 0) t = t + RF_NUMWD; /* wrap around? */ - sim_activate (&rf_unit, t * rf_time); /* schedule op */ - AC = 0; } /* clear AC */ -return AC; -} - -int32 rf61 (int32 IR, int32 AC) -{ -int32 pulse = IR & 07; - -UPDATE_PCELL; /* update photocell */ -switch (pulse) { /* decode IR<9:11> */ -case 1: /* DCIM */ - rf_sta = rf_sta & 07007; /* clear STA<3:8> */ - int_req = int_req & ~INT_RF; /* clear int req */ - sim_cancel (&pcell_unit); /* cancel photocell */ - return AC; -case 2: /* DSAC */ - return ((rf_da & RF_WMASK) == GET_POS (rf_time))? IOT_SKP: 0; -case 5: /* DIML */ - rf_sta = (rf_sta & 07007) | (AC & 0770); /* STA<3:8> <- AC */ - if (rf_sta & RFS_PIE) /* photocell int? */ - sim_activate (&pcell_unit, (RF_NUMWD - GET_POS (rf_time)) * - rf_time); - else sim_cancel (&pcell_unit); - RF_INT_UPDATE; /* update int req */ - return 0; /* clear AC */ -case 6: /* DIMA */ - return rf_sta; } /* AC <- STA<0:11> */ -return AC; -} - -/* IOT's, continued */ - -int32 rf62 (int32 IR, int32 AC) -{ -int32 pulse = IR & 07; - -UPDATE_PCELL; /* update photocell */ -if (pulse & 1) { /* DFSE */ - if (rf_sta & RFS_ERR) AC = AC | IOT_SKP; } -if (pulse & 2) { /* DFSC */ - if (pulse & 4) AC = AC & ~07777; /* for DMAC */ - else if (rf_done) AC = AC | IOT_SKP; } -if (pulse & 4) AC = AC | (rf_da & 07777); /* DMAC */ -return AC; -} - -int32 rf64 (int32 IR, int32 AC) -{ -int32 pulse = IR & 07; - -UPDATE_PCELL; /* update photocell */ -switch (pulse) { /* decode IR<9:11> */ -case 1: /* DCXA */ - rf_da = rf_da & 07777; /* clear DAR<0:7> */ - break; -case 3: /* DXAL */ - rf_da = rf_da & 07777; /* clear DAR<0:7> */ -case 2: /* DXAL w/o clear */ - rf_da = rf_da | ((AC & 0377) << 12); /* DAR<0:7> |= AC */ - AC = AC & ~07777; /* clear AC */ - break; -case 5: /* DXAC */ - AC = AC & ~07777; /* clear AC */ -case 4: /* DXAC w/o clear */ - AC = AC | ((rf_da >> 12) & 0377); /* AC |= DAR<0:7> */ - break; -default: - AC = (stop_inst << IOT_V_REASON) + AC; - break; } /* end switch */ -if ((uint32) rf_da >= rf_unit.capac) rf_sta = rf_sta | RFS_NXD; -else rf_sta = rf_sta & ~RFS_NXD; -RF_INT_UPDATE; -return AC; -} - -/* Unit service - - Note that for reads and writes, memory addresses wrap around in the - current field. This code assumes the entire disk is buffered. -*/ - -t_stat rf_svc (UNIT *uptr) -{ -int32 pa, t, mex; - -UPDATE_PCELL; /* update photocell */ -if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ - rf_sta = rf_sta | RFS_NXD; - rf_done = 1; - RF_INT_UPDATE; /* update int req */ - return IORETURN (rf_stopioe, SCPE_UNATT); } - -mex = GET_MEX (rf_sta); -do { if ((uint32) rf_da >= rf_unit.capac) { /* disk overflow? */ - rf_sta = rf_sta | RFS_NXD; - break; } - M[RF_WC] = (M[RF_WC] + 1) & 07777; /* incr word count */ - M[RF_MA] = (M[RF_MA] + 1) & 07777; /* incr mem addr */ - pa = mex | M[RF_MA]; /* add extension */ - if (uptr->FUNC == RF_READ) { /* read? */ - if (MEM_ADDR_OK (pa)) /* check nxm */ - M[pa] = *(((int16 *) uptr->filebuf) + rf_da); } - else { /* write */ - t = ((rf_da >> 15) & 030) | ((rf_da >> 14) & 07); - if ((rf_wlk >> t) & 1) rf_sta = rf_sta | RFS_WLS; - else { - *(((int16 *) uptr->filebuf) + rf_da) = M[pa]; - if (((uint32) rf_da) >= uptr->hwmark) uptr->hwmark = rf_da + 1; } } - rf_da = (rf_da + 1) & 03777777; } /* incr disk addr */ -while ((M[RF_WC] != 0) && (rf_burst != 0)); /* brk if wc, no brst */ - -if ((M[RF_WC] != 0) && ((rf_sta & RFS_ERR) == 0)) /* more to do? */ - sim_activate (&rf_unit, rf_time); /* sched next */ -else { rf_done = 1; /* done */ - RF_INT_UPDATE; } /* update int req */ -return SCPE_OK; -} - -/* Photocell unit service */ - -t_stat pcell_svc (UNIT *uptr) -{ -rf_sta = rf_sta | RFS_PCA; /* set photocell */ -if (rf_sta & RFS_PIE) { /* int enable? */ - sim_activate (&pcell_unit, RF_NUMWD * rf_time); - int_req = int_req | INT_RF; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat rf_reset (DEVICE *dptr) -{ -rf_sta = rf_da = 0; -rf_done = 1; -int_req = int_req & ~INT_RF; /* clear interrupt */ -sim_cancel (&rf_unit); -sim_cancel (&pcell_unit); -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define OS8_START 07750 -#define OS8_LEN (sizeof (os8_rom) / sizeof (int16)) -#define DM4_START 00200 -#define DM4_LEN (sizeof (dm4_rom) / sizeof (int16)) - -static const uint16 os8_rom[] = { - 07600, /* 7750, CLA CLL ; also word count */ - 06603, /* 7751, DMAR ; also address */ - 06622, /* 7752, DFSC ; done? */ - 05352, /* 7753, JMP .-1 ; no */ - 05752 /* 7754, JMP @.-2 ; enter boot */ -}; - -static const uint16 dm4_rom[] = { - 00200, 07600, /* 0200, CLA CLL */ - 00201, 06603, /* 0201, DMAR ; read */ - 00202, 06622, /* 0202, DFSC ; done? */ - 00203, 05202, /* 0203, JMP .-1 ; no */ - 00204, 05600, /* 0204, JMP @.-4 ; enter boot */ - 07750, 07576, /* 7750, 7576 ; word count */ - 07751, 07576 /* 7751, 7576 ; address */ -}; - -t_stat rf_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 sim_switches, saved_PC; - -if (rf_dib.dev != DEV_RF) return STOP_NOTSTD; /* only std devno */ -if (sim_switches & SWMASK ('D')) { - for (i = 0; i < DM4_LEN; i = i + 2) - M[dm4_rom[i]] = dm4_rom[i + 1]; - saved_PC = DM4_START; } -else { for (i = 0; i < OS8_LEN; i++) - M[OS8_START + i] = os8_rom[i]; - saved_PC = OS8_START; } -return SCPE_OK; -} - -/* Attach routine */ - -t_stat rf_attach (UNIT *uptr, char *cptr) -{ -uint32 sz, p; -uint32 ds_bytes = RF_DKSIZE * sizeof (int16); - -if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) { - p = (sz + ds_bytes - 1) / ds_bytes; - if (p >= RF_NUMDK) p = RF_NUMDK - 1; - uptr->flags = (uptr->flags & ~UNIT_PLAT) | - (p << UNIT_V_PLAT); } -uptr->capac = UNIT_GETP (uptr->flags) * RF_DKSIZE; -return attach_unit (uptr, cptr); -} - -/* Change disk size */ - -t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (val < 0) return SCPE_IERR; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = UNIT_GETP (val) * RF_DKSIZE; -uptr->flags = uptr->flags & ~UNIT_AUTO; -return SCPE_OK; -} diff --git a/PDP8/pdp8_rk.c b/PDP8/pdp8_rk.c deleted file mode 100644 index 7273430e..00000000 --- a/PDP8/pdp8_rk.c +++ /dev/null @@ -1,410 +0,0 @@ -/* pdp8_rk.c: RK8E cartridge disk simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - rk RK8E/RK05 cartridge disk - - 25-Apr-03 RMS Revised for extended file support - 04-Oct-02 RMS Added DIB, device number support - 06-Jan-02 RMS Changed enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Converted FLG to array, made register names consistent - 25-Apr-01 RMS Added device enable/disable support - 29-Jun-96 RMS Added unit enable/disable support -*/ - -#include "pdp8_defs.h" - -/* Constants */ - -#define RK_NUMSC 16 /* sectors/surface */ -#define RK_NUMSF 2 /* surfaces/cylinder */ -#define RK_NUMCY 203 /* cylinders/drive */ -#define RK_NUMWD 256 /* words/sector */ -#define RK_SIZE (RK_NUMCY * RK_NUMSF * RK_NUMSC * RK_NUMWD) /* words/drive */ -#define RK_NUMDR 4 /* drives/controller */ -#define RK_M_NUMDR 03 - -/* Flags in the unit flags word */ - -#define UNIT_V_HWLK (UNIT_V_UF + 0) /* hwre write lock */ -#define UNIT_V_SWLK (UNIT_V_UF + 1) /* swre write lock */ -#define UNIT_HWLK (1 << UNIT_V_HWLK) -#define UNIT_SWLK (1 << UNIT_V_SWLK) -#define UNIT_WPRT (UNIT_HWLK|UNIT_SWLK|UNIT_RO) /* write protect */ - -/* Parameters in the unit descriptor */ - -#define CYL u3 /* current cylinder */ -#define FUNC u4 /* function */ - -/* Status register */ - -#define RKS_DONE 04000 /* transfer done */ -#define RKS_HMOV 02000 /* heads moving */ -#define RKS_SKFL 00400 /* drive seek fail */ -#define RKS_NRDY 00200 /* drive not ready */ -#define RKS_BUSY 00100 /* control busy error */ -#define RKS_TMO 00040 /* timeout error */ -#define RKS_WLK 00020 /* write lock error */ -#define RKS_CRC 00010 /* CRC error */ -#define RKS_DLT 00004 /* data late error */ -#define RKS_STAT 00002 /* drive status error */ -#define RKS_CYL 00001 /* cyl address error */ -#define RKS_ERR (RKS_BUSY+RKS_TMO+RKS_WLK+RKS_CRC+RKS_DLT+RKS_STAT+RKS_CYL) - -/* Command register */ - -#define RKC_M_FUNC 07 /* function */ -#define RKC_READ 0 -#define RKC_RALL 1 -#define RKC_WLK 2 -#define RKC_SEEK 3 -#define RKC_WRITE 4 -#define RKC_WALL 5 -#define RKC_V_FUNC 9 -#define RKC_IE 00400 /* interrupt enable */ -#define RKC_SKDN 00200 /* int on seek done */ -#define RKC_HALF 00100 /* 128W sector */ -#define RKC_MEX 00070 /* memory extension */ -#define RKC_V_MEX 3 -#define RKC_M_DRV 03 /* drive select */ -#define RKC_V_DRV 1 -#define RKC_CYHI 00001 /* high cylinder addr */ - -#define GET_FUNC(x) (((x) >> RKC_V_FUNC) & RKC_M_FUNC) -#define GET_DRIVE(x) (((x) >> RKC_V_DRV) & RKC_M_DRV) -#define GET_MEX(x) (((x) & RKC_MEX) << (12 - RKC_V_MEX)) - -/* Disk address */ - -#define RKD_V_SECT 0 /* sector */ -#define RKD_M_SECT 017 -#define RKD_V_SUR 4 /* surface */ -#define RKD_M_SUR 01 -#define RKD_V_CYL 5 /* cylinder */ -#define RKD_M_CYL 0177 -#define GET_CYL(x,y) ((((x) & RKC_CYHI) << (12-RKD_V_CYL)) | \ - (((y) >> RKD_V_CYL) & RKD_M_CYL)) -#define GET_DA(x,y) ((((x) & RKC_CYHI) << 12) | y) - -/* Reset commands */ - -#define RKX_CLS 0 /* clear status */ -#define RKX_CLC 1 /* clear control */ -#define RKX_CLD 2 /* clear drive */ -#define RKX_CLSA 3 /* clear status alt */ - -#define RK_INT_UPDATE \ - if (((rk_sta & (RKS_DONE + RKS_ERR)) != 0) && \ - ((rk_cmd & RKC_IE) != 0)) int_req = int_req | INT_RK; \ - else int_req = int_req & ~INT_RK -#define RK_MIN 10 -#define MAX(x,y) (((x) > (y))? (x): (y)) - -extern uint16 M[]; -extern int32 int_req, stop_inst; -extern UNIT cpu_unit; - -int32 rk_busy = 0; /* controller busy */ -int32 rk_sta = 0; /* status register */ -int32 rk_cmd = 0; /* command register */ -int32 rk_da = 0; /* disk address */ -int32 rk_ma = 0; /* memory address */ -int32 rk_swait = 10, rk_rwait = 10; /* seek, rotate wait */ -int32 rk_stopioe = 1; /* stop on error */ - -DEVICE rk_dev; -int32 rk (int32 IR, int32 AC); -t_stat rk_svc (UNIT *uptr); -t_stat rk_reset (DEVICE *dptr); -t_stat rk_boot (int32 unitno, DEVICE *dptr); -void rk_go (int32 function, int32 cylinder); - -/* RK-8E data structures - - rk_dev RK device descriptor - rk_unit RK unit list - rk_reg RK register list - rk_mod RK modifiers list -*/ - -DIB rk_dib = { DEV_RK, 1, { &rk } }; - -UNIT rk_unit[] = { - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) } }; - -REG rk_reg[] = { - { ORDATA (RKSTA, rk_sta, 12) }, - { ORDATA (RKCMD, rk_cmd, 12) }, - { ORDATA (RKDA, rk_da, 12) }, - { ORDATA (RKMA, rk_ma, 12) }, - { FLDATA (BUSY, rk_busy, 0) }, - { FLDATA (INT, int_req, INT_V_RK) }, - { DRDATA (STIME, rk_swait, 24), PV_LEFT }, - { DRDATA (RTIME, rk_rwait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, rk_stopioe, 0) }, - { ORDATA (DEVNUM, rk_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB rk_mod[] = { - { UNIT_HWLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_HWLK, UNIT_HWLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE rk_dev = { - "RK", rk_unit, rk_reg, rk_mod, - RK_NUMDR, 8, 24, 1, 8, 12, - NULL, NULL, &rk_reset, - &rk_boot, NULL, NULL, - &rk_dib, DEV_DISABLE }; - -/* IOT routine */ - -int32 rk (int32 IR, int32 AC) -{ -int32 i; -UNIT *uptr; - -switch (IR & 07) { /* decode IR<9:11> */ -case 0: /* unused */ - return (stop_inst << IOT_V_REASON) + AC; -case 1: /* DSKP */ - return (rk_sta & (RKS_DONE + RKS_ERR))? /* skip on done, err */ - IOT_SKP + AC: AC; -case 2: /* DCLR */ - rk_sta = 0; /* clear status */ - switch (AC & 03) { /* decode AC<10:11> */ - case RKX_CLS: /* clear status */ - if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; - case RKX_CLSA: /* clear status alt */ - break; - case RKX_CLC: /* clear control */ - rk_cmd = rk_busy = 0; /* clear registers */ - rk_ma = rk_da = 0; - for (i = 0; i < RK_NUMDR; i++) sim_cancel (&rk_unit[i]); - break; - case RKX_CLD: /* reset drive */ - if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; - else rk_go (RKC_SEEK, 0); /* seek to 0 */ - break; } /* end switch AC */ - break; -case 3: /* DLAG */ - if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; - else { - rk_da = AC; /* load disk addr */ - rk_go (GET_FUNC (rk_cmd), GET_CYL (rk_cmd, rk_da)); } - break; -case 4: /* DLCA */ - if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; - else rk_ma = AC; /* load curr addr */ - break; -case 5: /* DRST */ - uptr = rk_dev.units + GET_DRIVE (rk_cmd); /* selected unit */ - rk_sta = rk_sta & ~(RKS_HMOV + RKS_NRDY); /* clear dynamic */ - if ((uptr->flags & UNIT_ATT) == 0) rk_sta = rk_sta | RKS_NRDY; - if (sim_is_active (uptr)) rk_sta = rk_sta | RKS_HMOV; - return rk_sta; -case 6: /* DLDC */ - if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; - else { - rk_cmd = AC; /* load command */ - rk_sta = 0; } /* clear status */ - break; -case 7: /* DMAN */ - break; } /* end case pulse */ -RK_INT_UPDATE; /* update int req */ -return 0; /* clear AC */ -} - -/* Initiate new function - - Called with function, cylinder, to allow recalibrate as well as - load and go to be processed by this routine. - - Assumes that the controller is idle, and that updating of interrupt - request will be done by the caller. -*/ - -void rk_go (int32 func, int32 cyl) -{ -int32 t; -UNIT *uptr; - -if (func == RKC_RALL) func = RKC_READ; /* all? use standard */ -if (func == RKC_WALL) func = RKC_WRITE; -uptr = rk_dev.units + GET_DRIVE (rk_cmd); /* selected unit */ -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rk_sta = rk_sta | RKS_DONE | RKS_NRDY | RKS_STAT; - return; } -if (sim_is_active (uptr) || (cyl >= RK_NUMCY)) { /* busy or bad cyl? */ - rk_sta = rk_sta | RKS_DONE | RKS_STAT; - return; } -if ((func == RKC_WRITE) && (uptr->flags & UNIT_WPRT)) { - rk_sta = rk_sta | RKS_DONE | RKS_WLK; /* write and locked? */ - return; } -if (func == RKC_WLK) { /* write lock? */ - uptr->flags = uptr->flags | UNIT_SWLK; - rk_sta = rk_sta | RKS_DONE; - return; } -t = abs (cyl - uptr->CYL) * rk_swait; /* seek time */ -if (func == RKC_SEEK) { /* seek? */ - sim_activate (uptr, MAX (RK_MIN, t)); /* schedule */ - rk_sta = rk_sta | RKS_DONE; } /* set done */ -else { sim_activate (uptr, t + rk_rwait); /* schedule */ - rk_busy = 1; } /* set busy */ -uptr->FUNC = func; /* save func */ -uptr->CYL = cyl; /* put on cylinder */ -return; -} - -/* Unit service - - If seek, complete seek command - Else complete data transfer command - - The unit control block contains the function and cylinder address for - the current command. - - Note that memory addresses wrap around in the current field. -*/ - -static uint16 fill[RK_NUMWD/2] = { 0 }; -t_stat rk_svc (UNIT *uptr) -{ -int32 err, wc, wc1, awc, swc, pa, da; -UNIT *seluptr; - -if (uptr->FUNC == RKC_SEEK) { /* seek? */ - seluptr = rk_dev.units + GET_DRIVE (rk_cmd); /* see if selected */ - if ((uptr == seluptr) && ((rk_cmd & RKC_SKDN) != 0)) { - rk_sta = rk_sta | RKS_DONE; - RK_INT_UPDATE; } - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* not att? abort */ - rk_sta = rk_sta | RKS_DONE | RKS_NRDY | RKS_STAT; - rk_busy = 0; - RK_INT_UPDATE; - return IORETURN (rk_stopioe, SCPE_UNATT); } - -if ((uptr->FUNC == RKC_WRITE) && (uptr->flags & UNIT_WPRT)) { - rk_sta = rk_sta | RKS_DONE | RKS_WLK; /* write and locked? */ - rk_busy = 0; - RK_INT_UPDATE; - return SCPE_OK; } - -pa = GET_MEX (rk_cmd) | rk_ma; /* phys address */ -da = GET_DA (rk_cmd, rk_da) * RK_NUMWD * sizeof (int16);/* disk address */ -swc = wc = (rk_cmd & RKC_HALF)? RK_NUMWD / 2: RK_NUMWD; /* get transfer size */ -if ((wc1 = ((rk_ma + wc) - 010000)) > 0) wc = wc - wc1; /* if wrap, limit */ -err = fseek (uptr->fileref, da, SEEK_SET); /* locate sector */ - -if ((uptr->FUNC == RKC_READ) && (err == 0) && MEM_ADDR_OK (pa)) { /* read? */ - awc = fxread (&M[pa], sizeof (int16), wc, uptr->fileref); - for ( ; awc < wc; awc++) M[pa + awc] = 0; /* fill if eof */ - err = ferror (uptr->fileref); - if ((wc1 > 0) && (err == 0)) { /* field wraparound? */ - pa = pa & 070000; /* wrap phys addr */ - awc = fxread (&M[pa], sizeof (int16), wc1, uptr->fileref); - for ( ; awc < wc1; awc++) M[pa + awc] = 0; /* fill if eof */ - err = ferror (uptr->fileref); } } - -if ((uptr->FUNC == RKC_WRITE) && (err == 0)) { /* write? */ - fxwrite (&M[pa], sizeof (int16), wc, uptr->fileref); - err = ferror (uptr->fileref); - if ((wc1 > 0) && (err == 0)) { /* field wraparound? */ - pa = pa & 070000; /* wrap phys addr */ - fxwrite (&M[pa], sizeof (int16), wc1, uptr->fileref); - err = ferror (uptr->fileref); } - if ((rk_cmd & RKC_HALF) && (err == 0)) { /* fill half sector */ - fxwrite (fill, sizeof (int16), RK_NUMWD/2, uptr->fileref); - err = ferror (uptr->fileref); } } - -rk_ma = (rk_ma + swc) & 07777; /* incr mem addr reg */ -rk_sta = rk_sta | RKS_DONE; /* set done */ -rk_busy = 0; -RK_INT_UPDATE; - -if (err != 0) { - perror ("RK I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat rk_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -rk_cmd = rk_ma = rk_da = rk_sta = rk_busy = 0; -int_req = int_req & ~INT_RK; /* clear interrupt */ -for (i = 0; i < RK_NUMDR; i++) { /* stop all units */ - uptr = rk_dev.units + i; - sim_cancel (uptr); - uptr->flags = uptr->flags & ~UNIT_SWLK; - uptr->CYL = uptr->FUNC = 0; } -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define BOOT_START 023 -#define BOOT_UNIT 032 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 06007, /* 23, CAF */ - 06744, /* 24, DLCA ; addr = 0 */ - 01032, /* 25, TAD UNIT ; unit no */ - 06746, /* 26, DLDC ; command, unit */ - 06743, /* 27, DLAG ; disk addr, go */ - 01032, /* 30, TAD UNIT ; unit no, for OS */ - 05031, /* 31, JMP . */ - 00000 /* UNIT, 0 ; in bits <9:10> */ -}; - -t_stat rk_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -if (rk_dib.dev != DEV_RK) return STOP_NOTSTD; /* only std devno */ -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -M[BOOT_UNIT] = (unitno & RK_M_NUMDR) << 1; -saved_PC = BOOT_START; -return SCPE_OK; -} diff --git a/PDP8/pdp8_rl.c b/PDP8/pdp8_rl.c deleted file mode 100644 index 69a91459..00000000 --- a/PDP8/pdp8_rl.c +++ /dev/null @@ -1,629 +0,0 @@ - /* pdp8_rl.c: RL8A cartridge disk simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - rl RL8A cartridge disk - - 25-Apr-03 RMS Revised for extended file support - 04-Oct-02 RMS Added DIB, device number support - 06-Jan-02 RMS Changed enable/disable support - 30-Nov-01 RMS Cloned from RL11 - - The RL8A is a four drive cartridge disk subsystem. An RL01 drive - consists of 256 cylinders, each with 2 surfaces containing 40 sectors - of 256 bytes. An RL02 drive has 512 cylinders. - - The RL8A controller has several serious complications. - - Seeking is relative to the current disk address; this requires - keeping accurate track of the current cylinder. - - The RL8A will not switch heads or cross cylinders during transfers. - - The RL8A operates in 8b and 12b mode, like the RX8E; in 12b mode, it - packs 2 12b words into 3 bytes, creating a 170 "word" sector with - one wasted byte. Multi-sector transfers in 12b mode don't work. -*/ - -#include "pdp8_defs.h" - -/* Constants */ - -#define RL_NUMBY 256 /* 8b bytes/sector */ -#define RL_NUMSC 40 /* sectors/surface */ -#define RL_NUMSF 2 /* surfaces/cylinder */ -#define RL_NUMCY 256 /* cylinders/drive */ -#define RL_NUMDR 4 /* drives/controller */ -#define RL_MAXFR (1 << 12) /* max transfer */ -#define RL01_SIZE (RL_NUMCY*RL_NUMSF*RL_NUMSC*RL_NUMBY) /* words/drive */ -#define RL02_SIZE (RL01_SIZE * 2) /* words/drive */ -#define RL_BBMAP 014 /* sector for bblk map */ -#define RL_BBID 0123 /* ID for bblk map */ - -/* Flags in the unit flags word */ - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write lock */ -#define UNIT_V_RL02 (UNIT_V_UF + 1) /* RL01 vs RL02 */ -#define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize enable */ -#define UNIT_V_DUMMY (UNIT_V_UF + 3) /* dummy flag */ -#define UNIT_DUMMY (1u << UNIT_V_DUMMY) -#define UNIT_WLK (1u << UNIT_V_WLK) -#define UNIT_RL02 (1u << UNIT_V_RL02) -#define UNIT_AUTO (1u << UNIT_V_AUTO) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -/* Parameters in the unit descriptor */ - -#define TRK u3 /* current cylinder */ -#define STAT u4 /* status */ - -/* RLDS, NI = not implemented, * = kept in STAT, ^ = kept in TRK */ - -#define RLDS_LOAD 0 /* no cartridge */ -#define RLDS_LOCK 5 /* lock on */ -#define RLDS_BHO 0000010 /* brushes home NI */ -#define RLDS_HDO 0000020 /* heads out NI */ -#define RLDS_CVO 0000040 /* cover open NI */ -#define RLDS_HD 0000100 /* head select ^ */ -#define RLDS_RL02 0000200 /* RL02 */ -#define RLDS_DSE 0000400 /* drv sel err NI */ -#define RLDS_VCK 0001000 /* vol check * */ -#define RLDS_WGE 0002000 /* wr gate err * */ -#define RLDS_SPE 0004000 /* spin err * */ -#define RLDS_STO 0010000 /* seek time out NI */ -#define RLDS_WLK 0020000 /* wr locked */ -#define RLDS_HCE 0040000 /* hd curr err NI */ -#define RLDS_WDE 0100000 /* wr data err NI */ -#define RLDS_ATT (RLDS_HDO+RLDS_BHO+RLDS_LOCK) /* att status */ -#define RLDS_UNATT (RLDS_CVO+RLDS_LOAD) /* unatt status */ -#define RLDS_ERR (RLDS_WDE+RLDS_HCE+RLDS_STO+RLDS_SPE+RLDS_WGE+ \ - RLDS_VCK+RLDS_DSE) /* errors bits */ - -/* RLCSA, seek = offset/rw = address (also uptr->TRK) */ - -#define RLCSA_DIR 04000 /* direction */ -#define RLCSA_HD 02000 /* head select */ -#define RLCSA_CYL 00777 /* cyl offset */ -#define GET_CYL(x) ((x) & RLCSA_CYL) -#define GET_TRK(x) ((((x) & RLCSA_CYL) * RL_NUMSF) + \ - (((x) & RLCSA_HD)? 1: 0)) -#define GET_DA(x) ((GET_TRK(x) * RL_NUMSC) + rlsa) - -/* RLCSB, function/unit select */ - -#define RLCSB_V_FUNC 0 /* function */ -#define RLCSB_M_FUNC 07 -#define RLCSB_MNT 0 -#define RLCSB_CLRD 1 -#define RLCSB_GSTA 2 -#define RLCSB_SEEK 3 -#define RLCSB_RHDR 4 -#define RLCSB_WRITE 5 -#define RLCSB_READ 6 -#define RLCSB_RNOHDR 7 -#define RLCSB_V_MEX 3 /* memory extension */ -#define RLCSB_M_MEX 07 -#define RLCSB_V_DRIVE 6 /* drive */ -#define RLCSB_M_DRIVE 03 -#define RLCSB_V_IE 8 /* int enable */ -#define RLCSB_IE (1u << RLCSB_V_IE) -#define RLCSB_8B 01000 /* 12b/8b */ -#define RCLS_MNT 02000 /* maint NI */ -#define RLCSB_RW 0001777 /* read/write */ -#define GET_FUNC(x) (((x) >> RLCSB_V_FUNC) & RLCSB_M_FUNC) -#define GET_MEX(x) (((x) >> RLCSB_V_MEX) & RLCSB_M_MEX) -#define GET_DRIVE(x) (((x) >> RLCSB_V_DRIVE) & RLCSB_M_DRIVE) - -/* RLSA, disk sector */ - -#define RLSA_V_SECT 6 /* sector */ -#define RLSA_M_SECT 077 -#define GET_SECT(x) (((x) >> RLSA_V_SECT) & RLSA_M_SECT) - -/* RLER, error register */ - -#define RLER_DRDY 00001 /* drive ready */ -#define RLER_DRE 00002 /* drive error */ -#define RLER_HDE 01000 /* header error */ -#define RLER_INCMP 02000 /* incomplete */ -#define RLER_ICRC 04000 /* CRC error */ -#define RLER_MASK 07003 - -/* RLSI, silo register, used only in read header */ - -#define RLSI_V_TRK 6 /* track */ - -extern uint16 M[]; -extern int32 int_req; -extern UNIT cpu_unit; - -uint8 *rlxb = NULL; /* xfer buffer */ -int32 rlcsa = 0; /* control/status A */ -int32 rlcsb = 0; /* control/status B */ -int32 rlma = 0; /* memory address */ -int32 rlwc = 0; /* word count */ -int32 rlsa = 0; /* sector address */ -int32 rler = 0; /* error register */ -int32 rlsi = 0, rlsi1 = 0, rlsi2 = 0; /* silo queue */ -int32 rl_lft = 0; /* silo left/right */ -int32 rl_done = 0; /* done flag */ -int32 rl_erf = 0; /* error flag */ -int32 rl_swait = 10; /* seek wait */ -int32 rl_rwait = 10; /* rotate wait */ -int32 rl_stopioe = 1; /* stop on error */ - -DEVICE rl_dev; -int32 rl60 (int32 IR, int32 AC); -int32 rl61 (int32 IR, int32 AC); -t_stat rl_svc (UNIT *uptr); -t_stat rl_reset (DEVICE *dptr); -void rl_set_done (int32 error); -t_stat rl_boot (int32 unitno, DEVICE *dptr); -t_stat rl_attach (UNIT *uptr, char *cptr); -t_stat rl_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat rl_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* RL8A data structures - - rl_dev RL device descriptor - rl_unit RL unit list - rl_reg RL register list - rl_mod RL modifier list -*/ - -DIB rl_dib = { DEV_RL, 2, { &rl60, &rl61 } }; - -UNIT rl_unit[] = { - { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE, RL01_SIZE) }, - { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE, RL01_SIZE) }, - { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE, RL01_SIZE) }, - { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE, RL01_SIZE) } }; - -REG rl_reg[] = { - { ORDATA (RLCSA, rlcsa, 12) }, - { ORDATA (RLCSB, rlcsb, 12) }, - { ORDATA (RLMA, rlma, 12) }, - { ORDATA (RLWC, rlwc, 12) }, - { ORDATA (RLSA, rlsa, 6) }, - { ORDATA (RLER, rler, 12) }, - { ORDATA (RLSI, rlsi, 16) }, - { ORDATA (RLSI1, rlsi1, 16) }, - { ORDATA (RLSI2, rlsi2, 16) }, - { FLDATA (RLSIL, rl_lft, 0) }, - { FLDATA (INT, int_req, INT_V_RL) }, - { FLDATA (DONE, rl_done, INT_V_RL) }, - { FLDATA (IE, rlcsb, RLCSB_V_IE) }, - { FLDATA (ERR, rl_erf, 0) }, - { DRDATA (STIME, rl_swait, 24), PV_LEFT }, - { DRDATA (RTIME, rl_rwait, 24), PV_LEFT }, - { URDATA (CAPAC, rl_unit[0].capac, 10, T_ADDR_W, 0, - RL_NUMDR, PV_LEFT + REG_HRO) }, - { FLDATA (STOP_IOE, rl_stopioe, 0) }, - { ORDATA (DEVNUM, rl_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB rl_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { UNIT_DUMMY, 0, NULL, "BADBLOCK", &rl_set_bad }, - { (UNIT_RL02+UNIT_ATT), UNIT_ATT, "RL01", NULL, NULL }, - { (UNIT_RL02+UNIT_ATT), (UNIT_RL02+UNIT_ATT), "RL02", NULL, NULL }, - { (UNIT_AUTO+UNIT_RL02+UNIT_ATT), 0, "RL01", NULL, NULL }, - { (UNIT_AUTO+UNIT_RL02+UNIT_ATT), UNIT_RL02, "RL02", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_RL02), 0, NULL, "RL01", &rl_set_size }, - { (UNIT_AUTO+UNIT_RL02), UNIT_RL02, NULL, "RL02", &rl_set_size }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE rl_dev = { - "RL", rl_unit, rl_reg, rl_mod, - RL_NUMDR, 8, 24, 1, 8, 8, - NULL, NULL, &rl_reset, - &rl_boot, &rl_attach, NULL, - &rl_dib, DEV_DISABLE | DEV_DIS }; - -/* IOT 60 routine */ - -int32 rl60 (int32 IR, int32 AC) -{ -int32 curr, offs, newc, maxc; -UNIT *uptr; - -switch (IR & 07) { /* case IR<9:11> */ -case 0: /* RLDC */ - rl_reset (&rl_dev); /* reset device */ - break; -case 1: /* RLSD */ - if (rl_done) AC = IOT_SKP; /* skip if done */ - else AC = 0; - rl_done = 0; /* clear done */ - int_req = int_req & ~INT_RL; /* clear intr */ - return AC; -case 2: /* RLMA */ - rlma = AC; - break; -case 3: /* RLCA */ - rlcsa = AC; - break; -case 4: /* RLCB */ - rlcsb = AC; - rl_done = 0; /* clear done */ - rler = rl_erf = 0; /* clear errors */ - int_req = int_req & ~INT_RL; /* clear intr */ - rl_lft = 0; /* clear silo ptr */ - uptr = rl_dev.units + GET_DRIVE (rlcsb); /* select unit */ - switch (GET_FUNC (rlcsb)) { /* case on func */ - case RLCSB_CLRD: /* clear drive */ - uptr->STAT = uptr->STAT & ~RLDS_ERR; /* clear errors */ - case RLCSB_MNT: /* mnt */ - rl_set_done (0); - break; - case RLCSB_SEEK: /* seek */ - curr = GET_CYL (uptr->TRK); /* current cylinder */ - offs = GET_CYL (rlcsa); /* offset */ - if (rlcsa & RLCSA_DIR) { /* in or out? */ - newc = curr + offs; /* out */ - maxc = (uptr->flags & UNIT_RL02)? - RL_NUMCY * 2: RL_NUMCY; - if (newc >= maxc) newc = maxc - 1; } - else { - newc = curr - offs; /* in */ - if (newc < 0) newc = 0; } - uptr->TRK = newc | (rlcsa & RLCSA_HD); - sim_activate (uptr, rl_swait * abs (newc - curr)); - break; - default: /* data transfer */ - sim_activate (uptr, rl_swait); /* activate unit */ - break; } /* end switch func */ - break; -case 5: /* RLSA */ - rlsa = GET_SECT (AC); - break; -case 6: /* spare */ - return 0; -case 7: /* RLWC */ - rlwc = AC; - break; } /* end switch pulse */ -return 0; /* clear AC */ -} - -/* IOT 61 routine */ - -int32 rl61 (int32 pulse, int32 AC) -{ -int32 dat; -UNIT *uptr; - -switch (pulse) { /* case IR<9:11> */ -case 0: /* RRER */ - uptr = rl_dev.units + GET_DRIVE (rlcsb); /* select unit */ - if (!sim_is_active (uptr) && /* update drdy */ - (uptr->flags & UNIT_ATT)) - rler = rler | RLER_DRDY; - else rler = rler & ~RLER_DRDY; - dat = rler & RLER_MASK; - break; -case 1: /* RRWC */ - dat = rlwc; - break; -case 2: /* RRCA */ - dat = rlcsa; - break; -case 3: /* RRCB */ - dat = rlcsb; - break; -case 4: /* RRSA */ - dat = (rlsa << RLSA_V_SECT) & 07777; - break; -case 5: /* RRSI */ - if (rl_lft) { /* silo left? */ - dat = (rlsi >> 8) & 0377; /* get left 8b */ - rlsi = rlsi1; /* ripple */ - rlsi1 = rlsi2; } - else dat = rlsi & 0377; /* get right 8b */ - rl_lft = rl_lft ^ 1; /* change side */ - break; -case 6: /* spare */ - return AC; -case 7: /* RLSE */ - if (rl_erf) dat = IOT_SKP | AC; /* skip if err */ - else dat = AC; - rl_erf = 0; - break; } /* end switch pulse */ -return dat; -} - -/* Service unit timeout - - If seek in progress, complete seek command - Else complete data transfer command - - The unit control block contains the function and cylinder for - the current command. -*/ - -t_stat rl_svc (UNIT *uptr) -{ -int32 err, wc, maxc; -int32 i, j, func, da, bc, wbc; -uint32 ma; - -func = GET_FUNC (rlcsb); /* get function */ -if (func == RLCSB_GSTA) { /* get status? */ - rlsi = uptr->STAT | - ((uptr->TRK & RLCSA_HD)? RLDS_HD: 0) | - ((uptr->flags & UNIT_ATT)? RLDS_ATT: RLDS_UNATT); - if (uptr->flags & UNIT_RL02) rlsi = rlsi | RLDS_RL02; - if (uptr->flags & UNIT_WPRT) rlsi = rlsi | RLDS_WLK; - rlsi2 = rlsi1 = rlsi; - rl_set_done (0); /* done */ - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ - uptr->STAT = uptr->STAT | RLDS_SPE; /* spin error */ - rl_set_done (RLER_INCMP); /* flag error */ - return IORETURN (rl_stopioe, SCPE_UNATT); } - -if ((func == RLCSB_WRITE) && (uptr->flags & UNIT_WPRT)) { - uptr->STAT = uptr->STAT | RLDS_WGE; /* write and locked */ - rl_set_done (RLER_DRE); /* flag error */ - return SCPE_OK; } - -if (func == RLCSB_SEEK) { /* seek? */ - rl_set_done (0); /* done */ - return SCPE_OK; } - -if (func == RLCSB_RHDR) { /* read header? */ - rlsi = (GET_TRK (uptr->TRK) << RLSI_V_TRK) | rlsa; - rlsi1 = rlsi2 = 0; - rl_set_done (0); /* done */ - return SCPE_OK; } - -if (((func != RLCSB_RNOHDR) && (GET_CYL (uptr->TRK) != GET_CYL (rlcsa))) - || (rlsa >= RL_NUMSC)) { /* bad cyl or sector? */ - rl_set_done (RLER_HDE | RLER_INCMP); /* flag error */ - return SCPE_OK; } - -ma = (GET_MEX (rlcsb) << 12) | rlma; /* get mem addr */ -da = GET_DA (rlcsa) * RL_NUMBY; /* get disk addr */ -wc = 010000 - rlwc; /* get true wc */ -if (rlcsb & RLCSB_8B) { /* 8b mode? */ - bc = wc; /* bytes to xfr */ - maxc = (RL_NUMSC - rlsa) * RL_NUMBY; /* max transfer */ - if (bc > maxc) wc = bc = maxc; } /* trk ovrun? limit */ -else { bc = ((wc * 3) + 1) / 2; /* 12b mode */ - if (bc > RL_NUMBY) { /* > 1 sector */ - bc = RL_NUMBY; /* cap xfer */ - wc = (RL_NUMBY * 2) / 3; } } - -err = fseek (uptr->fileref, da, SEEK_SET); - -if ((func >= RLCSB_READ) && (err == 0) && /* read (no hdr)? */ - MEM_ADDR_OK (ma)) { /* valid bank? */ - i = fxread (rlxb, sizeof (int8), bc, uptr->fileref); - err = ferror (uptr->fileref); - for ( ; i < bc; i++) rlxb[i] = 0; /* fill buffer */ - for (i = j = 0; i < wc; i++) { /* store buffer */ - if (rlcsb & RLCSB_8B) /* 8b mode? */ - M[ma] = rlxb[i] & 0377; /* store */ - else if (i & 1) { /* odd wd 12b? */ - M[ma] = ((rlxb[j + 1] >> 4) & 017) | - (((uint16) rlxb[j + 2]) << 4); - j = j + 3; } - else M[ma] = rlxb[j] | /* even wd 12b */ - ((((uint16) rlxb[j + 1]) & 017) << 8); - ma = (ma & 070000) + ((ma + 1) & 07777); - } /* end for */ - } /* end if wr */ - -if ((func == RLCSB_WRITE) && (err == 0)) { /* write? */ - for (i = j = 0; i < wc; i++) { /* fetch buffer */ - if (rlcsb & RLCSB_8B) /* 8b mode? */ - rlxb[i] = M[ma] & 0377; /* fetch */ - else if (i & 1) { /* odd wd 12b? */ - rlxb[j + 1] = rlxb[j + 1] | ((M[ma] & 017) << 4); - rlxb[j + 2] = ((M[ma] >> 4) & 0377); - j = j + 3; } - else { /* even wd 12b */ - rlxb[j] = M[ma] & 0377; - rlxb[j + 1] = (M[ma] >> 8) & 017; } - ma = (ma & 070000) + ((ma + 1) & 07777); - } /* end for */ - wbc = (bc + (RL_NUMBY - 1)) & ~(RL_NUMBY - 1); /* clr to */ - for (i = bc; i < wbc; i++) rlxb[i] = 0; /* end of blk */ - fxwrite (rlxb, sizeof (int8), wbc, uptr->fileref); - err = ferror (uptr->fileref); - } /* end write */ - -rlwc = (rlwc + wc) & 07777; /* final word count */ -if (rlwc != 0) rler = rler | RLER_INCMP; /* completed? */ -rlma = (rlma + wc) & 07777; /* final word addr */ -rlsa = rlsa + ((bc + (RL_NUMBY - 1)) / RL_NUMBY); -rl_set_done (0); - -if (err != 0) { /* error? */ - perror ("RL I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -return SCPE_OK; -} - -/* Set done and possibly errors */ - -void rl_set_done (int32 status) -{ -rl_done = 1; -rler = rler | status; -if (rler) rl_erf = 1; -if (rlcsb & RLCSB_IE) int_req = int_req | INT_RL; -else int_req = int_req & ~INT_RL; -return; -} - -/* Device reset - - Note that the RL8A does NOT recalibrate its drives on RESET -*/ - -t_stat rl_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -rlcsa = rlcsb = rlsa = rler = 0; -rlma = rlwc = 0; -rlsi = rlsi1 = rlsi2 = 0; -rl_lft = 0; -rl_done = 0; -rl_erf = 0; -int_req = int_req & ~INT_RL; -for (i = 0; i < RL_NUMDR; i++) { - uptr = rl_dev.units + i; - sim_cancel (uptr); - uptr->STAT = 0; } -if (rlxb == NULL) rlxb = calloc (RL_MAXFR, sizeof (unsigned int8)); -if (rlxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat rl_attach (UNIT *uptr, char *cptr) -{ -uint32 p; -t_stat r; - -uptr->capac = (uptr->flags & UNIT_RL02)? RL02_SIZE: RL01_SIZE; -r = attach_unit (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* error? */ -uptr->TRK = 0; /* cyl 0 */ -uptr->STAT = RLDS_VCK; /* new volume */ -if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK; /* seek to end */ -if ((p = ftell (uptr->fileref)) == 0) { /* new disk image? */ - if (uptr->flags & UNIT_RO) return SCPE_OK; - return rl_set_bad (uptr, 0, NULL, NULL); } -if ((uptr->flags & UNIT_AUTO) == 0) return r; /* autosize? */ -if (p > (RL01_SIZE * sizeof (int16))) { - uptr->flags = uptr->flags | UNIT_RL02; - uptr->capac = RL02_SIZE; } -else { uptr->flags = uptr->flags & ~UNIT_RL02; - uptr->capac = RL01_SIZE; } -return SCPE_OK; -} - -/* Set size routine */ - -t_stat rl_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = (val & UNIT_RL02)? RL02_SIZE: RL01_SIZE; -return SCPE_OK; -} - -/* Factory bad block table creation routine - - This routine writes the OS/8 specific bad block map in track 0, sector 014 (RL_BBMAP): - - words 0 magic number = 0123 (RL_BBID) - words 1-n block numbers - : - words n+1 end of table = 0 - - Inputs: - uptr = pointer to unit - val = ignored - Outputs: - sta = status code -*/ - -t_stat rl_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 i, da = RL_BBMAP * RL_NUMBY; - -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; -if (uptr->flags & UNIT_RO) return SCPE_RO; -if (!get_yn ("Create bad block table? [N]", FALSE)) return SCPE_OK; -if (fseek (uptr->fileref, da, SEEK_SET)) return SCPE_IOERR; -rlxb[0] = RL_BBID; -for (i = 1; i < RL_NUMBY; i++) rlxb[i] = 0; -fxwrite (rlxb, sizeof (int8), RL_NUMBY, uptr->fileref); -if (ferror (uptr->fileref)) return SCPE_IOERR; -return SCPE_OK; -} - -/* Bootstrap */ - -#define BOOT_START 1 /* start */ -#define BOOT_UNIT 02006 /* unit number */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 06600, /* BT, RLDC ; reset */ - 07201, /* 02, CLA IAC ; clr drv = 1 */ - 04027, /* 03, JMS GO ; do io */ - 01004, /* 04, TAD 4 ; rd hdr fnc */ - 04027, /* 05, JMS GO ; do io */ - 06615, /* 06, RRSI ; rd hdr lo */ - 07002, /* 07, BSW ; swap */ - 07012, /* 10, RTR ; lo cyl to L */ - 06615, /* 11, RRSI ; rd hdr hi */ - 00025, /* 12, AND 25 ; mask = 377 */ - 07004, /* 13, RTL ; get cyl */ - 06603, /* 14, RLCA ; set addr */ - 07325, /* 15, CLA STL IAC RAL ; seek = 3 */ - 04027, /* 16, JMS GO ; do io */ - 07332, /* 17, CLA STL RTR ; dir in = 2000 */ - 06605, /* 20, RLSA ; sector */ - 01026, /* 21, TAD (-200) ; one sector */ - 06607, /* 22, RLWC ; word cnt */ - 07327, /* 23, CLA STL IAC RTL ; read = 6*/ - 04027, /* 24, JMS GO ; do io */ - 00377, /* 25, JMP 377 ; start */ - 07600, /* 26, -200 ; word cnt */ - 00000, /* GO, 0 ; subr */ - 06604, /* 30, RLCB ; load fnc */ - 06601, /* 31, RLSD ; wait */ - 05031, /* 32, JMP .-1 ; */ - 06617, /* 33, RLSE ; error? */ - 05427, /* 34, JMP I GO ; no, ok */ - 05001 /* 35, JMP BT ; restart */ -}; - - -t_stat rl_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -if (unitno) return SCPE_ARG; /* only unit 0 */ -if (rl_dib.dev != DEV_RL) return STOP_NOTSTD; /* only std devno */ -rl_unit[unitno].TRK = 0; -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} diff --git a/PDP8/pdp8_rx.c b/PDP8/pdp8_rx.c deleted file mode 100644 index ba68fcdd..00000000 --- a/PDP8/pdp8_rx.c +++ /dev/null @@ -1,659 +0,0 @@ -/* pdp8_rx.c: RX8E/RX01, RX28/RX02 floppy disk simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - rx RX8E/RX01, RX28/RX02 floppy disk - - 25-Apr-03 RMS Revised for extended file support - 14-Mar-03 RMS Fixed variable size interaction with save/restore - 03-Mar-03 RMS Fixed autosizing - 08-Oct-02 RMS Added DIB, device number support - Fixed reset to work with disabled device - 15-Sep-02 RMS Added RX28/RX02 support - 06-Jan-02 RMS Changed enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Converted FLG to array - 17-Jul-01 RMS Fixed warning from VC++ 6 - 26-Apr-01 RMS Added device enable/disable support - 13-Apr-01 RMS Revised for register arrays - 14-Apr-99 RMS Changed t_addr to unsigned - 15-Aug-96 RMS Fixed bug in LCD - - An RX01 diskette consists of 77 tracks, each with 26 sectors of 128B. - An RX02 diskette consists of 77 tracks, each with 26 sectors of 128B - (single density) or 256B (double density). Tracks are numbered 0-76, - sectors 1-26. The RX8E (RX28) can store data in 8b mode or 12b mode. - In 8b mode, the controller reads or writes 128 bytes (128B or 256B) - per sector. In 12b mode, it reads or writes 64 (64 or 128) 12b words - per sector. The 12b words are bit packed into the first 96 (192) bytes - of the sector; the last 32 (64) bytes are zeroed on writes. -*/ - -#include "pdp8_defs.h" - -#define RX_NUMTR 77 /* tracks/disk */ -#define RX_M_TRACK 0377 -#define RX_NUMSC 26 /* sectors/track */ -#define RX_M_SECTOR 0177 /* cf Jones!! */ -#define RX_NUMBY 128 /* bytes/sector */ -#define RX2_NUMBY 256 -#define RX_NUMWD (RX_NUMBY / 2) /* words/sector */ -#define RX2_NUMWD (RX2_NUMBY / 2) -#define RX_SIZE (RX_NUMTR * RX_NUMSC * RX_NUMBY) /* bytes/disk */ -#define RX2_SIZE (RX_NUMTR * RX_NUMSC * RX2_NUMBY) -#define RX_NUMDR 2 /* drives/controller */ -#define RX_M_NUMDR 01 -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_DEN (UNIT_V_UF + 1) /* double density */ -#define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize */ -#define UNIT_WLK (1u << UNIT_V_WLK) -#define UNIT_DEN (1u << UNIT_V_DEN) -#define UNIT_AUTO (1u << UNIT_V_AUTO) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -#define IDLE 0 /* idle state */ -#define CMD8 1 /* 8b cmd, ho next */ -#define RWDS 2 /* rw, sect next */ -#define RWDT 3 /* rw, track next */ -#define RWXFR 4 /* rw, transfer */ -#define FILL 5 /* fill buffer */ -#define EMPTY 6 /* empty buffer */ -#define SDCNF 7 /* set dens, conf next */ -#define SDXFR 8 /* set dens, transfer */ -#define CMD_COMPLETE 9 /* set done next */ -#define INIT_COMPLETE 10 /* init compl next */ - -#define RXCS_V_FUNC 1 /* function */ -#define RXCS_M_FUNC 7 -#define RXCS_FILL 0 /* fill buffer */ -#define RXCS_EMPTY 1 /* empty buffer */ -#define RXCS_WRITE 2 /* write sector */ -#define RXCS_READ 3 /* read sector */ -#define RXCS_SDEN 4 /* set density (RX28) */ -#define RXCS_RXES 5 /* read status */ -#define RXCS_WRDEL 6 /* write del data */ -#define RXCS_ECODE 7 /* read error code */ -#define RXCS_DRV 0020 /* drive */ -#define RXCS_MODE 0100 /* mode */ -#define RXCS_MAINT 0200 /* maintenance */ -#define RXCS_DEN 0400 /* density (RX28) */ -#define RXCS_GETFNC(x) (((x) >> RXCS_V_FUNC) & RXCS_M_FUNC) - -#define RXES_CRC 0001 /* CRC error NI */ -#define RXES_ID 0004 /* init done */ -#define RXES_RX02 0010 /* RX02 (RX28) */ -#define RXES_DERR 0020 /* density err (RX28) */ -#define RXES_DEN 0040 /* density (RX28) */ -#define RXES_DD 0100 /* deleted data */ -#define RXES_DRDY 0200 /* drive ready */ - -#define TRACK u3 /* current track */ -#define READ_RXDBR ((rx_csr & RXCS_MODE)? AC | (rx_dbr & 0377): rx_dbr) -#define CALC_DA(t,s,b) (((t) * RX_NUMSC) + ((s) - 1)) * b - -extern int32 int_req, int_enable, dev_done; - -int32 rx_28 = 0; /* controller type */ -int32 rx_tr = 0; /* xfer ready flag */ -int32 rx_err = 0; /* error flag */ -int32 rx_csr = 0; /* control/status */ -int32 rx_dbr = 0; /* data buffer */ -int32 rx_esr = 0; /* error status */ -int32 rx_ecode = 0; /* error code */ -int32 rx_track = 0; /* desired track */ -int32 rx_sector = 0; /* desired sector */ -int32 rx_state = IDLE; /* controller state */ -int32 rx_cwait = 100; /* command time */ -int32 rx_swait = 10; /* seek, per track */ -int32 rx_xwait = 1; /* tr set time */ -int32 rx_stopioe = 0; /* stop on error */ -uint8 rx_buf[RX2_NUMBY] = { 0 }; /* sector buffer */ -static int32 bptr = 0; /* buffer pointer */ - -DEVICE rx_dev; -int32 rx (int32 IR, int32 AC); -t_stat rx_svc (UNIT *uptr); -t_stat rx_reset (DEVICE *dptr); -t_stat rx_boot (int32 unitno, DEVICE *dptr); -t_stat rx_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat rx_attach (UNIT *uptr, char *cptr); -void rx_cmd (void); -void rx_done (int32 esr_flags, int32 new_ecode); -t_stat rx_settype (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat rx_showtype (FILE *st, UNIT *uptr, int32 val, void *desc); - -/* RX8E data structures - - rx_dev RX device descriptor - rx_unit RX unit list - rx_reg RX register list - rx_mod RX modifier list -*/ - -DIB rx_dib = { DEV_RX, 1, { &rx } }; - -UNIT rx_unit[] = { - { UDATA (&rx_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF+ - UNIT_ROABLE, RX_SIZE) }, - { UDATA (&rx_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF+ - UNIT_ROABLE, RX_SIZE) } }; - -REG rx_reg[] = { - { ORDATA (RXCS, rx_csr, 12) }, - { ORDATA (RXDB, rx_dbr, 12) }, - { ORDATA (RXES, rx_esr, 12) }, - { ORDATA (RXERR, rx_ecode, 8) }, - { ORDATA (RXTA, rx_track, 8) }, - { ORDATA (RXSA, rx_sector, 8) }, - { DRDATA (STAPTR, rx_state, 4), REG_RO }, - { DRDATA (BUFPTR, bptr, 8) }, - { FLDATA (TR, rx_tr, 0) }, - { FLDATA (ERR, rx_err, 0) }, - { FLDATA (DONE, dev_done, INT_V_RX) }, - { FLDATA (ENABLE, int_enable, INT_V_RX) }, - { FLDATA (INT, int_req, INT_V_RX) }, - { DRDATA (CTIME, rx_cwait, 24), PV_LEFT }, - { DRDATA (STIME, rx_swait, 24), PV_LEFT }, - { DRDATA (XTIME, rx_xwait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, rx_stopioe, 0) }, - { BRDATA (SBUF, rx_buf, 8, 8, RX2_NUMBY) }, - { FLDATA (RX28, rx_28, 0), REG_HRO }, - { URDATA (CAPAC, rx_unit[0].capac, 10, T_ADDR_W, 0, - RX_NUMDR, REG_HRO | PV_LEFT) }, - { ORDATA (DEVNUM, rx_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB rx_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "RX28", - &rx_settype, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "RX8E", - &rx_settype, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL, - NULL, &rx_showtype, NULL }, - { (UNIT_DEN+UNIT_ATT), UNIT_ATT, "single density", NULL, NULL }, - { (UNIT_DEN+UNIT_ATT), (UNIT_DEN+UNIT_ATT), "double density", NULL, NULL }, - { (UNIT_AUTO+UNIT_DEN+UNIT_ATT), 0, "single density", NULL, NULL }, - { (UNIT_AUTO+UNIT_DEN+UNIT_ATT), UNIT_DEN, "double density", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_DEN), 0, NULL, "SINGLE", &rx_set_size }, - { (UNIT_AUTO+UNIT_DEN), UNIT_DEN, NULL, "DOUBLE", &rx_set_size }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE rx_dev = { - "RX", rx_unit, rx_reg, rx_mod, - RX_NUMDR, 8, 20, 1, 8, 8, - NULL, NULL, &rx_reset, - &rx_boot, &rx_attach, NULL, - &rx_dib, DEV_DISABLE }; - -/* IOT routine */ - -int32 rx (int32 IR, int32 AC) -{ -int32 drv = ((rx_csr & RXCS_DRV)? 1: 0); /* get drive number */ - -switch (IR & 07) { /* decode IR<9:11> */ -case 0: /* unused */ - break; -case 1: /* LCD */ - if (rx_state != IDLE) return AC; /* ignore if busy */ - dev_done = dev_done & ~INT_RX; /* clear done, int */ - int_req = int_req & ~INT_RX; - rx_tr = rx_err = 0; /* clear flags */ - bptr = 0; /* clear buf pointer */ - if (rx_28 && (AC & RXCS_MODE)) { /* RX28 8b mode? */ - rx_dbr = rx_csr = AC & 0377; /* save 8b */ - rx_tr = 1; /* xfer is ready */ - rx_state = CMD8; } /* wait for part 2 */ - else { - rx_dbr = rx_csr = AC; /* save new command */ - rx_cmd (); } /* issue command */ - return 0; /* clear AC */ -case 2: /* XDR */ - switch (rx_state & 017) { /* case on state */ - case EMPTY: /* emptying buffer */ - sim_activate (&rx_unit[drv], rx_xwait); /* sched xfer */ - return READ_RXDBR; /* return data reg */ - case CMD8: /* waiting for cmd */ - rx_dbr = AC & 0377; - rx_csr = (rx_csr & 0377) | ((AC & 017) << 8); - rx_cmd (); - break; - case RWDS:case RWDT:case FILL:case SDCNF: /* waiting for data */ - rx_dbr = AC; /* save data */ - sim_activate (&rx_unit[drv], rx_xwait); /* schedule */ - break; - default: /* default */ - return READ_RXDBR; } /* return data reg */ - break; -case 3: /* STR */ - if (rx_tr != 0) { - rx_tr = 0; - return IOT_SKP + AC; } - break; -case 4: /* SER */ - if (rx_err != 0) { - rx_err = 0; - return IOT_SKP + AC; } - break; -case 5: /* SDN */ - if ((dev_done & INT_RX) != 0) { - dev_done = dev_done & ~INT_RX; - int_req = int_req & ~INT_RX; - return IOT_SKP + AC; } - break; -case 6: /* INTR */ - if (AC & 1) int_enable = int_enable | INT_RX; - else int_enable = int_enable & ~INT_RX; - int_req = INT_UPDATE; - break; -case 7: /* INIT */ - rx_reset (&rx_dev); /* reset device */ - break; } /* end case pulse */ -return AC; -} - -void rx_cmd (void) -{ -int32 drv = ((rx_csr & RXCS_DRV)? 1: 0); /* get drive number */ - -switch (RXCS_GETFNC (rx_csr)) { /* decode command */ -case RXCS_FILL: - rx_state = FILL; /* state = fill */ - rx_tr = 1; /* xfer is ready */ - break; -case RXCS_EMPTY: - rx_state = EMPTY; /* state = empty */ - sim_activate (&rx_unit[drv], rx_xwait); /* sched xfer */ - break; -case RXCS_READ: case RXCS_WRITE: case RXCS_WRDEL: - rx_state = RWDS; /* state = get sector */ - rx_tr = 1; /* xfer is ready */ - rx_esr = rx_esr & RXES_ID; /* clear errors */ - break; -case RXCS_SDEN: - if (rx_28) { /* RX28? */ - rx_state = SDCNF; /* state = get conf */ - rx_tr = 1; /* xfer is ready */ - break; } /* else fall thru */ -default: - rx_state = CMD_COMPLETE; /* state = cmd compl */ - sim_activate (&rx_unit[drv], rx_cwait); /* sched done */ - break; } /* end switch func */ -return; -} - -/* Unit service; the action to be taken depends on the transfer state: - - IDLE Should never get here - RWDS Save sector, set TR, set RWDT - RWDT Save track, set RWXFR - RWXFR Read/write buffer - FILL copy dbr to rx_buf[bptr], advance ptr - if bptr > max, finish command, else set tr - EMPTY if bptr > max, finish command, else - copy rx_buf[bptr] to dbr, advance ptr, set tr - CMD_COMPLETE copy requested data to dbr, finish command - INIT_COMPLETE read drive 0, track 1, sector 1 to buffer, finish command - - For RWDT and CMD_COMPLETE, the input argument is the selected drive; - otherwise, it is drive 0. -*/ - -t_stat rx_svc (UNIT *uptr) -{ -int32 i, func, byptr, bps, wps; -uint32 da; -#define PTR12(x) (((x) + (x) + (x)) >> 1) - -if (rx_28 && (uptr->flags & UNIT_DEN)) - bps = RX2_NUMBY; -else bps = RX_NUMBY; -wps = bps / 2; -func = RXCS_GETFNC (rx_csr); /* get function */ -switch (rx_state) { /* case on state */ - -case IDLE: /* idle */ - return SCPE_IERR; - -case EMPTY: /* empty buffer */ - if (rx_csr & RXCS_MODE) { /* 8b xfer? */ - if (bptr >= bps) { /* done? */ - rx_done (0, 0); /* set done */ - break; } /* and exit */ - rx_dbr = rx_buf[bptr]; } /* else get data */ - else { - byptr = PTR12 (bptr); /* 12b xfer */ - if (bptr >= wps) { /* done? */ - rx_done (0, 0); /* set done */ - break; } /* and exit */ - rx_dbr = (bptr & 1)? /* get data */ - ((rx_buf[byptr] & 017) << 8) | rx_buf[byptr + 1]: - (rx_buf[byptr] << 4) | ((rx_buf[byptr + 1] >> 4) & 017); } - bptr = bptr + 1; - rx_tr = 1; - break; - -case FILL: /* fill buffer */ - if (rx_csr & RXCS_MODE) { /* 8b xfer? */ - rx_buf[bptr] = rx_dbr; /* fill buffer */ - bptr = bptr + 1; - if (bptr < bps) rx_tr = 1; /* if more, set xfer */ - else rx_done (0, 0); } /* else done */ - else { - byptr = PTR12 (bptr); /* 12b xfer */ - if (bptr & 1) { /* odd or even? */ - rx_buf[byptr] = (rx_buf[byptr] & 0360) | ((rx_dbr >> 8) & 017); - rx_buf[byptr + 1] = rx_dbr & 0377; } - else { - rx_buf[byptr] = (rx_dbr >> 4) & 0377; - rx_buf[byptr + 1] = (rx_dbr & 017) << 4; } - bptr = bptr + 1; - if (bptr < wps) rx_tr = 1; /* if more, set xfer */ - else { - for (i = PTR12 (RX_NUMWD); i < RX_NUMBY; i++) - rx_buf[i] = 0; /* else fill sector */ - rx_done (0, 0); } } /* set done */ - break; - -case RWDS: /* wait for sector */ - rx_sector = rx_dbr & RX_M_SECTOR; /* save sector */ - rx_tr = 1; /* set xfer ready */ - rx_state = RWDT; /* advance state */ - return SCPE_OK; -case RWDT: /* wait for track */ - rx_track = rx_dbr & RX_M_TRACK; /* save track */ - rx_state = RWXFR; - sim_activate (uptr, /* sched done */ - rx_swait * abs (rx_track - uptr->TRACK)); - return SCPE_OK; -case RWXFR: /* transfer */ - if ((uptr->flags & UNIT_BUF) == 0) { /* not buffered? */ - rx_done (0, 0110); /* done, error */ - return IORETURN (rx_stopioe, SCPE_UNATT); } - if (rx_track >= RX_NUMTR) { /* bad track? */ - rx_done (0, 0040); /* done, error */ - break; } - uptr->TRACK = rx_track; /* now on track */ - if ((rx_sector == 0) || (rx_sector > RX_NUMSC)) { /* bad sect? */ - rx_done (0, 0070); /* done, error */ - break; } - if (rx_28 && /* RX28? */ - (((uptr->flags & UNIT_DEN) != 0) ^ - ((rx_csr & RXCS_DEN) != 0))) { /* densities agree? */ - rx_done (RXES_DERR, 0240); /* no, error */ - break; } - da = CALC_DA (rx_track, rx_sector, bps); /* get disk address */ - if (func == RXCS_WRDEL) rx_esr = rx_esr | RXES_DD; /* del data? */ - if (func == RXCS_READ) { /* read? */ - for (i = 0; i < bps; i++) - rx_buf[i] = *(((int8 *) uptr->filebuf) + da + i); } - else { /* write */ - if (uptr->flags & UNIT_WPRT) { /* locked? */ - rx_done (0, 0100); /* done, error */ - break; } - for (i = 0; i < RX_NUMBY; i++) /* write */ - *(((int8 *) uptr->filebuf) + da + i) = rx_buf[i]; - da = da + RX_NUMBY; - if (da > uptr->hwmark) uptr->hwmark = da; } - rx_done (0, 0); /* done */ - break; - -case SDCNF: /* confirm set density */ - if ((rx_dbr & 0377) != 0111) { /* confirmed? */ - rx_done (0, 0250); /* no, error */ - break; } - rx_state = SDXFR; /* next state */ - sim_activate (uptr, rx_cwait * 100); /* schedule operation */ - break; -case SDXFR: /* erase disk */ - for (i = 0; i < (int32) uptr->capac; i++) - *(((int8 *) uptr->filebuf) + i) = 0; - uptr->hwmark = uptr->capac; - if (rx_csr & RXCS_DEN) uptr->flags = uptr->flags | UNIT_DEN; - else uptr->flags = uptr->flags & ~UNIT_DEN; - rx_done (0, 0); - break; - -case CMD_COMPLETE: /* command complete */ - if (func == RXCS_ECODE) { /* read ecode? */ - rx_dbr = rx_ecode; /* set dbr */ - rx_done (0, -1); } /* don't update */ - else rx_done (0, 0); - break; - -case INIT_COMPLETE: /* init complete */ - rx_unit[0].TRACK = 1; /* drive 0 to trk 1 */ - rx_unit[1].TRACK = 0; /* drive 1 to trk 0 */ - if ((rx_unit[0].flags & UNIT_BUF) == 0) { /* not buffered? */ - rx_done (RXES_ID, 0010); /* init done, error */ - break; } - da = CALC_DA (1, 1, bps); /* track 1, sector 1 */ - for (i = 0; i < bps; i++) /* read sector */ - rx_buf[i] = *(((int8 *) uptr->filebuf) + da + i); - rx_done (RXES_ID, 0); /* set done */ - if ((rx_unit[1].flags & UNIT_ATT) == 0) rx_ecode = 0020; - break; } /* end case state */ -return SCPE_OK; -} - -/* Command complete. Set done and put final value in interface register, - return to IDLE state. -*/ - -void rx_done (int32 esr_flags, int32 new_ecode) -{ -int32 drv = (rx_csr & RXCS_DRV)? 1: 0; - -rx_state = IDLE; /* now idle */ -dev_done = dev_done | INT_RX; /* set done */ -int_req = INT_UPDATE; /* update ints */ -rx_esr = (rx_esr | esr_flags) & ~(RXES_DRDY|RXES_RX02|RXES_DEN); -if (rx_28) rx_esr = rx_esr | RXES_RX02; /* update estat */ -if (rx_unit[drv].flags & UNIT_ATT) { /* update drv rdy */ - rx_esr = rx_esr | RXES_DRDY; - if (rx_unit[drv].flags & UNIT_DEN) /* update density */ - rx_esr = rx_esr | RXES_DEN; } -if (new_ecode > 0) rx_err = 1; /* test for error */ -if (new_ecode < 0) return; /* don't update? */ -rx_ecode = new_ecode; /* update ecode */ -rx_dbr = rx_esr; /* update RXDB */ -return; -} - -/* Reset routine. The RX is one of the few devices that schedules - an I/O transfer as part of its initialization */ - -t_stat rx_reset (DEVICE *dptr) -{ -rx_dbr = rx_csr = 0; /* 12b mode, drive 0 */ -rx_esr = rx_ecode = 0; /* clear error */ -rx_tr = rx_err = 0; /* clear flags */ -rx_track = rx_sector = 0; /* clear address */ -rx_state = IDLE; /* ctrl idle */ -dev_done = dev_done & ~INT_RX; /* clear done, int */ -int_req = int_req & ~INT_RX; -int_enable = int_enable & ~INT_RX; -sim_cancel (&rx_unit[1]); /* cancel drive 1 */ -if (dptr->flags & DEV_DIS) sim_cancel (&rx_unit[0]); /* disabled? */ -else if (rx_unit[0].flags & UNIT_BUF) { /* attached? */ - rx_state = INIT_COMPLETE; /* yes, sched init */ - sim_activate (&rx_unit[0], rx_swait * abs (1 - rx_unit[0].TRACK)); } -else rx_done (rx_esr | RXES_ID, 0010); /* no, error */ -return SCPE_OK; -} - -/* Attach routine */ - -t_stat rx_attach (UNIT *uptr, char *cptr) -{ -uint32 sz; - -if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) { - if (sz > RX_SIZE) uptr->flags = uptr->flags | UNIT_DEN; - else uptr->flags = uptr->flags & ~UNIT_DEN; } -uptr->capac = (uptr->flags & UNIT_DEN)? RX2_SIZE: RX_SIZE; -return attach_unit (uptr, cptr); -} - -/* Set size routine */ - -t_stat rx_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -if ((rx_28 == 0) && val) return SCPE_NOFNC; /* not on RX8E */ -uptr->capac = val? RX2_SIZE: RX_SIZE; -return SCPE_OK; -} - -/* Set controller type */ - -t_stat rx_settype (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 i; - -if ((val < 0) || (val > 1) || (cptr != NULL)) return SCPE_ARG; -if (val == rx_28) return SCPE_OK; -for (i = 0; i < RX_NUMDR; i++) { - if (rx_unit[i].flags & UNIT_ATT) return SCPE_ALATT; } -for (i = 0; i < RX_NUMDR; i++) { - rx_unit[i].flags = rx_unit[i].flags & ~(UNIT_DEN | UNIT_AUTO); - rx_unit[i].capac = RX_SIZE; - if (val) rx_unit[i].flags = rx_unit[i].flags | UNIT_AUTO; } -rx_28 = val; -return SCPE_OK; -} - -/* Show controller type */ - -t_stat rx_showtype (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (rx_28) fprintf (st, "RX28"); -else fprintf (st, "RX8E"); -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define BOOT_START 022 -#define BOOT_ENTRY 022 -#define BOOT_INST 060 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) -#define BOOT2_START 020 -#define BOOT2_ENTRY 033 -#define BOOT2_LEN (sizeof (boot2_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 06755, /* 22, SDN */ - 05022, /* 23, JMP .-1 */ - 07126, /* 24, CLL CML RTL ; read command + */ - 01060, /* 25, TAD UNIT ; unit no */ - 06751, /* 26, LCD ; load read+unit */ - 07201, /* 27, CLA IAC ; AC = 1 */ - 04053, /* 30, JMS LOAD ; load sector */ - 04053, /* 31, JMS LOAD ; load track */ - 07104, /* 32, CLL RAL ; AC = 2 */ - 06755, /* 33, SDN */ - 05054, /* 34, JMP LOAD+1 */ - 06754, /* 35, SER */ - 07450, /* 36, SNA ; more to do? */ - 07610, /* 37, CLA SKP ; error */ - 05046, /* 40, JMP 46 ; go empty */ - 07402, /* 41-45, HALT ; error */ - 07402, - 07402, - 07402, - 07402, - 06751, /* 46, LCD ; load empty */ - 04053, /* 47, JMS LOAD ; get data */ - 03002, /* 50, DCA 2 ; store */ - 02050, /* 51, ISZ 50 ; incr store */ - 05047, /* 52, JMP 47 ; loop until done */ - 00000, /* LOAD, 0 */ - 06753, /* 54, STR */ - 05033, /* 55, JMP 33 */ - 06752, /* 56, XDR */ - 05453, /* 57, JMP I LOAD */ - 07024, /* UNIT, CML RAL ; for unit 1 */ - 06030 /* 61, KCC */ -}; - -static const uint16 boot2_rom[] = { - 01061, /* READ, TAD UNIT ; next unit+den */ - 01046, /* 21, TAD CON360 ; add in 360 */ - 00060, /* 22, AND CON420 ; mask to 420 */ - 03061, /* 23, DCA UNIT ; 400,420,0,20... */ - 07327, /* 24, STL CLA IAC RTL ; AC = 6 = read */ - 01061, /* 25, TAD UNIT ; +unit+den */ - 06751, /* 26, LCD ; load cmd */ - 07201, /* 27, CLA IAC; ; AC = 1 = trksec */ - 04053, /* 30, JMS LOAD ; load trk */ - 04053, /* 31, JMS LOAD ; load sec */ - 07004, /* CN7004, RAL ; AC = 2 = empty */ - 06755, /* START, SDN ; done? */ - 05054, /* 34, JMP LOAD+1 ; check xfr */ - 06754, /* 35, SER ; error? */ - 07450, /* 36, SNA ; AC=0 on start */ - 05020, /* 37, JMP RD ; try next den,un */ - 01061, /* 40, TAD UNIT ; +unit+den */ - 06751, /* 41, LCD ; load cmd */ - 01061, /* 42, TAD UNIT ; set 60 for sec boot */ - 00046, /* 43, AND CON360 ; only density */ - 01032, /* 44, TAD CN7004 ; magic */ - 03060, /* 45, DCA 60 */ - 00360, /* CON360, 360 ; NOP */ - 04053, /* 47, JMS LOAD ; get data */ - 03002, /* 50, DCA 2 ; store */ - 02050, /* 51, ISZ .-1 ; incr store */ - 05047, /* 52, JMP .-3 ; loop until done */ - 00000, /* LOAD, 0 */ - 06753, /* 54, STR ; xfr ready? */ - 05033, /* 55, JMP 33 ; no, chk done */ - 06752, /* 56, XDR ; get word */ - 05453, /* 57, JMP I 53 ; return */ - 00420, /* CON420, 420 ; toggle */ - 00020 /* UNIT, 20 ; unit+density */ -}; - -t_stat rx_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; -extern uint16 M[]; - -if (rx_dib.dev != DEV_RX) return STOP_NOTSTD; /* only std devno */ -if (rx_28) { - for (i = 0; i < BOOT2_LEN; i++) M[BOOT2_START + i] = boot2_rom[i]; - saved_PC = BOOT2_ENTRY; } -else { - for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; - M[BOOT_INST] = unitno? 07024: 07004; - saved_PC = BOOT_ENTRY; } -return SCPE_OK; -} diff --git a/PDP8/pdp8_sys.c b/PDP8/pdp8_sys.c deleted file mode 100644 index 9149e149..00000000 --- a/PDP8/pdp8_sys.c +++ /dev/null @@ -1,515 +0,0 @@ -/* pdp8_sys.c: PDP-8 simulator interface - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 25-Apr-03 RMS Revised for extended file support - 30-Dec-01 RMS Revised for new TTX - 26-Nov-01 RMS Added RL8A support - 17-Sep-01 RMS Removed multiconsole support - 16-Sep-01 RMS Added TSS/8 packed char support, added KL8A support - 27-May-01 RMS Added multiconsole support - 18-Mar-01 RMS Added DF32 support - 14-Mar-01 RMS Added extension detection of RIM binary tapes - 15-Feb-01 RMS Added DECtape support - 30-Oct-00 RMS Added support for examine to file - 27-Oct-98 RMS V2.4 load interface - 10-Apr-98 RMS Added RIM loader support - 17-Feb-97 RMS Fixed bug in handling of bin loader fields -*/ - -#include "pdp8_defs.h" -#include - -extern DEVICE cpu_dev; -extern UNIT cpu_unit; -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE tti_dev, tto_dev; -extern DEVICE clk_dev, lpt_dev; -extern DEVICE rk_dev, rl_dev; -extern DEVICE rx_dev; -extern DEVICE df_dev, rf_dev; -extern DEVICE dt_dev, mt_dev; -extern DEVICE ttix_dev, ttox_dev; -extern REG cpu_reg[]; -extern uint16 M[]; -extern int32 sim_switches; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax maximum number of words for examine/deposit - sim_devices array of pointers to simulated devices - sim_consoles array of pointers to consoles (if more than one) - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "PDP-8"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { - &cpu_dev, - &ptr_dev, &ptp_dev, - &tti_dev, &tto_dev, - &ttix_dev, &ttox_dev, - &clk_dev, &lpt_dev, - &rk_dev, &rl_dev, - &rx_dev, - &df_dev, &rf_dev, - &dt_dev, &mt_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unimplemented instruction", - "HALT instruction", - "Breakpoint", - "Non-standard device number" }; - -/* Binary loader - - Two loader formats are supported: RIM loader (-r) and BIN (-b) loader. - - RIM loader format consists of alternating pairs of addresses and 12-bit - words. It can only operate in field 0 and is not checksummed. - - BIN loader format consists of a string of 12-bit words (made up from - 7-bit characters) between leader and trailer (200). The last word on - tape is the checksum. A word with the "link" bit set is a new origin; - a character > 0200 indicates a change of field. -*/ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 rubout, word, low, high, csum, newf, state, i; -uint32 origin, field; - -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; -rubout = state = field = newf = origin = csum = 0; -if ((sim_switches & SWMASK ('R')) || /* RIM format? */ - (match_ext (fnam, "RIM") && !(sim_switches & SWMASK ('B')))) { - while ((i = getc (fileref)) != EOF) { - switch (state) { - case 0: /* leader */ - if ((i != 0) && (i < 0200)) state = 1; - high = i; - break; - case 1: /* low byte */ - word = (high << 6) | i; /* form word */ - if (word > 07777) origin = word & 07777; - else M[origin] = word; - state = 2; - break; - case 2: /* high byte */ - if (i >= 0200) return SCPE_OK; /* end of tape? */ - high = i; /* save high */ - state = 1; - break; } /* end switch */ - } /* end while */ - } /* end if */ -else { while ((i = getc (fileref)) != EOF) { /* BIN format */ - if (rubout) { - rubout = 0; - continue; } - if (i == 0377) { - rubout = 1; - continue; } - if (i > 0200) { - newf = (i & 070) << 9; - continue; } - switch (state) { - case 0: /* leader */ - if ((i != 0) && (i != 0200)) state = 1; - high = i; /* save as high */ - break; - case 1: /* low byte */ - low = i; - state = 2; - break; - case 2: /* high with test */ - word = (high << 6) | low; - if (i == 0200) { /* end of tape? */ - if ((csum - word) & 07777) return SCPE_CSUM; - return SCPE_OK; } - csum = csum + low + high; - if (word >= 010000) origin = word & 07777; - else { - if ((field | origin) >= MEMSIZE) - return SCPE_NXM; - M[field | origin] = word & 07777; - origin = (origin + 1) & 07777; } - field = newf; - high = i; - state = 1; - break; } /* end switch */ - } /* end while */ - } /* end else */ -return SCPE_FMT; /* eof? error */ -} - -/* Symbol tables */ - -#define I_V_FL 18 /* flag start */ -#define I_M_FL 07 /* flag mask */ -#define I_V_NPN 0 /* no operand */ -#define I_V_FLD 1 /* field change */ -#define I_V_MRF 2 /* mem ref */ -#define I_V_IOT 3 /* general IOT */ -#define I_V_OP1 4 /* operate 1 */ -#define I_V_OP2 5 /* operate 2 */ -#define I_V_OP3 6 /* operate 3 */ -#define I_NPN (I_V_NPN << I_V_FL) -#define I_FLD (I_V_FLD << I_V_FL) -#define I_MRF (I_V_MRF << I_V_FL) -#define I_IOT (I_V_IOT << I_V_FL) -#define I_OP1 (I_V_OP1 << I_V_FL) -#define I_OP2 (I_V_OP2 << I_V_FL) -#define I_OP3 (I_V_OP3 << I_V_FL) - -static const int32 masks[] = { - 07777, 07707, 07000, 07000, - 07416, 07571, 017457 }; - -static const char *opcode[] = { - "SKON", "ION", "IOF", "SRQ", - "GTF", "RTF", "SGT", "CAF", - "RPE", "RSF", "RRB", "RFC", "RFC RRB", - "PCE", "PSF", "PCF", "PPC", "PLS", - "KCF", "KSF", "KCC", "KRS", "KIE", "KRB", - "TLF", "TSF", "TCF", "TPC", "SPI", "TLS", - "SBE", "SPL", "CAL", - "CLEI", "CLDI", "CLSC", "CLLE", "CLCL", "CLSK", - "CINT", "RDF", "RIF", "RIB", - "RMF", "SINT", "CUF", "SUF", - "ADCL", "ADLM", "ADST", "ADRB", - "ADSK", "ADSE", "ADLE", "ADRS", - "DCMA", "DMAR", "DMAW", - "DCIM", "DSAC", "DIML", "DIMA", - "DCEA", "DEAL", "DEAC", - "DFSE", "DFSC", "DISK", "DMAC", - "DCXA", "DXAL", "DXAC", - "PSKF", "PCLF", "PSKE", - "PSTB", "PSIE", "PCLF PSTB", "PCIE", - "LWCR", "CWCR", "LCAR", - "CCAR", "LCMR", "LFGR", "LDBR", - "RWCR", "CLT", "RCAR", - "RMSR", "RCMR", "RFSR", "RDBR", - "SKEF", "SKCB", "SKJD", "SKTR", "CLF", - "DSKP", "DCLR", "DLAG", - "DLCA", "DRST", "DLDC", "DMAN", - "LCD", "XDR", "STR", - "SER", "SDN", "INTR", "INIT", - "DTRA", "DTCA", "DTXA", "DTLA", - "DTSF", "DTRB", "DTLB", - "RLDC", "RLSD", "RLMA", "RLCA", - "RLCB", "RLSA", "RLWC", - "RRER", "RRWC", "RRCA", "RRCB", - "RRSA", "RRSI", "RLSE", - - "CDF", "CIF", "CIF CDF", - "AND", "TAD", "ISZ", "DCA", "JMS", "JMP", "IOT", - "NOP", "NOP2", "NOP3", "SWAB", "SWBA", - "STL", "GLK", "STA", "LAS", "CIA", - "BSW", "RAL", "RTL", "RAR", "RTR", "RAL RAR", "RTL RTR", - "SKP", "SNL", "SZL", - "SZA", "SNA", "SZA SNL", "SNA SZL", - "SMA", "SPA", "SMA SNL", "SPA SZL", - "SMA SZA", "SPA SNA", "SMA SZA SNL", "SPA SNA SZL", - "SCL", "MUY", "DVI", "NMI", "SHL", "ASR", "LSR", - "SCA", "SCA SCL", "SCA MUY", "SCA DVI", - "SCA NMI", "SCA SHL", "SCA ASR", "SCA LSR", - "ACS", "MUY", "DVI", "NMI", "SHL", "ASR", "LSR", - "SCA", "DAD", "DST", "SWBA", - "DPSZ", "DPIC", "DCIM", "SAM", - "CLA", "CLL", "CMA", "CML", "IAC", /* encode only */ - "CLA", "OAS", "HLT", - "CLA", "MQA", "MQL", - NULL, NULL, NULL, NULL, /* decode only */ - NULL }; - -static const int32 opc_val[] = { - 06000+I_NPN, 06001+I_NPN, 06002+I_NPN, 06003+I_NPN, - 06004+I_NPN, 06005+I_NPN, 06006+I_NPN, 06007+I_NPN, - 06010+I_NPN, 06011+I_NPN, 06012+I_NPN, 06014+I_NPN, 06016+I_NPN, - 06020+I_NPN, 06021+I_NPN, 06022+I_NPN, 06024+I_NPN, 06026+I_NPN, - 06030+I_NPN, 06031+I_NPN, 06032+I_NPN, 06034+I_NPN, 06035+I_NPN, 06036+I_NPN, - 06040+I_NPN, 06041+I_NPN, 06042+I_NPN, 06044+I_NPN, 06045+I_NPN, 06046+I_NPN, - 06101+I_NPN, 06102+I_NPN, 06103+I_NPN, - 06131+I_NPN, 06132+I_NPN, 06133+I_NPN, 06135+I_NPN, 06136+I_NPN, 06137+I_NPN, - 06204+I_NPN, 06214+I_NPN, 06224+I_NPN, 06234+I_NPN, - 06244+I_NPN, 06254+I_NPN, 06264+I_NPN, 06274+I_NPN, - 06530+I_NPN, 06531+I_NPN, 06532+I_NPN, 06533+I_NPN, - 06534+I_NPN, 06535+I_NPN, 06536+I_NPN, 06537+I_NPN, - 06601+I_NPN, 06603+I_NPN, 06605+I_NPN, - 06611+I_NPN, 06612+I_NPN, 06615+I_NPN, 06616+I_NPN, - 06611+I_NPN, 06615+I_NPN, 06616+I_NPN, - 06621+I_NPN, 06622+I_NPN, 06623+I_NPN, 06626+I_NPN, - 06641+I_NPN, 06643+I_NPN, 06645+I_NPN, - 06661+I_NPN, 06662+I_NPN, 06663+I_NPN, - 06664+I_NPN, 06665+I_NPN, 06666+I_NPN, 06667+I_NPN, - 06701+I_NPN, 06702+I_NPN, 06703+I_NPN, - 06704+I_NPN, 06705+I_NPN, 06706+I_NPN, 06707+I_NPN, - 06711+I_NPN, 06712+I_NPN, 06713+I_NPN, - 06714+I_NPN, 06715+I_NPN, 06716+I_NPN, 06717+I_NPN, - 06721+I_NPN, 06722+I_NPN, 06723+I_NPN, 06724+I_NPN, 06725+I_NPN, - 06741+I_NPN, 06742+I_NPN, 06743+I_NPN, - 06744+I_NPN, 06745+I_NPN, 06746+I_NPN, 06747+I_NPN, - 06751+I_NPN, 06752+I_NPN, 06753+I_NPN, - 06754+I_NPN, 06755+I_NPN, 06756+I_NPN, 06757+I_NPN, - 06761+I_NPN, 06762+I_NPN, 06764+I_NPN, 06766+I_NPN, - 06771+I_NPN, 06772+I_NPN, 06774+I_NPN, - 06600+I_NPN, 06601+I_NPN, 06602+I_NPN, 06603+I_NPN, - 06604+I_NPN, 06605+I_NPN, 06607+I_NPN, - 06610+I_NPN, 06611+I_NPN, 06612+I_NPN, 06613+I_NPN, - 06614+I_NPN, 06615+I_NPN, 06617+I_NPN, - - 06201+I_FLD, 06202+I_FLD, 06203+I_FLD, - 00000+I_MRF, 01000+I_MRF, 02000+I_MRF, 03000+I_MRF, - 04000+I_MRF, 05000+I_MRF, 06000+I_IOT, - 07000+I_NPN, 07400+I_NPN, 07401+I_NPN, 07431+I_NPN, 07447+I_NPN, - 07120+I_NPN, 07204+I_NPN, 07240+I_NPN, 07604+I_NPN, 07041+I_NPN, - 07002+I_OP1, 07004+I_OP1, 07006+I_OP1, - 07010+I_OP1, 07012+I_OP1, 07014+I_OP1, 07016+I_OP1, - 07410+I_OP2, 07420+I_OP2, 07430+I_OP2, - 07440+I_OP2, 07450+I_OP2, 07460+I_OP2, 07470+I_OP2, - 07500+I_OP2, 07510+I_OP2, 07520+I_OP2, 07530+I_OP2, - 07540+I_OP2, 07550+I_OP2, 07560+I_OP2, 07570+I_OP2, - 07403+I_OP3, 07405+I_OP3, 07407+I_OP3, - 07411+I_OP3, 07413+I_OP3, 07415+I_OP3, 07417+I_OP3, - 07441+I_OP3, 07443+I_OP3, 07445+I_OP3, 07447+I_OP3, - 07451+I_OP3, 07453+I_OP3, 07455+I_OP3, 07457+I_OP3, - 017403+I_OP3, 017405+I_OP3, 0174017+I_OP3, - 017411+I_OP3, 017413+I_OP3, 017415+I_OP3, 017417+I_OP3, - 017441+I_OP3, 017443+I_OP3, 017445+I_OP3, 017447+I_OP3, - 017451+I_OP3, 017453+I_OP3, 017455+I_OP3, 017457+I_OP3, - 07200+I_OP1, 07100+I_OP1, 07040+I_OP1, 07020+I_OP1, 07001+I_OP1, - 07600+I_OP2, 07404+I_OP2, 07402+I_OP2, - 07601+I_OP3, 07501+I_OP3, 07421+I_OP3, - 07000+I_OP1, 07400+I_OP2, 07401+I_OP3, 017401+I_OP3, - -1 }; - -/* Operate decode - - Inputs: - *of = output stream - inst = mask bits - class = instruction class code - sp = space needed? - Outputs: - status = space needed -*/ - -int32 fprint_opr (FILE *of, int32 inst, int32 class, int32 sp) -{ -int32 i, j; - -for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - if ((j == class) && (opc_val[i] & inst)) { /* same class? */ - inst = inst & ~opc_val[i]; /* mask bit set? */ - fprintf (of, (sp? " %s": "%s"), opcode[i]); - sp = 1; } } -return sp; -} - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current PC - *val = pointer to data - *uptr = pointer to unit - sw = switches - Outputs: - return = status code -*/ - -#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) -#define SIXTOASC(x) (((x) >= 040)? (x): (x) + 0100) -#define TSSTOASC(x) ((x) + 040) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, i, j, sp, inst, disp; -extern int32 emode; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -inst = val[0]; -if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; - fprintf (of, FMTASC (inst & 0177)); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* characters? */ - fprintf (of, "%c", SIXTOASC ((inst >> 6) & 077)); - fprintf (of, "%c", SIXTOASC (inst & 077)); - return SCPE_OK; } -if (sw & SWMASK ('T')) { /* TSS8 packed? */ - fprintf (of, "%c", TSSTOASC ((inst >> 6) & 077)); - fprintf (of, "%c", TSSTOASC (inst & 077)); - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; - -/* Instruction decode */ - -inst = val[0] | ((emode & 1) << 12); /* include EAE mode */ -for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - if ((opc_val[i] & 017777) == (inst & masks[j])) { /* match? */ - - switch (j) { /* case on class */ - case I_V_NPN: /* no operands */ - fprintf (of, "%s", opcode[i]); /* opcode */ - break; - case I_V_FLD: /* field change */ - fprintf (of, "%s %-o", opcode[i], (inst >> 3) & 07); - break; - case I_V_MRF: /* mem ref */ - disp = inst & 0177; /* displacement */ - fprintf (of, "%s%s", opcode[i], ((inst & 00400)? " I ": " ")); - if (inst & 0200) { /* current page? */ - if (cflag) fprintf (of, "%-o", (addr & 07600) | disp); - else fprintf (of, "C %-o", disp); } - else fprintf (of, "%-o", disp); /* page zero */ - break; - case I_V_IOT: /* IOT */ - fprintf (of, "%s %-o", opcode[i], inst & 0777); - break; - case I_V_OP1: /* operate group 1 */ - sp = fprint_opr (of, inst & 0361, j, 0); - if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]); - break; - case I_V_OP2: /* operate group 2 */ - if (opcode[i]) fprintf (of, "%s", opcode[i]); /* skips */ - fprint_opr (of, inst & 0206, j, opcode[i] != NULL); - break; - case I_V_OP3: /* operate group 3 */ - sp = fprint_opr (of, inst & 0320, j, 0); - if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]); - break; } /* end case */ - return SCPE_OK; } /* end if */ - } /* end for */ -return SCPE_ARG; -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = error status -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 cflag, d, i, j, k; -t_stat r; -char gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ -if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (t_value) cptr[0] | 0200; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (((t_value) cptr[0] & 077) << 6) | - ((t_value) cptr[1] & 077); - return SCPE_OK; } -if ((sw & SWMASK ('T')) || ((*cptr == '"') && cptr++)) { /* TSS8 string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (((t_value) (cptr[0] - 040) & 077) << 6) | - ((t_value) (cptr[1] - 040) & 077); - return SCPE_OK; } - -/* Instruction parse */ - -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; -if (opcode[i] == NULL) return SCPE_ARG; -val[0] = opc_val[i] & 07777; /* get value */ -j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - -switch (j) { /* case on class */ -case I_V_IOT: /* IOT */ - cptr = get_glyph (cptr, gbuf, 0); /* get dev+pulse */ - d = get_uint (gbuf, 8, 0777, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | d; - break; -case I_V_FLD: /* field */ - for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; - cptr = get_glyph (cptr, gbuf, 0)) { - for (i = 0; (opcode[i] != NULL) && - (strcmp (opcode[i], gbuf) != 0) ; i++) ; - if (opcode[i] != NULL) { - k = (opc_val[i] >> I_V_FL) & I_M_FL; - if (k != j) return SCPE_ARG; - val[0] = val[0] | (opc_val[i] & 07777); } - else { - d = get_uint (gbuf, 8, 07, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << 3); - break; } } - break; -case I_V_MRF: /* mem ref */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - if (strcmp (gbuf, "I") == 0) { /* indirect? */ - val[0] = val[0] | 0400; - cptr = get_glyph (cptr, gbuf, 0); } - if ((k = (strcmp (gbuf, "C") == 0)) || (strcmp (gbuf, "Z") == 0)) { - cptr = get_glyph (cptr, gbuf, 0); - d = get_uint (gbuf, 8, 0177, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | d | (k? 0200: 0); } - else { - d = get_uint (gbuf, 8, 07777, &r); - if (r != SCPE_OK) return SCPE_ARG; - if (d <= 0177) val[0] = val[0] | d; - else if (cflag && (((addr ^ d) & 07600) == 0)) - val[0] = val[0] | (d & 0177) | 0200; - else return SCPE_ARG; } - break; -case I_V_NPN: case I_V_OP1: case I_V_OP2: case I_V_OP3: /* operates */ - for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; - cptr = get_glyph (cptr, gbuf, 0)) { - for (i = 0; (opcode[i] != NULL) && - (strcmp (opcode[i], gbuf) != 0) ; i++) ; - k = opc_val[i] & 07777; - if ((opcode[i] == NULL) || (((k ^ val[0]) & 07000) != 0)) - return SCPE_ARG; - val[0] = val[0] | k; } - break; } /* end case */ -if (*cptr != 0) return SCPE_ARG; /* junk at end? */ -return SCPE_OK; -} diff --git a/PDP8/pdp8_tt.c b/PDP8/pdp8_tt.c deleted file mode 100644 index 33712fb5..00000000 --- a/PDP8/pdp8_tt.c +++ /dev/null @@ -1,264 +0,0 @@ -/* pdp8_tt.c: PDP-8 console terminal simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - tti,tto KL8E terminal input/output - - 25-Apr-03 RMS Revised for extended file support - 02-Mar-02 RMS Added SET TTI CTRL-C - 22-Dec-02 RMS Added break support - 01-Nov-02 RMS Added 7B/8B support - 04-Oct-02 RMS Added DIBs, device number support - 30-May-02 RMS Widened POS to 32b - 07-Sep-01 RMS Moved function prototypes -*/ - -#include "pdp8_defs.h" -#include - -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_KSR (1 << UNIT_V_KSR) - -extern int32 int_req, int_enable, dev_done, stop_inst; - -int32 tti (int32 IR, int32 AC); -int32 tto (int32 IR, int32 AC); -t_stat tti_svc (UNIT *uptr); -t_stat tto_svc (UNIT *uptr); -t_stat tti_reset (DEVICE *dptr); -t_stat tto_reset (DEVICE *dptr); -t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit descriptor - tti_reg TTI register list - tti_mod TTI modifiers list -*/ - -DIB tti_dib = { DEV_TTI, 1, { &tti } }; - -UNIT tti_unit = { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }; - -REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, 8) }, - { FLDATA (DONE, dev_done, INT_V_TTI) }, - { FLDATA (ENABLE, int_enable, INT_V_TTI) }, - { FLDATA (INT, int_req, INT_V_TTI) }, - { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (UC, tti_unit.flags, UNIT_V_KSR), REG_HRO }, - { NULL } }; - -MTAB tti_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, - { MTAB_XTD|MTAB_VDV|MTAB_VUN, 0, NULL, "CTRL-C", &tti_set_ctrlc, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev, NULL }, - { 0 } }; - -DEVICE tti_dev = { - "TTI", &tti_unit, tti_reg, tti_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tti_reset, - NULL, NULL, NULL, - &tti_dib, 0 }; - -/* TTO data structures - - tto_dev TTO device descriptor - tto_unit TTO unit descriptor - tto_reg TTO register list -*/ - -DIB tto_dib = { DEV_TTO, 1, { &tto } }; - -UNIT tto_unit = { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }; - -REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, 8) }, - { FLDATA (DONE, dev_done, INT_V_TTO) }, - { FLDATA (ENABLE, int_enable, INT_V_TTO) }, - { FLDATA (INT, int_req, INT_V_TTO) }, - { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -MTAB tto_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev }, - { 0 } }; - -DEVICE tto_dev = { - "TTO", &tto_unit, tto_reg, tto_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto_reset, - NULL, NULL, NULL, - &tto_dib, 0 }; - -/* Terminal input: IOT routine */ - -int32 tti (int32 IR, int32 AC) -{ -switch (IR & 07) { /* decode IR<9:11> */ -case 0: /* KCF */ - dev_done = dev_done & ~INT_TTI; /* clear flag */ - int_req = int_req & ~INT_TTI; - return AC; -case 1: /* KSF */ - return (dev_done & INT_TTI)? IOT_SKP + AC: AC; -case 2: /* KCC */ - dev_done = dev_done & ~INT_TTI; /* clear flag */ - int_req = int_req & ~INT_TTI; - return 0; /* clear AC */ -case 4: /* KRS */ - return (AC | tti_unit.buf); /* return buffer */ -case 5: /* KIE */ - if (AC & 1) int_enable = int_enable | (INT_TTI+INT_TTO); - else int_enable = int_enable & ~(INT_TTI+INT_TTO); - int_req = INT_UPDATE; /* update interrupts */ - return AC; -case 6: /* KRB */ - dev_done = dev_done & ~INT_TTI; /* clear flag */ - int_req = int_req & ~INT_TTI; - return (tti_unit.buf); /* return buffer */ -default: - return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ -} - -/* Unit service */ - -t_stat tti_svc (UNIT *uptr) -{ -int32 c; - -sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ -if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -if (c & SCPE_BREAK) tti_unit.buf = 0; /* break? */ -else if (tti_unit.flags & UNIT_KSR) { /* KSR? */ - c = c & 0177; - if (islower (c)) c = toupper (c); - tti_unit.buf = c | 0200; } /* add TTY bit */ -else tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177); -tti_unit.pos = tti_unit.pos + 1; -dev_done = dev_done | INT_TTI; /* set done */ -int_req = INT_UPDATE; /* update interrupts */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tti_reset (DEVICE *dptr) -{ -tti_unit.buf = 0; -dev_done = dev_done & ~INT_TTI; /* clear done, int */ -int_req = int_req & ~INT_TTI; -int_enable = int_enable | INT_TTI; /* set enable */ -sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ -return SCPE_OK; -} - -/* Set control-C */ - -t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -uptr->buf = (uptr->flags & UNIT_KSR)? 0203: 0003; -uptr->pos = uptr->pos + 1; -dev_done = dev_done | INT_TTI; /* set done */ -int_req = INT_UPDATE; /* update interrupts */ -return SCPE_OK; -} - -/* Terminal output: IOT routine */ - -int32 tto (int32 IR, int32 AC) -{ -switch (IR & 07) { /* decode IR<9:11> */ -case 0: /* TLF */ - dev_done = dev_done | INT_TTO; /* set flag */ - int_req = INT_UPDATE; /* update interrupts */ - return AC; -case 1: /* TSF */ - return (dev_done & INT_TTO)? IOT_SKP + AC: AC; -case 2: /* TCF */ - dev_done = dev_done & ~INT_TTO; /* clear flag */ - int_req = int_req & ~INT_TTO; /* clear int req */ - return AC; -case 5: /* SPI */ - return (int_req & (INT_TTI+INT_TTO))? IOT_SKP + AC: AC; -case 6: /* TLS */ - dev_done = dev_done & ~INT_TTO; /* clear flag */ - int_req = int_req & ~INT_TTO; /* clear int req */ -case 4: /* TPC */ - sim_activate (&tto_unit, tto_unit.wait); /* activate unit */ - tto_unit.buf = AC; /* load buffer */ - return AC; -default: - return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ -} - -/* Unit service */ - -t_stat tto_svc (UNIT *uptr) -{ -int32 c; -t_stat r; - -dev_done = dev_done | INT_TTO; /* set done */ -int_req = INT_UPDATE; /* update interrupts */ -if (tto_unit.flags & UNIT_KSR) { /* UC only? */ - c = tto_unit.buf & 0177; - if (islower (c)) c = toupper (c); } -else c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); -if ((r = sim_putchar (c)) != SCPE_OK) return r; -tto_unit.pos = tto_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tto_reset (DEVICE *dptr) -{ -tto_unit.buf = 0; -dev_done = dev_done & ~INT_TTO; /* clear done, int */ -int_req = int_req & ~INT_TTO; -int_enable = int_enable | INT_TTO; /* set enable */ -sim_cancel (&tto_unit); /* deactivate unit */ -return SCPE_OK; -} - -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -tti_unit.flags = (tti_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; -tto_unit.flags = (tto_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; -return SCPE_OK; -} diff --git a/PDP8/pdp8_ttx.c b/PDP8/pdp8_ttx.c deleted file mode 100644 index ac6d3125..00000000 --- a/PDP8/pdp8_ttx.c +++ /dev/null @@ -1,383 +0,0 @@ -/* pdp8_ttx.c: PDP-8 additional terminals simulator - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - ttix,ttox PT08/KL8JA terminal input/output - - 09-May-03 RMS Added network device flag - 25-Apr-03 RMS Revised for extended file support - 22-Dec-02 RMS Added break support - 02-Nov-02 RMS Added 7B/8B support - 04-Oct-02 RMS Added DIB, device number support - 22-Aug-02 RMS Updated for changes to sim_tmxr.c - 06-Jan-02 RMS Added device enable/disable support - 30-Dec-01 RMS Complete rebuild - 30-Nov-01 RMS Added extended SET/SHOW support - - This module implements four individual serial interfaces similar in function - to the console. These interfaces are mapped to Telnet based connections as - though they were the four lines of a terminal multiplexor. The connection - polling mechanism is superimposed onto the keyboard of the first interface. -*/ - -#include "pdp8_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" -#include - -#define TTX_LINES 4 -#define TTX_MASK (TTX_LINES - 1) - -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_UC (UNIT_V_UF + 1) /* upper case */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_UC (1 << UNIT_V_UC) - -#define TTX_GETLN(x) (((x) >> 4) & TTX_MASK) - -extern int32 int_req, int_enable, dev_done, stop_inst; - -uint8 ttix_buf[TTX_LINES] = { 0 }; /* input buffers */ -uint8 ttox_buf[TTX_LINES] = { 0 }; /* output buffers */ -int32 ttx_tps = 100; /* polls per second */ -TMLN ttx_ldsc[TTX_LINES] = { 0 }; /* line descriptors */ -TMXR ttx_desc = { /* mux descriptor */ - TTX_LINES, 0, 0, &ttx_ldsc[0], &ttx_ldsc[1], &ttx_ldsc[2], &ttx_ldsc[3] }; - -DEVICE ttix_dev, ttox_dev; -int32 ttix (int32 IR, int32 AC); -int32 ttox (int32 IR, int32 AC); -t_stat ttix_svc (UNIT *uptr); -t_stat ttix_reset (DEVICE *dptr); -t_stat ttox_svc (UNIT *uptr); -t_stat ttox_reset (DEVICE *dptr); -t_stat ttx_attach (UNIT *uptr, char *cptr); -t_stat ttx_detach (UNIT *uptr); -t_stat ttx_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc); -void ttx_enbdis (int32 dis); - -/* TTIx data structures - - ttix_dev TTIx device descriptor - ttix_unit TTIx unit descriptor - ttix_reg TTIx register list - ttix_mod TTIx modifiers list -*/ - -DIB ttix_dib = { DEV_KJ8, 8, - { &ttix, &ttox, &ttix, &ttox, &ttix, &ttox, &ttix, &ttox } }; - -UNIT ttix_unit = { UDATA (&ttix_svc, UNIT_ATTABLE, 0), KBD_POLL_WAIT }; - -REG ttix_reg[] = { - { BRDATA (BUF, ttix_buf, 8, 8, TTX_LINES) }, - { GRDATA (DONE, dev_done, 8, TTX_LINES, INT_V_TTI1) }, - { GRDATA (ENABLE, int_enable, 8, TTX_LINES, INT_V_TTI1) }, - { GRDATA (INT, int_req, 8, TTX_LINES, INT_V_TTI1) }, - { DRDATA (TIME, ttix_unit.wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS, ttx_tps, 10), REG_NZ + PV_LEFT }, - { ORDATA (DEVNUM, ttix_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB ttix_mod[] = { - { UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &ttx_summ }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &ttx_desc }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &ttx_show, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &ttx_show, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE ttix_dev = { - "TTIX", &ttix_unit, ttix_reg, ttix_mod, - 1, 10, 31, 1, 8, 8, - &tmxr_ex, &tmxr_dep, &ttix_reset, - NULL, &ttx_attach, &ttx_detach, - &ttix_dib, DEV_NET | DEV_DISABLE }; - -/* TTOx data structures - - ttox_dev TTOx device descriptor - ttox_unit TTOx unit descriptor - ttox_reg TTOx register list -*/ - -UNIT ttox_unit[] = { - { UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT } }; - -REG ttox_reg[] = { - { BRDATA (BUF, ttox_buf, 8, 8, TTX_LINES) }, - { GRDATA (DONE, dev_done, 8, TTX_LINES, INT_V_TTO1) }, - { GRDATA (ENABLE, int_enable, 8, TTX_LINES, INT_V_TTO1) }, - { GRDATA (INT, int_req, 8, TTX_LINES, INT_V_TTO1) }, - { URDATA (TIME, ttox_unit[0].wait, 10, 24, 0, - TTX_LINES, PV_LEFT) }, - { NULL } }; - -MTAB ttox_mod[] = { - { UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", NULL }, - { UNIT_UC+UNIT_8B, 0 , "7b" , "7B" , NULL }, - { UNIT_UC+UNIT_8B, UNIT_8B , "8b" , "8B" , NULL }, - { 0 } }; - -DEVICE ttox_dev = { - "TTOX", ttox_unit, ttox_reg, ttox_mod, - 4, 10, 31, 1, 8, 8, - NULL, NULL, &ttox_reset, - NULL, NULL, NULL, - NULL, DEV_DISABLE }; - -/* Terminal input: IOT routine */ - -int32 ttix (int32 inst, int32 AC) -{ -int32 pulse = inst & 07; /* IOT pulse */ -int32 ln = TTX_GETLN (inst); /* line # */ -int32 itti = (INT_TTI1 << ln); /* rx intr */ -int32 itto = (INT_TTO1 << ln); /* tx intr */ - -switch (pulse) { /* case IR<9:11> */ -case 0: /* KCF */ - dev_done = dev_done & ~itti; /* clear flag */ - int_req = int_req & ~itti; - break; -case 1: /* KSF */ - return (dev_done & itti)? IOT_SKP + AC: AC; -case 2: /* KCC */ - dev_done = dev_done & ~itti; /* clear flag */ - int_req = int_req & ~itti; - return 0; /* clear AC */ -case 4: /* KRS */ - return (AC | ttix_buf[ln]); /* return buf */ -case 5: /* KIE */ - if (AC & 1) int_enable = int_enable | (itti + itto); - else int_enable = int_enable & ~(itti + itto); - int_req = INT_UPDATE; /* update intr */ - break; -case 6: /* KRB */ - dev_done = dev_done & ~itti; /* clear flag */ - int_req = int_req & ~itti; - return ttix_buf[ln]; /* return buf */ -default: - return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ -return AC; -} - -/* Unit service */ - -t_stat ttix_svc (UNIT *uptr) -{ -int32 ln, c, temp; - -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ -temp = sim_rtcn_calb (ttx_tps, TMR_TTX); /* calibrate */ -sim_activate (uptr, temp); /* continue poll */ -ln = tmxr_poll_conn (&ttx_desc); /* look for connect */ -if (ln >= 0) { /* got one? */ - ttx_ldsc[ln].rcve = 1; } /* rcv enabled */ -tmxr_poll_rx (&ttx_desc); /* poll for input */ -for (ln = 0; ln < TTX_LINES; ln++) { /* loop thru lines */ - if (ttx_ldsc[ln].conn) { /* connected? */ - if (temp = tmxr_getc_ln (&ttx_ldsc[ln])) { /* get char */ - if (temp & SCPE_BREAK) c = 0; /* break? */ - else if (ttox_unit[ln].flags & UNIT_UC) { /* UC? */ - c = temp & 0177; - if (islower (c)) c = toupper (c); } - else c = temp & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177); - ttix_buf[ln] = c; - dev_done = dev_done | (INT_TTI1 << ln); - int_req = INT_UPDATE; } } } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ttix_reset (DEVICE *dptr) -{ -int32 t, ln, itto; - -ttx_enbdis (dptr->flags & DEV_DIS); /* sync enables */ -if (ttix_unit.flags & UNIT_ATT) { /* if attached, */ - if (!sim_is_active (&ttix_unit)) { - t = sim_rtcn_init (ttix_unit.wait, TMR_TTX); - sim_activate (&ttix_unit, t); } } /* activate */ -else sim_cancel (&ttix_unit); /* else stop */ -for (ln = 0; ln < TTX_LINES; ln++) { /* for all lines */ - ttix_buf[ln] = 0; /* clear buf, */ - itto = (INT_TTI1 << ln); /* interrupt */ - dev_done = dev_done & ~itto; /* clr done, int */ - int_req = int_req & ~itto; - int_enable = int_enable | itto; } /* set enable */ -return SCPE_OK; -} - -/* Terminal output: IOT routine */ - -int32 ttox (int32 inst, int32 AC) -{ -int32 pulse = inst & 07; /* pulse */ -int32 ln = TTX_GETLN (inst); /* line # */ -int32 itti = (INT_TTI1 << ln); /* rx intr */ -int32 itto = (INT_TTO1 << ln); /* tx intr */ - -switch (pulse) { /* case IR<9:11> */ -case 0: /* TLF */ - dev_done = dev_done | itto; /* set flag */ - int_req = INT_UPDATE; /* update intr */ - break; -case 1: /* TSF */ - return (dev_done & itto)? IOT_SKP + AC: AC; -case 2: /* TCF */ - dev_done = dev_done & ~itto; /* clear flag */ - int_req = int_req & ~itto; /* clear intr */ - break; -case 5: /* SPI */ - return (int_req & (itti | itto))? IOT_SKP + AC: AC; -case 6: /* TLS */ - dev_done = dev_done & ~itto; /* clear flag */ - int_req = int_req & ~itto; /* clear int req */ -case 4: /* TPC */ - sim_activate (&ttox_unit[ln], ttox_unit[ln].wait); /* activate */ - ttox_buf[ln] = AC & 0377; /* load buffer */ - break; -default: - return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ -return AC; -} - -/* Unit service */ - -t_stat ttox_svc (UNIT *uptr) -{ -int32 c, ln = uptr - ttox_unit; /* line # */ - -if (ttx_desc.ldsc[ln]->conn) { /* connected? */ - if (ttx_desc.ldsc[ln]->xmte) { /* tx enabled? */ - TMLN *lp = ttx_desc.ldsc[ln]; /* get line */ - if (ttox_unit[ln].flags & UNIT_UC) { /* UC mode? */ - c = ttox_buf[ln] & 0177; /* get char */ - if (islower (c)) c = toupper (c); } - else c = ttox_buf[ln] & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177); - tmxr_putc_ln (lp, c); /* output char */ - tmxr_poll_tx (&ttx_desc); } /* poll xmt */ - else { - tmxr_poll_tx (&ttx_desc); /* poll xmt */ - sim_activate (uptr, ttox_unit[ln].wait); /* wait */ - return SCPE_OK; } } -dev_done = dev_done | (INT_TTO1 << ln); /* set done */ -int_req = INT_UPDATE; /* update intr */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ttox_reset (DEVICE *dptr) -{ -int32 ln, itto; - -ttx_enbdis (dptr->flags & DEV_DIS); /* sync enables */ -for (ln = 0; ln < TTX_LINES; ln++) { /* for all lines */ - ttox_buf[ln] = 0; /* clear buf */ - itto = (INT_TTO1 << ln); /* interrupt */ - dev_done = dev_done & ~itto; /* clr done, int */ - int_req = int_req & ~itto; - int_enable = int_enable | itto; /* set enable */ - sim_cancel (&ttox_unit[ln]); } /* deactivate */ -return SCPE_OK; -} - -/* Attach master unit */ - -t_stat ttx_attach (UNIT *uptr, char *cptr) -{ -int32 t; -t_stat r; - -r = tmxr_attach (&ttx_desc, uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error */ -t = sim_rtcn_init (ttix_unit.wait, TMR_TTX); /* init calib */ -sim_activate (uptr, t); /* start poll */ -return SCPE_OK; -} - -/* Detach master unit */ - -t_stat ttx_detach (UNIT *uptr) -{ -int32 i; -t_stat r; - -r = tmxr_detach (&ttx_desc, uptr); /* detach */ -for (i = 0; i < TTX_LINES; i++) { /* all lines, */ - ttx_desc.ldsc[i]->rcve = 0; /* disable rcv */ - sim_cancel (&ttox_unit[i]); } /* stop poll */ -return r; -} - -/* Show summary processor */ - -t_stat ttx_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < TTX_LINES; i++) t = t + (ttx_ldsc[i].conn != 0); -if (t == 1) fprintf (st, "1 connection"); -else fprintf (st, "%d connections", t); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i; - -for (i = 0; (i < TTX_LINES) && (ttx_ldsc[i].conn == 0); i++) ; -if (i < TTX_LINES) { - for (i = 0; i < TTX_LINES; i++) { - if (ttx_ldsc[i].conn) - if (val) tmxr_fconns (st, &ttx_ldsc[i], i); - else tmxr_fstats (st, &ttx_ldsc[i], i); } } -else fprintf (st, "all disconnected\n"); -return SCPE_OK; -} - -/* Enable/disable device */ - -void ttx_enbdis (int32 dis) -{ -if (dis) { - ttix_dev.flags = ttox_dev.flags | DEV_DIS; - ttox_dev.flags = ttox_dev.flags | DEV_DIS; } -else { ttix_dev.flags = ttix_dev.flags & ~DEV_DIS; - ttox_dev.flags = ttox_dev.flags & ~DEV_DIS; } -return; -} diff --git a/Pcap-VMS/pcap-vci/VMS_PCAP.COM b/Pcap-VMS/pcap-vci/VMS_PCAP.COM index 263db128..3e9c5135 100644 --- a/Pcap-VMS/pcap-vci/VMS_PCAP.COM +++ b/Pcap-VMS/pcap-vci/VMS_PCAP.COM @@ -2,7 +2,7 @@ $ if f$search("pcap.olb") .eqs. "" $ then $ libr/crea pcap.olb $ endif -$ if p1 .eqs. "DEBUG" +$ if p1 .nes. "" $ then $ opt = "/debug/noopt" $ else diff --git a/S3/haltguide.txt b/S3/haltguide.txt deleted file mode 100644 index 24e90f86..00000000 --- a/S3/haltguide.txt +++ /dev/null @@ -1,950 +0,0 @@ - IBM System/3 Model 8/10 SCP - - ********** - Halt Guide - ********** - -This following list is my own reformatting and rewording of the -official IBM Halt Guide for the Model 8/10 SCP. - -The halts are those displayed on the message display unit. The -list is in alphabetical order for easy reference. - -When the system halts, the two 7-segment displays will display the -halt as listed here, and the system console (or printer if the log -device is the printer) will print the "SCP Message" below. To -respond to the halt, deposit one of the valid response numbers -(0 thru 3) into the SR, and then use the C command to continue. - -Unless otherwise stated, a response of 0 means to continue and accept -the error, 1 means to retry the operation or re-read the statement in -error, 2 means to cancel the job and retain added records (if any) and -3 means to end the job and discard any added records in files. - -This is a listing of those halts likely to be encountered using SCP on -the simuator, it is not the complete list of all possible halts. - -Halt SCP Message Description ----- ----------- ----------- - -00 Invalid response to another halt. Deposit a valid - value (0 thru 3) in SR. - -0A A 5448 Disk Unit not ready. - -0C 5448 Disk Equipment Check - -0E Permanent disk error during logging. - -0F ID0FXX 23 Invalid cylinder number on disk operation. - XX = Disk Drive. - -0H ID0HXX 23 Invalid sector number on disk operation - XX = Disk Drive. - -0Y IK0Y0X 123 3741 Error. X: 1=not ready 2=wrong mode - 3=parity error 5=record length error - -0 ID0 XX 23 Disk Data Check - XX = Disk Drive. - -0- ID0-XX Invalid disk operation code: Start cancels job. - XX = Disk Drive. - -10 3 No input file allocate, user error. - -11 0 23 Square root of a negative field - -12 0 23 Divide Overflow - -13 0 23 Divide by zero - -14 0 23 Varible index zero of out of range - -15 0 23 Sequenced table is out of sequence - -16 0 23 (RPG) OBject tables expected. /* Read. - -17 0 23 (RPG) Object table exceeds specified length - -18 0 23 (RPG) Terminal errors in source program. - -19 0 3 (RPG) Warning errors in source program. 0=continue. - -1A 3 (RPG) Out of core memory - -1C 23 Unidentified halt has been issued. Probable system - error. - -1E 0 3 (RPG) Demand file at end of file. - -1F 23 (RPG) End of file or end of extent. If during RPG - compilation, expand $SOURCE or $WORK. - -1H 0 23 Duplicate keys found during build of indexed file. - 0=skip this record and continue. - -1J 0 23 Out of sequence keys during build of indexed file. - 0=skip this record and continue. - -1L 0 23 Key changed during record update. User error. - 0=continue, do not update record. - -1P 01 Forms in printer need positioning. - -1U 123 No record found on direct or indexed file. - -1Y 0 23 (RPG) Invalid numeric data to DSPLY statement. - -1 0 3 Object program ready to punch tables. - -20 1 3 Disk Sort: Invalid header and no // SOURCE - -21 01 3 Disk Sort: Name on // SOURCE not found - -22 0 2 Disk Sort: Warning errors found. - -23 3 Disk Sort: Unrecoverable error. - -25 3 Disk Sort: Terminal errors in sort statements. - -27 0 Disk Sort: In debug mode, finished pass. - -2C 0 3 Disk Sort: No Input Records selected. - -2E 3 Disk Sort: Workfile too small. - -2F 23 Disk Sort: Output file too small. - -2L DT2LY2 3 Tape Record too large to process. - DT2LY7 3 No FILE statement for tape file open. - DT2LY9 3 No enough storage for tape operation - DT2LTC 3 Invalid tape header length - DT2LYF 123 Incorrect block length read from tape - -2P Permanent tape error. - -2U 12 Tape unit is write protected. - -2Y 3 Invalid device specification in object. - -2- 0 3 First statement was not a Tape Sort header. - -30 EG30 3 Space not available on R1 or F1. - UB30A1 0 3 Active files exist on output disk - UB30AF 0 3 Active files exist on 5448 disk - UB30H1 0 3 Wrong capacity or uninitialized pack - UB30NS 3 No 5448 disk for $PCOPY - UB30TP 0 3 Pack change required. - UC30AF 3 Active or system files on target - UC30BD 3 Volume label cannot be read - UC30SP 3 Not enough space for work file - UP30AF 3 Active or system files on target - -31 UI31AF 0 3 Active or system files on target - 0=proceed to next unit to initialize - UI30WP 01 3 Wrong pack, name does not match. - -32 UB32Bx 01 3 5444 pack is not a $PCOPY backup pack. - UB32NP 01 3 Unit specified is not a $PCOPY pack. - UC32BD 3 FROM pack is a TO pack from an interrupted - COPYPACK run. - UC32BP 3 Output pack is a $PCOPY output pack. - Must be initialized or reset by a RESET - statement to be used. - UC32DS 3 Packs FROM and TO are different sizes. - -33 UI33PU 0 3 Pack defective, cannot be initialized. - -34 Ux34 1 3 Keyword in a utility control statement is invalid. - -35 UC35xx 1 3 Error in $COPY or $KCOPY control statement. - -36 UI36CE 0 3 CE track defective on unit F1. - -37 UC37xx 0 3 Pack change required. xx: FP=mount on R1, - IP=pack on COPYIN, OP=pack on COPYO. - -38 UA38XX 0 3 Wrong pack mounted. - UB38DA 01 3 Dates do not match. - UB38DM 01 3 2nd 5444 pack not from same backup set as 1st. - UB38IP 01 3 PACKIN keyword pack not same as pack mounted. - UB38OP 01 3 PACKO keyword not same as pack mounted. - -3A UC3Axx 3 Key out of sequence (DP), invalid high key (HK), - out of space to copy file (XE), or disk I/O error. - -3C UC3CCS 3 COPYFILE out of core. - UC3CNF 3 Module not found, name is logged as R XXXXXX. - -3E UC3EOX 0 3 COPYFILE output not as big as size of input. - -3F UC3Fxx 1 3 Error in COPYFILE statement. - -3J UC3Fxx 3 Invalid specification for Copy/Dump. - -3P UC3Pxx 1 3 Error in COPYPACK, RESET, or LABELS statement. - -3Y UI3YIS 0 3 Requested secondary init when primary required. - -3 UI3 xx 1 3 Error in VOL statement. - -40 DD40 3 File has been referenced as an output or add file - and the file is already allocated. - -4A DD4A 3 File had already been opened and is re-opened. - -4C DD4C 3 Multivolumne file spec error. - -4E DD4E 3 FILE indicates a multivolule file being built, - but program compiled for single volume. - -4F DD4F 3 Print buffers not aligned in program. - -4H DD4H 0 3 Unordered load specified for ISAM. Ordered load - must be specified on RPG file specs. - -4J DD4J 3 All file specs have been checked and there were - errors. - -4L DD4L 3 Referenced file already allocated. - -4P DD4P 3 Prgram/FILE statement mismatch. - -4U DD4U 3 File referenced as update, already allocated. - -4Y DD4Y 3 File has an incorrect device specification. - -4 DD4 3 No FILE specification for referenced file. - -4' DD4' 3 Attempting reference to a file in 2 levels, one or - both using RETAIN-S. - -50 UA50ID 2 Bad track which can't be reassigned. - -51 UR51 12 Can't use Alternate Track program in procedure. - -52 ML52 12 EOJ for Card List program. - -53 IU53 1 3 Number of VOL statements does not agree with number - of units on UIN statement. - -54 EO54 3 End-of-file. - -55 UF55xx 1 3 Error in SCRATCH or REMOVE statement. - -56 UA56TS 0 3 ASSIGN track is over disk capacity. - UA56XX 0 3 Unit specified is uninitialized. - -57 UF57WP 01 3 File delete program. Wrong pack is mounted. - 0: Mount correct pack and continue. 1: - correct statement and retry. - -5A UA5Axx 012 Alternate track assignment error. - -5C MR5Cxx 1 3 Invalid reformat specs. - -5F UF5Fxx 1 3 Error in DISPLAY statement. - -5H UA5HEU 0123 Primary track is still defective. - -5L UF5LAF 0 3 PRogram try to delete files that are being used by - another program. - UF5LNF 0 3 File not found. - UF5LTM 23 Too many files specified. Max is 40. - -5U UI5Uxx 1 3 Error in UIN statement. - -5Y UR5Yxx 1 3 Error in REBUILD statment. - -5 UA5 xx 1 3 Error in ALT statement. - -5- 3 Tape Sort error occurred. - -5' UF5'N1 0 3 Pack cannot be used. Not inited. - UF5'NU 0 3 Pack was used as TO pack on a COPYPACK job - that required early termination. Can only - be used for another COPYPACK job. - -60 LM60SY 0 3 Cannot remove or change library size on pack - from which $MAINT was loaded. - -61 LM61EP 0 3 Trying to copy a system to a library that is - 1) not empty, 2) not allocated with large enough - SWA, or 3) not allocated with enough space. - LM61NS 0 3 System does not exist on FROM pack. - -62 LM62CS 01 3 Check Sum error. - LM62DR Can't determine if REMOVE is data or control. - LM62EF FROM, TO, or AFTER statement does not exist or - is out of sequence. - LM62ND NO data records following INSERT or REPLACE. - LM62SQ Records are out of sequence. - LM62TP Incorrect type record. - -63 LM63DE 0 3 Directory entry error. Name can't be found or - attributes don't match, or attempt to remove - dir entry with MODIFY. - -64 LM64DS 0 3 Syntax error in ALLOCATE. - -65 LM65UN 0 3 Pack not properly initialized. - -66 LA66xx 3 Error with LOAD * function. - -67 EL67NL 0 3 Library does not exist. - -68 EL68DF 0 3 No room in library or directory. - -69 XX69HE 3 Disk I/O Error while using library. - -6A LM6Axx 1 3 $MAINT has detected a syntax error on a control - statement. xx gives a hint of what might be wrong. - AL: SOURCE or OBJECT missing or invalid - AZ: SYSTEM missing or invalid - D2: FROM, TO, or WORK is R2 or F2, not available - DK: Duplicate keyword - DS: Invalid DIRSIZE - FL: Invalid or missing FILE keyword - FM: Invalid or missing FROM keyword - IK: Invalid keyword - IN: Invalid INCR keyword - IS: first 3 columns must be // blank - IV: Invalid statement identifier - LB: Invalid LIBRARY keyword - LS: Invalid LIST keyword - NK: No keywords - NM: Invalid NAME keyword - NU: Invalid NEWNAME keyword - OM: Invalid OMIT keyword - RL: Invalid RECL keyword - RS: Invalid RESER keyword - RT: Invalid RETAIN keyword - SF: INvalid SEQFLD keyword - SQ: Invalid FROM, TO, or AFTER in MODIFY mode - XC: Invalid record. - XD: Duplicate keyword - XF: $$SYFG could not be found. - XL: LIBRARY keyword missing - XM: NAME keyword missing - XN: NAME parameter is invalid - XP: Library does not exist on this pack - XS: Syntax error - XT: Invalid library type - XV: INvalid operation - -6C LM6CSP 0 3 Not enough space on pack. - LM6CSW 0 3 Space not available for work file. - -6E LM6EOF 0 3 Overflow in seq field during RESER. - LM6EDP 0 3 Entry with same name already exists in library. - -6H EL6HDT 0 3 Trying to replace perm with temp entry. - LM6HDP 0 3 NEWNAME is already in library. - -6J LM6JCC 0 3 Control statements are missing. - -6L UA6L 3 Log device is required for this program. - -6Y LM6YNN 1 3 No NEWNAME when copying to same library. - -6 LM6 BC 3 Invalid character in source record. - LM6 CM 0 3 Invalid object deck. - LM6 ND 0 3 No data between COPY and CEND. - -6- LM6-BC 01 Entry containing a blank card being placed in - library. 0: accept, 1: skip and read next card. - -6' LM6'CE 1 3 // CEND expected but not found. 1: Retry, - provide CEND. NOTE: For option 3, if a module - was being replaced, it may have been deleted but - new module not loaded. - -70 CR70 3 Too many overrides for procedure. Max is 25. - -71 CR71 0 3 OCL Syntax Error. - -73 CR73 0 // PARTITION given in invalid location. - -74 CR74 3 /& between LOAD and RUN or CALL and RUN. - -75 CR75 23 Extraneous statement. - -76 CR76 0 3 // Missing from OCL statement. - -77 CR77 23 Invalid OCL statement identifier. - -78 CR78 0 3 Unknown OCL keyword. - -79 CR79 23 Continuation expected but not received. - -7A CR7A 3 A second LOAD or CALL found before run, or a - CALL in procedure overrides. - -7C CR7C 0 3 // COMPILE found between jobs. - -7E CR7E 0 3 // DATE found between jobs. 0: Ignore and continue. - -7F CR7F 0 3 // FILE found between jobs. Must go between - // LOAD or // CALL and // RUN statements. - -7H CR7H 0 3 // SWITCH found between jobs. - -7J CR7J 23 // READER found between LOAD or CALL and RUN. - -7L CI7Lxx 23 Error when reading a tape file. - -7P New print chain expected. Load it and press START. - -7U CR7U 3 RUN statement not preceeded by LOAD or CALL. - -7Y CI7Yxx 23 Error outputing a tape file. - -7 CR7 3 Too many utility control statements, max is 25. - -7- CR7- 0 // PARTITION was read but system does not support - Dual Programming. - -7' Error during tape processing. - -80 CR80 0 // DATE card has not been entered. - -81 CR81 23 Error in LOAD statement. - -83 CR83 23 Error in LOAD * statement. - -84 CR84 23 Error in CALL statement - -85 CR85 23 Second SWITCH statement found. - -86 CR86 23 Invalid paramter in switch statement. - -88 CR88 1 3 Procedure not found. - -89 CR89 01 // DATE has already been given. - 0 - accept the new date as the date. - 1 - leave the old date as the current date. - -8A CR8A01 0 Invalid date specified. - CR8A02 0 DATE parameter missing. - -8C CR8C 23 Second DATE found. - -8E CR8E01 23 Date specified incorrectly. - -8F CR8Fxx 23 Invalid BSCA statement. - -8H CR8H 3 More than 9 levels of procedures have been called. - -8J CR8J 0 Invalid // READER parameter. - -8L CR8L 0 Desired system input device being used by other - program. - -8P CR8P 0 Output device not defined. - -8U CU8UIP 23 Invalid HIKEY in FILE statement: non-numeric. - CR8UKL Parameter length mismatch. - CR8ULO Key greater than 29. - CR8UPL HIKEY-P greater than 15. - CR8USQ HIKEY parameters not in sequence. - -8Y CR8Y 0 Not logging can be done. Log turned off by - other program level. - -8- CR8- 0 3 Logging requested but cannot be done. - -90 CR90 0 // PAUSE statement read. Check printer or console - for instructions and continue. PAUSE was outside - LOAD and RUN. - -91 CR90 0 // PAUSE statement read. Check printer or console - for instructions and continue. PAUSE was inside - LOAD and RUN. - -92 CR92 23 COMPILE already recieved for this job. - -93 CR93 23 Error in COMPILE statement. - -94 CR94 23 Error in COMPILE statement. - -95 CR95 23 Error in COMPILE statement. - -96 CR96 0 23 System error. An OCL error was found, but the system - cannot resolve the error. - -97 CR97 0 Error in LOG statement. - -98 CR98 23 Error in LOG statement. - -99 CR99 0 23 Error in LOG statement. - -9A CR9A 23 Indicated action on last OCL statement read will - be ignored due to previous errors detected. - -9C CR9Cxx 123 Incorrect tape volume online. - -9E CR9E 0 Logging device being used by other program level. - -9F CR9F 0 23 Logging device in use by other program. - -9H CR9H 23 Log device in use. - -9J CR9J 0 Error in FORMS statement. - -9L CR9L 0 23 Error in FORMS statement. - -9P CR9P 23 Error in FORMS statement. - -9U CR9U 0 3 Other program has gotten a // IMAGE or other - program level is using the printer. - -9Y CR9Y 0 23 Logging device not sysgenned or CCP has it. - -9 CR9 0 23 Same as 9Y. - -9- CR9- 0 3 Other program level received a // FORMS or - other level using the printer. - -9' CR9' 0 Same as 9Y. - -A0 CRa0xx 23 Syntax error in FILE statement. - -A1 CRA1xx 23 Keyword error in FILE statement. - -A2 CRA2xx 23 Parameter error on FILE statement. - xx gives parameter: - 01 NAME, 02 UNIT, 03 PACK, 04 LABEL, - 05 RETAIN, 06 DATE, 07 RECORDS, 08 TRACKS, - 09 LOCATION, AS ASCII, BL BLKL, CV CONVERT, - DF DEFER, DN DENSITY, EN END, PT PARITY, - RC RECL, RF RECFM, RL REEL, SP SPLIT, - TN TRANSLATE. - -A3 CRA3xx 23 Missing Parameter on FILE statement, xx = - NN: NAME, NP: PACK, NU: UNIT, OP: no - parameters. - -A4 CRA4xx 23 Invalid parameter combination in FILE statement: - AS: ASCII-YES and RECFM-D/DB on 7-track tape - AV: ASCII-YES and RECFB-V/VB - AY: RECFM-D/DB without ASCII-YES - CT: CONVERT-ON and TRANSLATE - DI: UNIT says tape but disk parameters given - DN: DENSITY-800 not supported. - FS: RECFM is fexed and block or rec len less than 18 - IL: Incorrected RECL or BLKL for RECFM - IP: SPLIT or LOCATION used with RECORDS / TRACKS. - IR: LABEL, DATE or RETAIN wirh REEL-NL or REEL-NS - NS: Not all units are 7-track - PC: CONVERT-ON and PARITY-EVEN - RC: CONVERT-ON not given with RECFM-V/VB for 7-track - SD: DENSITY-1600 invalid for 7-track - SL: LOCATION missing or invalid for SPLIT. - SM: SPLIT invalid for multivolume files. - ST: 7-track paras with 9-track unit - SU: SPlit can't be used with 5444 - TL: TRACKS/LOCATION invalid with unit - TP: UNIT is disk but tape paras given - TR: TRACKS and RECORDS both given - -A6 CRA6xx 23 Error in FILE statement for multivolumne files. - -A7 CRA7xx 23 Error in IMAGE statement. - -A8 CRA8xx 0 Error in IMAGE statements o disk. - -A9 CRA9xx 0 23 Same as A8. - -AA CRAAxx 23 Same as A8. - -AC CRAC 0 Invalid hex character in chain image. - -AE CRAE 0 23 Same as AC. - -AF CRAF 23 Same as AC. - -AH CRAH 0 Error in IMAGE statement. - -AJ CRAJ 0 23 Same as AH - -AL CRALxx 0 Error in PARTITION statement. - -AP CRMN 0 3 Either reocvery option has has been selected during - a job, or OCL errors have occurred for this job. - 0: Continue iwth next job, or no data cards in - reader for this job, otherwise, 3 to cancel. - -AU CRAUxx 23 Error in PARTITION statement. - -A CRA 23 Total number of volumes for a FILE statement - exceeds 40 (!). - -A- CRA-xx 0 23 Error in PARTITION statement. - -A' CRA' 3 No space remaining is System work area. Too many - FILE statements are in this job. - -C1-C9 IFC1 123 1442 Check, various causes. - -CL UDCLxx 1 3 5445 Data Interchange Utility error - -E7 DKE7 0 3 Incorrect record length for attached 3741 - -E8 UTE8xx 1 3 Error in Tape Init VOL statement. - -E9 UTE9xy 0 3 Error during Tape Init Processing. - -F8 DDF8 3 RPG--LIne counter specs omitted and skip past - page size for printer. - -F9 CIF9xy 23 Tape drive not available, x = drive #. - -FA CIFA 3 Program requesting Data Recorder, unsupported. - -FC CIFC 3 Program requesting CRT, unsupported. - -FE DDFE 0 3 Program requesting line line on printer that - exceeds sysgen value. - -FF RPQ routine error. Press start to continue. - -FH CIFH 123 BSCA line not supported. - -FJ CIFJ01 123 1442 not supported but requested - CIFJ02 123 3741 not supported but requested - -FL CIFL 123 Printer/keyboard not supported or unavailable. - -FP CIFP 123 Printer not supported or allocated to other level - -FU CIFU 123 MFCU not supported or allocated to other level - -FY CIFY 23 Device is not supported or in use. - -F CIF 23 Conflict with a resource being used by other level. - -H0-H9 0 23 RPG Programmed halt indicator is on. - -HA CIHA 3 Out of space on $SOURCE during compile. - -HC CIHC 3 Program given on LOAD statement not found. - -HE Hardware error. Simulator has messed up. - -HF CIHF 0 3 // COMPILE read but not required. - -HJ CIHJ01 1 3 Program not found on removable unit, 1: - mount new unit and retry. - CIHJ02 3 Program not found, but removable unit in use. - -HL CIHL 3 Inquiry request made but program is wrong type. - -HP CIHP 3 Insufficient main storage for program. - LMHP 3 $MAINT function out of storage. NOTE: After the - cancel, IPL from the system pack or the pack will - be unusable. - -HU CIHUxx 3 Source program not found on disk. IF a 1 option - is present, you can mount a new removeable pack. - -HY CCHYNN 0 A checkpoint is received and accepted. - -H CCH NN 0 23 A restart has been requested. - -H' CIH' 3 An uninitialized pack has been referenced. - -J0-J9 123 Record with specified match field out of sequence. - This is an RPG error, the 2nd digit indicates which - RPG file statement the error applies to in the - source program. 0=greater than statement 9, - otherwise indicates the file statement number. - -JA CIJA 3 Trying to laod a program that requires or allows - inquiry while another inquiry program is running - in the other level. - -JC CIJCxx 3 Program cannot be run for this reason (xx): - 01: Must be dedicated and other level active - 02: Program in other level must be dedicated - 03: $$RSTR cannot run in level 2 - 04: CHeckpointed program not allowed in level 2 - 05: Program can't run while checkpoint active - -JE CIJE 0 3 Level 1 partition too small. - -JF CIJF 3 Attempt to start inquiry program but keyboard - in use. - -JH CIJF 3 Attempt to start program which allows interrupts in - level 2. - -JJ CIJJ 3 No object library on pack requested for load. - -JL CIJL 3 Not enough storage for program. DPF only. - -JP System input device in use by other level. - -JU 0123 Cancel request made from interrupt key. 0: ignore - 1: continue, request ignored - -JY CIJYRD 0 2 Inquiry request made and accepted. - -J- 3 Attempt to run a CCP program, but CCP not running. - -J' 01 3 Inquiry request is completed, interrupted program - can now resume. - -L0-L9 123 RPG. Unidentified record, 2nd digit gives file - statement number in source program 1-9, 0 means - greater than 9. Can also occur if record is out - of sequence. - -LA CILA 23 Too little storage for number of files in program. - -LC CILC 23 Too little storage for requested allocation. - -LE CILE 23 No FILE or an incorrect FILE for a file requested - by current program. - -LH CILH 23 No space given for an output file on FILE statement. - -LJ CILJ 23 Attempt to output to existing permanent file. - -LL CILL 0 23 Attempt to output over an existing temporary file. - -LP CILP 23 File already exists. - -LU CILU 123 Pack name requested but wrong pack mounted. 1: - retry after mounting correct pack. - -LY CILYxx 23 Attempt to allocate space that isn't available. - xx=02 means space not available in split cylinder - area. - -L LML CP 01 3 $MAINT detected attempt to modify a program on - a pack with an active checkpoint. - -L- CIL- 3 Attempt to add a split cylinder to a split cyl - file while other level is fiddling with a split - cylinder file. - -L' CIl' 23 Trying to allocate a split cylinder file before - allocating the first split cylinder file in a group. - -P1-P8 Printer hardware errors, should not occur in sim. - -PC IPPC 0 23 Unprintable character. - -PH CIPH 23 LOCATION plus TRACKS goes past end of pack. - -PJ CIPJxx 1 A Pack is to be remounted, pack name printed before - half code, xx= unit. - -PU CIPU 3 Duplicate file names in the FILE statements. - -PY CIPY01 3 ISAM file requires at least 2 tracks. - CIPY02 3 ISAM file can't be split cylinder. - -P' CIP'xx 23 Too many scratch or work files. - -U0-U9 0123 RPG. Unidentified record in file, 2nd digit of - halt is file statement in RPG source, 0= greater - than 9. - -UA CIUA 3 Attempt to create a multivolume file in - invalid. - -UC CIUC 3 The printed actived file cannot be found in the - list of scratch files. - -UE CIUExx 1 3 PACK parameter does not match pack name on unit. - xx = Unit referenced. - 1 = Mount another pack and continue. - -UF CIUF 3 Disk file referenced by name and date not found. - -UH CIUH 3 Attempt to create multivolume file failed, - because name alreayd exists. - -UJ CIUJ 3 A LOCATION was specified for an existing disk file - and the file exists but not at that location. - -UL CIUL 3 File on // FILE statement not found, and no size - in TRACKS or RECORDS was given. - -UP CIUP 3 Permanent file referenced with RETAIN-S - -UU CIUU 3 Disk Pack not available. - -UY CIUY 3 File is a System/3 BASIC file which must be unique. - -U CIU 3 Existing file: TRACKS/RECORDS or LOCATION mismatch. - -U- General CCP halt. Press start to see subhalt. - Refer to CCP manual for more info. - -U' CIU' 23 VTOC is full, or more than 2 multivolume files per - pack, or more than 2 ISAM files using HIKEY - parameter. - -YH CRYH 0 3 Cards are being punched, but card read from - reader was not blank. This means you are trying to - punch with a file attached to the CDR device. - Unattach the file and take the zero option. - - 0 (blank 0) FILE WRITE switch in off position. - - 1 (blank 1) Permanent DIsk I/O Error - - 2 RC 211 3 COBOL. Out of room on $WORK. - RC 212 3 Out of room on $SOURCE. - RC 213 3 Out of room on $WORKX. - RC 214 3 Subprogram name table greater than 20. - RC 219 0 3 C or E level diagnostics during compile. - RC 2A1 23 Subscript invalid - RC 2A2 23 Negative exponent or 0 degrees in program - RC 2F1 23 MFCU File not open or opened improperly - RC 2F2 23 1442 File not open or opened improperly - RC 2F3 23 1403/5203 File not open or opened improperly - RC 2F4 23 5444 Disk File not open or opened improperly - RC 2F5 23 5444 File not open or opened improperly - RC 2F7 23 5444 File not open or opened improperly - RC 2F8 23 Tape File not open or opened improperly - RC 2H1 23 OPEN attempted after CLOSE WITH LOCK - RC 2H2 23 Error during ACCEPT - RC 2H3 23 $$STOP not found - RC 2H4 23 CHeckpoint could not be taken. - RC 2H5 23 $$STIC not found for ACCEPT - RC 2H6 23 Parameter mismatch CALL and USING - RC 2H7 23 ACCEPT after /& read - RC 2H8 23 OPEN for a file already OPEN - RC 2 0 3 Too little core for compile - RC 2 1 3 PROCEDURE or DATA division not found. - RC 2 3 3 Program has more than 65535 statements (!) - RC 2 4 3 Source name on COMPILE statement not found - - 3 R 3XX 0 3 COBOL Stop literal. XX is user-specified. - 0 continues program 3 cancels. - - 4 VF 4NF 3 Program not found. Program library and - not printed before halt message. - - 6 RF 6XX 0 23 FORTRAN stop statement. - - 7 RF 701 23 Source member on COMPILE not found - RF 702 23 Object program too large for core. - - 8 CS 8 1 3 System input device allocated to other level. - - 9 CS 9 1 3 System input device has an error. This usually - means the card hopper is empty (i.e. EOF on the - file attached to the reader but SCP wants more - input). - - A DC A 123 Number of characters entered from keyboard - incorrect. - - C DD C 0 23 Unprintable character for printer/keyboard. - - E DC E 123 Hardware error, PKB - - F DC F 0 23 End of forms, PKB - - L DD L 0 3 Records with duplicate keys have been loaded - into ISAM file. Each dup key is logged followed - by blank P halt. 0: continue. Index will - contain duplicate keys. 3: cancel, file is - not usable, reload it. - - P DD P 0 3 Duplicate key encountered. The key is printed - on the log. 0: continue, halt will recur for - any other duplicates, then blank L appears. - - U DD U 3 Disk I/O error while sorting ISAM index. - - Y DD Y 3 System error during file termination. - --0 DD-0XX 3 ISAM multivolume file being used and high key - not found for current columme, or does not agree - with HIKEY spec. XX=unit number. - --1 DD-1XX 123 Halt -P occurred and option 0 taken. But, the - pack mounted is not a part of volume set. - --2 DD-2XX 123 Multivolume load sequence error. - --3 DD-3XX 123 Multivolume load sequence error. - --4 DD-4XX 0123 Warning that one or more volumes are about to be - bypassed. - --5 DD-5XX 123 Multivolume file not found. 1: mount correct pack. - --6 DD-6XX 0 23 Warning. ENd of volume and HIKEY not found. - --7 DD-7XX 1 3 -A halt and option 1 taken. But the pack referenced - does not match pack name. - --8 DD-8XX 3 Multivolume file referenced but file isn't - multivolume. - --9 DD-9XX 3 Add to a multivolumen file, but last pack not - mounted. - --A DD-AXX 1 3 Add to existing multivolume filebut no room. - --C DD-CXX 3 Multivolume file error. Probably out of sequence - volume mounts. - --E DD-EXX 123 Next volume cannot be processed, because the - location is not available or space is not available - or there are scratch files on the pack. - --F DD-Fxx 123 Finished a volume, next cannot be processed, mount - the correct pack or cancel. - --H DD-Hxx 3 HIKEY length does not match file. - --J DD-Jxx 01 3 First volume referenced is not volumme 1. 0: - continue with this volume, 1: mount another pack. - --L DD-Lxx 3 Output to multivolume, but file isn't multivolume - or referenced volume isn't first one of set. - --P DD-PXX 0123 Mount next volume. XX=unit number. 0: continue - bypassing volumes, 1: mount next volume. - --U DD-UXX 1 3 Halt -J just occurred and 0 or 1 taken. But the - pack name is incorrect or the file isn't found. - -- DD- 123 Multivolume key error. Key too low or high for - volume. - --' DD-' 123 Sequential add to multivolume file, but HIKEY - record missing on previous volume. - -'0 GM'0DE 3 SYSGEN. I/O Error on reader. - GM'0EX 3 SYSGEN. End of extent on MACOUT or $SOURCE. - GM'0IC 1 3 SYSGEN. Option dependent on a preceding option, the - preceding one was omitted or invalid. - GM'0ID 1 3 SYSGEN invalid delimiter. - GM'0IK 1 3 SYSGEN invalid keyword. - GM'0IR 1 3 SYSGEN invalid option. - GM'0IS 1 3 SYSGEN sequence error. - GM'0NF 1 3 SYSGEN entry in cols 8-12 not found. - GM'0NS 3 SYSGEN Requested source program not found. - GM'0EM 1 3 SYSGEN. END statement not found. - GM'0NP 3 SYSGEN. Module $SGXP2, $SGXP3, $SGXP4, $SGXP5, or - $SGXP6 missing for sysgen, or $MPXP2, $MPXP3 or - $MPXP4 missing for macro processor. - -'1 GG'1 3 System Generation Errors. - -'2 0 3 Error during macro processor run. - -'3 3 Invalid 5445 disk label record. - -'4 GG'4EX 3 Out of room on Sysgen, or disk error. - ------------------------ End of haltguide.txt --------------------------- diff --git a/S3/readme_s3.txt b/S3/readme_s3.txt deleted file mode 100644 index 37afdd9c..00000000 --- a/S3/readme_s3.txt +++ /dev/null @@ -1,78 +0,0 @@ - Welcome to the IBM System/3 Model 10 SIMH simulator. - --------------------------------------------------- - - To compile under linux: - - cc s3*.c scp*.c sim_rev.c -o s3 - - This code can be compiled and run as a console application using - Microsoft Visual C++. - - - - To IPL the provided SCP distribution disk: - - ./s3 - sim> at r1 m10scp.dsk - sim> at f1 f1f1f1.dsk - sim> at lpt print.txt - sim> d sr 5471 - sim> boot r1 - - - // DATE 06/14/01 - // NOHALT - // LOAD $MAINT,R1 - // RUN - // COPY FROM-R1,LIBRARY-ALL,NAME-DIR,TO-PRINT - // END - - - (A printout of the libraries and directories on the SCP DTR - disk will be in the file print.txt) - - - The text file "system3.txt" gives details on the simulators - implementation of System/3 hardware. - - A write up on the use of the SCP and the OCL job control language is - in the text file "userguide.txt". This includes examples of using the - utility programs, and a tutorial guiding you thru a sysgen. - - A nearly complete listing of all possible SCP halts is in the - document "haltguide.txt". - - IMPORTANT NOTES: - - 1) How to correct typing errors when using the System/3 console: - If you make an error, press ESC, which will cancel the current - line being typed and print a quote in position 1. Then you - can use CTRL/R to retype characters up until the error, then - type correctly. Or simply retype the line. BACKSPACE DOES NOT - WORK with the SCP. - - 2) While the simulator allows disk images to be independently - attached to any disk unit, on the real hardware R1 and F1 were on - a single spindle, and R2 and F2 likewise. It is not possible using - SCP to attach R1 without attaching a disk image to F1 also, because - SCP will always look at F1 even when IPLed off R1. - - The OS distributed with the simulator is version 16 of the Model - 10 SCP. This is sysgenned with support only for R1 and F1. If you - do a sysgen to support R2 amd F2 also, you must have images attached - to all 4 disks when you IPL, because SCP looks at all drives when - it starts up, and you will get an "Unattached Unit" error if you - fail to have one attached. - - 3) The 1442 card reader had in reality one card input hopper - and two stackers. This means the same path is used for reading and - punching cards. When punching cards, SCP does a read operation - and inspects the card read for blanks, and if it is not blank, - issues a YH halt. SCP will not punch data onto non-blank cards. - This feature causes problems in the simulator, and as a result - if you punch cards from SCP, YOU MUST not have any file attached - to the CDR device. Leaving this device unattached presents an - infinite supply of blank cards to SCP for punching. - - - -- End of README_S3.txt -- diff --git a/S3/s3_cd.c b/S3/s3_cd.c deleted file mode 100644 index 77423b19..00000000 --- a/S3/s3_cd.c +++ /dev/null @@ -1,442 +0,0 @@ -/* s3_cd.c: IBM 1442 card reader/punch - - Copyright (c) 2001-2003, Charles E. Owen - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. - - cdr card reader - cdp card punch - cdp2 card punch stacker 2 - - 25-Apr-03 RMS Revised for extended file support - 08-Oct-02 RMS Added impossible function catcher - - Normally, cards are represented as ASCII text streams terminated by newlines. - This allows cards to be created and edited as normal files. Set the EBCDIC - flag on the card unit allows cards to be read or punched in EBCDIC format, - suitable for binary data. -*/ - -#include "s3_defs.h" -#include - -extern uint8 M[]; -extern char ebcdic_to_ascii[256]; -extern char ascii_to_ebcdic[256]; -int32 s1sel, s2sel; -char rbuf[CBUFSIZE]; /* > CDR_WIDTH */ -t_stat cdr_svc (UNIT *uptr); -t_stat cdr_boot (int32 unitno, DEVICE *dptr); -t_stat cdr_attach (UNIT *uptr, char *cptr); -t_stat cd_reset (DEVICE *dptr); -t_stat read_card (int32 ilnt, int32 mod); -t_stat punch_card (int32 ilnt, int32 mod); - -int32 DAR; /* Data address register */ -int32 LCR; /* Length Count Register */ -int32 lastcard = 0; /* Last card switch */ -int32 carderr = 0; /* Error switch */ -int32 pcherror = 0; /* Punch error */ -int32 notready = 0; /* Not ready error */ -int32 cdr_ebcdic = 0; /* EBCDIC mode on reader */ -int32 cdp_ebcdic = 0; /* EBCDIC mode on punch */ - -extern int32 GetMem(int32 addr); -extern int32 PutMem(int32 addr, int32 data); - -/* Card reader data structures - - cdr_dev CDR descriptor - cdr_unit CDR unit descriptor - cdr_reg CDR register list -*/ - -UNIT cdr_unit = { - UDATA (&cdr_svc, UNIT_SEQ+UNIT_ATTABLE, 0), 100 }; - -REG cdr_reg[] = { - { FLDATA (LAST, lastcard, 0) }, - { FLDATA (ERR, carderr, 0) }, - { FLDATA (NOTRDY, notready, 0) }, - { HRDATA (DAR, DAR, 16) }, - { HRDATA (LCR, LCR, 16) }, - { FLDATA (EBCDIC, cdr_ebcdic, 0) }, - { FLDATA (S2, s2sel, 0) }, - { DRDATA (POS, cdr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, cdr_unit.wait, 24), PV_LEFT }, - { BRDATA (BUF, rbuf, 8, 8, CDR_WIDTH) }, - { NULL } }; - -DEVICE cdr_dev = { - "CDR", &cdr_unit, cdr_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &cd_reset, - &cdr_boot, &cdr_attach, NULL }; - -/* CDP data structures - - cdp_dev CDP device descriptor - cdp_unit CDP unit descriptor - cdp_reg CDP register list -*/ - -UNIT cdp_unit = { - UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }; - -REG cdp_reg[] = { - { FLDATA (ERR, pcherror, 0) }, - { FLDATA (EBCDIC, cdp_ebcdic, 0) }, - { FLDATA (S2, s2sel, 0) }, - { FLDATA (NOTRDY, notready, 0) }, - { HRDATA (DAR, DAR, 16) }, - { HRDATA (LCR, LCR, 16) }, - { DRDATA (POS, cdp_unit.pos, T_ADDR_W), PV_LEFT }, - { NULL } }; - -DEVICE cdp_dev = { - "CDP", &cdp_unit, cdp_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &cd_reset, - NULL, NULL, NULL }; - -/* Stacker data structures - - stack_dev STACK device descriptor - stack_unit STACK unit descriptors - stack_reg STACK register list -*/ - -UNIT stack_unit[] = { - { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) } }; - -REG stack_reg[] = { - { DRDATA (POS0, stack_unit[0].pos, 32), PV_LEFT }, - { NULL } }; - -DEVICE stack_dev = { - "CDP2", stack_unit, stack_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &cd_reset, - NULL, NULL, NULL }; - - -/* -------------------------------------------------------------------- */ - -/* 1442: master routine */ - -int32 crd (int32 op, int32 m, int32 n, int32 data) -{ - int32 iodata; - switch (op) { - case 0: /* SIO 1442 */ - /* if (n == 1) - return STOP_IBKPT; */ - switch (data) { /* Select stacker */ - case 0x00: - break; - case 0x01: - s2sel = 1; - break; - default: - break; - } - switch (n) { - case 0x00: /* Feed */ - iodata = SCPE_OK; - break; - case 0x01: /* Read only */ - if (cdr_ebcdic) - iodata = read_card(0, 1); - else - iodata = read_card(0, 0); - break; - case 0x02: /* Punch and feed */ - iodata = punch_card(0, 0); - break; - case 0x03: /* Read Col Binary */ - iodata = read_card(0, 1); - break; - case 0x04: /* Punch no feed */ - iodata = punch_card(0, 1); - break; - default: - return STOP_INVDEV; - } - return iodata; - case 1: /* LIO 1442 */ - switch (n) { - case 0x00: /* Load LCR */ - LCR = data & 0xffff; - break; - case 0x04: - DAR = data & 0xffff; - break; - default: - return STOP_INVDEV; - } - return SCPE_OK; - case 2: /* TIO 1442 */ - iodata = 0; - switch (n) { - case 0x00: /* Error */ - if (carderr || pcherror || notready) - iodata = 1; - if ((cdr_unit.flags & UNIT_ATT) == 0) - iodata = 1; /* attached? */ - break; - case 0x02: /* Busy */ - if (sim_is_active (&cdr_unit)) - iodata = 1; - break; - default: - return (STOP_INVDEV << 16); - } - return ((SCPE_OK << 16) | iodata); - case 3: /* SNS 1442 */ - iodata = 0; - switch (n) { - case 0x01: - break; - case 0x02: - break; - case 0x03: - if (carderr) - iodata |= 0x80; - if (lastcard) - iodata |= 0x40; - if (pcherror) - iodata |= 0x20; - if ((cdr_unit.flags & UNIT_ATT) == 0) - iodata |= 0x08; - if (notready) - iodata |= 0x08; - break; - case 0x04: - iodata = DAR; - break; - default: - return (STOP_INVDEV << 16); - } - iodata |= ((SCPE_OK << 16) & 0xffff0000); - return (iodata); - case 4: /* APL 1442 */ - iodata = 0; - switch (n) { - case 0x00: /* Error */ - if (carderr || pcherror || notready) - iodata = 1; - if ((cdr_unit.flags & UNIT_ATT) == 0) - iodata = 1; /* attached? */ - break; - case 0x02: /* Busy */ - if (sim_is_active (&cdr_unit)) - iodata = 1; - break; - default: - return (STOP_INVDEV << 16); - } - return ((SCPE_OK << 16) | iodata); - default: - break; - } - printf (">>CRD non-existent function %d\n", op); - return SCPE_OK; -} - -/* Card read routine - mod 0 = ASCII read - mod 1 = EBCDIC read -*/ - -t_stat read_card (int32 ilnt, int32 mod) -{ -int32 i; -t_stat r; - -if (sim_is_active (&cdr_unit)) { /* busy? */ - sim_cancel (&cdr_unit); /* cancel */ - if (r = cdr_svc (&cdr_unit)) return r; /* process */ -} - -if (((cdp_unit.flags & UNIT_ATT) != 0 || - (stack_unit[0].flags & UNIT_ATT) != 0) && /* Punch is attached and */ - (cdr_unit.flags & UNIT_ATT) == 0) { /* reader is not --- */ - for (i = 0; i < 80; i++) { /* Assume blank cards in hopper */ - PutMem(DAR, 0x40); - DAR++; - } - sim_activate (&cdr_unit, cdr_unit.wait); /* activate */ - return SCPE_OK; -} - -if ((cdr_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ - -lastcard = carderr = notready = s1sel = s2sel = 0; /* default stacker */ - -for (i = 0; i < CBUFSIZE; i++) rbuf[i] = 0x20; /* clear buffer */ -if (mod) { - for (i = 0; i < 80; i++) { - rbuf[i] = fgetc(cdr_unit.fileref); /* Read EBCDIC */ - } -} else { - fgets (rbuf, CBUFSIZE, cdr_unit.fileref); /* read Ascii */ -} -if (feof (cdr_unit.fileref)) { /* eof? */ - notready = 1; - return STOP_NOCD; -} -if (ferror (cdr_unit.fileref)) { /* error? */ - perror ("Card reader I/O error"); - clearerr (cdr_unit.fileref); - carderr = 1; - return SCPE_OK; } -cdr_unit.pos = ftell (cdr_unit.fileref); /* update position */ -i = getc (cdr_unit.fileref); /* see if more */ -if (feof (cdr_unit.fileref)) lastcard = 1; /* eof? set flag */ -fseek (cdr_unit.fileref, cdr_unit.pos, SEEK_SET); -for (i = 0; i < 80; i++) { - if (mod == 0) { /* If ASCII mode... */ - if (rbuf[i] == '\n' || /* remove ASCII CR/LF */ - rbuf[i] == '\r' || - rbuf[i] == 0x00) - rbuf[i] = ' '; - rbuf[i] = ascii_to_ebcdic[rbuf[i]]; /* convert to EBCDIC */ - } - PutMem(DAR, rbuf[i]); /* Copy to main memory */ - DAR++; -} -sim_activate (&cdr_unit, cdr_unit.wait); /* activate */ -return SCPE_OK; -} - -/* Card reader service. If a stacker select is active, copy to the - selected stacker. Otherwise, copy to the normal stacker. If the - unit is unattached, simply exit. -*/ - -t_stat cdr_svc (UNIT *uptr) -{ -int32 i; - -if (s2sel) uptr = &stack_unit[0]; /* stacker 1? */ -else uptr = &stack_unit[0]; /* then default */ -if ((uptr -> flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ -for (i = 0; i < CDR_WIDTH; i++) rbuf[i] = ebcdic_to_ascii[rbuf[i]]; -for (i = CDR_WIDTH - 1; (i >= 0) && (rbuf[i] == ' '); i--) rbuf[i] = 0; -rbuf[CDR_WIDTH] = 0; /* null at end */ -fputs (rbuf, uptr -> fileref); /* write card */ -fputc ('\n', uptr -> fileref); /* plus new line */ -if (ferror (uptr -> fileref)) { /* error? */ - perror ("Card stacker I/O error"); - clearerr (uptr -> fileref); -} -uptr -> pos = ftell (uptr -> fileref); /* update position */ -return SCPE_OK; -} - -/* Card punch routine - - mod: not used -*/ - -t_stat punch_card (int32 ilnt, int32 mod) -{ -int32 i, colcount; -static char pbuf[CDP_WIDTH + 1]; /* + null */ -UNIT *uptr; - -if (s2sel) uptr = &stack_unit[0]; /* stack 2? */ -else uptr = &cdp_unit; /* normal output */ -if ((uptr -> flags & UNIT_ATT) == 0) { /* Attached? */ - notready = 1; - return SCPE_OK; -} -pcherror = s1sel = notready = 0; /* clear flags */ - -colcount = 128 - LCR; -for (i = 0; i < colcount; i++) { /* Fetch data */ - if (cdp_ebcdic) - pbuf[i] = GetMem(DAR) & 0xff; - else - pbuf[i] = ebcdic_to_ascii[GetMem(DAR)]; - DAR++; -} -for (i = CDP_WIDTH - 1; (i >= 0) && (pbuf[i] == ' '); i--) pbuf[i] = 0; -pbuf[CDP_WIDTH] = 0; /* trailing null */ -if (!cdp_ebcdic) { - fputs (pbuf, uptr -> fileref); /* output card */ - fputc ('\n', uptr -> fileref); /* plus new line */ -} else { - for (i = 0; i < 80; i++) { - fputc(pbuf[i], uptr -> fileref); - } -} -if (ferror (uptr -> fileref)) { /* error? */ - perror ("Card punch I/O error"); - clearerr (uptr -> fileref); - pcherror = 1; -} -uptr -> pos = ftell (uptr -> fileref); /* update position */ -return SCPE_OK; -} - -/* Select stack routine - - Modifiers have been checked by the caller - Modifiers are 1, 2, for the respective stack -*/ - -t_stat select_stack (int32 ilnt, int32 mod) -{ -if (mod == 1) s1sel = 1; -else if (mod == 2) s2sel = 1; -return SCPE_OK; -} - -/* Card reader/punch reset */ - -t_stat cd_reset (DEVICE *dptr) -{ -lastcard = carderr = notready = pcherror = 0; /* clear indicators */ -s1sel = s2sel = 0; /* clear stacker sel */ -sim_cancel (&cdr_unit); /* clear reader event */ -return SCPE_OK; -} - -/* Card reader attach */ - -t_stat cdr_attach (UNIT *uptr, char *cptr) -{ -carderr = lastcard = notready = 0; /* clear last card */ -return attach_unit (uptr, cptr); -} - -/* Bootstrap routine */ - -t_stat cdr_boot (int32 unitno, DEVICE *dptr) -{ -cdr_ebcdic = 1; -DAR = 0; -LCR = 80; -read_card(0, 1); -return SCPE_OK; -} diff --git a/S3/s3_cpu.c b/S3/s3_cpu.c deleted file mode 100644 index ae496175..00000000 --- a/S3/s3_cpu.c +++ /dev/null @@ -1,1832 +0,0 @@ -/* s3_cpu.c: IBM System/3 CPU simulator - - Copyright (c) 2001-2003, Charles E. Owen - HPL & SLC instruction code Copyright (c) 2001 by Henk Stegeman - Decimal Arithmetic Copyright (c) 2000 by Roger Bowler - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. - - ------------------------------------------------------------------------------ - - cpu System/3 (models 10 and 15) central processor - - The IBM System/3 was a popular small-business computing system introduced - in 1969 as an entry-level system for businesses that could not afford - the lowest rungs of the System/360. Its architecture is inspired by and - in some ways similar to the 360, but to save cost the instruction set is - much smaller and the I/O channel system greatly simplified. There is no - compatibilty between the two systems. - - The original System/3 had two models, 6 and 10, and these came in two - configurations: card system and disk system. The unique feature of - the /3 was the use of 96-column cards, although traditional 80-column - cards were supprted also via attachment of a 1442 reader/punch. - System/3 is a batch-oriented system, controlled by an operating - system known as SCP (System Control Program), with it's own job control - language known as OCL (simpler and more logical than the JCL used on - the mainframes). Original models did not support multiprogramming - or any form of interactivity. (There was a hardware dual-program - facility available on the model 10 at the high end). - - The line grew throughout the 1970s, overlapping the low end of the 360 - line with the introduction of the model 15. The 15 (and later larger - variations of the model 12) broke the 64K limit designed in the original - models by adding a simple address translation unit to support up to 512K - bytes. The model 15 added a system of storage protection and allowed - multiprogramming in up to 3 partitions. Communications were added to - allow support of multiple 3270 terminals and the models 12 and 15 broke - the batch orientation and facilitated interactive use via the CCP - (communications control program). The System/3 was effectively replaced - by the much easier to manage and use System/34 and System/36 at the - low and middle of the range, and by System/370 or System/38 at the - high end. - - This simulator implements the model 10 and model 15. Models 4, 6, - 8, and 12 are not supported (these were technical variations on the - design which offered no functionality not present on either 10 or 15). - - The System/3 is a byte-oriented machine with a data path of 8 bits - in all models, and an address width of 16 bits. - - The register state for the System/3 CPU is: - - BAR <0:15> Operand 1 address register - AAR <0:15> Operand 2 address register - XR1 <0:15> Index Register 1 - XR2 <0:15> Index Register 2 - PSR <0:15> Condition Register - IAR [0:9]<0:15> Instruction Address Register (p1, p2, plus 1 for each interrupt) - ARR [0:9]<0:15> Address Recall Register (p1, p2, plus 1 for each interrupt) - (The P2 IAR & ARR are used for the Dual Program feature) - - Instruction formats follow the same basic pattern: a 1-byte opcode, a - 1-byte "Q byte", and one or two addresses following in a format defined - by the first 4 bits of the opcode: - - Op Code Q Byte Address(es) - - 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 - +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--... - | A 1 | A 2 | operation | | (defined by operation)| | Format based on A1, A2 - +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--... - - { --- } <---------------- Bits 00 = Operand 2 specified by 2-byte direct addr - Bits 01 = Operand 2 is 1-byte displacement + XR1 - Bits 10 = Operand 2 is 1-byte displacement + XR2 - Bits 11 = Operand 2 is not used - - { --- } <---------------------- Bits 00 = Operand 1 specified by 2-byte direct addr - Bits 01 = Operand 1 is 1-byte displacement + XR1 - Bits 10 = Operand 1 is 1-byte displacement + XR2 - Bits 11 = Operand 1 is not used - - Instructions come in 3 basic formats, of varying lengths which are determined - by the top 4 bits of opcode defined above. Minimum instruction length is 3 bytes, - maximum is 6. - - 1) Command Format (Bits 0-3 are 1111): - - +------------+ +------------+ +------------+ - | Opcode | | Q-byte | | R-byte + - +------------+ +------------+ +------------+ - - (The meaning of Q-byte and R-byte defined by the operation) - - - 2) One Address Instructions (either bits 0-1 or bits 2-3 are 01): - - - Direct Addressing Format: - - +------------+ +------------+ +-----------+----------+ - | Opcode | | Q-byte | | MSB + LSB + - +------------+ +------------+ +-----------+----------+ - - Base-Displacement Format: - - +------------+ +------------+ +------------+ - | Opcode | | Q-byte | |displacement+ - +------------+ +------------+ +------------+ - - Opcodes are 0011xxxx or 1100xxxx. - - Q-byte can be: 1) An immediate operand - 2) A mask - 3) A branch condition - 4) A data selection - - 2) Two Address Instructions (neither bits 0-1 nor bits 2-3 are both 11): - - Operand 1 Address Direct (opcodes 0001 or 0010): - - +------------+ +------------+ +----------+----------+ +------------+ - | Opcode | | Q-byte | | MSB + LSB + |displacement| - +------------+ +------------+ +----------+----------+ +------------+ - - Operand 2 Address Direct (opcodes 0100 or 1000): - - +------------+ +------------+ +------------+ +----------+----------+ - | Opcode | | Q-byte | |displacement| | MSB + LSB + - +------------+ +------------+ +------------+ +----------+----------+ - - Both Addresses Direct (opcode 0000): - - +------------+ +------------+ +----------+----------+ +-----------+----------+ - | Opcode | | Q-byte | | MSB + LSB + + MSB + LSB + - +------------+ +------------+ +----------+----------+ +-----------+----------+ - - Both Addresses Displacement (opcodes 0101, 0110, 1001, or 1010): - - +------------+ +------------+ +------------+ +------------+ - | Opcode | | Q-byte | |displacement| |displacement| - +------------+ +------------+ +------------+ +------------+ - - -Assembler Mnemonic Format -------------------------- - - The assembler format contains the same elements as the machine language operation, -but not always in the same format. The operation code frequently specifies both -the opcode and the Q byte, and the top nybble of the opcode is determined by -the format of the addresses. - - Addresses take two forms: the direct address in hex, or a relative address -specified thusly: (byte,XRx) where 'byte' is a 1-byte offset, and XRx is -either XR1 or XR2 for the two index registers. Use these formats when -'address' is indicated below: - - When 'reg' is mentioned, a mnemonic may be used for the register, thusly: - IAR Instruction Address Register for the current program level - ARR Address Recall Register for the current program level - P1IAR IAR for Program Level 1 - P2IAR IAR for Program Level 2 - PSR Program Status Register - 0x01 - Equal - 0x02 - Low - 0x04 - High - 0x08 - Decimal overflow - 0x10 - Test false - 0x20 - Binary overflow - 0x40 - Not used - 0x80 - Not used - XR1 Index Register 1 - XR2 Index Register 2 - IARx IAR for the interrupt level x (x = 0 thru 7) - - All other operands mentioned below are single-byte hex, except for the -length (len) operand of the two-address instructions, which is a decimal length -in the range 1-256. - - No-address formats: - ------------------ - - HPL hex,hex Halt Program Level, the operands are the Q and R bytes - - - One-address formats: - ------------------- - - A reg,address Add to register - CLI address,byte Compare Logical Immediate - MVI address,byte Move Immediate - TBF address,mask Test Bits Off - TBN address,mask Test Bits On - SBF address,mask Set Bits Off - SBN address,mask Set Bits On - ST reg,address Store Register - L reg,address Load Register - LA reg,address Load Address - JC address,cond Jump on Condition - BC address,cond Branch on Condition - - These operations do not specify a qbyte, it is implicit in the opcode: - - B address Unconditional branch to address - BE address Branch Equal - BNE address Branch Not Equal - BH address Branch High - BNH address Branch Not High - BL address Branch Low - BNL address Branch Not Low - BT address Branch True - BF address Branch False - BP address Branch Plus - BM address Branch Minus - BNP address Branch Not Plus - BNM address Branch Not Minus - BZ address Branch Zero - BNZ address Branch Not Zero - BOZ address Branch Overflow Zoned - BOL address Branch Overflow Logical - BNOZ address Branch No Overflow Zoned - BNOL address Branch No Overflow Logical - NOPB address No - never jump - - (substitute J for B above for a set of Jumps -- 1-byte operand (not 2), - always jumps forward up to 255 bytes. In this case, 'address' cannot be - less than the current address, nor greater than the current address + 255) - - Two-address formats (first address is destination, len is decimal 1-256): - ------------------- - - MVC address,address,len Move Characters - CLC address,address,len Compare Logical Characters - ALC address,address,len Add Logical Characters - SLC address,address,len Subtract Logical Characters - ED address,address,len Edit - ITC address,address,len Insert and Test Characters - AZ address,address,len Add Zoned Decimal - SZ address,address,len Subtract Zoned Decimal - - MNN address,address Move Numeric to Numeric - MNZ address,address Move Numeric to Zone - MZZ address,address Move Zone to Zone - MZN address,address Move Zone to Numeric - - I/O Format - ---------- - - In the I/O format, there are always 3 fields: - - da - Device Address 0-15 (decimal) - m - Modifier 0-1 - n - Function 0-7 - - The meaning of these is entirely defined by the device addressed. - - There may be an optional control byte, or an optional address (based on -the type of instruction). - - SNS da,m,n,address Sense I/O - LIO da,m,n,address Load I/O - TIO da,m,n,address Test I/O - - SIO da,m,n,cc Start I/O -- cc is a control byte - - APL da,m,n Advance Program Level - - - - --------------------------------------------- - Here is a handy opcode cross-reference table: - --------------------------------------------- - - | x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ----+------------------------------------------------------------------ -0x | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -1x | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -2x | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -3x | SNS LIO - - ST L A - TBN TBF SBN SBF MVI CLI - - - | -4x | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -5x | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -6x | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -7x | SNS LIO - - ST L A - TBN TBF SBN SBF MVI CLI - - - | -8x | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -9x | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -Ax | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -Bx | SNS LIO - - ST L A - TBN TBF SBN SBF MVI CLI - - - | -Cx | BC TIO LA - - - - - - - - - - - - - -Dx | BC TIO LA - - - - - - - - - - - - - -Ex | BC TIO LA - - - - - - - - - - - - - -Fx | HPL APL JC SIO - - - - - - - - - - - - - -*/ - -/* This routine is the instruction decode routine for System/3. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - breakpoint encountered - program check caused by invalid opcode or qbyte or address or I/O spec - unknown I/O device and STOP_DEV flag set - I/O error in I/O simulator - - 2. Interrupts. - - There are 8 levels of interrupt, each with it's own IAR (program - counter). When an interrupt occurs, execution begins at the - location in the IAR for that level interrupt. The program - must save and restore state. Each device is assigned both a - level and a priority in hardware. Interrupts are reset via - an SIO instruction, when this happens, the program level - IAR resumes control. - - Interrupts are maintained in the global variable int_req, - which is zero if no interrupts are pending, otherwise, the - lower 16 bits represent devices, rightmost bit being device - 0. Each device requesting an interrupt sets its bit on. - - - 3. Non-existent memory. On the System/3, any reference to non-existent - memory (read or write) causes a program check and machine stop. - - 4. Adding I/O devices. These modules must be modified: - - ibms3_defs.h add interrupt request definition - ibms3_cpu.c add IOT mask, PI mask, and routine to dev_table - ibms3_sys.c add pointer to data structures to sim_devices -*/ - -#include "s3_defs.h" - -#define UNIT_V_M15 (UNIT_V_UF) /* Model 15 extensions */ -#define UNIT_M15 (1 << UNIT_V_M15) -#define UNIT_V_DPF (UNIT_V_UF+1) /* Dual Programming */ -#define UNIT_DPF (1 << UNIT_V_DPF) -#define UNIT_V_MSIZE (UNIT_V_UF+3) /* dummy mask */ -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -uint8 M[MAXMEMSIZE] = { 0 }; /* memory */ -int32 AAR = 0; /* Operand 1 addr reg */ -int32 BAR = 0; /* Operand 2 addr reg */ -int32 XR1 = 0; /* Index register 1 */ -int32 XR2 = 0; /* Index register 2 */ -int32 PSR = 0; /* Condition Register */ -int32 IAR[10] = { 0 }; /* IAR 0-7 = int level 8=P1 9=P2 */ -int32 ARR[10] = { 0 }; /* ARR 0-7 = int level 8=P1 9=P2 */ -int32 dev_disable = 0; /* interrupt disable mask */ -int32 int_req = 0; /* Interrupt request device bitmap */ -int32 level = 8; /* Current Execution Level*/ -int32 stop_dev = 0; /* stop on ill dev */ -int32 SR = 0; /* Switch Register */ -int32 saved_PC; /* Saved (old) PC) */ -int32 debug_reg = 0; /* set for debug/trace */ -int32 debug_flag = 0; /* 1 when trace.log open */ -FILE *trace; -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_boot (int32 unitno, DEVICE *dptr1); -extern int32 pkb (int32 op, int32 m, int32 n, int32 data); -extern int32 crd (int32 op, int32 m, int32 n, int32 data); -extern int32 lpt (int32 op, int32 m, int32 n, int32 data); -extern int32 dsk1 (int32 op, int32 m, int32 n, int32 data); -extern int32 dsk2 (int32 op, int32 m, int32 n, int32 data); -extern int32 cpu (int32 op, int32 m, int32 n, int32 data); -extern t_stat sim_activate (UNIT *uptr, int32 delay); -extern int32 fprint_sym (FILE *of, int32 addr, unsigned int32 *val, - UNIT *uptr, int32 sw); -int32 nulldev (int32 opcode, int32 m, int32 n, int32 data); -int add_zoned (int32 addr1, int32 len1, int32 addr2, int32 len2); -int32 subtract_zoned (int32 addr1, int32 len1, int32 addr2, int32 len2); -static int32 compare(int32 byte1, int32 byte2, int32 cond); -static int32 condition(int32 qbyte); -static void store_decimal (int32 addr, int32 len, uint8 *dec, int sign); -static void load_decimal (int32 addr, int32 len, uint8 *result, int32 *count, int32 *sign); -static void add_decimal (uint8 *dec1, uint8 *dec2, uint8 *result, int32 *count); -static void subtract_decimal (uint8 *dec1, uint8 *dec2, uint8 *result, int *count, int *sign); -int32 GetMem(int32 addr); -int32 PutMem(int32 addr, int32 data); - -/* IOT dispatch table */ - -/* System/3 supports only 16 unique device addresses! */ - -struct ndev dev_table[16] = { - { 0, 0, &cpu }, /* Device 0: CPU control */ - { 1, 0, &pkb }, /* Device 1: 5471 console printer/keyboard */ - { 0, 0, &nulldev }, - { 0, 0, &nulldev }, - { 0, 0, &nulldev }, - { 0, 0, &crd }, /* Device 5: 1442 card reader/punch */ - { 0, 0, &nulldev }, /* Device 6: 3410 Tape drives 1 & 2 */ - { 0, 0, &nulldev }, /* Device 7: 3410 Tape drives 3 & 4 */ - { 0, 0, &nulldev }, - { 0, 0, &nulldev }, - { 0, 0, &dsk1 }, /* Device 10: 5444 Disk Drive 1 */ - { 0, 0, &dsk2 }, /* Device 11: 5444 Disk Drive 2 */ - { 0, 0, &nulldev }, /* Device 12: 5448 Disk Drive 1 */ - { 0, 0, &nulldev }, /* DEvice 13: 5448 Disk Drive 2 */ - { 0, 0, &lpt }, /* Device 14: 1403/5203 Printer */ - { 0, 0, &nulldev } /* Device 15: 5424 MFCU */ -}; - -/* Priority assigned to interrupt levels */ - -int32 priority[8] = {8, 7, 5, 4, 3, 6, 2, 1}; - - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifiers list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, MAXMEMSIZE) }; - -REG cpu_reg[] = { - { HRDATA (IAR, saved_PC, 16), REG_RO }, - { HRDATA (IAR-P1, IAR[8], 16) }, - { HRDATA (IAR-P2, IAR[9], 16) }, - { HRDATA (ARR-P1, ARR[8], 16) }, - { HRDATA (ARR-P2, ARR[9], 16) }, - { HRDATA (AAR, AAR, 16) }, - { HRDATA (BAR, BAR, 16) }, - { HRDATA (XR1, XR1, 16) }, - { HRDATA (XR2, XR2, 16) }, - { HRDATA (PSR, PSR, 16) }, - { HRDATA (SR, SR, 16) }, - { HRDATA (INT, int_req, 16), REG_RO }, - { HRDATA (LEVEL, level, 16) }, - { HRDATA (IAR0, IAR[0], 16) }, - { HRDATA (IAR1, IAR[1], 16) }, - { HRDATA (IAR2, IAR[2], 16) }, - { HRDATA (IAR3, IAR[3], 16) }, - { HRDATA (IAR4, IAR[4], 16) }, - { HRDATA (IAR5, IAR[5], 16) }, - { HRDATA (IAR6, IAR[6], 16) }, - { HRDATA (IAR7, IAR[7], 16) }, - { HRDATA (ARR0, ARR[0], 16) }, - { HRDATA (ARR1, ARR[1], 16) }, - { HRDATA (ARR2, ARR[2], 16) }, - { HRDATA (ARR3, ARR[3], 16) }, - { HRDATA (ARR4, ARR[4], 16) }, - { HRDATA (ARR5, ARR[5], 16) }, - { HRDATA (ARR6, ARR[6], 16) }, - { HRDATA (ARR7, ARR[7], 16) }, - { HRDATA (DISABLE, dev_disable, 16), REG_RO }, - { FLDATA (STOP_DEV, stop_dev, 0) }, - { HRDATA (WRU, sim_int_char, 8) }, - { HRDATA (DEBUG, debug_reg, 16) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_M15, UNIT_M15, "M15", "M15", NULL }, - { UNIT_M15, 0, "M10", "M10", NULL }, - { UNIT_DPF, UNIT_DPF, "DPF", "DPF", NULL }, - { UNIT_DPF, 0, "NODPF", "NODPF", NULL }, - { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, - { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, - { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, - { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size }, - { UNIT_MSIZE, 65535, NULL, "64K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 16, 16, 1, 16, 8, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -t_stat sim_instr (void) -{ -extern int32 sim_interval; -register int32 PC, IR; -int32 i, j, carry, zero, op1, op2; -int32 opcode = 0, qbyte = 0, rbyte = 0; -int32 opaddr, addr1, addr2, dlen1, dlen2, r; -int32 int_savelevel = 8, intpri, intlev, intdev, intmask; -int32 devno, devm, devn; -char display[3][9]; -int32 val [32]; -register t_stat reason; - -/* Restore register state */ - -PC = IAR[level]; /* load local PC */ -reason = 0; - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } - - -if (int_req) { /* interrupt? */ - intpri = 16; - for (i = 0; i < 16; i++) { /* Get highest priority device */ - if ((int_req >> i) & 0x01) { - intlev = dev_table[i].level; - if (priority[intlev] < intpri) { - intdev = i; - intpri = priority[intlev]; - } - } - } - intmask = 1 << intdev; /* mask is interrupting dev bit */ - int_req = ~int_req & intmask; /* Turn off int_req for device */ - int_savelevel = level; /* save current level for reset */ - level = dev_table[intdev].level; /* get int level from device */ - PC = IAR[level]; /* Use int level IAR for new PC */ -} /* end interrupt */ - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; -} - -/* Machine Instruction Execution Here */ - -if ((debug_reg == 0) && debug_flag == 1) { - fclose(trace); - debug_flag = 0; -} -if (debug_reg) { - if (!debug_flag) { - trace = fopen("trace.log", "w"); - debug_flag = 1; - } -} - -if (debug_reg & 0x01) { - fprintf(trace, "ARR=%04X XR1=%04X XR2=%04X IAR=%04X ", ARR[level], XR1, XR2, PC); - val[0] = GetMem(PC); - val[1] = GetMem(PC+1); - val[2] = GetMem(PC+2); - val[3] = GetMem(PC+3); - val[4] = GetMem(PC+4); - val[5] = GetMem(PC+5); - fprint_sym(trace, PC, (uint32 *) val, &cpu_unit, SWMASK('M')); - fprintf(trace, "\n"); -} - -saved_PC = PC; -opaddr = GetMem(PC) & 0xf0; /* fetch addressing mode */ -opcode = GetMem(PC) & 0x0f; /* fetch opcode */ -PC = (PC + 1) & AMASK; -sim_interval = sim_interval - 1; - -qbyte = GetMem(PC) & 0xff; /* fetch qbyte */ -PC = (PC + 1) & AMASK; - -if (opaddr == 0xf0) { /* Is it command format? */ - rbyte = GetMem(PC) & 0xff; - PC = (PC + 1) & AMASK; - switch (opcode) { - case 0x00: /* HPL: Halt Program Level */ - for (i = 0; i < 3; i++) { - for (j = 0; j < 9; j++) { - display[i][j] = ' '; - } - } - /* First line */ - if (qbyte & 0x04) display[0][2] = '_' ; - if (rbyte & 0x04) display[0][6] = '_' ; - /* Second line */ - if (qbyte & 0x08) display[1][1] = '|' ; - if (rbyte & 0x08) display[1][5] = '|' ; - if (qbyte & 0x10) display[1][2] = '_' ; - if (rbyte & 0x10) display[1][6] = '_' ; - if (qbyte & 0x02) display[1][3] = '|' ; - if (rbyte & 0x02) display[1][7] = '|' ; - /* Third line */ - if (qbyte & 0x20) display[2][1] = '|' ; - if (rbyte & 0x20) display[2][5] = '|' ; - if (qbyte & 0x40) display[2][2] = '_' ; - if (rbyte & 0x40) display[2][6] = '_' ; - if (qbyte & 0x01) display[2][3] = '|' ; - if (rbyte & 0x01) display[2][7] = '|' ; - /* Print display segment array */ - printf("\n\r"); - for (i = 0; i < 3; i++) { - for (j = 0; j < 9; j++) { - printf ("%c", display[i][j]); - } - printf ("\n\r"); - } - reason = STOP_HALT; - break; - case 0x01: /* APL: Advance Program Level */ - devno = (qbyte >> 4) & 0x0f; - devm = (qbyte >> 3) & 0x01; - devn = qbyte & 0x07; - op1 = dev_table[devno].routine(4, devm, devn, rbyte); - if (op1 & 0x01) { - if (cpu_unit.flags & UNIT_DPF) { /* Dual Programming? */ - if (level == 8) /* Yes: switch program levels */ - level = 9; - else - level = 8; - PC = IAR[level]; - } else { /* No: Loop on this inst */ - PC = PC - 3; - } - } - reason = (op1 >> 16) & 0xffff; - break; - case 0x02: /* JC: Jump on Condition */ - if (condition(qbyte) == 1) { - PC = (PC + rbyte) & AMASK; - } - break; - case 0x03: /* SIO: Start I/O */ - devno = (qbyte >> 4) & 0x0f; - devm = (qbyte >> 3) & 0x01; - devn = qbyte & 0x07; - reason = dev_table[devno].routine(0, devm, devn, rbyte); - if (reason == RESET_INTERRUPT) { - reason = SCPE_OK; - IAR[level] = PC; - level = int_savelevel; - PC = IAR[level]; - } - break; - default: - reason = STOP_INVOP; - break; - } /* switch (opcode) */ - IAR[level] = PC; - continue; -} -/* Not command format: fetch the addresses */ - -addr1 = (opaddr >> 6) & 3; -addr2 = (opaddr >> 4) & 3; - -switch (addr1) { - case 0: - BAR = GetMem(PC) << 8; - PC = (PC + 1) & AMASK; - BAR |=GetMem(PC); - PC = (PC + 1) & AMASK; - break; - case 1: - BAR = GetMem(PC); - BAR = (BAR + XR1) & AMASK; - PC = (PC + 1) & AMASK; - break; - case 2: - BAR = GetMem(PC); - BAR = (BAR + XR2) & AMASK; - PC = (PC + 1) & AMASK; - break; - case 3: - break; - default: - break; -} /* switch (addr1) */ - -switch (addr2) { - case 0: - AAR = GetMem(PC) << 8; - PC = (PC + 1) & AMASK; - AAR |= GetMem(PC); - PC = (PC + 1) & AMASK; - break; - case 1: - AAR = GetMem(PC); - AAR = (AAR + XR1) & AMASK; - PC = (PC + 1) & AMASK; - break; - case 2: - AAR = GetMem(PC); - AAR = (AAR + XR2) & AMASK; - PC = (PC + 1) & AMASK; - break; - case 3: - break; - default: - break; -} /* switch (addr1) */ - -switch (opaddr) { - case 0x00: - case 0x10: - case 0x20: - case 0x40: - case 0x50: - case 0x60: - case 0x80: - case 0x90: - case 0xa0: - switch (opcode) { - case 4: /* ZAZ: Zero and Add Zoned */ - dlen2 = qbyte & 0x0f; - dlen1 = (qbyte >> 4) & 0xf; - dlen1 += dlen2; - op1 = BAR; - for (i = 0; i < (dlen1+1); i++) { - PutMem(op1, 0xf0); - op1--; - } - r = add_zoned(BAR, dlen1+1, AAR, dlen2+1); - PSR &= 0xF8; /* HJS mod */ - switch (r) { - case 0: - PSR |= 0x01; - break; - case 1: - PSR |= 0x02; - break; - case 2: - PSR |= 0x04; - break; - default: - break; - } - break; - case 6: /* AZ: Add Zoned */ - dlen2 = qbyte & 0x0f; - dlen1 = (qbyte >> 4) & 0xf; - dlen1 += dlen2; - r = add_zoned(BAR, dlen1+1, AAR, dlen2+1); - PSR &= 0xF0; - switch (r) { - case 0: - PSR |= 0x01; - break; - case 1: - PSR |= 0x02; - break; - case 2: - PSR |= 0x04; - break; - case 3: - PSR |= 0x08; - break; - default: - break; - } - break; - case 7: /* SZ: Subtract Zoned */ - dlen2 = qbyte & 0x0f; - dlen1 = (qbyte >> 4) & 0xf; - dlen1 += dlen2; - r = subtract_zoned(BAR, dlen1+1, AAR, dlen2+1); - PSR &= 0xF0; - switch (r) { - case 0: - PSR |= 0x01; - break; - case 1: - PSR |= 0x02; - break; - case 2: - PSR |= 0x04; - break; - case 3: - PSR |= 0x08; - break; - default: - break; - } - break; - case 8: /* MVX: Move Hex */ - op1 = GetMem(BAR); - op2 = GetMem(AAR); - switch (qbyte) { - case 0: /* Zone to zone */ - op1 = (op1 & 0x0F) | (op2 & 0xF0); - break; - case 1: /* Numeric to zone */ - op1 = (op1 & 0x0F) | (op2 << 4); - break; - case 2: /* Zone to numeric */ - op1 = (op1 & 0xF0) | (op2 >> 4); - break; - case 3: /* Numeric to numeric */ - op1 = (op1 & 0xF0) | (op2 & 0x0F); - break; - default: - reason = STOP_INVQ; - break; - } - PutMem(BAR, op1); - break; - case 0xa: /* ED: Edit */ - zero = 1; - PSR &= 0xF8; - IR = GetMem(AAR); - if ((IR & 0xf0) != 0xF0) - PSR |= 0x02; - else - PSR |= 0x04; - while (qbyte > -1) { - op2 = GetMem(AAR); - op1 = GetMem(BAR); - if (op1 == 0x20) { - op2 |= 0xf0; - PutMem(BAR, op2); - AAR--; - if (op2 != 0xF0) zero = 0; - } - BAR--; - qbyte--; - } - if (zero) - PSR |= 0x01; - break; - case 0xb: /* ITC: Insert and Test Chars */ - op2 = GetMem(AAR); - while (qbyte > -1) { - op1 = GetMem(BAR); - if (op1 >= 0xF1 && op1 <= 0xF9) - break; - PutMem(BAR, op2); - BAR++; - qbyte--; - } - ARR[level] = BAR; - break; - case 0xc: /* MVC: Move Characters */ - while (qbyte > -1) { - PutMem(BAR, GetMem(AAR)); - BAR--; - AAR--; - qbyte--; - } - break; - case 0xd: /* CLC: Compare Characters */ - PSR &= 0xF8; - i = BAR = BAR - qbyte; - j = AAR = AAR - qbyte; - while (qbyte > -1) { - if (GetMem(i) > GetMem(j)) { - PSR |= 0x04; - break; - } - if (GetMem(i) < GetMem(j)) { - PSR |= 0x02; - break; - } - i++; - j++; - qbyte--; - } - if (qbyte == -1) - PSR |= 0x01; - break; - case 0xe: /* ALC: Add Logical Characters */ - carry = 0; - zero = 1; - while (qbyte > -1) { - IR = GetMem(BAR) + GetMem(AAR) + carry; - if (IR & 0x100) - carry = 1; - else - carry = 0; - if ((IR & 0xFF) != 0) zero = 0; /* HJS mod */ - PutMem(BAR,(IR & 0xFF)); - BAR--; - AAR--; - qbyte--; - } - PSR &= 0xD8; - if (zero) - PSR |= 0x01; /* Equal */ - if (!zero && !carry) - PSR |= 0x02; /* Low */ - if (!zero && carry) - PSR |= 0x04; /* High */ - if (carry) - PSR |= 0x20; /* Overflow */ - break; - case 0xf: /* SLC: Subtract Logical Characters */ - carry = 1; - zero = 1; - while (qbyte > -1) { - IR = GetMem(BAR) + (0xFF - GetMem(AAR)) + carry; - if (IR & 0x100) - carry = 1; - else - carry = 0; - if ((IR & 0xFF) != 0) zero = 0; /* HJS mod */ - PutMem(BAR,(IR & 0xFF)); - BAR--; - AAR--; - qbyte--; - } - PSR &= 0xF8; - if (zero) - PSR |= 0x01; /* Equal */ - if (!zero && !carry) - PSR |= 0x02; /* Low */ - if (!zero && carry) - PSR |= 0x04; /* High */ - break; - default: - reason = STOP_INVOP; - break; - } - IAR[level] = PC; - continue; - break; - case 0x30: - case 0x70: - case 0xb0: - switch (opcode) { - case 0: /* SNS: Sense I/O */ - devno = (qbyte >> 4) & 0x0f; - devm = (qbyte >> 3) & 0x01; - devn = qbyte & 0x07; - i = dev_table[devno].routine(3, devm, devn, rbyte); - PutMem(BAR, i & 0xff); - BAR--; - PutMem(BAR, (i >> 8) & 0xff); - reason = (i >> 16) & 0xffff; - break; - case 1: /* LIO: Load I/O */ - devno = (qbyte >> 4) & 0x0f; - devm = (qbyte >> 3) & 0x01; - devn = qbyte & 0x07; - op1 = GetMem(BAR); - BAR--; - op1 |= (GetMem(BAR) << 8) & 0xff00; - reason = dev_table[devno].routine(1, devm, devn, op1); - break; - case 4: /* ST: Store Register */ - switch (qbyte) { - case 0x01: - PutMem(BAR, XR1 & 0xff); - BAR--; - PutMem(BAR, (XR1 >> 8) & 0xff); - break; - case 0x02: - PutMem(BAR, XR2 & 0xff); - BAR--; - PutMem(BAR, (XR2 >> 8) & 0xff); - break; - case 0x04: - PutMem(BAR, PSR & 0xFF); - BAR--; - PutMem(BAR, 0); /* LCRR, not imp. */ - break; - case 0x08: - PutMem(BAR, ARR[level] & 0xff); - BAR--; - PutMem(BAR, (ARR[level] >> 8) & 0xff); - break; - case 0x10: - PutMem(BAR, IAR[level] & 0xff); - BAR--; - PutMem(BAR, (IAR[level] >> 8) & 0xff); - break; - case 0x20: - PutMem(BAR, IAR[8] & 0xff); - BAR--; - PutMem(BAR, (IAR[8] >> 8) & 0xff); - break; - case 0x40: - PutMem(BAR, IAR[9] & 0xff); - BAR--; - PutMem(BAR, (IAR[9] >> 8) & 0xff); - break; - case 0x80: - PutMem(BAR, IAR[0] & 0xff); - BAR--; - PutMem(BAR, (IAR[0] >> 8) & 0xff); - break; - case 0x81: - PutMem(BAR, IAR[7] & 0xff); - BAR--; - PutMem(BAR, (IAR[7] >> 8) & 0xff); - break; - case 0x82: - PutMem(BAR, IAR[6] & 0xff); - BAR--; - PutMem(BAR, (IAR[6] >> 8) & 0xff); - break; - case 0x84: - PutMem(BAR, IAR[5] & 0xff); - BAR--; - PutMem(BAR, (IAR[5] >> 8) & 0xff); - break; - case 0x88: - PutMem(BAR, IAR[4] & 0xff); - BAR--; - PutMem(BAR, (IAR[4] >> 8) & 0xff); - break; - case 0x90: - PutMem(BAR, IAR[3] & 0xff); - BAR--; - PutMem(BAR, (IAR[3] >> 8) & 0xff); - break; - case 0xA0: - PutMem(BAR, IAR[2] & 0xff); - BAR--; - PutMem(BAR, (IAR[2] >> 8) & 0xff); - break; - case 0xC0: - PutMem(BAR, IAR[1] & 0xff); - BAR--; - PutMem(BAR, (IAR[1] >> 8) & 0xff); - break; - default: - reason = STOP_INVQ; - break; - } - break; - case 5: /* L: Load Register */ - switch (qbyte) { - case 0x01: - XR1 = GetMem(BAR) & 0xff; - BAR--; - XR1 |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x02: - XR2 = GetMem(BAR) & 0xff; - BAR--; - XR2 |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x04: - PSR = GetMem(BAR) & 0xff; - BAR--; - break; - case 0x08: - ARR[level] = GetMem(BAR) & 0xff; - BAR--; - ARR[level] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x10: - IAR[level] = GetMem(BAR) & 0xff; - BAR--; - IAR[level] |= (GetMem(BAR) << 8) & 0xff00; - PC = IAR[level]; - break; - case 0x20: - IAR[8] = GetMem(BAR) & 0xff; - BAR--; - IAR[8] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x40: - IAR[9] = GetMem(BAR) & 0xff; - BAR--; - IAR[9] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x80: - IAR[0] = GetMem(BAR) & 0xff; - BAR--; - IAR[0] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x81: - IAR[7] = GetMem(BAR) & 0xff; - BAR--; - IAR[7] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x82: - IAR[6] = GetMem(BAR) & 0xff; - BAR--; - IAR[6] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x84: - IAR[5] = GetMem(BAR) & 0xff; - BAR--; - IAR[5] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x88: - IAR[4] = GetMem(BAR) & 0xff; - BAR--; - IAR[4] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x90: - IAR[3] = GetMem(BAR) & 0xff; - BAR--; - IAR[3] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0xA0: - IAR[2] = GetMem(BAR) & 0xff; - BAR--; - IAR[2] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0xC0: - IAR[1] = GetMem(BAR) & 0xff; - BAR--; - IAR[1] |= (GetMem(BAR) << 8) & 0xff00; - break; - default: - reason = STOP_INVQ; - break; - } - break; - case 6: /* A: Add to Register */ - IR = GetMem(BAR) & 0x00ff; - BAR--; - IR |= (GetMem(BAR) << 8) & 0xff00; - switch (qbyte) { - case 0x01: - IR += XR1; - XR1 = IR & AMASK; - break; - case 0x02: - IR += XR2; - XR2 = IR & AMASK; - break; - case 0x04: - IR += PSR; - PSR = IR & AMASK; - break; - case 0x08: - IR += ARR[level]; - ARR[level] = IR & AMASK; - break; - case 0x10: - IR += IAR[level]; - IAR[level] = IR & AMASK; - break; - case 0x20: - IR += IAR[8]; - IAR[8] = IR & AMASK; - break; - case 0x40: - IR += IAR[9]; - IAR[9] = IR & AMASK; - break; - case 0x80: - IR += IAR[0]; - IAR[0] = IR & AMASK; - break; - case 0x81: - IR += IAR[7]; - IAR[7] = IR & AMASK; - break; - case 0x82: - IR += IAR[6]; - IAR[6] = IR & AMASK; - break; - case 0x84: - IR += IAR[5]; - IAR[5] = IR & AMASK; - break; - case 0x88: - IR += IAR[4]; - IAR[4] = IR & AMASK; - break; - case 0x90: - IR += IAR[3]; - IAR[3] = IR & AMASK; - break; - case 0xA0: - IR += IAR[2]; - IAR[2] = IR & AMASK; - break; - case 0xC0: - IR += IAR[1]; - IAR[1] = IR & AMASK; - break; - default: - reason = STOP_INVQ; - break; - } - PSR &= 0xD8; - if ((IR & 0xffff) == 0) - PSR |= 0x01; /* Zero */ - if ((IR & 0xffff) != 0 && !(IR & 0x10000)) - PSR |= 0x02; /* Low */ - if ((IR & 0xffff) != 0 && (IR & 0x10000)) - PSR |= 0x04; /* High */ - if ((IR & 0x10000)) - PSR |= 0x20; /* Bin overflow */ - break; - case 8: /* TBN: Test Bits On */ - IR = GetMem(BAR); - PSR &= 0xFF; - if ((IR & qbyte) != qbyte) - PSR |= 0x10; - break; - case 9: /* TBF: Test Bits Off */ - IR = GetMem(BAR); - PSR &= 0xFF; - if ((IR & qbyte)) - PSR |= 0x10; - break; - case 0xa: /* SBN: Set Bits On */ - IR = GetMem(BAR); - IR |= qbyte; - PutMem(BAR, IR); - break; - case 0xb: /* SBF: Set Bits Off */ - IR = GetMem(BAR); - IR &= ~qbyte; - PutMem(BAR, IR); - break; - case 0xc: /* MVI: Move Immediate */ - PutMem(BAR, qbyte); - break; - case 0xd: /* CLI: Compare Immediate */ - PSR = compare(GetMem(BAR), qbyte, PSR); - break; - default: - reason = STOP_INVOP; - break; - } - IAR[level] = PC; - continue; - break; - case 0xc0: - case 0xd0: - case 0xe0: - switch (opcode) { - case 0: /* BC: Branch on Condition */ - ARR[level] = AAR & AMASK; - if (condition(qbyte) == 1) { - IR = ARR[level]; - ARR[level] = PC & AMASK; - PC = IR; - } - break; - case 1: /* TIO: Test I/O */ - devno = (qbyte >> 4) & 0x0f; - devm = (qbyte >> 3) & 0x01; - devn = qbyte & 0x07; - op1 = dev_table[devno].routine(2, devm, devn, rbyte); - if (op1 & 0x01) { - ARR[level] = AAR & AMASK; - IR = ARR[level]; - ARR[level] = PC & AMASK; - PC = IR; - } - reason = (op1 >> 16) & 0xffff; - break; - case 2: /* LA: Load Address */ - switch (qbyte) { - case 1: - XR1 = AAR; - break; - case 2: - XR2 = AAR; - break; - default: - reason = STOP_INVQ; - break; - } - break; - default: - reason = STOP_INVOP; - break; - } /* switch (opcode) */ - IAR[level] = PC; - continue; - - default: - reason = STOP_INVOP; - break; -} /* switch (opaddr) */ - -} /* end while (reason == 0) */ - -/* Simulation halted */ - -saved_PC = PC; -return reason; -} - -/* On models 4-12, these memory functions could be inline, but - on a model 15 with ATU address mapping must be performed so - they are in functions here for future expansion. -*/ - -/* Fetch a byte from memory */ - -int32 GetMem(int32 addr) -{ - return M[addr] & 0xff; -} - -/* Place a byte in memory */ - -int32 PutMem(int32 addr, int32 data) -{ - M[addr] = data & 0xff; - return 0; -} - -/* Check the condition register against the qbyte and return 1 if true */ - -int32 condition(int32 qbyte) -{ - int32 r = 0, t, q; - t = (qbyte & 0xf0) >> 4; - q = qbyte & 0x0f; - if (qbyte & 0x80) { /* True if any condition tested = 1*/ - if (((qbyte & 0x3f) & PSR) != 0) r = 1; - } else { /* True if all conditions tested = 0 */ - if (((qbyte & 0x3f) & PSR) == 0) r = 1; - } - /* these bits reset by a test */ - if (qbyte & 0x10) - PSR &= 0xEF; /* Reset test false if used */ - if (qbyte & 0x08) - PSR &= 0xF7; /* Reset decimal overflow if tested */ - if (qbyte == 0x00) - r = 1; /* unconditional branch */ - if (qbyte == 0x80) - r = 0; /* force no branch */ - if (t >=0 && t < 8 && (q == 7 || q == 0xf)) - r = 0; /* no-op */ - if (t > 7 && t < 0x10 && (q == 7 || q == 0xf)) - r = 1; /* Force branch */ -return (r); -} -/* Given operand 1 and operand 2, compares the two and returns - the System/3 condition register bits appropriately, given the - condition register initial state in parameter 3 -*/ - -int32 compare(int32 byte1, int32 byte2, int32 cond) -{ - int32 r; - - r = cond & 0xF8; /* mask off all but unaffected bits 2,3,4 */ - if (byte1 == byte2) - r |= 0x01; /* set equal bit */ - if (byte1 < byte2) - r |= 0x02; /* set less-than bit */ - if (byte1 > byte2) - r |= 0x04; /* set greater than bit */ - return r; -} - -/*-------------------------------------------------------------------*/ -/* Add two zoned decimal operands */ -/* */ -/* Input: */ -/* addr1 Logical address of packed decimal storage operand 1 */ -/* len1 Length minus one of storage operand 1 (range 0-15) */ -/* addr2 Logical address of packed decimal storage operand 2 */ -/* len2 Length minus one of storage operand 2 (range 0-15) */ -/* Output: */ -/* The return value is the condition code: */ -/* 0=result zero, 1=result -ve, 2=result +ve, 3=overflow */ -/* */ -/* A program check may be generated if either logical address */ -/* causes an addressing, translation, or fetch protection */ -/* exception, or if either operand causes a data exception */ -/* because of invalid decimal digits or sign, or if the */ -/* first operand is store protected. Depending on the PSW */ -/* program mask, decimal overflow may cause a program check. */ -/*-------------------------------------------------------------------*/ -int32 add_zoned (int32 addr1, int32 len1, int32 addr2, int32 len2) -{ -int cc; /* Condition code */ -uint8 dec1[MAX_DECIMAL_DIGITS]; /* Work area for operand 1 */ -uint8 dec2[MAX_DECIMAL_DIGITS]; /* Work area for operand 2 */ -uint8 dec3[MAX_DECIMAL_DIGITS]; /* Work area for result */ -int count1, count2, count3; /* Significant digit counters*/ -int sign1, sign2, sign3; /* Sign of operands & result */ - - /* Load operands into work areas */ - load_decimal (addr1, len1, dec1, &count1, &sign1); - load_decimal (addr2, len2, dec2, &count2, &sign2); - - /* Add or subtract operand values */ - if (count2 == 0) - { - /* If second operand is zero then result is first operand */ - memcpy (dec3, dec1, MAX_DECIMAL_DIGITS); - count3 = count1; - sign3 = sign1; - } - else if (count1 == 0) - { - /* If first operand is zero then result is second operand */ - memcpy (dec3, dec2, MAX_DECIMAL_DIGITS); - count3 = count2; - sign3 = sign2; - } - else if (sign1 == sign2) - { - /* If signs are equal then add operands */ - add_decimal (dec1, dec2, dec3, &count3); - sign3 = sign1; - } - else - { - /* If signs are opposite then subtract operands */ - subtract_decimal (dec1, dec2, dec3, &count3, &sign3); - if (sign1 < 0) sign3 = -sign3; - } - - /* Set condition code */ - cc = (count3 == 0) ? 0 : (sign3 < 1) ? 1 : 2; - - /* Overflow if result exceeds first operand length */ - if (count3 > len1) - cc = 3; - - /* Set positive sign if result is zero */ - if (count3 == 0) - sign3 = 1; - - /* Store result into first operand location */ - store_decimal (addr1, len1, dec3, sign3); - - /* Return condition code */ - return cc; - -} /* end function add_packed */ - -/*-------------------------------------------------------------------*/ -/* Subtract two zoned decimal operands */ -/* */ -/* Input: */ -/* addr1 Logical address of packed decimal storage operand 1 */ -/* len1 Length minus one of storage operand 1 (range 0-15) */ -/* addr2 Logical address of packed decimal storage operand 2 */ -/* len2 Length minus one of storage operand 2 (range 0-15) */ -/* Output: */ -/* The return value is the condition code: */ -/* 0=result zero, 1=result -ve, 2=result +ve, 3=overflow */ -/* */ -/* A program check may be generated if either logical address */ -/* causes an addressing, translation, or fetch protection */ -/* exception, or if either operand causes a data exception */ -/* because of invalid decimal digits or sign, or if the */ -/* first operand is store protected. Depending on the PSW */ -/* program mask, decimal overflow may cause a program check. */ -/*-------------------------------------------------------------------*/ -int32 subtract_zoned (int32 addr1, int32 len1, int32 addr2, int32 len2) -{ -int cc; /* Condition code */ -uint8 dec1[MAX_DECIMAL_DIGITS]; /* Work area for operand 1 */ -uint8 dec2[MAX_DECIMAL_DIGITS]; /* Work area for operand 2 */ -uint8 dec3[MAX_DECIMAL_DIGITS]; /* Work area for result */ -int count1, count2, count3; /* Significant digit counters*/ -int sign1, sign2, sign3; /* Sign of operands & result */ - - /* Load operands into work areas */ - load_decimal (addr1, len1, dec1, &count1, &sign1); - load_decimal (addr2, len2, dec2, &count2, &sign2); - - /* Add or subtract operand values */ - if (count2 == 0) - { - /* If second operand is zero then result is first operand */ - memcpy (dec3, dec1, MAX_DECIMAL_DIGITS); - count3 = count1; - sign3 = sign1; - } - else if (count1 == 0) - { - /* If first operand is zero then result is -second operand */ - memcpy (dec3, dec2, MAX_DECIMAL_DIGITS); - count3 = count2; - sign3 = -sign2; - } - else if (sign1 != sign2) - { - /* If signs are opposite then add operands */ - add_decimal (dec1, dec2, dec3, &count3); - sign3 = sign1; - } - else - { - /* If signs are equal then subtract operands */ - subtract_decimal (dec1, dec2, dec3, &count3, &sign3); - if (sign1 < 0) sign3 = -sign3; - } - - /* Set condition code */ - cc = (count3 == 0) ? 0 : (sign3 < 1) ? 1 : 2; - - /* Overflow if result exceeds first operand length */ - if (count3 > len1) - cc = 3; - - /* Set positive sign if result is zero */ - if (count3 == 0) - sign3 = 1; - - /* Store result into first operand location */ - store_decimal (addr1, len1, dec3, sign3); - - /* Return condition code */ - return cc; - -} /* end function subtract_packed */ - - -/*-------------------------------------------------------------------*/ -/* Add two decimal byte strings as unsigned decimal numbers */ -/* */ -/* Input: */ -/* dec1 A 31-byte area containing the decimal digits of */ -/* the first operand. Each byte contains one decimal */ -/* digit in the low-order 4 bits of the byte. */ -/* dec2 A 31-byte area containing the decimal digits of */ -/* the second operand. Each byte contains one decimal */ -/* digit in the low-order 4 bits of the byte. */ -/* Output: */ -/* result Points to a 31-byte area to contain the result */ -/* digits. One decimal digit is placed in the low-order */ -/* 4 bits of each byte. */ -/* count Points to an integer to receive the number of */ -/* digits in the result excluding leading zeroes. */ -/* This field is set to zero if the result is all zero, */ -/* or to MAX_DECIMAL_DIGITS+1 if overflow occurred. */ -/*-------------------------------------------------------------------*/ -static void add_decimal (uint8 *dec1, uint8 *dec2, uint8 *result, int32 *count) -{ -int d; /* Decimal digit */ -int i; /* Array subscript */ -int n = 0; /* Significant digit counter */ -int carry = 0; /* Carry indicator */ - - /* Add digits from right to left */ - for (i = MAX_DECIMAL_DIGITS - 1; i >= 0; i--) - { - /* Add digits from first and second operands */ - d = dec1[i] + dec2[i] + carry; - - /* Check for carry into next digit */ - if (d > 9) { - d -= 10; - carry = 1; - } else { - carry = 0; - } - - /* Check for significant digit */ - if (d != 0) - n = MAX_DECIMAL_DIGITS - i; - - /* Store digit in result */ - result[i] = d; - - } /* end for */ - - /* Check for carry out of leftmost digit */ - if (carry) - n = MAX_DECIMAL_DIGITS + 1; - - /* Return significant digit counter */ - *count = n; - -} /* end function add_decimal */ - -/*-------------------------------------------------------------------*/ -/* Subtract two decimal byte strings as unsigned decimal numbers */ -/* */ -/* Input: */ -/* dec1 A 31-byte area containing the decimal digits of */ -/* the first operand. Each byte contains one decimal */ -/* digit in the low-order 4 bits of the byte. */ -/* dec2 A 31-byte area containing the decimal digits of */ -/* the second operand. Each byte contains one decimal */ -/* digit in the low-order 4 bits of the byte. */ -/* Output: */ -/* result Points to a 31-byte area to contain the result */ -/* digits. One decimal digit is placed in the low-order */ -/* 4 bits of each byte. */ -/* count Points to an integer to receive the number of */ -/* digits in the result excluding leading zeroes. */ -/* This field is set to zero if the result is all zero. */ -/* sign -1 if the result is negative (operand2 > operand1) */ -/* +1 if the result is positive (operand2 <= operand1) */ -/*-------------------------------------------------------------------*/ -static void subtract_decimal (uint8 *dec1, uint8 *dec2, uint8 *result, int *count, int *sign) -{ -int d; /* Decimal digit */ -int i; /* Array subscript */ -int n = 0; /* Significant digit counter */ -int borrow = 0; /* Borrow indicator */ -int rc; /* Return code */ -uint8 *higher; /* -> Higher value operand */ -uint8 *lower; /* -> Lower value operand */ - - /* Compare digits to find which operand has higher numeric value */ - rc = memcmp (dec1, dec2, MAX_DECIMAL_DIGITS); - - /* Return positive zero result if both operands are equal */ - if (rc == 0) { - memset (result, 0, MAX_DECIMAL_DIGITS); - *count = 0; - *sign = +1; - return; - } - - /* Point to higher and lower value operands and set sign */ - if (rc > 0) { - higher = dec1; - lower = dec2; - *sign = +1; - } else { - lower = dec1; - higher = dec2; - *sign = -1; - } - - /* Subtract digits from right to left */ - for (i = MAX_DECIMAL_DIGITS - 1; i >= 0; i--) - { - /* Subtract lower operand digit from higher operand digit */ - d = higher[i] - lower[i] - borrow; - - /* Check for borrow from next digit */ - if (d < 0) { - d += 10; - borrow = 1; - } else { - borrow = 0; - } - - /* Check for significant digit */ - if (d != 0) - n = MAX_DECIMAL_DIGITS - i; - - /* Store digit in result */ - result[i] = d; - - } /* end for */ - - /* Return significant digit counter */ - *count = n; - -} /* end function subtract_decimal */ - -/*-------------------------------------------------------------------*/ -/* Load a zoned decimal storage operand into a decimal byte string */ -/* */ -/* Input: */ -/* addr Logical address of zoned decimal storage operand */ -/* len Length minus one of storage operand (range 0-15) */ -/* Output: */ -/* result Points to a 31-byte area into which the decimal */ -/* digits are loaded. One decimal digit is loaded */ -/* into the low-order 4 bits of each byte, and the */ -/* result is padded to the left with high-order zeroes */ -/* if the storage operand contains less than 31 digits. */ -/* count Points to an integer to receive the number of */ -/* digits in the result excluding leading zeroes. */ -/* This field is set to zero if the result is all zero. */ -/* sign Points to an integer which will be set to -1 if a */ -/* negative sign was loaded from the operand, or +1 if */ -/* a positive sign was loaded from the operand. */ -/* */ -/* A program check may be generated if the logical address */ -/* causes an addressing, translation, or fetch protection */ -/* exception, or if the operand causes a data exception */ -/* because of invalid decimal digits or sign. */ -/*-------------------------------------------------------------------*/ -static void load_decimal (int32 addr, int32 len, uint8 *result, int32 *count, int32 *sign) -{ -int h; /* Hexadecimal digit */ -int i, j; /* Array subscripts */ -int n; /* Significant digit counter */ - - if ((GetMem(addr) & 0xf0) == 0xD0) - *sign = -1; - else - *sign = 1; - j = len; - for (i = MAX_DECIMAL_DIGITS; i > -1; i--) { - if (j) { - h = GetMem(addr) & 0x0f; - addr--; - j--; - } else { - h = 0; - } - result [i-1] = h; - if (h > 0) n = i; - } - *count = 32 - n; - -} /* end function load_decimal */ - -/*-------------------------------------------------------------------*/ -/* Store decimal byte string into packed decimal storage operand */ -/* */ -/* Input: */ -/* addr Logical address of packed decimal storage operand */ -/* len Length minus one of storage operand (range 0-15) */ -/* dec A 31-byte area containing the decimal digits to be */ -/* stored. Each byte contains one decimal digit in */ -/* the low-order 4 bits of the byte. */ -/* sign -1 if a negative sign is to be stored, or +1 if a */ -/* positive sign is to be stored. */ -/* */ -/* A program check may be generated if the logical address */ -/* causes an addressing, translation, or protection exception. */ -/*-------------------------------------------------------------------*/ -static void store_decimal (int32 addr, int32 len, uint8 *dec, int sign) -{ -int i, j, a; /* Array subscripts */ - - j = len; - a = addr; - for (i = MAX_DECIMAL_DIGITS; i > -1; i--) { - if (j) { - PutMem(a, (dec[i-1] | 0xf0)); - a--; - j--; - } else { - break; - } - } - if (sign == -1) { - PutMem(addr, (GetMem(addr) & 0x0f)); - PutMem(addr, (GetMem(addr) | 0xf0)); - } - -} /* end function store_decimal */ - -/* CPU Device Control */ - -int32 cpu (int32 op, int32 m, int32 n, int32 data) -{ - int32 iodata = 0; - - switch (op) { - case 0x00: /* Start IO */ - return SCPE_OK; - case 0x01: /* LIO */ - return SCPE_OK; - case 0x02: /* TIO */ - break; - case 0x03: /* SNS */ - /* SNS CPU gets the data switches */ - iodata = SR; - break; - case 0x04: /* APL */ - break; - default: - break; - } - return ((SCPE_OK << 16) | iodata); -} - - - -/* Null device */ - -int32 nulldev (int32 opcode, int32 m, int32 n, int32 data) -{ -if (opcode == 1) - return SCPE_OK; /* Ok to LIO unconfigured devices? */ -return STOP_INVDEV; -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -int_req = 0; -level = 8; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & 0xff; -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -M[addr] = val & 0xff; -return SCPE_OK; -} - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; -if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_OK; -MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; -return SCPE_OK; -} - -t_stat cpu_boot (int32 unitno, DEVICE *dptr) -{ -level = 8; -IAR[8] = 0; -return SCPE_OK; -} diff --git a/S3/s3_defs.h b/S3/s3_defs.h deleted file mode 100644 index f018effa..00000000 --- a/S3/s3_defs.h +++ /dev/null @@ -1,94 +0,0 @@ -/* s3_defs.h: IBM System/3 simulator definitions - - Copyright (c) 2001-2003, Charles E. Owen - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_INVOP 4 /* program check - invalid op */ -#define STOP_INVQ 5 /* Prog check - invalid Q */ -#define STOP_INVADDR 6 /* Prog check - invalid addr */ -#define STOP_INVDEV 7 /* Prog check - invalid dev cmd */ -#define STOP_NOCD 8 /* ATTN card reader */ -#define RESET_INTERRUPT 77 /* special return from SIO */ - -/* Memory */ - -#define MAXMEMSIZE 65536 /* max memory size */ -#define AMASK (MAXMEMSIZE - 1) /* logical addr mask */ -#define PAMASK (MAXMEMSIZE - 1) /* physical addr mask */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ - -#define MAX_DECIMAL_DIGITS 31 /* max size of a decimal number */ -#define CDR_WIDTH 80 /* Max card size */ -#define CDP_WIDTH 80 /* Punch width */ -#define LPT_WIDTH 132 -#define CCT_LNT 132 - -#define DSK_SECTSIZE 256 /* Sector length */ -#define DSK_CYLSIZE 256*48 /* Cylinder length */ - -/* I/O structure - - The I/O structure is tied together by dev_table, indexed by - the device number. Each entry in dev_table consists of - - level Interrupt level for device (0-7) - priority Priority for device (1-8) - routine IOT action routine -*/ - -struct ndev { - int32 level; /* interrupt level */ - int32 pri; /* Device priority */ - int32 (*routine)(); /* dispatch routine */ -}; - -/* Structure to define operation codes */ - -struct opdef { - char op[6]; /* Mnemonic for op */ - int32 opmask; /* Bits set on in opcode */ - int32 q; /* Qbyte */ - int32 form; /* Forms are: - 0 - 1-byte hex operand - 1 - 1-byte register addr, A-Addr - 2 - A-addr,B-addr,Qbyte - 3 - A-addr,Qbyte - 4 - da,m,n - 5 - da,m,n,cc - 6 - da,m,n,A-addr - 7 - 1-address implict Q - 8 - 2-address implict Q */ - int32 group; /* Group Code: - 0 - Command Format (0xFx) - 1 - 1-address A (0xx) - 2 - 2-address (0x<0,1,2,4,5,6,8,9,A>x) - 3 - 1-address B (0x<3,7,B>x) */ -}; diff --git a/S3/s3_disk.c b/S3/s3_disk.c deleted file mode 100644 index 21d54027..00000000 --- a/S3/s3_disk.c +++ /dev/null @@ -1,788 +0,0 @@ -/* s3_disk.c: IBM 5444 Disk Drives - - Copyright (c) 2001-2003, Charles E. Owen - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. - - r1 Removeable disk 1 - f1 Fixed disk 1 - r2 Removeable disk 2 - f2 Fixed disk 2 - - 25-Apr-03 RMS Revised for extended file support - 08-Oct-02 RMS Added impossible function catcher -*/ - -#include "s3_defs.h" -#include - -extern uint8 M[]; -extern int32 IAR[], level; -extern FILE *trace; -extern int32 debug_reg; -char dbuf[DSK_SECTSIZE]; /* Disk buffer */ -int32 dsk (int32 disk, int32 op, int32 m, int32 n, int32 data); -int32 read_sector(UNIT *uptr, char *dbuf, int32 sect); -int32 write_sector(UNIT *uptr, char *dbuf, int32 sect); -t_stat r1_svc (UNIT *uptr); -t_stat r1_boot (int32 unitno, DEVICE *dptr); -t_stat r1_attach (UNIT *uptr, char *cptr); -t_stat r1_reset (DEVICE *dptr); -t_stat f1_svc (UNIT *uptr); -t_stat f1_boot (int32 unitno, DEVICE *dptr); -t_stat f1_attach (UNIT *uptr, char *cptr); -t_stat f1_reset (DEVICE *dptr); -t_stat r2_svc (UNIT *uptr); -t_stat r2_boot (int32 unitno, DEVICE *dptr); -t_stat r2_attach (UNIT *uptr, char *cptr); -t_stat r2_reset (DEVICE *dptr); -t_stat f2_svc (UNIT *uptr); -t_stat f2_boot (int32 unitno, DEVICE *dptr); -t_stat f2_attach (UNIT *uptr, char *cptr); -t_stat f2_reset (DEVICE *dptr); -extern int32 GetMem(int32 addr); -extern int32 PutMem(int32 addr, int32 data); - -char opstr[5][5] = { "SIO", "LIO", "TIO", "SNS", "APL" }; - -int32 DDAR[2]; /* Data address register */ -int32 DCAR[2]; /* Disk Control Address Register */ -int32 diskerr[2] = { 0, 0 }; /* Error status */ -int32 notrdy[2] = { 0, 0 }; /* Not ready error */ -int32 seekbusy[2] = { 0, 0 }; /* Drive busy flags */ -int32 seekhead[2] = { 0, 0 }; /* Disk head 0,1 */ -int32 found[2] = { 0, 0 }; /* Scan found bit */ -int32 RIDsect[2] = { 0, 0 }; /* for Read ID */ - -/* Disk data structures - - xy_dev CDR descriptor - xy_unit CDR unit descriptor - xy_reg CDR register list - - x = F or R - y = 1 or 2 -*/ - -UNIT r1_unit = { - UDATA (&r1_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 }; - -REG r1_reg[] = { - { FLDATA (NOTRDY, notrdy[0], 0) }, - { FLDATA (SEEK, seekbusy[0], 0) }, - { HRDATA (DAR, DDAR[0], 16) }, - { HRDATA (CAR, DCAR[0], 16) }, - { HRDATA (ERR, diskerr[0], 16) }, - { DRDATA (CYL, r1_unit.u3, 8) }, - { DRDATA (HEAD, seekhead[0], 8) }, - { DRDATA (POS, r1_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, r1_unit.wait, 24), PV_LEFT }, - { BRDATA (BUF, dbuf, 8, 8, 256) }, - { NULL } }; - -DEVICE r1_dev = { - "R1", &r1_unit, r1_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &r1_reset, - &r1_boot, &r1_attach, NULL }; - -UNIT f1_unit = { - UDATA (&f1_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 }; - -REG f1_reg[] = { - { FLDATA (NOTRDY, notrdy[0], 0) }, - { FLDATA (SEEK, seekbusy[0], 0) }, - { HRDATA (DAR, DDAR[0], 16) }, - { HRDATA (CAR, DCAR[0], 16) }, - { HRDATA (ERR, diskerr[0], 16) }, - { DRDATA (CYL, f1_unit.u3, 8) }, - { DRDATA (HEAD, seekhead[0], 8) }, - { DRDATA (POS, f1_unit.pos, 32), PV_LEFT }, - { DRDATA (TIME, f1_unit.wait, 24), PV_LEFT }, - { BRDATA (BUF, dbuf, 8, 8, 256) }, - { NULL } }; - -DEVICE f1_dev = { - "F1", &f1_unit, f1_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &f1_reset, - &f1_boot, &f1_attach, NULL }; - -UNIT r2_unit = { - UDATA (&r2_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 }; - -REG r2_reg[] = { - { FLDATA (NOTRDY, notrdy[1], 0) }, - { FLDATA (SEEK, seekbusy[1], 0) }, - { HRDATA (DAR, DDAR[1], 16) }, - { HRDATA (CAR, DCAR[1], 16) }, - { HRDATA (ERR, diskerr[1], 16) }, - { DRDATA (CYL, r2_unit.u3, 8) }, - { DRDATA (HEAD, seekhead[1], 8) }, - { DRDATA (POS, r2_unit.pos, 32), PV_LEFT }, - { DRDATA (TIME, r2_unit.wait, 24), PV_LEFT }, - { BRDATA (BUF, dbuf, 8, 8, 256) }, - { NULL } }; - -DEVICE r2_dev = { - "R2", &r2_unit, r2_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &r2_reset, - &r2_boot, &r2_attach, NULL }; - -UNIT f2_unit = { - UDATA (&f2_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 }; - -REG f2_reg[] = { - { FLDATA (NOTRDY, notrdy[1], 0) }, - { FLDATA (SEEK, seekbusy[1], 0) }, - { HRDATA (DAR, DDAR[1], 16) }, - { HRDATA (CAR, DCAR[1], 16) }, - { HRDATA (ERR, diskerr[1], 16) }, - { DRDATA (CYL, f2_unit.u3, 8) }, - { DRDATA (HEAD, seekhead[1], 8) }, - { DRDATA (POS, f2_unit.pos, 32), PV_LEFT }, - { DRDATA (TIME, f2_unit.wait, 24), PV_LEFT }, - { BRDATA (BUF, dbuf, 8, 8, 256) }, - { NULL } }; - -DEVICE f2_dev = { - "F2", &f2_unit, f2_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &f2_reset, - &f2_boot, &f2_attach, NULL }; - - -/* -------------------------------------------------------------------- */ - -/* 5444: master routines */ - -int32 dsk1 (int32 op, int32 m, int32 n, int32 data) -{ - int32 r; - - r = dsk(0, op, m, n, data); - return (r); -} - -int32 dsk2 (int32 op, int32 m, int32 n, int32 data) -{ - int32 r; - - r = dsk(1, op, m, n, data); - return (r); -} - -/* 5444: operational routine */ - -int32 dsk (int32 disk, int32 op, int32 m, int32 n, int32 data) -{ - int32 iodata, i, j, u, sect, nsects, addr, r, c, res; - int32 F, C, S, N, usave; - UNIT *uptr; - - u = m; - if (disk == 1) u += 2; - F = GetMem(DCAR[disk]+0); /* Flag bits */ - C = GetMem(DCAR[disk]+1); /* Cylinder */ - S = GetMem(DCAR[disk]+2); /* Sector */ - N = GetMem(DCAR[disk]+3); /* Number of sectors */ - switch (u) { - case 0: - uptr = r1_dev.units; - break; - case 1: - uptr = f1_dev.units; - break; - case 2: - uptr = r2_dev.units; - break; - case 3: - uptr = f2_dev.units; - break; - default: - break; - } - if (debug_reg & 0x02) - fprintf(trace, "==> %04X %s %01X,%d,%04X DAR=%04X CAR=%04X C=%02X, S=%02X, N=%02X\n", - IAR[level], - opstr[op], - m, n, data, - DDAR[disk], - DCAR[disk], - C, S, N); - - switch (op) { - - /* SIO 5444 */ - case 0: - if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_UNATT; - diskerr[disk] = 0; /* SIO resets errors */ - found[disk] = 0; /* ... and found bit */ - iodata = 0; - switch (n) { - case 0x00: /* Seek */ - if (S & 0x80) - seekhead[disk] = 1; - else - seekhead[disk] = 0; - if (S & 1) { - uptr -> u3 += N; - } else { - uptr -> u3 -= N; - } - if (uptr -> u3 < 0) - uptr -> u3 = 0; - if (uptr -> u3 > 203) { - uptr -> u3 = 0; - diskerr[disk] |= 0x0100; - if (debug_reg & 0x02) - fprintf(trace, "==> Seek Past End of Disk\n"); - } - - /*sim_activate(uptr, uptr -> wait);*/ - sim_activate(uptr, 1); - - /* Seek arms are the same for both disks on a drive: - update the other arm */ - - usave = uptr -> u3; - if (u == 0) uptr = f1_dev.units; - if (u == 1) uptr = r1_dev.units; - if (u == 2) uptr = f2_dev.units; - if (u == 3) uptr = r2_dev.units; - uptr -> u3 = usave; - - seekbusy[disk] = 1; - iodata = SCPE_OK; - break; - - case 0x01: /* Read */ - switch (data) { - case 0: /* Read data */ - sect = (S >> 2) & 0x3F; - nsects = N + 1; - addr = DDAR[disk]; - - for (i = 0; i < nsects; i++) { - r = read_sector(uptr, dbuf, sect); - if (r != 1 || uptr->u3 != C) { - diskerr[disk] |= 0x0800; - break; - } - for (j = 0; j < DSK_SECTSIZE; j++) { - PutMem(addr, dbuf[j]); - addr++; - } - - if ((sect == 55) ) { /* HJS MODS */ - S = sect; - N = nsects - i - 2; - if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */ - DDAR[disk] = addr & 0xFFFF; /* HJS mod */ - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - sim_activate(uptr, 1); - iodata = SCPE_OK; - break; - } - - sect++; - S = sect - 1; - N = nsects - i - 2; - if (sect == 24) - sect = 32; - } - DDAR[disk] = addr & 0xFFFF; /* HJS mod */ - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - /*sim_activate(uptr, uptr -> wait);*/ - sim_activate(uptr, 1); - iodata = SCPE_OK; - break; - case 1: /* Read ID */ - if (uptr -> u3 > 0 && uptr -> u3 < 4) - PutMem(DCAR[disk], 1); - else - PutMem(DCAR[disk], 0); - PutMem(DCAR[disk]+1, uptr -> u3); - PutMem(DCAR[disk]+2, RIDsect[disk]); - RIDsect[disk]++; - if (RIDsect[disk] > 23) - RIDsect[disk] = 32; - if (RIDsect[disk] > 55) - RIDsect[disk] = 0; - break; - case 2: /* Read Diagnostic */ - iodata = STOP_INVDEV; - break; - case 3: /* Verify */ - sect = (S >> 2) & 0x3F; - nsects = N + 1; - addr = DDAR[disk]; - for (i = 0; i < nsects; i++) { - r = read_sector(uptr, dbuf, sect); - if (r != 1 || uptr->u3 != C) { - diskerr[disk] |= 0x0800; - break; - } - if ((sect == 55) ) { /* HJS MODS */ - S = sect; - N = nsects - i - 2; - if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */ - DDAR[disk] = addr & 0xFFFF; - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - sim_activate(uptr, 1); - iodata = SCPE_OK; - break; - } - sect++; - S = sect - 1; - N = nsects - i - 2; - if (sect == 24) - sect = 32; - } - DDAR[disk] = addr & 0xFFFF; - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - /*sim_activate(uptr, uptr -> wait);*/ - sim_activate(uptr, 1); - break; - default: - return STOP_INVDEV; - } - break; - case 0x02: /* Write */ - switch (data) { - case 0: /* Write Data */ - sect = (S >> 2) & 0x3F; - nsects = N + 1; - addr = DDAR[disk]; - for (i = 0; i < nsects; i++) { - for (j = 0; j < DSK_SECTSIZE; j++) { - dbuf[j] = GetMem(addr); - addr++; - } - r = write_sector(uptr, dbuf, sect); - if (r != 1 || uptr->u3 != C) { - diskerr[disk] |= 0x0400; - break; - } - if ((sect == 55) ) { /* HJS MODS */ - S = sect; - N = nsects - i - 2; - if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */ - DDAR[disk] = addr & 0xFFFF; - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - sim_activate(uptr, 1); - iodata = SCPE_OK; - break; - } - sect++; - S = sect - 1; - N = nsects - i - 2; - if (sect == 24) - sect = 32; - } - DDAR[disk] = addr & 0xFFFF; /* HJS mod */ - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - /*sim_activate(uptr, uptr -> wait);*/ - sim_activate(uptr, 1); - break; - case 1: /* Write identifier */ - if (seekhead[disk] == 0) - S = 0; - else - S = 0x80; - N = 23; - - sect = (S >> 2) & 0x3F; - nsects = N + 1; - addr = DDAR[disk]; - for (i = 0; i < nsects; i++) { - for (j = 0; j < DSK_SECTSIZE; j++) { - dbuf[j] = GetMem(addr); - } - r = write_sector(uptr, dbuf, sect); - if (r != 1) { - diskerr[disk] |= 0x0400; - break; - } - if ((sect == 55) ) { - S = sect; - N = nsects - i - 2; - if (N > 0) diskerr[disk] |= 0x0020; - DDAR[disk] = addr & 0xFFFF; - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - sim_activate(uptr, 1); - iodata = SCPE_OK; - break; - } - sect++; - S = sect - 1; - N = nsects - i - 2; - if (sect == 24) - sect = 32; - } - DDAR[disk] = addr & 0xFFFF; - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - /*sim_activate(uptr, uptr -> wait);*/ - sim_activate(uptr, 1); - break; - default: - return STOP_INVDEV; - } - break; - case 0x03: /* Scan */ - sect = (S >> 2) & 0x3F; - nsects = N + 1; - addr = DDAR[disk]; - for (i = 0; i < nsects; i++) { - r = read_sector(uptr, dbuf, sect); - if (r != 1 || uptr->u3 != C) { - diskerr[disk] |= 0x0800; - break; - } - res = 0; - for (j = 0; j < DSK_SECTSIZE; j++) { - c = GetMem(addr); - if (j != 0xff) { - if (dbuf[i] < c) - res = 1; - if (dbuf[i] > c) - res = 3; - } - addr++; - } - if (res == 0) - found[disk] = 1; - if (res == data) - break; - if ((sect == 55) ) { /* HJS MODS */ - S = sect; - N = nsects - i - 2; - if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */ - DDAR[disk] = addr & 0xFFFF; - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - sim_activate(uptr, 1); - iodata = SCPE_OK; - break; - } - sect++; - S = sect - 1; - N = nsects - i - 2; - if (sect == 24) - sect = 32; - } - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - /*sim_activate(uptr, uptr -> wait);*/ - sim_activate(uptr, 1); - break; - default: - return STOP_INVDEV; - } - return iodata; - - /* LIO 5444 */ - case 1: - if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_UNATT; - switch (n) { - case 0x04: /* Data Addr */ - DDAR[disk] = data; - break; - case 0x06: /* Control Addr */ - DCAR[disk] = data; - break; - default: - return STOP_INVDEV; - } - return SCPE_OK; - case 2: /* TIO 5444 */ - if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_UNATT << 16; - iodata = 0; - switch (n) { - case 0x00: /* Error */ - if (diskerr[disk] || notrdy[disk]) - iodata = 1; - if ((uptr -> flags & UNIT_ATT) == 0) - iodata = 1; - break; - case 0x02: /* Busy */ - if (sim_is_active (uptr)) - iodata = 1; - break; - case 0x04: - if (found[disk]) - iodata = 1; - break; - default: - return (STOP_INVDEV << 16); - } - return ((SCPE_OK << 16) | iodata); - - /* SNS 5444 */ - case 3: - if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_UNATT << 16; - iodata = 0; - switch (n) { - case 0x01: - break; - case 0x02: - iodata = diskerr[disk]; - if (notrdy[disk]) - iodata |= 0x4000; - if ((uptr -> flags & UNIT_ATT) == 0) - iodata |= 0x4000; - if (seekbusy[disk]) - iodata |= 0x0010; - if (uptr -> u3 == 0) - iodata |= 0x0040; - break; - case 0x03: - iodata = 0; - break; - case 0x04: - iodata = DDAR[disk]; - break; - case 0x06: - iodata = DCAR[disk]; - break; - default: - return (STOP_INVDEV << 16); - } - iodata |= ((SCPE_OK << 16) & 0xffff0000); - return (iodata); - - /* APL 5444 */ - case 4: - if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_UNATT << 16; - iodata = 0; - switch (n) { - case 0x00: /* Error */ - if (diskerr[disk] || notrdy[disk]) - iodata = 1; - if ((uptr -> flags & UNIT_ATT) == 0) - iodata = 1; - break; - case 0x02: /* Busy */ - if (sim_is_active (uptr)) - iodata = 1; - break; - default: - return (STOP_INVDEV << 16); - } - return ((SCPE_OK << 16) | iodata); - default: - break; - } - printf (">>DSK%d non-existent function %d\n", disk, op); - return SCPE_OK; -} - -/* Disk unit service. If a stacker select is active, copy to the - selected stacker. Otherwise, copy to the normal stacker. If the - unit is unattached, simply exit. -*/ - -t_stat r1_svc (UNIT *uptr) -{ -seekbusy[0] = 0; -return SCPE_OK; -} -t_stat f1_svc (UNIT *uptr) -{ -seekbusy[0] = 0; -return SCPE_OK; -} -t_stat r2_svc (UNIT *uptr) -{ -seekbusy[1] = 0; -return SCPE_OK; -} -t_stat f2_svc (UNIT *uptr) -{ -seekbusy[1] = 0; -return SCPE_OK; -} - - -/* Disk reset */ - -t_stat r1_reset (DEVICE *dptr) -{ -diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear indicators */ -found[0] = 0; -sim_cancel (&r1_unit); /* clear event */ -r1_unit.u3 = 0; /* cylinder 0 */ -return SCPE_OK; -} -t_stat f1_reset (DEVICE *dptr) -{ -diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear indicators */ -found[0] = 0; -sim_cancel (&f1_unit); /* clear event */ -f1_unit.u3 = 0; /* cylinder 0 */ -return SCPE_OK; -} -t_stat r2_reset (DEVICE *dptr) -{ -diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear indicators */ -found[1] = 0; -sim_cancel (&r2_unit); /* clear event */ -r2_unit.u3 = 0; /* cylinder 0 */ -return SCPE_OK; -} -t_stat f2_reset (DEVICE *dptr) -{ -diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear indicators */ -found[1] = 0; -sim_cancel (&f2_unit); /* clear event */ -f2_unit.u3 = 0; /* cylinder 0 */ -return SCPE_OK; -} - -/* Disk unit attach */ - -t_stat r1_attach (UNIT *uptr, char *cptr) -{ -diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear status */ -found[0] = 0; -uptr -> u3 = 0; /* cylinder 0 */ -return attach_unit (uptr, cptr); -} -t_stat f1_attach (UNIT *uptr, char *cptr) -{ -diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear status */ -found[0] = 0; -uptr -> u3 = 0; /* cylinder 0 */ -return attach_unit (uptr, cptr); -} -t_stat r2_attach (UNIT *uptr, char *cptr) -{ -diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear status */ -found[1] = 0; -uptr -> u3 = 0; /* cylinder 0 */ -return attach_unit (uptr, cptr); -} -t_stat f2_attach (UNIT *uptr, char *cptr) -{ -diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear status */ -found[1] = 0; -uptr -> u3 = 0; /* cylinder 0 */ -return attach_unit (uptr, cptr); -} - -/* Bootstrap routine */ - -t_stat r1_boot (int32 unitno, DEVICE *dptr) -{ -int i; -r1_unit.u3 = 0; -read_sector(r1_dev.units, dbuf, 0); -for (i = 0; i < 256; i++) { - M[i] = dbuf[i]; -} -return SCPE_OK; -} -t_stat f1_boot (int32 unitno, DEVICE *dptr) -{ -int i; -f1_unit.u3 = 0; -read_sector(f1_dev.units, dbuf, 0); -for (i = 0; i < 256; i++) { - M[i] = dbuf[i]; -} -return SCPE_OK; -} -t_stat r2_boot (int32 unitno, DEVICE *dptr) -{ -int i; -r2_unit.u3 = 0; -read_sector(r2_dev.units, dbuf, 0); -for (i = 0; i < 256; i++) { - M[i] = dbuf[i]; -} -return SCPE_OK; -} -t_stat f2_boot (int32 unitno, DEVICE *dptr) -{ -int i; -f2_unit.u3 = 0; -read_sector(f2_dev.units, dbuf, 0); -for (i = 0; i < 256; i++) { - M[i] = dbuf[i]; -} -return SCPE_OK; -} - - -/* Raw Disk Data In/Out */ - -int32 read_sector(UNIT *uptr, char *dbuf, int32 sect) -{ - static int32 rtn, realsect; - static long pos; - - /* calculate real sector no */ - if (sect > 23) - realsect = sect - 8; - else - realsect = sect; - /* physically read the sector */ - pos = DSK_CYLSIZE * uptr -> u3; - pos += DSK_SECTSIZE * realsect; - rtn = fseek(uptr -> fileref, pos, 0); - rtn = fread(dbuf, DSK_SECTSIZE, 1, uptr -> fileref); - return (rtn); -} - -int32 write_sector(UNIT *uptr, char *dbuf, int32 sect) -{ - static int32 rtn, realsect; - static long pos; - - /* calculate real sector no */ - if (sect > 23) - realsect = sect - 8; - else - realsect = sect; - if (uptr -> u3 == 0 && realsect == 32) - rtn = 0; - /* physically write the sector */ - pos = DSK_CYLSIZE * uptr -> u3; - pos += DSK_SECTSIZE * realsect; - rtn = fseek(uptr -> fileref, pos, 0); - rtn = fwrite(dbuf, DSK_SECTSIZE, 1, uptr -> fileref); - return (rtn); -} diff --git a/S3/s3_lp.c b/S3/s3_lp.c deleted file mode 100644 index b643be61..00000000 --- a/S3/s3_lp.c +++ /dev/null @@ -1,353 +0,0 @@ -/* s3_lp.c: IBM 1403 line printer simulator - - Copyright (c) 2001-2003, Charles E. Owen - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. - - lpt 1403 line printer - - 25-Apr-03 RMS Revised for extended file support - 08-Oct-02 RMS Added impossible function catcher -*/ - -#include "s3_defs.h" - -extern uint8 M[]; -extern char bcd_to_ascii[64]; -extern int32 iochk, ind[64]; -int32 cct[CCT_LNT] = { 03 }; -int32 cctlnt = 66, cctptr = 0, lines = 0, lflag = 0; -t_stat lpt_reset (DEVICE *dptr); -t_stat lpt_attach (UNIT *uptr, char *cptr); -t_stat write_line (int32 ilnt, int32 mod); -t_stat space (int32 lines, int32 lflag); -t_stat carriage_control (int32 action, int32 mod); -extern unsigned char ebcdic_to_ascii[256]; - -#define UNIT_V_PCHAIN (UNIT_V_UF + 0) -#define UNIT_M_PCHAIN 03 -#define M_UCS 00 /* Universal */ -#define M_PCF 00 /* full */ -#define M_PCA 01 /* business */ -#define M_PCH 02 /* Fortran */ -#define UNIT_PCHAIN (UNIT_M_PCHAIN << UNIT_V_PCHAIN) -#define UCS (M_UCS << UNIT_V_PCHAIN) -#define PCF (M_PCF << UNIT_V_PCHAIN) -#define PCA (M_PCA << UNIT_V_PCHAIN) -#define PCH (M_PCH << UNIT_V_PCHAIN) -#define GET_PCHAIN(x) (((x) >> UNIT_V_PCHAIN) & UNIT_M_PCHAIN) -#define CHP(ch,val) ((val) & (1 << (ch))) - -int32 LPDAR; /* Data Address */ -int32 LPFLR; /* Forms Length */ -int32 LPIAR; /* Image address */ -int32 linectr; /* current line # */ -int32 lpterror = 0; -int32 CC9 = 0; -int32 CC12 = 0; - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list -*/ - -UNIT lpt_unit = { - UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }; - -REG lpt_reg[] = { - { FLDATA (ERR, lpterror, 0) }, - { HRDATA (LPDAR, LPDAR, 16) }, - { HRDATA (LPFLR, LPFLR, 8) }, - { HRDATA (LPIAR, LPIAR, 16) }, - { DRDATA (LINECT, linectr, 8) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { BRDATA (CCT, cct, 8, 32, CCT_LNT) }, - { DRDATA (LINES, lines, 8), PV_LEFT }, - { DRDATA (CCTP, cctptr, 8), PV_LEFT }, - { DRDATA (CCTL, cctlnt, 8), REG_RO + PV_LEFT }, - { GRDATA (CHAIN, lpt_unit.flags, 10, 2, UNIT_V_PCHAIN), REG_HRO }, - { NULL } }; - -MTAB lpt_mod[] = { - { UNIT_PCHAIN, UCS, "UCS", "UCS", NULL }, - { UNIT_PCHAIN, PCA, "A chain", "PCA", NULL }, - { UNIT_PCHAIN, PCH, "H chain", "PCH", NULL }, - { 0 } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, lpt_mod, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &lpt_reset, - NULL, NULL, NULL }; - - -/* -------------------------------------------------------------------- */ - -/* Printer: master routine */ - -int32 lpt (int32 op, int32 m, int32 n, int32 data) -{ - int32 iodata; - switch (op) { - case 0: /* SIO 1403 */ - iodata = 0; - printf("\0"); - switch (n) { - case 0x00: /* Spacing only */ - if (data > 0 && data < 4) - iodata = carriage_control(2, data); - break; - case 0x02: /* Print & space */ - iodata = write_line(0, 0); - if (data > 3) data = 0; - if (iodata == SCPE_OK) - iodata = carriage_control(2, data); - break; - case 0x04: /* Skip only */ - iodata = carriage_control(4, data); - break; - case 0x06: /* Print and skip */ - iodata = write_line(0, 0); - if (iodata == SCPE_OK) - iodata = carriage_control(4, data); - break; - default: - return STOP_INVDEV; - } - return iodata; - case 1: /* LIO 1403 */ - switch (n) { - case 0x00: /* LPFLR */ - LPFLR = (data >> 8) & 0xff; - break; - case 0x04: - LPIAR = data & 0xffff; - break; - case 0x06: - LPDAR = data & 0xffff; - break; - default: - return STOP_INVDEV; - } - return SCPE_OK; - case 2: /* TIO 1403 */ - iodata = 0; - switch (n) { - case 0x00: /* Not ready/check */ - if (lpterror) - iodata = 1; - if ((lpt_unit.flags & UNIT_ATT) == 0) - iodata = 1; - break; - case 0x02: /* Buffer Busy */ - iodata = 0; - break; - case 0x04: /* Carriage Busy */ - iodata = 0; - break; - case 0x06: /* Printer busy */ - iodata = 0; - break; - default: - return (STOP_INVDEV << 16); - } - return ((SCPE_OK << 16) | iodata); - case 3: /* SNS 1403 */ - switch (n) { - case 0x00: /* Line count */ - iodata = (linectr << 8); - break; - case 0x02: /* Timing data */ - iodata = 0; - break; - case 0x03: /* Check data */ - iodata = 0; - break; - case 0x04: /* LPIAR */ - iodata = LPIAR; - break; - case 0x06: /* LPDAR */ - iodata = LPDAR; - break; - default: - return (STOP_INVDEV << 16); - } - return ((SCPE_OK << 16) | iodata); - case 4: /* APL 1403 */ - iodata = 0; - return ((SCPE_OK << 16) | iodata); - default: - break; - } - printf (">>LPT non-existent function %d\n", op); - return SCPE_OK; -} - - -/* Print routine - - Modifiers have been checked by the caller - S = suppress automatic newline -*/ - -t_stat write_line (int32 ilnt, int32 mod) -{ -int32 i, t, lc; -static char lbuf[LPT_WIDTH + 1]; /* + null */ - -if ((lpt_unit.flags & UNIT_ATT) == 0) - return SCPE_UNATT; - -lpterror = 0; -lc = LPDAR; /* clear error */ -for (i = 0; i < LPT_WIDTH; i++) { /* convert print buf */ - t = M[lc]; - lbuf[i] = ebcdic_to_ascii[t & 0xff]; - M[lc] = 0x40; /* HJS MOD */ - lc++; -} -for (i = LPT_WIDTH - 1; (i >= 0) && (lbuf[i] == ' '); i--) lbuf[i] = 0; -fputs (lbuf, lpt_unit.fileref); /* write line */ -if (lines) space (lines, lflag); /* cc action? do it */ -else if (mod == 0) space (1, FALSE); /* default? 1 line */ -else { fputc ('\r', lpt_unit.fileref); /* sup -> overprint */ - lpt_unit.pos = ftell (lpt_unit.fileref); } /* update position */ -lines = lflag = 0; /* clear cc action */ -if (ferror (lpt_unit.fileref)) { /* error? */ - perror ("Line printer I/O error"); - clearerr (lpt_unit.fileref); - lpterror = 1; } -return SCPE_OK; -} - -/* Carriage control routine - - Parameters: - action = 00, skip to channel now - = 01, space lines after - = 02, space lines now - = 03, skip to channel after - = 04, skip to line number - mod = number of lines or channel number or line number -*/ - -t_stat carriage_control (int32 action, int32 mod) -{ -int32 i; - -if ((lpt_unit.flags & UNIT_ATT) == 0) - return SCPE_UNATT; - -switch (action) { -case 0: /* to channel now */ - if ((mod == 0) || (mod > 12) || CHP (mod, cct[cctptr])) return SCPE_OK; - for (i = 1; i < cctlnt + 1; i++) { /* sweep thru cct */ - if (CHP (mod, cct[(cctptr + i) % cctlnt])) - return space (i, TRUE); } - return STOP_INVDEV; /* runaway channel */ -case 1: /* space after */ - if (mod <= 3) { - lines = mod; /* save # lines */ - lflag = FALSE; /* flag spacing */ - CC9 = CC12 = 0; } - return SCPE_OK; -case 2: /* space now */ - if (mod <= 3) return space (mod, FALSE); - return SCPE_OK; -case 3: /* to channel after */ - if ((mod == 0) || (mod > 12)) return SCPE_OK; /* check channel */ - CC9 = CC12 = 0; - for (i = 1; i < cctlnt + 1; i++) { /* sweep thru cct */ - if (CHP (mod, cct[(cctptr + i) % cctlnt])) { - lines = i; /* save # lines */ - lflag = TRUE; /* flag skipping */ - return SCPE_OK; } - return STOP_INVDEV; -case 4: /* To line # */ - if (mod < 2) { - fputs ("\n\f", lpt_unit.fileref); /* nl, ff */ - linectr = 1; - } else { - if (mod <= linectr) { - fputs ("\n\f", lpt_unit.fileref); - linectr = 1; - } - while (1) { - if (linectr == mod) - break; - space(1, 0); - } - } - return SCPE_OK; } -} -return SCPE_OK; -} - -/* Space routine - space or skip n lines - - Inputs: - count = number of lines to space or skip - sflag = skip (TRUE) or space (FALSE) -*/ - -t_stat space (int32 count, int32 sflag) -{ -int32 i; - -if ((lpt_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT; -cctptr = (cctptr + count) % cctlnt; /* adv cct, mod lnt */ -if (sflag && CHP (0, cct[cctptr])) { /* skip, top of form? */ - fputs ("\n\f", lpt_unit.fileref); /* nl, ff */ - linectr = 1; -} -else { for (i = 0; i < count; i++) fputc ('\n', lpt_unit.fileref); } -lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */ -CC9 = CHP (9, cct[cctptr]) != 0; /* set indicators */ -CC12 = CHP (12, cct[cctptr]) != 0; -linectr += count; -if (linectr > LPFLR) - linectr -= LPFLR; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ -cctptr = 0; /* clear cct ptr */ -lines = linectr = lflag = 0; /* no cc action */ -lpterror = 0; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat lpt_attach (UNIT *uptr, char *cptr) -{ -cctptr = 0; /* clear cct ptr */ -lines = 0; /* no cc action */ -lpterror = 0; -linectr = 0; -return attach_unit (uptr, cptr); -} diff --git a/S3/s3_pkb.c b/S3/s3_pkb.c deleted file mode 100644 index 881bf360..00000000 --- a/S3/s3_pkb.c +++ /dev/null @@ -1,312 +0,0 @@ -/* s3_pkb.c: System/3 5471 console terminal simulator - - Copyright (c) 2001, Charles E. Owen - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. - - pkb 5471 printer/keyboard - - 25-Apr-03 RMS Revised for extended file support - 08-Oct-02 RMS Added impossible function catcher -*/ - -#include "s3_defs.h" -#include - -extern int32 int_req, dev_busy, dev_done, dev_disable; -t_stat pkb_svc (UNIT *uptr); -t_stat pkb_reset (DEVICE *dptr); -extern t_stat sim_poll_kbd (void); -extern t_stat sim_putchar (int32 out); -extern int32 IAR[], level; -extern int32 debug_reg; - -/* 5471 data structures - - pkb_dev TTI device descriptor - pkb_unit TTI unit descriptor - pkb_reg TTI register list - pkb_mod TTI/TTO modifiers list -*/ - -/* Flag bits : (kept in pkb_unit.u3) */ - -#define PRT_INTREQ 0x800 /* Printer interrupt pending */ -#define KBD_INTREQ 0x400 /* Request key interrupt pending */ -#define KBD_INTEND 0x200 /* End or cancel key interrupt pending */ -#define KBD_INTKEY 0x100 /* Return or other key interrupt pending */ -#define KBD_REQLIGHT 0x20 /* Request Pending Indicator (light on/off) */ -#define KBD_PROLIGHT 0x10 /* Proceed indicator (light on/off) */ -#define KBD_REQINT 0x04 /* Req key interrupts enabled */ -#define KBD_KEYINT 0x02 /* Other key interrupts enabled */ -#define PRT_PRTINT 0x01 /* Printer interrupts enabled */ - -/* Keys mapped to 5471 functions */ - -int32 key_req = 0x01; /* Request key: ^A */ -int32 key_rtn = 0x12; /* Return key: ^R */ -int32 key_can = 0x1B; /* Cancel key: ESC */ -int32 key_end = 0x0d; /* End key - CR */ - -UNIT pkb_unit = { UDATA (&pkb_svc, 0, 0), KBD_POLL_WAIT }; - -REG pkb_reg[] = { - { HRDATA (FLAG, pkb_unit.u3, 16) }, - { HRDATA (IBUF, pkb_unit.buf, 8) }, - { HRDATA (OBUF, pkb_unit.u4, 8) }, - { HRDATA (REQKEY, key_req, 8) }, - { HRDATA (RTNKEY, key_rtn, 8) }, - { HRDATA (CANKEY, key_can, 8) }, - { HRDATA (ENDKEY, key_end, 8) }, - { DRDATA (POS, pkb_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, pkb_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB pkb_mod[] = { - { 0 } }; - -DEVICE pkb_dev = { - "PKB", &pkb_unit, pkb_reg, pkb_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &pkb_reset, - NULL, NULL, NULL }; - - -/*-------------------------------------------------------------------*/ -/* EBCDIC to ASCII translate table */ -/*-------------------------------------------------------------------*/ -unsigned char ebcdic_to_ascii[] = { -"\x00\x01\x02\x03\xA6\x09\xA7\x7F\xA9\xB0\xB1\x0B\x0C\x0D\x0E\x0F" -"\x10\x11\x12\x13\xB2\xB4\x08\xB7\x18\x19\x1A\xB8\xBA\x1D\xBB\x1F" -"\xBD\xC0\x1C\xC1\xC2\x0A\x17\x1B\xC3\xC4\xC5\xC6\xC7\x05\x06\x07" -"\xC8\xC9\x16\xCB\xCC\x1E\xCD\x04\xCE\xD0\xD1\xD2\x14\x15\xD3\xFC" -"\x20\xD4\x83\x84\x85\xA0\xD5\x86\x87\xA4\xD6\x2E\x3C\x28\x2B\xD7" -"\x26\x82\x88\x89\x8A\xA1\x8C\x8B\x8D\xD8\x21\x24\x2A\x29\x3B\x5E" -"\x2D\x2F\xD9\x8E\xDB\xDC\xDD\x8F\x80\xA5\x7C\x2C\x25\x5F\x3E\x3F" -"\xDE\x90\xDF\xE0\xE2\xE3\xE4\xE5\xE6\x60\x3A\x23\x40\x27\x3D\x22" -"\xE7\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAE\xAF\xE8\xE9\xEA\xEC" -"\xF0\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xF1\xF2\x91\xF3\x92\xF4" -"\xF5\x7E\x73\x74\x75\x76\x77\x78\x79\x7A\xAD\xA8\xF6\x5B\xF7\xF8" -"\x9B\x9C\x9D\x9E\x9F\xB5\xB6\xAC\xAB\xB9\xAA\xB3\xBC\x5D\xBE\xBF" -"\x7B\x41\x42\x43\x44\x45\x46\x47\x48\x49\xCA\x93\x94\x95\xA2\xCF" -"\x7D\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xDA\x96\x81\x97\xA3\x98" -"\x5C\xE1\x53\x54\x55\x56\x57\x58\x59\x5A\xFD\xEB\x99\xED\xEE\xEF" -"\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xFE\xFB\x9A\xF9\xFA\xFF" -}; - -/*-------------------------------------------------------------------*/ -/* ASCII to EBCDIC translate table */ -/*-------------------------------------------------------------------*/ -unsigned char ascii_to_ebcdic[] = { -"\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x25\x0B\x0C\x0D\x0E\x0F" -"\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x1A\x27\x22\x1D\x35\x1F" -"\x40\x5A\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" -"\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" -"\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" -"\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xAD\xE0\xBD\x5F\x6D" -"\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" -"\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x6A\xD0\xA1\x07" -"\x68\xDC\x51\x42\x43\x44\x47\x48\x52\x53\x54\x57\x56\x58\x63\x67" -"\x71\x9C\x9E\xCB\xCC\xCD\xDB\xDD\xDF\xEC\xFC\xB0\xB1\xB2\xB3\xB4" -"\x45\x55\xCE\xDE\x49\x69\x04\x06\xAB\x08\xBA\xB8\xB7\xAA\x8A\x8B" -"\x09\x0A\x14\xBB\x15\xB5\xB6\x17\x1B\xB9\x1C\x1E\xBC\x20\xBE\xBF" -"\x21\x23\x24\x28\x29\x2A\x2B\x2C\x30\x31\xCA\x33\x34\x36\x38\xCF" -"\x39\x3A\x3B\x3E\x41\x46\x4A\x4F\x59\x62\xDA\x64\x65\x66\x70\x72" -"\x73\xE1\x74\x75\x76\x77\x78\x80\x8C\x8D\x8E\xEB\x8F\xED\xEE\xEF" -"\x90\x9A\x9B\x9D\x9F\xA0\xAC\xAE\xAF\xFD\xFE\xFB\x3F\xEA\xFA\xFF" -}; - -/* -------------------------------------------------------------------- */ - -/* Console Input: master routine */ - -int32 pkb (int32 op, int32 m, int32 n, int32 data) -{ - int32 iodata= 0, ec, ac; - switch (op) { - case 0: /* SIO 5471 */ - if (n != 0) - return STOP_INVDEV; - /*printf("%04X SIO %d,%d,%02X\n\r", IAR[level]-4, m, n, data);*/ - if (m == 0) { /* Keyboard */ - pkb_unit.u3 &= 0xFC1; - pkb_unit.u3 |= data; - if (data & 0x01) { - pkb_unit.u3 &= ~KBD_INTREQ; - pkb_unit.u3 &= ~KBD_INTKEY; - pkb_unit.u3 &= ~KBD_INTEND; - return RESET_INTERRUPT; - } - } else { /* Printer */ - if (data & 0x80) { /* start print bit */ - if (debug_reg & 0x80) - return STOP_IBKPT; - ec = pkb_unit.u4 & 0xff; - ac = ebcdic_to_ascii[ec]; - sim_putchar(ac); - pkb_unit.u3 |= PRT_INTREQ; - } - if (data & 0x40) { /* Carr. Return */ - sim_putchar('\n'); - sim_putchar('\r'); - pkb_unit.u3 |= PRT_INTREQ; - } - pkb_unit.u3 &= 0xFFe; - if (data & 0x04) /* Print interrupt flag */ - pkb_unit.u3 |= PRT_PRTINT; - if (data & 0x01) { /* Reset Interrupt */ - if (level < 8) { - if (!(data & 0x80)) - pkb_unit.u3 &= ~PRT_INTREQ; - return RESET_INTERRUPT; - } - } - } - return SCPE_OK; - case 1: /* LIO 5471 */ - if (n != 0) - return STOP_INVDEV; - if (m != 1) - return STOP_INVDEV; - pkb_unit.u4 = (data >> 8) & 0xff; - return SCPE_OK; - break; - case 2: /* TIO 5471 */ - return STOP_INVDEV; - case 3: /* SNS 5471 */ - if (n != 1 && n != 3) - return (STOP_INVDEV << 16); - if (m == 0) { /* Keyboard data */ - if (n == 1) { /* Sense bytes 0 & 1 */ - iodata = (pkb_unit.buf << 8) & 0xff00; - if (pkb_unit.u3 & KBD_INTREQ) - iodata |= 0x80; - if (pkb_unit.u3 & KBD_INTEND) - iodata |= 0x40; - if (pkb_unit.u3 & KBD_INTKEY) - iodata |= 0x08; - if (pkb_unit.buf == 0x12) /* Return key */ - iodata |= 0x04; - if (pkb_unit.buf == 0x03) /* Cancel key */ - iodata |= 0x20; - if (pkb_unit.buf == 0x0d) /* End key */ - iodata |= 0x10; - iodata |= ((SCPE_OK << 16) & 0xffff0000); - } else { /* Sense bytes 2 & 3 */ - iodata = 0; /* Manual says CE use only */ - } - } else { /* Printer Data */ - if (n == 1) { /* Sense bytes 0 & 1 */ - iodata = 0; - if (pkb_unit.u3 & PRT_INTREQ) - iodata |= 0x80; - } else { - iodata = 0; /* CE use only */ - } - } - iodata |= ((SCPE_OK << 16) & 0xffff0000); - return (iodata); - case 4: /* APL 5471 */ - return STOP_INVDEV; - default: - break; - } - printf (">>PKB non-existent function %d\n", op); - return SCPE_OK; -} - -/* Unit service */ - -t_stat pkb_svc (UNIT *uptr) -{ -int32 temp, ac, ec; - -sim_activate (&pkb_unit, pkb_unit.wait); /* continue poll */ - -if (pkb_unit.u3 & PRT_INTREQ) { /* Printer Interrupt */ - int_req |= 2; - return SCPE_OK; -} - -/* Keyboard : handle input */ - -if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ - -ac = temp & 0x7f; /* placed type ASCII char in ac */ -if (pkb_unit.u3 & KBD_REQINT) { - if (ac == key_req) { /* Request Key */ - pkb_unit.u3 |= KBD_INTREQ; - int_req |= 2; - return SCPE_OK; - } -} -if (islower(ac)) - ac = toupper(ac); -ec = ascii_to_ebcdic[ac]; /* Translate */ -pkb_unit.buf = ec; /* put in buf */ -pkb_unit.pos = pkb_unit.pos + 1; -if (ac == key_end) { /* End key */ - if (pkb_unit.u3 & KBD_KEYINT) { - pkb_unit.u3 |= KBD_INTEND; - pkb_unit.buf = 0x0d; - int_req |= 2; - } - return SCPE_OK; -} -if (ac == key_can) { /* Cancel key */ - if (pkb_unit.u3 & KBD_KEYINT) { - pkb_unit.u3 |= KBD_INTEND; - pkb_unit.buf = 0x03; - int_req |= 2; - } - return SCPE_OK; -} -if (ac == key_rtn) { /* Return key */ - if (pkb_unit.u3 & KBD_KEYINT) { - pkb_unit.u3 |= KBD_INTKEY; - pkb_unit.buf = 0x12; - int_req |= 2; - } - return SCPE_OK; -} -if (pkb_unit.u3 & KBD_KEYINT) { /* Key interupts enabled ? */ - int_req |= 2; /* Device 1 Interrupt! */ - pkb_unit.u3 |= KBD_INTKEY; /* Set pending flag */ -} -return SCPE_OK; -} - -/* Reset routine */ - -t_stat pkb_reset (DEVICE *dptr) -{ -pkb_unit.buf = 0; -int_req = int_req & ~0x02; /* reset interrupt */ -sim_activate (&pkb_unit, pkb_unit.wait); /* activate unit */ -return SCPE_OK; -} - -t_stat pkb_setmod (UNIT *uptr, int32 value) -{ -return SCPE_OK; -} - diff --git a/S3/s3_sys.c b/S3/s3_sys.c deleted file mode 100644 index c18e1506..00000000 --- a/S3/s3_sys.c +++ /dev/null @@ -1,942 +0,0 @@ -/* s3_sys.c: IBM System/3 system interface - - Copyright (c) 2001-2003, Charles E. Owen - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. -*/ - -#include -#include "s3_defs.h" - -extern DEVICE cpu_dev; -extern DEVICE pkb_dev; -extern DEVICE cdr_dev; -extern DEVICE cdp_dev; -extern DEVICE stack_dev; -extern DEVICE lpt_dev; -extern DEVICE r1_dev; -extern DEVICE f1_dev; -extern DEVICE r2_dev; -extern DEVICE f2_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern unsigned char M[]; -extern int32 saved_PC, IAR[]; -extern char ebcdic_to_ascii[256]; -char *parse_addr(char *cptr, char *gbuf, int32 *addr, int32 *addrtype); - -int32 printf_sym (FILE *of, char *strg, int32 addr, unsigned int32 *val, - UNIT *uptr, int32 sw); - -/* SCP data structures - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words needed for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "System/3"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 6; - -DEVICE *sim_devices[] = { &cpu_dev, - &pkb_dev, - &cdr_dev, - &cdp_dev, - &stack_dev, - &lpt_dev, - &r1_dev, - &f1_dev, - &r2_dev, - &f2_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unknown I/O Instruction", - "HALT instruction", - "Breakpoint", - "Invalid Opcode", - "Invalid Qbyte", - "Invalid Address", - "Invalid Device Command", - "ATTN Card Reader" -}; - -/* This is the opcode master defintion table. Each possible opcode mnemonic - is defined here, with enough information to translate to and from - symbolic to binary machine code. - First field is the opcode's mnemonic - Second field is the hex of the right nybble of the binary opcode - Third field is the Q code for those with implicit Q codes - Fourth field is the symbolic format of the operands: - 0 - (Q-byte),(R-byte) - 1 - (Q-byte),(Address) - 2 - (Address),(Address),(Qbyte) - 3 - (Address),(Qbyte) - 4 - (device),(modifier),(function) -- these 3 make up qbyte - 5 - (device),(modifier),(function),(control) - 6 - (device),(modifier),(function),(Address) - 7 - (displacement) -- Q byte is implicit in opcode - 8 - (address) -- Qbyte is implicit in opcode - 9 - (Address),(Address) -- Qbyte is implicit in opcode - Fifth Field is the group number: - 0 - Command Group (left op nybble is F) - 1 - One Address Operations A (Left Nybble C, D, or E) - 2 - Two Address Operations (Left Nybble 0,1,2,4,5,6,8,9, or A) - 3 - One Address Operations B (left Nybble 3, 7, or B) - - There is duplication in this table -- IBM defines different opcodes - that resolve to the same binary machine instruction -- e.g. JE and - JZ. On input this is no problem, on output, define the one you - want to appear first, the second will never appear on output. -*/ - -int32 nopcode = 75; -struct opdef opcode[75] = { - "HPL", 0x00,0,0,0, /* Halt Program Level */ - "A", 0x06,0,1,3, /* Add to Register: A R,AADD */ - "ST", 0x04,0,1,3, /* Store Register */ - "L", 0x05,0,1,3, /* Load Register */ - "LA", 0x02,0,1,1, /* Load Address */ - "ZAZ", 0x04,0,2,2, /* Zero and Add Zoned */ - "AZ", 0x06,0,2,2, /* Add Zoned Decimal */ - "SZ", 0x07,0,2,2, /* Subtract Zoned Decimal */ - "ALC", 0x0E,0,2,2, /* Add Logical: ALC BADD,AADD,LEN */ - "SLC", 0x0F,0,2,2, /* Sub Logical: SLC BADD,AADD,LEN */ - "MVC", 0x0C,0,2,2, /* Move Chars MVX BADD,AADD,LEN */ - "ED", 0x0A,0,2,2, /* Edit: ED BADD,AADD,LEN */ - "ITC", 0x0B,0,2,2, /* Insert Chars: ITC BADD,AADD,LEN */ - "CLC", 0x0D,0,2,2, /* Compare Logical: CLC BADD,AADD,LEN */ - "MVI", 0x0C,0,3,3, /* Move Immediate */ - "SBN", 0x0A,0,3,3, /* Set Bits On */ - "SBF", 0x0B,0,3,3, /* Set Bits Off */ - "CLI", 0x0D,0,3,3, /* Compare Immediate */ - "TBN", 0x08,0,3,3, /* Test Bits On */ - "TBF", 0x09,0,3,3, /* Test Bits Off */ - "APL", 0x01,0,4,0, /* Advance Program Level */ - "SIO", 0x03,0,5,0, /* Start I/O */ - "SNS", 0x00,0,6,3, /* Sense I/O */ - "LIO", 0x01,0,6,3, /* Load I/O */ - "TIO", 0x01,0,6,1, /* Test I/O */ - "J", 0x02,0,7,0, /* Jump Unconditional */ - "J", 0x02,0x87,7,0, /* Alternate J */ - "JH", 0x02,132,7,0, /* Jump if High */ - "JL", 0x02,130,7,0, /* Jump if Low */ - "JE", 0x02,129,7,0, /* Jump if Equal */ - "JNH", 0x02,4,7,0, /* Jump if Not High */ - "JNL", 0x02,2,7,0, /* Jump if Not Low */ - "JNE", 0x02,1,7,0, /* Jump if Not Equal */ - "JOZ", 0x02,136,7,0, /* Jump if Overflow Zoned */ - "JOL", 0x02,160,7,0, /* Jump if Overflow Logical */ - "JNOZ", 0x02,8,7,0, /* Jump if No Overflow Zoned */ - "JNOL", 0x02,32,7,0, /* Jump if No Overflow Logical */ - "JT", 0x02,16,7,0, /* Jump if True */ - "JF", 0x02,144,7,0, /* Jump if False */ - "JP", 0x02,132,7,0, /* Jump if Plus */ - "JM", 0x02,130,7,0, /* Jump if Minus */ - "JZ", 0x02,129,7,0, /* Jump if Zero */ - "JNP", 0x02,4,7,0, /* Jump if Not Plus */ - "JNM", 0x02,2,7,0, /* Jump if Not Minus */ - "JNZ", 0x02,1,7,0, /* Jump if Not Zero */ - "NOPJ", 0x02,0x80,7,0, /* Never Jump - NOP */ - "B", 0x00,0x00,8,1, /* Branch Unconditional */ - "B", 0x00,0x87,8,1, /* Alternate B */ - "BH", 0x00,0x84,8,1, /* Branch if High */ - "BL", 0x00,0x82,8,1, /* Branch if Low */ - "BE", 0x00,0x81,8,1, /* Branch if Equal */ - "BNH", 0x00,0x04,8,1, /* Branch if Not High */ - "BNL", 0x00,0x02,8,1, /* Branch if Not Low */ - "BNE", 0x00,0x01,8,1, /* Branch if Not Equal */ - "BOZ", 0x00,0x88,8,1, /* Branch if Overflow Zoned */ - "BOL", 0x00,0xA0,8,1, /* Branch if Overflow Logical */ - "BNOZ", 0x00,0x08,8,1, /* Branch if No Overflow Zoned */ - "BNOL", 0x00,0x20,8,1, /* Branch if No Overflow Logical */ - "BT", 0x00,0x10,8,1, /* Branch if True */ - "BF", 0x00,0x90,8,1, /* Branch if False */ - "BP", 0x00,0x84,8,1, /* Branch if Plus */ - "BM", 0x00,0x82,8,1, /* Branch if Minus */ - "BZ", 0x00,0x81,8,1, /* Branch if Zero */ - "BNP", 0x00,0x04,8,1, /* Branch if Not Plus */ - "BNM", 0x00,0x02,8,1, /* Branch if Not Minus */ - "BNZ", 0x00,0x01,8,1, /* Branch if Not Zero */ - "NOPB", 0x00,0x80,8,1, /* Never Branch - NOP */ - "MZZ", 0x08,0,9,2, /* Move Zone to Zone */ - "MNZ", 0x08,1,9,2, /* Move Numeric to Zone */ - "MZN", 0x08,2,9,2, /* Move Zone to Numeric */ - "MNN", 0x08,3,9,2, /* Move Numeric to Numeric */ - "MVX", 0x08,0,2,2, /* Move Hex: MVX BADD,AADD,CODE */ - "JC", 0x02,0,3,0, /* Jump on Specified Condition bits */ - "BC", 0x00,0,3,1, /* Branch on Specified Condition */ - "***", 0x00,0,0,0 -}; - -int32 regcode[15] = { 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, - 0x80, 0xC0, 0xA0, 0x90, 0x88, 0x84, 0x82, 0x81 }; - -char regname[15][8] = { "(P2IAR)", - "(P1IAR)", - "(IAR)", - "(ARR)", - "(PSR)", - "(XR2)", - "(XR1)", - "(IAR0)", - "(IAR1)", - "(IAR2)", - "(IAR3)", - "(IAR4)", - "(IAR5)", - "(IAR6)", - "(IAR7)" }; - -/* This is the binary loader. The input file is considered to be - a string of literal bytes with no special format. The - load starts at the current value of the P1IAR. -*/ - -int32 sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 i, addr = 0, cnt = 0; - -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; -addr = IAR[8]; -while ((i = getc (fileref)) != EOF) { - M[addr] = i & 0xff; - addr++; - cnt++; - } /* end while */ -printf ("%d Bytes loaded.\n", cnt); -return (SCPE_OK); -} - -/* Symbolic output - - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - status = error code -*/ - -int32 fprint_sym (FILE *of, int32 addr, unsigned int32 *val, - UNIT *uptr, int32 sw) -{ - int32 r; - char strg[256]; - - strcpy(strg, ""); - r = printf_sym(of, strg, addr, val, uptr, sw); - if (sw & SWMASK ('A')) - strcpy(strg, ""); - else - fprintf(of, "%s", strg); - return (r); -} - -int32 printf_sym (FILE *of, char *strg, int32 addr, unsigned int32 *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, c1, c2, group, len1, len2, inst, aaddr, baddr; -int32 oplen, groupno, i, j, vpos, qbyte, da, m, n; -char bld[128], bldaddr[32], boperand[32], aoperand[32]; -int32 blk[16], blt[16]; -int32 blkadd; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -c1 = val[0] & 0xff; -if (sw & SWMASK ('A')) { - for (i = 0; i < 16; i++) { - blkadd = addr + (i*16); - for (j = 0; j < 16; j++) { - blk[j] = M[blkadd+j] & 0xff; - c2 = ebcdic_to_ascii[blk[j]]; - if (c2 < 040 || c2 > 0177 || blk[j] == 07) { - blt[j] = '.'; - } else { - blt[j] = c2; - } - } - if (i == 0) { - fprintf(of, "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X [%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c]\n ", - blk[0], blk[1], blk[2], blk[3], blk[4], blk[5], blk[6], blk[7], - blk[8], blk[9], blk[10], blk[11], blk[12], blk[13], blk[14], blk[15], - blt[0], blt[1], blt[2], blt[3], blt[4], blt[5], blt[6], blt[7], - blt[8], blt[9], blt[10], blt[11], blt[12], blt[13], blt[14], blt[15]); - } else { - fprintf(of, "%X\t%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X [%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c]\n ", - blkadd, blk[0], blk[1], blk[2], blk[3], blk[4], blk[5], blk[6], blk[7], - blk[8], blk[9], blk[10], blk[11], blk[12], blk[13], blk[14], blk[15], - blt[0], blt[1], blt[2], blt[3], blt[4], blt[5], blt[6], blt[7], - blt[8], blt[9], blt[10], blt[11], blt[12], blt[13], blt[14], blt[15]); - } - } - return SCPE_OK; } -if (sw & SWMASK ('C')) { - c2 = ebcdic_to_ascii[c1]; - if (c2 < 040 || c2 > 0177) { - sprintf(strg, "<%02X>", c1 & 0xff); - } else { - sprintf (strg, "%c", c2 & 0xff); - } - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; - -inst = val[0] & 0x0f; -len1 = (val[0] >> 6) & 3; -len2 = (val[0] >> 4) & 3; -group = (val[0] >> 4) & 0x0f; -qbyte = val[1]; - -/* Get total length of instruction */ - -if (group == 0x0f) { - oplen = 3; -} else { - oplen = 2; - if (len1 == 0) oplen += 2; - if (len1 == 1 || len1 == 2) oplen++; - if (len2 == 0) oplen += 2; - if (len2 == 1 || len2 == 2) oplen++; -} - -/* Find which group it belongs to */ - -switch (group) { - case 0x0f: - groupno = 0; - break; - case 0x0c: - case 0x0d: - case 0x0e: - groupno = 1; - break; - case 0x03: - case 0x07: - case 0x0b: - groupno = 3; - break; - default: - groupno = 2; - break; -} - -/* find the table entry */ - -for (i = 0; i < nopcode; i++) { - if (opcode[i].form < 7) { /* Explicit Q */ - if (opcode[i].group == groupno && - opcode[i].opmask == inst) break; - } else { /* Implicit Q */ - if (opcode[i].group == groupno && - opcode[i].opmask == inst && - opcode[i].q == qbyte) break; - } -} - -/* print the opcode */ - -if (i >= nopcode) { - sprintf(strg, "%02X", val[0]); - oplen = 1; -} else { - sprintf(bld, "%s ", opcode[i].op); - - /* Extract the addresses into aaddr and baddr */ - - strcpy(aoperand, "ERROR"); - strcpy(boperand, "ERROR"); - vpos = 2; - aaddr = baddr = 0; - switch (len1) { - case 0: - baddr = ((val[vpos] << 8) & 0xff00) | (val[vpos + 1] & 0x00ff); - sprintf(boperand, "%04X", baddr); - vpos = 4; - break; - case 1: - baddr = val[vpos] & 255; - sprintf(boperand, "(%02X,XR1)", baddr); - vpos = 3; - break; - case 2: - baddr = val[vpos] & 255; - sprintf(boperand, "(%02X,XR2)", baddr); - vpos = 3; - break; - default: - baddr = 0; - break; - } - switch (len2) { - case 0: - aaddr = ((val[vpos] << 8) & 0xff00) | (val[vpos + 1] & 0x00ff); - if (group == 0x0C || group == 0x0D || group == 0x0E) - sprintf(boperand, "%04X", aaddr); - else - sprintf(aoperand, "%04X", aaddr); - break; - case 1: - aaddr = val[vpos] & 255; - if (group == 0x0C || group == 0x0D || group == 0x0E) - sprintf(boperand, "(%02X,XR1)", aaddr); - else - sprintf(aoperand, "(%02X,XR1)", aaddr); - break; - case 2: - aaddr = val[vpos] & 255; - if (group == 0x0C || group == 0x0D || group == 0x0E) - sprintf(boperand, "(%02X,XR2)", aaddr); - else - sprintf(aoperand, "(%02X,XR2)", aaddr); - break; - default: - aaddr = 0; - break; - } - - /* Display the operands in the correct format */ - - da = (qbyte >> 4) & 0x0f; - m = (qbyte >> 3) & 0x01; - n = (qbyte) & 0x07; - - switch (opcode[i].form) { - case 0: - sprintf(bldaddr, "%02X,%02X", qbyte, val[2]); - break; - case 1: - if (inst == 2 || inst == 4 || inst == 5 || inst == 6) { - for (i = 0; i < 16; i++) { - if (regcode[i] == qbyte) - break; - } - if (i < 16) { - sprintf(bldaddr, "%s,%s", regname[i], boperand); - } else { - sprintf(bldaddr, "%02X,%s", qbyte, boperand); - } - } else { - sprintf(bldaddr, "%02X,%s", qbyte, boperand); - } - break; - case 2: - if (inst > 9 || inst == 4 || inst == 6 || inst == 7) - qbyte++; /* special +1 for length display */ - sprintf(bldaddr, "%s,%s,%d", boperand, aoperand, qbyte); - break; - case 3: - if (strcmp(opcode[i].op, "JC") == 0) { - sprintf(bldaddr, "%04X,%02X", addr+oplen+val[2], qbyte); - } else { - sprintf(bldaddr, "%s,%02X", boperand, qbyte); - } - break; - case 4: - sprintf(bldaddr, "%d,%d,%d", da, m, n); - break; - case 5: - sprintf(bldaddr, "%d,%d,%d,%02X", da, m, n, val[2]); - break; - case 6: - sprintf(bldaddr, "%d,%d,%d,%s", da, m, n, boperand); - break; - case 7: - sprintf(bldaddr, "%04X", addr+oplen+val[2]); - break; - case 8: - sprintf(bldaddr, "%s", boperand); - break; - default: - sprintf(bldaddr, "%s,%s", boperand, aoperand); - break; - } - sprintf(strg, "%s%s", bld, bldaddr); -} - -return -(oplen - 1); -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = error status -*/ - -int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, unsigned int32 *val, int32 sw) -{ -int32 cflag, i = 0, j, r, oplen, addtyp, saveaddr, vptr; -char gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ -if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (unsigned int) cptr[0]; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = ((unsigned int) cptr[0] << 8) + (unsigned int) cptr[1]; - return SCPE_OK; } - -/* An instruction: get opcode (all characters until null, comma, left paren, - or numeric (including spaces). -*/ - -while (1) { - if (*cptr == ',' || *cptr == '\0' || *cptr == '(' || - isdigit(*cptr)) - break; - gbuf[i] = toupper(*cptr); - cptr++; - i++; -} - -/* kill trailing spaces if any */ -gbuf[i] = '\0'; -for (j = i - 1; gbuf[j] == ' '; j--) { - gbuf[j] = '\0'; -} - -/* find opcode in table */ -for (j = 0; j < nopcode; j++) { - if (strcmp(gbuf, opcode[j].op) == 0) - break; -} -if (j >= nopcode) /* not found */ - return SCPE_ARG; - -oplen = 2; /* start with op & q */ - -val[0] = opcode[j].opmask; /* store opcode right nybble */ - -switch (opcode[j].form) { /* Get operands based on operand format */ - case 0: /* Single Byte Operand */ - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); /* Get Q Byte */ - sscanf(gbuf, "%x", &r); - val[1] = r; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, 0); /* Get R Byte */ - sscanf(gbuf, "%x", &r); - val[2] = r; - oplen = 3; - val[0] = 0xf0 | opcode[j].opmask; - break; - case 1: - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - if (opcode[j].opmask == 2 || - opcode[j].opmask == 4 || - opcode[j].opmask == 5 || - opcode[j].opmask == 6) { - if (isdigit(gbuf[0])) { - sscanf(gbuf, "%x", &r); - } else { - for (i = 0; i < 16; i++) { - if (strcmp(gbuf, regname[i]) == 0) - break; - } - if (i < 16) { - r = regcode[i]; - } else { - return SCPE_ARG; - } - } - } else { - sscanf(gbuf, "%x", &r); - } - if (r > 255) return SCPE_ARG; - val[1] = r; - if (*cptr == ',') cptr++; - cptr = parse_addr(cptr, gbuf, &addr, &addtyp); - switch(addtyp) { - case 0: - val[2] = (addr >> 8) & 0x00ff; - val[3] = addr & 0xff; - oplen = 4; - if (opcode[j].group == 1) - val[0] = 0xC0 | opcode[j].opmask; - else - val[0] = 0x30 | opcode[j].opmask; - break; - case 1: - val[2] = addr & 0xff; - oplen = 3; - if (opcode[j].group == 1) - val[0] = 0xD0 | opcode[j].opmask; - else - val[0] = 0x70 | opcode[j].opmask; - break; - case 2: - val[2] = addr & 0xff; - oplen = 3; - if (opcode[j].group == 1) - val[0] = 0xE0 | opcode[j].opmask; - else - val[0] = 0xB0 | opcode[j].opmask; - break; - default: - return SCPE_ARG; - break; - } - break; - case 2: - oplen = 2; - cptr = parse_addr(cptr, gbuf, &addr, &addtyp); - switch(addtyp) { - case 0: - val[2] = (addr >> 8) & 0xff; - val[3] = addr & 0xff; - oplen += 2; - vptr = 4; - val[0] = 0x00 | opcode[j].opmask; - break; - case 1: - val[2] = addr & 0xff; - oplen += 1; - vptr = 3; - val[0] = 0x40 | opcode[j].opmask; - break; - case 2: - val[2] = addr & 0xff; - oplen += 1; - vptr = 3; - val[0] = 0x80 | opcode[j].opmask; - break; - default: - return SCPE_ARG; - break; - } - if (*cptr == ',') cptr++; - cptr = parse_addr(cptr, gbuf, &addr, &addtyp); - switch(addtyp) { - case 0: - val[vptr] = (addr >> 8) & 0xff; - val[vptr+1] = addr & 0xff; - oplen += 2; - break; - case 1: - val[vptr] = addr & 0xff; - oplen += 1; - val[0] = 0x10 | val[0]; - break; - case 2: - val[vptr] = addr & 0xff; - oplen += 1; - val[0] = 0x20 | val[0]; - break; - default: - return SCPE_ARG; - break; - } - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, 0); - sscanf(gbuf, "%d", &r); - if (opcode[j].opmask > 9 || - opcode[j].opmask == 4 || - opcode[j].opmask == 6 || - opcode[j].opmask == 7) r--; /* special: length -1 */ - val[1] = r; - if (*cptr == ',') cptr++; - break; - case 3: - saveaddr = addr; - if (*cptr == ',') cptr++; - cptr = parse_addr(cptr, gbuf, &addr, &addtyp); - switch(addtyp) { - case 0: - if (opcode[j].group == 0) { /* Group 0 form 3 is JC with explicit Q */ - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, 0); - sscanf(gbuf, "%x", &r); - if ((addr - (saveaddr+3)) > 255 || (addr - (saveaddr+3)) < 1) - return SCPE_ARG; - val[2] = addr - (saveaddr+3); - val[1] = r; - val[0] = 0xf0 | opcode[j].opmask; - oplen = 3; - - } else { - val[2] = (addr >> 8) & 0x00ff; - val[3] = addr & 0xff; - oplen = 4; - if (opcode[j].group == 1) - val[0] = 0xC0 | opcode[j].opmask; - else - val[0] = 0x30 | opcode[j].opmask; - } - break; - case 1: - val[2] = addr & 0xff; - oplen = 3; - if (opcode[j].group == 1) - val[0] = 0xD0 | opcode[j].opmask; - else - val[0] = 0x70 | opcode[j].opmask; - break; - case 2: - val[2] = addr & 0xff; - oplen = 3; - if (opcode[j].group == 1) - val[0] = 0xE0 | opcode[j].opmask; - else - val[0] = 0xB0 | opcode[j].opmask; - break; - default: - return SCPE_ARG; - break; - } - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, 0); - sscanf(gbuf, "%x", &r); - if (r > 255) return SCPE_ARG; - val[1] = r; - break; - case 4: - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - sscanf(gbuf, "%d", &r); - if (r > 15) return SCPE_ARG; - val[1] = (r << 4) & 0xf0; - val[0] = 0xf0 | opcode[j].opmask; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - sscanf(gbuf, "%d", &r); - if (r > 1) return SCPE_ARG; - val[1] |= (r << 3) & 0x08; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, 0); - sscanf(gbuf, "%d", &r); - if (r > 7) return SCPE_ARG; - val[1] |= r & 0x07; - val[2] = 0; - oplen = 3; - break; - case 5: - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - sscanf(gbuf, "%d", &r); - if (r > 15) return SCPE_ARG; - val[1] = (r << 4) & 0xf0; - val[0] = 0xf0 | opcode[j].opmask; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - sscanf(gbuf, "%d", &r); - if (r > 1) return SCPE_ARG; - val[1] |= (r << 3) & 0x08; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - sscanf(gbuf, "%d", &r); - if (r > 7) return SCPE_ARG; - val[1] |= r & 0x07; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, 0); - sscanf(gbuf, "%x", &r); - if (r > 255) return SCPE_ARG; - val[2] = r; - oplen = 3; - break; - case 6: - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - sscanf(gbuf, "%d", &r); - if (r > 15) return SCPE_ARG; - val[1] = (r << 4) & 0xf0; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - sscanf(gbuf, "%d", &r); - if (r > 1) return SCPE_ARG; - val[1] |= (r << 3) & 0x08; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - sscanf(gbuf, "%d", &r); - if (r > 7) return SCPE_ARG; - val[1] |= r & 0x07; - if (*cptr == ',') cptr++; - cptr = parse_addr(cptr, gbuf, &addr, &addtyp); - switch(addtyp) { - case 0: - val[2] = (addr >> 8) & 0x00ff; - val[3] = addr & 0xff; - oplen = 4; - if (opcode[j].group == 1) - val[0] = 0xC0 | opcode[j].opmask; - else - val[0] = 0x30 | opcode[j].opmask; - break; - case 1: - val[2] = addr & 0xff; - oplen = 3; - if (opcode[j].group == 1) - val[0] = 0xD0 | opcode[j].opmask; - else - val[0] = 0x70 | opcode[j].opmask; - break; - case 2: - val[2] = addr & 0xff; - oplen = 3; - if (opcode[j].group == 1) - val[0] = 0xE0 | opcode[j].opmask; - else - val[0] = 0xB0 | opcode[j].opmask; - break; - default: - return SCPE_ARG; - break; - } - break; - case 7: - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, 0); - sscanf(gbuf, "%x", &r); - if ((r - (addr+3)) > 255 || (r - (addr+3)) < 1) return SCPE_ARG; - val[2] = r - (addr+3); - val[1] = opcode[j].q; - val[0] = 0xf0 | opcode[j].opmask; - oplen = 3; - break; - - case 8: - if (*cptr == ',') cptr++; - cptr = parse_addr(cptr, gbuf, &addr, &addtyp); - switch(addtyp) { - case 0: - val[2] = (addr >> 8) & 0x00ff; - val[3] = addr & 0xff; - oplen = 4; - val[0] = 0xC0 | opcode[j].opmask; - break; - case 1: - val[2] = addr & 0xff; - oplen = 3; - val[0] = 0xD0 | opcode[j].opmask; - break; - case 2: - val[2] = addr & 0xff; - oplen = 3; - val[0] = 0xE0 | opcode[j].opmask; - break; - default: - return SCPE_ARG; - break; - } - val[1] = opcode[j].q; - break; - case 9: - oplen = 2; - val[0] = 0; - cptr = parse_addr(cptr, gbuf, &addr, &addtyp); - switch(addtyp) { - case 0: - val[2] = (addr >> 8) & 0xff; - val[3] = addr & 0xff; - oplen += 2; - vptr = 4; - val[0] = 0x00 | opcode[j].opmask; - break; - case 1: - val[2] = addr & 0xff; - oplen += 1; - vptr = 3; - val[0] = 0x40 | opcode[j].opmask; - break; - case 2: - val[2] = addr & 0xff; - oplen += 1; - vptr = 3; - val[0] = 0x80 | opcode[j].opmask; - break; - default: - return SCPE_ARG; - break; - } - if (*cptr == ',') cptr++; - cptr = parse_addr(cptr, gbuf, &addr, &addtyp); - switch(addtyp) { - case 0: - val[vptr] = (addr >> 8) & 0xff; - val[vptr+1] = addr & 0xff; - oplen += 2; - break; - case 1: - val[vptr] = addr & 0xff; - oplen += 1; - val[0] = 0x10 | val[0]; - break; - case 2: - val[vptr] = addr & 0xff; - oplen += 1; - val[0] = 0x20 | val[0]; - break; - default: - return SCPE_ARG; - break; - } - val[1] = opcode[j].q; - break; - default: - break; -} - - -return (-(oplen-1)); -} - -char *parse_addr(char *cptr, char *gbuf, int32 *addr, int32 *addrtype) -{ -int32 nybble = 0; -char temp[32]; - -cptr = get_glyph(cptr, gbuf, ','); -if (gbuf[0] == '(') { /* XR relative */ - strcpy(temp, gbuf+1); - sscanf(temp, "%x", addr); - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - nybble = -1; - if (strcmp(gbuf, "XR1)") == 0) - nybble = 1; - if (strcmp(gbuf, "XR2)") == 0) - nybble = 2; -} else { /* Direct */ - sscanf(gbuf, "%x", addr); - nybble = 0; -} -*addrtype = nybble; -return cptr; -} - diff --git a/S3/system3.txt b/S3/system3.txt deleted file mode 100644 index e01a97df..00000000 --- a/S3/system3.txt +++ /dev/null @@ -1,472 +0,0 @@ - The IBM System/3 simulator is configured as follows: - - CPU 5410 (Model 10) CPU with 64KB of memory. - PKB 5471 Printer/Keyboard console. - CDR 1442 Card Reader - CDP 1442 Card Punch - CDP2 1442 2nd stacker - LPT 1403 Line Printer - R1 5444 Top Drive (removeable) - F1 5444 Top Drive (fixed) - R2 5444 Bottom Drive (removeable) - F2 5444 Bottom Drive (fixed - - The only CPU options are to set Model 15 mode (not implemented), DPF -(Dual Programming Facility, not implemented), and the memory size 8K, 16K, -32K, 48K, or 64K. - - CPU registers are the standard System/3 set: - - name size Description - - IAR-P1 16 Instruction Address Register for Program Level 1 - ARR-P2 16 Address Recall Register for Program Level 1 - IAR-P2 16 IAR for Program Level 2 (not implemented) - ARR-P2 16 ARR for Program Level 2 (not implemented) - AAR 16 A-Address Register - BAR 16 B-Address Register - PSR 16 Program Status Register - XR1 16 Index Register 1 - XR2 16 Index Register 2 - IAR<0:7> 16 IAR for interrupt level 0 thru 7 - ARR<0:7> 16 ARR for interrupt level 0 thru 7 - - Plus these simulator registers: - - IAR 16 Value of last IAR used. - LEVEL 8 Current operating level (8=P1, 9=P2, - 0 thru 7 = Interrupt level) - SR 16 Front Panel switches - INT 16 Interrupt Request Flags - WRU 8 Simulator Interrupt Character - BREAK 17 Breakpoint Address - DEBUG 16 Debugging bits: - 0x01: Write all instructions executed to - file trace.log. - 0x02: Write details of all Disk I/O - requests to trace.log. - 0x80: Breakpoint on first character - written to 5471 printer. - -1 5471 Printer/Keyboard - - This is the operator console. It has the following registers: - - FLAG 5471 Flag Bytes - IBUF: Input character from keyboard - OBUF: Output character to printer - POS: Number of characters printed - TIME: Delay for device operation - REQKEY: ASCII value of key mapped to 5471 REQUEST key - RTNKEY: ASCII value of key mapped to 5471 RETURN key - ENDKEY: ASCII value of key mapped to 5471 END key - CANKEY: ASCII value of key mapped to 5471 CANCEL key - - -2 1442 Card Reader. This reader reads 80-column cards; the input - is usually an ASCII file which is translated to EBCDIC when read, - but optionally can be a binary file in EBCDIC format (such as an - object program). - - LAST Last card switch - ERR Card Reader Error - NOTRDY 1442 reader not ready (not attached or past EOF) - DAR Data Address Register (shared with punch) - LCR Length Count Register (shared with punch) - EBCDIC EBCDIC mode flag: if 1, input is 80-col EBCDIC binary. - (IPL from 1442 automatically sets this to 1). - S2 Stacker 2 is selected when this is 1 - POS Number of cards read - TIME Device Delay - - The real hardware 1442 had only 1 hopper for cards, whether - these were used for blank cards for punching, or cards to be - read. Cards could be read without a feed cycle, then - punched. When punching cards, the SCP does a read of a card, - makes sure it is blank, and then punches it. To simulate - this without requiring that a stack of blank lines be attached - to the card reader device, a special feature of the simulator - is this: if no file is attached to the cdr device, but a file - is attached to the cdp or the cdp2 devices, any read from the - reader will return a blank card -- i.e. when punching, an - unattached cdr device is assumed to be loaded with an unlimited - supply of blank cards. - - -3 1442 Card Punch. Normally cards are written to the attached - disk file as ASCII with newline/cr delimiters. But an optional - flag allows writing as 80-column binary EBCDIC. - - ERR Card Punch Error - EBCDIC When this is 1, output will be 80-col EBCDIC. - S2 When this is 1, output is placed in stacker 2 - NOTRDY 1442 punch not ready (not attached) - DAR Data Address Register (shared with reader) - LCR Length Count Register (shared with reader) - POS Number of cards punched - TIME Device Delay - -4 1442 Stacker 2. When cards are to be punched in stacker 2, - attach a disk file to this device (cdp2) to hold that output. - Note: When SCP punches cards, the default is to punch in - stacker 2. - - POS0 Number of cards punched. - -5 1403 Printer. This is a 132-column output device, emulating - the famous IBM 1403, models 2, 6, and N1. Output is always - translated to ASCII with newline/CR delimiters. Page advance - is output as a form feed. - - ERR 1403 error flags - LPDAR Data Address Register - LPFLR Forms Length Register - LPIAR Image Address Register - LINECT Current Line on form - POS Number of lines printed - -6 5444 Disk Drives (R1, R2, F1, F2) - - The 5444 came as a set of two drives, each with two disks. The - top disk in a drive was removable, the bottom fixed. The first - drive consists of disks R1 and F1, the second drive R2 and F2. - Each disk holds 2,467,600 bytes of user data, plus 3 alternate - tracks and a CE track. Flagging of alternate tracks is not - supported in this version of the simulator. - - NOTRDY Drive not ready (not attached) - SEEK Drive is busy with a seek operation - DAR Data Address Register - CAR Control Address Register - ERR Error Flags (16 bits) - CYL Current Cylinder (0 thru 203) - HEAD Current head (0 or 1) - POS Current position in attached disk file - TIME Device Delay - -7 Symbolic Display and Input - - The System/3 Simulator supports symbolic display and input. - Display is controlled by command line switches: - - (none) display as hex EBCDIC - -c display bytes as characters - -m display instruction mnemonics. - -a display a 256-byte block of memory in both hex and ASCII. - - The symbolic format contains the same elements as the machine - language operation, but not always in the same order. The - operation code frequently specifies both the opcode and the Q byte, - and the top nybble of the opcode is determined by the format of the - addresses. - - Addresses take two forms: the direct address in hex, or a relative - address specified thusly: (byte,XRx) where 'byte' is a 1-byte - offset, and XRx is either XR1 or XR2 for the two index registers. - Use these formats when 'address' is indicated below: - - When 'reg' is mentioned, a mnemonic may be used for the register, - thusly: - - IAR Instruction Address Register for the current program level - ARR Address Recall Register for the current program level - P1IAR IAR for Program Level 1 - P2IAR IAR for Program Level 2 - PSR Program Status Register - XR1 Index Register 1 - XR2 Index Register 2 - IARx IAR for the interrupt level x (x = 0 thru 7) - - All other operands mentioned below are single-byte hex, except for - the length (len) operand of the two-address instructions, which is a - decimal length in the range 1-256. - - In operations where there is a source and a destination, the - destination is always operand 1, the source is operand 2. - - No-address formats: - ------------------ - - HPL hex,hex Halt Program Level, the operands are the - Q and R bytes. - - - One-address formats: - ------------------- - - A reg,address Add to register - CLI address,byte Compare Logical Immediate - MVI address,byte Move Immediate - TBF address,mask Test Bits Off - TBN address,mask Test Bits On - SBF address,mask Set Bits Off - SBN address,mask Set Bits On - ST reg,address Store Register - L reg,address Load Register - LA reg,address Load Address (reg can only be XR1 or XR2) - JC address,cond Jump on Condition - BC address,cond Branch on Condition - - These operations do not specify a qbyte, it is implicit in the - opcode: - - B address Unconditional branch to address - BE address Branch Equal - BNE address Branch Not Equal - BH address Branch High - BNH address Branch Not High - BL address Branch Low - BNL address Branch Not Low - BT address Branch True - BF address Branch False - BP address Branch Plus - BM address Branch Minus - BNP address Branch Not Plus - BNM address Branch Not Minus - BZ address Branch Zero - BNZ address Branch Not Zero - BOZ address Branch Overflow Zoned - BOL address Branch Overflow Logical - BNOZ address Branch No Overflow Zoned - BNOL address Branch No Overflow Logical - NOPB address No - never branch - - (substitute J for B above for a set of Jumps -- 1-byte operand (not - 2), always jumps forward up to 255 bytes from the address following - the Jump instruction. In this case, 'address' cannot be less than - the current address, nor greater than the current address + 255) - - Two-address formats (first address is destination, len is decimal 1-256): - ------------------- - - MVC address,address,len Move Characters - CLC address,address,len Compare Logical Characters - ALC address,address,len Add Logical Characters - SLC address,address,len Subtract Logical Characters - ED address,address,len Edit - ITC address,address,len Insert and Test Characters - AZ address,address,len Add Zoned Decimal - SZ address,address,len Subtract Zoned Decimal - - MNN address,address Move Numeric to Numeric - MNZ address,address Move Numeric to Zone - MZZ address,address Move Zone to Zone - MZN address,address Move Zone to Numeric - - I/O Format - ---------- - - In the I/O format, there are always 3 fields: - - da - Device Address 0-15 (decimal) - m - Modifier 0-1 - n - Function 0-7 - - The meaning of these is entirely defined by the device addressed. - - There may be an optional control byte, or an optional address (based - on the type of instruction). - - SNS da,m,n,address Sense I/O - LIO da,m,n,address Load I/O - TIO da,m,n,address Test I/O - - SIO da,m,n,cc Start I/O -- cc is a control byte - - APL da,m,n Advance Program Level - - -8 Device Programming. - - Note: On a model 15, interrupts are used for all devices. On - other models, interrupts are only used for the printer/keyboard. - - This is a summary of the DA, M, N, and CC codes for all supported - devices: - - 5471 Printer Keyboard - --------------------- - - The PKB has 2 visible indicators: Proceed and Request - Pending. It has a normal keyboard and 4 special keys: - Request, Return, End, and Cancel. - - SIO 1,0,0,XX Start Keyboard Operation, bit masks for XX are: - X'20': Request Pending Indicator On - X'10': Proceed Indicator On - X'04': Request Key Interrupts Enable (1) Disable (0) - X'02': Other Key Interrupts Enable (1) Disable (0) - X'01': Reset request key and other key interrupts - - SIO 1,1,0,XX Start Printer Operation, bit masks for XX are: - X'80': Start Printing - X'40': Start Carrier Return - X'04': Printer Interrupt Enable(1) or Disable (0) - X'01': Reset Printer Interrupt - - LIO 1,1,0,addr Load Printer Output Character - addr is address of low-order (highest numbered) - byte of two-byte field, and high-order byte - (that is, addr - 1) is loaded into output - register to print. Printing is done one character - at a time. - - SNS 1,0,1,addr Sense Status Bytes 0 and 1: - Byte 0 (leftmost) is the character typed in - in EBCDIC. - Byte 1 is status: - X'80': Request key interrupt pending - X'40': End or Cancel key interrupt pending - X'20': Cancel key pressed - X'10': End Key Pressed - X'08': Return or data key interrupt pending - X'04': Return key pressed - - SNS 1,0,3,addr Sense Status Bytes 2 and 3: returns 0000 in - this sim. - - 1442 Reader/Punch - ----------------- - - SIO 5,0,0,XX Feed Card without reading/punching - XX is stacker select for all functions: 0 = stacker - 1 (normal), 1 = stacker 2. - - SIO 5,0,1,XX Read Card - SIO 5,0,2,XX Punch and Feed - SIO 5,0,3,XX Read Column Binary - SIO 5,0,4,XX Punch with no feed - - TIO 5,0,0,addr Branch to addr if not ready or busy - TIO 5,0,2,addr Branch to addr if busy - TIO 5,0,5,addr (mod 15 only) branch if interrupt pending - - APL 5,0,0 Loop (or switch prog levels) if not ready/busy - APL 5,0,2 Loop (or switch) if busy - APL 5,0,5 Loop (or switch) if interrupt pending (mod 15 only) - - LIO 5,0,0,addr Load 2-byte field to Length Count Register - LIO 5,0,4,addr Load 2-byte field to Data Address Register - (DAR is incremented by a read/punch operation and must - be reset every card) - - SNS 5,0,1,addr Sense CE indicators (0000 returned in this sim) - SNS 5,0,2,addr Sense CE indicators (0000 returned in this sim) - SNS 5,0,3,addr Sense Status Indicators: (only simulated bits shown) - X'8000': Read Check - X'4000': Last Card - X'2000': Punch Check - X'1000': Data Overrun - X'0800': Not Ready - - - 1403 Printer - ------------ - - SIO 14,0,0,XX Line space XX lines (0-3 valid in XX) - SIO 14,0,2,XX Print a line space (0-3 valid in XX) - SIO 14,0,4,XX Skip Only (line number 1-112 in XX) - - SIO 14,0,6,XX Print and Skip (line number 0-112 in XX) - - TIO 14,0,0,addr Branch to addr if not ready - TIO 14,0,2,addr Branch to addr if buffer busy - TIO 14,0,3,addr Branch to addr if interrupt pending (mod 15 only) - TIO 14,0,4,addr Branch if carriage busy - TIO 14,0,6,addr Branch if printer busy - - APL 14,0,0 Loop (or switch prog levels) if not ready/check - APL 14,0,2 Loop (or switch) if buffer busy - APL 14,0,3 Loop (or switch) if interrupt pending (mod 15 only) - APL 14,0,4 Loop (or switch) if carriage busy - APL 14,0,6 Loop (or switch) if printer busy - - LIO 14,0,0,addr Load 1 byte to Forms Length Reg at addr-1 - LIO 14,0,4,addr Load 2 bytes to Chain Image Address Register - LIO 14,0,6,addr Load 2 bytes to Data Address Register - - SNS 14,0,0,addr Sense Character Count - SNS 14,0,4,addr Sense LPIAR (Image Address Register) - SNS 14,0,6,addr Sense LPDAR (data addres register) - - - 5444 Disk Drives - ---------------- - - Each drive has two disks (upper and lower), each disk - has two surfaces (upper and lower), each surface has - 24 256-byte sectors, sectors are number 0 thru 23 on - upper surface, 32 thru 55 on lower. - - d = drive, 0 is R1/F1, 1 is R2/F2 - s = surface, 0 = upper (removable), 1 = lower (fixed) - - The Control register points to the leftmost byte of a 4-byte - control field in memory with these bytes: - - F - Flag byte (not supported in this sim) - C - Cylinder Address (0-203) - S - Sector Number (0-23, or 32-55) in top 6 bits - N - Number of sectors minus 1 - - These have meaning for all operations except seek, seek uses - the fields differently. - - SIO 1d,s,0,XX Seek, XX not used, control field is used: - - F - not used - C - not used - S - high bit is head to be used 0-upper 1-lower - low bit is direction to move 0-back 1-forward - N - number of cylinders to move - - SIO 1d,s,1,XX Read, values of XX are as follows: - X'00': Read Data - X'01': Read Identifier (updates control field, no - data is read) - X'02': Read Data Diagnostic - X'03': Verify (does not read, but checks) - - SIO 1d,s,2,XX Write, values of XX are as follows: - X'00': Write Data - X'01': Write Identifier (24 sectors with byte at - data address register) - - SIO 1d,s,3,XX Scan. All 256 bytes in memory at data - address register are compared to disk - sectors on current track, except those - bytes of X'FF' are not compared. Values of - XX are: - - X'00': Scan Equal - X'01': Scan Low or Equal - X'02': Scan High or Equal - - LIO 1d,0,4,addr Load Data Address Register - LIO 1d,0,6,addr Load Disk Control Address Register - - TIO 1d,0,0,addr Branch if not ready/unit check - TIO 1d,0,2,addr Branch if busy - TIO 1d,0,4,addr Branch if Scan Found - - APL 1d,0,0 Loop if not ready/unit check - APL 1d,0,2 Loop if busy - APL 1d,0,4 Loop if scan found - - SNS 1d,0,2,addr Sense Status Bytes 0 and 1: (simulated - bits only are shown, otehrs are 0): - X'1000': equipment check - X'0800': data check - X'0400': No record found - X'0100': Seek Check (past cyl 203) - X'0080': Scan equal Hit - X'0040': Cylinder 0 - X'0020': End of Cylinder - X'0010': Seek Busy - SNS 1d,0,3,addr Sense bytes 2 and 3 (0000 in this sim) - SNS 1d,0,4,addr Sense Data Address Register - SNS 1d,0,6,addr Sense Control Address Register - - - - diff --git a/SDS/sds_cpu.c b/SDS/sds_cpu.c deleted file mode 100644 index 2489cd13..00000000 --- a/SDS/sds_cpu.c +++ /dev/null @@ -1,1282 +0,0 @@ -/* sds_cpu.c: SDS 940 CPU simulator - - Copyright (c) 2001-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - The system state for the SDS 940 is: - - A<0:23> A register - B<0:23> B register - X<0:23> X (index) register - OV overflow indicator - P<0:13> program counter - nml_mode compatible (1) vs 940 (0) mode - usr_mode user (1) vs monitor (0) mode - RL1<0:23> user map low - RL2<0:23> user map high - RL4<12:23> monitor map high - EM2<0:2> memory extension, block 2 - EM3<0:2> memory extension, block 3 - bpt breakpoint switches - - cpu central processor - rtc real time clock - - 01-Mar-03 RMS Added SET/SHOW RTC FREQ support -*/ - -/* The SDS 940 has three instruction format -- memory reference, register change, - and I/O. The memory reference format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 23 23 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | U| X| P| opcode |IN| address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - U force user mode addressing (monitor mode only) - X indexed - P opcode is a programmed operator - opcode opcode - IN indirect addressing - address virtual address - - Virtual addresses are 14b. Depending on the operating mode (normal, user, - or monitor), virtual addresses are translated to 15b or 16b physical addresses. - - normal virtual [000000:017777] are unmapped - EM2 and EM3 extend virtual [020000:037777] to 15b - user RL1 and RL2 map virtual [000000:037777] to 16b - monitor virtual [000000:017777] are unmapped - EM2 extends virtual [020000:027777] to 15b - RL4 maps virtual [030000:037777] to 16b - - The register change format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 23 23 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0| m| 0| opcode | microcoded register change instruction | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The I/O format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 23 23 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0|CH| 0| opcode |mode | I/O function | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -*/ - -/* This routine is the instruction decode routine for the SDS 940. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - breakpoint encountered - invalid instruction and stop_invins flag set - invalid I/O device and stop_invdev flag set - invalid I/O operation and stop_inviop flag set - I/O error in I/O simulator - indirect loop exceeding limit - EXU loop exceeding limit - mapping exception in interrupt or trap instruction - - 2. Interrupts. The interrupt structure consists of the following: - - int_req interrupt requests (low bit reserved) - api_lvl active interrupt levels - int_reqhi highest interrupt request - api_lvlhi highest interrupt service (0 if none) - ion interrupt enable - ion_defer interrupt defer (one instruction) - - 3. Channels. The SDS 940 has a channel-based I/O structure. Each - channel is represented by a set of registers. Channels test the - I/O transfer requests from devices, which are kept in xfr_req. - - 4. Non-existent memory. On the SDS 940, reads to non-existent memory - return zero, and writes are ignored. In the simulator, the - largest possible memory is instantiated and initialized to zero. - Thus, only writes need be checked against actual memory size. - - 5. Adding I/O devices. These modules must be modified: - - sds_defs.h add interrupt, transfer, and alert definitions - sds_io.c add alert dispatches aldisp - sds_sys.c add pointer to data structures to sim_devices -*/ - -#include "sds_defs.h" - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = pc -#define UNIT_V_MSIZE (UNIT_V_GENIE + 1) /* dummy mask */ -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -uint32 M[MAXMEMSIZE] = { 0 }; /* memory */ -uint32 A, B, X; /* registers */ -uint32 P; /* program counter */ -uint32 OV; /* overflow */ -uint32 xfr_req = 0; /* xfr req */ -uint32 ion = 0; /* int enable */ -uint32 ion_defer = 0; /* int defer */ -uint32 int_req = 0; /* int requests */ -uint32 int_reqhi = 0; /* highest int request */ -uint32 api_lvl = 0; /* api active */ -uint32 api_lvlhi = 0; /* highest api active */ -t_bool chan_req; /* chan request */ -uint32 nml_mode = 1; /* normal mode */ -uint32 usr_mode = 0; /* user mode */ -uint32 mon_usr_trap = 0; /* mon-user trap */ -uint32 EM2 = 2, EM3 = 3; /* extension registers */ -uint32 RL1, RL2, RL4; /* relocation maps */ -uint32 bpt; /* breakpoint switches */ -uint32 alert; /* alert dispatch */ -uint32 em2_dyn, em3_dyn; /* extensions, dynamic */ -uint32 usr_map[8]; /* user map, dynamic */ -uint32 mon_map[8]; /* mon map, dynamic */ -int32 ind_lim = 32; /* indirect limit */ -int32 exu_lim = 32; /* EXU limit */ -int32 cpu_genie = 0; /* Genie flag */ -int32 cpu_astop = 0; /* address stop */ -int32 stop_invins = 1; /* stop inv inst */ -int32 stop_invdev = 1; /* stop inv dev */ -int32 stop_inviop = 1; /* stop inv io op */ -uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -int32 rtc_pie = 0; /* rtc pulse ie */ -int32 rtc_tps = 60; /* rtc ticks/sec */ - -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern UNIT mux_unit; - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_type (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat Ea (uint32 wd, uint32 *va); -t_stat EaSh (uint32 wd, uint32 *va); -t_stat Read (uint32 va, uint32 *dat); -t_stat Write (uint32 va, uint32 dat); -void set_dyn_map (void); -uint32 api_findreq (void); -void api_dismiss (void); -uint32 Add24 (uint32 s1, uint32 s2, uint32 cin); -uint32 AddM24 (uint32 s1, uint32 s2); -void Mul48 (uint32 mplc, uint32 mplr); -void Div48 (uint32 dvdh, uint32 dvdl, uint32 dvr); -void RotR48 (uint32 sc); -void ShfR48 (uint32 sc, uint32 sgn); -t_stat one_inst (uint32 inst, uint32 pc, uint32 mode); -t_stat rtc_inst (uint32 inst); -t_stat rtc_svc (UNIT *uptr); -t_stat rtc_reset (DEVICE *dptr); -t_stat rtc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat rtc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc); - -extern t_bool io_init (void); -extern t_stat op_wyim (uint32 inst, uint32 *dat); -extern t_stat op_miwy (uint32 inst, uint32 dat); -extern t_stat op_pin (uint32 *dat); -extern t_stat op_pot (uint32 dat); -extern t_stat op_eomd (uint32 inst); -extern t_stat op_sks (uint32 inst, uint32 *skp); - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifiers list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, MAXMEMSIZE) }; - -REG cpu_reg[] = { - { ORDATA (P, P, 14) }, - { ORDATA (A, A, 24) }, - { ORDATA (B, B, 24) }, - { ORDATA (X, X, 24) }, - { FLDATA (OV, OV, 0) }, - { ORDATA (EM2, EM2, 3) }, - { ORDATA (EM3, EM3, 3) }, - { ORDATA (RL1, RL1, 24) }, - { ORDATA (RL2, RL2, 24) }, - { ORDATA (RL4, RL4, 12) }, - { FLDATA (NML, nml_mode, 0) }, - { FLDATA (USR, usr_mode, 0) }, - { FLDATA (MONUSR, mon_usr_trap, 0) }, - { FLDATA (ION, ion, 0) }, - { FLDATA (INTDEF, ion_defer, 0) }, - { ORDATA (INTREQ, int_req, 32) }, - { ORDATA (APILVL, api_lvl, 32) }, - { DRDATA (INTRHI, int_reqhi, 5) }, - { DRDATA (APILHI, api_lvlhi, 5), REG_RO }, - { ORDATA (XFRREQ, xfr_req, 32) }, - { FLDATA (BPT1, bpt, 3) }, - { FLDATA (BPT2, bpt, 2) }, - { FLDATA (BPT3, bpt, 1) }, - { FLDATA (BPT4, bpt, 0) }, - { ORDATA (ALERT, alert, 6) }, - { FLDATA (STOP_INVINS, stop_invins, 0) }, - { FLDATA (STOP_INVDEV, stop_invdev, 0) }, - { FLDATA (STOP_INVIOP, stop_inviop, 0) }, - { DRDATA (INDLIM, ind_lim, 8), REG_NZ+PV_LEFT }, - { DRDATA (EXULIM, exu_lim, 8), REG_NZ+PV_LEFT }, - { BRDATA (PCQ, pcq, 8, 14, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_GENIE, 0, "standard peripherals", "SDS", &cpu_set_type }, - { UNIT_GENIE, UNIT_GENIE, "Genie peripherals", "GENIE", &cpu_set_type }, - { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, - { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, - { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size }, - { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, 16, 1, 8, 24, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL, - NULL, 0 }; - -/* Clock data structures - - rtc_dev RTC device descriptor - rtc_unit RTC unit - rtc_reg RTC register list -*/ - -UNIT rtc_unit = { UDATA (&rtc_svc, 0, 0), 16000 }; - -REG rtc_reg[] = { - { FLDATA (PIE, rtc_pie, 0) }, - { DRDATA (TIME, rtc_unit.wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS, rtc_tps, 8), PV_LEFT + REG_HRO }, - { NULL } }; - -MTAB rtc_mod[] = { - { MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ", - &rtc_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ", - &rtc_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL, - NULL, &rtc_show_freq, NULL }, - { 0 } }; - -DEVICE rtc_dev = { - "RTC", &rtc_unit, rtc_reg, rtc_mod, - 1, 8, 8, 1, 8, 8, - NULL, NULL, &rtc_reset, - NULL, NULL, NULL }; - -/* Interrupt tables */ - -static const uint32 api_mask[32] = { - 0xFFFFFFFE, 0xFFFFFFFC, 0xFFFFFFF8, 0xFFFFFFF0, - 0xFFFFFFE0, 0xFFFFFFC0, 0xFFFFFF80, 0xFFFFFF00, - 0xFFFFFE00, 0xFFFFFC00, 0xFFFFF800, 0xFFFFF000, - 0xFFFFE000, 0xFFFFC000, 0xFFFF8000, 0xFFFF0000, - 0xFFFE0000, 0xFFFC0000, 0xFFF80000, 0xFFF00000, - 0xFFE00000, 0xFFC00000, 0xFF800000, 0xFF000000, - 0xFE000000, 0xFC000000, 0xF8000000, 0xF0000000, - 0xE0000000, 0xC0000000, 0x80000000, 0x00000000 }; - -static const uint32 int_vec[32] = { - 0, 0, 0, 0, - VEC_FORK, VEC_DRM, VEC_MUXCF,VEC_MUXCO, - VEC_MUXT, VEC_MUXR, VEC_HEOR, VEC_HZWC, - VEC_GEOR, VEC_GZWC, VEC_FEOR, VEC_FZWC, - VEC_EEOR, VEC_EZWC, VEC_DEOR, VEC_DZWC, - VEC_CEOR, VEC_CZWC, VEC_WEOR, VEC_YEOR, - VEC_WZWC, VEC_YZWC, VEC_RTCP, VEC_RTCS, - VEC_IPAR, VEC_CPAR, VEC_PWRF, VEC_PWRO }; - -t_stat sim_instr (void) -{ -extern int32 sim_interval; -uint32 inst, tinst, pa, save_P, save_mode; -t_stat reason, tr; - -/* Restore register state */ - -if (io_init ()) return SCPE_STOP; /* init IO; conflict? */ -reason = 0; -xfr_req = xfr_req & ~1; /* <0> reserved */ -int_req = int_req & ~1; /* <0> reserved */ -api_lvl = api_lvl & ~1; /* <0> reserved */ -set_dyn_map (); /* set up mapping */ -int_reqhi = api_findreq (); /* recalc int req */ -chan_req = chan_testact (); /* recalc chan act */ -sim_rtcn_init (rtc_unit.wait, TMR_RTC); /* init calibration */ -sim_rtcn_init (mux_unit.wait, TMR_MUX); /* init calibration */ - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ - -if (cpu_astop) { /* debug stop? */ - cpu_astop = 0; - return SCPE_STOP; } - -if (sim_interval <= 0) { /* event queue? */ - if (reason = sim_process_event ()) break; /* process */ - int_reqhi = api_findreq (); /* recalc int req */ - chan_req = chan_testact (); /* recalc chan act */ - } - -if (chan_req) { /* channel request? */ - if (reason = chan_process ()) break; /* process */ - int_reqhi = api_findreq (); /* recalc int req */ - chan_req = chan_testact (); /* recalc chan act */ - } - -sim_interval = sim_interval - 1; /* count down */ -if (ion && !ion_defer && int_reqhi) { /* int request? */ - pa = int_vec[int_reqhi]; /* get vector */ - if (pa == 0) { /* bad value? */ - reason = STOP_ILLVEC; - break; } - tinst = ReadP (pa); /* get inst */ - save_mode = usr_mode; /* save mode */ - usr_mode = 0; /* switch to mon */ - if (pa != VEC_RTCP) { /* normal intr? */ - tr = one_inst (tinst, P, save_mode); /* exec intr inst */ - if (tr) { /* stop code? */ - usr_mode = save_mode; /* restore mode */ - reason = (tr > 0)? tr: STOP_MMINT; - break; } - api_lvl = api_lvl | (1u << int_reqhi); /* set level active */ - api_lvlhi = int_reqhi; } /* elevate api */ - else { /* clock intr */ - tr = rtc_inst (tinst); /* exec RTC inst */ - usr_mode = save_mode; /* restore mode */ - if (tr) { /* stop code? */ - reason = (tr > 0)? tr: STOP_MMINT; - break; } - int_req = int_req & ~INT_RTCP; } /* clr clkp intr */ - int_reqhi = api_findreq (); /* recalc int req */ - } -else { /* normal instr */ - if (sim_brk_summ && sim_brk_test (P, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - reason = Read (save_P = P, &inst); /* get instr */ - P = (P + 1) & VA_MASK; /* incr PC */ - if (reason == SCPE_OK) { /* fetch ok? */ - ion_defer = 0; /* clear ion */ - reason = one_inst (inst, save_P, usr_mode); /* exec inst */ - if (reason > 0) { /* stop code? */ - if (reason != STOP_HALT) P = save_P; - if (reason == STOP_IONRDY) reason = 0; } - } /* end if r == 0 */ - if (reason < 0) { /* mm (fet or ex)? */ - pa = -reason; /* get vector */ - reason = 0; /* defang */ - tinst = ReadP (pa); /* get inst */ - if (I_GETOP (tinst) != BRM) { /* not BRM? */ - reason = STOP_TRPINS; /* fatal err */ - break; } - save_mode = usr_mode; /* save mode */ - usr_mode = 0; /* switch to mon */ - mon_usr_trap = 0; - tr = one_inst (tinst, save_P, save_mode); /* trap inst */ - if (tr) { /* stop code? */ - usr_mode = save_mode; /* restore mode */ - P = save_P; /* restore PC */ - reason = (tr > 0)? tr: STOP_MMTRP; - break; } - } /* end if reason */ - } /* end else int */ -} /* end while */ - -/* Simulation halted */ - -pcq_r->qptr = pcq_p; /* update pc q ptr */ -return reason; -} - -/* Simulate one instruction */ - -t_stat one_inst (uint32 inst, uint32 pc, uint32 mode) -{ -uint32 op, shf_op, va, dat; -uint32 old_A, old_B, old_X; -int32 i, exu_cnt, sc; -t_stat r; - -exu_cnt = 0; /* init EXU count */ -EXU_LOOP: -op = I_GETOP (inst); /* get opcode */ -if (inst & I_POP) { /* POP? */ - dat = (EM3 << 18) | (EM2 << 15) | I_IND | pc; /* data to save */ - if (nml_mode) { /* normal mode? */ - dat = (OV << 23) | dat; /* ov in <0> */ - WriteP (0, dat); } - else if (usr_mode) { /* user mode? */ - if (inst & I_USR) { /* SYSPOP? */ - dat = I_USR | (OV << 21) | dat; /* ov in <2> */ - WriteP (0, dat); - usr_mode = 0; } /* set mon mode */ - else { /* normal POP */ - dat = (OV << 23) | dat; /* ov in <0> */ - if (r = Write (0, dat)) return r; } } - else { /* mon mode */ - dat = (OV << 21) | dat; /* ov in <2> */ - WriteP (0, dat); } /* store return */ - PCQ_ENTRY; /* save PC */ - P = 0100 | op; /* new PC */ - OV = 0; /* clear ovflo */ - return SCPE_OK; } /* end POP */ -switch (op) { /* case on opcode */ - -/* Loads and stores */ - -case LDA: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &A)) return r; /* get operand */ - break; -case LDB: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &B)) return r; /* get operand */ - break; -case LDX: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &X)) return r; /* get operand */ - break; -case STA: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Write (va, A)) return r; /* write operand */ - break; -case STB: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Write (va, B)) return r; /* write operand */ - break; -case STX: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Write (va, X)) return r; /* write operand */ - break; -case EAX: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (nml_mode || usr_mode) /* normal or user? */ - X = (X & ~VA_MASK) | (va & VA_MASK); /* only 14b */ - else X = (X & ~XVA_MASK) | (va & XVA_MASK); /* mon, 15b */ - break; -case XMA: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - if (r = Write (va, A)) return r; /* write A */ - A = dat; /* load A */ - break; - -/* Arithmetic and logical */ - -case ADD: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - A = Add24 (A, dat, 0); /* add */ - break; -case ADC: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - OV = 0; /* clear overflow */ - A = Add24 (A, dat, X >> 23); /* add with carry */ - break; -case SUB: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - A = Add24 (A, dat ^ DMASK, 1); /* subtract */ - break; -case SUC: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - OV = 0; /* clear overflow */ - A = Add24 (A, dat ^ DMASK, X >> 23); /* sub with carry */ - break; -case ADM: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - dat = AddM24 (dat, A); /* mem + A */ - if (r = Write (va, dat)) return r; /* rewrite */ - break; -case MIN: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - dat = AddM24 (dat, 1); /* mem + 1 */ - if (r = Write (va, dat)) return r; /* rewrite */ - break; -case MUL: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - Mul48 (A, dat); /* multiply */ - break; -case DIV: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - Div48 (A, B, dat); /* divide */ - break; -case ETR: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - A = A & dat; /* and */ - break; -case MRG: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - A = A | dat; /* or */ - break; -case EOR: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - A = A ^ dat; /* xor */ - break; - -/* Skips */ - -case SKE: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - if (A == dat) P = (P + 1) & VA_MASK; /* if A = op, skip */ - break; -case SKG: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - if (SXT (A) > SXT (dat)) P = (P + 1) & VA_MASK; /* if A > op, skip */ - break; -case SKM: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - if (((A ^ dat) & B) == 0) P = (P + 1) & VA_MASK; /* if A = op masked */ - break; -case SKA: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - if ((A & dat) == 0) P = (P + 1) & VA_MASK; /* if !(A & op), skip */ - break; -case SKB: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - if ((B & dat) == 0) P = (P + 1) & VA_MASK; /* if !(B & op), skip */ - break; -case SKN: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - if (dat & SIGN) P = (P + 1) & VA_MASK; /* if op < 0, skip */ - break; -case SKR: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - dat = AddM24 (dat, DMASK); /* decr operand */ - if (r = Write (va, dat)) return r; /* rewrite operand */ - if (dat & SIGN) P = (P + 1) & VA_MASK; /* if op < 0, skip */ - break; -case SKD: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - if (SXT_EXP (B) < SXT_EXP (dat)) { /* B < dat? */ - X = (dat - B) & DMASK; /* X = dat - B */ - P = (P + 1) & VA_MASK; } /* skip */ - else X = (B - dat) & DMASK; /* X = B - dat */ - break; - -/* Control */ - -case NOP: - break; -case HLT: - if (!nml_mode && usr_mode) return MM_PRVINS; /* priv inst */ - return STOP_HALT; /* halt CPU */ -case EXU: - exu_cnt = exu_cnt + 1; /* count chained EXU */ - if (exu_cnt > exu_lim) return STOP_EXULIM; /* too many? */ - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - inst = dat; - goto EXU_LOOP; -case BRU: - if (nml_mode && (inst & I_IND)) api_dismiss (); /* normal BRU*, dism */ - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* test dest access */ - PCQ_ENTRY; - P = va & VA_MASK; /* branch */ - break; -case BRX: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - X = (X + 1) & DMASK; /* incr X */ - if (X & I_IND) { /* bit 9 set? */ - if (r = Read (va, &dat)) return r; /* test dest access */ - PCQ_ENTRY; - P = va & VA_MASK; } /* branch */ - break; -case BRM: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - dat = (EM3 << 18) | (EM2 << 15) | pc; /* form return word */ - if (!nml_mode && !usr_mode) /* monitor mode? */ - dat = dat | (mode << 23) | (OV << 21); - else dat = dat | (OV << 23); /* normal or user */ - if (r = Write (va, dat)) return r; /* write ret word */ - PCQ_ENTRY; - P = (va + 1) & VA_MASK; /* branch */ - break; -case BRR: - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - PCQ_ENTRY; - P = (dat + 1) & VA_MASK; /* branch */ - if (!nml_mode && !usr_mode) { /* monitor mode? */ - OV = OV | ((dat >> 21) & 1); /* restore OV */ - if ((va & VA_USR) | (dat & I_USR)) { /* mode change? */ - usr_mode = 1; - if (mon_usr_trap) return MM_MONUSR; } } - else OV = OV | ((dat >> 23) & 1); /* restore OV */ - break; -case BRI: - if (!nml_mode && usr_mode) return MM_PRVINS; /* priv inst */ - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - api_dismiss (); /* dismiss hi api */ - PCQ_ENTRY; - P = dat & VA_MASK; /* branch */ - if (!nml_mode) { /* monitor mode? */ - OV = (dat >> 21) & 1; /* restore OV */ - if ((va & VA_USR) | (dat & I_USR)) { /* mode change? */ - usr_mode = 1; - if (mon_usr_trap) return MM_MONUSR; } } - else OV = (dat >> 23) & 1; /* restore OV */ - break; - -/* Register change (microprogrammed) */ - -case RCH: - old_A = A; /* save orig reg */ - old_B = B; - old_X = X; - if (inst & 000001211) { /* A change? */ - if (inst & 01000) dat = (~old_A + 1) & DMASK; /* CNA */ - else dat = 0; - if (inst & 00200) dat = dat | old_X; - if (inst & 00010) dat = dat | old_B; - if (inst & 00100) A = (A & ~EXPMASK) | (dat & EXPMASK); - else A = dat; } - if (inst & 000000046) { /* B change? */ - if (inst & 00040) dat = old_X; - else dat = 0; - if (inst & 00004) dat = dat | old_A; - if (inst & 00100) B = (B & ~EXPMASK) | (dat & EXPMASK); - else B = dat; } - if (inst & 020000420) { /* X change? */ - if (inst & 00400) dat = old_A; - else dat = 0; - if (inst & 00020) dat = dat | old_B; - if (inst & 00100) X = SXT_EXP (dat) & DMASK; - else X = dat; } - break; - -/* Overflow instruction */ - -case OVF: - if ((inst & 0100) & OV) P = (P + 1) & VA_MASK; - if (inst & 0001) OV = 0; - if ((inst & 0010) && (((X >> 1) ^ X) & EXPS)) OV = 1; - break; - -/* Shifts */ - -case RSH: - if (r = EaSh (inst, &va)) return r; /* decode eff addr */ - shf_op = I_GETSHFOP (va); /* get eff op */ - sc = va & I_SHFMSK; /* get eff count */ - switch (shf_op) { /* case on sub-op */ - case 00: /* right arithmetic */ - if (sc) ShfR48 (sc, (A & SIGN)? DMASK: 0); - break; - case 04: /* right cycle */ - sc = sc % 48; /* mod 48 */ - if (sc) RotR48 (sc); - break; - case 05: /* right logical */ - if (sc) ShfR48 (sc, 0); - break; - default: - CRETINS; /* invalid inst */ - break; } /* end case shf op */ - break; - -case LSH: - if (r = EaSh (inst, &va)) return r; /* decode eff addr */ - shf_op = I_GETSHFOP (va); /* get eff op */ - sc = va & I_SHFMSK; /* get eff count */ - switch (shf_op) { /* case on sub-op */ - case 00: /* left arithmetic */ - dat = A; /* save sign */ - if (sc > 48) sc = 48; - for (i = 0; i < sc; i++) { /* loop */ - A = ((A << 1) | (B >> 23)) & DMASK; - B = (B << 1) & DMASK; - if ((A ^ dat) & SIGN) OV = 1; } - break; - case 02: /* normalize */ - if (sc > 48) sc = 48; - for (i = 0; i < sc; i++) { /* until max count */ - if ((A ^ (A << 1)) & SIGN) break; - A = ((A << 1) | (B >> 23)) & DMASK; - B = (B << 1) & DMASK; } - X = (X - i) & DMASK; - break; - case 04: /* left cycle */ - sc = sc % 48; /* mod 48 */ - if (sc) RotR48 (48 - sc); /* rotate */ - break; - case 06: /* cycle normalize */ - if (sc > 48) sc = 48; - for (i = 0; i < sc; i++) { /* until max count */ - if ((A ^ (A << 1)) & SIGN) break; - old_A = A; /* cyclic shift */ - A = ((A << 1) | (B >> 23)) & DMASK; - B = ((B << 1) | (old_A >> 23)) & DMASK; } - X = (X - i) & DMASK; - break; - default: - CRETINS; /* invalid inst */ - break; } /* end case shf op */ - break; - -/* I/O instructions */ - -case MIW: case MIY: - if (!nml_mode && usr_mode) return MM_PRVINS; /* priv inst */ - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - if (r = op_miwy (inst, dat)) return r; /* process inst */ - int_reqhi = api_findreq (); /* recalc int req */ - chan_req = chan_testact (); /* recalc chan act */ - break; -case WIM: case YIM: - if (!nml_mode && usr_mode) return MM_PRVINS; /* priv inst */ - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = op_wyim (inst, &dat)) return r; /* process inst */ - if (r = Write (va, dat)) return r; /* write result */ - int_reqhi = api_findreq (); /* recalc int req */ - chan_req = chan_testact (); /* recalc chan act */ - break; -case EOM: case EOD: - if (!nml_mode && usr_mode) return MM_PRVINS; /* priv inst */ - if (r = op_eomd (inst)) return r; /* process inst */ - int_reqhi = api_findreq (); /* recalc int req */ - chan_req = chan_testact (); /* recalc chan act */ - ion_defer = 1; - break; -case POT: - if (!nml_mode && usr_mode) return MM_PRVINS; /* priv inst */ - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = Read (va, &dat)) return r; /* get operand */ - if (r = op_pot (dat)) return r; /* process inst */ - int_reqhi = api_findreq (); /* recalc int req */ - chan_req = chan_testact (); /* recalc chan act */ - break; -case PIN: - if (!nml_mode && usr_mode) return MM_PRVINS; /* priv inst */ - if (r = Ea (inst, &va)) return r; /* decode eff addr */ - if (r = op_pin (&dat)) return r; /* process inst */ - if (r = Write (va, dat)) return r; /* write result */ - int_reqhi = api_findreq (); /* recalc int req */ - chan_req = chan_testact (); /* recalc chan act */ - break; -case SKS: - if (!nml_mode && usr_mode) return MM_PRVINS; /* priv inst */ - if (r = op_sks (inst, &dat)) return r; /* process inst */ - if (dat) P = (P + 1) & VA_MASK; - break; - -default: - if (!nml_mode && usr_mode) return MM_PRVINS; /* usr? priv viol */ - CRETINS; /* invalid inst */ - break; } -return SCPE_OK; -} - -/* Effective address calculation */ - -t_stat Ea (uint32 inst, uint32 *addr) -{ -int32 i; -uint32 wd = inst; /* homeable */ -uint32 va = wd & XVA_MASK; /* initial va */ -t_stat r; - -for (i = 0; i < ind_lim; i++) { /* count indirects */ - if (wd & I_IDX) va = (va & VA_USR) | ((va + X) & VA_MASK); - *addr = va; - if ((wd & I_IND) == 0) return SCPE_OK; /* indirect? */ - if (r = Read (va, &wd)) return r; /* read ind; fails? */ - va = (va & VA_USR) | (wd & XVA_MASK); - } -return STOP_INDLIM; /* too many indirects */ -} - -/* Effective address calculation for shifts - direct indexing is 9b */ - -t_stat EaSh (uint32 inst, uint32 *addr) -{ -int32 i; -uint32 wd = inst; /* homeable */ -uint32 va = wd & XVA_MASK; /* initial va */ -t_stat r; - -for (i = 0; i < ind_lim; i++) { /* count indirects */ - if ((wd & I_IND) == 0) { /* end of ind chain? */ - if (wd & I_IDX) *addr = (va & (VA_MASK & ~I_SHFMSK)) | - ((va + X) & I_SHFMSK); /* 9b indexing */ - else *addr = va & VA_MASK; - return SCPE_OK; } - if (wd & I_IDX) va = (va & VA_USR) | ((va + X) & VA_MASK); - if (r = Read (va, &wd)) return r; /* read ind; fails? */ - va = (va & VA_USR) | (wd & XVA_MASK); - } -return STOP_INDLIM; /* too many indirects */ -} - -/* Read word from virtual address */ - -t_stat Read (uint32 va, uint32 *dat) -{ -uint32 pgn, map, pa; - -if (nml_mode) { /* normal? */ - va = va & VA_MASK; /* ignore user */ - if (va < 020000) pa = va; /* first 8K: 1 for 1 */ - else if (va < 030000) pa = va + em2_dyn; /* next 4K: ext EM2 */ - else pa = va + em3_dyn; } /* next 4K: ext EM3 */ -else if (usr_mode || (va & VA_USR)) { /* user mapping? */ - pgn = VA_GETPN (va); /* get page no */ - map = usr_map[pgn]; /* get map entry */ - if (map == MAP_PROT) return MM_NOACC; /* prot? no access */ - pa = (map & ~MAP_PROT) | (va & VA_POFF); } /* map address */ -else { pgn = VA_GETPN (va); /* mon, get page no */ - map = mon_map[pgn]; /* get map entry */ - if (map & MAP_PROT) return MM_NOACC; /* prot? no access */ - pa = map | (va & VA_POFF); } /* map address */ -*dat = M[pa]; /* return word */ -return SCPE_OK; -} - -/* Write word to virtual address */ - -t_stat Write (uint32 va, uint32 dat) -{ -uint32 pgn, map, pa; - -if (nml_mode) { /* normal? */ - va = va & VA_MASK; /* ignore user */ - if (va < 020000) pa = va; /* first 8K: 1 for 1 */ - else if (va < 030000) pa = va + em2_dyn; /* next 4K: ext EM2 */ - else pa = va + em3_dyn; } /* next 4K: ext EM3 */ -else if (usr_mode || (va & VA_USR)) { /* user mapping? */ - pgn = VA_GETPN (va); /* get page no */ - map = usr_map[pgn]; /* get map entry */ - if (map & MAP_PROT) { /* protected page? */ - if (map == MAP_PROT) return MM_NOACC; /* zero? no access */ - else return MM_WRITE; } /* else, write prot */ - pa = map | (va & VA_POFF); } /* map address */ -else { pgn = VA_GETPN (va); /* mon, get page no */ - map = mon_map[pgn]; /* get map entry */ - if (map & MAP_PROT) return MM_NOACC; /* prot? no access */ - pa = map | (va & VA_POFF); } /* map address */ -if (MEM_ADDR_OK (pa)) M[pa] = dat; -return SCPE_OK; -} - -/* Relocate addr for console access */ - -uint32 RelocC (int32 va, int32 sw) -{ -uint32 nml = nml_mode, usr = usr_mode; -uint32 pa, pgn, map; - -if (sw & SWMASK ('N')) nml = 1; /* -n: normal */ -else if (sw & SWMASK ('X')) nml = usr = 0; /* -x: mon */ -else if (sw & SWMASK ('U')) nml = 0, usr = 1; /* -u: user */ -else if (!(sw & SWMASK ('V'))) return va; /* -v: curr */ -set_dyn_map (); -if (nml) { /* normal? */ - if (va < 020000) pa = va; /* first 8K: 1 for 1 */ - else if (va < 030000) pa = va + em2_dyn; /* next 4K: ext EM2 */ - else pa = va + em3_dyn; } /* next 4K: ext EM3 */ -else { pgn = VA_GETPN (va); /* get page no */ - map = usr? usr_map[pgn]: mon_map[pgn]; /* get map entry */ - if (map == MAP_PROT) return MAXMEMSIZE + 1; /* no access page? */ - pa = (map & ~MAP_PROT) | (va & VA_POFF); } /* map address */ -return pa; -} - -/* Arithmetic routines */ - -uint32 Add24 (uint32 s1, uint32 s2, uint32 cin) -{ -uint32 t = s1 + s2 + cin; /* add with carry in */ -if (t > DMASK) X = X | SIGN; /* carry to X<0> */ -else X = X & ~SIGN; -if (((s1 ^ ~s2) & (s1 ^ t)) & SIGN) OV = 1; /* overflow */ -return t & DMASK; -} - -uint32 AddM24 (uint32 s1, uint32 s2) -{ -uint32 t = s1 + s2; /* add */ -if (((s1 ^ ~s2) & (s1 ^ t)) & SIGN) OV = 1; /* overflow */ -return t & DMASK; -} - -void Mul48 (uint32 s1, uint32 s2) -{ -uint32 a = ABS (s1); -uint32 b = ABS (s2); -uint32 hi, md, lo, t, u; - -if ((a == 0) || (b == 0)) { /* ops zero? */ - A = B = 0; - return; } -t = a >> 12; /* split op1 */ -a = a & 07777; -u = b >> 12; /* split op2 */ -b = b & 07777; -md = (a * u) + (b * t); /* cross product */ -lo = (a * b) + ((md & 07777) << 12); /* low result */ -hi = (t * u) + (md >> 12) + (lo >> 24); /* hi result */ -A = ((hi << 1) & DMASK) | ((lo & DMASK) >> 23); -B = (lo << 1) & DMASK; -if ((s1 ^ s2) & SIGN) { - B = ((B ^ DMASK) + 1) & DMASK; - A = ((A ^ DMASK) + (B == 0)) & DMASK; } -else if (A & SIGN) OV = 1; -return; -} - -/* Divide - the SDS 940 uses a non-restoring divide. The algorithm - runs even for overflow cases. Hence it must be emulated precisely - to give the right answers for diagnostics. If the dividend is - negative, AB are 2's complemented starting at B<22>, and B<23> - is unchanged. */ - -void Div48 (uint32 ar, uint32 br, uint32 m) -{ -int32 i; -uint32 quo = 0; /* quotient */ -uint32 dvdh = ar, dvdl = br; /* dividend */ -uint32 dvr = ABS (m); /* make dvr pos */ - -if (TSTS (dvdh)) { /* dvd < 0? */ - dvdl = (((dvdl ^ DMASK) + 2) & (DMASK & ~1)) | /* 23b negate */ - (dvdl & 1); /* low bit unch */ - dvdh = ((dvdh ^ DMASK) + (dvdl <= 1)) & DMASK; } -if ((dvdh > dvr) || /* divide fail? */ - ((dvdh == dvr) && dvdl) || - ((dvdh == dvr) && !TSTS (ar ^ m))) OV = 1; -dvdh = (dvdh - dvr) & DMASK; /* initial sub */ -for (i = 0; i < 23; i++) { /* 23 iterations */ - quo = (quo << 1) | ((dvdh >> 23) ^ 1); /* quo bit = ~sign */ - dvdh = ((dvdh << 1) | (dvdl >> 23)) & DMASK; /* shift divd */ - dvdl = (dvdl << 1) & DMASK; - if (quo & 1) /* test ~sign */ - dvdh = (dvdh - dvr) & DMASK; /* sign was +, sub */ - else dvdh = (dvdh + dvr) & DMASK; } /* sign was -, add */ -quo = quo << 1; /* shift quo */ -if (dvdh & SIGN) dvdh = (dvdh + dvr) & DMASK; /* last op -? restore */ -else quo = quo | 1; /* +, set quo bit */ -if (TSTS (ar ^ m)) A = NEG (quo); /* sign of quo */ -else A = quo; /* A = quo */ -if (TSTS (ar)) B = NEG (dvdh); /* sign of rem */ -else B = dvdh; /* B = rem */ -return; -} - -void RotR48 (uint32 sc) -{ -uint32 t = A; - -if (sc >= 24) { - sc = sc - 24; - A = ((B >> sc) | (A << (24 - sc))) & DMASK; - B = ((t >> sc) | (B << (24 - sc))) & DMASK; } -else { A = ((A >> sc) | (B << (24 - sc))) & DMASK; - B = ((B >> sc) | (t << (24 - sc))) & DMASK; } -return; -} - -void ShfR48 (uint32 sc, uint32 sgn) -{ -if (sc >= 48) A = B = sgn; -if (sc >= 24) { - sc = sc - 24; - B = ((A >> sc) | (sgn << (24 - sc))) & DMASK; - A = sgn; } -else { B = ((B >> sc) | (A << (24 - sc)) & DMASK); - A = ((A >> sc) | (sgn << (24 - sc))) & DMASK; } -return; -} - -/* POT routines for RL1, RL2, RL4 */ - -t_stat pot_RL1 (uint32 num, uint32 *dat) -{ -RL1 = *dat; -set_dyn_map (); -return SCPE_OK; -} - -t_stat pot_RL2 (uint32 num, uint32 *dat) -{ -RL2 = *dat; -set_dyn_map (); -return SCPE_OK; -} - -t_stat pot_RL4 (uint32 num, uint32 *dat) -{ -RL4 = (*dat) & 03737; -set_dyn_map (); -return SCPE_OK; -} - -/* Map EM2, EM3, RL1, RL2, RL4 to dynamic forms - - EM2, EM3 - left shifted 12, base virtual address subtracted - RL1, RL2 - page left shifted 11 - RL3 - filled in as 1 to 1 map - RL4 - EM2 or page left shifted 11, PROT bit inserted -*/ - -void set_dyn_map (void) -{ -em2_dyn = ((EM2 & 07) << 12) - 020000; -em3_dyn = ((EM3 & 07) << 12) - 030000; -usr_map[0] = (RL1 >> 7) & (MAP_PROT | MAP_PAGE); -usr_map[1] = (RL1 >> 1) & (MAP_PROT | MAP_PAGE); -usr_map[2] = (RL1 << 5) & (MAP_PROT | MAP_PAGE); -usr_map[3] = (RL1 << 11) & (MAP_PROT | MAP_PAGE); -usr_map[4] = (RL2 >> 7) & (MAP_PROT | MAP_PAGE); -usr_map[5] = (RL2 >> 1) & (MAP_PROT | MAP_PAGE); -usr_map[6] = (RL2 << 5) & (MAP_PROT | MAP_PAGE); -usr_map[7] = (RL2 << 11) & (MAP_PROT | MAP_PAGE); -mon_map[0] = (0 << VA_V_PN); -mon_map[1] = (1 << VA_V_PN); -mon_map[2] = (2 << VA_V_PN); -mon_map[3] = (3 << VA_V_PN); -mon_map[4] = ((EM2 & 07) << 12); -mon_map[5] = ((EM2 & 07) << 12) + (1 << VA_V_PN); -mon_map[6] = (RL4 << 5) & MAP_PAGE; -mon_map[7] = (RL4 << 11) & MAP_PAGE; -if (mon_map[6] == 0) mon_map[6] = MAP_PROT; -if (mon_map[7] == 0) mon_map[7] = MAP_PROT; -return; -} - -/* Recalculate api requests */ - -uint32 api_findreq (void) -{ -uint32 i, t; - -t = (int_req & ~1) & api_mask[api_lvlhi]; /* unmasked int */ -for (i = 31; t && (i > 0); i--) { /* find highest */ - if ((t >> i) & 1) return i; } -return 0; /* none */ -} - -/* Dismiss highest priority interrupt */ - -void api_dismiss (void) -{ -uint32 i, t; - -t = 1u << api_lvlhi; /* highest active */ -int_req = int_req & ~t; /* clear int req */ -api_lvl = api_lvl & ~t; /* clear api level */ -api_lvlhi = 0; /* assume all clear */ -for (i = 31; api_lvl && (i > 0); i--) { /* find highest api */ - if ((api_lvl >> i) & 1) { /* bit set? */ - api_lvlhi = i; /* record level */ - break; } } /* done */ -int_reqhi = api_findreq (); /* recalc intreq */ -return; -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -OV = 0; -EM2 = 2; -EM3 = 3; -RL1 = RL2 = RL4 = 0; -ion = ion_defer = 0; -nml_mode = 1; -usr_mode = 0; -mon_usr_trap = 0; -int_req = 0; -int_reqhi = 0; -api_lvl = 0; -api_lvlhi = 0; -alert = 0; -pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -uint32 pa; - -pa = RelocC (addr, sw); -if (pa > MAXMEMSIZE) return SCPE_REL; -if (pa >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[pa] & DMASK; -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -uint32 pa; - -pa = RelocC (addr, sw); -if (pa > MAXMEMSIZE) return SCPE_REL; -if (pa >= MEMSIZE) return SCPE_NXM; -M[pa] = val & DMASK; -return SCPE_OK; -} - -/* Set memory size */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 037777) != 0)) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; -if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_OK; -MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; -return SCPE_OK; -} - -/* Set system type (1 = Genie, 0 = standard) */ - -t_stat cpu_set_type (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -extern t_stat drm_reset (DEVICE *dptr); -extern DEVICE drm_dev, mux_dev, muxl_dev; -extern UNIT drm_unit, mux_unit; -extern DIB mux_dib; - -if ((cpu_unit.flags & UNIT_GENIE) == (uint32) val) return SCPE_OK; -if ((drm_unit.flags & UNIT_ATT) || /* attached? */ - (mux_unit.flags & UNIT_ATT)) return SCPE_NOFNC; /* can't do it */ -if (val) { /* Genie? */ - drm_dev.flags = drm_dev.flags & ~DEV_DIS; /* enb drum */ - mux_dev.flags = mux_dev.flags & ~DEV_DIS; /* enb mux */ - muxl_dev.flags = muxl_dev.flags & ~DEV_DIS; - mux_dib.dev = DEV3_GMUX; } /* Genie mux */ -else { drm_dev.flags = drm_dev.flags | DEV_DIS; /* dsb drum */ - mux_dib.dev = DEV3_SMUX; /* std mux */ - return drm_reset (&drm_dev); } -return SCPE_OK; -} - -/* The real time clock runs continuously; therefore, it only has - a unit service routine and a reset routine. The service routine - sets an interrupt that invokes the clock counter. The clock counter - is a "one instruction interrupt", and only MIN/SKR are valid. -*/ - -t_stat rtc_svc (UNIT *uptr) -{ -if (rtc_pie) int_req = int_req | INT_RTCP; /* set pulse intr */ -sim_activate (&rtc_unit, sim_rtcn_calb (rtc_tps, TMR_RTC)); /* reactivate unit */ -return SCPE_OK; -} - -/* Clock interrupt instruction */ - -t_stat rtc_inst (uint32 inst) -{ -uint32 op, dat, val, va; -t_stat r; - -op = I_GETOP (inst); /* get opcode */ -if (op == MIN) val = 1; /* incr */ -else if (op == SKR) val = DMASK; /* decr */ -else return STOP_RTCINS; /* can't do it */ -if (r = Ea (inst, &va)) return r; /* decode eff addr */ -if (r = Read (va, &dat)) return r; /* get operand */ -dat = AddM24 (dat, val); /* mem +/- 1 */ -if (r = Write (va, dat)) return r; /* rewrite */ -if (dat == 0) int_req = int_req | INT_RTCS; /* set clk sync int */ -return SCPE_OK; -} - -/* Clock reset */ - -t_stat rtc_reset (DEVICE *dptr) -{ -rtc_pie = 0; /* disable pulse */ -sim_activate (&rtc_unit, rtc_unit.wait); /* activate unit */ -return SCPE_OK; -} - -/* Set frequency */ - -t_stat rtc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; -rtc_tps = val; -return SCPE_OK; -} - -/* Show frequency */ - -t_stat rtc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, (rtc_tps == 50)? "50Hz": "60Hz"); -return SCPE_OK; -} diff --git a/SDS/sds_defs.h b/SDS/sds_defs.h deleted file mode 100644 index d6b6a549..00000000 --- a/SDS/sds_defs.h +++ /dev/null @@ -1,403 +0,0 @@ -/* sds_defs.h: SDS 940 simulator definitions - - Copyright (c) 2001-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 25-Apr-03 RMS Revised for extended file support -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Simulator stop codes */ - -#define STOP_IONRDY 1 /* I/O dev not ready */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_INVDEV 4 /* invalid dev */ -#define STOP_INVINS 5 /* invalid instr */ -#define STOP_INVIOP 6 /* invalid I/O op */ -#define STOP_INDLIM 7 /* indirect limit */ -#define STOP_EXULIM 8 /* EXU limit */ -#define STOP_MMINT 9 /* mm in intr */ -#define STOP_MMTRP 10 /* mm in trap */ -#define STOP_TRPINS 11 /* trap inst not BRM */ -#define STOP_RTCINS 12 /* rtc inst not MIN/SKR */ -#define STOP_ILLVEC 13 /* zero vector */ -#define STOP_CCT 14 /* runaway CCT */ - -/* Trap codes */ - -#define MM_PRVINS -040 /* privileged */ -#define MM_NOACC -041 /* no access */ -#define MM_WRITE -043 /* write protect */ -#define MM_MONUSR -044 /* mon to user */ - -/* Conditional error returns */ - -#define CRETINS return ((stop_invins)? STOP_INVINS: SCPE_OK) -#define CRETDEV return ((stop_invdev)? STOP_INVDEV: SCPE_OK) -#define CRETIOP return ((stop_inviop)? STOP_INVIOP: SCPE_OK) -#define CRETIOE(f,c) return ((f)? c: SCPE_OK) - -/* Architectural constants */ - -#define SIGN 040000000 /* sign */ -#define DMASK 077777777 /* data mask */ -#define EXPS 0400 /* exp sign */ -#define EXPMASK 0777 /* exp mask */ -#define SXT(x) ((int32) (((x) & SIGN)? ((x) | ~DMASK): \ - ((x) & DMASK))) -#define SXT_EXP(x) ((int32) (((x) & EXPS)? ((x) | ~EXPMASK): \ - ((x) & EXPMASK))) - -/* Memory */ - -#define MAXMEMSIZE (1 << 16) /* max memory size */ -#define PAMASK (MAXMEMSIZE - 1) /* physical addr mask */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) -#define ReadP(x) M[x] -#define WriteP(x,y) if (MEM_ADDR_OK (x)) M[x] = y - -/* Virtual addressing */ - -#define VA_SIZE (1 << 14) /* virtual addr size */ -#define VA_MASK (VA_SIZE - 1) /* virtual addr mask */ -#define VA_V_PN 11 /* page number */ -#define VA_M_PN 07 -#define VA_GETPN(x) (((x) >> VA_V_PN) & VA_M_PN) -#define VA_POFF ((1 << VA_V_PN) - 1) /* offset */ -#define VA_USR (I_USR) /* user flag in addr */ -#define XVA_MASK (VA_USR | VA_MASK) - -/* Arithmetic */ - -#define TSTS(x) ((x) & SIGN) -#define NEG(x) (-((int32) (x)) & DMASK) -#define ABS(x) (TSTS (x)? NEG(x): (x)) - -/* Memory map */ - -#define MAP_PROT (040 << VA_V_PN) /* protected */ -#define MAP_PAGE (037 << VA_V_PN) /* phys page number */ - -/* Instruction format */ - -#define I_USR (1 << 23) /* user */ -#define I_IDX (1 << 22) /* indexed */ -#define I_POP (1 << 21) /* programmed op */ -#define I_V_TAG 21 /* tag */ -#define I_V_OP 15 /* opcode */ -#define I_M_OP 077 -#define I_GETOP(x) (((x) >> I_V_OP) & I_M_OP) -#define I_IND (1 << 14) /* indirect */ -#define I_V_SHFOP 11 /* shift op */ -#define I_M_SHFOP 07 -#define I_GETSHFOP(x) (((x) >> I_V_SHFOP) & I_M_SHFOP) -#define I_SHFMSK 0777 /* shift count */ -#define I_V_IOMD 12 /* IO inst mode */ -#define I_M_IOMD 03 -#define I_GETIOMD(x) (((x) >> I_V_IOMD) & I_M_IOMD) -#define I_V_SKCND 7 /* SKS skip cond */ -#define I_M_SKCND 037 -#define I_GETSKCND(x) (((x) >> I_V_SKCND) & I_M_SKCND) -#define I_EOB2 000400000 /* chan# bit 2 */ -#define I_SKB2 000040000 /* skschan# bit 2 */ -#define I_EOB1 020000000 /* chan# bit 1 */ -#define I_EOB0 000000100 /* chan# bit 0 */ -#define I_GETEOCH(x) ((((x) & I_EOB2)? 4: 0) | \ - (((x) & I_EOB1)? 2: 0) | \ - (((x) & I_EOB0)? 1: 0)) -#define I_SETEOCH(x) ((((x) & 4)? I_EOB2: 0) | \ - (((x) & 2)? I_EOB1: 0) | \ - (((x) & 1)? I_EOB0: 0)) -#define I_GETSKCH(x) ((((x) & I_SKB2)? 4: 0) | \ - (((x) & I_EOB1)? 2: 0) | \ - (((x) & I_EOB0)? 1: 0)) -#define I_SETSKCH(x) ((((x) & 4)? I_SKB2: 0) | \ - (((x) & 2)? I_EOB1: 0) | \ - (((x) & 1)? I_EOB0: 0)) - -/* Globally visible flags */ - -#define UNIT_V_GENIE (UNIT_V_UF + 0) -#define UNIT_GENIE (1 << UNIT_V_GENIE) - -/* Timers */ - -#define TMR_RTC 0 /* clock */ -#define TMR_MUX 1 /* mux */ - -/* I/O routine functions */ - -#define IO_CONN 0 /* connect */ -#define IO_EOM1 1 /* EOM mode 1 */ -#define IO_DISC 2 /* disconnect */ -#define IO_READ 3 /* read */ -#define IO_WRITE 4 /* write */ -#define IO_WREOR 5 /* write eor */ -#define IO_SKS 6 /* skip signal */ - -/* Dispatch template */ - -struct sdsdspt { - uint32 num; /* # entries */ - uint32 off; /* offset from base */ - }; - -typedef struct sdsdspt DSPT; - -/* Device information block */ - -struct sdsdib { - int32 chan; /* channel */ - int32 dev; /* base dev no */ - int32 xfr; /* xfer flag */ - DSPT *tplt; /* dispatch templates */ - t_stat (*iop) (uint32 fnc, uint32 dev, uint32 *dat); - }; - -typedef struct sdsdib DIB; - -/* Channels */ - -#define NUM_CHAN 8 /* max num chan */ -#define CHAN_W 0 /* TMCC */ -#define CHAN_Y 1 -#define CHAN_C 2 -#define CHAN_D 3 -#define CHAN_E 4 /* DACC */ -#define CHAN_F 5 -#define CHAN_G 6 -#define CHAN_H 7 - -/* I/O control EOM */ - -#define CHC_REV 04000 /* reverse */ -#define CHC_NLDR 02000 /* no leader */ -#define CHC_BIN 01000 /* binary */ -#define CHC_V_CPW 7 /* char/word */ -#define CHC_M_CPW 03 -#define CHC_GETCPW(x) (((x) >> CHC_V_CPW) & CHC_M_CPW) - -/* Buffer control (extended) EOM */ - -#define CHM_CE 04000 /* compat/ext */ -#define CHM_ER 02000 /* end rec int */ -#define CHM_ZC 01000 /* zero wc int */ -#define CHM_V_FNC 7 /* term func */ -#define CHM_M_FNC 03 -#define CHM_GETFNC(x) (((x) & CHM_CE)? (((x) >> CHM_V_FNC) & CHM_M_FNC): CHM_COMP) -#define CHM_IORD 0 /* record, disc */ -#define CHM_IOSD 1 /* signal, disc */ -#define CHM_IORP 2 /* record, proc */ -#define CHM_IOSP 3 /* signal, proc */ -#define CHM_COMP 5 /* compatible */ -#define CHM_SGNL 1 /* signal bit */ -#define CHM_PROC 2 /* proceed bit */ -#define CHM_V_HMA 5 /* hi mem addr */ -#define CHM_M_HMA 03 -#define CHM_GETHMA(x) (((x) >> CHM_V_HMA) & CHM_M_HMA) -#define CHM_V_HWC 0 /* hi word count */ -#define CHM_M_HWC 037 -#define CHM_GETHWC(x) (((x) >> CHM_V_HWC) & CHM_M_HWC) - -/* Channel flags word */ - -#define CHF_ERR 00001 /* error */ -#define CHF_IREC 00002 /* interrecord */ -#define CHF_ILCE 00004 /* interlace */ -#define CHF_DCHN 00010 /* data chain */ -#define CHF_EOR 00020 /* end of record */ -#define CHF_12B 00040 /* 12 bit mode */ -#define CHF_24B 00100 /* 24 bit mode */ -#define CHF_OWAK 00200 /* output wake */ -#define CHF_SCAN 00400 /* scan */ -#define CHF_TOP 01000 /* TOP pending */ -#define CHF_N_FLG 9 /* <= 16 */ - -/* Interrupts and vectors (0 is reserved), highest bit is highest priority */ - -#define INT_V_PWRO 31 /* power on */ -#define INT_V_PWRF 30 /* power off */ -#define INT_V_CPAR 29 /* CPU parity err */ -#define INT_V_IPAR 28 /* IO parity err */ -#define INT_V_RTCS 27 /* clock sync */ -#define INT_V_RTCP 26 /* clock pulse */ -#define INT_V_YZWC 25 /* chan Y zero wc */ -#define INT_V_WZWC 24 /* chan W zero wc */ -#define INT_V_YEOR 23 /* chan Y end rec */ -#define INT_V_WEOR 22 /* chan W end rec */ -#define INT_V_CZWC 21 /* chan C */ -#define INT_V_CEOR 20 -#define INT_V_DZWC 19 /* chan D */ -#define INT_V_DEOR 18 -#define INT_V_EZWC 17 /* chan E */ -#define INT_V_EEOR 16 -#define INT_V_FZWC 15 /* chan F */ -#define INT_V_FEOR 14 -#define INT_V_GZWC 13 /* chan G */ -#define INT_V_GEOR 12 -#define INT_V_HZWC 11 /* chan H */ -#define INT_V_HEOR 10 -#define INT_V_MUXR 9 /* mux receive */ -#define INT_V_MUXT 8 /* mux transmit */ -#define INT_V_MUXCO 7 /* SDS carrier on */ -#define INT_V_MUXCF 6 /* SDS carrier off */ -#define INT_V_DRM 5 /* Genie drum */ -#define INT_V_FORK 4 /* fork */ - -#define INT_PWRO (1 << INT_V_PWRO) -#define INT_PWRF (1 << INT_V_PWRF) -#define INT_CPAR (1 << INT_V_CPAR) -#define INT_IPAR (1 << INT_V_IPAR) -#define INT_RTCS (1 << INT_V_RTCS) -#define INT_RTCP (1 << INT_V_RTCP) -#define INT_YZWC (1 << INT_V_YZWC) -#define INT_WZWC (1 << INT_V_WZWC) -#define INT_YEOR (1 << INT_V_YEOR) -#define INT_WEOR (1 << INT_V_WEOR) -#define INT_CZWC (1 << INT_V_CZWC) -#define INT_CEOR (1 << INT_V_CEOR) -#define INT_DZWC (1 << INT_V_DZWC) -#define INT_DEOR (1 << INT_V_DEOR) -#define INT_EZWC (1 << INT_V_EZWC) -#define INT_EEOR (1 << INT_V_EEOR) -#define INT_FZWC (1 << INT_V_FZWC) -#define INT_FEOR (1 << INT_V_FEOR) -#define INT_GZWC (1 << INT_V_GZWC) -#define INT_GEOR (1 << INT_V_GEOR) -#define INT_HZWC (1 << INT_V_HZWC) -#define INT_HEOR (1 << INT_V_HEOR) -#define INT_MUXR (1 << INT_V_MUXR) -#define INT_MUXT (1 << INT_V_MUXT) -#define INT_MUXCO (1 << INT_V_MUXCO) -#define INT_MUXCF (1 << INT_V_MUXCF) -#define INT_DRM (1 << INT_V_DRM) -#define INT_FORK (1 << INT_V_FORK) - -#define VEC_PWRO 0036 -#define VEC_PWRF 0037 -#define VEC_CPAR 0056 -#define VEC_IPAR 0057 -#define VEC_RTCS 0074 -#define VEC_RTCP 0075 -#define VEC_YZWC 0030 -#define VEC_WZWC 0031 -#define VEC_YEOR 0032 -#define VEC_WEOR 0033 -#define VEC_CZWC 0060 -#define VEC_CEOR 0061 -#define VEC_DZWC 0062 -#define VEC_DEOR 0063 -#define VEC_EZWC 0064 -#define VEC_EEOR 0065 -#define VEC_FZWC 0066 -#define VEC_FEOR 0067 -#define VEC_GZWC 0070 -#define VEC_GEOR 0071 -#define VEC_HZWC 0072 -#define VEC_HEOR 0073 -#define VEC_MUXR 0200 /* term mux rcv */ -#define VEC_MUXT 0201 /* term mux xmt */ -#define VEC_MUXCO 0202 /* SDS: mux carrier on */ -#define VEC_MUXCF 0203 /* SDS: mux carrier off */ -#define VEC_DRM 0202 /* Genie: drum */ -#define VEC_FORK 0216 /* "fork" */ - -/* Device constants */ - -#define DEV_MASK 077 /* device mask */ -#define DEV_TTI 001 /* teletype */ -#define DEV_PTR 004 /* paper tape rdr */ -#define DEV_MT 010 /* magtape */ -#define DEV_RAD 026 /* fixed head disk */ -#define DEV_DSK 026 /* moving head disk */ -#define DEV_TTO 041 /* teletype */ -#define DEV_PTP 044 /* paper tape punch */ -#define DEV_LPT 060 /* line printer */ -#define DEV_MTS 020 /* MT scan/erase */ -#define DEV_OUT 040 /* output flag */ -#define DEV3_GDRM 004 /* Genie drum */ -#define DEV3_GMUX 001 /* Genie mux */ -#define DEV3_SMUX (DEV_MASK) /* standard mux */ - -#define LPT_WIDTH 132 /* line print width */ -#define CCT_LNT 132 /* car ctrl length */ - -/* Transfer request flags for devices (0 is reserved) */ - -#define XFR_V_TTI 1 /* console */ -#define XFR_V_TTO 2 -#define XFR_V_PTR 3 /* paper tape */ -#define XFR_V_PTP 4 -#define XFR_V_LPT 5 /* line printer */ -#define XFR_V_RAD 6 /* fixed hd disk */ -#define XFR_V_DSK 7 /* mving hd disk */ -#define XFR_V_MT0 8 /* magtape */ - -#define XFR_TTI (1 << XFR_V_TTI) -#define XFR_TTO (1 << XFR_V_TTO) -#define XFR_PTR (1 << XFR_V_PTR) -#define XFR_PTP (1 << XFR_V_PTP) -#define XFR_LPT (1 << XFR_V_LPT) -#define XFR_RAD (1 << XFR_V_RAD) -#define XFR_DSK (1 << XFR_V_DSK) -#define XFR_MT0 (1 << XFR_V_MT0) - -/* PIN/POT ordinals (0 is reserved) */ - -#define POT_ILCY 1 /* interlace */ -#define POT_DCRY (POT_ILCY + NUM_CHAN) /* data chain */ -#define POT_ADRY (POT_DCRY + NUM_CHAN) /* address reg */ -#define POT_RL1 (POT_ADRY + NUM_CHAN) /* RL1 */ -#define POT_RL2 (POT_RL1 + 1) /* RL2 */ -#define POT_RL4 (POT_RL2 + 1) /* RL4 */ -#define POT_RADS (POT_RL4 + 1) /* fhd sector */ -#define POT_RADA (POT_RADS + 1) /* fhd addr */ -#define POT_DSK (POT_RADA + 1) /* mhd sec/addr */ -#define POT_SYSI (POT_DSK + 1) /* sys intr */ -#define POT_MUX (POT_SYSI + 1) /* multiplexor */ - -/* Opcodes */ - -enum opcodes { - HLT, BRU, EOM, EOD = 006, - MIY = 010, BRI, MIW, POT, ETR, MRG = 016, EOR, - NOP, OVF = 022, EXU, - YIM = 030, WIM = 032, PIN, STA = 035, STB, STX, - SKS, BRX, BRM = 043, RCH = 046, - SKE = 050, BRR, SKB, SKN, SUB, ADD, SUC, ADC, - SKR, MIN, XMA, ADM, MUL, DIV, RSH, LSH, - SKM, LDX, SKA, SKG, SKD, LDB, LDA, EAX }; - -/* Channel function prototypes */ - -void chan_set_flag (int32 ch, uint32 fl); -void chan_set_ordy (int32 ch); -void chan_disc (int32 ch); -void chan_set_uar (int32 ch, uint32 dev); -t_stat set_chan (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_chan (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat chan_process (void); -t_bool chan_testact (void); diff --git a/SDS/sds_diag.txt b/SDS/sds_diag.txt deleted file mode 100644 index 6f095a7f..00000000 --- a/SDS/sds_diag.txt +++ /dev/null @@ -1,113 +0,0 @@ -SDS Diagnostics, using the SDS 930/940 Master Diagnostic Tape image (D930X4A.TAP) - -Summary - -930 0-16K Memory Test passed -930 16K-32K Memory Test passed -930 Instruction Test passed -930 P&S Register Test passed - ---- -930 0-16K Memory Test - -sim> att mt diag.tap -sim> d a 1 -sim> d bpt4 1 ; stop every 1/2 cycle -sim> boot mt - -HALT instruction, P: 00050 (STA 122,4) -sim> ex a -A: 00000000 ; error count -sim> c - -HALT instruction, P: 37650 (STA 37722,4) - -sim> ex a -A: 00000000 ; error count - ---- -930 16K-32K Memory Test - -sim> att mt diag.tap -sim> d a 2 -sim> d bpt4 2 ; stop every 1/2 cycle -sim> boot mt - - -HALT instruction, P: 00050 (STA 6) -sim> ex a -A: 00000000 ; error count -sim> c - -HALT instruction, P: 37650 (STA 37406) -sim> ex a -A: 00000000 ; error count -sim> c - ---- -930 Instruction Diagnostic - -sim> att mt diag.tap -sim> d a 3 -sim> br 17 ; catch start of diagnostic -sim> boot mt - -Breakpoint, P: 00017 (BRR 12,2) -sim> nobr 17 -sim> br 112 ; catch end of diagnostic -sim> c - -Breakpoint, P: 00112 (BRU 3) - ---- -930 P&S Register Test - -sim> att mt diag.tap -sim> d a 4 -sim> br 60 ; catch end of pass -sim> boot mt - -Breakpoint, P: 00060 (BRU 22) - ---- -Bugs - -1. IO: Channel WAR not cleared after memory store -2. IO: dev_map should contain _flags, not _v_flags -3. SYS: Errors in system tables -4. SYS: Character conversion table had 0 (space) as illegal, should be -1 -5. IO: Channel CPW calculation wrong for 12b mode -6. RAD, DSK, MT: Instruction masks wrong for RAD, DSK, MT -7. IO: Missing subscripts in dev_disp references -8. RAD: typos referencing DSK -9. IO: SKS 3 call incorrect -10. DRM: Drum track mask width incorrect -11. CPU: Memory management trap left reason in bogus state, stopped simulator -12. CPU: Interrupts require api_lvl as well as api_lvlhi, like PDP-10, PDP-15 -13. CPU: Bug in find interrupt request -14. CPU: Interrupt priority scheme recoded for left to right priority -15. CPU: overflow test coded backwards -16. CPU: Rotates operate mod 48, not with upper limit of 48 (manual incorrect) -17. CPU: RSH not handling >= 48 correctly -18. CPU: CNA is 2's complement not 1's complement -19. CPU: MUL failed to mask cross product correctly -20. CPU: EM2, EM3 test using wrong 'channel' -21. CPU: EM3 test tested EM2 instead -22. CPU: POP must save EM2, EM3 like BRM (manual incorrect) -23. CPU: Shifts need special EA calculation, direct cycles using 9b indexing -24. CPU: Shifts ignore addr<13:14> -25. CPU: Diagnostic uses undefined shift 'normalize cyclic' -26. CPU: Divide 2'c complement of AB leaves B<23> unchanged -27. CPU: Divide overflow test requires special cases for divd.h == divr -28. CPU: Divide uses non-restoring algorithm -29. CPU: Channel terminate output must be deferred until channel buffer clears -30. CPU: Channel terminate output to magtape is convert to scan, must be - handled in channel logic -31. SYS: duplicate entries for shifts -32. SYS: mask for shifts did not include indirect flag -33. MUX: Genie/SDS use inverted meanings for line enable flag -34. MT: missing fseek before write eof -35. MT: displayed characters only 7b wide instead of 8b -36. CPU: EOD 20000 used by diagnostic (EM change is NOP) -37. CPU: SKD sets all 24b of X, not just exponent -38. CPU: reset should not clear A, B, X diff --git a/SDS/sds_doc.txt b/SDS/sds_doc.txt deleted file mode 100644 index 97ec45c8..00000000 --- a/SDS/sds_doc.txt +++ /dev/null @@ -1,536 +0,0 @@ -To: Users -From: Bob Supnik -Subj: SDS 940 Simulator Usage -Date: 15-Mar-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - Original code published in 1993-2003, written by Robert M Supnik - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - -This memorandum documents the SDS 940 simulator. - - -1. Simulator Files - -sim/ sim_defs.h - sim_rev.h - sim_sock.h - sim_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tape.c - sim_tmxr.c - -sim/sds/ sds_defs.h - sds_cpu.c - sds_drm.c - sds_dsk.c - sds_io.c - sds_lp.c - sds_mt.c - sds_mux.c - sds_rad.c - sds_stddev.c - sds_sys.c - -2. SDS 940 Features - -The SDS-940 simulator is configured as follows: - -device simulates -name(s) - -CPU SDS-940 CPU with 16KW to 64KW of memory -CHAN I/O channels -PTR paper tape reader -PTP paper tape punch -TTI console input -TTO console output -LPT line printer -RTC real-time clock -MUX terminal multiplexor -DRM Project Genie drum -RAD fixed head disk -DSK 9164/9165 rapid access (moving head) disk -MT magnetic tape - -Most devices can be disabled or enabled with the SET DISABLED and -SET ENABLED commands, respectively. - -2.1 CPU - -The CPU options set the size of main memory and the configuration of -peripherals. - - SET CPU 16K set memory size = 16KW - SET CPU 32K set memory size = 32KW - SET CPU 48K set memory size = 48KW - SET CPU 64K set memory size = 64KW - SET CPU GENIE enable DRM, set terminal mux - to GENIE mode - SET CPU SDS disable DRM, set terminal mux - to SDS mode - -If memory size is being reduced, and the memory being truncated contains -non-zero data, the simulator asks for confirmation. Data in the truncated -portion of memory is lost. Initial memory size is 64KW. - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - P 14 program counter - A 24 accumulator A - B 24 accumulator B - X 24 index register - OV 1 overflow indicator - EM2 3 memory extension, quadrant 2 - EM3 3 memory extension, quadrant 3 - RL1 24 user relocation register 1 - RL2 24 user relocation register 2 - RL4 12 kernel relocation register - NML 1 normal mode flag - USR 1 user mode flag - MONUSR 1 monitor-to-user trap enable - ION 1 interrupt enable - INTDEF 1 interrupt defer - INTREQ 32 interrupt request flags - APIACT 5 highest active API level - APIREQ 5 highest requesting API level - XFRREQ 32 device transfer request flags - BPT 4 breakpoint switches - ALERT 6 outstanding alert number - STOP_INVINS 1 stop on invalid instruction - STOP_INVDEV 1 stop on invalid device number - STOP_INVIOP 1 stop on invalid I/O operation - INDLIM 8 maximum indirect nesting depth - EXULIM 8 maximum execute nesting depth - PCQ[0:63] 14 P prior to last branch or interrupt; - most recent P change first - WRU 8 interrupt character - -2.2 Channels (CHAN) - -The SDS 940 has up to eight I/O channels, designated W, Y, C, D, E, F, G, -and H. W, Y, C, and D are time-multiplexed communications channels (TMCC); -E, F, G, and H are direct access communications channels (DACC). Unlike -real SDS 940 channels, the simulated channels handle 6b, 12b, and 24b transfers -simultaneously. The association between a device and a channel is displayed -by the SHOW CHAN command: - - SIM> SHOW LPT CHAN - channel=W - -The user can change the association with the SET CHAN= command, -where is a channel letter: - - SIM> SET LPT CHAN=E - SIM> SHOW LPT CHAN - channel=E - -Each channel has nine registers. The registers are arrays, with entry [0] -for channel W, entry [1] for channel Y, etc. - - name size comments - - UAR[0:7] 6 unit address register - WCR[0:7] 15 word count register - MAR[0:7] 16 memory address register - DCR[0:7] 6 data chaining register - WAR[0:7] 24 word assembly register - CPW[0:7] 2 characters per word - CNT[0:7] 3 character count - MODE[0:7] 12 channel mode (from EOM instruction) - FLAG[0:7] 9 channel flags - -The user can display all the registers in a channel with the command: - - SHOW CHAN channel-letter - -2.3 Console Input (TTI) - -The console input (TTI) polls the console keyboard for input. It -implements these registers: - - name size comments - - BUF 6 data buffer - XFR 1 transfer ready flag - POS 32 number of characters input - TIME 24 polling interval - -By default, the console input is assigned to channel W. - -2.4 Console Output (TTO) - -The console output (TTO) writes to the simulator console window. It -implements these registers: - - name size comments - - BUF 6 data buffer - XFR 1 transfer ready flag - POS 32 number of characters input - TIME 24 time from I/O initiation to interrupt - -By default, the console output is assigned to channel W. - -2.5 Paper Tape Reader (PTR) - -The paper tape reader (PTR) reads data from a disk file. The POS -register specifies the number of the next data item to be read. Thus, -by changing POS, the user can backspace or advance the reader. - -The paper tape reader implements these registers: - - name size comments - - BUF 6 data buffer - XFR 1 transfer ready flag - SOR 1 start of record flag - CHAN 4 active channel - POS 32 number of characters input - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - end of file 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -By default, the paper tape reader is assigned to channel W. - -2.6 Paper Tape Punch (PTP) - -The paper tape punch (PTP) writes data to a disk file. The POS -register specifies the number of the next data item to be written. -Thus, by by changing POS, the user can backspace or advance the punch. - -The paper tape punch implements these registers: - - name size comments - - BUF 6 data buffer - XFR 1 transfer ready flag - LDR 1 punch leader flag - CHAN 4 active channel - POS 32 number of characters input - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -By default, the paper tape punch is assigned to channel W. - -2.7 Line Printer (LPT) - -The line printer (LPT) writes data to a disk file. The POS register -specifies the number of the next data item to be written. Thus, -by changing POS, the user can backspace or advance the printer. - -The line printer implements these registers: - - name size comments - - BUF[0:131] 8 data buffer - BPTR 8 buffer pointer - XFR 1 transfer ready flag - ERR 1 error flag - CHAN 4 active channel - CCT[0:131] 8 carriage control tape - CCTP 8 pointer into carriage control tape - CCTL 8 length of carriage control tape - SPCINST 24 spacing instruction - POS 32 number of characters input - CTIME 24 intercharacter time - PTIME 24 print time - STIME 24 space time - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of paper - - OS I/O error x report error and stop - -By default, the line printer is assigned to channel W. - -2.8 Real-Time Clock (RTC) - -The real-time clock (RTC) frequency can be adjusted as follows: - - SET RTC 60HZ set frequency to 60Hz - SET RTC 50HZ set frequency to 50Hz - -The default is 60Hz. - -The clock implements these registers: - - name size comments - - PIE 1 interrupt enable - TIME 24 tick interval - -The real-time clock autocalibrates; the clock interval is adjusted up or -down so that the clock tracks actual elapsed time. - -2.9 Terminal Multiplexor (MUX) - -The terminal multiplexor provides 32 asynchronous interfaces. In Genie -mode, the interfaces are hard-wired; in SDS mode, they implement modem -control. The multiplexor has two controllers: MUX for the scanner, and -MUXL for the individual lines. The terminal multiplexor performs input -and output through Telnet sessions connected to a user-specified port. -The ATTACH command specifies the port to be used: - - ATTACH MUX set up listening port - -where port is a decimal number between 1 and 65535 that is not being used -for other TCP/IP activities. - -Each line (each unit of MUXL) supports one option: UC, when set, causes -lower case input characters to be automatically converted to upper case. - -Once MUX is attached and the simulator is running, the multiplexor listens -for connections on the specified port. It assumes that the incoming -connections are Telnet connections. The connections remain open until -disconnected either by the Telnet client, a SET MUX DISCONNECT command, -or a DETACH MUX command. - -The SHOW MUX CONNECTIONS command displays the current connections to the -extra terminals. The SHOW MUX STATISTICS command displays statistics for -active connections. The SET MUX DISCONNECT=linenumber disconnects the -specified line. - -The controller (MUX) implements these registers: - - name size comments - - STA[0:31] 6 status, lines 0 to 31 - RBUF[0:31] 8 receive buffer, lines 0 to 31 - XBUF[0:31] 8 transmit buffer, lines 0 to 31 - FLAGS[0:127] 1 line flags, 0 to 3 for line 0, - 4 to 7 for line 1, etc - SCAN 7 scanner current flag number - SLCK 1 scanner locked flag - TPS 8 character polls per second - -The lines (MUXL) implements these registers: - - name size comments - - TIME[0:31] 24 transmit time, lines 0 to 31 - -The terminal multiplexor does not support save and restore. All open -connections are lost when the simulator shuts down or MUX is detached. - -2.10 Project Genie Drum (DRM) - -The Project Genie drum (DRM) implements these registers: - - name size comments - - DA 19 drum address - CA 16 core address - WC 14 word count - PAR 12 cumulative sector parity - RW 1 read/write flag - ERR 1 error flag - STA 2 drum state - FTIME 24 channel program fetch time - XTIME 24 interword transfer time - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 drum not ready - -Drum data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. Unlike conventional SDS 940 devices, the Project -Genie drum does not use a channel. - -2.11 Rapid Access (fixed head) Disk (RAD) - -The rapid access disk (RAD) implements these registers: - - name size comments - - DA 15 disk address - SA 6 sector word address - BP 1 sector byte pointer - XFR 1 data transfer flag - NOBD 1 inhibit increment across track - ERR 1 error flag - CHAN 4 active channel - PROT 8 write protect switches - TIME 24 interval between halfword transfers - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -The rapid access disk is buffered in memory; end of file and OS I/O errors -cannot occur. By default, the rapid access disk is assigned to channel E. - -2.12 Moving Head Disk (DSK) - -DSK options include the ability to make the drive write enabled or write -locked: - - SET RAD LOCKED set write locked - SET RAD WRITEENABLED set write enabled - -The moving head disk implements these registers: - - name size comments - - BUF[0:63] 8 transfer buffer - BPTR 9 buffer pointer - BLNT 9 buffer length - DA 21 disk address - INST 24 disk instruction - XFR 1 data transfer flag - ERR 1 error flag - CHAN 4 active channel - WTIME 24 interval between character transfers - STIME 24 seek interval - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - - end of file x assume rest of disk is zero - - OS I/O error x report error and stop - - -By default, the moving head disk is assigned to channel F. - -2.13 Magnetic Tape (MT) - -MT options include the ability to make units write enabled or write locked. - - SET MTn LOCKED set unit n write locked - SET MTn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFLINE. - -The magnetic tape implements these registers: - - name size comments - - BUF[0:131071] 8 transfer buffer - BPTR 18 buffer pointer - BLNT 18 buffer length - XFR 1 data transfer flag - CHAN 4 active channel - INST 24 magtape instruction - EOF 1 end-of-file flag - GAP 1 inter-record gap flag - SKIP 1 skip data flag - CTIME 24 interval between character transfers - GTIME 24 gap interval - POS[0:7] 32 position, drives 0:7 - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error processed as - - not attached tape not ready; if STOP_IOE, stop - - end of file end of tape - - OS I/O error end of tape; if STOP_IOE, stop - -By default, the magnetic tape is assigned to channel W. - -2.13 Symbolic Display and Input - -The SDS 940 simulator implements symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as four character SDS string - -m display instruction mnemonics - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or -a ASCII character - " or -c four character SDS string - alphabetic instruction mnemonic - numeric octal number - -Instruction input uses (more or less) standard SDS 940 assembler syntax. -There are eight instruction classes: - -class operands examples comments - -no operand none EIR -POP (prog op) op,addr{,tag} POP 66,100 -I/O addr{,tag} EOM 1266 -mem reference addr{,tag} LDA 400,2 - STA* 300 indirect addr -reg change op op op... CLA CLB opcodes OR -shift cnt{,tag} LSH 10 -chan command chan ALC W -chan test chan CAT Y - -All numbers are octal. Channel designators can be alphabetic (W, Y, C, D, E, -F, G, H) or numeric (0-7). Tags must be 0-7, with 2 indicating indexing. diff --git a/SDS/sds_drm.c b/SDS/sds_drm.c deleted file mode 100644 index c41d5550..00000000 --- a/SDS/sds_drm.c +++ /dev/null @@ -1,270 +0,0 @@ -/* sds_drm.c: SDS 940 Project Genie drum simulator - - Copyright (c) 2002-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - drm drum - - The drum is buffered in memory. - - Note: the Project Genie documentation and the actual monitor sources disagree - on the I/O instruction definitions for the drum. The simulator follows the - monitor sources, as follows: - - DCC OP 00230404B RESET DRUM CHANNEL - DSC OP 00230204B START DRUM CHANNEL (NO CHAIN) - DRA OP 00230504B READ DRUM TIMING COUNTER INTO 21B - DSR OP 04030204B SKIP IF DRUM NOT BUSY - DSE OP 04037404B SKIP IF NO DRUM ERROR -*/ - -#include "sds_defs.h" -#include - -/* Constants */ - -#define DRM_N_WD 11 /* word addr width */ -#define DRM_V_WD 0 /* position */ -#define DRM_M_WD ((1 << DRM_N_WD) - 1) /* word mask */ -#define DRM_NUMWD (1 << DRM_N_WD) /* words/sector */ -#define DRM_NUMGP 236 /* gap/sector */ -#define DRM_PHYWD (DRM_NUMWD + DRM_NUMGP) /* phys wds/sector */ -#define DRM_N_SC 3 /* sect addr width */ -#define DRM_V_SC (DRM_N_WD) /* position */ -#define DRM_M_SC ((1 << DRM_N_SC) - 1) /* sector mask */ -#define DRM_NUMSC (1 << DRM_N_SC) /* sectors/track */ -#define DRM_N_TR 7 /* track addr width */ -#define DRM_V_TR (DRM_N_WD+DRM_N_SC) /* position */ -#define DRM_M_TR ((1 << DRM_N_TR) - 1) /* track mask */ -#define DRM_NUMTR 84 /* tracks/drum */ -#define DRM_N_ADDR (DRM_N_WD+DRM_N_SC+DRM_N_TR) /* drum addr width */ -#define DRM_SWMASK ((1 << (DRM_N_WD+DRM_N_SC)) - 1)/* sector+word mask */ -#define DRM_DAMASK ((1 << DRM_N_ADDR) - 1) /* drum addr mask */ -#define DRM_SIZE (DRM_NUMTR*DRM_NUMSC*DRM_NUMWD) /* words/disk */ -#define DRM_WCMASK 037777 /* wc mask */ -#define DRM_GETSC(x) (((x) >> DRM_V_SC) & DRM_M_SC) - -#define DRM_PC 020 -#define DRM_AD 021 -#define DRM_ADAT (1 << (DRM_N_WD + DRM_N_SC)) /* data flag */ - -#define DRM_SFET 0 /* fetch state */ -#define DRM_SFCA 1 /* fetch CA */ -#define DRM_SFDA 2 /* fetch DA */ -#define DRM_SXFR 3 /* xfer */ - -#define DRM_V_OP 21 /* drum op */ -#define DRM_M_OP 07 -#define DRM_V_RW 20 -#define DRM_GETOP(x) (((x) >> DRM_V_OP) & DRM_M_OP) -#define DRM_GETRW(x) (((x) >> DRM_V_RW) & 1) -#define DRM_OXF 0 /* xfer */ -#define DRM_OCX 1 /* cond xfer */ -#define DRM_OBR 2 /* branch */ -#define DRM_ORS 3 /* reset error */ -#define DRM_END 4 /* end prog */ -#define DRM_EIE 5 /* end int if err */ -#define DRM_EIU 7 /* end int uncond */ - -#define GET_TWORD(x) ((int32) fmod (sim_gtime() / ((double) (x)), \ - ((double) (DRM_NUMSC * DRM_PHYWD)))) - -extern uint32 M[]; /* memory */ -extern uint32 alert, int_req; -extern int32 stop_invins, stop_invdev, stop_inviop; -uint32 drm_da = 0; /* disk address */ -uint32 drm_ca = 0; /* core address */ -uint32 drm_wc = 0; /* word count */ -int32 drm_par = 0; /* cumulative par */ -int32 drm_err = 0; /* error */ -int32 drm_rw = 0; /* read/write */ -int32 drm_sta = 0; /* drum state */ -int32 drm_ftime = 3; /* time to fetch */ -int32 drm_xtime = 1; /* time to xfr */ -int32 drm_stopioe = 1; /* stop on error */ - -DEVICE drm_dev; -t_stat drm (uint32 fnc, uint32 inst, uint32 *dat); -t_stat drm_svc (UNIT *uptr); -t_stat drm_reset (DEVICE *dptr); - -/* DRM data structures - - drm_dev device descriptor - drm_unit unit descriptor - drm_reg register list -*/ - -DIB drm_dib = { -1, DEV3_GDRM, 0, NULL, &drm }; - -UNIT drm_unit = - { UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, - DRM_SIZE) }; - -REG drm_reg[] = { - { ORDATA (DA, drm_da, DRM_N_ADDR) }, - { ORDATA (CA, drm_ca, 16) }, - { ORDATA (WC, drm_wc, 14) }, - { ORDATA (PAR, drm_par, 12) }, - { FLDATA (RW, drm_rw, 0) }, - { FLDATA (ERR, drm_err, 0) }, - { ORDATA (STA, drm_sta, 2) }, - { DRDATA (FTIME, drm_ftime, 24), REG_NZ + PV_LEFT }, - { DRDATA (XTIME, drm_xtime, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, drm_stopioe, 0) }, - { NULL } }; - -DEVICE drm_dev = { - "DRM", &drm_unit, drm_reg, NULL, - 1, 8, DRM_N_ADDR, 1, 8, 24, - NULL, NULL, &drm_reset, - NULL, NULL, NULL, - &drm_dib, DEV_DISABLE | DEV_DIS }; - -/* Drum routine - EOM/SKS 3xx04 */ - -t_stat drm (uint32 fnc, uint32 inst, uint32 *dat) -{ -int32 t, op = inst & 07700; - -switch (fnc) { -case IO_CONN: /* connect */ - if (op == 00400) return drm_reset (&drm_dev); /* EOM 404 = reset */ - if (op == 00500) { /* EOM 504 = read DA */ - if (sim_is_active (&drm_unit)) return SCPE_OK; /* must be idle */ - t = GET_TWORD (drm_xtime); /* get position */ - if (t < DRM_NUMGP) M[DRM_AD] = DRM_NUMWD - t; /* in gap? */ - else M[DRM_AD] = (t - DRM_NUMGP) | DRM_ADAT; } /* in data */ - else if (op == 00200) { /* EOM 204 = start */ - if (sim_is_active (&drm_unit)) return SCPE_OK; /* must be idle */ - drm_sta = DRM_SFET; /* state = fetch */ - sim_activate (&drm_unit, drm_ftime); } /* activate */ - else CRETINS; - break; - -case IO_SKS: /* SKS */ - if (((op == 07400) && !drm_err) || /* 37404: no err */ - ((op == 00200) && !sim_is_active (&drm_unit))) /* 30204: idle */ - *dat = 1; - break; - -default: - return SCPE_IERR; } /* can't get here */ -return SCPE_OK; -} - -/* Unit service */ - -t_stat drm_svc (UNIT *uptr) -{ -int32 t, rda; -uint32 dpc, dwd; - -if (drm_sta != DRM_SXFR) { /* fetch drum prog? */ - dpc = M[DRM_PC]; /* get drum PC */ - dwd = M[dpc & PAMASK]; /* get drum inst */ - M[DRM_PC] = (dpc + 1) & PAMASK; /* update drum PC */ - if (drm_sta == DRM_SFCA) { /* fetch core addr? */ - drm_rw = DRM_GETRW (dwd); /* set op */ - drm_ca = dwd & PAMASK; /* set core addr */ - drm_sta = DRM_SFDA; } /* next is disk addr */ - else if (drm_sta == DRM_SFDA) { /* fetch disk addr? */ - drm_da = dwd & DRM_DAMASK; /* set disk addr */ - drm_sta = DRM_SXFR; /* next is xfer */ - drm_par = 0; /* init parity */ - rda = (drm_da & DRM_SWMASK) + (DRM_GETSC (drm_da) * DRM_NUMGP); - t = rda - GET_TWORD (drm_xtime); /* difference */ - if (t <= 0) t = t + (DRM_NUMSC * DRM_PHYWD); /* add trk lnt */ - sim_activate (&drm_unit, t * drm_xtime); } /* activate */ - else { - switch (DRM_GETOP (dwd)) { - case DRM_OCX: /* cond xfr */ - if (drm_err) { /* error? */ - int_req = int_req | INT_DRM; /* req int */ - return SCPE_OK; } /* done */ - case DRM_OXF: /* transfer */ - drm_wc = dwd & DRM_WCMASK; /* save wc */ - drm_sta = DRM_SFCA; /* next state */ - break; - case DRM_OBR: /* branch */ - M[DRM_PC] = dwd & PAMASK; /* new drum PC */ - break; - case DRM_END: /* end */ - return SCPE_OK; - case DRM_EIE: /* end, int if err */ - if (!drm_err) return SCPE_OK; - case DRM_EIU: /* end, int uncond */ - int_req = int_req | INT_DRM; - return SCPE_OK; } /* end switch */ - } /* end else sta */ - sim_activate (uptr, drm_ftime); /* fetch next word */ - } /* end if !xfr */ -else { /* transfer word */ - if ((uptr->flags & UNIT_BUF) == 0) { /* not buffered? */ - drm_err = 1; /* error */ - CRETIOE (drm_stopioe, SCPE_UNATT); } - if (drm_rw) { /* write? */ - dwd = M[drm_ca]; /* get mem word */ - *(((uint32 *) uptr->filebuf) + drm_da) = dwd; /* write to drum */ - if (drm_da >= uptr->hwmark) uptr->hwmark = drm_da + 1; } - else { /* read */ - dwd = *(((uint32 *) uptr->filebuf) + drm_da); /* get drum word */ - M[drm_ca] = dwd; } /* write to mem */ - drm_da = drm_da + 1; /* inc drum addr */ - if (drm_da >= DRM_SIZE) drm_da = 0; /* wrap */ - drm_ca = (drm_ca + 1) & PAMASK; /* inc core addr */ - drm_wc = (drm_wc - 1) & DRM_WCMASK; /* dec word cnt */ - drm_par = drm_par ^ (dwd >> 12); /* parity */ - drm_par = ((drm_par << 1) | (drm_par >> 11)) & 07777; - drm_par = drm_par ^ (dwd & 07777); - if (drm_wc) { /* more to do */ - if (drm_da & DRM_M_WD) sim_activate (uptr, drm_xtime); - else sim_activate (uptr, drm_xtime * DRM_NUMGP); } - else { /* end xfr */ -#if defined (DRM_PAR) - if ((drm_da & DRM_M_WD) && drm_rw) { /* wr end mid sector? */ - *(((uint32 *) uptr->filebuf) + drm_da) = drm_par << 12; - if (drm_da >= uptr->hwmark) uptr->hwmark = drm_da + 1; } -#endif - drm_sta = DRM_SFET; /* back to fetch */ - sim_activate (uptr, drm_ftime); /* schedule */ - } /* end else end xfr */ - } /* end else xfr */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat drm_reset (DEVICE *dptr) -{ -drm_da = 0; /* clear state */ -drm_ca = 0; -drm_wc = 0; -drm_par = 0; -drm_sta = 0; -drm_err = 0; -drm_rw = 0; -int_req = int_req & ~INT_DRM; /* clear intr */ -sim_cancel (&drm_unit); /* deactivate */ -return SCPE_OK; -} diff --git a/SDS/sds_dsk.c b/SDS/sds_dsk.c deleted file mode 100644 index adedeefa..00000000 --- a/SDS/sds_dsk.c +++ /dev/null @@ -1,357 +0,0 @@ -/* sds_dsk.c: SDS 940 moving head disk simulator - - Copyright (c) 2001-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - dsk moving head disk - - The SDS 9164 disk has a subsector feature, allowing each 64W sector to be - viewed as 16W packets. In addition, it has a chaining feature, allowing - records to be extended beyond a sector boundary. To accomodate this, the - first word of each sector has 3 extra bits: - - <26> = end of chain flag - <25:24> = 4 - number of packets - - These values were chosen so that 000 = continue chain, full sector. -*/ - -#include "sds_defs.h" - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -#define DSK_PKTWD 16 /* words/packet */ -#define DSK_NUMPKT 4 /* packets/sector */ -#define DSK_NUMWD (DSK_PKTWD*DSK_NUMPKT) /* words/sector */ -#define DSK_N_SC 5 /* sect addr width */ -#define DSK_V_SC 0 /* position */ -#define DSK_M_SC ((1 << DSK_N_SC) - 1) /* mask */ -#define DSK_NUMSC (1 << DSK_N_SC) /* sectors/track */ -#define DSK_N_TR 8 /* track addr width */ -#define DSK_V_TR (DSK_N_SC) /* position */ -#define DSK_M_TR ((1 << DSK_N_TR) - 1) /* mask */ -#define DSK_NUMTR (1 << DSK_N_TR) /* tracks/surface */ -#define DSK_N_SF 5 /* surf addr width */ -#define DSK_V_SF (DSK_N_SC + DSK_N_TR) /* position */ -#define DSK_M_SF ((1 << DSK_N_SF) - 1) /* mask */ -#define DSK_NUMSF (1 << DSK_N_SF) /* surfaces/drive */ -#define DSK_SCSIZE (DSK_NUMSF*DSK_NUMTR*DSK_NUMSC) /* sectors/drive */ -#define DSK_AMASK (DSK_SCSIZE - 1) /* address mask */ -#define DSK_SIZE (DSK_SCSIZE * DSK_NUMWD) /* words/drive */ -#define DSK_GETTR(x) (((x) >> DSK_V_TR) & DSK_M_TR) -#define cyl u3 /* curr cylinder */ -#define DSK_SIP (1 << (DSK_N_TR + 2)) -#define DSK_V_PKT 24 -#define DSK_M_PKT 03 -#define DSK_V_CHN 26 -#define DSK_GETPKT(x) (4 - (((x) >> DSK_V_PKT) & DSK_M_PKT)) -#define DSK_ENDCHN(x) ((x) & (1 << DSK_V_CHN)) - -extern uint32 xfr_req; -extern uint32 alert; -extern int32 stop_invins, stop_invdev, stop_inviop; -int32 dsk_da = 0; /* disk addr */ -int32 dsk_op = 0; /* operation */ -int32 dsk_err = 0; /* error flag */ -uint32 dsk_buf[DSK_NUMWD]; /* sector buf */ -int32 dsk_bptr = 0; /* byte ptr */ -int32 dsk_blnt = 0; /* byte lnt */ -int32 dsk_time = 5; /* time per char */ -int32 dsk_stime = 200; /* seek time */ -int32 dsk_stopioe = 1; -DSPT dsk_tplt[] = { /* template */ - { 1, 0 }, { 1, DEV_OUT }, { 0, 0 } }; - -DEVICE dsk_dev; -t_stat dsk_svc (UNIT *uptr); -t_stat dsk_reset (DEVICE *dptr); -t_stat dsk_fill (uint32 dev); -t_stat dsk_read_buf (uint32 dev); -t_stat dsk_write_buf (uint32 dev); -void dsk_end_op (uint32 fl); -t_stat dsk (uint32 fnc, uint32 inst, uint32 *dat); - -/* DSK data structures - - dsk_dev device descriptor - dsk_unit unit descriptor - dsk_reg register list -*/ - -DIB dsk_dib = { CHAN_F, DEV_DSK, XFR_DSK, dsk_tplt, &dsk }; - -UNIT dsk_unit = - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE, DSK_SIZE) }; - -REG dsk_reg[] = { - { BRDATA (BUF, dsk_buf, 8, 24, DSK_NUMWD) }, - { DRDATA (BPTR, dsk_bptr, 9), PV_LEFT }, - { DRDATA (BLNT, dsk_bptr, 9), PV_LEFT }, - { ORDATA (DA, dsk_da, 21) }, - { ORDATA (INST, dsk_op, 24) }, - { FLDATA (XFR, xfr_req, XFR_V_DSK) }, - { FLDATA (ERR, dsk_err, 0) }, - { DRDATA (WTIME, dsk_time, 24), REG_NZ + PV_LEFT }, - { DRDATA (STIME, dsk_stime,24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, dsk_stopioe, 0) }, - { NULL } }; - -MTAB dsk_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL", - &set_chan, &show_chan, NULL }, - { 0 } }; - -DEVICE dsk_dev = { - "DSK", &dsk_unit, dsk_reg, dsk_mod, - 1, 8, 24, 1, 8, 27, - NULL, NULL, &dsk_reset, - NULL, NULL, NULL, - &dsk_dib, DEV_DISABLE }; - -/* Moving head disk routine - - conn - inst = EOM0, dat = NULL - eom1 - inst = EOM1, dat = NULL - sks - inst = SKS, dat = ptr to result - disc - inst = device number, dat = NULL - wreor - inst = device number, dat = NULL - read - inst = device number, dat = ptr to data - write - inst = device number, dat = ptr to result -*/ - -t_stat dsk (uint32 fnc, uint32 inst, uint32 *dat) -{ -int32 i, t, new_ch, dsk_wptr, dsk_byte; -t_stat r; - -switch (fnc) { /* case on function */ -case IO_CONN: /* connect */ - new_ch = I_GETEOCH (inst); /* get new chan */ - if (new_ch != dsk_dib.chan) return SCPE_IERR; /* wrong chan? */ - dsk_op = inst; /* save instr */ - dsk_bptr = dsk_blnt = 0; /* init ptrs */ - for (i = 0; i < DSK_NUMWD; i++) dsk_buf[i] = 0; /* clear buffer */ - xfr_req = xfr_req & ~XFR_DSK; /* clr xfr flg */ - sim_activate (&dsk_unit, dsk_stime); /* activate */ - break; - -case IO_EOM1: /* EOM mode 1 */ - new_ch = I_GETEOCH (inst); /* get new chan */ - if (new_ch != dsk_dib.chan) return SCPE_IERR; /* wrong chan? */ - if (inst & 07600) CRETIOP; /* inv inst? */ - alert = POT_DSK; /* alert */ - break; - -case IO_DISC: /* disconnect */ - dsk_end_op (0); /* normal term */ - if (inst & DEV_OUT) return dsk_fill (inst); /* fill write */ - break; - -case IO_WREOR: /* write eor */ - dsk_end_op (CHF_EOR); /* eor term */ - return dsk_fill (inst); /* fill write */ - -case IO_SKS: /* SKS */ - new_ch = I_GETSKCH (inst); /* sks chan */ - if (new_ch != dsk_dib.chan) return SCPE_IERR; /* wrong chan? */ - t = I_GETSKCND (inst); /* sks cond */ - if (((t == 000) && !sim_is_active (&dsk_unit) && /* 10026: ready */ - (dsk_unit.flags & UNIT_ATT)) || - ((t == 004) && !dsk_err && /* 11026: !err */ - (dsk_unit.flags & UNIT_ATT)) || - ((t == 010) && ((dsk_unit.cyl & DSK_SIP) == 0)) || /* 12026: on trk */ - ((t == 014) && !(dsk_unit.flags & UNIT_WPRT)) ||/* 13026: !wrprot */ - ((t == 001) && (dsk_unit.flags & UNIT_ATT))) /* 10226: online */ - *dat = 1; - break; - -case IO_READ: - xfr_req = xfr_req & ~XFR_DSK; /* clr xfr req */ - if (dsk_bptr >= dsk_blnt) { /* no more data? */ - if (r = dsk_read_buf (inst)) return r; } /* read sector */ - dsk_wptr = dsk_bptr >> 2; /* word pointer */ - dsk_byte = dsk_bptr & 03; /* byte in word */ - *dat = (dsk_buf[dsk_wptr] >> ((3 - dsk_byte) * 6)) & 077; - dsk_bptr = dsk_bptr + 1; /* incr buf ptr */ - if ((dsk_bptr >= dsk_blnt) && /* end sector, */ - ((dsk_op & CHC_BIN) || DSK_ENDCHN (dsk_buf[0])))/* sec mode | eoch? */ - dsk_end_op (CHF_EOR); /* eor term */ - break; - -case IO_WRITE: - xfr_req = xfr_req & ~XFR_DSK; /* clr xfr req */ - if (dsk_bptr >= (DSK_NUMWD * 4)) { /* full? */ - if (r = dsk_write_buf (inst)) return r; } /* write sector */ - dsk_wptr = dsk_bptr >> 2; /* word pointer */ - dsk_buf[dsk_wptr] = ((dsk_buf[dsk_wptr] << 6) | (*dat & 077)) & DMASK; - dsk_bptr = dsk_bptr + 1; /* incr buf ptr */ - break; - -default: - CRETINS; } -return SCPE_OK; -} - -/* PIN routine - return disk address */ - -t_stat pin_dsk (uint32 num, uint32 *dat) -{ -*dat = dsk_da; /* ret disk addr */ -return SCPE_OK; -} - -/* POT routine - start seek */ - -t_stat pot_dsk (uint32 num, uint32 *dat) -{ -int32 st; - -if (sim_is_active (&dsk_unit)) return STOP_IONRDY; /* busy? wait */ -dsk_da = (*dat) & DSK_AMASK; /* save dsk addr */ -st = abs (DSK_GETTR (dsk_da) - /* calc seek time */ - (dsk_unit.cyl & DSK_M_TR)) * dsk_stime; -if (st == 0) st = dsk_stime; /* min time */ -sim_activate (&dsk_unit, st); /* set timer */ -dsk_unit.cyl = dsk_unit.cyl | DSK_SIP; /* seeking */ -return SCPE_OK; -} - -/* Unit service and read/write */ - -t_stat dsk_svc (UNIT *uptr) -{ -if (uptr->cyl & DSK_SIP) { /* end seek? */ - uptr->cyl = DSK_GETTR (dsk_da); /* on cylinder */ - if (dsk_op) sim_activate (&dsk_unit, dsk_stime); } /* sched r/w */ -else { - xfr_req = xfr_req | XFR_DSK; /* set xfr req */ - sim_activate (&dsk_unit, dsk_time); } /* activate */ -return SCPE_OK; -} - -/* Read sector */ - -t_stat dsk_read_buf (uint32 dev) -{ -int32 da, pkts, awc; - -if ((dsk_unit.flags & UNIT_ATT) == 0) { /* !attached? */ - dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */ - CRETIOE (dsk_stopioe, SCPE_UNATT); } -da = dsk_da * DSK_NUMWD * sizeof (uint32); -fseek (dsk_unit.fileref, da, SEEK_SET); /* locate sector */ -awc = fxread (dsk_buf, sizeof (uint32), DSK_NUMWD, dsk_unit.fileref); -if (ferror (dsk_unit.fileref)) { /* error? */ - dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */ - return SCPE_IOERR; } -for ( ; awc < DSK_NUMWD; awc++) dsk_buf[awc] = 0; -pkts = DSK_GETPKT (dsk_buf[0]); /* get packets */ -dsk_blnt = pkts * DSK_PKTWD * 4; /* new buf size */ -dsk_bptr = 0; /* init bptr */ -dsk_da = (dsk_da + 1) & DSK_AMASK; /* incr disk addr */ -return SCPE_OK; -} - -/* Write sector. If this routine is called directly, then the sector - buffer is full, and there is at least one more character to write; - therefore, there are 4 packets in the sector, and the sector is not - the end of the chain. -*/ - -t_stat dsk_write_buf (uint32 dev) -{ -int32 i, da; - -if ((dsk_unit.flags & UNIT_ATT) == 0) { /* !attached? */ - dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */ - CRETIOE (dsk_stopioe, SCPE_UNATT); } -if (dsk_unit.flags & UNIT_WPRT) { /* write prot? */ - dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */ - return SCPE_OK; } -da = dsk_da * DSK_NUMWD * sizeof (uint32); -fseek (dsk_unit.fileref, da, SEEK_SET); /* locate sector */ -fxwrite (dsk_buf, sizeof (uint32), DSK_NUMWD, dsk_unit.fileref); -if (ferror (dsk_unit.fileref)) { /* error? */ - dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */ - return SCPE_IOERR; } -dsk_bptr = 0; /* init bptr */ -dsk_da = (dsk_da + 1) & DSK_AMASK; /* incr disk addr */ -for (i = 0; i < DSK_NUMWD; i++) dsk_buf[i] = 0; /* clear buffer */ -return SCPE_OK; -} - -/* Fill incomplete sector at end of operation. Calculate the number - of packets and set the end of chain flag. -*/ - -t_stat dsk_fill (uint32 dev) -{ -int32 nochn = (dsk_op & CHC_BIN)? 0: 1; /* chain? */ -int32 pktend = (dsk_bptr + ((DSK_PKTWD * 4) - 1)) & /* end pkt */ - ~((DSK_PKTWD * 4) - 1); -int32 pkts = pktend / (DSK_PKTWD * 4); /* # packets */ - -if (dsk_bptr == 0) return SCPE_OK; /* no fill? */ -for ( ; dsk_bptr < pktend; dsk_bptr++) { /* fill packet */ - int32 dsk_wptr = dsk_bptr >> 2; - dsk_buf[dsk_wptr] = (dsk_buf[dsk_wptr] << 6) & DMASK; } -dsk_buf[0] = dsk_buf[0] | (nochn << DSK_V_CHN) | /* insert chain, */ - ((4 - pkts) << DSK_V_PKT); /* num pkts */ -return dsk_write_buf (dev); /* write sec */ -} - -/* Terminate DSK operation */ - -void dsk_end_op (uint32 fl) -{ -if (fl) chan_set_flag (dsk_dib.chan, fl); /* set flags */ -dsk_op = 0; /* clear op */ -xfr_req = xfr_req & ~XFR_DSK; /* clear xfr */ -sim_cancel (&dsk_unit); /* stop */ -if (fl & CHF_ERR) { /* error? */ - chan_disc (dsk_dib.chan); /* disconnect */ - dsk_err = 1; } /* set disk err */ -return; -} - -/* Reset routine */ - -t_stat dsk_reset (DEVICE *dptr) -{ -int32 i; - -chan_disc (dsk_dib.chan); /* disconnect */ -dsk_da = 0; /* clear state */ -dsk_op = 0; -dsk_err = 0; -dsk_bptr = dsk_blnt = 0; -xfr_req = xfr_req & ~XFR_DSK; /* clr xfr req */ -sim_cancel (&dsk_unit); /* deactivate */ -dsk_unit.cyl = 0; -for (i = 0; i < DSK_NUMWD; i++) dsk_buf[i] = 0; /* clear buffer */ -return SCPE_OK; -} diff --git a/SDS/sds_io.c b/SDS/sds_io.c deleted file mode 100644 index 702ea412..00000000 --- a/SDS/sds_io.c +++ /dev/null @@ -1,886 +0,0 @@ -/* sds_io.c: SDS 940 I/O simulator - - Copyright (c) 2001-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. -*/ - -#include "sds_defs.h" - -/* Data chain word */ - -#define CHD_INT 040 /* int on chain */ -#define CHD_PAGE 037 /* new page # */ - -/* Interlace POT */ - -#define CHI_V_WC 14 /* word count */ -#define CHI_M_WC 01777 -#define CHI_GETWC(x) (((x) >> CHI_V_WC) & CHI_M_WC) -#define CHI_V_MA 0 /* mem address */ -#define CHI_M_MA 037777 -#define CHI_GETMA(x) (((x) >> CHI_V_MA) & CHI_M_MA) - -/* System interrupt POT */ - -#define SYI_V_GRP 18 /* group */ -#define SYI_M_GRP 077 -#define SYI_GETGRP(x) (((x) >> SYI_V_GRP) & SYI_M_GRP) -#define SYI_DIS (1 << 17) /* disarm if 0 */ -#define SYI_ARM (1 << 16) /* arm if 1 */ -#define SYI_M_INT 0177777 /* interrupt */ - -/* Pseudo-device number for EOM/SKS mode 3 */ - -#define I_GETDEV3(x) ((((x) & 020046000) != 020046000)? ((x) & DEV_MASK): DEV_MASK) - -#define TST_XFR(d,c) (xfr_req && dev_map[d][c]) -#define SET_XFR(d,c) xfr_req = xfr_req | dev_map[d][c] -#define CLR_XFR(d,c) xfr_req = xfr_req & ~dev_map[d][c] -#define INV_DEV(d,c) (dev_dsp[d][c] == NULL) -#define VLD_DEV(d,c) (dev_dsp[d][c] != NULL) -#define TST_EOR(c) (chan_flag[c] & CHF_EOR) -#define QAILCE(a) (((a) >= POT_ILCY) && ((a) < (POT_ILCY + NUM_CHAN))) - -uint8 chan_uar[NUM_CHAN]; /* unit addr */ -uint16 chan_wcr[NUM_CHAN]; /* word count */ -uint16 chan_mar[NUM_CHAN]; /* mem addr */ -uint8 chan_dcr[NUM_CHAN]; /* data chain */ -uint32 chan_war[NUM_CHAN]; /* word assembly */ -uint8 chan_cpw[NUM_CHAN]; /* char per word */ -uint8 chan_cnt[NUM_CHAN]; /* char count */ -uint16 chan_mode[NUM_CHAN]; /* mode */ -uint16 chan_flag[NUM_CHAN]; /* flags */ -static const char *chname[NUM_CHAN] = - { "W", "Y", "C", "D", "E", "F", "G", "H" }; - -extern uint32 M[MAXMEMSIZE]; /* memory */ -extern uint32 int_req; /* int req */ -extern uint32 xfr_req; /* xfer req */ -extern uint32 alert; /* pin/pot alert */ -extern uint32 X, EM2, EM3, OV, ion, bpt; -extern uint32 nml_mode, usr_mode, rtc_pie; -extern int32 stop_invins, stop_invdev, stop_inviop; -extern int32 mon_usr_trap; -extern UNIT cpu_unit; -extern FILE *sim_log; -extern DEVICE *sim_devices[]; - -t_stat chan_reset (DEVICE *dptr); -t_stat chan_read (int32 ch); -t_stat chan_write (int32 ch); -void chan_write_mem (int32 ch); -void chan_flush_war (int32 ch); -uint32 chan_mar_inc (int32 ch); -t_stat chan_eor (int32 ch); -t_stat pot_ilc (uint32 num, uint32 *dat); -t_stat pot_dcr (uint32 num, uint32 *dat); -t_stat pin_adr (uint32 num, uint32 *dat); -t_stat pot_fork (uint32 num, uint32 *dat); -t_stat dev_disc (uint32 ch, uint32 dev); -t_stat dev_wreor (uint32 ch, uint32 dev); -extern t_stat pot_RL1 (uint32 num, uint32 *dat); -extern t_stat pot_RL2 (uint32 num, uint32 *dat); -extern t_stat pot_RL4 (uint32 num, uint32 *dat); -extern t_stat pin_rads (uint32 num, uint32 *dat); -extern t_stat pot_rada (uint32 num, uint32 *dat); -extern t_stat pin_dsk (uint32 num, uint32 *dat); -extern t_stat pot_dsk (uint32 num, uint32 *dat); -t_stat pin_mux (uint32 num, uint32 *dat); -t_stat pot_mux (uint32 num, uint32 *dat); -extern void set_dyn_map (void); - -/* SDS I/O model - - A device is modeled by its interactions with a channel. Devices can only be - accessed via channels. Each channel has its own device address space. This - means devices can only be accessed from a specific channel. - - I/O operations start with a channel connect. The EOM instruction is passed - to the device via the conn routine. This routine is also used for non-channel - EOM's to the device. For channel connects, the device must remember the - channel number. - - The device responds (after a delay) by setting its XFR_RDY flag. This causes - the channel to invoke either the read or write routine (for input or output) - to get or put the next character. If the device is an asynchronous output - device, it calls routine chan_set_ordy to see if there is output available. - If there is, XFR_RDY is set; if not, the channel is marked to wake the - attached device when output is available. This prevents invalid rate errors. - - Output may be terminated by a write end of record, a disconnect, or both. - Write end of record occurs when the word count reaches zero on an IORD or IORP - operation. It also occurs if a TOP instruction is issued. The device is - expected to respond by setting the end of record indicator in the channel, - which will in turn trigger an end of record interrupt. - - When the channel operation completes, the channel disconnects and calls the - disconnect processor to perform any device specific cleanup. The differences - between write end of record and disconnect are subtle. On magtape output, - for example, both signal end of record; but write end of record allows the - magtape to continue moving, while disconnect halts its motion. - - Valid devices supply a routine to handle potentially all I/O operations - (connect, disconnect, read, write, write end of record, sks). There are - separate routines for PIN and POT. - - Channels could, optionally, handle 12b or 24b characters. The simulator can - support all widths. -*/ - -t_stat chan_show_reg (FILE *st, UNIT *uptr, int32 val, void *desc); - -struct aldisp { - t_stat (*pin) (uint32 num, uint32 *dat); /* altnum, *dat */ - t_stat (*pot) (uint32 num, uint32 *dat); /* altnum, *dat */ - }; - -/* Channel data structures - - chan_dev channel device descriptor - chan_unit channel unit descriptor - chan_reg channel register list -*/ - -UNIT chan_unit = { UDATA (NULL, 0, 0) }; - -REG chan_reg[] = { - { BRDATA (UAR, chan_uar, 8, 6, NUM_CHAN) }, - { BRDATA (WCR, chan_wcr, 8, 15, NUM_CHAN) }, - { BRDATA (MAR, chan_mar, 8, 16, NUM_CHAN) }, - { BRDATA (DCR, chan_dcr, 8, 6, NUM_CHAN) }, - { BRDATA (WAR, chan_war, 8, 24, NUM_CHAN) }, - { BRDATA (CPW, chan_cpw, 8, 2, NUM_CHAN) }, - { BRDATA (CNT, chan_cnt, 8, 3, NUM_CHAN) }, - { BRDATA (MODE, chan_mode, 8, 12, NUM_CHAN) }, - { BRDATA (FLAG, chan_flag, 8, CHF_N_FLG, NUM_CHAN) }, - { NULL } }; - -MTAB chan_mod[] = { - { MTAB_XTD | MTAB_VDV | MTAB_NMO, CHAN_W, "W", NULL, - NULL, &chan_show_reg, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, CHAN_Y, "Y", NULL, - NULL, &chan_show_reg, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, CHAN_C, "C", NULL, - NULL, &chan_show_reg, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, CHAN_D, "D", NULL, - NULL, &chan_show_reg, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, CHAN_E, "E", NULL, - NULL, &chan_show_reg, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, CHAN_F, "F", NULL, - NULL, &chan_show_reg, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, CHAN_G, "G", NULL, - NULL, &chan_show_reg, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, CHAN_H, "H", NULL, - NULL, &chan_show_reg, NULL } }; - -DEVICE chan_dev = { - "CHAN", &chan_unit, chan_reg, chan_mod, - 1, 8, 8, 1, 8, 8, - NULL, NULL, &chan_reset, - NULL, NULL, NULL }; - -/* Tables */ - -static const uint32 int_zc[8] = { - INT_WZWC, INT_YZWC, INT_CZWC, INT_DZWC, - INT_EZWC, INT_FZWC, INT_GZWC, INT_HZWC }; - -static const uint32 int_er[8] = { - INT_WEOR, INT_YEOR, INT_CEOR, INT_DEOR, - INT_EEOR, INT_FEOR, INT_GEOR, INT_HEOR }; - -/* dev_map maps device and channel numbers to a transfer flag masks */ - -uint32 dev_map[64][NUM_CHAN]; - -/* dev_dsp maps device and channel numbers to dispatch routines */ - -t_stat (*dev_dsp[64][NUM_CHAN])() = { NULL }; - -/* dev_dsp maps system device numbers to dispatch routines */ - -t_stat (*dev3_dsp[64])() = { NULL }; - -/* dev_alt maps alert numbers to dispatch routines */ - -struct aldisp dev_alt[] = { - { NULL, NULL }, - { NULL, &pot_ilc }, { NULL, &pot_ilc }, - { NULL, &pot_ilc }, { NULL, &pot_ilc }, - { NULL, &pot_ilc }, { NULL, &pot_ilc }, - { NULL, &pot_ilc }, { NULL, &pot_ilc }, - { NULL, &pot_dcr }, { NULL, &pot_dcr }, - { NULL, &pot_dcr }, { NULL, &pot_dcr }, - { NULL, &pot_dcr }, { NULL, &pot_dcr }, - { NULL, &pot_dcr }, { NULL, &pot_dcr }, - { &pin_adr, NULL }, { &pin_adr, NULL }, - { &pin_adr, NULL }, { &pin_adr, NULL }, - { &pin_adr, NULL }, { &pin_adr, NULL }, - { &pin_adr, NULL }, { &pin_adr, NULL }, - { NULL, &pot_RL1 }, { NULL, &pot_RL2 }, - { NULL, &pot_RL4 }, - { &pin_rads, NULL }, { NULL, &pot_rada }, - { &pin_dsk, &pot_dsk }, { NULL, &pot_fork }, - { &pin_mux, &pot_mux } }; - -/* Single word I/O instructions */ - -t_stat op_wyim (uint32 inst, uint32 *dat) -{ -int32 ch, dev; - -ch = (inst & 000200000)? CHAN_W: CHAN_Y; /* get chan# */ -dev = chan_uar[ch] & DEV_MASK; /* get dev # */ -if (chan_cnt[ch] <= chan_cpw[ch]) { /* buffer empty? */ - if (dev == 0) return STOP_INVIOP; /* no device? dead */ - return STOP_IONRDY; } /* hang until full */ -*dat = chan_war[ch]; /* get data */ -chan_war[ch] = 0; /* reset war */ -chan_cnt[ch] = 0; /* reset cnt */ -return SCPE_OK; -} - -t_stat op_miwy (uint32 inst, uint32 dat) -{ -int32 ch, dev; - -ch = (inst & 000200000)? CHAN_W: CHAN_Y; /* get chan# */ -dev = chan_uar[ch] & DEV_MASK; /* get dev # */ -if (chan_cnt[ch] != 0) { /* buffer full? */ - if (dev == 0) return STOP_INVIOP; /* no device? dead */ - return STOP_IONRDY; } /* hang until full */ -chan_war[ch] = dat; /* get data */ -chan_cnt[ch] = chan_cpw[ch] + 1; /* buffer full */ -if (chan_flag[ch] & CHF_OWAK) { /* output wake? */ - if (VLD_DEV (dev, ch)) SET_XFR (dev, ch); /* wake channel */ - chan_flag[ch] = chan_flag[ch] & ~CHF_OWAK; } /* clear wake */ -return SCPE_OK; -} - -t_stat op_pin (uint32 *dat) -{ -uint32 al = alert; /* local copy */ - -alert = 0; /* clear alert */ -if ((al == 0) || (dev_alt[al].pin == NULL)) CRETIOP; /* inv alert? */ -return dev_alt[al].pin (al, dat); /* PIN from dev */ -} - -t_stat op_pot (uint32 dat) -{ -uint32 al = alert; /* local copy */ - -alert = 0; /* clear alert */ -if ((al == 0) || (dev_alt[al].pot == NULL)) CRETIOP; /* inv alert? */ -return dev_alt[al].pot (al, &dat); /* POT to dev */ -} - -/* EOM/EOD */ - -t_stat op_eomd (uint32 inst) -{ -uint32 mod = I_GETIOMD (inst); /* get mode */ -uint32 ch = I_GETEOCH (inst); /* get chan # */ -uint32 dev = inst & DEV_MASK; /* get dev # */ -uint32 ch_dev = chan_uar[ch] & DEV_MASK; /* chan curr dev # */ -t_stat r; - -switch (mod) { -case 0: /* IO control */ - if (dev) { /* new dev? */ - if (ch_dev) CRETIOP; /* chan act? err */ - if (INV_DEV (dev, ch)) CRETDEV; /* inv dev? err */ - chan_war[ch] = chan_cnt[ch] = 0; /* init chan */ - chan_flag[ch] = chan_dcr[ch] = 0; - chan_mode[ch] = chan_uar[ch] = 0; - if (ch > CHAN_E) chan_mode[ch] = CHM_CE; - if (r = dev_dsp[dev][ch] (IO_CONN, inst, NULL)) /* connect */ - return r; - if ((inst & I_IND) || (ch >= CHAN_C)) { /* C-H? alert ilc */ - alert = POT_ILCY + ch; - chan_mar[ch] = chan_wcr[ch] = 0; } - if (chan_flag[ch] & CHF_24B) chan_cpw[ch] = 0; /* 24B? 1 ch/wd */ - else if (chan_flag[ch] & CHF_12B) /* 12B? 2 ch/wd */ - chan_cpw[ch] = CHC_GETCPW (inst) & 1; - else chan_cpw[ch] = CHC_GETCPW (inst); /* 6b, 1-4 ch/wd */ - chan_uar[ch] = dev; /* connected */ - if ((dev & DEV_OUT) && ion && !QAILCE (alert)) /* out, prog IO? */ - int_req = int_req | int_zc[ch]; } /* initial intr */ - else return dev_disc (ch, ch_dev); /* disconnect */ - break; -case 1: /* buf control */ - if (QAILCE (alert)) { /* ilce alerted? */ - ch = alert - POT_ILCY; /* derive chan */ - if (ch >= CHAN_E) inst = inst | CHM_CE; /* DACC? ext */ - chan_mode[ch] = inst; /* save mode */ - chan_mar[ch] = (CHM_GETHMA (inst) << 14) | /* get hi mar */ - (chan_mar[ch] & CHI_M_MA); - chan_wcr[ch] = (CHM_GETHWC (inst) << 10) | /* get hi wc */ - (chan_wcr[ch] & CHI_M_WC); } - else if (dev) { /* dev EOM */ - if (INV_DEV (dev, ch)) CRETDEV; /* inv dev? err */ - return dev_dsp[dev][ch] (IO_EOM1, inst, NULL); } - else { /* chan EOM */ - inst = inst & 047677; - if (inst == 040000) { /* alert ilce */ - alert = POT_ILCY + ch; - chan_mar[ch] = chan_wcr[ch] = 0; } - else if (inst == 002000) alert = POT_ADRY + ch; /* alert addr */ - else if (inst == 001000) alert = POT_DCRY + ch; /* alert DCR */ - else if (inst == 004000) { /* term output */ - if (ch_dev & DEV_OUT) { /* to output dev? */ - if (chan_cnt[ch] || (chan_flag[ch] & CHF_ILCE)) /* busy, DMA in prog? */ - chan_flag[ch] = chan_flag[ch] | CHF_TOP; /* TOP pending */ - else return dev_wreor (ch, ch_dev); /* idle, write EOR */ - } /* end else TOP */ - else if (ch_dev & DEV_MT) { /* change to scan? */ - chan_uar[ch] = chan_uar[ch] | DEV_MTS; /* change dev addr */ - chan_flag[ch] = chan_flag[ch] | CHF_SCAN; /* set scan flag */ - } /* end else change scan */ - } /* end else term output */ - } /* end else chan EOM */ - break; -case 2: /* internal */ - if (ch >= CHAN_E) { /* EOD? */ - if (inst & 00300) { /* set EM? */ - if (inst & 00100) EM2 = inst & 07; - if (inst & 00200) EM3 = (inst >> 3) & 07; - set_dyn_map (); } - break; } /* end if EOD */ - if (inst & 00001) OV = 0; /* clr OV */ - if (inst & 00002) ion = 1; /* ion */ - else if (inst & 00004) ion = 0; /* iof */ - if ((inst & 00010) && (((X >> 1) ^ X) & EXPS)) OV = 1; - if (inst & 00020) alert = POT_SYSI; /* alert sys int */ - if (inst & 00100) rtc_pie = 1; /* arm clk pls */ - else if (inst & 00200) rtc_pie = 0; /* disarm pls */ - if ((inst & 01400) == 01400) alert = POT_RL4; /* alert RL4 */ - else if (inst & 00400) alert = POT_RL1; /* alert RL1 */ - else if (inst & 01000) alert = POT_RL2; /* alert RL2 */ - if (inst & 02000) { /* nml to mon */ - nml_mode = usr_mode = 0; - if (inst & 00400) mon_usr_trap = 1; } - break; -case 3: /* special */ - dev = I_GETDEV3 (inst); /* special device */ - if (dev3_dsp[dev]) /* defined? */ - return dev3_dsp[dev] (IO_CONN, inst, NULL); - CRETINS; } /* end case */ -return SCPE_OK; -} - -/* Skip if not signal */ - -t_stat op_sks (uint32 inst, uint32 *dat) -{ -uint32 mod = I_GETIOMD (inst); /* get mode */ -uint32 ch = I_GETSKCH (inst); /* get chan # */ -uint32 dev = inst & DEV_MASK; /* get dev # */ - -*dat = 0; -if ((ch == 4) && !(inst & 037774)) { /* EM test */ - if (((inst & 0001) && (EM2 != 2)) || - ((inst & 0002) && (EM3 != 3))) *dat = 1; - return SCPE_OK; } -switch (mod) { -case 1: /* ch, dev */ - if (dev) { /* device */ - if (INV_DEV (dev, ch)) CRETDEV; /* inv dev? err */ - dev_dsp[dev][ch] (IO_SKS, inst, dat); } /* do test */ - else { /* channel */ - if (((inst & 04000) && (chan_uar[ch] == 0)) || - ((inst & 02000) && (chan_wcr[ch] == 0)) || - ((inst & 01000) && ((chan_flag[ch] & CHF_ERR) == 0)) || - ((inst & 00400) && (chan_flag[ch] & CHF_IREC))) *dat = 1; } - break; -case 2: /* internal test */ - if (inst & 0001) { /* test OV */ - *dat = OV ^ 1; /* skip if off */ - OV = 0; /* and reset */ - break; } - if (((inst & 00002) && !ion) || /* ion, bpt test */ - ((inst & 00004) && ion) || - ((inst & 00010) && ((chan_flag[CHAN_W] & CHF_ERR) == 0)) || - ((inst & 00020) && ((chan_flag[CHAN_Y] & CHF_ERR) == 0)) || - ((inst & 00040) && ((bpt & 001) == 0)) || - ((inst & 00100) && ((bpt & 002) == 0)) || - ((inst & 00200) && ((bpt & 004) == 0)) || - ((inst & 00400) && ((bpt & 010) == 0)) || - ((inst & 01000) && (chan_uar[CHAN_W] == 0)) || - ((inst & 02000) && (chan_uar[CHAN_Y] == 0))) *dat = 1; - break; -case 3: /* special */ - dev = I_GETDEV3 (inst); /* special device */ - if (dev3_dsp[dev]) dev3_dsp[dev] (IO_SKS, inst, dat); - else CRETINS; } /* end case */ -return SCPE_OK; -} - -/* PIN/POT routines */ - -t_stat pot_ilc (uint32 num, uint32 *dat) -{ -uint32 ch = num - POT_ILCY; - -chan_mar[ch] = (chan_mar[ch] & ~CHI_M_MA) | CHI_GETMA (*dat); -chan_wcr[ch] = (chan_wcr[ch] & ~CHI_M_WC) | CHI_GETWC (*dat); -chan_flag[ch] = chan_flag[ch] | CHF_ILCE; -return SCPE_OK; -} - -t_stat pot_dcr (uint32 num, uint32 *dat) -{ -uint32 ch = num - POT_DCRY; - -chan_dcr[ch] = (*dat) & (CHD_INT | CHD_PAGE); -chan_flag[ch] = chan_flag[ch] | CHF_DCHN; -return SCPE_OK; -} - -t_stat pin_adr (uint32 num, uint32 *dat) -{ -uint32 ch = num - POT_ADRY; - -*dat = chan_mar[ch] & PAMASK; -return SCPE_OK; -} - -/* System interrupt POT. - - The SDS 940 timesharing system uses a permanently asserted - system interrupt as a way of forking the teletype input - interrupt handler to a lower priority. The interrupt is - armed to set up the fork, and disarmed in the fork routine */ - -t_stat pot_fork (uint32 num, uint32 *dat) -{ -uint32 igrp = SYI_GETGRP (*dat); /* get group */ -uint32 fbit = (1 << (VEC_FORK & 017)); /* bit in group */ - -if (igrp == (VEC_FORK / 020)) { /* right group? */ - if ((*dat & SYI_ARM) && (*dat & fbit)) /* arm, bit set? */ - int_req = int_req | INT_FORK; - if ((*dat & SYI_DIS) && !(*dat & fbit)) /* disarm, bit clr? */ - int_req = int_req & ~INT_FORK; } -return SCPE_OK; -} - -/* Channel read invokes the I/O device to get the next character and, - if not end of record, assembles it into the word assembly register. - If the interlace is on, the full word is stored in memory. - The key difference points for the various terminal functions are - - end of record comp: EOT interrupt - IORD, IOSD: EOR interrupt, disconnect - IORP, IOSP: EOR interrupt, interrecord - interlace off: comp: EOW interrupt - IORD, IORP: ignore - IOSD, IOSP: overrun error - --wcr == 0: comp: clear interlace - IORD, IORP, IOSP: ZWC interrupt - IOSD: ZWC interrupt, EOR interrupt, disconnect - - Note that the channel can be disconnected if CHN_EOR is set, but must - not be if XFR_REQ is set */ - -t_stat chan_read (int32 ch) -{ -uint32 dat = 0; -uint32 dev = chan_uar[ch] & DEV_MASK; -uint32 tfnc = CHM_GETFNC (chan_mode[ch]); -t_stat r = SCPE_OK; - -if (dev && TST_XFR (dev, ch)) { /* ready to xfr? */ - if (INV_DEV (dev, ch)) CRETIOP; /* can't read? */ - r = dev_dsp[dev][ch] (IO_READ, dev, &dat); /* read data */ - if (r) chan_flag[ch] = chan_flag[ch] | CHF_ERR; /* error? */ - if (chan_flag[ch] & CHF_24B) chan_war[ch] = dat; /* 24B? */ - else if (chan_flag[ch] & CHF_12B) /* 12B? */ - chan_war[ch] = ((chan_war[ch] << 12) | (dat & 07777)) & DMASK; - else chan_war[ch] = ((chan_war[ch] << 6) | (dat & 077)) & DMASK; - if (chan_flag[ch] & CHF_SCAN) /* scanning? */ - chan_cnt[ch] = chan_cpw[ch]; /* never full */ - else chan_cnt[ch] = chan_cnt[ch] + 1; /* insert char */ - if (chan_cnt[ch] > chan_cpw[ch]) { /* full? */ - if (chan_flag[ch] & CHF_ILCE) { /* interlace on? */ - chan_write_mem (ch); /* write to mem */ - if (chan_wcr[ch] == 0) { /* wc zero? */ - chan_flag[ch] = chan_flag[ch] & ~CHF_ILCE; /* clr interlace */ - if ((tfnc != CHM_COMP) && (chan_mode[ch] & CHM_ZC)) - int_req = int_req | int_zc[ch]; /* zwc interrupt */ - if (tfnc == CHM_IOSD) { /* IOSD? also EOR */ - if (chan_mode[ch] & CHM_ER) int_req = int_req | int_er[ch]; - dev_disc (ch, dev); /* disconnect */ - } /* end if IOSD */ - } /* end if wcr == 0 */ - } /* end if ilce on */ - else { /* interlace off */ - if (TST_EOR (ch)) return chan_eor (ch); /* eor? */ - if (tfnc == CHM_COMP) { /* C: EOW, intr */ - if (ion) int_req = int_req | int_zc[ch]; } - else if (tfnc & CHM_SGNL) /* Sx: error */ - chan_flag[ch] = chan_flag[ch] | CHF_ERR; - else chan_cnt[ch] = chan_cpw[ch]; /* Rx: ignore */ - } /* end else ilce */ - } /* end if full */ - } /* end if xfr */ -if (TST_EOR (ch)) { /* end record? */ - if (tfnc == CHM_COMP) chan_flush_war (ch); /* C: fill war */ - else if (chan_cnt[ch]) { /* RX, CX: fill? */ - chan_flush_war (ch); /* fill war */ - if (chan_flag[ch] & CHF_ILCE) /* ilce on? store */ - chan_write_mem (ch); } /* end else if cnt */ - return chan_eor (ch); } /* eot/eor int */ -return r; -} - -void chan_write_mem (int32 ch) -{ -WriteP (chan_mar[ch], chan_war[ch]); /* write to mem */ -chan_mar[ch] = chan_mar_inc (ch); /* incr mar */ -chan_wcr[ch] = (chan_wcr[ch] - 1) & 077777; /* decr wcr */ -chan_war[ch] = 0; /* reset war */ -chan_cnt[ch] = 0; /* reset cnt */ -return; -} - -void chan_flush_war (int32 ch) -{ -int32 i = (chan_cpw[ch] - chan_cnt[ch]) + 1; - -if (i) { - if (chan_flag[ch] & CHF_24B) chan_war[ch] = 0; - else if (chan_flag[ch] & CHF_12B) - chan_war[ch] = (chan_war[ch] << 12) & DMASK; - else chan_war[ch] = (chan_war[ch] << (i * 6)) & DMASK; - chan_cnt[ch] = chan_cpw[ch] + 1; } -return; -} - -/* Channel write gets the next character and sends it to the I/O device. - If this is the last character in an interlace operation, the end of - record operation is invoked. - The key difference points for the various terminal functions are - - end of record: comp: EOT interrupt - IORD, IOSD: EOR interrupt, disconnect - IORP, IOSP: EOR interrupt, interrecord - interlace off: if not end of record, EOW interrupt - --wcr == 0: comp: EOT interrupt, disconnect - IORD, IORP: ignore - IOSD: ZWC interrupt, disconnect - IOSP: ZWC interrupt, interrecord -*/ -t_stat chan_write (int32 ch) -{ -uint32 dat = 0; -uint32 dev = chan_uar[ch] & DEV_MASK; -uint32 tfnc = CHM_GETFNC (chan_mode[ch]); -t_stat r = SCPE_OK; - -if (dev && TST_XFR (dev, ch)) { /* ready to xfr? */ - if (INV_DEV (dev, ch)) CRETIOP; /* invalid dev? */ - if (chan_cnt[ch] == 0) { /* buffer empty? */ - if (chan_flag[ch] & CHF_ILCE) { /* interlace on? */ - chan_war[ch] = ReadP (chan_mar[ch]); - chan_mar[ch] = chan_mar_inc (ch); /* incr mar */ - chan_wcr[ch] = (chan_wcr[ch] - 1) & 077777; /* decr mar */ - chan_cnt[ch] = chan_cpw[ch] + 1; } /* set cnt */ - else { /* ilce off */ - CLR_XFR (dev, ch); /* cant xfr */ - if (TST_EOR (dev)) return chan_eor (ch); /* EOR? */ - chan_flag[ch] = chan_flag[ch] | CHF_ERR; /* rate err */ - return SCPE_OK; } /* end else ilce */ - } /* end if cnt */ - chan_cnt[ch] = chan_cnt[ch] - 1; /* decr cnt */ - if (chan_flag[ch] & CHF_24B) dat = chan_war[ch]; /* 24B? */ - else if (chan_flag[ch] & CHF_12B) { /* 12B? */ - dat = (chan_war[ch] >> 12) & 07777; /* get halfword */ - chan_war[ch] = (chan_war[ch] << 12) & DMASK; } /* remove from war */ - else { /* 6B */ - dat = (chan_war[ch] >> 18) & 077; /* get char */ - chan_war[ch] = (chan_war[ch] << 6) & DMASK; } /* remove from war */ - r = dev_dsp[dev][ch] (IO_WRITE, dev, &dat); /* write */ - if (r) chan_flag[ch] = chan_flag[ch] | CHF_ERR; /* error? */ - if (chan_cnt[ch] == 0) { /* buf empty? */ - if (chan_flag[ch] & CHF_ILCE) { /* ilce on? */ - if (chan_wcr[ch] == 0) { /* wc now 0? */ - chan_flag[ch] = chan_flag[ch] & ~CHF_ILCE; /* ilc off */ - if (tfnc == CHM_COMP) { /* compatible? */ - if (ion) int_req = int_req | int_zc[ch]; - dev_disc (ch, dev); /* disconnnect */ - } /* end if comp */ - else { /* extended */ - if (chan_mode[ch] & CHM_ZC) /* ZWC int */ - int_req = int_req | int_zc[ch]; - if (tfnc == CHM_IOSD) { /* SD */ - if (chan_mode[ch] & CHM_ER) /* EOR int */ - int_req = int_req | int_er[ch]; - dev_disc (ch, dev); /* disconnnect */ - } /* end if SD */ - else if (!(tfnc && CHM_SGNL) || /* IORx or IOSP TOP? */ - (chan_flag[ch] & CHF_TOP)) - dev_wreor (ch, dev); /* R: write EOR */ - chan_flag[ch] = chan_flag[ch] & ~CHF_TOP; - } /* end else comp */ - } /* end if wcr */ - } /* end if ilce */ - else if (chan_flag[ch] & CHF_TOP) { /* off, TOP pending? */ - chan_flag[ch] = chan_flag[ch] & ~CHF_TOP; /* clear TOP */ - dev_wreor (ch, dev); } /* write EOR */ - else if (ion) int_req = int_req | int_zc[ch]; /* no TOP, EOW intr */ - } /* end if cnt */ - } /* end if xfr */ -if (TST_EOR (ch)) return chan_eor (ch); /* eor rcvd? */ -return r; -} - -/* MAR increment */ - -uint32 chan_mar_inc (int32 ch) -{ -uint32 t = (chan_mar[ch] + 1) & PAMASK; /* incr mar */ - -if ((chan_flag[ch] & CHF_DCHN) && ((t & VA_POFF) == 0)) { /* chain? */ - chan_flag[ch] = chan_flag[ch] & ~CHF_DCHN; /* clr flag */ - if (chan_dcr[ch] & CHD_INT) /* if armed, intr */ - int_req = int_req | int_zc[ch]; - t = (chan_dcr[ch] & CHD_PAGE) << VA_V_PN; } /* new mar */ -return t; -} - -/* End of record action */ - -t_stat chan_eor (int32 ch) -{ -uint32 tfnc = CHM_GETFNC (chan_mode[ch]); -uint32 dev = chan_uar[ch] & DEV_MASK; - -chan_flag[ch] = chan_flag[ch] & ~(CHF_EOR | CHF_ILCE); /* clr eor, ilce */ -if (((tfnc == CHM_COMP) && ion) || (chan_mode[ch] & CHM_ER)) - int_req = int_req | int_er[ch]; /* EOT/EOR? */ -if (dev && (tfnc & CHM_PROC)) /* P, still conn? */ - chan_flag[ch] = chan_flag[ch] | CHF_IREC; /* interrecord */ -else return dev_disc (ch, dev); /* disconnect */ -return SCPE_OK; -} - -/* Utility routines */ - -t_stat dev_disc (uint32 ch, uint32 dev) -{ -chan_uar[ch] = 0; /* disconnect */ -if (dev_dsp[dev][ch]) return dev_dsp[dev][ch] (IO_DISC, dev, NULL); -return SCPE_OK; -} - -t_stat dev_wreor (uint32 ch, uint32 dev) -{ -if (dev_dsp[dev][ch]) return dev_dsp[dev][ch] (IO_WREOR, dev, NULL); -chan_flag[ch] = chan_flag[ch] | CHF_EOR; /* set eor */ -return SCPE_OK; -} - -/* Externally visible routines */ -/* Channel driver */ - -t_stat chan_process (void) -{ -int32 i, dev; -t_stat r; - -for (i = 0; i < NUM_CHAN; i++) { /* loop thru */ - dev = chan_uar[i] & DEV_MASK; /* get dev */ - if ((dev && TST_XFR (dev, i)) || TST_EOR (i)) { /* chan active? */ - if (dev & DEV_OUT) r = chan_write (i); /* write */ - else r = chan_read (i); /* read */ - if (r) return r; } } -return SCPE_OK; -} - -/* Test for channel active */ - -t_bool chan_testact (void) -{ -int32 i, dev; - -for (i = 0; i < NUM_CHAN; i++) { - dev = chan_uar[i] & DEV_MASK; - if ((dev && TST_XFR (dev, i)) || TST_EOR (i)) return 1; } -return 0; -} - -/* Async output device ready for more data */ - -void chan_set_ordy (int32 ch) -{ -if ((ch >= 0) && (ch < NUM_CHAN)) { - int32 dev = chan_uar[ch] & DEV_MASK; /* get dev */ - if (chan_cnt[ch] || (chan_flag[ch] & CHF_ILCE)) /* buf or ilce? */ - SET_XFR (dev, ch); /* set xfr flg */ - else chan_flag[ch] = chan_flag[ch] | CHF_OWAK; } /* need wakeup */ -return; -} - -/* Set flag in channel */ - -void chan_set_flag (int32 ch, uint32 fl) -{ -if ((ch >= 0) && (ch < NUM_CHAN)) chan_flag[ch] = chan_flag[ch] | fl; -return; -} - -/* Set UAR in channel */ - -void chan_set_uar (int32 ch, uint32 dev) -{ -if ((ch >= 0) && (ch < NUM_CHAN)) chan_uar[ch] = dev & DEV_MASK; -return; -} - -/* Disconnect channel */ - -void chan_disc (int32 ch) -{ -if ((ch >= 0) && (ch < NUM_CHAN)) chan_uar[ch] = 0; -return; -} - -/* Reset channels */ - -t_stat chan_reset (DEVICE *dptr) -{ -int32 i; - -xfr_req = 0; -for (i = 0; i < NUM_CHAN; i++) { - chan_uar[i] = 0; - chan_wcr[i] = 0; - chan_mar[i] = 0; - chan_dcr[i] = 0; - chan_war[i] = 0; - chan_cpw[i] = 0; - chan_cnt[i] = 0; - chan_mode[i] = 0; - chan_flag[i] = 0; } -return SCPE_OK; -} - -/* Channel assignment routines */ - -t_stat set_chan (UNIT *uptr, int32 val, char *sptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -int32 i; - -if (sptr == NULL) return SCPE_ARG; /* valid args? */ -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -for (i = 0; i < NUM_CHAN; i++) { /* match input */ - if (strcmp (sptr, chname[i]) == 0) { /* find string */ - if (val && !(val & (1 << i))) return SCPE_ARG; /* legal? */ - dibp->chan = i; /* store new */ - return SCPE_OK; } } -return SCPE_ARG; -} - -t_stat show_chan (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -DEVICE *dptr; -DIB *dibp; - -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -fprintf (st, "channel=%s", chname[dibp->chan]); -return SCPE_OK; -} - -/* Init device tables */ - -t_bool io_init (void) -{ -DEVICE *dptr; -DIB *dibp; -DSPT *tplp; -int32 ch; -uint32 i, j, dev, doff; - -/* Clear dispatch table, device map */ - -for (i = 0; i < NUM_CHAN; i++) { - for (j = 0; j < (DEV_MASK + 1); j++) { - dev_dsp[j][i] = NULL; - dev_map[j][i] = 0; } } - -/* Test each device for conflict; add to map; init tables */ - -for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru devices */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if ((dibp == NULL) || (dptr->flags & DEV_DIS)) continue; /* exist, enabled? */ - ch = dibp->chan; /* get channel */ - dev = dibp->dev; /* get device num */ - if (ch < 0) dev3_dsp[dev] = dibp->iop; /* special device */ - else { - if (dibp->tplt == NULL) return TRUE; /* must have template */ - for (tplp = dibp->tplt; tplp->num; tplp++) { /* loop thru templates */ - for (j = 0; j < tplp->num; j++) { /* repeat as needed */ - doff = dev + tplp->off + j; /* get offset dnum */ - if (dev_map[doff][ch]) { /* slot in use? */ - printf ("Device number conflict, chan = %s, devno = %02o\n", - chname[ch], doff); - if (sim_log) fprintf (sim_log, - "Device number conflict, chan = %s, dev = %02o\n", - chname[ch], doff); - return TRUE; } - dev_map[doff][ch] = dibp->xfr; /* set xfr flag */ - dev_dsp[doff][ch] = dibp->iop; /* set dispatch */ - } /* end for j */ - } /* end for tplt */ - } /* end else */ - } /* end for i */ -return FALSE; -} - -/* Display channel state */ - -t_stat chan_show_reg (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if ((val < 0) || (val >= NUM_CHAN)) return SCPE_IERR; -fprintf (st, "UAR: %02o\n", chan_uar[val]); -fprintf (st, "WCR: %05o\n", chan_wcr[val]); -fprintf (st, "MAR: %06o\n", chan_mar[val]); -fprintf (st, "DCR: %02o\n", chan_dcr[val]); -fprintf (st, "WAR: %08o\n", chan_war[val]); -fprintf (st, "CPW: %o\n", chan_cpw[val]); -fprintf (st, "CNT: %o\n", chan_cnt[val]); -fprintf (st, "MODE: %03o\n", chan_mode[val]); -fprintf (st, "FLAG: %04o\n", chan_flag[val]); -return SCPE_OK; -} diff --git a/SDS/sds_lp.c b/SDS/sds_lp.c deleted file mode 100644 index f3e4ffc5..00000000 --- a/SDS/sds_lp.c +++ /dev/null @@ -1,285 +0,0 @@ -/* sds_lp.c: SDS 940 line printer simulator - - Copyright (c) 2001-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - lpt line printer - - 25-Apr-03 RMS Revised for extended file support -*/ - -#include "sds_defs.h" - -#define LPT_V_LN 9 -#define LPT_M_LN 07 -#define LPT_GETLN(x) (((x) >> LPT_V_LN) & LPT_M_LN) -#define CHP(ch,val) ((val) & (1 << (ch))) /* CCL chan test */ -#define SET_XFR 1 /* set xfr */ -#define SET_EOR 2 /* print, set eor */ -#define SET_SPC 4 /* space */ - -extern char sds_to_ascii[64]; -extern uint32 xfr_req; -extern int32 stop_invins, stop_invdev, stop_inviop; -int32 lpt_spc = 0; /* space instr */ -int32 lpt_sta = 0; /* timeout state */ -int32 lpt_bptr = 0; /* line buf ptr */ -int32 lpt_err = 0; /* error */ -int32 lpt_ccl = 1, lpt_ccp = 0; /* cctl lnt, ptr */ -int32 lpt_ctime = 10; /* char time */ -int32 lpt_ptime = 1000; /* print time */ -int32 lpt_stime = 10000; /* space time */ -int32 lpt_stopioe = 1; /* stop on err */ -char lpt_buf[LPT_WIDTH + 1] = { 0 }; /* line buffer */ -uint8 lpt_cct[CCT_LNT] = { 0377 }; /* car ctl tape */ -DSPT lpt_tplt[] = { { 1, 0 }, { 0, 0 } }; /* template */ - -DEVICE lpt_dev; -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); -t_stat lpt_attach (UNIT *uptr, char *cptr); -t_stat lpt_crctl (int32 ch); -t_stat lpt_status (UNIT *uptr); -t_stat lpt_bufout (UNIT *uptr); -void lpt_end_op (int32 fl); -t_stat lpt (uint32 fnc, uint32 inst, uint32 *dat); - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list -*/ - -DIB lpt_dib = { CHAN_W, DEV_LPT, XFR_LPT, lpt_tplt, &lpt }; - -UNIT lpt_unit = { - UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0) }; - -REG lpt_reg[] = { - { BRDATA (BUF, lpt_buf, 8, 8, LPT_WIDTH) }, - { DRDATA (BPTR, lpt_bptr, 8), PV_LEFT }, - { FLDATA (XFR, xfr_req, XFR_V_LPT) }, - { FLDATA (ERR, lpt_err, 0) }, - { ORDATA (STA, lpt_sta, 3) }, - { BRDATA (CCT, lpt_cct, 8, 8, CCT_LNT) }, - { DRDATA (CCTP, lpt_ccp, 8), PV_LEFT }, - { DRDATA (CCTL, lpt_ccl, 8), REG_RO + PV_LEFT }, - { ORDATA (SPCINST, lpt_spc, 24) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (CTIME, lpt_ctime, 24), REG_NZ + PV_LEFT }, - { DRDATA (PTIME, lpt_ptime, 24), REG_NZ + PV_LEFT }, - { DRDATA (STIME, lpt_stime, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, lpt_stopioe, 0) }, - { NULL } }; - -MTAB lpt_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL", - &set_chan, &show_chan, NULL }, - { 0 } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, lpt_mod, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &lpt_reset, - NULL, &lpt_attach, NULL, - &lpt_dib, DEV_DISABLE }; - -/* Line printer routine - - conn - inst = EOM0, dat = NULL - eom1 - inst = EOM1, dat = NULL - sks - inst = SKS, dat = ptr to result - disc - inst = device number, dat = NULL - wreor - inst = device number, dat = NULL - read - inst = device number, dat = ptr to data - write - inst = device number, dat = ptr to result - - The line printer is an asynchronous output device, that is, it - can never set the channel rate error flag. -*/ - -t_stat lpt (uint32 fnc, uint32 inst, uint32 *dat) -{ -int32 i, t, new_ch; -char asc; - -switch (fnc) { /* case function */ -case IO_CONN: /* connect */ - new_ch = I_GETEOCH (inst); /* get new chan */ - if (new_ch != lpt_dib.chan) return SCPE_IERR; /* wrong chan? */ - for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = 0; /* clr buffer */ - lpt_bptr = 0; /* clr buf ptr */ - lpt_err = 0; /* err = 0 */ - xfr_req = xfr_req & ~XFR_LPT; /* clr xfr flag */ - lpt_sta = lpt_sta | SET_XFR; /* need xfr */ - sim_activate (&lpt_unit, lpt_ctime); /* start timer */ - break; - -case IO_EOM1: /* EOM mode 1 */ - new_ch = I_GETEOCH (inst); /* get new chan */ - if (new_ch != lpt_dib.chan) CRETIOP; /* wrong chan? */ - if (inst & 0400) { /* space? */ - lpt_spc = inst; /* save instr */ - lpt_sta = lpt_sta | SET_SPC; /* need space */ - sim_cancel (&lpt_unit); /* cancel timer */ - sim_activate (&lpt_unit, lpt_stime); } /* start timer */ - break; - -case IO_DISC: /* disconnect */ - lpt_end_op (0); /* normal term */ - return lpt_bufout (&lpt_unit); /* dump output */ - -case IO_WREOR: /* write eor */ - lpt_sta = (lpt_sta | SET_EOR) & ~SET_XFR; /* need eor */ - sim_activate (&lpt_unit, lpt_ptime); /* start timer */ - break; - -case IO_SKS: /* SKS */ - new_ch = I_GETSKCH (inst); /* sks chan */ - if (new_ch != lpt_dib.chan) return SCPE_IERR; /* wrong chan? */ - t = I_GETSKCND (inst); /* sks cond */ - if (((t == 020) && (!CHP (7, lpt_cct[lpt_ccp]))) || /* 14062: !ch 7 */ - ((t == 010) && (lpt_unit.flags & UNIT_ATT)) || /* 12062: !online */ - (t == 004) && !lpt_err) *dat = 1; /* 11062: !err */ - break; - -case IO_WRITE: /* write */ - asc = sds_to_ascii[(*dat) & 077]; /* convert data */ - xfr_req = xfr_req & ~XFR_LPT; /* clr xfr flag */ - if (lpt_bptr < LPT_WIDTH) lpt_buf[lpt_bptr++] = asc;/* store data */ - lpt_sta = lpt_sta | SET_XFR; /* need xfr */ - sim_activate (&lpt_unit, lpt_ctime); /* start ch timer */ - break; - -default: - CRETINS; } -return SCPE_OK; -} - -/* Unit service and write */ - -t_stat lpt_svc (UNIT *uptr) -{ -t_stat r = SCPE_OK; -static const char *lpt_stabl[] = { - "\r", "\n", "\n\n", "\n\n\n", - "\n\n\n\n", "\n\n\n\n\n", - "\n\n\n\n\n\n", "\n\n\n\n\n\n\n" }; - -if (lpt_sta & SET_XFR) chan_set_ordy (lpt_dib.chan); /* need lpt xfr? */ -if (lpt_sta & SET_EOR) { /* printing? */ - chan_set_flag (lpt_dib.chan, CHF_EOR); /* set eor flg */ - r = lpt_bufout (uptr); } /* output buf */ -if (lpt_sta & SET_SPC) { /* spacing? */ - if (uptr->flags & UNIT_ATT) { /* attached? */ - int32 ln = LPT_GETLN (lpt_spc); /* get lines, ch */ - if (lpt_spc & 0200) /* n lines? */ - fputs (lpt_stabl[ln], uptr->fileref); /* upspace */ - else lpt_crctl (ln); } /* carriage ctl */ - r = lpt_status (uptr); } /* update status */ -lpt_sta = 0; /* clear state */ -return r; -} - -/* Trim and output buffer */ - -t_stat lpt_bufout (UNIT *uptr) -{ -int32 i; - -if ((uptr->flags & UNIT_ATT) && lpt_bptr) { /* attached? */ - for (i = LPT_WIDTH - 1; (i >= 0) && (lpt_buf[i] == ' '); i--) - lpt_buf[i] = 0; /* trim line */ - fputs (lpt_buf, uptr->fileref); /* write line */ - lpt_bptr = 0; } -return lpt_status (uptr); /* return status */ -} - -/* Status update after I/O */ - -t_stat lpt_status (UNIT *uptr) -{ -if (uptr->flags & UNIT_ATT) { /* attached? */ - uptr->pos = ftell (uptr->fileref); /* update position */ - if (ferror (uptr->fileref)) { /* I/O error? */ - lpt_end_op (CHF_EOR | CHF_ERR); /* set err, disc */ - perror ("LPT I/O error"); /* print msg */ - clearerr (uptr->fileref); - return SCPE_IOERR; } } /* ret error */ -else { - lpt_end_op (CHF_EOR | CHF_ERR); /* set err, disc */ - CRETIOE (lpt_stopioe, SCPE_UNATT); } /* ret error */ -return SCPE_OK; -} - -/* Terminate LPT operation */ - -void lpt_end_op (int32 fl) -{ -if (fl) chan_set_flag (lpt_dib.chan, fl); /* set flags */ -xfr_req = xfr_req & ~XFR_LPT; /* clear xfr */ -sim_cancel (&lpt_unit); /* stop */ -if (fl & CHF_ERR) { /* error? */ - chan_disc (lpt_dib.chan); /* disconnect */ - lpt_err = 1; } /* set lpt err */ -return; -} - -/* Carriage control */ - -t_stat lpt_crctl (int32 ch) -{ -int32 i, j; - -if ((ch == 1) && CHP (ch, lpt_cct[0])) { /* top of form? */ - fputs ("\f\n", lpt_unit.fileref); /* ff + nl */ - lpt_ccp = 0; /* top of page */ - return SCPE_OK; } -for (i = 1; i < lpt_ccl + 1; i++) { /* sweep thru cct */ - lpt_ccp = (lpt_ccp + 1) %lpt_ccl; /* adv pointer */ - if (CHP (ch, lpt_cct[lpt_ccp])) { /* chan punched? */ - for (j = 0; j < i; j++) fputc ('\n', lpt_unit.fileref); - return SCPE_OK; } } -return STOP_CCT; /* runaway channel */ -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ -chan_disc (lpt_dib.chan); /* disconnect */ -lpt_spc = 0; /* clr state */ -lpt_sta = 0; -xfr_req = xfr_req & ~XFR_LPT; /* clr xfr flag */ -sim_cancel (&lpt_unit); /* deactivate */ -return SCPE_OK; -} - -/* Attach routine */ - -t_stat lpt_attach (UNIT *uptr, char *cptr) -{ -lpt_ccp = 0; /* top of form */ -return attach_unit (uptr, cptr); -} diff --git a/SDS/sds_mt.c b/SDS/sds_mt.c deleted file mode 100644 index 7d62a81d..00000000 --- a/SDS/sds_mt.c +++ /dev/null @@ -1,443 +0,0 @@ -/* sds_mt.c: SDS 940 magnetic tape simulator - - Copyright (c) 2001-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - mt 7 track magnetic tape - - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Revised for magtape library - - Magnetic tapes are represented as a series of variable 8b records - of the form: - - 32b record length in bytes - exact number - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32b record length in bytes - exact number - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a single record length of 0. - End of tape is two consecutive end of file marks. -*/ - -#include "sds_defs.h" -#include "sim_tape.h" - -#define MT_MAXFR (32768 * 4) -#define MT_NUMDR 8 /* number drives */ -#define MT_UNIT 07 -#define botf u3 /* bot tape flag */ -#define eotf u4 /* eot tape flag */ - -extern uint32 xfr_req; -extern int32 stop_invins, stop_invdev, stop_inviop; -int32 mt_inst = 0; /* saved instr */ -int32 mt_eof = 0; /* end of file */ -int32 mt_gap = 0; /* in gap */ -int32 mt_skip = 0; /* skip rec */ -int32 mt_bptr = 0; /* buf ptr */ -int32 mt_blnt = 0; /* buf length */ -int32 mt_ctime = 10; /* char time */ -int32 mt_gtime = 1000; /* gap time */ -int32 mt_stopioe = 1; /* stop on err */ -uint8 mtxb[MT_MAXFR]; /* record buffer */ -DSPT mt_tplt[] = { /* template */ - { MT_NUMDR, 0 }, { MT_NUMDR, DEV_MTS }, - { MT_NUMDR, DEV_OUT }, { MT_NUMDR, DEV_MTS+DEV_OUT }, - { 0, 0 } }; - -DEVICE mt_dev; -t_stat mt_svc (UNIT *uptr); -t_stat mt_reset (DEVICE *dptr); -t_stat mt_boot (int32 unitno, DEVICE *dptr); -t_stat mt_attach (UNIT *uptr, char *cptr); -t_stat mt_detach (UNIT *uptr); -t_stat mt_readrec (UNIT *uptr); -t_mtrlnt mt_readbc (UNIT *uptr); -void mt_readend (UNIT *uptr); -t_stat mt_wrend (uint32 dev); -void mt_set_err (UNIT *uptr); -t_stat mt (uint32 fnc, uint32 inst, uint32 *dat); - -static const char sds_to_bcd[64] = { - 012, 001, 002, 003, 004, 005, 006, 007, - 010, 011, 012, 013, 014, 015, 016, 017, - 060, 061, 062, 063, 064, 065, 066, 067, - 070, 071, 072, 073, 074, 075, 076, 077, - 040, 041, 042, 043, 044, 045, 046, 047, - 050, 051, 052, 053, 054, 055, 056, 057, - 020, 021, 022, 023, 024, 025, 026, 027, - 030, 031, 032, 033, 034, 035, 036, 037 }; - -static const char bcd_to_sds[64] = { - 000, 001, 002, 003, 004, 005, 006, 007, - 010, 011, 000, 013, 014, 015, 016, 017, - 060, 061, 062, 063, 064, 065, 066, 067, - 070, 071, 072, 073, 074, 075, 076, 077, - 040, 041, 042, 043, 044, 045, 046, 047, - 050, 051, 052, 053, 054, 055, 056, 057, - 020, 021, 022, 023, 024, 025, 026, 027, - 030, 031, 032, 033, 034, 035, 036, 037 }; - -/* MT data structures - - mt_dev MT device descriptor - mt_unit MT unit descriptor - mt_reg MT register list -*/ - -DIB mt_dib = { CHAN_W, DEV_MT, XFR_MT0, mt_tplt, &mt }; - -UNIT mt_unit[] = { - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) } }; - -REG mt_reg[] = { - { BRDATA (BUF, mtxb, 8, 8, MT_MAXFR) }, - { DRDATA (BPTR, mt_bptr, 18), PV_LEFT }, - { DRDATA (BLNT, mt_blnt, 18), PV_LEFT }, - { FLDATA (XFR, xfr_req, XFR_V_MT0) }, - { ORDATA (INST, mt_inst, 24) }, - { FLDATA (EOF, mt_eof, 0) }, - { FLDATA (GAP, mt_gap, 0) }, - { FLDATA (SKIP, mt_skip, 0) }, - { DRDATA (CTIME, mt_ctime, 24), REG_NZ + PV_LEFT }, - { DRDATA (GTIME, mt_gtime, 24), REG_NZ + PV_LEFT }, - { URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0, - MT_NUMDR, PV_LEFT | REG_RO) }, - { URDATA (BOT, mt_unit[0].botf, 10, 1, 0, MT_NUMDR, REG_RO) }, - { URDATA (EOT, mt_unit[0].eotf, 10, 1, 0, MT_NUMDR, REG_RO) }, - { FLDATA (STOP_IOE, mt_stopioe, 0) }, - { NULL } }; - -MTAB mt_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL", - &set_chan, &show_chan, NULL }, - { 0 } }; - -DEVICE mt_dev = { - "MT", mt_unit, mt_reg, mt_mod, - MT_NUMDR, 10, 31, 1, 8, 8, - NULL, NULL, &mt_reset, - &mt_boot, &mt_attach, NULL, - &mt_dib, DEV_DISABLE }; - -/* Mag tape routine - - conn - inst = EOM0, dat = NULL - eom1 - inst = EOM1, dat = NULL - sks - inst = SKS, dat = ptr to result - disc - inst = device number, dat = NULL - wreor - inst = device number, dat = NULL - read - inst = device number, dat = ptr to data - write - inst = device number, dat = ptr to result -*/ - -t_stat mt (uint32 fnc, uint32 inst, uint32 *dat) -{ -int32 u = inst & MT_UNIT; /* get unit */ -UNIT *uptr = mt_dev.units + u; /* get unit ptr */ -int32 t, new_ch; -uint8 chr; -t_stat r; - -switch (fnc) { /* case function */ -case IO_CONN: /* connect */ - new_ch = I_GETEOCH (inst); /* get new chan */ - if (new_ch != mt_dib.chan) return SCPE_IERR; /* wrong chan? */ - if (mt_gap) { /* in gap? */ - mt_gap = 0; /* clr gap flg */ - sim_cancel (uptr); } /* cancel timer */ - else if (sim_is_active (uptr)) CRETIOP; /* busy? */ - uptr->eotf = 0; /* clr eot flag */ - mt_eof = 0; /* clr eof flag */ - mt_skip = 0; /* clr skp flag */ - mt_bptr = mt_blnt = 0; /* init buffer */ - if ((inst & DEV_MTS)? (CHC_GETCPW (inst) < 2): /* scn & cpw<3? */ - (inst & CHC_REV)) return STOP_INVIOP; /* rw & rev? */ - mt_inst = inst; /* save inst */ - if ((inst & DEV_MTS) && !(inst && DEV_OUT)) /* scanning? */ - chan_set_flag (mt_dib.chan, CHF_SCAN); /* set chan flg */ - xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */ - sim_activate (uptr, mt_gtime); /* start timer */ - break; - -case IO_EOM1: /* EOM mode 1 */ - new_ch = I_GETEOCH (inst); /* get new chan */ - if (new_ch != mt_dib.chan) CRETIOP; /* wrong chan? */ - t = inst & 07670; /* get command */ - if ((t == 04010) && !sim_is_active (uptr)) { /* rewind? */ - sim_tape_rewind (uptr); /* rewind unit */ - uptr->eotf = 0; /* clr eot */ - uptr->botf = 1; } /* set bot */ - else if ((t == 03610) && sim_is_active (uptr) && /* skip rec? */ - ((mt_inst & DEV_OUT) == 0)) mt_skip = 1; /* set flag */ - else CRETINS; - break; - -case IO_DISC: /* disconnect */ - sim_cancel (uptr); /* no more xfr's */ - if (inst & DEV_OUT) { /* write? */ - if (r = mt_wrend (inst)) return r; } /* end record */ - break; - -case IO_WREOR: /* write eor */ - chan_set_flag (mt_dib.chan, CHF_EOR); /* set eor flg */ - if (r = mt_wrend (inst)) return r; /* end record */ - mt_gap = 1; /* in gap */ - sim_activate (uptr, mt_gtime); /* start timer */ - break; - -case IO_SKS: /* SKS */ - new_ch = I_GETSKCH (inst); /* get chan # */ - if (new_ch != mt_dib.chan) return SCPE_IERR; /* wrong chan? */ - if ((inst & (DEV_OUT | DEV_MTS)) == 0) { /* not sks 1n? */ - t = I_GETSKCND (inst); /* get skip cond */ - switch (t) { /* case sks cond */ - case 001: /* sks 1021n */ - *dat = 1; /* not magpak */ - break; - case 002: /* sks 1041n */ - if (!(uptr->flags & UNIT_ATT) || /* not ready */ - sim_is_active (uptr)) *dat = 1; - break; - case 004: /* sks 1101n */ - if (!uptr->eotf) *dat = 1; /* not EOT */ - break; - case 010: /* sks 1201n */ - if (!uptr->botf) *dat = 1; /* not BOT */ - break; - case 013: /* sks 12610 */ - if (!mt_gap) *dat = 1; /* not in gap */ - break; - case 017: /* sks 13610 */ - if (!mt_eof) *dat = 1; /* not EOF */ - break; - case 020: /* sks 1401n */ - if (!sim_tape_wrp (uptr)) *dat = 1; /* not wrp */ - break; - case 031: /* sks 1621n */ - case 033: /* sks 1661n */ - *dat = 1; /* not 556bpi */ - case 035: /* sks 1721n */ - break; } /* not 800bpi */ - } /* end if */ - break; - -case IO_READ: /* read */ - xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */ - if (mt_blnt == 0) { /* first read? */ - r = mt_readrec (uptr); /* get data */ - if ((r != SCPE_OK) || (mt_blnt == 0)) return r; } /* err, inv reclnt? */ - uptr->botf = 0; /* off BOT */ - if (mt_inst & CHC_REV) chr = mtxb[--mt_bptr] & 077; /* get next rev */ - else chr = mtxb[mt_bptr++] & 077; /* get next fwd */ - if (!(mt_inst & CHC_BIN)) chr = bcd_to_sds[chr]; /* bcd? */ - *dat = chr & 077; /* give to chan */ - if ((mt_inst & CHC_REV)? (mt_bptr <= 0): /* rev or fwd, */ - (mt_bptr >= mt_blnt)) mt_readend (uptr); /* recd done? */ - break; - -case IO_WRITE: /* write */ - uptr->botf = 0; /* off BOT */ - chr = (*dat) & 077; - xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */ - if (!(mt_inst & CHC_BIN)) chr = sds_to_bcd[chr]; /* bcd? */ - if (mt_bptr < MT_MAXFR) mtxb[mt_bptr++] = chr; /* insert in buf */ - break; - -default: - CRETINS; } - -return SCPE_OK; -} - -/* Unit service */ - -t_stat mt_svc (UNIT *uptr) -{ -if (mt_gap) { /* gap timeout */ - mt_gap = 0; /* clr gap flg */ - chan_disc (mt_dib.chan); } /* disc chan */ -else if (mt_skip) mt_readend (uptr); /* skip record */ -else { /* normal xfr */ - xfr_req = xfr_req | XFR_MT0; /* set xfr req */ - sim_activate (uptr, mt_ctime); } /* reactivate */ -return SCPE_OK; -} - -/* Read start (get new record) */ - -t_stat mt_readrec (UNIT *uptr) -{ -t_mtrlnt tbc; -t_stat st, r = SCPE_OK; - -if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ - mt_set_err (uptr); /* no, err, disc */ - return SCPE_UNATT; } -if (mt_inst & CHC_REV) /* reverse? */ - st = sim_tape_rdrecr (uptr, mtxb, &tbc, MT_MAXFR); /* read rec rev */ -else st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* no, fwd */ -if (st == MTSE_TMK) { /* tape mark? */ - mt_eof = 1; /* set eof flag */ - mtxb[0] = mtxb[1] = 017; /* EOR char */ - mt_blnt = 2; /* store 2 */ - return SCPE_OK; } -if (st != MTSE_OK) { /* other error? */ - mt_set_err (uptr); /* err, disc */ - if (st == MTSE_IOERR) return SCPE_IOERR; /* IO error? */ - if (st == MTSE_INVRL) return SCPE_MTRLNT; /* inv rec lnt? */ - if (st == MTSE_EOM) uptr->eotf = 1; /* eom? set eot */ - return SCPE_OK; } -mt_blnt = tbc; /* set buf lnt */ -return SCPE_OK; -} - -/* Read done (eof, end of record) */ - -void mt_readend (UNIT *uptr) -{ -sim_cancel (uptr); /* stop timer */ -mt_skip = 0; /* clr skp flg */ -chan_set_flag (mt_dib.chan, CHF_EOR); /* end record */ -if (mt_eof) chan_disc (mt_dib.chan); /* EOF? */ -else { - mt_gap = 1; /* no, in gap */ - sim_activate (uptr, mt_gtime); } /* start timer */ -return; -} - -/* Write complete (end of record or disconnect) */ - -t_stat mt_wrend (uint32 dev) -{ -UNIT *uptr = mt_dev.units + (dev & MT_UNIT); -t_mtrlnt tbc; -t_stat st; - -sim_cancel (uptr); /* no more xfr's */ -if (mt_bptr == 0) return SCPE_OK; /* buf empty? */ -if (!(uptr->flags & UNIT_ATT)) { /* attached? */ - mt_set_err (uptr); /* no, err, disc */ - return SCPE_UNATT; } -if (sim_tape_wrp (uptr)) { /* write lock? */ - mt_set_err (uptr); /* yes, err, disc */ - return SCPE_OK; } -if (dev & DEV_MTS) { /* erase? */ - if (mt_inst & CHC_REV) /* reverse? */ - sim_tape_sprecr (uptr, &tbc); /* backspace */ - st = sim_tape_wreom (uptr); /* write eom */ - } -else { - if ((mt_bptr == 1) && (mtxb[0] == 017) && /* wr eof? */ - ((mt_inst & 01670) == 00050)) - st = sim_tape_wrtmk (uptr); /* write tape mark */ - else st = sim_tape_wrrecf (uptr, mtxb, mt_bptr); /* write record */ - } -mt_bptr = 0; -if (st != MTSE_OK) mt_set_err (uptr); /* error? */ -if (st == MTSE_IOERR) return SCPE_IOERR; -return SCPE_OK; -} - -/* Fatal error */ - -void mt_set_err (UNIT *uptr) -{ -chan_set_flag (mt_dib.chan, CHF_EOR | CHF_ERR); /* eor, error */ -chan_disc (mt_dib.chan); /* disconnect */ -xfr_req = xfr_req & ~XFR_MT0; /* clear xfr */ -sim_cancel (uptr); /* stop */ -mt_bptr = 0; /* buf empty */ -return; -} -/* Reset routine */ - -t_stat mt_reset (DEVICE *dptr) -{ -int32 i; - -chan_disc (mt_dib.chan); /* disconnect */ -mt_eof = 0; /* clear state */ -mt_gap = 0; -mt_skip = 0; -mt_inst = 0; -mt_bptr = mt_blnt = 0; -xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */ -for (i = 0; i < MT_NUMDR; i++) { /* deactivate */ - sim_cancel (&mt_unit[i]); - sim_tape_reset (&mt_unit[i]); - mt_unit[i].eotf = 0; } -return SCPE_OK; -} - -/* Attach and detach routines */ - -t_stat mt_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; -uptr->botf = 1; -uptr->eotf = 0; -return SCPE_OK; -} - -t_stat mt_detach (UNIT *uptr) -{ -uptr->botf = uptr->eotf = 0; -return sim_tape_detach (uptr); -} - -/* Boot routine - simulate FILL console command */ - -t_stat mt_boot (int32 unitno, DEVICE *dptr) -{ -extern uint32 P, M[]; - -if (unitno) return SCPE_ARG; /* only unit 0 */ -M[0] = 077777771; /* -7B */ -M[1] = 007100000; /* LDX 0 */ -M[2] = 000203610; /* EOM 3610B */ -M[3] = 003200002; /* WIM 2 */ -M[4] = 000100002; /* BRU 2 */ -P = 1; /* start at 1 */ -return SCPE_OK; -} diff --git a/SDS/sds_mux.c b/SDS/sds_mux.c deleted file mode 100644 index 65192e08..00000000 --- a/SDS/sds_mux.c +++ /dev/null @@ -1,506 +0,0 @@ -/* sds_mux.c: SDS 940 terminal multiplexor simulator - - Copyright (c) 2001-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - mux terminal multiplexor - - 09-May-03 RMS Added network device flag - - This module implements up to 32 individual serial interfaces, representing - either the project Genie terminal multiplexor or the SDS 940 CTE option. -*/ - -#include "sds_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" -#include - -#define PROJ_GENIE (cpu_unit.flags & UNIT_GENIE) -#define MUX_NUMLIN mux_desc.lines - -#define MUX_LINES 32 /* lines */ -#define MUX_FLAGS 4 /* intr per line */ -#define MUX_FLAGMASK (MUX_FLAGS - 1) -#define MUX_SCANMAX (MUX_LINES * MUX_FLAGS) /* flags to scan */ -#define MUX_SCANMASK (MUX_SCANMAX - 1) -#define UNIT_V_UC (UNIT_V_UF + 0) /* UC only */ -#define UNIT_UC (1 << UNIT_V_UC) -#define MUX_INIT_POLL 8000 -#define MUXL_WAIT 500 -#define MUX_SETFLG(l,x) mux_flags[((l) * MUX_FLAGS) + (x)] = 1 -#define MUX_SETINT(x) int_req = int_req | (INT_MUXR >> (x)) -#define MUX_CLRINT(x) int_req = int_req & ~(INT_MUXR >> (x)) - -/* PIN/POT */ - -#define P_V_CHAR 16 /* char */ -#define P_M_CHAR 0377 -#define P_CHAR(x) (((x) >> P_V_CHAR) & P_M_CHAR) -#define PIN_OVR 000100000 /* overrun */ -#define POT_NOX 000100000 /* no xmit */ -#define POT_XMI 000040000 /* xmit int */ -#define POT_GLNE 000020000 /* Genie: enable */ -#define POT_SCDT 000020000 /* 940: clr DTR */ -#define P_V_CHAN 0 /* channel */ -#define P_M_CHAN (MUX_LINES - 1) -#define P_CHAN(x) (((x) >> P_V_CHAN) & P_M_CHAN) - -/* SKS 940 */ - -#define SKS_XBE 000001000 /* xmt buf empty */ -#define SKS_CRO 000000400 /* carrier on */ -#define SKS_DSR 000000200 /* data set ready */ -#define SKS_CHAN(x) P_CHAN(x) - -/* SKS Genie */ - -#define SKG_V_CHAN 7 -#define SKG_M_CHAN (MUX_LINES - 1) -#define SKG_CHAN(x) (((x) >> SKG_V_CHAN) & SKG_M_CHAN) - -/* Flags */ - -#define MUX_FRCV 0 /* receive */ -#define MUX_FXMT 1 /* transmit */ -#define MUX_FCRN 2 /* carrier on */ -#define MUX_FCRF 3 /* carrier off */ - -/* Line status */ - -#define MUX_SCHP 001 /* char pending */ -#define MUX_SOVR 002 /* overrun */ -#define MUX_SLNE 004 /* line enabled */ -#define MUX_SXIE 010 /* xmt int enab */ -#define MUX_SCRO 020 /* carrier on */ -#define MUX_SDSR 040 /* data set ready */ - -/* Data */ -extern uint32 alert, int_req; -extern int32 stop_invins, stop_invdev, stop_inviop; -extern UNIT cpu_unit; - -uint8 mux_rbuf[MUX_LINES]; /* rcv buf */ -uint8 mux_xbuf[MUX_LINES]; /* xmt buf */ -uint8 mux_sta[MUX_LINES]; /* status */ -uint8 mux_flags[MUX_SCANMAX]; /* flags */ -uint32 mux_tps = 100; /* polls/second */ -uint32 mux_scan = 0; /* scanner */ -uint32 mux_slck = 0; /* scanner locked */ - -TMLN mux_ldsc[MUX_LINES] = { 0 }; /* line descriptors */ -TMXR mux_desc = { MUX_LINES, 0, 0, NULL }; /* mux descriptor */ - -t_stat mux (uint32 fnc, uint32 inst, uint32 *dat); -t_stat muxi_svc (UNIT *uptr); -t_stat muxo_svc (UNIT *uptr); -t_stat mux_reset (DEVICE *dptr); -t_stat mux_attach (UNIT *uptr, char *cptr); -t_stat mux_detach (UNIT *uptr); -t_stat mux_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat mux_show (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat mux_vlines (UNIT *uptr, int32 val, char *cptr, void *desc); -void mux_reset_ln (int32 ln); -void mux_scan_next (void); - -/* MUX data structures - - mux_dev MUX device descriptor - mux_unit MUX unit descriptor - mux_reg MUX register list - mux_mod MUX modifiers list -*/ - -DIB mux_dib = { -1, DEV3_GMUX, 0, NULL, &mux }; - -REG mux_nlreg = { DRDATA (NLINES, MUX_NUMLIN, 6), PV_LEFT }; - -UNIT mux_unit = { UDATA (&muxi_svc, UNIT_ATTABLE, 0), MUX_INIT_POLL }; - -REG mux_reg[] = { - { BRDATA (STA, mux_sta, 8, 6, MUX_LINES) }, - { BRDATA (RBUF, mux_rbuf, 8, 8, MUX_LINES) }, - { BRDATA (XBUF, mux_xbuf, 8, 8, MUX_LINES) }, - { BRDATA (INT, mux_flags, 8, 1, MUX_SCANMAX) }, - { ORDATA (SCAN, mux_scan, 7) }, - { FLDATA (SLCK, mux_slck, 0) }, - { DRDATA (TPS, mux_tps, 8), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB mux_mod[] = { - { MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES", - &mux_vlines, NULL, &mux_nlreg }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &mux_desc }, - { UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &mux_summ }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &mux_show, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &mux_show, NULL }, - { 0 } }; - -DEVICE mux_dev = { - "MUX", &mux_unit, mux_reg, mux_mod, - 1, 10, 31, 1, 8, 8, - &tmxr_ex, &tmxr_dep, &mux_reset, - NULL, &mux_attach, &mux_detach, - &mux_dib, DEV_NET | DEV_DISABLE }; - -/* MUXL data structures - - muxl_dev MUXL device descriptor - muxl_unit MUXL unit descriptor - muxl_reg MUXL register list - muxl_mod MUXL modifiers list -*/ - -UNIT muxl_unit[] = { - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT } }; - -MTAB muxl_mod[] = { - { UNIT_UC, 0, "lower case", "LC", NULL }, - { UNIT_UC, UNIT_UC, "upper case", "UC", NULL }, - { 0 } }; - -REG muxl_reg[] = { - { URDATA (TIME, muxl_unit[0].wait, 10, 24, 0, - MUX_LINES, REG_NZ + PV_LEFT) }, - { NULL } }; - -DEVICE muxl_dev = { - "MUXL", muxl_unit, muxl_reg, muxl_mod, - MUX_LINES, 10, 31, 1, 8, 8, - NULL, NULL, &mux_reset, - NULL, NULL, NULL, - NULL, 0 }; - -/* MUX: IO routine */ - -/* Mux routine - EOM 30001 or EOM 77777,2 */ - -t_stat mux (uint32 fnc, uint32 inst, uint32 *dat) -{ -uint32 ln; - -switch (fnc) { -case IO_CONN: /* connect */ - if ((PROJ_GENIE && (inst == 000230001)) || /* set alert */ - (!PROJ_GENIE && (inst == 020277777))) alert = POT_MUX; - else CRETINS; - break; -case IO_SKS: /* skip */ - if (PROJ_GENIE && ((inst & 077770077) == 004030001)) { - ln = SKG_CHAN (inst); /* get line */ - if (!sim_is_active (&muxl_unit[ln])) *dat = 1; } - else if (!PROJ_GENIE && ((inst & 077776000) == 024076000)) { - ln = SKS_CHAN (inst); /* get line */ - if (inst & (SKS_XBE|SKS_CRO|SKS_DSR)) *dat = 1; - if (((inst & SKS_XBE) && sim_is_active (&muxl_unit[ln])) || - ((inst & SKS_CRO) && !(mux_sta[ln] & MUX_SCRO)) || - ((inst & SKS_DSR) && !(mux_sta[ln] & MUX_SDSR))) - *dat = 0; } /* no skip if fail */ - else CRETINS; -default: - return SCPE_IERR; } /* end case */ -return SCPE_OK; -} - -/* PIN routine */ - -t_stat pin_mux (uint32 num, uint32 *dat) -{ -uint32 ln = mux_scan >> 2; -uint32 flag = mux_scan & MUX_FLAGMASK; - -mux_scan = mux_scan & MUX_SCANMASK; /* mask scan */ -mux_flags[mux_scan] = 0; /* clear flag */ -if (flag == MUX_FRCV) { /* rcv event? */ - *dat = ln | ((uint32) mux_rbuf[ln] << P_V_CHAR) | /* line + char + */ - ((mux_sta[ln] & MUX_SOVR)? PIN_OVR: 0); /* overrun */ - mux_sta[ln] = mux_sta[ln] & ~(MUX_SCHP | MUX_SOVR); } -else *dat = ln; /* just line */ -mux_slck = 0; /* unlock scanner */ -mux_scan_next (); /* kick scanner */ -return SCPE_OK; -} - -t_stat pot_mux (uint32 num, uint32 *dat) -{ -uint32 ln = P_CHAN (*dat); -uint32 chr = P_CHAR (*dat); - -if (PROJ_GENIE && ((*dat & POT_GLNE) == 0)) { /* Genie disable? */ - mux_sta[ln] = mux_sta[ln] & ~MUX_SLNE; /* clear status */ - mux_ldsc[ln].rcve = 0; } -else if (!PROJ_GENIE && (*dat & POT_SCDT)) { /* SDS disable? */ - if (mux_ldsc[ln].conn) { /* connected? */ - tmxr_msg (mux_ldsc[ln].conn, "\r\nLine hangup\r\n"); - tmxr_reset_ln (&mux_ldsc[ln]); /* reset line */ - mux_reset_ln (ln); /* reset state */ - MUX_SETFLG (ln, MUX_FCRF); /* set carrier off */ - mux_scan_next (); } /* kick scanner */ - mux_sta[ln] = mux_sta[ln] & ~MUX_SLNE; /* clear status */ - mux_ldsc[ln].rcve = 0; } -else { /* enabled */ - if ((*dat & POT_NOX) == 0) { /* output char? */ - mux_xbuf[ln] = chr; /* store char */ - sim_activate (&muxl_unit[ln], muxl_unit[ln].wait); } - if (*dat & POT_XMI) mux_sta[ln] = mux_sta[ln] | MUX_SXIE; - else mux_sta[ln] = mux_sta[ln] & ~MUX_SXIE; - mux_sta[ln] = mux_sta[ln] | MUX_SLNE; /* line is enabled */ - mux_ldsc[ln].rcve = 1; } -return SCPE_OK; -} - -/* Unit service - receive side - - Poll all active lines for input - Poll for new connections -*/ - -t_stat muxi_svc (UNIT *uptr) -{ -int32 ln, c, t; - -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ -t = sim_rtcn_calb (mux_tps, TMR_MUX); /* calibrate */ -sim_activate (uptr, t); /* continue poll */ -ln = tmxr_poll_conn (&mux_desc); /* look for connect */ -if (ln >= 0) { /* got one? */ - if (!PROJ_GENIE && (mux_sta[ln] & MUX_SLNE)) { /* modem & DTR? */ - mux_sta[ln] = mux_sta[ln] | (MUX_SCRO|MUX_SDSR);/* carrier on */ - MUX_SETFLG (ln, MUX_FCRN); /* set carr on flag */ - mux_scan_next (); } /* kick scanner */ - mux_ldsc[ln].rcve = 1; } /* set rcv enable */ -tmxr_poll_rx (&mux_desc); /* poll for input */ -for (ln = 0; ln < MUX_NUMLIN; ln++) { /* loop thru lines */ - if (mux_ldsc[ln].conn) { /* connected? */ - if (c = tmxr_getc_ln (&mux_ldsc[ln])) { /* get char */ - if (mux_sta[ln] & MUX_SCHP) /* already got one? */ - mux_sta[ln] = mux_sta[ln] | MUX_SOVR; /* overrun */ - else mux_sta[ln] = mux_sta[ln] | MUX_SCHP; /* char pending */ - c = c & 0177; /* mask to 7b */ - if ((muxl_unit[ln].flags & UNIT_UC) && /* cvt to UC? */ - islower (c & 0x7F)) c = toupper (c); - mux_rbuf[ln] = c; /* save char */ - MUX_SETFLG (ln, MUX_FRCV); /* set rcv flag */ - mux_scan_next (); } } /* kick scanner */ - else mux_sta[ln] = 0; /* disconnected */ - } /* end for */ -return SCPE_OK; -} - -/* Unit service - transmit side */ - -t_stat muxo_svc (UNIT *uptr) -{ -int32 c; -uint32 ln = uptr - muxl_unit; /* line # */ - -if (mux_ldsc[ln].conn) { /* connected? */ - if (mux_ldsc[ln].xmte) { /* xmt enabled? */ - c = mux_xbuf[ln] & 0177; /* get char */ - if ((muxl_unit[ln].flags & UNIT_UC) && islower (c)) - c = toupper (c); /* cvt to UC? */ - tmxr_putc_ln (&mux_ldsc[ln], c); /* output char */ - tmxr_poll_tx (&mux_desc); } /* poll xmt */ - else { /* buf full */ - tmxr_poll_tx (&mux_desc); /* poll xmt */ - sim_activate (uptr, muxl_unit[ln].wait); /* wait */ - return SCPE_OK; } } -if (mux_sta[ln] & MUX_SXIE) { - MUX_SETFLG (ln, MUX_FXMT); /* set flag */ - mux_scan_next (); } /* kick scanner */ -return SCPE_OK; -} - -/* Kick scanner */ - -void mux_scan_next (void) -{ -int32 i; - -if (mux_slck) return; /* locked? */ -for (i = 0; i < MUX_SCANMAX; i++) { /* scan flags */ - mux_scan = (mux_scan + 1) & MUX_SCANMASK; /* next flag */ - if (mux_flags[mux_scan]) { /* flag set? */ - mux_slck = 1; /* lock scanner */ - MUX_SETINT (mux_scan & MUX_FLAGMASK); /* request int */ - return; } - } -return; -} - -/* Reset routine */ - -t_stat mux_reset (DEVICE *dptr) -{ -int32 i, t; - -if (mux_dev.flags & DEV_DIS) /* master disabled? */ - muxl_dev.flags = muxl_dev.flags | DEV_DIS; /* disable lines */ -else muxl_dev.flags = muxl_dev.flags & ~DEV_DIS; -if (mux_unit.flags & UNIT_ATT) { /* master att? */ - if (!sim_is_active (&mux_unit)) { - t = sim_rtcn_init (mux_unit.wait, TMR_MUX); - sim_activate (&mux_unit, t); } } /* activate */ -else sim_cancel (&mux_unit); /* else stop */ -for (i = 0; i < MUX_LINES; i++) { - mux_desc.ldsc[i] = &mux_ldsc[i]; - mux_reset_ln (i); } -for (i = 0; i < MUX_FLAGS; i++) MUX_CLRINT (i); /* clear all ints */ -return SCPE_OK; -} - -/* Attach master unit */ - -t_stat mux_attach (UNIT *uptr, char *cptr) -{ -t_stat r; -int32 t; - -r = tmxr_attach (&mux_desc, uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error */ -t = sim_rtcn_init (mux_unit.wait, TMR_MUX); -sim_activate (uptr, t); /* start poll */ -return SCPE_OK; -} - -/* Detach master unit */ - -t_stat mux_detach (UNIT *uptr) -{ -int32 i; -t_stat r; - -r = tmxr_detach (&mux_desc, uptr); /* detach */ -for (i = 0; i < MUX_LINES; i++) mux_ldsc[i].rcve = 0; /* disable rcv */ -sim_cancel (uptr); /* stop poll */ -return r; -} - -/* Show summary processor */ - -t_stat mux_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < MUX_LINES; i++) t = t + (mux_ldsc[i].conn != 0); -if (t == 1) fprintf (st, "1 connection"); -else fprintf (st, "%d connections", t); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat mux_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i; - -for (i = 0; (i < MUX_LINES) && (mux_ldsc[i].conn == 0); i++) ; -if (i < MUX_LINES) { - for (i = 0; i < MUX_LINES; i++) { - if (mux_ldsc[i].conn) - if (val) tmxr_fconns (st, &mux_ldsc[i], i); - else tmxr_fstats (st, &mux_ldsc[i], i); } } -else fprintf (st, "all disconnected\n"); -return SCPE_OK; -} - -/* Change number of lines */ - -t_stat mux_vlines (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 newln, i, t; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -newln = get_uint (cptr, 10, MUX_LINES, &r); -if ((r != SCPE_OK) || (newln == MUX_NUMLIN)) return r; -if (newln == 0) return SCPE_ARG; -if (newln < MUX_NUMLIN) { - for (i = newln, t = 0; i < MUX_NUMLIN; i++) t = t | mux_ldsc[i].conn; - if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) - return SCPE_OK; - for (i = newln; i < MUX_NUMLIN; i++) { - if (mux_ldsc[i].conn) { - tmxr_msg (mux_ldsc[i].conn, "\r\nOperator disconnected line\r\n"); - tmxr_reset_ln (&mux_ldsc[i]); } /* reset line */ - muxl_unit[i].flags = muxl_unit[i].flags | UNIT_DIS; - mux_reset_ln (i); } - } -else { - for (i = MUX_NUMLIN; i < newln; i++) { - muxl_unit[i].flags = muxl_unit[i].flags & ~UNIT_DIS; - mux_reset_ln (i); } - } -MUX_NUMLIN = newln; -return SCPE_OK; -} - -/* Reset an individual line */ - -void mux_reset_ln (int32 ln) -{ -int32 flg = ln * MUX_FLAGS; - -if (mux_ldsc[ln].conn) mux_sta[ln] = MUX_SCRO | MUX_SDSR; -else mux_sta[ln] = 0; -sim_cancel (&muxl_unit[ln]); -mux_flags[flg + MUX_FRCV] = 0; -mux_flags[flg + MUX_FXMT] = 0; -mux_flags[flg + MUX_FCRN] = 0; -mux_flags[flg + MUX_FCRF] = 0; -return; -} diff --git a/SDS/sds_rad.c b/SDS/sds_rad.c deleted file mode 100644 index d111ba4d..00000000 --- a/SDS/sds_rad.c +++ /dev/null @@ -1,290 +0,0 @@ -/* sds_rad.c: SDS 940 fixed head disk simulator - - Copyright (c) 2001-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - rad fixed head disk - - The fixed head disk is a head-per-track disk, with up to four disks. Each - disk is divided into two logical units. Reads and writes cannot cross logical - unit boundaries. The fixed head disk transfers 12b characters, rather than 6b - characters. To minimize overhead, the disk is buffered in memory. -*/ - -#include "sds_defs.h" -#include - -/* Constants */ - -#define RAD_NUMWD 64 /* words/sector */ -#define RAD_NUMSC 64 /* sectors/track */ -#define RAD_NUMTR 64 /* tracks/log unit */ -#define RAD_NUMLU 8 /* log units/ctrl */ -#define RAD_SCSIZE (RAD_NUMLU*RAD_NUMTR*RAD_NUMSC) /* sectors/disk */ -#define RAD_AMASK (RAD_SCSIZE - 1) /* sec addr mask */ -#define RAD_SIZE (RAD_SCSIZE * RAD_NUMWD) /* words/disk */ -#define RAD_GETLUN(x) ((x) / (RAD_NUMTR * RAD_NUMSC)) -#define RAD_SCMASK (RAD_NUMSC - 1) /* sector mask */ -#define RAD_TRSCMASK ((RAD_NUMSC * RAD_NUMTR) - 1) /* track/sec mask */ - -#define GET_SECTOR(x) ((int) fmod (sim_gtime() / ((double) (x)), \ - ((double) RAD_NUMSC))) - -extern uint32 xfr_req; -extern uint32 alert; -extern int32 stop_invins, stop_invdev, stop_inviop; -int32 rad_err = 0; /* error */ -int32 rad_nobi = 0; /* !incr x track */ -int32 rad_da = 0; /* disk address */ -int32 rad_sba = 0; /* sec byte addr */ -int32 rad_wrp = 0; /* write prot */ -int32 rad_time = 2; /* time per 12b */ -int32 rad_stopioe = 1; /* stop on error */ -DSPT rad_tplt[] = { /* template */ - { 1, 0 }, { 1, DEV_OUT }, { 0, 0 } }; - -DEVICE rad_dev; -t_stat rad_svc (UNIT *uptr); -t_stat rad_reset (DEVICE *dptr); -t_stat rad_fill (int32 sba); -void rad_end_op (int32 fl); -int32 rad_adjda (int32 sba, int32 inc); -t_stat rad (uint32 fnc, uint32 inst, uint32 *dat); - -/* RAD data structures - - rad_dev device descriptor - rad_unit unit descriptor - rad_reg register list -*/ - -DIB rad_dib = { CHAN_E, DEV_RAD, XFR_RAD, rad_tplt, &rad }; - -UNIT rad_unit = - { UDATA (&rad_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, - RAD_SIZE) }; - -REG rad_reg[] = { - { ORDATA (DA, rad_da, 15) }, - { GRDATA (SA, rad_sba, 8, 6, 1) }, - { FLDATA (BP, rad_sba, 0) }, - { FLDATA (XFR, xfr_req, XFR_V_RAD) }, - { FLDATA (NOBD, rad_nobi, 0) }, - { FLDATA (ERR, rad_err, 0) }, - { ORDATA (PROT, rad_wrp, 8) }, - { DRDATA (TIME, rad_time, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, rad_stopioe, 0) }, - { NULL } }; - -MTAB rad_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL", - &set_chan, &show_chan, NULL }, - { 0 } }; - -DEVICE rad_dev = { - "RAD", &rad_unit, rad_reg, rad_mod, - 1, 8, 21, 1, 8, 24, - NULL, NULL, &rad_reset, - NULL, NULL, NULL, - &rad_dib, DEV_DISABLE }; - -/* Fixed head disk routine - - conn - inst = EOM0, dat = NULL - eom1 - inst = EOM1, dat = NULL - sks - inst = SKS, dat = ptr to result - disc - inst = device number, dat = NULL - wreor - inst = device number, dat = NULL - read - inst = device number, dat = ptr to data - write - inst = device number, dat = ptr to result -*/ - -t_stat rad (uint32 fnc, uint32 inst, uint32 *dat) -{ -int32 t, lun, new_ch; -uint32 *wptr; -uint32 p; - -switch (fnc) { /* case function */ -case IO_CONN: /* connect */ - new_ch = I_GETEOCH (inst); /* get new chan */ - if (new_ch != rad_dib.chan) return SCPE_IERR; /* wrong chan? */ - if (CHC_GETCPW (inst) > 1) return STOP_INVIOP; /* 1-2 char/word? */ - if (sim_is_active (&rad_unit) || (alert == POT_RADA)) /* protocol viol? */ - return STOP_INVIOP; - rad_err = 0; /* clr error */ - rad_sba = 0; /* clr sec bptr */ - chan_set_flag (rad_dib.chan, CHF_12B); /* 12B mode */ - t = (rad_da & RAD_SCMASK) - GET_SECTOR (rad_time * RAD_NUMWD); - if (t <= 0) t = t + RAD_NUMSC; /* seek */ - sim_activate (&rad_unit, t * rad_time * (RAD_NUMWD / 2)); - xfr_req = xfr_req & ~XFR_RAD; /* clr xfr flg */ - break; - -case IO_EOM1: /* EOM mode 1 */ - new_ch = I_GETEOCH (inst); /* get new chan */ - if (new_ch != rad_dib.chan) return SCPE_IERR; /* wrong chan? */ - if ((inst & 00600) == 00200) alert = POT_RADS; /* alert for sec */ - else if ((inst & 06600) == 0) { /* alert for addr */ - if (sim_is_active (&rad_unit)) rad_err = 1; /* busy? */ - else { - rad_nobi = (inst & 01000)? 1: 0; /* save inc type */ - alert = POT_RADA; } } /* set alert */ - break; - -case IO_DISC: /* disconnect */ - rad_end_op (0); /* normal term */ - if (inst & DEV_OUT) return rad_fill (rad_sba); /* fill write */ - break; - -case IO_WREOR: /* write eor */ - rad_end_op (CHF_EOR); /* eor term */ - return rad_fill (rad_sba); /* fill write */ - -case IO_SKS: /* SKS */ - new_ch = I_GETSKCH (inst); /* sks chan */ - if (new_ch != rad_dib.chan) return SCPE_IERR; /* wrong chan? */ - t = I_GETSKCND (inst); /* sks cond */ - lun = RAD_GETLUN (rad_da); - if (((t == 000) && !sim_is_active (&rad_unit)) || /* 10026: ready */ - ((t == 004) && !rad_err) || /* 11026: !err */ - ((t == 014) && !(rad_wrp & (1 << lun)))) /* 13026: !wrprot */ - *dat = 1; - break; - -case IO_READ: /* read */ - p = (rad_da * RAD_NUMWD) + (rad_sba >> 1); /* buf wd addr */ - xfr_req = xfr_req & ~XFR_RAD; /* clr xfr req */ - if ((rad_unit.flags & UNIT_BUF) == 0) { /* not buffered? */ - rad_end_op (CHF_ERR | CHF_EOR); /* set rad err */ - CRETIOE (rad_stopioe, SCPE_UNATT); } - if (p >= rad_unit.capac) { /* end of disk? */ - rad_end_op (CHF_ERR | CHF_EOR); /* set rad err */ - return SCPE_OK; } - wptr = ((uint32 *) rad_unit.filebuf) + p; /* ptr to word */ - if (rad_sba & 1) *dat = *wptr & 07777; /* odd byte? */ - else *dat = (*wptr >> 12) & 07777; /* even */ - rad_sba = rad_adjda (rad_sba, 1); /* next byte */ - break; - -case IO_WRITE: - p = (rad_da * RAD_NUMWD) + (rad_sba >> 1); - xfr_req = xfr_req & ~XFR_RAD; /* clr xfr req */ - if ((rad_unit.flags & UNIT_BUF) == 0) { /* not buffered? */ - rad_end_op (CHF_ERR | CHF_EOR); /* set rad err */ - CRETIOE (rad_stopioe, SCPE_UNATT); } - if ((p >= rad_unit.capac) || /* end of disk? */ - (rad_wrp & (1 << RAD_GETLUN (rad_da)))) { /* write prot? */ - rad_end_op (CHF_ERR | CHF_EOR); /* set rad err */ - return SCPE_OK; } - wptr = ((uint32 *) rad_unit.filebuf) + p; /* ptr to word */ - if (rad_sba & 1) *wptr = *wptr | (*dat & 07777); /* odd byte? */ - else *wptr = (*dat & 07777) << 12; /* even */ - if (p >= rad_unit.hwmark) rad_unit.hwmark = p + 1; /* mark hiwater */ - rad_sba = rad_adjda (rad_sba, 1); /* next byte */ - break; - -default: - CRETINS; } -return SCPE_OK; -} - -/* PIN routine */ - -t_stat pin_rads (uint32 num, uint32 *dat) -{ -*dat = GET_SECTOR (rad_time * RAD_NUMWD); /* ret curr sec */ -return SCPE_OK; -} - -/* POT routine */ - -t_stat pot_rada (uint32 num, uint32 *dat) -{ -rad_da = (*dat) & RAD_AMASK; /* save dsk addr */ -return SCPE_OK; -} - -/* Unit service and read/write */ - -t_stat rad_svc (UNIT *uptr) -{ -xfr_req = xfr_req | XFR_RAD; /* set xfr req */ -sim_activate (&rad_unit, rad_time); /* activate */ -return SCPE_OK; -} - -/* Fill incomplete sector */ - -t_stat rad_fill (int32 sba) -{ -uint32 p = rad_da * RAD_NUMWD; -int32 wa = (sba + 1) >> 1; /* whole words */ - -if (sba && (p < rad_unit.capac)) { /* fill needed? */ - for ( ; wa < RAD_NUMWD; wa++) - *(((uint32 *) rad_unit.filebuf) + p + wa) = 0; - if ((p + wa) >= rad_unit.hwmark) rad_unit.hwmark = p + wa + 1; - rad_adjda (sba, RAD_NUMWD - 1); } /* inc da */ -return SCPE_OK; -} - -/* Adjust disk address */ - -int32 rad_adjda (int32 sba, int32 inc) -{ -sba = sba + inc; -if (rad_sba >= (RAD_NUMWD * 2)) { /* next sector? */ - if (rad_nobi) rad_da = (rad_da & ~RAD_SCMASK) + /* within band? */ - ((rad_da + 1) & RAD_SCMASK); - else rad_da = (rad_da & ~RAD_TRSCMASK) + /* cross band */ - ((rad_da + 1) & RAD_TRSCMASK); - sba = 0; } /* start new sec */ -return sba; -} - -/* Terminate disk operation */ - -void rad_end_op (int32 fl) -{ -if (fl) chan_set_flag (rad_dib.chan, fl); /* set flags */ -xfr_req = xfr_req & ~XFR_RAD; /* clear xfr */ -sim_cancel (&rad_unit); /* stop */ -if (fl & CHF_ERR) { /* error? */ - chan_disc (rad_dib.chan); /* disconnect */ - rad_err = 1; } /* set rad err */ -return; -} - -/* Reset routine */ - -t_stat rad_reset (DEVICE *dptr) -{ -chan_disc (rad_dib.chan); /* disconnect */ -rad_nobi = 0; /* clear state */ -rad_da = 0; -rad_sba = 0; -xfr_req = xfr_req & ~XFR_RAD; /* clr xfr req */ -sim_cancel (&rad_unit); /* deactivate */ -return SCPE_OK; -} diff --git a/SDS/sds_stddev.c b/SDS/sds_stddev.c deleted file mode 100644 index 02892571..00000000 --- a/SDS/sds_stddev.c +++ /dev/null @@ -1,557 +0,0 @@ -/* sds_stddev.c: SDS 940 standard devices - - Copyright (c) 2001-2003, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - ptr paper tape reader - ptp paper tape punch - tti keyboard - tto teleprinter - - 25-Apr-03 RMS Revised for extended file support -*/ - -#include "sds_defs.h" -#define TT_CR 052 /* typewriter */ -#define TT_TB 072 -#define TT_BS 032 - -extern uint32 xfr_req; -extern int32 stop_invins, stop_invdev, stop_inviop; -int32 ptr_sor = 0; /* start of rec */ -int32 ptr_stopioe = 1; /* stop on err */ -int32 ptp_ldr = 0; /* no leader */ -int32 ptp_stopioe = 1; -DSPT std_tplt[] = { { 1, 0 }, { 0, 0 } }; /* template */ - -DEVICE ptr_dev, ptp_dev; -t_stat ptr (uint32 fnc, uint32 inst, uint32 *dat); -t_stat ptr_svc (UNIT *uptr); -t_stat ptr_reset (DEVICE *dptr); -t_stat ptr_boot (int32 unitno, DEVICE *dptr); -void ptr_set_err (void); -t_stat ptp (uint32 fnc, uint32 inst, uint32 *dat); -t_stat ptp_svc (UNIT *uptr); -t_stat ptp_reset (DEVICE *dptr); -t_stat ptp_out (int32 dat); -void ptp_set_err (void); -t_stat tti (uint32 fnc, uint32 inst, uint32 *dat); -t_stat tti_svc (UNIT *uptr); -t_stat tti_reset (DEVICE *dptr); -t_stat tto (uint32 fnc, uint32 inst, uint32 *dat); -t_stat tto_svc (UNIT *uptr); -t_stat tto_reset (DEVICE *dptr); - -extern const char ascii_to_sds[128]; -extern const char sds_to_ascii[64]; -extern const char odd_par[64]; - -/* PTR data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit - ptr_reg PTR register list -*/ - -DIB ptr_dib = { CHAN_W, DEV_PTR, XFR_PTR, std_tplt, &ptr }; - -UNIT ptr_unit = { - UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), - SERIAL_IN_WAIT }; - -REG ptr_reg[] = { - { ORDATA (BUF, ptr_unit.buf, 7) }, - { FLDATA (XFR, xfr_req, XFR_V_PTR) }, - { FLDATA (SOR, ptr_sor, 0) }, - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptr_unit.wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, ptr_stopioe, 0) }, - { NULL } }; - -MTAB ptr_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", - "CHANNEL", &set_chan, &show_chan, NULL }, - { 0 } }; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, ptr_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - &ptr_boot, NULL, NULL, - &ptr_dib, DEV_DISABLE }; - -/* PTP data structures - - ptp_dev PTP device descriptor - ptp_unit PTP unit - ptp_reg PTP register list -*/ - -DIB ptp_dib = { CHAN_W, DEV_PTP, XFR_PTP, std_tplt, &ptp }; - -UNIT ptp_unit = { - UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG ptp_reg[] = { - { ORDATA (BUF, ptp_unit.buf, 7) }, - { FLDATA (XFR, xfr_req, XFR_V_PTP) }, - { FLDATA (LDR, ptp_ldr, 0) }, - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptp_unit.wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, ptp_stopioe, 0) }, - { NULL } }; - -MTAB ptp_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL", - &set_chan, &show_chan, NULL }, - { 0 } }; - -DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, ptp_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptp_reset, - NULL, NULL, NULL, - &ptp_dib, DEV_DISABLE }; - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit - tti_reg TTI register list -*/ - -DIB tti_dib = { CHAN_W, DEV_TTI, XFR_TTI, std_tplt, &tti }; - -UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }; - -REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, 6) }, - { FLDATA (XFR, xfr_req, XFR_V_TTI) }, - { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB tti_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL", - &set_chan, &show_chan, &tti_dib }, - { 0 } }; - -DEVICE tti_dev = { - "TTI", &tti_unit, tti_reg, tti_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tti_reset, - NULL, NULL, NULL, - &tti_dib, 0 }; - -/* TTO data structures - - tto_dev TTO device descriptor - tto_unit TTO unit - tto_reg TTO register list -*/ - -DIB tto_dib = { CHAN_W, DEV_TTO, XFR_TTO, std_tplt, &tto }; - -UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT }; - -REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, 6) }, - { FLDATA (XFR, xfr_req, XFR_V_TTO) }, - { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tto_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB tto_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL", - &set_chan, &show_chan, &tto_dib }, - { 0 } }; - -DEVICE tto_dev = { - "TTO", &tto_unit, tto_reg, tto_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto_reset, - NULL, NULL, NULL, - &tto_dib, 0 }; - -/* Paper tape reader - - conn - inst = EOM0, dat = NULL - eom1 - inst = EOM1, dat = NULL - sks - inst = SKS, dat = ptr to result - disc - inst = device number, dat = NULL - wreor - inst = device number, dat = NULL - read - inst = device number, dat = ptr to data - write - inst = device number, dat = ptr to result - - The paper tape reader is a streaming input device. Once started, it - continues to read until disconnected. Leader before the current record - is ignored; leader after the current record sets channel EndOfRecord. -*/ - -t_stat ptr (uint32 fnc, uint32 inst, uint32 *dat) -{ -int32 new_ch; - -switch (fnc) { /* case function */ -case IO_CONN: /* connect */ - new_ch = I_GETEOCH (inst); /* get new chan */ - if (new_ch != ptr_dib.chan) return SCPE_IERR; /* inv conn? err */ - ptr_sor = 1; /* start of rec */ - xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */ - sim_activate (&ptr_unit, ptr_unit.wait); /* activate */ - break; - -case IO_DISC: /* disconnect */ - ptr_sor = 0; /* clear state */ - xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */ - sim_cancel (&ptr_unit); /* deactivate unit */ - break; - -case IO_READ: /* read */ - xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */ - *dat = ptr_unit.buf & 077; /* get buf data */ - if (ptr_unit.buf != odd_par[*dat]) /* good parity? */ - chan_set_flag (ptr_dib.chan, CHF_ERR); /* no, error */ - break; - -case IO_WREOR: /* write eor */ - break; - -case IO_EOM1: /* EOM mode 1*/ -case IO_WRITE: /* write */ - CRETINS; } /* error */ -return SCPE_OK; -} - -/* Unit service */ - -t_stat ptr_svc (UNIT *uptr) -{ -int32 temp; - -if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */ - ptr_set_err (); /* no, err, disc */ - CRETIOE (ptr_stopioe, SCPE_UNATT); } -if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */ - ptr_set_err (); /* yes, err, disc */ - if (feof (ptr_unit.fileref)) { /* end of file? */ - if (ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } - else perror ("PTR I/O error"); /* I/O error */ - clearerr (ptr_unit.fileref); - return SCPE_IOERR; } -ptr_unit.pos = ptr_unit.pos + 1; /* inc position */ -if (temp) { /* leader/gap? */ - ptr_unit.buf = temp & 0177; /* no, save char */ - xfr_req = xfr_req | XFR_PTR; /* set xfr flag */ - ptr_sor = 0; } /* in record */ -else if (!ptr_sor) /* end record? */ - chan_set_flag (ptr_dib.chan, CHF_EOR); /* ignore leader */ -sim_activate (&ptr_unit, ptr_unit.wait); /* get next char */ -return SCPE_OK; -} - -/* Fatal error */ - -void ptr_set_err (void) -{ -chan_set_flag (ptr_dib.chan, CHF_EOR | CHF_ERR); /* eor, error */ -chan_disc (ptr_dib.chan); /* disconnect */ -xfr_req = xfr_req & ~XFR_PTR; /* clear xfr */ -sim_cancel (&ptr_unit); /* stop */ -return; -} - -/* Reset routine */ - -t_stat ptr_reset (DEVICE *dptr) -{ -chan_disc (ptr_dib.chan); /* disconnect */ -ptr_sor = 0; /* clear state */ -ptr_unit.buf = 0; -xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */ -sim_cancel (&ptr_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Boot routine - simulate FILL console command */ - -t_stat ptr_boot (int32 unitno, DEVICE *dptr) -{ -extern uint32 P, M[]; - -M[0] = 077777771; /* -7B */ -M[1] = 007100000; /* LDX 0 */ -M[2] = 000203604; /* EOM 3604B */ -M[3] = 003200002; /* WIM 2 */ -M[4] = 000100002; /* BRU 2 */ -P = 1; /* start at 1 */ -return SCPE_OK; -} - -/* Paper tape punch - - conn - inst = EOM0, dat = NULL - eom1 - inst = EOM1, dat = NULL - sks - inst = SKS, dat = ptr to result - disc - inst = device number, dat = NULL - wreor - inst = device number, dat = NULL - read - inst = device number, dat = ptr to data - write - inst = device number, dat = ptr to result - - The paper tape punch is an asynchronous streaming output device. That is, - it can never cause a channel rate error; if no data is available, it waits. -*/ - -t_stat ptp (uint32 fnc, uint32 inst, uint32 *dat) -{ -int32 new_ch; - -switch (fnc) { /* case function */ -case IO_CONN: - new_ch = I_GETEOCH (inst); /* get new chan */ - if (new_ch != ptp_dib.chan) return SCPE_IERR; /* inv conn? err */ - ptp_ldr = (inst & CHC_NLDR)? 0: 1; /* leader? */ - xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */ - sim_activate (&ptp_unit, ptp_unit.wait); /* activate */ - break; - -case IO_DISC: /* disconnect */ - ptp_ldr = 0; /* clear state */ - xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */ - sim_cancel (&ptp_unit); /* deactivate unit */ - break; - -case IO_WRITE: /* write */ - xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */ - sim_activate (&ptp_unit, ptp_unit.wait); /* activate */ - ptp_unit.buf = odd_par[(*dat) & 077]; /* save data */ - return ptp_out (ptp_unit.buf); /* punch w/ par */ - -case IO_WREOR: /* write eor */ - break; - -case IO_EOM1: /* EOM mode 1*/ -case IO_READ: /* read */ - CRETINS; } /* error */ -return SCPE_OK; -} - -/* Unit service */ - -t_stat ptp_svc (UNIT *uptr) -{ -int32 i; -t_stat r = SCPE_OK; - -if (ptp_ldr) { /* need leader? */ - for (i = 0; i < 12; i++) { /* punch leader */ - if (r = ptp_out (0)) break; } } -ptp_ldr = 0; /* clear flag */ -chan_set_ordy (ptp_dib.chan); /* ptp ready */ -return r; -} - -/* Punch I/O */ - -t_stat ptp_out (int32 dat) -{ -if ((ptp_unit.flags & UNIT_ATT) == 0) { /* attached? */ - ptp_set_err (); /* no, disc, err */ - CRETIOE (ptp_stopioe, SCPE_UNATT); } -if (putc (dat, ptp_unit.fileref) == EOF) { /* I/O error? */ - ptp_set_err (); /* yes, disc, err */ - perror ("PTP I/O error"); /* print msg */ - clearerr (ptp_unit.fileref); - return SCPE_IOERR; } -ptp_unit.pos = ptp_unit.pos + 1; /* inc position */ -return SCPE_OK; -} - -/* Fatal error */ - -void ptp_set_err (void) -{ -chan_set_flag (ptp_dib.chan, CHF_ERR); /* error */ -chan_disc (ptp_dib.chan); /* disconnect */ -xfr_req = xfr_req & ~XFR_PTP; /* clear xfr */ -sim_cancel (&ptp_unit); /* stop */ -return; -} - -/* Reset routine */ - -t_stat ptp_reset (DEVICE *dptr) -{ -chan_disc (ptp_dib.chan); /* disconnect */ -ptp_ldr = 0; /* clear state */ -ptp_unit.buf = 0; -xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */ -sim_cancel (&ptp_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Typewriter input - - conn - inst = EOM0, dat = NULL - eom1 - inst = EOM1, dat = NULL - sks - inst = SKS, dat = ptr to result - disc - inst = device number, dat = NULL - wreor - inst = device number, dat = NULL - read - inst = device number, dat = ptr to data - write - inst = device number, dat = ptr to result - - The typewriter input is an asynchronous input device. That is, it can - never cause a channel rate error; if no data is available, it waits. -*/ - -t_stat tti (uint32 fnc, uint32 inst, uint32 *dat) -{ -int32 new_ch; - -switch (fnc) { /* case function */ -case IO_CONN: /* connect */ - new_ch = I_GETEOCH (inst); /* get new chan */ - if (new_ch != tti_dib.chan) return SCPE_IERR; /* inv conn? err */ - xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */ - break; - -case IO_DISC: /* disconnect */ - xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */ - break; - -case IO_READ: /* read */ - xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */ - *dat = tti_unit.buf; /* get buf data */ - break; - -case IO_WREOR: /* write eor */ - break; - -case IO_EOM1: /* EOM mode 1*/ -case IO_WRITE: /* write */ - CRETINS; } /* error */ -return SCPE_OK; -} - -/* Unit service */ - -t_stat tti_svc (UNIT *uptr) -{ -int32 temp; - -sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ -if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ -if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */ -temp = temp & 0177; -tti_unit.pos = tti_unit.pos + 1; -if (ascii_to_sds[temp] >= 0) { - tti_unit.buf = ascii_to_sds[temp]; /* internal rep */ - sim_putchar (temp); /* echo */ - if (temp == 015) sim_putchar (012); /* lf after cr */ - xfr_req = xfr_req | XFR_TTI; } /* set xfr flag */ -else sim_putchar (007); /* ding! */ -return SCPE_OK; -} - -t_stat tti_reset (DEVICE *dptr) -{ -chan_disc (tti_dib.chan); /* disconnect */ -tti_unit.buf = 0; /* clear state */ -xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */ -sim_activate (&tti_unit, tti_unit.wait); /* start poll */ -return SCPE_OK; -} - -/* Typewriter output - - conn - inst = EOM0, dat = NULL - eom1 - inst = EOM1, dat = NULL - sks - inst = SKS, dat = ptr to result - disc - inst = device number, dat = NULL - wreor - inst = device number, dat = NULL - read - inst = device number, dat = ptr to data - write - inst = device number, dat = ptr to result - - The typewriter output is an asynchronous streaming output device. That is, - it can never cause a channel rate error; if no data is available, it waits. -*/ - -t_stat tto (uint32 fnc, uint32 inst, uint32 *dat) -{ -int32 asc, new_ch; - -switch (fnc) { /* case function */ -case IO_CONN: - new_ch = I_GETEOCH (inst); /* get new chan */ - if (new_ch != tto_dib.chan) return SCPE_IERR; /* inv conn? err */ - xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */ - sim_activate (&tto_unit, tto_unit.wait); /* activate */ - break; - -case IO_DISC: /* disconnect */ - xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */ - sim_cancel (&tto_unit); /* deactivate unit */ - break; - -case IO_WRITE: /* write */ - xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */ - tto_unit.buf = (*dat) & 077; /* save data */ - if (tto_unit.buf == TT_CR) { /* control chars? */ - sim_putchar (015); /* CR generates LF */ - tto_unit.pos = tto_unit.pos + 1; - asc = 012; } - else if (tto_unit.buf == TT_BS) asc = '\b'; - else if (tto_unit.buf == TT_TB) asc = '\t'; - else asc = sds_to_ascii[tto_unit.buf]; /* translate */ - tto_unit.pos = tto_unit.pos + 1; /* inc position */ - sim_activate (&tto_unit, tto_unit.wait); /* activate */ - return sim_putchar (asc); /* output */ - -case IO_WREOR: /* write eor */ - break; - -case IO_EOM1: /* EOM mode 1*/ -case IO_READ: /* read */ - CRETINS; } /* error */ -return SCPE_OK; -} - -/* Unit service */ - -t_stat tto_svc (UNIT *uptr) -{ -chan_set_ordy (tto_dib.chan); /* tto rdy */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tto_reset (DEVICE *dptr) -{ -chan_disc (tto_dib.chan); /* disconnect */ -tto_unit.buf = 0; /* clear state */ -xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */ -sim_cancel (&tto_unit); /* deactivate unit */ -return SCPE_OK; -} diff --git a/SDS/sds_sys.c b/SDS/sds_sys.c deleted file mode 100644 index 8ff8d2af..00000000 --- a/SDS/sds_sys.c +++ /dev/null @@ -1,576 +0,0 @@ -/* sds_sys.c: SDS 940 simulator interface - - Copyright (c) 2001-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. -*/ - -#include "sds_defs.h" -#include -#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) - -extern DEVICE cpu_dev; -extern DEVICE chan_dev; -extern DEVICE ptr_dev; -extern DEVICE ptp_dev; -extern DEVICE tti_dev; -extern DEVICE tto_dev; -extern DEVICE lpt_dev; -extern DEVICE rtc_dev; -extern DEVICE drm_dev; -extern DEVICE rad_dev; -extern DEVICE dsk_dev; -extern DEVICE mt_dev; -extern DEVICE mux_dev, muxl_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern uint32 M[MAXMEMSIZE]; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "SDS 940"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 1; - -DEVICE *sim_devices[] = { - &cpu_dev, - &chan_dev, - &ptr_dev, - &ptp_dev, - &tti_dev, - &tto_dev, - &lpt_dev, - &rtc_dev, - &drm_dev, - &rad_dev, - &dsk_dev, - &mt_dev, - &mux_dev, - &muxl_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "IO device not ready", - "HALT instruction", - "Breakpoint", - "Invalid IO device", - "Invalid instruction", - "Invalid I/O operation", - "Nested indirects exceed limit", - "Nested EXU's exceed limit", - "Memory management trap during interrupt", - "Memory management trap during trap", - "Trap instruction not BRM", - "RTC instruction not MIN or SKR", - "Interrupt vector zero", - "Runaway carriage control tape" }; - -/* Character conversion tables */ - -const char sds_to_ascii[64] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', ' ', '=', '\'', ':', '>', '%', /* 17 = check mark */ - '+', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', '?', '.', ')', '[', '<', '@', /* 37 = stop code */ - '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', '!', '$', '*', ']', ';', '^', /* 57 = triangle */ - '_', '/', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', '?', ',', '(', '~', '\\', '#' }; /* 72 = rec mark */ - /* 75 = squiggle, 77 = del */ - -const char ascii_to_sds[128] = { - -1, -1, -1, -1, -1, -1, -1, -1, /* 0 - 37 */ - 032, 072, -1, -1, -1, 052, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 012, 052, -1, 077, 053, 017, -1, 014, /* 40 - 77 */ - 074, 034, 054, 020, 073, 040, 033, 061, - 000, 001, 002, 003, 004, 005, 006, 007, - 010, 011, 015, 056, 036, 013, 016, 072, - 037, 021, 022, 023, 024, 025, 026, 027, /* 100 - 137 */ - 030, 031, 041, 042, 043, 044, 045, 046, - 047, 050, 051, 062, 063, 064, 065, 066, - 067, 070, 071, 035, 076, 055, 057, 060, - 000, 021, 022, 023, 024, 025, 026, 027, /* 140 - 177 */ - 030, 031, 041, 042, 043, 044, 045, 046, - 047, 050, 051, 062, 063, 064, 065, 066, - 067, 070, 071, -1, -1, -1, -1, -1 }; - -const char odd_par[64] = { - 0100, 0001, 0002, 0103, 0004, 0105, 0106, 0007, - 0010, 0111, 0112, 0013, 0114, 0015, 0016, 0117, - 0020, 0121, 0122, 0023, 0124, 0025, 0026, 0127, - 0130, 0031, 0032, 0133, 0034, 0135, 0136, 0037, - 0040, 0141, 0142, 0043, 0144, 0045, 0046, 0147, - 0150, 0051, 0052, 0153, 0054, 0155, 0156, 0057, - 0160, 0061, 0062, 0163, 0064, 0165, 0166, 0067, - 0070, 0171, 0172, 0073, 0174, 0075, 0076, 0177 }; - -/* Load carriage control tape - - A carriage control tape consists of entries of the form - - (repeat count) column number,column number,column number,... - - The CCT entries are stored in lpt_cct[0:lnt-1], lpt_ccl contains the - number of entries -*/ - -t_stat sim_load_cct (FILE *fileref) -{ -int32 col, rpt, ptr, mask, cctbuf[CCT_LNT]; -t_stat r; -extern int32 lpt_ccl, lpt_ccp, lpt_cct[CCT_LNT]; -char *cptr, cbuf[CBUFSIZE], gbuf[CBUFSIZE]; - -ptr = 0; -for ( ; (cptr = fgets (cbuf, CBUFSIZE, fileref)) != NULL; ) { /* until eof */ - mask = 0; - if (*cptr == '(') { /* repeat count? */ - cptr = get_glyph (cptr + 1, gbuf, ')'); /* get 1st field */ - rpt = get_uint (gbuf, 10, CCT_LNT, &r); /* repeat count */ - if (r != SCPE_OK) return SCPE_FMT; } - else rpt = 1; - while (*cptr != 0) { /* get col no's */ - cptr = get_glyph (cptr, gbuf, ','); /* get next field */ - col = get_uint (gbuf, 10, 7, &r); /* column number */ - if (r != SCPE_OK) return SCPE_FMT; - mask = mask | (1 << col); } /* set bit */ - for ( ; rpt > 0; rpt--) { /* store vals */ - if (ptr >= CCT_LNT) return SCPE_FMT; - cctbuf[ptr++] = mask; } } -if (ptr == 0) return SCPE_FMT; -lpt_ccl = ptr; -lpt_ccp = 0; -for (rpt = 0; rpt < lpt_ccl; rpt++) lpt_cct[rpt] = cctbuf[rpt]; -return SCPE_OK; -} - -/* Load command. -l means load a line printer tape. Otherwise, load - a bootstrap paper tape. -*/ - -int32 get_word (FILE *fileref, int32 *ldr) -{ -int32 i, c, wd; - -for (i = wd = 0; i < 4; ) { - if ((c = fgetc (fileref)) == EOF) return -1; - if ((c == 0) && (*ldr == 0)) return -1; - if (c == 0) continue; - *ldr = 0; - wd = (wd << 6) | (c & 077); - i++; } -return wd; -} - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 i, wd, buf[8]; -int32 ldr = 1; -extern int32 sim_switches; -extern uint32 P; - -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; -if (sim_switches & SWMASK ('L')) return sim_load_cct (fileref); -for (i = 0; i < 8; i++) { /* read boot */ - if ((wd = get_word (fileref, &ldr)) < 0) return SCPE_FMT; - buf[i] = wd; } -if ((buf[0] != 023200012) || /* 2 = WIM 12,2 */ - (buf[1] != 004100002) || /* 3 = BRX 2 */ - (buf[2] != 007100011) || /* 4 = LDX 11 */ - (buf[3] != 023200000) || /* 5 = WIM 0,2 */ - (buf[4] != 004021000) || /* 6 = SKS 21000 */ - (buf[5] != 004100005)) return SCPE_FMT; /* 7 = BRX 5 */ -for (i = 0; i < 8; i++) M[i + 2] = buf[i]; /* copy boot */ -if (I_GETOP (buf[6]) == BRU) P = buf[6] & VA_MASK; -for (i = buf[7] & VA_MASK; i <= VA_MASK; i++) { /* load data */ - if ((wd = get_word (fileref, &ldr)) < 0) return SCPE_OK; - M[i] = wd; } -return SCPE_NXM; -} - -/* Symbol tables */ - -#define I_V_FL 24 /* inst class */ -#define I_M_FL 017 /* class mask */ -#define I_V_NPN 000 /* no operand */ -#define I_V_PPO 001 /* POP */ -#define I_V_IOI 002 /* IO */ -#define I_V_MRF 003 /* memory reference */ -#define I_V_REG 004 /* register change */ -#define I_V_SHF 005 /* shift */ -#define I_V_OPO 006 /* opcode only */ -#define I_V_CHC 007 /* chan cmd */ -#define I_V_CHT 010 /* chan test */ -#define I_NPN (I_V_NPN << I_V_FL) -#define I_PPO (I_V_PPO << I_V_FL) -#define I_IOI (I_V_IOI << I_V_FL) -#define I_MRF (I_V_MRF << I_V_FL) -#define I_REG (I_V_REG << I_V_FL) -#define I_SHF (I_V_SHF << I_V_FL) -#define I_OPO (I_V_OPO << I_V_FL) -#define I_CHC (I_V_CHC << I_V_FL) -#define I_CHT (I_V_CHT << I_V_FL) - -static const int32 masks[] = { - 037777777, 010000000, 017700000, - 017740000, 017700000, 017774000, - 017700000, 017377677, 027737677 }; - -static const char *opcode[] = { - "POP", "EIR", "DIR", - "ROV", "REO", "OTO", "OVT", - "IDT", "IET", - "BPT4", "BPT3", "BPT2", "BPT1", - "CLAB", "ABC", "BAC", "XAB", - "XXB", "STE", "LDE", "XEE", - "CLEAR", - - "HLT", "BRU", "EOM", "EOD", - "MIY", "BRI", "MIW", "POT", - "ETR", "MRG", "EOR", - "NOP", "EXU", - "YIM", "WIM", "PIN", - "STA", "STB", "STX", - "SKS", "BRX", "BRM", - "SKE", "BRR", "SKB", "SKN", - "SUB", "ADD", "SUC", "ADC", - "SKR", "MIN", "XMA", "ADM", - "MUL", "DIV", - "SKM", "LDX", "SKA", "SKG", - "SKD", "LDB", "LDA", "EAX", - - "BRU*", - "MIY*", "BRI*", "MIW*", "POT*", - "ETR*", "MRG*", "EOR*", - "EXU*", - "YIM*", "WIM*", "PIN*", - "STA*", "STB*", "STX*", - "BRX*", "BRM*", - "SKE*", "BRR*", "SKB*", "SKN*", - "SUB*", "ADD*", "SUC*", "ADC*", - "SKR*", "MIN*", "XMA*", "ADM*", - "MUL*", "DIV*", - "SKM*", "LDX*", "SKA*", "SKG*", - "SKD*", "LDB*", "LDA*", "EAX*", - - "RSH", "RCY", "LRSH", - "LSH", "NOD", "LCY", - "RSH*", "LSH*", - - "ALC", "DSC", "ASC", "TOP", - "CAT", "CET", "CZT", "CIT", - - "CLA", "CLB", "CAB", /* encode only */ - "CBA", "CBX", "CXB", - "XPO", "CXA", "CAX", - "CNA", "CLX", NULL, - NULL }; - -static const int32 opc_val[] = { - 010000000+I_PPO, 000220002+I_NPN, 000220004+I_NPN, - 002200001+I_NPN, 002200010+I_NPN, 002200100+I_NPN, 002200101+I_NPN, - 004020002+I_NPN, 004020004+I_NPN, - 004020040+I_NPN, 004020100+I_NPN, 004020200+I_NPN, 004020400+I_NPN, - 004600003+I_NPN, 004600005+I_NPN, 004600012+I_NPN, 004600014+I_NPN, - 004600060+I_NPN, 004600122+I_NPN, 004600140+I_NPN, 004600160+I_NPN, - 024600003+I_NPN, - - 000000000+I_NPN, 000100000+I_MRF, 000200000+I_IOI, 000600000+I_IOI, - 001000000+I_MRF, 001100000+I_MRF, 001200000+I_MRF, 001300000+I_MRF, - 001400000+I_MRF, 001600000+I_MRF, 001700000+I_MRF, - 002000000+I_OPO, 002300000+I_MRF, - 003000000+I_MRF, 003200000+I_MRF, 003300000+I_MRF, - 003500000+I_MRF, 003600000+I_MRF, 003700000+I_MRF, - 004000000+I_IOI, 004100000+I_MRF, 004300000+I_MRF, - 005000000+I_MRF, 005100000+I_MRF, 005200000+I_MRF, 005300000+I_MRF, - 005400000+I_MRF, 005500000+I_MRF, 005600000+I_MRF, 005700000+I_MRF, - 006000000+I_MRF, 006100000+I_MRF, 006200000+I_MRF, 006300000+I_MRF, - 006400000+I_MRF, 006500000+I_MRF, - 007000000+I_MRF, 007100000+I_MRF, 007200000+I_MRF, 007300000+I_MRF, - 007400000+I_MRF, 007500000+I_MRF, 007600000+I_MRF, 007700000+I_MRF, - - 000140000+I_MRF, - 001040000+I_MRF, 001140000+I_MRF, 001240000+I_MRF, 001340000+I_MRF, - 001440000+I_MRF, 001640000+I_MRF, 001740000+I_MRF, - 002340000+I_MRF, - 003040000+I_MRF, 003240000+I_MRF, 003340000+I_MRF, - 003540000+I_MRF, 003640000+I_MRF, 003740000+I_MRF, - 004140000+I_MRF, 004340000+I_MRF, - 005040000+I_MRF, 005140000+I_MRF, 005240000+I_MRF, 005340000+I_MRF, - 005440000+I_MRF, 005540000+I_MRF, 005640000+I_MRF, 005740000+I_MRF, - 006040000+I_MRF, 006140000+I_MRF, 006240000+I_MRF, 006340000+I_MRF, - 006440000+I_MRF, 006540000+I_MRF, - 007040000+I_MRF, 007140000+I_MRF, 007240000+I_MRF, 007340000+I_MRF, - 007440000+I_MRF, 007540000+I_MRF, 007640000+I_MRF, 007740000+I_MRF, - - 006600000+I_SHF, 006620000+I_SHF, 006624000+I_SHF, - 006700000+I_SHF, 006710000+I_SHF, 006720000+I_SHF, - 006640000+I_MRF, 006740000+I_MRF, - - 000250000+I_CHC, 000200000+I_CHC, 000212000+I_CHC, 000214000+I_CHC, - 004014000+I_CHT, 004011000+I_CHT, 004012000+I_CHT, 004010400+I_CHT, - - 004600001+I_REG, 004600002+I_REG, 004600004+I_REG, - 004600010+I_REG, 004600020+I_REG, 004600040+I_REG, - 004600100+I_REG, 004600200+I_REG, 004600400+I_REG, - 004601000+I_REG, 024600000+I_REG, 004600000+I_REG, - -1 }; - -static const char *chname[] = { - "W", "Y", "C", "D", "E", "F", "G", "H", NULL }; - -/* Register change decode - - Inputs: - *of = output stream - inst = mask bits -*/ - -void fprint_reg (FILE *of, int32 inst) -{ -int32 i, j, sp; - -inst = inst & ~(I_M_OP << I_V_OP); /* clear opcode */ -for (i = sp = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - if ((j == I_V_REG) && (opc_val[i] & inst)) { /* reg class? */ - inst = inst & ~opc_val[i]; /* mask bit set? */ - fprintf (of, (sp? " %s": "%s"), opcode[i]); - sp = 1; } } -return; -} - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - return = status code -*/ - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 i, j, ch; -int32 inst, op, tag, va, shf, nonop; - -inst = val[0]; /* get inst */ -op = I_GETOP (inst); /* get fields */ -tag = (inst >> 21) & 06; -va = inst & VA_MASK; -shf = inst & I_SHFMSK; -nonop = inst & 077777; - -if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; - fprintf (of, FMTASC (inst & 0177)); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* character? */ - fprintf (of, "%c", sds_to_ascii[(inst >> 18) & 077]); - fprintf (of, "%c", sds_to_ascii[(inst >> 12) & 077]); - fprintf (of, "%c", sds_to_ascii[(inst >> 6) & 077]); - fprintf (of, "%c", sds_to_ascii[inst & 077]); - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; - -/* Instruction decode */ - -for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */ - - switch (j) { /* case on class */ - case I_V_NPN: /* no operands */ - case I_V_OPO: /* opcode only */ - fprintf (of, "%s", opcode[i]); /* opcode */ - break; - case I_V_SHF: /* shift */ - fprintf (of, "%s %-o", opcode[i], shf); - if (tag) fprintf (of, ",%-o", tag); - break; - case I_V_PPO: /* pop */ - fprintf (of, "POP %-o,%-o", op, nonop); - if (tag) fprintf (of, ",%-o", tag); - break; - case I_V_IOI: /* I/O */ - fprintf (of, "%s %-o", opcode[i], nonop); - if (tag) fprintf (of, ",%-o", tag); - break; - case I_V_MRF: /* mem ref */ - fprintf (of, "%s %-o", opcode[i], va); - if (tag) fprintf (of, ",%-o", tag); - break; - case I_V_REG: /* reg change */ - fprint_reg (of, inst); /* decode */ - break; - case I_V_CHC: /* chan cmd */ - ch = I_GETEOCH (inst); /* get chan */ - fprintf (of, "%s %s", opcode[i], chname[ch]); - break; - case I_V_CHT: /* chan test */ - ch = I_GETSKCH (inst); /* get chan */ - fprintf (of, "%s %s", opcode[i], chname[ch]); - break; - } /* end case */ - return SCPE_OK; - } /* end if */ - } /* end for */ -return SCPE_ARG; -} - -/* Get (optional) tag - - Inputs: - *cptr = pointer to input string - *tag = pointer to tag - Outputs: - cptr = updated pointer to input string -*/ - -char *get_tag (char *cptr, t_value *tag) -{ -char *tptr, gbuf[CBUFSIZE]; -t_stat r; - -tptr = get_glyph (cptr, gbuf, 0); /* get next field */ -*tag = get_uint (gbuf, 8, 07, &r) << I_V_TAG; /* parse */ -if (r == SCPE_OK) return tptr; /* ok? advance */ -*tag = 0; -return cptr; /* no change */ -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = error status -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 i, j, k; -t_value d, tag; -t_stat r; -char gbuf[CBUFSIZE]; - -while (isspace (*cptr)) cptr++; -for (i = 1; (i < 4) && (cptr[i] != 0); i++) - if (cptr[i] == 0) for (j = i + 1; j <= 4; j++) cptr[j] = 0; -if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (t_value) cptr[0] | 0200; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - for (i = j = 0, val[0] = 0; i < 4; i++) { - if (cptr[i] == 0) j = 1; /* latch str end */ - k = ascii_to_sds[cptr[i] & 0177]; /* cvt char */ - if (j || (k < 0)) k = 0; /* bad, end? spc */ - val[0] = (val[0] << 6) | k; } - return SCPE_OK; } - -/* Symbolic input, continued */ - -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; -if (opcode[i] == NULL) return SCPE_ARG; -val[0] = opc_val[i] & DMASK; /* get value */ -j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - -switch (j) { /* case on class */ -case I_V_NPN: case I_V_OPO: /* opcode only */ - break; -case I_V_SHF: /* shift */ - cptr = get_glyph (cptr, gbuf, ','); /* get next field */ - d = get_uint (gbuf, 8, I_SHFMSK, &r); /* shift count */ - if (r != SCPE_OK) return SCPE_ARG; - cptr = get_tag (cptr, &tag); /* get opt tag */ - val[0] = val[0] | d | tag; - break; -case I_V_PPO: /* pop */ - cptr = get_glyph (cptr, gbuf, ','); /* get next field */ - d = get_uint (gbuf, 8, 077, &r); /* opcode */ - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | d; /* fall thru */ -case I_V_IOI: /* I/O */ - cptr = get_glyph (cptr, gbuf, ','); /* get next field */ - d = get_uint (gbuf, 8, 077777, &r); /* 15b address */ - if (r != SCPE_OK) return SCPE_ARG; - cptr = get_tag (cptr, &tag); /* get opt tag */ - val[0] = val[0] | d | tag; - break; -case I_V_MRF: /* mem ref */ - cptr = get_glyph (cptr, gbuf, ','); /* get next field */ - d = get_uint (gbuf, 8, VA_MASK, &r); /* virt address */ - if (r != SCPE_OK) return SCPE_ARG; - cptr = get_tag (cptr, &tag); /* get opt tag */ - val[0] = val[0] | d | tag; - break; -case I_V_REG: /* register */ - for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; - cptr = get_glyph (cptr, gbuf, 0)) { - for (i = 0; (opcode[i] != NULL) && - (strcmp (opcode[i], gbuf) != 0); i++) ; - if (opcode[i] != NULL) { - k = opc_val[i] & DMASK;; - if (I_GETOP (k) != RCH) return SCPE_ARG; - val[0] = val[0] | k; } - else { - d = get_uint (gbuf, 8, 077777, &r); - if (r != SCPE_OK) return SCPE_ARG; - else val[0] = val[0] | d; } } - break; -case I_V_CHC: case I_V_CHT: /* channel */ - cptr = get_glyph (cptr, gbuf, ','); /* get next field */ - for (i = 0; (chname[i] != NULL) && (strcmp (chname[i], gbuf) != 0); - i++); - if (chname[i] != NULL) d = i; /* named chan */ - else { - d = get_uint (gbuf, 8, NUM_CHAN - 1, &r); - if (r != SCPE_OK) return SCPE_ARG; } /* numbered chan */ - val[0] = val[0] | ((j == I_V_CHC)? I_SETEOCH (d): I_SETSKCH (d)); - break; } /* end case */ -if (*cptr != 0) return SCPE_ARG; /* junk at end? */ -return SCPE_OK; -} diff --git a/VAX/ka655.bin b/VAX/ka655.bin deleted file mode 100644 index 1edd8b931e10cc59037aab5a07569afb2b5acf1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131072 zcmd?Sdwf*Y)i=J+%$Z~ohLD*Fm;jOkf}#aIgQ#c`a^+GXoH;X-3tGyM3}H-2XfB8? z0mMteQYLA^wrM*9f=EcT;H9=gp9ZjfKw3T6fUPtde8fuM>Y)}d4TAk}_7uh9 zwt5`GhuPK`1E7G|W9-yeB@(lt1i_NYQdtgTTIA=~GNw2)wa6>k6iC$~pMweI6XnZm zV*6N%bWQ9fAY6g=T84?X#9^YX&NR@@iDsE5i!Ixw?L{ryCkD0c@^;0uik*^_)2WIZ z%$y#gIL=v3aL*!e!z#Q5VVVNdQ>NPX9$STr02j_A%1xF(o)vxJ9GrXlZ zwMcntmb56Ur+gWYE5{Y+wJ41lrzwjL>269o<@B~k)~VgfL!YP@qWU`*<8l209-col ztL+W0_FU=Tid}*dJ6pKwD=o2?5mQ@Yhw$>Z#9qa#v?cZiUga&ZxA0on5_=b~`%X<* z^Va4GZ?QZ3hQ%%*0j>29ycSu^w;;SFOtZ*$OzH93z+PNHpL6soUkLi%sf?{wZ2KM4 z7pvMf(dSHQe^`;fH|4zg*=prwhppG!8}U+&WAo5Afg z*j5(12EY;iWa&4ta#qD!*u(6H>;?8QvkOjPq;O5_22qrpm*kg(R)s@4U+alw1Ft8R z!k_7QPNKe!pFNg=m=>7~^07=jJb#GG2W9ygLH-8wyd0N*C(GZHzbnPGjdl?*q_lkhxSGu0eMv9>024Iof*Qd2($G@ z9yXF&ksOUZg~HWnj4Jn}*!!di_>(XrdzB@K7Kh;~vK3zc2JmiuXnyHLz7+ z%MT5gk1zC$h|BL*$VV1>hQ{UZx#Zt1^oVhJ(!KJp7Ji^uJr}<8d~&HbvdKUj1vK5B z!kcmp${K=rZ|qa5yFO|W*tO`NPXW6<%4x&wS&sIV+KX#^k_3^S5Cx8 zqHgPvOhsn~u=kwTW>FGFdE4`K?VF4tH5I9*IYBJVs%X4_cu%K#Q;$R#nLwMoHm)gZ zJ8wH*RR0w){cXM~S7zrlzUQ}pgrylz`}ir@Ku`%VEU*G!XtU(w6(&+>&;PrC~i zLh*fQv2g0lHQ__MB}RS8>Kb{@GSsNt?g&famDm!qKm^WIwC*)`FxI2$qR2B8cgAtW zF($2z0}LDGI%hR=3=~aJ`(^t(51QoG;iuC%=5eH^QU%Os4wE`oZ#lY-wc3w9 z#9A|su4k>n(TAD*X~tRQJ~_yGO668|R=H>Ikf+5}_EM!oRI24QNV)U*2otMaH*13O zJVwu_Q{0x5il(g5O4qc5o^mjfPwcLV>Yv@m*cx>3pUaGWESCQA31mB??M%_SM6cK< zbcr`(yy%O^%ao&dTY*FrfEfj*@-FKVt=$%)jk=YAh)s*E3s=Wu*W!uV$|ga8pV>Z8GNSr-%(OzJ zae4huB}3W_5B^u=ne!!gLN+HZuN|NLo-Yt&h8ShG$5Ea!v$)B6d&Jl*DbCjP?FCzyuP zm7H{gS{}GPsk|CF2d*F~WW7yE>MK)~Xx`C2R(^R&(TQeBW6oH(+S^9_Cd>I(qgdOC zB{{uF$aEg@c-U)=6d9IKY>mt(^r#*xB^zMZx7MS@I}8bWHZ4fJ@*-xoO=@duUdIj8 z%>zAt!bsg^*8*6FjTn`xjZpU5ccr6T$9~U5rKsbET^TQXx)uK+CGcj)=~=-|MAq zap#AJROL-Y+pOB!ZDGyAm4S$7X`7Mijp>+_fXp?EW3Tsq>ACHq$s_uK1H5K@1?Y2M zdeSfQ9t8O4(Z@wKVe$@QMhpoY^^1coo+HWPRkmhB3YJ|C4Pd)6_eN&3U86B-?#k`i zCCU4~kU#mt&@)WH+CV&YjJq8#sQ*JgQh$rS^?JrQk#Pe=3X+M`ej)GWL@-;0vEqhi z9B6npu>bFD^NRjzi7QnuU>_*|vT2#Vy^&e>C{M0eKJi_^imNpT_4+E7{(3>a_KO~c zcR5URZ3Nu2%h5vun3c@?-V5^i3rT>QP#QhDSyc8!tbL2!sokRTvAy);sD45<<^vlh zz$$B&sJ@^qNd-@Rx%TLKF?KX4_6lo{E_kjBjU)?7jq+*vtkQT0)z5AZ-iRG&q5?6?9f z_vEO)8)Li~%WV^gAdtKqcEncjMNvPGrjGb)x#+n&j()a(JoNq6cpJbiIa$4_(DC%O zNADLg_YY%*@__;-TL{ThD71QyE)t27%j&7b1ZN=`$97$%*BVq_(H42-_s3vTdP1Sf z-N^BV2%NZ^YKz{w#&d!7_?+2q7eYOhwrv*BB;ZmG{5Jcz)c0O1(vEHtp^S?~YtGnS z?(^x5*s;#&wXZ$eK-?WeZO{8``&7*GymRg&9KQc-I&p4{;DtUqm1x%6ai)yZTF% zu-+`8mIcWY zU5=b|JTtRI;EO$qsCBF^BR%QNA;zgRmGQZZ20#r@wpsrPg)%A@p$^(V`5KQ(O4BQ z|J{n(Evj3ew7TAk>ggb*IK}9bR^{cu;05w|@SOPF@ZvKtR@cjkW6X+VG4^Im1dMxBFMosg+fju<3o%;{&w4eJ z^K!;;kueBnFw~2Y>5wCBEBK+MJH-L!oM2Am%muWkChoKkVA z@d%>keQF~7ZaeMpFEh(i6SwS~)U(sEW#>&NeC{kw-RaOriA$7LW#>(NUcPEcRDbFH z0l(82M^t|r@uwyp5%6cQ{_f~1tQuk?$T!LqEFSG_Fe~5Utax4NR5^HYdQ|b0Lp?Rr zhlv9^p1D@Syn^+uUGF^(_f_gAzH^$ah=)Y=ltVeJsNPknUatY@H6|d0sCcQsem(1R z)r`2H|2ho6vAZX-+S6ynR?RuiSn6qsOI(e`78haZ`J>~ z)3z$juVC#+Y$)P?nQl_gM)rm7A}%+RPAF>5gC9KUXoh1BKWJk@@oq=i=&<)uMy`mA zb;zc%`C22RFyS)g?)TUsW_c%BnLoo`5$1iMFfs;zv7zO|fc`cz$Phqw&_Qx@Yux`# zRb*^`3?z%WLsYjAaoV&Xy;2dpMN#m~aMWnEl&V52+kMDS;&o%PI4$(avwp`J6 zh~Dmp)Q@wO|30qnz{;YV3)<)Wi{?WgCdA7qpcBOGe4Aq{7OpXdpbaikycGDvX`b90 zA@kB3!T8T2F%cUb%xY(8%*kM2d$}*snbI36;Mv9=+%W9HU4uOX{kPQ^8Zu(~etM_G z^xxne(;vh0ixmC((Tuf4N+YFicW(r`f}HPCjzxDMr#F(yi-n#bV<}}=^?#3o4TA%D ze+G#y<12+`dreTB*OHdU<343oB<}TgtyfkFigG4XvHVK;#Cz^)(y;YjxsCW;aK^V0 z@8$s*pj{NeUK~s-Z^hoouZMu&VZB0c(e*yk>oSd5P> z)+zUP(PZW9aOxP7-7_!f&w*k6sUog2C))%Va@XtBy~WtEhcIIUa1}5OMf(*7M|!ZqPMSloI-ML;?+Vk|cLXcaV(j|_WXd+*McovAM=l$EMKHBy8 zL)lbg^dA0aj&U`;omo(mAHmka(z<(LY&HQ5#`ldJk`JK0op!A=t8-F!r@b@le5Z6Q z3BNDB=0$7=X-enBSf`_xQ?u$5(l|ANaI^Ixwi@Lh%%&*sbY^1@2DRwU)3flZL&3Eu z<$}H+jiLV+v1b%Ckr(t#QbF=Jc_Hm+NZ%og@3c^3J1BI*M`clkmIAbCrz44h=g^;M z;IN%k+f<{KhJ0Uo%k7C%$efruSY`s|MJOC`=r}hG4@clSyC={lL{{ ztx3^3?TQm3nW#7|uoIi_<*ExjG_z69E-|LhMiZf)d3aGhAHkLv%1PE=-IfpxIFIRN z27+QD_)G+oE%}?+FzTF0QxR1=*2a8Pdq0>69QUa?nTG|x@=5^nG3=B2UJC>SLl`PL z`cKgLxh#w%npgZNkz|OZQ-Vyy5#0e_cR)o0ALas~RY2rf(gmyjb1bX&Pmk(LegM70 zrtRB$A6iVs<|<&gbgd^B{ksFwt)$ZEh(7L znH#^-?|!)mH<))yUC0rE+wJiWtJ^z7=TfYMZGr$NWev zJr+2&m6aV=OI^0(zB2d7K6lN??u8Xl9SmvZ(41G@=gWB?LeBfVV`&wgSuMa#SOm-K zZ(qEipIpq?>+DPCp$mG}#A4*yWX0`#zF#C3g=&hO=5^Qv^r3^Ue;9N8CtxPY0Q`$A$C^Wyx^{?e zP5ZIOv2e5MuV8dc5Rg+{*&@3Cr1Z8u$HusYC9aM#l%agFuSMNk=;`s)yD>n zmG3id@CX~ghvB2yFk=}@AQ-G@y_z!TDB8q}r+vDjbbIqUvH^D!a}7T%AneuXIUSn^ zM&8GKqFjC`sz0;X;BP4SlbL`$6I+fms=sI^f9k@DY*sv~zicL)p@iGwa7a6%s0Nl? z9bzkdmGj%Y5?r+2Nv?nGw_&J7()Dm(zJY@TV_r#Dugy6md%L~rwNB)?-fves9PX6k z^mIk_29x$i(0sym@H@Fl#s#C=y^ z?vnzRIIaxSt2+|_T8c0FWXhWMCv9*oOyZbU{d#1)=|dW}9iB{4oshstljsm+VJ>g) zqx~%G$S~R|#HM~!|6Lo}^&?fCJzr?2a3I++|?#*WaR+u<8#x z(Gts|b?cQMTqoVWqqv+jp9 zs_t|{Rg@2%quxZK-DT^cJh;E&@wL5P4A?2)hrH4>fy3b>418*<$DR?7oaF~EZ|YBj#_U?YN2D8jL~$_SR8iQoqY0$Rm>g6 zD&~%_oRAN{+H_m|2cLc%8lpt?r%2P3UoV zu{<`5&0{K~GTu7iV9ptM3eIVGTAWkxv^poD1b)`aIqnoY;BbyUCEz*Ylm*YsQ&v3F zjWbvXF)ag37|fh@qEyfKS)@y3GaqBdzwPEb5g<U~hh9-T>79H1z3Zv`{|}e0dOr z9hK@5J?q&i2vSqHxI9ffYe=G|o+?;ZI$n0b;i(wNqLXW$xu%B*Su=Rn&~pbInKmwI z&m^XsL1gFlXAcwjK_|~prkg=zlLe;(i2PwQkF|;Nvw{s%PIv;2@k4B2^00s{V6^V5 zJb_#o(1cMq!KKQ>N%@T_beDLt%khc&4@jTuh~dak{BVOP0ey@`!Mc;yvBTLob_+XY zS5Kw+jt6{WMmwcb>FTK=6v-XtbQ{hS%CR_8NNl5pw~LpQwUt_OY+7}>^Ty+4=n!n( z7@iq7y)lwy9k~Ku|MNwS9D&%|JA>Mnr)Xmp&neaiRhR_lPdScUSqz;#=M`}PD_4L6 z^qe;ZXS)>rX`IsF2z$8TCh<-umK!CPS35`bmUD-iWZ`bd*PAcGoyN<0kkJ_47cZ|^ zl~z%4#9yIRpg%Zx2T9c`;DL2ul&3R+6)G35?@eEKh0hSE@3;yl@IScBBdSeIXTw+) zP9u$Bt&4-soV|EtX?P54!6O}ymTmU!cBndc5JA><<+P}bKb@gSI1D@bbgnWKoWpS7 z+@@V}4mrXP+VKeW-2`8D?%hGN{=YBzwAf`If^))&GI;+s*dYzS`?!}{NX|_|AReE| zM!Ad>DR&&D&#pCTT14IIzggATW^#cyfXRsu-QO6)t0_DQ_ zN{xqk&q0h_SE!gD(oBuVyX+Tg^(`OAJW_P*(W2y<(dh z`O@vcGwx2o^OEbjRd!W}nTx--KJ&SvD*!?jMBN4T;f#R$Zm<8~GoK5}hb|Q39vajC zgNO)v5r~|8=5tDZ=JS!i2A`MW?%VPDGVZz$j*X)@p2k>0C_8cJu3PM{T}+P<6^nie z3v=gW4xX0;-b~<@B=DsM`0D`g_Xiw81m#7T+lkjNnL8b?*BLtGY^M32Ie*APBF0>P zfQ@TG7ZnpkR2wz5=qGScV#?+<-Orq_gLo=APxpf^3P1nM#os~+4x_!jB0tYZZLjtm za74Q7EOj+Y{By!xhT)yGz?fg7n;gy4Pk~xj<{Ca>e(LjhoV#|w+&?V9w^>q|1HF&^ z#Orlhr+B^XK*A9D7?9M1UKNe?kWuBoVev|tTAm(8Cim20_9#DXY4_uxW-6eRHs9jh zls4ZsVU(>KuAp;K{TzW#*=E5c%6m<))px+r>x=2P8YDM@q-UXpw0}%uxIft?UZ{P2 zRQy$L@w)79cA@2AnCT#i4`cXbB6!f77X)YL5r*svh>Y7Z0F#ykbHacbLom890CNVj z@dTY0444a8czcc|!5mD2*=oR?B$%g@V1AJV^MC>K9Kk#+kg(*9LQCnI7C)TO6vaj- zK#XF+_(lL~evC_{Nd)I55v()_28rMlq1~d$cM84!n64V>b18i!&Ee&-NfgriDG)3P z?6l}Z&%GI;I&?c1q5T(53@Y+JV8s)X{WDfB25W>iv>z?QL_39vpQnov7tbf5{d^GG zhbY@9?IVP!w4H?3Ovl#b)$AvJ|3MYf(ErvC_g52cHNnm2T>06Q1l-|%xNZ~9PjC}B z8$Z8ycB}?lpK4f3iUZwmjZ>LZf&D&`q=Q##ByONm)H#t^lmMl1K(2=m` zulWPc9BkG41Hb^V;7`0?ta80{qST$%9#SSMPhnE0l`7(XdEeq-)*UU2)s~?DMb&)+ zHZ1!TeYTe|>v~CPf7ILO)$cT7-Zo4{954A_Qe7ur^t)4>X+7j}g9i?dJmqEC2A-#j zhej{b7A;I1b02*_-1Y%-1Pgi_ENUw&IAHIEk9Z+;@W<#F$Gwx`MDQwNRR1xx=04>h z+*4Rk9<;EL&M5~)oIcZAkmKw2p%-^YAYI(4_{#|_7v3ZnEfoD(=GhfTDG4X(GcZ-K zTE|uFv0An9ICd;xc5qzvW)E$ZfPpPeNs+r*Pry@$qwS_^^#NcRjDCP3U>svQ*4Wg^ zzlj{c7Q`ns!c`9!Ald#ol&BgAFChs4W8;egL(^G*X~SCg*o@-#*c4eIkV}_5UtH?( zV*0Z|frvK<-qUHudG-w!@7aKLgXo3$YmvtffAuOc{oci}komeFFIX~iTmH#PO&zfH z8K}e023!Of00bEOCFO3W8P)_MBX1IH2Nga7tkEJ^eV{WuC;&ii6u6HRYYo1MGKPlo z1|VZ#fUEQ#qGr*9l%PfEFsQO+@dnG{E!!+xwpq7q6MMF$k$;vhFu)l$5iVDni(>0q zemzd1{>-SJWnrvSit5AZJsy@Bn$TH=jcj_?M)fh^s&isgA3^U)#tx-&jt#Xg-h+cd zi^-d7+n;W5;oFMMpqwA?5ZiZHaK3+sO?krm{m4b{4$I5wCs2OI`|^(j*9bZ1eeA}u z@BPS{qm#!I2Pj`ox5*C)@T(xO-?2(m)Kzu`YNf79GhXS&Ybbx2r9CcGLe;GDOK0Q< z*lBB}{o`K-xPil)!1tkfg@Cz-%UxL350ih%a2d-k zw_a*>Db5G_+oK96SV!!yZG(HA9MuM&neB0eoT$aHHYF7v6eSCpVx@CYn=;Hb zW|L5PnpMIF5rCGcoQn(X>%Hzg@ZmhyrdVCskj9oB;+7rOEjuhHcBEmudPmx#-a1>` z4pGd`Zr@?`K8~hnRnRPEt5~1dA@WL`!d;|PY*5)w@#|yORx5(z%(S<>*TLkmp7NfG zo`vn-hkI}W_6g2d%UN5^WS8xTz5L|8uUgC7YHo66X`2=vu^@h8VRp)E3l}2KDfcXV z6)T4t*=0Q#{l4}#+ zyPR#+lzU-Sm3zDG_sJhzIz3Fe>6c1GSQl}wo6K%!Gua&G#lMAYFyRC{#5aq33dR~cZn-qD|m!AD`7-;zig6Fw7&h^TV2%e6(2E+MX!Lu!{r7LoS z;Q4V}E@YmzxLhH4z7L<9f@P3JaSqcknMwz+69?B6Cqs?p@fJ@wE`Q77sRXnICopB7 z#ZwlS=UY5p6j_F)p`d^7JxuqMQk`KLh#_j21Q*0?T$>trKg@Qp-yv?iwNh+>!$KZl z7?-e!ldCP*2tDkpz!F5RLYOjRJaeH}{)UmckTPeRnd@0gg(Axqt<)>ul$3vik?*YJ zg!Nnh@WnfFI_3BHP4YIx0?tCp2knn=?3Cwm>SyT?s`CaSeL^78uT!>(_(z2OhbuT> zHvzUvw1qDh3AlFlJw?vEc;5FJr3JjQjGebl*m5kzW@DM>{Y!8wvDKwm)Ll4c{ zOPWqWZBuEF|GP?QsoGjlxdyADQrEwF0zIWYWl6G>Ah&V&n}~lm<2{Z4lh_RWD`L(` zhy4o!&g=0kb4uVZaM)i_<{W`|sWX$Orc(-XN}bH)ua&jRidN>8zsK4!It0G>#Lrnr zm7CeiVAj@WEq9$3$}>*0@^l~p+bb_*HYB-_lyTZRkX(qPIMd-(g*7R|abB~2_fb&W zBPH%mgo>W@h;93vc@Wtp?u3ehZ8=yyoyqsEYib7a&Nwy{E!>9#{Fg zYRvW8Ohta?0tn#@Yo7iQ)`N=t3nIqjZ}a#ME)f2*Q^4E0#O2V2D)M(Okj^(z29~I} zKj=kg_QLC?c+v9^pm_{>tu^ZV>Lbfo$HMoG12V+xjf`i>HPA1?1b%X=QZUEB{Sl zx3WC^%g4X=J*n!>^nyKhSjTM&-ZtA4ds5r>q}p?=8!Y$RY!F%sPRuoy!}7HqWZ=+s zZQC9jCU?2R>1|~rhpw{k5%vhJ2LaQe1bpMJjjU%=`3Rb~4KA05m2WX1y7x;=5o1;Rksb%=D#Kr_t@a>Q?r& z1@j)-t)eQtF_d3`Jv}T&ce_6~FM%hRj_hRoQri-dd`! z)zYyNqkLbgV)dM0?MtxVe4SRz&m4QNXtu9DigMojMynN+B!klTapwuKvC5w#43l;8 zKdxe}wvLr;$`ZH5x%{O1iSN-X$S@&C!ZU z_8$>z#X{px{OyQU;+>em>0dm=SmOF_|03m$&*E{+b~zo|B5cjmzgr3kh*3^dd17%} z=Hl$kR$*~JN(?Bm*bQojjF#QJ_~EcOOv#5DeVoj<7t?Xlx{u8DEhV)|IZ zOV$0rYvVbVoV%m3-2hQ~S6ulorVk^8A^LSdc-gw&x*z+}I80$AX7EJY1^r3HU;oRc z<7hzasy~8G1J@(|*a?1;3+J=DS)`7o9Dr--fcdYIc{*9-S$kxibqIS32SJ{K3B`T} zzY1)4*p`Lc$>${JU79WPe;wXSVdvniD1&EbT3jcu5Z7n1-E~G*zR4V@!}Ori}BTm7L{Lp zZ}Ic1?=7YL>U&E$zxv*?kY9aoxsRW{!!=Oais-G=>fru-N#G533XX#A$T~#oV7vZ= zSbKqf4a!wlMJ}nT6E4Z;49I=RJFlLL>A#{lPMjj%%L(`L!g@Iay?jRr9!SXi3!A>0 z1HDhh#!m9*ANccEc*b;?83HQfK%6(uZ!fPyFRxcj|D^#mg#*3Kv0vlQ|KK!!PuZgG zMs|-HgP(B*v6rG-knpjne#q@0w_iikr3P8LTbdwGD^HUerkX*Ceht%-V^Y3iMj0V_ z29Rz`25Y!8IVQ~-gfwLU>GmYB22X+oUasUDgmmiw(j9}45-bc&hZ_Jq;TNb2ty&SP zYzkFLp;eWk6;0v#I%%>rae_Rh{6>kTDZz%|@=#N#!6XF4G^NleRq9W}0(G95W=IBL zB%r&}=*eX@@IW4RH2BYM#|xv8h@X-2RnLiEl`)WRXLj>vq}lCb#tOpNF}#pzMJOT{ ze|6ub+!^`#f<;6QF@WE=apSV=Gw_ec2j^xu1xtq0nPJa#W*E@<<3B)soa7&AKUHwyz@i%P6BU>~_&2j2#PdqCL~$8asCEO#A^9>B&)q zlcU$?u;eIafXPvZ%aI%fwbkiqX*1K((jFu(@FPXR54w_qa%Unq41Y6`gL0FjppzU$ zLCI0zl8VufngUfxjsiD13fw`_!O}pD#*V#i!i^rI`k*`pA^MT1K{+`J%E?jSCPz`w zpePO(pz3$xZw*M{w`i>A#v3PG$0?&z7{wR`W!lB$C>NuVz+3!QFqsssWcm5%NA%-_ z2eCN3ld8YSgZ3RmLPsw|6$sTV2rZl( zrGk=jiE?r@5g#K-=pC2U=&~p;ZQx*Qo)1? zF1vlas*)*S4A$70;q;F6l_LM^CX5JvcBmKqD1aXlc@&RvS!=V#B_cFvtW79v zf8uBdCNJi1Z6eVBwvXm)<>g6`o&}bI=RkD)XPRldBi*R-44w<&0Nh~_403A`nU7ga^SUsaChNA?sSxKcVT|M3B1-QShN^Cf^t6nnYk1UE&_<5NTA2r zHF-`%%?k1gKqE4Za;b3em#8t%;2@Mi%}q5>7n7KbVX!Kk1;YaB{mi$4xL6CHg9 z{t9NAxDXS5CXYYE< znU-oxbB;B*;ylp9sA7J8WgswjZi46h{KDe7-e4lig^EamXM|t~@H1;fS^0ClGx8`t zlX9sXqo5i2kjp>|l7<;Sj!TIAXNV3#48>VlS%$V#&RqNghLRdKm85IpnkLo&CPm^( zXw+yrH#m4q=fHvmZHU&D@_2L%^#uAExM<%}KmyzZ#yCKdoZDYb&U1n?=L%f*1DiDh2fR{d6;K%-y>nIp=_n85 zf%?u!^k3NdnI!q5X^C90hu@+^lv+5^zDVN@Y_=~&(WFUj!BIUoOQsI5Sn?3NIc_g_XJnS7ff|;eQkopRG}54qpg|9SGpBODEwHPf|`C=Ac+8C`@HRFR~ z^cgvvL5agZMqiGL(PDJa?Kb0b9*&nJ-*6j#(mWNTZRThACq{mMxBky`fgNI&o)|5J zd-!^{Cq~QK9=?|D;fv)S&dI<*f3g4TUv7MMMp5(S=f%BZrDwR1R5RZ`Y{`k5gu5q| z@Lv5lgc^ms(CX*TkYjR_5&173i5ZcTh{)Gj(Sm9GOLu=rhWrhWY%?Icc!b~D;)lR{ zchKFJV!i}lh|gVdANpk1u>Nws3k2tUfPsP6UM01wbk88IeI8mn?4`<)Lwd&{%THjN z+L21iTL9%J<$a!%m+CXR_j&-`0w5e1MvHsRsvlP;yN67wd>*>Rzc|-ltO(F#q4fIr zw)-|2~-hyaNs1u3OYv%!H?M~&Hh3uba? z%)0Z+htaxn@Lo>$PL_73EHcR&S3MvUd@)7HwH^1;S!EO&)iH-<%8dMNmy~mh&Ck@e zZWH*Y>qwA-)skXKw~AIKX4ovYp|-RXdupoPkv1&dHe^Ur`;O2r{u0Ws^unF>n*y!_ z@4gFH7ibt?C5-7^lx)$DA(=?Wcss`QpBu?9n902srve!yk~4v!1^ihVqi z#v@!L=@%v%mR88ZjRIYvJ90t zsqh~84UD%2(Qm*vV1zF0Mf3B5K0x_4dE@ViapRmhESJ|gqCJQ`<1TT?pSROD*+|92 zZkx9)c&+OUK*jx$#jqp16C85lY)!>hG_T9S8Aw4Jdxl#cLJEcl#Wn10eeZw91SqJvc-ea^U5dh50Zz2U7}O*A#&ljIpCLOBMut zGIK3K_IBC9PI<*}sb;;Qzti4|$8owVS-wjd$#*dhur2}&E~@xj{KQ~XFF_oK z6ao{|LLGL`*-L0MB6Zjx_2FNk^P9cNq(*U4!+{zD4DP4kxMGXS<F#5vozEpqg~LPv*V65Q)kR=%Ej@b0 z-T;^4%dha>B#2bw-at%$in@qZp9MBsHmk(uHJDmzH!9*0Urmp%MJ04nXt_3yni0ye zZ*Ua1Q8W5Pj7abpv#e=2l0BJW?u)x?*yL|f`mxXc{;<+HX;7MWS-hpwkpPFrKSrep z`j6i>YzBtCt@%Rf*XJ{7e$~zUt@TrZP@bb&I z16tBy&cBm~qu%_xg)Z|$gaIu;UnOyZi}n=d_qI~Bd|7+-nnR^! zxa+U^aWCcX3+P^oUH`Bbh64LXR_p=dOnDg{i#eTJy+UV}YQ-IX6JJKHrtea&QiM`{ zgjlVt8leQ_wK&g7-@sgzRf;>#2bI7Yl!(!lDBz0tMMc$A6tbHaV$(OEknV}NEzS2K z@lCtm@(e+*r;O6_Zhu90W*JWZ=Yc@(I^5*ZD%NP_pm2}_iux=7o`A)&%J))@#Z{5> zxa=BhqFtd?DW%>X{~PO6x8sDGZ8_;*C8(L+sDj4?e3%0+GXa|k&^Rd(>% zf8slPIN)DH-*v!A3A_U+<;P|zXJMah1oIqe0!vJ<6W{;zCBFW-KVp~o9zMc`?ZNBl!*t1a z^8&Bp18qKj9nYtX$(mk>>v;SyIVAj3oX+z*bF@I2ycxkpet~Xzw{dwc;FS1vy<7Qp zJ)d`slZfD!IFTqlr1+e;$cLMCcOO*zmtCy$A1|wLN$BTMeI{qyqW>25lP<}zb^No< zr?IFy>GM?M>x1}ue77ZF-s7|35RcX7xjlZ__k0{jG2!PQ_qf{ke9VzR?h^3v+G$+X z*tD-ywb6rGyZ>W5qrjo_cP6Q0kz6qzujv$%zl+^}UlpH?;P-f=zkC!%0xg9PkK<@m zG3r`}-uJUVqiKD(z51NFVShot4_W#G3$DO?9qH}zpFWkRAka4A6vi84;v|nn!n&>e zyD~T+VD&V{2Qi9a$%eHieNGzZu~QAkaM-B-0|bu?{KJrZmRIr@+Qf8b^%ii1nEoQ> zCYT)Fj`V-?tH|nm{Y#v&NYpyT8Vpf5!C`zMMWF8!(8;4iBH!zMhhMP4oqY*cop=hy z(MK?k124Dq!+eB3eHqMR17^s;;?uT;*Ky#>3HY#M9tL{j1(DM+l1ZA_X}Ccfd(QVxnbnrghtW=hgoO*}V*0 zGE)fx==NnVR%1m!5ue?`w?0enx~uvn(LGFCRC-YG?h7a1WP%+&-R=2a2X~+MDyo$j;2`(jlWwCIJO+f z*1ARqw607#i(lSb4heJ-o>Fnw*otLag6$iWH!E-g^e5x6dOTUNb(MQb+bzpnIVa28 z4rF&_WtVH^Pl+#tUU{;-A;`DIgSE912X2%aLXDw@l_B_$xGxe9Y>M}9 zeOs+euv#tFulg}z?IlbqENjoP6lSfyWEU7L4r79io)-SJ@~6n3wv@GfOtjhY%);{$ z)^2GJ04pt>aMSFBWlLcnt;2KOM}m-=^3X?_0>YQ_1Y7F1k3cwe-A9r$C0z$(Du3Gf z)5dXA_%oG1?fhxbOy^;oiEIisG==M`rJ{f$@rpOxeDlpi=?sCdseZ+Zt7ob6N@NSSQuj)jlXSHm^YAHxc7S zKHpraDzq|O8EPCmG(DXu4fWMH8nK+}-n1-apc+z1&RQA_*M_PLSrymOISOB~f09%< zuQ*?wB>CnnD4QhBDW0cHl8VdcBBQ=R@&@MmsRVz0y|g@7_n@>i9ICBqBpwqf-);`p zhLPMrsfG2+0ahh}|KRc^;p*o4=F5_s>uT!iAE*PYH-Sjd&2l*ecBCd}%m--g;G_X;skt#EEqPE1CJSv4{RBk6+^$wu0w`El z54eWQh(Sx1qN--kYzi)^<-9L#uB`>J{&u{fNm>$;s=|!~kX%U+MMbHM1ZOZNsBXSl zT}k3~L?*R9{U-CDsUk)sDObYzmfPz&Ac9PFB~UGwrKp@u7HOb4^yGTUZ`G<`WW$P6MCs^hY_O!$<;buPgJC0ylaO6u~q zBS_NKt6&UDYFt+TfK=Js&_JfMGP#M23XrA`Lbys~MMD_KP1GHmLaUk#MCu$@fgO~z z!sw9$z0p9W?lcJQDv_%CI%vvO2&DI)e@e8Y*@jmkGLR%oP4&_pM)89iY5*oVbjR(o zj1ygiM8Byf=0Kw+0}l#M@kkTVW;HjG;g~W-n%D&E$E_*L5U#mjl!m7JgRq$;IK(wm z!p^xc35gcGr{XJAO)sX6K!_Sp%%%{v zh&YBqBw&mx!%`DJg!&`HQmwhehQXI(VGfu$zcgnaj2q5;Ii$HT_85v0vmsVgFppv$ zL|p^XDTulUqPHTNf+&bcb4z?g33qfQUts~^QZ6SnN6Ie+f)lZOz$%a6oRLIl-HOW#Z$sY5f#~gsjv9!f_1U#% zR4txMz+(oY1e`k%CEz?nOBVP7g>#CEOIbc*c;{o(nO(vP`txSZomb2X5v737uLcVJ zxKH7b3i6A?&+XaN{SZD;)Lf8 z;FjdiFJ|AMcwpA7Vs%03EOrlKg?@D&B#n=BaQ^0&*}qL>%4k_GC5`S{pJqTVG7ii&Yt0g6%Ln>9aQQHy6YKcZ@}AB+bm zqZBd$XK)696`J_@OW0V-z+6u)p2fzQ;llYvxQ67A^5+-KmMC%uWt8{=v!r}=HoJ|o z)Y;O4(qeTMyN>6TN=38%Y%0RuK>j>4%ae$fEGW&Nhbt8(Ndm#?9urnA_DYmJ9trdO z^KkdV;3yyRzaC-aN&W>3qFbvl|n^iut&QL^^wqZ$A4P zLQwVMB7F1=%~rw{6iW|>> z*e2$Hru~3978T;XPH?OUHa3P=hA^G24F&m7_>kb3AFNy!t_w+(%R-ekfLkv(NdE_> z1rOuP^z{#5NT$gR03Hz>syQFN1=f2dW<1p)%tz`Pn;M!cY3dB1M+HY=b7NEea^NLq z&zFHbHb6(JUlD4+qy~uJOG-5dJeqTnaYXJ0!I58yIa#B$GF)HF=jlk@C^-B;Z!{7l z8tfBun#XxoWk^~Ps;dGaK!0Cw6f}f_H7n{d@*uuRa5UFpW z#}%n}B6ZIdsrg9lydt##sa;p3QeS!Iiqs;cK6^zfHTy5GNS%e$y@F#d&Htf?Qd1bc z0BQS@B>kM=C|=%dDr_SyxB&2caw6taScEl`*1wR1_+nD{S4rWQlES}E3jZc4{Blxw ze^U5BQuwz?;r}3wt!u2uWE*N5g6RM=zZ*zwqE5FwOsxM9M#yucRD=W=5orp7q2{K> z%4O0-Gf<2Eeap#4$fO|@u3Uy$i*#!el&^Bx1EKJDD0%9QQgK~%ZMYH0fx0jqR=)>b zx2k?Q<=%E>E*7j!p~hPZgLT2GAi>-Yn8p>sf7QcYNq5{R%>tu;4`PZraR6poaxwu_ zhHfbc)mDeU-Aq#|>CWVQUvs#zk&->~jnZ8B48mBaAciWJgsMUfRJlgPQSXxa1`>e> zl~b^qY_4wp2j!qrzUKPnVFXbF-^vgKh0ZTc^xS+iQtqOQr`CD(K{8TO855oSBH7Sz`_Ersm|=f7Z9(@+gs1Q=$E zz@tPG>*=Mz=2|S#fN3tSrDefJEZIVJQX{S<&>EMs5M$Q-m8dOW+nCF6qO*-zi}<1( zliTeif~JNCNnUlKrU&X9YB*(#LctX`Lz=dE_0{1@ET$(@y+2qU!eR+EZEk2p;TZ0M z4b>rX`Viqq@a@@PU7aagn;NP*yFA#?5Uj>(vRSIVj1XbqYxusakR{nt_6BA%L<@aK z6P)Gp-pFjlt5($3!|BAO3epMI!pjGX*ES1%1S|f*ta4e~iqV6b8wM}9q~&Lq*M|+| zh%y^>o3n&FP>&Ts5Ic(&pp`J%38sY@jhVm@O1N=FeI2zhEq)+tg9;b5t+=r<7*3+r z2nHI?Him-DBxe1zwWRiLT~iS^S5m$g9{=PGIiO9A>r zIJBhE?B@@J8>*!0P;Ia(#7lpKS!RWn!8J#$JbHETx==GvxMc}(MShG~NY6vdd1KVR z*Syr!Z;PSd!6g8%TviL?V3e|vSq$?5RUmhM5v)A(JItqjHa-_-q%$H8>%J;V0f!A`)qixNqV5U0n#u^3f5I4 zb&0`Hj9E%y3NKbKp=r%*0uC7pZs8FwV$ROWdeY)*=^|V(u-&2^li34O46%oezDKme=n8ev*HCqHcuBZ6Y)C#O;jj!s(WC+Hcr%#H zQ%-+>FxWypp=yKrL<*UiJ_*{wn`1CJUUnFh?n=yZspJ?l;S+`i92xCkr1N%2DQT`p zAL7c+dlT_DU{+w;G2fu+NK=SZUYJ`~Rr@}C)aKY``gE3uYN^CWm@q4JKMy|2gxMH! zX~g^r;Ku-554y1V4G9xsbR=pJBDaAFNnIhhw6V6ismbUi8<}8^nKhp`G(sc7H8n6G z&9&ibL+B=E7y^S;htX)n*vTa>%xSKH?=V!`7-}4(?2SuJ-lI$?0#EplQ%#tk5SRs{ z)fm-6b;~eGY6{m%!6s@BR8m^nU`kymrd(jtUk#ky=ob%yans5RbFhM|=_i6&No_v_ zZxTUi_tsDTjB7^z%3n73dou4;lBnuf$^iqu*4&0LI+UI|zi z4mCe87~!#gC=!1or-|~L!%fwpmGz+pK2O-dQmI>DHCSKUR9_!9=P#+I0g|Zy^7%m+ zqFN47)rRk{F&ZRw!3r*@CBTRJ@}}S{VswNBTo!6Zb^E&j8jaAREOj=YtZJZbDO}fzM%1{+1 zef=^uM3s;%q&@_O6vl9H2QWlFWR}qn9%VxoEa!ZpyI%?T7#m_Luc7bILcWJ1tvFMC zh7T4S*bqbW`?G3lgS4dCn8<*9Nwq@vOToI8@4+1K2~Rt+NgEToP7Fz52@|5a%aq+P z)loKNE=)IOgQiI##cq<8ehTfYTOMqp(YCR_k2hg7M!gf_#^wMoG{%Pb!?m^5@6j5f z8sjz52sIeu9zva=iOU*AU4>-Lrrsu$n@lCPR+t^N0wSV>(7x z=tYtQn%BjppVw=;F0d}xQYB0>TmrN&(22j*StZ*<`aXw<;EnHiDe+UW>J*Cx2 zlAhWJ^mGtYNy=YyKUGtzJ0m4baT83kX^Yb^S7``UoAZu=i8)E-5tfGOIA*eglOJVi zG|#LI^ZEDR|BKIL2hGjXidSKlV&-sZH^SaE(878!sSPM0yc~(NsRQ}*#@NWxu-Qr; zFwA9*NeYpw!yiqQxoeWQemh}f?iV(u>WRrNSMfBOTwx>|n4OsHU}Ey`{>ge;(kz>R z6C{kn5*EW;JH%Krcw$oi;mT0h93hjlxyGlJ)UOQo&ru-9q!NM>27;zAMq55F$1G*w zH*`WHwxlK6h`xD36`PE|NmA+j0_-3nj+VJ6|MsaeJ#RCfw_&dYhYJ|}&v59EK1o9V zKOFo7i&eCxq}u7?HT}|uIEH2nGs0JUUY3vlwXbn$=xVTL+E>HS|JLFE=@+-I0SNtF z@x$RLqY_u-^e50A9P_u95)%=;*G@#7ZaNj3e>m^Nzc6qu-nc0X-#Ekfr|7K4Y-xg8 zDg6(_8qPpe`ATR+*qaV7zLL*SC#VJ-zVdd~EG7 z>{{Vy82*OikAB(4i%I62$gaa5@s<25=7$6f7sr53(^@BSPyj1P+I&MRU?T zL`Hf(`b>2ltw-QtVuojgw&|141q`GP91AGno6LhZ^bNSiyRZR1*)!$ln;KD^0mrvO zJ+xgp<+j@y24$2|t@MPKuzh#1aYkh(NY*pW~(qIrveDWMEt*yrZGI2r`rmF)R z#UXwg1Dye74Z{}Yn~#Z-!Nnw_VDvTi-R-!(^JF}}bVod%`&2xB4u9X@@cJM1k8~*E zFs3sdO23Y=Ir;OjExA}=B@1xud9j6I8xC(PD^Mt1M4a9>ruqtS-ZF*FD^d#m*He;TLDCJZXl|(@u&#-0{({oNTM@dE70y>EwD%_FE6gt`MCfbGr%=f9!XyrN z8$y#g+-*YUuWzO_f1!~1ms@x!P+0QAM`V&#S;-HpJdjqI_lLWuP@!e>@_)GdRvs!4 z*rurjPsQIx#FSefVqLd$cITlocknd)Kk~F`thi{dUn$II+MR5EzQ1q|+HTWbY~KH7 z@7?30s;<8AeP+%ilMp0xCWLU!0Eq;RG82LZ8zpxV4RGenCF7NZa7ij4B;0Hz4k}jL z%1jhmpA-zV`jq1Z@F`k>ssS%mta1Vgw&6(%^-^ziQZ-(|dB1C)Gsy(|ywB(N`Tg;} zpU?XQ)|_?L*_XA~-e>K-*Is*{1*L@ifO)QyOWhB?R!GU+P*YvCJ$yAQE-k64dT{qO zL@NgN@*F1nJe9>Y4`!)2W2~&KBJaVhr*PI7u$iEhkiwgZT2v)$6Ik%)-zsKK5s!;MRL|tJ|-`yzP_R@OZ8J) z6=f)Q00l#_GuUf4@zz{P=*=AUR@vEWxA2BtN$5h3daF)7tJab@%JNP<`&1prW`eee z#KCFx93$Fd5(lR(;TX}Dk~lbR8OLV6^sL%I{FIfv@vPd&v6>Ulsz2md^@(R+zm+hh ztU813UQTF9+4T?ZUO`w*849zKuNZ-@Q z;A3hmk zrNy3dVE2WIX+l~_T0nL`$mW$Um`9|CkeV0BJzJ@)glr@E5%LSPl2Sr`$;!%0OVDf| z=CxC8WxM~4V>Qr>ZIt*8B_O``D;=!~XFaf;DGRWWo)X?cRfa@%Kf)yk?B#Y{awTY; zJ4s$Oc~uWSxr<{nLHjkyi_?C?F`_+6^5V3|I7YO8CwXz&Z#hP^-6StgQ#nSo$4OqC z_5{a>_9V%R)1KlO(e`l3K|?&bmrD-Vefx-MLY^kc0onZ@TyjME9a8fGxo1B~j*w?a za)dlfk|X5zB)J-az5E=pBYOxvKwJRD<5B~5zeZ9cq?4ouL_N->Mx+x+%?o667fFqf zZju@yCrN6AyiHOAa{r%EyqZ!Ve_`lE20t{>xy`_@mW+$ z!4;iH+nP(7znEjB(M!&wZE;#D$B0&T9&L-$$~i`~it}h&oHmzZr1>j(%B1Rpw>|O93$FNDj26NhT6jxw0gs>hVU7)udHD{zHycr&S%jl`y5U z+EMlRazaZgC$rrv2&<`_QuX*s!m2B?<~?{D6%qXXbQKkmkkwQ~;<$+y5!k)WRK&`Z z@@LoZB37nU?pe!=SUI8U@pY6|2qUG-q_J3=rt*8j3EE1+3LwlhCKGcr1H z4%azz=D=wY4o?pHyBwxW*fg5?IdULRrSs(IHy;CaMsr3JfaY0r07fbxp60-P5g-VN zJ#YXm0tAgK%^52Im>a;WjlpG&!6yxyD*=?pjeuJKivUXjjezBV+W?A_DK4huF=ZxG z@|iM=DOWJ%N~RPrWi}qsV;3uyS%r+DFO!kioN?QW7C5)d3)gS2z3o@qSKayI_TZLx zwuc|d-?4MgsvY}YShb_$t>5m@`hL6P^gsG`^ncg4BNR&9(cT`|v3Kw2M_zn!^drZP zUH!;k|9bT!k;sxqqR}OfaFKX!fl%@S?8fZon^|@<%gJt@&MxD>^m8en4_`Q)twN-x zMT}q8>zC#FWwm~}jTPy!i*&)4+(Mb~REy&98j$l1avWX_a)CjP!zm&vktcvFMW9>b zst066#+8k+r&u#5;9M66oet-4;G~nAvg_GRx8Mi=>2eb)-^w0*k^-KsZ zVy55*oRWSU6N77+CAgR+1e;l6a0Rml7d0gX*Eb~xmp6?Fu5L;R!WApHwCSSY;-*o- zWlgEUh9+B((s8=-X6Dbj;>v>A#U-U>U2aiB`vqMDvX|CYp*CCMG#s5>r^ziZE7$u_BBW@gb8LRy@NVl1wX}n?W-p zj2U5Ydhs|j=w{J5$82%TFeenXm=Q)q7!hGagb@)&L>LiaM1&C$Mno73!dMW-f-n|@ zu^@~E&nV0Ig?7EtoBKGp+#gLgXBtM4C;s^p? z5u;ogLkeQZY#otZPL3e)CLO~Op|L!gVtF*h@@UfY7@6Fp=YhbnJep#8G#PooZ#9-Q z3GyjG+@BT3leC9L$BlHv$<0?ea!M8~@Xk{IKB!-syo{l}}8`AUB`;3!%2dlACTc`e1X95MX7>R8U63H@HKt%l;B2o${quHYW z<^Sw^+*{vzE*fp1V2hRx;^sw5mk-{ExLG!MXTe?FGVA+@wHmQRavZZ39*9PNM0X8X z_p(+%xOd~u3J<(xYq53@oUx=>v6Es_O0pPO(g+@ciBk|W5evMu)G1z#8!*MM#1Ka~ zGaSZ8tRs>;h4}M{+JV%EMFyV0R{%R z(~-D~ZkB9-YsAVW;(iLV0!u>TAAy;%$w=%W5^dHI&k{yX2qJ@Z-?Db)59?NlcA$E( zE+!&hx)KQ$n#I}l42K4<5vze&NnYfX%I}1FaUqBa@B(Y9ZxEXZZ(6cyN!=Q8GjL&p z_%JTwQaFK#PY_0HLE;O*l41+%s4iYFLHwGUoaogsRO7hIN=;J7^Q@%xbbKa1*ipyx ztyIrCKFf+TZVdbieju7ozmlJorsD;CwM55fTj|Xs+>GOut<)-v8yEW3!J9nm$f28= z){BO2@~tpD$KuQyjAN=>H5kRTbk$%CQ}e392&Pr_dZ{sjO*V2- z#fz*{;wft=%+%o&gvlC4S%j3c<0)_pY_ifa6y?rKx&j*(nyfV18DwY$R)MXT#0P4w zTZdM0sXmVjM4~-)u3=T;8X%q$}m#nI*?L_#j9^}S<{A58bQez77Z!6 ztP_Tjkdg~L>2ga%M^N9)SsF%gfumuBJn%D&FcaJiBjkgbVT4)WWfyG4X4bs7F8bSA;fZX#2#0o6#7>p*y^Km_hQUYFWGjofq_7 z?3Vg6G-Ts;^`aF}ehgDPYW5b~E?Ggh`dhGiQR8iN$AUq;Ab3@Qj>DRyAYyQ2$^a%d z92$kG&%+jG>G%~6Z4crnk>)~lC=*L!4>N2~>^I@Nqo*0>u^rg4$&eO07CQb6H&Cip zT4T2I1!hnYgH$Fj4y`gByBB=1-bF&7&e&CZTx!%@LwcfJpLI2Omt$Q3a^P_gW>D+ zz4kg+oTEkXn}qKeN*K@9U_^&wJvN7-Jk7Vm85?`u>LH`s!5y4h>iMQK+OIP**$)?* z#g3tE`w$SNF{8vWqsB3#+A+iJm;rMx-_TjLV7~EmE{Kj9e#Z>iF=L)V^LWeUs~j`t z6D)ue08geySuh`gvB4~sRji7PjLOR81s?2!zOitKhih(j6dLBWYw!TB*K1b{AvfQw zr(GT>o`+qX7skACFscy__QCH38Voa(k)EgrryrD7UYKTF@KtqiEo)jy?5x24 z-)yPj#oynIlz6KiYPv=?^J(AwjhrWgLfeO{=K2()n6xV&1{|2M%8f}U&atRlMQ)Bx zM-C1Y$j^6Ts~Wou_Mm?i2!{wzpetg5N?;H|M6&h5o9AEuPUEC7ht)s3@D~$XSY!KDGwLHZJh3ywkZS5bfDQ_k+MVx8OE9 zi3h#T_Y>nu)3BG0;2BIGtipH~$HU;0k;w+9C5>w^H0H^d8v7VM^>7oeZ*UZ211^8y z#(dl{&j{s#!xHgOf^x`4IdJHWLFGZKW-P$ol)CyQJod0hMy|1^I)nP5HvF(4EMg2} znnYfJy$)QA{Foe~%)D(n`ey32Q-zh(Yp0r;W>L4DD#DX;l}O#XWqs3aE0>8h`xO?6 zH1QSIi-~kuF4BlZSS`}*c0}BsY>{Sp!ZO%;acLB3LMN=_-?b1{i8PZHR)`pKVAQ{A zkw|knVXa6LI5UPkB2C=P=*vYKdx&)Eibw+x!)`&t5D}X?ZWS>WVIrMLA<_&jk!lPl z=!i5hF)v=bN~B5Ih!u5wGZSsNL}=J9agvn-{q;4xHNh5zyn_h%U;I%qt8p?~60Yyz zx&uHGcpull1AzWN@F(EFWD6h(FcM$`j0TJaOax2@WCNxHE(5p#vjDRJR|ARwWq?XR zHNXw<0j>w!45$Mv0W<fLVaqfU5z;fO0?;U>?8?@Byv|+zhA#ECDnERsdE5)&gz^Yy@lqYzF)r zU^fKFzdIj4$oGsndYqsH7I@=F>Ew-h-3ARPOiMCsMt+pF_lWhLp zWSi1E!ZyD*#ddA)NLxkkMYfXOQMPM(Q*BrE+H6Q1n6Fj)ULmqgT2_Evn!z}P{1$ej; zJQRS3+2G+S@bClhPzWBb1`pSOhdE;+i-`wjy909A06DCI99BUN%OQsb$YC+$PzyQS z1UUpC2QTCxLk`uDLnY);200W#4uz0I0pySmIXEGQT*x5@a>#-l9FW5V$RPuANP`?w zA%_&m!3sHuy_xs`ai|E|X62a3+jQb34u$?dDw9EOs=y7O1BykNC7ETJ6`3MbE&ZcE zfu)ju#x>2jW*FBAV=0!!Qk^MUQ>B1}4@{Y?!!e;)aRAiT6zmPkead&WXDx?wk1BL{lQ>yUa9-|LXYv*Wb9f0_M(w zz{akk>rk6W`hu42ibLdHM z66HhkN17}+LC{m7(yD(HaIeJ*LjHjQXV`X{TE?yr*kos|6pBa@}~m*3cP&8 z6P|K9H#vw^a;ZY&mtZ14b!wp#H{e!34Q;BEhBUE9F5C<~a?uzk_9zcGLyz)k%oBSw z6E{PTX7X{6rCRp8Tzo8Kxh`-mP#O;~!g) z8a_=CX;fqJdi>5=eAr@90{%RgIDx08AX<$``wbGx2rm&cDRddndooAoQOZ*}T3+og z21@yryXO;1`IUP()f_bIkHw%_e`pDs=}{KNRorEPnLrWuy0YR~PN0aZC}kYQlAPi$ z&6@?Ph+SKBn&D+M$;G`TC@SjyP6qRY;sD1B2*0j|r3VO-J#2*IhqHTRVJs8JgLVBbTFDz4A&M8kE=jGc=_uu1H2>nKi2g&7iF8 z7jVujEsfx}xOh?xgTv{F>#;A&H6OoD=jw&uu0d$VX90u2ofX#ph09ygu0gnQn1UwIT z1@I=I8_)}Q4{#PR05}h@9L5|3Fd8rskPWyDFbi-spd2s{-~-$YSOQo9SPR$)*bI08 zunn*S@EG7Jz%zj70j~hw1at#>0q+6M0tNu*0XU%CF%mEuK;{1*_#YYkzuE@6T5RLP zd&KtNC8jz0_J}PVd&HG(Vhi`0X|uMtz7iN~OKEZS(>1ll^#NVeT3n~;n$hC=GhHXN zxHMe*_E=lm94)Rt#qg{ad~gZRb6Q;c=$hN&+D%tyi)$xc^IKdrc55qWafRu=u*G#B zT|-4JF1T;Bh00o7Ffg`-DqCC_ueXJ&TeOueeS1>&h^}P`ldh{;Tx00Ero}ait{Ylhm=Lvv?r3pE zDZgNg>r1-c)8dNI^}ZI@-|71E7S~_t8g6mDP1mh0u48n4xW)BHx^8cAy-3%cEw10w z_0bmBUb^mXas8IAPqw()>AJ7Q^-H?$Z*hg_`do|aCv^Qoi|bChcC@(G)Ai*R*KKrt zt;MyBu77HAEu^c4^3$~o<)`bPQGUAqC(2LP(y7r^|bp0IV zr|VZJKV8qY*cg|zb&sfjL?TcL7 zf^pbA?37KV6w~@5OEB1U_qc7_)U}c&tgcblhSjy|nl^Q<$DY#ZG1(J4J!X8Y!Q#AS zgl$HvN01VnA2C!yYv?-<@F{}pB}S}v$#;i#dgRP$Qqop6QBzaFQfH=|IVLRQwkUE% z7#}~8%&u+Bx!QtC2#3B=*Y`zAzlcV?+ZIc+Z5L;+q!YW=!qz{u_K@rFI%bzUa4en! z#|y5>Udh_`zTGRNM@mvKbgE*m3U<=l>bb`*cHd)r?yr&02cpr#i??_+ubPqfsLA(8 z`Qq1uEFy{?U%xM3Yz%wUWap2?qajGh)ad+M!u{$xb-gSx5@EzCHn!mVjpX#wlPPgY zwuYkWdZ`e%JdW6?sTtnaD0)$2U*t_xqMGuOc#C>R-lL*#tGa%xx-PwZF@krgDLh6| zqs2Bd8)x|NrH!kzm$P1VLi^scy{7cYMws|*DY-aRW970n4OeHc$1_L!-ha@uI(l|d zu71iZ*7)_OQ`+}_LQhNSDNlB7GgeIWWV4K9FQ$if-zPTlFA!wD0{p z#WzzB8-g^iUBs8iR@L(W5LWx%4=BVLtVh@`LI^qx69)n5@ozHne~F%s$kh)FygGXk z7+=@EH$oA2^N6(VeBly0sZD>n-iY{9dYX=8V~-c=JJ0n{8`}52OKB{oQ1)D$-v;kW zoQuL&@AM$I8zm^FAY*c|7=vXfJtu_1vY;-gAGPm&hf*4cV21?FEZasS(^XCI0LAh9 zG0spKMe1TB(+CzQy5-S1onpfHq?cr|rE^O{#<;g-n+5Axv5=orqOTyNt?Qs*%RrjT zv0Aop$%gtR+?QctOprSv$TJl9VG5jrfP6Kai?PuV)kb=hiZajwrSX{BfY`qGBZ_)6 zJs*Rp4UNkhC`?Qqx+s#2GG2jThlB{4w``M$qa}+M(ve-u>u%=(<@UWFQgRm|9GE8Q zV=0|Z2^|(pO*RDaJ}fX?T<~XGvTy}l%;MyKWBcCsD6zv7C=FFaVNlUA{;4V4(7yM5 z3bTX4n0d1fwD0|rNIxYKF*&#nyAU4t^it#)4X=ShBsv`MzbA5T``*teqT3+D8=uHd zgM5`ihHpNR^9}M;gA7l7A{Q9s6e17L9WMM7qR`0wBfQa+I~@9nTx3K%VUXe8PvkO# z{0D=K4FyE5G{}$XWZGUpJ74+h)ny z9Z1XSs+C2Tru_cTLAg>^@^Qq_;TX4HYK7#~zS=x3AN?&AMzpl&^ z`gY=jhz~_^**0@a+4VIjpE_0BieqT1Y$ZOi+`l9k;x>WfWJ#VKv!pPdk)( z%GSa=x%T!V(b2QTb}$pV_6*x;$~esyr=3pRX_|gE)zoN~tk9}WsKV+q!cNoZ)52mK zJxn<((L;;#8H+9NA@fd?J((g;p+FPQnD7%xGq;mFq;G>SM4nu}4j*)(%@PiMtFFg~ z^LC29uur``uHJSg`cZctUUwIx?!>OUZR1gI0n}Tk5Rfd|=DTgl+P!ygHw6M60pCDP zPuos2z6cj+r8K3uQlabSWwK2+I;PX+onj*IWlW7{z`xn~T)uM_bJ}O|{t6-i(_&&j zK7_4`mR6w#9qY+xtBI~}MO)1^v zHg>(f6Gv-vu^X4Z$S3IN)RgqU1exBYZBy6T=lAn4=q!IO>Y??^>9LK)&ei$OMTvv; zrJ+%_Xlmg4^hb<#%FB6%sbYG1`<(0RylEb<-g z{CehKrZf`b+30<@87)Qc0{to%h?saOgXK*srb+@5xa& zw1#Ri8cWkcJIyAh-jp6$hGAY0o6^G^eGyvFe<3%P$SJ9%e@m)mk7&}=J8rSq60=u& z(NUo9`GQ7C6U>nCrP(W|!V9f<@XIOmu?ccZi~Y%i&Uc7+oZ`KU457GbwDk?$ci~Cpos>orJ`=TMAvRqj&gT^8r#vMX zO&y-TNW~`@d~U0QG74{!@t@ewUgU7_M0ihoBZB`mG6~@hZ`$JB=WTg|+hCIA zlk^$Zff}=Ga@6(jQHYIwzjean)SNuRl$ttjyjilP2z`71;cnfeuC-e_M7M1~YbQ@` z`7ATZW-0ZoXqH7u#HW5OZMy{7a@J(x&zUr_ZI@Z@Ra5%-ht<@SXWDVRkwe>}rrO(AtTQ5)4x z{?b~=2D@oHxmS0#lS{RFQ|1?zzP%^*oI7h9wdY*O1chl&7}Nfbw-OxmD>{yt)SJ@2 zvG8}m(P%OBjin1;uEwVjHIqkEyhr`sqcvW8hUTr)>U>9Qe4RcozPu)QEXNgPz|+e= z`PtP~*X6MsnxlnY+zhiSzLx2QbTxH?+wOczP)_2bwP%#NuTCnT%APNd$jXK!r6tFE z>}TJ-!1|7D{?7Ljsd3-oEp$0J$8yMlYQ|?Lmz!)~9CTQE1Bb<10(j|}w%e-o?N0Hw z-6h*?t=ag9AF$NPm=hG6Y#(X6MQ>jjezbHoZ3A#-!H0P_-~8)6ff$%7Zh#o1^0Ski+NE6Ues@yB{end-fBrr-bcTp zhTlUe&L*bSC~bFny4>9!$$T)y@^Y&CZ4X#$oh^^G9&zGDa@*cLa;4mwDyNx`IQV@R zBF>JFn1IwMZn7TNi1xlSjkPWFA1ci8|5n(~4i;{$*w4D}LAJ%2v-vd!EzHT0IW?C9R$$dv@4!m+j9l)!@VFf^0vwt*Ol_J6){JAv-T+gl99? zb5VMJw;(SA1BWJc$%8|cw`S=>l}R8Q#MY6rWZ9}(ZJDTCXfyeLTC!R*#*(6JNq@21xoGhpA#VGRBG`SyNQB(sFs0N^;&1yhvCl`HpWTM#( z$|z9qd0#?Dh(HrfgeFmxNv3w%>w()u-0JGV9Z3`@K!Sh(CLYa%X#H-CF#`CkEwqaJ zOmaIp>8C~nGe_hNf{f2WyZ6<}kx@YVvFxq}Fe=3gb}*M6hT==dYD($CRrEcQwW}Cr zAjY4AO=eSquv4TttnXwrnqBv^zP;!1miFy^*B=(tb#3=znA3Kza>^}tx+hDft#YR# zOAWSnU~O23SAg_Tj%HP~137B0ElHZ+A*wk8N`If~bZepiz}GGn?boTBv|pzItbi22 z1VF~7CM3 zSQ!P^B0iv?^Gm$;MM^+aon7E4#3ieR(jX`|SAZS0TCJK(Y)9B6HCM4KlsPH^xKu$| z_X`t+My*ciXSjwf>bg!r&5~wD#-_7M13JUBrdO!aOj`^i) zNvaew#6FBh{mx@wNmptDLdd*T$byu^8wK*}QnXYL9_+_wZWYOfNP0%-IzQwkKa;6e z=NuYEd>O1420a^6Js3A_8c;sdg1cY`i~bc0$Kt_JXzk+}nYAEmH_iqclr_dm?~H-4 zF_5LV6O2*2)+J3%4lm#1p`cgI=~Qz0gI=_0oMes1FTcxD#(-3oDN&0hM1U)hyl+>wZor+o}U2Z%-%U?Y; z%Y(Y13@A*!5hghn#+IllYNac|Ld{24H&olsxJc>*Z=s3_u-WJ9s^bQKN!1J%?}0fW^9DH zo4S-(O{5L)QuJqov9_wyG5-uFsq6OFKT{h{R@ZG)r%Ox2Bh+;ed8;~IkggA>3}wf2 zktz@eF~cL(bz6TUAl^lKyvxI*hT=^Qrw+v%%#aeePqNq&T;`~&(|kr*ob)=CHi&A$ zYlfG?^QlkyTi6C+lFp{r0>bP>@_nlynjEcgY{gj>WPxg1)DXqGuG? z{;?rRmOK11Ldzv}yiW?2)OFQr^0IIm7+;3M$!Me5;nBFOHSWeBT_o)92o*tG-T~iZ zTA-v3O;bkGywwy=r<%~;+A-?7!OGCkPhwnOL$O)x)ADX!7*Glalq}|IXL9|c% zzHkPYA4_0(!+4@6Q32G&3T#&|S0w;yX5ho(vUbXB)wG2iT z!SzRB9skI)vnHUKea9IeYiS|c0_lMs&4eR~R__gm{(!}YdM%(jHD3egtGhvOBELE3 zJv-6t740K82tJ?me0TyXWvvjNh<;R0O%J||2iKEqr{ud1I7zF--X(pMrxtdp1xEc^ z3)|^kQVXN^}OJk|1Sw3jeOE4MOtVjN`+if?${n$B# z{{#xv*X7nWQ=(sYx=opRJmr%-ZAutQ4;IkMmoSVCPenP<0PQ2fSyZAjULq?)IxleT z9w*+@nX1za8Goo=a`7R0tDr<>WK>*BIVJVG!M~;y*XpX&{r7{3mS3nj9VU#mexXiB zM|BGuZ61fu6vno!U>60BftmA$-_tY3_&E*>7uBs@ z%<%0y9qGrpCD1N0OVG`*qEfG#zX1v=SAabR+CJo%kMYz=<%sM~`+7sN0&dkZ%$~_~ zl#2+|IrXdgDY}J|x}sAK`P5|j)D-#DRM|Dcv@V^SXM4mch>1vFM&PA2S#@r8Q`d89 zit0R*s5-Bpex}DgRS$E5!Z`FN6DaWSLhJ+8DW$@G?39wXxuqnS9No6(U4Id%&xxhd zPaQ>1h{m5rO83X5beuYko{&29^wzki`>6-$3HgSe&Wn4xg!%>Iq&4(7SnyNt0H!*C zUrU{X{>X>hA5fRj8tPD8l9M`x^oR%P^rT_YuAoaT>Iu=Ha|&_%P^d_Cq7k9P=vE6P zlg;c(7O2PQu}c`E7fAio1$3sVMbi7Eu^~b{>EZg#LE_O9I7$k*i(XkI9#`}&{}>YD zzmwubnuXGKQkp!?2T3Ik6=`G`YB45svy0|R=P~*wrRvBmKAWmnuo;Tl9m44yj&YaS zk~nH{jGICVvBxsSXcuY7ne-r<0XqBLXh>2XX+7P{_?eok=2KyRdA{F_28cN(w-2fL zL+yxOBRzENDNK<@8?$T>@XFnEk{Z+FXCYc{y!;p8PO1f`B(=zLQZ3|H8ml+3bwUO{ z&T6btImo*cBR`QX6s)Ex`ip~>&xDxc_&Bm32{sOy(k$KRILxlIjO*dP2-ZlMT83)VZED?WA)X#%Ts?QI6Qo3Xm0U+? z90UWHI>ApPxCr)e_|E#Q2PVKs1hZJ`5#DF|$GuPQl4~o|{Ay8bY^bS4Pc%SRicd7~ zL0pJ^N4h6S9W6_8WDY?4mW+Z8m=F3x44U|fLTD&9$N5BH-<(5*SmVh*9KvpM_C&)i zG0Q`wU<2&MTWp$|f6GQ0Gf%v6ohI2nw%?5Mk||>Zy=MI;+}VubHYz|<%b?OsY$3Zz z7>lpra=DZEE+hF-1(XR%@EzxxOqgz5XT=GhHLhH>7F#Wwo8mFFb47;_M_5T*M*|?k)1%teNL4C zM~@>QZ%Fa`!G>__(%u_2|BbssEWwXjq8YiGgGx~Ip9nzu1&}`G0rAp52+vF|{eoMx zEjLmHbjxNL-xN|YLocn6i<6ispB+J??-Hnpa8;%0gj){%sGKys znp1>n$w_yo=pJof5c<(8jPW1&?@6R*E^?*+q{g)}bpNvQsg&Z#1&@rz^H=dai$DJZwX`OxRXjY#AF6{7+ex3t*f~y9 z$+=KGJnZ(~j7B6hl5~0rkvKmOF;ePXYJPfT7v{%!OM=J+%^~0Z4j=y~lLB`>2mL#D z3U3PZ&}n~_6h0mtzyl2Sa^fFKDs=&P^`)Jp<~1u%q8!oh)YEp_C-ON$5`Qq4Mmo%@ zr>nm_l&S^(IC7_2uu3wYRGl43sN<7reutIU^-XM(DIGN~;|u8AjMRj|!3OqkraRcL zO%^k45x^hmH2O0;nTc?!Gh>Rmz5$=tSjaz1%GTpME*xFBwwX5+ye`Se3PQ^7H$iPT zZpYNyeHgC=Ok@H0TB!x3*evk2QVXb|Xe60nLw5uENVF0yfNAt0WQM_9GQQS;scGPY zXjGa_jiqn5)tw$GqxncaOnbPi@TlVayRo)PE0gBgbVMFwAE2)Iu_uh_ z2aGM`eQ@3^=L$IA)G;rdPxu#H^?ukSni^3=48N#-o*FM}d@)|l$MRRB$!_U4;|hCL zehM|%9$`F=U@H6BAF@1(>5&w#C1;0+Q+Bb3nH zwF@FB8fj)Qeo*&{X$viI)tnlybeNRG$%iu1O3dC8!rQXOh_^MM)Iq9yY$;48id_ z)*0Yybm&4R;|SbwP&mWCXpBKr2lE>?w0_e?B=a17_CW1-!Mhl!r5l6S4A`gM!JZK` zh778cp3xF1k(7Qjq9Ml~mVwcq4lq3B^DJ*ksP8d%ed* zePX^`qfhRBD|Y#NSawh7G@fU3#RoHr-9t_2!^M?-d!O~R-R+}Bq}{C?XUq7g4;~eo zLiScZ$|K9_)H5bkv{L&zJ#kt3fbaOHYOenX37rN5Ht_?vWNOO-r>3dS9ySdbLN3`@ z+{H<>&*D`W$LjIDcDPY3S+TGl2N2b>#Fz}gmIz?xqQNl~-HYZbvN7^Mk?)2Bs?QDS zpbS1Y%DImTB zc-ItwseLeF0~L(aI}dm@%?gq9EQ(-81i-syM9_m_j)?p-XugL)shI!j)nRt6{LVG^ zJJ$$?X~z;Y4r;@vvekSv-2$WO(!g4z$7j<>@uv2haBXGkIte-$D7W-=@Wn$ThB;Wm zUa`=8p_JOW3oeCq%NDL!OfRiDA=x~RnJ_z{Ki;-=6u(1_cWC8F;|arxlgtsW(?s-} z7|=Qo{gv7-Jf?j;zU))ka*r9mZoOesOYX!q~K+ z({I^G-UnXN=&uQZoLvl)cHeZgWV1mG1sSP9i;x?Y~&p($R`Jk*qh`V}Q^4w7AANBO6GyJ#>Gjlh zrRYno5D8?!2Vi9WZKHSdEK7tNZHQjW&YBeIUL=F2-WS0XA88;(JsG@=-F3W^;5M3R z@yYKG0yTj@|?sgwl+ynl<(bCwNaqhSE>Wd{YEEd_YwR#`5uuQT# zcY1tMdR!V^MjEe!y=H-|(fYgXj#UjBDK9a^+g-;C_;yFCQTre3Qif$3k-m#2B9dMg z@sV~}d8}Q7u|DFl@EW(Oxu!`8zff~s2frmv5{6ORx#E=bS^?|jlm(Z~ADJNy!3%+G zlj<>eI|#>!r zWknbim*#=aPSr^RQY!|Fhrb~;&jY}~!}Th3exa`O(Xy#=TVhY*)ce2e0EEU<*?Z2l z?K!6wotn1iTo_2P^Y>9SJW5GR4fLzI3252qi%}4Z_JXKZV;UT@d1SC`aFx!g8;t{| znlU8hL$~xu@!QcTaY`r4|2wxo&GVGXm(hV_hVKH7U=$L~WB6Fff%O(gLmG1+J^WS4 z+~`C@9c*nWpyhhi*#=uGAG+G5{Rc44J&lP9jdRET1>@XIsqlbPUndsSqR0qQcDK3( zsf2ov)1&08sP{ONBYCKKB7-w-S&jfmG@nR zjJlV$km%l59C;7i9l*?w#=3Elwjt8f2b{%`SMZ#oy^DQUpS$0(C4a6Knq3btS6P($ zA1Xt7lw74BZvvg+OD$ z+jLD8mq;Sw!iFO0nWr+>PO6F?wZMjgskxRxjN9FiEvF3LfXRFdd6f8k{a9{b!BW;E z%)J3F^`XOp`-kt7lfzg76^+mRzjxfX@8WLbih#AUQ7z%S~ z{&8tXDoj*rj$ohs#wb)W;ndO{naLb;0MpH~6@vcqU}%8(viq4$RI|@)GXCkByCX%- zrHA`WyG;9cnW)YScfo{GSci3u6gB@K)%m9F70f>_oC@YF`gVhYt4br&pVoN zaAkc1PoBHvx+(c4Mq5sFvEr-2Is3?{cj|H|#q)UOf&gzT zMn`!i0I=hXYIvv)(a`YRjh;jB@CiuWGj-cGZQG>(4tOFoe&bJ#km&RDNf?c{Zi1#9 z@O)xCqFUTo=kLOV4SiMJ#yamte;rj^r{a}dRA1EhL#;$lcu8^iNc3W4vZn!piCa;~VUD;9i_`yJS zY|nSH7WQdjzZS01!hybHJ3tV_nmMeQ!kQ57JN9!5;nu>67WQaiZ{M*WgWwBm{;*aP z)&gM~FLt^`X-}tOmQ-xylOFB#3Q{|-Mj@ENZXH&Q_=ptKH8I~t0l}0BR8?I*$epoN zKgObZ4Fq5=q`JaJ21VNxgoMa`h^M#}d|F+dwyA@O9dNE!J{^2Q6|8~m(}Esd?(Z?G zR^=l;Vn@_~8;k2u9&YkZ>JU8x%9oTPlID3(4bwdz^m>R)K1|<$bll^m+q$6U1?5Yw ztM!O=#2hsNBO&k@G$O@i$ETD*A613|mUz|?J;rgbM+^F>O^|1DK512|@Jl)8?-{8g z0O}ufyPXs)LK^O8?{QJ1KTBsHLWF7L2RY1(i6jdjOs&@436Hr-61Udwgn^3B0*c@{ zl+WeXPN!>w#-uDREjS+NVaP#TO68(~pMW05J_bqxwiS8<872ti@5g6eB$&Rv@9BFN z^%EqxpMWY@zjX7n5VFc9^WEm}MBUxM|Ma&#Y!NUHF(&Ia39T zCh|lqi9siO32PbCnZL1V%~~vklY(+!iIVLVve?T)HG5kqVjl|$oJUM#zA9#^WF0+6 z*L>>4(<7v1dKfnc_ORL9+iNHFqc&#Uc_6<>D8Rni5IdLYAPk!l1C~YOlGMyt@r*!x^5uw6$$;laR;1p@RNTP$+jmH9hJ(GU{M3V;4eKA)uPe9 zz3PQ&qCsN+OOE9<1}SD2Ho`(7A(I{~A|gI7q2mCiExECDeoyHftBqcm5ZBPT_CHX& z8=n_S9-*wXcnM3{(We!G1 zrSyax4jhh3!SI*|GsS|z=>mg&`7;D%aLh2IL>aPRBg7163~IPI2em z@71&L5{KZ;Z}2t|en(UQt~HkWy7U|BXrT>%i9EeJ%YpH)8i~frk7%ean|IsOrf5gO~Qo|6NI8W^nc- z@{-z&l9IWBN_vEs6yAgLsHC_SQAvw2ucn4WO+~=k%J3SdG8!)kuivktHCt6Ep4nY6 z`wg}#GF))huu%5g8&KH8s$26fjW0a*86yapAe{9AypPH24YMSyU&77+Y_>Gx1pN3U zvlAX0WJRE+P@YJ&mQKb1D$B^hT3bhD*a#D;-uUqFhS>BU6&r2f-L!ay405* znMnChMgH$FsgP#rJpa6Kwvm5M_+mWVngCmr^G^wS#?vm$xQ#Lv8R=kWW5TKImbR5N z%U&5?sTOx{q3N}*CE)OCp+OqA&fB*4yttWJb# z@eaxd1&e?$@wLJRJcZkU^ROndX34UqHMf%yOgWZrEV0>`LP&=O61D`*P)!G7_pKl&1p5aTQH1~(jrW( zkx5NPGDNj3&>E1XDaXCu0nhKqnSDS}H-ygB)O35L9lG9AbH{H+<<1oio-hP(u1PR> zqW=FlyBGgS^=XOjuzMZtgn+KwxKtr_ox2jGi}@&1(XGQ{`AE~Fn}$;c^LPe%ykj=< zAhnm8(2vz6QsMn*#gJ%fpfdnwVByaV9PtM_tbq-o^8u_`k}Vk{dbj3Ajve|l3aJSTF&D_sc)79l#MkNz)uP$JqvKMP zQ7sUp&rsthF$yB<=ucv5A{VTjF@X!bBmgFdFT)Ff0aFMc17b8I`zkYPAOB%|h|3Y8 zR-tAUo`LA!nlM3gqG2jBwraVkg)&LHAc3Q3ICEHBDm;1~qW{5!Y1d4W2qS?zf5WJw zIDSEVjrR{#?Ei27U^5y00}e-_LKpCvC+1+#zkI?OVdKuYp}5U4;jz4Z*XbhV60sj(tR3AC81R_k>8G@i!f!KY*NlIv1{#D)boBN<`?4nC9w zWy+H=+c{l|qhp^H-?-DOkiZ%s;?qkNDbfY%0bVg)!`)Kl~PPg#QdJ3d0`! ziplkm$>_r297MAy7fqpDn@naHuwFF%E&4*#Sajx>Jmy-&BapR;mqK;I6$Fz!c(EkF zXa&DGW0k2I^J{~3s4-eM!G8=@-OhVy6#WHvi0C^u#-vt~v5Oj+x9+5uTYd&;KtN$* zPwM1OuS~NE_epgA{m#$%$`TG&Lo^yCz?2x+$dry%jn`g)LtTO8U#_j;II`WaOpyl>{$rE+nF((AkmlO5<6UiX zxvR|?xY|f36}pT-5bSz!cF8t7v^CzR7}uG{j$?G50;34+qrHRMdrNMsYg+73=!=AW zAG1D!F*f&1q`@*?oFI8q%eqaa$k>G__jBt7cW$Glgs$hwjOKu2KfP&bn3~`xu5TFZ zEyzg8Eta5=ky6vGiZDE;B1X)(=oTz(r$;Vkxt3|EQc2)P;1bwVw zmJ;y_I^4FAF^WktVV2{rg&5mH&-1-dU9nB;NwICG$jjKi4hJ@{OqNsKCAL;$JK^zJ z+mRx}Z8kWZ2>02YDSG9^G{>NxkvFnIE%~|e6h|*nUv1%zpX6 z!Dhgl?FEq^D?^oCjO3?(SK6?o{?>(9VWJ6HQ*&%ZhRi*USnqS%ZEb3dg>-O3&IcpMSi!_zm6AK3VJ?U_! z4AjMj4gLZ_S{U60*u(K+Ypa2D2e zB0=kZLaRZZ(=^887l(dvvQ8X{HRVK#+irT>b99uu3yc5sj}Imfj_el{IE}j= zh#L2<+oRjC7H<40jt=Y%k#pj=LS%IoK5-GdSFo(}QZ$J2UFBJpgqSx#8p_GIc! zPG`!O+eTAgawb#GqORm@x(H9Dv0Q4gG@qefrQ3s^ZkJ$juF7^@V@}4G4xl3VA9)}S z;-H9Tcg!P^2FC(3-JqLHV}auQ6Jzd)b+|)u?R=^n_saQSw2GxcAcUR)2M`dC`5DjeTv6~*FDJdTNXnsQF z+nx<3kEg?fv8r-9Q?d4AuZo&)t2Lt2K(+`g@Ywxot3C>o0YG<`6fxR{LoS7mq+8S+ z=mM&hnlqWp5+S=~vVB5_NG^xGHaJBIhfD~O z35RXk9g1<0eM}@N4Nf}l0~0XgcMAt57&|}@n)-3h0aoXoKNk#ATukQ^QLIGd$9y&) zC*LyeIby=_*#ag_9!vKY-FL+K#Z>a?oOJ1-tU~n)h2s;Kk1|%5F6rm!9K-pu z_h8lm5soGBxShP;OD{EivNf*{mXyp?jI?!hl11~nZBO^J6j9ATB7XFI6@@D-XE)_sQxM3sropx<2$Btc;UcoQw^r^M)`DJ539*)3neM8#R;~ zdwI+D@v6i|IPM2QelwMtS`F*lR<)#`CBP@)%tXH7SVSLPawtP{c(gq!UU(~i=r#XB zEdgg_fBN(wI*1ZeCR%?YBw`z}O)bIbU%;6z`P!D1IEN{SwLu)}`-ffQt( zs_Xh6zi;NvFpMm-pn?mIJ5gfZs2F2N#4RzYN#1+2Fya!yeW{wIscD6PrcIir0r)DfUtPdlUE`J(} z5Bh@rwJ9Rxw@sTKaL@(lL%kjOX-D$rg70|LHFHkyEQE=pv2w_vO2?tf5sj6jIxuyw z?qDOh)ono64h|1OW;a+qVL?x8G=gXnff++&3RX29%Epyb62KTze_xcpqKQSz!a%$b z%_+^wI(_B5ldPhfQo)XzFi2(GjBzGcMfxRYLQr+jP^=k?l%Tkg~m)osis5=&Da_9C#G za=vxM>S*H2TkzROCz&Q-Q$5)lM~+m)jEf#yy_O6NIVC$ptoTWmeUhO%;J}Nbc10B# zcVWKXWhmkirr)J6g6c{Uw~H%c*%~tr+NFcU4>=M$j!G{eS(&Pd3cYBIsA(r6d=_!m zhmZkD#^@`E>hTrv(TE*QA~6I*)gkm1xMvEFMg3xk6QUx;z~FYk5M10a_B2h z_$z4bhrau$_q%8kpb;2PkZ8V9YV@Fh47pi(5F7#W5Q$pom7)xBWZx{S_D;>kMU2tHXTIFf`5M#W*F|T)2)O zcDlaO`We!>Pz52Bqp~?*DQe~g^l-$F<*z_sK8{KCzN5-`NBcp8U9d$%Ez;yIEf$wK zwBo`F@k>Z?@sfe1z%e%o{YTZhD;*dZLy%Drb|4+upk|saH6p_h0lPsmA$bpa>SEj& z^%6u65^Sq&qH|udwEeM8ch`F!PswBQCXWogm~3J9P~qIwS1U(Uj_3d*x7wL?MHRu^ zdND^!mFYrqS5f7(%Damy@2Z?ugi|Yb6~WB%R2q!VoNitI9M*W1v6n9qcR4%z$!x}< z?BFvYlEINIdK@ey;0GJx_ytWJ_-(YXApRw=?)bWAnDhMQh;)DdCE?DieP{#@Ctz|H zY`ki!6od@2!*k^FzQTOo*Ie^5w1Alj)UfFHb1P>RSIz?eY&}&uHza$JY-TO|rOH`2 z74cK1?Fm4-rIvA?k}`w$q*p%aA$Br~^L2Px6wS~W!yR(?v2q>;C1}rfiU=hjtn}cF z7nszBl|EZ0k(E%i_7MhTg9tI-!y1i2f;ms4VDvU1j-7we3$jUfgxr2rBu zH)pq+uwE51uGYDLdG29)=a3+*48n%Y)OR%E?yXF>#$oP=yvvp8wJR$#XriA?^y|-J z<ZlnhN*{)JmH-7*8daA+WA=zh+1?AO3wVCaQxDCp9VeZKI>0)`F1wo z%A;34?4;hC`Sg>^BkKxU3M7AXts{h8m%->s!XGc82kyE=z-(6D!RV+rk%~Umy#x#) z^#)}fqQQV3DBcZ}jR+F}sF5kXOiE!J365dXm=5A5*UG!}>AUor$`>VggxZ>$4LhCS z=YU+`8xU&OwpeJZ!GJIdvg@pxx+IOm!5VWF0`Qs3Apm3PKPTv%rZGyEPXQn+pcADf zw4N3!zH$B~h;2_@{s6{Ze(>_~iv*MzAxoQm;bQC*esSp-&JmH3z-gVh`0p#|K?Q3!8#Qr{2OvWSRf zkAiUMDg|voJ{}}k1ZmXKkfQ-d$VgRuACQY@64)-#BMZ~`JG={@ccNA+JDZhhs3QTI z7%oI$^>-OJI(7&3he~g6w_>{%<3wwK#~wqSV7-@SN$XUt&P_kIHMZ!a{=M0BM`>aV zce2j<+i+mG3WW2;&ds5f*iCKy%SCFd&ial)mp`06@l7IgUZ5VCGi%nPbI2GuEn_zE zZuTqQS#dE!KvrKk#%Br_I&bJ7Bek;NqAGbpNDAVMwXFwRXzsyAr$_Jn4WrU710gP| z6+HIXjzapvVlntDcvY7j+Tp3-8?tq_jl~swx^2w~ZPSNh>lt|Xd?ZIao^`f|wG^<& z5(-rH^$g~@dQ`qZ0WBR5r_DNyX+ss-D-V$XUV$nN)9bP5i99(uI%D~0rGJ>I} zF{dE}))zSWh9(l(Zf;LOg)ljyF|cFf+YjBFNMrWVGZ8MTJPs6Rb7j=?1pS}{5_$M+u^1&-5LV!{(Mq&=7^ixq$Y76&3}e0X z7f`X@hd##0Tp2=HO$;CFBR2GBE70fE!NiO_<*sSz(`U?_ zHG9r|_s@Oc!SBp_=;231Nrve{Z|3~0g^w=D&RM!_`HGdR*R0#{*yB%rf71_h^R$86 zkLEig0Oh>U4fz|j7pp``IN2d69m2aE!k;>vj|cxT%E;HDj2uE4`DTmgEN?Y=@hkkF?u;m)%PJ- zdfQzZDVY=@HkdE?KJl8I+16i66JKJ^Zpb#1<=jqVog+hUM z;TSD9pkRbo0?L^+CGK|$pXmt>TM3jVKHFidr$iXzG;^3m+p9FnBWXfIof3r67A>He zB}}9U8~g3jgGA9F)y9yE#%Sd8P!ZS&pamKxE|6}JHk6}>8E9<-g-9JOz5p=-UkF3r z>gdJLS9+YKJp?~fh;jOl9^sc?IzI_&T^&zdZAMo^Gn@K1)Ymn*VQNZZAGQzec=>bc z*;yMNe|-7UCs%J+&zuQgMmqJ>=fcwVYdwk{run#8`7L%9oet(3GHCIz1&fkarH)&F z$J+1SwsG>rr|x{>d(Nqwe{kntrj_4G zz4|^G$gEpwYo-pT^)=Q$Xi&S%`8=q7hX)VTgb>{tf)*rR-vSV?Ia&jz_cq|V1^QyG z&sU1ALq!*n*ieBY?6ZP2HhM@VTqC=*8oUlqc7EB5Cy(_w zpX!Sz8+wEdp94?AC~;Opi3x0=!Te>SCQZ3-_Ct@(+prQx#Yx_-d*g4Iy7~%Ku8H2U zuH>A}e;025J59<#M#Q2FX7T4R0@4;$9dLxO3Yi|vf3)mcc|3^iK|?1s9((CMLt zGp?QK++O?01}_QZy(DEJpX#GbG>uL-(l}d z?|gu7R_0)DJ;bAGWmKjR=SR4Oyx=3D#Z@W5Kxw6BBUBTke(K!JV7S){_(8ZES>W<3 z>UnQiDo_wwIv3zLhL(wF|0C^Z!$uHr1xBGE`@>5;+67$J)cTs z8Xx*hz;wJ2Gi}=usxzRpgY~I4);*G#tXW@bDzIMw5c)KO&^+?}vQC)&1e)WWT4i%< z>;+!XHrxH0`WL;hI@`2x6J3PAsNgtAGKO8!_FRF*k^B;{FHML{>s;1S(T$451)bY; zG}R*m3}~+lAAg~JY;B_Xy%9j$EDQNMn$!`OK_V#RM+*hpBoa2^g;osEO(R)TxaCRO z;q(HVwNt)AvZhFh7~8{inp##E^v)rG%r)$=^udmE&V2;^kUY6t5~{gtV3J^8-wXTb z5R)|e+PvdVL4_^o^#aKWAr5rc#T>v=@<2B@+!mVAo$ELfKHO#f&rlvV-3K5PUi<7u zu}%^@y;n&9Mr*_WLg*<3bcJMKF57|L08)4rq0QGDph?3#wiliE2Zcw$3FCwn4%TWw zr(NO#GpT%i6{xkH4kICqI6QCcS*80c1TD|;8ui@ZDj2qgKlMLQeBBT zqMeyVx!r6QUF`{G(G9!Rq6aj8rAWRKPKeNjBMe*#KOE>NVUEU~{l;lLCro3`J?D>* zyDns?iO53(S3cp$IpHX?;Bw#+P!tlB%{~l?KH28yyjCMUG!lV{Y?OrRqvg`*!MS+| zMFCKk3g1wA6^9*MuzH=@GAwgcr+7g#N^Ehp^6s;Ja%l5{L0nJP|ItPwT$xQPZLv6o zt!2t=I_p~}+#c&OUH(%n%J>+pdquc zgod-g{b#U|M`Rw$j1}6nkdB2cHYd|yo+<$*fvNc%W(xe#oYV;J7 zY#Py0>m9@%5Q8-a`CvxZS>GlascQCFD5E%JWELi$)5@?`3yEh#PgO)Zo0a=$EsM6H zVyIlYN0>~N%e!^u{-?T~w4NZ^3wZ_jM3UvD5uruhKwWRB8!6Y^P`6+GHBz_DpGE2h zlH07z>aAOP2ynmp40W@Ac1ys8>ox$*9Zs{b`%3_=$@&hFX;cjKIaDzaXjBZ8`MQez znaJ~v6$^$zRV#e@X}Dta(S(*UtH*tT!OUzUao*OJ+yG4kpdpXrij`ACv>zvJ(>216 z3jgw3;ov92?>-CR7IqqFw~WpV1%q`#Xj>8E+$afmchez9mcbzNlNm9d*g#ByT{Tkm z31LrY2(RRTacJBX=bwW#SqM|R1x07qS&ym`B>u>OiAVvB2~5c(63Sqb^JC4D<#9gK ztF=VnyHVtcu29Ap<}_nr$1+lZSFcq-J9*#K1$Q8}_kd#|lp$pGfV#S9BH$Xbajvv= z#OlGVLstw$8t8#hP%`>rknsCZr&5hvr#d}vQ;o0zYCRzQ?2`~w|3(`r;kGp^4)i+Z z47QCjv1uQ6qP>3;?(4#wJU1vET6KPwGaIiJfHq34ROxxC6McW<- z3X`wi+_r^5niE59`_5IgEgo&7M!|SOsK<=Lq^r&=ExlNyccNX6tHN)Y?WERe*SCwN z#DCOhhETgSZWevkr(OTu5@{D^)Bmwu+J~V&`}q~L>meBAMIWsT3JY6=(Vr0Ki(PZ! znJWh2hgU)~n>Ia!bpfE@qcsd#Wy3=otY8W4X4-KQTg1vK+9njR+WOzvo~E1$?i`b_ znXb#vXRow=);d6&R^;U?VB&NY=9GsKANuin_qAslwy+8mHYF8S+}PEuO)K<)eo@HI zpd}8vTj2~scBV*&1GYS2Sc*&z!s{SZIF|L@xfP}~3&&gD#tHmuJ1y6y7j4vQlgjZk zwj`Qt8nH&hCRi?Lepu3t^$$%Vn-Z`)1a-0>{W6FhX%LHMWgD=RW&s*dSKIMy604~rQ44i$f$Lm}{gidkC7!$xQg55JQk>5Lhc zJT>c$U}%^=+kSw+{YO zmi5_Cz%HQ=ie<3kfGu*Y`$9@5M0>S!#G1Q1K(1Tc!s^4p2u?cI2gM^u1{^NxfjSG$ zT7RSBT>DZtmU;^ty+B2`$8IVGQ|9gTTt4WnbR^HIhkaBq;*28QP>X?HhiwpT7545V zmf|=NR4l|n`eSY^&|m};S}qVLPlk@4%Tp)LfpBbVr~E5=#rhfc!Cuhz4nu_WkGK;GFwKjPE9X_3Q(h4b$I@qS>Ux>{{|VM+ipH3o^l^|J3O}b zPPw(y)pQu28NzyJ_IH}whohg|CC}1Pf}lO_I2tW~VKT}d+uyC#s5i!vWIcg#W{mC^ z8y}>FB|cyY+C77%X!m@UuHEY>3L?*u5GajVy%6p>wB?Y5Re46X+|CTLt9T$3T_VL# zEgs;qO`^CjD9)DhwMG1@gTv=I&;{j8i+H8E=0%*67wxej4+RBa-IiFtgiDXsk*hNz z`P`|-!;HZEpj@1TMnn~F@!5x4FQ8PP%We)eLWI^H*3&~Gt8s3{Mc=!W$+So&&Lgp; zje{*7SF;iu6x$P`Tyimvj&b{+Dwq{~&tx6Mvv|g8jI%+>2HuW%YYg6W$O2@# zQd15-GQAew%ET10UH9`~a3|VfX>Pw%412Z5MR4ev;sLYJBRrCky5JKLM|3m6hll&t+6jt6GVa`i@bkRQAO zh_v>DXTVvq5Q^DJO0Qv$yq8f&`p*48Z!CW;_AimxhY_t6xzltl_Gl#b0dFLh%!!6` z_G__Pxz2F8WPdXpo8SAb9Em00a^cvVNG!??If&I<(S>7YM`BTKIF@XehGWMd_9F*? zF?zl1yAc@C6ggajl5^Lj{qj!yb$gcj+(=}UzoM}{MB{PI7eYP)A z%ZO|Hn& zvqfzbh_mGNnk#5{ebh#Qg>vrW(~{A9(&+Uxf!`;498QM=k5F@dG>qp&$amH>(+Fw= z)w7yl>?VwCBsd8BaQ=NHYGPz`^hWt3Q6Znju(aD7wUwg!6h5)H@Q@>87;^0`JTsC_ z$eA%bF!pAX9*GKhF~$(-jT#<_3VAYyZQtG~;|+yR>McCv-gu|uTH$}$7H)aS#qrKj z*RuJqa8%gM@lKlP!a&&*i3-Cj^;*$Mxw&-qKP+Lub6P*=*h@0)aTAH05h%?-tx0h%bj5WlCEtyn>P>zCwHLQ!`N?N z#sogI9$%jQekpuRerY{ig z!C*~w-ZPtwXu`fy>co5ScadWnT&$m|OgU2tKhbOhn7GG-4+W&WH7iSs)4{33Afhp%&oZ<|1A=cm-2^~Z+cQQ)#iXzubkzN zUsvfCs`U5Ja1`#c8Mo)tj8;6o@*Z2v5m>F7^%Fppv;G2yq)La4#ozxLG~8--+#Z1_ zdC*3(c_^v~Ht&VI4bBxoNbH*1bx(zS$c~}LJiGx8?U$}{kPXuH8=iP__0r*t{Kex_ zD?W8j44#sTT?HW*t8braf8%>_EStT}t>t-+*KRF5e8$Qz!KAzha89-vTiLSvtb8lC zEWKx)>o<@QHO$Cy{%y8+{l>38EJ{QiR+3qScqwL+>L_ zXx2Z^mj+)d4cb<;#4pRaxz=yIfE?}!t2wP+ztTY**K`N4cjKz3pIE&#dmZZgRLJ_z zP34@Ra@L|8IznN1zA(QucykF$sf0V_Zl}+S`?$V!mB%+3ttEP9w6OzmvzJ(%G2=#<%j-rPu__{FGqt`d~e-4 z6ym(DkhiIj2YU;_kVYYT?iPjILxqfUJ-K0Hc$_#Q5Yh^H_z@H_e~#;>68=mjoX5wZ zW`s)6!8jWYtrqU))-*mJ47T(9uAt9q2dkkKgCj*xJ5omH+%`?~e|(VQ8qto?*^X%%8T=7BcJ81iypI^?(Xi9!TYdT} zeQJq(3c>}7Kb@T}=T9%EO#XVBAJD!HX^M5_-S(MkjLT|F8NKc{%nIeEFfG_XS?J+H zJ3{C+;LSjrshh^C<#0M7$gIxgaZV)f+&3glL_(av!eV6kFbn>c^Mj&=ky>&+bIuEr zJL-v7ofmox$6*Dva%xi22QY?OnUZff&TH?{$8d*qAm3me7b2w_vzIPUb>w6(UHiR_ zWTFs0b)H(i;d@W?p|2n+?-NmZ^~cv!yJqFhE9(t^V6|Kh&*F?ZSR~^ZEgoZJJZT%- z;a7^GeQwT0v91_Ak~E5|r`LLJGTkO~#kfTkbCYn3p2WRDfp2gg-1>RA`{;HbzTvqv zJQ~vQXkjoa!W_tF7RAnD5HH|RFET0OCgK)7k$Vfbn723yH?zdKaqH*iCO?bYWbO^R zy}`=L8TX%vph_XDKG$Bx!B|V2$;mxHw+FPiV+=`;aRP-1TF4_&czi_rns#{bUkiSi zg5k7F`&|ouh=L!wDR>?Q&$}u3I~4q#n}Q#t;0JFCo=d@VBf(S)5{r|dmAjv!?vF$P zP+BFmKFOe_WKe37Uukupji7$B>5ZF$N5d2fC%aj+Bq@?rk0yyX0XFYcd;Y882%pM1oS!hQi{b$iCBw|pbZ6M zq}(bPBjr}X7%8_3#z?tUFh=^0l!TTMP=%)Pz{)gIWW1Ra(U->1mx!e=jn}>;@{3mu z=RtnMpKHAndZifc733GOlzoK!Qf?r>bOZS{qJbd4#%M<5mjXe4sa%j>-0;)LuMw-F z8_2H~o1u|k$^_(>G6DIeOhA6&NSBDI5kLhor5keKj-efh$AE~0fF9s6{0k8kN(g#z zt6&U=TLoh{+$tFK;8wvH4z~)%aOe|E)$PR&5Ys+UECUrpbYwUnie70{X^jLi4Z%($ zrW)+7C#D22%t-`i%t>?uX+>c87lHyvD#;}+o{3<> zA}y9%f}4?1U(&_pXs=Y|f9-o%PdB3_MWNdy+<*ZSLpO{TGj)CFMkRnE#DysW3J#A0 zAR$sjWrQ-h3*P^b$<$CLchZnEo2G;^Nz*{9Wipv+48{YoG57$t-q(qgDunqI>(t>j zg<|XJRp9WcIp#L*4Z5XpI2U2=H|?n~l`{tdxKQBVaaI zDCsqB06|gFoSPDvxXJmrMR9M?&B)E6I6^M^g_@V8Lzil`A^%ZCKg}_Cz^`+z!Ep)K zYY!M4zr)plYr=O7j)}Mu<{2E5aK$}jaM*D5$CZfd@3^kwihkJOxEI$9T(fX#8Q$X0 zPeg;`Pq=1E2FGSx*OHK3vRM40@r%ffmL%sbakAlH#WN;O8a#5+xJY5x50 z_4jyIM?dhuhWJMw*=P~P1%rRMVA0UrMcLep8Bf?^bushi-OZ-mJ(i6ayKu_ZQwveeWGY{G;)hE2aC)Vf+Wk&Qt8GbT+*9)o({fqJK)-nXIN_Xy+J^zn<> zf<>3vhaZk)3rCJ+7%6c+!ZmLne<+8Jd=|AbHAyMZ@k~ zH2j&V!_Tq1&b2V1OeZjbh_Q5ge#K3)$#}BU#2sf=Mcyo_aT%aQ8HJ$25Y~ zq``NfPSdAQd@388+Q$C$r#pv@z4H(3=pQoJ!VId{-E2J4kDEqy`-Yu5^%;BpbqXKJ z#*Q4%#*LpexMI>7HvJ62n96ptqv)>%XzwEAJ#vb`777HrJJ_^4# zCa}9FjA!?Z&tT4sk!<3~N0X;KdVbiQ=h-t;*#dUgf<;VNbUPb=`{(SQ&quK_qpq;g zSH`i0V7;rSM}sHKf9XdA^wj-q;XvxVK? zum#_I#uk0{SN7(c)aPHZhK6&Dor|=S`gTh4h$#g3v24lMbL_3R^4Q`$!V{d_H5hHl z?MPtfz`0VD26>o;(ukQS3T%9$3MGAsnuiA4fR;uw;oHb)gwF2`Y7r#owA^M^vz@H4SC!}c}%0W z+?_OfR$BU?F|*U|8Jw0e2cOPNyLbAGTjX&gJhVJ=!g)-jJSI^dD<-EcU7nU^S+?>P zdHj?0SdDtDqI#?e=aB|@Y)lKmWBrY7dF+;Lp*+63E^WiIwUK%}PJR1?2Gb{R$m4sx zFan)uvL!g;*-Gh6b@;kIm}dK6y6vAc?I*_Q3pFE6DP{rngIdLF+D=kd$`2&FwwGK!(44%HMFG?Qj1+ zCjG$N?E!aVV5+~pvmT)fon|)sff@G;+Kkv3nAaE()qrolI$tiSXJyb7>d5fUvmf%@H9%Yn>O+GE|v{H#kSG@_U920Nb$G-g6^sQ zcCw}uSmtjprTaQ)?i!`Ts4{dtTDV-%Q?i%Otn+53Kj*_a2u`xjX;``37S~Y0m-Du$ zgB7N7lf7Tvpv+F+Iape?j;*hV^U7+4IZ~gxI;yVSpz0;7xxT`N(+Hes)isKTkv+=T z!pQ4#2`3FWA{@qBZ%|`z$bch5+C;uc3U~}f0gs3jFGAy#UDh+XF5r_JUA3+)Uqk-} zemOb^97#EhXhRcDo}bPfa3odTmT8S`kf2;ZuPJziA+X}Y8rc^0ye{B|yNcq%1N6e< zB_A)fvd!_LDd7GEE_<}UeFO3ptx^8=)$}mn$Yf_0QvDjAykNv953ypo@aVAnk7>uT zQf`&_ZbOl9vuw$!?v?-@f-sFqrpxA-Fr{s@vu&nYlDc13}Y<6ZMz0>a?lW&s}O_~tCaZRR77xF_Iw0EIm? z5f{eZ&e%^<60Iw-V}YL;UK z!X66cXCsMB2Et^7`6RHGj4fdnZnOho=doTEWi2e4BIx&kwuUxEXUsLtutd+SGtDxY zW?M{iQcU+%>F(cXnwtorpYcIA`%a@{-m~l>mjAFR{}D^Rn3ylUsFP>wT@&NnvuWKB zYc@L^6DLf-12&Lx7bZ+V7+!D3HFLv;CmpjPS6#Y%ngiuVcy+47|D!*SE#U$o#{L%N zq&jX9c#EK@_^8MaPrWbkQTk!=@x;4_ZObL7g@CY7Q`ubex>&+5X|CB>%KMd~yEE(P zKo}#RopkfR1>4Fcg~9pF${$SMzc~MLqap_V%0p2VNF5(tv7`x}Rtye%oL`wd?X45c zuVhbq>s|JjOzTJY;v~prlQmZ^RKR(kpmTe z1UsbMz-&1;km_!Y_HayH>_zG3#Z85cFQSBGfBVqeaVQWp=X-Qd@hj1+ebHDn$>8Di z{x?|<{Dkctk}K~WmFwP{8ZL6;PUZEU)7G8J$eu2}VzV|Y@Arr$N^Q>)zY^#vD^XvdQEKEG#N4c&CUJrMy$jROKh#?^rm$^2cu%s*AJK%=x*2Q8H2GcX%#W z4$R)9m*vK)nB$yWW%0j*qjRdfs&OA*;_z(tLX|9&lK*@w&Wv@+m#r3#gWWty)Sb$_ z5G8$M{X4}Xhrm3P&vVBz1M{q~UxrZ8pOGz}`m3N4%Sb}GN^20V|&qsyuiTJ!;7d8;WPjM z5ry&AX@2GDuFO_GAQ=40)~?L=ji_Wx+rhHSMhY=lyZ?6Sd}7HaDnwjg$n|! zRVBSEum;uh*yGf4-kZMMV>cA9a3l;+3qe4Hz>vm(11Gr9EKYR(ikmjdv%;QzT=c+J zm?@#HDbs$oxbT5pI$QH`PW0q@UByf9N*G_fRY)4s>AujA$t5Ig6;>#}?k-kpx=o2u zpYT0=!WSWl5S{mPr#-2eD;%aOSZ?xsqOVG2b(!8%-Ug2;;l<5?At{~}fg!np zA&R&ACB@xs>!%jZ0KHWn=!VrNWp+2FKS8;tTUDlYi(3U{Qn!>eu~>>uxV=P@N_ZKr zO$Tog#H8e6F*+fsM0CAwmY_nrqwul_+iR`q5_HO8syDrGu1RzrVYRaIw=RsetC@!a z%f4WVN=w&D`{36qO!laQN+X`*>k=|wTWMqp6!0yfk$%%S7sl&bfGGot3zq~|*yD=}m*Qs1 zHw0D{O+Z)2^&;4#SAi|rv0Do>6u#>n6GufY#vhFy!NXD-|NV>Z%P++2q_nSe_)6ar2X0m+WJ=D;qBr3(AH|_9}$ene0gvZL-^N zO94ZOo5^J7Pv}HLqfh1Lt65&*M_@z0N=IU`WWP=>-mm9upWHihjU=S$+QgB~ zr<5I+_o64`w3|5ICyAMXpVJB-{@rh0lPj%t!an&pf^0G)o_zciOij zIy3LIx9$M%t;_Uv8I|w$YZH@?WzJ7{yA^dvIL)+_qw?^8e_c^Z?L_#c1{yXg-Ip*U z9^l2gZHrZ<{nC0}dZ8&_1pT04aNUIp6A3D`KQpyA)kpSis)d#jF!*Q*hf_I79itC2-@Gk!_;QUlXOwxzva%G%EL8 z0+SxC(HeCd{7gy#w*hRq=q{;wl5+a+1sPPzOwDat3`SPdYAuVr_-FI#QJ?h12%pKyO%G@r09(=1DALe(6eRA_$v>Cn zV%RIP+3I(h;EJ|xmjw#(yAp5!TQuZKdFh3mQQR?bf!tj7jJ#uDmQ*)ivKm_Dqlr;p zOYn=viMePr%21Wb->kR4qylP~GN@<&>E9;rWZRKs;m1*J;+&%SHDB(>TwHTDw=lvH z)*LS}NheHh;U$cNPxevlTP<;-3F$Iw{$MpCB%|iF+?wq*B|Tt4Qd(Cbz zC(r#tUsFim^KPLAky3HZi)EZ`uF$}@iL+l;@`5F15JUrn|3{-?9^rPZor&ce#z^Iq}`zkN7u zdrRM>Z_xuwGLcj~Cc6B}3m3(fI4P=D+0-Lj_319yQY+PC&LyL2rMev^Syq)9U=nMU z={=>U52@#1OM&ixjQ^5>$?i~7#>XPdSW7N}C5a1^Yua8W$8Bup80DkH#K znfSb&Z(DTu!h=pW3bBBWQ8>V#7aKxjCeM#(*{^h7kaBnN%AdY1*`;&sFu7bsyY#Mu zg&!MS!{+X=xI}8cco3)Pw%GbN6zWZE{1%(LWJ@UN7MFEoQI6{ciwmn%m(5U;4E^-t z!cSc`XUQ<>d|7bZYmYmB%MQZNnaeH!gQC*6h&v$TE*_RMEbd^TZi&n8K3K@%_Kd1{ zzLn~@`cn2GtKY+%FEXT$*-_XbipS!#kJ59bT_!2VKch@19n=-r)}GH^m7A@^ed|~5 zxFFS{5IFM8E*Xk-f3YFQW(GTo+UHBwDaFw_s9ZnEnp$kkvAxt1t6b{7J&Z)3b_-AI zt-~;iTU>6~>ksa5aqc1@T3lwsFocB`sEc59Kc zxEp_b-CNadqG6cF!dmvzCKV&WNL`T$aWj#C--=9O3v_qz6~)=TRby?73VU`3X~MJ> z1y=129=Y?Cz$zR<2&`Uu_|ENHg(1vPWX9)Q_tx!O4MkD-duVHGykw{?)9vo5MP>Aq z@1d==x~)aJt+j>o+1A>qtwqMIs#4yywH7QJ0+%tZ-pU{7g<7EfuPrRbojx-1TMb9< zR3%YWp6`;1`faU6O995{l)@7%d#Q65dkrjcJiM*j%<$Z8Gc@gru^V1xTdn%q?5*T} zCfeOpmSBfP)vZ=uEwjKCwcP3cyv`!4MmIc6ZmvJU4vD!rId=U%k65<_uODuyf0ylm z-Mmisx!3C7W;SCJ0z$bOYLQ@Tt+*8qn;T3X+aIV1-u>FKGD>!APj9kgr7Tp`XNT`Z z3pN4kq!cL!urpwprL~h$)3k_Vdc>9KDe}m@hs02rQR<)Me;X&L>&kR4;eC(`GZGn> zhDp}pdksh8HdjsFTs3NQ)x5^}heX0`m%mIWAJe(|J4&{QC0isox-t%BW7$k5vn-Z_ ze|0eCD7g|oa!L%e#0SZgS{9t|oW=ZAlSRwIS}CxqK{5^IYfXVw{=gd1@__YSf7K|_ zBKQL-;^rlm6zfrc)ojt?v>x(TrHhtCYn8uho@g0v-9y#&)Xn$MgcgT$i8@;h4whm! zZb^C$x$c`zIqN~m0f{9zta4;xgUdIJuXjmUYhS{tE^W~ci?Np^=`E8dVntG$z-rxj zyChHEUeo&0ZR-zi3(QWi)dl9dKlez>AR2^C3q6%Okti6(Ar^U3V?Ez`e1>LDT!1rt;gWsWsTDX&9eIln?QL$VM z^dtA4a8#upQgSZ$O`?4lN!GM$ojn@V%%a?L*~*u2yVe0B%J|FS){nTXvE;;y+rZoF zdLMttFgjE? zh!y2l<5K+#j-{t?bn#+Im5B^F!ossGs#P&^k+>yA%+A5GsLr$)eajz7ZWIUXG~weH z3iCxUDGdAetP@v9c$+(xeI0aRH(VFl5l7rDe)%}IjbM^$(bXNVRwd5=XsV>ns9fkm zd$Q82OgLc3+;S2LnTlVob;3{04Z2{a8)cp zO)3_;Rg(t~F0nZyN3u9niwDR2Afl;oyLSw9yDf3)6>iZ#3tPFtV1EOQKykylp4t$3vCL;8cNm9hJ*WI>`sCg26lo7mU`hvNX|TRllK1N519FA2Hb!cwvN&w|TC;?1TPgTh(mi{0D9dLb zMa5R|Qswjt-uoMGJF4Vqbk|mxvUXUqvT7@IS6l@4W+Jk^@rx&B+S_S~5LmRPvtZ;b7kd1}wh-V`EI z{2Fy@x1slJmio%cg){NAUi~9mk1spLPeLCzZNul}yJFA1r}o^7Y8lmSRIp|O1s`1Z zi*b9dVL^=8=j9MUhCfJT$ zX1ngCerwD_hq{xJT4Zn!*ys?^DwhA6JE^^PYlZGYoP02p zUFnax-t1nh(AjU1(|O9NzHmD-P>PwdgVh%{(({j)vYpi@D7j22LYSMv9%IV$tWnw0 zW66XVDZR`hzFwF=$Vgtwl*fAd8&pwQ(<7|rR4ymIa#N^WIA&-01md7x?GvkZgQEsUejU*XG4&Vf4i6BMhd0MY&CUplmZ zh%)}GzyICu|J8E;UElc?7L?nRueu>#o)VN#%Oz3b<}ICKm%2?Za+LKmSWbhQ499`| z0ti@`q0xPCUDPmMts3HP@+8?_8C_;NQn--`PqV|gwTZ4`owB#vW`qy8HZj9e`pWP! zNMf0;ET+MySvpGORbLt8f@K!L0xTX04g;J^7L0!5=1Zu1NmB`L3X?WJz68G_C=3~nEZjUV%Yg~h>IJ%b++47fJh!T#r z^Zv3JsmYTV1w-KbOl4-(lPzq=80HKwDObCo6y{gjz6B7z=mHQv{Z@Wi`4pB+Fqo9) zuE`(FF8Gl`&w&q{)6I=Ud5-6(#EA>oWV5OnQBgD)vCv%gX&- zR1{h7%+IM^DbhEI$3g@-pG9aD$N^@s|KkXA%&YZQ7=uv3ptUG9LTnX3lf%?jR-WpC$i@j1oZRw8l+Tx&HkZe2E>D0- zX-puvZb59*Zy8Ey|KIr)4X=3~l)!;i!w4l87UyezruvjkK{ZSHJ`QE)zx*pEYaO?xh9F*x;?G!8xJ^ZDNx4H6O%iSL7fl(m~E`<26P~ zEmNuo)&@Z>_YE`-)PgS%1$__JZj$n^FpJ5|h=Tf03Wbyiy-3A#-IxtF_ z^W#qG>M6NX?C5lT;#YoZkT=5zj|3|tkR)LJ7||nRjrTWDjq0U0tUf!o>TvUojY|VuhZJ_1Tb>p(oFmnh%o#gYu@0bpaphlpBH=wfviC7Zss9)R&3peYoetmyyqEYV$$3i)X*`Sa+6YN7P539wCQn~$R z+byOEjoYW0Xf4<#RVN}F^L~?UcB^T>$y~?P)je^$rKxqwK3!=do`&EM z?tYWoJ`ld&V77-V6%pvRn(#CiPxBz6;aj8kn<&7CfQ5v3^s)pm%QSr9OX5TTwN8f} z3GYqdvwh@OmUU&pq^b`Rz781%=9YXqfGNqkHeAsl^Jtu6(Vd=nJ)mm2{pL!5&P`yt z#LYWK#J>#WX$ z<+{BwHrx4feoR9-#varH%T0UD_7Q&NKFEx?I@*4y+rv87>z(iRI0ppPy~c9BcCWeI z6etW{-ft3%_M64h2|$|xoUe}C=lGEA8&xOnv*4c4w!(s-sd!9BkbwK-QUW+Kh!Zzq z-=h{?bZznqk>=N#k-%9IgZb_M6LwRv-BJqh**_r#2-3+<{Jy~gkpD6mBrn~OA0{j9 zM{7d}e6{EQz`#G*9t@6$2+e|!p}10UeTcR5INWgt8h;rpNBpeLV9*=No>5*7Tx24Z zbOVFICHTwO3Fzt7!FQ1X=|^fI3}+g^_}k`vwX)t z=d~EjGt<9-`7dv#eM(BXX~ifdT+U9j|qPh_QW*q8KRa$s%xnCN_&Ph?s2H) ziQzX#pe8rT;(v1n0y_lhdZ$IrXlP zFNz7N;~g2}M&G_5+8lewh9B z`)c7OokeHu7OryBe7Dt9+0PsoZxd^{|=R`;;(Htq;}f&GYW)GgMX z)cssnYWSJnXDHXtVE424^#}1)>FXAdc<%{*jbX@~CuTQjsU(8F{_oJh5?k|Qj@ z8`8DEs`mGzwFrQMchj0A!;V0YB-Kf44SdWHp)hDUZy9g-;|Xp}3BpTe)U?T{s;h-t z!&_W%jpYiMHc6bkeP+O9nGb=Cu$B1(iLT?WwXP)Fn><|9$0wLe3Lh6Oa-(dut7~2A z5V>hhVsuI2M$vLFEG1fEO70M?lM$;&ls^FeN9J8p(G2Cvx6dBq<;0Hd%P6$uSt!a_ zVyu@8C4~!VugNEth|pYWK45|lLi@$P!e9gTeo7po^;}7;X!)eX3{SEpKk?Z)1L1=( z`)EsPTG?v!VH?C}*<0lM$uyry`Ng;PcZy?u zHl3w*`)bO;`l>LfXRA#_=Qeqvxe(j)VqyLo19jcCPJ?}*K5#rHt#$sfN66_xKOy1y z05ANe2QCx9Xs_9>^^H$_;Ql!?UqEl)(<6w%X+C4k=QWT6O=Vx|PO^6P5sdyiM}0eM zUgk`}iDDpkt=;RhM1gbflxT-p<+D#vJuac7M|iMDDC~jFLt##j@Z%mt{<;fZaD_YR@dO@? z!p0uqww?dowKWHL$r{rP&3ROvMgTlpd7Z!NZVn`R zFnl|OyL+bjEXwCy_S=t(7Hq04_Zl!P9PQAy|6FRGp={}rtgpi{NSDX*zPiF|Jq}{< zm-sQx_AdCL$rY6YSN+PXSEXFJAlF@x>n+Ij735|WG;SBhGcb@q?Ymp{+ffOyjq%whkd1qYN-PcJ4+pE=_owBTsq1*p(i)sKEP|= zq~V(aBrib90wgLZ9pxw0=mI&nz@1y*%`Ncd7G&iXEX-8~T*dLooX6LanJA*c!XrVU ziZua(&nK=C*02^n;G3$tJc978(9-R%dEYHuMUS~%!l`ay;J1MB?5kL1snS|uK{wvK zc+;yARI-(htCozj`Zdv?APe@1VGR=&26aMv&soD7Y(@rrme|kuH6J6dwSuGD`krdS zuAB1S713_Quxq=rq*H1)gaUt$z=WbDGnDtQ{33CU-Pj=FWQ4v*k0h-~;%W%EXDQp^ z6|mEF(V(vN2tVsC9_zCkihMt^UQj)2Z=^j%f%8Y0p;r5gzQ*%kK=Taf`e?k)hhdrN zR}DZ6X2_l){2=SD%sYj2rkZ7I3~tbg#(t-2!Gd+O>jRfHqh!`mlc&jLi!1hww@)ng z+-~DfxvjS~O2wWTHGdoyMYqF)jbH1fFRf#?%&0jCCmeF}kRQmRN5m-+``1;x>j-?l zz9)*Rcr+%o!v@yrbQQ0z7uC|qB6R(#ET^kXr>hdq9F6HRX4Epix*V!(<$cVDt<|sstC~9NK>PpJ~R0EtMNZQl~we6_3(fvs=u~m+Zq} zueBjCPfGeaT_$}9?9sqkuG?~Fk|9@CZdahgY_PnmDkBxyKH?a^7~8$ab#mV6*iF%j zUCG-NE$21nofe_3^ch#jFE)_+TOBrZMOU2+5I|A6MLaS$_P9%gs+>E~QqPGlcx#Y8 z3x^oecZ02p_0L)&S(5y-uzzf^rSCS0_9(nKB#WVBw?%^Gn`|k`1dj<&q?BZXDRMG} zMdLWitVbSt=#hu{Zd1d$=p;K-C`ZL<`k#JfQIu>yH!w$4>fbxcA1m|$Ad8!;TdF^9 ztX4^IkyyR2VVx-{TCH+atLLj#d$V%)dkdg8u1v)(>fl<=u4`NX)5gKflIOgqGLPxJ zY8C1>Hg}0UZJN9kmE6U-{2S%s!UapAWS+j%Hnc#uRs2AnCdx~JVYPbIm3iDHd6A|W zNjK*;tcyzGbE^{9pQ*l@TV=^RT@`bty7BZ;{I^h_Uv&x?b7M(K>S*%ayC^ za=q0jnydFgMYURuZ&nt(yGmWP&(w_Fi+wS*eDzh8ukKc#hePoasCdTYieBLg%dI}) zwd&y@J6Ei3JhT4vf-aq+AkTr=ytm-AjBRq$^ERPrl|41Lx=yzKZgX|Zq3ZKZt8Bk% z@+O=>sf~?tQ*~p)>r`VbJJ+L5?Rq{vCbudk>v&-zxXLUsDXW%S3%zAsfY<(--WXMt zARUv$q#5;E5-9*;9}}=_impn8Xh-aC!VWbMQMvie;N4^wH3T52gxz#rvTT2zCm@2_`0qN^l} ze%m&wx%vy)vhOetF_u50`foT`HDUGxazSn3-Og-3-f;}haAa!AftWv9s{eL)>ftEs zheK#@-nAo|%Ok~J*J%#J`LqF$8r|I{E`UAV^r50q%i}>P=Zkm8>TLI`yA!4K-40RR zJ;Ytk?~Zeqitc(*I$-MBrnF-#Wi%247=;|hEe4x#4`1s(-os&Nx*<*d#Jt-Gi^L+p z4Gm`qfsP4_36q8OjSCuJ4c`RG%mU!(LLk$M6ywpv^|?n)*k3gEAKf6vCpb`&d=L$K zoKym-d5_y-ju~-;qWTn+FRDMN5AX|o^#Rj@`PSsyEY<2Nn^E;uU$iDSh~|W7dVHz+ zl-*J{3QFzshn-fdFZ%5FTH~AcCELv@#(l|06RC2!`z+Nh>b}J4^R@eiRDXV)tNzTJ zUfq(JUj2D>cYXEw1=W|qmpY*;_!9={mhwx;@S(_J!FhqB3Erf(=JEvh4lJZHU)vJ{ zzb~2foVWV3+RW;fBCh%qwCs`NggY`cG-TO6vq8=TS%7#dU~v&WLRajZwf1!NXXuPB zgHm!8+SRID-R+;Xw)!%vZ?n|O)t{@b>hnkq{xe`fWkB_zQciG9#NXD~^2zN`ax^Wo zod*DYjaj)q*R%<)Wf<`rT^RK4X?MGp*^FAy#ABlGOy162+|G?a;KNti#KY>gEbHKs za)bMJ-)iPAH`<3LS<;sSt;%(t*On)oy^!gJ%+eAq^1^qS^@~&Pw>h_ecDd0NNz{~O zw;s$|YL6N8VI8JEmuJ{l);Du^>%8finJLEIx}%8zLn<{Us;T;-ZG_dNdaJ(#h`v?> zCSUz1ANo8HlVDcGfGK5EwK{h#^^0>*u&KJ+9`^yrMfGJ*^BYW8ec3>O52Nsz<)@*h zPf%NS<-B;7-^||QK;MaMnUZ2bCP9~TmsEE&9vuQQAm>&kxO121sf#^%dEU*-K3JB% zJg?PUW;7I)8xH8eBZCBfm!%);;Q(gwRCV{6oHI*Li&O%yd>11oQ+b&WZPCEO(cbPxIV6XPL*)9;aJ|^&Kf54TZE~hviwZ zgTXtF`mAJ4dJnDDxk=agS+U(@6s4yjJ}TMMEka8?9YHJ(JOC1QbhFLghIM=r^pUU~ z8lAhu`*xJK5zIjq?HC@(W>~I zDn0jqwRb`*u|a8{*N!cVjK-5N@=A1W!yB;$0=|E`t-VCl4r+f6$SXv4^ zyb~?o*KGN!J>vFX&04V^W^va3N6Ee++i<$tKrwQsc5%p#;jcd$9f!%-ict<# z9*N;fLF6jQl&HDKTNU(X(A--Q%vOXB6`^f!gs_V6rT#Aw)ONrowrlS5`mc_bRFRPJ zI$RIdaT2?CD_&BgNCN|S(>!uqJt(y~)BSyBdJi7+&rI^na?%~E%caQ3&4LK@)Z8oe z-zM#?HM*_&i_Wo>{EX$%ORBv~Y+IxewFkh$h4+c0#_q4|isK^A*0y}>(*j}s?0!{7xVbyvo0RPcvt(BS)b8F@zi49HIHfGkhMDMk zJ&u*YI5Ubdj?UziULCFCYueYXgqpI?M3xFV*_`a(unw%+GQ5!Y34O!<>SPmAM+N@x z&Sb*ht)^RZ5;=TkZ~8wvi79_OYHLo78jbM^jmGPD zLnl-}rP3Q&Lo6rcbFC_n)UP=Epypa2CZ zKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt t00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZK!N{3;3udauI~T< diff --git a/VAX/vax_cpu.c b/VAX/vax_cpu.c deleted file mode 100644 index 6a851f48..00000000 --- a/VAX/vax_cpu.c +++ /dev/null @@ -1,2505 +0,0 @@ -/* vax_cpu.c: VAX CPU simulator - - Copyright (c) 1998-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - cpu CVAX central processor - - 17-May-03 RMS Fixed operand order in EMODx - 23-Apr-03 RMS Revised for 32b/64b t_addr - 05-Jan-02 RMS Added memory size restore support - 25-Dec-02 RMS Added instruction history (from Mark Pizzolato) - 29-Sep-02 RMS Revised to build dib_tab dynamically - 14-Jul-02 RMS Added halt to console, infinite loop detection - (from Mark Pizzolato) - 02-May-02 RMS Fixed bug in indexed autoincrement register logging - 30-Apr-02 RMS Added TODR powerup routine - 18-Apr-02 RMS Cleanup ambiguous signed left shifts - 15-Apr-02 RMS Fixed bug in CASEL condition codes - - The register state for the VAX is: - - R[0:15] general registers - PSL<31:0> processor status longword - TP<30> trace pending - FPD<27> first part done - IS<26> interrupt stack - CM<25:24> current mode - PM<23:22> previous mode - IPL<20:16> interrupt priority level - PSW<15:0> non-privileged processor status word - DV<7> decimal overflow trap enable - FU<6> floating underflow fault enable - IV<5> integer overflow trap enable - T<4> trace trap enable - CC<3:0> condition codes - SCBB system control block base - PCBB process control block base - SBR system page table base - SLR system page table length - P0BR process region 0 page table base - P0LR process region 0 page table length - P1BR process region 1 page table base - P1LR process region 1 page table length - SIRR/SISR software interrupt request/summary register - ASTLVL AST level register - - The CVAX CPU adds a few specific IPRs: - - CADR cache disable register - MSER memory system error register -*/ - -/* The VAX has a variable length instruction format with up to six operands: - - opcode byte - operand 1 specifier - : - operand n specifier - - Each operand specifier is a byte consisting of an addressing mode, a - register, and possibly 1-8 bytes of extension: - - number name extension mnemonic operation - - 0-3 short literal - #n op <- specifier - 4 index - [Rn] index by Rn - 5 register - Rn op <- Rn - 6 register def - (Rn) op <- M[Rn] - 7 autodecrement - -(Rn) Rn <- Rn - length - op <- M[Rn] - 8 autoincrement - (Rn)+ op <- M[Rn] - Rn <- Rn + length - 9 auto deferred - @(Rn)+ op <- M[M[Rn]] - Rn <- Rn + 4 - A byte displ byte d d(Rn) op <- M[Rn + sxt.d] - B byte displ def byte d @d(Rn) op <- M[M[Rn + sxt.d]] - C word displ word d d(Rn) op <- M[Rn + sxt.d] - D word displ def word d @d(Rn) op <- M[M[Rn + sxt.d]] - E long displ long d d(Rn) op <- M[Rn + d] - F long displ def long d @d(Rn) op <- M[M[Rn + d]] - - When the general register is the PC, certain modes are forbidden, and - others have special interpretations: - - 4F index fault - 5F register fault - 6F register def fault - 7F autodecrement fault - 8F immediate 1-8B #imm op <- imm - 9 absolute 4B @#imm op <- M[imm] - A byte relative byte d d(Rn) op <- M[PC + sxt.d] - B byte rel def byte d @d(Rn) op <- M[M[PC + sxt.d]] - C word relative word d d(Rn) op <- M[PC + sxt.d] - D word rel def word d @d(Rn) op <- M[M[PC + sxt.d]] - E long relative long d d(Rn) op <- M[PC + d] - F long rel def long d @d(Rn) op <- M[M[PC + d]] -*/ - -/* This routine is the instruction decode routine for the VAX. It - is called from the simulator control program to execute instructions - in simulated memory, starting at the simulated PC. It runs until an - enabled exception is encountered. - - General notes: - - 1. Traps and interrupts. Variable trpirq microencodes the outstanding - trap request (if any) and the level of the highest outstanding - interrupt (if any). - - 2. Interrupt requests are maintained in the int_req array, one word per - interrupt level, one bit per device. - - 3. Adding I/O devices. These modules must be modified: - - vax_defs.h add device address and interrupt definitions - vax_sys.c add sim_devices table entry -*/ - -/* Definitions */ - -#include "vax_defs.h" - -#define OP_MEM -1 -#define UNIT_V_CONH (UNIT_V_UF + 0) /* halt to console */ -#define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy */ -#define UNIT_CONH (1u << UNIT_V_CONH) -#define UNIT_MSIZE (1u << UNIT_V_MSIZE) -#define GET_CUR acc = ACC_MASK (PSL_GETCUR (PSL)) - -#define OPND_SIZE 10 -#define op0 opnd[0] -#define op1 opnd[1] -#define op2 opnd[2] -#define op3 opnd[3] -#define op4 opnd[4] -#define op5 opnd[5] -#define op6 opnd[6] -#define op7 opnd[7] -#define op8 opnd[8] -#define CHECK_FOR_PC if (rn == nPC) RSVD_ADDR_FAULT -#define CHECK_FOR_SP if (rn >= nSP) RSVD_ADDR_FAULT -#define RECW(l) ((l) << 4) | rn -#define WRITE_B(r) if (spec > (GRN | nPC)) Write (va, r, L_BYTE, WA); \ - else R[rn] = (R[rn] & ~BMASK) | ((r) & BMASK) -#define WRITE_W(r) if (spec > (GRN | nPC)) Write (va, r, L_WORD, WA); \ - else R[rn] = (R[rn] & ~WMASK) | ((r) & WMASK) -#define WRITE_L(r) if (spec > (GRN | nPC)) Write (va, r, L_LONG, WA); \ - else R[rn] = (r) -#define WRITE_Q(rl,rh) if (spec > (GRN | nPC)) { \ - if (Test (va + 7, WA, &mstat) >= 0) \ - Write (va, rl, L_LONG, WA); \ - Write (va + 4, rh, L_LONG, WA); } \ - else { R[rn] = rl; R[rnplus1] = rh; } - -#define HIST_SIZE 4096 -struct InstHistory { - int32 iPC; - int32 PSL; - int32 opc; - int32 brdest; - int32 opnd[OPND_SIZE]; }; - -uint32 *M = NULL; /* memory */ -int32 R[16]; /* registers */ -int32 STK[5]; /* stack pointers */ -int32 PSL; /* PSL */ -int32 SCBB = 0; /* SCB base */ -int32 PCBB = 0; /* PCB base */ -int32 P0BR = 0; /* P0 mem mgt */ -int32 P0LR = 0; -int32 P1BR = 0; /* P1 mem mgt */ -int32 P1LR = 0; -int32 SBR = 0; /* S0 mem mgt */ -int32 SLR = 0; -int32 SISR; /* swre int req */ -int32 ASTLVL; /* AST level */ -int32 CADR = 0; /* cache disable */ -int32 MSER = 0; /* mem error */ -int32 mapen; /* map enable */ -int32 trpirq; /* trap/intr req */ -int32 conpc, conpsl; /* console reg */ -int32 in_ie = 0; /* in exc, int */ -int32 recq[6]; /* recovery queue */ -int32 recqptr; /* recq pointer */ -int32 mem_err = 0; /* mem err intr */ -int32 crd_err = 0; /* CRD err intr */ -int32 hlt_pin = 0; /* HLT pin intr */ -int32 p1 = 0, p2 = 0; /* fault parameters */ -int32 fault_PC; /* fault PC */ -int32 pcq_p = 0; /* PC queue ptr */ -int32 hst_p = 0; /* history pointer */ -int32 hst_lnt = 0; /* history length */ -int32 badabo = 0; -int32 cpu_astop = 0; -int32 dbg_stop = 0; -int32 mchk_va, mchk_ref; /* mem ref param */ -int32 ibufl, ibufh; /* prefetch buf */ -int32 ibcnt, ppc; /* prefetch ctl */ -int32 cpu_log = 0; /* logging */ -jmp_buf save_env; -REG *pcq_r = NULL; /* PC queue reg ptr */ -int32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -static struct InstHistory hst[HIST_SIZE] = { { 0 } }; /* instruction history */ - -const uint32 byte_mask[33] = { 0x00000000, - 0x00000001, 0x00000003, 0x00000007, 0x0000000F, - 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF, - 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF, - 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, - 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, - 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF, - 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, - 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF }; -const uint32 byte_sign[33] = { 0x00000000, - 0x00000001, 0x00000002, 0x00000004, 0x00000008, - 0x00000010, 0x00000020, 0x00000040, 0x00000080, - 0x00000100, 0x00000200, 0x00000400, 0x00000800, - 0x00001000, 0x00002000, 0x00004000, 0x00008000, - 0x00010000, 0x00020000, 0x00040000, 0x00080000, - 0x00100000, 0x00200000, 0x00400000, 0x00800000, - 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000 }; -const uint32 align[4] = { - 0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF, 0x000000FF }; - -/* External and forward references */ - -extern int32 sim_interval; -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern UNIT clk_unit; - -extern t_stat build_dib_tab (void); -extern UNIT rom_unit, nvr_unit; -extern int32 op_ashq (int32 *opnd, int32 *rh, int32 *flg); -extern int32 op_emul (int32 mpy, int32 mpc, int32 *rh); -extern int32 op_ediv (int32 *opnd, int32 *rh, int32 *flg); -extern int32 op_bb_n (int32 *opnd, int32 acc); -extern int32 op_bb_x (int32 *opnd, int32 newb, int32 acc); -extern int32 op_extv (int32 *opnd, int32 vfldrp1, int32 acc); -extern int32 op_ffs (uint32 fld, int32 size); -extern void op_insv (int32 *opnd, int32 vfldrp1, int32 acc); -extern int32 op_call (int32 *opnd, t_bool gs, int32 acc); -extern int32 op_ret (int32 acc); -extern int32 op_insque (int32 *opnd, int32 acc); -extern int32 op_remque (int32 *opnd, int32 acc); -extern int32 op_insqhi (int32 *opnd, int32 acc); -extern int32 op_insqti (int32 *opnd, int32 acc); -extern int32 op_remqhi (int32 *opnd, int32 acc); -extern int32 op_remqti (int32 *opnd, int32 acc); -extern void op_pushr (int32 *opnd, int32 acc); -extern void op_popr (int32 *opnd, int32 acc); -extern int32 op_movc (int32 *opnd, int32 opc, int32 acc); -extern int32 op_cmpc (int32 *opnd, int32 opc, int32 acc); -extern int32 op_locskp (int32 *opnd, int32 opc, int32 acc); -extern int32 op_scnspn (int32 *opnd, int32 opc, int32 acc); -extern int32 op_chm (int32 *opnd, int32 cc, int32 opc); -extern int32 op_rei (int32 acc); -extern void op_ldpctx (int32 acc); -extern void op_svpctx (int32 acc); -extern int32 op_probe (int32 *opnd, int32 opc); -extern int32 op_mtpr (int32 *opnd); -extern int32 op_mfpr (int32 *opnd); -extern int32 op_movfd (int32 val); -extern int32 op_movg (int32 val); -extern int32 op_mnegfd (int32 val); -extern int32 op_mnegg (int32 val); -extern int32 op_cmpfd (int32 h1, int32 l1, int32 h2, int32 l2); -extern int32 op_cmpg (int32 h1, int32 l1, int32 h2, int32 l2); -extern int32 op_cvtifdg (int32 val, int32 *rh, int32 opc); -extern int32 op_cvtfdgi (int32 *opnd, int32 *rh, int32 opc); -extern int32 op_cvtdf (int32 *opnd); -extern int32 op_cvtgf (int32 *opnd); -extern int32 op_cvtfg (int32 *opnd, int32 *rh); -extern int32 op_addf (int32 *opnd, t_bool sub); -extern int32 op_addd (int32 *opnd, int32 *rh, t_bool sub); -extern int32 op_addg (int32 *opnd, int32 *rh, t_bool sub); -extern int32 op_mulf (int32 *opnd); -extern int32 op_muld (int32 *opnd, int32 *rh); -extern int32 op_mulg (int32 *opnd, int32 *rh); -extern int32 op_divf (int32 *opnd); -extern int32 op_divd (int32 *opnd, int32 *rh); -extern int32 op_divg (int32 *opnd, int32 *rh); -extern int32 op_emodf (int32 *opnd, int32 *intgr, int32 *flg); -extern int32 op_emodd (int32 *opnd, int32 *rh, int32 *intgr, int32 *flg); -extern int32 op_emodg (int32 *opnd, int32 *rh, int32 *intgr, int32 *flg); -extern void op_polyf (int32 *opnd, int32 acc); -extern void op_polyd (int32 *opnd, int32 acc); -extern void op_polyg (int32 *opnd, int32 acc); -extern int32 op_emulate (int32 *opnd, int32 cc, int32 opc, int32 acc); -extern int32 intexc (int32 vec, int32 cc, int32 ipl, int ei); -extern int32 Read (uint32 va, int32 lnt, int32 acc); -extern void Write (uint32 va, int32 val, int32 lnt, int32 acc); -extern int32 ReadB (uint32 pa); -extern int32 WriteB (uint32 pa, int32 val); -extern int32 Test (uint32 va, int32 acc, int32 *status); -extern int32 ReadLP (uint32 pa); -extern int32 eval_int (void); -extern int32 get_vector (int32 lvl); -extern void set_map_reg (void); -extern void rom_wr (int32 pa, int32 val, int32 lnt); -extern uint16 drom[NUM_INST][MAX_SPEC + 1]; -extern t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc); - -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_boot (int32 unitno, DEVICE *dptr); -t_stat cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_show_virt (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc); -int32 get_istr (int32 lnt, int32 acc); -int32 con_halt (int32 code, int32 cc); - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit - cpu_reg CPU register list - cpu_mod CPU modifier list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, INITMEMSIZE) }; - -REG cpu_reg[] = { - { HRDATA (PC, R[nPC], 32) }, - { HRDATA (R0, R[0], 32) }, - { HRDATA (R1, R[1], 32) }, - { HRDATA (R2, R[2], 32) }, - { HRDATA (R3, R[3], 32) }, - { HRDATA (R4, R[4], 32) }, - { HRDATA (R5, R[5], 32) }, - { HRDATA (R6, R[6], 32) }, - { HRDATA (R7, R[7], 32) }, - { HRDATA (R8, R[8], 32) }, - { HRDATA (R9, R[9], 32) }, - { HRDATA (R10, R[10], 32) }, - { HRDATA (R11, R[11], 32) }, - { HRDATA (R12, R[12], 32) }, - { HRDATA (R13, R[13], 32) }, - { HRDATA (R14, R[14], 32) }, - { HRDATA (AP, R[nAP], 32) }, - { HRDATA (FP, R[nFP], 32) }, - { HRDATA (SP, R[nSP], 32) }, - { HRDATA (PSL, PSL, 32) }, - { HRDATA (CC, PSL, 4) }, - { HRDATA (KSP, KSP, 32) }, - { HRDATA (ESP, ESP, 32) }, - { HRDATA (SSP, SSP, 32) }, - { HRDATA (USP, USP, 32) }, - { HRDATA (IS, IS, 32) }, - { HRDATA (SCBB, SCBB, 32) }, - { HRDATA (PCBB, PCBB, 32) }, - { HRDATA (P0BR, P0BR, 32) }, - { HRDATA (P0LR, P0LR, 22) }, - { HRDATA (P1BR, P1BR, 32) }, - { HRDATA (P1LR, P1LR, 22) }, - { HRDATA (SBR, SBR, 32) }, - { HRDATA (SLR, SLR, 22) }, - { HRDATA (SISR, SISR, 16) }, - { HRDATA (ASTLVL, ASTLVL, 4) }, - { HRDATA (CADR, CADR, 8) }, - { HRDATA (MSER, MSER, 8) }, - { FLDATA (MAPEN, mapen, 0) }, - { HRDATA (TRPIRQ, trpirq, 8) }, - { FLDATA (CRDERR, crd_err, 0) }, - { FLDATA (MEMERR, mem_err, 0) }, - { FLDATA (HLTPIN, hlt_pin, 0) }, - { HRDATA (DBGLOG, cpu_log, 16), REG_HIDDEN }, - { FLDATA (DBGSTOP, dbg_stop, 0), REG_HIDDEN }, - { BRDATA (PCQ, pcq, 16, 32, PCQ_SIZE), REG_RO+REG_CIRC }, - { HRDATA (PCQP, pcq_p, 6), REG_HRO }, - { HRDATA (BADABO, badabo, 32), REG_HRO }, - { HRDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_MSIZE, (1u << 23), NULL, "8M", &cpu_set_size }, - { UNIT_MSIZE, (1u << 24), NULL, "16M", &cpu_set_size }, - { UNIT_MSIZE, (1u << 25), NULL, "32M", &cpu_set_size }, - { UNIT_MSIZE, (1u << 26), NULL, "64M", &cpu_set_size }, - { UNIT_CONH, 0, "HALT to SIMH", "SIMHALT", NULL }, - { UNIT_CONH, UNIT_CONH, "HALT to console", "CONHALT", NULL }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL, - NULL, &show_iospace }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", "HISTORY", - &cpu_set_hist, &cpu_show_hist }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "VIRTUAL", &cpu_show_virt }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 16, 32, 1, 16, 8, - &cpu_ex, &cpu_dep, &cpu_reset, - &cpu_boot, NULL, NULL, - NULL, DEV_DYNM, &cpu_set_size }; - -t_stat sim_instr (void) -{ -volatile int32 opc, cc; /* used by setjmp */ -int32 acc; /* set by setjmp */ -int abortval; -t_stat r; - -if ((r = build_dib_tab ()) != SCPE_OK) return r; /* build, chk dib_tab */ -cc = PSL & CC_MASK; /* split PSL */ -PSL = PSL & ~CC_MASK; -in_ie = 0; /* not in exc */ -set_map_reg (); /* set map reg */ -GET_CUR; /* set access mask */ -SET_IRQL; /* eval interrupts */ -FLUSH_ISTR; /* clear prefetch */ -sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init clock */ - -abortval = setjmp (save_env); /* set abort hdlr */ -if (abortval > 0) { /* sim stop? */ - PSL = PSL | cc; /* put PSL together */ - pcq_r->qptr = pcq_p; /* update pc q ptr */ - return abortval; } /* return to SCP */ -else if (abortval < 0) { /* mm or rsrv or int */ - int32 i, temp, st1, st2, hsir; - if ((PSL & PSL_FPD) == 0) { /* FPD? no recovery */ - for (i = 0; i < recqptr; i++) { /* unwind inst */ - int32 rrn, rlnt; - rrn = recq[i] & 0xF; /* recovery reg# */ - rlnt = DR_LNT ((recq[i] >> 4) & 0x3); /* recovery lnt */ - if (recq[i] & 0x800) R[rrn] = R[rrn] - rlnt; - else R[rrn] = R[rrn] + rlnt; } } - recqptr = 0; /* clear queue */ - temp = fault_PC - PC; /* delta PC if needed */ - SETPC (fault_PC); /* restore PC */ - switch (-abortval) { /* case on abort code */ - case SCB_RESIN: case SCB_RESAD: case SCB_RESOP: /* reserved fault */ - if (in_ie) ABORT (STOP_INIE); /* in exc? panic */ - cc = intexc (-abortval, cc, 0, IE_EXC); /* take exception */ - GET_CUR; /* PSL changed */ - break; - case SCB_ARITH: /* arithmetic fault */ - if (in_ie) ABORT (STOP_INIE); /* in exc? panic */ - cc = intexc (-abortval, cc, 0, IE_EXC); /* take exception */ - GET_CUR; - in_ie = 1; - Write (SP - 4, p1, L_LONG, WA); /* write arith param */ - SP = SP - 4; - in_ie = 0; - break; - case SCB_ACV: case SCB_TNV: /* mem management */ - if (in_ie) { /* in exception? */ - if (PSL & PSL_IS) ABORT (STOP_INIE); /* on is? panic */ - cc = intexc (SCB_KSNV, cc, 0, IE_SVE); /* ksnv */ - GET_CUR; } - else { - cc = intexc (-abortval, cc, 0, IE_EXC); /* take exception */ - GET_CUR; - in_ie = 1; - Write (SP - 8, p1, L_LONG, WA); /* write mm params */ - Write (SP - 4, p2, L_LONG, WA); - SP = SP - 8; - in_ie = 0; } - break; - case SCB_MCHK: /* machine check */ - if (in_ie) ABORT (STOP_INIE); /* in exception? */ - if (p1 & 0x80) p1 = p1 + mchk_ref; /* mref? set v/p */ - p2 = mchk_va + 4; /* save vap */ - for (i = hsir = 0; i < 16; i++) { /* find hsir */ - if ((SISR >> i) & 1) hsir = i; } - st1 = ((((uint32) opc) & 0xFF) << 24) | - (hsir << 16) | - ((CADR & 0xFF) << 8) | - (MSER & 0xFF); - st2 = 0x00C07000 + (temp & 0xFF); - cc = intexc (-abortval, cc, 0, IE_SVE); /* take exception */ - GET_CUR; /* PSL changed */ - in_ie = 1; - SP = SP - 20; /* push 5 words */ - Write (SP, 16, L_LONG, WA); /* # bytes */ - Write (SP + 4, p1, L_LONG, WA); /* mcheck type */ - Write (SP + 8, p2, L_LONG, WA); /* address */ - Write (SP + 12, st1, L_LONG, WA); /* state 1 */ - Write (SP + 16, st2, L_LONG, WA); /* state 2 */ - in_ie = 0; - break; - case 1: /* interrupt */ - break; /* just proceed */ - default: /* other */ - badabo = abortval; /* save code */ - ABORT (STOP_UNKABO); } /* panic */ -} /* end else */ - -/* Main instruction loop */ - -for ( ;; ) { -int32 spec, disp, rn, index, numspec; -int32 vfldrp1, brdisp, flg, mstat; -int32 i, j, r, rh, temp; -uint32 va, iad; -int32 opnd[OPND_SIZE]; /* operand queue */ - -if (cpu_astop) { - cpu_astop = 0; - ABORT (SCPE_STOP); } - -fault_PC = PC; -recqptr = 0; /* clr recovery q */ -if (sim_interval <= 0) { /* chk clock queue */ - temp = sim_process_event (); - if (temp) ABORT (temp); - SET_IRQL; } /* update interrupts */ - -/* Test for non-instruction dispatches, in SRM order - - - trap or interrupt (trpirq != 0) - - PSL set - - If any of these conditions are met, re-dispatch; otherwise, - set PSL from PSL. -*/ - -if (trpirq) { /* trap or interrupt? */ - if (temp = GET_TRAP (trpirq)) { /* trap? */ - cc = intexc (SCB_ARITH, cc, 0, IE_EXC); /* take, clear trap */ - GET_CUR; /* set cur mode */ - in_ie = 1; - Write (SP - 4, temp, L_LONG, WA); /* write parameter */ - SP = SP - 4; - in_ie = 0; } - else if (temp = GET_IRQL (trpirq)) { /* interrupt? */ - int32 vec; - if (temp == IPL_HLTPIN) { /* console halt? */ - cc = con_halt (CON_HLTPIN, cc); /* invoke firmware */ - hlt_pin = 0; /* clear intr */ - trpirq = 0; /* clear everything */ - continue; } /* continue */ - if (temp == IPL_MEMERR) { /* mem error? */ - vec = SCB_MEMERR; - mem_err = 0; } - else if (temp == IPL_CRDERR) { /* CRD error? */ - vec = SCB_CRDERR; - crd_err = 0; } - else if (temp > IPL_HMAX) { /* error req lvl? */ - ABORT (STOP_UIPL); } /* unknown intr */ - else if (temp >= IPL_HMIN) /* hardware req? */ - vec = get_vector (temp); /* get vector */ - else if (temp > IPL_SMAX) ABORT (STOP_UIPL); - else { - vec = SCB_IPLSOFT + (temp << 2); - SISR = SISR & ~(1u << temp); } - if (vec) cc = intexc (vec, cc, temp, IE_INT);/* take intr */ - GET_CUR; } /* set cur mode */ - else trpirq = 0; /* clear everything */ - SET_IRQL; /* eval interrupts */ - continue; } - -if (PSL & PSL_TP) { /* trace trap? */ - PSL = PSL & ~PSL_TP; /* clear */ - cc = intexc (SCB_TP, cc, 0, IE_EXC); /* take trap */ - GET_CUR; /* set cur mode */ - continue; } -if (PSL & PSW_T) PSL = PSL | PSL_TP; /* if T, set TP */ - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - ABORT (STOP_IBKPT); } /* stop simulation */ - -sim_interval = sim_interval - 1; /* count instr */ -GET_ISTR (opc, L_BYTE); /* get opcode */ -if (opc == 0xFD) { /* 2 byte op? */ - GET_ISTR (opc, L_BYTE); /* get second byte */ - opc = opc | 0x100; } /* flag */ -numspec = drom[opc][0]; /* get # specs */ -if (PSL & PSL_FPD) { - if ((numspec & DR_F) == 0) RSVD_INST_FAULT; } -else { numspec = numspec & DR_NSPMASK; /* get # specifiers */ - -/* Specifier flows. Operands are parsed and placed into queue opnd. - - r.bwl opnd[j] = value of operand - r.q opnd[j:j+1] = value of operand - a.bwlq opnd[j] = address of operand - m.bwl opnd[j] = value of operand - m.q opnd[j:j+1] = value of operand - w.bwlq opnd[j] = register/memory flag - opnd[j+1] = memory address - - For the last memory specifier, the specifier is in spec, the register - number is in rn, and the effective address is in va. Modify specifiers - (always last) can test spec > reg+PC, as short literal are illegal for - modifiers specifiers, and final index specifiers are always illegal. -*/ - - for (i = 1, j = 0; i <= numspec; i++) { /* loop thru specs */ - disp = drom[opc][i]; /* get dispatch */ - if (disp >= BB) { - GET_ISTR (brdisp, DR_LNT (disp)); - break; } - GET_ISTR (spec, L_BYTE); /* get spec byte */ - rn = spec & RGMASK; /* get reg # */ - disp = (spec & ~RGMASK) | disp; /* merge w dispatch */ - switch (disp) { /* dispatch spec */ - -/* Short literal - only read access permitted */ - - case SH0|RB: case SH0|RW: case SH0|RL: - case SH1|RB: case SH1|RW: case SH1|RL: - case SH2|RB: case SH2|RW: case SH2|RL: - case SH3|RB: case SH3|RW: case SH3|RL: - opnd[j++] = spec; - break; - case SH0|RQ: case SH1|RQ: case SH2|RQ: case SH3|RQ: - opnd[j++] = spec; - opnd[j++] = 0; - break; - case SH0|RF: case SH1|RF: case SH2|RF: case SH3|RF: - opnd[j++] = (spec << 4) | 0x4000; - break; - case SH0|RD: case SH1|RD: case SH2|RD: case SH3|RD: - opnd[j++] = (spec << 4) | 0x4000; - opnd[j++] = 0; - break; - case SH0|RG: case SH1|RG: case SH2|RG: case SH3|RG: - opnd[j++] = (spec << 1) | 0x4000; - opnd[j++] = 0; - break; - -/* Register */ - - case GRN|RB: case GRN|MB: - CHECK_FOR_PC; - opnd[j++] = R[rn] & BMASK; - break; - case GRN|RW: case GRN|MW: - CHECK_FOR_PC; - opnd[j++] = R[rn] & WMASK; - break; - case GRN|VB: - vfldrp1 = R[rnplus1]; - case GRN|WB: case GRN|WW: case GRN|WL: case GRN|WQ: - opnd[j++] = rn; - case GRN|RL: case GRN|RF: case GRN|ML: - CHECK_FOR_PC; - opnd[j++] = R[rn]; - break; - case GRN|RQ: case GRN|RD: case GRN|RG: case GRN|MQ: - CHECK_FOR_SP; - opnd[j++] = R[rn]; - opnd[j++] = R[rnplus1]; - break; - -/* Register deferred, autodecrement */ - - case RGD|VB: - case RGD|WB: case RGD|WW: case RGD|WL: case RGD|WQ: - opnd[j++] = OP_MEM; - case RGD|AB: case RGD|AW: case RGD|AL: case RGD|AQ: - CHECK_FOR_PC; - va = opnd[j++] = R[rn]; - break; - case ADC|VB: - case ADC|WB: case ADC|WW: case ADC|WL: case ADC|WQ: - opnd[j++] = OP_MEM; - case ADC|AB: case ADC|AW: case ADC|AL: case ADC|AQ: - CHECK_FOR_PC; - va = opnd[j++] = R[rn] = R[rn] - DR_LNT (disp); - recq[recqptr++] = RECW (disp); - break; - case ADC|RB: case ADC|RW: case ADC|RL: case ADC|RF: - case ADC|MB: case ADC|MW: case ADC|ML: - R[rn] = R[rn] - (DR_LNT (disp)); - recq[recqptr++] = RECW (disp); - case RGD|RB: case RGD|RW: case RGD|RL: case RGD|RF: - case RGD|MB: case RGD|MW: case RGD|ML: - CHECK_FOR_PC; - opnd[j++] = Read (va = R[rn], DR_LNT (disp), RA); - break; - case ADC|RQ: case ADC|RD: case ADC|RG: case ADC|MQ: - R[rn] = R[rn] - 8; - recq[recqptr++] = RECW (disp); - case RGD|RQ: case RGD|RD: case RGD|RG: case RGD|MQ: - CHECK_FOR_PC; - opnd[j++] = Read (va = R[rn], L_LONG, RA); - opnd[j++] = Read (R[rn] + 4, L_LONG, RA); - break; - -/* Autoincrement */ - - case AIN|VB: - case AIN|WB: case AIN|WW: case AIN|WL: case AIN|WQ: -/* CHECK_FOR_PC; */ - opnd[j++] = OP_MEM; - case AIN|AB: case AIN|AW: case AIN|AL: case AIN|AQ: - va = opnd[j++] = R[rn]; - if (rn == nPC) { - if (DR_LNT (disp) == L_QUAD) { - GET_ISTR (temp, L_LONG); - GET_ISTR (temp, L_LONG); } - else GET_ISTR (temp, DR_LNT (disp)); } - else { - R[rn] = R[rn] + DR_LNT (disp); - recq[recqptr++] = RECW (disp); } - break; - case AIN|MB: case AIN|MW: case AIN|ML: -/* CHECK_FOR_PC; */ - case AIN|RB: case AIN|RW: case AIN|RL: case AIN|RF: - va = R[rn]; - if (rn == nPC) { GET_ISTR (opnd[j++], DR_LNT (disp)); } - else { - opnd[j++] = Read (R[rn], DR_LNT (disp), RA); - R[rn] = R[rn] + DR_LNT (disp); - recq[recqptr++] = RECW (disp); } - break; - case AIN|MQ: -/* CHECK_FOR_PC; */ - case AIN|RQ: case AIN|RD: case AIN|RG: - va = R[rn]; - if (rn == nPC) { - GET_ISTR (opnd[j++], L_LONG); - GET_ISTR (opnd[j++], L_LONG); } - else { - opnd[j++] = Read (va, L_LONG, RA); - opnd[j++] = Read (va + 4, L_LONG, RA); - R[rn] = R[rn] + 8; - recq[recqptr++] = RECW (disp); } - break; - -/* Autoincrement deferred */ - - case AID|VB: - case AID|WB: case AID|WW: case AID|WL: case AID|WQ: - opnd[j++] = OP_MEM; - case AID|AB: case AID|AW: case AID|AL: case AID|AQ: - if (rn == nPC) { GET_ISTR (va = opnd[j++], L_LONG); } - else { - va = opnd[j++] = Read (R[rn], L_LONG, RA); - R[rn] = R[rn] + 4; - recq[recqptr++] = RECW (AID|RL); } - break; - case AID|RB: case AID|RW: case AID|RL: case AID|RF: - case AID|MB: case AID|MW: case AID|ML: - if (rn == nPC) { GET_ISTR (va, L_LONG); } - else { - va = Read (R[rn], L_LONG, RA); - R[rn] = R[rn] + 4; - recq[recqptr++] = RECW (AID|RL); } - opnd[j++] = Read (va, DR_LNT (disp), RA); - break; - case AID|RQ: case AID|RD: case AID|RG: case AID|MQ: - if (rn == nPC) { GET_ISTR (va, L_LONG); } - else { - va = Read (R[rn], L_LONG, RA); - R[rn] = R[rn] + 4; - recq[recqptr++] = RECW (AID|RL); } - opnd[j++] = Read (va, L_LONG, RA); - opnd[j++] = Read (va + 4, L_LONG, RA); - break; - -/* Byte displacement */ - - case BDP|VB: - case BDP|WB: case BDP|WW: case BDP|WL: case BDP|WQ: - opnd[j++] = OP_MEM; - case BDP|AB: case BDP|AW: case BDP|AL: case BDP|AQ: - GET_ISTR (temp, L_BYTE); - va = opnd[j++] = R[rn] + SXTB (temp); - break; - case BDP|RB: case BDP|RW: case BDP|RL: case BDP|RF: - case BDP|MB: case BDP|MW: case BDP|ML: - GET_ISTR (temp, L_BYTE); - va = R[rn] + SXTB (temp); - opnd[j++] = Read (va, DR_LNT (disp), RA); - break; - case BDP|RQ: case BDP|RD: case BDP|RG: case BDP|MQ: - GET_ISTR (temp, L_BYTE); - va = R[rn] + SXTB (temp); - opnd[j++] = Read (va, L_LONG, RA); - opnd[j++] = Read (va + 4, L_LONG, RA); - break; - -/* Byte displacement deferred */ - - case BDD|VB: - case BDD|WB: case BDD|WW: case BDD|WL: case BDD|WQ: - opnd[j++] = OP_MEM; - case BDD|AB: case BDD|AW: case BDD|AL: case BDD|AQ: - GET_ISTR (temp, L_BYTE); - iad = R[rn] + SXTB (temp); - va = opnd[j++] = Read (iad, L_LONG, RA); - break; - case BDD|RB: case BDD|RW: case BDD|RL: case BDD|RF: - case BDD|MB: case BDD|MW: case BDD|ML: - GET_ISTR (temp, L_BYTE); - iad = R[rn] + SXTB (temp); - va = Read (iad, L_LONG, RA); - opnd[j++] = Read (va, DR_LNT (disp), RA); - break; - case BDD|RQ: case BDD|RD: case BDD|RG: case BDD|MQ: - GET_ISTR (temp, L_BYTE); - iad = R[rn] + SXTB (temp); - va = Read (iad, L_LONG, RA); - opnd[j++] = Read (va, L_LONG, RA); - opnd[j++] = Read (va + 4, L_LONG, RA); - break; - -/* Word displacement */ - - case WDP|VB: - case WDP|WB: case WDP|WW: case WDP|WL: case WDP|WQ: - opnd[j++] = OP_MEM; - case WDP|AB: case WDP|AW: case WDP|AL: case WDP|AQ: - GET_ISTR (temp, L_WORD); - va = opnd[j++] = R[rn] + SXTW (temp); - break; - case WDP|MB: case WDP|MW: case WDP|ML: - case WDP|RB: case WDP|RW: case WDP|RL: case WDP|RF: - GET_ISTR (temp, L_WORD); - va = R[rn] + SXTW (temp); - opnd[j++] = Read (va, DR_LNT (disp), RA); - break; - case WDP|MQ: case WDP|RQ: case WDP|RD: case WDP|RG: - GET_ISTR (temp, L_WORD); - va = R[rn] + SXTW (temp); - opnd[j++] = Read (va, L_LONG, RA); - opnd[j++] = Read (va + 4, L_LONG, RA); - break; - -/* Word displacement deferred */ - - case WDD|VB: - case WDD|WB: case WDD|WW: case WDD|WL: case WDD|WQ: - opnd[j++] = OP_MEM; - case WDD|AB: case WDD|AW: case WDD|AL: case WDD|AQ: - GET_ISTR (temp, L_WORD); - iad = R[rn] + SXTW (temp); - va = opnd[j++] = Read (iad, L_LONG, RA); - break; - case WDD|MB: case WDD|MW: case WDD|ML: - case WDD|RB: case WDD|RW: case WDD|RL: case WDD|RF: - GET_ISTR (temp, L_WORD); - iad = R[rn] + SXTW (temp); - va = Read (iad, L_LONG, RA); - opnd[j++] = Read (va, DR_LNT (disp), RA); - break; - case WDD|MQ: case WDD|RQ: case WDD|RD: case WDD|RG: - GET_ISTR (temp, L_WORD); - iad = R[rn] + SXTW (temp); - va = Read (iad, L_LONG, RA); - opnd[j++] = Read (va, L_LONG, RA); - opnd[j++] = Read (va + 4, L_LONG, RA); - break; - -/* Longword displacement */ - - case LDP|VB: - case LDP|WB: case LDP|WW: case LDP|WL: case LDP|WQ: - opnd[j++] = OP_MEM; - case LDP|AB: case LDP|AW: case LDP|AL: case LDP|AQ: - GET_ISTR (temp, L_LONG); - va = opnd[j++] = R[rn] + temp; - break; - case LDP|MB: case LDP|MW: case LDP|ML: - case LDP|RB: case LDP|RW: case LDP|RL: case LDP|RF: - GET_ISTR (temp, L_LONG); - va = R[rn] + temp; - opnd[j++] = Read (va, DR_LNT (disp), RA); - break; - case LDP|MQ: case LDP|RQ: case LDP|RD: case LDP|RG: - GET_ISTR (temp, L_LONG); - va = R[rn] + temp; - opnd[j++] = Read (va, L_LONG, RA); - opnd[j++] = Read (va + 4, L_LONG, RA); - break; - -/* Longword displacement deferred */ - - case LDD|VB: - case LDD|WB: case LDD|WW: case LDD|WL: case LDD|WQ: - opnd[j++] = OP_MEM; - case LDD|AB: case LDD|AW: case LDD|AL: case LDD|AQ: - GET_ISTR (temp, L_LONG); - iad = R[rn] + temp; - va = opnd[j++] = Read (iad, L_LONG, RA); - break; - case LDD|MB: case LDD|MW: case LDD|ML: - case LDD|RB: case LDD|RW: case LDD|RL: case LDD|RF: - GET_ISTR (temp, L_LONG); - iad = R[rn] + temp; - va = Read (iad, L_LONG, RA); - opnd[j++] = Read (va, DR_LNT (disp), RA); - break; - case LDD|MQ: case LDD|RQ: case LDD|RD: case LDD|RG: - GET_ISTR (temp, L_LONG); - iad = R[rn] + temp; - va = Read (iad, L_LONG, RA); - opnd[j++] = Read (va, L_LONG, RA); - opnd[j++] = Read (va + 4, L_LONG, RA); - break; - -/* Index */ - - case IDX|VB: - case IDX|WB: case IDX|WW: case IDX|WL: case IDX|WQ: - case IDX|AB: case IDX|AW: case IDX|AL: case IDX|AQ: - case IDX|MB: case IDX|MW: case IDX|ML: case IDX|MQ: - case IDX|RB: case IDX|RW: case IDX|RL: case IDX|RQ: - case IDX|RF: case IDX|RD: case IDX|RG: - index = R[rn] << (disp & 03); - CHECK_FOR_PC; - GET_ISTR (spec, L_BYTE); - rn = spec & RGMASK; - switch (spec & ~RGMASK) { - case ADC: - R[rn] = R[rn] - DR_LNT (disp); - recq[recqptr++] = RECW (ADC | (disp & DR_LNMASK)); - case RGD: - CHECK_FOR_PC; - index = index + R[rn]; - break; - case AIN: - CHECK_FOR_PC; - index = index + R[rn]; - R[rn] = R[rn] + DR_LNT (disp); - recq[recqptr++] = RECW (AIN | (disp & DR_LNMASK)); - break; - case AID: - if (rn == nPC) { GET_ISTR (temp, L_LONG); } - else { - temp = Read (R[rn], L_LONG, RA); - R[rn] = R[rn] + 4; - recq[recqptr++] = RECW (AID|RL); } - index = temp + index; - break; - case BDP: - GET_ISTR (temp, L_BYTE); - index = index + R[rn] + SXTB (temp); - break; - case BDD: - GET_ISTR (temp, L_BYTE); - index = index + Read (R[rn] + SXTB (temp), L_LONG, RA); - break; - case WDP: - GET_ISTR (temp, L_WORD); - index = index + R[rn] + SXTW (temp); - break; - case WDD: - GET_ISTR (temp, L_WORD); - index = index + Read (R[rn] + SXTW (temp), L_LONG, RA); - break; - case LDP: - GET_ISTR (temp, L_LONG); - index = index + R[rn] + temp; - break; - case LDD: - GET_ISTR (temp, L_LONG); - index = index + Read (R[rn] + temp, L_LONG, RA); - break; - default: - RSVD_ADDR_FAULT; } /* end case idxspec */ - switch (disp & 0xF) { /* case disp type */ - case WB: case WW: case WL: case WQ: - opnd[j++] = OP_MEM; - case AB: case AW: case AL: case AQ: - va = opnd[j++] = index; - break; - case MB: case MW: case ML: - case RB: case RW: case RL: - opnd[j++] = Read (va = index, DR_LNT (disp), RA); - break; - case RQ: case MQ: - opnd[j++] = Read (va = index, L_LONG, RA); - opnd[j++] = Read (index + 4, L_LONG, RA); - break; } /* end case access/lnt */ - break; /* end index */ - default: /* all others */ - RSVD_ADDR_FAULT; /* fault */ - break; - } /* end case spec */ - } /* end for */ -} - /* end if not FPD */ -/* Optionally record instruction history */ - -if (hst_lnt) { - struct InstHistory *h = &hst[hst_p]; - int32 i; - - hst_p = (hst_p + 1) % HIST_SIZE; - h->iPC = fault_PC; - h->PSL = PSL | cc; - h->opc = opc; - h->brdest = brdisp + PC; - for (i = 0; i < (numspec & DR_NSPMASK); i++) - h->opnd[i] = opnd[i]; - } - -/* Dispatch to instructions */ - -switch (opc) { - -/* Single operand instructions with dest, write only - CLRx dst.wx - - spec = reg/memory flag - rn = register number - va = virtual address -*/ - -case CLRB: - WRITE_B (0); /* store result */ - CC_ZZ1P; /* set cc's */ - break; -case CLRW: - WRITE_W (0); /* store result */ - CC_ZZ1P; /* set cc's */ - break; -case CLRL: - WRITE_L (0); /* store result */ - CC_ZZ1P; /* set cc's */ - break; -case CLRQ: - WRITE_Q (0, 0); /* store result */ - CC_ZZ1P; /* set cc's */ - break; - -/* Single operand instructions with source, read only - TSTx src.rx - - opnd[0] = source - */ - -case TSTB: - CC_IIZZ_B (op0); /* set cc's */ - break; -case TSTW: - CC_IIZZ_W (op0); /* set cc's */ - break; -case TSTL: - CC_IIZZ_L (op0); /* set cc's */ - break; - -/* Single operand instructions with source, read/write - op src.mx - - opnd[0] = operand - spec = reg/mem flag - rn = register number - va = operand address -*/ - -case INCB: - r = (op0 + 1) & BMASK; /* calc result */ - WRITE_B (r); /* store result */ - CC_ADD_B (r, 1, op0); /* set cc's */ - break; -case INCW: - r = (op0 + 1) & WMASK; /* calc result */ - WRITE_W (r); /* store result */ - CC_ADD_W (r, 1, op0); /* set cc's */ - break; -case INCL: - r = (op0 + 1) & LMASK; /* calc result */ - WRITE_L (r); /* store result */ - CC_ADD_L (r, 1, op0); /* set cc's */ - break; -case DECB: - r = (op0 - 1) & BMASK; /* calc result */ - WRITE_B (r); /* store result */ - CC_SUB_B (r, 1, op0); /* set cc's */ - break; -case DECW: - r = (op0 - 1) & WMASK; /* calc result */ - WRITE_W (r); /* store result */ - CC_SUB_W (r, 1, op0); /* set cc's */ - break; -case DECL: - r = (op0 - 1) & LMASK; /* calc result */ - WRITE_L (r); /* store result */ - CC_SUB_L (r, 1, op0); /* set cc's */ - break; - -/* Push instructions - PUSHL src.rl or PUSHAx src.ax - - opnd[0] = source -*/ - -case PUSHL: case PUSHAB: case PUSHAW: case PUSHAL: case PUSHAQ: - Write (SP - 4, op0, L_LONG, WA); /* push operand */ - SP = SP - 4; /* decr stack ptr */ - CC_IIZP_L (op0); /* set cc's */ - break; - -/* Moves, converts, and ADAWI - op src.rx, dst.wx - - opnd[0] = source - spec = reg/mem flag - rn = register number - va = operand address -*/ - -case MOVB: - WRITE_B (op0); /* result */ - CC_IIZP_B (op0); /* set cc's */ - break; -case MOVW: case MOVZBW: - WRITE_W (op0); /* result */ - CC_IIZP_W (op0); /* set cc's */ - break; -case MOVL: case MOVZBL: case MOVZWL: -case MOVAB: case MOVAW: case MOVAL: case MOVAQ: - WRITE_L (op0); /* result */ - CC_IIZP_L (op0); /* set cc's */ - break; -case MCOMB: - r = op0 ^ BMASK; /* compl opnd */ - WRITE_B (r); /* store result */ - CC_IIZP_B (r); /* set cc's */ - break; -case MCOMW: - r = op0 ^ WMASK; /* compl opnd */ - WRITE_W (r); /* store result */ - CC_IIZP_W (r); /* set cc's */ - break; -case MCOML: - r = op0 ^ LMASK; /* compl opnd */ - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - break; -case MNEGB: - r = (-op0) & BMASK; /* negate opnd */ - WRITE_B (r); /* store result */ - CC_SUB_B (r, op0, 0); /* set cc's */ - break; -case MNEGW: - r = (-op0) & WMASK; /* negate opnd */ - WRITE_W (r); /* store result */ - CC_SUB_W (r, op0, 0); /* set cc's */ - break; -case MNEGL: - r = (-op0) & LMASK; /* negate opnd */ - WRITE_L (r); /* store result */ - CC_SUB_L (r, op0, 0); /* set cc's */ - break; - -case CVTBW: - r = SXTBW (op0); /* ext sign */ - WRITE_W (r); /* store result */ - CC_IIZZ_W (r); /* set cc's */ - break; -case CVTBL: - r = SXTB (op0); /* ext sign */ - WRITE_L (r); /* store result */ - CC_IIZZ_L (r); /* set cc's */ - break; -case CVTWL: - r = SXTW (op0); /* ext sign */ - WRITE_L (r); /* store result */ - CC_IIZZ_L (r); /* set cc's */ - break; -case CVTLB: - r = op0 & BMASK; /* set result */ - WRITE_B (r); /* store result */ - CC_IIZZ_B (r); /* initial cc's */ - if ((op0 > 127) || (op0 < -128)) { V_INTOV; } - break; -case CVTLW: - r = op0 & WMASK; /* set result */ - WRITE_W (r); /* store result */ - CC_IIZZ_W (r); /* initial cc's */ - if ((op0 > 32767) || (op0 < -32768)) { V_INTOV; } - break; -case CVTWB: - r = op0 & BMASK; /* set result */ - WRITE_B (r); /* store result */ - CC_IIZZ_B (r); /* initial cc's */ - temp = SXTW (op0); /* cvt op to long */ - if ((temp > 127) || (temp < -128)) { V_INTOV; } - break; - -case ADAWI: - if (op1 >= 0) { /* reg? ADDW2 */ - temp = R[op1]; - r = R[op1] = (op0 + temp) & WMASK; } - else { - if (op2 & 1) RSVD_OPND_FAULT; /* mem? chk align */ - temp = Read (op2, L_WORD, WA); /* ok, ADDW2 */ - r = (op0 + temp) & WMASK; - WRITE_W (r); } - CC_ADD_W (r, op0, temp); /* set cc's */ - break; - -/* Integer operates, 2 operand, read only - op src1.rx, src2.rx - - opnd[0] = source1 - opnd[1] = source2 -*/ - -case CMPB: - CC_CMP_B (op0, op1); /* set cc's */ - break; -case CMPW: - CC_CMP_W (op0, op1); /* set cc's */ - break; -case CMPL: - CC_CMP_L (op0, op1); /* set cc's */ - break; -case BITB: - r = op1 & op0; /* calc result */ - CC_IIZP_B (r); /* set cc's */ - break; -case BITW: - r = op1 & op0; /* calc result */ - CC_IIZP_W (r); /* set cc's */ - break; -case BITL: - r = op1 & op0; /* calc result */ - CC_IIZP_L (r); /* set cc's */ - break; - -/* Integer operates, 2 operand read/write, and 3 operand, also MOVQ - op2 src.rx, dst.mx op3 src.rx, src.rx, dst.wx - - opnd[0] = source1 - opnd[1] = source2 - spec = register/memory flag - rn = register number - va = memory address -*/ - -case ADDB2: case ADDB3: - r = (op1 + op0) & BMASK; /* calc result */ - WRITE_B (r); /* store result */ - CC_ADD_B (r, op0, op1); /* set cc's */ - break; -case ADDW2: case ADDW3: - r = (op1 + op0) & WMASK; /* calc result */ - WRITE_W (r); /* store result */ - CC_ADD_W (r, op0, op1); /* set cc's */ - break; -case ADWC: - r = (op1 + op0 + (cc & CC_C)) & LMASK; /* calc result */ - WRITE_L (r); /* store result */ - CC_ADD_L (r, op0, op1); /* set cc's */ - if ((r == op1) && op0) cc = cc | CC_C; /* special case */ - break; -case ADDL2: case ADDL3: - r = (op1 + op0) & LMASK; /* calc result */ - WRITE_L (r); /* store result */ - CC_ADD_L (r, op0, op1); /* set cc's */ - break; -case SUBB2: case SUBB3: - r = (op1 - op0) & BMASK; /* calc result */ - WRITE_B (r); /* store result */ - CC_SUB_B (r, op0, op1); /* set cc's */ - break; -case SUBW2: case SUBW3: - r = (op1 - op0) & WMASK; /* calc result */ - WRITE_W (r); /* store result */ - CC_SUB_W (r, op0, op1); /* set cc's */ - break; -case SBWC: - r = (op1 - op0 - (cc & CC_C)) & LMASK; /* calc result */ - WRITE_L (r); /* store result */ - CC_SUB_L (r, op0, op1); /* set cc's */ - if ((op0 == op1) && r) cc = cc | CC_C; /* special case */ - break; -case SUBL2: case SUBL3: - r = (op1 - op0) & LMASK; /* calc result */ - WRITE_L (r); /* store result */ - CC_SUB_L (r, op0, op1); /* set cc's */ - break; -case MULB2: case MULB3: - temp = SXTB (op0) * SXTB (op1); /* multiply */ - r = temp & BMASK; /* mask to result */ - WRITE_B (r); /* store result */ - CC_IIZZ_B (r); /* set cc's */ - if ((temp > 127) || (temp < -128)) { V_INTOV; } - break; -case MULW2: case MULW3: - temp = SXTW (op0) * SXTW (op1); /* multiply */ - r = temp & WMASK; /* mask to result */ - WRITE_W (r); /* store result */ - CC_IIZZ_W (r); /* set cc's */ - if ((temp > 32767) || (temp < -32768)) { V_INTOV; } - break; -case MULL2: case MULL3: - r = op_emul (op0, op1, &rh); /* get 64b result */ - WRITE_L (r); /* store result */ - CC_IIZZ_L (r); /* set cc's */ - if (rh != ((r & LSIGN)? -1: 0)) { V_INTOV; } /* chk overflow */ - break; -case DIVB2: case DIVB3: - if (op0 == 0) { /* div by zero? */ - r = op1; - temp = CC_V; - SET_TRAP (TRAP_DIVZRO); } - else if ((op0 == BMASK) && (op1 == BSIGN)) { /* overflow? */ - r = op1; - temp = CC_V; - INTOV; } - else { - r = SXTB (op1) / SXTB (op0); /* ok, divide */ - temp = 0; } - WRITE_B (r); /* write result */ - CC_IIZZ_B (r); /* set cc's */ - cc = cc | temp; /* error? set V */ - break; -case DIVW2: case DIVW3: - if (op0 == 0) { /* div by zero? */ - r = op1; - temp = CC_V; - SET_TRAP (TRAP_DIVZRO); } - else if ((op0 == WMASK) && (op1 == WSIGN)) { /* overflow? */ - r = op1; - temp = CC_V; - INTOV; } - else { - r = SXTW (op1) / SXTW (op0); /* ok, divide */ - temp = 0; } - WRITE_W (r); /* write result */ - CC_IIZZ_W (r); /* set cc's */ - cc = cc | temp; /* error? set V */ - break; -case DIVL2: case DIVL3: - if (op0 == 0) { /* div by zero? */ - r = op1; - temp = CC_V; - SET_TRAP (TRAP_DIVZRO); } - else if ((op0 == LMASK) && (op1 == LSIGN)) { /* overflow? */ - r = op1; - temp = CC_V; - INTOV; } - else { - r = op1 / op0; /* ok, divide */ - temp = 0; } - WRITE_L (r); /* write result */ - CC_IIZZ_L (r); /* set cc's */ - cc = cc | temp; /* error? set V */ - break; - -case BISB2: case BISB3: - r = op1 | op0; /* calc result */ - WRITE_B (r); /* store result */ - CC_IIZP_B (r); /* set cc's */ - break; -case BISW2: case BISW3: - r = op1 | op0; /* calc result */ - WRITE_W (r); /* store result */ - CC_IIZP_W (r); /* set cc's */ - break; -case BISL2: case BISL3: - r = op1 | op0; /* calc result */ - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - break; -case BICB2: case BICB3: - r = op1 & ~op0; /* calc result */ - WRITE_B (r); /* store result */ - CC_IIZP_B (r); /* set cc's */ - break; -case BICW2: case BICW3: - r = op1 & ~op0; /* calc result */ - WRITE_W (r); /* store result */ - CC_IIZP_W (r); /* set cc's */ - break; -case BICL2: case BICL3: - r = op1 & ~op0; /* calc result */ - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - break; -case XORB2: case XORB3: - r = op1 ^ op0; /* calc result */ - WRITE_B (r); /* store result */ - CC_IIZP_B (r); /* set cc's */ - break; -case XORW2: case XORW3: - r = op1 ^ op0; /* calc result */ - WRITE_W (r); /* store result */ - CC_IIZP_W (r); /* set cc's */ - break; -case XORL2: case XORL3: - r = op1 ^ op0; /* calc result */ - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - break; - -/* MOVQ - movq src.rq, dst.wq - - opnd[0:1] = source - spec = register/memory flag - rn = register number - va = memory address - -*/ - -case MOVQ: - WRITE_Q (op0, op1); /* store result */ - CC_IIZP_Q (op0, op1); - break; - -/* Shifts - op shf.rb,src.rl,dst.wl - - opnd[0] = shift count - opnd[1] = source - spec = register/memory flag - rn = register number - va = memory address -*/ - -case ROTL: - j = op0 % 32; /* reduce sc, mod 32 */ - if (j) r = ((((uint32) op1) << j) | - (((uint32) op1) >> (32 - j))) & LMASK; - else r = op1; - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - break; -case ASHL: - if (op0 & BSIGN) { /* right shift? */ - temp = 0x100 - op0; /* get |shift| */ - if (temp > 31) r = (op1 & LSIGN)? -1: 0; /* sc > 31? */ - else r = op1 >> temp; /* shift */ - WRITE_L (r); /* store result */ - CC_IIZZ_L (r); /* set cc's */ - break; } - else { - if (op0 > 31) r = temp = 0; /* sc > 31? */ - else { - r = ((uint32) op1) << op0; /* shift */ - temp = r >> op0; } /* shift back */ - WRITE_L (r); /* store result */ - CC_IIZZ_L (r); /* set cc's */ - if (op1 != temp) { V_INTOV; } } /* bits lost? */ - break; -case ASHQ: - r = op_ashq (opnd, &rh, &flg); /* do qw shift */ - WRITE_Q (r, rh); /* store results */ - CC_IIZZ_Q (r, rh); /* set cc's */ - if (flg) { V_INTOV; } /* if ovflo, set */ - break; - -/* EMUL - emul mplr.rl,mpcn.rl,add.rl,dst.wq - - op0 = multiplier - op1 = multiplicand - op2 = adder - op3:op4 = destination (.wq) -*/ - -case EMUL: - r = op_emul (op0, op1, &rh); /* calc 64b result */ - r = r + op2; /* add 32b value */ - rh = rh + (((uint32) r) < ((uint32) op2)) - /* into 64b result */ - ((op2 & LSIGN)? 1: 0); - WRITE_Q (r, rh); /* write result */ - CC_IIZZ_Q (r, rh); /* set cc's */ - break; - -/* EDIV - ediv dvr.rl,dvd.rq,quo.wl,rem.wl - - op0 = divisor (.rl) - op1:op2 = dividend (.rq) - op3:op4 = quotient address (.wl) - op5:op6 = remainder address (.wl) -*/ - -case EDIV: - if (op5 < 0) Read (op6, L_LONG, WA); /* wtest remainder */ - if (op0 == 0) { /* divide by zero? */ - flg = CC_V; /* set V */ - r = opnd[1]; /* quo = low divd */ - rh = 0; /* rem = 0 */ - SET_TRAP (TRAP_DIVZRO); } /* set trap */ - else { - r = op_ediv (opnd, &rh, &flg); /* extended divide */ - if (flg) { INTOV; } } /* if ovf+IV, set trap */ - if (op3 >= 0) R[op3] = r; /* store quotient */ - else Write (op4, r, L_LONG, WA); - if (op5 >= 0) R[op5] = rh; /* store remainder */ - else Write (op6, rh, L_LONG, WA); - CC_IIZZ_L (r); /* set cc's */ - cc = cc | flg; /* set V if required */ - break; - -/* Control instructions */ - -/* Simple branches and subroutine calls */ - -case BRB: - BRANCHB (brdisp); /* branch */ - if ((PC == fault_PC) && (PSL_GETIPL (PSL) == 0x1F)) - ABORT (STOP_LOOP); - break; - -case BRW: - BRANCHW (brdisp); /* branch */ - if ((PC == fault_PC) && (PSL_GETIPL (PSL) == 0x1F)) - ABORT (STOP_LOOP); - break; - -case BSBB: - Write (SP - 4, PC, L_LONG, WA); /* push PC on stk */ - SP = SP - 4; /* decr stk ptr */ - BRANCHB (brdisp); /* branch */ - break; - -case BSBW: - Write (SP - 4, PC, L_LONG, WA); /* push PC on stk */ - SP = SP - 4; /* decr stk ptr */ - BRANCHW (brdisp); /* branch */ - break; - -case BGEQ: - if (!(cc & CC_N)) BRANCHB (brdisp); /* br if N = 0 */ - break; -case BLSS: - if (cc & CC_N) BRANCHB (brdisp); /* br if N = 1 */ - break; -case BNEQ: - if (!(cc & CC_Z)) BRANCHB (brdisp); /* br if Z = 0 */ - break; -case BEQL: - if (cc & CC_Z) BRANCHB (brdisp); /* br if Z = 1 */ - break; -case BVC: - if (!(cc & CC_V)) BRANCHB (brdisp); /* br if V = 0 */ - break; -case BVS: - if (cc & CC_V) BRANCHB (brdisp); /* br if V = 1 */ - break; -case BGEQU: - if (!(cc & CC_C)) BRANCHB (brdisp); /* br if C = 0 */ - break; -case BLSSU: - if (cc & CC_C) BRANCHB (brdisp); /* br if C = 1 */ - break; -case BGTR: - if (!(cc & (CC_N | CC_Z))) BRANCHB (brdisp); /* br if N | Z = 0 */ - break; -case BLEQ: - if (cc & (CC_N | CC_Z)) BRANCHB (brdisp); /* br if N | Z = 1 */ - break; -case BGTRU: - if (!(cc & (CC_C | CC_Z))) BRANCHB (brdisp); /* br if C | Z = 0 */ - break; -case BLEQU: - if (cc & (CC_C | CC_Z)) BRANCHB (brdisp); /* br if C | Z = 1 */ - break; - -/* Simple jumps and subroutine calls - op addr.ab - - opnd[0] = address -*/ - -case JSB: - Write (SP - 4, PC, L_LONG, WA); /* push PC on stk */ - SP = SP - 4; /* decr stk ptr */ -case JMP: - JUMP (op0); /* jump */ - break; - -case RSB: - temp = Read (SP, L_LONG, RA); /* get top of stk */ - SP = SP + 4; /* incr stk ptr */ - JUMP (temp); - break; - -/* SOB instructions - op idx.ml,disp.bb - - opnd[0] = index - spec = register/memory flag - rn = register number - va = memory address -*/ - -case SOBGEQ: - r = op0 - 1; /* decr index */ - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - V_SUB_L (r, 1, op0); /* test for ovflo */ - if (r >= 0) BRANCHB (brdisp); /* if >= 0, branch */ - break; -case SOBGTR: - r = op0 - 1; /* decr index */ - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - V_SUB_L (r, 1, op0); /* test for ovflo */ - if (r > 0) BRANCHB (brdisp); /* if >= 0, branch */ - break; - -/* AOB instructions - op limit.rl,idx.ml,disp.bb - - opnd[0] = limit - opnd[1] = index - spec = register/memory flag - rn = register number - va = memory address -*/ - -case AOBLSS: - r = op1 + 1; /* incr index */ - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - V_ADD_L (r, 1, op1); /* test for ovflo */ - if (r < op0) BRANCHB (brdisp); /* if < lim, branch */ - break; -case AOBLEQ: - r = op1 + 1; /* incr index */ - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - V_ADD_L (r, 1, op1); /* test for ovflo */ - if (r <= op0) BRANCHB (brdisp); /* if < lim, branch */ - break; - -/* ACB instructions - op limit.rx,add.rx,index.mx,disp.bw - - opnd[0] = limit - opnd[1] = adder - opnd[2] = index - spec = register/memory flag - rn = register number - va = memory address -*/ - -case ACBB: - r = (op2 + op1) & BMASK; /* calc result */ - WRITE_B (r); /* store result */ - CC_IIZP_B (r); /* set cc's */ - V_ADD_B (r, op1, op2); /* test for ovflo */ - if ((op1 & BSIGN)? (SXTB (r) >= SXTB (op0)): - (SXTB (r) <= SXTB (op0))) BRANCHW (brdisp); - break; -case ACBW: - r = (op2 + op1) & WMASK; /* calc result */ - WRITE_W (r); /* store result */ - CC_IIZP_W (r); /* set cc's */ - V_ADD_W (r, op1, op2); /* test for ovflo */ - if ((op1 & WSIGN)? (SXTW (r) >= SXTW (op0)): - (SXTW (r) <= SXTW (op0))) BRANCHW (brdisp); - break; -case ACBL: - r = (op2 + op1) & LMASK; /* calc result */ - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - V_ADD_L (r, op1, op2); /* test for ovflo */ - if ((op1 & LSIGN)? (r >= op0): (r <= op0)) - BRANCHW (brdisp); - break; - -/* CASE instructions - casex sel.rx,base.rx,lim.rx - - opnd[0] = selector - opnd[1] = base - opnd[2] = limit -*/ - -case CASEB: - r = (op0 - op1) & BMASK; /* sel - base */ - CC_CMP_B (r, op2); /* r:limit, set cc's */ - if (r > op2) JUMP (PC + ((op2 + 1) * 2)); /* r > limit (unsgnd)? */ - else { - temp = Read (PC + (r * 2), L_WORD, RA); - BRANCHW (temp); } - break; -case CASEW: - r = (op0 - op1) & WMASK; /* sel - base */ - CC_CMP_W (r, op2); /* r:limit, set cc's */ - if (r > op2) JUMP (PC + ((op2 + 1) * 2)); /* r > limit (unsgnd)? */ - else { - temp = Read (PC + (r * 2), L_WORD, RA); - BRANCHW (temp); } - break; -case CASEL: - r = (op0 - op1) & LMASK; /* sel - base */ - CC_CMP_L (r, op2); /* r:limit, set cc's */ - if (((uint32) r) > ((uint32) op2)) /* r > limit (unsgnd)? */ - JUMP (PC + ((op2 + 1) * 2)); - else { - temp = Read (PC + (r * 2), L_WORD, RA); - BRANCHW (temp); } - break; - -/* Branch on bit instructions - bbxy pos.rl,op.wb,disp.bb - - opnd[0] = position - opnd[1] = register number/memory flag - opnd[2] = memory address, if memory -*/ - -case BBS: - if (op_bb_n (opnd, acc)) BRANCHB (brdisp); /* br if bit set */ - break; -case BBC: - if (!op_bb_n (opnd, acc)) BRANCHB (brdisp); /* br if bit clr */ - break; -case BBSS: case BBSSI: - if (op_bb_x (opnd, 1, acc)) BRANCHB (brdisp); /* br if set, set */ - break; -case BBCC: case BBCCI: - if (!op_bb_x (opnd, 0, acc)) BRANCHB (brdisp); /* br if clr, clr*/ - break; -case BBSC: - if (op_bb_x (opnd, 0, acc)) BRANCHB (brdisp); /* br if clr, set */ - break; -case BBCS: - if (!op_bb_x (opnd, 1, acc)) BRANCHB (brdisp); /* br if set, clr */ - break; -case BLBS: - if (op0 & 1) BRANCHB (brdisp); /* br if bit set */ - break; -case BLBC: - if ((op0 & 1) == 0) BRANCHB (brdisp); /* br if bit clear */ - break; - -/* Extract field instructions - ext?v pos.rl,size.rb,base.wb,dst.wl - - opnd[0] = position - opnd[1] = size - opnd[2] = register number/memory flag - opnd[3] = register content/memory address - spec = register/memory flag - rn = register number - va = memory address -*/ - -case EXTV: - r = op_extv (opnd, vfldrp1, acc); /* get field */ - if (r & byte_sign[op1]) r = r | ~byte_mask[op1]; - WRITE_L (r); /* store field */ - CC_IIZP_L (r); /* set cc's */ - break; -case EXTZV: - r = op_extv (opnd, vfldrp1, acc); /* get field */ - WRITE_L (r); /* store field */ - CC_IIZP_L (r); /* set cc's */ - break; - -/* Compare field instructions - cmp?v pos.rl,size.rb,base.wb,src2.rl - - opnd[0] = position - opnd[1] = size - opnd[2] = register number/memory flag - opnd[3] = register content/memory address - opnd[4] = source2 -*/ - -case CMPV: - r = op_extv (opnd, vfldrp1, acc); /* get field */ - if (r & byte_sign[op1]) r = r | ~byte_mask[op1]; - CC_CMP_L (r, op4); /* set cc's */ - break; -case CMPZV: - r = op_extv (opnd, vfldrp1, acc); /* get field */ - CC_CMP_L (r, op4); /* set cc's */ - break; - -/* Find first field instructions - ff? pos.rl,size.rb,base.wb,dst.wl - - opnd[0] = position - opnd[1] = size - opnd[2] = register number/memory flag - opnd[3] = register content/memory address - spec = register/memory flag - rn = register number - va = memory address -*/ - -case FFS: - r = op_extv (opnd, vfldrp1, acc); /* get field */ - temp = op_ffs (r, op1); /* find first 1 */ - WRITE_L (op0 + temp); /* store result */ - cc = r? 0: CC_Z; /* set cc's */ - break; -case FFC: - r = op_extv (opnd, vfldrp1, acc); /* get field */ - r = r ^ byte_mask[op1]; /* invert bits */ - temp = op_ffs (r, op1); /* find first 1 */ - WRITE_L (op0 + temp); /* store result */ - cc = r? 0: CC_Z; /* set cc's */ - break; - -/* Insert field instruction - insv src.rl,pos.rb,size.rl,base.wb - - opnd[0] = source - opnd[1] = position - opnd[2] = size - opnd[3] = register number/memory flag - opnd[4] = register content/memory address -*/ - -case INSV: - op_insv (opnd, vfldrp1, acc); /* insert field */ - break; - -/* Call and return - call? arg.rx,proc.ab - - opnd[0] = argument - opnd[1] = procedure address -*/ - -case CALLS: - cc = op_call (opnd, TRUE, acc); - break; -case CALLG: - cc = op_call (opnd, FALSE, acc); - break; -case RET: - cc = op_ret (acc); - break; - -/* Miscellaneous instructions */ - -case HALT: - if (PSL & PSL_CUR) RSVD_INST_FAULT; /* not kern? rsvd inst */ - else if (cpu_unit.flags & UNIT_CONH) /* halt to console? */ - cc = con_halt (CON_HLTINS, cc); /* enter firmware */ - else { - ABORT (STOP_HALT); } /* halt to simulator */ -case NOP: - break; -case BPT: - SETPC (fault_PC); - cc = intexc (SCB_BPT, cc, 0, IE_EXC); - GET_CUR; - break; -case XFC: - SETPC (fault_PC); - cc = intexc (SCB_XFC, cc, 0, IE_EXC); - GET_CUR; - break; -case BISPSW: - if (opnd[0] & PSW_MBZ) RSVD_OPND_FAULT; - PSL = PSL | (opnd[0] & ~CC_MASK); - cc = cc | (opnd[0] & CC_MASK); - break; -case BICPSW: - if (opnd[0] & PSW_MBZ) RSVD_OPND_FAULT; - PSL = PSL & ~opnd[0]; - cc = cc & ~opnd[0]; - break; -case MOVPSL: - r = PSL | cc; - WRITE_L (r); - break; -case PUSHR: - op_pushr (opnd, acc); - break; -case POPR: - op_popr (opnd, acc); - break; -case INDEX: - if ((op0 < op1) || (op0 > op2)) SET_TRAP (TRAP_SUBSCR); - r = (op0 + op4) * op3; - WRITE_L (r); - CC_IIZZ_L (r); - break; - -/* Queue and interlocked queue */ - -case INSQUE: - cc = op_insque (opnd, acc); - break; -case REMQUE: - cc = op_remque (opnd, acc); - break; -case INSQHI: - cc = op_insqhi (opnd, acc); - break; -case INSQTI: - cc = op_insqti (opnd, acc); - break; -case REMQHI: - cc = op_remqhi (opnd, acc); - break; -case REMQTI: - cc = op_remqti (opnd, acc); - break; - -/* String instructions */ - -case MOVC3: -case MOVC5: - cc = op_movc (opnd, opc & 4, acc); - break; -case CMPC3: -case CMPC5: - cc = op_cmpc (opnd, opc & 4, acc); - break; -case LOCC: -case SKPC: - cc = op_locskp (opnd, opc & 1, acc); - break; -case SCANC: -case SPANC: - cc = op_scnspn (opnd, opc & 1, acc); - break; - -/* Floating point instructions */ - -case TSTF: case TSTD: - r = op_movfd (op0); - CC_IIZZ_FP (r); - break; -case TSTG: - r = op_movg (op0); - CC_IIZZ_FP (r); - break; - -case MOVF: - r = op_movfd (op0); - WRITE_L (r); - CC_IIZP_FP (r); - break; -case MOVD: - if ((r = op_movfd (op0)) == 0) op1 = 0; - WRITE_Q (r, op1); - CC_IIZP_FP (r); - break; -case MOVG: - if ((r = op_movg (op0)) == 0) op1 = 0; - WRITE_Q (r, op1); - CC_IIZP_FP (r); - break; - -case MNEGF: - r = op_mnegfd (op0); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case MNEGD: - if ((r = op_mnegfd (op0)) == 0) op1 = 0; - WRITE_Q (r, op1); - CC_IIZZ_FP (r); - break; -case MNEGG: - if ((r = op_mnegg (op0)) == 0) op1 = 0; - WRITE_Q (r, op1); - CC_IIZZ_FP (r); - break; - -case CMPF: - cc = op_cmpfd (op0, 0, op1, 0); - break; -case CMPD: - cc = op_cmpfd (op0, op1, op2, op3); - break; -case CMPG: - cc = op_cmpg (op0, op1, op2, op3); - break; - -case CVTBF: - r = op_cvtifdg (SXTB (op0), NULL, opc); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case CVTWF: - r = op_cvtifdg (SXTW (op0), NULL, opc); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case CVTLF: - r = op_cvtifdg (op0, NULL, opc); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case CVTBD: case CVTBG: - r = op_cvtifdg (SXTB (op0), &rh, opc); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case CVTWD: case CVTWG: - r = op_cvtifdg (SXTW (op0), &rh, opc); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case CVTLD: case CVTLG: - r = op_cvtifdg (op0, &rh, opc); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; - -case CVTFB: case CVTDB: case CVTGB: - r = op_cvtfdgi (opnd, &temp, opc) & BMASK; - WRITE_B (r); - CC_IIZZ_B (r); - cc = cc | temp; - break; -case CVTFW: case CVTDW: case CVTGW: - r = op_cvtfdgi (opnd, &temp, opc) & WMASK; - WRITE_W (r); - CC_IIZZ_W (r); - cc = cc | temp; - break; -case CVTFL: case CVTDL: case CVTGL: -case CVTRFL: case CVTRDL: case CVTRGL: - r = op_cvtfdgi (opnd, &temp, opc) & LMASK; - WRITE_L (r); - CC_IIZZ_L (r); - cc = cc | temp; - break; - -case CVTFD: - r = op_movfd (op0); - WRITE_Q (r, 0); - CC_IIZZ_FP (r); - break; -case CVTDF: - r = op_cvtdf (opnd); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case CVTFG: - r = op_cvtfg (opnd, &rh); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case CVTGF: - r = op_cvtgf (opnd); - WRITE_L (r); - CC_IIZZ_FP (r); - break; - -case ADDF2: case ADDF3: - r = op_addf (opnd, FALSE); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case ADDD2: case ADDD3: - r = op_addd (opnd, &rh, FALSE); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case ADDG2: case ADDG3: - r = op_addg (opnd, &rh, FALSE); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case SUBF2: case SUBF3: - r = op_addf (opnd, TRUE); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case SUBD2: case SUBD3: - r = op_addd (opnd, &rh, TRUE); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case SUBG2: case SUBG3: - r = op_addg (opnd, &rh, TRUE); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case MULF2: case MULF3: - r = op_mulf (opnd); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case MULD2: case MULD3: - r = op_muld (opnd, &rh); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case MULG2: case MULG3: - r = op_mulg (opnd, &rh); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case DIVF2: case DIVF3: - r = op_divf (opnd); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case DIVD2: case DIVD3: - r = op_divd (opnd, &rh); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case DIVG2: case DIVG3: - r = op_divg (opnd, &rh); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; - -case ACBF: - r = op_addf (opnd + 1, FALSE); /* add + index */ - temp = op_cmpfd (r, 0, op0, 0); /* result : limit */ - WRITE_L (r); /* write result */ - CC_IIZP_FP (r); /* set cc's */ - if ((temp & CC_Z) || ((op1 & FPSIGN)? /* test br cond */ - !(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp); - break; -case ACBD: - r = op_addd (opnd + 2, &rh, FALSE); - temp = op_cmpfd (r, rh, op0, op1); - WRITE_Q (r, rh); - CC_IIZP_FP (r); - if ((temp & CC_Z) || ((op1 & FPSIGN)? /* test br cond */ - !(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp); - break; -case ACBG: - r = op_addg (opnd + 2, &rh, FALSE); - temp = op_cmpg (r, rh, op0, op1); - WRITE_Q (r, rh); - CC_IIZP_FP (r); - if ((temp & CC_Z) || ((op1 & FPSIGN)? /* test br cond */ - !(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp); - break; - -/* EMODF - - op0 = multiplier - op1 = extension - op2 = multiplicand - op3:op4 = integer destination (int.wl) - op5:op6 = floating destination (flt.wl) -*/ - -case EMODF: - r = op_emodf (opnd, &temp, &flg); - if (op5 < 0) Read (op6, L_LONG, WA); - if (op3 >= 0) R[op3] = temp; - else Write (op4, temp, L_LONG, WA); - WRITE_L (r); - CC_IIZZ_FP (r); - if (flg) { V_INTOV; } - break; - -/* EMODD, EMODG - - op0:op1 = multiplier - op2 = extension - op3:op4 = multiplicand - op5:op6 = integer destination (int.wl) - op7:op8 = floating destination (flt.wq) -*/ - -case EMODD: - r = op_emodd (opnd, &rh, &temp, &flg); - if (op7 < 0) Read (op8, L_LONG, WA); - if (op5 >= 0) R[op5] = temp; - else Write (op6, temp, L_LONG, WA); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - if (flg) { V_INTOV; } - break; - -case EMODG: - r = op_emodg (opnd, &rh, &temp, &flg); - if (op7 < 0) Read (op8, L_LONG, WA); - if (op5 >= 0) R[op5] = temp; - else Write (op6, temp, L_LONG, WA); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - if (flg) { V_INTOV; } - break; - -/* POLY */ - -case POLYF: - op_polyf (opnd, acc); - CC_IIZZ_FP (R[0]); - break; - -case POLYD: - op_polyd (opnd, acc); - CC_IIZZ_FP (R[0]); - break; - -case POLYG: - op_polyg (opnd, acc); - CC_IIZZ_FP (R[0]); - break; - -/* Operating system instructions */ - -case CHMK: case CHME: case CHMS: case CHMU: - cc = op_chm (opnd, cc, opc); /* CHMx */ - GET_CUR; /* update cur mode */ - SET_IRQL; /* update intreq */ - break; -case REI: - cc = op_rei (acc); /* REI */ - GET_CUR; /* update cur mode */ - SET_IRQL; /* update intreq */ - break; -case LDPCTX: - op_ldpctx (acc); - break; -case SVPCTX: - op_svpctx (acc); - break; -case PROBER: case PROBEW: - cc = (cc & CC_C) | op_probe (opnd, opc & 1); - break; -case MTPR: - cc = (cc & CC_C) | op_mtpr (opnd); - SET_IRQL; /* update intreq */ - break; -case MFPR: - r = op_mfpr (opnd); - WRITE_L (r); - CC_IIZP_L (r); - break; - -/* Emulated instructions */ - -case CVTPL: - opnd[2] = (opnd[2] >= 0)? ~opnd[2]: opnd[3]; -case MOVP: case CMPP3: case CMPP4: case CVTLP: -case CVTPS: case CVTSP: case CVTTP: case CVTPT: -case ADDP4: case ADDP6: case SUBP4: case SUBP6: -case MULP: case DIVP: case ASHP: case CRC: -case MOVTC: case MOVTUC: case MATCHC: case EDITPC: - cc = op_emulate (opnd, cc, opc, acc); - break; -default: - RSVD_INST_FAULT; - break; } /* end case op */ -} /* end for */ -ABORT (STOP_UNKNOWN); -} /* end sim_instr */ - -/* Prefetch buffer routine - - Prefetch buffer state - - ibufl, ibufh = the prefetch buffer - ibcnt = number of bytes available (0, 4, 8) - ppc = physical PC - - The get_istr routines fetches the indicated number of bytes from - the prefetch buffer. Although it is complicated, it is faster - than calling Read on every byte of the instruction stream. - - If the prefetch buffer has enough bytes, the required bytes are - extracted from the prefetch buffer and returned. If it does not - have enough bytes, enough prefetch words are fetched until there - are. A longword is only prefetched if data is needed from it, - so any translation errors are real. -*/ - -int32 get_istr (int32 lnt, int32 acc) -{ -int32 bo = PC & 3; -int32 sc, val, t; - -while ((bo + lnt) > ibcnt) { /* until enuf bytes */ - if ((ppc < 0) || (VA_GETOFF (ppc) == 0)) { /* PPC inv, xpg? */ - ppc = Test ((PC + ibcnt) & ~03, RD, &t); /* xlate PC */ - if (ppc < 0) Read ((PC + ibcnt) & ~03, L_LONG, RA); } - if (ibcnt == 0) ibufl = ReadLP (ppc); /* fill low */ - else ibufh = ReadLP (ppc); /* or high */ - ppc = ppc + 4; /* incr phys PC */ - ibcnt = ibcnt + 4; } /* incr ibuf cnt */ -PC = PC + lnt; /* incr PC */ -if (lnt == L_BYTE) val = (ibufl >> (bo << 3)) & BMASK; /* byte? */ -else if (lnt == L_WORD) { /* word? */ - if (bo == 3) val = ((ibufl >> 24) & 0xFF) | ((ibufh & 0xFF) << 8); - else val = (ibufl >> (bo << 3)) & WMASK; } -else if (bo) { /* unaligned lw? */ - sc = bo << 3; - val = (((ibufl >> sc) & align[bo]) | (((uint32) ibufh) << (32 - sc))); } -else val = ibufl; /* aligned lw */ -if ((bo + lnt) >= 4) { /* retire ibufl? */ - ibufl = ibufh; - ibcnt = ibcnt - 4; } -return val; -} - -/* Console entry */ - -int32 con_halt (int32 code, int32 cc) -{ -int32 temp; - -conpc = PC; /* save PC */ -conpsl = ((PSL | cc) & 0xFFFF00FF) | CON_HLTINS; /* PSL, param */ -temp = (PSL >> PSL_V_CUR) & 0x7; /* get is'cur */ -if (temp > 4) conpsl = conpsl | CON_BADPSL; /* invalid? */ -else STK[temp] = SP; /* save stack */ -if (mapen) conpsl = conpsl | CON_MAPON; /* mapping on? */ -mapen = 0; /* turn off map */ -SP = IS; /* set SP from IS */ -PSL = PSL_IS | PSL_IPL1F; /* PSL = 41F0000 */ -JUMP (ROMBASE); /* PC = 20040000 */ -return 0; /* new cc = 0 */ -} - -/* To do list: - Examine/deposit I/O -*/ - -/* Reset */ - -t_stat cpu_reset (DEVICE *dptr) -{ -mem_err = 0; -crd_err = 0; -hlt_pin = 0; -PSL = PSL_IS | PSL_IPL1F; -SISR = 0; -ASTLVL = 4; -MSER = 0; -CADR = 0; -mapen = 0; -if (M == NULL) M = calloc (((uint32) MEMSIZE) >> 2, sizeof (int32)); -if (M == NULL) return SCPE_MEM; -pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -return SCPE_OK; -} - -/* Bootstrap */ - -t_stat cpu_boot (int32 unitno, DEVICE *dptr) -{ -extern int32 clk_csr; -extern t_stat qba_powerup (void); -extern t_stat sysd_powerup (void); -extern t_stat todr_powerup (void); -extern uint32 *rom; -extern t_stat load_cmd (int32 flag, char *cptr); -extern FILE *sim_log; -t_stat r; - -qba_powerup (); -sysd_powerup (); -todr_powerup (); -PC = ROMBASE; -PSL = PSL_IS | PSL_IPL1F; -conpc = 0; -conpsl = PSL_IS | PSL_IPL1F | CON_PWRUP; -if (rom == NULL) return SCPE_IERR; -if (*rom == 0) { /* no boot? */ - printf ("Loading boot code from ka655.bin\n"); - if (sim_log) fprintf (sim_log, - "Loading boot code from ka655.bin\n"); - r = load_cmd (0, "-R ka655.bin"); - if (r != SCPE_OK) return r; } -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) -{ -int32 st; -uint32 addr = (uint32) exta; - -if (vptr == NULL) return SCPE_ARG; -if (sw & SWMASK ('V')) addr = Test (addr, RD, &st); -else addr = addr & PAMASK; -if (ADDR_IS_MEM (addr) || ADDR_IS_CDG (addr) || - ADDR_IS_ROM (addr) || ADDR_IS_NVR (addr)) { - *vptr = (uint32) ReadB (addr); - return SCPE_OK; } -return SCPE_NXM; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw) -{ -int32 st; -uint32 addr = (uint32) exta; - -if (sw & SWMASK ('V')) addr = Test (addr, RD, &st); -else addr = addr & PAMASK; -if (ADDR_IS_MEM (addr) || ADDR_IS_CDG (addr) || - ADDR_IS_NVR (addr)) { - WriteB (addr, (int32) val); - return SCPE_OK; } -if (ADDR_IS_ROM (addr)) { - rom_wr (addr, (int32) val, L_BYTE); - return SCPE_OK; } -return SCPE_NXM; -} - -/* Memory allocation */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i, clim; -uint32 *nM = NULL; - -if ((val <= 0) || (val > MAXMEMSIZE)) return SCPE_ARG; -for (i = val; i < MEMSIZE; i = i + 4) mc = mc | M[i >> 2]; -if ((mc != 0) && !get_yn ("Really truncate memory [N]?", FALSE)) - return SCPE_OK; -nM = calloc (val >> 2, sizeof (uint32)); -if (nM == NULL) return SCPE_MEM; -clim = (uint32) ((((uint32) val) < MEMSIZE)? val: MEMSIZE); -for (i = 0; i < clim; i = i + 4) nM[i >> 2] = M[i >> 2]; -free (M); -M = nM; -MEMSIZE = val; -return SCPE_OK; } - -/* Virtual address translation */ - -t_stat cpu_show_virt (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -t_stat r; -uint32 va, pa; -int32 st; -static const char *mm_str[] = { - "Access control violation", - "Length violation", - "Process PTE access control violation", - "Process PTE length violation", - "Translation not valid", - "Internal error", - "Process PTE translation not valid" }; - -if (cptr == NULL) return SCPE_ARG; -va = (uint32) get_uint (cptr, 16, 0xFFFFFFFF, &r); -if (r != SCPE_OK) return SCPE_ARG; -pa = Test (va, RD, &st); -if (st == PR_OK) printf ("Virtual %-X = physical %-X\n", va, pa); -else printf ("Virtual %-X: %s\n", va, mm_str[st]); -return SCPE_OK; -} - -/* Set history */ - -t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 i, lnt; -t_stat r; - -if (cptr == NULL) { - for (i = 0; i < HIST_SIZE; i++) hst[i].iPC = 0; - return SCPE_OK; } -lnt = (int32) get_uint (cptr, 10, HIST_SIZE, &r); -if (r != SCPE_OK) return SCPE_ARG; -hst_lnt = lnt; -return SCPE_OK; -} - -/* Show history */ - -t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, j, k, di, disp, numspec; -struct InstHistory *h; -extern char *opcode[]; - -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ -di = hst_p + HIST_SIZE - hst_lnt; /* work forward */ -for (k = 0; k < hst_lnt; k++) { /* print specified */ - h = &hst[(di++) % HIST_SIZE]; /* entry pointer */ - if (h->iPC == 0) continue; /* filled in? */ - fprintf(st, "%08X %08X ", h->iPC, h->PSL); /* PC, PSL */ - numspec = drom[h->opc][0] & DR_NSPMASK; /* #specifiers */ - if (opcode[h->opc] == NULL) /* undefined? */ - fprintf (st, "%03X (undefined)", h->opc); - else if (h->PSL & PSL_FPD) /* FPD set? */ - fprintf (st, "%s FPD set", opcode[h->opc]); - else { /* normal */ - fprintf (st, "%s", opcode[h->opc]); /* print opcode */ - for (i = 1, j = 0; i <= numspec; i++) { /* loop thru specs */ - fputc ((i == 1)? ' ': ',', st); /* separator */ - disp = drom[h->opc][i]; /* specifier type */ - if (disp == RG) disp = RQ; /* fix specials */ - else if (disp >= BB) fprintf (st, "%X", h->brdest); - else switch (disp & 0xF) { /* case on type */ - case RB: case RW: case RL: /* read */ - case AB: case AW: case AL: case AQ: /* address */ - case MB: case MW: case ML: /* modify */ - fprintf (st, "%X", h->opnd[j++]); - break; - case RQ: /* read quad */ - case MQ: /* modify quad */ - fprintf (st, "%X%08X", h->opnd[j], h->opnd[j + 1]); - j = j + 2; - break; - case WB: case WW: case WL: case WQ: /* write */ - if (h->opnd[j] < 0) fprintf (st, "%X", h->opnd[j + 1]); - else fprintf (st, "R%d", h->opnd[j]); - j = j + 2; - break; - } /* end case */ - } /* end for */ - } /* end else */ - fputc ('\n', st); /* end line */ - } /* end for */ -return SCPE_OK; -} diff --git a/VAX/vax_cpu1.c b/VAX/vax_cpu1.c deleted file mode 100644 index ad1f6c23..00000000 --- a/VAX/vax_cpu1.c +++ /dev/null @@ -1,1492 +0,0 @@ -/* vax_cpu1.c: VAX complex instructions - - Copyright (c) 1998-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 30-Apr-02 RMS Fixed interrupt/exception handler to clear traps - 17-Apr-02 RMS Fixed pos > 31 test in bit fields (should be unsigned) - 14-Apr-02 RMS Fixed prv_mode handling for interrupts (found by Tim Stark) - Fixed PROBEx to mask mode to 2b (found by Kevin Handy) - - This module contains the instruction simulators for - - Field instructions: - - BBS, BBC, BBSSI, BBCCI - - BBSC, BBCC, BBCS, BBSS - - EXTV, EXTZV, CMPV, CMPZV - - FFS, FFC, INSV - - Call/return and push/pop instructions: - - CALLS, CALLG, RET - - PUSHR, POPR - - Queue instructions: - - INSQUE, REMQUE - - INSQHI, INSQTI, REMQHI, REMQTI - - String instructions: - - MOVC3, MOVC5, CMPC3, CMPC5 - - LOCC, SKPC, SCANC, SPANC - - Operating system interface instructions: - - CHMK, CHME, CHMS, CHMU - - PROBER, PROBEW, REI - - MTPR, MFPR - - LDPCTX, SVPCTX - - (interrupt and exception routine) - - Emulated instructions: - - MOVP, CMPP3, CMPP4, ASHP - - ADDP4, ADDP6, SUBP4, SUBP6 - - MULP, DIVP, CVTLP, CVTPL, - - CVTPT, CVTTP, CVTPS, CVTSP - - EDITPC, CRC - - MATCHC, MOVTC, MOVTUC -*/ - -#include "vax_defs.h" - -static const uint8 rcnt[128] = { - 0, 4, 4, 8, 4, 8, 8,12, 4, 8, 8,12, 8,12,12,16, /* 00 - 0F */ - 4, 8, 8,12, 8,12,12,16, 8,12,12,16,12,16,16,20, /* 10 - 1F */ - 4, 8, 8,12, 8,12,12,16, 8,12,12,16,12,16,16,20, /* 20 - 2F */ - 8,12,12,16,12,16,16,20,12,16,16,20,16,20,20,24, /* 30 - 3F */ - 4, 8, 8,12, 8,12,12,16, 8,12,12,16,12,16,16,20, /* 40 - 4F */ - 8,12,12,16,12,16,16,20,12,16,16,20,16,20,20,24, /* 50 - 5F */ - 8,12,12,16,12,16,16,20,12,16,16,20,16,20,20,24, /* 60 - 6F */ -12,16,16,20,16,20,20,24,16,20,20,24,20,24,24,28 /* 70 - 7F */ -}; - -int32 last_chm = 0; - -extern uint32 *M; -extern uint32 byte_mask[33]; -extern int32 R[16]; -extern int32 STK[5]; -extern int32 PSL; -extern int32 SCBB, PCBB, SBR, SLR; -extern int32 P0BR, P0LR, P1BR, P1LR; -extern int32 ASTLVL, SISR, mapen; -extern int32 CADR, MSER; -extern int32 trpirq; -extern int32 p1, p2; -extern int32 conpsl, conpc; -extern int32 fault_PC; -extern int32 pcq[PCQ_SIZE]; -extern int32 pcq_p; -extern int32 in_ie; -extern int32 mchk_va; -extern int32 sim_interval; -extern int32 ibcnt, ppc; -extern int32 cpu_log; -extern FILE *sim_log; - -extern int32 Read (uint32 va, int32 lnt, int32 acc); -extern void Write (uint32 va, int32 val, int32 lnt, int32 acc); -extern int32 Test (uint32 va, int32 acc, int32 *status); -extern int32 ReadLP (uint32 pa); -extern void WriteLP (uint32 pa, int32 val); -extern void set_map_reg (void); -extern void zap_tb (int stb); -extern void zap_tb_ent (uint32 va); -extern t_bool chk_tb_ent (uint32 va); -extern int32 ReadIPR (int32 rg); -extern void WriteIPR (int32 rg, int32 val); -extern jmp_buf save_env; - -/* Branch on bit and no modify - Branch on bit and modify - - opnd[0] = position (pos.rl) - opnd[1] = register number/memory flag - opnd[2] = memory address, if memory - Returns bit to be tested -*/ - -int32 op_bb_n (int32 *opnd, int32 acc) -{ -int32 pos = opnd[0]; -int32 rn = opnd[1]; -int32 ea, by; - -if (rn >= 0) { /* register? */ - if (((uint32) pos) > 31) RSVD_OPND_FAULT; /* pos > 31? fault */ - return (R[rn] >> pos) & 1; } /* get bit */ -ea = opnd[2] + (pos >> 3); /* base byte addr */ -pos = pos & 07; /* pos in byte */ -by = Read (ea, L_BYTE, RA); /* read byte */ -return ((by >> pos) & 1); /* get bit */ -} - -int32 op_bb_x (int32 *opnd, int32 newb, int32 acc) -{ -int32 pos = opnd[0]; -int32 rn = opnd[1]; -int32 ea, by, bit; - -if (rn >= 0) { /* register? */ - if (((uint32) pos) > 31) RSVD_OPND_FAULT; /* pos > 31? fault */ - bit = (R[rn] >> pos) & 1; /* get bit */ - R[rn] = newb? (R[rn] | (1u << pos)): (R[rn] & ~(1u << pos)); - return bit; } -ea = opnd[2] + (pos >> 3); /* base byte addr */ -pos = pos & 07; /* pos in byte */ -by = Read (ea, L_BYTE, WA); /* read byte */ -bit = (by >> pos) & 1; /* get bit */ -by = newb? (by | (1u << pos)): (by & ~(1u << pos)); /* change bit */ -Write (ea, by, L_BYTE, WA); /* rewrite byte */ -return bit; -} - -/* Extract field - - opnd[0] = position (pos.rl) - opnd[1] = size (size.rb) - opnd[2] = register number/memory flag - opnd[3] = register content/memory address - - If the field is in a register, rn + 1 is in vfldrp1 -*/ - -int32 op_extv (int32 *opnd, int32 vfldrp1, int32 acc) -{ -int32 pos = opnd[0]; -int32 size = opnd[1]; -int32 rn = opnd[2]; -uint32 wd = opnd[3]; -int32 ba, wd1 = 0; - -if (size == 0) return 0; /* size 0? field = 0 */ -if (size > 32) RSVD_OPND_FAULT; /* size > 32? fault */ -if (rn >= 0) { /* register? */ - if (((uint32) pos) > 31) RSVD_OPND_FAULT; /* pos > 31? fault */ - if (pos) wd = (wd >> pos) | (((uint32) vfldrp1) << (32 - pos)); } -else { ba = wd + (pos >> 3); /* base byte addr */ - pos = (pos & 07) | ((ba & 03) << 3); /* bit offset */ - ba = ba & ~03; /* lw align base */ - wd = Read (ba, L_LONG, RA); /* read field */ - if ((size + pos) > 32) wd1 = Read (ba + 4, L_LONG, RA); - if (pos) wd = (wd >> pos) | (((uint32) wd1) << (32 - pos)); } -return wd & byte_mask[size]; -} - -/* Insert field - - opnd[0] = field (src.rl) - opnd[1] = position (pos.rl) - opnd[2] = size (size.rb) - opnd[3] = register number/memory flag - opnd[4] = register content/memory address - - If the field is in a register, rn + 1 is in vfldrp1 -*/ - -void op_insv (int32 *opnd, int32 vfldrp1, int32 acc) -{ -uint32 ins = opnd[0]; -int32 pos = opnd[1]; -int32 size = opnd[2]; -int32 rn = opnd[3]; -int32 val, mask, ba, wd, wd1; - -if (size == 0) return; /* size = 0? done */ -if (size > 32) RSVD_OPND_FAULT; /* size > 32? fault */ -if (rn >= 0) { /* in registers? */ - if (((uint32) pos) > 31) RSVD_OPND_FAULT; /* pos > 31? fault */ - if ((pos + size) > 32) { /* span two reg? */ - if (rn >= nSP) RSVD_OPND_FAULT; /* if PC, fault */ - mask = byte_mask[pos + size - 32]; /* insert fragment */ - val = ins >> (32 - pos); - R[rnplus1] = (vfldrp1 & ~mask) | (val & mask); } - mask = byte_mask[size] << pos; /* insert field */ - val = ins << pos; - R[rn] = (R[rn] & ~mask) | (val & mask); } -else { ba = opnd[4] + (pos >> 3); /* base byte addr */ - pos = (pos & 07) | ((ba & 03) << 3); /* bit offset */ - ba = ba & ~03; /* lw align base */ - wd = Read (ba, L_LONG, WA); /* read field */ - if ((size + pos) > 32) { /* field span lw? */ - wd1 = Read (ba + 4, L_LONG, WA); /* read 2nd lw */ - mask = byte_mask[pos + size - 32]; /* insert fragment */ - val = ins >> (32 - pos); - Write (ba + 4, (wd1 & ~mask) | (val & mask), L_LONG, WA); } - mask = byte_mask[size] << pos; /* insert field */ - val = ins << pos; - Write (ba, (wd & ~mask) | (val & mask), L_LONG, WA); } -return; -} - -/* Find first */ - -int32 op_ffs (uint32 wd, int32 size) -{ -int32 i; - -for (i = 0; wd; i++, wd = wd >> 1) if (wd & 1) return i; -return size; -} - -#define CALL_DV 0x8000 /* DV set */ -#define CALL_IV 0x4000 /* IV set */ -#define CALL_MBZ 0x3000 /* MBZ */ -#define CALL_MASK 0x0FFF /* mask */ -#define CALL_V_SPA 30 /* SPA */ -#define CALL_M_SPA 03 -#define CALL_V_S 29 /* S flag */ -#define CALL_S (1 << CALL_V_S) -#define CALL_V_MASK 16 -#define CALL_PUSH(n) if ((mask >> (n)) & 1) { \ - tsp = tsp - 4; \ - Write (tsp, R[n], L_LONG, WA); } -#define CALL_GETSPA(x) (((x) >> CALL_V_SPA) & CALL_M_SPA) -#define RET_POP(n) if ((spamask >> (n + CALL_V_MASK)) & 1) { \ - R[n] = Read (tsp, L_LONG, RA); \ - tsp = tsp + 4; } -#define PUSHR_PUSH(n) CALL_PUSH(n) -#define POPR_POP(n) if ((mask >> (n)) & 1) { \ - R[n] = Read (SP, L_LONG, RA); \ - SP = SP + 4; } - -/* CALLG, CALLS - - opnd[0] = argument (arg.rx) - opnd[1] = procedure address (adr.ab) - flg = CALLG (0), CALLS (1) - acc = access mask - - These instructions implement a generalized procedure call and return facility. - The principal data structure involved is the stack frame. - CALLS and CALLG build a stack frame in the following format: - - - +---------------------------------------------------------------+ - | condition handler (initially 0) | - +---+-+-+-----------------------+--------------------+----------+ - |SPA|S|0| entry mask<11:0> | saved PSW<15:5> | 0 0 0 0 0| - +---+-+-+-----------------------+--------------------+----------+ - | saved AP | - +---------------------------------------------------------------+ - | saved FP | - +---------------------------------------------------------------+ - | saved PC | - +---------------------------------------------------------------+ - | saved R0 (...) | - +---------------------------------------------------------------+ - . . - . (according to entry mask<11:0>) . - . . - +---------------------------------------------------------------+ - | saved R11 (...) | - +---------------+-----------------------------------------------+ - | #args (CALLS) | (0-3 bytes needed to align stack) | - +---------------+-----------------------------------------------+ - | | 0 0 0 (CALLS) | - +---------------+-----------------------------------------------+ - - RET expects to find this structure based at the frame pointer (FP). - - For CALLG and CALLS, the entry mask specifies the new settings of - DV and IV, and also which registers are to be saved on entry: - - 15 14 13 12 11 0 - +--+--+-----+----------------------------------+ - |DV|IV| MBZ | register mask | - +--+--+-----+----------------------------------+ - - CALLG/CALLS operation: - - read the procedure entry mask - make sure that the stack frame will be accessible - if CALLS, push the number of arguments onto the stack - align the stack to the next lower longword boundary - push the registers specified by the procedure entry mask - push PC, AP, FP, saved SPA/S0/mask/PSW, condition handler - update PC, SP, FP, AP - update PSW traps, clear condition codes -*/ - -int32 op_call (int32 *opnd, t_bool gs, int32 acc) -{ -int32 addr = opnd[1]; -int32 mask, stklen, tsp, wd; - -mask = Read (addr, L_WORD, RA); /* get proc mask */ -if (mask & CALL_MBZ) RSVD_OPND_FAULT; /* test mbz */ -stklen = rcnt[mask & 077] + rcnt[(mask >> 6) & 077] + (gs? 24: 20); -Read (SP - stklen, L_BYTE, WA); /* wchk stk */ -if (gs) { - Write (SP - 4, opnd[0], L_LONG, WA); /* if S, push #arg */ - SP = SP - 4; } /* stack is valid */ -tsp = SP & ~CALL_M_SPA; /* lw align stack */ -CALL_PUSH (11); /* check mask bits, */ -CALL_PUSH (10); /* push sel reg */ -CALL_PUSH (9); -CALL_PUSH (8); -CALL_PUSH (7); -CALL_PUSH (6); -CALL_PUSH (5); -CALL_PUSH (4); -CALL_PUSH (3); -CALL_PUSH (2); -CALL_PUSH (1); -CALL_PUSH (0); -Write (tsp - 4, PC, L_LONG, WA); /* push PC */ -Write (tsp - 8, FP, L_LONG, WA); /* push AP */ -Write (tsp - 12, AP, L_LONG, WA); /* push FP */ -wd = ((SP & CALL_M_SPA) << CALL_V_SPA) | (gs << CALL_V_S) | - ((mask & CALL_MASK) << CALL_V_MASK) | (PSL & 0xFFE0); -Write (tsp - 16, wd, L_LONG, WA); /* push spa/s/mask/psw */ -Write (tsp - 20, 0, L_LONG, WA); /* push cond hdlr */ -if (gs) AP = SP; /* update AP */ -else AP = opnd[0]; -SP = FP = tsp - 20; /* update FP, SP */ -PSL = (PSL & ~(PSW_DV | PSW_FU | PSW_IV)) | /* update PSW */ - ((mask & CALL_DV)? PSW_DV: 0) | - ((mask & CALL_IV)? PSW_IV: 0); -JUMP (addr + 2); /* new PC */ -return 0; /* new cc's */ -} - -int32 op_ret (int32 acc) -{ -int32 spamask, stklen, newpc, nargs; -int32 tsp = FP; - -spamask = Read (tsp + 4, L_LONG, RA); /* spa/s/mask/psw */ -if (spamask & PSW_MBZ) RSVD_OPND_FAULT; /* test mbz */ -stklen = rcnt[(spamask >> CALL_V_MASK) & 077] + - rcnt[(spamask >> (CALL_V_MASK + 6)) & 077] + ((spamask & CALL_S)? 23: 19); -Read (tsp + stklen, L_BYTE, RA); /* rchk stk end */ -AP = Read (tsp + 8, L_LONG, RA); /* restore AP */ -FP = Read (tsp + 12, L_LONG, RA); /* restore FP */ -newpc = Read (tsp + 16, L_LONG, RA); /* get new PC */ -tsp = tsp + 20; /* update stk ptr */ -RET_POP (0); /* chk mask bits, */ -RET_POP (1); /* pop sel regs */ -RET_POP (2); -RET_POP (3); -RET_POP (4); -RET_POP (5); -RET_POP (6); -RET_POP (7); -RET_POP (8); -RET_POP (9); -RET_POP (10); -RET_POP (11); -SP = tsp + CALL_GETSPA (spamask); /* dealign stack */ -if (spamask & CALL_S) { /* CALLS? */ - nargs = Read (SP, L_LONG, RA); /* read #args */ - SP = SP + 4 + ((nargs & BMASK) << 2); } /* pop arg list */ -PSL = (PSL & ~(PSW_DV | PSW_FU | PSW_IV | PSW_T)) | /* reset PSW */ - (spamask & (PSW_DV | PSW_FU | PSW_IV | PSW_T)); -JUMP (newpc); /* set new PC */ -return spamask & (CC_MASK); /* return cc's */ -} - -/* PUSHR and POPR */ - -void op_pushr (int32 *opnd, int32 acc) -{ -int32 mask = opnd[0] & 0x7FFF; -int32 stklen, tsp; - -if (mask == 0) return; -stklen = rcnt[(mask >> 7) & 0177] + rcnt[mask & 0177] + - ((mask & 0x4000)? 4: 0); -Read (SP - stklen, L_BYTE, WA); /* wchk stk end */ -tsp = SP; /* temp stk ptr */ -PUSHR_PUSH (14); /* check mask bits, */ -PUSHR_PUSH (13); /* push sel reg */ -PUSHR_PUSH (12); -PUSHR_PUSH (11); -PUSHR_PUSH (10); -PUSHR_PUSH (9); -PUSHR_PUSH (8); -PUSHR_PUSH (7); -PUSHR_PUSH (6); -PUSHR_PUSH (5); -PUSHR_PUSH (4); -PUSHR_PUSH (3); -PUSHR_PUSH (2); -PUSHR_PUSH (1); -PUSHR_PUSH (0); -SP = tsp; /* update stk ptr */ -return; -} - -void op_popr (int32 *opnd, int32 acc) -{ -int32 mask = opnd[0] & 0x7FFF; -int32 stklen; - -if (mask == 0) return; -stklen = rcnt[(mask >> 7) & 0177] + rcnt[mask & 0177] + - ((mask & 0x4000)? 4: 0); -Read (SP + stklen - 1, L_BYTE, RA); /* rchk stk end */ -POPR_POP (0); /* check mask bits, */ -POPR_POP (1); /* pop sel regs */ -POPR_POP (2); -POPR_POP (3); -POPR_POP (4); -POPR_POP (5); -POPR_POP (6); -POPR_POP (7); -POPR_POP (8); -POPR_POP (9); -POPR_POP (10); -POPR_POP (11); -POPR_POP (12); -POPR_POP (13); -if (mask & 0x4000) SP = Read (SP, L_LONG, RA); /* if pop SP, no inc */ -return; -} - -/* INSQUE - - opnd[0] = entry address (ent.ab) - opnd[1] = predecessor address (pred.ab) - - Condition codes returned to caller on comparison of (ent):(ent+4). - All writes must be checked before any writes are done. - - Pictorially: - - BEFORE AFTER - - P: S P: E W - P+4: (n/a) P+4: (n/a) - - E: --- E: S W - E+4: --- E+4: P W - - S: (n/a) S: (n/a) - S+4: P S+4: E W - - s+4 must be tested with a read modify rather than a probe, as it - might be misaligned. -*/ - -int32 op_insque (int32 *opnd, int32 acc) -{ -int32 p = opnd[1]; -int32 e = opnd[0]; -int32 s, cc; - -s = Read (p, L_LONG, WA); /* s <- (p), wchk */ -Read (s + 4, L_LONG, WA); /* wchk s+4 */ -Read (e + 4, L_LONG, WA); /* wchk e+4 */ -Write (e, s, L_LONG, WA); /* (e) <- s */ -Write (e + 4, p, L_LONG, WA); /* (e+4) <- p */ -Write (s + 4, e, L_LONG, WA); /* (s+4) <- ent */ -Write (p, e, L_LONG, WA); /* (p) <- e */ -CC_CMP_L (s, p); /* set cc's */ -return cc; -} - -/* REMQUE - - opnd[0] = entry address (ent.ab) - opnd[1:2] = destination address (dst.wl) - - Condition codes returned to caller based on (ent):(ent+4). - All writes must be checked before any writes are done. - - Pictorially: - - BEFORE AFTER - - P: E P: S W - P+4: (n/a) P+4: (n/a) - - E: S W E: S - E+4: P W E+4: P - - S: (n/a) S: (n/a) - S+4: E W S+4: P - -*/ - -int32 op_remque (int32 *opnd, int32 acc) -{ -int32 e = opnd[0]; -int32 s, p, cc; - -s = Read (e, L_LONG, RA); /* s <- (e) */ -p = Read (e + 4, L_LONG, RA); /* p <- (e+4) */ -CC_CMP_L (s, p); /* set cc's */ -if (e != p) { /* queue !empty? */ - Read (s + 4, L_LONG, WA); /* wchk (s+4) */ - if (opnd[1] < 0) Read (opnd[2], L_LONG, WA); /* wchk dest */ - Write (p, s, L_LONG, WA); /* (p) <- s */ - Write (s + 4, p, L_LONG, WA); } /* (s+4) <- p */ -else cc = cc | CC_V; /* else set v */ -if (opnd[1] >= 0) R[opnd[1]] = e; /* store result */ -else Write (opnd[2], e, L_LONG, WA); -return cc; -} - -/* Interlocked insert instructions - - opnd[0] = entry (ent.ab) - opnd[1] = header (hdr.aq) - - Pictorially: - - BEFORE AFTER INSQHI AFTER INSQTI - - H: A-H H: D-H W H: A-H W for interlock - H+4: C-H H+4: C-H H+4: D-H W - - A: B-A A: B-A A: B-A - A+4: H-A A+4: D-A W A+4: H-A - - B: C-B B: C-B B: C-B - B+4: A-B B+4: A-B B+4: A-B - - C: H-C C: H-C C: D-C W - C+4: B-C C+4: B-C C+4: B-C - - D: --- D: A-D W D: H-D W - D+4: --- D+4: H-D W D+4: C-D W - - Note that the queue header, the entry to be inserted, and all - the intermediate entries that are "touched" in any way must be - QUADWORD aligned. In addition, the header and the entry must - not be equal. -*/ - -int32 op_insqhi (int32 *opnd, int32 acc) -{ -int32 h = opnd[1]; -int32 d = opnd[0]; -int32 a, t; - -if ((h == d) || ((h | d) & 07)) RSVD_OPND_FAULT; /* h, d quad align? */ -Read (d, L_BYTE, WA); /* wchk ent */ -a = Read (h, L_LONG, WA); /* a <- (h), wchk */ -if (a & 06) RSVD_OPND_FAULT; /* chk quad align */ -if (a & 01) return CC_C; /* busy, cc = 0001 */ -Write (h, a | 1, L_LONG, WA); /* get interlock */ -a = a + h; /* abs addr of a */ -if (Test (a, WA, &t) < 0) Write (h, a - h, L_LONG, WA); /* wtst a, rls if err */ -Write (a + 4, d - a, L_LONG, WA); /* (a+4) <- d-a, flt ok */ -Write (d, a - d, L_LONG, WA); /* (d) <- a-d */ -Write (d + 4, h - d, L_LONG, WA); /* (d+4) <- h-d */ -Write (h, d - h, L_LONG, WA); /* (h) <- d-h, rls int */ -return (a == h)? CC_Z: 0; /* Z = 1 if a = h */ -} - -int32 op_insqti (int32 *opnd, int32 acc) -{ -int32 h = opnd[1]; -int32 d = opnd[0]; -int32 a, c, t; - -if ((h == d) || ((h | d) & 07)) RSVD_OPND_FAULT; /* h, d quad align? */ -Read (d, L_BYTE, WA); /* wchk ent */ -a = Read (h, L_LONG, WA); /* a <- (h), wchk */ -if (a == 0) return op_insqhi (opnd, acc); /* if empty, ins hd */ -if (a & 06) RSVD_OPND_FAULT; /* chk quad align */ -if (a & 01) return CC_C; /* busy, cc = 0001 */ -Write (h, a | 1, L_LONG, WA); /* acquire interlock */ -c = Read (h + 4, L_LONG, RA) + h; /* c <- (h+4) + h */ -if (c & 07) { /* c quad aligned? */ - Write (h, a, L_LONG, WA); /* release interlock */ - RSVD_OPND_FAULT; } /* fault */ -if (Test (c, WA, &t) < 0) Write (h, a, L_LONG, WA); /* wtst c, rls if err */ -Write (c, d - c, L_LONG, WA); /* (c) <- d-c, flt ok */ -Write (d, h - d, L_LONG, WA); /* (d) <- h-d */ -Write (d + 4, c - d, L_LONG, WA); /* (d+4) <- c-d */ -Write (h + 4, d - h, L_LONG, WA); /* (h+4) <- d-h */ -Write (h, a, L_LONG, WA); /* release interlock */ -return 0; /* q >= 2 entries */ -} - -/* Interlocked remove instructions - - opnd[0] = header (hdr.aq) - opnd[1:2] = destination address (dst.al) - - Pictorially: - - BEFORE AFTER REMQHI AFTER REMQTI - - H: A-H H: B-H W H: A-H W for interlock - H+4: C-H H+4: C-H H+4: B-H W - - A: B-A A: B-A R A: B-A - A+4: H-A A+4: H-A A+4: H-A - - B: C-B B: C-B B: H-B W - B+4: A-B B+4: H-B W B+4: A-B - - C: H-C C: H-C C: H-C - C+4: B-C C+4: B-C C+4: B-C R - - Note that the queue header and all the entries that are - "touched" in any way must be QUADWORD aligned. In addition, - the header and the destination must not be equal. -*/ - -int32 op_remqhi (int32 *opnd, int32 acc) -{ -int32 h = opnd[0]; -int32 ar, a, b, t; - -if (h & 07) RSVD_OPND_FAULT; /* h quad aligned? */ -if (opnd[1] < 0) { /* mem destination? */ - if (h == opnd[2]) RSVD_OPND_FAULT; /* hdr = dst? */ - Read (opnd[2], L_LONG, WA); } /* wchk dst */ -ar = Read (h, L_LONG, WA); /* ar <- (h) */ -if (ar & 06) RSVD_OPND_FAULT; /* a quad aligned? */ -if (ar & 01) return CC_V | CC_C; /* busy, cc = 0011 */ -a = ar + h; /* abs addr of a */ -if (ar) { /* queue not empty? */ - Write (h, ar | 1, L_LONG, WA); /* acquire interlock */ - if (Test (a, RA, &t) < 0) /* read tst a */ - Write (h, ar, L_LONG, WA); /* release if error */ - b = Read (a, L_LONG, RA) + a; /* b <- (a)+a, flt ok */ - if (b & 07) { /* b quad aligned? */ - Write (h, ar, L_LONG, WA); /* release interlock */ - RSVD_OPND_FAULT; } /* fault */ - if (Test (b, WA, &t) < 0) /* write test b */ - Write (h, ar, L_LONG, WA); /* release if err */ - Write (b + 4, h - b, L_LONG, WA); /* (b+4) <- h-b, flt ok */ - Write (h, b - h, L_LONG, WA); } /* (h) <- b-h, rls int */ -if (opnd[1] >= 0) R[opnd[1]] = a; /* store result */ -else Write (opnd[2], a, L_LONG, WA); -if (ar == 0) return CC_Z | CC_V; /* empty, cc = 0110 */ -return (b == h)? CC_Z: 0; /* if b = h, q empty */ -} - -int32 op_remqti (int32 *opnd, int32 acc) -{ -int32 h = opnd[0]; -int32 ar, b, c, t; - -if (h & 07) RSVD_OPND_FAULT; /* h quad aligned? */ -if (opnd[1] < 0) { /* mem destination? */ - if (h == opnd[2]) RSVD_OPND_FAULT; /* hdr = dst? */ - Read (opnd[2], L_LONG, WA); } /* wchk dst */ -ar = Read (h, L_LONG, WA); /* a <- (h) */ -if (ar & 06) RSVD_OPND_FAULT; /* a quad aligned? */ -if (ar & 01) return CC_V | CC_C; /* busy, cc = 0011 */ -if (ar) { /* queue not empty */ - Write (h, ar | 1, L_LONG, WA); /* acquire interlock */ - c = Read (h + 4, L_LONG, RA); /* c <- (h+4) */ - if (ar == c) { /* single entry? */ - Write (h, ar, L_LONG, WA); /* release interlock */ - return op_remqhi (opnd, acc); } /* treat as remqhi */ - if (c & 07) { /* c quad aligned? */ - Write (h, ar, L_LONG, WA); /* release interlock */ - RSVD_OPND_FAULT; } /* fault */ - c = c + h; /* abs addr of c */ - if (Test (c + 4, RA, &t) < 0) /* read test c+4 */ - Write (h, ar, L_LONG, WA); /* release if error */ - b = Read (c + 4, L_LONG, RA) + c; /* b <- (c+4)+c, flt ok */ - if (b & 07) { /* b quad aligned? */ - Write (h, ar, L_LONG, WA); /* release interlock */ - RSVD_OPND_FAULT; } /* fault */ - if (Test (b, WA, &t) < 0) /* write test b */ - Write (h, ar, L_LONG, WA); /* release if error */ - Write (b, h - b, L_LONG, WA); /* (b) <- h-b */ - Write (h + 4, b - h, L_LONG, WA); /* (h+4) <- b-h */ - Write (h, ar, L_LONG, WA); } /* release interlock */ -else c = h; /* empty, result = h */ -if (opnd[1] >= 0) R[opnd[1]] = c; /* store result */ -else Write (opnd[2], c, L_LONG, WA); -if (ar == 0) return CC_Z | CC_V; /* empty, cc = 0110 */ -return 0; /* q can't be empty */ -} - -/* String instructions */ - -#define MVC_FRWD 0 /* movc state codes */ -#define MVC_BACK 1 -#define MVC_FILL 3 /* must be 3 */ -#define MVC_M_STATE 3 -#define MVC_V_CC 2 -#define STR_V_DPC 24 -#define STR_M_DPC 0xFF -#define STR_V_CHR 16 -#define STR_M_CHR 0xFF -#define STR_LNMASK 0xFFFF -#define STR_GETDPC(x) (((x) >> STR_V_DPC) & STR_M_DPC) -#define STR_GETCHR(x) (((x) >> STR_V_CHR) & STR_M_CHR) -#define STR_PACK(m,x) ((((PC - fault_PC) & STR_M_DPC) << STR_V_DPC) | \ - (((m) & STR_M_CHR) << STR_V_CHR) | ((x) & STR_LNMASK)) - -/* MOVC3, MOVC5 - - if PSL = 0 and MOVC3, - opnd[0] = length - opnd[1] = source address - opnd[2] = dest address - - if PSL = 0 and MOVC5, - opnd[0] = source length - opnd[1] = source address - opnd[2] = fill - opnd[3] = dest length - opnd[4] = dest address - - if PSL = 1, - R0 = delta-PC/fill/initial move length - R1 = current source address - R2 = current move length - R3 = current dest address - R4 = dstlen - srclen (loop count if fill state) - R5 = cc/state -*/ - -int32 op_movc (int32 *opnd, int32 movc5, int32 acc) -{ -int32 i, cc, fill, wd; -int32 j, lnt, mlnt[3]; -static const int32 looplnt[3] = { L_BYTE, L_LONG, L_BYTE }; - -if (PSL & PSL_FPD) { /* FPD set? */ - SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */ - fill = STR_GETCHR (R[0]); /* get fill */ - R[2] = R[2] & STR_LNMASK; /* mask lengths */ - if (R[4] > 0) R[4] = R[4] & STR_LNMASK; } -else { R[1] = opnd[1]; /* src addr */ - if (movc5) { /* MOVC5? */ - R[2] = (opnd[0] < opnd[3])? opnd[0]: opnd[3]; - R[3] = opnd[4]; /* dst addr */ - R[4] = opnd[3] - opnd[0]; /* dstlen - srclen */ - fill = opnd[2]; /* set fill */ - CC_CMP_W (opnd[0], opnd[3]); } /* set cc's */ - else { - R[2] = opnd[0]; /* mvlen = srclen */ - R[3] = opnd[2]; /* dst addr */ - R[4] = fill = 0; /* no fill */ - cc = CC_Z; } /* set cc's */ - R[0] = STR_PACK (fill, R[2]); /* initial mvlen */ - if (R[2]) { /* any move? */ - if (((uint32) R[1]) < ((uint32) R[3])) { - R[1] = R[1] + R[2]; /* backward, adjust */ - R[3] = R[3] + R[2]; /* addr to end */ - R[5] = MVC_BACK; } /* set state */ - else R[5] = MVC_FRWD; } /* fwd, set state */ - else R[5] = MVC_FILL; /* fill, set state */ - R[5] = R[5] | (cc << MVC_V_CC); /* pack with state */ - PSL = PSL | PSL_FPD; } /* set FPD */ - -/* At this point, - - R0 = delta PC'fill'initial move length - R1 = current src addr - R2 = current move length - R3 = current dst addr - R4 = dst length - src length - R5 = cc'state -*/ - -switch (R[5] & MVC_M_STATE) { /* case on state */ -case MVC_FRWD: /* move forward */ - mlnt[0] = (4 - R[3]) & 3; /* length to align */ - if (mlnt[0] > R[2]) mlnt[0] = R[2]; /* cant exceed total */ - mlnt[1] = (R[2] - mlnt[0]) & ~03; /* aligned length */ - mlnt[2] = R[2] - mlnt[0] - mlnt[1]; /* tail */ - for (i = 0; i < 3; i++) { /* head, align, tail */ - lnt = looplnt[i]; /* length for loop */ - for (j = 0; j < mlnt[i]; j = j + lnt, sim_interval--) { -/* if (sim_interval == 0) ABORT (ABORT_INTR); */ - wd = Read (R[1], lnt, RA); /* read src */ - Write (R[3], wd, lnt, WA); /* write dst */ - R[1] = R[1] + lnt; /* inc src addr */ - R[3] = R[3] + lnt; /* inc dst addr */ - R[2] = R[2] - lnt; } } /* dec move lnt */ - goto FILL; /* check for fill */ -case MVC_BACK: /* move backward */ - mlnt[0] = R[3] & 03; /* length to align */ - if (mlnt[0] > R[2]) mlnt[0] = R[2]; /* cant exceed total */ - mlnt[1] = (R[2] - mlnt[0]) & ~03; /* aligned length */ - mlnt[2] = R[2] - mlnt[0] - mlnt[1]; /* tail */ - for (i = 0; i < 3; i++) { /* head, align, tail */ - lnt = looplnt[i]; /* length for loop */ - for (j = 0; j < mlnt[i]; j = j + lnt, sim_interval--) { -/* if (sim_interval == 0) ABORT (ABORT_INTR); */ - wd = Read (R[1] - lnt, lnt, RA); /* read src */ - Write (R[3] - lnt, wd, lnt, WA); /* write dst */ - R[1] = R[1] - lnt; /* dec src addr */ - R[3] = R[3] - lnt; /* dec dst addr */ - R[2] = R[2] - lnt; } } /* dec move lnt */ - R[1] = R[1] + (R[0] & STR_LNMASK); /* final src addr */ - R[3] = R[3] + (R[0] & STR_LNMASK); /* final dst addr */ -case MVC_FILL: /* fill */ -FILL: - if (R[4] <= 0) break; /* any fill? */ - R[5] = R[5] | MVC_FILL; /* set state */ - mlnt[0] = (4 - R[3]) & 3; /* length to align */ - if (mlnt[0] > R[4]) mlnt[0] = R[4]; /* cant exceed total */ - mlnt[1] = (R[4] - mlnt[0]) & ~03; /* aligned length */ - mlnt[2] = R[4] - mlnt[0] - mlnt[1]; /* tail */ - for (i = 0; i < 3; i++) { /* head, align, tail */ - lnt = looplnt[i]; /* length for loop */ - fill = fill & BMASK; /* fill for loop */ - if (lnt == L_LONG) fill = - (((uint32) fill) << 24) | (fill << 16) | (fill << 8) | fill; - for (j = 0; j < mlnt[i]; j = j + lnt, sim_interval--) { -/* if (sim_interval == 0) ABORT (ABORT_INTR); */ - Write (R[3], fill, lnt, WA); /* write fill */ - R[3] = R[3] + lnt; /* inc dst addr */ - R[4] = R[4] - lnt; } } /* dec fill lnt */ - break; -default: /* bad state */ - RSVD_OPND_FAULT; } /* you lose */ -PSL = PSL & ~PSL_FPD; /* clear FPD */ -cc = (R[5] >> MVC_V_CC) & CC_MASK; /* get cc's */ -R[0] = NEG (R[4]); /* set R0 */ -R[2] = R[4] = R[5] = 0; /* clear reg */ -return cc; -} - -/* CMPC3, CMPC5 - - if PSL = 0 and CMPC3, - opnd[0] = length - opnd[1] = source1 address - opnd[2] = source2 address - - if PSL = 0 and CMPC5, - opnd[0] = source1 length - opnd[1] = source1 address - opnd[2] = fill - opnd[3] = source2 length - opnd[4] = source2 address - - if PSL = 1, - R0 = delta-PC/fill/source1 length - R1 = source1 address - R2 = source2 length - R3 = source2 address -*/ - -int32 op_cmpc (int32 *opnd, int32 cmpc5, int32 acc) -{ -int32 cc, s1, s2, fill; - -if (PSL & PSL_FPD) { /* FPD set? */ - SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */ - fill = STR_GETCHR (R[0]); } /* get fill */ -else { R[1] = opnd[1]; /* src1len */ - if (cmpc5) { /* CMPC5? */ - R[2] = opnd[3]; /* get src2 opnds */ - R[3] = opnd[4]; - fill = opnd[2]; } - else { - R[2] = opnd[0]; /* src2len = src1len */ - R[3] = opnd[2]; - fill = 0; } - R[0] = STR_PACK (fill, opnd[0]); /* src1len + FPD data */ - PSL = PSL | PSL_FPD; } -R[2] = R[2] & STR_LNMASK; /* mask src2len */ -for (s1 = s2 = 0; ((R[0] | R[2]) & STR_LNMASK) != 0; sim_interval--) { -/* if (sim_interval == 0) ABORT (ABORT_INTR); /* timer event */ - if (R[0] & STR_LNMASK) s1 = Read (R[1], L_BYTE, RA); /* src1? read */ - else s1 = fill; /* no, use fill */ - if (R[2]) s2 = Read (R[3], L_BYTE, RA); /* src2? read */ - else s2 = fill; /* no, use fill */ - if (s1 != s2) break; /* src1 = src2? */ - if (R[0] & STR_LNMASK) { /* if src1, decr */ - R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - 1) & STR_LNMASK); - R[1] = R[1] + 1; } - if (R[2]) { /* if src2, decr */ - R[2] = (R[2] - 1) & STR_LNMASK; - R[3] = R[3] + 1; } } -PSL = PSL & ~PSL_FPD; /* clear FPD */ -CC_CMP_B (s1, s2); /* set cc's */ -R[0] = R[0] & STR_LNMASK; /* clear packup */ -return cc; -} - -/* LOCC, SKPC - - if PSL = 0, - opnd[0] = match character - opnd[1] = source length - opnd[2] = source address - - if PSL = 1, - R0 = delta-PC/match/source length - R1 = source address -*/ - -int32 op_locskp (int32 *opnd, int32 skpc, int32 acc) -{ -int32 c, match; - -if (PSL & PSL_FPD) { /* FPD set? */ - SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */ - match = STR_GETCHR (R[0]); } /* get match char */ -else { match = opnd[0]; /* get operands */ - R[0] = STR_PACK (match, opnd[1]); /* src len + FPD data */ - R[1] = opnd[2]; /* src addr */ - PSL = PSL | PSL_FPD; } -for ( ; (R[0] & STR_LNMASK) != 0; sim_interval-- ) { /* loop thru string */ -/* if (sim_interval == 0) ABORT (ABORT_INTR); /* timer event? */ - c = Read (R[1], L_BYTE, RA); /* get src byte */ - if ((c == match) ^ skpc) break; /* match & locc? */ - R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - 1) & STR_LNMASK); - R[1] = R[1] + 1; } /* incr src1adr */ -PSL = PSL & ~PSL_FPD; /* clear FPD */ -R[0] = R[0] & STR_LNMASK; /* clear packup */ -return (R[0]? 0: CC_Z); /* set cc's */ -} - -/* SCANC, SPANC - - if PSL = 0, - opnd[0] = source length - opnd[1] = source address - opnd[2] = table address - opnd[3] = mask - - if PSL = 1, - R0 = delta-PC/char/source length - R1 = source address - R3 = table address -*/ - -int32 op_scnspn (int32 *opnd, int32 spanc, int32 acc) -{ -int32 c, t, mask; - -if (PSL & PSL_FPD) { /* FPD set? */ - SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */ - mask = STR_GETCHR (R[0]); } /* get mask */ -else { R[1] = opnd[1]; /* src addr */ - R[3] = opnd[2]; /* tblad */ - mask = opnd[3]; /* mask */ - R[0] = STR_PACK (mask, opnd[0]); /* srclen + FPD data */ - PSL = PSL | PSL_FPD; } -for ( ; (R[0] & STR_LNMASK) != 0; sim_interval-- ) { /* loop thru string */ -/* if (sim_interval == 0) ABORT (ABORT_INTR); /* timer event? */ - c = Read (R[1], L_BYTE, RA); /* get byte */ - t = Read (R[3] + c, L_BYTE, RA); /* get table ent */ - if (((t & mask) != 0) ^ spanc) break; /* test vs instr */ - R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - 1) & STR_LNMASK); - R[1] = R[1] + 1; } -PSL = PSL & ~PSL_FPD; -R[0] = R[0] & STR_LNMASK; /* clear packup */ -R[2] = 0; -return (R[0]? 0: CC_Z); -} - -/* Operating system interfaces */ - -/* Interrupt or exception - - vec = SCB vector - cc = condition codes - ipl = new IPL if interrupt - ei = -1: severe exception - 0: normal exception - 1: interrupt -*/ - -int32 intexc (int32 vec, int32 cc, int32 ipl, int ei) -{ -int32 oldpsl = PSL | cc; -int32 oldcur = PSL_GETCUR (oldpsl); -int32 oldsp = SP; -int32 newpsl; -int32 newpc; -int32 acc; - -in_ie = 1; /* flag int/exc */ -CLR_TRAPS; /* clear traps */ -newpc = ReadLP ((SCBB + vec) & PAMASK); /* read new PC */ -if (ei < 0) newpc = newpc | 1; /* severe? on istk */ -if (newpc & 2) ABORT (STOP_ILLVEC); /* bad flags? */ -if (oldpsl & PSL_IS) newpsl = PSL_IS; /* on int stk? */ -else { STK[oldcur] = SP; /* no, save cur stk */ - if (newpc & 1) { /* to int stk? */ - newpsl = PSL_IS; /* flag */ - SP = IS; } /* new stack */ - else { - newpsl = 0; /* to ker stk */ - SP = KSP; } } /* new stack */ -if (ei > 0) PSL = newpsl | (ipl << PSL_V_IPL); /* if int, new IPL */ -else PSL = newpsl | ((newpc & 1)? PSL_IPL1F: (oldpsl & PSL_IPL)) | - (oldcur << PSL_V_PRV); -if (DBG_LOG (LOG_CPU_I)) fprintf (sim_log, - ">>IEX: PC=%08x, PSL=%08x, SP=%08x, VEC=%08x, nPSL=%08x, nSP=%08x\n", - PC, oldpsl, oldsp, vec, PSL, SP); -acc = ACC_MASK (KERN); /* new mode is kernel */ -Write (SP - 4, oldpsl, L_LONG, WA); /* push old PSL */ -Write (SP - 8, PC, L_LONG, WA); /* push old PC */ -SP = SP - 8; /* update stk ptr */ -JUMP (newpc & ~3); /* change PC */ -in_ie = 0; /* out of flows */ -return 0; -} - -/* CHMK, CHME, CHMS, CHMU - - opnd[0] = operand -*/ - -int32 op_chm (int32 *opnd, int32 cc, int32 opc) -{ -int32 mode = opc & PSL_M_MODE; -int32 cur = PSL_GETCUR (PSL); -int32 tsp, newpc, acc, sta; - -if (PSL & PSL_IS) ABORT (STOP_CHMFI); -newpc = ReadLP ((SCBB + SCB_CHMK + (mode << 2)) & PAMASK); -if (cur < mode) mode = cur; /* only inward */ -STK[cur] = SP; /* save stack */ -tsp = STK[mode]; /* get new stk */ -acc = ACC_MASK (mode); /* set new mode */ -if (Test (p2 = tsp - 1, WA, &sta) < 0) { /* probe stk */ - p1 = MM_WRITE | (sta & MM_EMASK); - ABORT ((sta & 4)? ABORT_TNV: ABORT_ACV); } -if (Test (p2 = tsp - 12, WA, &sta) < 0) { - p1 = MM_WRITE | (sta & MM_EMASK); - ABORT ((sta & 4)? ABORT_TNV: ABORT_ACV); } -Write (tsp - 12, SXTW (opnd[0]), L_LONG, WA); /* push argument */ -Write (tsp - 8, PC, L_LONG, WA); /* push PC */ -Write (tsp - 4, PSL | cc, L_LONG, WA); /* push PSL */ -SP = tsp - 12; /* set new stk */ -PSL = (mode << PSL_V_CUR) | (PSL & PSL_IPL) | /* set new PSL */ - (cur << PSL_V_PRV); -last_chm = fault_PC; -JUMP (newpc & ~03); /* set new PC */ -return 0; /* cc = 0 */ -} - -/* REI - return from exception or interrupt - -The lengthiest part of the REI instruction is the validity checking of the PSL -popped off the stack. The new PSL is checked against the following eight rules: - -let tmp = new PSL popped off the stack -let PSL = current PSL - -Rule SRM formulation Comment ----- --------------- ------- - 1 tmp<25:24> GEQ PSL<25:24> tmp GEQ PSL - 2 tmp<26> LEQ PSL<26> tmp LEQ tmp - 3 tmp<26> = 1 => tmp<25:24> = 0 tmp = 1 => tmp = ker - 4 tmp<26> = 1 => tmp<20:16> > 0 tmp = 1 => tmp > 0 - 5 tmp<20:16> > 0 => tmp<25:24> = 0 tmp > 0 => tmp = ker - 6 tmp<25:24> LEQ tmp<23:22> tmp LEQ tmp - 7 tmp<20:16> LEQ PSL<20:16> tmp LEQ PSL - 8 tmp<31,29:28,21,15:8> = 0 tmp = 0 -*/ - -int32 op_rei (int32 acc) -{ -int32 newpc = Read (SP, L_LONG, RA); -int32 newpsl = Read (SP + 4, L_LONG, RA); -int32 newcur = PSL_GETCUR (newpsl); -int32 oldcur = PSL_GETCUR (PSL); -int32 newipl; - -if ((newpsl & PSL_MBZ) || /* rule 8 */ - (newcur < oldcur)) RSVD_OPND_FAULT; /* rule 1 */ -if (newcur) { /* to esu, skip 2,4,7 */ - if ((newpsl & (PSL_IS | PSL_IPL)) || /* rules 3,5 */ - (newcur > PSL_GETPRV (newpsl))) /* rule 6 */ - RSVD_OPND_FAULT; } /* end rei to esu */ -else { /* to k, skip 3,5,6 */ - newipl = PSL_GETIPL (newpsl); /* get new ipl */ - if ((newpsl & PSL_IS) && /* setting IS? */ - (((PSL & PSL_IS) == 0) || (newipl == 0))) /* test rules 2,4 */ - RSVD_OPND_FAULT; /* else skip 2,4 */ - if (newipl > PSL_GETIPL (PSL)) RSVD_OPND_FAULT; /* test rule 7 */ - } /* end if kernel */ -SP = SP + 8; /* pop stack */ -if (PSL & PSL_IS) IS = SP; /* save stack */ -else STK[oldcur] = SP; -if (DBG_LOG (LOG_CPU_R)) fprintf (sim_log, - ">>REI: PC=%08x, PSL=%08x, SP=%08x, nPC=%08x, nPSL=%08x, nSP=%08x\n", - PC, PSL, SP - 8, newpc, newpsl, ((newpsl & IS)? IS: STK[newcur])); -PSL = (PSL & PSL_TP) | (newpsl & ~CC_MASK); /* set new PSL */ -if (PSL & PSL_IS) SP = IS; /* set new stack */ -else { SP = STK[newcur]; /* if ~IS, chk AST */ - if (newcur >= ASTLVL) { - if (DBG_LOG (LOG_CPU_R)) fprintf (sim_log, - ">>REI: AST delivered\n"); - SISR = SISR | SISR_2; } } -JUMP (newpc); /* set new PC */ -return newpsl & CC_MASK; /* set new cc */ -} - -/* LDCPTX - load process context */ - -void op_ldpctx (int32 acc) -{ -int32 newpc, newpsl, pcbpa; - -if (PSL & PSL_CUR) RSVD_INST_FAULT; /* must be kernel */ -pcbpa = PCBB & PAMASK; /* phys address */ -KSP = ReadLP (pcbpa); /* restore stk ptrs */ -ESP = ReadLP (pcbpa + 4); -SSP = ReadLP (pcbpa + 8); -USP = ReadLP (pcbpa + 12); -R[0] = ReadLP (pcbpa + 16); /* restore registers */ -R[1] = ReadLP (pcbpa + 20); -R[2] = ReadLP (pcbpa + 24); -R[3] = ReadLP (pcbpa + 28); -R[4] = ReadLP (pcbpa + 32); -R[5] = ReadLP (pcbpa + 36); -R[6] = ReadLP (pcbpa + 40); -R[7] = ReadLP (pcbpa + 44); -R[8] = ReadLP (pcbpa + 48); -R[9] = ReadLP (pcbpa + 52); -R[10] = ReadLP (pcbpa + 56); -R[11] = ReadLP (pcbpa + 60); -R[12] = ReadLP (pcbpa + 64); -R[13] = ReadLP (pcbpa + 68); -newpc = ReadLP (pcbpa + 72); /* get PC, PSL */ -newpsl = ReadLP (pcbpa + 76); -P0BR = ReadLP (pcbpa + 80); /* restore mem mgt */ -P0LR = ReadLP (pcbpa + 84); -P1BR = ReadLP (pcbpa + 88); -P1LR = ReadLP (pcbpa + 92); -ASTLVL = (P0LR >> 24) & AST_MASK; /* restore AST */ -P0BR = P0BR & BR_MASK; -P0LR = P0LR & LR_MASK; -P1BR = P1BR & BR_MASK; -P1LR = P1LR & LR_MASK; -zap_tb (0); /* clear process TB */ -set_map_reg (); -if (DBG_LOG (LOG_CPU_P)) fprintf (sim_log, - ">>LDP: PC=%08x, PSL=%08x, SP=%08x, nPC=%08x, nPSL=%08x, nSP=%08x\n", - PC, PSL, SP, newpc, newpsl, KSP); -if (PSL & PSL_IS) IS = SP; /* if istk, */ -PSL = PSL & ~PSL_IS; /* switch to kstk */ -SP = KSP - 8; -Write (SP, newpc, L_LONG, WA); /* push PC, PSL */ -Write (SP + 4, newpsl, L_LONG, WA); -return; -} - -/* SVPCTX - save processor context */ - -void op_svpctx (int32 acc) -{ -int32 savpc, savpsl, pcbpa; - -if (PSL & PSL_CUR) RSVD_INST_FAULT; /* must be kernel */ -savpc = Read (SP, L_LONG, RA); /* pop PC, PSL */ -savpsl = Read (SP + 4, L_LONG, RA); -if (DBG_LOG (LOG_CPU_P)) fprintf (sim_log, - ">>SVP: PC=%08x, PSL=%08x, SP=%08x, oPC=%08x, oPSL=%08x\n", - PC, PSL, SP, savpc, savpsl); -if (PSL & PSL_IS) SP = SP + 8; /* int stack? */ -else { KSP = SP + 8; /* pop kernel stack */ - SP = IS; /* switch to int stk */ - if ((PSL & PSL_IPL) == 0) PSL = PSL | PSL_IPL1; /* make IPL > 0 */ - PSL = PSL | PSL_IS; } /* set PSL */ -pcbpa = PCBB & PAMASK; -WriteLP (pcbpa, KSP); /* save stk ptrs */ -WriteLP (pcbpa + 4, ESP); -WriteLP (pcbpa + 8, SSP); -WriteLP (pcbpa + 12, USP); -WriteLP (pcbpa + 16, R[0]); /* save registers */ -WriteLP (pcbpa + 20, R[1]); -WriteLP (pcbpa + 24, R[2]); -WriteLP (pcbpa + 28, R[3]); -WriteLP (pcbpa + 32, R[4]); -WriteLP (pcbpa + 36, R[5]); -WriteLP (pcbpa + 40, R[6]); -WriteLP (pcbpa + 44, R[7]); -WriteLP (pcbpa + 48, R[8]); -WriteLP (pcbpa + 52, R[9]); -WriteLP (pcbpa + 56, R[10]); -WriteLP (pcbpa + 60, R[11]); -WriteLP (pcbpa + 64, R[12]); -WriteLP (pcbpa + 68, R[13]); -WriteLP (pcbpa + 72, savpc); /* save PC, PSL */ -WriteLP (pcbpa + 76, savpsl); -return; -} - -/* PROBER and PROBEW - - opnd[0] = mode - opnd[1] = length - opnd[2] = base address -*/ - -int32 op_probe (int32 *opnd, int32 rw) -{ -int32 mode = opnd[0] & PSL_M_MODE; /* mask mode */ -int32 length = opnd[1]; -int32 ba = opnd[2]; -int32 prv = PSL_GETPRV (PSL); -int32 acc, sta, sta1; - -if (prv > mode) mode = prv; /* maximize mode */ -acc = ACC_MASK (mode) << (rw? TLB_V_WACC: 0); /* set acc mask */ -Test (ba, acc, &sta); /* probe */ -switch (sta) { /* case on status */ -case PR_PTNV: /* pte TNV */ - p1 = MM_PARAM (rw, PR_PTNV); - p2 = ba; - ABORT (ABORT_TNV); /* force TNV */ -case PR_TNV: case PR_OK: /* TNV or ok */ - break; /* continue */ -default: /* other */ - return CC_Z; } /* lose */ -Test (ba + length - 1, acc, &sta1); /* probe end addr */ -switch (sta1) { /* case on status */ -case PR_PTNV: /* pte TNV */ - p1 = MM_PARAM (rw, PR_PTNV); - p2 = ba + length - 1; - ABORT (ABORT_TNV); /* force TNV */ -case PR_TNV: case PR_OK: /* TNV or ok */ - break; /* win */ -default: /* other */ - return CC_Z; } /* lose */ -return 0; -} - - -/* MTPR - move to processor register - - opnd[0] = data - opnd[1] = register number -*/ - -int32 op_mtpr (int32 *opnd) -{ -int32 val = opnd[0]; -int32 prn = opnd[1]; -int32 cc; - -if (PSL & PSL_CUR) RSVD_INST_FAULT; /* must be kernel */ -if (prn > 63) RSVD_OPND_FAULT; /* reg# > 63? fault */ -CC_IIZZ_L (val); /* set cc's */ -switch (prn) { /* case on reg # */ -case MT_KSP: /* KSP */ - if (PSL & PSL_IS) KSP = val; /* on IS? store KSP */ - else SP = val; /* else store SP */ - break; -case MT_ESP: case MT_SSP: case MT_USP: /* ESP, SSP, USP */ - STK[prn] = val; /* store stack */ - break; -case MT_IS: /* IS */ - if (PSL & PSL_IS) SP = val; /* on IS? store SP */ - else IS = val; /* else store IS */ - break; -case MT_P0BR: /* P0BR */ - P0BR = val & BR_MASK; /* lw aligned */ - zap_tb (0); /* clr proc TLB */ - set_map_reg (); - break; -case MT_P0LR: /* P0LR */ - P0LR = val & LR_MASK; - zap_tb (0); /* clr proc TLB */ - set_map_reg (); - break; -case MT_P1BR: /* P1BR */ - P1BR = val & BR_MASK; /* lw aligned */ - zap_tb (0); /* clr proc TLB */ - set_map_reg (); - break; -case MT_P1LR: /* P1LR */ - P1LR = val & LR_MASK; - zap_tb (0); /* clr proc TLB */ - set_map_reg (); - break; -case MT_SBR: /* SBR */ - SBR = val & BR_MASK; /* lw aligned */ - zap_tb (1); /* clr entire TLB */ - set_map_reg (); - break; -case MT_SLR: /* SLR */ - SLR = val & LR_MASK; - zap_tb (1); /* clr entire TLB */ - set_map_reg (); - break; -case MT_SCBB: /* SCBB */ - SCBB = val & BR_MASK; /* lw aligned */ - break; -case MT_PCBB: /* PCBB */ - PCBB = val & BR_MASK; /* lw aligned */ - break; -case MT_IPL: /* IPL */ - PSL = (PSL & ~PSL_IPL) | ((val & PSL_M_IPL) << PSL_V_IPL); - break; -case MT_ASTLVL: /* ASTLVL */ - if (val > AST_MAX) RSVD_OPND_FAULT; /* > 4? fault */ - ASTLVL = val; - break; -case MT_SIRR: /* SIRR */ - if ((val > 0xF) || (val == 0)) RSVD_OPND_FAULT; - SISR = SISR | (1 << val); /* set bit in SISR */ - break; -case MT_SISR: /* SISR */ - SISR = val & SISR_MASK; - break; -case MT_CADR: /* CADR */ - CADR = (val & CADR_RW) | CADR_MBO; - break; -case MT_MSER: /* MSER */ - MSER = MSER & MSER_HM; - break; -case MT_MAPEN: /* MAPEN */ - mapen = val & 1; -case MT_TBIA: /* TBIA */ - zap_tb (1); /* clr entire TLB */ - break; -case MT_TBIS: /* TBIS */ - zap_tb_ent (val); - break; -case MT_SID: -case MT_CONPC: -case MT_CONPSL: - RSVD_OPND_FAULT; /* read only */ -case MT_TBCHK: /* TBCHK */ - if (chk_tb_ent (val)) cc = cc | CC_V; - break; -default: - WriteIPR (prn, val); /* others */ - break; } -return cc; -} - -int32 op_mfpr (int32 *opnd) -{ -int32 prn = opnd[0]; -int32 val; - -if (PSL & PSL_CUR) RSVD_INST_FAULT; /* must be kernel */ -if (prn > 63) RSVD_OPND_FAULT; /* reg# > 63? fault */ -switch (prn) { /* case on reg# */ -case MT_KSP: /* KSP */ - val = (PSL & PSL_IS)? KSP: SP; /* return KSP or SP */ - break; -case MT_ESP: case MT_SSP: case MT_USP: /* ESP, SSP, USP */ - val = STK[prn]; /* return stk ptr */ - break; -case MT_IS: /* IS */ - val = (PSL & PSL_IS)? SP: IS; /* return SP or IS */ - break; -case MT_P0BR: /* P0BR */ - val = P0BR; - break; -case MT_P0LR: /* P0LR */ - val = P0LR; - break; -case MT_P1BR: /* P1BR */ - val = P1BR; - break; -case MT_P1LR: /* P1LR */ - val = P1LR; - break; -case MT_SBR: /* SBR */ - val = SBR; - break; -case MT_SLR: /* SLR */ - val = SLR; - break; -case MT_SCBB: /* SCBB */ - val = SCBB; - break; -case MT_PCBB: /* PCBB */ - val = PCBB; - break; -case MT_IPL: /* IPL */ - val = PSL_GETIPL (PSL); - break; -case MT_ASTLVL: /* ASTLVL */ - val = ASTLVL; - break; -case MT_SISR: /* SISR */ - val = SISR & SISR_MASK; - break; -case MT_CADR: /* CADR */ - val = CADR & 0xFF; - break; -case MT_MSER: /* MSER */ - val = MSER & 0xFF; - break; -case MT_CONPC: /* console PC */ - val = conpc; - break; -case MT_CONPSL: /* console PSL */ - val = conpsl; - break; -case MT_MAPEN: /* MAPEN */ - val = mapen; - break; -case MT_SID: /* SID */ - val = CVAX_SID | CVAX_UREV; - break; -case MT_SIRR: -case MT_TBIA: -case MT_TBIS: -case MT_TBCHK: - RSVD_OPND_FAULT; /* write only */ -default: /* others */ - val = ReadIPR (prn); /* read from SSC */ - break; } -return val; -} - -/* Emulated instructions - - opnd[0:5] = six operands to be pushed (if PSL = 0) - cc = condition codes - opc = opcode - - If FPD is set, push old PC and PSL on stack, vector thru SCB. - If FPD is clear, push opcode, old PC, operands, new PC, and PSL - on stack, vector thru SCB. - In both cases, the exception occurs in the current mode. -*/ - -int32 op_emulate (int32 *opnd, int32 cc, int32 opc, int32 acc) -{ -int32 vec; - -if (PSL & PSL_FPD) { /* FPD set? */ - Read (SP - 1, L_BYTE, WA); /* wchk stack */ - Write (SP - 8, fault_PC, L_LONG, WA); /* push old PC */ - Write (SP - 4, PSL | cc, L_LONG, WA); /* push PSL */ - SP = SP - 8; /* decr stk ptr */ - vec = ReadLP ((SCBB + SCB_EMULFPD) & PAMASK); } -else { Read (SP - 1, L_BYTE, WA); /* wchk stack */ - Write (SP - 48, opc, L_LONG, WA); /* push opcode */ - Write (SP - 44, fault_PC, L_LONG, WA); /* push old PC */ - Write (SP - 40, opnd[0], L_LONG, WA); /* push operands */ - Write (SP - 36, opnd[1], L_LONG, WA); - Write (SP - 32, opnd[2], L_LONG, WA); - Write (SP - 28, opnd[3], L_LONG, WA); - Write (SP - 24, opnd[4], L_LONG, WA); - Write (SP - 20, opnd[5], L_LONG, WA); - Write (SP - 8, PC, L_LONG, WA); /* push cur PC */ - Write (SP - 4, PSL | cc, L_LONG, WA); /* push PSL */ - SP = SP - 48; /* decr stk ptr */ - vec = ReadLP ((SCBB + SCB_EMULATE) & PAMASK); } -PSL = PSL & ~(PSL_TP | PSL_FPD | PSW_DV | PSW_FU | PSW_IV | PSW_T); -JUMP (vec & ~03); /* set new PC */ -return 0; /* set new cc's */ -} diff --git a/VAX/vax_defs.h b/VAX/vax_defs.h deleted file mode 100644 index 6541c71f..00000000 --- a/VAX/vax_defs.h +++ /dev/null @@ -1,575 +0,0 @@ -/* vax_defs.h: VAX architecture definitions file - - Copyright (c) 1998-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - The author gratefully acknowledges the help of Stephen Shirron, Antonio - Carlini, and Kevin Peterson in providing specifications for the Qbus VAX's - - 19-May-03 RMS Revised for new conditional compilation scheme - 14-Jul-02 RMS Added infinite loop message - 30-Apr-02 RMS Added CLR_TRAPS macro -*/ - -#ifndef _VAX_DEFS_H -#define _VAX_DEFS_H 0 - -#ifndef VM_VAX -#define VM_VAX 0 -#endif - -#include "sim_defs.h" -#include - -/* Stops and aborts */ - -#define STOP_HALT 1 /* halt */ -#define STOP_IBKPT 2 /* breakpoint */ -#define STOP_CHMFI 3 /* chg mode IS */ -#define STOP_ILLVEC 4 /* illegal vector */ -#define STOP_INIE 5 /* exc in intexc */ -#define STOP_PPTE 6 /* proc pte in Px */ -#define STOP_UIPL 7 /* undefined IPL */ -#define STOP_RQ 8 /* fatal RQ err */ -#define STOP_LOOP 9 /* infinite loop */ -#define STOP_SANITY 10 /* sanity timer exp */ -#define STOP_UNKNOWN 11 /* unknown reason */ -#define STOP_UNKABO 12 /* unknown abort */ -#define ABORT_INTR -1 /* interrupt */ -#define ABORT_MCHK (-SCB_MCHK) /* machine check */ -#define ABORT_RESIN (-SCB_RESIN) /* rsvd instruction */ -#define ABORT_RESAD (-SCB_RESAD) /* rsvd addr mode */ -#define ABORT_RESOP (-SCB_RESOP) /* rsvd operand */ -#define ABORT_ARITH (-SCB_ARITH) /* arithmetic trap */ -#define ABORT_ACV (-SCB_ACV) /* access violation */ -#define ABORT_TNV (-SCB_TNV) /* transl not vaid */ -#define ABORT(x) longjmp (save_env, (x)) /* abort */ -#define RSVD_INST_FAULT ABORT (ABORT_RESIN) -#define RSVD_ADDR_FAULT ABORT (ABORT_RESAD) -#define RSVD_OPND_FAULT ABORT (ABORT_RESOP) -#define FLT_OVFL_FAULT p1 = FLT_OVRFLO, ABORT (ABORT_ARITH) -#define FLT_DZRO_FAULT p1 = FLT_DIVZRO, ABORT (ABORT_ARITH) -#define FLT_UNFL_FAULT p1 = FLT_UNDFLO, ABORT (ABORT_ARITH) -#define MACH_CHECK(cd) p1 = (cd), ABORT (ABORT_MCHK) - -/* Address space */ - -#define VAMASK 0xFFFFFFFF /* virt addr mask */ -#define PAWIDTH 30 /* phys addr width */ -#define PASIZE (1 << PAWIDTH) /* phys addr size */ -#define PAMASK (PASIZE - 1) /* phys addr mask */ -#define IOPAGE (1 << (PAWIDTH - 1)) /* start of I/O page */ - -/* Architectural constants */ - -#define BMASK 0x000000FF /* byte */ -#define BSIGN 0x00000080 -#define WMASK 0x0000FFFF /* word */ -#define WSIGN 0x00008000 -#define LMASK 0xFFFFFFFF /* longword */ -#define LSIGN 0x80000000 -#define FPSIGN 0x00008000 /* floating point */ -#define L_BYTE 1 /* bytes per */ -#define L_WORD 2 /* data type */ -#define L_LONG 4 -#define L_QUAD 8 -#define NUM_INST 512 /* one byte+two byte */ -#define MAX_SPEC 6 /* max spec/instr */ - -/* Memory management modes */ - -#define KERN 0 -#define EXEC 1 -#define SUPV 2 -#define USER 3 - -/* Register and stack aliases */ - -#define nAP 12 -#define nFP 13 -#define nSP 14 -#define nPC 15 -#define AP R[nAP] -#define FP R[nFP] -#define SP R[nSP] -#define PC R[nPC] -#define RGMASK 0xF -#define rnplus1 ((rn + 1) & RGMASK) -#define KSP STK[KERN] -#define ESP STK[EXEC] -#define SSP STK[SUPV] -#define USP STK[USER] -#define IS STK[4] - -/* PSL, PSW, and condition codes */ - -#define PSL_V_TP 30 /* trace pending */ -#define PSL_TP (1 << PSL_V_TP) -#define PSL_V_FPD 27 /* first part done */ -#define PSL_FPD (1 << PSL_V_FPD) -#define PSL_V_IS 26 /* interrupt stack */ -#define PSL_IS (1 << PSL_V_IS) -#define PSL_V_CUR 24 /* current mode */ -#define PSL_V_PRV 22 /* previous mode */ -#define PSL_M_MODE 0x3 /* mode mask */ -#define PSL_CUR (PSL_M_MODE << PSL_V_CUR) -#define PSL_PRV (PSL_M_MODE << PSL_V_CUR) -#define PSL_V_IPL 16 /* int priority lvl */ -#define PSL_M_IPL 0x1F -#define PSL_IPL (PSL_M_IPL << PSL_V_IPL) -#define PSL_IPL1 (0x01 << PSL_V_IPL) -#define PSL_IPL1F (0x1F << PSL_V_IPL) -#define PSL_MBZ (0xB0200000 | PSW_MBZ) /* must be zero */ -#define PSW_MBZ 0xFF00 /* must be zero */ -#define PSW_DV 0x80 /* dec ovflo enable */ -#define PSW_FU 0x40 /* flt undflo enable */ -#define PSW_IV 0x20 /* int ovflo enable */ -#define PSW_T 0x10 /* trace enable */ -#define CC_N 0x08 /* negative */ -#define CC_Z 0x04 /* zero */ -#define CC_V 0x02 /* overflow */ -#define CC_C 0x01 /* carry */ -#define CC_MASK (CC_N | CC_Z | CC_V | CC_C) -#define PSL_GETCUR(x) (((x) >> PSL_V_CUR) & PSL_M_MODE) -#define PSL_GETPRV(x) (((x) >> PSL_V_PRV) & PSL_M_MODE) -#define PSL_GETIPL(x) (((x) >> PSL_V_IPL) & PSL_M_IPL) - -/* Software interrupt summary register */ - -#define SISR_MASK 0xFFFE -#define SISR_2 (1 << 2) - -/* AST register */ - -#define AST_MASK 7 -#define AST_MAX 4 - -/* Virtual address */ - -#define VA_N_OFF 9 /* offset size */ -#define VA_PAGSIZE (1u << VA_N_OFF) /* page size */ -#define VA_M_OFF ((1u << VA_N_OFF) - 1) /* offset mask */ -#define VA_V_VPN VA_N_OFF /* vpn start */ -#define VA_N_VPN (31 - VA_N_OFF) /* vpn size */ -#define VA_M_VPN ((1u << VA_N_VPN) - 1) /* vpn mask */ -#define VA_S0 (1u << 31) /* S0 space */ -#define VA_P1 (1u << 30) /* P1 space */ -#define VA_N_TBI 12 /* TB index size */ -#define VA_TBSIZE (1u << VA_N_TBI) /* TB size */ -#define VA_M_TBI ((1u << VA_N_TBI) - 1) /* TB index mask */ -#define VA_GETOFF(x) ((x) & VA_M_OFF) -#define VA_GETVPN(x) (((x) >> VA_V_VPN) & VA_M_VPN) -#define VA_GETTBI(x) ((x) & VA_M_TBI) - -/* PTE */ - -#define PTE_V_V 31 /* valid */ -#define PTE_V (1u << PTE_V_V) -#define PTE_V_ACC 27 /* access */ -#define PTE_M_ACC 0xF -#define PTE_V_M 26 /* modified */ -#define PTE_M (1u << PTE_V_M) -#define PTE_GETACC(x) (((x) >> PTE_V_ACC) & PTE_M_ACC) - -/* TLB entry */ - -#define TLB_V_RACC 0 /* rd acc field */ -#define TLB_V_WACC 4 /* wr acc field */ -#define TLB_M_ACC 0xF -#define TLB_RACC (TLB_M_ACC << TLB_V_RACC) -#define TLB_WACC (TLB_M_ACC << TLB_V_WACC) -#define TLB_V_M 8 /* m bit */ -#define TLB_M (1u << TLB_V_M) -#define TLB_N_PFN (PAWIDTH - VA_N_OFF) /* ppfn size */ -#define TLB_M_PFN ((1u << TLB_N_PFN) - 1) /* ppfn mask */ -#define TLB_PFN (TLB_M_PFN << VA_V_VPN) - -/* Traps and interrupt requests */ - -#define TIR_V_IRQL 0 /* int request lvl */ -#define TIR_V_TRAP 5 /* trap requests */ -#define TIR_M_TRAP 07 -#define TIR_TRAP (TIR_M_TRAP << TIR_V_TRAP) -#define TRAP_INTOV (1 << TIR_V_TRAP) /* integer overflow */ -#define TRAP_DIVZRO (2 << TIR_V_TRAP) /* divide by zero */ -#define TRAP_SUBSCR (7 << TIR_V_TRAP) /* subscript range */ -#define SET_TRAP(x) trpirq = (trpirq & PSL_M_IPL) | (x) -#define CLR_TRAPS trpirq = trpirq & ~TIR_TRAP -#define SET_IRQL trpirq = (trpirq & TIR_TRAP) | eval_int () -#define GET_TRAP(x) (((x) >> TIR_V_TRAP) & TIR_M_TRAP) -#define GET_IRQL(x) (((x) >> TIR_V_IRQL) & PSL_M_IPL) - -/* Floating point fault parameters */ - -#define FLT_OVRFLO 0x8 /* flt overflow */ -#define FLT_DIVZRO 0x9 /* flt div by zero */ -#define FLT_UNDFLO 0xA /* flt underflow */ - -/* SCB offsets */ - -#define SCB_MCHK 0x04 /* machine chk */ -#define SCB_KSNV 0x08 /* ker stk invalid */ -#define SCB_PWRFL 0x0C /* power fail */ -#define SCB_RESIN 0x10 /* rsvd/priv instr */ -#define SCB_XFC 0x14 /* XFC instr */ -#define SCB_RESOP 0x18 /* rsvd operand */ -#define SCB_RESAD 0x1C /* rsvd addr mode */ -#define SCB_ACV 0x20 /* ACV */ -#define SCB_TNV 0x24 /* TNV */ -#define SCB_TP 0x28 /* trace pending */ -#define SCB_BPT 0x2C /* BPT instr */ -#define SCB_ARITH 0x34 /* arith fault */ -#define SCB_CHMK 0x40 /* CHMK */ -#define SCB_CHME 0x44 /* CHME */ -#define SCB_CHMS 0x48 /* CHMS */ -#define SCB_CHMU 0x4C /* CHMU */ -#define SCB_CRDERR 0x54 /* CRD err intr */ -#define SCB_MEMERR 0x60 /* mem err intr */ -#define SCB_IPLSOFT 0x80 /* software intr */ -#define SCB_INTTIM 0xC0 /* timer intr */ -#define SCB_EMULATE 0xC8 /* emulation */ -#define SCB_EMULFPD 0xCC /* emulation, FPD */ -#define SCB_CSI 0xF0 /* constor input */ -#define SCB_CSO 0xF4 /* constor output */ -#define SCB_TTI 0xF8 /* console input */ -#define SCB_TTO 0xFC /* console output */ -#define SCB_INTR 0x100 /* hardware intr */ - -#define IPL_HLTPIN 0x1F /* halt pin IPL */ -#define IPL_MEMERR 0x1D /* mem err IPL */ -#define IPL_CRDERR 0x1A /* CRD err IPL */ - -/* Interrupt and exception types */ - -#define IE_SVE -1 /* severe exception */ -#define IE_EXC 0 /* normal exception */ -#define IE_INT 1 /* interrupt */ - -/* Decode ROM: opcode entry */ - -#define DR_F 0x80 /* FPD ok flag */ -#define DR_NSPMASK 0x07 /* #specifiers */ -#define DR_USPMASK 0x70 /* #spec, sym_ */ - -/* Decode ROM: specifier entry */ - -#define DR_ACMASK 0xC /* type */ -#define DR_LNMASK 0x3 /* length mask */ -#define DR_LNT(x) (1 << (x & DR_LNMASK)) /* disp to lnt */ - -/* Decode ROM: operand type */ - -#define SH0 0x00 /* short literal */ -#define SH1 0x10 -#define SH2 0x20 -#define SH3 0x30 -#define IDX 0x40 /* indexed */ -#define GRN 0x50 /* register */ -#define RGD 0x60 /* register def */ -#define ADC 0x70 /* autodecrement */ -#define AIN 0x80 /* autoincrement */ -#define AID 0x90 /* autoinc def */ -#define BDP 0xA0 /* byte disp */ -#define BDD 0xB0 /* byte disp def */ -#define WDP 0xC0 /* word disp */ -#define WDD 0xD0 /* word disp def */ -#define LDP 0xE0 /* long disp */ -#define LDD 0xF0 /* long disp def */ - -/* Decode ROM: access type and length */ - -#define RB 0x0 /* .rb */ -#define RW 0x1 /* .rw */ -#define RL 0x2 /* .rl */ -#define RQ 0x3 /* .rq */ -#define MB 0x4 /* .mb */ -#define MW 0x5 /* .mw */ -#define ML 0x6 /* .ml */ -#define MQ 0x7 /* .mq */ -#define AB 0x8 /* .ab */ -#define AW 0x9 /* .aw */ -#define AL 0xA /* .al */ -#define AQ 0xB /* .aq */ -#define WB 0xC /* .wb */ -#define WW 0xD /* .ww */ -#define WL 0xE /* .wl */ -#define WQ 0xF /* .wq */ - -/* Special dispatches. - - vb = variable bit field, treated as wb except for register - rf = f_floating, treated as rl except for short literal - rd = d_floating, treated as rl except for short literal - rg = g_floating, treated as rl except for short literal - bw = branch byte displacement - bw = branch word displacement - - The 'underlying' access type and length must be correct for - indexing, which only looks at the low order 4b. rg works because - rq and mq are treated identically. -*/ - -#define VB (0x100|WB) /* .vb */ -#define RF (0x100|RL) /* .rf */ -#define RD (0x100|RQ) /* .rd */ -#define RG (0x100|MQ) /* .rg */ -#define BB (0x1F0|WB) /* byte branch */ -#define BW (0x1F0|WW) /* word branch */ -#define OC (0x1F0|WQ) /* octa, sym_ */ - -/* Probe results and memory management fault codes */ - -#define PR_ACV 0 /* ACV */ -#define PR_LNV 1 /* length viol */ -/* #define PR_PACV 2 /* impossible */ -#define PR_PLNV 3 /* pte len viol */ -#define PR_TNV 4 /* TNV */ -/* #define PR_TB 5 /* impossible */ -#define PR_PTNV 6 /* pte TNV */ -#define PR_OK 7 /* ok */ -#define MM_PARAM(w,p) (((w)? 4: 0) | ((p) & 3)) /* fault param */ - -/* Memory management errors */ - -#define MM_WRITE 4 /* write */ -#define MM_EMASK 3 /* against probe */ - -/* Privileged registers */ - -#define MT_KSP 0 -#define MT_ESP 1 -#define MT_SSP 2 -#define MT_USP 3 -#define MT_IS 4 -#define MT_P0BR 8 -#define MT_P0LR 9 -#define MT_P1BR 10 -#define MT_P1LR 11 -#define MT_SBR 12 -#define MT_SLR 13 -#define MT_PCBB 16 -#define MT_SCBB 17 -#define MT_IPL 18 -#define MT_ASTLVL 19 -#define MT_SIRR 20 -#define MT_SISR 21 -#define MT_ICCS 24 -#define MT_TODR 27 -#define MT_CSRS 28 -#define MT_CSRD 29 -#define MT_CSTS 30 -#define MT_CSTD 31 -#define MT_RXCS 32 -#define MT_RXDB 33 -#define MT_TXCS 34 -#define MT_TXDB 35 -#define MT_CADR 37 -#define MT_MSER 39 -#define MT_CONPC 42 -#define MT_CONPSL 43 -#define MT_IORESET 55 -#define MT_MAPEN 56 -#define MT_TBIA 57 -#define MT_TBIS 58 -#define MT_SID 62 -#define MT_TBCHK 63 - -#define BR_MASK 0xFFFFFFFC -#define LR_MASK 0x003FFFFF - -/* Opcodes */ - -enum opcodes { - HALT, NOP, REI, BPT, RET, RSB, LDPCTX, SVPCTX, - CVTPS, CVTSP, INDEX, CRC, PROBER, PROBEW, INSQUE, REMQUE, - BSBB, BRB, BNEQ, BEQL, BGTR, BLEQ, JSB, JMP, - BGEQ, BLSS, BGTRU, BLEQU, BVC, BVS, BGEQU, BLSSU, - ADDP4, ADDP6, SUBP4, SUBP6, CVTPT, MULP, CVTTP, DIVP, - MOVC3, CMPC3, SCANC, SPANC, MOVC5, CMPC5, MOVTC, MOVTUC, - BSBW, BRW, CVTWL, CVTWB, MOVP, CMPP3, CVTPL, CMPP4, - EDITPC, MATCHC, LOCC, SKPC, MOVZWL, ACBW, MOVAW, PUSHAW, - ADDF2, ADDF3, SUBF2, SUBF3, MULF2, MULF3, DIVF2, DIVF3, - CVTFB, CVTFW, CVTFL, CVTRFL, CVTBF, CVTWF, CVTLF, ACBF, - MOVF, CMPF, MNEGF, TSTF, EMODF, POLYF, CVTFD, - ADAWI = 0x58, INSQHI = 0x5C, INSQTI, REMQHI, REMQTI, - ADDD2, ADDD3, SUBD2, SUBD3, MULD2, MULD3, DIVD2, DIVD3, - CVTDB, CVTDW, CVTDL, CVTRDL, CVTBD, CVTWD, CVTLD, ACBD, - MOVD, CMPD, MNEGD, TSTD, EMODD, POLYD, CVTDF, - ASHL = 0x78, ASHQ, EMUL, EDIV, CLRQ, MOVQ, MOVAQ, PUSHAQ, - ADDB2, ADDB3, SUBB2, SUBB3, MULB2, MULB3, DIVB2, DIVB3, - BISB2, BISB3, BICB2, BICB3, XORB2, XORB3, MNEGB, CASEB, - MOVB, CMPB, MCOMB, BITB, CLRB, TSTB, INCB, DECB, - CVTBL, CVTBW, MOVZBL, MOVZBW, ROTL, ACBB, MOVAB, PUSHAB, - ADDW2, ADDW3, SUBW2, SUBW3, MULW2, MULW3, DIVW2, DIVW3, - BISW2, BISW3, BICW2, BICW3, XORW2, XORW3, MNEGW, CASEW, - MOVW, CMPW, MCOMW, BITW, CLRW, TSTW, INCW, DECW, - BISPSW, BICPSW, POPR, PUSHR, CHMK, CHME, CHMS, CHMU, - ADDL2, ADDL3, SUBL2, SUBL3, MULL2, MULL3, DIVL2, DIVL3, - BISL2, BISL3, BICL2, BICL3, XORL2, XORL3, MNEGL, CASEL, - MOVL, CMPL, MCOML, BITL, CLRL, TSTL, INCL, DECL, - ADWC, SBWC, MTPR, MFPR, MOVPSL, PUSHL, MOVAL, PUSHAL, - BBS, BBC, BBSS, BBCS, BBSC, BBCC, BBSSI, BBCCI, - BLBS, BLBC, FFS, FFC, CMPV, CMPZV, EXTV, EXTZV, - INSV, ACBL, AOBLSS, AOBLEQ, SOBGEQ, SOBGTR, CVTLB, CVTLW, - ASHP, CVTLP, CALLG, CALLS, XFC, CVTGF = 0x133, - ADDG2= 0x140, ADDG3, SUBG2, SUBG3, MULG2, MULG3, DIVG2, DIVG3, - CVTGB, CVTGW, CVTGL, CVTRGL, CVTBG, CVTWG, CVTLG, ACBG, - MOVG, CMPG, MNEGG, TSTG, EMODG, POLYG, CVTFG = 0x199 }; - -/* Repeated operations */ - -#define SXTB(x) (((x) & BSIGN)? ((x) | ~BMASK): ((x) & BMASK)) -#define SXTW(x) (((x) & WSIGN)? ((x) | ~WMASK): ((x) & WMASK)) -#define SXTBW(x) (((x) & BSIGN)? ((x) | (WMASK - BMASK)): ((x) & BMASK)) -#define SXTL(x) (((x) & LSIGN)? ((x) | ~LMASK): ((x) & LMASK)) -#define INTOV if (PSL & PSW_IV) SET_TRAP (TRAP_INTOV) -#define V_INTOV cc = cc | CC_V; INTOV -#define NEG(x) ((~(x) + 1) & LMASK) - -/* Istream access */ - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = fault_PC -#define GET_ISTR(d,l) d = get_istr (l, acc) -#define BRANCHB(d) PCQ_ENTRY, PC = PC + SXTB (d), FLUSH_ISTR -#define BRANCHW(d) PCQ_ENTRY, PC = PC + SXTW (d), FLUSH_ISTR -#define JUMP(d) PCQ_ENTRY, PC = (d), FLUSH_ISTR -#define SETPC(d) PC = (d), FLUSH_ISTR -#define FLUSH_ISTR ibcnt = 0, ppc = -1 - -/* Read and write */ - -#define RA (acc) -#define WA ((acc) << TLB_V_WACC) -#define ACC_MASK(x) (1 << (x)) -#define TLB_ACCR(x) (ACC_MASK (x) << TLB_V_RACC) -#define TLB_ACCW(x) (ACC_MASK (x) << TLB_V_WACC) -#define REF_V 0 -#define REF_P 1 - -/* Condition code macros */ - -#define CC_ZZ1P cc = CC_Z | (cc & CC_C) - -#define CC_IIZZ_B(r) \ - if ((r) & BSIGN) cc = CC_N; \ - else if ((r) == 0) cc = CC_Z; \ - else cc = 0 -#define CC_IIZZ_W(r) \ - if ((r) & WSIGN) cc = CC_N; \ - else if ((r) == 0) cc = CC_Z; \ - else cc = 0 -#define CC_IIZZ_L(r) \ - if ((r) & LSIGN) cc = CC_N; \ - else if ((r) == 0) cc = CC_Z; \ - else cc = 0 -#define CC_IIZZ_Q(rl,rh) \ - if ((rh) & LSIGN) cc = CC_N; \ - else if (((rl) | (rh)) == 0) cc = CC_Z; \ - else cc = 0 -#define CC_IIZZ_FP CC_IIZZ_W - -#define CC_IIZP_B(r) \ - if ((r) & BSIGN) cc = CC_N | (cc & CC_C); \ - else if ((r) == 0) cc = CC_Z | (cc & CC_C); \ - else cc = cc & CC_C -#define CC_IIZP_W(r) \ - if ((r) & WSIGN) cc = CC_N | (cc & CC_C); \ - else if ((r) == 0) cc = CC_Z | (cc & CC_C); \ - else cc = cc & CC_C -#define CC_IIZP_L(r) \ - if ((r) & LSIGN) cc = CC_N | (cc & CC_C); \ - else if ((r) == 0) cc = CC_Z | (cc & CC_C); \ - else cc = cc & CC_C -#define CC_IIZP_Q(rl,rh) \ - if ((rh) & LSIGN) cc = CC_N | (cc & CC_C); \ - else if (((rl) | (rh)) == 0) cc = CC_Z | (cc & CC_C); \ - else cc = cc & CC_C -#define CC_IIZP_FP CC_IIZP_W - -#define V_ADD_B(r,s1,s2) \ - if (((~(s1) ^ (s2)) & ((s1) ^ (r))) & BSIGN) { V_INTOV; } -#define V_ADD_W(r,s1,s2) \ - if (((~(s1) ^ (s2)) & ((s1) ^ (r))) & WSIGN) { V_INTOV; } -#define V_ADD_L(r,s1,s2) \ - if (((~(s1) ^ (s2)) & ((s1) ^ (r))) & LSIGN) { V_INTOV; } -#define C_ADD(r,s1,s2) \ - if (((uint32) r) < ((uint32) s2)) cc = cc | CC_C - -#define CC_ADD_B(r,s1,s2) \ - CC_IIZZ_B (r); \ - V_ADD_B (r, s1, s2); \ - C_ADD (r, s1, s2) -#define CC_ADD_W(r,s1,s2) \ - CC_IIZZ_W (r); \ - V_ADD_W (r, s1, s2); \ - C_ADD (r, s1, s2) -#define CC_ADD_L(r,s1,s2) \ - CC_IIZZ_L (r); \ - V_ADD_L (r, s1, s2); \ - C_ADD (r, s1, s2) - -#define V_SUB_B(r,s1,s2) \ - if ((((s1) ^ (s2)) & (~(s1) ^ (r))) & BSIGN) { V_INTOV; } -#define V_SUB_W(r,s1,s2) \ - if ((((s1) ^ (s2)) & (~(s1) ^ (r))) & WSIGN) { V_INTOV; } -#define V_SUB_L(r,s1,s2) \ - if ((((s1) ^ (s2)) & (~(s1) ^ (r))) & LSIGN) { V_INTOV; } -#define C_SUB(r,s1,s2) \ - if (((uint32) s2) < ((uint32) s1)) cc = cc | CC_C - -#define CC_SUB_B(r,s1,s2) \ - CC_IIZZ_B (r); \ - V_SUB_B (r, s1, s2); \ - C_SUB (r, s1, s2) -#define CC_SUB_W(r,s1,s2) \ - CC_IIZZ_W (r); \ - V_SUB_W (r, s1, s2); \ - C_SUB (r, s1, s2) -#define CC_SUB_L(r,s1,s2) \ - CC_IIZZ_L (r); \ - V_SUB_L (r, s1, s2); \ - C_SUB (r, s1, s2) - -#define CC_CMP_B(s1,s2) \ - if (SXTB (s1) < SXTB (s2)) cc = CC_N; \ - else if ((s1) == (s2)) cc = CC_Z; \ - else cc = 0; \ - if (((uint32) s1) < ((uint32) s2)) cc = cc | CC_C -#define CC_CMP_W(s1,s2) \ - if (SXTW (s1) < SXTW (s2)) cc = CC_N; \ - else if ((s1) == (s2)) cc = CC_Z; \ - else cc = 0; \ - if (((uint32) s1) < ((uint32) s2)) cc = cc | CC_C -#define CC_CMP_L(s1,s2) \ - if ((s1) < (s2)) cc = CC_N; \ - else if ((s1) == (s2)) cc = CC_Z; \ - else cc = 0; \ - if (((uint32) s1) < ((uint32) s2)) cc = cc | CC_C - -/* Model dependent definitions */ - -#include "vaxmod_defs.h" - -#endif /* _VAX_DEFS_H */ diff --git a/VAX/vax_doc.txt b/VAX/vax_doc.txt deleted file mode 100644 index a8c12387..00000000 --- a/VAX/vax_doc.txt +++ /dev/null @@ -1,923 +0,0 @@ -To: Users -From: Bob Supnik -Subj: VAX Simulator Usage -Date: 15-Jul-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - Original code published in 1993-2003, written by Robert M Supnik - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - -This memorandum documents the VAX simulator. - - -1. Simulator Files - -To compile the VAX, you must define VM_VAX and USE_INT64 as part of the compilation -command line. To enable extended file support (files greater than 2GB), you must -define USE_ADDR64 as part of the command line as well. - -sim/ sim_defs.h - sim_ether.h - sim_rev.h - sim_sock.h - sim_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_ether.c - sim_sock.c - sim_tape.c - sim_tmxr.c - -sim/vax/ vax_defs.h - vaxmod_defs.h - vax_cpu.c - vax_cpu1.c - vax_fpa.c - vax_io.c - vax_mmu.c - vax_stddev.c - vax_sys.c - vax_sysdev.c - -sim/pdp11/ pdp11_mscp.h - pdp11_uqssp.h - pdp11_xq.h - pdp11_xq_bootrom.h - pdp11_dz.c - pdp11_lp.c - pdp11_pt.c - pdp11_rl.c - pdp11_rq.c - pdp11_tq.c - pdp11_ts.c - pdp11_xp.c - -2. VAX Features - -The VAX simulator is configured as follows: - -device simulates -name(s) - -CPU KA655 CPU with 16MB-64MB of memory -TLB translation buffer -ROM read-only memory -NVR non-volatile memory -SYSD system devices -QBA Qbus adapter -PTR,PTP PCV11 paper tape reader/punch -TTI,TTO console terminal -LPT LPV11 line printer -CLK real-time clock -DZ DZV11 4-line terminal multiplexor (up to 4) -RL RLV12/RL01(2) cartridge disk controller with four drives -RQ RQDX3 MSCP controller with four drives -RQB second RQDX3 MSCP controller with four drives -RQC third RQDX3 MSCP controller with four drives -RQD fourth RQDX3 MSCP controller with four drives -TS TSV11/TSV05 magnetic tape controller with one drive -TQ TQK50 TMSCP magnetic tape controller with four drives -XQ DELQA/DEQNA Ethernet controller -XQB second DELQA/DEQNA Ethernet controller - -The PTR, PTP, LPT, DZ, RL, RQ, RQB, RQC, RQD, TS, TQ, XQ, and XQB devices -can be set DISABLED. RQB, RQC, RQD, and XQB are disabled by default. - -The VAX simulator implements several unique stop conditions: - - - change mode to interrupt stack - - illegal vector (bits<1:0> = 2 or 3) - - unexpected exception during interrupt or exception - - process PTE in P0 or P1 space instead of system space - - unknown IPL - - infinite loop (BRB/W to self at IPL 1F) - -The VAX supports a simple binary format consisting of a stream of -binary bytes without origin or checksum, for loading memory, the boot -ROM, or the non-volatile memory. - -2.1 CPU and System Devices - -2.2 CPU - -CPU options include the size of main memory and the treatment of the -HALT instruction. - - SET CPU 16M set memory size = 16MB - SET CPU 32M set memory size = 32MB - SET CPU 48M set memory size = 48MB - SET CPU 64M set memory size = 64MB - SET CPU SIMHALT kernel HALT returns to simulator - SET CPU CONHALT kernel HALT returns to boot ROM console - -The CPU implements a show command to display the I/O address map: - - SHOW CPU IOSPACE show I/O space address map - -If memory size is being reduced, and the memory being truncated contains -non-zero data, the simulator asks for confirmation. Data in the truncated -portion of memory is lost. Initial memory size is 16MB. If the simulator -is running VMS, the operating system will not recognize memory size changes -until AUTOGEN is run. - -Memory can be loaded with a binary byte stream using the LOAD command. -The LOAD command recognizes one switch: - - -o Origin argument follows file name - -The CPU supports the BOOT command and is the only VAX device to do so. -Note that the behavior of the bootstrap depends on the capabilities of -the console terminator emulator. If the terminal window supports full -VT100 emulation (including Multilanguage Character Set support), the -bootstrap will ask the user to specify the language; otherwise, it will -default to English. - -These switches are recognized when examining or depositing in CPU memory -(or any other byte oriented device): - - -b examine/deposit bytes - -w examine/deposit words - -l examine/deposit longwords - -d data radix is decimal - -o data radix is octal - -h data radix is hexadecimal - -v interpret address as virtual, current mode - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - PC 32 program counter - R0..R14 32 R0..R14 - AP 32 alias for R12 - FP 32 alias for R13 - SP 32 alias for R14 - PSL 32 processor status longword - CC 4 condition codes, PSL<3:0> - KSP 32 kernel stack pointer - ESP 32 executive stack pointer - SSP 32 supervisor stack pointer - USP 32 user stack pointer - IS 32 interrupt stack pointer - SCBB 32 system control block base - PCBB 32 process controll block base - P0BR 32 P0 base register - P0LR 22 P0 length register - P1BR 32 P1 base register - P1LR 22 P1 length register - SBR 32 system base register - SLR 22 system length register - SISR 16 software interrupt summary register - ASTLVL 4 AST level register - CADR 8 cache disable register - MSER 8 memory system error register - MAPEN 1 memory management enable flag - TRPIRQ 8 trap/interrupt pending - CRDERR 1 correctible read data error flag - MEMERR 1 memory error flag - PCQ[0:63] 32 PC prior to last PC change or interrupt; - most recent PC change first - WRU 8 interrupt character - -The CPU can maintain a history of the most recently executed instructions. -This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands: - - SET CPU HISTORY clear history buffer - SET CPU HISTORY=0 disable history - SET CPU HISTORY=n enable history, display length = n - SHOW CPU HISTORY print CPU history - -The maximum length for the history is 4096 entries. - -2.1.2 Translation Buffer (TLB) - -The translation buffer consists of two units, representing the system -and user translation buffers, respectively. It has no registers. Each -translation buffer entry consists of two 32b words, as follows: - - word n tag - word n+1 cached PTE - -An invalid entry is indicated by a tag of FFFFFFFF. - -2.1.3 Read-only memory (ROM) - -The boot ROM consists of a single unit, representing the 128KB boot ROM. -It has no registers. The boot ROM is loaded with a binary byte stream -using the LOAD -r command: - - LOAD -r KA655.BIN load boot ROM image KA655.BIN - -ROM accesses a use a calibrated delay that slows ROM-based execution to -about 500K instructions per second. This delay is required to make the -power-up self-test routines run correctly on very fast hosts. The delay -is controlled with the commands: - - SET ROM NODELAY ROM runs like RAM - SET ROM DELAY ROM runs slowly - -2.1.4 Non-volatile Memory (NVR) - -The NVR consists of a single unit, representing 1KB of battery-backed up -memory. When the simulator starts, NVR is cleared to 0, and the SSC -battery-low indicator is set. Normally, NVR is saved and restored like -other memory in the system. Alternately, NVR can be attached to a file. -This allows its contents to be saved and restored independently of -other memories, so that NVR state can be preserved across simulator runs. - -Successfully loading an NVR image clears the SSC battery-low indicator. - -2.1.5 System Devices (SYSD) - -The system devices are the facilities implemented in KA655 CPU board, -the CMCTL memory controller, and the SSC system support chip. Note that -the simulation of these devices is incomplete and is intended strictly -to allow the patched bootstrap code to run. The SYSD registers are: - - name size comments - - CMCSR[0:17] 32 CMCTL control and status registers - CACR 8 second-level cache control register - BDR 8 front panel jumper register - BASE 29 SSC base address register - CNF 32 SSC configuration register - BTO 32 SSC bus timeout register - TCSR0 32 SSC timer 0 control/status register - TIR0 32 SSC timer 0 interval register - TNIR0 32 SSC timer 0 next interval register - TIVEC0 9 SSC timer 0 interrupt vector register - TCSR1 32 SSC timer 1 control/status register - TIR1 32 SSC timer 1 interval register - TNIR1 32 SSC timer 1 next interval register - TIVEC1 9 SSC timer 1 interrupt vector register - ADSM0 32 SSC address match 0 address - ADSK0 32 SSC address match 0 mask - ADSM1 32 SSC address match 1 address - ADSK1 32 SSC address match 1 mask - CDGDAT[0:16383] 32 cache diagnostic data store - -BDR<7> is the halt-enabled switch. It controls how the console firmware -responds to a BOOT command, a kernel halt (if option CONHALT is set), or -a console halt (BREAK typed on the console terminal). If BDR<7> is set, -the console firmware responds to all these conditions by entering its -interactive command mode. If BDR<7> is clear, the console firmware -boots the operating system in response to these conditions. - -2.1.6 Qbus Adapter (QBA) - -The QBA represents the CQBIC Qbus adapter chip. The QBA registers are: - - name size comments - - SCR 16 system configuration register - DSER 8 DMA system error register - MEAR 13 master error address register - SEAR 20 slave error address register - MBR 29 Qbus map base register - IPC 16 interprocessor communications register - IPL17 32 IPL 17 interrupt flags - IPL16 32 IPL 16 interrupt flags - IPL15 32 IPL 15 interrupt flags - IPL14 32 IPL 14 interrupt flags - -2.2 I/O Device Addressing - -Qbus I/O space is not large enough to allow all possible devices to be -configured simultaneously at fixed addresses. Instead, many devices have -floating addresses; that is, the assigned device address depends on the -presense of other devices in the configuration: - - DZ11 all instances have floating addresses - RL11 first instance has fixed address, rest floating - MSCP disk first instance has fixed address, rest floating - TMSCP tape first instance has fixed address, rest floating - -To maintain addressing consistency as the configuration changes, the -simulator implements DEC's standard I/O address and vector autoconfiguration -algorithms for devices DZ, RL, RQ, and TQ. This allows the user to -enable or disable devices without needing to manage I/O addresses -and vectors. - -In addition to autoconfiguration, most devices support the SET ADDRESS -command, which allows the I/O page address of the device to be changed, -and the SET VECTOR command, which allows the vector of the device to be -changed. Explicitly setting the I/O address of a device which normally -uses autoconfiguration DISABLES autoconfiguration for that device. As -a consequence, the user may have to manually configure all other -autoconfigured devices, because the autoconfiguration algorithm no -longer recognizes the explicitly configured device. A device can be -reset to autoconfigure with the SET AUTOCONFIGURE command. - -The current I/O map can be displayed with the SHOW CPU IOSPACE command. -Addresses that have set by autoconfiguration are marked with an asterisk (*). - -All devices support the SHOW ADDRESS and SHOW VECTOR commands, which display -the device address and vector, respectively. - -2.3 Programmed I/O Devices - -2.3.1 PC11 Paper Tape Reader (PTR) - -The paper tape reader (PTR) reads data from a disk file. The POS -register specifies the number of the next data item to be read. Thus, -by changing POS, the user can backspace or advance the reader. - -The paper tape reader implements these registers: - - name size comments - - BUF 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - BUSY 1 busy flag (CSR<11>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - POS 32 position in the input file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - end of file 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -2.3.2 PC11 Paper Tape Punch (PTP) - -The paper tape punch (PTP) writes data to a disk file. The POS -register specifies the number of the next data item to be written. -Thus, by by changing POS, the user can backspace or advance the punch. - -The paper tape punch implements these registers: - - name size comments - - BUF 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -2.3.3 Terminal Input (TTI) - -The terminal interfaces (TTI, TTO) can be set to one of two modes: -7B or 8B. In 7B mode, input and output characters are masked to 7 -bits. In 8B mode, characters are not modified. Changing the mode -of either interface changes both. The default mode is 8B. - -When the console terminal is attached to a Telnet session, it -recognizes BREAK. If BREAK is entered, and BDR<7> is set, control -returns to the console firmware; otherwise, BREAK is treated as a -normal terminal input condition. - -The terminal input (TTI) polls the console keyboard for input. It -implements these registers: - - name size comments - - BUF 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - POS 32 number of characters input - TIME 24 keyboard polling interval - -If the simulator is compiled under Windows Visual C++, typing ^C to the -terminal input causes a fatal run-time error. Use the following command -to simulate typing ^C: - - SET TTI CTRL-C - -2.3.4 Terminal Output (TTO) - -The terminal output (TTO) writes to the simulator console window. It -implements these registers: - - name size comments - - BUF 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - POS 32 number of characters input - TIME 24 time from I/O initiation to interrupt - -2.3.5 Line Printer (LPT) - -The line printer (LPT) writes data to a disk file. The POS register -specifies the number of the next data item to be written. Thus, -by changing POS, the user can backspace or advance the printer. - -The line printer implements these registers: - - name size comments - - BUF 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of paper - - OS I/O error x report error and stop - -2.3.6 Real-Time Clock (CLK) - -The clock (CLK) implements these registers: - - name size comments - - CSR 16 control/status register - INT 1 interrupt pending flag - IE 1 interrupt enable flag (CSR<6>) - TODR 32 time-of-day register - BLOW 1 TODR battery low indicator - TIME 24 clock frequency - TPS 8 ticks per second (100) - -The real-time clock autocalibrates; the clock interval is adjusted up or -down so that the clock tracks actual elapsed time. - -2.3.7 DZV11 Terminal Multiplexor (DZ) - -The DZV11 is an 4-line terminal multiplexor. Up to 4 DZ11's (16 lines) -are supported. The number of lines can be changed with the command - - SET DZ LINES=n set line count to n - -The line count must be a multiple of 4, with a maximum of 16. - -The DZV11 supports 8-bit input and output of characters. 8-bit output -may be incompatible with certain operating systems. The command - - SET DZ 7B - -forces output characters to be masked to 7 bits. - -The terminal lines perform input and output through Telnet sessions -connected to a user-specified port. The ATTACH command specifies -the port to be used: - - ATTACH {-am} DZ set up listening port - -where port is a decimal number between 1 and 65535 that is not being used -for other TCP/IP activities. The optional switch -m turns on the DZV11's -modem controls; the optional switch -a turns on active disconnects -(disconnect session if computer clears Data Terminal Ready). Without -modem control, the DZ behaves as though terminals were directly connected; -disconnecting the Telnet session does not cause any operating system- -visible change in line status. - -Once the DZ is attached and the simulator is running, the DZ will listen -for connections on the specified port. It assumes that the incoming -connections are Telnet connections. The connection remains open until -disconnected by the simulated program, the Telnet client, a SET DZ -DISCONNECT command, or a DETACH DZ command. - -The SHOW DZ CONNECTIONS command displays the current connections to the DZ. -The SHOW DZ STATISTICS command displays statistics for active connections. -The SET DZ DISCONNECT=linenumber disconnects the specified line. - -The DZV11 implements these registers: - - name size comments - - CSR[0:3] 16 control/status register, boards 0-3 - RBUF[0:3] 16 receive buffer, boards 0-3 - LPR[0:3] 16 line parameter register, boards 0-3 - TCR[0:3] 16 transmission control register, boards 0-3 - MSR[0:3] 16 modem status register, boards 0-3 - TDR[0:3] 16 transmit data register, boards 0-3 - SAENB[0:3] 1 silo alarm enabled, boards 0-3 - RXINT 4 receive interrupts, boards 3..0 - TXINT 4 transmit interrupts, boards 3..0 - MDMTCL 1 modem control enabled - AUTODS 1 autodisconnect enabled - -The DZV11 does not support save and restore. All open connections are -lost when the simulator shuts down or the DZ is detached. - -2.4 RLV12/RL01,RL02 Cartridge Disk (RL) - -RLV12 options include the ability to set units write enabled or write locked, -to set the drive size to RL01, RL02, or autosize, and to write a DEC standard -044 compliant bad block table on the last track: - - SET RLn LOCKED set unit n write locked - SET RLn WRITEENABLED set unit n write enabled - SET RLn RL01 set size to RL01 - SET RLn RL02 set size to RL02 - SET RLn AUTOSIZE set size based on file size at attach - SET RLn BADBLOCK write bad block table on last track - -The size options can be used only when a unit is not attached to a file. The -bad block option can be used only when a unit is attached to a file. Units -can also be set ONLINE or OFFLINE. - -The RL11 implements these registers: - - name size comments - - RLCS 16 control/status - RLDA 16 disk address - RLBA 16 memory address - RLBAE 6 memory address extension (RLV12) - RLMP..RLMP2 16 multipurpose register queue - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - - end of file x assume rest of disk is zero - - OS I/O error x report error and stop - -2.5 RQDX3 MSCP Disk Controllers (RQ, RQB, RQC, RQD) - -The simulator implements four MSCP disk controllers, RQ, RQB, RQC, RQD. -Initially, RQB, RQC, and RQD are disabled. Each RQ controller simulates -an RQDX3 MSCP disk controller. RQ options include the ability to set -units write enabled or write locked, and to set the drive type to one -of many disk types: - - SET RQn LOCKED set unit n write locked - SET RQn WRITEENABLED set unit n write enabled - SET RQn RX50 set type to RX50 - SET RQn RX33 set type to RX33 - SET RQn RD51 set type to RD51 - SET RQn RD52 set type to RD52 - SET RQn RD53 set type to RD53 - SET RQn RD54 set type to RD54 - SET RQn RD31 set type to RD31 - SET RQn RA82 set type to RA82 - SET RQn RA72 set type to RA72 - SET RQn RA90 set type to RA90 - SET RQn RA92 set type to RA92 - SET RQn RAUSER{=n} set type to RA81 with n LBN's - -The type options can be used only when a unit is not attached to a file. -RAUSER is a "user specified" disk; the user can specify the size of the -disk in logical block numbers (LBN's, 512 bytes each). The minimum size -is 50MB. The maximum size is 2GB if the simulator is compiled without -64b addressing, 1000GB with 64b addressing. - -Units can also be set ONLINE or OFFLINE. - -Each RQ controller implements the following special SHOW commands: - - SHOW RQn TYPE show drive type - SHOW RQ RINGS show command and response rings - SHOW RQ FREEQ show packet free queue - SHOW RQ RESPQ show packet response queue - SHOW RQ UNITQ show unit queues - SHOW RQ ALL show all ring and queue state - SHOW RQn UNITQ show unit queues for unit n - -Each RQ controller implements these registers: - - name size comments - - SA 16 status/address register - S1DAT 16 step 1 init host data - CQBA 22 command queue base address - CQLNT 8 command queue length - CQIDX 8 command queue index - RQBA 22 request queue base address - RQLNT 8 request queue length - RQIDX 8 request queue index - FREE 5 head of free packet list - RESP 5 head of response packet list - PBSY 5 number of busy packets - CFLGS 16 controller flags - CSTA 4 controller state - PERR 9 port error number - CRED 5 host credits - HAT 17 host available timer - HTMO 17 host timeout value - CPKT[0:3] 5 current packet, units 0-3 - PKTQ[0:3] 5 packet queue, units 0-3 - UFLG[0:3] 16 unit flags, units 0-3 - INT 1 interrupt request - ITIME 1 response time for initialization steps - (except for step 4) - QTIME 24 response time for 'immediate' packets - XTIME 24 response time for data transfers - PKTS[33*32] 16 packet buffers, 33W each, - 32 entries - -Error handling is as follows: - - error processed as - - not attached disk not ready - - end of file assume rest of disk is zero - - OS I/O error report error and stop - -2.6 TSV11/TSV05 Magnetic Tape (TS) - -TS options include the ability to make the unit write enabled or write locked. - - SET TS LOCKED set unit write locked - SET TS WRITEENABLED set unit write enabled - -The magnetic tape controller implements these registers: - - name size comments - - TSSR 16 status register - TSBA 16 bus address register - TSDBX 16 data buffer extension register - CHDR 16 command packet header - CADL 16 command packet low address or count - CADH 16 command packet high address - CLNT 16 command packet length - MHDR 16 message packet header - MRFC 16 message packet residual frame count - MXS0 16 message packet extended status 0 - MXS1 16 message packet extended status 1 - MXS2 16 message packet extended status 2 - MXS3 16 message packet extended status 3 - MXS4 16 message packet extended status 4 - WADL 16 write char packet low address - WADH 16 write char packet high address - WLNT 16 write char packet length - WOPT 16 write char packet options - WXOPT 16 write char packet extended options - ATTN 1 attention message pending - BOOT 1 boot request pending - OWNC 1 if set, tape owns command buffer - OWNM 1 if set, tape owns message buffer - TIME 24 delay - POS 32 position - -Error handling is as follows: - - error processed as - - not attached tape not ready - - end of file (read or space) end of physical tape - (write) ignored - - OS I/O error fatal tape error - -2.7 TQK50 TMSCP Disk Controller (TQ) - -The TQ controller simulates the TQK50 TMSCP disk controller. TQ options -include the ability to set units write enabled or write locked, and to -specify the controller type and tape length: - - SET TQn LOCKED set unit n write locked - SET TQn WRITEENABLED set unit n write enabled - SET TQ TK50 set controller type to TK50 - SET TQ TK70 set controller type to TK70 - SET TQ TU81 set controller type to TU81 - SET TQ TKUSER{=n} set controller type to TK50 with - tape capacity of n MB - -User-specified capacity must be between 50 and 2000 MB. - -The TQ controller implements the following special SHOW commands: - - SHOW TQ TYPE show controller type - SHOW TQ RINGS show command and response rings - SHOW TQ FREEQ show packet free queue - SHOW TQ RESPQ show packet response queue - SHOW TQ UNITQ show unit queues - SHOW TQ ALL show all ring and queue state - SHOW TQn UNITQ show unit queues for unit n - -The TQ controller implements these registers: - - name size comments - - SA 16 status/address register - S1DAT 16 step 1 init host data - CQBA 22 command queue base address - CQLNT 8 command queue length - CQIDX 8 command queue index - RQBA 22 request queue base address - RQLNT 8 request queue length - RQIDX 8 request queue index - FREE 5 head of free packet list - RESP 5 head of response packet list - PBSY 5 number of busy packets - CFLGS 16 controller flags - CSTA 4 controller state - PERR 9 port error number - CRED 5 host credits - HAT 17 host available timer - HTMO 17 host timeout value - CPKT[0:3] 5 current packet, units 0-3 - PKTQ[0:3] 5 packet queue, units 0-3 - UFLG[0:3] 16 unit flags, units 0-3 - POS[0:3] 32 tape position, units 0-3 - OBJP[0:3] 32 object position, units 0-3 - INT 1 interrupt request - ITIME 1 response time for initialization steps - (except for step 4) - QTIME 24 response time for 'immediate' packets - XTIME 24 response time for data transfers - PKTS[33*32] 16 packet buffers, 33W each, - 32 entries - -Error handling is as follows: - - error processed as - - not attached tape not ready - - end of file end of medium - - OS I/O error report error and stop - -2.8 DELQA/DEQNA Qbus Ethernet Controllers (XQ, XQB) - -The simulator implements two DELQA/DEQNA Qbus Ethernet controllers (XQ, -XQB). Initially, XQ is enabled, and XQB is disabled. Options allow -control of the MAC address, the controller mode, and the sanity timer. - - SET XQ MAC= ex. 08-00-2B-AA-BB-CC - SHOW XQ MAC - -These commands are used to change or display the MAC address. -is a valid ethernet MAC, delimited by dashes or periods. The controller -defaults to 08-00-2B-AA-BB-CC, which should be sufficient if there is -only one SIMH controller on your LAN. Two cards with the same MAC address -will see each other's packets, resulting in a serious mess. - - SET XQ TYPE={DEQNA|[DELQA]} - SHOW XQ TYPE - -These commands are used to change or display the controller mode. DELQA -mode is better and faster but may not be usable by older or non-DEC OS's. -Also, be aware that DEQNA mode is not supported by many modern OS's. The -DEQNA-LOCK mode of the DELQA card is emulated by setting the the controller -to DEQNA - there is no need for a separate mode. DEQNA-LOCK mode behaves -exactly like a DEQNA, except for the operation of the VAR and MOP processing. - - SET XQ SANITY={ON|[OFF]} - SHOW XQ SANITY - -These commands change or display the INITIALIZATION sanity timer (DEQNA -jumper W3/DELQA switch S4). The INITIALIZATION sanity timer has a default -timeout of 4 minutes, and cannot be turned off, just reset. The normal -sanity timer can be set by operating system software regardless of the -state of this switch. Note that only the DEQNA (or the DELQA in DEQNA- -LOCK mode (=DEQNA)) supports the sanity timer - it is ignored by a DELQA -in Normal mode, which uses switch S4 for a different purpose. - -To access the network, the simulated Ethernet controller must be attached -to a real Ethernet interface: - - ATTACH XQ0 {ethX|} ex. eth0 or /dev/era0 - SHOW XQ ETH - -where X in 'ethX' is the number of the ethernet controller to attach, or -the real device name. The X number is system dependant. If you only have -one ethernet controller, the number will probably be 0. To find out what -your system thinks the ethernet numbers are, use the SHOW XQ ETH command. -The device list can be quite cryptic, depending on the host system, but -is probably better than guessing. If you do not attach the device, the -controller will behave as though the ethernet cable were unplugged. - -XQ has the following registers: - - name size comments - - SA0 16 station address word 0 - SA1 16 station address word 1 - SA2 16 station address word 2 - SA3 16 station address word 3 - SA4 16 station address word 4 - SA5 16 station address word 5 - CSR 16 control status register - VAR 16 vector address register - RBDL 32 receive buffer descriptor list - XBDL 32 trans(X)mit buffer descriptorlList - -One final note: because of it's asynchronous nature, the XQ controller is -not limited to the ~1.5Mbit/sec of the real DEQNA/DELQA controllers, -nor the 10Mbit/sec of a standard Ethernet. Attach it to a Fast Ethernet -(100 Mbit/sec) card, and "Feel the Power!" :-) - -2.9 Symbolic Display and Input - -The VAX simulator implements symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as ASCII string - -m display instruction mnemonics - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or -a ASCII character - " or -c ASCII string - alphabetic instruction mnemonic - numeric octal number - -Instruction input uses standard VAX assembler syntax. - -The syntax for specifiers is as follows: - -syntax specifier displacement comments - -#s^n, #n 0n - short literal, integer only -[Rn] 4n - indexed, second specifier - follows -Rn 5n - PC illegal -(Rn) 6n - PC illegal --(Rn) 7n - PC illegal -(Rn)+ 8n - -#i^n, #n 8F n immediate -@(Rn)+ 9n - -@#addr 9F addr absolute -{+/-}b^d(Rn) An {+/-}d byte displacement -b^d AF d - PC byte PC relative -@{+/-}b^d(Rn) Bn {+/-}d byte displacement deferred -@b^d BF d - PC byte PC relative deferred -{+/-}w^d(Rn) Cn {+/-}d word displacement -w^d CF d - PC word PC relative -@{+/-}w^d(Rn) Dn {+/-}d word displacement deferred -@w^d DF d - PC word PC relative deferred -{+/-}l^d(Rn) En {+/-}d long displacement -l^d EF d - PC long PC relative -@{+/-}l^d(Rn) Fn {+/-}d long displacement deferred -@l^d FF d - PC long PC relative deferred - -If no override is given for a literal (s^ or i^) or for a displacement or PC -relative addres (b^, w^, or l^), the simulator chooses the mode automatically. diff --git a/VAX/vax_fpa.c b/VAX/vax_fpa.c deleted file mode 100644 index 483dd9df..00000000 --- a/VAX/vax_fpa.c +++ /dev/null @@ -1,1395 +0,0 @@ -/* vax_fpa.c - VAX floating point accelerator simulator - - Copyright (c) 1998-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 19-Jun-03 RMS Simplified add algorithm - 16-May-03 RMS Fixed bug in floating to integer convert overflow - Fixed multiple bugs in EMODx - Integrated 32b only code - 05-Jul-02 RMS Changed internal routine names for C library conflict - 17-Apr-02 RMS Fixed bug in EDIV zero quotient - - This module contains the instruction simulators for - - - 64 bit arithmetic (ASHQ, EMUL, EDIV) - - single precision floating point - - double precision floating point, D and G format -*/ - -#include "vax_defs.h" -#include - -#define M32 0xFFFFFFFF /* 32b */ -#define M16 0x0000FFFF - -#define FD_V_EXP 7 /* f/d exponent */ -#define FD_M_EXP 0xFF -#define FD_BIAS 0x80 /* f/d bias */ -#define FD_EXP (FD_M_EXP << FD_V_EXP) -#define FD_HB (1 << FD_V_EXP) /* f/d hidden bit */ -#define FD_GUARD (15 - FD_V_EXP) /* # guard bits */ -#define FD_GETEXP(x) (((x) >> FD_V_EXP) & FD_M_EXP) - -#define G_V_EXP 4 /* g exponent */ -#define G_M_EXP 0x7FF -#define G_BIAS 0x400 /* g bias */ -#define G_EXP (G_M_EXP << G_V_EXP) -#define G_HB (1 << G_V_EXP) /* g hidden bit */ -#define G_GUARD (15 - G_V_EXP) /* # guard bits */ -#define G_GETEXP(x) (((x) >> G_V_EXP) & G_M_EXP) - -extern int32 R[16]; -extern int32 PSL; -extern int32 p1; -extern jmp_buf save_env; - -extern int32 Read (uint32 va, int32 size, int32 acc); - -#if defined (USE_INT64) - -#define M64 0xFFFFFFFFFFFFFFFF /* 64b */ -#define FD_FRACW (0xFFFF & ~(FD_EXP | FPSIGN)) -#define FD_FRACL (FD_FRACW | 0xFFFF0000) /* f/d fraction */ -#define G_FRACW (0xFFFF & ~(G_EXP | FPSIGN)) -#define G_FRACL (G_FRACW | 0xFFFF0000) /* g fraction */ -#define UNSCRAM(h,l) (((((t_uint64) (h)) << 48) & 0xFFFF000000000000) | \ - ((((t_uint64) (h)) << 16) & 0x0000FFFF00000000) | \ - ((((t_uint64) (l)) << 16) & 0x00000000FFFF0000) | \ - ((((t_uint64) (l)) >> 16) & 0x000000000000FFFF)) -#define CONCAT(h,l) ((((t_uint64) (h)) << 32) | ((uint32) (l))) - -struct ufp { - int32 sign; - int32 exp; - t_uint64 frac; }; - -typedef struct ufp UFP; - -#define UF_NM 0x8000000000000000 /* normalized */ -#define UF_FRND 0x0000008000000000 /* F round */ -#define UF_DRND 0x0000000000000080 /* D round */ -#define UF_GRND 0x0000000000000400 /* G round */ -#define UF_V_NM 63 -#define UF_V_FDHI 40 -#define UF_V_FDLO (UF_V_FDHI - 32) -#define UF_V_GHI 43 -#define UF_V_GLO (UF_V_GHI - 32) -#define UF_GETFDHI(x) (int32) ((((x) >> (16 + UF_V_FDHI)) & FD_FRACW) | \ - (((x) >> (UF_V_FDHI - 16)) & ~0xFFFF)) -#define UF_GETFDLO(x) (int32) ((((x) >> (16 + UF_V_FDLO)) & 0xFFFF) | \ - (((x) << (16 - UF_V_FDLO)) & ~0xFFFF)) -#define UF_GETGHI(x) (int32) ((((x) >> (16 + UF_V_GHI)) & G_FRACW) | \ - (((x) >> (UF_V_GHI - 16)) & ~0xFFFF)) -#define UF_GETGLO(x) (int32) ((((x) >> (16 + UF_V_GLO)) & 0xFFFF) | \ - (((x) << (16 - UF_V_GLO)) & ~0xFFFF)) - -void unpackf (int32 hi, UFP *a); -void unpackd (int32 hi, int32 lo, UFP *a); -void unpackg (int32 hi, int32 lo, UFP *a); -void norm (UFP *a); -int32 rpackfd (UFP *a, int32 *rh); -int32 rpackg (UFP *a, int32 *rh); -void vax_fadd (UFP *a, UFP *b, t_int64 mask); -void vax_fmul (UFP *a, UFP *b, int32 prec, int32 bias, t_int64 mask); -void vax_fdiv (UFP *b, UFP *a, int32 prec, int32 bias); -void vax_fmod (UFP *a, int32 bias, int32 *intgr, int32 *flg); - -/* Quadword arithmetic shift - - opnd[0] = shift count (cnt.rb) - opnd[1:2] = source (src.rq) - opnd[3:4] = destination (dst.wq) -*/ - -int32 op_ashq (int32 *opnd, int32 *rh, int32 *flg) -{ -t_int64 src, r; -int32 sc = opnd[0]; - -src = CONCAT (opnd[2], opnd[1]); /* build src */ -if (sc & BSIGN) { /* right shift? */ - *flg = 0; /* no ovflo */ - sc = 0x100 - sc; /* |shift| */ - if (sc > 63) r = (opnd[2] & LSIGN)? -1: 0; /* sc > 63? */ - else r = src >> sc; } -else { if (sc > 63) { /* left shift */ - r = 0; /* sc > 63? */ - *flg = (src != 0); } /* ovflo test */ - else { - r = src << sc; /* do shift */ - *flg = (src != (r >> sc)); } } /* ovflo test */ -*rh = (int32) (r >> 32); /* hi result */ -return ((int32) r); /* lo result */ -} - -/* Extended multiply subroutine */ - -int32 op_emul (int32 mpy, int32 mpc, int32 *rh) -{ -t_int64 lmpy = mpy; -t_int64 lmpc = mpc; - -lmpy = lmpy * lmpc; -*rh = ((int32) (lmpy >> 32)); -return (int32) lmpy; -} - -/* Extended divide - - opnd[0] = divisor (non-zero) - opnd[1:2] = dividend -*/ - -int32 op_ediv (int32 *opnd, int32 *rh, int32 *flg) -{ -t_int64 ldvd, ldvr; -int32 quo, rem; - -*flg = CC_V; /* assume error */ -*rh = 0; -ldvr = ((opnd[0] & LSIGN)? -opnd[0]: opnd[0]) & M32; /* |divisor| */ -ldvd = CONCAT (opnd[2], opnd[1]); /* 64b dividend */ -if (opnd[2] & LSIGN) ldvd = -ldvd; /* |dividend| */ -if (((ldvd >> 32) & M32) >= ldvr) return opnd[1]; /* divide work? */ -quo = (int32) (ldvd / ldvr); /* do divide */ -rem = (int32) (ldvd % ldvr); -if ((opnd[0] ^ opnd[2]) & LSIGN) { /* result -? */ - quo = -quo; /* negate */ - if (quo && ((quo & LSIGN) == 0)) return opnd[1]; } /* right sign? */ -else if (quo & LSIGN) return opnd[1]; -if (opnd[2] & LSIGN) rem = -rem; /* sign of rem */ -*flg = 0; /* no overflow */ -*rh = rem; /* set rem */ -return quo; /* return quo */ -} - -/* Compare floating */ - -int32 op_cmpfd (int32 h1, int32 l1, int32 h2, int32 l2) -{ -t_uint64 n1, n2; - -if ((h1 & FD_EXP) == 0) { - if (h1 & FPSIGN) RSVD_OPND_FAULT; - h1 = l1 = 0; } -if ((h2 & FD_EXP) == 0) { - if (h2 & FPSIGN) RSVD_OPND_FAULT; - h2 = l2 = 0; } -if ((h1 ^ h2) & FPSIGN) return ((h1 & FPSIGN)? CC_N: 0); -n1 = UNSCRAM (h1, l1); -n2 = UNSCRAM (h2, l2); -if (n1 == n2) return CC_Z; -return (((n1 < n2) ^ ((h1 & FPSIGN) != 0))? CC_N: 0); -} - -int32 op_cmpg (int32 h1, int32 l1, int32 h2, int32 l2) -{ -t_uint64 n1, n2; - -if ((h1 & G_EXP) == 0) { - if (h1 & FPSIGN) RSVD_OPND_FAULT; - h1 = l1 = 0; } -if ((h2 & G_EXP) == 0) { - if (h2 & FPSIGN) RSVD_OPND_FAULT; - h2 = l2 = 0; } -if ((h1 ^ h2) & FPSIGN) return ((h1 & FPSIGN)? CC_N: 0); -n1 = UNSCRAM (h1, l1); -n2 = UNSCRAM (h2, l2); -if (n1 == n2) return CC_Z; -return (((n1 < n2) ^ ((h1 & FPSIGN) != 0))? CC_N: 0); -} - -/* Integer to floating convert */ - -int32 op_cvtifdg (int32 val, int32 *rh, int32 opc) -{ -UFP a; - -if (val == 0) { - if (rh) *rh = 0; - return 0; } -if (val < 0) { - a.sign = FPSIGN; - val = - val; } -else a.sign = 0; -a.exp = 32 + ((opc & 0x100)? G_BIAS: FD_BIAS); -a.frac = ((t_uint64) val) << (UF_V_NM - 31); -norm (&a); -if (opc & 0x100) return rpackg (&a, rh); -return rpackfd (&a, rh); -} - -/* Floating to integer convert */ - -int32 op_cvtfdgi (int32 *opnd, int32 *flg, int32 opc) -{ -UFP a; -int32 lnt = opc & 03; -int32 ubexp; -static t_uint64 maxv[4] = { 0x7F, 0x7FFF, 0x7FFFFFFF, 0x7FFFFFFF }; - -*flg = 0; -if (opc & 0x100) { - unpackg (opnd[0], opnd[1], &a); - ubexp = a.exp - G_BIAS; } -else { if (opc & 0x20) unpackd (opnd[0], opnd[1], &a); - else unpackf (opnd[0], &a); - ubexp = a.exp - FD_BIAS; } -if ((a.exp == 0) || (ubexp < 0)) return 0; -if (ubexp <= UF_V_NM) { - a.frac = a.frac >> (UF_V_NM - ubexp); /* leave rnd bit */ - if ((opc & 03) == 03) a.frac = a.frac + 1; /* if CVTR, round */ - a.frac = a.frac >> 1; /* now justified */ - if (a.frac > (maxv[lnt] + (a.sign? 1: 0))) *flg = CC_V; } -else { *flg = CC_V; /* set overflow */ - if (ubexp > (UF_V_NM + 32)) return 0; - a.frac = a.frac << (ubexp - UF_V_NM - 1); } /* no rnd bit */ -return ((int32) (a.sign? (a.frac ^ M32) + 1: a.frac)); -} - -/* Extended modularize - - One of three floating point instructions dropped from the architecture, - EMOD presents two sets of complications. First, it requires an extended - fraction multiply, with precise (and unusual) truncation conditions. - Second, it has two write operands, a dubious distinction it shares - with EDIV. -*/ - -int32 op_emodf (int32 *opnd, int32 *intgr, int32 *flg) -{ -UFP a, b; - -unpackf (opnd[0], &a); /* unpack operands */ -unpackf (opnd[2], &b); -a.frac = a.frac | (((t_uint64) opnd[1]) << 32); /* extend src1 */ -vax_fmul (&a, &b, 32, FD_BIAS, M32); /* multiply */ -vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */ -return rpackfd (&a, NULL); /* return frac */ -} - -int32 op_emodd (int32 *opnd, int32 *flo, int32 *intgr, int32 *flg) -{ -UFP a, b; - -unpackd (opnd[0], opnd[1], &a); /* unpack operands */ -unpackd (opnd[3], opnd[4], &b); -a.frac = a.frac | opnd[2]; /* extend src1 */ -vax_fmul (&a, &b, 64, FD_BIAS, 0); /* multiply */ -vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */ -return rpackfd (&a, flo); /* return frac */ -} - -int32 op_emodg (int32 *opnd, int32 *flo, int32 *intgr, int32 *flg) -{ -UFP a, b; - -unpackg (opnd[0], opnd[1], &a); /* unpack operands */ -unpackg (opnd[3], opnd[4], &b); -a.frac = a.frac | (opnd[2] >> 5); /* extend src1 */ -vax_fmul (&a, &b, 64, G_BIAS, 0); /* multiply */ -vax_fmod (&a, G_BIAS, intgr, flg); /* sep int & frac */ -return rpackg (&a, flo); /* return frac */ -} - -/* Unpacked floating point routines */ - -void vax_fadd (UFP *a, UFP *b, t_int64 mask) -{ -int32 ediff; -UFP t; - -if (a->exp == 0) { /* s1 = 0? */ - *a = *b; - return; } -if (b->exp == 0) return; /* s2 = 0? */ -if ((a->exp < b->exp) || /* |s1| < |s2|? swap */ - ((a->exp == b->exp) && (a->frac < b->frac))) { - t = *a; - *a = *b; - *b = t; } -ediff = a->exp - b->exp; /* exp diff */ -if (a->sign ^ b->sign) { /* eff sub? */ - if (ediff) { /* exp diff? */ - if (ediff > 63) b->frac = M64; /* retain sticky */ - else b->frac = ((-((t_int64) b->frac) >> ediff) | /* denormalize */ - (M64 << (64 - ediff))); /* preserve sign */ - a->frac = a->frac + b->frac; } /* add frac */ - else a->frac = a->frac - b->frac; /* sub frac */ - a->frac = a->frac & ~mask; - norm (a); } /* normalize */ -else { if (ediff > 63) b->frac = 0; /* add */ - else if (ediff) b->frac = b->frac >> ediff; /* denormalize */ - a->frac = a->frac + b->frac; /* add frac */ - if (a->frac < b->frac) { /* chk for carry */ - a->frac = UF_NM | (a->frac >> 1); /* shift in carry */ - a->exp = a->exp + 1; } /* skip norm */ - a->frac = a->frac & ~mask; } -return; -} - -/* Floating multiply - 64b * 64b with cross products */ - -void vax_fmul (UFP *a, UFP *b, int32 prec, int32 bias, t_int64 mask) -{ -t_uint64 ah, bh, al, bl, rhi, rlo, rmid1, rmid2; - -if ((a->exp == 0) || (b->exp == 0)) { /* zero argument? */ - a->frac = a->sign = a->exp = 0; /* result is zero */ - return; } -a->sign = a->sign ^ b->sign; /* sign of result */ -a->exp = a->exp + b->exp - bias; /* add exponents */ -ah = (a->frac >> 32) & M32; /* split operands */ -bh = (b->frac >> 32) & M32; /* into 32b chunks */ -rhi = ah * bh; /* high result */ -if (prec > 32) { /* 64b needed? */ - al = a->frac & M32; - bl = b->frac & M32; - rmid1 = ah * bl; - rmid2 = al * bh; - rlo = al * bl; - rhi = rhi + ((rmid1 >> 32) & M32) + ((rmid2 >> 32) & M32); - rmid1 = rlo + (rmid1 << 32); /* add mid1 to lo */ - if (rmid1 < rlo) rhi = rhi + 1; /* carry? incr hi */ - rmid2 = rmid1 + (rmid2 << 32); /* add mid2 to to */ - if (rmid2 < rmid1) rhi = rhi + 1; } /* carry? incr hi */ -a->frac = rhi & ~mask; /* mask out */ -norm (a); /* normalize */ -return; -} - -/* Floating modulus - there are three cases - - exp <= bias - integer is 0, fraction is input, - no overflow - bias < exp <= bias+64 - separate integer and fraction, - integer overflow may occur - bias+64 < exp - result is integer, fraction is 0 - integer overflow -*/ - -void vax_fmod (UFP *a, int32 bias, int32 *intgr, int32 *flg) -{ -if (a->exp <= bias) *intgr = *flg = 0; /* 0 or <1? int = 0 */ -else if (a->exp <= (bias + 64)) { /* in range? */ - *intgr = (int32) (a->frac >> (64 - (a->exp - bias))); - if ((a->exp > (bias + 32)) || /* test ovflo */ - ((a->exp == (bias + 32)) && - (((uint32) *intgr) > (a->sign? 0x80000000: 0x7FFFFFFF)))) - *flg = CC_V; - else *flg = 0; - if (a->sign) *intgr = -*intgr; /* -? comp int */ - a->frac = a->frac << (a->exp - bias); - a->exp = bias; } -else { *intgr = 0; /* out of range */ - a->frac = a->sign = a->exp = 0; /* result 0 */ - *flg = CC_V; } /* overflow */ -norm (a); /* normalize */ -return; -} - -/* Floating divide - Needs to develop at least one rounding bit. Since the first - divide step can fail, caller should specify 2 more bits than - the precision of the fraction. -*/ - -void vax_fdiv (UFP *a, UFP *b, int32 prec, int32 bias) -{ -int32 i; -t_uint64 quo = 0; - -if (a->exp == 0) FLT_DZRO_FAULT; /* divr = 0? */ -if (b->exp == 0) return; /* divd = 0? */ -b->sign = b->sign ^ a->sign; /* result sign */ -b->exp = b->exp - a->exp + bias + 1; /* unbiased exp */ -a->frac = a->frac >> 1; /* allow 1 bit left */ -b->frac = b->frac >> 1; -for (i = 0; (i < prec) && b->frac; i++) { /* divide loop */ - quo = quo << 1; /* shift quo */ - if (b->frac >= a->frac) { /* div step ok? */ - b->frac = b->frac - a->frac; /* subtract */ - quo = quo + 1; } /* quo bit = 1 */ - b->frac = b->frac << 1; } /* shift divd */ -b->frac = quo << (UF_V_NM - i + 1); /* shift quo */ -norm (b); /* normalize */ -return; -} - -/* Support routines */ - -void unpackf (int32 hi, UFP *r) -{ -r->sign = hi & FPSIGN; /* get sign */ -r->exp = FD_GETEXP (hi); /* get exponent */ -if (r->exp == 0) { /* exp = 0? */ - if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ - r->frac = 0; /* else 0 */ - return; } -hi = (((hi & FD_FRACW) | FD_HB) << 16) | ((hi >> 16) & 0xFFFF); -r->frac = ((t_uint64) hi) << (32 + UF_V_FDLO); -return; -} - -void unpackd (int32 hi, int32 lo, UFP *r) -{ -r->sign = hi & FPSIGN; /* get sign */ -r->exp = FD_GETEXP (hi); /* get exponent */ -if (r->exp == 0) { /* exp = 0? */ - if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ - r->frac = 0; /* else 0 */ - return; } -hi = (hi & FD_FRACL) | FD_HB; /* canonical form */ -r->frac = UNSCRAM (hi, lo) << UF_V_FDLO; /* guard bits */ -return; -} - -void unpackg (int32 hi, int32 lo, UFP *r) -{ -r->sign = hi & FPSIGN; /* get sign */ -r->exp = G_GETEXP (hi); /* get exponent */ -if (r->exp == 0) { /* exp = 0? */ - if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ - r->frac = 0; /* else 0 */ - return; } -hi = (hi & G_FRACL) | G_HB; /* canonical form */ -r->frac = UNSCRAM (hi, lo) << UF_V_GLO; /* guard bits */ -return; -} - -void norm (UFP *r) -{ -int32 i; -static t_uint64 normmask[5] = { - 0xc000000000000000, 0xf000000000000000, 0xff00000000000000, - 0xffff000000000000, 0xffffffff00000000 }; -static int32 normtab[6] = { 1, 2, 4, 8, 16, 32}; - -if (r->frac == 0) { /* if fraction = 0 */ - r->sign = r->exp = 0; /* result is 0 */ - return; } -while ((r->frac & UF_NM) == 0) { /* normalized? */ - for (i = 0; i < 5; i++) { /* find first 1 */ - if (r->frac & normmask[i]) break; } - r->frac = r->frac << normtab[i]; /* shift frac */ - r->exp = r->exp - normtab[i]; } /* decr exp */ -return; -} - -int32 rpackfd (UFP *r, int32 *rh) -{ -if (rh) *rh = 0; /* assume 0 */ -if (r->frac == 0) return 0; /* result 0? */ -r->frac = r->frac + (rh? UF_DRND: UF_FRND); /* round */ -if ((r->frac & UF_NM) == 0) { /* carry out? */ - r->frac = r->frac >> 1; /* renormalize */ - r->exp = r->exp + 1; } -if (r->exp > (int32) FD_M_EXP) FLT_OVFL_FAULT; /* ovflo? fault */ -if (r->exp <= 0) { /* underflow? */ - if (PSL & PSW_FU) FLT_UNFL_FAULT; /* fault if fu */ - return 0; } /* else 0 */ -if (rh) *rh = UF_GETFDLO (r->frac); /* get low */ -return r->sign | (r->exp << FD_V_EXP) | UF_GETFDHI (r->frac); -} - -int32 rpackg (UFP *r, int32 *rh) -{ -*rh = 0; /* assume 0 */ -if (r->frac == 0) return 0; /* result 0? */ -r->frac = r->frac + UF_GRND; /* round */ -if ((r->frac & UF_NM) == 0) { /* carry out? */ - r->frac = r->frac >> 1; /* renormalize */ - r->exp = r->exp + 1; } -if (r->exp > (int32) G_M_EXP) FLT_OVFL_FAULT; /* ovflo? fault */ -if (r->exp <= 0) { /* underflow? */ - if (PSL & PSW_FU) FLT_UNFL_FAULT; /* fault if fu */ - return 0; } /* else 0 */ -if (rh) *rh = UF_GETGLO (r->frac); /* get low */ -return r->sign | (r->exp << G_V_EXP) | UF_GETGHI (r->frac); -} - -#else /* 32b code */ - -#define WORDSWAP(x) ((((x) & 0xFFFF) << 16) | (((x) >> 16) & 0xFFFF)) -#define INC32(x) (((x) + 1) & M32) -#define NEG32(x) (((~(x)) + 1) & M32) - -struct udp { - uint32 lo; - uint32 hi; -}; - -typedef struct udp UDP; - -struct ufp { - int32 sign; - int32 exp; - struct udp frac; }; - -typedef struct ufp UFP; - -#define UF_NM_H 0x80000000 /* normalized */ -#define UF_FRND_H 0x00000080 /* F round */ -#define UF_FRND_L 0x00000000 -#define UF_DRND_H 0x00000000 /* D round */ -#define UF_DRND_L 0x00000080 -#define UF_GRND_H 0x00000000 /* G round */ -#define UF_GRND_L 0x00000400 -#define UF_V_NM 63 - -void unpackf (uint32 hi, UFP *a); -void unpackd (uint32 hi, uint32 lo, UFP *a); -void unpackg (uint32 hi, uint32 lo, UFP *a); -void norm (UFP *a); -int32 rpackfd (UFP *a, int32 *rh); -int32 rpackg (UFP *a, int32 *rh); -void vax_fadd (UFP *a, UFP *b, uint32 mask); -void vax_fmul (UFP *a, UFP *b, int32 prec, int32 bias, uint32 mask); -void vax_fmod (UFP *a, int32 bias, int32 *intgr, int32 *flg); -void vax_fdiv (UFP *b, UFP *a, int32 prec, int32 bias); -int32 vax_fcmp (UFP *a, UFP *b); -void dp_add (UDP *a, UDP *b); -void dp_inc (UDP *a); -void dp_sub (UDP *a, UDP *b); -void dp_imul (uint32 a, uint32 b, UDP *r); -void dp_lsh (UDP *a, uint32 sc); -void dp_rsh (UDP *a, uint32 sc); -void dp_rsh_s (UDP *a, uint32 sc, uint32 neg); -void dp_neg (UDP *a); -int32 dp_cmp (UDP *a, UDP *b); - -/* Quadword arithmetic shift - - opnd[0] = shift count (cnt.rb) - opnd[1:2] = source (src.rq) - opnd[3:4] = destination (dst.wq) -*/ - -int32 op_ashq (int32 *opnd, int32 *rh, int32 *flg) -{ -UDP r, sr; -uint32 sc = opnd[0]; - -r.lo = opnd[1]; /* get source */ -r.hi = opnd[2]; -*flg = 0; /* assume no ovflo */ -if (sc & BSIGN) /* right shift? */ - dp_rsh_s (&r, 0x100 - sc, r.hi & LSIGN); /* signed right */ -else { dp_lsh (&r, sc); /* left shift */ - sr = r; /* copy result */ - dp_rsh_s (&sr, sc, sr.hi & LSIGN); /* signed right */ - if ((sr.hi != ((uint32) opnd[2])) || /* reshift != orig? */ - (sr.lo != ((uint32) opnd[1]))) *flg = 1; } /* overflow */ -*rh = r.hi; /* hi result */ -return r.lo; /* lo result */ -} - -/* Extended multiply subroutine */ - -int32 op_emul (int32 mpy, int32 mpc, int32 *rh) -{ -UDP r; -int32 sign = mpy ^ mpc; /* sign of result */ - -if (mpy & LSIGN) mpy = -mpy; /* abs value */ -if (mpc & LSIGN) mpc = -mpc; -dp_imul (mpy & M32, mpc & M32, &r); /* 32b * 32b -> 64b */ -if (sign & LSIGN) dp_neg (&r); /* negative result? */ -*rh = r.hi; -return r.lo; -} - -/* Extended divide - - opnd[0] = divisor (non-zero) - opnd[1:2] = dividend -*/ - -int32 op_ediv (int32 *opnd, int32 *rh, int32 *flg) -{ -UDP dvd; -uint32 i, dvr, quo; - -dvr = opnd[0]; /* get divisor */ -dvd.lo = opnd[1]; /* get dividend */ -dvd.hi = opnd[2]; -*flg = CC_V; /* assume error */ -*rh = 0; -if (dvd.hi & LSIGN) dp_neg (&dvd); /* |dividend| */ -if (dvr & LSIGN) dvr = NEG32 (dvr); /* |divisor| */ -if (dvd.hi >= dvr) return opnd[1]; /* divide work? */ -for (i = quo = 0; i < 32; i++) { /* 32 iterations */ - quo = quo << 1; /* shift quotient */ - dp_lsh (&dvd, 1); /* shift dividend */ - if (dvd.hi >= dvr) { /* step work? */ - dvd.hi = (dvd.hi - dvr) & M32; /* subtract dvr */ - quo = quo + 1; } } -if ((opnd[0] ^ opnd[2]) & LSIGN) { /* result -? */ - quo = NEG32 (quo); /* negate */ - if (quo && ((quo & LSIGN) == 0)) return opnd[1]; } /* right sign? */ -else if (quo & LSIGN) return opnd[1]; -if (opnd[2] & LSIGN) *rh = NEG32 (dvd.hi); /* sign of rem */ -else *rh = dvd.hi; -*flg = 0; /* no overflow */ -return quo; /* return quo */ -} - -/* Compare floating */ - -int32 op_cmpfd (int32 h1, int32 l1, int32 h2, int32 l2) -{ -UFP a, b; -int32 r; - -unpackd (h1, l1, &a); -unpackd (h2, l2, &b); -if (a.sign != b.sign) return (a.sign? CC_N: 0); -r = a.exp - b.exp; -if (r == 0) r = dp_cmp (&a.frac, &b.frac); -if (r < 0) return (a.sign? 0: CC_N); -if (r > 0) return (a.sign? CC_N: 0); -return CC_Z; -} - -int32 op_cmpg (int32 h1, int32 l1, int32 h2, int32 l2) -{ -UFP a, b; -int32 r; - -unpackg (h1, l1, &a); -unpackg (h2, l2, &b); -if (a.sign != b.sign) return (a.sign? CC_N: 0); -r = a.exp - b.exp; -if (r == 0) r = dp_cmp (&a.frac, &b.frac); -if (r < 0) return (a.sign? 0: CC_N); -if (r > 0) return (a.sign? CC_N: 0); -return CC_Z; -} - -/* Integer to floating convert */ - -int32 op_cvtifdg (int32 val, int32 *rh, int32 opc) -{ -UFP a; - -if (val == 0) { /* zero? */ - if (rh) *rh = 0; /* return true 0 */ - return 0; } -if (val < 0) { /* negative? */ - a.sign = FPSIGN; /* sign = - */ - val = -val; } -else a.sign = 0; /* else sign = + */ -a.exp = 32 + ((opc & 0x100)? G_BIAS: FD_BIAS); /* initial exp */ -a.frac.hi = val & M32; /* fraction */ -a.frac.lo = 0; -norm (&a); /* normalize */ -if (opc & 0x100) return rpackg (&a, rh); /* pack and return */ -return rpackfd (&a, rh); -} - -/* Floating to integer convert */ - -int32 op_cvtfdgi (int32 *opnd, int32 *flg, int32 opc) -{ -UFP a; -int32 lnt = opc & 03; -int32 ubexp; -static uint32 maxv[4] = { 0x7F, 0x7FFF, 0x7FFFFFFF, 0x7FFFFFFF }; - -*flg = 0; -if (opc & 0x100) { /* G? */ - unpackg (opnd[0], opnd[1], &a); /* unpack */ - ubexp = a.exp - G_BIAS; } /* unbiased exp */ -else { if (opc & 0x20) unpackd (opnd[0], opnd[1], &a); /* F or D */ - else unpackf (opnd[0], &a); /* unpack */ - ubexp = a.exp - FD_BIAS; } /* unbiased exp */ -if ((a.exp == 0) || (ubexp < 0)) return 0; /* true zero or frac? */ -if (ubexp <= UF_V_NM) { /* exp in range? */ - dp_rsh (&a.frac, UF_V_NM - ubexp); /* leave rnd bit */ - if (lnt == 03) dp_inc (&a.frac); /* if CVTR, round */ - dp_rsh (&a.frac, 1); /* now justified */ - if ((a.frac.hi != 0) || - (a.frac.lo > (maxv[lnt] + (a.sign? 1: 0)))) *flg = CC_V; } -else { *flg = CC_V; /* always ovflo */ - if (ubexp > (UF_V_NM + 32)) return 0; /* in ext range? */ - dp_lsh (&a.frac, ubexp - UF_V_NM - 1); } /* no rnd bit */ -return (a.sign? NEG32 (a.frac.lo): a.frac.lo); /* return lo frac */ -} - -/* Extended modularize - - One of three floating point instructions dropped from the architecture, - EMOD presents two sets of complications. First, it requires an extended - fraction multiply, with precise (and unusual) truncation conditions. - Second, it has two write operands, a dubious distinction it shares - with EDIV. -*/ - -int32 op_emodf (int32 *opnd, int32 *intgr, int32 *flg) -{ -UFP a, b; - -unpackf (opnd[0], &a); /* unpack operands */ -unpackf (opnd[2], &b); -a.frac.hi = a.frac.hi | opnd[1]; /* extend src1 */ -vax_fmul (&a, &b, 32, FD_BIAS, M32); /* multiply */ -vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */ -return rpackfd (&a, NULL); /* return frac */ -} - -int32 op_emodd (int32 *opnd, int32 *flo, int32 *intgr, int32 *flg) -{ -UFP a, b; - -unpackd (opnd[0], opnd[1], &a); /* unpack operands */ -unpackd (opnd[3], opnd[4], &b); -a.frac.lo = a.frac.lo | opnd[2]; /* extend src1 */ -vax_fmul (&a, &b, 64, FD_BIAS, 0); /* multiply */ -vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */ -return rpackfd (&a, flo); /* return frac */ -} - -int32 op_emodg (int32 *opnd, int32 *flo, int32 *intgr, int32 *flg) -{ -UFP a, b; - -unpackg (opnd[0], opnd[1], &a); /* unpack operands */ -unpackg (opnd[3], opnd[4], &b); -a.frac.lo = a.frac.lo | (opnd[2] >> 5); /* extend src1 */ -vax_fmul (&a, &b, 64, G_BIAS, 0); /* multiply */ -vax_fmod (&a, G_BIAS, intgr, flg); /* sep int & frac */ -return rpackg (&a, flo); /* return frac */ -} - -/* Unpacked floating point routines */ - -/* Floating add */ - -void vax_fadd (UFP *a, UFP *b, uint32 mask) -{ -int32 ediff; -UFP t; - -if (a->exp == 0) { /* s1 = 0? */ - *a = *b; - return; } -if (b->exp == 0) return; /* s2 = 0? */ -if ((a->exp < b->exp) || /* |s1| < |s2|? swap */ - ((a->exp == b->exp) && (dp_cmp (&a->frac, &b->frac) < 0))) { - t = *a; - *a = *b; - *b = t; } -ediff = a->exp - b->exp; /* exp diff */ -if (a->sign ^ b->sign) { /* eff sub? */ - if (ediff) { /* exp diff? */ - dp_neg (&b->frac); /* negate fraction */ - dp_rsh_s (&b->frac, ediff, 1); /* signed right */ - dp_add (&a->frac, &b->frac); } /* "add" frac */ - else dp_sub (&a->frac, &b->frac); /* a >= b */ - a->frac.lo = a->frac.lo & ~mask; /* trim low result */ - norm (a); } /* normalize */ -else { if (ediff) dp_rsh (&b->frac, ediff); /* add, denormalize */ - dp_add (&a->frac, &b->frac); /* add frac */ - if (dp_cmp (&a->frac, &b->frac) < 0) { /* chk for carry */ - dp_rsh (&a->frac, 1); /* renormalize */ - a->frac.hi = a->frac.hi | UF_NM_H; /* add norm bit */ - a->exp = a->exp + 1; } /* skip norm */ - a->frac.lo = a->frac.lo & ~mask; } /* trim low result */ -return; -} - -/* Floating compare */ - -int32 vax_fcmp (UFP *a, UFP *b) -{ -int32 r; - -if (a->sign != b->sign) return ((a->sign)? CC_N: 0); -r = a->exp - b->exp; -if (r == 0) r = dp_cmp (&a->frac, &b->frac); -if (r == 0) return CC_Z; -if (r < 0) return (a->sign? 0: CC_N); -else return (a->sign? CC_N: 0); -} - -/* Floating multiply - 64b * 64b with cross products */ - -void vax_fmul (UFP *a, UFP *b, int32 prec, int32 bias, uint32 mask) -{ -UDP rhi, rlo, rmid1, rmid2; - -if ((a->exp == 0) || (b->exp == 0)) { /* zero argument? */ - a->frac.hi = a->frac.lo = 0; /* result is zero */ - a->sign = a->exp = 0; - return; } -a->sign = a->sign ^ b->sign; /* sign of result */ -a->exp = a->exp + b->exp - bias; /* add exponents */ -dp_imul (a->frac.hi, b->frac.hi, &rhi); /* high result */ -if (prec > 32) { /* 64b needed? */ - dp_imul (a->frac.hi, b->frac.lo, &rmid1); /* cross products */ - dp_imul (a->frac.lo, b->frac.hi, &rmid2); - dp_imul (a->frac.lo, b->frac.lo, &rlo); /* low result */ - rhi.lo = (rhi.lo + rmid1.hi) & M32; /* add hi cross */ - if (rhi.lo < rmid1.hi) rhi.hi = INC32 (rhi.hi); /* to low high res */ - rhi.lo = (rhi.lo + rmid2.hi) & M32; - if (rhi.lo < rmid2.hi) rhi.hi = INC32 (rhi.hi); - rlo.hi = (rlo.hi + rmid1.lo) & M32; /* add mid1 to low res */ - if (rlo.hi < rmid1.lo) dp_inc (&rhi); /* carry? incr high res */ - rlo.hi = (rlo.hi + rmid2.lo) & M32; /* add mid2 to low res */ - if (rlo.hi < rmid1.hi) dp_inc (&rhi); } /* carry? incr high res */ -a->frac.hi = rhi.hi; /* mask low fraction */ -a->frac.lo = rhi.lo & ~mask; -norm (a); /* normalize */ -return; -} - -/* Floating modulus - there are three cases - - exp <= bias - integer is 0, fraction is input, - no overflow - bias < exp <= bias+64 - separate integer and fraction, - integer overflow may occur - bias+64 < exp - result is integer, fraction is 0 - integer overflow -*/ - -void vax_fmod (UFP *a, int32 bias, int32 *intgr, int32 *flg) -{ -UDP ifr; - -if (a->exp <= bias) *intgr = *flg = 0; /* 0 or <1? int = 0 */ -else if (a->exp <= (bias + 64)) { /* in range? */ - ifr = a->frac; - dp_rsh (&ifr, 64 - (a->exp - bias)); /* separate integer */ - if ((a->exp > (bias + 32)) || /* test ovflo */ - ((a->exp == (bias + 32)) && - (ifr.lo > (a->sign? 0x80000000: 0x7FFFFFFF)))) - *flg = CC_V; - else *flg = 0; - *intgr = ifr.lo; - if (a->sign) *intgr = -*intgr; /* -? comp int */ - dp_lsh (&a->frac, a->exp - bias); /* excise integer */ - a->exp = bias; } -else { *intgr = 0; /* out of range */ - a->frac.hi = a->frac.lo = a->sign = a->exp = 0; /* result 0 */ - *flg = CC_V; } /* overflow */ -norm (a); /* normalize */ -return; -} - -/* Floating divide - Needs to develop at least one rounding bit. Since the first - divide step can fail, caller should specify 2 more bits than - the precision of the fraction. -*/ - -void vax_fdiv (UFP *a, UFP *b, int32 prec, int32 bias) -{ -int32 i; -UDP quo = { 0, 0 }; - -if (a->exp == 0) FLT_DZRO_FAULT; /* divr = 0? */ -if (b->exp == 0) return; /* divd = 0? */ -b->sign = b->sign ^ a->sign; /* result sign */ -b->exp = b->exp - a->exp + bias + 1; /* unbiased exp */ -dp_rsh (&a->frac, 1); /* allow 1 bit left */ -dp_rsh (&b->frac, 1); -for (i = 0; i < prec; i++) { /* divide loop */ - dp_lsh (&quo, 1); /* shift quo */ - if (dp_cmp (&b->frac, &a->frac) >= 0) { /* div step ok? */ - dp_sub (&b->frac, &a->frac); /* subtract */ - quo.lo = quo.lo + 1; } /* quo bit = 1 */ - dp_lsh (&b->frac, 1); } /* shift divd */ -dp_lsh (&quo, UF_V_NM - prec + 1); /* put in position */ -b->frac = quo; -norm (b); /* normalize */ -return; -} - -/* Double precision integer routines */ - -int32 dp_cmp (UDP *a, UDP *b) -{ -if (a->hi < b->hi) return -1; /* compare hi */ -if (a->hi > b->hi) return +1; -if (a->lo < b->lo) return -1; /* hi =, compare lo */ -if (a->lo > b->lo) return +1; -return 0; /* hi, lo equal */ -} - -void dp_add (UDP *a, UDP *b) -{ -a->lo = (a->lo + b->lo) & M32; /* add lo */ -if (a->lo < b->lo) a->hi = a->hi + 1; /* carry? */ -a->hi = (a->hi + b->hi) & M32; /* add hi */ -return; -} - -void dp_inc (UDP *a) -{ -a->lo = (a->lo + 1) & M32; /* inc lo */ -if (a->lo == 0) a->hi = (a->hi + 1) & M32; /* carry? inc hi */ -return; -} - -void dp_sub (UDP *a, UDP *b) -{ -if (a->lo < b->lo) a->hi = a->hi - 1; /* borrow? decr hi */ -a->lo = (a->lo - b->lo) & M32; /* sub lo */ -a->hi = (a->hi - b->hi) & M32; /* sub hi */ -return; -} - -void dp_lsh (UDP *r, uint32 sc) -{ -if (sc > 63) r->hi = r->lo = 0; /* > 63? result 0 */ -else if (sc > 31) { /* [32,63]? */ - r->hi = (r->lo << (sc - 32)) & M32; - r->lo = 0; } -else if (sc != 0) { - r->hi = ((r->hi << sc) | (r->lo >> (32 - sc))) & M32; - r->lo = (r->lo << sc) & M32; } -return; -} - -void dp_rsh (UDP *r, uint32 sc) -{ -if (sc > 63) r->hi = r->lo = 0; /* > 63? result 0 */ -else if (sc > 31) { /* [32,63]? */ - r->lo = (r->hi >> (sc - 32)) & M32; - r->hi = 0; } -else if (sc != 0) { - r->lo = ((r->lo >> sc) | (r->hi << (32 - sc))) & M32; - r->hi = (r->hi >> sc) & M32; } -return; -} - -void dp_rsh_s (UDP *r, uint32 sc, uint32 neg) -{ -dp_rsh (r, sc); /* do unsigned right */ -if (neg && sc) { /* negative? */ - if (sc > 63) r->hi = r->lo = M32; /* > 63? result -1 */ - else { - UDP ones = { M32, M32 }; - dp_lsh (&ones, 64 - sc); /* shift ones */ - r->hi = r->hi | ones.hi; /* or into result */ - r->lo = r->lo | ones.lo; } } -return; -} - -void dp_imul (uint32 a, uint32 b, UDP *r) -{ -uint32 ah, bh, al, bl, rhi, rlo, rmid1, rmid2; - -if ((a == 0) || (b == 0)) { /* zero argument? */ - r->hi = r->lo = 0; /* result is zero */ - return; } -ah = (a >> 16) & M16; /* split operands */ -bh = (b >> 16) & M16; /* into 16b chunks */ -al = a & M16; -bl = b & M16; -rhi = ah * bh; /* high result */ -rmid1 = ah * bl; -rmid2 = al * bh; -rlo = al * bl; -rhi = rhi + ((rmid1 >> 16) & M16) + ((rmid2 >> 16) & M16); -rmid1 = (rlo + (rmid1 << 16)) & M32; /* add mid1 to lo */ -if (rmid1 < rlo) rhi = rhi + 1; /* carry? incr hi */ -rmid2 = (rmid1 + (rmid2 << 16)) & M32; /* add mid2 to to */ -if (rmid2 < rmid1) rhi = rhi + 1; /* carry? incr hi */ -r->hi = rhi & M32; /* mask result */ -r->lo = rmid2; -return; -} - -void dp_neg (UDP *r) -{ -r->lo = NEG32 (r->lo); -r->hi = (~r->hi + (r->lo == 0)) & M32; -return; -} - -/* Support routines */ - -void unpackf (uint32 hi, UFP *r) -{ -r->sign = hi & FPSIGN; /* get sign */ -r->exp = FD_GETEXP (hi); /* get exponent */ -if (r->exp == 0) { /* exp = 0? */ - if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ - r->frac.hi = r->frac.lo = 0; /* else 0 */ - return; } -r->frac.hi = WORDSWAP ((hi & ~(FPSIGN | FD_EXP)) | FD_HB); -r->frac.lo = 0; -dp_lsh (&r->frac, FD_GUARD); -return; -} - -void unpackd (uint32 hi, uint32 lo, UFP *r) -{ -r->sign = hi & FPSIGN; /* get sign */ -r->exp = FD_GETEXP (hi); /* get exponent */ -if (r->exp == 0) { /* exp = 0? */ - if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ - r->frac.hi = r->frac.lo = 0; /* else 0 */ - return; } -r->frac.hi = WORDSWAP ((hi & ~(FPSIGN | FD_EXP)) | FD_HB); -r->frac.lo = WORDSWAP (lo); -dp_lsh (&r->frac, FD_GUARD); -return; -} - -void unpackg (uint32 hi, uint32 lo, UFP *r) -{ -r->sign = hi & FPSIGN; /* get sign */ -r->exp = G_GETEXP (hi); /* get exponent */ -if (r->exp == 0) { /* exp = 0? */ - if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ - r->frac.hi = r->frac.lo = 0; /* else 0 */ - return; } -r->frac.hi = WORDSWAP ((hi & ~(FPSIGN | G_EXP)) | G_HB); -r->frac.lo = WORDSWAP (lo); -dp_lsh (&r->frac, G_GUARD); -return; -} - -void norm (UFP *r) -{ -int32 i; -static uint32 normmask[5] = { - 0xc0000000, 0xf0000000, 0xff000000, 0xffff0000, 0xffffffff }; -static int32 normtab[6] = { 1, 2, 4, 8, 16, 32}; - -if ((r->frac.hi == 0) && (r->frac.lo == 0)) { /* if fraction = 0 */ - r->sign = r->exp = 0; /* result is 0 */ - return; } -while ((r->frac.hi & UF_NM_H) == 0) { /* normalized? */ - for (i = 0; i < 5; i++) { /* find first 1 */ - if (r->frac.hi & normmask[i]) break; } - dp_lsh (&r->frac, normtab[i]); /* shift frac */ - r->exp = r->exp - normtab[i]; } /* decr exp */ -return; -} - -int32 rpackfd (UFP *r, int32 *rh) -{ -static UDP f_round = { UF_FRND_L, UF_FRND_H }; -static UDP d_round = { UF_DRND_L, UF_DRND_H }; - -if (rh) *rh = 0; /* assume 0 */ -if ((r->frac.hi == 0) && (r->frac.lo == 0)) return 0; /* result 0? */ -if (rh) dp_add (&r->frac, &d_round); /* round */ -else dp_add (&r->frac, &f_round); -if ((r->frac.hi & UF_NM_H) == 0) { /* carry out? */ - dp_rsh (&r->frac, 1); /* renormalize */ - r->exp = r->exp + 1; } -if (r->exp > (int32) FD_M_EXP) FLT_OVFL_FAULT; /* ovflo? fault */ -if (r->exp <= 0) { /* underflow? */ - if (PSL & PSW_FU) FLT_UNFL_FAULT; /* fault if fu */ - return 0; } /* else 0 */ -dp_rsh (&r->frac, FD_GUARD); /* remove guard */ -if (rh) *rh = WORDSWAP (r->frac.lo); /* get low */ -return r->sign | (r->exp << FD_V_EXP) | - (WORDSWAP (r->frac.hi) & ~(FD_HB | FPSIGN | FD_EXP)); -} - -int32 rpackg (UFP *r, int32 *rh) -{ -static UDP g_round = { UF_GRND_L, UF_GRND_H }; - -*rh = 0; /* assume 0 */ -if ((r->frac.hi == 0) && (r->frac.lo == 0)) return 0; /* result 0? */ -dp_add (&r->frac, &g_round); /* round */ -if ((r->frac.hi & UF_NM_H) == 0) { /* carry out? */ - dp_rsh (&r->frac, 1); /* renormalize */ - r->exp = r->exp + 1; } -if (r->exp > (int32) G_M_EXP) FLT_OVFL_FAULT; /* ovflo? fault */ -if (r->exp <= 0) { /* underflow? */ - if (PSL & PSW_FU) FLT_UNFL_FAULT; /* fault if fu */ - return 0; } /* else 0 */ -dp_rsh (&r->frac, G_GUARD); /* remove guard */ -*rh = WORDSWAP (r->frac.lo); /* get low */ -return r->sign | (r->exp << G_V_EXP) | - (WORDSWAP (r->frac.hi) & ~(G_HB | FPSIGN | G_EXP)); -} - -#endif - -/* Floating point instructions */ - -/* Move/test/move negated floating - - Note that only the high 32b is processed. - If the high 32b is not zero, it is unchanged. -*/ - -int32 op_movfd (int32 val) -{ -if (val & FD_EXP) return val; -if (val & FPSIGN) RSVD_OPND_FAULT; -return 0; -} - -int32 op_mnegfd (int32 val) -{ -if (val & FD_EXP) return (val ^ FPSIGN); -if (val & FPSIGN) RSVD_OPND_FAULT; -return 0; -} - -int32 op_movg (int32 val) -{ -if (val & G_EXP) return val; -if (val & FPSIGN) RSVD_OPND_FAULT; -return 0; -} - -int32 op_mnegg (int32 val) -{ -if (val & G_EXP) return (val ^ FPSIGN); -if (val & FPSIGN) RSVD_OPND_FAULT; -return 0; -} - -/* Floating to floating convert - F to D is essentially done with MOVFD */ - -int32 op_cvtdf (int32 *opnd) -{ -UFP a; - -unpackd (opnd[0], opnd[1], &a); -return rpackfd (&a, NULL); -} - -int32 op_cvtfg (int32 *opnd, int32 *rh) -{ -UFP a; - -unpackf (opnd[0], &a); -a.exp = a.exp - FD_BIAS + G_BIAS; -return rpackg (&a, rh); -} - -int32 op_cvtgf (int32 *opnd) -{ -UFP a; - -unpackg (opnd[0], opnd[1], &a); -a.exp = a.exp - G_BIAS + FD_BIAS; -return rpackfd (&a, NULL); -} - -/* Floating add and subtract */ - -int32 op_addf (int32 *opnd, t_bool sub) -{ -UFP a, b; - -unpackf (opnd[0], &a); /* F format */ -unpackf (opnd[1], &b); -if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */ -vax_fadd (&a, &b, 0); /* add fractions */ -return rpackfd (&a, NULL); -} - -int32 op_addd (int32 *opnd, int32 *rh, t_bool sub) -{ -UFP a, b; - -unpackd (opnd[0], opnd[1], &a); -unpackd (opnd[2], opnd[3], &b); -if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */ -vax_fadd (&a, &b, 0); /* add fractions */ -return rpackfd (&a, rh); -} - -int32 op_addg (int32 *opnd, int32 *rh, t_bool sub) -{ -UFP a, b; - -unpackg (opnd[0], opnd[1], &a); -unpackg (opnd[2], opnd[3], &b); -if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */ -vax_fadd (&a, &b, 0); /* add fractions */ -return rpackg (&a, rh); /* round and pack */ -} - -/* Floating multiply */ - -int32 op_mulf (int32 *opnd) -{ -UFP a, b; - -unpackf (opnd[0], &a); /* F format */ -unpackf (opnd[1], &b); -vax_fmul (&a, &b, 24, FD_BIAS, 0); /* do multiply */ -return rpackfd (&a, NULL); /* round and pack */ -} - -int32 op_muld (int32 *opnd, int32 *rh) -{ -UFP a, b; - -unpackd (opnd[0], opnd[1], &a); -unpackd (opnd[2], opnd[3], &b); -vax_fmul (&a, &b, 56, FD_BIAS, 0); /* do multiply */ -return rpackfd (&a, rh); /* round and pack */ -} - -int32 op_mulg (int32 *opnd, int32 *rh) -{ -UFP a, b; - -unpackg (opnd[0], opnd[1], &a); /* G format */ -unpackg (opnd[2], opnd[3], &b); -vax_fmul (&a, &b, 53, G_BIAS, 0); /* do multiply */ -return rpackg (&a, rh); /* round and pack */ -} - -/* Floating divide */ - -int32 op_divf (int32 *opnd) -{ -UFP a, b; - -unpackf (opnd[0], &a); /* F format */ -unpackf (opnd[1], &b); -vax_fdiv (&a, &b, 26, FD_BIAS); /* do divide */ -return rpackfd (&b, NULL); /* round and pack */ -} - -int32 op_divd (int32 *opnd, int32 *rh) -{ -UFP a, b; - -unpackd (opnd[0], opnd[1], &a); -unpackd (opnd[2], opnd[3], &b); -vax_fdiv (&a, &b, 58, FD_BIAS); /* do divide */ -return rpackfd (&b, rh); /* round and pack */ -} - -int32 op_divg (int32 *opnd, int32 *rh) -{ -UFP a, b; - -unpackg (opnd[0], opnd[1], &a); /* G format */ -unpackg (opnd[2], opnd[3], &b); -vax_fdiv (&a, &b, 55, G_BIAS); /* do divide */ -return rpackg (&b, rh); /* round and pack */ -} - -/* Polynomial evaluation - The most mis-implemented instruction in the VAX (probably here too). - POLY requires a precise combination of masking versus normalizing - to achieve the desired answer. In particular, both the multiply - and add steps are masked prior to normalization. In addition, - negative small fractions must not be treated as 0 during denorm. -*/ - -void op_polyf (int32 *opnd, int32 acc) -{ -UFP r, a, c; -int32 deg = opnd[1]; -int32 ptr = opnd[2]; -int32 i, wd, res; - -if (deg > 31) RSVD_OPND_FAULT; /* degree > 31? fault */ -unpackf (opnd[0], &a); /* unpack arg */ -wd = Read (ptr, L_LONG, RD); /* get C0 */ -ptr = ptr + 4; -unpackf (wd, &r); /* unpack C0 */ -res = rpackfd (&r, NULL); /* first result */ -for (i = 0; (i < deg) && a.exp; i++) { /* loop */ - unpackf (res, &r); /* unpack result */ - vax_fmul (&r, &a, 32, FD_BIAS, M32); /* r = r * arg */ - wd = Read (ptr, L_LONG, RD); /* get Cnext */ - ptr = ptr + 4; - unpackf (wd, &c); /* unpack Cnext */ - vax_fadd (&r, &c, M32); /* r = r + Cnext */ - res = rpackfd (&r, NULL); } /* round and pack */ -R[0] = res; -R[1] = R[2] = 0; -R[3] = opnd[2] + 4 + (opnd[1] << 2); -return; -} - -void op_polyd (int32 *opnd, int32 acc) -{ -UFP r, a, c; -int32 deg = opnd[2]; -int32 ptr = opnd[3]; -int32 i, wd, wd1, res, resh; - -if (deg > 31) RSVD_OPND_FAULT; /* degree > 31? fault */ -unpackd (opnd[0], opnd[1], &a); /* unpack arg */ -wd = Read (ptr, L_LONG, RD); /* get C0 */ -wd1 = Read (ptr + 4, L_LONG, RD); -ptr = ptr + 8; -unpackd (wd, wd1, &r); /* unpack C0 */ -res = rpackfd (&r, &resh); /* first result */ -for (i = 0; (i < deg) && a.exp; i++) { /* loop */ - unpackd (res, resh, &r); /* unpack result */ - vax_fmul (&r, &a, 32, FD_BIAS, 0); /* r = r * arg */ - wd = Read (ptr, L_LONG, RD); /* get Cnext */ - wd1 = Read (ptr + 4, L_LONG, RD); - ptr = ptr + 8; - unpackd (wd, wd1, &c); /* unpack Cnext */ - vax_fadd (&r, &c, 0); /* r = r + Cnext */ - res = rpackfd (&r, &resh); } /* round and pack */ -R[0] = res; -R[1] = resh; -R[2] = 0; -R[3] = opnd[3] + 4 + (opnd[2] << 2); -return; -} - -void op_polyg (int32 *opnd, int32 acc) -{ -UFP r, a, c; -int32 deg = opnd[2]; -int32 ptr = opnd[3]; -int32 i, wd, wd1, res, resh; - -if (deg > 31) RSVD_OPND_FAULT; /* degree > 31? fault */ -unpackg (opnd[0], opnd[1], &a); /* unpack arg */ -wd = Read (ptr, L_LONG, RD); /* get C0 */ -wd1 = Read (ptr + 4, L_LONG, RD); -ptr = ptr + 8; -unpackg (wd, wd1, &r); /* unpack C0 */ -res = rpackg (&r, &resh); /* first result */ -for (i = 0; (i < deg) && a.exp; i++) { /* loop */ - unpackg (res, resh, &r); /* unpack result */ - vax_fmul (&r, &a, 32, G_BIAS, 0); /* r = r * arg */ - wd = Read (ptr, L_LONG, RD); /* get Cnext */ - wd1 = Read (ptr + 4, L_LONG, RD); - ptr = ptr + 8; - unpackg (wd, wd1, &c); /* unpack Cnext */ - vax_fadd (&r, &c, 0); /* r = r + Cnext */ - res = rpackg (&r, &resh); } /* round and pack */ -R[0] = res; -R[1] = resh; -R[2] = 0; -R[3] = opnd[3] + 4 + (opnd[2] << 2); -return; -} diff --git a/VAX/vax_io.c b/VAX/vax_io.c deleted file mode 100644 index 5074b68e..00000000 --- a/VAX/vax_io.c +++ /dev/null @@ -1,950 +0,0 @@ -/* vax_io.c: VAX Qbus IO simulator - - Copyright (c) 1998-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - qba Qbus adapter - - 19-Apr-03 RMS Added optimized byte and word DMA routines - 12-Mar-03 RMS Added logical name support - 22-Dec-02 RMS Added console halt support - 12-Oct-02 RMS Added autoconfigure support - Added SHOW IO space routine - 29-Sep-02 RMS Added dynamic table support - 07-Sep-02 RMS Added TMSCP and variable vector support -*/ - -#include "vax_defs.h" - -/* CQBIC system configuration register */ - -#define CQSCR_POK 0x00008000 /* power ok RO1 */ -#define CQSCR_BHL 0x00004000 /* BHALT enb */ -#define CQSCR_AUX 0x00000400 /* aux mode RONI */ -#define CQSCR_DBO 0x0000000C /* offset NI */ -#define CQSCR_RW (CQSCR_BHL | CQSCR_DBO) -#define CQSCR_MASK (CQSCR_RW | CQSCR_POK | CQSCR_AUX) - -/* CQBIC DMA system error register - W1C */ - -#define CQDSER_BHL 0x00008000 /* BHALT NI */ -#define CQDSER_DCN 0x00004000 /* DC ~OK NI */ -#define CQDSER_MNX 0x00000080 /* master NXM */ -#define CQDSER_MPE 0x00000020 /* master par NI */ -#define CQDSER_SME 0x00000010 /* slv mem err NI */ -#define CQDSER_LST 0x00000008 /* lost err */ -#define CQDSER_TMO 0x00000004 /* no grant NI */ -#define CQDSER_SNX 0x00000001 /* slave NXM */ -#define CQDSER_ERR (CQDSER_MNX | CQDSER_MPE | CQDSER_TMO | CQDSER_SNX) -#define CQDSER_MASK 0x0000C0BD - -/* CQBIC master error address register */ - -#define CQMEAR_MASK 0x00001FFF /* Qbus page */ - -/* CQBIC slave error address register */ - -#define CQSEAR_MASK 0x000FFFFF /* mem page */ - -/* CQBIC map base register */ - -#define CQMBR_MASK 0x1FFF8000 /* 32KB aligned */ - -/* CQBIC IPC register */ - -#define CQIPC_QME 0x00008000 /* Qbus read NXM W1C */ -#define CQIPC_INV 0x00004000 /* CAM inval NIWO */ -#define CQIPC_AHLT 0x00000100 /* aux halt NI */ -#define CQIPC_DBIE 0x00000040 /* dbell int enb NI */ -#define CQIPC_LME 0x00000020 /* local mem enb */ -#define CQIPC_DB 0x00000001 /* doorbell req NI */ -#define CQIPC_W1C CQIPC_QME -#define CQIPC_RW (CQIPC_AHLT | CQIPC_DBIE | CQIPC_LME | CQIPC_DB) -#define CQIPC_MASK (CQIPC_RW | CQIPC_QME ) - -/* CQBIC map entry */ - -#define CQMAP_VLD 0x80000000 /* valid */ -#define CQMAP_PAG 0x000FFFFF /* mem page */ - -int32 int_req[IPL_HLVL] = { 0 }; /* intr, IPL 14-17 */ -int32 cq_scr = 0; /* SCR */ -int32 cq_dser = 0; /* DSER */ -int32 cq_mear = 0; /* MEAR */ -int32 cq_sear = 0; /* SEAR */ -int32 cq_mbr = 0; /* MBR */ -int32 cq_ipc = 0; /* IPC */ - -extern uint32 *M; -extern UNIT cpu_unit; -extern int32 PSL, SISR, trpirq, mem_err, hlt_pin; -extern int32 p1; -extern int32 ssc_bto; -extern jmp_buf save_env; -extern DEVICE *sim_devices[]; - -extern int32 ReadB (uint32 pa); -extern int32 ReadW (uint32 pa); -extern int32 ReadL (uint32 pa); -extern int32 WriteB (uint32 pa, int32 val); -extern int32 WriteW (uint32 pa, int32 val); -extern int32 WriteL (uint32 pa, int32 val); -extern FILE *sim_log; - -t_stat dbl_rd (int32 *data, int32 addr, int32 access); -t_stat dbl_wr (int32 data, int32 addr, int32 access); -int32 eval_int (void); -void cq_merr (int32 pa); -void cq_serr (int32 pa); -t_stat qba_reset (DEVICE *dptr); - -/* Qbus adapter data structures - - qba_dev QBA device descriptor - qba_unit QBA units - qba_reg QBA register list -*/ - -DIB qba_dib = { IOBA_DBL, IOLN_DBL, &dbl_rd, &dbl_wr, 0 }; - -UNIT qba_unit = { UDATA (NULL, 0, 0) }; - -REG qba_reg[] = { - { HRDATA (SCR, cq_scr, 16) }, - { HRDATA (DSER, cq_dser, 8) }, - { HRDATA (MEAR, cq_mear, 13) }, - { HRDATA (SEAR, cq_sear, 20) }, - { HRDATA (MBR, cq_mbr, 29) }, - { HRDATA (IPC, cq_ipc, 16) }, - { HRDATA (IPL17, int_req[3], 32), REG_RO }, - { HRDATA (IPL16, int_req[2], 32), REG_RO }, - { HRDATA (IPL15, int_req[1], 32), REG_RO }, - { HRDATA (IPL14, int_req[0], 32), REG_RO }, - { NULL } }; - -DEVICE qba_dev = { - "QBA", &qba_unit, qba_reg, NULL, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &qba_reset, - NULL, NULL, NULL, - &qba_dib, DEV_QBUS }; - -/* IO page addresses */ - -DIB *dib_tab[DIB_MAX]; /* DIB table */ - -/* Interrupt request to interrupt action map */ - -int32 (*int_ack[IPL_HLVL][32])(); /* int ack routines */ - -/* Interrupt request to vector map */ - -int32 int_vec[IPL_HLVL][32]; /* int req to vector */ - -/* The KA65x handles errors in I/O space as follows - - - read: set DSER<7>, latch addr in MEAR, machine check - - write: set DSER<7>, latch addr in MEAR, MEMERR interrupt -*/ - -int32 ReadQb (uint32 pa) -{ -int32 i, val; -DIB *dibp; - -for (i = 0; dibp = dib_tab[i]; i++ ) { - if ((pa >= dibp->ba) && - (pa < (dibp->ba + dibp->lnt))) { - dibp->rd (&val, pa, READ); - return val; } } -cq_merr (pa); -MACH_CHECK (MCHK_READ); -return 0; -} - -void WriteQb (uint32 pa, int32 val, int32 mode) -{ -int32 i; -DIB *dibp; - -for (i = 0; dibp = dib_tab[i]; i++ ) { - if ((pa >= dibp->ba) && - (pa < (dibp->ba + dibp->lnt))) { - dibp->wr (val, pa, mode); - return; } } -cq_merr (pa); -mem_err = 1; -return; -} - -/* ReadIO - read I/O space - - Inputs: - pa = physical address - lnt = length (BWLQ) - Output: - longword of data -*/ - -int32 ReadIO (int32 pa, int32 lnt) -{ -int32 iod; - -iod = ReadQb (pa); /* wd from Qbus */ -if (lnt < L_LONG) iod = iod << ((pa & 2)? 16: 0); /* bw? position */ -else iod = (ReadQb (pa + 2) << 16) | iod; /* lw, get 2nd wd */ -SET_IRQL; -return iod; -} - -/* WriteIO - write I/O space - - Inputs: - pa = physical address - val = data to write, right justified in 32b longword - lnt = length (BWLQ) - Outputs: - none -*/ - -void WriteIO (int32 pa, int32 val, int32 lnt) -{ -if (lnt == L_BYTE) WriteQb (pa, val, WRITEB); -else if (lnt == L_WORD) WriteQb (pa, val, WRITE); -else { WriteQb (pa, val & 0xFFFF, WRITE); - WriteQb (pa + 2, (val >> 16) & 0xFFFF, WRITE); } -SET_IRQL; -return; -} - -/* Find highest priority outstanding interrupt */ - -int32 eval_int (void) -{ -int32 ipl = PSL_GETIPL (PSL); -int32 i, t; - -static const int32 sw_int_mask[IPL_SMAX] = { - 0xFFFE, 0xFFFC, 0xFFF8, 0xFFF0, /* 0 - 3 */ - 0xFFE0, 0xFFC0, 0xFF80, 0xFF00, /* 4 - 7 */ - 0xFE00, 0xFC00, 0xF800, 0xF000, /* 8 - B */ - 0xE000, 0xC000, 0x8000 }; /* C - E */ - -if (hlt_pin) return IPL_HLTPIN; /* hlt pin int */ -if ((ipl < IPL_MEMERR) && mem_err) return IPL_MEMERR; /* mem err int */ -for (i = IPL_HMAX; i >= IPL_HMIN; i--) { /* chk hwre int */ - if (i <= ipl) return 0; /* at ipl? no int */ - if (int_req[i - IPL_HMIN]) return i; } /* req != 0? int */ -if (ipl >= IPL_SMAX) return 0; /* ipl >= sw max? */ -if ((t = SISR & sw_int_mask[ipl]) == 0) return 0; /* eligible req */ -for (i = IPL_SMAX; i > ipl; i--) { /* check swre int */ - if ((t >> i) & 1) return i; } /* req != 0? int */ -return 0; -} - -/* Return vector for highest priority hardware interrupt at IPL lvl */ - -int32 get_vector (int32 lvl) -{ -int32 i; -int32 l = lvl - IPL_HMIN; - -for (i = 0; int_req[l] && (i < 32); i++) { - if ((int_req[l] >> i) & 1) { - int_req[l] = int_req[l] & ~(1u << i); - if (int_ack[l][i]) return int_ack[l][i](); - return int_vec[l][i]; } } -return 0; -} - -/* CQBIC registers - - SCR system configuration register - DSER DMA system error register (W1C) - MEAR master error address register (RO) - SEAR slave error address register (RO) - MBR map base register - IPC inter-processor communication register -*/ - -int32 cqbic_rd (int32 pa) -{ -int32 rg = (pa - CQBICBASE) >> 2; - -switch (rg) { -case 0: /* SCR */ - return (cq_scr | CQSCR_POK) & CQSCR_MASK; -case 1: /* DSER */ - return cq_dser & CQDSER_MASK; -case 2: /* MEAR */ - return cq_mear & CQMEAR_MASK; -case 3: /* SEAR */ - return cq_sear & CQSEAR_MASK; -case 4: /* MBR */ - return cq_mbr & CQMBR_MASK; } -return 0; -} - -void cqbic_wr (int32 pa, int32 val, int32 lnt) -{ -int32 nval, rg = (pa - CQBICBASE) >> 2; - -if (lnt < L_LONG) { - int32 sc = (pa & 3) << 3; - int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF; - int32 t = cqbic_rd (pa); - nval = ((val & mask) << sc) | (t & ~(mask << sc)); - val = val << sc; } -else nval = val; - -switch (rg) { -case 0: /* SCR */ - cq_scr = ((cq_scr & ~CQSCR_RW) | (nval & CQSCR_RW)) & CQSCR_MASK; - break; -case 1: /* DSER */ - cq_dser = (cq_dser & ~val) & CQDSER_MASK; - if (val & CQDSER_SME) cq_ipc = cq_ipc & ~CQIPC_QME; - break; -case 2: case 3: - cq_merr (pa); /* MEAR, SEAR */ - MACH_CHECK (MCHK_WRITE); - break; -case 4: /* MBR */ - cq_mbr = nval & CQMBR_MASK; - break; } -return; -} - -/* IPC can be read as local register or as Qbus I/O - Because of the W1C */ - -int32 cqipc_rd (int32 pa) -{ -return cq_ipc & CQIPC_MASK; /* IPC */ -} - -void cqipc_wr (int32 pa, int32 val, int32 lnt) -{ -int32 nval = val; - -if (lnt < L_LONG) { - int32 sc = (pa & 3) << 3; - nval = val << sc; } - -cq_ipc = cq_ipc & ~(nval & CQIPC_W1C); /* W1C */ -if ((pa & 3) == 0) /* low byte only */ - cq_ipc = ((cq_ipc & ~CQIPC_RW) | (val & CQIPC_RW)) & CQIPC_MASK; -return; -} - -/* I/O page routines */ - -t_stat dbl_rd (int32 *data, int32 addr, int32 access) -{ -*data = cq_ipc & CQIPC_MASK; -return SCPE_OK; -} - -t_stat dbl_wr (int32 data, int32 addr, int32 access) -{ -cqipc_wr (addr, data, (access == WRITEB)? L_BYTE: L_WORD); -return SCPE_OK; -} - -/* CQBIC map read and write (reflects to main memory) - - Read error: set DSER<0>, latch slave address, machine check - Write error: set DSER<0>, latch slave address, memory error interrupt -*/ - -int32 cqmap_rd (int32 pa) -{ -int32 ma = (pa & CQMAPAMASK) + cq_mbr; /* mem addr */ - -if (ADDR_IS_MEM (ma)) return M[ma >> 2]; -cq_serr (ma); /* set err */ -MACH_CHECK (MCHK_READ); /* mcheck */ -return 0; -} - -void cqmap_wr (int32 pa, int32 val, int32 lnt) -{ -int32 ma = (pa & CQMAPAMASK) + cq_mbr; /* mem addr */ - -if (ADDR_IS_MEM (ma)) { - if (lnt < L_LONG) { - int32 sc = (pa & 3) << 3; - int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF; - int32 t = M[ma >> 2]; - val = ((val & mask) << sc) | (t & ~(mask << sc)); } - M[ma >> 2] = val; } -else { cq_serr (ma); /* error */ - mem_err = 1; } -return; -} - -/* CQBIC Qbus memory read and write (reflects to main memory) - - May give master or slave error, depending on where the failure occurs -*/ - -int32 cqmem_rd (int32 pa) -{ -int32 qa = pa & CQMAMASK; /* Qbus addr */ -uint32 ma; - -if (map_addr (qa, &ma)) return M[ma >> 2]; /* map addr */ -MACH_CHECK (MCHK_READ); /* err? mcheck */ -return 0; -} - -void cqmem_wr (int32 pa, int32 val, int32 lnt) -{ -int32 qa = pa & CQMAMASK; /* Qbus addr */ -uint32 ma; - -if (map_addr (qa, &ma)) { /* map addr */ - if (lnt < L_LONG) { - int32 sc = (pa & 3) << 3; - int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF; - int32 t = M[ma >> 2]; - val = ((val & mask) << sc) | (t & ~(mask << sc)); } - M[ma >> 2] = val; } -else mem_err = 1; -return; -} - -/* Map an address via the translation map */ - -t_bool map_addr (uint32 qa, uint32 *ma) -{ -int32 qblk = (qa >> VA_V_VPN); /* Qbus blk */ -int32 qmma = ((qblk << 2) & CQMAPAMASK) + cq_mbr; /* map entry */ - -if (ADDR_IS_MEM (qmma)) { /* legit? */ - int32 qmap = M[qmma >> 2]; /* get map */ - if (qmap & CQMAP_VLD) { /* valid? */ - *ma = ((qmap & CQMAP_PAG) << VA_V_VPN) + VA_GETOFF (qa); - if (ADDR_IS_MEM (*ma)) return 1; /* legit addr */ - cq_serr (*ma); /* slave nxm */ - return 0; } - cq_merr (qa); /* master nxm */ - return 0; } -cq_serr (0); /* inv mem */ -return 0; -} - -/* Set master error */ - -void cq_merr (int32 pa) -{ -if (cq_dser & CQDSER_ERR) cq_dser = cq_dser | CQDSER_LST; -cq_dser = cq_dser | CQDSER_MNX; /* master nxm */ -cq_mear = (pa >> VA_V_VPN) & CQMEAR_MASK; /* page addr */ -return; -} - -/* Set slave error */ - -void cq_serr (int32 pa) -{ -if (cq_dser & CQDSER_ERR) cq_dser = cq_dser | CQDSER_LST; -cq_dser = cq_dser | CQDSER_SNX; /* slave nxm */ -cq_sear = (pa >> VA_V_VPN) & CQSEAR_MASK; -return; -} - -/* Reset I/O bus */ - -void ioreset_wr (int32 data) -{ -reset_all (5); /* from qba on... */ -return; -} - -/* Reset CQBIC */ - -t_stat qba_reset (DEVICE *dptr) -{ -int32 i; - -cq_scr = (cq_scr & CQSCR_BHL) | CQSCR_POK; -cq_dser = cq_mear = cq_sear = cq_ipc = 0; -for (i = 0; i < IPL_HLVL; i++) int_req[i] = 0; -return SCPE_OK; -} - -/* Powerup CQBIC */ - -t_stat qba_powerup (void) -{ -cq_mbr = 0; -cq_scr = CQSCR_POK; -return qba_reset (&qba_dev); -} - -/* I/O buffer routines, aligned access - - map_ReadB - fetch byte buffer from memory - map_ReadW - fetch word buffer from memory - map_ReadL - fetch longword buffer from memory - map_WriteB - store byte buffer into memory - map_WriteW - store word buffer into memory - map_WriteL - store longword buffer into memory -*/ - -int32 map_readB (uint32 ba, int32 bc, uint8 *buf) -{ -int32 i; -uint32 ma, dat; - -if ((ba | bc) & 03) { /* check alignment */ - for (i = ma = 0; i < bc; i++, buf++) { /* by bytes */ - if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } - *buf = ReadB (ma); - ma = ma + 1; } - } -else { for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by longwords */ - if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } - dat = ReadL (ma); /* get lw */ - *buf++ = dat & BMASK; /* low 8b */ - *buf++ = (dat >> 8) & BMASK; /* next 8b */ - *buf++ = (dat >> 16) & BMASK; /* next 8b */ - *buf = (dat >> 24) & BMASK; - ma = ma + 4; } - } -return 0; -} - -int32 map_readW (uint32 ba, int32 bc, uint16 *buf) -{ -int32 i; -uint32 ma,dat; - -ba = ba & ~01; -bc = bc & ~01; -if ((ba | bc) & 03) { /* check alignment */ - for (i = ma = 0; i < bc; i = i + 2, buf++) { /* by words */ - if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } - *buf = ReadW (ma); - ma = ma + 2; } - } -else { for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by longwords */ - if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } - dat = ReadL (ma); /* get lw */ - *buf++ = dat & WMASK; /* low 16b */ - *buf = (dat >> 16) & WMASK; /* high 16b */ - ma = ma + 4; } - } -return 0; -} - -int32 map_readL (uint32 ba, int32 bc, uint32 *buf) -{ -int32 i; -uint32 ma; - -ba = ba & ~03; -bc = bc & ~03; -for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by lw */ - if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } - *buf = ReadL (ma); - ma = ma + 4; } -return 0; -} - -int32 map_writeB (uint32 ba, int32 bc, uint8 *buf) -{ -int32 i; -uint32 ma, dat; - -if ((ba | bc) & 03) { /* check alignment */ - for (i = ma = 0; i < bc; i++, buf++) { /* by bytes */ - if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } - WriteB (ma, *buf); - ma = ma + 1; } - } -else { for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by longwords */ - if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } - dat = (uint32) *buf++; /* get low 8b */ - dat = dat | (((uint32) *buf++) << 8); /* merge next 8b */ - dat = dat | (((uint32) *buf++) << 16); /* merge next 8b */ - dat = dat | (((uint32) *buf) << 24); /* merge hi 8b */ - WriteL (ma, dat); /* store lw */ - ma = ma + 4; } - } -return 0; -} - -int32 map_writeW (uint32 ba, int32 bc, uint16 *buf) -{ -int32 i; -uint32 ma, dat; - -ba = ba & ~01; -bc = bc & ~01; -if ((ba | bc) & 03) { /* check alignment */ - for (i = ma = 0; i < bc; i = i + 2, buf++) { /* by words */ - if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } - WriteW (ma, *buf); - ma = ma + 2; } - } -else { for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by longwords */ - if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } - dat = (uint32) *buf++; /* get low 16b */ - dat = dat | (((uint32) *buf) << 16); /* merge hi 16b */ - WriteL (ma, dat); /* store lw */ - ma = ma + 4; } - } -return 0; -} - -int32 map_writeL (uint32 ba, int32 bc, uint32 *buf) -{ -int32 i; -uint32 ma; - -ba = ba & ~03; -bc = bc & ~03; -for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by lw */ - if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } - WriteL (ma, *buf); - ma = ma + 4; } -return 0; -} - -/* Change device address */ - -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newba; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if ((val == 0) || (uptr == NULL)) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newba = (uint32) get_uint (cptr, 16, IOPAGEBASE+IOPAGEMASK, &r); /* get new */ -if (r != SCPE_OK) return r; -if ((newba <= IOPAGEBASE) || /* must be > 0 */ - (newba % ((uint32) val))) return SCPE_ARG; /* check modulus */ -dibp->ba = newba; /* store */ -dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */ -return auto_config (0, 0); /* autoconfigure */ -} - -/* Show device address */ - -t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -DEVICE *dptr; -DIB *dibp; - -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if ((dibp == NULL) || (dibp->ba <= IOPAGEBASE)) return SCPE_IERR; -fprintf (st, "address=%08X", dibp->ba); -if (dibp->lnt > 1) - fprintf (st, "-%08X", dibp->ba + dibp->lnt - 1); -if (dptr->flags & DEV_FLTA) fprintf (st, "*"); -return SCPE_OK; -} - -/* Set address floating */ - -t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; - -if (cptr == NULL) return SCPE_ARG; -if ((val == 0) || (uptr == NULL)) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dptr->flags = dptr->flags | DEV_FLTA; /* floating */ -return auto_config (0, 0); /* autoconfigure */ -} - -/* Change device vector */ - -t_stat set_vec (UNIT *uptr, int32 arg, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newvec; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newvec = (uint32) get_uint (cptr, 16, VEC_Q + 01000, &r); -if ((r != SCPE_OK) || (newvec <= VEC_Q) || - ((newvec + (dibp->vnum * 4)) >= (VEC_Q + 01000)) || - (newvec & ((dibp->vnum > 1)? 07: 03))) return SCPE_ARG; -dibp->vec = newvec; -return SCPE_OK; -} - -/* Show device vector */ - -t_stat show_vec (FILE *st, UNIT *uptr, int32 arg, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 vec, numvec; - -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -vec = dibp->vec; -if (arg) numvec = arg; -else numvec = dibp->vnum; -if (vec == 0) fprintf (st, "no vector"); -else { fprintf (st, "vector=%X", vec); - if (numvec > 1) fprintf (st, "-%X", vec + (4 * (numvec - 1))); } -return SCPE_OK; -} - -/* Test for conflict in device addresses */ - -t_bool dev_conflict (DIB *curr) -{ -uint32 i, end; -DEVICE *dptr; -DIB *dibp; - -end = curr->ba + curr->lnt - 1; /* get end */ -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if ((dibp == NULL) || (dibp == curr) || - (dptr->flags & DEV_DIS)) continue; - if (((curr->ba >= dibp->ba) && /* overlap start? */ - (curr->ba < (dibp->ba + dibp->lnt))) || - ((end >= dibp->ba) && /* overlap end? */ - (end < (dibp->ba + dibp->lnt)))) { - printf ("Device %s address conflict at %08X\n", - sim_dname (dptr), dibp->ba); - if (sim_log) fprintf (sim_log, - "Device %s address conflict at %08X\n", - sim_dname (dptr), dibp->ba); - return TRUE; } } -return FALSE; -} - -/* Build interrupt tables */ - -void build_int_vec (int32 vloc, int32 ivec, int32 (*iack)(void) ) -{ -int32 ilvl = vloc / 32; -int32 ibit = vloc % 32; - -if (iack != NULL) int_ack[ilvl][ibit] = iack; -else int_vec[ilvl][ibit] = ivec; -return; -} - -/* Build dib_tab from device list */ - -t_stat build_dib_tab (void) -{ -int32 i, j, k; -DEVICE *dptr; -DIB *dibp; - -for (i = 0; i < IPL_HLVL; i++) { /* clear int tables */ - for (j = 0; j < 32; j++) { - int_vec[i][j] = 0; - int_ack[i][j] = NULL; } } -for (i = j = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if (dibp && !(dptr->flags & DEV_DIS)) { /* defined, enabled? */ - if (dibp->vnum > VEC_DEVMAX) return SCPE_IERR; - for (k = 0; k < dibp->vnum; k++) /* loop thru vec */ - build_int_vec (dibp->vloc + k, /* add vector */ - dibp->vec + (k * 4), dibp->ack[k]); - if (dibp->lnt != 0) { /* I/O addresses? */ - dib_tab[j++] = dibp; /* add DIB to dib_tab */ - if (j >= DIB_MAX) return SCPE_IERR; } /* too many? */ - } /* end if enabled */ - } /* end for */ -dib_tab[j] = NULL; /* end with NULL */ -for (i = 0; (dibp = dib_tab[i]) != NULL; i++) { /* test built dib_tab */ - if (dev_conflict (dibp)) return SCPE_STOP; } /* for conflicts */ -return FALSE; -} - -/* Show dib_tab */ - -t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, j, done = 0; -DEVICE *dptr; -DIB *dibt; - -build_dib_tab (); /* build table */ -while (done == 0) { /* sort ascending */ - done = 1; /* assume done */ - for (i = 0; dib_tab[i + 1] != NULL; i++) { /* check table */ - if (dib_tab[i]->ba > dib_tab[i + 1]->ba) { /* out of order? */ - dibt = dib_tab[i]; /* interchange */ - dib_tab[i] = dib_tab[i + 1]; - dib_tab[i + 1] = dibt; - done = 0; } } /* not done */ - } /* end while */ -for (i = 0; dib_tab[i] != NULL; i++) { /* print table */ - for (j = 0, dptr = NULL; sim_devices[j] != NULL; j++) { - if (((DIB*) sim_devices[j]->ctxt) == dib_tab[i]) { - dptr = sim_devices[j]; - break; } } - fprintf (st, "%08X - %08X%c\t%s\n", dib_tab[i]->ba, - dib_tab[i]->ba + dib_tab[i]->lnt - 1, - (dptr && (dptr->flags & DEV_FLTA))? '*': ' ', - dptr? sim_dname (dptr): "CPU"); - } -return SCPE_OK; -} - -/* Autoconfiguration */ - -#define AUTO_DYN 0001 -#define AUTO_VEC 0002 -#define AUTO_MAXC 4 -#define AUTO_CSRBASE 0010 -#define AUTO_VECBASE 0300 - -struct auto_con { - uint32 amod; - uint32 vmod; - uint32 flags; - uint32 num; - uint32 fix; - char *dnam[AUTO_MAXC]; }; - -struct auto_con auto_tab[AUTO_LNT + 1] = { - { 0x7, 0x7 }, /* DJ11 */ - { 0xf, 0x7 }, /* DH11 */ - { 0x7, 0x7 }, /* DQ11 */ - { 0x7, 0x7 }, /* DU11 */ - { 0x7, 0x7 }, /* DUP11 */ - { 0x7, 0x7 }, /* LK11A */ - { 0x7, 0x7 }, /* DMC11 */ - { 0x7, 0x7, AUTO_VEC, DZ_MUXES, 0, { "DZ" } }, - - { 0x7, 0x7 }, /* KMC11 */ - { 0x7, 0x7 }, /* LPP11 */ - { 0x7, 0x7 }, /* VMV21 */ - { 0xf, 0x7 }, /* VMV31 */ - { 0x7, 0x7 }, /* DWR70 */ - { 0x7, 0x3, AUTO_DYN|AUTO_VEC, 0, IOBA_RL, { "RL", "RLB" } }, - { 0xf, 0x7 }, /* LPA11K */ - { 0x7, 0x7 }, /* KW11C */ - - { 0x7, 0 }, /* reserved */ - { 0x7, 0x3 }, /* RX11/RX211 */ - { 0x7, 0x3 }, /* DR11W */ - { 0x7, 0x3 }, /* DR11B */ - { 0x7, 0x7 }, /* DMP11 */ - { 0x7, 0x7 }, /* DPV11 */ - { 0x7, 0x7 }, /* ISB11 */ - { 0xf, 0x7 }, /* DMV11 */ - - { 0x7, 0x3 }, /* DEUNA/DELUA */ - { 0x3, 0x3, AUTO_DYN|AUTO_VEC, 0, IOBA_RQ, { "RQ", "RQB", "RQC", "RQD" } }, - { 0x1f, 0x3 }, /* DMF32 */ - { 0xf, 0x7 }, /* KMS11 */ - { 0xf, 0x3 }, /* VS100 */ - { 0x3, 0x3, AUTO_DYN|AUTO_VEC, 0, IOBA_TQ, { "TQ", "TQB" } }, - { 0xf, 0x7 }, /* KMV11 */ - { 0xf, 0x7 }, /* DHU11/DHQ11 */ - - { 0x1f, 0x7 }, /* DMZ32 */ - { 0x1f, 0x7 }, /* CP132 */ - { 0 }, /* padding */ -}; - -t_stat auto_config (uint32 rank, uint32 nctrl) -{ -uint32 csr = IOPAGEBASE + AUTO_CSRBASE; -uint32 vec = VEC_Q + AUTO_VECBASE; -struct auto_con *autp; -DEVICE *dptr; -DIB *dibp; -int32 i, j, k; -extern DEVICE *find_dev (char *ptr); - -if (rank > AUTO_LNT) return SCPE_IERR; /* legal rank? */ -if (rank) auto_tab[rank - 1].num = nctrl; /* update num? */ -for (i = 0, autp = auto_tab; i < AUTO_LNT; i++) { /* loop thru table */ - for (j = k = 0; (j < AUTO_MAXC) && autp->dnam[j]; j++) { - dptr = find_dev (autp->dnam[j]); /* find ctrl */ - if ((dptr == NULL) || (dptr->flags & DEV_DIS) || - !(dptr->flags & DEV_FLTA)) continue; /* enabled, floating? */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if ((k++ == 0) && autp->fix) /* 1st & fixed? */ - dibp->ba = autp->fix; /* gets fixed CSR */ - else { /* no, float */ - dibp->ba = csr; /* set CSR */ - csr = (csr + autp->amod + 1) & ~autp->amod; /* next CSR */ - if ((autp->flags & AUTO_DYN) == 0) /* static? */ - csr = csr + ((autp->num - 1) * (autp->amod + 1)); - if (autp->flags & AUTO_VEC) { /* vectors too? */ - dibp->vec = (vec + autp->vmod) & ~autp->vmod; - if (autp->flags & AUTO_DYN) vec = vec + autp->vmod + 1; - else vec = vec + (autp->num * (autp->vmod + 1)); } - } /* end else flt */ - } /* end for j */ - autp++; - csr = (csr + autp->amod + 1) & ~autp->amod; /* gap */ - } /* end for i */ -return SCPE_OK; -} diff --git a/VAX/vax_mmu.c b/VAX/vax_mmu.c deleted file mode 100644 index 1f131b23..00000000 --- a/VAX/vax_mmu.c +++ /dev/null @@ -1,538 +0,0 @@ -/* vax_mm.c - VAX memory management simulator - - Copyright (c) 1998-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 01-Jun-03 RMS Fixed compilation problem with USE_ADDR64 - - This module contains the instruction simulators for - - Read - read virtual - Write - write virtual - ReadL(P) - read aligned physical longword (physical context) - WriteL(P) - write aligned physical longword (physical context) - ReadB(W) - read aligned physical byte (word) - WriteB(W) - write aligned physical byte (word) - Test - test acccess - - zap_tb - clear TB - zap_tb_ent - clear TB entry - chk_tb_ent - check TB entry - set_map_reg - set up working map registers -*/ - -#include "vax_defs.h" -#include - -struct tlbent { - int32 tag; /* tag */ - int32 pte; /* pte */ -}; - -typedef struct tlbent TLBENT; - -extern uint32 *M; -extern uint32 align[4]; -extern int32 PSL; -extern int32 mapen; -extern int32 p1, p2; -extern int32 P0BR, P0LR; -extern int32 P1BR, P1LR; -extern int32 SBR, SLR; -extern int32 SISR; -extern jmp_buf save_env; -extern UNIT cpu_unit; - -int32 p0br, p0lr; /* dynamic copies */ -int32 p1br, p1lr; /* altered per ucode */ -int32 sbr, slr; -extern int32 mchk_va, mchk_ref; /* for mcheck */ -TLBENT stlb[VA_TBSIZE], ptlb[VA_TBSIZE]; -static const int32 insert[4] = { - 0x00000000, 0x000000FF, 0x0000FFFF, 0x00FFFFFF }; -static const int32 cvtacc[16] = { 0, 0, - TLB_ACCW (KERN)+TLB_ACCR (KERN), - TLB_ACCR (KERN), - TLB_ACCW (KERN)+TLB_ACCW (EXEC)+TLB_ACCW (SUPV)+TLB_ACCW (USER)+ - TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV)+TLB_ACCR (USER), - TLB_ACCW (KERN)+TLB_ACCW (EXEC)+TLB_ACCR (KERN)+TLB_ACCR (EXEC), - TLB_ACCW (KERN)+TLB_ACCR (KERN)+TLB_ACCR (EXEC), - TLB_ACCR (KERN)+TLB_ACCR (EXEC), - TLB_ACCW (KERN)+TLB_ACCW (EXEC)+TLB_ACCW (SUPV)+ - TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV), - TLB_ACCW (KERN)+TLB_ACCW (EXEC)+ - TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV), - TLB_ACCW (KERN)+TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV), - TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV), - TLB_ACCW (KERN)+TLB_ACCW (EXEC)+TLB_ACCW (SUPV)+ - TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV)+TLB_ACCR (USER), - TLB_ACCW (KERN)+TLB_ACCW (EXEC)+ - TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV)+TLB_ACCR (USER), - TLB_ACCW (KERN)+ - TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV)+TLB_ACCR (USER), - TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV)+TLB_ACCR (USER) -}; - -t_stat tlb_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat tlb_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat tlb_reset (DEVICE *dptr); - -TLBENT fill (uint32 va, int32 lnt, int32 acc, int32 *stat); -int32 ReadB (uint32 pa); -void WriteB (uint32 pa, int32 val); -int32 ReadW (uint32 pa); -void WriteW (uint32 pa, int32 val); -int32 ReadL (uint32 pa); -void WriteL (uint32 pa, int32 val); -int32 ReadLP (uint32 pa); -void WriteLP (uint32 pa, int32 val); -extern int32 ReadIO (uint32 pa, int32 lnt); -extern void WriteIO (uint32 pa, int32 val, int32 lnt); -extern int32 ReadReg (uint32 pa, int32 lnt); -extern void WriteReg (uint32 pa, int32 val, int32 lnt); - -/* TLB data structures - - tlb_dev pager device descriptor - tlb_unit pager units - pager_reg pager register list -*/ - -UNIT tlb_unit[] = { - { UDATA (NULL, UNIT_FIX, VA_TBSIZE * 2) }, - { UDATA (NULL, UNIT_FIX, VA_TBSIZE * 2) } }; - -REG tlb_reg[] = { - { NULL } }; - -DEVICE tlb_dev = { - "TLB", tlb_unit, tlb_reg, NULL, - 2, 16, VA_N_TBI * 2, 1, 16, 32, - &tlb_ex, &tlb_dep, &tlb_reset, - NULL, NULL, NULL }; - -/* Read and write virtual - - These routines logically fall into three phases: - - 1. Look up the virtual address in the translation buffer, calling - the fill routine on a tag mismatch or access mismatch (invalid - tlb entries have access = 0 and thus always mismatch). The - fill routine handles all errors. If the resulting physical - address is aligned, do an aligned physical read or write. - 2. Test for unaligned across page boundaries. If cross page, look - up the physical address of the second page. If not cross page, - the second physical address is the same as the first. - 3. Using the two physical addresses, do an unaligned read or - write, with three cases: unaligned long, unaligned word within - a longword, unaligned word crossing a longword boundary. -*/ - -/* Read virtual - - Inputs: - va = virtual address - lnt = length code (BWLQ) - acc = access code (KESU) - Output: - returned data, right justified in 32b longword -*/ - -int32 Read (uint32 va, int32 lnt, int32 acc) -{ -int32 vpn, off, tbi, pa; -int32 pa1, bo, sc, wl, wh; -TLBENT xpte; - -mchk_va = va; -if (mapen) { /* mapping on? */ - vpn = VA_GETVPN (va); /* get vpn, offset */ - off = VA_GETOFF (va); - tbi = VA_GETTBI (vpn); - xpte = (va & VA_S0)? stlb[tbi]: ptlb[tbi]; /* access tlb */ - if (((xpte.pte & acc) == 0) || (xpte.tag != vpn) || - ((acc & TLB_WACC) && ((xpte.pte & TLB_M) == 0))) - xpte = fill (va, lnt, acc, NULL); /* fill if needed */ - pa = (xpte.pte & TLB_PFN) | off; } /* get phys addr */ -else pa = va & PAMASK; -if ((pa & (lnt - 1)) == 0) { /* aligned? */ - if (lnt >= L_LONG) return ReadL (pa); /* long, quad? */ - if (lnt == L_WORD) return ReadW (pa); /* word? */ - return ReadB (pa); } /* byte */ -if (mapen && ((off + lnt) > VA_PAGSIZE)) { /* cross page? */ - vpn = VA_GETVPN (va + lnt); /* vpn 2nd page */ - tbi = VA_GETTBI (vpn); - xpte = (va & VA_S0)? stlb[tbi]: ptlb[tbi]; /* access tlb */ - if (((xpte.pte & acc) == 0) || (xpte.tag != vpn) || - ((acc & TLB_WACC) && ((xpte.pte & TLB_M) == 0))) - xpte = fill (va + lnt, lnt, acc, NULL); /* fill if needed */ - pa1 = (xpte.pte & TLB_PFN) | VA_GETOFF (va + 4); } -else pa1 = (pa + 4) & PAMASK; /* not cross page */ -bo = pa & 3; -if (lnt >= L_LONG) { /* lw unaligned? */ - sc = bo << 3; - wl = ReadL (pa); /* read both lw */ - wh = ReadL (pa1); /* extract */ - return (((wl >> sc) & align[bo]) | (wh << (32 - sc))); } -else if (bo == 1) return ((ReadL (pa) >> 8) & WMASK); -else { wl = ReadL (pa); /* word cross lw */ - wh = ReadL (pa1); /* read, extract */ - return (((wl >> 24) & 0xFF) | ((wh & 0xFF) << 8)); } -} - -/* Write virtual - - Inputs: - va = virtual address - val = data to be written, right justified in 32b lw - lnt = length code (BWLQ) - acc = access code (KESU) - Output: - none -*/ - -void Write (uint32 va, int32 val, int32 lnt, int32 acc) -{ -int32 vpn, off, tbi, pa; -int32 pa1, bo, sc, wl, wh; -TLBENT xpte; - -mchk_va = va; -if (mapen) { - vpn = VA_GETVPN (va); - off = VA_GETOFF (va); - tbi = VA_GETTBI (vpn); - xpte = (va & VA_S0)? stlb[tbi]: ptlb[tbi]; /* access tlb */ - if (((xpte.pte & acc) == 0) || (xpte.tag != vpn) || - ((xpte.pte & TLB_M) == 0)) - xpte = fill (va, lnt, acc, NULL); - pa = (xpte.pte & TLB_PFN) | off; } -else pa = va & PAMASK; -if ((pa & (lnt - 1)) == 0) { /* aligned? */ - if (lnt >= L_LONG) WriteL (pa, val); /* long, quad? */ - else if (lnt == L_WORD) WriteW (pa, val); /* word? */ - else WriteB (pa, val); /* byte */ - return; } -if (mapen && ((off + lnt) > VA_PAGSIZE)) { - vpn = VA_GETVPN (va + 4); - tbi = VA_GETTBI (vpn); - xpte = (va & VA_S0)? stlb[tbi]: ptlb[tbi]; /* access tlb */ - if (((xpte.pte & acc) == 0) || (xpte.tag != vpn) || - ((xpte.pte & TLB_M) == 0)) - xpte = fill (va + lnt, lnt, acc, NULL); - pa1 = (xpte.pte & TLB_PFN) | VA_GETOFF (va + 4); } -else pa1 = (pa + 4) & PAMASK; -bo = pa & 3; -wl = ReadL (pa); -if (lnt >= L_LONG) { - sc = bo << 3; - wh = ReadL (pa1); - wl = (wl & insert[bo]) | (val << sc); - wh = (wh & ~insert[bo]) | ((val >> (32 - sc)) & insert[bo]); - WriteL (pa, wl); - WriteL (pa1, wh); } -else if (bo == 1) { - wl = (wl & 0xFF0000FF) | (val << 8); - WriteL (pa, wl); } -else { wh = ReadL (pa1); - wl = (wl & 0x00FFFFFF) | (val << 24); - wh = (wh & 0xFFFFFF00) | ((val >> 8) & 0xFF); - WriteL (pa, wl); - WriteL (pa1, wh); } -return; -} - -/* Test access to a byte (VAX PROBEx) */ - -int32 Test (int32 va, int32 acc, int32 *status) -{ -int32 vpn, off, tbi; -TLBENT xpte; - -*status = PR_OK; /* assume ok */ -if (mapen) { /* mapping on? */ - vpn = VA_GETVPN (va); /* get vpn, off */ - off = VA_GETOFF (va); - tbi = VA_GETTBI (vpn); - xpte = (va & VA_S0)? stlb[tbi]: ptlb[tbi]; /* access tlb */ - if ((xpte.pte & acc) && (xpte.tag == vpn)) /* TB hit, acc ok? */ - return (xpte.pte & TLB_PFN) | off; - xpte = fill (va, L_BYTE, acc, status); /* fill TB */ - if (*status == PR_OK) return (xpte.pte & TLB_PFN) | off; - else return -1; } -return va & PAMASK; /* ret phys addr */ -} - -/* Read aligned physical (in virtual context, unless indicated) - - Inputs: - pa = physical address, naturally aligned - Output: - returned data, right justified in 32b longword -*/ - -int32 ReadB (uint32 pa) -{ -int32 dat; - -if (ADDR_IS_MEM (pa)) dat = M[pa >> 2]; -else { mchk_ref = REF_V; - if (ADDR_IS_IO (pa)) dat = ReadIO (pa, L_BYTE); - else dat = ReadReg (pa, L_BYTE); } -return ((dat >> ((pa & 3) << 3)) & BMASK); -} - -int32 ReadW (uint32 pa) -{ -int32 dat; - -if (ADDR_IS_MEM (pa)) dat = M[pa >> 2]; -else { mchk_ref = REF_V; - if (ADDR_IS_IO (pa)) dat = ReadIO (pa, L_WORD); - else dat = ReadReg (pa, L_WORD); } -return ((dat >> ((pa & 2)? 16: 0)) & WMASK); -} - -int32 ReadL (uint32 pa) -{ -if (ADDR_IS_MEM (pa)) return M[pa >> 2]; -mchk_ref = REF_V; -if (ADDR_IS_IO (pa)) return ReadIO (pa, L_LONG); -return ReadReg (pa, L_LONG); -} - -int32 ReadLP (uint32 pa) -{ -if (ADDR_IS_MEM (pa)) return M[pa >> 2]; -mchk_va = pa; -mchk_ref = REF_P; -if (ADDR_IS_IO (pa)) return ReadIO (pa, L_LONG); -return ReadReg (pa, L_LONG); -} - -/* Write aligned physical (in virtual context, unless indicated) - - Inputs: - pa = physical address, naturally aligned - val = data to be written, right justified in 32b longword - Output: - none -*/ - -void WriteB (uint32 pa, int32 val) -{ -if (ADDR_IS_MEM (pa)) { - int32 id = pa >> 2; - int32 sc = (pa & 3) << 3; - int32 mask = 0xFF << sc; - M[id] = (M[id] & ~mask) | (val << sc); } -else { mchk_ref = REF_V; - if (ADDR_IS_IO (pa)) WriteIO (pa, val, L_BYTE); - else WriteReg (pa, val, L_BYTE); } -return; -} - -void WriteW (uint32 pa, int32 val) -{ -if (ADDR_IS_MEM (pa)) { - int32 id = pa >> 2; - M[id] = (pa & 2)? (M[id] & 0xFFFF) | (val << 16): - (M[id] & ~0xFFFF) | val; } -else { mchk_ref = REF_V; - if (ADDR_IS_IO (pa)) WriteIO (pa, val, L_WORD); - else WriteReg (pa, val, L_WORD); } -return; -} - -void WriteL (uint32 pa, int32 val) -{ -if (ADDR_IS_MEM (pa)) M[pa >> 2] = val; -else { mchk_ref = REF_V; - if (ADDR_IS_IO (pa)) WriteIO (pa, val, L_LONG); - else WriteReg (pa, val, L_LONG); } -return; -} - -void WriteLP (uint32 pa, int32 val) -{ -if (ADDR_IS_MEM (pa)) M[pa >> 2] = val; -else { mchk_va = pa; - mchk_ref = REF_P; - if (ADDR_IS_IO (pa)) WriteIO (pa, val, L_LONG); - else WriteReg (pa, val, L_LONG); } -return; -} - -/* TLB fill - - This routine fills the TLB after a tag or access mismatch, or - on a write if pte = 0. It fills the TLB and returns the - pte to the caller. On an error, it aborts directly to the - fault handler in the CPU. - - If called from map (VAX PROBEx), the error status is returned - to the caller, and no fault occurs. -*/ - -#define MM_ERR(param) { \ - if (stat) { *stat = param; return zero_pte; } \ - p1 = MM_PARAM (acc & TLB_WACC, param); \ - p2 = va; \ - ABORT ((param & PR_TNV)? ABORT_TNV: ABORT_ACV); } - -TLBENT fill (uint32 va, int32 lnt, int32 acc, int32 *stat) -{ -int32 ptidx = (((uint32) va) >> 7) & ~03; -int32 tlbpte, ptead, pte, tbi, vpn; -static TLBENT zero_pte = { 0, 0 }; - -if (va & VA_S0) { /* system space? */ - if (ptidx >= slr) MM_ERR (PR_LNV); /* system */ - ptead = sbr + ptidx; } -else { if (va & VA_P1) { /* P1? */ - if (ptidx < p1lr) MM_ERR (PR_LNV); - ptead = p1br + ptidx; } - else { /* P0 */ - if (ptidx >= p0lr) - MM_ERR (PR_LNV); - ptead = p0br + ptidx; } - if ((ptead & VA_S0) == 0) - ABORT (STOP_PPTE); /* ppte must be sys */ - vpn = VA_GETVPN (ptead); /* get vpn, tbi */ - tbi = VA_GETTBI (vpn); - if (stlb[tbi].tag != vpn) { /* in sys tlb? */ - ptidx = ((uint32) ptead) >> 7; /* xlate like sys */ - if (ptidx >= slr) MM_ERR (PR_PLNV); - pte = ReadLP (sbr + ptidx); /* get system pte */ - if ((pte & PTE_V) == 0) MM_ERR (PR_PTNV); /* spte TNV? */ - stlb[tbi].tag = vpn; /* set stlb tag */ - stlb[tbi].pte = cvtacc[PTE_GETACC (pte)] | - ((pte << VA_N_OFF) & TLB_PFN); } /* set stlb data */ - ptead = (stlb[tbi].pte & TLB_PFN) | VA_GETOFF (ptead); } -pte = ReadL (ptead); /* read pte */ -tlbpte = cvtacc[PTE_GETACC (pte)] | /* cvt access */ - ((pte << VA_N_OFF) & TLB_PFN); /* set addr */ -if ((tlbpte & acc) == 0) MM_ERR (PR_ACV); /* chk access */ -if ((pte & PTE_V) == 0) MM_ERR (PR_TNV); /* check valid */ -if (acc & TLB_WACC) { /* write? */ - if ((pte & PTE_M) == 0) WriteL (ptead, pte | PTE_M); - tlbpte = tlbpte | TLB_M; } /* set M */ -vpn = VA_GETVPN (va); -tbi = VA_GETTBI (vpn); -if ((va & VA_S0) == 0) { /* process space? */ - ptlb[tbi].tag = vpn; /* store tlb ent */ - ptlb[tbi].pte = tlbpte; - return ptlb[tbi]; } -stlb[tbi].tag = vpn; /* system space */ -stlb[tbi].pte = tlbpte; /* store tlb ent */ -return stlb[tbi]; -} - -/* Utility routines */ - -extern void set_map_reg (void) -{ -p0br = P0BR & ~03; -p1br = (P1BR - 0x800000) & ~03; /* VA<30> >> 7 */ -sbr = (SBR - 0x1000000) & ~03; /* VA<31> >> 7 */ -p0lr = (P0LR << 2); -p1lr = (P1LR << 2) + 0x800000; /* VA<30> >> 7 */ -slr = (SLR << 2) + 0x1000000; /* VA<31> >> 7 */ -return; -} - -/* Zap process (0) or whole (1) tb */ - -void zap_tb (int stb) -{ -int32 i; - -for (i = 0; i < VA_TBSIZE; i++) { - ptlb[i].tag = ptlb[i].pte = -1; - if (stb) stlb[i].tag = stlb[i].pte = -1; } -return; -} - -/* Zap single tb entry corresponding to va */ - -void zap_tb_ent (int32 va) -{ -int32 tbi = VA_GETTBI (VA_GETVPN (va)); - -if (va & VA_S0) stlb[tbi].tag = stlb[tbi].pte = -1; -else ptlb[tbi].tag = ptlb[tbi].pte = -1; -return; -} - -/* Check for tlb entry corresponding to va */ - -t_bool chk_tb_ent (int32 va) -{ -int32 vpn = VA_GETVPN (va); -int32 tbi = VA_GETTBI (vpn); -TLBENT xpte; - -xpte = (va & VA_S0)? stlb[tbi]: ptlb[tbi]; -if (xpte.tag == vpn) return TRUE; -return FALSE; -} - -/* TLB examine */ - -t_stat tlb_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -int32 tlbn = uptr - tlb_unit; -int32 idx = (uint32) addr >> 1; - -if (idx >= VA_TBSIZE) return SCPE_NXM; -if (addr & 1) *vptr = ((uint32) (tlbn? stlb[idx].pte: ptlb[idx].pte)); -else *vptr = ((uint32) (tlbn? stlb[idx].tag: ptlb[idx].tag)); -return SCPE_OK; -} - -/* TLB deposit */ - -t_stat tlb_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -int32 tlbn = uptr - tlb_unit; -int32 idx = (uint32) addr >> 1; - -if (idx >= VA_TBSIZE) return SCPE_NXM; -if (addr & 1) { - if (tlbn) stlb[idx].pte = (int32) val; - else ptlb[idx].pte = (int32) val; } -else { if (tlbn) stlb[idx].tag = (int32) val; - else ptlb[idx].tag = (int32) val; } -return SCPE_OK; -} - -/* TLB reset */ - -t_stat tlb_reset (DEVICE *dptr) -{ -int32 i; - -for (i = 0; i < VA_TBSIZE; i++) - stlb[i].tag = ptlb[i].tag = stlb[i].pte = ptlb[i].pte = -1; -return SCPE_OK; -} diff --git a/VAX/vax_stddev.c b/VAX/vax_stddev.c deleted file mode 100644 index e33a2b40..00000000 --- a/VAX/vax_stddev.c +++ /dev/null @@ -1,385 +0,0 @@ -/* vax_stddev.c: VAX standard I/O devices simulator - - Copyright (c) 1998-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - tti terminal input - tto terminal output - clk 100Hz and TODR clock - - 25-Apr-03 RMS Revised for extended file support - 02-Mar-02 RMS Added SET TTI CTRL-C - 22-Dec-02 RMS Added console halt capability - 01-Nov-02 RMS Added 7B/8B capability to terminal - 12-Sep-02 RMS Removed paper tape, added variable vector support - 30-May-02 RMS Widened POS to 32b - 30-Apr-02 RMS Automatically set TODR to VMS-correct value during boot -*/ - -#include "vax_defs.h" -#include - -#define TTICSR_IMP (CSR_DONE + CSR_IE) /* terminal input */ -#define TTICSR_RW (CSR_IE) -#define TTIBUF_ERR 0x8000 /* error */ -#define TTIBUF_OVR 0x4000 /* overrun */ -#define TTIBUF_FRM 0x2000 /* framing error */ -#define TTIBUF_RBR 0x0400 /* receive break */ -#define TTOCSR_IMP (CSR_DONE + CSR_IE) /* terminal output */ -#define TTOCSR_RW (CSR_IE) -#define CLKCSR_IMP (CSR_IE) /* real-time clock */ -#define CLKCSR_RW (CSR_IE) -#define CLK_DELAY 5000 /* 100 Hz */ -#define TMXR_MULT 2 /* 50 Hz */ - -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B mode */ -#define UNIT_8B (1 << UNIT_V_8B) - -extern int32 int_req[IPL_HLVL]; -extern int32 hlt_pin; - -int32 tti_csr = 0; /* control/status */ -int32 tto_csr = 0; /* control/status */ -int32 clk_csr = 0; /* control/status */ -int32 clk_tps = 100; /* ticks/second */ -int32 todr_reg = 0; /* TODR register */ -int32 todr_blow = 1; /* TODR battery low */ -int32 tmxr_poll = CLK_DELAY * TMXR_MULT; /* term mux poll */ -int32 tmr_poll = CLK_DELAY; /* pgm timer poll */ - -t_stat tti_svc (UNIT *uptr); -t_stat tto_svc (UNIT *uptr); -t_stat clk_svc (UNIT *uptr); -t_stat tti_reset (DEVICE *dptr); -t_stat tto_reset (DEVICE *dptr); -t_stat clk_reset (DEVICE *dptr); -t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc); - -extern int32 sysd_hlt_enb (void); - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit descriptor - tti_reg TTI register list -*/ - -DIB tti_dib = { 0, 0, NULL, NULL, 1, IVCL (TTI), SCB_TTI, { NULL } }; - -UNIT tti_unit = { UDATA (&tti_svc, UNIT_8B, 0), KBD_POLL_WAIT }; - -REG tti_reg[] = { - { HRDATA (BUF, tti_unit.buf, 16) }, - { HRDATA (CSR, tti_csr, 16) }, - { FLDATA (INT, int_req[IPL_TTI], INT_V_TTI) }, - { FLDATA (DONE, tti_csr, CSR_V_DONE) }, - { FLDATA (IE, tti_csr, CSR_V_IE) }, - { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB tti_mod[] = { - { UNIT_8B, UNIT_8B, "8b", "8B", NULL }, - { UNIT_8B, 0 , "7b", "7B", NULL }, - { MTAB_XTD|MTAB_VDV|MTAB_VUN, 0, NULL, "CTRL-C", - &tti_set_ctrlc, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; - -DEVICE tti_dev = { - "TTI", &tti_unit, tti_reg, tti_mod, - 1, 10, 31, 1, 16, 8, - NULL, NULL, &tti_reset, - NULL, NULL, NULL, - &tti_dib, 0 }; - -/* TTO data structures - - tto_dev TTO device descriptor - tto_unit TTO unit descriptor - tto_reg TTO register list -*/ - -DIB tto_dib = { 0, 0, NULL, NULL, 1, IVCL (TTO), SCB_TTO, { NULL } }; - -UNIT tto_unit = { UDATA (&tto_svc, UNIT_8B, 0), SERIAL_OUT_WAIT }; - -REG tto_reg[] = { - { HRDATA (BUF, tto_unit.buf, 8) }, - { HRDATA (CSR, tto_csr, 16) }, - { FLDATA (INT, int_req[IPL_TTO], INT_V_TTO) }, - { FLDATA (DONE, tto_csr, CSR_V_DONE) }, - { FLDATA (IE, tto_csr, CSR_V_IE) }, - { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -MTAB tto_mod[] = { - { UNIT_8B, UNIT_8B, "8b", "8B", NULL }, - { UNIT_8B, 0 , "7b", "7B", NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec }, - { 0 } }; - -DEVICE tto_dev = { - "TTO", &tto_unit, tto_reg, tto_mod, - 1, 10, 31, 1, 16, 8, - NULL, NULL, &tto_reset, - NULL, NULL, NULL, - &tto_dib, 0 }; - -/* CLK data structures - - clk_dev CLK device descriptor - clk_unit CLK unit descriptor - clk_reg CLK register list -*/ - -DIB clk_dib = { 0, 0, NULL, NULL, 1, IVCL (CLK), SCB_INTTIM, { NULL } }; - -UNIT clk_unit = { UDATA (&clk_svc, 0, 0), CLK_DELAY }; - -REG clk_reg[] = { - { HRDATA (CSR, clk_csr, 16) }, - { FLDATA (INT, int_req[IPL_CLK], INT_V_CLK) }, - { FLDATA (IE, clk_csr, CSR_V_IE) }, - { DRDATA (TODR, todr_reg, 32), PV_LEFT }, - { FLDATA (BLOW, todr_blow, 0) }, - { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS, clk_tps, 8), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB clk_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec }, - { 0 } }; - -DEVICE clk_dev = { - "CLK", &clk_unit, clk_reg, clk_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &clk_reset, - NULL, NULL, NULL, - &clk_dib, 0 }; - -/* Clock and terminal MxPR routines - - iccs_rd/wr interval timer - todr_rd/wr time of year clock - rxcs_rd/wr input control/status - rxdb_rd input buffer - txcs_rd/wr output control/status - txdb_wr output buffer -*/ - -int32 iccs_rd (void) -{ -return (clk_csr & CLKCSR_IMP); -} - -int32 todr_rd (void) -{ -return todr_reg; -} - -int32 rxcs_rd (void) -{ -return (tti_csr & TTICSR_IMP); -} - -int32 rxdb_rd (void) -{ -int32 t = tti_unit.buf; /* char + error */ - -tti_csr = tti_csr & ~CSR_DONE; /* clr done */ -tti_unit.buf = tti_unit.buf & 0377; /* clr errors */ -CLR_INT (TTI); -return t; -} - -int32 txcs_rd (void) -{ -return (tto_csr & TTOCSR_IMP); -} - -void iccs_wr (int32 data) -{ -if ((data & CSR_IE) == 0) CLR_INT (CLK); -clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW); -return; -} - -void todr_wr (int32 data) -{ -todr_reg = data; -if (data) todr_blow = 0; -return; -} - -void rxcs_wr (int32 data) -{ -if ((data & CSR_IE) == 0) CLR_INT (TTI); -else if ((tti_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) - SET_INT (TTI); -tti_csr = (tti_csr & ~TTICSR_RW) | (data & TTICSR_RW); -return; -} - -void txcs_wr (int32 data) -{ -if ((data & CSR_IE) == 0) CLR_INT (TTO); -else if ((tto_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) - SET_INT (TTO); -tto_csr = (tto_csr & ~TTOCSR_RW) | (data & TTOCSR_RW); -return; -} - -void txdb_wr (int32 data) -{ -tto_unit.buf = data & 0377; -tto_csr = tto_csr & ~CSR_DONE; -CLR_INT (TTO); -sim_activate (&tto_unit, tto_unit.wait); -return; -} - -/* Terminal input routines - - tti_svc process event (character ready) - tti_reset process reset -*/ - -t_stat tti_svc (UNIT *uptr) -{ -int32 c; - -sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ -if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -if (c & SCPE_BREAK) { /* break? */ - if (sysd_hlt_enb ()) hlt_pin = 1; /* if enabled, halt */ - tti_unit.buf = TTIBUF_ERR | TTIBUF_FRM | TTIBUF_RBR; } -else tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177); -tti_unit.pos = tti_unit.pos + 1; -tti_csr = tti_csr | CSR_DONE; -if (tti_csr & CSR_IE) SET_INT (TTI); -return SCPE_OK; -} - -t_stat tti_reset (DEVICE *dptr) -{ -tti_unit.buf = 0; -tti_csr = 0; -CLR_INT (TTI); -sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ -return SCPE_OK; -} - -/* Set control-C */ - -t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -uptr->buf = 003; -uptr->pos = uptr->pos + 1; -tti_csr = tti_csr | CSR_DONE; -if (tti_csr & CSR_IE) SET_INT (TTI); -return SCPE_OK; -} - -/* Terminal output routines - - tto_svc process event (character typed) - tto_reset process reset -*/ - -t_stat tto_svc (UNIT *uptr) -{ -int32 c; -t_stat r; - -tto_csr = tto_csr | CSR_DONE; -if (tto_csr & CSR_IE) SET_INT (TTO); -c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); -if ((r = sim_putchar (c)) != SCPE_OK) return r; -tto_unit.pos = tto_unit.pos + 1; -return SCPE_OK; -} - -t_stat tto_reset (DEVICE *dptr) -{ -tto_unit.buf = 0; -tto_csr = CSR_DONE; -CLR_INT (TTO); -sim_cancel (&tto_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Clock routines - - clk_svc process event (clock tick) - clk_reset process reset - todr_powerup powerup for TODR (get date from system) -*/ - -t_stat clk_svc (UNIT *uptr) -{ -int32 t; - -if (clk_csr & CSR_IE) SET_INT (CLK); -t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */ -sim_activate (&clk_unit, t); /* reactivate unit */ -tmr_poll = t; /* set tmr poll */ -tmxr_poll = t * TMXR_MULT; /* set mux poll */ -if (!todr_blow) todr_reg = todr_reg + 1; /* incr TODR */ -return SCPE_OK; -} - -t_stat clk_reset (DEVICE *dptr) -{ -int32 t; - -clk_csr = 0; -CLR_INT (CLK); -t = sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init timer */ -sim_activate (&clk_unit, t); /* activate unit */ -tmr_poll = t; /* set tmr poll */ -tmxr_poll = t * TMXR_MULT; /* set mux poll */ -return SCPE_OK; -} - -t_stat todr_powerup (void) -{ -uint32 base; -time_t curr; -struct tm *ctm; - -curr = time (NULL); /* get curr time */ -if (curr == (time_t) -1) return SCPE_NOFNC; /* error? */ -ctm = localtime (&curr); /* decompose */ -if (ctm == NULL) return SCPE_NOFNC; /* error? */ -base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */ - ctm->tm_hour) * 60) + - ctm->tm_min) * 60) + - ctm->tm_sec; -todr_reg = (base * 100) + 0x10000000; /* cvt to VAX form */ -todr_blow = 0; -return SCPE_OK; -} diff --git a/VAX/vax_sys.c b/VAX/vax_sys.c deleted file mode 100644 index 2933fd2e..00000000 --- a/VAX/vax_sys.c +++ /dev/null @@ -1,1373 +0,0 @@ -/* vax_sys.c: VAX simulator interface - - Copyright (c) 1998-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 06-May-03 RMS Added support for second DELQA - 12-Oct-02 RMS Added multiple RQ controller support - 10-Oct-02 RMS Added DELQA support - 21-Sep-02 RMS Extended symbolic ex/mod to all byte devices - 06-Sep-02 RMS Added TMSCP support - 14-Jul-02 RMS Added infinite loop message -*/ - -#include "vax_defs.h" -#include - -extern DEVICE cpu_dev; -extern DEVICE tlb_dev; -extern DEVICE rom_dev; -extern DEVICE nvr_dev; -extern DEVICE sysd_dev; -extern DEVICE qba_dev; -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE tti_dev, tto_dev; -extern DEVICE csi_dev, cso_dev; -extern DEVICE lpt_dev; -extern DEVICE clk_dev; -extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev; -extern DEVICE rl_dev; -extern DEVICE ts_dev; -extern DEVICE tq_dev; -extern DEVICE dz_dev; -extern DEVICE xq_dev, xqb_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern uint32 *M; -extern int32 saved_PC; -extern int32 sim_switches; - -extern void WriteB (int32 pa, int32 val); -extern void rom_wr (int32 pa, int32 val, int32 lnt); -t_stat fprint_sym_m (FILE *of, uint32 addr, t_value *val); -int32 fprint_sym_qoimm (FILE *of, t_value *val, int32 vp, int32 lnt); -t_stat parse_sym_m (char *cptr, uint32 addr, t_value *val); -int32 parse_brdisp (char *cptr, uint32 addr, t_value *val, - int32 vp, int32 lnt, t_stat *r); -int32 parse_spec (char *cptr, uint32 addr, t_value *val, - int32 vp, int32 disp, t_stat *r); -char *parse_rnum (char *cptr, int32 *rn); -int32 parse_sym_qoimm (int32 *lit, t_value *val, int32 vp, - int lnt, int32 minus); - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "VAX"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 60; - -DEVICE *sim_devices[] = { - &cpu_dev, - &tlb_dev, - &rom_dev, - &nvr_dev, - &sysd_dev, - &qba_dev, - &tti_dev, - &tto_dev, - &csi_dev, - &cso_dev, - &clk_dev, - &ptr_dev, - &ptp_dev, - &lpt_dev, - &dz_dev, - &rl_dev, - &rq_dev, - &rqb_dev, - &rqc_dev, - &rqd_dev, - &ts_dev, - &tq_dev, - &xq_dev, - &xqb_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "HALT instruction", - "Breakpoint", - "CHMx on interrupt stack", - "Invalid SCB vector", - "Exception in interrupt or exception", - "Process PTE in P0 or P1 space", - "Interrupt at undefined IPL", - "Fatal RQDX3 error", - "Infinite loop", - "Sanity timer expired", - "Unknown error", - "Unknown abort code" }; - -/* Binary loader - - The binary loader handles absolute system images, that is, system - images linked /SYSTEM. These are simply a byte stream, with no - origin or relocation information. - - -r load ROM - -n load NVR - -o for memory, specify origin -*/ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -t_stat r; -int32 i; -uint32 origin, limit; -extern int32 ssc_cnf; -#define SSCCNF_BLO 0x80000000 - -if (flag) return SCPE_ARG; /* dump? */ -if (sim_switches & SWMASK ('R')) { /* ROM? */ - origin = ROMBASE; - limit = ROMBASE + ROMSIZE; } -else if (sim_switches & SWMASK ('N')) { /* NVR? */ - origin = NVRBASE; - limit = NVRBASE + NVRSIZE; - ssc_cnf = ssc_cnf & ~SSCCNF_BLO; } -else { origin = 0; /* memory */ - limit = (uint32) cpu_unit.capac; - if (sim_switches & SWMASK ('O')) { /* origin? */ - origin = (int32) get_uint (cptr, 16, 0xFFFFFFFF, &r); - if (r != SCPE_OK) return SCPE_ARG; } } - -while ((i = getc (fileref)) != EOF) { /* read byte stream */ - if (origin >= limit) return SCPE_NXM; /* NXM? */ - if (sim_switches & SWMASK ('R')) /* ROM? */ - rom_wr (origin, i, L_BYTE); /* not writeable */ - else WriteB (origin, i); /* store byte */ - origin = origin + 1; } -return SCPE_OK; -} - -/* Factory bad block table creation routine - - This routine writes a DEC standard 044 compliant bad block table on the - last track of the specified unit. The bad block table consists of 10 - repetitions of the same table, formatted as follows: - - words 0-1 pack id number - words 2-3 cylinder/sector/surface specifications - : - words n-n+1 end of table (-1,-1) - - Inputs: - uptr = pointer to unit - sec = number of sectors per surface - wds = number of words per sector - Outputs: - sta = status code -*/ - -t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds) -{ -int32 i, da; -int32 *buf; - -if ((sec < 2) || (wds < 16)) return SCPE_ARG; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; -if (!get_yn ("Overwrite last track? [N]", FALSE)) return SCPE_OK; -da = (int32) (uptr->capac - (sec * wds)) * sizeof (int16); -if (fseek (uptr->fileref, da, SEEK_SET)) return SCPE_IOERR; -if ((buf = malloc (wds * sizeof (int32))) == NULL) return SCPE_MEM; -buf[0] = 0x12345678; -buf[1] = 0; -for (i = 2; i < wds; i++) buf[i] = 0xFFFFFFFF; -for (i = 0; (i < sec) && (i < 10); i++) - fxwrite (buf, sizeof (int32), wds, uptr->fileref); -free (buf); -if (ferror (uptr->fileref)) return SCPE_IOERR; -return SCPE_OK; -} - -/* Dispatch/decoder table - - The first entry contains: - - FPD legal flag (DR_F) - - number of specifiers for decode bits 2:0> - - number of specifiers for unimplemented instructions bits<6:4> - */ - -const uint16 drom[NUM_INST][MAX_SPEC + 1] = { -0, 0, 0, 0, 0, 0, 0, /* HALT */ -0, 0, 0, 0, 0, 0, 0, /* NOP */ -0, 0, 0, 0, 0, 0, 0, /* REI */ -0, 0, 0, 0, 0, 0, 0, /* BPT */ -0, 0, 0, 0, 0, 0, 0, /* RET */ -0, 0, 0, 0, 0, 0, 0, /* RSB */ -0, 0, 0, 0, 0, 0, 0, /* LDPCTX */ -0, 0, 0, 0, 0, 0, 0, /* SVPCTX */ -4+DR_F, RW, AB, RW, AB, 0, 0, /* CVTPS */ -4+DR_F, RW, AB, RW, AB, 0, 0, /* CVTSP */ -6, RL, RL, RL, RL, RL, WL, /* INDEX */ -4+DR_F, AB, RL, RW, AB, 0, 0, /* CRC */ -3, RB, RW, AB, 0, 0, 0, /* PROBER */ -3, RB, RW, AB, 0, 0, 0, /* PROBEW */ -2, AB, AB, 0, 0, 0, 0, /* INSQUE */ -2, AB, WL, 0, 0, 0, 0, /* REMQUE */ -1, BB, 0, 0, 0, 0, 0, /* BSBB */ -1, BB, 0, 0, 0, 0, 0, /* BRB */ -1, BB, 0, 0, 0, 0, 0, /* BNEQ */ -1, BB, 0, 0, 0, 0, 0, /* BEQL */ -1, BB, 0, 0, 0, 0, 0, /* BGTR */ -1, BB, 0, 0, 0, 0, 0, /* BLEQ */ -1, AB, 0, 0, 0, 0, 0, /* JSB */ -1, AB, 0, 0, 0, 0, 0, /* JMP */ -1, BB, 0, 0, 0, 0, 0, /* BGEQ */ -1, BB, 0, 0, 0, 0, 0, /* BLSS */ -1, BB, 0, 0, 0, 0, 0, /* BGTRU */ -1, BB, 0, 0, 0, 0, 0, /* BLEQU */ -1, BB, 0, 0, 0, 0, 0, /* BVC */ -1, BB, 0, 0, 0, 0, 0, /* BVS */ -1, BB, 0, 0, 0, 0, 0, /* BCC */ -1, BB, 0, 0, 0, 0, 0, /* BCS */ -4+DR_F, RW, AB, RW, AB, 0, 0, /* ADDP4 */ -6+DR_F, RW, AB, RW, AB, RW, AB, /* ADDP6 */ -4+DR_F, RW, AB, RW, AB, 0, 0, /* SUBP4 */ -6+DR_F, RW, AB, RW, AB, RW, AB, /* SUBP6 */ -5+DR_F, RW, AB, AB, RW, AB, 0, /* CVTPT */ -6+DR_F, RW, AB, RW, AB, RW, AB, /* MULP6 */ -5+DR_F, RW, AB, AB, RW, AB, 0, /* CVTTP */ -6+DR_F, RW, AB, RW, AB, RW, AB, /* DIVP6 */ -3+DR_F, RW, AB, AB, 0, 0, 0, /* MOVC3 */ -3+DR_F, RW, AB, AB, 0, 0, 0, /* CMPC3 */ -4+DR_F, RW, AB, AB, RB, 0, 0, /* SCANC */ -4+DR_F, RW, AB, AB, RB, 0, 0, /* SPANC */ -5+DR_F, RW, AB, RB, RW, AB, 0, /* MOVC5 */ -5+DR_F, RW, AB, RB, RW, AB, 0, /* CMPC5 */ -6+DR_F, RW, AB, RB, AB, RW, AB, /* MOVTC */ -6+DR_F, RW, AB, RB, AB, RW, AB, /* MOVTUC */ -1, BW, 0, 0, 0, 0, 0, /* BSBW */ -1, BW, 0, 0, 0, 0, 0, /* BRW */ -2, RW, WL, 0, 0, 0, 0, /* CVTWL */ -2, RW, WB, 0, 0, 0, 0, /* CVTWB */ -3+DR_F, RW, AB, AB, 0, 0, 0, /* MOVP */ -3+DR_F, RW, AB, AB, 0, 0, 0, /* CMPP3 */ -3+DR_F, RW, AB, WL, 0, 0, 0, /* CVTPL */ -4+DR_F, RW, AB, RW, AB, 0, 0, /* CMPP4 */ -4+DR_F, RW, AB, AB, AB, 0, 0, /* EDITPC */ -4+DR_F, RW, AB, RW, AB, 0, 0, /* MATCHC */ -3+DR_F, RB, RW, AB, 0, 0, 0, /* LOCC */ -3+DR_F, RB, RW, AB, 0, 0, 0, /* SKPC */ -2, RW, WL, 0, 0, 0, 0, /* MOVZWL */ -4, RW, RW, MW, BW, 0, 0, /* ACBW */ -2, AW, WL, 0, 0, 0, 0, /* MOVAW */ -1, AW, 0, 0, 0, 0, 0, /* PUSHAW */ -2, RF, ML, 0, 0, 0, 0, /* ADDF2 */ -3, RF, RF, WL, 0, 0, 0, /* ADDF3 */ -2, RF, ML, 0, 0, 0, 0, /* SUBF2 */ -3, RF, RF, WL, 0, 0, 0, /* SUBF3 */ -2, RF, ML, 0, 0, 0, 0, /* MULF2 */ -3, RF, RF, WL, 0, 0, 0, /* MULF3 */ -2, RF, ML, 0, 0, 0, 0, /* DIVF2 */ -3, RF, RF, WL, 0, 0, 0, /* DIVF3 */ -2, RF, WB, 0, 0, 0, 0, /* CVTFB */ -2, RF, WW, 0, 0, 0, 0, /* CVTFW */ -2, RF, WL, 0, 0, 0, 0, /* CVTFL */ -2, RF, WL, 0, 0, 0, 0, /* CVTRFL */ -2, RB, WL, 0, 0, 0, 0, /* CVTBF */ -2, RW, WL, 0, 0, 0, 0, /* CVTWF */ -2, RL, WL, 0, 0, 0, 0, /* CVTLF */ -4, RF, RF, ML, BW, 0, 0, /* ACBF */ -2, RF, WL, 0, 0, 0, 0, /* MOVF */ -2, RF, RF, 0, 0, 0, 0, /* CMPF */ -2, RF, WL, 0, 0, 0, 0, /* MNEGF */ -1, RF, 0, 0, 0, 0, 0, /* TSTF */ -5, RF, RB, RF, WL, WL, 0, /* EMODF */ -3, RF, RW, AB, 0, 0, 0, /* POLYF */ -2, RF, WQ, 0, 0, 0, 0, /* CVTFD */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -2, RW, WW, 0, 0, 0, 0, /* ADAWI */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -2, AB, AQ, 0, 0, 0, 0, /* INSQHI */ -2, AB, AQ, 0, 0, 0, 0, /* INSQTI */ -2, AQ, WL, 0, 0, 0, 0, /* REMQHI */ -2, AQ, WL, 0, 0, 0, 0, /* REMQTI */ -2, RD, MQ, 0, 0, 0, 0, /* ADDD2 */ -3, RD, RD, WQ, 0, 0, 0, /* ADDD3 */ -2, RD, MQ, 0, 0, 0, 0, /* SUBD2 */ -3, RD, RD, WQ, 0, 0, 0, /* SUBD3 */ -2, RD, MQ, 0, 0, 0, 0, /* MULD2 */ -3, RD, RD, WQ, 0, 0, 0, /* MULD3 */ -2, RD, MQ, 0, 0, 0, 0, /* DIVD2 */ -3, RD, RD, WQ, 0, 0, 0, /* DIVD3 */ -2, RD, WB, 0, 0, 0, 0, /* CVTDB */ -2, RD, WW, 0, 0, 0, 0, /* CVTDW */ -2, RD, WL, 0, 0, 0, 0, /* CVTDL */ -2, RD, WL, 0, 0, 0, 0, /* CVTRDL */ -2, RB, WQ, 0, 0, 0, 0, /* CVTBD */ -2, RW, WQ, 0, 0, 0, 0, /* CVTWD */ -2, RL, WQ, 0, 0, 0, 0, /* CVTLD */ -4, RD, RD, MQ, BW, 0, 0, /* ACBD */ -2, RD, WQ, 0, 0, 0, 0, /* MOVD */ -2, RD, RD, 0, 0, 0, 0, /* CMPD */ -2, RD, WQ, 0, 0, 0, 0, /* MNEGD */ -1, RD, 0, 0, 0, 0, 0, /* TSTD */ -5, RD, RB, RD, WL, WQ, 0, /* EMODD */ -3, RD, RW, AB, 0, 0, 0, /* POLYD */ -2, RD, WL, 0, 0, 0, 0, /* CVTDF */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -3, RB, RL, WL, 0, 0, 0, /* ASHL */ -3, RB, RQ, WQ, 0, 0, 0, /* ASHQ */ -4, RL, RL, RL, WQ, 0, 0, /* EMUL */ -4, RL, RQ, WL, WL, 0, 0, /* EDIV */ -1, WQ, 0, 0, 0, 0, 0, /* CLRQ */ -2, RQ, WQ, 0, 0, 0, 0, /* MOVQ */ -2, AQ, WL, 0, 0, 0, 0, /* MOVAQ */ -1, AQ, 0, 0, 0, 0, 0, /* PUSHAQ */ -2, RB, MB, 0, 0, 0, 0, /* ADDB2 */ -3, RB, RB, WB, 0, 0, 0, /* ADDB3 */ -2, RB, MB, 0, 0, 0, 0, /* SUBB2 */ -3, RB, RB, WB, 0, 0, 0, /* SUBB3 */ -2, RB, MB, 0, 0, 0, 0, /* MULB2 */ -3, RB, RB, WB, 0, 0, 0, /* MULB3 */ -2, RB, MB, 0, 0, 0, 0, /* DIVB2 */ -3, RB, RB, WB, 0, 0, 0, /* DIVB3 */ -2, RB, MB, 0, 0, 0, 0, /* BISB2 */ -3, RB, RB, WB, 0, 0, 0, /* BISB3 */ -2, RB, MB, 0, 0, 0, 0, /* BICB2 */ -3, RB, RB, WB, 0, 0, 0, /* BICB3 */ -2, RB, MB, 0, 0, 0, 0, /* XORB2 */ -3, RB, RB, WB, 0, 0, 0, /* XORB3 */ -2, RB, WB, 0, 0, 0, 0, /* MNEGB */ -3, RB, RB, RB, 0, 0, 0, /* CASEB */ -2, RB, WB, 0, 0, 0, 0, /* MOVB */ -2, RB, RB, 0, 0, 0, 0, /* CMPB */ -2, RB, WB, 0, 0, 0, 0, /* MCOMB */ -2, RB, RB, 0, 0, 0, 0, /* BITB */ -1, WB, 0, 0, 0, 0, 0, /* CLRB */ -1, RB, 0, 0, 0, 0, 0, /* TSTB */ -1, MB, 0, 0, 0, 0, 0, /* INCB */ -1, MB, 0, 0, 0, 0, 0, /* DECB */ -2, RB, WL, 0, 0, 0, 0, /* CVTBL */ -2, RB, WW, 0, 0, 0, 0, /* CVTBW */ -2, RB, WL, 0, 0, 0, 0, /* MOVZBL */ -2, RB, WW, 0, 0, 0, 0, /* MOVZBW */ -3, RB, RL, WL, 0, 0, 0, /* ROTL */ -4, RB, RB, MB, BW, 0, 0, /* ACBB */ -2, AB, WL, 0, 0, 0, 0, /* MOVAB */ -1, AB, 0, 0, 0, 0, 0, /* PUSHAB */ -2, RW, MW, 0, 0, 0, 0, /* ADDW2 */ -3, RW, RW, WW, 0, 0, 0, /* ADDW3 */ -2, RW, MW, 0, 0, 0, 0, /* SUBW2 */ -3, RW, RW, WW, 0, 0, 0, /* SUBW3 */ -2, RW, MW, 0, 0, 0, 0, /* MULW2 */ -3, RW, RW, WW, 0, 0, 0, /* MULW3 */ -2, RW, MW, 0, 0, 0, 0, /* DIVW2 */ -3, RW, RW, WW, 0, 0, 0, /* DIVW3 */ -2, RW, MW, 0, 0, 0, 0, /* BISW2 */ -3, RW, RW, WW, 0, 0, 0, /* BISW3 */ -2, RW, MW, 0, 0, 0, 0, /* BICW2 */ -3, RW, RW, WW, 0, 0, 0, /* BICW3 */ -2, RW, MW, 0, 0, 0, 0, /* XORW2 */ -3, RW, RW, WW, 0, 0, 0, /* XORW3 */ -2, RW, WW, 0, 0, 0, 0, /* MNEGW */ -3, RW, RW, RW, 0, 0, 0, /* CASEW */ -2, RW, WW, 0, 0, 0, 0, /* MOVW */ -2, RW, RW, 0, 0, 0, 0, /* CMPW */ -2, RW, WW, 0, 0, 0, 0, /* MCOMW */ -2, RW, RW, 0, 0, 0, 0, /* BITW */ -1, WW, 0, 0, 0, 0, 0, /* CLRW */ -1, RW, 0, 0, 0, 0, 0, /* TSTW */ -1, MW, 0, 0, 0, 0, 0, /* INCW */ -1, MW, 0, 0, 0, 0, 0, /* DECW */ -1, RW, 0, 0, 0, 0, 0, /* BISPSW */ -1, RW, 0, 0, 0, 0, 0, /* BICPSW */ -1, RW, 0, 0, 0, 0, 0, /* POPR */ -1, RW, 0, 0, 0, 0, 0, /* PUSHR */ -1, RW, 0, 0, 0, 0, 0, /* CHMK */ -1, RW, 0, 0, 0, 0, 0, /* CHME */ -1, RW, 0, 0, 0, 0, 0, /* CHMS */ -1, RW, 0, 0, 0, 0, 0, /* CHMU */ -2, RL, ML, 0, 0, 0, 0, /* ADDL2 */ -3, RL, RL, WL, 0, 0, 0, /* ADDL3 */ -2, RL, ML, 0, 0, 0, 0, /* SUBL2 */ -3, RL, RL, WL, 0, 0, 0, /* SUBL3 */ -2, RL, ML, 0, 0, 0, 0, /* MULL2 */ -3, RL, RL, WL, 0, 0, 0, /* MULL3 */ -2, RL, ML, 0, 0, 0, 0, /* DIVL2 */ -3, RL, RL, WL, 0, 0, 0, /* DIVL3 */ -2, RL, ML, 0, 0, 0, 0, /* BISL2 */ -3, RL, RL, WL, 0, 0, 0, /* BISL3 */ -2, RL, ML, 0, 0, 0, 0, /* BICL2 */ -3, RL, RL, WL, 0, 0, 0, /* BICL3 */ -2, RL, ML, 0, 0, 0, 0, /* XORL2 */ -3, RL, RL, WL, 0, 0, 0, /* XORL3 */ -2, RL, WL, 0, 0, 0, 0, /* MNEGL */ -3, RL, RL, RL, 0, 0, 0, /* CASEL */ -2, RL, WL, 0, 0, 0, 0, /* MOVL */ -2, RL, RL, 0, 0, 0, 0, /* CMPL */ -2, RL, WL, 0, 0, 0, 0, /* MCOML */ -2, RL, RL, 0, 0, 0, 0, /* BITL */ -1, WL, 0, 0, 0, 0, 0, /* CLRL */ -1, RL, 0, 0, 0, 0, 0, /* TSTL */ -1, ML, 0, 0, 0, 0, 0, /* INCL */ -1, ML, 0, 0, 0, 0, 0, /* DECL */ -2, RL, ML, 0, 0, 0, 0, /* ADWC */ -2, RL, ML, 0, 0, 0, 0, /* SBWC */ -2, RL, RL, 0, 0, 0, 0, /* MTPR */ -2, RL, WL, 0, 0, 0, 0, /* MFPR */ -1, WL, 0, 0, 0, 0, 0, /* MOVPSL */ -1, RL, 0, 0, 0, 0, 0, /* PUSHL */ -2, AL, WL, 0, 0, 0, 0, /* MOVAL */ -1, AL, 0, 0, 0, 0, 0, /* PUSHAL */ -3, RL, VB, BB, 0, 0, 0, /* BBS */ -3, RL, VB, BB, 0, 0, 0, /* BBC */ -3, RL, VB, BB, 0, 0, 0, /* BBSS */ -3, RL, VB, BB, 0, 0, 0, /* BBCS */ -3, RL, VB, BB, 0, 0, 0, /* BBSC */ -3, RL, VB, BB, 0, 0, 0, /* BBCC */ -3, RL, VB, BB, 0, 0, 0, /* BBSSI */ -3, RL, VB, BB, 0, 0, 0, /* BBCCI */ -2, RL, BB, 0, 0, 0, 0, /* BLBS */ -2, RL, BB, 0, 0, 0, 0, /* BLBC */ -4, RL, RB, VB, WL, 0, 0, /* FFS */ -4, RL, RB, VB, WL, 0, 0, /* FFC */ -4, RL, RB, VB, RL, 0, 0, /* CMPV */ -4, RL, RB, VB, RL, 0, 0, /* CMPZV */ -4, RL, RB, VB, WL, 0, 0, /* EXTV */ -4, RL, RB, VB, WL, 0, 0, /* EXTZV */ -4, RL, RL, RB, VB, 0, 0, /* INSV */ -4, RL, RL, ML, BW, 0, 0, /* ACBL */ -3, RL, ML, BB, 0, 0, 0, /* AOBLSS */ -3, RL, ML, BB, 0, 0, 0, /* AOBLEQ */ -2, ML, BB, 0, 0, 0, 0, /* SOBGEQ */ -2, ML, BB, 0, 0, 0, 0, /* SOBGTR */ -2, RL, WB, 0, 0, 0, 0, /* CVTLB */ -2, RL, WW, 0, 0, 0, 0, /* CVTLW */ -6+DR_F, RB, RW, AB, RB, RW, AB, /* ASHP */ -3+DR_F, RL, RW, AB, 0, 0, 0, /* CVTLP */ -2, AB, AB, 0, 0, 0, 0, /* CALLG */ -2, RL, AB, 0, 0, 0, 0, /* CALLS */ -0, 0, 0, 0, 0, 0, 0, /* XFC */ -0, 0, 0, 0, 0, 0, 0, /* 0FD */ -0, 0, 0, 0, 0, 0, 0, /* 0FE */ -0, 0, 0, 0, 0, 0, 0, /* 0FF */ -0, 0, 0, 0, 0, 0, 0, /* 100-10F */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 110-11F */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 120-12F */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 130-13F */ -0, 0, 0, 0, 0, 0, 0, -0x20, RD, OC, 0, 0, 0, 0, /* CVTDH */ -2, RG, WL, 0, 0, 0, 0, /* CVTGF */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -2, RG, MQ, 0, 0, 0, 0, /* ADDG2 */ -3, RG, RG, WQ, 0, 0, 0, /* ADDG3 */ -2, RG, MQ, 0, 0, 0, 0, /* SUBG2 */ -3, RG, RG, WQ, 0, 0, 0, /* SUBG3 */ -2, RG, MQ, 0, 0, 0, 0, /* MULG2 */ -3, RG, RG, WQ, 0, 0, 0, /* MULG3 */ -2, RG, MQ, 0, 0, 0, 0, /* DIVG2 */ -3, RG, RG, WQ, 0, 0, 0, /* DIVG3 */ -2, RG, WB, 0, 0, 0, 0, /* CVTGB */ -2, RG, WW, 0, 0, 0, 0, /* CVTGW */ -2, RG, WL, 0, 0, 0, 0, /* CVTGL */ -2, RG, WL, 0, 0, 0, 0, /* CVTRGL */ -2, RB, WQ, 0, 0, 0, 0, /* CVTBG */ -2, RW, WQ, 0, 0, 0, 0, /* CVTWG */ -2, RL, WQ, 0, 0, 0, 0, /* CVTLG */ -4, RG, RG, MQ, BW, 0, 0, /* ACBG */ -2, RG, WQ, 0, 0, 0, 0, /* MOVG */ -2, RG, RG, 0, 0, 0, 0, /* CMPG */ -2, RG, WQ, 0, 0, 0, 0, /* MNEGG */ -1, RG, 0, 0, 0, 0, 0, /* TSTG */ -5, RG, RW, RG, WL, WQ, 0, /* EMODG */ -3, RG, RW, AB, 0, 0, 0, /* POLYG */ -0x20, RG, OC, 0, 0, 0, 0, /* CVTGH */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0x20, OC, OC, 0, 0, 0, 0, /* ADDH2 */ -0x30, OC, OC, OC, 0, 0, 0, /* ADDH3 */ -0x20, OC, OC, 0, 0, 0, 0, /* SUBH2 */ -0x30, OC, OC, OC, 0, 0, 0, /* SUBH3 */ -0x20, OC, OC, 0, 0, 0, 0, /* MULH2 */ -0x30, OC, OC, OC, 0, 0, 0, /* MULH3 */ -0x20, OC, OC, 0, 0, 0, 0, /* DIVH2 */ -0x30, OC, OC, OC, 0, 0, 0, /* DIVH3 */ -0x20, OC, WB, 0, 0, 0, 0, /* CVTHB */ -0x20, OC, WW, 0, 0, 0, 0, /* CVTHW */ -0x20, OC, WL, 0, 0, 0, 0, /* CVTHL */ -0x20, OC, WL, 0, 0, 0, 0, /* CVTRHL */ -0x20, RB, OC, 0, 0, 0, 0, /* CVTBH */ -0x20, RW, OC, 0, 0, 0, 0, /* CVTWH */ -0x20, RL, OC, 0, 0, 0, 0, /* CVTLH */ -0x40, OC, OC, OC, BW, 0, 0, /* ACBH */ -0x20, OC, OC, 0, 0, 0, 0, /* MOVH */ -0x20, OC, OC, 0, 0, 0, 0, /* CMPH */ -0x20, OC, OC, 0, 0, 0, 0, /* MNEGH */ -0x10, OC, 0, 0, 0, 0, 0, /* TSTH */ -0x50, OC, RW, OC, WL, OC, 0, /* EMODH */ -0x30, OC, RW, AB, 0, 0, 0, /* POLYH */ -0x20, OC, WQ, 0, 0, 0, 0, /* CVTHG */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0x10, OC, 0, 0, 0, 0, 0, /* CLRO */ -0x20, OC, OC, 0, 0, 0, 0, /* MOVO */ -0x20, OC, WL, 0, 0, 0, 0, /* MOVAO*/ -0x10, OC, 0, 0, 0, 0, 0, /* PUSHAO*/ -0, 0, 0, 0, 0, 0, 0, /* 180-18F */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 190-19F */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0x20, RF, OC, 0, 0, 0, 0, /* CVTFH */ -2, RF, WQ, 0, 0, 0, 0, /* CVTFG */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 1A0-1AF */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 1B0-1BF */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 1C0-1CF */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 1D0-1DF */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 1E0-1EF */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 1F0-1FF */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0x20, OC, WL, 0, 0, 0, 0, /* CVTHF */ -0x20, OC, WQ, 0, 0, 0, 0, /* CVTHD */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0 }; - -/* Opcode mnemonics table */ - -const char *opcode[] = { -"HALT", "NOP", "REI", "BPT", "RET", "RSB", "LDPCTX", "SVPCTX", -"CVTPS", "CVTSP", "INDEX", "CRC", "PROBER", "PROBEW", "INSQUE", "REMQUE", -"BSBB", "BRB", "BNEQ", "BEQL", "BGTR", "BLEQ", "JSB", "JMP", -"BGEQ", "BLSS", "BGTRU", "BLEQU", "BVC", "BVS", "BGEQU", "BLSSU", -"ADDP4", "ADDP6", "SUBP4", "SUBP6", "CVTPT", "MULP6", "CVTTP", "DIVP", -"MOVC3", "CMPC3", "SCANC", "SPANC", "MOVC5", "CMPC5", "MOVTC", "MOVTUC", -"BSBW", "BRW", "CVTWL", "CVTWB", "MOVP", "CMPP3", "CVTPL", "CMPP4", -"EDITPC", "MATCHC", "LOCC", "SKPC", "MOVZWL", "ACBW", "MOVAW", "PUSHAW", -"ADDF2", "ADDF3", "SUBF2", "SUBF3", "MULF2", "MULF3", "DIVF2", "DIVF3", -"CVTFB", "CVTFW", "CVTFL", "CVTRFL", "CVTBF", "CVTWF", "CVTLF", "ACBF", -"MOVF", "CMPF", "MNEGF", "TSTF", "EMODF", "POLYF", "CVTFD", NULL, -"ADAWI", NULL, NULL, NULL, "INSQHI", "INSQTI", "REMQHI", "REMQTI", -"ADDD2", "ADDD3", "SUBD2", "SUBD3", "MULD2", "MULD3", "DIVD2", "DIVD3", -"CVTDB", "CVTDW", "CVTDL", "CVTRDL", "CVTBD", "CVTWD", "CVTLD", "ACBD", -"MOVD", "CMPD", "MNEGD", "TSTD", "EMODD", "POLYD", "CVTDF", NULL, -"ASHL", "ASHQ", "EMUL", "EDIV", "CLRQ", "MOVQ", "MOVAQ", "PUSHAQ", -"ADDB2", "ADDB3", "SUBB2", "SUBB3", "MULB2", "MULB3", "DIVB2", "DIVB3", -"BISB2", "BISB3", "BICB2", "BICB3", "XORB2", "XORB3", "MNEGB", "CASEB", -"MOVB", "CMPB", "MCOMB", "BITB", "CLRB", "TSTB", "INCB", "DECB", -"CVTBL", "CVTBW", "MOVZBL", "MOVZBW", "ROTL", "ACBB", "MOVAB", "PUSHAB", -"ADDW2", "ADDW3", "SUBW2", "SUBW3", "MULW2", "MULW3", "DIVW2", "DIVW3", -"BISW2", "BISW3", "BICW2", "BICW3", "XORW2", "XORW3", "MNEGW", "CASEW", -"MOVW", "CMPW", "MCOMW", "BITW", "CLRW", "TSTW", "INCW", "DECW", -"BISPSW", "BICPSW", "POPR", "PUSHR", "CHMK", "CHME", "CHMS", "CHMU", -"ADDL2", "ADDL3", "SUBL2", "SUBL3", "MULL2", "MULL3", "DIVL2", "DIVL3", -"BISL2", "BISL3", "BICL2", "BICL3", "XORL2", "XORL3", "MNEGL", "CASEL", -"MOVL", "CMPL", "MCOML", "BITL", "CLRL", "TSTL", "INCL", "DECL", -"ADWC", "SBWC", "MTPR", "MFPR", "MOVPSL", "PUSHL", "MOVAL", "PUSHAL", -"BBS", "BBC", "BBSS", "BBCS", "BBSC", "BBCC", "BBSSI", "BBCCI", -"BLBS", "BLBC", "FFS", "FFC", "CMPV", "CMPZV", "EXTV", "EXTZV", -"INSV", "ACBL", "AOBLSS", "AOBLEQ", "SOBGEQ", "SOBGTR", "CVTLB", "CVTLW", -"ASHP", "CVTLP", "CALLG", "CALLS", "XFC", NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 100 - 11F */ -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 120 - 13F */ -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, "CVTDH", "CVTGF", NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -"ADDG2", "ADDG3", "SUBG2", "SUBG3", "MULG2", "MULG3", "DIVG2", "DIVG3", -"CVTGB", "CVTGW", "CVTGL", "CVTRGL", "CVTBG", "CVTWG", "CVTLG", "ACBG", -"MOVG", "CMPG", "MNEGG", "TSTG", "EMODG", "POLYG", "CVTGH", NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -"ADDH2", "ADDH3", "SUBH2", "SUBH3", "MULH2", "MULH3", "DIVH2", "DIVH3", -"CVTHB", "CVTHW", "CVTHL", "CVTRHL", "CVTBH", "CVTWH", "CVTLH", "ACBH", -"MOVH", "CMPH", "MNEGH", "TSTH", "EMODH", "POLYH", "CVTHG", NULL, -NULL, NULL, NULL, NULL, "CLRO", "MOVO", "MOVAO", "PUSHAO", -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 180 - 19F */ -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -"CVTFH", "CVTFG", NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 1A0 - 1BF */ -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 1C0 - 1DF */ -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 1E0 - 1FF */ -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, "CVTHF", "CVTHD", -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; - -const char *altcod[] = { -"CLRF", "CLRD", "CLRG", "CLRH", "MOVAF", "MOVAD", "MOVAG", "MOVAH", -"PUSHAF", "PUSHAD", "PUSHAG", "PUSHAH", "BNEQU", "BEQLU", "BCC", "BCS", -NULL }; - -const int32 altop[] = { - 0xD4, 0x7C, 0x7C, 0x17C, 0xDE, 0x7E, 0x7E, 0x17E, - 0xDF, 0x7F, 0x7F, 0x17F, 0x12, 0x13, 0x1E, 0x1F }; - -const char* regname[] = { - "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", - "R8", "R9", "R10", "R11", "AP", "FP", "SP", "PC" }; - -#define GETNUM(d,n) for (k = d = 0; k < n; k++) \ - d = d | (((int32) val[vp++]) << (k * 8)) - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current PC - *val = values to decode - *uptr = pointer to unit - sw = switches - Outputs: - return = if >= 0, error code - if < 0, number of extra bytes retired -*/ - -t_stat fprint_sym (FILE *of, t_addr exta, t_value *val, - UNIT *uptr, int32 sw) -{ -uint32 addr = (uint32) exta; -int32 c, k, num, vp, lnt, rdx; -t_stat r; -DEVICE *dptr; - -if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ -dptr = find_dev_from_unit (uptr); /* find dev */ -if (dptr == NULL) return SCPE_IERR; -if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */ -if (sw & SWMASK ('B')) lnt = 1; /* get length */ -else if (sw & SWMASK ('W')) lnt = 2; -else if (sw & SWMASK ('L')) lnt = 4; -else lnt = (uptr == &cpu_unit)? 4: 1; -if (sw & SWMASK ('D')) rdx = 10; /* get radix */ -else if (sw & SWMASK ('O')) rdx = 8; -else if (sw & SWMASK ('H')) rdx = 16; -else rdx = dptr->dradix; -vp = 0; /* init ptr */ -if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */ - if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */ - if ((val[0] & 0x7F) == 0) return SCPE_ARG; - while (vp < lnt) { /* print string */ - if ((c = (int32) val[vp++] & 0x7F) == 0) break; - fprintf (of, (c < 0x20)? "<%02X>": "%c", c); } - return -(vp - 1); } /* return # chars */ - -if (sw & SWMASK ('M') && (uptr == &cpu_unit)) { /* inst format? */ - r = fprint_sym_m (of, addr, val); /* decode inst */ - if (r <= 0) return r; } - -GETNUM (num, lnt); /* get number */ -fprint_val (of, (uint32) num, rdx, lnt * 8, PV_RZRO); -return -(vp - 1); -} - -/* Symbolic decode for -m - - Inputs: - of = output stream - addr = current PC - *val = values to decode - Outputs: - return = if >= 0, error code - if < 0, number of extra bytes retired -*/ - -t_stat fprint_sym_m (FILE *of, uint32 addr, t_value *val) -{ -int32 i, k, vp, inst, numspec; -int32 num, spec, rn, disp, index; - -vp = 0; /* init ptr */ -inst = (int32) val[vp++]; /* get opcode */ -if (inst == 0xFD) inst = 0x100 | (int32) val[vp++]; /* 2 byte op? */ -if (opcode[inst] == NULL) return SCPE_ARG; /* defined? */ -numspec = drom[inst][0] & DR_NSPMASK; /* get # spec */ -if (numspec == 0) numspec = (drom[inst][0] & DR_USPMASK) >> 4; -fprintf (of, "%s", opcode[inst]); /* print name */ -for (i = 0; i < numspec; i++) { /* loop thru spec */ - fputc (i? ',': ' ', of); /* separator */ - disp = drom[inst][i + 1]; /* get drom value */ - if (disp == BB) { /* byte br disp? */ - GETNUM (num, 1); - fprintf (of, "%-X", SXTB (num) + addr + vp); } - else if (disp == BW) { /* word br disp? */ - GETNUM (num, 2); - fprintf (of, "%-X", SXTW (num) + addr + vp); } - else { - spec = (int32) val[vp++]; /* get specifier */ - if ((spec & 0xF0) == IDX) { /* index? */ - index = spec; /* copy, get next */ - spec = (int32) val[vp++]; } - else index = 0; - rn = spec & 0xF; /* get reg # */ - switch (spec & 0xF0) { /* case on mode */ - case SH0: case SH1: case SH2: case SH3: /* s^# */ - fprintf (of, "#%-X", spec); - break; - case GRN: /* Rn */ - fprintf (of, "%-s", regname[rn]); - break; - case RGD: /* (Rn) */ - fprintf (of, "(%-s)", regname[rn]); - break; - case ADC: /* -(Rn) */ - fprintf (of, "-(%-s)", regname[rn]); - break; - case AIN: /* (Rn)+, #n */ - if (rn != nPC) fprintf (of, "(%-s)+", regname[rn]); - else { - if (disp == OC) - vp = fprint_sym_qoimm (of, val, vp, 4); - else if (DR_LNT (disp) == L_QUAD) - vp = fprint_sym_qoimm (of, val, vp, 2); - else { - GETNUM (num, DR_LNT (disp)); - fprintf (of, "#%-X", num); } } - break; - case AID: /* @(Rn)+, @#n */ - if (rn != nPC) fprintf (of, "@(%-s)+", regname[rn]); - else { - GETNUM (num, 4); - fprintf (of, "@#%-X", num); } - break; - case BDD: /* @b^d(r),@b^n */ - fputc ('@', of); - case BDP: /* b^d(r), b^n */ - GETNUM (num, 1); - if (rn == nPC) fprintf (of, "%-X", addr + vp + SXTB (num)); - else if (num & BSIGN) fprintf (of, "-%-X(%-s)", - -num & BMASK, regname[rn]); - else fprintf (of, "%-X(%-s)", num, regname[rn]); - break; - case WDD: /* @w^d(r),@w^n */ - fputc ('@', of); - case WDP: /* w^d(r), w^n */ - GETNUM (num, 2); - if (rn == nPC) fprintf (of, "%-X", addr + vp + SXTW (num)); - else if (num & WSIGN) fprintf (of, "-%-X(%-s)", - -num & WMASK, regname[rn]); - else fprintf (of, "%-X(%-s)", num, regname[rn]); - break; - case LDD: /* @l^d(r),@l^n */ - fputc ('@', of); - case LDP: /* l^d(r),l^n */ - GETNUM (num, 4); - if (rn == nPC) fprintf (of, "%-X", addr + vp + num); - else if (num & LSIGN) fprintf (of, "-%-X(%-s)", - -num, regname[rn]); - else fprintf (of, "%-X(%-s)", num, regname[rn]); - break; } /* end case */ - if (index) fprintf (of, "[%-s]", regname[index & 0xF]); - } /* end else */ - } /* end for */ -return -(vp - 1); -} - -/* Symbolic decode, quad/octa immediates - - Inputs: - *of = output stream - *val = pointer to input values - vp = current index into val - lnt = number of longwords in immediate - Outputs: - vp = updated index into val -*/ - -int32 fprint_sym_qoimm (FILE *of, t_value *val, int32 vp, int32 lnt) -{ -int32 i, k, startp, num[4]; - -for (i = 0; i < lnt; i++) { GETNUM (num[lnt - 1 - i], 4); } -for (i = startp = 0; i < lnt; i++) { - if (startp) fprintf (of, "%08X", num[i]); - else if (num[i] || (i == (lnt - 1))) { - fprintf (of, "#%-X", num[i]); - startp = 1; } } -return vp; -} - -#define PUTNUM(d,n) for (k = 0; k < n; k++) val[vp++] = (d >> (k * 8)) & 0xFF - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = > 0 error code - <= 0 -number of extra words -*/ - -t_stat parse_sym (char *cptr, t_addr exta, UNIT *uptr, t_value *val, int32 sw) -{ -uint32 addr = (uint32) exta; -int32 k, rdx, lnt, num, vp; -t_stat r; -DEVICE *dptr; -static const uint32 maxv[5] = { 0, 0xFF, 0xFFFF, 0, 0xFFFFFFFF }; - -if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ -dptr = find_dev_from_unit (uptr); /* find dev */ -if (dptr == NULL) return SCPE_IERR; -if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */ -if (sw & SWMASK ('B')) lnt = 1; /* get length */ -else if (sw & SWMASK ('W')) lnt = 2; -else if (sw & SWMASK ('L')) lnt = 4; -else lnt = (uptr == &cpu_unit)? 4: 1; -if (sw & SWMASK ('D')) rdx = 10; /* get radix */ -else if (sw & SWMASK ('O')) rdx = 8; -else if (sw & SWMASK ('H')) rdx = 16; -else rdx = dptr->dradix; -vp = 0; -if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */ - if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */ - if (*cptr == 0) return SCPE_ARG; - while ((vp < lnt) && *cptr) { /* get chars */ - val[vp++] = *cptr++; } - return -(vp - 1); } /* return # chars */ - -if (uptr == &cpu_unit) { /* cpu only */ - r = parse_sym_m (cptr, addr, val); /* try to parse inst */ - if (r <= 0) return r; } - -num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */ -if (r != SCPE_OK) return r; -PUTNUM (num, lnt); /* store */ -return -(lnt - 1); -} - -/* Symbolic input for -m - - Inputs: - *cptr = pointer to input string - addr = current PC - *val = pointer to output values - Outputs: - status = > 0 error code - <= 0 -number of extra words -*/ - -t_stat parse_sym_m (char *cptr, uint32 addr, t_value *val) -{ -int32 i, numspec, disp, opc, vp; -t_stat r; -char gbuf[CBUFSIZE]; - -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -for (i = 0, opc = -1; (i < NUM_INST) && (opc < 0); i++) { - if (opcode[i] && strcmp (gbuf, opcode[i]) == 0) opc = i; } -if (opc < 0) { /* check alternates */ - for (i = 0; altcod[i] && (opc < 0); i++) { - if (strcmp (gbuf, altcod[i]) == 0) opc = altop[i]; } } -if (opc < 0) return SCPE_ARG; /* undefined? */ -vp = 0; -if (opc >= 0x100) val[vp++] = 0xFD; /* 2 byte? */ -val[vp++] = opc & 0xFF; /* store opcode */ -numspec = drom[opc][0] & DR_NSPMASK; /* get # specifiers */ -if (numspec == 0) numspec = (drom[opc][0] & DR_USPMASK) >> 4; -for (i = 1; i <= numspec; i++) { /* loop thru specs */ - if (i == numspec) cptr = get_glyph (cptr, gbuf, 0); - else cptr = get_glyph (cptr, gbuf, ','); /* get specifier */ - disp = drom[opc][i]; /* get drom value */ - if (disp == BB) vp = parse_brdisp (gbuf, addr, val, vp, 0, &r); - else if (disp == BW) vp = parse_brdisp (gbuf, addr, val, vp, 1, &r); - else vp = parse_spec (gbuf, addr, val, vp, disp, &r); - if (r != SCPE_OK) return r; } -if (*cptr != 0) return SCPE_ARG; -return -(vp - 1); -} - -/* Parse a branch displacement - - Inputs: - cptr = pointer to input buffer - addr = current address - val = pointer to output array - vp = current pointer in output array - lnt = length (0 = byte, 1 = word) - r = pointer to status - Outputs: - vp = updated output pointer -*/ - -int32 parse_brdisp (char *cptr, uint32 addr, t_value *val, int32 vp, - int32 lnt, t_stat *r) -{ -int32 k, dest, num; - -dest = (int32) get_uint (cptr, 16, 0xFFFFFFFF, r); /* get value */ -num = dest - (addr + vp + lnt + 1); /* compute offset */ -if ((num > (lnt? 32767: 127)) || (num < (lnt? -32768: -128))) return SCPE_ARG; -PUTNUM (num, lnt + 1); /* store offset */ -return vp; -} - -/* Parse a specifier - - Inputs: - cptr = pointer to input buffer - addr = current address - val = pointer to output array - vp = current pointer in output array - disp = specifier dispatch - r = pointer to status - Outputs: - vp = updated output pointer -*/ - -#define SP_IND 0x200 /* indirect */ -#define SP_V_FORCE 6 -#define SP_FS 0x040 /* S^ */ -#define SP_FI 0x080 /* I^ */ -#define SP_FB 0x0C0 /* B^ */ -#define SP_FW 0x100 /* W^ */ -#define SP_FL 0x140 /* L^ */ -#define SP_LIT 0x020 /* # */ -#define SP_PLUS 0x010 /* plus */ -#define SP_MINUS 0x008 /* minus */ -#define SP_NUM 0x004 /* number */ -#define SP_IDX 0x002 /* (Rn) */ -#define SP_POSTP 0x001 /* trailing + */ -#define M1C(c,v) if (*cptr == c) { cptr++; fl = fl | v; } -#define SPUTNUM(v,d) if (fl & SP_MINUS) v = -v; PUTNUM (v, d) -#define PARSE_LOSE { *r = SCPE_ARG; return vp; } -#define SEL_LIM(p,m,u) ((fl & SP_PLUS)? (p): ((fl & SP_MINUS)? (m): (u))) - -int32 parse_spec (char *cptr, uint32 addr, t_value *val, int32 vp, int32 disp, t_stat *r) -{ -int32 i, k, litsize, rn, index; -int32 num, dispsize, mode; -int32 lit[4] = { 0 }; -int32 fl = 0; -char c, *tptr; -const char *force[] = { "S^", "I^", "B^", "W^", "L^", NULL }; - -*r = SCPE_OK; /* assume ok */ -M1C ('@', SP_IND); /* look for @ */ -if (tptr = parse_rnum (cptr, &rn)) { /* look for Rn */ - if (*cptr == '[') { /* look for [Rx] */ - cptr = parse_rnum (++cptr, &index); - if ((cptr == NULL) || (*cptr++ != ']')) PARSE_LOSE; - val[vp++] = index | IDX; } - else val[vp++] = rn | GRN | (fl? 1: 0); /* Rn or @Rn */ - if (*tptr != 0) *r = SCPE_ARG; /* must be done */ - return vp; } -for (i = 0; force[i]; i++) { /* look for x^ */ - if (strncmp (cptr, force[i], 2) == 0) { - cptr = cptr + 2; - fl = fl | ((i + 1) << SP_V_FORCE); - break; } } -M1C ('#', SP_LIT); /* look for # */ -M1C ('+', SP_PLUS); /* look for + */ -M1C ('-', SP_MINUS); /* look for - */ -for (litsize = 0;; cptr++) { /* look for mprec int */ - c = *cptr; - if ((c < '0') || (c > 'F') || ((c > '9') && (c < 'A'))) break; - num = (c <= '9')? c - '0': c - 'A' + 10; - fl = fl | SP_NUM; - for (i = 3; i >= 0; i--) { - lit[i] = lit[i] << 4; - if (i > 0) lit[i] = lit[i] | ((lit[i - 1] >> 28) & 0xF); - else lit[i] = lit[i] | num; - if (lit[i] && (i > litsize)) litsize = i; } } -if (*cptr == '(') { /* look for (Rn) */ - cptr = parse_rnum (++cptr, &rn); - if ((cptr == NULL) || (*cptr++ != ')')) PARSE_LOSE; - fl = fl | SP_IDX; } -M1C ('+', SP_POSTP); /* look for + */ -if (*cptr == '[') { /* look for [Rx] */ - cptr = parse_rnum (++cptr, &index); - if ((cptr == NULL) || (*cptr++ != ']')) PARSE_LOSE; - val[vp++] = index | IDX; } -switch (fl) { /* case on state */ -case SP_FS|SP_LIT|SP_NUM: /* S^#n */ -case SP_FS|SP_LIT|SP_PLUS|SP_NUM: /* S^#+n */ - if ((litsize > 0) || (lit[0] & ~0x3F)) PARSE_LOSE; - val[vp++] = lit[0]; - break; -case SP_IDX: /* (Rn) */ - val[vp++] = rn | RGD; - break; -case SP_MINUS|SP_IDX: /* -(Rn) */ - val[vp++] = rn | ADC; - break; -case SP_IDX|SP_POSTP: /* (Rn)+ */ - val[vp++] = rn | AIN; - break; -case SP_LIT|SP_NUM: /* #n */ -case SP_LIT|SP_PLUS|SP_NUM: /* #+n */ - if ((litsize == 0) && ((lit[0] & ~0x3F) == 0)) { - val[vp++] = lit[0]; - break; } -case SP_LIT|SP_MINUS|SP_NUM: /* #-n */ -case SP_FI|SP_LIT|SP_NUM: /* I^#n */ -case SP_FI|SP_LIT|SP_PLUS|SP_NUM: /* I^#+n */ -case SP_FI|SP_LIT|SP_MINUS|SP_NUM: /* I^#-n */ - val[vp++] = nPC | AIN; - disp = (disp == OC)? DR_LNMASK + 1: disp & DR_LNMASK; - switch (disp) { /* case spec lnt */ - case 00: /* check fit */ - if ((litsize > 0) || (lit[0] < 0) || - (lit[0] > SEL_LIM (0x7F, 0x80, 0xFF))) PARSE_LOSE; - SPUTNUM (lit[0], 1); /* store */ - break; - case 01: /* check fit */ - if ((litsize > 0) || (lit[0] < 0) || - (lit[0] > SEL_LIM (0x7FFF, 0x8000, 0xFFFF))) PARSE_LOSE; - SPUTNUM (lit[0], 2); - break; - case 02: /* check 1 lw */ - if (litsize > 0) PARSE_LOSE; - SPUTNUM (lit[0], 4); - break; - case 03: /* check 2 lw */ - if (litsize > 1) PARSE_LOSE; - vp = parse_sym_qoimm (lit, val, vp, 2, fl & SP_MINUS); - break; - case DR_LNMASK + 1: - vp = parse_sym_qoimm (lit, val, vp, 4, fl & SP_MINUS); - break; } /* end case disp */ - break; -case SP_IND|SP_IDX|SP_POSTP: /* @(Rn)+ */ - val[vp++] = rn | AID; - break; -case SP_IND|SP_LIT|SP_NUM: /* @#n */ - if (litsize > 0) PARSE_LOSE; - val[vp++] = nPC | AID; - PUTNUM (lit[0], 4); - break; -case SP_NUM|SP_IDX: /* d(rn) */ -case SP_PLUS|SP_NUM|SP_IDX: /* +d(rn) */ -case SP_MINUS|SP_NUM|SP_IDX: /* -d(rn) */ -case SP_IND|SP_NUM|SP_IDX: /* @d(rn) */ -case SP_IND|SP_PLUS|SP_NUM|SP_IDX: /* @+d(rn) */ -case SP_IND|SP_MINUS|SP_NUM|SP_IDX: /* @-d(rn) */ - if (litsize > 0) PARSE_LOSE; - dispsize = 4; /* find fit for */ - mode = LDP; /* displacement */ - if (lit[0] >= 0) { - if (lit[0] <= SEL_LIM (0x7F, 0x80, 0xFF)) { - dispsize = 1; - mode = BDP; } - else if (lit[0] <= SEL_LIM (0x7FFF, 0x8000, 0xFFFF)) { - dispsize = 2; - mode = WDP; } } - val[vp++] = mode | rn | ((fl & SP_IND)? 1: 0); - SPUTNUM (lit[0], dispsize); - break; -case SP_FB|SP_NUM|SP_IDX: /* B^d(rn) */ -case SP_FB|SP_PLUS|SP_NUM|SP_IDX: /* B^+d(rn) */ -case SP_FB|SP_MINUS|SP_NUM|SP_IDX: /* B^-d(rn) */ -case SP_IND|SP_FB|SP_NUM|SP_IDX: /* @B^d(rn) */ -case SP_IND|SP_FB|SP_PLUS|SP_NUM|SP_IDX: /* @B^+d(rn) */ -case SP_IND|SP_FB|SP_MINUS|SP_NUM|SP_IDX: /* @B^-d(rn) */ - if ((litsize > 0) || (lit[0] < 0) || - (lit[0] > SEL_LIM (0x7F, 0x80, 0xFF))) PARSE_LOSE; - val[vp++] = rn | BDP | ((fl & SP_IND)? 1: 0); - SPUTNUM (lit[0], 1); - break; -case SP_FW|SP_NUM|SP_IDX: /* W^d(rn) */ -case SP_FW|SP_PLUS|SP_NUM|SP_IDX: /* W^+d(rn) */ -case SP_FW|SP_MINUS|SP_NUM|SP_IDX: /* W^-d(rn) */ -case SP_IND|SP_FW|SP_NUM|SP_IDX: /* @W^d(rn) */ -case SP_IND|SP_FW|SP_PLUS|SP_NUM|SP_IDX: /* @W^+d(rn) */ -case SP_IND|SP_FW|SP_MINUS|SP_NUM|SP_IDX: /* @W^-d(rn) */ - if ((litsize > 0) || (lit[0] < 0) || - (lit[0] > SEL_LIM (0x7FFF, 0x8000, 0xFFFF))) PARSE_LOSE; - val[vp++] = rn | WDP | ((fl & SP_IND)? 1: 0); - SPUTNUM (lit[0], 2); - break; -case SP_FL|SP_NUM|SP_IDX: /* L^d(rn) */ -case SP_FL|SP_PLUS|SP_NUM|SP_IDX: /* L^+d(rn) */ -case SP_FL|SP_MINUS|SP_NUM|SP_IDX: /* L^-d(rn) */ -case SP_IND|SP_FL|SP_NUM|SP_IDX: /* @L^d(rn) */ -case SP_IND|SP_FL|SP_PLUS|SP_NUM|SP_IDX: /* @L^+d(rn) */ -case SP_IND|SP_FL|SP_MINUS|SP_NUM|SP_IDX: /* @L^-d(rn) */ - if ((litsize > 0) || (lit[0] < 0)) PARSE_LOSE; - val[vp++] = rn | LDP | ((fl & SP_IND)? 1: 0); - SPUTNUM (lit[0], 2); - break; -case SP_NUM: /* n */ -case SP_IND|SP_NUM: /* @n */ - if (litsize > 0) PARSE_LOSE; - num = lit[0] - (addr + vp + 2); /* fit in byte? */ - if ((num >= -128) && (num <= 127)) { - mode = BDP; - dispsize = 1; } - else { - num = lit[0] - (addr + vp + 3); /* fit in word? */ - if ((num >= -32768) && (num <= 32767)) { - mode = WDP; - dispsize = 2; } - else { - num = lit[0] - (addr + vp + 5); /* no, use lw */ - mode = LDP; - dispsize = 4; } } - val[vp++] = mode | nPC | ((fl & SP_IND)? 1: 0); - PUTNUM (num, dispsize); - break; -case SP_FB|SP_NUM: /* B^n */ -case SP_IND|SP_FB|SP_NUM: /* @B^n */ - num = lit[0] - (addr + vp + 2); - if ((litsize > 0) || (num > 127) || (num < -128)) PARSE_LOSE; - val[vp++] = nPC | BDP | ((fl & SP_IND)? 1: 0); - PUTNUM (num, 1); - break; -case SP_FW|SP_NUM: /* W^n */ -case SP_IND|SP_FW|SP_NUM: /* @W^n */ - num = lit[0] - (addr + vp + 3); - if ((litsize > 0) || (num > 32767) || (num < -32768)) PARSE_LOSE; - val[vp++] = nPC | WDP | ((fl & SP_IND)? 1: 0); - PUTNUM (num, 2); - break; -case SP_FL|SP_NUM: /* L^n */ -case SP_IND|SP_FL|SP_NUM: /* @L^n */ - num = lit[0] - (addr + vp + 5); - if (litsize > 0) PARSE_LOSE; - val[vp++] = nPC | LDP | ((fl & SP_IND)? 1: 0); - PUTNUM (num, 4); - break; -default: - PARSE_LOSE; } /* end case */ -if (*cptr != 0) *r = SCPE_ARG; /* must be done */ -return vp; -} - -char *parse_rnum (char *cptr, int32 *rn) -{ -int32 i, lnt; -t_value regnum; -char *tptr; - -for (i = 15; i >= 0; i--) { /* chk named reg */ - lnt = strlen (regname[i]); - if (strncmp (cptr, regname[i], lnt) == 0) { - *rn = i; - return cptr + lnt; } } -if (*cptr++ != 'R') return NULL; /* look for R */ -regnum = strtotv (cptr, &tptr, 10); /* look for reg # */ -if ((cptr == tptr) || (regnum > 15)) return NULL; -*rn = (int32) regnum; -return tptr; -} - -int32 parse_sym_qoimm (int32 *lit, t_value *val, int32 vp, int lnt, int32 minus) -{ -int32 i, k, prev; - -for (i = prev = 0; i < lnt; i++) { - if (minus) prev = lit[i] = ~lit[i] + (prev == 0); - PUTNUM (lit[i], 4); } -return vp; -} - diff --git a/VAX/vax_sysdev.c b/VAX/vax_sysdev.c deleted file mode 100644 index 77214ad1..00000000 --- a/VAX/vax_sysdev.c +++ /dev/null @@ -1,1293 +0,0 @@ -/* vax_sysreg.c: VAX system registers simulator - - Copyright (c) 1998-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - This module contains the CVAX system-specific devices implemented in the - CMCTL memory controller and the SSC system support chip. (The architecturally - specified devices are implemented in module vax_stddev.c.) - - rom bootstrap ROM (no registers) - nvr non-volatile ROM (no registers) - csi console storage input - cso console storage output - sysd system devices (SSC miscellany) - - 7-Jun-03 MP Added calibrated delay to ROM reads (from Mark Pizzolato) - Fixed calibration problems interval timer (from Mark Pizzolato) - 12-May-03 RMS Fixed compilation warnings from VC.Net - 23-Apr-03 RMS Revised for 32b/64b t_addr - 19-Aug-02 RMS Removed unused variables (found by David Hittner) - Allowed NVR to be attached to file - 30-May-02 RMS Widened POS to 32b - 28-Feb-02 RMS Fixed bug, missing end of table (found by Lars Brinkhoff) -*/ - -#include "vax_defs.h" - -#define UNIT_V_NODELAY (UNIT_V_UF + 0) /* ROM access equal to RAM access */ -#define UNIT_NODELAY (1u << UNIT_V_NODELAY) - -/* Console storage control/status */ - -#define CSICSR_IMP (CSR_DONE + CSR_IE) /* console input */ -#define CSICSR_RW (CSR_IE) -#define CSOCSR_IMP (CSR_DONE + CSR_IE) /* console output */ -#define CSOCSR_RW (CSR_IE) - -/* CMCTL configuration registers */ - -#define CMCNF_VLD 0x80000000 /* addr valid */ -#define CMCNF_BA 0x1FF00000 /* base addr */ -#define CMCNF_LOCK 0x00000040 /* lock NI */ -#define CMCNF_SRQ 0x00000020 /* sig req WO */ -#define CMCNF_SIG 0x0000001F /* signature */ -#define CMCNF_RW (CMCNF_VLD | CMCNF_BA) /* read/write */ -#define CMCNF_MASK (CMCNF_RW | CMCNF_SIG) -#define MEM_BANK (1 << 22) /* bank size 4MB */ -#define MEM_SIG 0x17; /* ECC, 4 x 4MB */ - -/* CMCTL error register */ - -#define CMERR_RDS 0x80000000 /* uncorr err NI */ -#define CMERR_FRQ 0x40000000 /* 2nd RDS NI */ -#define CMERR_CRD 0x20000000 /* CRD err NI */ -#define CMERR_PAG 0x1FFFFC00 /* page addr NI */ -#define CMERR_DMA 0x00000100 /* DMA err NI */ -#define CMERR_BUS 0x00000080 /* bus err NI */ -#define CMERR_SYN 0x0000007F /* syndrome NI */ -#define CMERR_W1C (CMERR_RDS | CMERR_FRQ | CMERR_CRD | \ - CMERR_DMA | CMERR_BUS) - -/* CMCTL control/status register */ - -#define CMCSR_PMI 0x00002000 /* PMI speed NI */ -#define CMCSR_CRD 0x00001000 /* enb CRD int NI */ -#define CMCSR_FRF 0x00000800 /* force ref WONI */ -#define CMCSR_DET 0x00000400 /* dis err NI */ -#define CMCSR_FDT 0x00000200 /* fast diag NI */ -#define CMCSR_DCM 0x00000080 /* diag mode NI */ -#define CMCSR_SYN 0x0000007F /* syndrome NI */ -#define CMCSR_MASK (CMCSR_PMI | CMCSR_CRD | CMCSR_DET | \ - CMCSR_FDT | CMCSR_DCM | CMCSR_SYN) - -/* KA655 boot/diagnostic register */ - -#define BDR_BRKENB 0x00000080 /* break enable */ - -/* KA655 cache control register */ - -#define CACR_DRO 0x00FFFF00 /* diag bits RO */ -#define CACR_V_DPAR 24 /* data parity */ -#define CACR_FIXED 0x00000040 /* fixed bits */ -#define CACR_CPE 0x00000020 /* parity err W1C */ -#define CACR_CEN 0x00000010 /* enable */ -#define CACR_DPE 0x00000004 /* disable par NI */ -#define CACR_WWP 0x00000002 /* write wrong par NI */ -#define CACR_DIAG 0x00000001 /* diag mode */ -#define CACR_W1C (CACR_CPE) -#define CACR_RW (CACR_CEN | CACR_DPE | CACR_WWP | CACR_DIAG) - -/* SSC base register */ - -#define SSCBASE_MBO 0x20000000 /* must be one */ -#define SSCBASE_RW 0x1FFFFC00 /* base address */ - -/* SSC configuration register */ - -#define SSCCNF_BLO 0x80000000 /* batt low W1C */ -#define SSCCNF_IVD 0x08000000 /* int dsbl NI */ -#define SSCCNF_IPL 0x03000000 /* int IPL NI */ -#define SSCCNF_ROM 0x00F70000 /* ROM param NI */ -#define SSCCNF_CTLP 0x00008000 /* ctrl P enb */ -#define SSCCNF_BAUD 0x00007700 /* baud rates NI */ -#define SSCCNF_ADS 0x00000077 /* addr strb NI */ -#define SSCCNF_W1C SSCCNF_BLO -#define SSCCNF_RW 0x0BF7F777 - -/* SSC timeout register */ - -#define SSCBTO_BTO 0x80000000 /* timeout W1C */ -#define SSCBTO_RWT 0x40000000 /* read/write W1C */ -#define SSCBTO_INTV 0x00FFFFFF /* interval NI */ -#define SSCBTO_W1C (SSCBTO_BTO | SSCBTO_RWT) -#define SSCBTO_RW SSCBTO_INTV - -/* SSC output port */ - -#define SSCOTP_MASK 0x0000000F /* output port */ - -/* SSC timer control/status */ - -#define TMR_CSR_ERR 0x80000000 /* error W1C */ -#define TMR_CSR_DON 0x00000080 /* done W1C */ -#define TMR_CSR_IE 0x00000040 /* int enb */ -#define TMR_CSR_SGL 0x00000020 /* single WO */ -#define TMR_CSR_XFR 0x00000010 /* xfer WO */ -#define TMR_CSR_STP 0x00000004 /* stop */ -#define TMR_CSR_RUN 0x00000001 /* run */ -#define TMR_CSR_W1C (TMR_CSR_ERR | TMR_CSR_DON) -#define TMR_CSR_RW (TMR_CSR_IE | TMR_CSR_STP | TMR_CSR_RUN) - -/* SSC timer intervals */ - -#define TMR_INC 10000 /* usec/interval */ - -/* SSC timer vector */ - -#define TMR_VEC_MASK 0x000003FC /* vector */ - -/* SSC address strobes */ - -#define SSCADS_MASK 0x3FFFFFFC /* match or mask */ - -extern int32 int_req[IPL_HLVL]; -extern UNIT cpu_unit; -extern UNIT clk_unit; -extern jmp_buf save_env; -extern int32 p1; -extern int32 sim_switches; -extern int32 MSER; -extern int32 tmr_poll; - -uint32 *rom = NULL; /* boot ROM */ -uint32 *nvr = NULL; /* non-volatile mem */ -int32 csi_csr = 0; /* control/status */ -int32 cso_csr = 0; /* control/status */ -int32 cmctl_reg[CMCTLSIZE >> 2] = { 0 }; /* CMCTL reg */ -int32 ka_cacr = 0; /* KA655 cache ctl */ -int32 ka_bdr = BDR_BRKENB; /* KA655 boot diag */ -int32 ssc_base = SSCBASE; /* SSC base */ -int32 ssc_cnf = 0; /* SSC conf */ -int32 ssc_bto = 0; /* SSC timeout */ -int32 ssc_otp = 0; /* SSC output port */ -int32 tmr_csr[2] = { 0 }; /* SSC timers */ -uint32 tmr_tir[2] = { 0 }; /* curr interval */ -uint32 tmr_tnir[2] = { 0 }; /* next interval */ -int32 tmr_tivr[2] = { 0 }; /* vector */ -uint32 tmr_inc[2] = { 0 }; /* tir increment */ -uint32 tmr_sav[2] = { 0 }; /* saved inst cnt */ -int32 ssc_adsm[2] = { 0 }; /* addr strobes */ -int32 ssc_adsk[2] = { 0 }; -int32 cdg_dat[CDASIZE >> 2]; /* cache data */ -static uint32 rom_delay = 0; - -t_stat rom_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw); -t_stat rom_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw); -t_stat rom_reset (DEVICE *dptr); -t_stat nvr_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw); -t_stat nvr_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw); -t_stat nvr_reset (DEVICE *dptr); -t_stat nvr_attach (UNIT *uptr, char *cptr); -t_stat nvr_detach (UNIT *uptr); -t_stat csi_reset (DEVICE *dptr); -t_stat cso_reset (DEVICE *dptr); -t_stat cso_svc (UNIT *uptr); -t_stat tmr_svc (UNIT *uptr); -t_stat sysd_reset (DEVICE *dptr); - -int32 rom_rd (int32 pa); -int32 nvr_rd (int32 pa); -void nvr_wr (int32 pa, int32 val, int32 lnt); -int32 csrs_rd (void); -int32 csrd_rd (void); -int32 csts_rd (void); -void csrs_wr (int32 dat); -void csts_wr (int32 dat); -void cstd_wr (int32 dat); -int32 cmctl_rd (int32 pa); -void cmctl_wr (int32 pa, int32 val, int32 lnt); -int32 ka_rd (int32 pa); -void ka_wr (int32 pa, int32 val, int32 lnt); -int32 cdg_rd (int32 pa); -void cdg_wr (int32 pa, int32 val, int32 lnt); -int32 ssc_rd (int32 pa); -void ssc_wr (int32 pa, int32 val, int32 lnt); -int32 tmr_tir_rd (int32 tmr, t_bool interp); -void tmr_csr_wr (int32 tmr, int32 val); -void tmr_sched (int32 tmr); -void tmr_incr (int32 tmr, uint32 inc); -int32 tmr0_inta (void); -int32 tmr1_inta (void); -int32 parity (int32 val, int32 odd); - -extern int32 cqmap_rd (int32 pa); -extern void cqmap_wr (int32 pa, int32 val, int32 lnt); -extern int32 cqipc_rd (int32 pa); -extern void cqipc_wr (int32 pa, int32 val, int32 lnt); -extern int32 cqbic_rd (int32 pa); -extern void cqbic_wr (int32 pa, int32 val, int32 lnt); -extern int32 cqmem_rd (int32 pa); -extern void cqmem_wr (int32 pa, int32 val, int32 lnt); -extern int32 iccs_rd (void); -extern int32 todr_rd (void); -extern int32 rxcs_rd (void); -extern int32 rxdb_rd (void); -extern int32 txcs_rd (void); -extern void iccs_wr (int32 dat); -extern void todr_wr (int32 dat); -extern void rxcs_wr (int32 dat); -extern void txcs_wr (int32 dat); -extern void txdb_wr (int32 dat); -extern void ioreset_wr (int32 dat); -extern uint32 sim_os_msec(); - -/* ROM data structures - - rom_dev ROM device descriptor - rom_unit ROM units - rom_reg ROM register list -*/ - -UNIT rom_unit = { UDATA (NULL, UNIT_FIX+UNIT_BINK, ROMSIZE) }; - -REG rom_reg[] = { - { NULL } }; - -MTAB rom_mod[] = { - { UNIT_NODELAY, UNIT_NODELAY, "fast access", "NODELAY", NULL }, - { UNIT_NODELAY, 0, "1usec calibrated access", "DELAY", NULL }, - { 0 } }; - -DEVICE rom_dev = { - "ROM", &rom_unit, rom_reg, rom_mod, - 1, 16, ROMAWIDTH, 4, 16, 32, - &rom_ex, &rom_dep, &rom_reset, - NULL, NULL, NULL, - NULL, 0 }; - -/* NVR data structures - - nvr_dev NVR device descriptor - nvr_unit NVR units - nvr_reg NVR register list -*/ - -UNIT nvr_unit = - { UDATA (NULL, UNIT_FIX+UNIT_BINK, NVRSIZE) }; - -REG nvr_reg[] = { - { NULL } }; - -DEVICE nvr_dev = { - "NVR", &nvr_unit, nvr_reg, NULL, - 1, 16, NVRAWIDTH, 4, 16, 32, - &nvr_ex, &nvr_dep, &nvr_reset, - NULL, &nvr_attach, &nvr_detach, - NULL, 0 }; - -/* CSI data structures - - csi_dev CSI device descriptor - csi_unit CSI unit descriptor - csi_reg CSI register list -*/ - -DIB csi_dib = { 0, 0, NULL, NULL, 1, IVCL (CSI), SCB_CSI, { NULL } }; - -UNIT csi_unit = { UDATA (NULL, 0, 0), KBD_POLL_WAIT }; - -REG csi_reg[] = { - { ORDATA (BUF, csi_unit.buf, 8) }, - { ORDATA (CSR, csi_csr, 16) }, - { FLDATA (INT, int_req[IPL_CSI], INT_V_CSI) }, - { FLDATA (DONE, csi_csr, CSR_V_DONE) }, - { FLDATA (IE, csi_csr, CSR_V_IE) }, - { DRDATA (POS, csi_unit.pos, 32), PV_LEFT }, - { DRDATA (TIME, csi_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB csi_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec }, - { 0 } }; - -DEVICE csi_dev = { - "CSI", &csi_unit, csi_reg, csi_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &csi_reset, - NULL, NULL, NULL, - &csi_dib, 0 }; - -/* CSO data structures - - cso_dev CSO device descriptor - cso_unit CSO unit descriptor - cso_reg CSO register list -*/ - -DIB cso_dib = { 0, 0, NULL, NULL, 1, IVCL (CSO), SCB_CSO, { NULL } }; - -UNIT cso_unit = { UDATA (&cso_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG cso_reg[] = { - { ORDATA (BUF, cso_unit.buf, 8) }, - { ORDATA (CSR, cso_csr, 16) }, - { FLDATA (INT, int_req[IPL_CSO], INT_V_CSO) }, - { FLDATA (DONE, cso_csr, CSR_V_DONE) }, - { FLDATA (IE, cso_csr, CSR_V_IE) }, - { DRDATA (POS, cso_unit.pos, 32), PV_LEFT }, - { DRDATA (TIME, cso_unit.wait, 24), PV_LEFT }, - { NULL } }; - -MTAB cso_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec }, - { 0 } }; - -DEVICE cso_dev = { - "CSO", &cso_unit, cso_reg, cso_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &cso_reset, - NULL, NULL, NULL, - &cso_dib, 0 }; - -/* SYSD data structures - - sysd_dev SYSD device descriptor - sysd_unit SYSD units - sysd_reg SYSD register list -*/ - -DIB sysd_dib[] = { 0, 0, NULL, NULL, - 2, IVCL (TMR0), 0, { &tmr0_inta, &tmr1_inta } }; - -UNIT sysd_unit[] = { - { UDATA (&tmr_svc, 0, 0) }, - { UDATA (&tmr_svc, 0, 0) } }; - -REG sysd_reg[] = { - { BRDATA (CMCSR, cmctl_reg, 16, 32, CMCTLSIZE >> 2) }, - { HRDATA (CACR, ka_cacr, 8) }, - { HRDATA (BDR, ka_bdr, 8) }, - { HRDATA (BASE, ssc_base, 29) }, - { HRDATA (CNF, ssc_cnf, 32) }, - { HRDATA (BTO, ssc_bto, 32) }, - { HRDATA (OTP, ssc_otp, 4) }, - { HRDATA (TCSR0, tmr_csr[0], 32) }, - { HRDATA (TIR0, tmr_tir[0], 32) }, - { HRDATA (TNIR0, tmr_tnir[0], 32) }, - { HRDATA (TIVEC0, tmr_tivr[0], 9) }, - { HRDATA (TINC0, tmr_inc[0], 32) }, - { HRDATA (TSAV0, tmr_sav[0], 32) }, - { HRDATA (TCSR1, tmr_csr[1], 32) }, - { HRDATA (TIR1, tmr_tir[1], 32) }, - { HRDATA (TNIR1, tmr_tnir[1], 32) }, - { HRDATA (TIVEC1, tmr_tivr[1], 9) }, - { HRDATA (TINC1, tmr_inc[1], 32) }, - { HRDATA (TSAV1, tmr_sav[1], 32) }, - { HRDATA (ADSM0, ssc_adsm[0], 32) }, - { HRDATA (ADSK0, ssc_adsk[0], 32) }, - { HRDATA (ADSM1, ssc_adsm[1], 32) }, - { HRDATA (ADSK1, ssc_adsk[1], 32) }, - { BRDATA (CDGDAT, cdg_dat, 16, 32, CDASIZE >> 2) }, - { NULL } }; - -DEVICE sysd_dev = { - "SYSD", sysd_unit, sysd_reg, NULL, - 2, 16, 16, 1, 16, 8, - NULL, NULL, &sysd_reset, - NULL, NULL, NULL, - &sysd_dib, 0 }; - -/* ROM: read only memory - stored in a buffered file - Register space access routines see ROM twice - - ROM access has been 'regulated' to about 1Mhz to avoid issues - with testing the interval timers in self-test. Specifically, - the VAX boot ROM (ka655.bin) contains code which presumes that - the VAX runs at a particular slower speed when code is running - from ROM (which is not cached). These assumptions are built - into instruction based timing loops. As the host platform gets - much faster than the original VAX, the assumptions embedded in - these code loops are no longer valid. - - Code has been added to the ROM implementation to limit CPU speed - to about 500K instructions per second. This heads off any future - issues with the embedded timing loops. -*/ - -int32 rom_swapb(int32 val) -{ -return ((val << 24) & 0xff000000) | (( val << 8) & 0xff0000) | - ((val >> 8) & 0xff00) | ((val >> 24) & 0xff); -} - -int32 rom_read_delay (int32 val) -{ -uint32 i, l = rom_delay; -int32 loopval = 0; - -if (rom_unit.flags & UNIT_NODELAY) return val; - -/* Calibrate the loop delay factor when first used. - Do this 4 times to and use the largest value computed. */ - -if (rom_delay == 0) { - uint32 ts, te, c = 10000, samples = 0; - while (1) { - c = c * 2; - te = sim_os_msec(); - while (te == (ts = sim_os_msec ())); /* align on ms tick */ - -/* This is merely a busy wait with some "work" that won't get optimized - away by a good compiler. loopval always is zero. To avoid smart compilers, - the loopval variable is referenced in the function arguments so that the - function expression is not loop invariant. It also must be referenced - by subsequent code or to avoid the whole computation being eliminated. */ - - for (i = 0; i < c; i++) - loopval |= (loopval + ts) ^ rom_swapb (rom_swapb (loopval + ts)); - te = sim_os_msec (); - if ((te - ts) < 50) continue; /* sample big enough? */ - if (rom_delay < (loopval + (c / (te - ts) / 1000) + 1)) - rom_delay = loopval + (c / (te - ts) / 1000) + 1; - if (++samples >= 4) break; - c = c / 2; } - if (rom_delay < 5) rom_delay = 5; } - -for (i = 0; i < l; i++) - loopval |= (loopval + val) ^ rom_swapb (rom_swapb (loopval + val)); -return val + loopval; -} - -int32 rom_rd (int32 pa) -{ -int32 rg = ((pa - ROMBASE) & ROMAMASK) >> 2; - -return rom_read_delay (rom[rg]); -} - -void rom_wr (int32 pa, int32 val, int32 lnt) -{ -int32 rg = ((pa - ROMBASE) & ROMAMASK) >> 2; - -if (lnt < L_LONG) { /* byte or word? */ - int32 sc = (pa & 3) << 3; /* merge */ - int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF; - rom[rg] = ((val & mask) << sc) | (rom[rg] & ~(mask << sc)); } -else rom[rg] = val; -return; -} - -/* ROM examine */ - -t_stat rom_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) -{ -uint32 addr = (uint32) exta; - -if ((vptr == NULL) || (addr & 03)) return SCPE_ARG; -if (addr >= ROMSIZE) return SCPE_NXM; -*vptr = rom[addr >> 2]; -return SCPE_OK; -} - -/* ROM deposit */ - -t_stat rom_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw) -{ -uint32 addr = (uint32) exta; - -if (addr & 03) return SCPE_ARG; -if (addr >= ROMSIZE) return SCPE_NXM; -rom[addr >> 2] = (uint32) val; -return SCPE_OK; -} - -/* ROM reset */ - -t_stat rom_reset (DEVICE *dptr) -{ -if (rom == NULL) rom = calloc (ROMSIZE >> 2, sizeof (int32)); -if (rom == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* NVR: non-volatile RAM - stored in a buffered file */ - -int32 nvr_rd (int32 pa) -{ -int32 rg = (pa - NVRBASE) >> 2; - -return nvr[rg]; -} - -void nvr_wr (int32 pa, int32 val, int32 lnt) -{ -int32 rg = (pa - NVRBASE) >> 2; - -if (lnt < L_LONG) { /* byte or word? */ - int32 sc = (pa & 3) << 3; /* merge */ - int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF; - nvr[rg] = ((val & mask) << sc) | (nvr[rg] & ~(mask << sc)); } -else nvr[rg] = val; -return; -} - -/* NVR examine */ - -t_stat nvr_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) -{ -uint32 addr = (uint32) exta; - -if ((vptr == NULL) || (addr & 03)) return SCPE_ARG; -if (addr >= NVRSIZE) return SCPE_NXM; -*vptr = nvr[addr >> 2]; -return SCPE_OK; -} - -/* NVR deposit */ - -t_stat nvr_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw) -{ -uint32 addr = (uint32) exta; - -if (addr & 03) return SCPE_ARG; -if (addr >= NVRSIZE) return SCPE_NXM; -nvr[addr >> 2] = (uint32) val; -return SCPE_OK; -} - -/* NVR reset */ - -t_stat nvr_reset (DEVICE *dptr) -{ -if (nvr == NULL) { - nvr = calloc (NVRSIZE >> 2, sizeof (int32)); - nvr_unit.filebuf = nvr; - ssc_cnf = ssc_cnf | SSCCNF_BLO; } -if (nvr == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* NVR attach */ - -t_stat nvr_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -uptr->flags = uptr->flags | (UNIT_ATTABLE | UNIT_BUFABLE); -r = attach_unit (uptr, cptr); -if (r != SCPE_OK) - uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE); -else { uptr->hwmark = uptr->capac; - ssc_cnf = ssc_cnf & ~SSCCNF_BLO; } -return r; -} - -/* NVR detach */ - -t_stat nvr_detach (UNIT *uptr) -{ -t_stat r; - -r = detach_unit (uptr); -if ((uptr->flags & UNIT_ATT) == 0) - uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE); -return r; -} - -/* CSI: console storage input */ - -int32 csrs_rd (void) -{ -return (csi_csr & CSICSR_IMP); -} - -int32 csrd_rd (void) -{ -csi_csr = csi_csr & ~CSR_DONE; -CLR_INT (CSI); -return (csi_unit.buf & 0377); -} - -void csrs_wr (int32 data) -{ -if ((data & CSR_IE) == 0) CLR_INT (CSI); -else if ((csi_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) - SET_INT (CSI); -csi_csr = (csi_csr & ~CSICSR_RW) | (data & CSICSR_RW); -return; -} - -t_stat csi_reset (DEVICE *dptr) -{ -csi_unit.buf = 0; -csi_csr = 0; -CLR_INT (CSI); -return SCPE_OK; -} - -/* CSO: console storage output */ - -int32 csts_rd (void) -{ -return (cso_csr & CSOCSR_IMP); -} - -void csts_wr (int32 data) -{ -if ((data & CSR_IE) == 0) CLR_INT (CSO); -else if ((cso_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) - SET_INT (CSO); -cso_csr = (cso_csr & ~CSOCSR_RW) | (data & CSOCSR_RW); -return; -} - -void cstd_wr (int32 data) -{ -cso_unit.buf = data & 0377; -cso_csr = cso_csr & ~CSR_DONE; -CLR_INT (CSO); -sim_activate (&cso_unit, cso_unit.wait); -return; -} - -t_stat cso_svc (UNIT *uptr) -{ -cso_csr = cso_csr | CSR_DONE; -if (cso_csr & CSR_IE) SET_INT (CSO); -if ((cso_unit.flags & UNIT_ATT) == 0) return SCPE_OK; -if (putc (cso_unit.buf, cso_unit.fileref) == EOF) { - perror ("CSO I/O error"); - clearerr (cso_unit.fileref); - return SCPE_IOERR; } -cso_unit.pos = cso_unit.pos + 1; -return SCPE_OK; -} - -t_stat cso_reset (DEVICE *dptr) -{ -cso_unit.buf = 0; -cso_csr = CSR_DONE; -CLR_INT (CSO); -sim_cancel (&cso_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* SYSD: SSC access mechanisms and devices - - - IPR space read/write routines - - register space read/write routines - - SSC local register read/write routines - - SSC console storage UART - - SSC timers - - CMCTL local register read/write routines -*/ - -/* Read/write IPR register space - - These routines implement the SSC's response to IPR's which are - sent off the CPU chip for processing. -*/ - -int32 ReadIPR (int32 rg) -{ -int32 val; - -switch (rg) { -case MT_ICCS: /* ICCS */ - val = iccs_rd (); - break; -case MT_CSRS: /* CSRS */ - val = csrs_rd (); - break; -case MT_CSRD: /* CSRD */ - val = csrd_rd (); - break; -case MT_CSTS: /* CSTS */ - val = csts_rd (); - break; -case MT_CSTD: /* CSTD */ - val = 0; - break; -case MT_RXCS: /* RXCS */ - val = rxcs_rd (); - break; -case MT_RXDB: /* RXDB */ - val = rxdb_rd (); - break; -case MT_TXCS: /* TXCS */ - val = txcs_rd (); - break; -case MT_TXDB: /* TXDB */ - val = 0; - break; -case MT_TODR: - val = todr_rd (); - break; -default: - ssc_bto = ssc_bto | SSCBTO_BTO; /* set BTO */ - val = 0; - break; } -return val; -} - -void WriteIPR (int32 rg, int32 val) -{ -switch (rg) { -case MT_ICCS: /* ICCS */ - iccs_wr (val); - break; -case MT_TODR: /* TODR */ - todr_wr (val); - break; -case MT_CSRS: /* CSRS */ - csrs_wr (val); - break; -case MT_CSRD: /* CSRD */ - break; -case MT_CSTS: /* CSTS */ - csts_wr (val); - break; -case MT_CSTD: /* CSTD */ - cstd_wr (val); - break; -case MT_RXCS: /* RXCS */ - rxcs_wr (val); - break; -case MT_RXDB: /* RXDB */ - break; -case MT_TXCS: /* TXCS */ - txcs_wr (val); - break; -case MT_TXDB: /* TXDB */ - txdb_wr (val); - break; -case MT_IORESET: /* IORESET */ - ioreset_wr (val); - break; -default: - ssc_bto = ssc_bto | SSCBTO_BTO; /* set BTO */ - break; } -return; -} - -/* Read/write I/O register space - - These routines are the 'catch all' for address space map. Any - address that doesn't explicitly belong to memory, I/O, or ROM - is given to these routines for processing. -*/ - -struct reglink { /* register linkage */ - int32 low; /* low addr */ - int32 high; /* high addr */ - t_stat (*read)(int32 pa); /* read routine */ - void (*write)(int32 pa, int32 val, int32 lnt); }; /* write routine */ - -struct reglink regtable[] = { - { CQMAPBASE, CQMAPBASE+CQMAPSIZE, &cqmap_rd, &cqmap_wr }, - { ROMBASE, ROMBASE+ROMSIZE+ROMSIZE, &rom_rd, NULL }, - { NVRBASE, NVRBASE+NVRSIZE, &nvr_rd, &nvr_wr }, - { CMCTLBASE, CMCTLBASE+CMCTLSIZE, &cmctl_rd, &cmctl_wr }, - { SSCBASE, SSCBASE+SSCSIZE, &ssc_rd, &ssc_wr }, - { KABASE, KABASE+KASIZE, &ka_rd, &ka_wr }, - { CQBICBASE, CQBICBASE+CQBICSIZE, &cqbic_rd, &cqbic_wr }, - { CQIPCBASE, CQIPCBASE+CQIPCSIZE, &cqipc_rd, &cqipc_wr }, - { CQMBASE, CQMBASE+CQMSIZE, &cqmem_rd, &cqmem_wr }, - { CDGBASE, CDGBASE+CDGSIZE, &cdg_rd, &cdg_wr }, - { 0, 0, NULL, NULL } }; - -/* ReadReg - read register space - - Inputs: - pa = physical address - lnt = length (BWLQ) - ignored - Output: - longword of data -*/ - -int32 ReadReg (int32 pa, int32 lnt) -{ -struct reglink *p; - -for (p = ®table[0]; p->low != 0; p++) { - if ((pa >= p->low) && (pa < p->high) && p->read) - return p->read (pa); } -ssc_bto = ssc_bto | SSCBTO_BTO | SSCBTO_RWT; -MACH_CHECK (MCHK_READ); -return 0; -} - -/* WriteReg - write register space - - Inputs: - pa = physical address - val = data to write, right justified in 32b longword - lnt = length (BWLQ) - Outputs: - none -*/ - -void WriteReg (int32 pa, int32 val, int32 lnt) -{ -struct reglink *p; - -for (p = ®table[0]; p->low != 0; p++) { - if ((pa >= p->low) && (pa < p->high) && p->write) { - p->write (pa, val, lnt); - return; } } -ssc_bto = ssc_bto | SSCBTO_BTO | SSCBTO_RWT; -MACH_CHECK (MCHK_WRITE); -return; -} - -/* CMCTL registers - - CMCTL00 - 15 configure memory banks 00 - 15. Note that they are - here merely to entertain the firmware; the actual configuration - of memory is unaffected by the settings here. - - CMCTL16 - error status register - - CMCTL17 - control/diagnostic status register - - The CMCTL registers are cleared at power up. -*/ - -int32 cmctl_rd (int32 pa) -{ -int32 rg = (pa - CMCTLBASE) >> 2; - -switch (rg) { -default: /* config reg */ - return cmctl_reg[rg] & CMCNF_MASK; -case 16: /* err status */ - return cmctl_reg[rg]; -case 17: /* csr */ - return cmctl_reg[rg] & CMCSR_MASK; } -return 0; -} - -void cmctl_wr (int32 pa, int32 val, int32 lnt) -{ -int32 i, rg = (pa - CMCTLBASE) >> 2; - -if (lnt < L_LONG) { /* LW write only */ - int32 sc = (pa & 3) << 3; /* shift data to */ - val = val << sc; } /* proper location */ -switch (rg) { -default: /* config reg */ - if (val & CMCNF_SRQ) { /* sig request? */ - for (i = rg; i < (rg + 4); i++) { - cmctl_reg[i] = cmctl_reg[i] & ~CMCNF_SIG; - if (ADDR_IS_MEM (i * MEM_BANK)) - cmctl_reg[i] = cmctl_reg[i] | MEM_SIG; } } - cmctl_reg[rg] = (cmctl_reg[rg] & ~CMCNF_RW) | (val & CMCNF_RW); - break; -case 16: /* err status */ - cmctl_reg[rg] = cmctl_reg[rg] & ~(val & CMERR_W1C); - break; -case 17: /* csr */ - cmctl_reg[rg] = val & CMCSR_MASK; - break; } -return; -} - -/* KA655 registers */ - -int32 ka_rd (int32 pa) -{ -int32 rg = (pa - KABASE) >> 2; - -switch (rg) -{ -case 0: /* CACR */ - return ka_cacr; -case 1: /* BDR */ - return ka_bdr; } -return 0; -} - -void ka_wr (int32 pa, int32 val, int32 lnt) -{ -int32 rg = (pa - KABASE) >> 2; - -if ((rg == 0) && ((pa & 3) == 0)) { /* lo byte only */ - ka_cacr = (ka_cacr & ~(val & CACR_W1C)) | CACR_FIXED; - ka_cacr = (ka_cacr & ~CACR_RW) | (val & CACR_RW); } -return; -} - -int32 sysd_hlt_enb (void) -{ -return ka_bdr & BDR_BRKENB; -} - -/* Cache diagnostic space - byte/word merges done in WriteReg */ - -int32 cdg_rd (int32 pa) -{ -int32 t, row = CDG_GETROW (pa); - -t = cdg_dat[row]; -ka_cacr = ka_cacr & ~CACR_DRO; /* clear diag */ -ka_cacr = ka_cacr | - (parity ((t >> 24) & 0xFF, 1) << (CACR_V_DPAR + 3)) | - (parity ((t >> 16) & 0xFF, 0) << (CACR_V_DPAR + 2)) | - (parity ((t >> 8) & 0xFF, 1) << (CACR_V_DPAR + 1)) | - (parity (t & 0xFF, 0) << CACR_V_DPAR); -return t; -} - -void cdg_wr (int32 pa, int32 val, int32 lnt) -{ -int32 row = CDG_GETROW (pa); - -if (lnt < L_LONG) { /* byte or word? */ - int32 sc = (pa & 3) << 3; /* merge */ - int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF; - int32 t = cdg_dat[row]; - val = ((val & mask) << sc) | (t & ~(mask << sc)); } -cdg_dat[row] = val; /* store data */ -return; -} - -int32 parity (int32 val, int32 odd) -{ -for ( ; val != 0; val = val >> 1) { - if (val & 1) odd = odd ^ 1; } -return odd; -} - -/* SSC registers - byte/word merges done in WriteReg */ - -int32 ssc_rd (int32 pa) -{ -int32 rg = (pa - SSCBASE) >> 2; - -switch (rg) { -case 0x00: /* base reg */ - return ssc_base; -case 0x04: /* conf reg */ - return ssc_cnf; -case 0x08: /* bus timeout */ - return ssc_bto; -case 0x0C: /* output port */ - return ssc_otp & SSCOTP_MASK; -case 0x1B: /* TODR */ - return todr_rd (); -case 0x1C: /* CSRS */ - return csrs_rd (); -case 0x1D: /* CSRD */ - return csrd_rd (); -case 0x1E: /* CSTS */ - return csts_rd (); -case 0x20: /* RXCS */ - return rxcs_rd (); -case 0x21: /* RXDB */ - return rxdb_rd (); -case 0x22: /* TXCS */ - return txcs_rd (); -case 0x40: /* T0CSR */ - return tmr_csr[0]; -case 0x41: /* T0INT */ - return tmr_tir_rd (0, FALSE); -case 0x42: /* T0NI */ - return tmr_tnir[0]; -case 0x43: /* T0VEC */ - return tmr_tivr[0]; -case 0x44: /* T1CSR */ - return tmr_csr[1]; -case 0x45: /* T1INT */ - return tmr_tir_rd (1, FALSE); -case 0x46: /* T1NI */ - return tmr_tnir[1]; -case 0x47: /* T1VEC */ - return tmr_tivr[1]; -case 0x4C: /* ADS0M */ - return ssc_adsm[0]; -case 0x4D: /* ADS0K */ - return ssc_adsk[0]; -case 0x50: /* ADS1M */ - return ssc_adsm[1]; -case 0x51: /* ADS1K */ - return ssc_adsk[1]; } -return 0; -} - -void ssc_wr (int32 pa, int32 val, int32 lnt) -{ -int32 rg = (pa - SSCBASE) >> 2; - -if (lnt < L_LONG) { /* byte or word? */ - int32 sc = (pa & 3) << 3; /* merge */ - int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF; - int32 t = ssc_rd (pa); - val = ((val & mask) << sc) | (t & ~(mask << sc)); } - -switch (rg) { -case 0x00: /* base reg */ - ssc_base = (val & SSCBASE_RW) | SSCBASE_MBO; - break; -case 0x04: /* conf reg */ - ssc_cnf = ssc_cnf & ~(val & SSCCNF_W1C); - ssc_cnf = (ssc_cnf & ~SSCCNF_RW) | (val & SSCCNF_RW); - break; -case 0x08: /* bus timeout */ - ssc_bto = ssc_bto & ~(val & SSCBTO_W1C); - ssc_bto = (ssc_bto & ~SSCBTO_RW) | (val & SSCBTO_RW); - break; -case 0x0C: /* output port */ - ssc_otp = val & SSCOTP_MASK; - break; -case 0x1B: /* TODR */ - todr_wr (val); - break; -case 0x1C: /* CSRS */ - csrs_wr (val); - break; -case 0x1E: /* CSTS */ - csts_wr (val); - break; -case 0x1F: /* CSTD */ - cstd_wr (val); - break; -case 0x20: /* RXCS */ - rxcs_wr (val); - break; -case 0x22: /* TXCS */ - txcs_wr (val); - break; -case 0x23: /* TXDB */ - txdb_wr (val); - break; -case 0x40: /* T0CSR */ - tmr_csr_wr (0, val); - break; -case 0x42: /* T0NI */ - tmr_tnir[0] = val; - break; -case 0x43: /* T0VEC */ - tmr_tivr[0] = val & TMR_VEC_MASK; - break; -case 0x44: /* T1CSR */ - tmr_csr_wr (1, val); - break; -case 0x46: /* T1NI */ - tmr_tnir[1] = val; - break; -case 0x47: /* T1VEC */ - tmr_tivr[1] = val & TMR_VEC_MASK; - break; -case 0x4C: /* ADS0M */ - ssc_adsm[0] = val & SSCADS_MASK; - break; -case 0x4D: /* ADS0K */ - ssc_adsk[0] = val & SSCADS_MASK; - break; -case 0x50: /* ADS1M */ - ssc_adsm[1] = val & SSCADS_MASK; - break; -case 0x51: /* ADS1K */ - ssc_adsk[1] = val & SSCADS_MASK; - break; } -return; -} - -/* Programmable timers - - The SSC timers, which increment at 1Mhz, cannot be accurately - simulated due to the overhead that would be required for 1M - clock events per second. Instead, a gross hack is used. When - a timer is started, the clock interval is inspected. - - if (int < 0 and small) then testing timer, count instructions. - Small is determined by when the requested interval is less - than the size of a 100hz system clock tick. - if (int >= 0 or large) then counting a real interval, schedule - clock events at 100Hz using calibrated line clock delay - and when the remaining time value gets small enough, behave - like the small case above. - - If the interval register is read, then its value between events - is interpolated using the current instruction count versus the - count when the most recent event started, the result is scaled - to the calibrated system clock, unless the interval being timed - is less than a calibrated system clock tick (or the calibrated - clock is running very slowly) at which time the result will be - the elapsed instruction count. - - The powerup TOY Test sometimes fails its tolerance test. This was - due to varying system load causing varying calibration values to be - used at different times while referencing the TIR. While timing long - intervals, we now synchronize the stepping (and calibration) of the - system tick with the opportunity to reference the value. This gives - precise tolerance measurement values (when interval timers are used - to measure the system clock), regardless of other load issues on the - host system which might cause varying values of the system clock's - calibration factor. -*/ - -int32 tmr_tir_rd (int32 tmr, t_bool interp) -{ -uint32 delta; - -if (interp || (tmr_csr[tmr] & TMR_CSR_RUN)) { /* interp, running? */ - delta = sim_grtime () - tmr_sav[tmr]; /* delta inst */ - if ((tmr_inc[tmr] == TMR_INC) && /* scale large int */ - (tmr_poll > TMR_INC)) - delta = (uint32) ((((double) delta) * TMR_INC) / tmr_poll); - if (delta >= tmr_inc[tmr]) delta = tmr_inc[tmr] - 1; - return tmr_tir[tmr] + delta; } -return tmr_tir[tmr]; -} - -void tmr_csr_wr (int32 tmr, int32 val) -{ -if ((tmr < 0) || (tmr > 1)) return; -if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */ - sim_cancel (&sysd_unit[tmr]); /* cancel timer */ - if (tmr_csr[tmr] & TMR_CSR_RUN) /* run 1 -> 0? */ - tmr_tir[tmr] = tmr_tir_rd (tmr, TRUE); } /* update itr */ -tmr_csr[tmr] = tmr_csr[tmr] & ~(val & TMR_CSR_W1C); /* W1C csr */ -tmr_csr[tmr] = (tmr_csr[tmr] & ~TMR_CSR_RW) | /* new r/w */ - (val & TMR_CSR_RW); -if (val & TMR_CSR_XFR) tmr_tir[tmr] = tmr_tnir[tmr]; /* xfr set? */ -if (val & TMR_CSR_RUN) { /* run? */ - if (val & TMR_CSR_XFR) /* new tir? */ - sim_cancel (&sysd_unit[tmr]); /* stop prev */ - if (!sim_is_active (&sysd_unit[tmr])) /* not running? */ - tmr_sched (tmr); } /* activate */ -else if (val & TMR_CSR_SGL) { /* single step? */ - tmr_incr (tmr, 1); /* incr tmr */ - if (tmr_tir[tmr] == 0) /* if ovflo, */ - tmr_tir[tmr] = tmr_tnir[tmr]; } /* reload tir */ -if ((tmr_csr[tmr] & (TMR_CSR_DON | TMR_CSR_IE)) != /* update int */ - (TMR_CSR_DON | TMR_CSR_IE)) { - if (tmr) CLR_INT (TMR1); - else CLR_INT (TMR0); } -return; -} - -/* Unit service */ - -t_stat tmr_svc (UNIT *uptr) -{ -int32 tmr = uptr - sysd_dev.units; /* get timer # */ - -tmr_incr (tmr, tmr_inc[tmr]); /* incr timer */ -return SCPE_OK; -} - -/* Timer increment */ - -void tmr_incr (int32 tmr, uint32 inc) -{ -uint32 new_tir = tmr_tir[tmr] + inc; /* add incr */ - -if (new_tir < tmr_tir[tmr]) { /* ovflo? */ - tmr_tir[tmr] = 0; /* now 0 */ - if (tmr_csr[tmr] & TMR_CSR_DON) /* done? set err */ - tmr_csr[tmr] = tmr_csr[tmr] | TMR_CSR_ERR; - else tmr_csr[tmr] = tmr_csr[tmr] | TMR_CSR_DON; /* set done */ - if (tmr_csr[tmr] & TMR_CSR_STP) /* stop? */ - tmr_csr[tmr] = tmr_csr[tmr] & ~TMR_CSR_RUN; /* clr run */ - if (tmr_csr[tmr] & TMR_CSR_RUN) { /* run? */ - tmr_tir[tmr] = tmr_tnir[tmr]; /* reload */ - tmr_sched (tmr); } /* reactivate */ - if (tmr_csr[tmr] & TMR_CSR_IE) { /* set int req */ - if (tmr) SET_INT (TMR1); - else SET_INT (TMR0); } } -else { tmr_tir[tmr] = new_tir; /* no, upd tir */ - if (tmr_csr[tmr] & TMR_CSR_RUN) /* still running? */ - tmr_sched (tmr); } /* reactivate */ -return; -} - -/* Timer scheduling */ - -void tmr_sched (int32 tmr) -{ -int32 clk_time = sim_is_active (&clk_unit) - 1; -int32 tmr_time; - -tmr_sav[tmr] = sim_grtime (); /* save intvl base */ -if (tmr_tir[tmr] > (0xFFFFFFFFu - TMR_INC)) { /* short interval? */ - tmr_inc[tmr] = (~tmr_tir[tmr] + 1); /* inc = interval */ - tmr_time = tmr_inc[tmr]; } -else { tmr_inc[tmr] = TMR_INC; /* usec/interval */ - tmr_time = tmr_poll; } -if (tmr_time == 0) tmr_time = 1; -if ((tmr_inc[tmr] = TMR_INC) && (tmr_time > clk_time)) { - -/* Align scheduled event to be identical to the event for the next clock - tick. This lets us always see a consistent calibrated value, both for - this scheduling, AND for any query of the current timer register that - may happen in tmr_tir_rd (). This presumes that sim_activate will - queue the interval timer behind the event for the clock tick. */ - - tmr_inc[tmr] = (uint32) (((double) clk_time * TMR_INC) / tmr_poll); - tmr_time = clk_time; } -sim_activate (&sysd_unit[tmr], tmr_time); -return; -} - -int32 tmr0_inta (void) -{ -return tmr_tivr[0]; -} - -int32 tmr1_inta (void) -{ -return tmr_tivr[1]; -} - -/* SYSD reset */ - -t_stat sysd_reset (DEVICE *dptr) -{ -int32 i; - -for (i = 0; i < 2; i++) { - tmr_csr[i] = tmr_tnir[i] = tmr_tir[i] = 0; - tmr_inc[i] = tmr_sav[i] = 0; - sim_cancel (&sysd_unit[i]); } -csi_csr = 0; -csi_unit.buf = 0; -sim_cancel (&csi_unit); -CLR_INT (CSI); -cso_csr = CSR_DONE; -cso_unit.buf = 0; -sim_cancel (&cso_unit); -CLR_INT (CSO); -return SCPE_OK; -} - -/* SYSD powerup */ - -t_stat sysd_powerup (void) -{ -int32 i; - -for (i = 0; i < (CMCTLSIZE >> 2); i++) cmctl_reg[i] = 0; -for (i = 0; i < 2; i++) { - tmr_tivr[i] = 0; - ssc_adsm[i] = ssc_adsk[i] = 0; } -ka_cacr = 0; -ssc_base = SSCBASE; -ssc_cnf = ssc_cnf & SSCCNF_BLO; -ssc_bto = 0; -ssc_otp = 0; -return sysd_reset (&sysd_dev); -} - diff --git a/VAX/vaxmod_defs.h b/VAX/vaxmod_defs.h deleted file mode 100644 index 66a72894..00000000 --- a/VAX/vaxmod_defs.h +++ /dev/null @@ -1,410 +0,0 @@ -/* vaxmod_defs.h: VAX model-specific definitions file - - Copyright (c) 1998-2002, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 22-Dec-02 RMS Added BDR halt enable definition - 11-Nov-02 RMS Added log bits for XQ - 10-Oct-02 RMS Added DEQNA/DELQA, multiple RQ, autoconfigure support - 29-Sep-02 RMS Revamped bus support macros - 06-Sep-02 RMS Added TMSCP support - 14-Jul-02 RMS Added additional console halt codes - 28-Apr-02 RMS Fixed DZV vector base and number of lines - - This file covers the KA65x ("Mayfair") series of CVAX-based Qbus systems. - - System memory map - - 0000 0000 - 03FF FFFF main memory - 0400 0000 - 0FFF FFFF reserved - 1000 0000 - 13FF FFFF secondary cache diagnostic space - 1400 0000 - 1FFF FFFF reserved - - 2000 0000 - 2000 1FFF Qbus I/O page - 2000 2000 - 2003 FFFF reserved - 2004 0000 - 2005 FFFF ROM space, halt protected - 2006 0000 - 2007 FFFF ROM space, halt unprotected - 2008 0000 - 201F FFFF Local register space - 2020 0000 - 2FFF FFFF reserved - 3000 0000 - 303F FFFF Qbus memory space - 3400 0000 - 3FFF FFFF reserved -*/ - -/* Microcode constructs */ - -#define CVAX_SID (10 << 24) /* system ID */ -#define CVAX_UREV 6 /* ucode revision */ -#define CON_HLTPIN 0x0200 /* external CPU halt */ -#define CON_PWRUP 0x0300 /* powerup code */ -#define CON_HLTINS 0x0600 /* HALT instruction */ -#define CON_BADPSL 0x4000 /* invalid PSL flag */ -#define CON_MAPON 0x8000 /* mapping on flag */ -#define MCHK_TBM_P0 0x05 /* PPTE in P0 */ -#define MCHK_TBM_P1 0x06 /* PPTE in P1 */ -#define MCHK_M0_P0 0x07 /* PPTE in P0 */ -#define MCHK_M0_P1 0x08 /* PPTE in P1 */ -#define MCHK_INTIPL 0x09 /* invalid ireq */ -#define MCHK_READ 0x80 /* read check */ -#define MCHK_WRITE 0x82 /* write check */ - -/* Memory system error register */ - -#define MSER_HM 0x80 /* hit/miss */ -#define MSER_CPE 0x40 /* CDAL par err */ -#define MSER_CPM 0x20 /* CDAL mchk */ - -/* Cache disable register */ - -#define CADR_RW 0xF3 -#define CADR_MBO 0x0C - -/* Memory */ - -#define MAXMEMWIDTH 26 /* max mem addr width */ -#define MAXMEMSIZE (1 << MAXMEMWIDTH) /* max mem size */ -#define MAXMEMMASK (MAXMEMSIZE - 1) /* max mem addr mask */ -#define INITMEMSIZE (1 << 24) /* initial memory size */ -#define MEMSIZE (cpu_unit.capac) -#define ADDR_IS_MEM(x) (((uint32) (x)) < MEMSIZE) - -/* Cache diagnostic space */ - -#define CDAAWIDTH 16 /* cache dat addr width */ -#define CDASIZE (1u << CDAAWIDTH) /* cache dat length */ -#define CDAMASK (CDASIZE - 1) /* cache dat mask */ -#define CTGAWIDTH 10 /* cache tag addr width */ -#define CTGSIZE (1u << CTGAWIDTH) /* cache tag length */ -#define CTGMASK (CTGSIZE - 1) /* cache tag mask */ -#define CDGSIZE (CDASIZE * CTGSIZE) /* diag addr length */ -#define CDGBASE 0x10000000 /* diag addr base */ -#define CDG_GETROW(x) (((x) & CDAMASK) >> 2) -#define CDG_GETTAG(x) (((x) >> CDAAWIDTH) & CTGMASK) -#define CTG_V (1u << (CTGAWIDTH + 0)) /* tag valid */ -#define CTG_WP (1u << (CTGAWIDTH + 1)) /* wrong parity */ -#define ADDR_IS_CDG(x) ((((uint32) (x)) >= CDGBASE) && \ - (((uint32) (x)) < (CDGBASE + CDGSIZE))) - -/* Qbus I/O registers */ - -#define IOPAGEAWIDTH 13 /* IO addr width */ -#define IOPAGESIZE (1u << IOPAGEAWIDTH) /* IO page length */ -#define IOPAGEMASK (IOPAGESIZE - 1) /* IO addr mask */ -#define IOPAGEBASE 0x20000000 /* IO page base */ -#define ADDR_IS_IO(x) ((((uint32) (x)) >= IOPAGEBASE) && \ - (((uint32) (x)) < (IOPAGEBASE + IOPAGESIZE))) - -/* Read only memory - appears twice */ - -#define ROMAWIDTH 17 /* ROM addr width */ -#define ROMSIZE (1u << ROMAWIDTH) /* ROM length */ -#define ROMAMASK (ROMSIZE - 1) /* ROM addr mask */ -#define ROMBASE 0x20040000 /* ROM base */ -#define ADDR_IS_ROM(x) ((((uint32) (x)) >= ROMBASE) && \ - (((uint32) (x)) < (ROMBASE + ROMSIZE + ROMSIZE))) - -/* Local register space */ - -#define REGAWIDTH 19 /* REG addr width */ -#define REGSIZE (1u << REGAWIDTH) /* REG length */ -#define REGBASE 0x20080000 /* REG addr base */ - -/* KA655 board registers */ - -#define KAAWIDTH 3 /* KA reg width */ -#define KASIZE (1u << KAAWIDTH) /* KA reg length */ -#define KABASE (REGBASE + 0x4000) /* KA650 addr base */ - -/* CQBIC registers */ - -#define CQBICSIZE (5 << 2) /* 5 registers */ -#define CQBICBASE (REGBASE) /* CQBIC addr base */ -#define CQMAPASIZE 15 /* map addr width */ -#define CQMAPSIZE (1u << CQMAPASIZE) /* map length */ -#define CQMAPAMASK (CQMAPSIZE - 1) /* map addr mask */ -#define CQMAPBASE (REGBASE + 0x8000) /* map addr base */ -#define CQIPCSIZE 2 /* 2 bytes only */ -#define CQIPCBASE (REGBASE + 0x1F40) /* ipc reg addr */ - -/* CMCTL registers */ - -#define CMCTLSIZE (18 << 2) /* 18 registers */ -#define CMCTLBASE (REGBASE + 0x100) /* CMCTL addr base */ - -/* SSC registers */ - -#define SSCSIZE 0x150 /* SSC size */ -#define SSCBASE 0x20140000 /* SSC base */ - -/* Non-volatile RAM - 1KB long */ - -#define NVRAWIDTH 10 /* NVR addr width */ -#define NVRSIZE (1u << NVRAWIDTH) /* NVR length */ -#define NVRAMASK (NVRSIZE - 1) /* NVR addr mask */ -#define NVRBASE 0x20140400 /* NVR base */ -#define ADDR_IS_NVR(x) ((((uint32) (x)) >= NVRBASE) && \ - (((uint32) (x)) < (NVRBASE + NVRSIZE))) - -/* CQBIC Qbus memory space (seen from CVAX) */ - -#define CQMAWIDTH 22 /* Qmem addr width */ -#define CQMSIZE (1u << CQMAWIDTH) /* Qmem length */ -#define CQMAMASK (CQMSIZE - 1) /* Qmem addr mask */ -#define CQMBASE 0x30000000 /* Qmem base */ - -/* Qbus I/O modes */ - -#define READ 0 /* PDP-11 compatibility */ -#define WRITE (L_WORD) -#define WRITEB (L_BYTE) - -/* Common CSI flags */ - -#define CSR_V_GO 0 /* go */ -#define CSR_V_IE 6 /* interrupt enable */ -#define CSR_V_DONE 7 /* done */ -#define CSR_V_BUSY 11 /* busy */ -#define CSR_V_ERR 15 /* error */ -#define CSR_GO (1u << CSR_V_GO) -#define CSR_IE (1u << CSR_V_IE) -#define CSR_DONE (1u << CSR_V_DONE) -#define CSR_BUSY (1u << CSR_V_BUSY) -#define CSR_ERR (1u << CSR_V_ERR) - -/* Timers */ - -#define TMR_CLK 0 /* 100Hz clock */ - -/* I/O system definitions */ - -#define DZ_MUXES 4 /* max # of muxes */ -#define DZ_LINES 4 /* (DZV) lines per mux */ -#define MT_MAXFR (1 << 16) /* magtape max rec */ -#define AUTO_LNT 34 /* autoconfig ranks */ -#define DIB_MAX 100 /* max DIBs */ - -#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ -#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */ -#define DEV_V_FLTA (DEV_V_UF + 2) /* flt addr */ -#define DEV_UBUS (1u << DEV_V_UBUS) -#define DEV_QBUS (1u << DEV_V_QBUS) -#define DEV_FLTA (1u << DEV_V_FLTA) - -#define UNIBUS FALSE /* 22b only */ - -#define DEV_RDX 16 /* default device radix */ - -/* Device information block */ - -#define VEC_DEVMAX 4 /* max device vec */ - -struct pdp_dib { - uint32 ba; /* base addr */ - uint32 lnt; /* length */ - t_stat (*rd)(int32 *dat, int32 ad, int32 md); - t_stat (*wr)(int32 dat, int32 ad, int32 md); - int32 vnum; /* vectors: number */ - int32 vloc; /* locator */ - int32 vec; /* value */ - int32 (*ack[VEC_DEVMAX])(void); /* ack routine */ -}; - -typedef struct pdp_dib DIB; - -/* I/O page layout - RQB,RQC,RQD float based on number of DZ's */ - -#define IOBA_DZ (IOPAGEBASE + 000100) /* DZ11 */ -#define IOLN_DZ 010 -#define IOBA_RQB (IOPAGEBASE + 000334 + (020 * (DZ_MUXES / 2))) -#define IOLN_RQB 004 -#define IOBA_RQC (IOPAGEBASE + IOBA_RQB + IOLN_RQB) -#define IOLN_RQC 004 -#define IOBA_RQD (IOPAGEBASE + IOBA_RQC + IOLN_RQC) -#define IOLN_RQD 004 -#define IOBA_RQ (IOPAGEBASE + 012150) /* RQDX3 */ -#define IOLN_RQ 004 -#define IOBA_TS (IOPAGEBASE + 012520) /* TS11 */ -#define IOLN_TS 004 -#define IOBA_RL (IOPAGEBASE + 014400) /* RL11 */ -#define IOLN_RL 012 -#define IOBA_XQ (IOPAGEBASE + 014440) /* DEQNA/DELQA */ -#define IOLN_XQ 020 -#define IOBA_XQB (IOPAGEBASE + 014460) /* 2nd DEQNA/DELQA */ -#define IOLN_XQB 020 -#define IOBA_TQ (IOPAGEBASE + 014500) /* TMSCP */ -#define IOLN_TQ 004 -#define IOBA_RP (IOPAGEBASE + 016700) /* RP/RM */ -#define IOLN_RP 054 -#define IOBA_DBL (IOPAGEBASE + 017500) /* doorbell */ -#define IOLN_DBL 002 -#define IOBA_LPT (IOPAGEBASE + 017514) /* LP11 */ -#define IOLN_LPT 004 -#define IOBA_PTR (IOPAGEBASE + 017550) /* PC11 reader */ -#define IOLN_PTR 004 -#define IOBA_PTP (IOPAGEBASE + 017554) /* PC11 punch */ -#define IOLN_PTP 004 - -/* The KA65x maintains 4 separate hardware IPL levels, IPL 17 to IPL 14 - Within each IPL, priority is right to left -*/ - -/* IPL 17 */ - -/* IPL 16 */ - -#define INT_V_CLK 0 /* clock */ - -/* IPL 15 */ - -#define INT_V_RQ 0 /* RQDX3 */ -#define INT_V_RL 1 /* RLV12/RL02 */ -#define INT_V_DZRX 2 /* DZ11 */ -#define INT_V_DZTX 3 -#define INT_V_RP 4 /* RP,RM drives */ -#define INT_V_TS 5 /* TS11/TSV05 */ -#define INT_V_TQ 6 /* TMSCP */ -#define INT_V_XQ 7 /* DEQNA/DELQA */ - -/* IPL 14 */ - -#define INT_V_TTI 0 /* console */ -#define INT_V_TTO 1 -#define INT_V_PTR 2 /* PC11 */ -#define INT_V_PTP 3 -#define INT_V_LPT 4 /* LP11 */ -#define INT_V_CSI 5 /* SSC cons UART */ -#define INT_V_CSO 6 -#define INT_V_TMR0 7 /* SSC timers */ -#define INT_V_TMR1 8 - -#define INT_CLK (1u << INT_V_CLK) -#define INT_RQ (1u << INT_V_RQ) -#define INT_RL (1u << INT_V_RL) -#define INT_DZRX (1u << INT_V_DZRX) -#define INT_DZTX (1u << INT_V_DZTX) -#define INT_RP (1u << INT_V_RP) -#define INT_TS (1u << INT_V_TS) -#define INT_TQ (1u << INT_V_TQ) -#define INT_XQ (1u << INT_V_XQ) -#define INT_TTI (1u << INT_V_TTI) -#define INT_TTO (1u << INT_V_TTO) -#define INT_PTR (1u << INT_V_PTR) -#define INT_PTP (1u << INT_V_PTP) -#define INT_LPT (1u << INT_V_LPT) -#define INT_CSI (1u << INT_V_CSI) -#define INT_CSO (1u << INT_V_CSO) -#define INT_TMR0 (1u << INT_V_TMR0) -#define INT_TMR1 (1u << INT_V_TMR1) - -#define IPL_CLK (0x16 - IPL_HMIN) /* relative IPL */ -#define IPL_RQ (0x15 - IPL_HMIN) -#define IPL_RL (0x15 - IPL_HMIN) -#define IPL_DZRX (0x15 - IPL_HMIN) -#define IPL_DZTX (0x15 - IPL_HMIN) -#define IPL_RP (0x15 - IPL_HMIN) -#define IPL_TS (0x15 - IPL_HMIN) -#define IPL_TQ (0x15 - IPL_HMIN) -#define IPL_XQ (0x15 - IPL_HMIN) -#define IPL_TTI (0x14 - IPL_HMIN) -#define IPL_TTO (0x14 - IPL_HMIN) -#define IPL_PTR (0x14 - IPL_HMIN) -#define IPL_PTP (0x14 - IPL_HMIN) -#define IPL_LPT (0x14 - IPL_HMIN) -#define IPL_CSI (0x14 - IPL_HMIN) -#define IPL_CSO (0x14 - IPL_HMIN) -#define IPL_TMR0 (0x14 - IPL_HMIN) -#define IPL_TMR1 (0x14 - IPL_HMIN) - -#define IPL_HMAX 0x17 /* highest hwre level */ -#define IPL_HMIN 0x14 /* lowest hwre level */ -#define IPL_HLVL (IPL_HMAX - IPL_HMIN + 1) /* # hardware levels */ -#define IPL_SMAX 0xF /* highest swre level */ - -/* Device vectors */ - -#define VEC_Q 0x200 /* Qbus vector offset */ -#define VEC_PTR (VEC_Q + 0070) -#define VEC_PTP (VEC_Q + 0074) -#define VEC_XQ (VEC_Q + 0120) -#define VEC_RQ (VEC_Q + 0154) -#define VEC_RL (VEC_Q + 0160) -#define VEC_LPT (VEC_Q + 0200) -#define VEC_TS (VEC_Q + 0224) -#define VEC_RP (VEC_Q + 0254) -#define VEC_TQ (VEC_Q + 0260) -#define VEC_DZRX (VEC_Q + 0300) -#define VEC_DZTX (VEC_Q + 0304) - -/* Autoconfigure ranks */ - -#define RANK_DZ 8 -#define RANK_RL 14 -#define RANK_RQ 26 -#define RANK_TQ 30 - -/* Interrupt macros */ - -#define IVCL(dv) ((IPL_##dv * 32) + INT_V_##dv) -#define IREQ(dv) int_req[IPL_##dv] -#define SET_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] | (INT_##dv) -#define CLR_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] & ~(INT_##dv) -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ - -/* Logging */ - -#define LOG_CPU_I 0x0001 /* intexc */ -#define LOG_CPU_R 0x0002 /* REI */ -#define LOG_CPU_P 0x0004 /* context */ -#define LOG_CPU_H 0x0008 /* history */ -#define LOG_RP 0x0010 -#define LOG_TS 0x0020 -#define LOG_RQ 0x0040 -#define LOG_TQ 0x0080 -#define LOG_XQ0 0x0100 -#define LOG_XQ1 0x0200 -#define LOG_XQ2 0x0400 -#define LOG_XQ3 0x0800 - -#define DBG_LOG(x) (sim_log && (cpu_log & (x))) - -/* Function prototypes for I/O */ - -t_bool map_addr (uint32 qa, uint32 *ma); -int32 map_readB (uint32 ba, int32 bc, uint8 *buf); -int32 map_readW (uint32 ba, int32 bc, uint16 *buf); -int32 map_readL (uint32 ba, int32 bc, uint32 *buf); -int32 map_writeB (uint32 ba, int32 bc, uint8 *buf); -int32 map_writeW (uint32 ba, int32 bc, uint16 *buf); -int32 map_writeL (uint32 ba, int32 bc, uint32 *buf); - -#define Map_Addr(a,b) map_addr (a, b) -#define Map_ReadB(a,b,c,d) map_readB (a, b, c) -#define Map_ReadW(a,b,c,d) map_readW (a, b, c) -#define Map_WriteB(a,b,c,d) map_writeB (a, b, c) -#define Map_WriteW(a,b,c,d) map_writeW (a, b, c) - -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat set_vec (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_vec (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat auto_config (uint32 rank, uint32 num); diff --git a/build_mingw.bat b/build_mingw.bat deleted file mode 100644 index eaad7353..00000000 --- a/build_mingw.bat +++ /dev/null @@ -1,14 +0,0 @@ -@echo off -rem Compile all of SIMH using MINGW make and gcc environment -rem Individual simulator sources are in .\simulator_name -rem Individual simulator executables are to .\bin -rem -rem If needed, define the path for the MINGW bin directory. -rem (this should already be set if MINGW was installed correctly) -rem -gcc -v 1>NUL 2>NUL -if ERRORLEVEL 1 path C:\MinGW\bin;%path% -mkdir BIN -gcc -v 1>NUL 2>NUL -if ERRORLEVEL 1 echo "MinGW Environment Unavailable" -mingw32-make WIN32=1 -f makefile %1 %2 %3 %4 diff --git a/build_mingw_ether.bat b/build_mingw_ether.bat deleted file mode 100644 index 6d7b9282..00000000 --- a/build_mingw_ether.bat +++ /dev/null @@ -1,15 +0,0 @@ -@echo off -rem 12-Nov-02 rms Ethernet support -rem Compile all of SIMH using MINGW make and gcc environment -rem Individual simulator sources are in .\simulator_name -rem Individual simulator executables are to .\bin -rem -rem If needed, define the path for the MINGW bin directory. -rem (this should already be set if MINGW was installed correctly) -rem -gcc -v 1>NUL 2>NUL -if ERRORLEVEL 1 path C:\MinGW\bin;%path% -mkdir BIN -gcc -v 1>NUL 2>NUL -if ERRORLEVEL 1 echo "MinGW Environment Unavailable" -mingw32-make WIN32=1 USE_NETWORK=1 -f makefile %1 %2 %3 %4 diff --git a/descrip.mms b/descrip.mms deleted file mode 100644 index 81c7c01e..00000000 --- a/descrip.mms +++ /dev/null @@ -1,1023 +0,0 @@ -# -# DESCRIP.MMS -# Written By: Robert Alan Byer -# byer@mail.ourservers.net -# -# Modified By: Mark Pizzolato -# mark@infocomm.com -# -# This MMS/MMK build script is used to compile the various simulators in -# the SIMH package for OpenVMS using DEC C v6.0-001. -# -# Notes: On VAX, the PDP-10 and VAX simulator will not be built due to the -# fact that INT64 is required for those simulators. -# -# When using DEC's MMS on an Alpha you must use -# /MACRO=("__ALPHA__=1") to compile properly. -# -# This build script will accept the following build options. -# -# ALL Just Build "Everything". -# ALTAIR Just Build The MITS Altair. -# ALTAIRZ80 Just Build The MITS Altair Z80. -# ECLIPSE Just Build The Data General Eclipse. -# GRI Just Build The GRI Corporation GRI-909. -# H316 Just Build The Honewell 316/516. -# HP2100 Just Build The Hewlett-Packard HP-2100. -# I1401 Just Build The IBM 1401. -# IBM1130 Just Build The IBM 1130. -# ID16 Just Build The Interdata 16-bit CPU. -# ID32 Just Build The Interdata 32-bit CPU. -# NOVA Just Build The Data General Nova. -# PDP1 Just Build The DEC PDP-1. -# PDP4 Just Build The DEC PDP-4. -# PDP7 Just Build The DEC PDP-7. -# PDP8 Just Build The DEC PDP-8. -# PDP9 Just Build The DEC PDP-9. -# PDP10 Just Build The DEC PDP-10. -# PDP11 Just Build The DEC PDP-11. -# PDP15 Just Build The DEC PDP-15. -# S3 Just Build The IBM System 3. -# SDS Just Build The SDS 940. -# VAX Just Build The DEC VAX. -# CLEAN Will Clean Files Back To Base Kit. -# -# To build with debugging enabled (which will also enable traceback -# information) use.. -# -# MMK/FORCE/MACRO=(DEBUG=1) -# -# This will produce an executable named {Simulator}-{VAX|AXP}-DBG.EXE -# - -# -# Define The BIN Directory Where The Executables Will Go. -# -BIN_DIR = SYS$DISK:[.BIN] - -# -# Define Our Library Directory. -# -LIB_DIR = SYS$DISK:[.LIB] - -# -# Let's See If We Are Going To Build With DEBUG Enabled. -# -.IFDEF DEBUG -CC_DEBUG = /DEBUG=ALL -LINK_DEBUG = /DEBUG/TRACEBACK -CC_OPTIMIZE = /NOOPTIMIZE -.IFDEF __ALPHA__ -CC_FLAGS = /PREFIX=ALL -ARCH = AXP-DBG -.ELSE -ARCH = VAX-DBG -CC_FLAGS = $(CC_FLAGS) -.ENDIF -.ELSE -CC_DEBUG = /NODEBUG -LINK_DEBUG = /NODEBUG/NOTRACEBACK -.IFDEF __ALPHA__ -CC_OPTIMIZE = /OPTIMIZE=(LEVEL=5,TUNE=HOST)/ARCH=HOST -CC_FLAGS = /PREFIX=ALL -ARCH = AXP -.ELSE -CC_OPTIMIZE = /OPTIMIZE -ARCH = VAX -CC_FLAGS = $(CC_FLAGS) -.ENDIF -.ENDIF - -# -# Define Our Compiler Flags -# -CC_FLAGS = $(CC_FLAGS)$(CC_DEBUG)$(CC_OPTIMIZE)/NEST=PRIMARY/NAME=(AS_IS,SHORTENED) - -# -# Define The Compile Command. -# -CC = CC/DECC$(CC_FLAGS) - -# -# First, Let's Check To Make Sure We Have A SYS$DISK:[.BIN] And -# SYS$DISK:[.LIB] Directory. -# -.FIRST - @ IF (F$SEARCH("SYS$DISK:[]BIN.DIR").EQS."") THEN CREATE/DIRECTORY $(BIN_DIR) - @ IF (F$SEARCH("SYS$DISK:[]LIB.DIR").EQS."") THEN CREATE/DIRECTORY $(LIB_DIR) - -# -# Core SIMH File Definitions. -# -SIMH_DIR = SYS$DISK:[] -SIMH_LIB = $(LIB_DIR)SIMH-$(ARCH).OLB -SIMH_SOURCE = $(SIMH_DIR)SCP_TTY.C,$(SIMH_DIR)SIM_SOCK.C,\ - $(SIMH_DIR)SIM_TMXR.C,$(SIMH_DIR)SIM_ETHER.C,\ - $(SIMH_DIR)SIM_TAPE.C -SIMH_OBJS = $(SIMH_DIR)SCP_TTY.OBJ,$(SIMH_DIR)SIM_SOCK.OBJ,\ - $(SIMH_DIR)SIM_TMXR.OBJ,$(SIMH_DIR)SIM_ETHER.OBJ,\ - $(SIMH_DIR)SIM_TAPE.OBJ - -# -# MITS Altair Simulator Definitions. -# -ALTAIR_DIR = SYS$DISK:[.ALTAIR] -ALTAIR_LIB = $(LIB_DIR)ALTAIR-$(ARCH).OLB -ALTAIR_SOURCE = $(ALTAIR_DIR)ALTAIR_SIO.C,$(ALTAIR_DIR)ALTAIR_CPU.C,\ - $(ALTAIR_DIR)ALTAIR_DSK.C,$(ALTAIR_DIR)ALTAIR_SYS.C -ALTAIR_OBJS = $(ALTAIR_DIR)ALTAIR_SIO.OBJ,$(ALTAIR_DIR)ALTAIR_CPU.OBJ,\ - $(ALTAIR_DIR)ALTAIR_DSK.OBJ,$(ALTAIR_DIR)ALTAIR_SYS.OBJ -ALTAIR_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ALTAIR_DIR)) - -# -# MITS Altair Z80 Simulator Definitions. -# -ALTAIRZ80_DIR = SYS$DISK:[.ALTAIRZ80] -ALTAIRZ80_LIB = $(LIB_DIR)ALTAIRZ80-$(ARCH).OLB -ALTAIRZ80_SOURCE = $(ALTAIRZ80_DIR)ALTAIRZ80_CPU.C,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_DSK.C,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_SIO.C,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_SYS.C,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_HDSK.C -ALTAIRZ80_OBJS = $(ALTAIRZ80_DIR)ALTAIRZ80_CPU.OBJ,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_DSK.OBJ,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_SIO.OBJ,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_SYS.OBJ,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_HDSK.OBJ -ALTAIRZ80_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ALTAIRZ80_DIR)) - -# -# Data General Nova Simulator Definitions. -# -NOVA_DIR = SYS$DISK:[.NOVA] -NOVA_LIB = $(LIB_DIR)NOVA-$(ARCH).OLB -NOVA_SOURCE = $(NOVA_DIR)NOVA_SYS.C,$(NOVA_DIR)NOVA_CPU.C,\ - $(NOVA_DIR)NOVA_DKP.C,$(NOVA_DIR)NOVA_DSK.C,\ - $(NOVA_DIR)NOVA_LP.C,$(NOVA_DIR)NOVA_MTA.C,\ - $(NOVA_DIR)NOVA_PLT.C,$(NOVA_DIR)NOVA_PT.C,\ - $(NOVA_DIR)NOVA_CLK.C,$(NOVA_DIR)NOVA_TT.C,\ - $(NOVA_DIR)NOVA_TT1.C -NOVA_OBJS = $(NOVA_DIR)NOVA_SYS.OBJ,$(NOVA_DIR)NOVA_CPU.OBJ,\ - $(NOVA_DIR)NOVA_DKP.OBJ,$(NOVA_DIR)NOVA_DSK.OBJ,\ - $(NOVA_DIR)NOVA_LP.OBJ,$(NOVA_DIR)NOVA_MTA.OBJ,\ - $(NOVA_DIR)NOVA_PLT.OBJ,$(NOVA_DIR)NOVA_PT.OBJ,\ - $(NOVA_DIR)NOVA_CLK.OBJ,$(NOVA_DIR)NOVA_TT.OBJ,\ - $(NOVA_DIR)NOVA_TT1.OBJ -NOVA_OPTIONS = /INCLUDE=($(SIMH_DIR),$(NOVA_DIR)) - -# -# Data General Eclipse Simulator Definitions. -# -ECLIPSE_LIB = $(LIB_DIR)ECLIPSE-$(ARCH).OLB -ECLIPSE_SOURCE = $(NOVA_DIR)ECLIPSE_CPU.C,$(NOVA_DIR)ECLIPSE_TT.C,\ - $(NOVA_DIR)NOVA_SYS.C,$(NOVA_DIR)NOVA_DKP.C,\ - $(NOVA_DIR)NOVA_DSK.C,$(NOVA_DIR)NOVA_LP.C,\ - $(NOVA_DIR)NOVA_MTA.C,$(NOVA_DIR)NOVA_PLT.C,\ - $(NOVA_DIR)NOVA_PT.C,$(NOVA_DIR)NOVA_CLK.C,\ - $(NOVA_DIR)NOVA_TT1.C -ECLIPSE_OBJS = $(NOVA_DIR)ECLIPSE_CPU.OBJ,$(NOVA_DIR)ECLIPSE_TT.OBJ,\ - $(NOVA_DIR)NOVA_SYS.OBJ,$(NOVA_DIR)NOVA_DKP.OBJ,\ - $(NOVA_DIR)NOVA_DSK.OBJ,$(NOVA_DIR)NOVA_LP.OBJ,\ - $(NOVA_DIR)NOVA_MTA.OBJ,$(NOVA_DIR)NOVA_PLT.OBJ,\ - $(NOVA_DIR)NOVA_PT.OBJ,$(NOVA_DIR)NOVA_CLK.OBJ,\ - $(NOVA_DIR)NOVA_TT1.OBJ -ECLIPSE_OPTIONS = /INCLUDE=($(SIMH_DIR),$(NOVA_DIR))/DEFINE=("ECLIPSE=1") - -# -# GRI Corporation GRI-909 Simulator Definitions. -# -GRI_DIR = SYS$DISK:[.GRI] -GRI_LIB = $(LIB_DIR)GRI-$(ARCH).OLB -GRI_SOURCE = $(GRI_DIR)GRI_CPU.C,$(GRI_DIR)GRI_STDDEV.C,$(GRI_DIR)GRI_SYS.C -GRI_OBJS = $(GRI_DIR)GRI_CPU.OBJ,$(GRI_DIR)GRI_STDDEV.OBJ,\ - $(GRI_DIR)GRI_SYS.OBJ -GRI_OPTIONS = /INCLUDE=($(SIMH_DIR),$(GRI_DIR)) - -# -# Honeywell 316/516 Simulator Definitions. -# -H316_DIR = SYS$DISK:[.H316] -H316_LIB = $(LIB_DIR)H316-$(ARCH).OLB -H316_SOURCE = $(H316_DIR)H316_STDDEV.C,$(H316_DIR)H316_LP.C,\ - $(H316_DIR)H316_CPU.C,$(H316_DIR)H316_SYS.C -H316_OBJS = $(H316_DIR)H316_STDDEV.OBJ,$(H316_DIR)H316_LP.OBJ,\ - $(H316_DIR)H316_CPU.OBJ,$(H316_DIR)H316_SYS.OBJ -H316_OPTIONS = /INCLUDE=($(SIMH_DIR),$(H316_DIR)) - -# -# Hewlett-Packard HP-2100 Simulator Definitions. -# -HP2100_DIR = SYS$DISK:[.HP2100] -HP2100_LIB = $(LIB_DIR)HP2100-$(ARCH).OLB -HP2100_SOURCE = $(HP2100_DIR)HP2100_STDDEV.C,$(HP2100_DIR)HP2100_DP.C,\ - $(HP2100_DIR)HP2100_DQ.C,$(HP2100_DIR)HP2100_DR.C,\ - $(HP2100_DIR)HP2100_LPS.C,$(HP2100_DIR)HP2100_MS.C,\ - $(HP2100_DIR)HP2100_MT.C,$(HP2100_DIR)HP2100_MUX.C,\ - $(HP2100_DIR)HP2100_CPU.C,$(HP2100_DIR)HP2100_FP.C,\ - $(HP2100_DIR)HP2100_SYS.C,$(HP2100_DIR)HP2100_LPT.C,\ - $(HP2100_DIR)HP2100_IPL.C -HP2100_OBJS = $(HP2100_DIR)HP2100_STDDEV.OBJ,$(HP2100_DIR)HP2100_DP.OBJ,\ - $(HP2100_DIR)HP2100_DQ.OBJ,$(HP2100_DIR)HP2100_DR.OBJ,\ - $(HP2100_DIR)HP2100_LPS.OBJ,$(HP2100_DIR)HP2100_MS.OBJ,\ - $(HP2100_DIR)HP2100_MT.OBJ,$(HP2100_DIR)HP2100_MUX.OBJ,\ - $(HP2100_DIR)HP2100_CPU.OBJ,$(HP2100_DIR)HP2100_FP.OBJ,\ - $(HP2100_DIR)HP2100_SYS.OBJ,$(HP2100_DIR)HP2100_LPT.OBJ,\ - $(HP2100_DIR)HP2100_IPL.OBJ -HP2100_OPTIONS = /INCLUDE=($(SIMH_DIR),$(HP2100_DIR)) - -# -# Interdata 16-bit CPU. -# -ID16_DIR = SYS$DISK:[.INTERDATA] -ID16_LIB = $(LIB_DIR)ID16-$(ARCH).OLB -ID16_SOURCE = $(ID16_DIR)ID16_CPU.C,$(ID16_DIR)ID16_SYS.C,$(ID16_DIR)ID_DP.C,\ - $(ID16_DIR)ID_FD.C,$(ID16_DIR)ID_FP.C,$(ID16_DIR)ID_IDC.C,\ - $(ID16_DIR)ID_IO.C,$(ID16_DIR)ID_LP.C,$(ID16_DIR)ID_MT.C,\ - $(ID16_DIR)ID_PAS.C,$(ID16_DIR)ID_PT.C,$(ID16_DIR)ID_TT.C,\ - $(ID16_DIR)ID_UVC.C,$(ID16_DIR)ID16_DBOOT.C,$(ID16_DIR)ID_TTP.C -ID16_OBJS = $(ID16_DIR)ID16_CPU.OBJ,$(ID16_DIR)ID16_SYS.OBJ,\ - $(ID16_DIR)ID_DP.OBJ,$(ID16_DIR)ID_FD.OBJ,$(ID16_DIR)ID_FP.OBJ,\ - $(ID16_DIR)ID_IDC.OBJ,$(ID16_DIR)ID_IO.OBJ,$(ID16_DIR)ID_LP.OBJ,\ - $(ID16_DIR)ID_MT.OBJ,$(ID16_DIR)ID_PAS.OBJ,$(ID16_DIR)ID_PT.OBJ,\ - $(ID16_DIR)ID_TT.OBJ,$(ID16_DIR)ID_UVC.OBJ,\ - $(ID16_DIR)ID16_DBOOT.OBJ,$(ID16_DIR)ID_TTP.OBJ -ID16_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ID16_DIR)) - -# -# Interdata 32-bit CPU. -# -ID32_DIR = SYS$DISK:[.INTERDATA] -ID32_LIB = $(LIB_DIR)ID32-$(ARCH).OLB -ID32_SOURCE = $(ID32_DIR)ID32_CPU.C,$(ID32_DIR)ID32_SYS.C,$(ID32_DIR)ID_DP.C,\ - $(ID32_DIR)ID_FD.C,$(ID32_DIR)ID_FP.C,$(ID32_DIR)ID_IDC.C,\ - $(ID32_DIR)ID_IO.C,$(ID32_DIR)ID_LP.C,$(ID32_DIR)ID_MT.C,\ - $(ID32_DIR)ID_PAS.C,$(ID32_DIR)ID_PT.C,$(ID32_DIR)ID_TT.C,\ - $(ID32_DIR)ID_UVC.C,$(ID32_DIR)ID32_DBOOT.C,$(ID32_DIR)ID_TTP.C -ID32_OBJS = $(ID32_DIR)ID32_CPU.OBJ,$(ID32_DIR)ID32_SYS.OBJ,\ - $(ID32_DIR)ID_DP.OBJ,$(ID32_DIR)ID_FD.OBJ,\ - $(ID32_DIR)ID_FP.OBJ,$(ID32_DIR)ID_IDC.OBJ,\ - $(ID32_DIR)ID_IO.OBJ,$(ID32_DIR)ID_LP.OBJ,$(ID32_DIR)ID_MT.OBJ,\ - $(ID32_DIR)ID_PAS.OBJ,$(ID32_DIR)ID_PT.OBJ,$(ID32_DIR)ID_TT.OBJ,\ - $(ID32_DIR)ID_UVC.OBJ,$(ID32_DIR)ID32_DBOOT.OBJ,\ - $(ID32_DIR)ID_TTP.OBJ -ID32_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ID32_DIR)) - -# -# IBM 1130 Simulator Definitions. -# -IBM1130_DIR = SYS$DISK:[.IBM1130] -IBM1130_LIB = $(LIB_DIR)IBM1130-$(ARCH).OLB -IBM1130_SOURCE = $(IBM1130_DIR)IBM1130_CPU.C,$(IBM1130_DIR)IBM1130_CR.C,\ - $(IBM1130_DIR)IBM1130_DISK.C,$(IBM1130_DIR)IBM1130_STDDEV.C,\ - $(IBM1130_DIR)IBM1130_SYS.C,$(IBM1130_DIR)IBM1130_GDU.C,\ - $(IBM1130_DIR)IBM1130_GUI.C,$(IBM1130_DIR)IBM1130_PRT.C,\ - $(IBM1130_DIR)IBM1130_FMT.C -IBM1130_OBJS = $(IBM1130_DIR)IBM1130_CPU.OBJ,$(IBM1130_DIR)IBM1130_CR.OBJ,\ - $(IBM1130_DIR)IBM1130_DISK.OBJ,$(IBM1130_DIR)IBM1130_STDDEV.OBJ,\ - $(IBM1130_DIR)IBM1130_SYS.OBJ,$(IBM1130_DIR)IBM1130_GDU.OBJ,\ - $(IBM1130_DIR)IBM1130_GUI.OBJ,$(IBM1130_DIR)IBM1130_PRT.OBJ,\ - $(IBM1130_DIR)IBM1130_FMT.OBJ -IBM1130_OPTIONS = /INCLUDE=($(SIMH_DIR),$(IBM1130_DIR)) - -# -# IBM 1401 Simulator Definitions. -# -I1401_DIR = SYS$DISK:[.I1401] -I1401_LIB = $(LIB_DIR)I1401-$(ARCH).OLB -I1401_SOURCE = $(I1401_DIR)I1401_LP.C,$(I1401_DIR)I1401_CPU.C,\ - $(I1401_DIR)I1401_IQ.C,$(I1401_DIR)I1401_CD.C,\ - $(I1401_DIR)I1401_MT.C,$(I1401_DIR)I1401_DP.C,\ - $(I1401_DIR)I1401_SYS.C -I1401_OBJS = $(I1401_DIR)I1401_LP.OBJ,$(I1401_DIR)I1401_CPU.OBJ,\ - $(I1401_DIR)I1401_IQ.OBJ,$(I1401_DIR)I1401_CD.OBJ,\ - $(I1401_DIR)I1401_MT.OBJ,$(I1401_DIR)I1401_DP.OBJ,\ - $(I1401_DIR)I1401_SYS.OBJ -I1401_OPTIONS = /INCLUDE=($(SIMH_DIR),$(I1401_DIR)) - - -# -# IBM 1620 Simulators Definitions. -# -I1620_DIR = SYS$DISK:[.I1620] -I1620_LIB = $(LIB_DIR)I1620-$(ARCH).OLB -I1620_SOURCE = $(I1620_DIR)I1620_CD.C,$(I1620_DIR)I1620_DP.C,\ - $(I1620_DIR)I1620_PT.C,$(I1620_DIR)I1620_TTY.C,\ - $(I1620_DIR)I1620_CPU.C,$(I1620_DIR)I1620_LP.C,\ - $(I1620_DIR)I1620_FP.C,$(I1620_DIR)I1620_SYS.C -I1620_OBJS = $(I1620_DIR)I1620_CD.OBJ,$(I1620_DIR)I1620_DP.OBJ,\ - $(I1620_DIR)I1620_PT.OBJ,$(I1620_DIR)I1620_TTY.OBJ,\ - $(I1620_DIR)I1620_CPU.OBJ,$(I1620_DIR)I1620_LP.OBJ,\ - $(I1620_DIR)I1620_FP.OBJ,$(I1620_DIR)I1620_SYS.OBJ -I1620_OPTIONS = /INCLUDE=($(SIMH_DIR),$(I1620_DIR)) - -# -# PDP-1 Simulator Definitions. -# -PDP1_DIR = SYS$DISK:[.PDP1] -PDP1_LIB = $(LIB_DIR)PDP1-$(ARCH).OLB -PDP1_SOURCE = $(PDP1_DIR)PDP1_LP.C,$(PDP1_DIR)PDP1_CPU.C,\ - $(PDP1_DIR)PDP1_STDDEV.C,$(PDP1_DIR)PDP1_SYS.C,\ - $(PDP1_DIR)PDP1_DT.C,$(PDP1_DIR)PDP1_DRM.C -PDP1_OBJS = $(PDP1_DIR)PDP1_LP.OBJ,$(PDP1_DIR)PDP1_CPU.OBJ,\ - $(PDP1_DIR)PDP1_STDDEV.OBJ,$(PDP1_DIR)PDP1_SYS.OBJ,\ - $(PDP1_DIR)PDP1_DT.OBJ,$(PDP1_DIR)PDP1_DRM.OBJ -PDP1_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP1_DIR)) - -# -# Digital Equipment PDP-8 Simulator Definitions. -# -PDP8_DIR = SYS$DISK:[.PDP8] -PDP8_LIB = $(LIB_DIR)PDP8-$(ARCH).OLB -PDP8_SOURCE = $(PDP8_DIR)PDP8_CPU.C,$(PDP8_DIR)PDP8_CLK.C,\ - $(PDP8_DIR)PDP8_DF.C,$(PDP8_DIR)PDP8_DT.C,\ - $(PDP8_DIR)PDP8_LP.C,$(PDP8_DIR)PDP8_MT.C,\ - $(PDP8_DIR)PDP8_PT.C,$(PDP8_DIR)PDP8_RF.C,\ - $(PDP8_DIR)PDP8_RK.C,$(PDP8_DIR)PDP8_RX.C,\ - $(PDP8_DIR)PDP8_SYS.C,$(PDP8_DIR)PDP8_TT.C,\ - $(PDP8_DIR)PDP8_TTX.C,$(PDP8_DIR)PDP8_RL.C -PDP8_OBJS = $(PDP8_DIR)PDP8_CPU.OBJ,$(PDP8_DIR)PDP8_CLK.OBJ,\ - $(PDP8_DIR)PDP8_DF.OBJ,$(PDP8_DIR)PDP8_DT.OBJ,\ - $(PDP8_DIR)PDP8_LP.OBJ,$(PDP8_DIR)PDP8_MT.OBJ,\ - $(PDP8_DIR)PDP8_PT.OBJ,$(PDP8_DIR)PDP8_RF.OBJ,\ - $(PDP8_DIR)PDP8_RK.OBJ,$(PDP8_DIR)PDP8_RX.OBJ,\ - $(PDP8_DIR)PDP8_SYS.OBJ,$(PDP8_DIR)PDP8_TT.OBJ,\ - $(PDP8_DIR)PDP8_TTX.OBJ,$(PDP8_DIR)PDP8_RL.OBJ -PDP8_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP8_DIR)) - -# -# Digital Equipment PDP-4, PDP-7, PDP-9 And PDP-15 Simulator Definitions. -# -PDP18B_DIR = SYS$DISK:[.PDP18B] -PDP4_LIB = $(LIB_DIR)PDP4-$(ARCH).OLB -PDP7_LIB = $(LIB_DIR)PDP7-$(ARCH).OLB -PDP9_LIB = $(LIB_DIR)PDP9-$(ARCH).OLB -PDP15_LIB = $(LIB_DIR)PDP15-$(ARCH).OLB -PDP18B_SOURCE = $(PDP18B_DIR)PDP18B_DT.C,$(PDP18B_DIR)PDP18B_DRM.C,\ - $(PDP18B_DIR)PDP18B_CPU.C,$(PDP18B_DIR)PDP18B_LP.C,\ - $(PDP18B_DIR)PDP18B_MT.C,$(PDP18B_DIR)PDP18B_RF.C,\ - $(PDP18B_DIR)PDP18B_RP.C,$(PDP18B_DIR)PDP18B_STDDEV.C,\ - $(PDP18B_DIR)PDP18B_SYS.C,$(PDP18B_DIR)PDP18B_TT1.C,\ - $(PDP18B_DIR)PDP18B_RB.C,$(PDP18B_DIR)PDP18B_FPP.C -PDP18B_OBJS = $(PDP18B_DIR)PDP18B_DT.OBJ,$(PDP18B_DIR)PDP18B_DRM.OBJ,\ - $(PDP18B_DIR)PDP18B_CPU.OBJ,$(PDP18B_DIR)PDP18B_LP.OBJ,\ - $(PDP18B_DIR)PDP18B_MT.OBJ,$(PDP18B_DIR)PDP18B_RF.OBJ,\ - $(PDP18B_DIR)PDP18B_RP.OBJ,$(PDP18B_DIR)PDP18B_STDDEV.OBJ,\ - $(PDP18B_DIR)PDP18B_SYS.OBJ,$(PDP18B_DIR)PDP18B_TT1.OBJ,\ - $(PDP18B_DIR)PDP18B_RB.OBJ,$(PDP18B_DIR)PDP18B_FPP.OBJ -PDP4_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP4=1") -PDP7_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP7=1") -PDP9_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP9=1") -PDP15_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP15=1") - -# -# Digital Equipment PDP-11 Simulator Definitions. -# -PDP11_DIR = SYS$DISK:[.PDP11] -PDP11_LIB = $(LIB_DIR)PDP11-$(ARCH).OLB -PDP11_SOURCE = $(PDP11_DIR)PDP11_FP.C,$(PDP11_DIR)PDP11_CPU.C,\ - $(PDP11_DIR)PDP11_DZ.C,$(PDP11_DIR)PDP11_CIS.C,\ - $(PDP11_DIR)PDP11_LP.C,$(PDP11_DIR)PDP11_RK.C,\ - $(PDP11_DIR)PDP11_RL.C,$(PDP11_DIR)PDP11_RP.C,\ - $(PDP11_DIR)PDP11_RX.C,$(PDP11_DIR)PDP11_STDDEV.C,\ - $(PDP11_DIR)PDP11_SYS.C,$(PDP11_DIR)PDP11_TC.C,\ - $(PDP11_DIR)PDP11_TM.C,$(PDP11_DIR)PDP11_TS.C,\ - $(PDP11_DIR)PDP11_IO.C,$(PDP11_DIR)PDP11_RQ.C,\ - $(PDP11_DIR)PDP11_TQ.C,$(PDP11_DIR)PDP11_PCLK.C,\ - $(PDP11_DIR)PDP11_RY.C,$(PDP11_DIR)PDP11_PT.C,\ - $(PDP11_DIR)PDP11_HK.C,$(PDP11_DIR)PDP11_XQ.C,\ - $(PDP11_DIR)PDP11_XU.C -PDP11_OBJS = $(PDP11_DIR)PDP11_FP.OBJ,$(PDP11_DIR)PDP11_CPU.OBJ,\ - $(PDP11_DIR)PDP11_DZ.OBJ,$(PDP11_DIR)PDP11_CIS.OBJ,\ - $(PDP11_DIR)PDP11_LP.OBJ,$(PDP11_DIR)PDP11_RK.OBJ,\ - $(PDP11_DIR)PDP11_RL.OBJ,$(PDP11_DIR)PDP11_RP.OBJ,\ - $(PDP11_DIR)PDP11_RX.OBJ,$(PDP11_DIR)PDP11_STDDEV.OBJ,\ - $(PDP11_DIR)PDP11_SYS.OBJ,$(PDP11_DIR)PDP11_TC.OBJ,\ - $(PDP11_DIR)PDP11_TM.OBJ,$(PDP11_DIR)PDP11_TS.OBJ,\ - $(PDP11_DIR)PDP11_IO.OBJ,$(PDP11_DIR)PDP11_RQ.OBJ,\ - $(PDP11_DIR)PDP11_TQ.OBJ,$(PDP11_DIR)PDP11_PCLK.OBJ,\ - $(PDP11_DIR)PDP11_RY.OBJ,$(PDP11_DIR)PDP11_PT.OBJ,\ - $(PDP11_DIR)PDP11_HK.OBJ,$(PDP11_DIR)PDP11_XQ.OBJ,\ - $(PDP11_DIR)PDP11_XU.OBJ -PDP11_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP11_DIR))/DEFINE=("VM_PDP11=1") - -# -# Digital Equipment PDP-10 Simulator Definitions. -# -PDP10_DIR = SYS$DISK:[.PDP10] -PDP10_LIB = $(LIB_DIR)PDP10-$(ARCH).OLB -PDP10_SOURCE = $(PDP10_DIR)PDP10_FE.C,\ - $(PDP10_DIR)PDP10_CPU.C,$(PDP10_DIR)PDP10_KSIO.C,\ - $(PDP10_DIR)PDP10_LP20.C,$(PDP10_DIR)PDP10_MDFP.C,\ - $(PDP10_DIR)PDP10_PAG.C,$(PDP10_DIR)PDP10_XTND.C,\ - $(PDP10_DIR)PDP10_RP.C,$(PDP10_DIR)PDP10_SYS.C,\ - $(PDP10_DIR)PDP10_TIM.C,$(PDP10_DIR)PDP10_TU.C,\ - $(PDP11_DIR)PDP11_PT.C,$(PDP11_DIR)PDP11_DZ.C,\ - $(PDP11_DIR)PDP11_RY.C,$(PDP11_DIR)PDP11_XU.C -PDP10_OBJS = $(PDP10_DIR)PDP10_FE.OBJ,\ - $(PDP10_DIR)PDP10_CPU.OBJ,$(PDP10_DIR)PDP10_KSIO.OBJ,\ - $(PDP10_DIR)PDP10_LP20.OBJ,$(PDP10_DIR)PDP10_MDFP.OBJ,\ - $(PDP10_DIR)PDP10_PAG.OBJ,$(PDP10_DIR)PDP10_XTND.OBJ,\ - $(PDP10_DIR)PDP10_RP.OBJ,$(PDP10_DIR)PDP10_SYS.OBJ,\ - $(PDP10_DIR)PDP10_TIM.OBJ,$(PDP10_DIR)PDP10_TU.OBJ,\ - $(PDP10_DIR)PDP11_PT.OBJ,$(PDP10_DIR)PDP11_DZ.OBJ,\ - $(PDP10_DIR)PDP11_RY.OBJ,$(PDP10_DIR)PDP11_XU.OBJ -PDP10_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP10_DIR),$(PDP11_DIR))/DEFINE=("USE_INT64=1","VM_PDP10=1") - -# -# IBM System 3 Simulator Definitions. -# -S3_DIR = SYS$DISK:[.S3] -S3_LIB = $(LIB_DIR)S3-$(ARCH).OLB -S3_SOURCE = $(S3_DIR)S3_CD.C,$(S3_DIR)S3_CPU.C,$(S3_DIR)S3_DISK.C,\ - $(S3_DIR)S3_LP.C,$(S3_DIR)S3_PKB.C,$(S3_DIR)S3_SYS.C -S3_OBJS = $(S3_DIR)S3_CD.OBJ,$(S3_DIR)S3_CPU.OBJ,$(S3_DIR)S3_DISK.OBJ,\ - $(S3_DIR)S3_LP.OBJ,$(S3_DIR)S3_PKB.OBJ,$(S3_DIR)S3_SYS.OBJ -S3_OPTIONS = /INCLUDE=($(SIMH_DIR),$(S3_DIR)) - -# -# SDS 940 -# -SDS_DIR = SYS$DISK:[.SDS] -SDS_LIB = $(LIB_DIR)SDS-$(ARCH).OLB -SDS_SOURCE = $(SDS_DIR)SDS_CPU.C,$(SDS_DIR)SDS_DRM.C,$(SDS_DIR)SDS_DSK.C,\ - $(SDS_DIR)SDS_IO.C,$(SDS_DIR)SDS_LP.C,$(SDS_DIR)SDS_MT.C,\ - $(SDS_DIR)SDS_MUX.C,$(SDS_DIR)SDS_RAD.C,$(SDS_DIR)SDS_STDDEV.C,\ - $(SDS_DIR)SDS_SYS.C -SDS_OBJS = $(SDS_DIR)SDS_CPU.OBJ,$(SDS_DIR)SDS_DRM.OBJ,$(SDS_DIR)SDS_DSK.OBJ,\ - $(SDS_DIR)SDS_IO.OBJ,$(SDS_DIR)SDS_LP.OBJ,$(SDS_DIR)SDS_MT.OBJ,\ - $(SDS_DIR)SDS_MUX.OBJ,$(SDS_DIR)SDS_RAD.OBJ,\ - $(SDS_DIR)SDS_STDDEV.OBJ,$(SDS_DIR)SDS_SYS.OBJ -SDS_OPTIONS = /INCLUDE=($(SIMH_DIR),$(SDS_DIR)) - -# -# Digital Equipment VAX Simulator Definitions. -# -VAX_DIR = SYS$DISK:[.VAX] -VAX_LIB = $(LIB_DIR)VAX-$(ARCH).OLB -VAX_SOURCE = $(VAX_DIR)VAX_CPU1.C,$(VAX_DIR)VAX_CPU.C,\ - $(VAX_DIR)VAX_FPA.C,$(VAX_DIR)VAX_IO.C,\ - $(VAX_DIR)VAX_MMU.C,$(VAX_DIR)VAX_STDDEV.C,\ - $(VAX_DIR)VAX_SYS.C,$(VAX_DIR)VAX_SYSDEV.C,\ - $(PDP11_DIR)PDP11_RL.C,$(PDP11_DIR)PDP11_RQ.C,\ - $(PDP11_DIR)PDP11_TS.C,$(PDP11_DIR)PDP11_DZ.C,\ - $(PDP11_DIR)PDP11_LP.C,$(PDP11_DIR)PDP11_TQ.C,\ - $(PDP11_DIR)PDP11_PT.C,$(PDP11_DIR)PDP11_XQ.C -VAX_OBJS = $(VAX_DIR)VAX_CPU1.OBJ,$(VAX_DIR)VAX_CPU.OBJ,\ - $(VAX_DIR)VAX_FPA.OBJ,$(VAX_DIR)VAX_IO.OBJ,\ - $(VAX_DIR)VAX_MMU.OBJ,$(VAX_DIR)VAX_STDDEV.OBJ,\ - $(VAX_DIR)VAX_SYS.OBJ,$(VAX_DIR)VAX_SYSDEV.OBJ,\ - $(VAX_DIR)PDP11_RL.OBJ,$(VAX_DIR)PDP11_RQ.OBJ,\ - $(VAX_DIR)PDP11_TS.OBJ,$(VAX_DIR)PDP11_DZ.OBJ,\ - $(VAX_DIR)PDP11_LP.OBJ,$(VAX_DIR)PDP11_TQ.OBJ,\ - $(VAX_DIR)PDP11_PT.OBJ,$(VAX_DIR)PDP11_XQ.OBJ -# -# If On Alpha, Define "USE_INT64" As We Have INT64. -# -.IFDEF __ALPHA__ -VAX_OPTIONS = /INCLUDE=($(SIMH_DIR),$(VAX_DIR),$(PDP11_DIR))/DEFINE=("USE_INT64=1","VM_VAX=1") -.ELSE -# -# We Are On A VAX Platform So Don't Define "USE_INT64" As We Don't Have -# INT64. -# -VAX_OPTIONS = /INCLUDE=($(SIMH_DIR),$(VAX_DIR),$(PDP11_DIR))/DEFINE=("VM_VAX=1") -.ENDIF - -# -# If On Alpha, Build Everything. -# -.IFDEF __ALPHA__ -ALL : ALTAIR ALTAIRZ80 ECLIPSE GRI H316 HP2100 I1401 I1620 IBM1130 ID16 ID32 \ - NOVA PDP1 PDP4 PDP7 PDP8 PDP9 PDP10 PDP11 PDP15 S3 VAX SDS -.ELSE -# -# Else We Are On VAX And Build Everything EXCEPT The PDP-10 Since VAX -# Dosen't Have INT64 -# -ALL : ALTAIR ALTAIRZ80 ECLIPSE GRI H316 HP2100 I1401 I1620 IBM1130 ID16 ID32 \ - NOVA PDP1 PDP4 PDP7 PDP8 PDP9 PDP11 PDP15 S3 VAX SDS -.ENDIF - -CLEAN : - $! - $! Clean out all targets and building Remnants - $! - $ IF (F$SEARCH("$(BIN_DIR)*.EXE;*").NES."") THEN - - DELETE/NOLOG/NOCONFIRM $(BIN_DIR)*.EXE;* - $ IF (F$SEARCH("$(LIB_DIR)*.EXE;*").NES."") THEN - - DELETE/NOLOG/NOCONFIRM $(LIB_DIR)*.OLB;* - $ IF (F$SEARCH("SYS$DISK:[...]*.OBJ;*").NES."") THEN - - DELETE/NOLOG/NOCONFIRM SYS$DISK:[...]*.OBJ;* - -# -# Build The Libraries. -# -$(LIB_DIR)SIMH-$(ARCH).OLB : $(SIMH_SOURCE) - $! - $! Building The $(SIMH_LIB) Library. - $! - $ $(CC)/OBJECT=$(SIMH_DIR) $(SIMH_SOURCE) - $ IF (F$SEARCH("$(SIMH_LIB)").EQS."") THEN - - LIBRARY/CREATE $(SIMH_LIB) - $ LIBRARY/REPLACE $(SIMH_LIB) $(SIMH_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -$(LIB_DIR)ALTAIR-$(ARCH).OLB : $(ALTAIR_SOURCE) - $! - $! Building The $(ALTAIR_LIB) Library. - $! - $ $(CC)$(ALTAIR_OPTIONS)/OBJECT=$(ALTAIR_DIR) - - $(ALTAIR_SOURCE) - $ IF (F$SEARCH("$(ALTAIR_LIB)").EQS."") THEN - - LIBRARY/CREATE $(ALTAIR_LIB) - $ LIBRARY/REPLACE $(ALTAIR_LIB) - - $(ALTAIR_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(ALTAIR_DIR)*.OBJ;* - -$(LIB_DIR)ALTAIRZ80-$(ARCH).OLB : $(ALTAIRZ80_SOURCE) - $! - $! Building The $(ALTAIRZ80_LIB) Library. - $! - $ $(CC)$(ALTAIRZ80_OPTIONS) - - /OBJECT=$(ALTAIRZ80_DIR) - - $(ALTAIRZ80_SOURCE) - $ IF (F$SEARCH("$(ALTAIRZ80_LIB)").EQS."") - - THEN LIBRARY/CREATE $(ALTAIRZ80_LIB) - $ LIBRARY/REPLACE $(ALTAIRZ80_LIB) - - $(ALTAIRZ80_OBJS) - $ DELETE/NOLOG/NOCONFIRM - - $(ALTAIRZ80_DIR)*.OBJ;* - -$(LIB_DIR)ECLIPSE-$(ARCH).OLB : $(ECLIPSE_SOURCE) - $! - $! Building The $(ECLIPSE_LIB) Library. - $! - $ $(CC)$(ECLIPSE_OPTIONS)/OBJECT=$(NOVA_DIR) - - $(ECLIPSE_SOURCE) - $ IF (F$SEARCH("$(ECLIPSE_LIB)").EQS."") THEN - - LIBRARY/CREATE $(ECLIPSE_LIB) - $ LIBRARY/REPLACE $(ECLIPSE_LIB) - - $(ECLIPSE_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(NOVA_DIR)*.OBJ;* - -$(LIB_DIR)GRI-$(ARCH).OLB : $(GRI_SOURCE) - $! - $! Building The $(GRI_LIB) Library. - $! - $ $(CC)$(GRI_OPTIONS)/OBJECT=$(GRI_DIR) - - $(GRI_SOURCE) - $ IF (F$SEARCH("$(GRI_LIB)").EQS."") THEN - - LIBRARY/CREATE $(GRI_LIB) - $ LIBRARY/REPLACE $(GRI_LIB) $(GRI_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(GRI_DIR)*.OBJ;* - -$(LIB_DIR)H316-$(ARCH).OLB : $(H316_SOURCE) - $! - $! Building The $(H316_LIB) Library. - $! - $ $(CC)$(H316_OPTIONS)/OBJECT=$(H316_DIR) - - $(H316_SOURCE) - $ IF (F$SEARCH("$(H316_LIB)").EQS."") THEN - - LIBRARY/CREATE $(H316_LIB) - $ LIBRARY/REPLACE $(H316_LIB) $(H316_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(H316_DIR)*.OBJ;* - -$(LIB_DIR)HP2100-$(ARCH).OLB : $(HP2100_SOURCE) - $! - $! Building The $(HP2100_LIB) Library. - $! - $ $(CC)$(HP2100_OPTIONS)/OBJECT=$(HP2100_DIR) - - $(HP2100_SOURCE) - $ IF (F$SEARCH("$(HP2100_LIB)").EQS."") THEN - - LIBRARY/CREATE $(HP2100_LIB) - $ LIBRARY/REPLACE $(HP2100_LIB) $(HP2100_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(HP2100_DIR)*.OBJ;* - -$(LIB_DIR)I1401-$(ARCH).OLB : $(I1401_SOURCE) - $! - $! Building The $(I1401_LIB) Library. - $! - $ $(CC)$(I1401_OPTIONS)/OBJECT=$(I1401_DIR) - - $(I1401_SOURCE) - $ IF (F$SEARCH("$(I1401_LIB)").EQS."") THEN - - LIBRARY/CREATE $(I1401_LIB) - $ LIBRARY/REPLACE $(I1401_LIB) $(I1401_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(I1401_DIR)*.OBJ;* - -$(LIB_DIR)I1620-$(ARCH).OLB : $(I1620_SOURCE) - $! - $! Building The $(I1620_LIB) Library. - $! - $ $(CC)$(I1620_OPTIONS)/OBJECT=$(I1620_DIR) - - $(I1620_SOURCE) - $ IF (F$SEARCH("$(I1620_LIB)").EQS."") THEN - - LIBRARY/CREATE $(I1620_LIB) - $ LIBRARY/REPLACE $(I1620_LIB) $(I1620_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(I1620_DIR)*.OBJ;* - -$(LIB_DIR)IBM1130-$(ARCH).OLB : $(IBM1130_SOURCE) - $! - $! Building The $(IBM1130_LIB) Library. - $! - $ $(CC)$(IBM1130_OPTIONS) - - /OBJECT=$(IBM1130_DIR) - - $(IBM1130_SOURCE) - $ IF (F$SEARCH("$(IBM1130_LIB)").EQS."") THEN - - LIBRARY/CREATE $(IBM1130_LIB) - $ LIBRARY/REPLACE $(IBM1130_LIB) $(IBM1130_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(IBM1130_DIR)*.OBJ;* - -$(LIB_DIR)ID16-$(ARCH).OLB : $(ID16_SOURCE) - $! - $! Building The $(ID16_LIB) Library. - $! - $ $(CC)$(ID16_OPTIONS)/OBJECT=$(ID16_DIR) - - $(ID16_SOURCE) - $ IF (F$SEARCH("$(ID16_LIB)").EQS."") THEN - - LIBRARY/CREATE $(ID16_LIB) - $ LIBRARY/REPLACE $(ID16_LIB) $(ID16_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(ID16_DIR)*.OBJ;* - -$(LIB_DIR)ID32-$(ARCH).OLB : $(ID32_SOURCE) - $! - $! Building The $(ID32_LIB) Library. - $! - $ $(CC)$(ID32_OPTIONS)/OBJECT=$(ID32_DIR) - - $(ID32_SOURCE) - $ IF (F$SEARCH("$(ID32_LIB)").EQS."") THEN - - LIBRARY/CREATE $(ID32_LIB) - $ LIBRARY/REPLACE $(ID32_LIB) $(ID32_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(ID32_DIR)*.OBJ;* - -$(LIB_DIR)NOVA-$(ARCH).OLB : $(NOVA_SOURCE) - $! - $! Building The $(NOVA_LIB) Library. - $! - $ $(CC)$(NOVA_OPTIONS)/OBJECT=$(NOVA_DIR) - - $(NOVA_SOURCE) - $ IF (F$SEARCH("$(NOVA_LIB)").EQS."") THEN - - LIBRARY/CREATE $(NOVA_LIB) - $ LIBRARY/REPLACE $(NOVA_LIB) $(NOVA_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(NOVA_DIR)*.OBJ;* - -$(LIB_DIR)PDP1-$(ARCH).OLB : $(PDP1_SOURCE) - $! - $! Building The $(PDP1_LIB) Library. - $! - $ $(CC)$(PDP1_OPTIONS)/OBJECT=$(PDP1_DIR) - - $(PDP1_SOURCE) - $ IF (F$SEARCH("$(PDP1_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP1_LIB) - $ LIBRARY/REPLACE $(PDP1_LIB) $(PDP1_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP1_DIR)*.OBJ;* - -$(LIB_DIR)PDP4-$(ARCH).OLB : $(PDP18B_SOURCE) - $! - $! Building The $(PDP4_LIB) Library. - $! - $ $(CC)$(PDP4_OPTIONS)/OBJECT=$(PDP18B_DIR) - - $(PDP18B_SOURCE) - $ IF (F$SEARCH("$(PDP4_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP4_LIB) - $ LIBRARY/REPLACE $(PDP4_LIB) $(PDP18B_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* - -$(LIB_DIR)PDP7-$(ARCH).OLB : $(PDP18B_SOURCE) - $! - $! Building The $(PDP7_LIB) Library. - $! - $ $(CC)$(PDP7_OPTIONS)/OBJECT=$(PDP18B_DIR) - - $(PDP18B_SOURCE) - $ IF (F$SEARCH("$(PDP7_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP7_LIB) - $ LIBRARY/REPLACE $(PDP7_LIB) $(PDP18B_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* - -$(LIB_DIR)PDP8-$(ARCH).OLB : $(PDP8_SOURCE) - $! - $! Building The $(PDP8_LIB) Library. - $! - $ $(CC)$(PDP8_OPTIONS)/OBJECT=$(PDP8_DIR) - - $(PDP8_SOURCE) - $ IF (F$SEARCH("$(PDP8_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP8_LIB) - $ LIBRARY/REPLACE $(PDP8_LIB) $(PDP8_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP8_DIR)*.OBJ;* - -$(LIB_DIR)PDP9-$(ARCH).OLB : $(PDP18B_SOURCE) - $! - $! Building The $(PDP9_LIB) Library. - $! - $ $(CC)$(PDP9_OPTIONS)/OBJECT=$(PDP18B_DIR) - - $(PDP18B_SOURCE) - $ IF (F$SEARCH("$(PDP9_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP9_LIB) - $ LIBRARY/REPLACE $(PDP9_LIB) $(PDP18B_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* - -# -# If On Alpha, Build The PDP-10 Library. -# -.IFDEF __ALPHA__ -$(LIB_DIR)PDP10-$(ARCH).OLB : $(PDP10_SOURCE) - $! - $! Building The $(PDP10_LIB) Library. - $! - $ $(CC)$(PDP10_OPTIONS)/OBJECT=$(PDP10_DIR) - - $(PDP10_SOURCE) - $ IF (F$SEARCH("$(PDP10_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP10_LIB) - $ LIBRARY/REPLACE $(PDP10_LIB) $(PDP10_OBJS) - DELETE/NOLOG/NOCONFIRM $(PDP10_DIR)*.OBJ;* -.ELSE -# -# We Are On VAX And Due To The Use of INT64 We Can't Build It. -# -$(LIB_DIR)PDP10-$(ARCH).OLB : - $! - $! Due To The Use Of INT64 We Can't Build The - $! $(LIB_DIR)PDP10-$(ARCH).OLB Library On VAX. - $! -.ENDIF - -$(LIB_DIR)PDP11-$(ARCH).OLB : $(PDP11_SOURCE) - $! - $! Building The $(PDP11_LIB) Library. - $! - $(CC)$(PDP11_OPTIONS)/OBJECT=$(PDP11_DIR) - - $(PDP11_SOURCE) - $ IF (F$SEARCH("$(PDP11_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP11_LIB) - $ LIBRARY/REPLACE $(PDP11_LIB) $(PDP11_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP11_DIR)*.OBJ;* - -$(LIB_DIR)PDP15-$(ARCH).OLB : $(PDP18B_SOURCE) - $! - $! Building The $(PDP15_LIB) Library. - $! - $ $(CC)$(PDP15_OPTIONS)/OBJECT=$(PDP18B_DIR) - - $(PDP18B_SOURCE) - $ IF (F$SEARCH("$(PDP15_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP15_LIB) - $ LIBRARY/REPLACE $(PDP15_LIB) $(PDP18B_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* - -$(LIB_DIR)S3-$(ARCH).OLB : $(S3_SOURCE) - $! - $! Building The $(S3_LIB) Library. - $! - $ $(CC)$(S3_OPTIONS)/OBJECT=$(S3_DIR) $(S3_SOURCE) - $ IF (F$SEARCH("$(S3_LIB)").EQS."") THEN - - LIBRARY/CREATE $(S3_LIB) - $ LIBRARY/REPLACE $(S3_LIB) $(S3_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(S3_DIR)*.OBJ;* - -$(LIB_DIR)SDS-$(ARCH).OLB : $(SDS_SOURCE) - $! - $! Building The $(SDS_LIB) Library. - $! - $ $(CC)$(SDS_OPTIONS)/OBJECT=$(SDS_DIR) - - $(SDS_SOURCE) - $ IF (F$SEARCH("$(SDS_LIB)").EQS."") THEN - - LIBRARY/CREATE $(SDS_LIB) - $ LIBRARY/REPLACE $(SDS_LIB) $(SDS_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(SDS_DIR)*.OBJ;* - -# -# If On Alpha, Build The VAX Library. -# -$(LIB_DIR)VAX-$(ARCH).OLB : $(VAX_SOURCE) - $! - $! Building The $(VAX_LIB) Library. - $! - $ $(CC)$(VAX_OPTIONS)/OBJECT=$(VAX_DIR) - - $(VAX_SOURCE) - $ IF (F$SEARCH("$(VAX_LIB)").EQS."") THEN - - LIBRARY/CREATE $(VAX_LIB) - $ LIBRARY/REPLACE $(VAX_LIB) $(VAX_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(VAX_DIR)*.OBJ;* - -# -# Individual Simulator Builds. -# -ALTAIR : $(SIMH_LIB) $(ALTAIR_LIB) - $! - $! Building The $(BIN_DIR)ALTAIR-$(ARCH).EXE Simulator. - $! - $ $(CC)$(ALTAIR_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ALTAIR-$(ARCH).EXE - - SCP.OBJ,$(ALTAIR_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -ALTAIRZ80 : $(SIMH_LIB) $(ALTAIRZ80_LIB) - $! - $! Building The $(BIN_DIR)ALTAIRZ80-$(ARCH).EXE Simulator. - $! - $ $(CC)$(ALTAIRZ80_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ALTAIRZ80-$(ARCH).EXE - - SCP.OBJ,$(ALTAIRZ80_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -ECLIPSE : $(SIMH_LIB) $(ECLIPSE_LIB) - $! - $! Building The $(BIN_DIR)ECLPISE-$(ARCH).EXE Simulator. - $! - $ $(CC)$(ECLIPSE_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ECLIPSE-$(ARCH).EXE - - SCP.OBJ,$(ECLIPSE_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -GRI : $(SIMH_LIB) $(GRI_LIB) - $! - $! Building The $(BIN_DIR)GRI-$(ARCH).EXE Simulator. - $! - $ $(CC)$(GRI_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)GRI-$(ARCH).EXE - - SCP.OBJ,$(GRI_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -H316 : $(SIMH_LIB) $(H316_LIB) - $! - $! Building The $(BIN_DIR)H316-$(ARCH).EXE Simulator. - $! - $ $(CC)$(H316_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)H316-$(ARCH).EXE - - SCP.OBJ,$(H316_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -HP2100 : $(SIMH_LIB) $(HP2100_LIB) - $! - $! Building The $(BIN_DIR)HP2100-$(ARCH).EXE Simulator. - $! - $ $(CC)$(HP2100_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)HP2100-$(ARCH).EXE - - SCP.OBJ,$(HP2100_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -I1401 : $(SIMH_LIB) $(I1401_LIB) - $! - $! Building The $(BIN_DIR)I1401-$(ARCH).EXE Simulator. - $! - $ $(CC)$(I1401_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)I1401-$(ARCH).EXE - - SCP.OBJ,$(I1401_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -I1620 : $(SIMH_LIB) $(I1620_LIB) - $! - $! Building The $(BIN_DIR)I1620-$(ARCH).EXE Simulator. - $! - $ $(CC)$(I1620_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)I1620-$(ARCH).EXE - - SCP.OBJ,$(I1620_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -IBM1130 : $(SIMH_LIB) $(IBM1130_LIB) - $! - $! Building The $(BIN_DIR)IBM1130-$(ARCH).EXE Simulator. - $! - $ $(CC)$(IBM1130_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)IBM1130-$(ARCH).EXE - - SCP.OBJ,$(IBM1130_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -ID16 : $(SIMH_LIB) $(ID16_LIB) - $! - $! Building The $(BIN_DIR)ID16-$(ARCH).EXE Simulator. - $! - $ $(CC)$(ID16_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ID16-$(ARCH).EXE - - SCP.OBJ,$(ID16_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -ID32 : $(SIMH_LIB) $(ID32_LIB) - $! - $! Building The $(BIN_DIR)ID32-$(ARCH).EXE Simulator. - $! - $ $(CC)$(ID32_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ID32-$(ARCH).EXE - - SCP.OBJ,$(ID32_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -NOVA : $(SIMH_LIB) $(NOVA_LIB) - $! - $! Building The $(BIN_DIR)NOVA-$(ARCH).EXE Simulator. - $! - $ $(CC)$(NOVA_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)NOVA-$(ARCH).EXE - - SCP.OBJ,$(NOVA_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP1 : $(SIMH_LIB) $(PDP1_LIB) - $! - $! Building The $(BIN_DIR)PDP1-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP1_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP1-$(ARCH).EXE - - SCP.OBJ,$(PDP1_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP4 : $(SIMH_LIB) $(PDP4_LIB) - $! - $! Building The $(BIN_DIR)PDP4-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP4_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP4-$(ARCH).EXE - - SCP.OBJ,$(PDP4_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP7 : $(SIMH_LIB) $(PDP7_LIB) - $! - $! Building The $(BIN_DIR)PDP7-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP7_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP7-$(ARCH).EXE - - SCP.OBJ,$(PDP7_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP8 : $(SIMH_LIB) $(PDP8_LIB) - $! - $! Building The $(BIN_DIR)PDP8-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP8_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP8-$(ARCH).EXE - - SCP.OBJ,$(PDP8_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP9 : $(SIMH_LIB) $(PDP9_LIB) - $! - $! Building The $(BIN_DIR)PDP9-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP9_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP9-$(ARCH).EXE - - SCP.OBJ,$(PDP9_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -# -# If On Alpha, Build The PDP-10 Simulator. -# -.IFDEF __ALPHA__ -PDP10 : $(SIMH_LIB) $(PDP10_LIB) - $! - $! Building The $(BIN_DIR)PDP10-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP10_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP10-$(ARCH).EXE - - SCP.OBJ,$(PDP10_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* -.ELSE -# -# Else We Are On VAX And Tell The User We Can't Build On VAX -# Due To The Use Of INT64. -# -PDP10 : - $! - $! Sorry, Can't Build $(BIN_DIR)PDP10-$(ARCH).EXE Simulator - $! Because It Requires The Use Of INT64. - $! -.ENDIF - -PDP11 : $(SIMH_LIB) $(PDP11_LIB) - $! - $! Building The $(BIN_DIR)PDP11-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP11_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP11-$(ARCH).EXE - - SCP.OBJ,$(PDP11_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP15 : $(SIMH_LIB) $(PDP15_LIB) - $! - $! Building The $(BIN_DIR)PDP15-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP15_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP15-$(ARCH).EXE - - SCP.OBJ,$(PDP15_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -S3 : $(SIMH_LIB) $(S3_LIB) - $! - $! Building The $(BIN_DIR)S3-$(ARCH).EXE Simulator. - $! - $ $(CC)$(S3_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)S3-$(ARCH).EXE - - SCP.OBJ,$(S3_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -SDS : $(SIMH_LIB) $(SDS_LIB) - $! - $! Building The $(BIN_DIR)SDS-$(ARCH).EXE Simulator. - $! - $ $(CC)$(SDS_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)SDS-$(ARCH).EXE - - SCP.OBJ,$(SDS_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -VAX : $(SIMH_LIB) $(VAX_LIB) - $! - $! Building The $(BIN_DIR)VAX-$(ARCH).EXE Simulator. - $! - $ $(CC)$(VAX_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)VAX-$(ARCH).EXE - - SCP.OBJ,$(VAX_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* diff --git a/makefile b/makefile deleted file mode 100644 index f3c30c92..00000000 --- a/makefile +++ /dev/null @@ -1,340 +0,0 @@ -# CC Command -# -# Note: -O2 is sometimes broken in GCC when setjump/longjump is being -# used. Try -O2 only with released simulators. -# -ifeq ($(WIN32),) -#Unix Environments -CC = gcc -O2 -lm -I . -#CC = gcc -O2 -g -lm -I . -ifeq ($(USE_NETWORK),) -else -NETWORK_OPT = -DUSE_NETWORK -lpcap -endif -else -#Win32 Environments -LDFLAGS = -lm -lwsock32 -CC = gcc -O0 -I. -EXE = .exe -ifeq ($(USE_NETWORK),) -else -NETWORK_OPT = -DUSE_NETWORK -lwpcap -lpacket -endif -endif - - -# -# Common Libraries -# -BIN = BIN/ -SIM = scp.c scp_tty.c sim_sock.c sim_tmxr.c sim_ether.c sim_tape.c - - - -# -# Emulator source files and compile time options -# -PDP1D = PDP1/ -PDP1 = ${PDP1D}pdp1_lp.c ${PDP1D}pdp1_cpu.c ${PDP1D}pdp1_stddev.c \ - ${PDP1D}pdp1_sys.c ${PDP1D}pdp1_dt.c ${PDP1D}pdp1_drm.c -PDP1_OPT = -I ${PDP1D} - - -NOVAD = NOVA/ -NOVA = ${NOVAD}nova_sys.c ${NOVAD}nova_cpu.c ${NOVAD}nova_dkp.c \ - ${NOVAD}nova_dsk.c ${NOVAD}nova_lp.c ${NOVAD}nova_mta.c \ - ${NOVAD}nova_plt.c ${NOVAD}nova_pt.c ${NOVAD}nova_clk.c \ - ${NOVAD}nova_tt.c ${NOVAD}nova_tt1.c -NOVA_OPT = -I ${NOVAD} - - - -ECLIPSE = ${NOVAD}eclipse_cpu.c ${NOVAD}eclipse_tt.c ${NOVAD}nova_sys.c \ - ${NOVAD}nova_dkp.c ${NOVAD}nova_dsk.c ${NOVAD}nova_lp.c \ - ${NOVAD}nova_mta.c ${NOVAD}nova_plt.c ${NOVAD}nova_pt.c \ - ${NOVAD}nova_clk.c ${NOVAD}nova_tt1.c -ECLIPSE_OPT = -I ${NOVAD} -DECLIPSE - - - -PDP18BD = PDP18B/ -PDP18B = ${PDP18BD}pdp18b_dt.c ${PDP18BD}pdp18b_drm.c ${PDP18BD}pdp18b_cpu.c \ - ${PDP18BD}pdp18b_lp.c ${PDP18BD}pdp18b_mt.c ${PDP18BD}pdp18b_rf.c \ - ${PDP18BD}pdp18b_rp.c ${PDP18BD}pdp18b_stddev.c ${PDP18BD}pdp18b_sys.c \ - ${PDP18BD}pdp18b_rb.c ${PDP18BD}pdp18b_tt1.c ${PDP18BD}pdp18b_fpp.c -PDP4_OPT = -DPDP4 -I ${PDP18BD} -PDP7_OPT = -DPDP7 -I ${PDP18BD} -PDP9_OPT = -DPDP9 -I ${PDP18BD} -PDP15_OPT = -DPDP15 -I ${PDP18BD} - - - -PDP11D = PDP11/ -PDP11 = ${PDP11D}pdp11_fp.c ${PDP11D}pdp11_cpu.c ${PDP11D}pdp11_dz.c \ - ${PDP11D}pdp11_cis.c ${PDP11D}pdp11_lp.c ${PDP11D}pdp11_rk.c \ - ${PDP11D}pdp11_rl.c ${PDP11D}pdp11_rp.c ${PDP11D}pdp11_rx.c \ - ${PDP11D}pdp11_stddev.c ${PDP11D}pdp11_sys.c ${PDP11D}pdp11_tc.c \ - ${PDP11D}pdp11_tm.c ${PDP11D}pdp11_ts.c ${PDP11D}pdp11_io.c \ - ${PDP11D}pdp11_rq.c ${PDP11D}pdp11_tq.c ${PDP11D}pdp11_pclk.c \ - ${PDP11D}pdp11_ry.c ${PDP11D}pdp11_pt.c ${PDP11D}pdp11_hk.c \ - ${PDP11D}pdp11_xq.c ${PDP11D}pdp11_xu.c -PDP11_OPT = -DVM_PDP11 -I ${PDP11D} ${NETWORK_OPT} - - - -VAXD = VAX/ -VAX = ${VAXD}vax_cpu1.c ${VAXD}vax_cpu.c ${VAXD}vax_fpa.c ${VAXD}vax_io.c \ - ${VAXD}vax_mmu.c ${VAXD}vax_stddev.c ${VAXD}vax_sys.c \ - ${VAXD}vax_sysdev.c \ - ${PDP11D}pdp11_rl.c ${PDP11D}pdp11_rq.c ${PDP11D}pdp11_ts.c \ - ${PDP11D}pdp11_dz.c ${PDP11D}pdp11_lp.c ${PDP11D}pdp11_tq.c \ - ${PDP11D}pdp11_pt.c ${PDP11D}pdp11_xq.c -VAX_OPT = -DVM_VAX -DUSE_INT64 -I ${VAXD} -I ${PDP11D} ${NETWORK_OPT} - - - -PDP10D = PDP10/ -PDP10 = ${PDP10D}pdp10_fe.c ${PDP11D}pdp11_dz.c ${PDP10D}pdp10_cpu.c \ - ${PDP10D}pdp10_ksio.c ${PDP10D}pdp10_lp20.c ${PDP10D}pdp10_mdfp.c \ - ${PDP10D}pdp10_pag.c ${PDP10D}pdp10_rp.c ${PDP10D}pdp10_sys.c \ - ${PDP10D}pdp10_tim.c ${PDP10D}pdp10_tu.c ${PDP10D}pdp10_xtnd.c \ - ${PDP11D}pdp11_pt.c ${PDP11D}pdp11_ry.c ${PDP11D}pdp11_xu.c -PDP10_OPT = -DVM_PDP10 -DUSE_INT64 -I ${PDP10D} -I ${PDP11D} -I ${VAXD} - - - -PDP8D = PDP8/ -PDP8 = ${PDP8D}pdp8_cpu.c ${PDP8D}pdp8_clk.c ${PDP8D}pdp8_df.c \ - ${PDP8D}pdp8_dt.c ${PDP8D}pdp8_lp.c ${PDP8D}pdp8_mt.c \ - ${PDP8D}pdp8_pt.c ${PDP8D}pdp8_rf.c ${PDP8D}pdp8_rk.c \ - ${PDP8D}pdp8_rx.c ${PDP8D}pdp8_sys.c ${PDP8D}pdp8_tt.c \ - ${PDP8D}pdp8_ttx.c ${PDP8D}pdp8_rl.c -PDP8_OPT = -I ${PDP8D} - - - -H316D = H316/ -H316 = ${H316D}h316_stddev.c ${H316D}h316_lp.c ${H316D}h316_cpu.c \ - ${H316D}h316_sys.c -H316_OPT = -I ${H316D} - - - -HP2100D = HP2100/ -HP2100 = ${HP2100D}hp2100_stddev.c ${HP2100D}hp2100_dp.c ${HP2100D}hp2100_dq.c \ - ${HP2100D}hp2100_dr.c ${HP2100D}hp2100_lps.c ${HP2100D}hp2100_ms.c \ - ${HP2100D}hp2100_mt.c ${HP2100D}hp2100_mux.c ${HP2100D}hp2100_cpu.c \ - ${HP2100D}hp2100_fp.c ${HP2100D}hp2100_sys.c ${HP2100D}hp2100_lpt.c \ - ${HP2100D}hp2100_ipl.c -HP2100_OPT = -I ${HP2100D} - - - -I1401D = I1401/ -I1401 = ${I1401D}i1401_lp.c ${I1401D}i1401_cpu.c ${I1401D}i1401_iq.c \ - ${I1401D}i1401_cd.c ${I1401D}i1401_mt.c ${I1401D}i1401_dp.c \ - ${I1401D}i1401_sys.c -I1401_OPT = -I ${I1401D} - - - -I1620D = I1620/ -I1620 = ${I1620D}i1620_cd.c ${I1620D}i1620_dp.c ${I1620D}i1620_pt.c \ - ${I1620D}i1620_tty.c ${I1620D}i1620_cpu.c ${I1620D}i1620_lp.c \ - ${I1620D}i1620_fp.c ${I1620D}i1620_sys.c -I1620_OPT = -I ${I1620D} - - - -IBM1130D = Ibm1130/ -IBM1130 = ${IBM1130D}ibm1130_cpu.c ${IBM1130D}ibm1130_cr.c \ - ${IBM1130D}ibm1130_disk.c ${IBM1130D}ibm1130_stddev.c \ - ${IBM1130D}ibm1130_sys.c ${IBM1130D}ibm1130_gdu.c \ - ${IBM1130D}ibm1130_gui.c ${IBM1130D}ibm1130_prt.c \ - ${IBM1130D}ibm1130_fmt.c -IBM1130_OPT = -I ${IBM1130D} - - - -ID16D = Interdata/ -ID16 = ${ID16D}id16_cpu.c ${ID16D}id16_sys.c ${ID16D}id_dp.c \ - ${ID16D}id_fd.c ${ID16D}id_fp.c ${ID16D}id_idc.c ${ID16D}id_io.c \ - ${ID16D}id_lp.c ${ID16D}id_mt.c ${ID16D}id_pas.c ${ID16D}id_pt.c \ - ${ID16D}id_tt.c ${ID16D}id_uvc.c ${ID16D}id16_dboot.c ${ID16D}id_ttp.c -ID16_OPT = -I ${ID16D} - - - -ID32D = Interdata/ -ID32 = ${ID32D}id32_cpu.c ${ID32D}id32_sys.c ${ID32D}id_dp.c \ - ${ID32D}id_fd.c ${ID32D}id_fp.c ${ID32D}id_idc.c ${ID32D}id_io.c \ - ${ID32D}id_lp.c ${ID32D}id_mt.c ${ID32D}id_pas.c ${ID32D}id_pt.c \ - ${ID32D}id_tt.c ${ID32D}id_uvc.c ${ID32D}id32_dboot.c ${ID32D}id_ttp.c -ID32_OPT = -I ${ID32D} - - - -S3D = S3/ -S3 = ${S3D}s3_cd.c ${S3D}s3_cpu.c ${S3D}s3_disk.c ${S3D}s3_lp.c \ - ${S3D}s3_pkb.c ${S3D}s3_sys.c -S3_OPT = -I ${S3D} - - - -ALTAIRD = ALTAIR/ -ALTAIR = ${ALTAIRD}altair_sio.c ${ALTAIRD}altair_cpu.c ${ALTAIRD}altair_dsk.c \ - ${ALTAIRD}altair_sys.c -ALTAIR_OPT = -I ${ALTAIRD} - - - -ALTAIRZ80D = AltairZ80/ -ALTAIRZ80 = ${ALTAIRZ80D}altairz80_cpu.c ${ALTAIRZ80D}altairz80_dsk.c \ - ${ALTAIRZ80D}altairz80_sio.c ${ALTAIRZ80D}altairz80_sys.c \ - ${ALTAIRZ80D}altairz80_hdsk.c -ALTAIRZ80_OPT = -I ${ALTAIRZ80D} - - - -GRID = GRI/ -GRI = ${GRID}gri_cpu.c ${GRID}gri_stddev.c ${GRID}gri_sys.c -GRI_OPT = -I ${GRID} - - - -SDSD = SDS/ -SDS = ${SDSD}sds_cpu.c ${SDSD}sds_drm.c ${SDSD}sds_dsk.c ${SDSD}sds_io.c \ - ${SDSD}sds_lp.c ${SDSD}sds_mt.c ${SDSD}sds_mux.c ${SDSD}sds_rad.c \ - ${SDSD}sds_stddev.c ${SDSD}sds_sys.c -SDS_OPT = -I ${SDSD} - - - -# -# Build everything -# -ALL = ${BIN}pdp1${EXE} ${BIN}pdp4${EXE} ${BIN}pdp7${EXE} ${BIN}pdp8${EXE} \ - ${BIN}pdp9${EXE} ${BIN}pdp15${EXE} ${BIN}pdp11${EXE} ${BIN}pdp10${EXE} \ - ${BIN}vax${EXE} ${BIN}nova${EXE} ${BIN}eclipse${EXE} ${BIN}h316${EXE} \ - ${BIN}hp2100${EXE} ${BIN}i1401${EXE} ${BIN}i1620${EXE} ${BIN}s3${EXE} \ - ${BIN}altair${EXE} ${BIN}altairz80${EXE} ${BIN}gri${EXE} \ - ${BIN}i1620${EXE} ${BIN}ibm1130${EXE} ${BIN}id16${EXE} \ - ${BIN}id32${EXE} ${BIN}sds${EXE} - -all : ${ALL} - -clean : -ifeq ($(WIN32),) - ${RM} ${ALL} -else - if exist BIN\*.exe del /q BIN\*.exe -endif -# -# Individual builds -# -${BIN}pdp1${EXE} : ${PDP1} ${SIM} - ${CC} ${PDP1} ${SIM} ${PDP1_OPT} -o $@ ${LDFLAGS} - - - -${BIN}pdp4${EXE} : ${PDP18B} ${SIM} - ${CC} ${PDP18B} ${SIM} ${PDP4_OPT} -o $@ ${LDFLAGS} - - - -${BIN}pdp7${EXE} : ${PDP18B} ${SIM} - ${CC} ${PDP18B} ${SIM} ${PDP7_OPT} -o $@ ${LDFLAGS} - - - -${BIN}pdp8${EXE} : ${PDP8} ${SIM} - ${CC} ${PDP8} ${SIM} ${PDP8_OPT} -o $@ ${LDFLAGS} - - - -${BIN}pdp9${EXE} : ${PDP18B} ${SIM} - ${CC} ${PDP18B} ${SIM} ${PDP9_OPT} -o $@ ${LDFLAGS} - - - -${BIN}pdp15${EXE} : ${PDP18B} ${SIM} - ${CC} ${PDP18B} ${SIM} ${PDP15_OPT} -o $@ ${LDFLAGS} - - - -${BIN}pdp10${EXE} : ${PDP10} ${SIM} - ${CC} ${PDP10} ${SIM} ${PDP10_OPT} -o $@ ${LDFLAGS} - - - -${BIN}pdp11${EXE} : ${PDP11} ${SIM} - ${CC} ${PDP11} ${SIM} ${PDP11_OPT} -o $@ ${LDFLAGS} - - - -${BIN}vax${EXE} : ${VAX} ${SIM} - ${CC} ${VAX} ${SIM} ${VAX_OPT} -o $@ ${LDFLAGS} - - - -${BIN}nova${EXE} : ${NOVA} ${SIM} - ${CC} ${NOVA} ${SIM} ${NOVA_OPT} -o $@ ${LDFLAGS} - - - -${BIN}eclipse${EXE} : ${ECLIPSE} ${SIM} - ${CC} ${ECLIPSE} ${SIM} ${ECLIPSE_OPT} -o $@ ${LDFLAGS} - - - -${BIN}h316${EXE} : ${H316} ${SIM} - ${CC} ${H316} ${SIM} ${H316_OPT} -o $@ ${LDFLAGS} - - - -${BIN}hp2100${EXE} : ${HP2100} ${SIM} - ${CC} ${HP2100} ${SIM} ${HP2100_OPT} -o $@ ${LDFLAGS} - - - -${BIN}i1401${EXE} : ${I1401} ${SIM} - ${CC} ${I1401} ${SIM} ${I1401_OPT} -o $@ ${LDFLAGS} - - - -${BIN}i1620${EXE} : ${I1620} ${SIM} - ${CC} ${I1620} ${SIM} ${I1620_OPT} -o $@ ${LDFLAGS} - - -${BIN}ibm1130${EXE} : ${IBM1130} - ${CC} ${IBM1130} ${SIM} ${IBM1130_OPT} -o $@ ${LDFLAGS} - - -${BIN}s3${EXE} : ${S3} ${SIM} - ${CC} ${S3} ${SIM} ${S3_OPT} -o $@ ${LDFLAGS} - - -${BIN}altair${EXE} : ${ALTAIR} ${SIM} - ${CC} ${ALTAIR} ${SIM} ${ALTAIR_OPT} -o $@ ${LDFLAGS} - - -${BIN}altairz80${EXE} : ${ALTAIRZ80} ${SIM} - ${CC} ${ALTAIRZ80} ${SIM} ${ALTAIRZ80_OPT} -o $@ ${LDFLAGS} - - -${BIN}gri${EXE} : ${GRI} ${SIM} - ${CC} ${GRI} ${SIM} ${GRI_OPT} -o $@ ${LDFLAGS} - - -${BIN}id16${EXE} : ${ID16} ${SIM} - ${CC} ${ID16} ${SIM} ${ID16_OPT} -o $@ ${LDFLAGS} - - -${BIN}id32${EXE} : ${ID32} ${SIM} - ${CC} ${ID32} ${SIM} ${ID32_OPT} -o $@ ${LDFLAGS} - - -${BIN}sds${EXE} : ${SDS} ${SIM} - ${CC} ${SDS} ${SIM} ${SDS_OPT} -o $@ ${LDFLAGS} - - diff --git a/scp.c b/scp.c deleted file mode 100644 index 52e5bdeb..00000000 --- a/scp.c +++ /dev/null @@ -1,3773 +0,0 @@ -/* scp.c: simulator control program - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 01-Sep-03 RMS Fixed end-of-file problem in dep, idep - Fixed error on trailing spaces in dep, idep - 15-Jul-03 RMS Removed unnecessary test in reset_all - 15-Jun-03 RMS Added register flag REG_VMIO - 25-Apr-03 RMS Added extended address support (V3.0) - Fixed bug in SAVE (found by Peter Schorn) - Added u5, u6 fields - Added logical name support - 03-Mar-03 RMS Added sim_fsize - 27-Feb-03 RMS Fixed bug in multiword deposits to files - 08-Feb-03 RMS Changed sim_os_sleep to void, match_ext to char* - Added multiple actions, .ini file support - Added multiple switch evaluations per line - 07-Feb-03 RMS Added VMS support for ! (from Mark Pizzolato) - 01-Feb-03 RMS Added breakpoint table extension, actions - 14-Jan-03 RMS Added missing function prototypes - 10-Jan-03 RMS Added attach/restore flag, dynamic memory size support, - case sensitive SET options - 22-Dec-02 RMS Added ! (OS command) feature (from Mark Pizzolato) - 17-Dec-02 RMS Added get_ipaddr - 02-Dec-02 RMS Added EValuate command - 16-Nov-02 RMS Fixed bug in register name match algorithm - 13-Oct-02 RMS Fixed Borland compiler warnings (found by Hans Pufal) - 05-Oct-02 RMS Fixed bugs in set_logon, ssh_break (found by David Hittner) - Added support for fixed buffer devices - Added support for Telnet console, removed VT support - Added help - Added VMS file optimizations (from Robert Alan Byer) - Added quiet mode, DO with parameters, GUI interface, - extensible commands (from Brian Knittel) - Added device enable/disable commands - 14-Jul-02 RMS Fixed exit bug in do, added -v switch (from Brian Knittel) - 17-May-02 RMS Fixed bug in fxread/fxwrite error usage (found by - Norm Lastovic) - 02-May-02 RMS Added VT emulation interface, changed {NO}LOG to SET {NO}LOG - 22-Apr-02 RMS Fixed laptop sleep problem in clock calibration, added - magtape record length error (found by Jonathan Engdahl) - 26-Feb-02 RMS Fixed initialization bugs in do_cmd, get_aval - (found by Brian Knittel) - 10-Feb-02 RMS Fixed problem in clock calibration - 06-Jan-02 RMS Moved device enable/disable to simulators - 30-Dec-01 RMS Generalized timer packaged, added circular arrays - 19-Dec-01 RMS Fixed DO command bug (found by John Dundas) - 07-Dec-01 RMS Implemented breakpoint package - 05-Dec-01 RMS Fixed bug in universal register logic - 03-Dec-01 RMS Added read-only units, extended SET/SHOW, universal registers - 24-Nov-01 RMS Added unit-based registers - 16-Nov-01 RMS Added DO command - 28-Oct-01 RMS Added relative range addressing - 08-Oct-01 RMS Added SHOW VERSION - 30-Sep-01 RMS Relaxed attach test in BOOT - 27-Sep-01 RMS Added queue count routine, fixed typo in ex/mod - 17-Sep-01 RMS Removed multiple console support - 07-Sep-01 RMS Removed conditional externs on function prototypes - Added special modifier print - 31-Aug-01 RMS Changed int64 to t_int64 for Windoze (V2.7) - 18-Jul-01 RMS Minor changes for Macintosh port - 12-Jun-01 RMS Fixed bug in big-endian I/O (found by Dave Conroy) - 27-May-01 RMS Added multiple console support - 16-May-01 RMS Added logging - 15-May-01 RMS Added features from Tim Litt - 12-May-01 RMS Fixed missing return in disable_cmd - 25-Mar-01 RMS Added ENABLE/DISABLE - 14-Mar-01 RMS Revised LOAD/DUMP interface (again) - 05-Mar-01 RMS Added clock calibration support - 05-Feb-01 RMS Fixed bug, DETACH buffered unit with hwmark = 0 - 04-Feb-01 RMS Fixed bug, RESTORE not using device's attach routine - 21-Jan-01 RMS Added relative time - 22-Dec-00 RMS Fixed find_device for devices ending in numbers - 08-Dec-00 RMS V2.5a changes - 30-Oct-00 RMS Added output file option to examine - 11-Jul-99 RMS V2.5 changes - 13-Apr-99 RMS Fixed handling of 32b addresses - 04-Oct-98 RMS V2.4 changes - 20-Aug-98 RMS Added radix commands - 05-Jun-98 RMS Fixed bug in ^D handling for UNIX - 10-Apr-98 RMS Added switches to all commands - 26-Oct-97 RMS Added search capability - 25-Jan-97 RMS Revised data types - 23-Jan-97 RMS Added bi-endian I/O - 06-Sep-96 RMS Fixed bug in variable length IEXAMINE - 16-Jun-96 RMS Changed interface to parse/print_sym - 06-Apr-96 RMS Added error checking in reset all - 07-Jan-96 RMS Added register buffers in save/restore - 11-Dec-95 RMS Fixed ordering bug in save/restore - 22-May-95 RMS Added symbolic input - 13-Apr-95 RMS Added symbolic printouts -*/ - -/* Macros and data structures */ - -#include "sim_defs.h" -#include "sim_rev.h" -#include "sim_sock.h" -#include "sim_tmxr.h" -#include -#include - -#define EX_D 0 /* deposit */ -#define EX_E 1 /* examine */ -#define EX_I 2 /* interactive */ -#define SCH_OR 0 /* search logicals */ -#define SCH_AND 1 -#define SCH_XOR 2 -#define SCH_E 0 /* search booleans */ -#define SCH_N 1 -#define SCH_G 2 -#define SCH_L 3 -#define SCH_EE 4 -#define SCH_NE 5 -#define SCH_GE 6 -#define SCH_LE 7 -#define SSH_ST 0 /* set */ -#define SSH_SH 1 /* show */ -#define SSH_CL 2 /* clear */ -#define RU_RUN 0 /* run */ -#define RU_GO 1 /* go */ -#define RU_STEP 2 /* step */ -#define RU_CONT 3 /* continue */ -#define RU_BOOT 4 /* boot */ - -#define SRBSIZ 1024 /* save/restore buffer */ -#define SIM_BRK_INILNT 4096 /* bpt tbl length */ -#define SIM_BRK_ALLTYP 0xFFFFFFFF -#define SIM_NTIMERS 8 /* # timers */ -#define SIM_TMAX 500 /* max timer makeup */ -#define UPDATE_SIM_TIME(x) sim_time = sim_time + (x - sim_interval); \ - sim_rtime = sim_rtime + ((uint32) (x - sim_interval)); \ - x = sim_interval - -#define print_val(a,b,c,d) fprint_val (stdout, (a), (b), (c), (d)) -#define SZ_D(dp) (size_map[((dp)->dwidth + CHAR_BIT - 1) / CHAR_BIT]) -#define SZ_R(rp) \ - (size_map[((rp)->width + (rp)->offset + CHAR_BIT - 1) / CHAR_BIT]) -#if defined (t_int64) -#define SZ_LOAD(sz,v,mb,j) \ - if (sz == sizeof (uint8)) v = *(((uint8 *) mb) + ((uint32) j)); \ - else if (sz == sizeof (uint16)) v = *(((uint16 *) mb) + ((uint32) j)); \ - else if (sz == sizeof (uint32)) v = *(((uint32 *) mb) + ((uint32) j)); \ - else v = *(((t_uint64 *) mb) + ((uint32) j)); -#define SZ_STORE(sz,v,mb,j) \ - if (sz == sizeof (uint8)) *(((uint8 *) mb) + j) = (uint8) v; \ - else if (sz == sizeof (uint16)) *(((uint16 *) mb) + ((uint32) j)) = (uint16) v; \ - else if (sz == sizeof (uint32)) *(((uint32 *) mb) + ((uint32) j)) = (uint32) v; \ - else *(((t_uint64 *) mb) + ((uint32) j)) = v; -#else -#define SZ_LOAD(sz,v,mb,j) \ - if (sz == sizeof (uint8)) v = *(((uint8 *) mb) + ((uint32) j)); \ - else if (sz == sizeof (uint16)) v = *(((uint16 *) mb) + ((uint32) j)); \ - else v = *(((uint32 *) mb) + ((uint32) j)); -#define SZ_STORE(sz,v,mb,j) \ - if (sz == sizeof (uint8)) *(((uint8 *) mb) + ((uint32) j)) = (uint8) v; \ - else if (sz == sizeof (uint16)) *(((uint16 *) mb) + ((uint32) j)) = (uint16) v; \ - else *(((uint32 *) mb) + ((uint32) j)) = v; -#endif -#define GET_SWITCHES(cp) \ - if ((cp = get_sim_sw (cp)) == NULL) return SCPE_INVSW -#define GET_RADIX(val,dft) \ - if (sim_switches & SWMASK ('O')) val = 8; \ - else if (sim_switches & SWMASK ('D')) val = 10; \ - else if (sim_switches & SWMASK ('H')) val = 16; \ - else val = dft; - -#if defined(VMS) -#define FOPEN(file_spec, mode) fopen (file_spec, mode, "ALQ=32", "DEQ=4096", \ - "MBF=6", "MBC=127", "FOP=cbt,tef", "ROP=rah,wbh", "CTX=stm") -#else -#define FOPEN(file_spec, mode) fopen (file_spec, mode) -#endif - -/* VM interface */ - -extern char sim_name[]; -extern DEVICE *sim_devices[]; -extern REG *sim_PC; -extern char *sim_stop_messages[]; -extern t_stat sim_instr (void); -extern t_stat sim_load (FILE *ptr, char *cptr, char *fnam, int32 flag); -extern int32 sim_emax; -extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); -extern t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, - int32 sw); - -/* The per-simulator init routine is a weak global that defaults to NULL - The other per-simulator pointers can be overrriden by the init routine */ - -void (*sim_vm_init) (void); -char* (*sim_vm_read) (char *ptr, int32 size, FILE *stream) = NULL; -void (*sim_vm_post) (t_bool from_scp) = NULL; -CTAB *sim_vm_cmd = NULL; - -/* External routines */ - -extern t_stat ttinit (void); -extern t_stat ttrunstate (void); -extern t_stat ttcmdstate (void); -extern t_stat ttclose (void); -extern t_stat sim_os_poll_kbd (void); -extern t_stat sim_os_putchar (int32 out); -extern uint32 sim_os_msec (void); - -/* Prototypes */ - -/* Command processors */ - -t_stat reset_cmd (int32 flag, char *ptr); -t_stat exdep_cmd (int32 flag, char *ptr); -t_stat eval_cmd (int32 flag, char *ptr); -t_stat load_cmd (int32 flag, char *ptr); -t_stat run_cmd (int32 flag, char *ptr); -t_stat attach_cmd (int32 flag, char *ptr); -t_stat detach_cmd (int32 flag, char *ptr); -t_stat assign_cmd (int32 flag, char *ptr); -t_stat deassign_cmd (int32 flag, char *ptr); -t_stat save_cmd (int32 flag, char *ptr); -t_stat restore_cmd (int32 flag, char *ptr); -t_stat exit_cmd (int32 flag, char *ptr); -t_stat set_cmd (int32 flag, char *ptr); -t_stat show_cmd (int32 flag, char *ptr); -t_stat brk_cmd (int32 flag, char *ptr); -t_stat do_cmd (int32 flag, char *ptr); -t_stat help_cmd (int32 flag, char *ptr); -t_stat spawn_cmd (int32 flag, char *ptr); - -/* Set and show command processors */ - -t_stat set_telnet (int32 flg, char *cptr); -t_stat set_notelnet (int32 flg, char *cptr); -t_stat set_logon (int32 flag, char *cptr); -t_stat set_logoff (int32 flag, char *cptr); -t_stat set_radix (DEVICE *dptr, UNIT *uptr, int32 flag); -t_stat set_devenbdis (DEVICE *dptr, UNIT *uptr, int32 flag); -t_stat set_onoff (DEVICE *dptr, UNIT *uptr, int32 flag); -t_stat ssh_break (FILE *st, char *cptr, int32 flg); -t_stat show_config (FILE *st, int32 flag, char *cptr); -t_stat show_queue (FILE *st, int32 flag, char *cptr); -t_stat show_time (FILE *st, int32 flag, char *cptr); -t_stat show_mod_names (FILE *st, int32 flag, char *cptr); -t_stat show_log_names (FILE *st, int32 flag, char *cptr); -t_stat show_log (FILE *st, int32 flag, char *cptr); -t_stat show_telnet (FILE *st, int32 flag, char *cptr); -t_stat show_version (FILE *st, int32 flag, char *cptr); -t_stat show_break (FILE *st, int32 flag, char *cptr); -t_stat show_device (FILE *st, DEVICE *dptr, int32 flag); -t_stat show_unit (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag); -t_stat show_all_mods (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flg); -t_stat show_one_mod (FILE *st, DEVICE *dptr, UNIT *uptr, MTAB *mptr, int32 flag); -t_stat sim_check_console (int32 sec); -t_stat sim_save (FILE *sfile); -t_stat sim_rest (FILE *rfile); - -/* Breakpoint package */ - -t_stat sim_brk_init (void); -t_stat sim_brk_set (t_addr loc, int32 sw, int32 ncnt, char *act); -t_stat sim_brk_clr (t_addr loc, int32 sw); -t_stat sim_brk_clrall (int32 sw); -t_stat sim_brk_show (FILE *st, t_addr loc, int32 sw); -t_stat sim_brk_showall (FILE *st, int32 sw); -char *sim_brk_getact (char *buf, int32 size); -void sim_brk_clract (void); -void sim_brk_npc (void); -BRKTAB *sim_brk_new (t_addr loc); - -/* Commands support routines */ - -SCHTAB *get_search (char *cptr, DEVICE *dptr, SCHTAB *schptr); -int32 test_search (t_value val, SCHTAB *schptr); -char *get_glyph_gen (char *iptr, char *optr, char mchar, t_bool uc); -int32 get_switches (char *cptr); -char *get_sim_sw (char *cptr); -t_stat get_aval (t_addr addr, DEVICE *dptr, UNIT *uptr); -t_value get_rval (REG *rptr, uint32 idx); -void put_rval (REG *rptr, uint32 idx, t_value val); -t_value strtotv (char *inptr, char **endptr, uint32 radix); -void fprint_help (FILE *st); -void fprint_stopped (FILE *st, t_stat r); -void fprint_capac (FILE *st, DEVICE *dptr, UNIT *uptr); -char *read_line (char *ptr, int32 size, FILE *stream); -CTAB *find_ctab (CTAB *tab, char *gbuf); -C1TAB *find_c1tab (C1TAB *tab, char *gbuf); -CTAB *find_cmd (char *gbuf); -DEVICE *find_dev (char *ptr); -DEVICE *find_unit (char *ptr, UNIT **uptr); -REG *find_reg_glob (char *ptr, char **optr, DEVICE **gdptr); - -/* Forward references within commands */ - -t_bool restore_skip_val (FILE *rfile); -t_bool qdisable (DEVICE *dptr); -t_stat attach_err (UNIT *uptr, t_stat stat); -t_stat detach_all (int32 start_device, t_bool shutdown); -t_stat assign_device (DEVICE *dptr, char *cptr); -t_stat deassign_device (DEVICE *dptr); -t_stat exdep_reg_loop (FILE *ofile, SCHTAB *schptr, int32 flag, char *cptr, - REG *lowr, REG *highr, uint32 lows, uint32 highs); -t_stat ex_reg (FILE *ofile, t_value val, int32 flag, REG *rptr, uint32 idx); -t_stat dep_reg (int32 flag, char *cptr, REG *rptr, uint32 idx); -t_stat exdep_addr_loop (FILE *ofile, SCHTAB *schptr, int32 flag, char *cptr, - t_addr low, t_addr high, DEVICE *dptr, UNIT *uptr); -t_stat ex_addr (FILE *ofile, int32 flag, t_addr addr, DEVICE *dptr, UNIT *uptr); -t_stat dep_addr (int32 flag, char *cptr, t_addr addr, DEVICE *dptr, - UNIT *uptr, int32 dfltinc); -t_stat step_svc (UNIT *ptr); -void sub_args (char *instr, char *tmpbuf, int32 maxstr, int32 nargs, char *do_arg[]); - -/* Global data */ - -UNIT *sim_clock_queue = NULL; -int32 sim_interval = 0; -int32 sim_switches = 0; -int32 sim_is_running = 0; -uint32 sim_brk_summ = 0; -uint32 sim_brk_types = 0; -uint32 sim_brk_dflt = 0; -char *sim_brk_act = NULL; -BRKTAB *sim_brk_tab = NULL; -int32 sim_brk_ent = 0; -int32 sim_brk_lnt = 0; -int32 sim_brk_ins = 0; -t_bool sim_brk_pend = FALSE; -t_addr sim_brk_ploc = 0; -int32 sim_quiet = 0; -static double sim_time; -static uint32 sim_rtime; -static int32 noqueue_time; -volatile int32 stop_cpu = 0; -t_value *sim_eval = NULL; -int32 sim_end = 1; /* 1 = little */ -FILE *sim_log = NULL; /* log file */ -unsigned char sim_flip[FLIP_SIZE]; - -TMLN sim_con_ldsc = { 0 }; /* console line descr */ -TMXR sim_con_tmxr = { 1, 0, 0, &sim_con_ldsc }; /* console line mux */ -UNIT step_unit = { UDATA (&step_svc, 0, 0) }; - -/* Tables and strings */ - -const char save_vercur[] = "V3.0"; -const char save_ver210[] = "V2.10"; -const char save_ver26[] = "V2.6"; -const char *scp_error_messages[] = { - "Address space exceeded", - "Unit not attached", - "I/O error", - "Checksum error", - "Format error", - "Unit not attachable", - "File open error", - "Memory exhausted", - "Invalid argument", - "Step expired", - "Unknown command", - "Read only argument", - "Command not completed", - "Simulation stopped", - "Goodbye", - "Console input I/O error", - "Console output I/O error", - "End of file", - "Relocation error", - "No settable parameters", - "Unit already attached", - "Hardware timer error", - "SIGINT handler setup error", - "Console terminal setup error", - "Subscript out of range", - "Command not allowed", - "Unit disabled", - "Read only operation not allowed", - "Invalid switch", - "Missing value", - "Too few arguments", - "Too many arguments", - "Non-existent device", - "Non-existent unit", - "Non-existent register", - "Non-existent parameter", - "Nested DO commands", - "Internal error", - "Invalid magtape record length", - "Console Telnet connection lost", - "Console Telnet connection timed out" -}; - -const size_t size_map[] = { sizeof (int8), - sizeof (int8), sizeof (int16), sizeof (int32), sizeof (int32) -#if defined (t_int64) - , sizeof (t_int64), sizeof (t_int64), sizeof (t_int64), sizeof (t_int64) -#endif -}; - -const t_value width_mask[] = { 0, - 0x1, 0x3, 0x7, 0xF, - 0x1F, 0x3F, 0x7F, 0xFF, - 0x1FF, 0x3FF, 0x7FF, 0xFFF, - 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, - 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, - 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF, - 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, - 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF -#if defined (t_int64) - , 0x1FFFFFFFF, 0x3FFFFFFFF, 0x7FFFFFFFF, 0xFFFFFFFFF, - 0x1FFFFFFFFF, 0x3FFFFFFFFF, 0x7FFFFFFFFF, 0xFFFFFFFFFF, - 0x1FFFFFFFFFF, 0x3FFFFFFFFFF, 0x7FFFFFFFFFF, 0xFFFFFFFFFFF, - 0x1FFFFFFFFFFF, 0x3FFFFFFFFFFF, 0x7FFFFFFFFFFF, 0xFFFFFFFFFFFF, - 0x1FFFFFFFFFFFF, 0x3FFFFFFFFFFFF, 0x7FFFFFFFFFFFF, 0xFFFFFFFFFFFFF, - 0x1FFFFFFFFFFFFF, 0x3FFFFFFFFFFFFF, 0x7FFFFFFFFFFFFF, 0xFFFFFFFFFFFFFF, - 0x1FFFFFFFFFFFFFF, 0x3FFFFFFFFFFFFFF, - 0x7FFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFF, - 0x1FFFFFFFFFFFFFFF, 0x3FFFFFFFFFFFFFFF, - 0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF -#endif -}; - -static CTAB cmd_table[] = { - { "RESET", &reset_cmd, 0, - "r{eset} {ALL|} reset simulator\n" }, - { "EXAMINE", &exdep_cmd, EX_E, - "e{xamine} examine memory or registers\n" }, - { "IEXAMINE", &exdep_cmd, EX_E+EX_I, - "ie{xamine} interactive examine memory or registers\n" }, - { "DEPOSIT", &exdep_cmd, EX_D, - "d{eposit} deposit in memory or registers\n" }, - { "IDEPOSIT", &exdep_cmd, EX_D+EX_I, - "id{eposit} interactive deposit in memory or registers\n" }, - { "EVALUATE", &eval_cmd, 0, - "ev{aluate} evaluate symbolic expression\n" }, - { "RUN", &run_cmd, RU_RUN, - "ru{n} {new PC} reset and start simulation\n" }, - { "GO", &run_cmd, RU_GO, - "go {new PC} start simulation\n" }, - { "STEP", &run_cmd, RU_STEP, - "s{tep} {n} simulate n instructions\n" }, - { "CONT", &run_cmd, RU_CONT, - "c{ont} continue simulation\n" }, - { "BOOT", &run_cmd, RU_BOOT, - "b{oot} bootstrap unit\n" }, - { "BREAK", &brk_cmd, SSH_ST, - "br{eak} set breakpoints\n" }, - { "NOBREAK", &brk_cmd, SSH_CL, - "nobr{eak} clear breakpoints\n" }, - { "ATTACH", &attach_cmd, 0, - "at{tach} attach file to simulated unit\n" }, - { "DETACH", &detach_cmd, 0, - "det{ach} detach file from simulated unit\n" }, - { "ASSIGN", &assign_cmd, 0, - "as{sign} assign logical name for device\n" }, - { "DEASSIGN", &deassign_cmd, 0, - "dea{ssign} deassign logical name for device\n" }, - { "SAVE", &save_cmd, 0, - "sa{ve} save simulator to file\n" }, - { "RESTORE", &restore_cmd, 0, - "rest{ore}|ge{t} restore simulator from file\n" }, - { "GET", &restore_cmd, 0, NULL }, - { "LOAD", &load_cmd, 0, - "l{oad} {} load binary file\n" }, - { "DUMP", &load_cmd, 1, - "du(mp) {} dump binary file\n" }, - { "EXIT", &exit_cmd, 0, - "exi{t}|q{uit}|by{e} exit from simulation\n" }, - { "QUIT", &exit_cmd, 0, NULL }, - { "BYE", &exit_cmd, 0, NULL }, - { "SET", &set_cmd, 0, - "set log enable logging to file\n" - "set nolog disable logging\n" - "set telnet enable Telnet port for console\n" - "set notelnet disable Telnet for console\n" - "set OCT|DEC|HEX set device display radix\n" - "set ENABLED enable device\n" - "set DISABLED disable device\n" - "set ONLINE enable unit\n" - "set OFFLINE disable unit\n" - "set | set device/unit parameter\n" - }, - { "SHOW", &show_cmd, 0, - "sh{ow} br{eak} show breakpoints on address list\n" - "sh{ow} c{onfiguration} show configuration\n" - "sh{ow} d{evices} show devices\n" - "sh{ow} l{og} show log\n" - "sh{ow} m{odifiers} show modifiers\n" - "sh{ow} n{ames} show logical names\n" - "sh{ow} q{ueue} show event queue\n" - "sh{ow} te{lnet} show console Telnet status\n" - "sh{ow} ti{me} show simulated time\n" - "sh{ow} ve{rsion} show simulator version\n" - "sh{ow} | show device parameters\n" }, - { "DO", &do_cmd, 0, - "do {arg,arg...} process command file\n" }, - { "HELP", &help_cmd, 0, - "h{elp} type this message\n" - "h{elp} type help for command\n" }, - { "!", &spawn_cmd, 0, - "! execute local command interpreter\n" - "! execute local host command\n" }, - { NULL, NULL, 0 } }; - -/* Main command loop */ - -int main (int argc, char *argv[]) -{ -char cbuf[CBUFSIZE], gbuf[CBUFSIZE], *cptr; -int32 i, sw; -t_bool lookswitch; -t_stat stat; -CTAB *cmdp; -union {int32 i; char c[sizeof (int32)]; } end_test; - -#if defined (__MWERKS__) && defined (macintosh) -argc = ccommand (&argv); -#endif - -*cbuf = 0; /* init arg buffer */ -sim_switches = 0; /* init switches */ -lookswitch = TRUE; -for (i = 1; i < argc; i++) { /* loop thru args */ - if (argv[i] == NULL) continue; /* paranoia */ - if ((*argv[i] == '-') && lookswitch) { /* switch? */ - if ((sw = get_switches (argv[i])) < 0) { - fprintf (stderr, "Invalid switch %s\n", argv[i]); - return 0; } - sim_switches = sim_switches | sw; } - else { if ((strlen (argv[i]) + strlen (cbuf) + 1) >= CBUFSIZE) { - fprintf (stderr, "Argument string too long\n"); - return 0; } - if (*cbuf) strcat (cbuf, " "); /* concat args */ - strcat (cbuf, argv[i]); - lookswitch = FALSE; } /* no more switches */ - } /* end for */ -sim_quiet = sim_switches & SWMASK ('Q'); /* -q means quiet */ - -if (sim_vm_init != NULL) (*sim_vm_init)(); /* call once only */ -end_test.i = 1; /* test endian-ness */ -sim_end = end_test.c[0]; -stop_cpu = 0; -sim_interval = 0; -sim_time = sim_rtime = 0; -noqueue_time = 0; -sim_clock_queue = NULL; -sim_is_running = 0; -sim_log = NULL; -if (sim_emax <= 0) sim_emax = 1; - -if ((stat = ttinit ()) != SCPE_OK) { - fprintf (stderr, "Fatal terminal initialization error\n%s\n", - scp_error_messages[stat - SCPE_BASE]); - return 0; } -if ((sim_eval = calloc (sim_emax, sizeof (t_value))) == NULL) { - fprintf (stderr, "Unable to allocate examine buffer\n"); - return 0; }; -if ((stat = reset_all (0)) != SCPE_OK) { - fprintf (stderr, "Fatal simulator initialization error\n%s\n", - scp_error_messages[stat - SCPE_BASE]); - return 0; } -if ((stat = sim_brk_init ()) != SCPE_OK) { - fprintf (stderr, "Fatal breakpoint table initialization error\n%s\n", - scp_error_messages[stat - SCPE_BASE]); - return 0; } -if (!sim_quiet) { - printf ("\n"); - show_version (stdout, 0, NULL); } - -if (*cbuf) { /* cmd file arg? */ - stat = do_cmd (1, cbuf); /* proc cmd file */ - if (stat == SCPE_OPENERR) /* error? */ - fprintf (stderr, "Can't open file %s\n", cbuf); } -else if (*argv[0]) { /* sim name arg? */ - char nbuf[PATH_MAX + 7], *np; /* "path.ini" */ - nbuf[0] = '"'; /* starting " */ - strncpy (nbuf + 1, argv[0], PATH_MAX + 1); /* copy sim name */ - if (np = match_ext (nbuf, "EXE")) *np = 0; /* remove .exe */ - strcat (nbuf, ".ini\""); /* add .ini" */ - stat = do_cmd (1, nbuf); } /* proc cmd file */ - -while (stat != SCPE_EXIT) { /* in case exit */ - printf ("sim> "); /* prompt */ - if (cptr = sim_brk_getact (cbuf, CBUFSIZE)) /* pending action? */ - printf ("%s\n", cptr); /* echo */ - else if (sim_vm_read != NULL) /* sim routine? */ - cptr = (*sim_vm_read) (cbuf, CBUFSIZE, stdin); - else cptr = read_line (cbuf, CBUFSIZE, stdin); /* read command line */ - if (cptr == NULL) continue; /* ignore EOF */ - if (*cptr == 0) continue; /* ignore blank */ - if (sim_log) fprintf (sim_log, "sim> %s\n", cptr); /* log cmd */ - cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */ - sim_switches = 0; /* init switches */ - if (cmdp = find_cmd (gbuf)) /* lookup command */ - stat = cmdp->action (cmdp->arg, cptr); /* if found, exec */ - else stat = SCPE_UNK; - if (stat >= SCPE_BASE) { /* error? */ - printf ("%s\n", scp_error_messages[stat - SCPE_BASE]); - if (sim_log) fprintf (sim_log, "%s\n", - scp_error_messages[stat - SCPE_BASE]); } - if (sim_vm_post != NULL) (*sim_vm_post) (TRUE); - } /* end while */ - -detach_all (0, TRUE); /* close files */ -set_logoff (0, NULL); /* close log */ -set_notelnet (0, NULL); /* close Telnet */ -ttclose (); /* close console */ -return 0; -} - -/* Find command routine */ - -CTAB *find_cmd (char *gbuf) -{ -CTAB *cmdp = NULL; - -if (sim_vm_cmd) cmdp = find_ctab (sim_vm_cmd, gbuf); /* try ext commands */ -if (cmdp == NULL) cmdp = find_ctab (cmd_table, gbuf); /* try regular cmds */ -return cmdp; -} - -/* Exit command */ - -t_stat exit_cmd (int32 flag, char *cptr) -{ -return SCPE_EXIT; -} - -/* Help command */ - -void fprint_help (FILE *st) -{ -CTAB *cmdp; - -for (cmdp = cmd_table; cmdp && (cmdp->name != NULL); cmdp++) { - if (cmdp->help) fprintf (st, cmdp->help); } -for (cmdp = sim_vm_cmd; cmdp && (cmdp->name != NULL); cmdp++) { - if (cmdp->help) fprintf (st, cmdp->help); } -return; -} - -t_stat help_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; -CTAB *cmdp; - -GET_SWITCHES (cptr); -if (*cptr) { - cptr = get_glyph (cptr, gbuf, 0); - if (*cptr) return SCPE_2MARG; - if (cmdp = find_cmd (gbuf)) { - printf (cmdp->help); - if (sim_log) fprintf (sim_log, cmdp->help); } - else return SCPE_ARG; } -else { fprint_help (stdout); - if (sim_log) fprint_help (sim_log); } -return SCPE_OK; -} - -/* Spawn command */ - -t_stat spawn_cmd (int32 flag, char *cptr) -{ -if ((cptr == NULL) || (strlen (cptr) == 0)) cptr = getenv("SHELL"); -if ((cptr == NULL) || (strlen (cptr) == 0)) cptr = getenv("ComSpec"); -#if defined (VMS) -if ((cptr == NULL) || (strlen (cptr) == 0)) cptr = "SPAWN/INPUT=SYS$COMMAND:"; -#endif -fflush(stdout); /* flush stdout */ -if (sim_log) fflush (sim_log); /* flush log if enabled */ -system (cptr); -#if defined (VMS) -printf ("\n"); -#endif - -return SCPE_OK; -} - -/* Do command */ - -t_stat do_cmd (int32 flag, char *fcptr) -{ -char *cptr, cbuf[CBUFSIZE], gbuf[CBUFSIZE], *c, quote, *do_arg[10]; -FILE *fpin; -CTAB *cmdp; -int32 echo, nargs; -t_stat stat = SCPE_OK; - -if (flag == 0) { GET_SWITCHES (fcptr); } /* get switches */ -echo = sim_switches & SWMASK ('V'); /* -v means echo */ - -c = fcptr; -for (nargs = 0; nargs < 10; ) { /* extract arguments */ - while (isspace (*c)) c++; /* skip blanks */ - if (*c == 0) break; /* all done */ - if (*c == '\'' || *c == '"') quote = *c++; /* quoted string? */ - else quote = 0; - do_arg[nargs++] = c; /* save start */ - while (*c && (quote? (*c != quote): !isspace (*c))) c++; - if (*c) *c++ = 0; /* term at quote/spc */ - } /* end for */ -if (nargs <= 0) return SCPE_2FARG; /* need at least 1 */ -if ((fpin = fopen (do_arg[0], "r")) == NULL) /* cmd file failed to open? */ - return SCPE_OPENERR; - -do { cptr = read_line (cbuf, CBUFSIZE, fpin); /* get cmd line */ - sub_args (cbuf, gbuf, CBUFSIZE, nargs, do_arg); - if (cptr == NULL) break; /* exit on eof */ - if (*cptr == 0) continue; /* ignore blank */ - if (echo) printf("do> %s\n", cptr); /* echo if -v */ - if (sim_log) fprintf (sim_log, "do> %s\n", cptr); - cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */ - sim_switches = 0; /* init switches */ - if (strcmp (gbuf, "DO") == 0) { /* don't recurse */ - fclose (fpin); - return SCPE_NEST; } - if (cmdp = find_cmd (gbuf)) /* lookup command */ - stat = cmdp->action (cmdp->arg, cptr); /* if found, exec */ - else stat = SCPE_UNK; - if (stat >= SCPE_BASE) /* error? */ - printf ("%s\n", scp_error_messages[stat - SCPE_BASE]); - if (sim_vm_post != NULL) (*sim_vm_post) (TRUE); -} while (stat != SCPE_EXIT); - -fclose (fpin); /* close file */ -return (stat == SCPE_EXIT)? SCPE_EXIT: SCPE_OK; -} - -/* Substitute_args - replace %n tokens in 'instr' with the do command's arguments - - Calling sequence - instr = input string - tmpbuf = temp buffer - maxstr = min (len (instr), len (tmpbuf)) - nargs = number of arguments - do_arg[10] = arguments -*/ - -void sub_args (char *instr, char *tmpbuf, int32 maxstr, int32 nargs, char *do_arg[]) -{ -char *ip, *op, *ap, *oend = tmpbuf + maxstr - 2; - -for (ip = instr, op = tmpbuf; *ip && (op < oend); ) { - if ((*ip == '\\') && (ip[1] == '%')) { /* \% = literal % */ - ip++; /* skip \ */ - if (*ip) *op++ = *ip++; } /* copy next */ - else if ((*ip == '%') && /* %n = sub */ - ((ip[1] >= '1') && (ip[1] <= ('0'+ nargs - 1)))) { - ap = do_arg[ip[1] - '0']; - ip = ip + 2; - while (*ap && (op < oend)) *op++ = *ap++; }/* copy the argument */ - else *op++ = *ip++; } /* literal character */ -*op = 0; /* term buffer */ -strcpy (instr, tmpbuf); -return; -} - -/* Set command */ - -t_stat set_cmd (int32 flag, char *cptr) -{ -int32 lvl; -t_stat r; -char gbuf[CBUFSIZE], *cvptr, *svptr; -DEVICE *dptr; -UNIT *uptr; -MTAB *mptr; -CTAB *gcmdp; -C1TAB *ctbr, *glbr; -static CTAB set_glob_tab[] = { - { "TELNET", &set_telnet, 0 }, - { "NOTELNET", &set_notelnet, 0 }, - { "LOG", &set_logon, 0 }, - { "NOLOG", &set_logoff, 0 }, - { "BREAK", &brk_cmd, SSH_ST }, - { NULL, NULL, 0 } }; -static C1TAB set_dev_tab[] = { - { "OCTAL", &set_radix, 8 }, - { "DECIMAL", &set_radix, 10 }, - { "HEX", &set_radix, 16 }, - { "ENABLED", &set_devenbdis, 1 }, - { "DISABLED", &set_devenbdis, 0 }, - { NULL, NULL, 0 } }; -static C1TAB set_unit_tab[] = { - { "ONLINE", &set_onoff, 1 }, - { "OFFLINE", &set_onoff, 0 }, - { NULL, NULL, 0 } }; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -cptr = get_glyph (cptr, gbuf, 0); /* get glob/dev/unit */ - -if (dptr = find_dev (gbuf)) { /* device match? */ - uptr = dptr->units; /* first unit */ - ctbr = set_dev_tab; /* global table */ - lvl = MTAB_VDV; } /* device match */ -else if (dptr = find_unit (gbuf, &uptr)) { /* unit match? */ - if (uptr == NULL) return SCPE_NXUN; /* invalid unit */ - ctbr = set_unit_tab; /* global table */ - lvl = MTAB_VUN; } /* unit match */ -else if (gcmdp = find_ctab (set_glob_tab, gbuf)) /* global? */ - return gcmdp->action (gcmdp->arg, cptr); /* do the rest */ -else return SCPE_NXDEV; /* no match */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ - -while (*cptr != 0) { /* do all mods */ - cptr = get_glyph (svptr = cptr, gbuf, ','); /* get modifier */ - if (cvptr = strchr (gbuf, '=')) *cvptr++ = 0; /* = value? */ - for (mptr = dptr->modifiers; mptr && (mptr->mask != 0); mptr++) { - if ((mptr->mstring) && /* match string */ - (MATCH_CMD (gbuf, mptr->mstring) == 0)) { /* matches option? */ - if (mptr->mask & MTAB_XTD) { /* extended? */ - if ((lvl & mptr->mask) == 0) return SCPE_ARG; - if ((lvl & MTAB_VUN) && (uptr->flags & UNIT_DIS)) - return SCPE_UDIS; /* unit disabled? */ - if (mptr->valid) { /* validation rtn? */ - if (cvptr && (mptr->mask & MTAB_NC)) - get_glyph_nc (svptr, gbuf, ','); - r = mptr->valid (uptr, mptr->match, cvptr, mptr->desc); - if (r != SCPE_OK) return r; } - else if (!mptr->desc) break; /* value desc? */ - else if (mptr->mask & MTAB_VAL) { /* take a value? */ - if (!cvptr) return SCPE_MISVAL; /* none? error */ - r = dep_reg (0, cvptr, (REG *) mptr->desc, 0); - if (r != SCPE_OK) return r; } - else if (cvptr) return SCPE_ARG; /* = value? */ - else *((int32 *) mptr->desc) = mptr->match; - } /* end if xtd */ - else { /* old style */ - if (cvptr) return SCPE_ARG; /* = value? */ - if (uptr->flags & UNIT_DIS) /* disabled? */ - return SCPE_UDIS; - if ((mptr->valid) && ((r = mptr->valid - (uptr, mptr->match, cvptr, mptr->desc)) - != SCPE_OK)) return r; /* invalid? */ - uptr->flags = (uptr->flags & ~(mptr->mask)) | - (mptr->match & mptr->mask); /* set new value */ - } /* end else xtd */ - break; /* terminate for */ - } /* end if match */ - } /* end for */ - if (!mptr || (mptr->mask == 0)) { /* no match? */ - if (glbr = find_c1tab (ctbr, gbuf)) { /* global match? */ - r = glbr->action (dptr, uptr, glbr->arg); /* do global */ - if (r != SCPE_OK) return r; } - else if (!dptr->modifiers) return SCPE_NOPARAM; /* no modifiers? */ - else return SCPE_NXPAR; } /* end if no mat */ - } /* end while */ -return SCPE_OK; /* done all */ -} - -/* Match CTAB/CTAB1 name */ - -CTAB *find_ctab (CTAB *tab, char *gbuf) -{ -for (; tab->name != NULL; tab++) { - if (MATCH_CMD (gbuf, tab->name) == 0) return tab; } -return NULL; -} - -C1TAB *find_c1tab (C1TAB *tab, char *gbuf) -{ -for (; tab->name != NULL; tab++) { - if (MATCH_CMD (gbuf, tab->name) == 0) return tab; } -return NULL; -} - -/* Log on routine */ - -t_stat set_logon (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; - -if (*cptr == 0) return SCPE_2FARG; /* need arg */ -cptr = get_glyph_nc (cptr, gbuf, 0); /* get file name */ -if (*cptr != 0) return SCPE_2MARG; /* now eol? */ -set_logoff (0, NULL); /* close cur log */ -sim_log = FOPEN (gbuf, "a"); /* open log */ -if (sim_log == NULL) return SCPE_OPENERR; /* error? */ -if (!sim_quiet) printf ("Logging to file \"%s\"\n", gbuf); -fprintf (sim_log, "Logging to file \"%s\"\n", gbuf); /* start of log */ -return SCPE_OK; -} - -/* Log off routine */ - -t_stat set_logoff (int32 flag, char *cptr) -{ -if (cptr && (*cptr != 0)) return SCPE_2MARG; /* now eol? */ -if (sim_log == NULL) return SCPE_OK; /* no log? */ -if (!sim_quiet) printf ("Log file closed\n"); -fprintf (sim_log, "Log file closed\n"); /* close log */ -fclose (sim_log); -sim_log = NULL; -return SCPE_OK; -} - -/* Set controller data radix routine */ - -t_stat set_radix (DEVICE *dptr, UNIT *uptr, int32 flag) -{ -dptr->dradix = flag & 037; -return SCPE_OK; -} - -/* Set controller enabled/disabled routine */ - -t_stat set_devenbdis (DEVICE *dptr, UNIT *uptr, int32 flag) -{ -UNIT *up; -uint32 i; - -if ((dptr->flags & DEV_DISABLE) == 0) return SCPE_NOFNC;/* allowed? */ -if (flag) { /* enable? */ - if ((dptr->flags & DEV_DIS) == 0) return SCPE_OK; /* already enb? ok */ - dptr->flags = dptr->flags & ~DEV_DIS; } /* no, enable */ -else { /* disable */ - if (dptr->flags & DEV_DIS) return SCPE_OK; /* already dsb? ok */ - for (i = 0; i < dptr->numunits; i++) { /* check units */ - up = (dptr->units) + i; /* att or active? */ - if ((up->flags & UNIT_ATT) || sim_is_active (up)) - return SCPE_NOFNC; } /* can't do it */ - dptr->flags = dptr->flags | DEV_DIS; } /* disable */ -if (dptr->reset) return dptr->reset (dptr); /* reset device */ -else return SCPE_OK; -} - -/* Set unit online/offline routine */ - -t_stat set_onoff (DEVICE *dptr, UNIT *uptr, int32 flag) -{ -if (!(uptr->flags & UNIT_DISABLE)) return SCPE_NOFNC; /* allowed? */ -if (flag) uptr->flags = uptr->flags & ~UNIT_DIS; /* onl? enable */ -else { /* offline? */ - if ((uptr->flags & UNIT_ATT) || sim_is_active (uptr)) - return SCPE_NOFNC; /* more tests */ - uptr->flags = uptr->flags | UNIT_DIS; } /* disable */ -return SCPE_OK; -} - -/* Show command */ - -t_stat show_cmd (int32 flag, char *cptr) -{ -int32 i, lvl; -t_stat r; -char gbuf[CBUFSIZE]; -DEVICE *dptr; -UNIT *uptr; -MTAB *mptr; - -static SHTAB show_table[] = { - { "CONFIGURATION", &show_config, 0 }, - { "DEVICES", &show_config, 1 }, - { "QUEUE", &show_queue, 0 }, - { "TIME", &show_time, 0 }, - { "MODIFIERS", &show_mod_names, 0 }, - { "NAMES", &show_log_names, 0 }, - { "VERSION", &show_version, 0 }, - { "LOG", &show_log, 0 }, - { "TELNET", &show_telnet, 0 }, - { "BREAK", &show_break, 0 }, - { NULL, NULL, 0 } }; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ -for (i = 0; show_table[i].name != NULL; i++) { /* find command */ - if (MATCH_CMD (gbuf, show_table[i].name) == 0) { - r = show_table[i].action (stdout, show_table[i].arg, cptr); - if (sim_log) show_table[i].action (sim_log, show_table[i].arg, cptr); - return r; } } - -if (dptr = find_dev (gbuf)) { /* device match? */ - uptr = dptr->units; /* first unit */ - lvl = MTAB_VDV; } /* device match */ -else if (dptr = find_unit (gbuf, &uptr)) { /* unit match? */ - if (uptr == NULL) return SCPE_NXUN; /* invalid unit */ - if (uptr->flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ - lvl = MTAB_VUN; } /* unit match */ -else return SCPE_NXDEV; /* no match */ - -if (*cptr == 0) { /* now eol? */ - if (lvl == MTAB_VDV) { /* show dev? */ - r = show_device (stdout, dptr, 0); - if (sim_log) show_device (sim_log, dptr, 0); - return r; } - else { - r = show_unit (stdout, dptr, uptr, -1); - if (sim_log) show_unit (sim_log, dptr, uptr, -1); - return r; } } -if (dptr->modifiers == NULL) return SCPE_NOPARAM; /* any modifiers? */ - -while (*cptr != 0) { /* do all mods */ - cptr = get_glyph (cptr, gbuf, ','); /* get modifier */ - for (mptr = dptr->modifiers; mptr->mask != 0; mptr++) { - if (((mptr->mask & MTAB_XTD)? /* right level? */ - (mptr->mask & lvl): (MTAB_VUN & lvl)) && - ((mptr->disp && mptr->pstring && /* named disp? */ - (MATCH_CMD (gbuf, mptr->pstring) == 0)) || - ((mptr->mask & MTAB_VAL) && /* named value? */ - mptr->mstring && - (MATCH_CMD (gbuf, mptr->mstring) == 0)))) { - show_one_mod (stdout, dptr, uptr, mptr, 1); - if (sim_log) show_one_mod (sim_log, dptr, uptr, mptr, 1); - break; - } /* end if */ - } /* end for */ - if (mptr->mask == 0) return SCPE_ARG; /* any match? */ - } /* end while */ -return SCPE_OK; -} - -/* Show device and unit */ - -t_stat show_device (FILE *st, DEVICE *dptr, int32 flag) -{ -uint32 j, ucnt; -UNIT *uptr; - -fprintf (st, "%s", sim_dname (dptr)); /* print dev name */ -if (qdisable (dptr)) { /* disabled? */ - fprintf (st, ", disabled\n"); - return SCPE_OK; } -for (j = ucnt = 0; j < dptr->numunits; j++) { /* count units */ - uptr = dptr->units + j; - if (!(uptr->flags & UNIT_DIS)) ucnt++; } -show_all_mods (st, dptr, dptr->units, MTAB_VDV); /* show dev mods */ -if (dptr->numunits == 0) fprintf (st, "\n"); -else { if (ucnt == 0) fprintf (st, ", all units disabled\n"); - else if (ucnt > 1) fprintf (st, ", %d units\n", ucnt); - else if (flag) fprintf (st, "\n"); } -if (flag) return SCPE_OK; /* dev only? */ -for (j = 0; j < dptr->numunits; j++) { /* loop thru units */ - uptr = dptr->units + j; - if ((uptr->flags & UNIT_DIS) == 0) - show_unit (st, dptr, uptr, ucnt); } -return SCPE_OK; -} - -t_stat show_unit (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag) -{ -int32 u = uptr - dptr->units; - -if (flag > 1) fprintf (st, " %s%d", sim_dname (dptr), u); -else if (flag < 0) fprintf (st, "%s%d", sim_dname (dptr), u); -if (uptr->flags & UNIT_FIX) { - fprintf (st, ", "); - fprint_capac (st, dptr, uptr); } -if (uptr->flags & UNIT_ATT) { - fprintf (st, ", attached to %s", uptr->filename); - if (uptr->flags & UNIT_RO) fprintf (st, ", read only"); } -else if (uptr->flags & UNIT_ATTABLE) - fprintf (st, ", not attached"); -show_all_mods (st, dptr, uptr, MTAB_VUN); /* show unit mods */ -fprintf (st, "\n"); -return SCPE_OK; -} - -void fprint_capac (FILE *st, DEVICE *dptr, UNIT *uptr) -{ -t_addr kval = (uptr->flags & UNIT_BINK)? 1024: 1000; -t_addr mval = kval * kval; -t_addr psize = uptr->capac; -char scale, width; - -if ((dptr->dwidth / dptr->aincr) > 8) width = 'W'; -else width = 'B'; -if (uptr->capac < (kval * 10)) scale = 0; -else if (uptr->capac < (mval * 10)) { - scale = 'K'; - psize = psize / kval; } -else { scale = 'M'; - psize = psize / mval; } -fprint_val (st, (t_value) psize, 10, T_ADDR_W, PV_LEFT); -if (scale) fputc (scale, st); -fputc (width, st); -return; -} - -/* Show processors */ - -t_stat show_version (FILE *st, int32 flag, char *cptr) -{ -int32 vmaj = SIM_MAJOR, vmin = SIM_MINOR, vpat = SIM_PATCH; - -if (cptr && (*cptr != 0)) return SCPE_2MARG; -fprintf (st, "%s simulator V%d.%d-%d\n", sim_name, vmaj, vmin, vpat); -return SCPE_OK; -} - -t_stat show_config (FILE *st, int32 flag, char *cptr) -{ -int32 i; -DEVICE *dptr; - -if (cptr && (*cptr != 0)) return SCPE_2MARG; -fprintf (st, "%s simulator configuration\n\n", sim_name); -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) - show_device (st, dptr, flag); -return SCPE_OK; -} - -t_stat show_log_names (FILE *st, int32 flag, char *cptr) -{ -int32 i; -DEVICE *dptr; - -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { - if (dptr->lname) fprintf (st, "%s -> %s\n", - dptr->lname, dptr->name); } -return SCPE_OK; -} - -t_stat show_queue (FILE *st, int32 flag, char *cptr) -{ -DEVICE *dptr; -UNIT *uptr; -int32 accum; - -if (cptr && (*cptr != 0)) return SCPE_2MARG; -if (sim_clock_queue == NULL) { - fprintf (st, "%s event queue empty, time = %.0f\n", - sim_name, sim_time); - return SCPE_OK; } -fprintf (st, "%s event queue status, time = %.0f\n", - sim_name, sim_time); -accum = 0; -for (uptr = sim_clock_queue; uptr != NULL; uptr = uptr->next) { - if (uptr == &step_unit) fprintf (st, " Step timer"); - else if ((dptr = find_dev_from_unit (uptr)) != NULL) { - fprintf (st, " %s", sim_dname (dptr)); - if (dptr->numunits > 1) fprintf (st, " unit %d", - uptr - dptr->units); } - else fprintf (st, " Unknown"); - fprintf (st, " at %d\n", accum + uptr->time); - accum = accum + uptr->time; } -return SCPE_OK; -} - -t_stat show_time (FILE *st, int32 flag, char *cptr) -{ -if (cptr && (*cptr != 0)) return SCPE_2MARG; -fprintf (st, "Time: %.0f\n", sim_time); -return SCPE_OK; -} - -t_stat show_log (FILE *st, int32 flag, char *cptr) -{ -if (cptr && (*cptr != 0)) return SCPE_2MARG; -if (sim_log) fprintf (st, "Logging enabled\n"); -else fprintf (st, "Logging disabled\n"); -return SCPE_OK; -} - -t_stat show_break (FILE *st, int32 flag, char *cptr) -{ -t_stat r; - -if (cptr && (*cptr != 0)) { /* more? */ - r = ssh_break (stdout, cptr, 1); - if (sim_log) ssh_break (sim_log, cptr, SSH_SH); } -else { r = sim_brk_showall (stdout, sim_switches); - if (sim_log) sim_brk_showall (sim_log,sim_switches); } -return r; -} - -/* Show modifiers */ - -t_stat show_mod_names (FILE *st, int32 flag, char *cptr) -{ -int32 i, any, enb; -DEVICE *dptr; -MTAB *mptr; - -if (cptr && (*cptr != 0)) return SCPE_2MARG; /* now eol? */ -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { - any = enb = 0; - if (dptr->modifiers) { - for (mptr = dptr->modifiers; mptr->mask != 0; mptr++) { - if (mptr->mstring) { - if (strcmp (mptr->mstring, "ENABLED") == 0) enb = 1; - if (any++) fprintf (st, ", %s", mptr->mstring); - else fprintf (st, "%s\t%s", sim_dname (dptr), mptr->mstring); } } } - if (!enb && (dptr->flags & DEV_DISABLE)) { - if (any++) fprintf (st, ", ENABLED, DISABLED"); - else fprintf (st, "%s\tENABLED, DISABLED", sim_dname (dptr)); } - if (any) fprintf (st, "\n"); } -return SCPE_OK; -} - -t_stat show_all_mods (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag) -{ -MTAB *mptr; - -if (dptr->modifiers == NULL) return SCPE_OK; -for (mptr = dptr->modifiers; mptr->mask != 0; mptr++) { - if (mptr->pstring && ((mptr->mask & MTAB_XTD)? - ((mptr->mask & flag) && !(mptr->mask & MTAB_NMO)): - ((MTAB_VUN & flag) && ((uptr->flags & mptr->mask) == mptr->match)))) { - fputs (", ", st); - show_one_mod (st, dptr, uptr, mptr, 0); } } -return SCPE_OK; -} - -t_stat show_one_mod (FILE *st, DEVICE *dptr, UNIT *uptr, MTAB *mptr, int32 flag) -{ -t_value val; - -if (mptr->disp) mptr->disp (st, uptr, mptr->match, mptr->desc); -else if ((mptr->mask & MTAB_XTD) && (mptr->mask & MTAB_VAL)) { - REG *rptr = (REG *) mptr->desc; - fprintf (st, "%s=", mptr->pstring); - val = get_rval (rptr, 0); - fprint_val (st, val, rptr->radix, rptr->width, - rptr->flags & REG_FMT); } -else fputs (mptr->pstring, st); -if (flag && !((mptr->mask & MTAB_XTD) && - (mptr->mask & MTAB_NMO))) fputc ('\n', st); -return SCPE_OK; -} - -/* Breakpoint commands */ - -t_stat brk_cmd (int32 flg, char *cptr) -{ -GET_SWITCHES (cptr); /* get switches */ -return ssh_break (NULL, cptr, flg); /* call common code */ -} - -t_stat ssh_break (FILE *st, char *cptr, int32 flg) -{ -char gbuf[CBUFSIZE], *tptr, *t1ptr, *aptr; -DEVICE *dptr = sim_devices[0]; -UNIT *uptr = dptr->units; -t_stat r; -t_addr lo, hi, max = uptr->capac - dptr->aincr; -int32 cnt; - -if (*cptr == 0) return SCPE_2FARG; -if (sim_brk_types == 0) return SCPE_NOFNC; -if ((dptr == NULL) || (uptr == NULL)) return SCPE_IERR; -if (aptr = strchr (cptr, ';')) { /* ;action? */ - if (flg != SSH_ST) return SCPE_ARG; /* only on SET */ - *aptr++ = 0; } /* separate strings */ -while (*cptr) { - cptr = get_glyph (cptr, gbuf, ','); - tptr = get_range (gbuf, &lo, &hi, dptr->aradix, max, 0); - if (tptr == NULL) return SCPE_ARG; - if (*tptr == '[') { - cnt = (int32) strtotv (tptr + 1, &t1ptr, 10); - if ((tptr == t1ptr) || (*t1ptr != ']') || - (flg != SSH_ST)) return SCPE_ARG; - tptr = t1ptr + 1; } - else cnt = 0; - if (*tptr != 0) return SCPE_ARG; - if ((lo == 0) && (hi == max)) { - if (flg == SSH_CL) sim_brk_clrall (sim_switches); - else if (flg == SSH_SH) sim_brk_showall (st, sim_switches); - else return SCPE_ARG; } - else { - for ( ; lo <= hi; lo = lo + dptr->aincr) { - if (flg == SSH_ST) r = sim_brk_set (lo, sim_switches, cnt, aptr); - else if (flg == SSH_CL) r = sim_brk_clr (lo, sim_switches); - else if (flg == SSH_SH) r = sim_brk_show (st, lo, sim_switches); - else return SCPE_ARG; - if (r != SCPE_OK) return r; - } - } - } -return SCPE_OK; -} - -/* Reset command and routines - - re[set] reset all devices - re[set] all reset all devices - re[set] device reset specific device -*/ - -t_stat reset_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; -DEVICE *dptr; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return (reset_all (0)); /* reset(cr) */ -cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ -if (*cptr != 0) return SCPE_2MARG; /* now eol? */ -if (strcmp (gbuf, "ALL") == 0) return (reset_all (0)); -dptr = find_dev (gbuf); /* locate device */ -if (dptr == NULL) return SCPE_NXDEV; /* found it? */ -if (dptr->reset != NULL) return dptr->reset (dptr); -else return SCPE_OK; -} - -/* Reset devices start..end - - Inputs: - start = number of starting device - Outputs: - status = error status -*/ - -t_stat reset_all (uint32 start) -{ -DEVICE *dptr; -uint32 i; -t_stat reason; - -for (i = 0; i < start; i++) { - if (sim_devices[i] == NULL) return SCPE_IERR; } -for (i = start; (dptr = sim_devices[i]) != NULL; i++) { - if (dptr->reset != NULL) { - reason = dptr->reset (dptr); - if (reason != SCPE_OK) return reason; } } -return SCPE_OK; -} - -/* Load and dump commands - - lo[ad] filename {arg} load specified file - du[mp] filename {arg} dump to specified file -*/ - -t_stat load_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; -FILE *loadfile; -t_stat reason; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -cptr = get_glyph_nc (cptr, gbuf, 0); /* get file name */ -loadfile = FOPEN (gbuf, flag? "wb": "rb"); /* open for wr/rd */ -if (loadfile == NULL) return SCPE_OPENERR; -GET_SWITCHES (cptr); /* get switches */ -reason = sim_load (loadfile, cptr, gbuf, flag); /* load or dump */ -fclose (loadfile); -return reason; -} - -/* Attach command - - at[tach] unit file attach specified unit to file -*/ - -t_stat attach_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; -DEVICE *dptr; -UNIT *uptr; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* now eol? */ -dptr = find_unit (gbuf, &uptr); /* locate unit */ -if (dptr == NULL) return SCPE_NXDEV; /* found dev? */ -if (uptr == NULL) return SCPE_NXUN; /* valid unit? */ -if (dptr->attach != NULL) return dptr->attach (uptr, cptr); -return attach_unit (uptr, cptr); -} - -t_stat attach_unit (UNIT *uptr, char *cptr) -{ -DEVICE *dptr; -t_stat reason; - -if (uptr->flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ -if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOATT; /* not attachable? */ -if ((dptr = find_dev_from_unit (uptr)) == NULL) return SCPE_NOATT; -if (uptr->flags & UNIT_ATT) { /* already attached? */ - reason = detach_unit (uptr); - if (reason != SCPE_OK) return reason; } -uptr->filename = calloc (CBUFSIZE, sizeof (char)); -if (uptr->filename == NULL) return SCPE_MEM; -strncpy (uptr->filename, cptr, CBUFSIZE); -if (sim_switches & SWMASK ('R')) { /* read only? */ - if ((uptr->flags & UNIT_ROABLE) == 0) /* allowed? */ - return attach_err (uptr, SCPE_NORO); /* no, error */ - uptr->fileref = FOPEN (cptr, "rb"); /* open rd only */ - if (uptr->fileref == NULL) /* open fail? */ - return attach_err (uptr, SCPE_OPENERR); /* yes, error */ - uptr->flags = uptr->flags | UNIT_RO; /* set rd only */ - if (!sim_quiet) printf ("%s: unit is read only\n", sim_dname (dptr)); } -else { /* normal */ - uptr->fileref = FOPEN (cptr, "rb+"); /* open r/w */ - if (uptr->fileref == NULL) { /* open fail? */ - if (errno == EROFS) { /* read only? */ - if ((uptr->flags & UNIT_ROABLE) == 0) /* allowed? */ - return attach_err (uptr, SCPE_NORO); /* no error */ - uptr->fileref = FOPEN (cptr, "rb"); /* open rd only */ - if (uptr->fileref == NULL) /* open fail? */ - return attach_err (uptr, SCPE_OPENERR); /* yes, error */ - uptr->flags = uptr->flags | UNIT_RO; /* set rd only */ - if (!sim_quiet) printf ("%s: unit is read only\n", sim_dname (dptr)); } - else { /* doesn't exist */ - if (sim_switches & SWMASK ('E')) /* must exist? */ - return attach_err (uptr, SCPE_OPENERR); /* yes, error */ - uptr->fileref = FOPEN (cptr, "wb+"); /* open new file */ - if (uptr->fileref == NULL) /* open fail? */ - return attach_err (uptr, SCPE_OPENERR); /* yes, error */ - if (!sim_quiet) printf ("%s: creating new file\n", sim_dname (dptr)); } - } /* end if null */ - } /* end else */ -if (uptr->flags & UNIT_BUFABLE) { /* buffer? */ - uint32 cap = ((uint32) uptr->capac) / dptr->aincr; /* effective size */ - if (uptr->flags & UNIT_MUSTBUF) /* dyn alloc? */ - uptr->filebuf = calloc (cap, SZ_D (dptr)); /* allocate */ - if (uptr->filebuf == NULL) /* no buffer? */ - return attach_err (uptr, SCPE_MEM); /* error */ - if (!sim_quiet) printf ("%s: buffering file in memory\n", sim_dname (dptr)); - uptr->hwmark = fxread (uptr->filebuf, SZ_D (dptr), /* read file */ - cap, uptr->fileref); - uptr->flags = uptr->flags | UNIT_BUF; } /* set buffered */ -uptr->flags = uptr->flags | UNIT_ATT; -uptr->pos = 0; -return SCPE_OK; -} - -t_stat attach_err (UNIT *uptr, t_stat stat) -{ -free (uptr->filename); -uptr->filename = NULL; -return stat; -} - -/* Detach command - - det[ach] all detach all units - det[ach] unit detach specified unit -*/ - -t_stat detach_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; -DEVICE *dptr; -UNIT *uptr; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ -if (*cptr != 0) return SCPE_2MARG; /* now eol? */ -if (strcmp (gbuf, "ALL") == 0) return (detach_all (0, FALSE)); -dptr = find_unit (gbuf, &uptr); /* locate unit */ -if (dptr == NULL) return SCPE_NXDEV; /* found dev? */ -if (uptr == NULL) return SCPE_NXUN; /* valid unit? */ -if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOATT; -if (dptr->detach != NULL) return dptr->detach (uptr); -return detach_unit (uptr); -} - -/* Detach devices start..end - - Inputs: - start = number of starting device - shutdown = TRUE if simulator shutting down - Outputs: - status = error status -*/ - -t_stat detach_all (int32 start, t_bool shutdown) -{ -uint32 i, j; -t_stat reason; -DEVICE *dptr; -UNIT *uptr; - -if ((start < 0) || (start > 1)) return SCPE_IERR; -for (i = start; (dptr = sim_devices[i]) != NULL; i++) { - for (j = 0; j < dptr->numunits; j++) { - uptr = (dptr->units) + j; - if ((uptr->flags & UNIT_ATTABLE) || shutdown) { - if (dptr->detach != NULL) reason = dptr->detach (uptr); - else reason = detach_unit (uptr); - if (reason != SCPE_OK) return reason; } } } -return SCPE_OK; -} - -t_stat detach_unit (UNIT *uptr) -{ -DEVICE *dptr; - -if (uptr == NULL) return SCPE_IERR; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; -if ((dptr = find_dev_from_unit (uptr)) == NULL) return SCPE_OK; -if (uptr->flags & UNIT_BUF) { - uint32 cap = (uptr->hwmark + dptr->aincr - 1) / dptr->aincr; - if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { - if (!sim_quiet) printf ("%s: writing buffer to file\n", sim_dname (dptr)); - rewind (uptr->fileref); - fxwrite (uptr->filebuf, SZ_D (dptr), cap, uptr->fileref); - if (ferror (uptr->fileref)) perror ("I/O error"); } - if (uptr->flags & UNIT_MUSTBUF) { /* dyn alloc? */ - free (uptr->filebuf); /* free buf */ - uptr->filebuf = NULL; } - uptr->flags = uptr->flags & ~UNIT_BUF; } -uptr->flags = uptr->flags & ~(UNIT_ATT | UNIT_RO); -free (uptr->filename); -uptr->filename = NULL; -return (fclose (uptr->fileref) == EOF)? SCPE_IOERR: SCPE_OK; -} - -/* Assign command - - as[sign] device name assign logical name to device -*/ - -t_stat assign_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; -DEVICE *dptr; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* now eol? */ -dptr = find_dev (gbuf); /* locate device */ -if (dptr == NULL) return SCPE_NXDEV; /* found dev? */ -cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ -if (*cptr != 0) return SCPE_2MARG; /* must be eol */ -if (find_dev (gbuf)) return SCPE_ARG; /* name in use */ -deassign_device (dptr); /* release current */ -return assign_device (dptr, gbuf); -} - -t_stat assign_device (DEVICE *dptr, char *cptr) -{ -dptr->lname = calloc (CBUFSIZE, sizeof (char)); -if (dptr->lname == NULL) return SCPE_MEM; -strncpy (dptr->lname, cptr, CBUFSIZE); -return SCPE_OK; -} - -/* Deassign command - - dea[ssign] device deassign logical name -*/ - -t_stat deassign_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; -DEVICE *dptr; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ -if (*cptr != 0) return SCPE_2MARG; /* now eol? */ -dptr = find_dev (gbuf); /* locate device */ -if (dptr == NULL) return SCPE_NXDEV; /* found dev? */ -return deassign_device (dptr); -} - -t_stat deassign_device (DEVICE *dptr) -{ -if (dptr->lname) free (dptr->lname); -dptr->lname = NULL; -return SCPE_OK; -} - -/* Get device display name */ - -char *sim_dname (DEVICE *dptr) -{ -return (dptr->lname? dptr->lname: dptr->name); -} - -/* Save command - - sa[ve] filename save state to specified file -*/ - -t_stat save_cmd (int32 flag, char *cptr) -{ -FILE *sfile; -t_stat r; -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -if ((sfile = FOPEN (cptr, "wb")) == NULL) return SCPE_OPENERR; -r = sim_save (sfile); -fclose (sfile); -return r; -} - -t_stat sim_save (FILE *sfile) -{ -void *mbuf; -int32 l, t; -uint32 i, j; -t_addr k, high; -t_value val; -t_stat r; -t_bool zeroflg; -size_t sz; -DEVICE *dptr; -UNIT *uptr; -REG *rptr; - -#define WRITE_I(xx) fxwrite (&(xx), sizeof (xx), 1, sfile) - -fputs (save_vercur, sfile); /* [V2.5] save format */ -fputc ('\n', sfile); -fputs (sim_name, sfile); /* sim name */ -fputc ('\n', sfile); -WRITE_I (sim_time); /* sim time */ -WRITE_I (sim_rtime); /* [V2.6] sim rel time */ - -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru devices */ - fputs (dptr->name, sfile); /* device name */ - fputc ('\n', sfile); - if (dptr->lname) fputs (dptr->lname, sfile); /* [V3.0] logical name */ - fputc ('\n', sfile); - WRITE_I (dptr->flags); /* [V2.10] flags */ - for (j = 0; j < dptr->numunits; j++) { - uptr = dptr->units + j; - t = sim_is_active (uptr); - WRITE_I (j); /* unit number */ - WRITE_I (t); /* activation time */ - WRITE_I (uptr->u3); /* unit specific */ - WRITE_I (uptr->u4); - WRITE_I (uptr->u5); /* [V3.0] more unit */ - WRITE_I (uptr->u6); - WRITE_I (uptr->flags); /* [V2.10] flags */ - if (uptr->flags & UNIT_ATT) fputs (uptr->filename, sfile); - fputc ('\n', sfile); - if (((uptr->flags & (UNIT_FIX + UNIT_ATTABLE)) == UNIT_FIX) && - (dptr->examine != NULL) && - ((high = uptr->capac) != 0)) { /* memory-like unit? */ - WRITE_I (high); /* [V2.5] write size */ - sz = SZ_D (dptr); - if ((mbuf = calloc (SRBSIZ, sz)) == NULL) { - fclose (sfile); - return SCPE_MEM; } - for (k = 0; k < high; ) { /* loop thru mem */ - zeroflg = TRUE; - for (l = 0; (l < SRBSIZ) && (k < high); l++, - k = k + (dptr->aincr)) { /* check for 0 block */ - r = dptr->examine (&val, k, uptr, 0); - if (r != SCPE_OK) return r; - if (val) zeroflg = FALSE; - SZ_STORE (sz, val, mbuf, l); - } /* end for l */ - if (zeroflg) { /* all zero's? */ - l = -l; /* invert block count */ - WRITE_I (l); } /* write only count */ - else { - WRITE_I (l); /* block count */ - fxwrite (mbuf, sz, l, sfile); } - } /* end for k */ - free (mbuf); /* dealloc buffer */ - } /* end if mem */ - else { /* no memory */ - high = 0; /* write 0 */ - WRITE_I (high); - } /* end else mem */ - } /* end unit loop */ - t = -1; /* end units */ - WRITE_I (t); /* write marker */ - for (rptr = dptr->registers; (rptr != NULL) && /* loop thru regs */ - (rptr->name != NULL); rptr++) { - fputs (rptr->name, sfile); /* name */ - fputc ('\n', sfile); - WRITE_I (rptr->depth); /* [V2.10] depth */ - for (j = 0; j < rptr->depth; j++) { /* loop thru values */ - val = get_rval (rptr, j); /* get value */ - WRITE_I (val); } } /* store */ - fputc ('\n', sfile); } /* end registers */ -fputc ('\n', sfile); /* end devices */ -return (ferror (sfile))? SCPE_IOERR: SCPE_OK; /* error during save? */ -} - -/* Restore command - - re[store] filename restore state from specified file -*/ - -t_stat restore_cmd (int32 flag, char *cptr) -{ -FILE *rfile; -t_stat r; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -if ((rfile = FOPEN (cptr, "rb")) == NULL) return SCPE_OPENERR; -r = sim_rest (rfile); -fclose (rfile); -return r; -} - -t_stat sim_rest (FILE *rfile) -{ -char buf[CBUFSIZE]; -void *mbuf; -int32 j, blkcnt, limit, unitno, time, flg; -uint32 us, depth; -t_addr k, high; -t_value val, mask; -t_stat r; -size_t sz; -t_bool v30 = FALSE, v210 = FALSE; -DEVICE *dptr; -UNIT *uptr; -REG *rptr; - -#define READ_S(xx) if (read_line ((xx), CBUFSIZE, rfile) == NULL) \ - return SCPE_IOERR; -#define READ_I(xx) if (fxread (&xx, sizeof (xx), 1, rfile) == 0) \ - return SCPE_IOERR; - -READ_S (buf); /* [V2.5+] read version */ -if (strcmp (buf, save_vercur) == 0) v30 = v210 = TRUE; /* version 2.11? */ -else if (strcmp (buf, save_ver210) == 0) v210 = TRUE; /* version 2.10? */ -else if (strcmp (buf, save_ver26) != 0) { /* version 2.6? */ - printf ("Invalid file version: %s\n", buf); /* no, unknown */ - return SCPE_INCOMP; } -READ_S (buf); /* read sim name */ -if (strcmp (buf, sim_name)) { /* name match? */ - printf ("Wrong system type: %s\n", buf); - return SCPE_INCOMP; } -READ_I (sim_time); /* sim time */ -READ_I (sim_rtime); /* [V2.6+] sim rel time */ - -for ( ;; ) { /* device loop */ - READ_S (buf); /* read device name */ - if (buf[0] == 0) break; /* last? */ - if ((dptr = find_dev (buf)) == NULL) { /* locate device */ - printf ("Invalid device name: %s\n", buf); - return SCPE_INCOMP; } - if (v30) { /* [V3.0+] */ - READ_S (buf); /* read logical name */ - deassign_device (dptr); /* delete old name */ - if ((buf[0] != 0) && - ((r = assign_device (dptr, buf)) != SCPE_OK)) return r; } - if (v210) { /* [V2.10+] */ - READ_I (flg); /* cont flags */ - dptr->flags = (dptr->flags & ~DEV_RFLAGS) | /* restore */ - (flg & DEV_RFLAGS); } - for ( ;; ) { /* unit loop */ - READ_I (unitno); /* unit number */ - if (unitno < 0) break; /* end units? */ - if ((uint32) unitno >= dptr->numunits) { /* too big? */ - printf ("Invalid unit number: %s%d\n", sim_dname (dptr), unitno); - return SCPE_INCOMP; } - READ_I (time); /* event time */ - uptr = (dptr->units) + unitno; - sim_cancel (uptr); - if (time > 0) sim_activate (uptr, time - 1); - READ_I (uptr->u3); /* device specific */ - READ_I (uptr->u4); - if (v30) { /* [V3.0+] */ - READ_I (uptr->u5); /* more dev specific */ - READ_I (uptr->u6); } - if (v210) { /* [V2.10+] */ - READ_I (flg); /* unit flags */ - uptr->flags = (uptr->flags & ~UNIT_RFLAGS) | - (flg & UNIT_RFLAGS); } /* restore */ - READ_S (buf); /* attached file */ - if (!(dptr->flags & DEV_NET) || /* if not net dev or */ - !(uptr->flags & UNIT_ATT) || /* not currently att */ - (buf[0] == 0)) { /* or will not be att */ - if (dptr->detach) r = dptr->detach (uptr); /* detach old */ - else r = detach_unit (uptr); - if (r != SCPE_OK) return r; - if (buf[0] != 0) { /* any file? */ - uptr->flags = uptr->flags & ~UNIT_DIS; - sim_switches = SIM_SW_REST; /* attach/rest */ - if (v210 && (flg & UNIT_RO)) /* saved flgs & RO? */ - sim_switches |= SWMASK ('R'); /* RO attach */ - if (dptr->attach != NULL) r = dptr->attach (uptr, buf); - else r = attach_unit (uptr, buf); - if (r != SCPE_OK) return r; } } - READ_I (high); /* memory capacity */ - if (high > 0) { /* [V2.5+] any memory? */ - if (((uptr->flags & (UNIT_FIX + UNIT_ATTABLE)) != UNIT_FIX) || - (dptr->deposit == NULL)) { - printf ("Can't restore memory: %s%d\n", sim_dname (dptr), unitno); - return SCPE_INCOMP; } - if (high != uptr->capac) { - if ((dptr->flags & DEV_DYNM) && - ((dptr->msize == NULL) || - (dptr->msize (uptr, (int32) high, NULL, NULL) != SCPE_OK))) { - printf ("Can't change memory size: %s%d\n", - sim_dname (dptr), unitno); - return SCPE_INCOMP; } - uptr->capac = high; - printf ("Memory size changed: %s%d = ", sim_dname (dptr), unitno); - fprint_capac (stdout, dptr, uptr); - printf ("\n"); } - sz = SZ_D (dptr); /* allocate buffer */ - if ((mbuf = calloc (SRBSIZ, sz)) == NULL) - return SCPE_MEM; - for (k = 0; k < high; ) { /* loop thru mem */ - READ_I (blkcnt); /* block count */ - if (blkcnt < 0) limit = -blkcnt; /* compressed? */ - else limit = fxread (mbuf, sz, blkcnt, rfile); - if (limit <= 0) return SCPE_IOERR; /* invalid or err? */ - for (j = 0; j < limit; j++, k = k + (dptr->aincr)) { - if (blkcnt < 0) val = 0; /* compressed? */ - else SZ_LOAD (sz, val, mbuf, j);/* saved value */ - r = dptr->deposit (val, k, uptr, 0); - if (r != SCPE_OK) return r; - } /* end for j */ - } /* end for k */ - free (mbuf); /* dealloc buffer */ - } /* end if high */ - } /* end unit loop */ - for ( ;; ) { /* register loop */ - READ_S (buf); /* read reg name */ - if (buf[0] == 0) break; /* last? */ - if (v210) { READ_I (depth); } /* [V2.10+] depth */ - if ((rptr = find_reg (buf, NULL, dptr)) == NULL) { - printf ("Invalid register name: %s %s\n", sim_dname (dptr), buf); - if (v210) { /* [V2.10]+ */ - for (us = 0; us < depth; us++) { /* skip values */ - READ_I (val); } } - else { - READ_I (val); /* must be one val */ - if (!restore_skip_val (rfile)) /* grope for next reg */ - return SCPE_INCOMP; } /* err or eof? */ - continue; } /* pray! */ - if (v210 && (depth != rptr->depth)) /* [V2.10+] mismatch? */ - printf ("Register depth mismatch: %s %s, file = %d, sim = %d\n", - sim_dname (dptr), buf, depth, rptr->depth); - else depth = rptr->depth; /* depth validated */ - mask = width_mask[rptr->width]; /* get mask */ - for (us = 0; us < depth; us++) { /* loop thru values */ - READ_I (val); /* read value */ - if (val > mask) /* value ok? */ - printf ("Invalid register value: %s %s\n", sim_dname (dptr), buf); - else if (us < rptr->depth) /* in range? */ - put_rval (rptr, us, val); } } - } /* end device loop */ -return SCPE_OK; -} - -/* Restore skip values (pre V2.10) - - To find the next register name, sift through bytes looking for valid - upper case ASCII characters terminated by \n */ - -t_bool restore_skip_val (FILE *rfile) -{ -t_bool instr = FALSE; -char c; -int32 ic, pos; - -if ((ic = fgetc (rfile)) == EOF) return FALSE; /* one char */ -fseek (rfile, ftell (rfile) - 1, SEEK_SET); /* back up over */ -if ((ic & 0377) == '\n') return TRUE; /* immediate nl? */ -while ((ic = fgetc (rfile)) != EOF) { /* get char */ - c = ic & 0377; /* cut to 8b */ - if (isalnum (c) || (c == '*') || (c == '_')) { /* valid reg char? */ - if (!instr) pos = ftell (rfile) - 1; /* new? save pos */ - instr = TRUE; } - else { /* not ASCII */ - if ((c == '\n') && instr) { /* nl & in string? */ - fseek (rfile, pos, SEEK_SET); /* rewind file */ - return TRUE; } - instr = FALSE; } /* not in string */ - } /* end while */ -return FALSE; /* error */ -} - -/* Run, go, cont, step commands - - ru[n] [new PC] reset and start simulation - go [new PC] start simulation - co[nt] start simulation - s[tep] [step limit] start simulation for 'limit' instructions - b[oot] device bootstrap from device and start simulation -*/ - -t_stat run_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; -uint32 i, j; -int32 step, unitno; -t_stat r; -DEVICE *dptr; -UNIT *uptr; -void int_handler (int signal); - -GET_SWITCHES (cptr); /* get switches */ -step = 0; -if (((flag == RU_RUN) || (flag == RU_GO)) && (*cptr != 0)) { /* run or go */ - cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ - if ((r = dep_reg (0, gbuf, sim_PC, 0)) != SCPE_OK) return r; } - -if (flag == RU_STEP) { /* step */ - if (*cptr == 0) step = 1; - else { - cptr = get_glyph (cptr, gbuf, 0); - step = (int32) get_uint (gbuf, 10, INT_MAX, &r); - if ((r != SCPE_OK) || (step == 0)) return SCPE_ARG; } } - -if (flag == RU_BOOT) { /* boot */ - if (*cptr == 0) return SCPE_2FARG; /* must be more */ - cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ - dptr = find_unit (gbuf, &uptr); /* locate unit */ - if (dptr == NULL) return SCPE_NXDEV; /* found dev? */ - if (uptr == NULL) return SCPE_NXUN; /* valid unit? */ - if (dptr->boot == NULL) return SCPE_NOFNC; /* can it boot? */ - if (uptr->flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ - if ((uptr->flags & UNIT_ATTABLE) && - !(uptr->flags & UNIT_ATT)) return SCPE_UNATT; - unitno = uptr - dptr->units; /* recover unit# */ - if ((r = dptr->boot (unitno, dptr)) != SCPE_OK) return r; } - -if (*cptr != 0) return SCPE_2MARG; /* now eol? */ - -if ((flag == RU_RUN) || (flag == RU_BOOT)) { /* run or boot */ - sim_interval = 0; /* reset queue */ - sim_time = sim_rtime = 0; - noqueue_time = 0; - sim_clock_queue = NULL; - if ((r = reset_all (0)) != SCPE_OK) return r; } -for (i = 1; (dptr = sim_devices[i]) != NULL; i++) { - for (j = 0; j < dptr->numunits; j++) { - uptr = dptr->units + j; - if ((uptr->flags & (UNIT_ATT + UNIT_SEQ)) == - (UNIT_ATT + UNIT_SEQ)) - fseek_ext (uptr->fileref, uptr->pos, SEEK_SET); } } -stop_cpu = 0; -if (signal (SIGINT, int_handler) == SIG_ERR) { /* set WRU */ - return SCPE_SIGERR; } -if (ttrunstate () != SCPE_OK) { /* set console mode */ - ttcmdstate (); - return SCPE_TTYERR; } -if ((r = sim_check_console (30)) != SCPE_OK) { /* check console, error? */ - ttcmdstate (); - return r; } -if (step) sim_activate (&step_unit, step); /* set step timer */ -sim_is_running = 1; /* flag running */ -sim_brk_clract (); /* defang actions */ -r = sim_instr(); - -sim_is_running = 0; /* flag idle */ -ttcmdstate (); /* restore console */ -signal (SIGINT, SIG_DFL); /* cancel WRU */ -sim_cancel (&step_unit); /* cancel step timer */ -if (sim_clock_queue != NULL) { /* update sim time */ - UPDATE_SIM_TIME (sim_clock_queue->time); } -else { UPDATE_SIM_TIME (noqueue_time); } -#if defined (VMS) -printf ("\n"); -#endif -fprint_stopped (stdout, r); /* print msg */ -if (sim_log) fprint_stopped (sim_log, r); /* log if enabled */ -return SCPE_OK; -} - -/* Print stopped message */ - -void fprint_stopped (FILE *stream, t_stat v) -{ -int32 i; -t_stat r; -t_addr k; -t_value pcval; -DEVICE *dptr; - -if (v >= SCPE_BASE) fprintf (stream, "\n%s, %s: ", - scp_error_messages[v - SCPE_BASE], sim_PC->name); -else fprintf (stream, "\n%s, %s: ", sim_stop_messages[v], sim_PC->name); -pcval = get_rval (sim_PC, 0); -fprint_val (stream, pcval, sim_PC->radix, sim_PC->width, - sim_PC->flags & REG_FMT); -if (((dptr = sim_devices[0]) != NULL) && (dptr->examine != NULL)) { - for (i = 0; i < sim_emax; i++) sim_eval[i] = 0; - for (i = 0, k = (t_addr) pcval; i < sim_emax; i++, k = k + dptr->aincr) { - if ((r = dptr->examine (&sim_eval[i], k, dptr->units, - SWMASK ('V'))) != SCPE_OK) break; } - if ((r == SCPE_OK) || (i > 0)) { - fprintf (stream, " ("); - if (fprint_sym (stream, (t_addr) pcval, sim_eval, NULL, SWMASK('M')) > 0) - fprint_val (stream, sim_eval[0], dptr->dradix, - dptr->dwidth, PV_RZRO); - fprintf (stream, ")"); } } -fprintf (stream, "\n"); -return; -} - -/* Unit service for step timeout, originally scheduled by STEP n command - - Return step timeout SCP code, will cause simulation to stop -*/ - -t_stat step_svc (UNIT *uptr) -{ -return SCPE_STEP; -} - -/* Signal handler for ^C signal - - Set stop simulation flag -*/ - -void int_handler (int sig) -{ -stop_cpu = 1; -return; -} - -/* Examine/deposit commands - - ex[amine] [modifiers] list examine - de[posit] [modifiers] list val deposit - ie[xamine] [modifiers] list interactive examine - id[eposit] [modifiers] list interactive deposit - - modifiers - @filename output file - -letter(s) switches - devname'n device name and unit number - [{&|^}value]{=|==|!|!=|>|>=|<|<=} value search specification - - list list of addresses and registers - addr[:addr|-addr] address range - ALL all addresses - register[:register|-register] register range - STATE all registers -*/ - -t_stat exdep_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE], *gptr, *tptr; -int32 t; -t_bool exd2f; -t_addr low, high; -t_stat reason; -DEVICE *dptr, *tdptr; -UNIT *uptr, *tuptr; -REG *lowr, *highr; -SCHTAB stab, *schptr; -FILE *ofile; - -ofile = NULL; /* no output file */ -exd2f = FALSE; -sim_switches = 0; /* no switches */ -schptr = NULL; /* no search */ -stab.logic = SCH_OR; /* default search params */ -stab.bool = SCH_GE; -stab.mask = stab.comp = 0; -dptr = sim_devices[0]; /* default device, unit */ -uptr = dptr->units; -for (;;) { /* loop through modifiers */ - if (*cptr == 0) return SCPE_2FARG; /* must be more */ - if (*cptr == '@') { /* output file spec? */ - if (flag != EX_E) return SCPE_ARG; /* examine only */ - if (exd2f) { /* already got one? */ - fclose (ofile); /* one per customer */ - return SCPE_ARG; } - cptr = get_glyph_nc (cptr + 1, gbuf, 0); - ofile = FOPEN (gbuf, "a"); /* open for append */ - if (ofile == NULL) return SCPE_OPENERR; - exd2f = TRUE; - continue; } /* look for more */ - cptr = get_glyph (cptr, gbuf, 0); - if ((t = get_switches (gbuf)) != 0) { /* try for switches */ - if (t < 0) return SCPE_INVSW; /* err if bad switch */ - sim_switches = sim_switches | t; } /* or in new switches */ - else if (get_search (gbuf, dptr, &stab) != NULL) { /* try for search */ - schptr = &stab; } /* set search */ - else if (((tdptr = find_unit (gbuf, &tuptr)) != NULL) && - (tuptr != NULL)) { /* try for unit */ - dptr = tdptr; /* set as default */ - uptr = tuptr; } - else break; } /* not rec, break out */ -if (uptr == NULL) return SCPE_NXUN; /* got a unit? */ -if ((*cptr == 0) == (flag == 0)) return SCPE_ARG; /* eol if needed? */ - -if (ofile == NULL) ofile = stdout; /* no file? stdout */ -for (gptr = gbuf, reason = SCPE_OK; - (*gptr != 0) && (reason == SCPE_OK); gptr = tptr) { - tdptr = dptr; /* working dptr */ - if (strncmp (gptr, "STATE", strlen ("STATE")) == 0) { - tptr = gptr + strlen ("STATE"); - if (*tptr && (*tptr++ != ',')) return SCPE_ARG; - if ((lowr = dptr->registers) == NULL) return SCPE_NXREG; - for (highr = lowr; highr->name != NULL; highr++) ; - sim_switches = sim_switches | SIM_SW_HIDE; - reason = exdep_reg_loop (ofile, schptr, flag, cptr, - lowr, --highr, 0, 0); - continue; } - - if ((lowr = find_reg (gptr, &tptr, tdptr)) || - (lowr = find_reg_glob (gptr, &tptr, &tdptr))) { - low = high = 0; - if ((*tptr == '-') || (*tptr == ':')) { - highr = find_reg (tptr + 1, &tptr, tdptr); - if (highr == NULL) return SCPE_NXREG; } - else { - highr = lowr; - if (*tptr == '[') { - if (lowr->depth <= 1) return SCPE_ARG; - tptr = get_range (tptr + 1, &low, &high, - 10, lowr->depth - 1, ']'); - if (tptr == NULL) return SCPE_ARG; } } - if (*tptr && (*tptr++ != ',')) return SCPE_ARG; - reason = exdep_reg_loop (ofile, schptr, flag, cptr, - lowr, highr, (uint32) low, (uint32) high); - continue; } - - tptr = get_range (gptr, &low, &high, dptr->aradix, - (((uptr->capac == 0) || (flag == EX_E))? 0: - uptr->capac - dptr->aincr), 0); - if (tptr == NULL) return SCPE_ARG; - if (*tptr && (*tptr++ != ',')) return SCPE_ARG; - reason = exdep_addr_loop (ofile, schptr, flag, cptr, low, high, - dptr, uptr); - } /* end for */ -if (exd2f) fclose (ofile); /* close output file */ -return reason; -} - -/* Loop controllers for examine/deposit - - exdep_reg_loop examine/deposit range of registers - exdep_addr_loop examine/deposit range of addresses -*/ - -t_stat exdep_reg_loop (FILE *ofile, SCHTAB *schptr, int32 flag, char *cptr, - REG *lowr, REG *highr, uint32 lows, uint32 highs) -{ -t_stat reason; -uint32 idx; -t_value val; -REG *rptr; - -if ((lowr == NULL) || (highr == NULL)) return SCPE_IERR; -if (lowr > highr) return SCPE_ARG; -for (rptr = lowr; rptr <= highr; rptr++) { - if ((sim_switches & SIM_SW_HIDE) && - (rptr->flags & REG_HIDDEN)) continue; - for (idx = lows; idx <= highs; idx++) { - if (idx >= rptr->depth) return SCPE_SUB; - val = get_rval (rptr, idx); - if (schptr && !test_search (val, schptr)) continue; - if (flag != EX_D) { - reason = ex_reg (ofile, val, flag, rptr, idx); - if (reason != SCPE_OK) return reason; - if (sim_log && (ofile == stdout)) - ex_reg (sim_log, val, flag, rptr, idx); } - if (flag != EX_E) { - reason = dep_reg (flag, cptr, rptr, idx); - if (reason != SCPE_OK) return reason; } } } -return SCPE_OK; -} - -t_stat exdep_addr_loop (FILE *ofile, SCHTAB *schptr, int32 flag, char *cptr, - t_addr low, t_addr high, DEVICE *dptr, UNIT *uptr) -{ -t_addr i, mask; -t_stat reason; - -if (uptr->flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ -mask = (t_addr) width_mask[dptr->awidth]; -if ((low > mask) || (high > mask) || (low > high)) return SCPE_ARG; -for (i = low; i <= high; i = i + (dptr->aincr)) { - if ((flag & EX_E) || schptr) { /* examine or search? */ - reason = get_aval (i, dptr, uptr); /* get data */ - if (reason != SCPE_OK) return reason; /* return if error */ - if (schptr && !test_search (sim_eval[0], schptr)) continue; } - if (flag != EX_D) { - reason = ex_addr (ofile, flag, i, dptr, uptr); - if (reason > SCPE_OK) return reason; - if (sim_log && (ofile == stdout)) - ex_addr (sim_log, flag, i, dptr, uptr); } - if (flag != EX_E) { - reason = dep_addr (flag, cptr, i, dptr, uptr, reason); - if (reason > SCPE_OK) return reason; } - if (reason < SCPE_OK) i = i + ((-reason) * dptr->aincr); } -return SCPE_OK; -} - -/* Examine register routine - - Inputs: - ofile = output stream - val = current register value - flag = type of ex/mod command (ex, iex, idep) - rptr = pointer to register descriptor - idx = index - Outputs: - return = error status -*/ - -t_stat ex_reg (FILE *ofile, t_value val, int32 flag, REG *rptr, uint32 idx) -{ -int32 rdx; - -if (rptr == NULL) return SCPE_IERR; -if (rptr->depth > 1) fprintf (ofile, "%s[%d]: ", rptr->name, idx); -else fprintf (ofile, "%s: ", rptr->name); -if (!(flag & EX_E)) return SCPE_OK; -GET_RADIX (rdx, rptr->radix); -if (rptr->flags & REG_VMIO) - fprint_sym (ofile, rdx, &val, NULL, REG_VMIO); -else fprint_val (ofile, val, rdx, rptr->width, rptr->flags & REG_FMT); -if (flag & EX_I) fprintf (ofile, " "); -else fprintf (ofile, "\n"); -return SCPE_OK; -} - -/* Get register value - - Inputs: - rptr = pointer to register descriptor - idx = index - Outputs: - return = register value -*/ - -t_value get_rval (REG *rptr, uint32 idx) -{ -size_t sz; -t_value val; -UNIT *uptr; - -sz = SZ_R (rptr); -if ((rptr->depth > 1) && (rptr->flags & REG_CIRC)) { - idx = idx + rptr->qptr; - if (idx >= rptr->depth) idx = idx - rptr->depth; } -if ((rptr->depth > 1) && (rptr->flags & REG_UNIT)) { - uptr = ((UNIT *) rptr->loc) + idx; -#if defined (t_int64) - if (sz <= sizeof (uint32)) val = *((uint32 *) uptr); - else val = *((t_uint64 *) uptr); } -#else - val = *((uint32 *) uptr); } -#endif -else if ((rptr->depth > 1) && (sz == sizeof (uint8))) - val = *(((uint8 *) rptr->loc) + idx); -else if ((rptr->depth > 1) && (sz == sizeof (uint16))) - val = *(((uint16 *) rptr->loc) + idx); -#if defined (t_int64) -else if (sz <= sizeof (uint32)) - val = *(((uint32 *) rptr->loc) + idx); -else val = *(((t_uint64 *) rptr->loc) + idx); -#else -else val = *(((uint32 *) rptr->loc) + idx); -#endif -val = (val >> rptr->offset) & width_mask[rptr->width]; -return val; -} - -/* Deposit register routine - - Inputs: - flag = type of deposit (normal/interactive) - cptr = pointer to input string - rptr = pointer to register descriptor - idx = index - Outputs: - return = error status -*/ - -t_stat dep_reg (int32 flag, char *cptr, REG *rptr, uint32 idx) -{ -t_stat r; -t_value val, mask; -int32 rdx; -char gbuf[CBUFSIZE]; - -if ((cptr == NULL) || (rptr == NULL)) return SCPE_IERR; -if (rptr->flags & REG_RO) return SCPE_RO; -if (flag & EX_I) { - cptr = read_line (gbuf, CBUFSIZE, stdin); - if (sim_log) fprintf (sim_log, (cptr? "%s\n": "\n"), cptr); - if (cptr == NULL) return 1; /* force exit */ - if (*cptr == 0) return SCPE_OK; } /* success */ -mask = width_mask[rptr->width]; -GET_RADIX (rdx, rptr->radix); -if (rptr->flags & REG_VMIO) - r = parse_sym (cptr, rdx, NULL, &val, REG_VMIO); -else val = get_uint (cptr, rdx, mask, &r); -if (r != SCPE_OK) return SCPE_ARG; -if ((rptr->flags & REG_NZ) && (val == 0)) return SCPE_ARG; -put_rval (rptr, idx, val); -return SCPE_OK; -} - -/* Put register value - - Inputs: - rptr = pointer to register descriptor - idx = index - val = new value - mask = mask - Outputs: - none -*/ - -void put_rval (REG *rptr, uint32 idx, t_value val) -{ -size_t sz; -t_value mask; -UNIT *uptr; - -#define PUT_RVAL(sz,rp,id,v,m) \ - *(((sz *) rp->loc) + id) = \ - (*(((sz *) rp->loc) + id) & \ - ~((m) << (rp)->offset)) | ((v) << (rp)->offset) - -if (rptr == sim_PC) sim_brk_npc (); -sz = SZ_R (rptr); -mask = width_mask[rptr->width]; -if ((rptr->depth > 1) && (rptr->flags & REG_CIRC)) { - idx = idx + rptr->qptr; - if (idx >= rptr->depth) idx = idx - rptr->depth; } -if ((rptr->depth > 1) && (rptr->flags & REG_UNIT)) { - uptr = ((UNIT *) rptr->loc) + idx; -#if defined (t_int64) - if (sz <= sizeof (uint32)) - *((uint32 *) uptr) = (*((uint32 *) uptr) & - ~(((uint32) mask) << rptr->offset)) | - (((uint32) val) << rptr->offset); - else *((t_uint64 *) uptr) = (*((t_uint64 *) uptr) - & ~(mask << rptr->offset)) | (val << rptr->offset); } -#else - *((uint32 *) uptr) = (*((uint32 *) uptr) & - ~(((uint32) mask) << rptr->offset)) | - (((uint32) val) << rptr->offset); } -#endif -else if ((rptr->depth > 1) && (sz == sizeof (uint8))) - PUT_RVAL (uint8, rptr, idx, (uint32) val, (uint32) mask); -else if ((rptr->depth > 1) && (sz == sizeof (uint16))) - PUT_RVAL (uint16, rptr, idx, (uint32) val, (uint32) mask); -#if defined (t_int64) -else if (sz <= sizeof (uint32)) - PUT_RVAL (uint32, rptr, idx, (int32) val, (uint32) mask); -else PUT_RVAL (t_uint64, rptr, idx, val, mask); -#else -else PUT_RVAL (uint32, rptr, idx, val, mask); -#endif -return; -} - -/* Examine address routine - - Inputs: (sim_eval is an implicit argument) - ofile = output stream - flag = type of ex/mod command (ex, iex, idep) - addr = address to examine - dptr = pointer to device - uptr = pointer to unit - Outputs: - return = if >= 0, error status - if < 0, number of extra words retired -*/ - -t_stat ex_addr (FILE *ofile, int32 flag, t_addr addr, DEVICE *dptr, UNIT *uptr) -{ -t_stat reason; -int32 rdx; - -fprint_val (ofile, addr, dptr->aradix, dptr->awidth, PV_LEFT); -fprintf (ofile, ": "); -if (!(flag & EX_E)) return SCPE_OK; - -GET_RADIX (rdx, dptr->dradix); -if ((reason = fprint_sym (ofile, addr, sim_eval, uptr, sim_switches)) > 0) - reason = fprint_val (ofile, sim_eval[0], rdx, dptr->dwidth, PV_RZRO); -if (flag & EX_I) fprintf (ofile, " "); -else fprintf (ofile, "\n"); -return reason; -} - -/* Get address routine - - Inputs: - flag = type of ex/mod command (ex, iex, idep) - addr = address to examine - dptr = pointer to device - uptr = pointer to unit - Outputs: (sim_eval is an implicit output) - return = error status -*/ - -t_stat get_aval (t_addr addr, DEVICE *dptr, UNIT *uptr) -{ -int32 i; -t_value mask; -t_addr j, loc; -size_t sz; -t_stat reason = SCPE_OK; - -if ((dptr == NULL) || (uptr == NULL)) return SCPE_IERR; -mask = width_mask[dptr->dwidth]; -for (i = 0; i < sim_emax; i++) sim_eval[i] = 0; -for (i = 0, j = addr; i < sim_emax; i++, j = j + dptr->aincr) { - if (dptr->examine != NULL) { - reason = dptr->examine (&sim_eval[i], j, uptr, sim_switches); - if (reason != SCPE_OK) break; } - else { - if (!(uptr->flags & UNIT_ATT)) return SCPE_UNATT; - if ((uptr->flags & UNIT_FIX) && (j >= uptr->capac)) { - reason = SCPE_NXM; - break; } - sz = SZ_D (dptr); - loc = j / dptr->aincr; - if (uptr->flags & UNIT_BUF) { - SZ_LOAD (sz, sim_eval[i], uptr->filebuf, loc); } - else { - fseek_ext (uptr->fileref, sz * loc, SEEK_SET); - fxread (&sim_eval[i], sz, 1, uptr->fileref); - if ((feof (uptr->fileref)) && - !(uptr->flags & UNIT_FIX)) { - reason = SCPE_EOF; - break; } - else if (ferror (uptr->fileref)) { - clearerr (uptr->fileref); - reason = SCPE_IOERR; - break; } } } - sim_eval[i] = sim_eval[i] & mask; } -if ((reason != SCPE_OK) && (i == 0)) return reason; -return SCPE_OK; -} - -/* Deposit address routine - - Inputs: - flag = type of deposit (normal/interactive) - cptr = pointer to input string - addr = address to examine - dptr = pointer to device - uptr = pointer to unit - dfltinc = value to return on cr input - Outputs: - return = if >= 0, error status - if < 0, number of extra words retired -*/ - -t_stat dep_addr (int32 flag, char *cptr, t_addr addr, DEVICE *dptr, - UNIT *uptr, int32 dfltinc) -{ -int32 i, count, rdx; -t_addr j, loc; -t_stat r, reason; -t_value mask; -size_t sz; -char gbuf[CBUFSIZE]; - -if (dptr == NULL) return SCPE_IERR; -if (flag & EX_I) { - cptr = read_line (gbuf, CBUFSIZE, stdin); - if (sim_log) fprintf (sim_log, (cptr? "%s\n": "\n"), cptr); - if (cptr == NULL) return 1; /* force exit */ - if (*cptr == 0) return dfltinc; } /* success */ -if (uptr->flags & UNIT_RO) return SCPE_RO; /* read only? */ -mask = width_mask[dptr->dwidth]; - -GET_RADIX (rdx, dptr->dradix); -if ((reason = parse_sym (cptr, addr, uptr, sim_eval, sim_switches)) > 0) { - sim_eval[0] = get_uint (cptr, rdx, mask, &reason); - if (reason != SCPE_OK) return reason; } -count = 1 - reason; - -for (i = 0, j = addr; i < count; i++, j = j + dptr->aincr) { - sim_eval[i] = sim_eval[i] & mask; - if (dptr->deposit != NULL) { - r = dptr->deposit (sim_eval[i], j, uptr, sim_switches); - if (r != SCPE_OK) return r; } - else { - if (!(uptr->flags & UNIT_ATT)) return SCPE_UNATT; - if ((uptr->flags & UNIT_FIX) && (j >= uptr->capac)) - return SCPE_NXM; - sz = SZ_D (dptr); - loc = j / dptr->aincr; - if (uptr->flags & UNIT_BUF) { - SZ_STORE (sz, sim_eval[i], uptr->filebuf, loc); - if (loc >= uptr->hwmark) uptr->hwmark = (uint32) loc + 1; } - else { - fseek_ext (uptr->fileref, sz * loc, SEEK_SET); - fxwrite (&sim_eval[i], sz, 1, uptr->fileref); - if (ferror (uptr->fileref)) { - clearerr (uptr->fileref); - return SCPE_IOERR; } } } } -return reason; -} - -/* Evaluate command */ - -t_stat eval_cmd (int32 flg, char *cptr) -{ -DEVICE *dptr = sim_devices[0]; -int32 i, count, rdx; -t_stat r; - -GET_SWITCHES (cptr); -GET_RADIX (rdx, dptr->dradix); -for (i = 0; i < sim_emax; i++) sim_eval[i] = 0; -if (*cptr == 0) return SCPE_2FARG; -if ((r = parse_sym (cptr, 0, dptr->units, sim_eval, sim_switches)) > 0) { - sim_eval[0] = get_uint (cptr, rdx, width_mask[dptr->dwidth], &r); - if (r != SCPE_OK) return r; } -count = 1 - r; -for (i = 0; count > 0; i++, count = count - dptr->aincr) { - printf ("%d:\t", i); - if ((r = fprint_sym (stdout, 0, &sim_eval[i], dptr->units, sim_switches)) > 0) - r = fprint_val (stdout, sim_eval[i], rdx, dptr->dwidth, PV_RZRO); - printf ("\n"); - if (sim_log) { - fprintf (sim_log, "%d\t", i); - if ((r = fprint_sym (sim_log, 0, &sim_eval[i], dptr->units, sim_switches)) > 0) - r = fprint_val (sim_log, sim_eval[i], rdx, dptr->dwidth, PV_RZRO); - fprintf (sim_log, "\n"); } - if (r < 0) { - i = i - r; - count = count + (r * dptr->aincr); } - } -return SCPE_OK; -} - -/* String processing routines - - read_line read line - - Inputs: - cptr = pointer to buffer - size = maximum size - stream = pointer to input stream - Outputs: - optr = pointer to first non-blank character - NULL if EOF -*/ - -char *read_line (char *cptr, int32 size, FILE *stream) -{ -char *tptr; - -cptr = fgets (cptr, size, stream); /* get cmd line */ -if (cptr == NULL) { - clearerr (stream); /* clear error */ - return NULL; } /* ignore EOF */ -for (tptr = cptr; tptr < (cptr + size); tptr++) /* remove cr or nl */ - if ((*tptr == '\n') || (*tptr == '\r')) *tptr = 0; -while (isspace (*cptr)) cptr++; /* absorb spaces */ -if (*cptr == ';') *cptr = 0; /* ignore comment */ -return cptr; -} - -/* get_glyph get next glyph (force upper case) - get_glyph_nc get next glyph (no conversion) - get_glyph_gen get next glyph (general case) - - Inputs: - iptr = pointer to input string - optr = pointer to output string - mchar = optional end of glyph character - flag = TRUE for convert to upper case (_gen only) - Outputs - result = pointer to next character in input string -*/ - -char *get_glyph_gen (char *iptr, char *optr, char mchar, t_bool uc) -{ -while ((isspace (*iptr) == 0) && (*iptr != 0) && (*iptr != mchar)) { - if (islower (*iptr) && uc) *optr = toupper (*iptr); - else *optr = *iptr; - iptr++; optr++; } -*optr = 0; -if (mchar && (*iptr == mchar)) iptr++; /* skip terminator */ -while (isspace (*iptr)) iptr++; /* absorb spaces */ -return iptr; -} - -char *get_glyph (char *iptr, char *optr, char mchar) -{ -return get_glyph_gen (iptr, optr, mchar, TRUE); -} - -char *get_glyph_nc (char *iptr, char *optr, char mchar) -{ -return get_glyph_gen (iptr, optr, mchar, FALSE); -} - -/* get_yn yes/no question - - Inputs: - cptr = pointer to question - deflt = default answer - Outputs: - result = true if yes, false if no -*/ - -t_stat get_yn (char *ques, t_stat deflt) -{ -char cbuf[CBUFSIZE], *cptr; - -printf ("%s ", ques); -cptr = read_line (cbuf, CBUFSIZE, stdin); -if ((cptr == NULL) || (*cptr == 0)) return deflt; -if ((*cptr == 'Y') || (*cptr == 'y')) return TRUE; -return FALSE; -} - -/* get_uint unsigned number - - Inputs: - cptr = pointer to input string - radix = input radix - max = maximum acceptable value - *status = pointer to error status - Outputs: - val = value -*/ - -t_value get_uint (char *cptr, uint32 radix, t_value max, t_stat *status) -{ -t_value val; -char *tptr; - -*status = SCPE_OK; -val = strtotv (cptr, &tptr, radix); -if ((cptr == tptr) || (val > max)) *status = SCPE_ARG; -else { while (isspace (*tptr)) tptr++; - if (*tptr != 0) *status = SCPE_ARG; } -return val; -} - -/* get_range range specification - - Inputs: - cptr = pointer to input string - *lo = pointer to low result - *hi = pointer to high result - aradix = address radix - max = default high value - term = terminating character, 0 if none - Outputs: - tptr = input pointer after processing - NULL if error -*/ - -char *get_range (char *cptr, t_addr *lo, t_addr *hi, uint32 rdx, - t_addr max, char term) -{ -char *tptr; - -if (max && strncmp (cptr, "ALL", strlen ("ALL")) == 0) { /* ALL? */ - tptr = cptr + strlen ("ALL"); - *lo = 0; - *hi = max; } -else { *lo = (t_addr) strtotv (cptr, &tptr, rdx); /* get low */ - if (cptr == tptr) return NULL; /* error? */ - if ((*tptr == '-') || (*tptr == ':')) { /* range? */ - cptr = tptr + 1; - *hi = (t_addr) strtotv (cptr, &tptr, rdx); /* get high */ - if (cptr == tptr) return NULL; - if (*lo > *hi) return NULL; } - else if (*tptr == '/') { /* relative? */ - cptr = tptr + 1; - *hi = (t_addr) strtotv (cptr, &tptr, rdx); /* get high */ - if ((cptr == tptr) || (*hi == 0)) return NULL; - *hi = *lo + *hi - 1; } - else *hi = *lo; } -if (term && (*tptr++ != term)) return NULL; -return tptr; -} - -/* get_ipaddr IP address:port - - Inputs: - cptr = pointer to input string - Outputs: - ipa = pointer to IP address (may be NULL), 0 = none - ipp = pointer to IP port (may be NULL) - result = status -*/ - -t_stat get_ipaddr (char *cptr, uint32 *ipa, uint32 *ipp) -{ -char gbuf[CBUFSIZE]; -char *addrp, *portp, *octetp; -uint32 i, addr, port, octet; -t_stat r; - -if ((cptr == NULL) || (*cptr == 0) || (ipa == NULL) || (ipp == NULL)) - return SCPE_ARG; -strncpy (gbuf, cptr, CBUFSIZE); -addrp = gbuf; /* default addr */ -if (portp = strchr (gbuf, ':')) *portp++ = '.'; /* x:y? */ -else if (strchr (gbuf, '.')) portp = NULL; /* x.y...? */ -else { portp = gbuf; /* port only */ - addrp = NULL; } /* x is port */ -if (portp) { /* port string? */ - port = (int32) get_uint (portp, 10, 65535, &r); - if ((r != SCPE_OK) || (port == 0)) return SCPE_ARG; - *ipp = port; } -else *ipp = 0; -if (addrp) { - for (i = addr = 0; i < 4; i++) { - octetp = strchr (addrp, '.'); - if (octetp == NULL) return SCPE_ARG; - *octetp++ = 0; - octet = (int32) get_uint (addrp, 10, 255, &r); - if (r != SCPE_OK) return SCPE_ARG; - addr = (addr << 8) | octet; - addrp = octetp; } - if (((addr & 0377) == 0) || ((addr & 0377) == 255)) - return SCPE_ARG; - *ipa = addr; } -else *ipa = 0; -return SCPE_OK; -} - -/* Find_device find device matching input string - - Inputs: - cptr = pointer to input string - Outputs: - result = pointer to device -*/ - -DEVICE *find_dev (char *cptr) -{ -int32 i; -DEVICE *dptr; - -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { - if ((strcmp (cptr, dptr->name) == 0) || - (dptr->lname && - (strcmp (cptr, dptr->lname) == 0))) return dptr; } -return NULL; -} - -/* Find_unit find unit matching input string - - Inputs: - cptr = pointer to input string - uptr = pointer to unit pointer - Outputs: - result = pointer to device (null if no dev) - *iptr = pointer to unit (null if nx unit) -*/ - -DEVICE *find_unit (char *cptr, UNIT **uptr) -{ -uint32 i, u; -char *nptr, *tptr; -t_stat r; -DEVICE *dptr; - -if (uptr == NULL) return NULL; /* arg error? */ -if (dptr = find_dev (cptr)) { /* exact match? */ - if (qdisable (dptr)) return NULL; /* disabled? */ - *uptr = dptr->units; /* unit 0 */ - return dptr; } - -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* base + unit#? */ - if (dptr->numunits && /* any units? */ - (((nptr = dptr->name) && - (strncmp (cptr, nptr, strlen (nptr)) == 0)) || - ((nptr = dptr->lname) && - (strncmp (cptr, nptr, strlen (nptr)) == 0)))) { - tptr = cptr + strlen (nptr); - if (isdigit (*tptr)) { - if (qdisable (dptr)) return NULL; /* disabled? */ - u = (uint32) get_uint (tptr, 10, dptr->numunits - 1, &r); - if (r != SCPE_OK) *uptr = NULL; /* error? */ - else *uptr = dptr->units + u; - return dptr; } } } -return NULL; -} - -/* Find_dev_from_unit find device for unit - - Inputs: - uptr = pointer to unit - Outputs: - result = pointer to device -*/ - -DEVICE *find_dev_from_unit (UNIT *uptr) -{ -DEVICE *dptr; -uint32 i, j; - -if (uptr == NULL) return NULL; -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { - for (j = 0; j < dptr->numunits; j++) { - if (uptr == (dptr->units + j)) return dptr; } } -return NULL; -} - -/* Test for disabled device */ - -t_bool qdisable (DEVICE *dptr) -{ -return (dptr->flags & DEV_DIS? TRUE: FALSE); -} - -/* find_reg_glob find globally unique register - - Inputs: - cptr = pointer to input string - optr = pointer to output pointer (can be null) - gdptr = pointer to global device - Outputs: - result = pointer to register, NULL if error - *optr = pointer to next character in input string - *gdptr = pointer to device where found -*/ - -REG *find_reg_glob (char *cptr, char **optr, DEVICE **gdptr) -{ -int32 i; -DEVICE *dptr; -REG *rptr, *srptr = NULL; - -for (i = 0; (dptr = sim_devices[i]) != 0; i++) { /* all dev */ - if (rptr = find_reg (cptr, optr, dptr)) { /* found? */ - if (srptr) return NULL; /* ambig? err */ - srptr = rptr; /* save reg */ - *gdptr = dptr; } } /* save unit */ -return srptr; -} - -/* find_reg find register matching input string - - Inputs: - cptr = pointer to input string - optr = pointer to output pointer (can be null) - dptr = pointer to device - Outputs: - result = pointer to register, NULL if error - *optr = pointer to next character in input string -*/ - -REG *find_reg (char *cptr, char **optr, DEVICE *dptr) -{ -char *tptr; -REG *rptr; -uint32 slnt; - -if ((cptr == NULL) || (dptr == NULL) || - (dptr->registers == NULL)) return NULL; -tptr = cptr; -do { tptr++; } - while (isalnum (*tptr) || (*tptr == '*') || (*tptr == '_')); -slnt = tptr - cptr; -for (rptr = dptr->registers; rptr->name != NULL; rptr++) { - if ((slnt == strlen (rptr->name)) && - (strncmp (cptr, rptr->name, slnt) == 0)) { - if (optr != NULL) *optr = tptr; - return rptr; } } -return NULL; -} - -/* get_switches get switches from input string - - Inputs: - cptr = pointer to input string - Outputs: - sw = switch bit mask - 0 if no switches, -1 if error -*/ - -int32 get_switches (char *cptr) -{ -int32 sw; - -if (*cptr != '-') return 0; -sw = 0; -for (cptr++; (isspace (*cptr) == 0) && (*cptr != 0); cptr++) { - if (isalpha (*cptr) == 0) return -1; - sw = sw | SWMASK (toupper (*cptr)); } -return sw; -} - -/* get_sim_sw accumulate sim_switches - - Inputs: - cptr = pointer to input string - Outputs: - ptr = pointer to first non-string glyph - NULL if error -*/ - -char *get_sim_sw (char *cptr) -{ -int32 lsw; -char gbuf[CBUFSIZE]; - -while (*cptr == '-') { /* while switches */ - cptr = get_glyph (cptr, gbuf, 0); /* get switch glyph */ - lsw = get_switches (gbuf); /* parse */ - if (lsw <= 0) return NULL; /* invalid? */ - sim_switches = sim_switches | lsw; } /* accumulate */ -return cptr; -} - -/* Match file extension - - Inputs: - fnam = file name - ext = extension, without period - Outputs: - cp = pointer to final '.' if match, NULL if not -*/ - -char *match_ext (char *fnam, char *ext) -{ -char *pptr, *fptr, *eptr; - -if ((fnam == NULL) || (ext == NULL)) return NULL; -pptr = strrchr (fnam, '.'); -if (pptr) { - for (fptr = pptr + 1, eptr = ext; *fptr; fptr++, eptr++) { - if (toupper (*fptr) != toupper (*eptr)) return NULL; } - if (*eptr) return NULL; } -return pptr; -} - -/* Get search specification - - Inputs: - cptr = pointer to input string - dptr = pointer to device - schptr = pointer to search table - Outputs: - return = NULL if error - schptr if valid search specification -*/ - -SCHTAB *get_search (char *cptr, DEVICE *dptr, SCHTAB *schptr) -{ -int32 c, logop, cmpop; -t_value logval, cmpval; -char *sptr, *tptr; -const char logstr[] = "|&^", cmpstr[] = "=!><"; - -if (*cptr == 0) return NULL; /* check for clause */ -for (logop = cmpop = -1; c = *cptr++; ) { /* loop thru clauses */ - if (sptr = strchr (logstr, c)) { /* check for mask */ - logop = sptr - logstr; - logval = strtotv (cptr, &tptr, dptr->dradix); - if (cptr == tptr) return NULL; - cptr = tptr; } - else if (sptr = strchr (cmpstr, c)) { /* check for bool */ - cmpop = sptr - cmpstr; - if (*cptr == '=') { - cmpop = cmpop + strlen (cmpstr); - cptr++; } - cmpval = strtotv (cptr, &tptr, dptr->dradix); - if (cptr == tptr) return NULL; - cptr = tptr; } - else return NULL; } /* end while */ -if (logop >= 0) { - schptr->logic = logop; - schptr->mask = logval; } -if (cmpop >= 0) { - schptr->bool = cmpop; - schptr->comp = cmpval; } -return schptr; -} - -/* Test value against search specification - - Inputs: - val = value to test - schptr = pointer to search table - Outputs: - return = 1 if value passes search criteria, 0 if not -*/ - -int32 test_search (t_value val, SCHTAB *schptr) -{ -if (schptr == NULL) return 0; -switch (schptr->logic) { /* case on logical */ -case SCH_OR: - val = val | schptr->mask; - break; -case SCH_AND: - val = val & schptr->mask; - break; -case SCH_XOR: - val = val ^ schptr->mask; - break; } -switch (schptr->bool) { /* case on comparison */ -case SCH_E: case SCH_EE: - return (val == schptr->comp); -case SCH_N: case SCH_NE: - return (val != schptr->comp); -case SCH_G: - return (val > schptr->comp); -case SCH_GE: - return (val >= schptr->comp); -case SCH_L: - return (val < schptr->comp); -case SCH_LE: - return (val <= schptr->comp); } -return 0; -} - -/* Radix independent input/output package - - strtotv - general radix input routine - - Inputs: - inptr = string to convert - endptr = pointer to first unconverted character - radix = radix for input - Outputs: - value = converted value - - On an error, the endptr will equal the inptr. -*/ - -t_value strtotv (char *inptr, char **endptr, uint32 radix) -{ -int32 nodigit; -t_value val; -uint32 c, digit; - -*endptr = inptr; /* assume fails */ -if ((radix < 2) || (radix > 36)) return 0; -while (isspace (*inptr)) inptr++; /* bypass white space */ -val = 0; -nodigit = 1; -for (c = *inptr; isalnum(c); c = *++inptr) { /* loop through char */ - if (islower (c)) c = toupper (c); - if (isdigit (c)) digit = c - (uint32) '0'; /* digit? */ - else digit = c + 10 - (uint32) 'A'; /* no, letter */ - if (digit >= radix) return 0; /* valid in radix? */ - val = (val * radix) + digit; /* add to value */ - nodigit = 0; } -if (nodigit) return 0; /* no digits? */ -*endptr = inptr; /* result pointer */ -return val; -} - -/* fprint_val - general radix printing routine - - Inputs: - stream = stream designator - val = value to print - radix = radix to print - width = width to print - format = leading zeroes format - Outputs: - status = error status -*/ - -t_stat fprint_val (FILE *stream, t_value val, uint32 radix, - uint32 width, uint32 format) -{ -#define MAX_WIDTH ((int) (CHAR_BIT * sizeof (t_value))) -t_value owtest, wtest; -int32 d, digit, ndigits; -char dbuf[MAX_WIDTH + 1]; - -for (d = 0; d < MAX_WIDTH; d++) dbuf[d] = (format == PV_RZRO)? '0': ' '; -dbuf[MAX_WIDTH] = 0; -d = MAX_WIDTH; -do { d = d - 1; - digit = (int32) (val % radix); - val = val / radix; - dbuf[d] = (digit <= 9)? '0' + digit: 'A' + (digit - 10); - } while ((d > 0) && (val != 0)); - -if (format != PV_LEFT) { - wtest = owtest = radix; - ndigits = 1; - while ((wtest < width_mask[width]) && (wtest >= owtest)) { - owtest = wtest; - wtest = wtest * radix; - ndigits = ndigits + 1; } - if ((MAX_WIDTH - ndigits) < d) d = MAX_WIDTH - ndigits; } -if (fputs (&dbuf[d], stream) == EOF) return SCPE_IOERR; -return SCPE_OK; -} - -/* Event queue package - - sim_activate add entry to event queue - sim_cancel remove entry from event queue - sim_process_event process entries on event queue - sim_is_active see if entry is on event queue - sim_atime return absolute time for an entry - sim_gtime return global time - sim_qcount return event queue entry count - - Asynchronous events are set up by queueing a unit data structure - to the event queue with a timeout (in simulator units, relative - to the current time). Each simulator 'times' these events by - counting down interval counter sim_interval. When this reaches - zero the simulator calls sim_process_event to process the event - and to see if further events need to be processed, or sim_interval - reset to count the next one. - - The event queue is maintained in clock order; entry timeouts are - RELATIVE to the time in the previous entry. - - sim_process_event - process event - - Inputs: - none - Outputs: - reason reason code returned by any event processor, - or 0 (SCPE_OK) if no exceptions -*/ - -t_stat sim_process_event (void) -{ -UNIT *uptr; -t_stat reason; - -if (stop_cpu) return SCPE_STOP; /* stop CPU? */ -if (sim_clock_queue == NULL) { /* queue empty? */ - UPDATE_SIM_TIME (noqueue_time); /* update sim time */ - sim_interval = noqueue_time = NOQUEUE_WAIT; /* flag queue empty */ - return SCPE_OK; } -UPDATE_SIM_TIME (sim_clock_queue->time); /* update sim time */ -do { uptr = sim_clock_queue; /* get first */ - sim_clock_queue = uptr->next; /* remove first */ - uptr->next = NULL; /* hygiene */ - uptr->time = 0; - if (sim_clock_queue != NULL) sim_interval = sim_clock_queue->time; - else sim_interval = noqueue_time = NOQUEUE_WAIT; - if (uptr->action != NULL) reason = uptr->action (uptr); - else reason = SCPE_OK; - } while ((reason == SCPE_OK) && (sim_interval == 0)); - -/* Empty queue forces sim_interval != 0 */ - -return reason; -} - -/* sim_activate - activate (queue) event - - Inputs: - uptr = pointer to unit - event_time = relative timeout - Outputs: - reason = result (SCPE_OK if ok) -*/ - -t_stat sim_activate (UNIT *uptr, int32 event_time) -{ -UNIT *cptr, *prvptr; -int32 accum; - -if (event_time < 0) return SCPE_IERR; -if (sim_is_active (uptr)) return SCPE_OK; /* already active? */ -if (sim_clock_queue == NULL) { UPDATE_SIM_TIME (noqueue_time); } -else { UPDATE_SIM_TIME (sim_clock_queue->time); } /* update sim time */ - -prvptr = NULL; -accum = 0; -for (cptr = sim_clock_queue; cptr != NULL; cptr = cptr->next) { - if (event_time < (accum + cptr->time)) break; - accum = accum + cptr->time; - prvptr = cptr; } -if (prvptr == NULL) { /* insert at head */ - cptr = uptr->next = sim_clock_queue; - sim_clock_queue = uptr; } -else { cptr = uptr->next = prvptr->next; /* insert at prvptr */ - prvptr->next = uptr; } -uptr->time = event_time - accum; -if (cptr != NULL) cptr->time = cptr->time - uptr->time; -sim_interval = sim_clock_queue->time; -return SCPE_OK; -} - -/* sim_cancel - cancel (dequeue) event - - Inputs: - uptr = pointer to unit - Outputs: - reason = result (SCPE_OK if ok) - -*/ - -t_stat sim_cancel (UNIT *uptr) -{ -UNIT *cptr, *nptr; - -if (sim_clock_queue == NULL) return SCPE_OK; -UPDATE_SIM_TIME (sim_clock_queue->time); /* update sim time */ -nptr = NULL; -if (sim_clock_queue == uptr) nptr = sim_clock_queue = uptr->next; -else { for (cptr = sim_clock_queue; cptr != NULL; cptr = cptr->next) { - if (cptr->next == uptr) { - nptr = cptr->next = uptr->next; - break; } } } /* end queue scan */ -if (nptr != NULL) nptr->time = nptr->time + uptr->time; -uptr->next = NULL; /* hygiene */ -uptr->time = 0; -if (sim_clock_queue != NULL) sim_interval = sim_clock_queue->time; -else sim_interval = noqueue_time = NOQUEUE_WAIT; -return SCPE_OK; -} - -/* sim_is_active - test for entry in queue, return activation time - - Inputs: - uptr = pointer to unit - Outputs: - result = absolute activation time + 1, 0 if inactive -*/ - -int32 sim_is_active (UNIT *uptr) -{ -UNIT *cptr; -int32 accum; - -accum = 0; -for (cptr = sim_clock_queue; cptr != NULL; cptr = cptr->next) { - accum = accum + cptr->time; - if (cptr == uptr) return accum + 1; } -return 0; -} - -/* sim_gtime - return global time - sim_grtime - return global time with rollover - - Inputs: none - Outputs: - time = global time -*/ - -double sim_gtime (void) -{ -if (sim_clock_queue == NULL) { UPDATE_SIM_TIME (noqueue_time); } -else { UPDATE_SIM_TIME (sim_clock_queue->time); } -return sim_time; -} - -uint32 sim_grtime (void) -{ -if (sim_clock_queue == NULL) { UPDATE_SIM_TIME (noqueue_time); } -else { UPDATE_SIM_TIME (sim_clock_queue->time); } -return sim_rtime; -} - -/* sim_qcount - return queue entry count - - Inputs: none - Outputs: - count = number of entries on the queue -*/ - -int32 sim_qcount (void) -{ -int32 cnt; -UNIT *uptr; - -cnt = 0; -for (uptr = sim_clock_queue; uptr != NULL; uptr = uptr->next) cnt++; -return cnt; -} - -/* Endian independent binary I/O package - - For consistency, all binary data read and written by the simulator - is stored in little endian data order. That is, in a multi-byte - data item, the bytes are written out right to left, low order byte - to high order byte. On a big endian host, data is read and written - from high byte to low byte. Consequently, data written on a little - endian system must be byte reversed to be usable on a big endian - system, and vice versa. - - These routines are analogs of the standard C runtime routines - fread and fwrite. If the host is little endian, or the data items - are size char, then the calls are passed directly to fread or - fwrite. Otherwise, these routines perform the necessary byte swaps - using an intermediate buffer. -*/ - -size_t fxread (void *bptr, size_t size, size_t count, FILE *fptr) -{ -size_t c, j, nelem, nbuf, lcnt, total; -int32 i, k; -unsigned char *sptr, *dptr; - -if (sim_end || (size == sizeof (char))) - return fread (bptr, size, count, fptr); -if ((size == 0) || (count == 0)) return 0; -nelem = FLIP_SIZE / size; /* elements in buffer */ -nbuf = count / nelem; /* number buffers */ -lcnt = count % nelem; /* count in last buf */ -if (lcnt) nbuf = nbuf + 1; -else lcnt = nelem; -total = 0; -dptr = bptr; /* init output ptr */ -for (i = nbuf; i > 0; i--) { - c = fread (sim_flip, size, (i == 1? lcnt: nelem), fptr); - if (c == 0) return total; - total = total + c; - for (j = 0, sptr = sim_flip; j < c; j++) { - for (k = size - 1; k >= 0; k--) *(dptr + k) = *sptr++; - dptr = dptr + size; } } -return total; -} - -size_t fxwrite (void *bptr, size_t size, size_t count, FILE *fptr) -{ -size_t c, j, nelem, nbuf, lcnt, total; -int32 i, k; -unsigned char *sptr, *dptr; - -if (sim_end || (size == sizeof (char))) - return fwrite (bptr, size, count, fptr); -if ((size == 0) || (count == 0)) return 0; -nelem = FLIP_SIZE / size; /* elements in buffer */ -nbuf = count / nelem; /* number buffers */ -lcnt = count % nelem; /* count in last buf */ -if (lcnt) nbuf = nbuf + 1; -else lcnt = nelem; -total = 0; -sptr = bptr; /* init input ptr */ -for (i = nbuf; i > 0; i--) { - c = (i == 1)? lcnt: nelem; - for (j = 0, dptr = sim_flip; j < c; j++) { - for (k = size - 1; k >= 0; k--) *(dptr + k) = *sptr++; - dptr = dptr + size; } - c = fwrite (sim_flip, size, c, fptr); - if (c == 0) return total; - total = total + c; } -return total; -} - -/* Get file size */ - -uint32 sim_fsize (char *cptr) -{ -FILE *fp; -uint32 sz; - -fp = fopen (cptr, "rb"); -if (fp == NULL) return 0; -fseek (fp, 0, SEEK_END); -sz = ftell (fp); -fclose (fp); -return sz; -} - -/* OS independent clock calibration package - - sim_rtc_init initialize calibration - sim_rtc_calb calibrate clock -*/ - -static int32 rtc_ticks[SIM_NTIMERS] = { 0 }; /* ticks */ -static uint32 rtc_rtime[SIM_NTIMERS] = { 0 }; /* real time */ -static uint32 rtc_vtime[SIM_NTIMERS] = { 0 }; /* virtual time */ -static uint32 rtc_nxintv[SIM_NTIMERS] = { 0 }; /* next interval */ -static int32 rtc_based[SIM_NTIMERS] = { 0 }; /* base delay */ -static int32 rtc_currd[SIM_NTIMERS] = { 0 }; /* current delay */ -extern t_bool rtc_avail; - -int32 sim_rtcn_init (int32 time, int32 tmr) -{ -if (time == 0) time = 1; -if ((tmr < 0) || (tmr >= SIM_NTIMERS)) return time; -rtc_rtime[tmr] = sim_os_msec (); -rtc_vtime[tmr] = rtc_rtime[tmr]; -rtc_nxintv[tmr] = 1000; -rtc_ticks[tmr] = 0; -rtc_based[tmr] = time; -rtc_currd[tmr] = time; -return time; -} - -int32 sim_rtcn_calb (int32 ticksper, int32 tmr) -{ -uint32 new_rtime, delta_rtime; -int32 delta_vtime; - -if ((tmr < 0) || (tmr >= SIM_NTIMERS)) return 10000; -rtc_ticks[tmr] = rtc_ticks[tmr] + 1; /* count ticks */ -if (rtc_ticks[tmr] < ticksper) return rtc_currd[tmr]; /* 1 sec yet? */ -rtc_ticks[tmr] = 0; /* reset ticks */ -if (!rtc_avail) return rtc_currd[tmr]; /* no timer? */ -new_rtime = sim_os_msec (); /* wall time */ -if (new_rtime < rtc_rtime[tmr]) { /* time running backwards? */ - rtc_rtime[tmr] = new_rtime; /* reset wall time */ - return rtc_currd[tmr]; } /* can't calibrate */ -delta_rtime = new_rtime - rtc_rtime[tmr]; /* elapsed wtime */ -rtc_rtime[tmr] = new_rtime; /* adv wall time */ -if ((delta_rtime == 0) || (delta_rtime > 30000)) /* gap 0 or too big? */ - return rtc_currd[tmr]; /* can't calibr */ -rtc_based[tmr] = (int32) (((double) rtc_based[tmr] * (double) rtc_nxintv[tmr]) / - ((double) delta_rtime)); /* new base rate */ -rtc_vtime[tmr] = rtc_vtime[tmr] + 1000; /* adv sim time */ -delta_vtime = rtc_vtime[tmr] - rtc_rtime[tmr]; /* gap */ -if (delta_vtime > SIM_TMAX) delta_vtime = SIM_TMAX; /* limit gap */ -else if (delta_vtime < -SIM_TMAX) delta_vtime = -SIM_TMAX; -rtc_nxintv[tmr] = 1000 + delta_vtime; /* next wtime */ -rtc_currd[tmr] = (int32) (((double) rtc_based[tmr] * (double) rtc_nxintv[tmr]) / - 1000.0); /* next delay */ -if (rtc_currd[tmr] <= 0) rtc_currd[tmr] = 1; /* never negative or zero! */ -return rtc_currd[tmr]; -} - -/* Prior interfaces - default to timer 0 */ - -int32 sim_rtc_init (int32 time) -{ -return sim_rtcn_init (time, 0); -} - -int32 sim_rtc_calb (int32 ticksper) -{ -return sim_rtcn_calb (ticksper, 0); -} - -/* Breakpoint package. This module replaces the VM-implemented one - instruction breakpoint capability. - - Breakpoints are stored in table sim_brk_tab, which is ordered by address for - efficient binary searching. A breakpoint consists of a four entry structure: - - addr address of the breakpoint - type types of breakpoints set on the address - a bit mask representing letters A-Z - cnt number of iterations before breakp is taken - action pointer command string to be executed - when break is taken - - sim_brk_summ is a summary of the types of breakpoints that are currently set (it - is the bitwise OR of all the type fields). A simulator need only check for - a breakpoint of type X if bit SWMASK('X') is set in sim_brk_sum. - - The package contains the following public routines: - - sim_brk_init initialize - sim_brk_set set breakpoint - sim_brk_clr clear breakpoint - sim_brk_clrall clear all breakpoints - sim_brk_show show breakpoint - sim_brk_showall show all breakpoints - sim_brk_test test for breakpoint - sim_brk_npc PC has been changed - sim_brk_getact get next action - sim_brk_clract clear pending actions - - Initialize breakpoint system. -*/ - -t_stat sim_brk_init (void) -{ -sim_brk_lnt = SIM_BRK_INILNT; -sim_brk_tab = calloc (sim_brk_lnt, sizeof (BRKTAB)); -if (sim_brk_tab == NULL) return SCPE_MEM; -sim_brk_ent = sim_brk_ins = 0; -sim_brk_pend = FALSE; -sim_brk_act = NULL; -return SCPE_OK; -} - -/* Search for a breakpoint in the sorted breakpoint table */ - -BRKTAB *sim_brk_fnd (t_addr loc) -{ -int32 lo, hi, p; -BRKTAB *bp; - -if (sim_brk_ent == 0) { /* table empty? */ - sim_brk_ins = 0; /* insrt at head */ - return NULL; } /* sch fails */ -lo = 0; /* initial bounds */ -hi = sim_brk_ent - 1; -do { p = (lo + hi) >> 1; /* probe */ - bp = sim_brk_tab + p; /* table addr */ - if (loc == bp->addr) return bp; /* match? */ - else if (loc < bp->addr) hi = p - 1; /* go down? p is upper */ - else lo = p + 1; } /* go up? p is lower */ -while (lo <= hi); -if (loc < bp->addr) sim_brk_ins = p; /* insrt before or */ -else sim_brk_ins = p + 1; /* after last sch */ -return NULL; -} - -/* Insert a breakpoint */ - -BRKTAB *sim_brk_new (t_addr loc) -{ -int32 i, t; -BRKTAB *bp, *newp; - -if (sim_brk_ins < 0) return NULL; -if (sim_brk_ent >= sim_brk_lnt) { /* out of space? */ - t = sim_brk_lnt + SIM_BRK_INILNT; /* new size */ - newp = calloc (t, sizeof (BRKTAB)); /* new table */ - if (newp == NULL) return NULL; /* can't extend */ - for (i = 0; i < sim_brk_lnt; i++) /* copy table */ - *(newp + i) = *(sim_brk_tab + i); - free (sim_brk_tab); /* free old table */ - sim_brk_tab = newp; /* new base, lnt */ - sim_brk_lnt = t; } -if (sim_brk_ins != sim_brk_ent) { /* move needed? */ - for (bp = sim_brk_tab + sim_brk_ent; - bp > sim_brk_tab + sim_brk_ins; bp--) - *bp = *(bp - 1); } -bp = sim_brk_tab + sim_brk_ins; -bp->addr = loc; -bp->typ = 0; -bp->cnt = 0; -bp->act = NULL; -sim_brk_ent = sim_brk_ent + 1; -return bp; -} - -/* Set a breakpoint of type sw */ - -t_stat sim_brk_set (t_addr loc, int32 sw, int32 ncnt, char *act) -{ -BRKTAB *bp; - -if (sw == 0) sw = sim_brk_dflt; -if ((sim_brk_types & sw) == 0) return SCPE_NOFNC; -bp = sim_brk_fnd (loc); /* present? */ -if (!bp) bp = sim_brk_new (loc); /* no, allocate */ -if (!bp) return SCPE_MEM; /* still no? mem err */ -bp->typ = sw; /* set type */ -bp->cnt = ncnt; /* set count */ -if ((bp->act != NULL) && (act != NULL)) { /* replace old action? */ - free (bp->act); /* deallocate */ - bp->act = NULL; } /* now no action */ -if ((act != NULL) && (*act != 0)) { /* new action? */ - char *newp = calloc (CBUFSIZE, sizeof (char)); /* allocate buffer */ - if (newp == NULL) return SCPE_MEM; /* mem err? */ - strncpy (newp, act, CBUFSIZE); /* copy action */ - bp->act = newp; } /* set pointer */ -sim_brk_summ = sim_brk_summ | sw; -return SCPE_OK; -} - -/* Clear a breakpoint */ - -t_stat sim_brk_clr (t_addr loc, int32 sw) -{ -BRKTAB *bp = sim_brk_fnd (loc); - -if (!bp) return SCPE_OK; /* not there? ok */ -if (sw == 0) sw = SIM_BRK_ALLTYP; -bp->typ = bp->typ & ~sw; -if (bp->typ) return SCPE_OK; /* clear all types? */ -if (bp->act != NULL) free (bp->act); /* deallocate action */ -for ( ; bp < (sim_brk_tab + sim_brk_ent - 1); bp++) /* erase entry */ - *bp = *(bp + 1); -sim_brk_ent = sim_brk_ent - 1; /* decrement count */ -sim_brk_summ = 0; /* recalc summary */ -for (bp = sim_brk_tab; bp < (sim_brk_tab + sim_brk_ent); bp++) - sim_brk_summ = sim_brk_summ | bp->typ; -return SCPE_OK; -} - -/* Clear all breakpoints */ - -t_stat sim_brk_clrall (int32 sw) -{ -BRKTAB *bp; - -if (sw == 0) sw = SIM_BRK_ALLTYP; -for (bp = sim_brk_tab; bp < (sim_brk_tab + sim_brk_ent); ) { - if (bp->typ & sw) sim_brk_clr (bp->addr, sw); - else bp++; } -return SCPE_OK; -} - -/* Show a breakpoint */ - -t_stat sim_brk_show (FILE *st, t_addr loc, int32 sw) -{ -BRKTAB *bp = sim_brk_fnd (loc); -DEVICE *dptr; -int32 i, any; - -if (sw == 0) sw = SIM_BRK_ALLTYP; -if (!bp || (!(bp->typ & sw))) return SCPE_OK; -dptr = sim_devices[0]; -if (dptr == NULL) return SCPE_OK; -fprint_val (st, loc, dptr->aradix, dptr->awidth, PV_LEFT); -fprintf (st, ":\t"); -for (i = any = 0; i < 26; i++) { - if ((bp->typ >> i) & 1) { - if (any) fprintf (st, ", "); - fputc (i + 'A', st); - any = 1; } } -if (bp->cnt > 0) fprintf (st, " [%d]", bp->cnt); -if (bp->act != NULL) fprintf (st, "; %s", bp->act); -fprintf (st, "\n"); -return SCPE_OK; -} - -/* Show all breakpoints */ - -t_stat sim_brk_showall (FILE *st, int32 sw) -{ -BRKTAB *bp; - -if (sw == 0) sw = SIM_BRK_ALLTYP; -for (bp = sim_brk_tab; bp < (sim_brk_tab + sim_brk_ent); bp++) { - if (bp->typ & sw) sim_brk_show (st, bp->addr, sw); } -return SCPE_OK; -} - -/* Test for breakpoint */ - -t_bool sim_brk_test (t_addr loc, int32 btyp) -{ -BRKTAB *bp; - -if ((bp = sim_brk_fnd (loc)) && /* entry in table? */ - (btyp & bp->typ) && /* type match? */ - (!sim_brk_pend || (loc != sim_brk_ploc)) && /* new location? */ - (--(bp->cnt) <= 0)) { /* count reach 0? */ - bp->cnt = 0; /* reset count */ - sim_brk_ploc = loc; /* save location */ - sim_brk_act = bp->act; /* set up actions */ - sim_brk_pend = TRUE; /* don't do twice */ - return TRUE; } -sim_brk_pend = FALSE; -return FALSE; -} - -/* Get next pending action, if any */ - -char *sim_brk_getact (char *buf, int32 size) -{ -char *ep; -size_t lnt; - -if (sim_brk_act == NULL) return NULL; /* any action? */ -while (isspace (*sim_brk_act)) sim_brk_act++; /* skip spaces */ -if (*sim_brk_act == 0) return (sim_brk_act = NULL); /* now empty? */ -if (ep = strchr (sim_brk_act, ';')) { /* cmd delimiter? */ - lnt = ep - sim_brk_act; /* cmd length */ - memcpy (buf, sim_brk_act, lnt + 1); /* copy with ; */ - buf[lnt] = 0; /* erase ; */ - sim_brk_act = sim_brk_act + lnt + 1; } /* adv ptr */ -else { strncpy (buf, sim_brk_act, size); /* copy action */ - sim_brk_act = NULL; } /* no more */ -return buf; -} - -/* Clear pending actions */ - -void sim_brk_clract (void) -{ -sim_brk_act = NULL; -} - -/* New PC */ - -void sim_brk_npc (void) -{ -sim_brk_pend = FALSE; -return; -} - -/* Telnet console package. - - The console terminal can be attached to the controlling window - or to a Telnet connection. If attached to a Telnet connection, - the console is described by internal terminal multiplexor - sim_con_tmxr and internal terminal line description sim_con_ldsc. -*/ - -/* Set console to Telnet port */ - -t_stat set_telnet (int32 flg, char *cptr) -{ -if (*cptr == 0) return SCPE_2FARG; /* too few arguments? */ -if (sim_con_tmxr.master) return SCPE_ALATT; /* already open? */ -return tmxr_open_master (&sim_con_tmxr, cptr); /* open master socket */ -} - -/* Close console Telnet port */ - -t_stat set_notelnet (int32 flag, char *cptr) -{ -if (cptr && (*cptr != 0)) return SCPE_2MARG; /* too many arguments? */ -if (sim_con_tmxr.master == 0) return SCPE_OK; /* ignore if already closed */ -return tmxr_close_master (&sim_con_tmxr); /* close master socket */ -} - -/* Show console Telnet status */ - -t_stat show_telnet (FILE *st, int32 flag, char *cptr) -{ -if (cptr && (*cptr != 0)) return SCPE_2MARG; -if (sim_con_tmxr.master == 0) - fprintf (st, "Connected to console window\n"); -else if (sim_con_ldsc.conn == 0) - fprintf (st, "Listening on port %d\n", sim_con_tmxr.port); -else { fprintf (st, "Listening on port %d, connected to socket %d\n", - sim_con_tmxr.port, sim_con_ldsc.conn); - tmxr_fconns (st, &sim_con_ldsc, -1); - tmxr_fstats (st, &sim_con_ldsc, -1); } -return SCPE_OK; -} - -/* Check connection before executing */ - -t_stat sim_check_console (int32 sec) -{ -int32 c, i; - -if (sim_con_tmxr.master == 0) return SCPE_OK; /* not Telnet? done */ -if (sim_con_ldsc.conn) { /* connected? */ - tmxr_poll_rx (&sim_con_tmxr); /* poll (check disconn) */ - if (sim_con_ldsc.conn) return SCPE_OK; } /* still connected? */ -for (i = 0; i < sec; i++) { /* loop */ - if (tmxr_poll_conn (&sim_con_tmxr) >= 0) { /* poll connect */ - sim_con_ldsc.rcve = 1; /* rcv enabled */ - if (i) { /* if delayed */ - printf ("Running\n"); /* print transition */ - fflush (stdout); } - return SCPE_OK; } /* ready to proceed */ - c = sim_os_poll_kbd (); /* check for stop char */ - if ((c == SCPE_STOP) || stop_cpu) return SCPE_STOP; - if ((i % 10) == 0) { /* Status every 10 sec */ - printf ("Waiting for console Telnet connection\n"); - fflush (stdout); } - sim_os_sleep (1); /* wait 1 second */ - } -return SCPE_TTMO; /* timed out */ -} - -/* Poll for character */ - -t_stat sim_poll_kbd (void) -{ -int32 c; - -c = sim_os_poll_kbd (); /* get character */ -if ((c == SCPE_STOP) || (sim_con_tmxr.master == 0)) /* ^E or not Telnet? */ - return c; /* in-window */ -if (sim_con_ldsc.conn == 0) return SCPE_LOST; /* no Telnet conn? */ -tmxr_poll_rx (&sim_con_tmxr); /* poll for input */ -if (c = tmxr_getc_ln (&sim_con_ldsc)) /* any char? */ - return (c & (SCPE_BREAK | 0377)) | SCPE_KFLAG; -return SCPE_OK; -} - -/* Output character */ - -t_stat sim_putchar (int32 c) -{ -if (sim_con_tmxr.master == 0) /* not Telnet? */ - return sim_os_putchar (c); /* in-window version */ -if (sim_con_ldsc.conn == 0) return SCPE_LOST; /* no Telnet conn? */ -tmxr_putc_ln (&sim_con_ldsc, c); /* output char */ -tmxr_poll_tx (&sim_con_tmxr); /* poll xmt */ -return SCPE_OK; -} diff --git a/scp_tty.c b/scp_tty.c deleted file mode 100644 index fe4b7e19..00000000 --- a/scp_tty.c +++ /dev/null @@ -1,884 +0,0 @@ -/* scp_tty.c: operating system-dependent I/O routines - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 25-Apr-03 RMS Added long seek support from Mark Pizzolato - Added Unix priority control from Mark Pizzolato - 24-Sep-02 RMS Removed VT support, added Telnet console support - Added CGI support (from Brian Knittel) - Added MacOS sleep (from Peter Schorn) - 14-Jul-02 RMS Added Windows priority control from Mark Pizzolato - 20-May-02 RMS Added Windows VT support from Fischer Franz - 01-Feb-02 RMS Added VAX fix from Robert Alan Byer - 19-Sep-01 RMS More Mac changes - 31-Aug-01 RMS Changed int64 to t_int64 for Windoze - 20-Jul-01 RMS Added Macintosh support (from Louis Chretien, Peter Schorn, - and Ben Supnik) - 15-May-01 RMS Added logging support - 05-Mar-01 RMS Added clock calibration support - 08-Dec-00 BKR Added OS/2 support (from Bruce Ray) - 18-Aug-98 RMS Added BeOS support - 13-Oct-97 RMS Added NetBSD terminal support - 25-Jan-97 RMS Added POSIX terminal I/O support - 02-Jan-97 RMS Fixed bug in sim_poll_kbd - - This module implements the following routines to support terminal I/O: - - ttinit - called once to get initial terminal state - ttrunstate - called to put terminal into run state - ttcmdstate - called to return terminal to command state - ttclose - called once before the simulator exits - sim_os_poll_kbd - poll for keyboard input - sim_os_putchar - output character to terminal - - This module implements the following routines to support clock calibration: - - sim_os_msec - return elapsed time in msec - sim_os_sleep - sleep specified number of seconds - - Versions are included for VMS, Windows, OS/2, Macintosh, BSD UNIX, and POSIX UNIX. - The POSIX UNIX version works with LINUX. -*/ - -#include "sim_defs.h" -int32 sim_int_char = 005; /* interrupt character */ -extern FILE *sim_log; - -/* VMS routines, from Ben Thomas, with fixes from Robert Alan Byer */ - -#if defined (VMS) -#define _SIM_IO_TTY_ 0 -#if defined(__VAX) -#define sys$assign SYS$ASSIGN -#define sys$qiow SYS$QIOW -#define sys$gettim SYS$GETTIM -#endif - -#include -#include -#include -#include -#include -#include -#include -#define EFN 0 -unsigned int32 tty_chan = 0; -typedef struct { - unsigned short sense_count; - unsigned char sense_first_char; - unsigned char sense_reserved; - unsigned int32 stat; - unsigned int32 stat2; } SENSE_BUF; -typedef struct { - unsigned int16 status; - unsigned int16 count; - unsigned int32 dev_status; } IOSB; -SENSE_BUF cmd_mode = { 0 }; -SENSE_BUF run_mode = { 0 }; - -t_stat ttinit (void) -{ -unsigned int32 status; -IOSB iosb; -$DESCRIPTOR (terminal_device, "tt"); - -status = sys$assign (&terminal_device, &tty_chan, 0, 0); -if (status != SS$_NORMAL) return SCPE_TTIERR; -status = sys$qiow (EFN, tty_chan, IO$_SENSEMODE, &iosb, 0, 0, - &cmd_mode, sizeof (cmd_mode), 0, 0, 0, 0); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; -run_mode = cmd_mode; -run_mode.stat = cmd_mode.stat | TT$M_NOECHO & ~(TT$M_HOSTSYNC | TT$M_TTSYNC); -run_mode.stat2 = cmd_mode.stat2 | TT2$M_PASTHRU; -return SCPE_OK; -} - -t_stat ttrunstate (void) -{ -unsigned int status; -IOSB iosb; - -status = sys$qiow (EFN, tty_chan, IO$_SETMODE, &iosb, 0, 0, - &run_mode, sizeof (run_mode), 0, 0, 0, 0); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; -return SCPE_OK; -} - -t_stat ttcmdstate (void) -{ -unsigned int status; -IOSB iosb; - -status = sys$qiow (EFN, tty_chan, IO$_SETMODE, &iosb, 0, 0, - &cmd_mode, sizeof (cmd_mode), 0, 0, 0, 0); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; -return SCPE_OK; -} - -t_stat ttclose (void) -{ -return ttcmdstate (); -} - -t_stat sim_os_poll_kbd (void) -{ -unsigned int status, term[2]; -unsigned char buf[4]; -IOSB iosb; -SENSE_BUF sense; - -term[0] = 0; term[1] = 0; -status = sys$qiow (EFN, tty_chan, IO$_SENSEMODE | IO$M_TYPEAHDCNT, &iosb, - 0, 0, &sense, 8, 0, term, 0, 0); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; -if (sense.sense_count == 0) return SCPE_OK; -term[0] = 0; term[1] = 0; -status = sys$qiow (EFN, tty_chan, - IO$_READLBLK | IO$M_NOECHO | IO$M_NOFILTR | IO$M_TIMED | IO$M_TRMNOECHO, - &iosb, 0, 0, buf, 1, 0, term, 0, 0); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_OK; -if (buf[0] == sim_int_char) return SCPE_STOP; -return (buf[0] | SCPE_KFLAG); -} - -t_stat sim_os_putchar (int32 out) -{ -unsigned int status; -char c; -IOSB iosb; - -c = out; -status = sys$qiow (EFN, tty_chan, IO$_WRITELBLK | IO$M_NOFORMAT, - &iosb, 0, 0, &c, 1, 0, 0, 0, 0); -if (sim_log) fputc (c, sim_log); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTOERR; -return SCPE_OK; -} - -const t_bool rtc_avail = TRUE; - -uint32 sim_os_msec () -{ -uint32 quo, htod, tod[2]; -int32 i; - -sys$gettim (tod); /* time 0.1usec */ - -/* To convert to msec, must divide a 64b quantity by 10000. This is actually done - by dividing the 96b quantity 0'time by 10000, producing 64b of quotient, the - high 32b of which are discarded. This can probably be done by a clever multiply... -*/ - -quo = htod = 0; -for (i = 0; i < 64; i++) { /* 64b quo */ - htod = (htod << 1) | ((tod[1] >> 31) & 1); /* shift divd */ - tod[1] = (tod[1] << 1) | ((tod[0] >> 31) & 1); - tod[0] = tod[0] << 1; - quo = quo << 1; /* shift quo */ - if (htod >= 10000) { /* divd work? */ - htod = htod - 10000; /* subtract */ - quo = quo | 1; } } /* set quo bit */ -return quo; -} - -void sim_os_sleep (unsigned int sec) -{ -sleep (sec); -return; -} - -#endif - -/* Win32 routines */ - -#if defined (_WIN32) -#define _SIM_IO_TTY_ 0 -#include -#include -#include -#include -static volatile int sim_win_ctlc = 0; - -void win_handler (int sig) -{ -sim_win_ctlc = 1; -return; -} - -t_stat ttinit (void) -{ -return SCPE_OK; -} - -t_stat ttrunstate (void) -{ -if (signal (SIGINT, win_handler) == SIG_ERR) return SCPE_SIGERR; -SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL); -return SCPE_OK; -} - -t_stat ttcmdstate (void) -{ -SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_NORMAL); -return SCPE_OK; -} - -t_stat ttclose (void) -{ -return SCPE_OK; -} - -t_stat sim_os_poll_kbd (void) -{ -int c; - -if (sim_win_ctlc) { - sim_win_ctlc = 0; - signal (SIGINT, win_handler); - return 003 | SCPE_KFLAG; } -if (!kbhit ()) return SCPE_OK; -c = _getch (); -if ((c & 0177) == '\b') c = 0177; -if ((c & 0177) == sim_int_char) return SCPE_STOP; -return c | SCPE_KFLAG; -} - -t_stat sim_os_putchar (int32 c) -{ -if (c != 0177) { - _putch (c); - if (sim_log) fputc (c, sim_log); } -return SCPE_OK; -} - -const t_bool rtc_avail = TRUE; - -uint32 sim_os_msec () -{ -return GetTickCount (); -} - -void sim_os_sleep (unsigned int sec) -{ -Sleep (sec * 1000); -return; -} - -#endif - -/* OS/2 routines, from Bruce Ray */ - -#if defined (__OS2__) -#define _SIM_IO_TTY_ 0 -#include - -t_stat ttinit (void) -{ -return SCPE_OK; -} - -t_stat ttrunstate (void) -{ -return SCPE_OK; -} - -t_stat ttcmdstate (void) -{ -return SCPE_OK; -} - -t_stat ttclose (void) -{ -return SCPE_OK; -} - -t_stat sim_os_poll_kbd (void) -{ -int c; - -if (!kbhit ()) return SCPE_OK; -c = getch(); -if ((c & 0177) == '\b') c = 0177; -if ((c & 0177) == sim_int_char) return SCPE_STOP; -return c | SCPE_KFLAG; -} - -t_stat sim_os_putchar (int32 c) -{ -if (c != 0177) { - putch (c); - fflush (stdout) ; - if (sim_log) fputc (c, sim_log); } -return SCPE_OK; -} - -const t_bool rtc_avail = FALSE; - -uint32 sim_os_msec () -{ -return 0; -} - -#endif - -/* Metrowerks CodeWarrior Macintosh routines, from Louis Chretien, - Peter Schorn, and Ben Supnik -*/ - -#if defined (__MWERKS__) && defined (macintosh) -#define _SIM_IO_TTY_ 0 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* function prototypes */ - -Boolean SIOUXIsAppWindow(WindowPtr window); -void SIOUXDoMenuChoice(long menuValue); -void SIOUXUpdateMenuItems(void); -void SIOUXUpdateScrollbar(void); -int ps_kbhit(void); -int ps_getch(void); -t_stat ttinit (void); -t_stat ttrunstate (void); -t_stat ttcmdstate (void); -t_stat ttclose (void); -uint32 sim_os_msec (void); -t_stat sim_os_poll_kbd (void); -t_stat sim_os_putchar (int32 c); - -extern char sim_name[]; -extern pSIOUXWin SIOUXTextWindow; -static CursHandle iBeamCursorH = NULL; /* contains the iBeamCursor */ - -static void updateCursor(void) { - WindowPtr window; - window = FrontWindow(); - if (SIOUXIsAppWindow(window)) { - GrafPtr savePort; - Point localMouse; - GetPort(&savePort); - SetPort(window); -#if TARGET_API_MAC_CARBON - GetGlobalMouse(&localMouse); -#else - localMouse = LMGetMouseLocation(); -#endif - GlobalToLocal(&localMouse); - if (PtInRect(localMouse, &(*SIOUXTextWindow->edit)->viewRect) && iBeamCursorH) { - SetCursor(*iBeamCursorH); - } - else { - SetCursor(&qd.arrow); - } - TEIdle(SIOUXTextWindow->edit); - SetPort(savePort); - } - else { - SetCursor(&qd.arrow); - TEIdle(SIOUXTextWindow->edit); - } - return; -} - -int ps_kbhit(void) { - EventRecord event; - int c; - updateCursor(); - SIOUXUpdateScrollbar(); - while (GetNextEvent(updateMask | osMask | mDownMask | mUpMask | activMask | - highLevelEventMask | diskEvt, &event)) { - SIOUXHandleOneEvent(&event); - } - if (SIOUXQuitting) { - exit(1); - } - if (EventAvail(keyDownMask,&event)) { - c = event.message&charCodeMask; - if ((event.modifiers & cmdKey) && (c > 0x20)) { - GetNextEvent(keyDownMask, &event); - SIOUXHandleOneEvent(&event); - if (SIOUXQuitting) { - exit(1); - } - return false; - } - return true; - } - else { - return false; - } -} - -int ps_getch(void) { - int c; - EventRecord event; - fflush(stdout); - updateCursor(); - while(!GetNextEvent(keyDownMask,&event)) { - if (GetNextEvent(updateMask | osMask | mDownMask | mUpMask | activMask | - highLevelEventMask | diskEvt, &event)) { - SIOUXUpdateScrollbar(); - SIOUXHandleOneEvent(&event); - } - } - if (SIOUXQuitting) { - exit(1); - } - c = event.message&charCodeMask; - if ((event.modifiers & cmdKey) && (c > 0x20)) { - SIOUXUpdateMenuItems(); - SIOUXDoMenuChoice(MenuKey(c)); - } - if (SIOUXQuitting) { - exit(1); - } - return c; -} - -t_stat ttinit (void) { -/* Note that this only works if the call to ttinit comes before any output to the console */ - int i; - char title[50] = " "; /* this blank will later be replaced by the number of characters */ - unsigned char ptitle[50]; - SIOUXSettings.autocloseonquit = TRUE; - SIOUXSettings.asktosaveonclose = FALSE; - SIOUXSettings.showstatusline = FALSE; - SIOUXSettings.columns = 80; - SIOUXSettings.rows = 40; - SIOUXSettings.toppixel = 42; - SIOUXSettings.leftpixel = 6; - iBeamCursorH = GetCursor(iBeamCursor); - strcat(title, sim_name); - strcat(title, " Simulator"); - title[0] = strlen(title) - 1; /* Pascal string done */ - for (i = 0; i <= title[0]; i++) { /* copy to unsigned char */ - ptitle[i] = title[i]; - } - SIOUXSetTitle(ptitle); - return SCPE_OK; -} - -t_stat ttrunstate (void) -{ -return SCPE_OK; -} - -t_stat ttcmdstate (void) -{ -return SCPE_OK; -} - -t_stat ttclose (void) -{ -return SCPE_OK; -} - -t_stat sim_os_poll_kbd (void) -{ -int c; - -if (!ps_kbhit ()) return SCPE_OK; -c = ps_getch(); -if ((c & 0177) == '\b') c = 0177; -if ((c & 0177) == sim_int_char) return SCPE_STOP; -return c | SCPE_KFLAG; -} - -t_stat sim_os_putchar (int32 c) -{ -if (c != 0177) { - putchar (c); - fflush (stdout) ; - if (sim_log) fputc (c, sim_log); } -return SCPE_OK; -} - -const t_bool rtc_avail = TRUE; - -uint32 sim_os_msec (void) -{ -unsigned long long micros; -UnsignedWide macMicros; -unsigned long millis; - -Microseconds (&macMicros); -micros = *((unsigned long long *) &macMicros); -millis = micros / 1000LL; -return (uint32) millis; -} - -void sim_os_sleep (unsigned int sec) -{ -sleep (sec); -return; -} - -#endif - -/* BSD UNIX routines */ - -#if defined (BSDTTY) -#define _SIM_IO_TTY_ 0 -#include -#include -#include -#include - -struct sgttyb cmdtty,runtty; /* V6/V7 stty data */ -struct tchars cmdtchars,runtchars; /* V7 editing */ -struct ltchars cmdltchars,runltchars; /* 4.2 BSD editing */ -int cmdfl,runfl; /* TTY flags */ - -t_stat ttinit (void) -{ -cmdfl = fcntl (0, F_GETFL, 0); /* get old flags and status */ -runfl = cmdfl | FNDELAY; -if (ioctl (0, TIOCGETP, &cmdtty) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCGETC, &cmdtchars) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCGLTC, &cmdltchars) < 0) return SCPE_TTIERR; -runtty = cmdtty; /* initial run state */ -runtty.sg_flags = cmdtty.sg_flags & ~(ECHO|CRMOD) | CBREAK; -runtchars.t_intrc = sim_int_char; /* interrupt */ -runtchars.t_quitc = 0xFF; /* no quit */ -runtchars.t_startc = 0xFF; /* no host sync */ -runtchars.t_stopc = 0xFF; -runtchars.t_eofc = 0xFF; -runtchars.t_brkc = 0xFF; -runltchars.t_suspc = 0xFF; /* no specials of any kind */ -runltchars.t_dsuspc = 0xFF; -runltchars.t_rprntc = 0xFF; -runltchars.t_flushc = 0xFF; -runltchars.t_werasc = 0xFF; -runltchars.t_lnextc = 0xFF; -return SCPE_OK; /* return success */ -} - -t_stat ttrunstate (void) -{ -runtchars.t_intrc = sim_int_char; /* in case changed */ -fcntl (0, F_SETFL, runfl); /* non-block mode */ -if (ioctl (0, TIOCSETP, &runtty) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCSETC, &runtchars) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCSLTC, &runltchars) < 0) return SCPE_TTIERR; -nice (10); /* lower priority */ -return SCPE_OK; -} - -t_stat ttcmdstate (void) -{ -nice (-10); /* restore priority */ -fcntl (0, F_SETFL, cmdfl); /* block mode */ -if (ioctl (0, TIOCSETP, &cmdtty) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCSETC, &cmdtchars) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCSLTC, &cmdltchars) < 0) return SCPE_TTIERR; -return SCPE_OK; -} - -t_stat ttclose (void) -{ -return ttcmdstate (); -} - -t_stat sim_os_poll_kbd (void) -{ -int status; -unsigned char buf[1]; - -status = read (0, buf, 1); -if (status != 1) return SCPE_OK; -else return (buf[0] | SCPE_KFLAG); -} - -t_stat sim_os_putchar (int32 out) -{ -char c; - -c = out; -write (1, &c, 1); -if (sim_log) fputc (c, sim_log); -return SCPE_OK; -} - -const t_bool rtc_avail = TRUE; - -uint32 sim_os_msec () -{ -struct timeval cur; -struct timezone foo; -uint32 msec; - -gettimeofday (&cur, &foo); -msec = (((uint32) cur.tv_sec) * 1000) + (((uint32) cur.tv_usec) / 1000); -return msec; -} - -void sim_os_sleep (unsigned int sec) -{ -sleep (sec); -return; -} - -#endif - -/* POSIX UNIX routines, from Leendert Van Doorn */ - -#if !defined (_SIM_IO_TTY_) -#include -#include -#include - -struct termios cmdtty, runtty; -static int prior_norm = 1; - -t_stat ttinit (void) -{ -if (!isatty (fileno (stdin))) return SCPE_OK; /* skip if !tty */ -if (tcgetattr (0, &cmdtty) < 0) return SCPE_TTIERR; /* get old flags */ -runtty = cmdtty; -runtty.c_lflag = runtty.c_lflag & ~(ECHO | ICANON); /* no echo or edit */ -runtty.c_oflag = runtty.c_oflag & ~OPOST; /* no output edit */ -runtty.c_iflag = runtty.c_iflag & ~ICRNL; /* no cr conversion */ -runtty.c_cc[VINTR] = sim_int_char; /* interrupt */ -runtty.c_cc[VQUIT] = 0; /* no quit */ -runtty.c_cc[VERASE] = 0; -runtty.c_cc[VKILL] = 0; -runtty.c_cc[VEOF] = 0; -runtty.c_cc[VEOL] = 0; -runtty.c_cc[VSTART] = 0; /* no host sync */ -runtty.c_cc[VSUSP] = 0; -runtty.c_cc[VSTOP] = 0; -#if defined (VREPRINT) -runtty.c_cc[VREPRINT] = 0; /* no specials */ -#endif -#if defined (VDISCARD) -runtty.c_cc[VDISCARD] = 0; -#endif -#if defined (VWERASE) -runtty.c_cc[VWERASE] = 0; -#endif -#if defined (VLNEXT) -runtty.c_cc[VLNEXT] = 0; -#endif -runtty.c_cc[VMIN] = 0; /* no waiting */ -runtty.c_cc[VTIME] = 0; -#if defined (VDSUSP) -runtty.c_cc[VDSUSP] = 0; -#endif -#if defined (VSTATUS) -runtty.c_cc[VSTATUS] = 0; -#endif -return SCPE_OK; -} - -t_stat ttrunstate (void) -{ -if (!isatty (fileno (stdin))) return SCPE_OK; /* skip if !tty */ -runtty.c_cc[VINTR] = sim_int_char; /* in case changed */ -if (tcsetattr (0, TCSAFLUSH, &runtty) < 0) return SCPE_TTIERR; -if (prior_norm) { /* at normal pri? */ - errno = 0; - nice (10); /* try to lower pri */ - prior_norm = errno; } /* if no error, done */ -return SCPE_OK; -} - -t_stat ttcmdstate (void) -{ -if (!isatty (fileno (stdin))) return SCPE_OK; /* skip if !tty */ -if (!prior_norm) { /* priority down? */ - errno = 0; - nice (-10); /* try to raise pri*/ - prior_norm = (errno == 0); } /* if no error, done */ -if (tcsetattr (0, TCSAFLUSH, &cmdtty) < 0) return SCPE_TTIERR; -return SCPE_OK; -} - -t_stat ttclose (void) -{ -return ttcmdstate (); -} - -t_stat sim_os_poll_kbd (void) -{ -int status; -unsigned char buf[1]; - -status = read (0, buf, 1); -if (status != 1) return SCPE_OK; -else return (buf[0] | SCPE_KFLAG); -} - -t_stat sim_os_putchar (int32 out) -{ -char c; - -c = out; -write (1, &c, 1); -if (sim_log) fputc (c, sim_log); -return SCPE_OK; -} - -const t_bool rtc_avail = TRUE; - -uint32 sim_os_msec () -{ -struct timeval cur; -uint32 msec; - -gettimeofday (&cur, NULL); -msec = (((uint32) cur.tv_sec) * 1000) + (((uint32) cur.tv_usec) / 1000); -return msec; -} - -void sim_os_sleep (unsigned int sec) -{ -sleep (sec); -return; -} - -#endif - -/* Long seek routines */ - -#if defined (USE_INT64) && defined (USE_ADDR64) - -/* Alpha VMS */ - -#if defined (__ALPHA) && defined (VMS) /* Alpha VMS */ -#define _SIM_IO_FSEEK_EXT_ 0 - -static t_int64 fpos_t_to_int64 (fpos_t *pos) -{ -unsigned short *w = (unsigned short *) pos; /* endian dep! */ -t_int64 result; - -result = w[1]; -result <<= 16; -result += w[0]; -result <<= 9; -result += w[2]; -return result; -} - -static void int64_to_fpos_t (t_int64 ipos, fpos_t *pos, size_t mbc) -{ -unsigned short *w = (unsigned short *) pos; -int bufsize = mbc << 9; - -w[3] = 0; -w[2] = (unsigned short) (ipos % bufsize); -ipos -= w[2]; -ipos >>= 9; -w[0] = (unsigned short) ipos; -ipos >>= 16; -w[1] = (unsigned short) ipos; -if ((w[2] == 0) && (w[0] || w[1])) { - w[2] = bufsize; - w[0] -= mbc; } -} - -int fseek_ext (FILE *st, t_addr offset, int whence) -{ -t_addr fileaddr; -fpos_t filepos; - -switch (whence) { - case SEEK_SET: - fileaddr = offset; - break; - case SEEK_CUR: - if (fgetpos (st, &filepos)) return (-1); - fileaddr = fpos_t_to_int64 (&filepos); - fileaddr = fileaddr + offset; - break; - default: - errno = EINVAL; - return (-1); } -int64_to_fpos_t (fileaddr, &filepos, 127); -return fsetpos (st, &filepos); -} - -#endif - -/* Alpha UNIX - natively 64b */ - -#if defined (__ALPHA) && defined (__unix__) /* Alpha UNIX */ -#define _SIM_IO_FSEEK_EXT_ 0 - -int fseek_ext (FILE *st, t_addr offset, int whence) -{ -return fseek (st, offset, whence); -} - -#endif - -/* Windows */ - -#if defined (_WIN32) -#define _SIM_IO_FSEEK_EXT_ 0 - -int fseek_ext (FILE *st, t_addr offset, int whence) -{ -fpos_t fileaddr; - -switch (whence) { - case SEEK_SET: - fileaddr = offset; - break; - case SEEK_CUR: - if (fgetpos (st, &fileaddr)) return (-1); - fileaddr = fileaddr + offset; - break; - default: - errno = EINVAL; - return (-1); } -return fsetpos (st, &fileaddr); -} - -#endif /* end Windows */ - -#endif /* end 64b seek defs */ - -/* Default: no OS-specific routine has been defined */ - -#if !defined (_SIM_IO_FSEEK_EXT_) -#define _SIM_IO_FSEEK_EXT_ 0 - -int fseek_ext (FILE *st, t_addr xpos, int origin) -{ -return fseek (st, (int32) xpos, origin); -} - -uint32 sim_taddr_64 = 0; -#else -uint32 sim_taddr_64 = 1; -#endif diff --git a/sim_defs.h b/sim_defs.h deleted file mode 100644 index 7bdbbd62..00000000 --- a/sim_defs.h +++ /dev/null @@ -1,482 +0,0 @@ -/* sim_defs.h: simulator definitions - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 15-Jun-03 RMS Added register flag REG_VMIO - 23-Apr-03 RMS Revised for 32b/64b t_addr - 14-Mar-03 RMS Lengthened default serial output wait - 31-Mar-03 RMS Added u5, u6 fields - 18-Mar-03 RMS Added logical name support - Moved magtape definitions to sim_tape.h - Moved breakpoint definitions from scp.c - 03-Mar-03 RMS Added sim_fsize - 08-Feb-03 RMS Changed sim_os_sleep to void, added match_ext - 05-Jan-03 RMS Added hidden switch definitions, device dyn memory support, - parameters for function pointers, case sensitive SET support - 22-Dec-02 RMS Added break flag - 08-Oct-02 RMS Increased simulator error code space - Added Telnet errors - Added end of medium support - Added help messages to CTAB - Added flag and context fields to DEVICE - Added restore flag masks - Revised 64b definitions - 02-May-02 RMS Removed log status codes - 22-Apr-02 RMS Added magtape record length error - 30-Dec-01 RMS Generalized timer package, added circular arrays - 07-Dec-01 RMS Added breakpoint package - 01-Dec-01 RMS Added read-only unit support, extended SET/SHOW features, - improved error messages - 24-Nov-01 RMS Added unit-based registers - 27-Sep-01 RMS Added queue count prototype - 17-Sep-01 RMS Removed multiple console support - 07-Sep-01 RMS Removed conditional externs on function prototypes - 31-Aug-01 RMS Changed int64 to t_int64 for Windoze - 17-Jul-01 RMS Added additional function prototypes - 27-May-01 RMS Added multiple console support - 15-May-01 RMS Increased string buffer size - 25-Feb-01 RMS Revisions for V2.6 - 15-Oct-00 RMS Editorial revisions for V2.5 - 11-Jul-99 RMS Added unsigned int data types - 14-Apr-99 RMS Converted t_addr to unsigned - 04-Oct-98 RMS Additional definitions for V2.4 - - The interface between the simulator control package (SCP) and the - simulator consists of the following routines and data structures - - sim_name simulator name string - sim_devices[] array of pointers to simulated devices - sim_PC pointer to saved PC register descriptor - sim_interval simulator interval to next event - sim_stop_messages[] array of pointers to stop messages - sim_instr() instruction execution routine - sim_load() binary loader routine - sim_emax maximum number of words in an instruction - - In addition, the simulator must supply routines to print and parse - architecture specific formats - - print_sym print symbolic output - parse_sym parse symbolic input -*/ - -#ifndef _SIM_DEFS_H_ -#define _SIM_DEFS_H_ 0 - -#include -#include -#include -#include -#include -#include - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -/* Length specific integer declarations */ - -#define int8 char -#define int16 short -#define int32 int -typedef int t_stat; /* status */ -typedef int t_bool; /* boolean */ -typedef unsigned int8 uint8; -typedef unsigned int16 uint16; -typedef unsigned int32 uint32; - -#if defined (USE_INT64) /* 64b data */ -#if defined (_WIN32) /* Windows */ -#define t_int64 __int64 -#elif defined (__ALPHA) && defined (VMS) /* Alpha VMS */ -#define t_int64 __int64 -#elif defined (__ALPHA) && defined (__unix__) /* Alpha UNIX */ -#define t_int64 long -#else /* default GCC */ -#define t_int64 long long -#endif /* end OS's */ -typedef unsigned t_int64 t_uint64, t_value; /* value */ -typedef t_int64 t_svalue; /* signed value */ -#else /* 32b data */ -typedef unsigned int32 t_value; -typedef int32 t_svalue; -#endif /* end 64b data */ - -#if defined (USE_INT64) && defined (USE_ADDR64) /* 64b address */ -typedef unsigned t_int64 t_addr; -#define T_ADDR_W 64 -#else /* 32b address */ -typedef unsigned int32 t_addr; -#define T_ADDR_W 32 -#endif /* end 64b address */ - -/* System independent definitions */ - -#define FLIP_SIZE (1 << 16) /* flip buf size */ -#if !defined (PATH_MAX) /* usually in limits */ -#define PATH_MAX 512 -#endif -#define CBUFSIZE (128 + PATH_MAX) /* string buf size */ - -/* Extended switch definitions (bits >= 26) */ - -#define SIM_SW_HIDE (1u << 26) /* enable hiding */ -#define SIM_SW_REST (1u << 27) /* attach/restore */ -#define SIM_SW_REG (1u << 28) /* register value */ - -/* Simulator status codes - - 0 ok - 1 - (SCPE_BASE - 1) simulator specific - SCPE_BASE - n general -*/ - -#define SCPE_OK 0 /* normal return */ -#define SCPE_BASE 64 /* base for messages */ -#define SCPE_NXM (SCPE_BASE + 0) /* nxm */ -#define SCPE_UNATT (SCPE_BASE + 1) /* no file */ -#define SCPE_IOERR (SCPE_BASE + 2) /* I/O error */ -#define SCPE_CSUM (SCPE_BASE + 3) /* loader cksum */ -#define SCPE_FMT (SCPE_BASE + 4) /* loader format */ -#define SCPE_NOATT (SCPE_BASE + 5) /* not attachable */ -#define SCPE_OPENERR (SCPE_BASE + 6) /* open error */ -#define SCPE_MEM (SCPE_BASE + 7) /* alloc error */ -#define SCPE_ARG (SCPE_BASE + 8) /* argument error */ -#define SCPE_STEP (SCPE_BASE + 9) /* step expired */ -#define SCPE_UNK (SCPE_BASE + 10) /* unknown command */ -#define SCPE_RO (SCPE_BASE + 11) /* read only */ -#define SCPE_INCOMP (SCPE_BASE + 12) /* incomplete */ -#define SCPE_STOP (SCPE_BASE + 13) /* sim stopped */ -#define SCPE_EXIT (SCPE_BASE + 14) /* sim exit */ -#define SCPE_TTIERR (SCPE_BASE + 15) /* console tti err */ -#define SCPE_TTOERR (SCPE_BASE + 16) /* console tto err */ -#define SCPE_EOF (SCPE_BASE + 17) /* end of file */ -#define SCPE_REL (SCPE_BASE + 18) /* relocation error */ -#define SCPE_NOPARAM (SCPE_BASE + 19) /* no parameters */ -#define SCPE_ALATT (SCPE_BASE + 20) /* already attached */ -#define SCPE_TIMER (SCPE_BASE + 21) /* hwre timer err */ -#define SCPE_SIGERR (SCPE_BASE + 22) /* signal err */ -#define SCPE_TTYERR (SCPE_BASE + 23) /* tty setup err */ -#define SCPE_SUB (SCPE_BASE + 24) /* subscript err */ -#define SCPE_NOFNC (SCPE_BASE + 25) /* func not imp */ -#define SCPE_UDIS (SCPE_BASE + 26) /* unit disabled */ -#define SCPE_NORO (SCPE_BASE + 27) /* rd only not ok */ -#define SCPE_INVSW (SCPE_BASE + 28) /* invalid switch */ -#define SCPE_MISVAL (SCPE_BASE + 29) /* missing value */ -#define SCPE_2FARG (SCPE_BASE + 30) /* too few arguments */ -#define SCPE_2MARG (SCPE_BASE + 31) /* too many arguments */ -#define SCPE_NXDEV (SCPE_BASE + 32) /* nx device */ -#define SCPE_NXUN (SCPE_BASE + 33) /* nx unit */ -#define SCPE_NXREG (SCPE_BASE + 34) /* nx register */ -#define SCPE_NXPAR (SCPE_BASE + 35) /* nx parameter */ -#define SCPE_NEST (SCPE_BASE + 36) /* nested DO */ -#define SCPE_IERR (SCPE_BASE + 37) /* internal error */ -#define SCPE_MTRLNT (SCPE_BASE + 38) /* tape rec lnt error */ -#define SCPE_LOST (SCPE_BASE + 39) /* Telnet conn lost */ -#define SCPE_TTMO (SCPE_BASE + 40) /* Telnet conn timeout */ -#define SCPE_KFLAG 0010000 /* tti data flag */ -#define SCPE_BREAK 0020000 /* tti break flag */ - -/* Print value format codes */ - -#define PV_RZRO 0 /* right, zero fill */ -#define PV_RSPC 1 /* right, space fill */ -#define PV_LEFT 2 /* left justify */ - -/* Default timing parameters */ - -#define KBD_POLL_WAIT 5000 /* keyboard poll */ -#define SERIAL_IN_WAIT 100 /* serial in time */ -#define SERIAL_OUT_WAIT 100 /* serial output */ -#define NOQUEUE_WAIT 10000 /* min check time */ - -/* Convert switch letter to bit mask */ - -#define SWMASK(x) (1u << (((int) (x)) - ((int) 'A'))) - -/* String match */ - -#define MATCH_CMD(ptr,cmd) strncmp ((ptr), (cmd), strlen (ptr)) - -/* Device data structure */ - -struct sim_device { - char *name; /* name */ - struct sim_unit *units; /* units */ - struct sim_reg *registers; /* registers */ - struct sim_mtab *modifiers; /* modifiers */ - uint32 numunits; /* #units */ - uint32 aradix; /* address radix */ - uint32 awidth; /* address width */ - uint32 aincr; /* addr increment */ - uint32 dradix; /* data radix */ - uint32 dwidth; /* data width */ - t_stat (*examine)(t_value *v, t_addr a, struct sim_unit *up, - int32 sw); /* examine routine */ - t_stat (*deposit)(t_value v, t_addr a, struct sim_unit *up, - int32 sw); /* deposit routine */ - t_stat (*reset)(struct sim_device *dp);/* reset routine */ - t_stat (*boot)(int32 u, struct sim_device *dp); - /* boot routine */ - t_stat (*attach)(struct sim_unit *up, char *cp); - /* attach routine */ - t_stat (*detach)(struct sim_unit *up); /* detach routine */ - void *ctxt; /* context */ - uint32 flags; /* flags */ - t_stat (*msize)(struct sim_unit *up, int32 v, char *cp, void *dp); - /* mem size routine */ - char *lname; /* logical name */ -}; - -/* Device flags */ - -#define DEV_V_DIS 0 /* dev enabled */ -#define DEV_V_DISABLE 1 /* dev disable-able */ -#define DEV_V_DYNM 2 /* mem size dynamic */ -#define DEV_V_NET 3 /* network attach */ -#define DEV_V_UF 12 /* user flags */ -#define DEV_V_RSV 31 /* reserved */ - -#define DEV_DIS (1 << DEV_V_DIS) -#define DEV_DISABLE (1 << DEV_V_DISABLE) -#define DEV_DYNM (1 << DEV_V_DYNM) -#define DEV_NET (1 << DEV_V_NET) - -#define DEV_UFMASK (((1u << DEV_V_RSV) - 1) & ~((1u << DEV_V_UF) - 1)) -#define DEV_RFLAGS (DEV_UFMASK|DEV_DIS) /* restored flags */ - -/* Unit data structure - - Parts of the unit structure are device specific, that is, they are - not referenced by the simulator control package and can be freely - used by device simulators. Fields starting with 'buf', and flags - starting with 'UF', are device specific. The definitions given here - are for a typical sequential device. -*/ - -struct sim_unit { - struct sim_unit *next; /* next active */ - t_stat (*action)(struct sim_unit *up); /* action routine */ - char *filename; /* open file name */ - FILE *fileref; /* file reference */ - void *filebuf; /* memory buffer */ - uint32 hwmark; /* high water mark */ - int32 time; /* time out */ - uint32 flags; /* flags */ - t_addr capac; /* capacity */ - t_addr pos; /* file position */ - int32 buf; /* buffer */ - int32 wait; /* wait */ - int32 u3; /* device specific */ - int32 u4; /* device specific */ - int32 u5; /* device specific */ - int32 u6; /* device specific */ -}; - -/* Unit flags */ - -#define UNIT_V_UF 12 /* device specific */ -#define UNIT_V_RSV 31 /* reserved!! */ - -#define UNIT_ATTABLE 000001 /* attachable */ -#define UNIT_RO 000002 /* read only */ -#define UNIT_FIX 000004 /* fixed capacity */ -#define UNIT_SEQ 000010 /* sequential */ -#define UNIT_ATT 000020 /* attached */ -#define UNIT_BINK 000040 /* K = power of 2 */ -#define UNIT_BUFABLE 000100 /* bufferable */ -#define UNIT_MUSTBUF 000200 /* must buffer */ -#define UNIT_BUF 000400 /* buffered */ -#define UNIT_ROABLE 001000 /* read only ok */ -#define UNIT_DISABLE 002000 /* disable-able */ -#define UNIT_DIS 004000 /* disabled */ - -#define UNIT_UFMASK (((1u << UNIT_V_RSV) - 1) & ~((1u << UNIT_V_UF) - 1)) -#define UNIT_RFLAGS (UNIT_UFMASK|UNIT_DIS) /* restored flags */ - -/* Register data structure */ - -struct sim_reg { - char *name; /* name */ - void *loc; /* location */ - uint32 radix; /* radix */ - uint32 width; /* width */ - uint32 offset; /* starting bit */ - uint32 depth; /* save depth */ - uint32 flags; /* flags */ - uint32 qptr; /* circ q ptr */ -}; - -#define REG_FMT 0003 /* see PV_x */ -#define REG_RO 0004 /* read only */ -#define REG_HIDDEN 0010 /* hidden */ -#define REG_NZ 0020 /* must be non-zero */ -#define REG_UNIT 0040 /* in unit struct */ -#define REG_CIRC 0100 /* circular array */ -#define REG_VMIO 0200 /* use VM print/parse */ -#define REG_HRO (REG_RO | REG_HIDDEN) /* hidden, read only */ - -/* Command tables, base and alternate formats */ - -struct sim_ctab { - char *name; /* name */ - t_stat (*action)(int32 flag, char *cptr); - /* action routine */ - int32 arg; /* argument */ - char *help; /* help string */ -}; - -struct sim_c1tab { - char *name; /* name */ - t_stat (*action)(struct sim_device *dptr, struct sim_unit *uptr, - int32 flag); /* action routine */ - int32 arg; /* argument */ - char *help; /* help string */ -}; - -struct sim_shtab { - char *name; /* name */ - t_stat (*action)(FILE *st, int32 flag, char *cptr); - int32 arg; /* argument */ - char *help; /* help string */ -}; - -/* Modifier table - only extended entries have disp, reg, or flags */ - -struct sim_mtab { - uint32 mask; /* mask */ - uint32 match; /* match */ - char *pstring; /* print string */ - char *mstring; /* match string */ - t_stat (*valid)(struct sim_unit *up, int32 v, char *cp, void *dp); - /* validation routine */ - t_stat (*disp)(FILE *st, struct sim_unit *up, int32 v, void *dp); - /* display routine */ - void *desc; /* value descriptor */ - /* REG * if MTAB_VAL */ - /* int * if not */ -}; - -#define MTAB_XTD (1u << UNIT_V_RSV) /* ext entry flag */ -#define MTAB_VDV 001 /* valid for dev */ -#define MTAB_VUN 002 /* valid for unit */ -#define MTAB_VAL 004 /* takes a value */ -#define MTAB_NMO 010 /* only if named */ -#define MTAB_NC 020 /* no UC conversion */ - -/* Search table */ - -struct sim_schtab { - int32 logic; /* logical operator */ - int32 bool; /* boolean operator */ - t_value mask; /* mask for logical */ - t_value comp; /* comparison for boolean */ -}; - -/* Breakpoint table */ - -struct sim_brktab { - t_addr addr; /* address */ - int32 typ; /* mask of types */ - int32 cnt; /* proceed count */ - char *act; /* action string */ -}; - -/* The following macros define structure contents */ - -#define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,0,0,(fl),(cap),0,0 - -#if defined (__STDC__) || defined (_WIN32) -#define ORDATA(nm,loc,wd) #nm, &(loc), 8, (wd), 0, 1 -#define DRDATA(nm,loc,wd) #nm, &(loc), 10, (wd), 0, 1 -#define HRDATA(nm,loc,wd) #nm, &(loc), 16, (wd), 0, 1 -#define FLDATA(nm,loc,pos) #nm, &(loc), 2, 1, (pos), 1 -#define GRDATA(nm,loc,rdx,wd,pos) #nm, &(loc), (rdx), (wd), (pos), 1 -#define BRDATA(nm,loc,rdx,wd,dep) #nm, (loc), (rdx), (wd), 0, (dep) -#define URDATA(nm,loc,rdx,wd,off,dep,fl) \ - #nm, &(loc), (rdx), (wd), (off), (dep), ((fl) | REG_UNIT) -#else -#define ORDATA(nm,loc,wd) "nm", &(loc), 8, (wd), 0, 1 -#define DRDATA(nm,loc,wd) "nm", &(loc), 10, (wd), 0, 1 -#define HRDATA(nm,loc,wd) "nm", &(loc), 16, (wd), 0, 1 -#define FLDATA(nm,loc,pos) "nm", &(loc), 2, 1, (pos), 1 -#define GRDATA(nm,loc,rdx,wd,pos) "nm", &(loc), (rdx), (wd), (pos), 1 -#define BRDATA(nm,loc,rdx,wd,dep) "nm", (loc), (rdx), (wd), 0, (dep) -#define URDATA(nm,loc,rdx,wd,off,dep,fl) \ - "nm", &(loc), (rdx), (wd), (off), (dep), ((fl) | REG_UNIT) -#endif - -/* Typedefs for principal structures */ - -typedef struct sim_device DEVICE; -typedef struct sim_unit UNIT; -typedef struct sim_reg REG; -typedef struct sim_ctab CTAB; -typedef struct sim_c1tab C1TAB; -typedef struct sim_shtab SHTAB; -typedef struct sim_mtab MTAB; -typedef struct sim_schtab SCHTAB; -typedef struct sim_brktab BRKTAB; - -/* Function prototypes */ - -t_stat sim_process_event (void); -t_stat sim_activate (UNIT *uptr, int32 interval); -t_stat sim_cancel (UNIT *uptr); -int32 sim_is_active (UNIT *uptr); -double sim_gtime (void); -uint32 sim_grtime (void); -int32 sim_qcount (void); -t_stat attach_unit (UNIT *uptr, char *cptr); -t_stat detach_unit (UNIT *uptr); -t_stat reset_all (uint32 start_device); -size_t fxread (void *bptr, size_t size, size_t count, FILE *fptr); -size_t fxwrite (void *bptr, size_t size, size_t count, FILE *fptr); -int fseek_ext (FILE *st, t_addr xpos, int origin); -uint32 sim_fsize (char *cptr); -char *sim_dname (DEVICE *dptr); -t_stat get_yn (char *ques, t_stat deflt); -char *get_glyph (char *iptr, char *optr, char mchar); -char *get_glyph_nc (char *iptr, char *optr, char mchar); -t_value get_uint (char *cptr, uint32 radix, t_value max, t_stat *status); -char *get_range (char *cptr, t_addr *lo, t_addr *hi, uint32 rdx, - t_addr max, char term); -t_stat get_ipaddr (char *cptr, uint32 *ipa, uint32 *ipp); -t_value strtotv (char *cptr, char **endptr, uint32 radix); -t_stat fprint_val (FILE *stream, t_value val, uint32 rdx, uint32 wid, uint32 fmt); -DEVICE *find_dev_from_unit (UNIT *uptr); -REG *find_reg (char *ptr, char **optr, DEVICE *dptr); -int32 sim_rtc_init (int32 time); -int32 sim_rtc_calb (int32 ticksper); -int32 sim_rtcn_init (int32 time, int32 tmr); -int32 sim_rtcn_calb (int32 time, int32 tmr); -t_stat sim_poll_kbd (void); -t_stat sim_putchar (int32 out); -BRKTAB *sim_brk_fnd (t_addr loc); -t_bool sim_brk_test (t_addr bloc, int32 btyp); -void sim_os_sleep (unsigned int sec); -char *match_ext (char *fnam, char *ext); - -#endif diff --git a/sim_ether.c b/sim_ether.c deleted file mode 100644 index 48a4280f..00000000 --- a/sim_ether.c +++ /dev/null @@ -1,631 +0,0 @@ -/* sim_ether.c: OS-dependent network routines - ------------------------------------------------------------------------------ - - Copyright (c) 2002-2003, David T. Hittner - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of the author shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from the author. - - ------------------------------------------------------------------------------ - - This ethernet simulation is based on the PCAP and WinPcap packages. - - PCAP/WinPcap was chosen as the basis for network code since it is the most - "universal" of the various network packages available. Using this style has - allowed rapid network development for the major SIMH platforms. Developing - a network package specifically for SIMH was rejected due to the time required; - the advantage would be a more easily compiled and integrated code set. - - There are various problems associated with use of ethernet networking, which - would be true regardless of the network package used, since there are no - universally accepted networking methods. The most serious of these is getting - the proper networking package loaded onto the system, since most environments - do not come with the network interface packages loaded. - - The second most serious network issue relates to security. The network - simulation needs to simulate operating system level functionality (packet - driving). However, the host network programming interfaces tend to operate at - the user level of functionality, so getting to the full functionality of - the network interface usually requires that the person executing the - network code be a privileged user of the host system. See the PCAP/WinPcap - documentation for the appropriate host platform if unprivileged use of - networking is needed - there may be known workarounds. - - ------------------------------------------------------------------------------ - - Modification history: - - 30-May-03 DTH Changed WIN32 to _WIN32 for consistency - 07-Mar-03 MP Fixed Linux implementation of PacketGetAdapterNames to also - work on Red Hat 6.2-sparc and Debian 3.0r1-sparc. - 03-Mar-03 MP Changed logging to be consistent on stdout and sim_log - 01-Feb-03 MP Changed type of local variables in eth_packet_trace to - conform to the interface needs of eth_mac_fmt wich produces - char data instead of unsigned char data. Suggested by the - DECC compiler. - 15-Jan-03 DTH Corrected PacketGetAdapterNames parameter2 datatype - 26-Dec-02 DTH Merged Mark Pizzolato's enhancements with main source - Added networking documentation - Changed _DEBUG to ETH_DEBUG - 20-Dec-02 MP Added display of packet CRC to the eth_packet_trace. - This helps distinguish packets with identical lengths - and protocols. - 05-Dec-02 MP With the goal of draining the input buffer more rapidly - changed eth_read to call pcap_dispatch repeatedly until - either a timeout returns nothing or a packet allowed by - the filter is seen. This more closely reflects how the - pcap layer will work when the filtering is actually done - by a bpf filter. - 31-Oct-02 DTH Added USE_NETWORK conditional - Reworked not attached test - Added OpenBSD support (from Federico Schwindt) - Added ethX detection simplification (from Megan Gentry) - Removed sections of temporary code - Added parameter validation - 23-Oct-02 DTH Beta 5 released - 22-Oct-02 DTH Added all_multicast and promiscuous support - Fixed not attached behavior - 21-Oct-02 DTH Added NetBSD support (from Jason Thorpe) - Patched buffer size to make sure entire packet is read in - Made 'ethX' check characters passed as well as length - Corrected copyright again - 16-Oct-02 DTH Beta 4 released - Corrected copyright - 09-Oct-02 DTH Beta 3 released - Added pdp11 write acceleration (from Patrick Caulfield) - 08-Oct-02 DTH Beta 2 released - Integrated with 2.10-0p4 - Added variable vector and copyrights - 04-Oct-02 DTH Added linux support (from Patrick Caulfield) - 03-Oct-02 DTH Beta version of xq/sim_ether released for SIMH 2.09-11 - 24-Sep-02 DTH Finished eth_devices, eth_getname - 18-Sep-02 DTH Callbacks implemented - 13-Sep-02 DTH Basic packet read/write written - 20-Aug-02 DTH Created Sim_Ether for O/S independant ethernet implementation - - ------------------------------------------------------------------------------ - - Work left to do: - 1) Addition of other host Operating Systems (VMS, MAC, etc..) - 2) Possible efficiency increase by using BPF filtering - - ------------------------------------------------------------------------------ -*/ - - -#include "sim_ether.h" - -extern FILE *sim_log; - -/*============================================================================*/ -/* OS-independant ethernet routines */ -/*============================================================================*/ - -void eth_mac_fmt(ETH_MAC* mac, char* buff) -{ - uint8* m = (uint8*) mac; - sprintf(buff, "%02X-%02X-%02X-%02X-%02X-%02X", m[0], m[1], m[2], m[3], m[4], m[5]); - return; -} - -static const uint32 crcTable[256] = { - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, - 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, - 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, - 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, - 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, - 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, - 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, - 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, - 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, - 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, - 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, - 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, - 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, - 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, - 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, - 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, - 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, - 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, - 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, - 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, - 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, - 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, - 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, - 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, - 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, - 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, - 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, - 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, - 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, - 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, - 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, - 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, - 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, - 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, - 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, - 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, - 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D -}; - -uint32 eth_crc32(uint32 crc, const void* vbuf, size_t len) -{ - const uint32 mask = 0xFFFFFFFF; - const unsigned char* buf = (const unsigned char*)vbuf; - - crc ^= mask; - while (0 != len--) - crc = (crc >> 8) ^ crcTable[ (crc ^ (*buf++)) & 0xFF ]; - return(crc ^ mask); -} - - -void eth_packet_trace(ETH_PACK* packet, char* msg) -{ - char src[20]; - char dst[20]; - unsigned short* proto = (unsigned short*) &packet->msg[12]; - uint32 crc = eth_crc32(0, packet->msg, packet->len); - eth_mac_fmt((ETH_MAC*)&packet->msg[0], dst); - eth_mac_fmt((ETH_MAC*)&packet->msg[6], src); - printf("Eth: %s dst: %s src: %s protocol: %d len: %d crc: %X\n", - msg, dst, src, *proto, packet->len, crc); -} - -char* eth_getname(int number, char* name) -{ -#define ETH_SUPPORTED_DEVICES 10 - ETH_LIST list[ETH_SUPPORTED_DEVICES]; - int count = eth_devices(ETH_SUPPORTED_DEVICES, list); - - if (count < number) return 0; - strcpy(name, list[number].name); - return name; -} - -void eth_zero(ETH_DEV* dev) -{ - /* set all members to NULL OR 0 */ - memset(dev, 0, sizeof(ETH_DEV)); -} - -/*============================================================================*/ -/* Non-implemented versions */ -/*============================================================================*/ - -#if !defined (_WIN32) && !defined(linux) && !defined(__NetBSD__) && \ - !defined (__OpenBSD__) || !defined (USE_NETWORK) -t_stat eth_open (ETH_DEV* dev, char* name) - {return SCPE_NOFNC;} -t_stat eth_close (ETH_DEV* dev) - {return SCPE_NOFNC;} -t_stat eth_write (ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) - {return SCPE_NOFNC;} -t_stat eth_read (ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) - {return SCPE_NOFNC;} -t_stat eth_filter (ETH_DEV* dev, int addr_count, ETH_MAC* addresses, - ETH_BOOL all_multicast, ETH_BOOL promiscuous) - {return SCPE_NOFNC;} -int eth_devices (int max, ETH_LIST* dev) - {return 0;} -#else /* endif unimplemented */ - -/*============================================================================*/ -/* WIN32, Linux, NetBSD, and OpenBSD routines */ -/* Uses WinPcap and libpcap packages */ -/*============================================================================*/ - -#include -#include -#ifdef _WIN32 -#include -#endif /* _WIN32 */ -#if defined (__NetBSD__) || defined (__OpenBSD__) -#include -#include -#endif /* __NetBSD__ || __OpenBSD__*/ -#if defined (linux) || defined(__NetBSD__) || defined (__OpenBSD__) -#include -#endif /* linux || __NetBSD__ || __OpenBSD__ */ - -t_stat eth_open(ETH_DEV* dev, char* name) -{ - const int bufsz = (BUFSIZ < ETH_MAX_PACKET) ? ETH_MAX_PACKET : BUFSIZ; - char errbuf[PCAP_ERRBUF_SIZE]; - char temp[1024]; - char* savname = name; - int num; - - /* initialize device */ - eth_zero(dev); - - /* translate name of type "ethX" to real device name */ - if ((strlen(name) == 4) - && (tolower(name[0]) == 'e') - && (tolower(name[1]) == 't') - && (tolower(name[2]) == 'h') - && isdigit(name[3]) - ) { - num = atoi(&name[3]); - savname = eth_getname(num, temp); - } - - /* attempt to connect device */ - memset(errbuf, 0, sizeof(errbuf)); - dev->handle = (void*) pcap_open_live(savname, bufsz, ETH_PROMISC, -1, errbuf); - if (!dev->handle) { /* can't open device */ - printf ("Eth: pcap_open_live error - %s\n", errbuf); - if (sim_log) fprintf (sim_log, "Eth: pcap_open_live error - %s\n", errbuf); - return SCPE_OPENERR; - } else { - printf ("Eth: opened %s\n", savname); - if (sim_log) fprintf (sim_log, "Eth: opened %s\n", savname); - } - - /* save name of device */ - dev->name = malloc(strlen(savname)+1); - strcpy(dev->name, savname); - -#if defined (__NetBSD__) || defined(__OpenBSD__) - /* Tell the kernel that the header is fully-formed when it gets it. - This is required in order to fake the src address. - Code is embedded in braces to create a scope for the local variable */ - { - int one = 1; - ioctl(pcap_fileno(dev->handle), BIOCSHDRCMPLT, &one); - } -#endif /* __NetBSD__ || __OpenBSD__ */ - -#if defined(linux) || defined(__NetBSD__) || defined (__OpenBSD__) - /* set file non-blocking */ - fcntl(pcap_fileno(dev->handle), F_SETFL, fcntl(pcap_fileno(dev->handle), F_GETFL, 0) | O_NONBLOCK); -#endif /* linux || __NetBSD__ || __OpenBSD__ */ - - return SCPE_OK; -} - -t_stat eth_close(ETH_DEV* dev) -{ - /* make sure device exists */ - if (!dev) return SCPE_UNATT; - - /* close the device */ - pcap_close(dev->handle); - if (sim_log) fprintf (sim_log, "Eth: closed %s\n", dev->name); - - /* clean up the mess */ - free(dev->name); - eth_zero(dev); - - return SCPE_OK; -} - -t_stat eth_write(ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) -{ - int status = 1; /* default to failure */ - - /* make sure device exists */ - if (!dev) return SCPE_UNATT; - - /* make sure packet exists */ - if (!packet) return SCPE_ARG; - - /* make sure packet is acceptable length */ - if ((packet->len >= ETH_MIN_PACKET) && (packet->len <= ETH_MAX_PACKET)) { - /* dispatch write request (synchronous; no need to save write info to dev) */ -#ifdef ETH_DEBUG - eth_packet_trace (packet, "writing"); -#endif - status = pcap_sendpacket((pcap_t*)dev->handle, (u_char*)packet->msg, packet->len); - } /* if packet->len */ - - /* call optional write callback function */ - if (routine) - (routine)(status); - - return SCPE_OK; -} - -void eth_callback(u_char* info, const struct pcap_pkthdr* header, const u_char* data) -{ - ETH_DEV* dev = (ETH_DEV*) info; - - /* receive packet filter */ - int to_me = 0; - int from_me = 0; - int i; - for (i = 0; i < ETH_FILTER_MAX; i++) { - if (memcmp(data, dev->filter_address[i], 6) == 0) to_me = 1; -#ifdef _WIN32 - /* - WinPcap has a known bug/feature that whenever a packet is transmitted, - it is looped back into the receive buffers. This is not consistant with the - behavior of real ethernet adapters, so the extra packets must be disposed of. - - This behavior is seen when starting DECNET; DECNET broadcasts a packet - with the same source and destination addresses to make sure that no other - ethernet adapter on the network is using the DECNET address that it wants. - If it sees this test packet coming back in, it assumes that another node on - the network has the same DECNET address and refuses to start, giving an - "Invalid media address" error. - - This code section was ifdef'd for _WIN32 only to allow other OS's a chance to - properly implement the above behavior. If it breaks the ethernet simulator - on other platforms, remove the ifdef so that it will affect your platform, - and then notify the author so that he can fix the ifdef. :-) - */ - if (memcmp(&data[6], dev->filter_address[i], 6) == 0) from_me = 1; -#endif - } /* for */ - - /* all multicast mode? */ - if (dev->all_multicast && (data[0] & 0x01)) to_me = 1; - - /* promiscuous mode? */ - if (dev->promiscuous) to_me = 1; - - if (to_me && !from_me) { - - /* set data in passed read packet */ - dev->read_packet->len = header->len; - memcpy(dev->read_packet->msg, data, header->len); - -#ifdef ETH_DEBUG - eth_packet_trace (dev->read_packet, "reading"); -#endif - - /* call optional read callback function */ - if (dev->read_callback) - (dev->read_callback)(0); - - } /* if to_me && !from_me */ -} - -t_stat eth_read(ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) -{ - int status; - - /* make sure device exists */ - if (!dev) return SCPE_UNATT; - - /* make sure packet exists */ - if (!packet) return SCPE_ARG; - - /* set read packet */ - dev->read_packet = packet; - packet->len = 0; - - /* set optional callback routine */ - dev->read_callback = routine; - - /* dispatch read request to either receive a packet (after filtering) or timeout */ - do { - status = pcap_dispatch((pcap_t*)dev->handle, 1, ð_callback, (u_char*)dev); - } while ((status) && (0 == packet->len)); - return SCPE_OK; -} - -t_stat eth_filter(ETH_DEV* dev, int addr_count, ETH_MAC* addresses, - ETH_BOOL all_multicast, ETH_BOOL promiscuous) -{ - int i; - - /* make sure device exists */ - if (!dev) return SCPE_UNATT; - - /* filter count OK? */ - if ((addr_count < 0) || (addr_count > ETH_FILTER_MAX)) - return SCPE_ARG; - else - if (!addresses) return SCPE_ARG; - - /* clear filter array */ - memset(dev->filter_address, 0, sizeof(ETH_MAC) * ETH_FILTER_MAX); - - /* set new filter addresses */ - for (i = 0; i < addr_count; i++) - memcpy(dev->filter_address[i], addresses[i], sizeof(ETH_MAC)); - - /* store other flags */ - dev->all_multicast = all_multicast; - dev->promiscuous = promiscuous; - - return SCPE_OK; -} - -int eth_devices(int max, ETH_LIST* list) -{ - int i, index, len; - uint8 buffer[2048]; - uint8 buffer2[2048]; - uint8* cptr = buffer2; - unsigned long size = sizeof(buffer); - unsigned long ret; - - /* get names of devices from packet driver */ - ret = PacketGetAdapterNames(buffer, &size); - - /* device names in ascii or unicode format? */ - if ((buffer[1] == 0) && (buffer[3] == 0)) { /* unicode.. */ - int i = 0; - int cptr_inc = 2; - /* want to use buffer for scanning, so copy to buffer2 */ - memcpy (buffer2, buffer, sizeof(buffer)); - /* convert unicode to ascii (assuming every other byte is zero) */ - while (cptr < (buffer2 + sizeof(buffer2))) { - buffer[i] = *cptr; - if ((buffer[i] == 0) && (buffer[i-1] == 0)) { /* end of unicode devices */ - /* descriptions are in ascii, so change increment */ - cptr_inc = 1; - } - cptr += cptr_inc; - i++; - } - } - - /* scan ascii string and load list*/ - index = 0; - cptr = buffer; - /* extract device names and numbers */ - while (len = strlen(cptr)) { - list[index].num = index; - strcpy(list[index].name, cptr); - cptr += len + 1; - index++; - } - cptr += 2; - /* extract device descriptions */ - for (i=0; i < index; i++) { - len = strlen(cptr); - strcpy(list[i].desc, cptr); - cptr += len + 1; - } - return index; /* count of devices */ -} - -#endif /* (_WIN32 || linux || __NetBSD__ || __OpenBSD__) && USE_NETWORK */ - -/*============================================================================*/ -/* linux-specific code */ -/*============================================================================*/ - -#if defined (linux) && defined (USE_NETWORK) -#include -#include -#include /* for the glibc version number */ -#if (__GLIBC__ >= 2 && __GLIBC_MINOR >= 1) || __GLIBC__ >= 3 -#include -#include /* the L2 protocols */ -#else /*__GLIBC__*/ -#include -#include -#include -#include -#include /* The L2 protocols */ -#endif /*__GLIBC__*/ - -int pcap_sendpacket(pcap_t* handle, u_char* msg, int len) -{ - return (send(pcap_fileno(handle), msg, len, 0) == len)?0:-1; -} - -int PacketGetAdapterNames(char* buffer, unsigned long* size) -{ - struct ifreq ifr; - int iindex = 1; - int sock = socket(PF_PACKET, SOCK_RAW, 0); - int ptr = 0; - - ifr.ifr_ifindex = iindex; - - while (ioctl(sock, SIOCGIFNAME, &ifr) == 0) { - /* Only use ethernet interfaces */ - if ((0 == ioctl(sock, SIOCGIFHWADDR, &ifr)) && - (ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER)) { - strcpy(buffer+ptr, ifr.ifr_name); - ptr += strlen(buffer+ptr)+1; - } - ifr.ifr_ifindex = ++iindex; - } - if (ptr == 0) { /* Found any Ethernet Interfaces? */ - /* No, so try some good guesses since the SIOCGIFNAME ioctl - doesn't always return the ethernet interfaces, at least not - Debian or Red Hat running on sparc boxes. */ - - for (iindex=0; iindex < 10; ++iindex) { - sprintf(ifr.ifr_name, "eth%d", iindex); - if ((0 == ioctl(sock, SIOCGIFHWADDR, &ifr)) && - (ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER)) { - strcpy(buffer+ptr, ifr.ifr_name); - ptr += strlen(buffer+ptr)+1; - } - } - } - - close(sock); - - buffer[ptr++] = '\0'; - buffer[ptr++] = '\0'; - *size = ptr; -} - -#endif /* linux && USE_NETWORK */ - -/*============================================================================*/ -/* NetBSD/OpenBSD-specific code */ -/*============================================================================*/ - -#if (defined (__NetBSD__) || defined(__OpenBSD__)) && defined (USE_NETWORK) -#include -#include -#include -#include -#include -#include - -int pcap_sendpacket(pcap_t* handle, u_char* msg, int len) -{ - return (write(pcap_fileno(handle), msg, len) == len)?0:-1; -} - -int PacketGetAdapterNames(char* buffer, unsigned long* size) -{ - const struct sockaddr_dl *sdl; - struct ifaddrs *ifap, *ifa; - char *p; - int ptr = 0; - - if (getifaddrs(&ifap) != 0) { - *size = 0; - return (0); - } - - p = NULL; - for (ifa = ifap; ifa; ifa = ifa->ifa_next) { - if (ifa->ifa_addr->sa_family != AF_LINK) - continue; - if (p && strcmp(p, ifa->ifa_name) == 0) - continue; - sdl = (const struct sockaddr_dl *) ifa->ifa_addr; - if (sdl->sdl_type != IFT_ETHER) - continue; - - strcpy(buffer+ptr, ifa->ifa_name); - ptr += strlen(ifa->ifa_name)+1; - } - - freeifaddrs(ifap); - - buffer[ptr++] = '\0'; - buffer[ptr++] = '\0'; - *size = ptr; - - return (ptr); -} - -#endif /* (__NetBSD__ || __OpenBSD__) && USE_NETWORK */ - diff --git a/sim_ether.h b/sim_ether.h deleted file mode 100644 index b0471f57..00000000 --- a/sim_ether.h +++ /dev/null @@ -1,122 +0,0 @@ -/* sim_ether.h: OS-dependent network information - ------------------------------------------------------------------------------ - - Copyright (c) 2002-2003, David T. Hittner - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of the author shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from the author. - - ------------------------------------------------------------------------------ - - Modification history: - - 05-Jun-03 DTH Added used to struct eth_packet - 01-Feb-03 MP Changed some uint8 strings to char* to reflect usage - 22-Oct-02 DTH Added all_multicast and promiscuous support - 21-Oct-02 DTH Corrected copyright again - 16-Oct-02 DTH Fixed copyright - 08-Oct-02 DTH Integrated with 2.10-0p4, added variable vector and copyrights - 03-Oct-02 DTH Beta version of xq/sim_ether released for SIMH 2.09-11 - 15-Aug-02 DTH Started XQ simulation - - ------------------------------------------------------------------------------ -*/ - -#ifndef _SIM_ETHER_H -#define _SIM_ETHER_H - -#include "sim_defs.h" - -/* structure declarations */ - -#define ETH_PROMISC 1 /* promiscuous mode = true */ -#define ETH_TIMEOUT -1 /* read timeout in milliseconds (immediate) */ -#define ETH_FILTER_MAX 20 /* maximum address filters */ -#define ETH_BPF_INS_MAX 500 /* maximum bpf instructions */ -#define ETH_DEV_NAME_MAX 256 /* maximum device name size */ -#define ETH_DEV_DESC_MAX 256 /* maximum device description size */ -#define ETH_MIN_PACKET 60 /* minimum ethernet packet size */ -#define ETH_MAX_PACKET 1514 /* maximum ethernet packet size */ - -struct eth_packet { - uint8 msg[1518]; - int len; - int used; -}; - -struct eth_message { - int type; - struct eth_packet pack; -}; - -struct eth_queue { - int max; - int count; - int head; - int tail; - int loss; - struct eth_message* arr; -}; - -struct eth_list { - int num; - char name[ETH_DEV_NAME_MAX]; - char desc[ETH_DEV_DESC_MAX]; -}; - -typedef int ETH_BOOL; -typedef unsigned char ETH_MAC[6]; -typedef struct eth_packet ETH_PACK; -typedef void (*ETH_PCALLBACK)(int status); -typedef struct eth_list ETH_LIST; - -struct eth_device { - char* name; /* name of ethernet device */ - void* handle; /* handle of implementation-specific device */ - ETH_PCALLBACK read_callback; /* read callback function */ - ETH_PCALLBACK write_callback; /* write callback function */ - ETH_PACK* read_packet; /* read packet */ - ETH_PACK* write_packet; /* write packet */ - ETH_MAC filter_address[ETH_FILTER_MAX]; /* filtering addresses */ - ETH_BOOL promiscuous; /* promiscuous mode flag */ - ETH_BOOL all_multicast; /* receive all multicast messages */ -}; - -typedef struct eth_device ETH_DEV; - -/* prototype declarations*/ - -t_stat eth_open (ETH_DEV* dev, char* name); /* open ethernet interface */ -t_stat eth_close (ETH_DEV* dev); /* close ethernet interface */ -t_stat eth_write (ETH_DEV* dev, ETH_PACK* packet,/* write sychronous packet; */ - ETH_PCALLBACK routine); /* callback when done */ -t_stat eth_read (ETH_DEV* dev, ETH_PACK* packet,/* read single packet; */ - ETH_PCALLBACK routine); /* callback when done*/ -t_stat eth_filter (ETH_DEV* dev, int addr_count, /* set filter on incoming packets */ - ETH_MAC* addresses, - ETH_BOOL all_multicast, - ETH_BOOL promiscuous); -int eth_devices (int max, ETH_LIST* dev); /* get ethernet devices on host */ - -void eth_mac_fmt (ETH_MAC* add, char* buffer); /* format ethernet mac address */ -void eth_packet_trace (ETH_PACK* packet, char* msg); /* trace ethernet packet */ - -#endif /* _SIM_ETHER_H */ diff --git a/sim_rev.h b/sim_rev.h deleted file mode 100644 index 73702935..00000000 --- a/sim_rev.h +++ /dev/null @@ -1,832 +0,0 @@ -/* sim_rev.h: simulator revisions and current rev level - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. -*/ - -#ifndef _SIM_REV_H_ -#define _SIM_REV_H_ 0 - -#define SIM_MAJOR 3 -#define SIM_MINOR 0 -#define SIM_PATCH 2 - -/* V3.0 revision history - -patch date module(s) and fix(es) - - 2 tbd scp.c: - -- fixed end-of-file problem in dep, idep - -- fixed error on trailing spaces in dep, idep - - pdp1_stddev.c - -- fixed system hang if continue after PTR error - -- added PTR start/stop functionality - -- added address switch functionality to PTR BOOT - - pdp1_sys.c: added multibank capability to LOAD - - pdp18b_cpu.c: - -- fixed priorities in PDP-15 API (PI between 3 and 4) - -- fixed sign handling in PDP-15 unsigned mul/div - -- fixed bug in CAF, must clear API subsystem - - i1401_mt.c: - -- fixed tape read end-of-record handling based on real 1401 - -- added diagnostic read (space forward) - - i1620_cpu.c - -- fixed bug in immediate index add (found by Michael Short) - - 1 27-Jul-03 pdp1_cpu.c: updated to detect indefinite I/O wait - - pdp1_drm.c: fixed incorrect logical, missing activate, break - - pdp1_lp.c: - -- fixed bugs in instruction decoding, overprinting - -- updated to detect indefinite I/O wait - - pdp1_stddev.c: - -- changed RIM loader to be "hardware" - -- updated to detect indefinite I/O wait - - pdp1_sys.c: added block loader format support to LOAD - - pdp10_rp.c: fixed bug in read header - - pdp11_rq: fixed bug in user disk size (found by Chaskiel M Grundman) - - pdp18b_cpu.c: - -- added FP15 support - -- added XVM support - -- added EAE support to the PDP-4 - -- added PDP-15 "re-entrancy ECO" - -- fixed memory protect/skip interaction - -- fixed CAF to only reset peripherals - - pdp18b_fpp.c: added FP15 - - pdp18b_lp.c: fixed bug in Type 62 overprinting - - pdp18b_rf.c: fixed bug in set size routine - - pdp18b_stddev.c: - -- increased PTP TIME for PDP-15 operating systems - -- added hardware RIM loader for PDP-7, PDP-9, PDP-15 - - pdp18b_sys.c: added FP15, KT15, XVM instructions - - pdp8b_df.c, pdp8_rf.c: fixed bug in set size routine - - hp2100_dr.c: - -- fixed drum sizes - -- fixed variable capacity interaction with SAVE/RESTORE - - i1401_cpu.c: revised fetch to model hardware more closely - - ibm1130: fixed bugs found by APL 1130 - - nova_dsk.c: fixed bug in set size routine - - altairz80: fixed bug in real-time clock on Windows host - - 0 15-Jun-03 scp.c: - -- added ASSIGN/DEASSIGN - -- changed RESTORE to detach files - -- added u5, u6 unit fields - -- added USE_ADDR64 support - -- changed some structure fields to unsigned - - scp_tty.c: added extended file seek - - sim_sock.c: fixed calling sequence in stubs - - sim_tape.c: - -- added E11 and TPC format support - -- added extended file support - - sim_tmxr.c: fixed bug in SHOW CONNECTIONS - - all magtapes: - -- added multiformat support - -- added extended file support - - i1401_cpu.c: - -- fixed mnemonic, instruction lengths, and reverse - scan length check bug for MCS - -- fixed MCE bug, BS off by 1 if zero suppress - -- fixed chaining bug, D lost if return to SCP - -- fixed H branch, branch occurs after continue - -- added check for invalid 8 character MCW, LCA - - i1401_mt.c: fixed load-mode end of record response - - nova_dsk.c: fixed variable size interaction with restore - - pdp1_dt.c: fixed variable size interaction with restore - - pdp10_rp.c: fixed ordering bug in attach - - pdp11_cpu.c: - -- fixed bug in MMR1 update (found by Tim Stark) - -- fixed bug in memory size table - - pdp11_lp.c, pdp11_rq.c: added extended file support - - pdp11_rl.c, pdp11_rp.c, pdp11_ry.c: fixed ordering bug in attach - - pdp11_tc.c: fixed variable size interaction with restore - - pdp11_xq.c: - -- corrected interrupts on IE state transition (code by Tom Evans) - -- added interrupt clear on soft reset (first noted by Bob Supnik) - -- removed interrupt when setting XL or RL (multiple people) - -- added SET/SHOW XQ STATS - -- added SHOW XQ FILTERS - -- added ability to split received packet into multiple buffers - -- added explicit runt & giant packet processing - - vax_fpa.c: - -- fixed integer overflow bug in CVTfi - -- fixed multiple bugs in EMODf - - vax_io.c: optimized byte and word DMA routines - - vax_sysdev.c: - -- added calibrated delay to ROM reads (from Mark Pizzolato) - -- fixed calibration problems in interval timer (from Mark Pizzolato) - - pdp1_dt.c: fixed variable size interaction with restore - - pdp18b_dt.c: fixed variable size interaction with restore - - pdp18b_mt.c: fixed bug in MTTR - - pdp18b_rf.c: fixed variable size interaction with restore - - pdp8_df.c, pdp8_rf.c: fixed variable size interaction - with restore - - pdp8_dt.c: fixed variable size interaction with restore - - pdp8_mt.c: fixed bug in SKTR - - hp2100_dp.c,hp2100_dq.c: - -- fixed bug in read status (13210A controller) - -- fixed bug in seek completion - - id_pt.c: fixed type declaration (found by Mark Pizzolato) - - gri_cpu.c: fixed bug in SC queue pointer management - -/* V2.10 revision history - - 4 03-Mar-03 scp.c - -- added .ini startup file capability - -- added multiple breakpoint actions - -- added multiple switch evaluation points - -- fixed bug in multiword deposits to file - - sim_tape.c: magtape simulation library - - h316_stddev.c: added set line frequency command - - hp2100_mt.c, hp2100_ms.c: revised to use magtape library - - i1401_mt.c: revised to use magtape library - - id_dp.c, id_idc.c: fixed cylinder overflow on writes - - id_mt.c: - -- fixed error handling to stop selector channel - -- revised to use magtape library - - id16_sys.c, id32_sys.c: added relative addressing support - - id_uvc.c: - -- added set frequency command to line frequency clock - -- improved calibration algorithm for precision clock - - nova_clk.c: added set line frequency command - - nova_dsk.c: fixed autosizing algorithm - - nova_mt.c: revised to use magtape library - - pdp10_tu.c: revised to use magtape library - - pdp11_cpu.c: fixed bug in MMR1 update (found by Tim Stark) - - pdp11_stddev.c - -- added set line frequency command - -- added set ctrl-c command - - pdp11_rq.c: - -- fixed ordering problem in queue process - -- fixed bug in vector calculation for VAXen - -- added user defined drive support - - pdp11_ry.c: fixed autosizing algorithm - - pdp11_tm.c, pdp11_ts.c: revised to use magtape library - - pdp11_tq.c: - -- fixed ordering problem in queue process - -- fixed overly restrictive test for bad modifiers - -- fixed bug in vector calculation for VAXen - -- added variable controller, user defined drive support - -- revised to use magtape library - - pdp18b_cpu.c: fixed three EAE bugs (found by Hans Pufal) - - pdp18b_mt.c: - -- fixed bugs in BOT error handling, interrupt handling - -- revised to use magtape library - - pdp18b_rf.c: - -- removed 22nd bit from disk address - -- fixed autosizing algorithm - - pdp18b_stddev.c: - -- added set line frequency command - -- added set ctrl-c command - - pdp18b_sys.c: fixed FMTASC printouts (found by Hans Pufal) - - pdp8_clk.c: added set line frequency command - - pdp8_df.c, pdp8_rf.c, pdp8_rx.c: fixed autosizing algorithm - - pdp8_mt.c: - -- fixed bug in BOT error handling - -- revised to use magtape library - - pdp8_tt.c: added set ctrl-c command - - sds_cpu.c: added set line frequency command - - sds_mt.c: revised to use magtape library - - vax_stddev.c: added set ctrl-c command - - 3 06-Feb-03 scp.c: - -- added dynamic extension of the breakpoint table - -- added breakpoint actions - - hp2100_cpu.c: fixed last cycle bug in DMA output (found by - Mike Gemeny) - - hp2100_ipl.c: individual links are full duplex (found by - Mike Gemeny) - - pdp11_cpu.c: changed R, SP to track PSW respectively - - pdp18b_defs.h, pdp18b_sys.c: added RB09 fixed head disk, - LP09 printer - - pdp18b_rf.c: - -- fixed IOT decoding (found by Hans Pufal) - -- fixed address overrun logic - -- added variable number of platters and autosizing - - pdp18b_rf.c: - -- fixed IOT decoding - -- fixed bug in command initiation - - pdp18b_rb.c: new RB09 fixed head disk - - pdp18b_lp.c: new LP09 line printer - - pdp8_df.c: added variable number of platters and autosizing - - pdp8_rf.c: added variable number of platters and autosizing - - nova_dsk.c: added variable number of platters and autosizing - - id16_cpu.c: fixed bug in SETM, SETMR (found by Mark Pizzolato) - - 2 15-Jan-03 scp.c: - -- added dynamic memory size flag and RESTORE support - -- added EValuate command - -- added get_ipaddr routine - -- added ! (OS command) feature (from Mark Pizzolato) - -- added BREAK support to sim_poll_kbd (from Mark Pizzolato) - - sim_tmxr.c: - -- fixed bugs in IAC+IAC handling (from Mark Pizzolato) - -- added IAC+BRK handling (from Mark Pizzolato) - - sim_sock.c: - -- added use count for Windows start/stop - -- added sim_connect_sock - - pdp1_defs.h, pdp1_cpu.c, pdp1_sys.c, pdp1_drm.c: - added Type 24 serial drum - - pdp18_defs.h: added PDP-4 drum support - - hp2100_cpu.c: added 21MX IOP support - - hp2100_ipl.c: added HP interprocessor link support - - pdp11_tq.c: fixed bug in transfer end packet length - - pdp11_xq.c: - -- added VMScluster support (thanks to Mark Pizzolato) - -- added major performance enhancements (thanks to Mark Pizzolato) - -- added local packet processing - -- added system id broadcast - - pdp11_stddev.c: changed default to 7b (for early UNIX) - - vax_cpu.c, vax_io.c, vax_stddev.c, vax_sysdev.c: - added console halt capability (from Mark Pizzolato) - - all terminals and multiplexors: added BREAK support - - 1 21-Nov-02 pdp1_stddev.c: changed typewriter to half duplex - (found by Derek Peschel) - - pdp10_tu.c: - -- fixed bug in bootstrap (reported by Michael Thompson) - -- fixed bug in read (reported by Harris Newman) - - 0 15-Nov-02 SCP and libraries - scp.c: - -- added Telnet console support - -- removed VT emulation support - -- added support for statically buffered devices - -- added HELP - -- fixed bugs in set_logon, ssh_break (found by David Hittner) - -- added VMS file optimization (from Robert Alan Byer) - -- added quiet mode, DO with parameters, GUI interface, - extensible commands (from Brian Knittel) - -- added DEVICE context and flags - -- added central device enable/disable support - -- modified SAVE/GET to save and restore flags - -- modified boot routine calling sequence - scp_tty.c: - -- removed VT emulation support - -- added sim_os_sleep, renamed sim_poll_kbd, sim_putchar - sim_tmxr.c: - -- modified for Telnet console support - -- fixed bug in binary (8b) support - sim_sock.c: modified for Telnet console support - sim_ether.c: new library for Ethernet (from David Hittner) - - all magtapes: - -- added support for end of medium - -- cleaned up BOT handling - - all DECtapes: added support for RT11 image file format - - most terminals and multiplexors: - -- added support for 7b vs 8b character processing - - PDP-1 - pdp1_cpu.c, pdp1_sys.c, pdp1_dt.c: added PDP-1 DECtape support - - PDP-8 - pdp8_cpu.c, all peripherals: - -- added variable device number support - -- added new device enabled/disable support - pdp8_rx.c: added RX28/RX02 support - - PDP-11 - pdp11_defs.h, pdp11_io.c, pdp11_sys.c, all peripherals: - -- added variable vector support - -- added new device enable/disable support - -- added autoconfiguration support - all bootstraps: modified to support variable addresses - dec_mscp.h, pdp11_tq.c: added TK50 support - pdp11_rq.c: - -- added multicontroller support - -- fixed bug in HBE error log packet - -- fixed bug in ATP processing - pdp11_ry.c: added RX211/RX02 support - pdp11_hk.c: added RK611/RK06/RK07 support - pdp11_tq.c: added TMSCP support - pdp11_xq.c: added DEQNA/DELQA support (from David Hittner) - pdp11_pclk.c: added KW11P support - pdp11_ts.c: - -- fixed bug in CTL decoding - -- fixed bug in extended status XS0_MOT - pdp11_stddev.c: removed paper tape to its own module - - PDP-18b - pdp18b_cpu.c, all peripherals: - -- added variable device number support - -- added new device enabled/disabled support - - VAX - dec_dz.h: fixed bug in number of boards calculation - vax_moddefs.h, vax_io.c, vax_sys.c, all peripherals: - -- added variable vector support - -- added new device enable/disable support - -- added autoconfiguration support - vax_sys.c: - -- generalized examine/deposit - -- added TMSCP, multiple RQDX3, DEQNA/DELQA support - vax_stddev.c: removed paper tape, now uses PDP-11 version - vax_sysdev.c: - -- allowed NVR to be attached to file - -- removed unused variables (found by David Hittner) - - PDP-10 - pdp10_defs.h, pdp10_ksio.c, all peripherals: - -- added variable vector support - -- added new device enable/disable support - pdp10_defs.h, pdp10_ksio.c: added support for standard PDP-11 - peripherals, added RX211 support - pdp10_pt.c: rewritten to reference common implementation - - Nova, Eclipse: - nova_cpu.c, eclipse_cpu.c, all peripherals: - -- added new device enable/disable support - - HP2100 - hp2100_cpu: - -- fixed bugs in the EAU, 21MX, DMS, and IOP instructions - -- fixed bugs in the memory protect and DMS functions - -- created new options to enable/disable EAU, MPR, DMS - -- added new device enable/disable support - hp2100_fp.c: - -- recoded to conform to 21MX microcode algorithms - hp2100_stddev.c: - -- fixed bugs in TTY reset, OTA, time base generator - -- revised BOOT support to conform to RBL loader - -- added clock calibration - hp2100_dp.c: - -- changed default to 13210A - -- added BOOT support - hp2100_dq.c: - -- finished incomplete functions, fixed head switching - -- added BOOT support - hp2100_ms.c: - -- fixed bugs found by diagnostics - -- added 13183 support - -- added BOOT support - hp2100_mt.c: - -- fixed bugs found by diagnostics - -- disabled by default - hp2100_lpt.c: implemented 12845A controller - hp2100_lps.c: - -- renamed 12653A controller - -- added diagnostic mode for MPR, DCPC diagnostics - -- disabled by default - - IBM 1620: first release - -/* V2.9 revision history - - 11 20-Jul-02 i1401_mt.c: on read, end of record stores group mark - without word mark (found by Van Snyder) - - i1401_dp.c: reworked address generation and checking - - vax_cpu.c: added infinite loop detection and halt to - boot ROM option (from Mark Pizzolato) - - vax_fpa.c: changed function names to prevent conflict - with C math library - - pdp11_cpu.c: fixed bug in MMR0 update logic (from - John Dundas) - - pdp18b_stddev.c: added "ASCII mode" for reader and - punch (from Hans Pufal) - - gri_*.c: added GRI-909 simulator - - scp.c: added DO echo, DO exit (from Brian Knittel) - - scp_tty.c: added Windows priority hacking (from - Mark Pizzolato) - - 10 15-Jun-02 scp.c: fixed error checking on calls to fxread/fxwrite - (found by Norm Lastovic) - - scp_tty.c, sim_vt.h, sim_vt.c: added VTxxx emulation - support for Windows (from Fischer Franz) - - sim_sock.c: added OS/2 support (from Holger Veit) - - pdp11_cpu.c: fixed bugs (from John Dundas) - -- added special case for PS<15:12> = 1111 to MFPI - -- removed special case from MTPI - -- added masking of relocation adds - - i1401_cpu.c: - -- added multiply/divide - -- fixed bugs (found by Van Snyder) - o 5 and 7 character H, 7 character doesn't branch - o 8 character NOP - o 1401-like memory dump - - i1401_dp.c: added 1311 disk - - 9 04-May-02 pdp11_rq: fixed bug in polling routine - - 8 03-May-02 scp.c: - -- changed LOG/NOLOG to SET LOG/NOLOG - -- added SHOW LOG - -- added SET VT/NOVT and SHOW VT for VT emulation - - sim_sock.h: changed VMS stropt.h include to ioctl.h - - vax_cpu.c - -- added TODR powerup routine to set date, time on boot - -- fixed exception flows to clear trap request - -- fixed register logging in autoincrement indexed - - vax_stddev.c: added TODR powerup routine - - vax_cpu1.c: fixed exception flows to clear trap request - - 7 30-Apr-02 scp.c: fixed bug in clock calibration when (real) clock - jumps forward due too far (found by Jonathan Engdahl) - - pdp11_cpu.c: fixed bugs, added features (from John Dundas - and Wolfgang Helbig) - -- added HTRAP and BPOK to maintenance register - -- added trap on kernel HALT if MAINT set - -- fixed red zone trap, clear odd address and nxm traps - -- fixed RTS SP, don't increment restored SP - -- fixed TSTSET, write dst | 1 rather than prev R0 | 1 - -- fixed DIV, set N=0,Z=1 on div by zero (J11, 11/70) - -- fixed DIV, set set N=Z=0 on overfow (J11, 11/70) - -- fixed ASH, ASHC, count = -32 used implementation- - dependent 32 bit right shift - -- fixed illegal instruction test to detect 000010 - -- fixed write-only page test - - pdp11_rp.c: fixed SHOW ADDRESS command - - vaxmod_defs.h: fixed DZ vector base and number of lines - - dec_dz.h: - -- fixed interrupt acknowledge routines - -- fixed SHOW ADDRESS command - - all magtape routines: added test for badly formed - record length (suggested by Jonathan Engdahl) - - 6 18-Apr-02 vax_cpu.c: fixed CASEL condition codes - - vax_cpu1.c: fixed vfield pos > 31 test to be unsigned - - vax_fpu.c: fixed EDIV overflow test for 0 quotient - - 5 14-Apr-02 vax_cpu1.c: - -- fixed interrupt, prv_mode set to 0 (found by Tim Stark) - -- fixed PROBEx to mask mode to 2b (found by Kevin Handy) - - 4 1-Apr-02 pdp11_rq.c: fixed bug, reset cleared write protect status - - pdp11_ts.c: fixed bug in residual frame count after space - - 3 15-Mar-02 pdp11_defs.h: changed default model to KDJ11A (11/73) - - pdp11_rq.c: adjusted delays for M+ timing bugs - - hp2100_cpu.c, pdp10_cpu.c, pdp11_cpu.c: tweaked abort - code for ANSI setjmp/longjmp compliance - - hp2100_cpu.c, hp2100_fp.c, hp2100_stddev.c, hp2100_sys.c: - revised to allocate memory dynamically - - 2 01-Mar-02 pdp11_cpu.c: - -- fixed bugs in CPU registers - -- fixed double operand evaluation order for M+ - - pdp11_rq.c: added delays to initialization for - RSX11M+ prior to V4.5 - - 1 20-Feb-02 scp.c: fixed bug in clock calibration when (real) - time runs backwards - - pdp11_rq.c: fixed bug in host timeout logic - - pdp11_ts.c: fixed bug in message header logic - - pdp18b_defs.h, pdp18b_dt.c, pdp18b_sys.c: added - PDP-7 DECtape support - - hp2100_cpu.c: - -- added floating point and DMS - -- fixed bugs in DIV, ASL, ASR, LBT, SBT, CBT, CMW - - hp2100_sys.c: added floating point, DMS - - hp2100_fp.c: added floating point - - ibm1130: added Brian Knittel's IBM 1130 simulator - - 0 30-Jan-02 scp.c: - -- generalized timer package for multiple timers - -- added circular register arrays - -- fixed bugs, line spacing in modifier display - -- added -e switch to attach - -- moved device enable/disable to simulators - - scp_tty.c: VAX specific fix (from Robert Alan Byer) - - sim_tmxr.c, sim_tmxr.h: - -- added tmxr_fstats, tmxr_dscln - -- renamed tmxr_fstatus to tmxr_fconns - - sim_sock.c, sim_sock.h: added VMS support (from - Robert Alan Byer) - - pdp_dz.h, pdp18b_tt1.c, nova_tt1.c: - -- added SET DISCONNECT - -- added SHOW STATISTICS - - pdp8_defs.h: fixed bug in interrupt enable initialization - - pdp8_ttx.c: rewrote as unified multiplexor - - pdp11_cpu.c: fixed calc_MMR1 macro (found by Robert Alan Byer) - - pdp11_stddev.c: fixed bugs in KW11L (found by John Dundas) - - pdp11_rp.c: fixed bug in 18b mode boot - - pdp11 bootable I/O devices: fixed register setup at boot - exit (found by Doug Carman) - - hp2100_cpu.c: - -- fixed DMA register tables (found by Bill McDermith) - -- fixed SZx,SLx,RSS bug (found by Bill McDermith) - -- fixed flop restore logic (found by Bill McDermith) - - hp2100_mt.c: fixed bug on write of last character - - hp2100_dq,dr,ms,mux.c: added new disk, magtape, and terminal - multiplexor controllers - - i1401_cd.c, i1401_mt.c: new zero footprint bootstraps - (from Van Snyder) - - i1401_sys.c: fixed symbolic display of H, NOP with no trailing - word mark (found by Van Snyder) - - most CPUs: - -- replaced OLDPC with PC queue - -- implemented device enable/disable locally - - V2.8 revision history - -5 25-Dec-01 scp.c: fixed bug in DO command (found by John Dundas) - - pdp10_cpu.c: - -- moved trap-in-progress to separate variable - -- cleaned up declarations - -- cleaned up volatile state for GNU C longjmp - - pdp11_cpu.c: cleaned up declarations - - pdp11_rq.c: added RA-class disks - -4 17-Dec-01 pdp11_rq.c: added delayed processing of packets - -3 16-Dec-01 pdp8_cpu.c: - -- mode A EAE instructions didn't clear GTF - -- ASR shift count > 24 mis-set GTF - -- effective shift count == 32 didn't work - -2 07-Dec-01 scp.c: added breakpoint package - - all CPU's: revised to use new breakpoint package - -1 05-Dec-01 scp.c: fixed bug in universal register name logic - -0 30-Nov-01 Reorganized simh source and documentation tree - - scp: Added DO command, universal registers, extended - SET/SHOW logic - - pdp11: overhauled PDP-11 for DMA map support, shared - sources with VAX, dynamic buffer allocation - - 18b pdp: overhauled interrupt structure - - pdp8: added RL8A - - pdp10: fixed two ITS-related bugs (found by Dave Conroy) - - V2.7 revision history - -patch date module(s) and fix(es) - -15 23-Oct-01 pdp11_rp.c, pdp10_rp.c, pdp10_tu.c: fixed bugs - error interrupt handling - - pdp10_defs.h, pdp10_ksio.c, pdp10_fe.c, pdp10_fe.c, - pdp10_rp.c, pdp10_tu.c: reworked I/O page interface - to use symbolic base addresses and lengths - -14 20-Oct-01 dec_dz.h, sim_tmxr_h, sim_tmxr.c: fixed bug in Telnet - state handling (found by Thord Nilson), removed - tmxr_getchar, added tmxr_rqln and tmxr_tqln - -13 18-Oct-01 pdp11_tm.c: added stub diagnostic register clock - for RSTS/E (found by Thord Nilson) - -12 15-Oct-01 pdp11_defs.h, pdp11_cpu.c, pdp11_tc.c, pdp11_ts.c, - pdp11_rp.c: added operations logging - -11 8-Oct-01 scp.c: added sim_rev.h include and version print - - pdp11_cpu.c: fixed bug in interrupt acknowledge, - multiple outstanding interrupts caused the lowest - rather than the highest to be acknowledged - -10 7-Oct-01 pdp11_stddev.c: added monitor bits (CSR<7>) for full - KW11L compatibility, needed for RSTS/E autoconfiguration - -9 6-Oct-01 pdp11_rp.c, pdp10_rp.c, pdp10_tu.c: rewrote interrupt - logic from RH11/RH70 schematics, to mimic hardware quirks - - dec_dz.c: fixed bug in carrier detect logic, carrier - detect was being cleared on next modem poll - -8 4-Oct-01 pdp11_rp.c, pdp10_rp.c, pdp10_tu.c: undid edit of - 28-Sep-01; real problem was level-sensitive nature of - CS1_SC, but CS1_SC can only trigger an interrupt if - DONE is set - -7 2-Oct-01 pdp11_rp.c, pdp10_rp.c: CS1_SC is evaluated as a level- - sensitive, rather than an edge-sensitive, input to - interrupt request - -6 30-Sep-01 pdp11_rp.c, pdp10_rp.c: separated out CS1<5:0> to per- - drive registers - - pdp10_tu.c: based on above, cleaned up handling of - non-existent formatters, fixed non-data transfer - commands clearing DONE - -5 28-Sep-01 pdp11_rp.c, pdp10_rp.c, pdp10_tu.c: controller should - interrupt if ATA or SC sets when IE is set, was - interrupting only if DON = 1 as well - -4 27-Sep-01 pdp11_ts.c: - -- NXM errors should return TC4 or TC5; were returning TC3 - -- extended features is part of XS2; was returned in XS3 - -- extended characteristics (fifth) word needed for RSTS/E - - pdp11_tc.c: stop, stop all do cause an interrupt - - dec_dz.h: scanner should find a ready output line, even - if there are no connections; needed for RSTS/E autoconfigure - - scp.c: - -- added routine sim_qcount for 1130 - -- added "simulator exit" detach routine for 1130 - - sim_defs.h: added header for sim_qcount - -3 20-Sep-01 pdp11_ts.c: boot code binary was incorrect - -2 19-Sep-01 pdp18b_cpu.c: EAE should interpret initial count of 00 - as 100 - - scp.c: modified Macintosh support - -1 17-Sep-01 pdp8_ttx.c: new module for PDP-8 multi-terminal support - - pdp18b_tt1.c: modified to use sim_tmxr library - - nova_tt1.c: modified to use sim_tmxr library - - dec_dz.h: added autodisconnect support - - scp.c: removed old multiconsole support - - sim_tmxr.c: modified calling sequence for sim_putchar_ln - - sim_sock.c: added Macintosh sockets support -*/ - -#endif diff --git a/sim_sock.c b/sim_sock.c deleted file mode 100644 index e79380b3..00000000 --- a/sim_sock.c +++ /dev/null @@ -1,296 +0,0 @@ -/* sim_sock.c: OS-dependent socket routines - - Copyright (c) 2001-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 17-Apr-03 RMS Fixed non-implemented version of sim_close_sock - (found by Mark Pizzolato) - 17-Dec-02 RMS Added sim_connect_socket, sim_create_socket - 08-Oct-02 RMS Revised for .NET compatibility - 22-Aug-02 RMS Changed calling sequence for sim_accept_conn - 22-May-02 RMS Added OS2 EMX support from Holger Veit - 06-Feb-02 RMS Added VMS support from Robert Alan Byer - 16-Sep-01 RMS Added Macintosh support from Peter Schorn - 02-Sep-01 RMS Fixed UNIX bugs found by Mirian Lennox and Tom Markson -*/ - -#include "sim_defs.h" -#include "sim_sock.h" -#include - -/* OS dependent routines - - sim_master_sock create master socket - sim_accept_conn accept connection - sim_read_sock read from socket - sim_write_sock write from socket - sim_close_sock close socket - sim_setnonblock set socket non-blocking - sim_msg_sock send message to socket -*/ - -int32 sim_sock_cnt = 0; - -/* First, all the non-implemented versions */ - -#if defined (__OS2__) && !defined (__EMX__) - -SOCKET sim_master_sock (int32 port) -{ -return INVALID_SOCKET; -} - -SOCKET sim_connect_sock (int32 ip, int32 port) -{ -return INVALID_SOCKET; -} - -SOCKET sim_accept_conn (SOCKET master, uint32 *ipaddr) -{ -return INVALID_SOCKET; -} - -int32 sim_read_sock (SOCKET sock, char *buf, int32 nbytes) -{ -return -1; -} - -int32 sim_write_sock (SOCKET sock, char *msg, int32 nbytes) -{ -return 0; -} - -void sim_close_sock (SOCKET sock, t_bool master) -{ -return; -} - -SOCKET sim_setnonblock (SOCKET sock) -{ -return SOCKET_ERROR; -} - -#else /* endif unimpl */ - -/* UNIX, Win32, Macintosh, VMS, OS2 (Berkeley socket) routines */ - -SOCKET sim_err_sock (SOCKET s, char *emsg, int32 flg) -{ -int32 err = WSAGetLastError (); - -printf ("Sockets: %s error %d\n", emsg, err); -sim_close_sock (s, flg); -return INVALID_SOCKET; -} - -SOCKET sim_create_sock (void) -{ -SOCKET newsock; -int32 err; - -#if defined (_WIN32) -WORD wVersionRequested; -WSADATA wsaData; -wVersionRequested = MAKEWORD (1, 1); - -if (sim_sock_cnt == 0) { - err = WSAStartup (wVersionRequested, &wsaData); /* start Winsock */ - if (err != 0) { - printf ("Winsock: startup error %d\n", err); - return INVALID_SOCKET; } } -sim_sock_cnt = sim_sock_cnt + 1; -#endif /* endif Win32 */ - -newsock = socket (AF_INET, SOCK_STREAM, 0); /* create socket */ -if (newsock == INVALID_SOCKET) { /* socket error? */ - err = WSAGetLastError (); - printf ("Sockets: socket error %d\n", err); - return INVALID_SOCKET; } -return newsock; -} - -SOCKET sim_master_sock (int32 port) -{ -SOCKET newsock; -struct sockaddr_in name; -int32 sta; - -newsock = sim_create_sock (); /* create socket */ -if (newsock == INVALID_SOCKET) return newsock; /* socket error? */ - -name.sin_family = AF_INET; /* name socket */ -name.sin_port = htons ((unsigned short) port); /* insert port */ -name.sin_addr.s_addr = htonl (INADDR_ANY); /* insert addr */ - -sta = bind (newsock, (struct sockaddr *) &name, sizeof (name)); -if (sta == SOCKET_ERROR) /* bind error? */ - return sim_err_sock (newsock, "bind", 1); -sta = sim_setnonblock (newsock); /* set nonblocking */ -if (sta == SOCKET_ERROR) /* fcntl error? */ - return sim_err_sock (newsock, "fcntl", 1); -sta = listen (newsock, 1); /* listen on socket */ -if (sta == SOCKET_ERROR) /* listen error? */ - return sim_err_sock (newsock, "listen", 1); -return newsock; /* got it! */ -} - -SOCKET sim_connect_sock (int32 ip, int32 port) -{ -SOCKET newsock; -struct sockaddr_in name; -int32 sta; - -newsock = sim_create_sock (); /* create socket */ -if (newsock == INVALID_SOCKET) return newsock; /* socket error? */ - -name.sin_family = AF_INET; /* name socket */ -name.sin_port = htons ((unsigned short) port); /* insert port */ -name.sin_addr.s_addr = htonl (ip); /* insert addr */ - -sta = sim_setnonblock (newsock); /* set nonblocking */ -if (sta == SOCKET_ERROR) /* fcntl error? */ - return sim_err_sock (newsock, "fcntl", 1); -sta = connect (newsock, (struct sockaddr *) &name, sizeof (name)); -if ((sta == SOCKET_ERROR) && (WSAGetLastError () != WSAEWOULDBLOCK)) - return sim_err_sock (newsock, "connect", 1); - -return newsock; /* got it! */ -} - -SOCKET sim_accept_conn (SOCKET master, uint32 *ipaddr) -{ -int32 sta, err; -#if defined (macintosh) -socklen_t size; -#elif defined (_WIN32) || defined (__EMX__) -int size; -#else -size_t size; -#endif -SOCKET newsock; -struct sockaddr_in clientname; - -if (master == 0) return INVALID_SOCKET; /* not attached? */ -size = sizeof (clientname); -newsock = accept (master, (struct sockaddr *) &clientname, &size); -if (newsock == INVALID_SOCKET) { /* error? */ - err = WSAGetLastError (); - if (err != WSAEWOULDBLOCK) - printf ("Sockets: accept error %d\n", err); - return INVALID_SOCKET; } -if (ipaddr != NULL) *ipaddr = ntohl (clientname.sin_addr.s_addr); - -sta = sim_setnonblock (newsock); /* set nonblocking */ -if (sta == SOCKET_ERROR) /* fcntl error? */ - return sim_err_sock (newsock, "fcntl", 0); -return newsock; -} - -int32 sim_check_conn (SOCKET sock, t_bool rd) -{ -fd_set rw_set, er_set; -fd_set *rw_p = &rw_set; -fd_set *er_p = &er_set; -struct timeval tz; - -timerclear (&tz); -FD_ZERO (rw_p); -FD_ZERO (er_p); -FD_SET (sock, rw_p); -FD_SET (sock, er_p); -if (rd) select ((int) sock + 1, rw_p, NULL, er_p, &tz); -else select ((int) sock + 1, NULL, rw_p, er_p, &tz); -if (FD_ISSET (sock, rw_p)) return 1; -if (FD_ISSET (sock, er_p)) return -1; -return 0; -} - -int32 sim_read_sock (SOCKET sock, char *buf, int32 nbytes) -{ -int32 rbytes, err; - -rbytes = recv (sock, buf, nbytes, 0); -if (rbytes == 0) return -1; /* disconnect */ -if (rbytes == SOCKET_ERROR) { - err = WSAGetLastError (); - if (err == WSAEWOULDBLOCK) return 0; /* no data */ - printf ("Sockets: read error %d\n", err); - return -1; } -return rbytes; -} - -int32 sim_write_sock (SOCKET sock, char *msg, int32 nbytes) -{ -return send (sock, msg, nbytes, 0); -} - -void sim_close_sock (SOCKET sock, t_bool master) -{ -#if defined (_WIN32) -closesocket (sock); -if (master) { - sim_sock_cnt = sim_sock_cnt - 1; - if (sim_sock_cnt <= 0) { - WSACleanup (); - sim_sock_cnt = 0; } } -#else -close (sock); -#endif -return; -} - -#if defined (_WIN32) /* Windows */ -SOCKET sim_setnonblock (SOCKET sock) -{ -unsigned long non_block = 1; - -return ioctlsocket (sock, FIONBIO, &non_block); /* set nonblocking */ -} - -#elif defined (VMS) /* VMS */ -SOCKET sim_setnonblock (SOCKET sock) -{ -int non_block = 1; - -return ioctl (sock, FIONBIO, &non_block); /* set nonblocking */ -} - -#else /* Mac, Unix, OS/2 */ -int32 sim_setnonblock (SOCKET sock) -{ -int32 fl, sta; - -fl = fcntl (sock, F_GETFL,0); /* get flags */ -if (fl == -1) return SOCKET_ERROR; -sta = fcntl (sock, F_SETFL, fl | O_NONBLOCK); /* set nonblock */ -if (sta == -1) return SOCKET_ERROR; -#if !defined (macintosh) && !defined (__EMX__) /* Unix only */ -sta = fcntl (sock, F_SETOWN, getpid()); /* set ownership */ -if (sta == -1) return SOCKET_ERROR; -#endif -return 0; -} - -#endif /* endif !Win32 && !VMS */ - -#endif /* end else !implemented */ diff --git a/sim_sock.h b/sim_sock.h deleted file mode 100644 index c31ac676..00000000 --- a/sim_sock.h +++ /dev/null @@ -1,75 +0,0 @@ -/* sim_sock.h: OS-dependent socket routines header file - - Copyright (c) 2001-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 20-Mar-03 RMS Added missing timerclear definition for VMS (from - Robert Alan Byer) - 15-Feb-03 RMS Added time.h for EMX (from Holger Veit) - 17-Dec-02 RMS Added sim_connect_sock - 08-Oct-02 RMS Revised for .NET compatibility - 20-Aug-02 RMS Changed calling sequence for sim_accept_conn - 30-Apr-02 RMS Changed VMS stropts include to ioctl - 06-Feb-02 RMS Added VMS support from Robert Alan Byer - 16-Sep-01 RMS Added Macintosh support from Peter Schorn -*/ - -#ifndef _SIM_SOCK_H_ -#define _SIM_SOCK_H_ 0 - -#if defined (_WIN32) /* Windows */ -#undef INT_PTR /* hack, hack */ -#include - -#elif !defined (__OS2__) || defined (__EMX__) /* VMS, Mac, Unix, OS/2 EMX */ -#define WSAGetLastError() errno /* Windows macros */ -#define SOCKET int32 -#define WSAEWOULDBLOCK EWOULDBLOCK -#define INVALID_SOCKET -1 -#define SOCKET_ERROR -1 -#include /* for fcntl, getpid */ -#include /* for sockets */ -#include -#include -#include /* for sockaddr_in */ -#include -#include /* for EMX */ -#endif - -#if defined (VMS) /* VMS unique */ -#include /* for ioctl */ -#if !defined (timerclear) -#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 -#endif -#endif - -SOCKET sim_master_sock (int32 port); -SOCKET sim_connect_sock (int32 ip, int32 port); -SOCKET sim_accept_conn (SOCKET master, uint32 *ipaddr); -int32 sim_check_conn (SOCKET sock, t_bool rd); -int32 sim_read_sock (SOCKET sock, char *buf, int32 nbytes); -int32 sim_write_sock (SOCKET sock, char *msg, int32 nbytes); -void sim_close_sock (SOCKET sock, t_bool master); -SOCKET sim_setnonblock (SOCKET sock); - -#endif diff --git a/sim_tape.c b/sim_tape.c deleted file mode 100644 index ecd38a58..00000000 --- a/sim_tape.c +++ /dev/null @@ -1,548 +0,0 @@ -/* sim_tape.c: simulator tape support library - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - Ultimately, this will be a place to hide processing of various tape formats, - as well as OS-specific direct hardware access. - - 25-Apr-03 RMS Added extended file support - 28-Mar-03 RMS Added E11 and TPC format support - - Public routines: - - sim_tape_attach attach tape unit - sim_tape_detach detach tape unit - sim_tape_rdrecf read tape record forward - sim_tape_rdrecr read tape record reverse - sim_tape_wrrecf write tape record forward - sim_tape_sprecf space tape record forward - sim_tape_sprecr space tape record reverse - sim_tape_wrtmk write tape mark - sim_tape_wreom erase remainder of tape - sim_tape_rewind rewind - sim_tape_reset reset unit - sim_tape_bot TRUE if at beginning of tape - sim_tape_eot TRUE if at or beyond end of tape - sim_tape_wrp TRUE if write protected - sim_tape_set_fmt set tape format - sim_tape_show_fmt show tape format -*/ - -#include "sim_defs.h" -#include "sim_tape.h" - -struct sim_tape_fmt { - char *name; /* name */ - int32 uflags; /* unit flags */ - t_addr bot; /* bot test */ -}; - -static struct sim_tape_fmt fmts[MTUF_N_FMT] = { - { "SIMH", 0, sizeof (t_mtrlnt) - 1 }, - { "E11", 0, sizeof (t_mtrlnt) - 1 }, - { "TPC", UNIT_RO, sizeof (t_tpclnt) - 1 }, -/* { "TPF", UNIT_RO, 0 }, */ - { NULL, 0, 0 } -}; - -extern int32 sim_switches; - -t_stat sim_tape_ioerr (UNIT *uptr); -t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat); -uint32 sim_tape_tpc_map (UNIT *uptr, t_addr *map); -t_addr sim_tape_tpc_fnd (UNIT *uptr, t_addr *map); - -/* Attach tape unit */ - -t_stat sim_tape_attach (UNIT *uptr, char *cptr) -{ -uint32 objc; -char gbuf[CBUFSIZE]; -t_stat r; - -if (sim_switches & SWMASK ('F')) { /* format spec? */ - cptr = get_glyph (cptr, gbuf, 0); /* get spec */ - if (*cptr == 0) return SCPE_2FARG; /* must be more */ - if (sim_tape_set_fmt (uptr, 0, gbuf, NULL) != SCPE_OK) - return SCPE_ARG; } -r = attach_unit (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* error? */ - -switch (MT_GET_FMT (uptr)) { /* case on format */ -case MTUF_F_TPC: /* TPC */ - objc = sim_tape_tpc_map (uptr, NULL); /* get # objects */ - if (objc == 0) { /* tape empty? */ - sim_tape_detach (uptr); - return SCPE_FMT; } /* yes, complain */ - uptr->filebuf = calloc (objc + 1, sizeof (t_mtrlnt)); - if (uptr->filebuf == NULL) { /* map allocated? */ - sim_tape_detach (uptr); - return SCPE_MEM; } /* no, complain */ - uptr->hwmark = objc + 1; /* save map size */ - sim_tape_tpc_map (uptr, uptr->filebuf); /* fill map */ - break; -default: - break; } - -sim_tape_rewind (uptr); -return SCPE_OK; -} - -/* Detach tape unit */ - -t_stat sim_tape_detach (UNIT *uptr) -{ -uint32 f = MT_GET_FMT (uptr); -t_stat r; - -r = detach_unit (uptr); /* detach unit */ -if (r != SCPE_OK) return r; - -switch (f) { /* case on format */ -case MTUF_F_TPC: /* TPC */ - if (uptr->filebuf) free (uptr->filebuf); /* free map */ - uptr->filebuf = NULL; - uptr->hwmark = 0; - break; -default: - break; } - -sim_tape_rewind (uptr); -return SCPE_OK; -} - -/* Read record length forward (internal routine) - - Inputs: - uptr = pointer to tape unit - bc = pointer to returned record length - Outputs: - status = operation status - - exit condition position - - unit unattached unchanged - read error unchanged, PNU set - end of file/medium unchanged, PNU set - tape mark updated - data record updated, fxread will read record forward -*/ - -t_stat sim_tape_rdlntf (UNIT *uptr, t_mtrlnt *bc) -{ -uint32 f = MT_GET_FMT (uptr); -t_mtrlnt sbc; -t_tpclnt tpcbc; - -MT_CLR_PNU (uptr); -if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */ -fseek_ext (uptr->fileref, uptr->pos, SEEK_SET); /* set tape pos */ - -switch (f) { /* switch on fmt */ -case MTUF_F_STD: case MTUF_F_E11: - fxread (bc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */ - sbc = MTR_L (*bc); /* save rec lnt */ - if (ferror (uptr->fileref)) { /* error? */ - MT_SET_PNU (uptr); /* pos not upd */ - return sim_tape_ioerr (uptr); } - if (feof (uptr->fileref) || (*bc == MTR_EOM)) { /* eof or eom? */ - MT_SET_PNU (uptr); /* pos not upd */ - return MTSE_EOM; } - uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* spc over rec lnt */ - if (*bc == MTR_TMK) return MTSE_TMK; /* tape mark? */ - uptr->pos = uptr->pos + sizeof (t_mtrlnt) + /* spc over record */ - ((f == MTUF_F_STD)? ((sbc + 1) & ~1): sbc); - break; - -case MTUF_F_TPC: - fxread (&tpcbc, sizeof (t_tpclnt), 1, uptr->fileref); - *bc = tpcbc; /* save rec lnt */ - if (ferror (uptr->fileref)) { /* error? */ - MT_SET_PNU (uptr); /* pos not upd */ - return sim_tape_ioerr (uptr); } - if (feof (uptr->fileref)) { /* eof? */ - MT_SET_PNU (uptr); /* pos not upd */ - return MTSE_EOM; } - uptr->pos = uptr->pos + sizeof (t_tpclnt); /* spc over reclnt */ - if (tpcbc == TPC_TMK) return MTSE_TMK; /* tape mark? */ - uptr->pos = uptr->pos + ((tpcbc + 1) & ~1); /* spc over record */ - break; - -default: - return MTSE_FMT; } - -return MTSE_OK; -} - -/* Read record length reverse (internal routine) - - Inputs: - uptr = pointer to tape unit - bc = pointer to returned record length - Outputs: - status = operation status - - exit condition position - - unit unattached unchanged - beginning of tape unchanged - read error unchanged - end of file unchanged - end of medium updated - tape mark updated - data record updated, fxread will read record forward -*/ - -t_stat sim_tape_rdlntr (UNIT *uptr, t_mtrlnt *bc) -{ -uint32 f = MT_GET_FMT (uptr); -t_addr ppos; -t_mtrlnt sbc; -t_tpclnt tpcbc; - -MT_CLR_PNU (uptr); -if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */ -if (sim_tape_bot (uptr)) return MTSE_BOT; /* at BOT? */ - -switch (f) { /* switch on fmt */ -case MTUF_F_STD: case MTUF_F_E11: - fseek_ext (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET); - fxread (bc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */ - sbc = MTR_L (*bc); - if (ferror (uptr->fileref)) /* error? */ - return sim_tape_ioerr (uptr); - if (feof (uptr->fileref)) return MTSE_EOM; /* eof? */ - uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over rec lnt */ - if (*bc == MTR_EOM) return MTSE_EOM; /* eom? */ - if (*bc == MTR_TMK) return MTSE_TMK; /* tape mark? */ - uptr->pos = uptr->pos - sizeof (t_mtrlnt) - /* spc over record */ - ((f == MTUF_F_STD)? ((sbc + 1) & ~1): sbc); - fseek_ext (uptr->fileref, uptr->pos + sizeof (t_mtrlnt), SEEK_SET); - break; - -case MTUF_F_TPC: - ppos = sim_tape_tpc_fnd (uptr, uptr->filebuf); /* find prev rec */ - fseek_ext (uptr->fileref, ppos, SEEK_SET); /* position */ - fxread (&tpcbc, sizeof (t_tpclnt), 1, uptr->fileref); - *bc = tpcbc; /* save rec lnt */ - if (ferror (uptr->fileref)) /* error? */ - return sim_tape_ioerr (uptr); - if (feof (uptr->fileref)) return MTSE_EOM; /* eof? */ - uptr->pos = ppos; /* spc over record */ - if (*bc == MTR_TMK) return MTSE_TMK; /* tape mark? */ - fseek_ext (uptr->fileref, uptr->pos + sizeof (t_tpclnt), SEEK_SET); - break; -default: - return MTSE_FMT; } -return MTSE_OK; -} - -/* Read record forward - - Inputs: - uptr = pointer to tape unit - buf = pointer to buffer - bc = pointer to returned record length - max = maximum record size - Outputs: - status = operation status - - exit condition position - - unit unattached unchanged - read error unchanged, PNU set - end of file/medium unchanged, PNU set - invalid record unchanged, PNU set - tape mark updated - data record updated - data record error updated -*/ - -t_stat sim_tape_rdrecf (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max) -{ -t_mtrlnt i, tbc, rbc; -t_addr opos; -t_stat st; - -opos = uptr->pos; /* old position */ -if (st = sim_tape_rdlntf (uptr, &tbc)) return st; /* read rec lnt */ -*bc = rbc = MTR_L (tbc); /* strip error flag */ -if (rbc > max) { /* rec out of range? */ - MT_SET_PNU (uptr); - uptr->pos = opos; - return MTSE_INVRL; } -i = fxread (buf, sizeof (uint8), rbc, uptr->fileref); /* read record */ -if (ferror (uptr->fileref)) { /* error? */ - MT_SET_PNU (uptr); - uptr->pos = opos; - return sim_tape_ioerr (uptr); } -for ( ; i < rbc; i++) buf[i] = 0; /* fill with 0's */ -return (MTR_F (tbc)? MTSE_RECE: MTSE_OK); -} - -/* Read record reverse - - Inputs: - uptr = pointer to tape unit - buf = pointer to buffer - bc = pointer to returned record length - max = maximum record size - Outputs: - status = operation status - - exit condition position - - unit unattached unchanged - read error unchanged - end of file unchanged - end of medium updated - invalid record unchanged - tape mark updated - data record updated - data record error updated -*/ - -t_stat sim_tape_rdrecr (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max) -{ -t_mtrlnt i, rbc, tbc; -t_stat st; - -if (st = sim_tape_rdlntr (uptr, &tbc)) return st; /* read rec lnt */ -*bc = rbc = MTR_L (tbc); /* strip error flag */ -if (rbc > max) return MTSE_INVRL; /* rec out of range? */ -i = fxread (buf, sizeof (uint8), rbc, uptr->fileref); /* read record */ -if (ferror (uptr->fileref)) /* error? */ - return sim_tape_ioerr (uptr); -for ( ; i < rbc; i++) buf[i] = 0; /* fill with 0's */ -return (MTR_F (tbc)? MTSE_RECE: MTSE_OK); -} - -/* Write record forward - - Inputs: - uptr = pointer to tape unit - buf = pointer to buffer - bc = record length - Outputs: - status = operation status - - exit condition position - - unit unattached unchanged - write protect unchanged - write error unchanged, PNU set - data record updated -*/ - -t_stat sim_tape_wrrecf (UNIT *uptr, uint8 *buf, t_mtrlnt bc) -{ -uint32 f = MT_GET_FMT (uptr); -t_mtrlnt sbc; - -MT_CLR_PNU (uptr); -if (f == MTUF_F_STD) sbc = (bc + 1) & ~1; -else sbc = bc; -if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */ -if (uptr->flags & MTUF_WRP) return MTSE_WRP; /* write prot? */ -fseek_ext (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */ -fxwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref); -fxwrite (buf, sizeof (uint8), sbc, uptr->fileref); -fxwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref); -if (ferror (uptr->fileref)) { /* error? */ - MT_SET_PNU (uptr); - return sim_tape_ioerr (uptr); } -uptr->pos = uptr->pos + sbc + (2 * sizeof (t_mtrlnt)); /* move tape */ -return MTSE_OK; -} - -/* Write metadata forward (internal routine) */ - -t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat) -{ -MT_CLR_PNU (uptr); -if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */ -if (uptr-> flags & MTUF_WRP) return MTSE_WRP; /* write prot? */ -fseek_ext (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */ -fxwrite (&dat, sizeof (t_mtrlnt), 1, uptr->fileref); -if (ferror (uptr->fileref)) { /* error? */ - MT_SET_PNU (uptr); - return sim_tape_ioerr (uptr); } -uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* move tape */ -return MTSE_OK; -} - -/* Write tape mark */ - -t_stat sim_tape_wrtmk (UNIT *uptr) -{ -return sim_tape_wrdata (uptr, MTR_TMK); -} - -/* Write end of medium */ - -t_stat sim_tape_wreom (UNIT *uptr) -{ -return sim_tape_wrdata (uptr, MTR_EOM); -} - -/* Space record forward */ - -t_stat sim_tape_sprecf (UNIT *uptr, t_mtrlnt *bc) -{ -t_stat st; - -st = sim_tape_rdlntf (uptr, bc); /* get record length */ -*bc = MTR_L (*bc); -return st; -} - -/* Space record reverse */ - -t_stat sim_tape_sprecr (UNIT *uptr, t_mtrlnt *bc) -{ -t_stat st; - -if (MT_TST_PNU (uptr)) { - MT_CLR_PNU (uptr); - *bc = 0; - return SCPE_OK; } -st = sim_tape_rdlntr (uptr, bc); /* get record length */ -*bc = MTR_L (*bc); -return st; -} - -/* Rewind tape */ - -t_stat sim_tape_rewind (UNIT *uptr) -{ -uptr->pos = 0; -MT_CLR_PNU (uptr); -return MTSE_OK; -} - -/* Reset tape */ - -t_stat sim_tape_reset (UNIT *uptr) -{ -MT_CLR_PNU (uptr); -return SCPE_OK; -} - -/* Test for BOT */ - -t_bool sim_tape_bot (UNIT *uptr) -{ -uint32 f = MT_GET_FMT (uptr); - -return (uptr->pos <= fmts[f].bot)? TRUE: FALSE; -} - -/* Test for end of tape */ - -t_bool sim_tape_eot (UNIT *uptr, t_addr cap) -{ -return (uptr->pos > cap)? TRUE: FALSE; -} - -/* Test for write protect */ - -t_bool sim_tape_wrp (UNIT *uptr) -{ -return (uptr->flags & MTUF_WRP)? TRUE: FALSE; -} - -/* Process I/O error */ - -t_stat sim_tape_ioerr (UNIT *uptr) -{ -perror ("Magtape library I/O error"); -clearerr (uptr->fileref); -return SCPE_IOERR; -} - -/* Set tape format */ - -t_stat sim_tape_set_fmt (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 f; - -if (uptr == NULL) return SCPE_IERR; -if (cptr == NULL) return SCPE_ARG; -for (f = 0; f < MTUF_N_FMT; f++) { - if (fmts[f].name && (strcmp (cptr, fmts[f].name) == 0)) { - uptr->flags = (uptr->flags & ~MTUF_FMT) | - (f << MTUF_V_FMT) | fmts[f].uflags; - return SCPE_OK; } } -return SCPE_ARG; -} - -/* Show tape format */ - -t_stat sim_tape_show_fmt (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 f = MT_GET_FMT (uptr); - -if (fmts[f].name) fprintf (st, "%s format", fmts[f].name); -else fprintf (st, "invalid format"); -return SCPE_OK; -} - -/* Map a TPC format tape image */ - -uint32 sim_tape_tpc_map (UNIT *uptr, t_addr *map) -{ -t_addr tpos; -t_tpclnt bc; -uint32 i, objc; - -if ((uptr == NULL) || (uptr->fileref == NULL)) return 0; -for (objc = 0, tpos = 0;; ) { - fseek_ext (uptr->fileref, tpos, SEEK_SET); - i = fxread (&bc, sizeof (t_tpclnt), 1, uptr->fileref); - if (i == 0) break; - if (map) map[objc] = tpos; - objc++; - tpos = tpos + ((bc + 1) & ~1) + sizeof (t_tpclnt); } -if (map) map[objc] = tpos; -return objc; -} - -/* Find the preceding record in a TPC file */ - -t_addr sim_tape_tpc_fnd (UNIT *uptr, t_addr *map) -{ -uint32 lo, hi, p; - - -if (map == NULL) return 0; -lo = 0; -hi = uptr->hwmark - 1; -do { p = (lo + hi) >> 1; - if (uptr->pos == map[p]) - return ((p == 0)? map[p]: map[p - 1]); - else if (uptr->pos < map[p]) hi = p - 1; - else lo = p + 1; } -while (lo <= hi); -return ((p == 0)? map[p]: map[p - 1]); -} diff --git a/sim_tape.h b/sim_tape.h deleted file mode 100644 index 74d3f363..00000000 --- a/sim_tape.h +++ /dev/null @@ -1,101 +0,0 @@ -/* sim_tape.h: simulator tape support library definitions - - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. -*/ - -#ifndef _SIM_TAPE_H_ -#define _SIM_TAPE_H_ 0 - -/* SIMH/E11 tape format */ - -typedef uint32 t_mtrlnt; /* magtape rec lnt */ - -#define MTR_TMK 0x00000000 /* tape mark */ -#define MTR_EOM 0xFFFFFFFF /* end of medium */ -#define MTR_ERF 0x80000000 /* error flag */ -#define MTR_F(x) ((x) & MTR_ERF) /* record error flg */ -#define MTR_L(x) ((x) & ~MTR_ERF) /* record length */ - -/* TPC tape format */ - -typedef uint16 t_tpclnt; /* magtape rec lnt */ - -#define TPC_TMK 0x0000 /* tape mark */ - -/* Unit flags */ - -#define MTUF_V_PNU (UNIT_V_UF + 0) /* position not upd */ -#define MTUF_V_WLK (UNIT_V_UF + 1) /* write locked */ -#define MTUF_V_FMT (UNIT_V_UF + 2) /* tape file format */ -#define MTUF_W_FMT 3 /* 3b of formats */ -#define MTUF_N_FMT (1u << MTUF_W_FMT) /* number of formats */ -#define MTUF_M_FMT ((1u << MTUF_W_FMT) - 1) -#define MTUF_F_STD 0 /* SIMH format */ -#define MTUF_F_E11 1 /* E11 format */ -#define MTUF_F_TPC 2 /* TPC format */ -#define MUTF_F_TDF 3 /* TDF format */ -#define MTUF_V_UF (MTUF_V_FMT + MTUF_W_FMT) -#define MTUF_PNU (1u << MTUF_V_PNU) -#define MTUF_WLK (1u << MTUF_V_WLK) -#define MTUF_FMT (MTUF_M_FMT << MTUF_V_FMT) -#define MTUF_WRP (MTUF_WLK | UNIT_RO) - -#define MT_SET_PNU(u) (u)->flags = (u)->flags | MTUF_PNU -#define MT_CLR_PNU(u) (u)->flags = (u)->flags & ~MTUF_PNU -#define MT_TST_PNU(u) ((u)->flags & MTUF_PNU) -#define MT_GET_FMT(u) (((u)->flags >> MTUF_V_FMT) & MTUF_M_FMT) - -/* Return status codes */ - -#define MTSE_OK 0 /* no error */ -#define MTSE_TMK 1 /* tape mark */ -#define MTSE_UNATT 2 /* unattached */ -#define MTSE_IOERR 3 /* IO error */ -#define MTSE_INVRL 4 /* invalid rec lnt */ -#define MTSE_FMT 5 /* invalid format */ -#define MTSE_BOT 6 /* beginning of tape */ -#define MTSE_EOM 7 /* end of medium */ -#define MTSE_RECE 8 /* error in record */ -#define MTSE_WRP 9 /* write protected */ - -/* Prototypes */ - -t_stat sim_tape_attach (UNIT *uptr, char *cptr); -t_stat sim_tape_detach (UNIT *uptr); -t_stat sim_tape_rdrecf (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max); -t_stat sim_tape_rdrecr (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max); -t_stat sim_tape_wrrecf (UNIT *uptr, uint8 *buf, t_mtrlnt bc); -t_stat sim_tape_wrtmk (UNIT *uptr); -t_stat sim_tape_wreom (UNIT *uptr); -t_stat sim_tape_sprecf (UNIT *uptr, t_mtrlnt *bc); -t_stat sim_tape_sprecr (UNIT *uptr, t_mtrlnt *bc); -t_stat sim_tape_rewind (UNIT *uptr); -t_stat sim_tape_reset (UNIT *uptr); -t_bool sim_tape_bot (UNIT *uptr); -t_bool sim_tape_wrp (UNIT *uptr); -t_bool sim_tape_eot (UNIT *uptr, t_addr cap); -t_stat sim_tape_set_fmt (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat sim_tape_show_fmt (FILE *st, UNIT *uptr, int32 val, void *desc); - -#endif diff --git a/sim_tmxr.c b/sim_tmxr.c deleted file mode 100644 index e3f0f6a8..00000000 --- a/sim_tmxr.c +++ /dev/null @@ -1,496 +0,0 @@ -/* sim_tmxr.c: Telnet terminal multiplexor library - - Copyright (c) 2001-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - Based on the original DZ11 simulator by Thord Nilson, as updated by - Arthur Krewat. - - 09-Mar-03 RMS Fixed bug in SHOW CONN - 22-Dec-02 RMS Fixed bugs in IAC+IAC receive and transmit sequences - Added support for received break (all from by Mark Pizzolato) - Fixed bug in attach - 31-Oct-02 RMS Fixed bug in 8b (binary) support - 22-Aug-02 RMS Added tmxr_open_master, tmxr_close_master - 30-Dec-01 RMS Added tmxr_fstats, tmxr_dscln, renamed tmxr_fstatus - 03-Dec-01 RMS Changed tmxr_fconns for extended SET/SHOW - 20-Oct-01 RMS Fixed bugs in read logic (found by Thord Nilson). - Added tmxr_rqln, tmxr_tqln -*/ - -#include "sim_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" -#include - -/* Telnet protocol constants - negatives are for init'ing signed char data */ - -#define TN_IAC -1 /* protocol delim */ -#define TN_DONT -2 /* dont */ -#define TN_DO -3 /* do */ -#define TN_WONT -4 /* wont */ -#define TN_WILL -5 /* will */ -#define TN_BRK -13 /* break */ -#define TN_BIN 0 /* bin */ -#define TN_ECHO 1 /* echo */ -#define TN_SGA 3 /* sga */ -#define TN_LINE 34 /* line mode */ -#define TN_CR 015 /* carriage return */ - -/* Telnet line states */ - -#define TNS_NORM 000 /* normal */ -#define TNS_IAC 001 /* IAC seen */ -#define TNS_WILL 002 /* WILL seen */ -#define TNS_WONT 003 /* WONT seen */ -#define TNS_SKIP 004 /* skip next */ - -void tmxr_rmvrc (TMLN *lp, int32 p); -extern int32 sim_switches; -extern char sim_name[]; -extern FILE *sim_log; -extern uint32 sim_os_msec (void); - -/* Poll for new connection - - Called from unit service routine to test for new connection - - Inputs: - *mp = pointer to terminal multiplexor descriptor - Outputs: - line number activated, -1 if none -*/ - -int32 tmxr_poll_conn (TMXR *mp) -{ -SOCKET newsock; -TMLN *lp; -int32 i; -uint32 ipaddr; -static char mantra[] = { - TN_IAC, TN_WILL, TN_LINE, - TN_IAC, TN_WILL, TN_SGA, - TN_IAC, TN_WILL, TN_ECHO, - TN_IAC, TN_WILL, TN_BIN, - TN_IAC, TN_DO, TN_BIN }; - -newsock = sim_accept_conn (mp->master, &ipaddr); /* poll connect */ -if (newsock != INVALID_SOCKET) { /* got a live one? */ - for (i = 0; i < mp->lines; i++) { /* find avail line */ - lp = mp->ldsc[i]; /* ptr to ln desc */ - if (lp->conn == 0) break; } /* available? */ - if (i >= mp->lines) { /* all busy? */ - tmxr_msg (newsock, "All connections busy\r\n"); - sim_close_sock (newsock, 0); } - else { - lp = mp->ldsc[i]; /* get line desc */ - lp->conn = newsock; /* record connection */ - lp->ipad = ipaddr; /* ip address */ - lp->cnms = sim_os_msec (); /* time of conn */ - lp->rxbpr = lp->rxbpi = 0; /* init buf pointers */ - lp->txbpr = lp->txbpi = 0; - lp->rxcnt = lp->txcnt = 0; /* init counters */ - lp->tsta = 0; /* init telnet state */ - lp->xmte = 1; /* enable transmit */ - lp->dstb = 0; /* default bin mode */ - sim_write_sock (newsock, mantra, 15); - tmxr_msg (newsock, "\n\r\nConnected to the "); - tmxr_msg (newsock, sim_name); - tmxr_msg (newsock, " simulator\r\n\n"); - return i; } - } /* end if newsock */ -return -1; -} - -/* Reset line */ - -void tmxr_reset_ln (TMLN *lp) -{ -sim_close_sock (lp->conn, 0); /* reset conn */ -lp->conn = lp->tsta = 0; /* reset state */ -lp->rxbpr = lp->rxbpi = 0; -lp->txbpr = lp->txbpi = 0; -lp->xmte = 1; -lp->dstb = 0; -return; -} - -/* Get character from specific line - - Inputs: - *lp = pointer to terminal line descriptor - Output: - valid + char, 0 if line -*/ - -int32 tmxr_getc_ln (TMLN *lp) -{ -int32 j, val = 0; -uint32 tmp; - -if (lp->conn && lp->rcve) { /* conn & enb? */ - j = lp->rxbpi - lp->rxbpr; /* # input chrs */ - if (j) { /* any? */ - tmp = lp->rxb[lp->rxbpr]; /* get char */ - val = TMXR_VALID | (tmp & 0377); /* valid + chr */ - if (lp->rbr[lp->rxbpr]) val = val | SCPE_BREAK; /* break? */ - lp->rxbpr = lp->rxbpr + 1; } /* adv pointer */ - } /* end if conn */ -if (lp->rxbpi == lp->rxbpr) /* empty? zero ptrs */ - lp->rxbpi = lp->rxbpr = 0; -return val; -} - -/* Poll for input - - Inputs: - *mp = pointer to terminal multiplexor descriptor - Outputs: none -*/ - -void tmxr_poll_rx (TMXR *mp) -{ -int32 i, nbytes, j; -TMLN *lp; - -for (i = 0; i < mp->lines; i++) { /* loop thru lines */ - lp = mp->ldsc[i]; /* get line desc */ - if (!lp->conn || !lp->rcve) continue; /* skip if !conn */ - - nbytes = 0; - if (lp->rxbpi == 0) /* need input? */ - nbytes = sim_read_sock (lp->conn, /* yes, read */ - &(lp->rxb[lp->rxbpi]), /* leave spc for */ - TMXR_MAXBUF - TMXR_GUARD); /* Telnet cruft */ - else if (lp->tsta) /* in Telnet seq? */ - nbytes = sim_read_sock (lp->conn, /* yes, read to end */ - &(lp->rxb[lp->rxbpi]), - TMXR_MAXBUF - lp->rxbpi); - if (nbytes < 0) tmxr_reset_ln (lp); /* closed? reset ln */ - else if (nbytes > 0) { /* if data rcvd */ - j = lp->rxbpi; /* start of data */ - memset (&lp->rbr[j], 0, nbytes); /* clear status */ - lp->rxbpi = lp->rxbpi + nbytes; /* adv pointers */ - lp->rxcnt = lp->rxcnt + nbytes; - -/* Examine new data, remove TELNET cruft before making input available */ - - for (; j < lp->rxbpi; ) { /* loop thru char */ - char tmp = lp->rxb[j]; /* get char */ - switch (lp->tsta) { /* case tlnt state */ - case TNS_NORM: /* normal */ - if (tmp == TN_IAC) { /* IAC? */ - lp->tsta = TNS_IAC; /* change state */ - tmxr_rmvrc (lp, j); /* remove char */ - break; } - if ((tmp == TN_CR) && lp->dstb) /* CR, no bin */ - lp->tsta = TNS_SKIP; /* skip next */ - j = j + 1; /* advance j */ - break; - case TNS_IAC: /* IAC prev */ - if ((tmp == TN_IAC) & !lp->dstb) { /* IAC + IAC, bin? */ - lp->tsta = TNS_NORM; /* treat as normal */ - j = j + 1; /* advance j */ - break; } /* keep IAC */ - if (tmp == TN_BRK) { /* IAC + BRK? */ - lp->tsta = TNS_NORM; /* treat as normal */ - lp->rxb[j] = 0; /* char is null */ - lp->rbr[j] = 1; /* flag break */ - j = j + 1; /* advance j */ - break; } - if (tmp == TN_WILL) /* IAC + WILL? */ - lp->tsta = TNS_WILL; - else if (tmp == TN_WONT) /* IAC + WONT? */ - lp->tsta = TNS_WONT; - else lp->tsta = TNS_SKIP; /* IAC + other */ - tmxr_rmvrc (lp, j); /* remove char */ - break; - case TNS_WILL: case TNS_WONT: /* IAC+WILL/WONT prev */ - if (tmp == TN_BIN) { /* BIN? */ - if (lp->tsta == TNS_WILL) lp->dstb = 0; - else lp->dstb = 1; } - case TNS_SKIP: default: /* skip char */ - lp->tsta = TNS_NORM; /* next normal */ - tmxr_rmvrc (lp, j); /* remove char */ - break; } /* end case state */ - } /* end for char */ - } /* end else nbytes */ - } /* end for lines */ -for (i = 0; i < mp->lines; i++) { /* loop thru lines */ - lp = mp->ldsc[i]; /* get line desc */ - if (lp->rxbpi == lp->rxbpr) /* if buf empty, */ - lp->rxbpi = lp->rxbpr = 0; /* reset pointers */ - } /* end for */ -return; -} - -/* Return count of available characters for line */ - -int32 tmxr_rqln (TMLN *lp) -{ -return (lp->rxbpi - lp->rxbpr); -} - -/* Remove character p (and matching status) from line l input buffer */ - -void tmxr_rmvrc (TMLN *lp, int32 p) -{ -for ( ; p < lp->rxbpi; p++) { - lp->rxb[p] = lp->rxb[p + 1]; - lp->rbr[p] = lp->rbr[p + 1]; } -lp->rxbpi = lp->rxbpi - 1; -return; -} - -/* Store character in line buffer - - Inputs: - *lp = pointer to line descriptor - chr = characters - Outputs: - none -*/ - -void tmxr_putc_ln (TMLN *lp, int32 chr) -{ -if (lp->conn == 0) return; /* no conn? done */ -if (lp->txbpi < TMXR_MAXBUF) { /* room for char? */ - lp->txb[lp->txbpi] = (char) chr; /* buffer char */ - lp->txbpi = lp->txbpi + 1; /* adv pointer */ - if (((char) chr == TN_IAC) && /* IAC? */ - (lp->txbpi < TMXR_MAXBUF)) { /* room for char? */ - lp->txb[lp->txbpi] = (char) chr; /* IAC + IAC */ - lp->txbpi = lp->txbpi + 1; } /* adv pointer */ - if (lp->txbpi > (TMXR_MAXBUF - TMXR_GUARD)) /* near full? */ - lp->xmte = 0; } /* disable line */ -else lp->xmte = 0; /* disable line */ -return; -} - -/* Poll for output - - Inputs: - *mp = pointer to terminal multiplexor descriptor - Outputs: - none -*/ - -void tmxr_poll_tx (TMXR *mp) -{ -int32 i, nbytes, sbytes; -TMLN *lp; - -for (i = 0; i < mp->lines; i++) { /* loop thru lines */ - lp = mp->ldsc[i]; /* get line desc */ - if (lp->conn == 0) continue; /* skip if !conn */ - nbytes = lp->txbpi - lp->txbpr; /* avail bytes */ - if (nbytes) { /* >0? write */ - sbytes = sim_write_sock (lp->conn, - &(lp->txb[lp->txbpr]), nbytes); - if (sbytes != SOCKET_ERROR) { /* update ptrs */ - lp->txbpr = lp->txbpr + sbytes; - lp->txcnt = lp->txcnt + sbytes; - nbytes = nbytes - sbytes; } - } - if (nbytes == 0) { /* buf empty? */ - lp->xmte = 1; /* enable this line */ - lp->txbpr = lp->txbpi = 0; } - } /* end for */ -return; -} - -/* Return count of buffered characters for line */ - -int32 tmxr_tqln (TMLN *lp) -{ -return (lp->txbpi - lp->txbpr); -} - -/* Open master socket */ - -t_stat tmxr_open_master (TMXR *mp, char *cptr) -{ -int32 i, port; -SOCKET sock; -TMLN *lp; -t_stat r; - -port = (int32) get_uint (cptr, 10, 65535, &r); /* get port */ -if ((r != SCPE_OK) || (port == 0)) return SCPE_ARG; -sock = sim_master_sock (port); /* make master socket */ -if (sock == INVALID_SOCKET) return SCPE_OPENERR; /* open error */ -printf ("Listening on port %d (socket %d)\n", port, sock); -if (sim_log) fprintf (sim_log, - "Listening on port %d (socket %d)\n", port, sock); -mp->port = port; /* save port */ -mp->master = sock; /* save master socket */ -for (i = 0; i < mp->lines; i++) { /* initialize lines */ - lp = mp->ldsc[i]; - lp->conn = lp->tsta = 0; - lp->rxbpi = lp->rxbpr = 0; - lp->txbpi = lp->txbpr = 0; - lp->rxcnt = lp->txcnt = 0; - lp->xmte = 1; - lp->dstb = 0; } -return SCPE_OK; -} - -/* Attach unit to master socket */ - -t_stat tmxr_attach (TMXR *mp, UNIT *uptr, char *cptr) -{ -char* tptr; -t_stat r; - -if (uptr->flags & UNIT_ATT) { /* attached? */ - DEVICE *dptr = find_dev_from_unit (uptr); /* find device */ - if (dptr == NULL) return SCPE_IERR; - if (dptr->detach != NULL) r = dptr->detach (uptr); - else r = detach_unit (uptr); /* detach unit */ - if (r != SCPE_OK) return r; } -tptr = malloc (strlen (cptr) + 1); /* get string buf */ -if (tptr == NULL) return SCPE_MEM; /* no more mem? */ -r = tmxr_open_master (mp, cptr); /* open master socket */ -if (r != SCPE_OK) { /* error? */ - free (tptr); /* release buf */ - return SCPE_OPENERR; } -strcpy (tptr, cptr); /* copy port */ -uptr->filename = tptr; /* save */ -uptr->flags = uptr->flags | UNIT_ATT; /* no more errors */ -return SCPE_OK; -} - -/* Close master socket */ - -t_stat tmxr_close_master (TMXR *mp) -{ -int32 i; -TMLN *lp; - -for (i = 0; i < mp->lines; i++) { /* loop thru conn */ - lp = mp->ldsc[i]; - if (lp->conn) { - tmxr_msg (lp->conn, "\r\nDisconnected from the "); - tmxr_msg (lp->conn, sim_name); - tmxr_msg (lp->conn, " simulator\r\n\n"); - tmxr_reset_ln (lp); } /* end if conn */ - } /* end for */ -sim_close_sock (mp->master, 1); /* close master socket */ -mp->master = 0; -return SCPE_OK; -} - -/* Detach unit from master socket */ - -t_stat tmxr_detach (TMXR *mp, UNIT *uptr) -{ -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ -tmxr_close_master (mp); /* close master socket */ -free (uptr->filename); /* free port string */ -uptr->filename = NULL; -uptr->flags = uptr->flags & ~UNIT_ATT; /* not attached */ -return SCPE_OK; -} - -/* Stub examine and deposit */ - -t_stat tmxr_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -return SCPE_NOFNC; -} - -t_stat tmxr_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -return SCPE_NOFNC; -} - -/* Output message */ - -void tmxr_msg (SOCKET sock, char *msg) -{ -if (sock) sim_write_sock (sock, msg, strlen (msg)); -return; -} - -/* Print connections - used only in named SHOW command */ - -void tmxr_fconns (FILE *st, TMLN *lp, int32 ln) -{ -if (ln >= 0) fprintf (st, "line %d: ", ln); -if (lp->conn) { - int32 o1, o2, o3, o4, hr, mn, sc; - uint32 ctime; - - o1 = (lp->ipad >> 24) & 0xFF; - o2 = (lp->ipad >> 16) & 0xFF; - o3 = (lp->ipad >> 8) & 0xFF; - o4 = (lp->ipad) & 0xFF; - ctime = (sim_os_msec () - lp->cnms) / 1000; - hr = ctime / 3600; - mn = (ctime / 60) % 60; - sc = ctime % 60; - fprintf (st, "IP address %d.%d.%d.%d", o1, o2, o3, o4); - if (ctime) fprintf (st, ", connected %02d:%02d:%02d\n", hr, mn, sc); } -else fprintf (st, "line disconnected\n"); -return; -} - -/* Print statistics - used only in named SHOW command */ - -void tmxr_fstats (FILE *st, TMLN *lp, int32 ln) -{ -static const char *enab = "on"; -static const char *dsab = "off"; - -if (ln >= 0) fprintf (st, "line %d: ", ln); -if (lp->conn) { - fprintf (st, "input (%s) queued/total = %d/%d, ", - (lp->rcve? enab: dsab), - lp->rxbpi - lp->rxbpr, lp->rxcnt); - fprintf (st, "output (%s) queued/total = %d/%d\n", - (lp->xmte? enab: dsab), - lp->txbpi - lp->txbpr, lp->txcnt); } -else fprintf (st, "line disconnected\n"); -return; -} - -/* Disconnect line */ - -t_stat tmxr_dscln (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -TMXR *mp = (TMXR *) desc; -TMLN *lp; -int32 ln; -t_stat r; - -if ((mp == NULL) || (val && (cptr == NULL))) return SCPE_ARG; -if (cptr) { - ln = (int32) get_uint (cptr, 10, mp->lines - 1, &r); - if (r != SCPE_OK) return SCPE_ARG; } -else ln = 0; -lp = mp->ldsc[ln]; -if (lp->conn) { - tmxr_msg (lp->conn, "\r\nOperator disconnected line\r\n\n"); - tmxr_reset_ln (lp); } -return SCPE_OK; -} diff --git a/sim_tmxr.h b/sim_tmxr.h deleted file mode 100644 index 45ffa415..00000000 --- a/sim_tmxr.h +++ /dev/null @@ -1,95 +0,0 @@ -/* sim_tmxr.h: terminal multiplexor definitions - - Copyright (c) 2001-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - Based on the original DZ11 simulator by Thord Nilson, as updated by - Arthur Krewat. - - 22-Dec-02 RMS Added break support (from Mark Pizzolato) - 20-Aug-02 RMS Added tmxr_open_master, tmxr_close_master, tmxr.port - 30-Dec-01 RMS Renamed tmxr_fstatus, added tmxr_fstats - 20-Oct-01 RMS Removed tmxr_getchar, formalized buffer guard, - added tmxr_rqln, tmxr_tqln -*/ - -#ifndef _SIM_TMXR_H_ -#define _SIM_TMXR_H_ 0 - -#define TMXR_V_VALID 15 -#define TMXR_VALID (1 << TMXR_V_VALID) -#define TMXR_MAXBUF 128 /* buffer size */ -#define TMXR_GUARD 8 /* buffer guard */ -#define TMXR_MAXLIN 64 /* max lines */ - -struct tmln { - SOCKET conn; /* line conn */ - uint32 ipad; /* IP address */ - uint32 cnms; /* conn time */ - int32 tsta; /* Telnet state */ - int32 rcve; /* rcv enable */ - int32 xmte; /* xmt enable */ - int32 dstb; /* disable Tlnt bin */ - int32 rxbpr; /* rcv buf remove */ - int32 rxbpi; /* rcv buf insert */ - int32 rxcnt; /* rcv count */ - int32 txbpr; /* xmt buf remove */ - int32 txbpi; /* xmt buf insert */ - int32 txcnt; /* xmt count */ - char rxb[TMXR_MAXBUF]; /* rcv buffer */ - char rbr[TMXR_MAXBUF]; /* rcv break */ - char txb[TMXR_MAXBUF]; /* xmt buffer */ - }; - -typedef struct tmln TMLN; - -struct tmxr { - int32 lines; /* # lines */ - int32 port; /* listening port */ - SOCKET master; /* master socket */ - TMLN *ldsc[TMXR_MAXLIN]; /* line descriptors */ - }; - -typedef struct tmxr TMXR; - -int32 tmxr_poll_conn (TMXR *mp); -void tmxr_reset_ln (TMLN *lp); -int32 tmxr_getc_ln (TMLN *lp); -void tmxr_poll_rx (TMXR *mp); -void tmxr_putc_ln (TMLN *lp, int32 chr); -void tmxr_poll_tx (TMXR *mp); -t_stat tmxr_open_master (TMXR *mp, char *cptr); -t_stat tmxr_close_master (TMXR *mp); -t_stat tmxr_attach (TMXR *mp, UNIT *uptr, char *cptr); -t_stat tmxr_detach (TMXR *mp, UNIT *uptr); -t_stat tmxr_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat tmxr_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -void tmxr_msg (SOCKET sock, char *msg); -void tmxr_fconns (FILE *st, TMLN *lp, int32 ln); -void tmxr_fstats (FILE *st, TMLN *lp, int32 ln); -t_stat tmxr_dscln (UNIT *uptr, int32 val, char *cptr, void *desc); -int32 tmxr_rqln (TMLN *lp); -int32 tmxr_tqln (TMLN *lp); - -#endif - diff --git a/simh_doc.txt b/simh_doc.txt deleted file mode 100644 index 63c75a98..00000000 --- a/simh_doc.txt +++ /dev/null @@ -1,1267 +0,0 @@ -To: Users -From: Bob Supnik -Subj: Simulator Usage, V3.0-2 -Date: 15-Sep-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - Original code published in 1993-2003, written by Robert M Supnik - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - -This memorandum documents SIMH simulators. These simulators are freeware; -refer to the license terms above for conditions of use. Support is not -available. The best way to fix problems or add features is to read and -modify the sources yourself. Alternately, you can send Internet mail to -bsupnik@us.inter.net, but a response is not guaranteed. - -The simulators use a common command interface. This memorandum describes -the features of the command interface. The details of each simulator are -documented in separate, machine-specific memoranda. - - -1. Compiling And Running A Simulator - -The simulators have been tested on VAX VMS, Alpha VMS, Alpha UNIX, -NetBSD, FreeBSD, OpenBSD, Linux, Solaris, Windows 9x/Me/NT/2000, MacOS -9 and X, and OS/2. Porting to other environments will require changes -to the operating system dependent code in scp_tty.c, scp_sock.c, and -sim_ether.c. - -The simulator sources are provided in a zip archive and are organized -hierarchically. Source files for the simulator libraries are in the -top level directory; source files for each simulator are in individual -subdirectories. Note that the include files in the top level directory -are referenced from the subdirectories, without path identifiers. Your -build tool needs to search the top level directory for include files not -found in the simulator-specific directory, or you will have to copy all -files from the subdirectories into the master directory. File manifests -for each simulator are given in that simulator's documentation. - -The simulators recognize or require a few compile-time #defines: - -- The 18b simulators require that the model name be defined as part - of the compilation command line (i.e., PDP4 for the PDP-4, PDP7 - for the PDP-7, PDP9 for the PDP-9, PDP15 for the PDP-15). - -- The PDP-10 simulator uses 64b integer variables, requiring that - USE_INT64 be defined as part of the compilation command line. - Since 64b integer declarations vary, sim_defs.h has conditional - declarations for Windows (_int64) and Digital UNIX (long). The - default is GNU C (long long). If your compiler uses a different - convention, you will have to modify sim_defs.h. - -- The PDP-10, PDP-11, and VAX simulators share common peripherals. - To distinguish the target system, one of three variables must be - defined on the command line: VM_PDP10 for the PDP-10; VM_PDP11 - for the PDP-11; or VM_VAX for the VAX. - -- The PDP-11 and VAX simulators optionally support Ethernet. To - include Ethernet emulation, USE_NETWORK must be defined as part - of the compilation command line. At present, Ethernet support is - available only on Windows, Linux, NetBSD, and OpenBSD. - -- The PDP-11 and VAX simulators optionally support disks and serial - devices files greater than 2GB. To include large device support, - both USE_INT64 and USE_ADDR64 must be defined as part of the - compilation command line. - -To start the simulator, simply type its name. (On version of VMS -prior to 6.2, the simulators must then be defined as foreign commands -in order to be be started by name.) The simulator recognizes one -switch, -Q; if specified, certain informational messages are suppressed. - -The simulator interprets the arguments on the command line, if any, -as the file name and arguments for a DO command: - - % pdp10 { {arg,arg,...}}(cr) - -If no file is specified on the command line, the simulator looks for -an startup file consisting of the simulator name (including its path -components) plus the extension .ini. If a startup file is specified, -either on the command line or implicitly via the .ini capability, it -ishould contain a series of non-interactive simulator command, one -per line. These command can be used to set up standard parameters, -for example, disk sizes. - -After initializing its internal structures and processing the startup -file (if any), the simulator types out its name and version and then -prompts for input with: - - sim> - -1.1 Compiling Under UNIX/Linux - -The sources originate on a Windows system and have cr-lf at the end of -every line. For use on UNIX or Mac, the sources must be converted to -UNIX text conventions. This can be done with the UNIX UNZIP utility -(unzip -a). - -The supplied makefile will compile the simulators for UNIX systems -which support the POSIX TERMIOS. The VAX and PDP-11 can be compiled -with or without Ethernet support. To compile without Ethernet support: - - gmake {target|ALL|clean} - -To compile with Ethernet support: - - gmake USE_NETWORK=1 {target|ALL|clean} - -Notes for hand compilation: - -- The default UNIX terminal handling model is the POSIX TERMIOS - interface, which is supported by Linux, Mac OS/X, and Alpha UNIX. - If your UNIX only supports the BSD terminal interface, BSDTTY - must be defined as part of the compilation command line. - -- The PDP-8, PDP-11, 18b PDP, PDP-10, and Nova simulators use the - math library. If your UNIX does not link the math library - automatically, you must add -lm to the compilation command line. - -Examples: - -- PDP-11 under TERMIOS UNIX: - - % cc -DVM_PDP11 pdp11_*.c scp*.c sim_*.c -lm -o pdp11 - -- PDP-9 under TERMIOS UNIX: - - % cc -DPDP9 pdp18b_*.c scp*.c sim_*.c -lm -o pdp9 - -- PDP-10 under BSD terminal UNIX: - - % cc -DVM_PDP10 -DUSE_INT64 -DBSDTTY pdp10_*.c scp*.c sim_*.c -lm -o pdp10 - -1.2 Compiling Under Windows - -1.2.1 Compiling PDP-11 and VAX with Ethernet Support - -The Windows-specific Ethernet code uses the WinPCAP 3.0 package. -This package for windows simulates the libpcap package that is freely -available for Unix systems. - -WinPCAP must be installed prior to building the PDP-11 and VAX -simulators with Ethernet support. - -- Download V3.0 from http://winpcap.polito.it. -- Install the package as directed. -- Copy the required .h files (bittypes.h, devioctl.h, ip6_misc.h, - packet32.h, pcap.h, pcap-stdinc.h) from the WinPCAP 3.0 developer's - kit to the top level simulation directory. -- Get the required .lib files (packet.lib, wpcap.lib) from the WinPCAP - 3.0 developer's kit. If you're using Borland C++, use COFF2OMF to - convert the .lib files into a format that can be used by the compiler. - Then move the libraries to the standard library directory. -- Add -DUSE_NETWORK to the compilation command lines for the PDP-11 - and VAX. - -1.2.2 Compiling Under MinGW - -MinGW (Minimum GCC for Windows) is a free C compiler available from -http://www.mingw.org. The distribution includes a batch file -(build_mingw.bat) that will build all the simulators from source. -By default, the PDP-11 and VAX are built without Ethernet support. To -enable Ethernet support, install WinPCAP as described in the previous -section, and then use the alternative batch file (build_mingw_ether.bat). - -1.2.3 Compiling Under Visual C++ - -Each simulator must be organized as a separate Visual C++ project. -Starting from an empty console application, - -- Add all the files from the simulator file manifest to the project. -- Open the Project->Settings dialog box. -- On the C/C++ tab, Category: General, add any required preprocessor - definitions (for example, USE_INT64). -- On the C/C++ tab, Category: Preprocessor, add the top level - simulation directory to the Additional Include Directories. For - the VAX and PDP-10, you must also add the PDP-11 directory. -- On the Link tab, add wsock32.lib at the end of the list of - Object/Module Libraries. -- If you are building the PDP-11 and VAX with Ethernet support, you - must also add the WinPCAP libraries (packet.lib, wpcap.lib) to the - list of Object/Module libraries. - -If you are using Visual C++ .NET, you must turn off /Wp (warn about -potential 64b incompatibilities); otherwise, the compilations will -generate a lot of spurious conversion warnings. - -1.2.4 Compiling Under Borland C++ - -The Borland C++ compiler generates lots of spurious warnings about -missing function prototypes and conversions. All of these warnings -can be safely ignored. - -1.3 Compiling Under OpenVMS - -Compiling on OpenVMS requires DEC C. The simulators that require -64b (PDP-10 and VAX) will not compile on OpenVMS/VAX. The SIMH -distribution includes an MMS command file descrip.mms that will -build all the simulators from source. An example of hand compilation: - -- PDP-8 under VMS: - - $ cc scp*.c,sim_*.c,[.pdp8]pdp8*.c - $ link/exec=pdp8 scp*.obj,sim_*.obj,[.pdp8]pdp8*.obj - -1.4 Compiling Under MacOS - -The simulators have been tested on both MacOS 9 (with Codewarrior) -and MacOS/X (with Apple's tools). - -1.5 Compiling Under OS/2 - -Socket support requires the EMX compiler. - -2. Simulator Conventions - -A simulator consists of a series of devices, the first of which is -always the CPU. A device consists of named registers and one or more -numbered units. Registers correspond to device state, units to device -address spaces. Thus, the CPU device might have registers like PC, -ION, etc, and a unit corresponding to main memory; a disk device might -have registers like BUSY, DONE, etc, and units corresponding to individual -disk drives. Except for main memory, device address spaces are simulated -as unstructured binary disk files in the host file system. The SHOW -CONFIG command displays the simulator configuration. - -A simulator keeps time in terms of arbitrary units, usually one time unit -per instruction executed. Simulated events (such as completion of I/O) -are scheduled at some number of time units in the future. The simulator -executes synchronously, invoking event processors when simulated events -are scheduled to occur. Even asynchronous events, like keyboard input, -are handled by polling at synchronous intervals. The SHOW QUEUE command -displays the simulator event queue. - -3. Commands - -Simulator commands consist of a command verb, optional switches, and -optional arguments. Switches take the form: - - -{...} - -Multiple switches may be specified separately or together: -abcd or --a -b -c -d are treated identically. Verbs, switches, and other -input (except for file names) are case insensitive. - -Any command beginning with semicolon (;) is considered a comment and -ignored. - -3.1 Loading and Saving Programs - -The LOAD command (abbreviation LO) loads a file in binary paper-tape -loader format: - - sim> load {implementation options}(cr) - -The types of formats supported are implementation specific. Options -(such as load within range) are also implementation specific. - -The DUMP command (abbreviation DU) dumps memory in binary paper- -tape loader format: - - sim> dump {implementation options}(cr) - -The types of formats supported are implementation specific. Options -(such as dump within range) are also implementation specific. - -3.2 Saving and Restoring State - -The SAVE command (abbreviation SA) save the complete state of the -simulator to a file. This includes the contents of main memory and -all registers, and the I/O connections of devices: - - sim> save (cr) - -The RESTORE command (abbreviation REST, alternately GET) restores a -previously saved simulator state: - - sim> restore (cr) - -Note: SAVE file format compresses zeroes to minimize file size. - -3.3 Resetting Devices - -The RESET command (abbreviation RE) resets a device or the entire -simulator to a predefined condition: - - sim> RESET(cr) -- reset all devices - sim> RESET ALL(cr) -- reset all devices - sim> RESET (cr) -- reset specified device - -Typically, RESET stops any in-progress I/O operation, clears any -interrupt request, and returns the device to a quiescent state. It -does not clear main memory or affect I/O connections. - -3.4 Connecting and Disconnecting Devices - -Except for main memory, simulated unit address spaces are simulated -as unstructured binary disk files in the host file system. Before -using a simulated unit, the user must specify the file to be accessed -by that unit. The ATTACH (abbreviation AT) command associates a unit -and a file: - - sim> ATTACH (cr) - -If the file does not exist, and the -e switch was not specified, a -new file is created, and an appropriate message is printed. If the --e switch was specified, a new file is not created, and an error -message is printed. - -If the -r switch is specified, or the file is write protected, ATTACH -tries to open the file read only. If the file does not exist, or the -unit does not support read only operation, an error occurs. Input- -only devices, such as paper-tape readers, and devices with write lock -switches, such as disks and tapes, support read only operation; other -devices do not. If a file is ATTACHed read only, its contents can be -examined but not modified. - -For simulated magnetic tapes, the ATTACH command can specify the -format of the attached tape image file: - - sim> ATTACH -f (cr) - -The currently supported tape image file formats are: - - SIMH SIMH simulator format - E11 E11 simulator format - TPC TPC format - -The tape format can also be set with the SET command prior to ATTACH: - - sim> SET FORMAT=(cr) - sim> ATT (cr) - -The format of an attached file can be displayed with the SHOW command: - - sim> SHOW FORMAT(cr) - -For Telnet-based terminal emulators, the ATTACH command associates the -master unit with a TCP/IP port: - - sim> ATTACH (cr) - -The port is a decimal number between 1 and 65535 and should not used -by standard TCP/IP protocols. - -The DETACH (abbreviation DET) command breaks the association between -a unit and a file, or between a unit and a port: - - sim> DETACH ALL(cr) -- detach all units - sim> DETACH (cr) -- detach specified unit - -The EXIT command performs an automatic DETACH ALL. - -3.5 Examining and Changing State - -There are four commands to examine and change state: - - EXAMINE (abbreviated E) examines state - DEPOSIT (abbreviated D) changes state - IEXAMINE (interactive examine, abbreviated IE) examines state - and allows the user to interactively change it - IDEPOSIT (interactive deposit, abbreviated ID) allows the user - to interactively change state - -All four commands take the form - - command {modifiers} - -Deposit must also include a deposit value at the end of the command. - -There are four kinds of modifiers: switches, device/unit name, search -specifiers, and for EXAMINE, output file. Switches have been described -previously. A device/unit name identifies the device and unit whose -address space is to be examined or modified. If no device is specified, -the CPU (main memory)is selected; if a device but no unit is specified, -unit 0 of the device is selected. - -Search specifiers provide criteria for testing addresses or registers -to see if they should be processed. A specifier consists of a logical -operator, a relational operator, or both, optionally separated by spaces. - - { } - -where the logical operator is & (and), | (or), or ^ (xor), and the -relational operator is = or == (equal), ! or != (not equal), >= -(greater than or equal), > (greater than), <= (less than or equal), or -< (less than). If a logical operator is specified without a relational -operator, it is ignored. If a relational operator is specified without -a logical operator, no logical operation is performed. All comparisons -are unsigned. - -The output file modifier redirects command output to a file instead of -the console. An output file modifier consists of @ followed by a -valid file name. - -Modifiers may be specified in any order. If multiple modifiers of the -same time are specified, later modifiers override earlier modifiers. -Note that if the device/unit name comes after the search specifier, -the values will interpreted in the radix of the CPU, rather than of the -device/unit. - -The "state list" consists of one or more of the following, separated -by commas: - - register the specified register - register[sub1-sub2] the specified register array locations, - starting at location sub1 up to and - including location sub2 - register[sub1/length] the specified register array locations, - starting at location sub1 up to but - not including sub1+length - register[ALL] all locations in the specified register - array - register1-register2 all the registers starting at register1 - up to and including register2 - address the specified location - address1-address2 all locations starting at address1 up to - and including address2 - address/length all location starting at address up to - but not including address+length - STATE all registers in the device - ALL all locations in the unit - -Switches can be used to control the format of display information: - - -a display as ASCII - -c display as character string - -m display as instruction mnemonics - -o display as octal - -d display as decimal - -h display as hexidecimal - -The simulators typically accept symbolic input (see documentation with -each simulator). - -Examples: - - sim> ex 1000-1100 -- examine 1100:1100 - sim> de PC 1040 -- set PC to 1040 - sim> ie 40-50 -- interactively examine 40:50 - sim> ie >1000 40-50 -- interactively examine the subset - of locations 40:50 that are >1000 - sim> ex rx0 50060 -- examine 50060, RX unit 0 - sim> ex rx sbuf[3-6] -- examine SBUF[3] to SBUF[6] in RX - sim> de all 0 -- set main memory to 0 - sim> de &77>0 0 -- set all addresses whose low order - bits are non-zero to 0 - sim> ex -m @memdump.txt 0-7777 -- dump memory to file - -Note: to terminate an interactive command, simply type a bad value (eg, -XYZ) when input is requested. - -3.6 Running Programs - -The RUN command (abbreviated RU) resets all devices, deposits its argument -(if given) in the PC, and starts execution. If no argument is given, -execution starts at the current PC. - -The GO command does NOT reset devices, deposits its argument (if given) -in the PC, and starts execution. If no argument is given, execution -starts at the current PC. - -The CONT command (abbreviated CO) does NOT reset devices and resumes -execution at the current PC. - -The STEP command (abbreviated S) resumes execution at the current PC -for the number of instructions given by its argument. If no argument -is supplied, one instruction is executed. - -The BOOT command (abbreviated BO) bootstraps the device and unit given -by its argument. If no unit is supplied, unit 0 is bootstrapped. The -specified unit must be attached to a file. - -3.7 Stopping Programs - -Programs run until the simulator detects an error or stop condition, or -until the user forces a stop condition. - -3.7.1 Simulator Detected Stop Conditions - -These simulator-detected conditions stop simulation: - - - HALT instruction. If a HALT instruction is decoded, - simulation stops. - - - Breakpoint. The simulator may support breakpoints (see - below). - - - I/O error. If an I/O error occurs during simulation of an - I/O operation, and the device stop-on-I/O-error flag is set, - simulation usually stops. - - - Processor condition. Certain processor conditions can stop - simulation; these are described with the individual simulators. - -3.7.2 User Specified Stop Conditions - -Typing the interrupt character stops simulation. The interrupt character -is defined by the WRU (where are you) register and is initially set to -005 (^E). - -3.7.3 Breakpoints - -A simulator may offer breakpoint capability. A simulator may define -breakpoints of different types, identified by letter (for example, E -for execution, R for read, W for write, etc). At the moment, most -simulators support only E (execution) breakpoints. - -Associated with a breakpoint is a count and, optionally, one or more -actions. Each time the breakpoint is sprung, the associated count is -decremented. If the count is less than or equal to 0, the breakpoint -occurs; otherwise, it is deferred. When the breakpoint occurs, the -optional actions are automatically executed. - -A breakpoint is set by the BREAK command: - - sim> BREAK {-types} {[count]},{addr range...} - {;action;action...} - -If no type is specified, the simulator-specific default breakpoint -type (usually E for execution) is used. As with EXAMINE and DEPOSIT, -an address range may be a single address, a range of addresses low-high, -or a relative range of address/length. Examples of BREAK: - - sim> break -e 200 -- set E break at 200 - sim> break 2000/2[2] -- set E breaks at 2000,2001 - with count = 2 - sim> break 100;ex ac;d mq 0 -- set E break at 100 with - actions EX AC and D MQ 0 - sim> break 100; -- delete action on break at 100 - -Currently set breakpoints can be displayed with the SHOW BREAK command: - - sim> SHOW {-types} BREAK {ALL|{,...}} - -Locations with breakpoints of the specified type are displayed. - -Finally, breakpoints can be cleared by the NOBREAK command. - -3.8 Setting Device Parameters - -The SET command (abbreviated SE) changes the status of a device parameter: - - sim> SET {= SET {=} - -Most parameters are simulator and device specific. Disk drives, for -example, can usually be set WRITEENABLED or write LOCKED; if a device -supports multiple drive types, the SET command can be used to specify -the drive type. - -All devices recognize the following parameters: - - OCT sets the data radix = 8 - DEC sets the data radix = 10 - HEX sets the data radix = 16 - -3.9 Displaying Parameters and Status - -The SHOW CONFIGURATION command shows the simulator configuration and -the status of all simulated devices and units. - -The SHOW DEVICES command shows the configuration of all simulated -devices. - -The SHOW MODIFIERS command shows the modifiers available on all -simulated devices. - -The SHOW QUEUE command shows the state of the simulator event queue. -Times are in "simulation units", typically one unit per instruction -execution, relative to the current simulation time. - -The SHOW TIME command shows the number of time units elapsed since -the last RUN command. - -The SHOW command shows the status of the named simulated -device. SHOW shows the value of the named -parameter, if it can display a value. - -The SHOW command shows the status of the named simulated unit. -SHOW shows the value of the named parameter, if -it can display a value. - -3.10 Altering The Simulated Configuration - -In most simulators, the SET DISABLED command removes the -specified device from the configuration. A DISABLED device is -invisible to running programs. The device can still be RESET but -it cannot be ATTAChed, DETACHed, or BOOTed. SET ENABLED -restores a disabled device to a configuration. - -Most multi-unit devices allow units to be placed online or offline: - - sim> SET ONLINE - sim> SET OFFLINE - -When a unit is offline, it will not be displayed by SHOW DEVICE. - -The console terminal normally runs in the controlling window. -Optionally, the console terminal can be connected to a Telnet port. -This allows systems to emulate a VT100 using the built-in terminal -emulation of the Telnet client. - - sim> SET TELNET -- listen for console - Telnet connection on port - sim> SET NOTELNET -- disable console Telnet - sim> SHOW TELNET -- show console Telnet status - -The standard device names can be supplemented with logical names. -Logical names must be unique within a simulator (that is, they cannot -be the same as an existing device name). To assign a logical name -to a device: - - sim> ASSIGN device log-name -- assign log-name to device - -To remove a logical name: - - sim> DEASSIGN device -- remove logical name - -To show all logical names: - - sim> SHOW NAMES - -3.11 Logging Console Output - -Output to the console can be logged simultaneously to a file. Logging -is enabled by the LOG command: - - sim> SET LOG -- log console output to file - -Logging is disabled by the NOLOG command: - - sim> SET NOLOG -- disable logging - -SHOW LOG displays whether logging is enabled or disabled. - -3.12 Executing Command Files - -The simulator can execute command files with the DO command: - - sim> DO {arguments...} -- execute commands in file - -The DO command allows command files to contain substitutable arguments. -The string %n is recognized as meaning argument n from the DO command -line. The character \ has the usual UNIX meaning of an escape character; -the next character is interpreted literally, even if it is % or \. -Arguments with spaces can be enclosed in matching single or double -quotation marks. - -If the switch -V is specified, the commands in the file are echoed -before they are executed. - -3.13 Executing System Commands - -The simulator can execute operating system commands with the ! (spawn) -command: - - sim> ! - -If no operating system command is provided, the simulator attempts to -launch the host operating system's command shell. - -3.14 Getting Help - -The HELP command prints out information about a command or about all -commands: - - sim> HELP -- print all HELP messages - sim> HELP -- print HELP for command - -3.15 Exiting The Simulator - -EXIT (synonyms QUIT and BYE) returns control to the operating system. - -Appendix 1: File Representations - -All file representations are little endian. On big endian hosts, the -simulator automatically performs any required byte swapping. - -1. Hard Disks - -Hard disks are represented as unstructured binary files of 16b data -items for the 12b and 16b simulators, of 32b data items for the 18b, -24b, and 32b simulators, and 64b for the 36b simulators. - -2. Floppy Disks - -PDP-8 and PDP-11 floppy disks are represented as unstructured binary -files of 8b data items. They are nearly identical to the floppy disk -images for Doug Jones' PDP-8 simulator but lack the initial 256 byte -header. A utility for converting between the two formats is easily -written. - -3. Magnetic Tapes - -Magnetic tapes are represented as unstructured binary files of 8b data -items. Each record consists of a 32b record header, in little endian -format. If the record header is not a special header, it is followed -by n 8b bytes of data, followed by a repeat of the 32b record header. -A 1 in the high order bit of the record header indicates an error in -the record. If the byte count is odd, the record is padded to even -length; the pad byte is undefined. - -Special record headers occur only once and have no data. The currently -defined special headers are: - - 0x00000000 file mark (not repeated) - 0xFFFFFFFF end of medium (not repeated) - -Magnetic tapes are endian independent and consistent across simulator -families. A magtape produced by the Nova simulator will appear to -have its 16b words byte swapped if read by the PDP-11 simulator. - -SIMH can read and write E11-format magtape images. E11 format differs -from SIMH format only for odd-length records; the data portion of E11 -records is not padded with an extra byte. - -SIMH can read TPC-format magtape images. TPC format uses a 16b record -header, with 0x0000 denoting file mark. The record header is not -repeated at the end of the record. Odd-length records are padded with -an extra byte. - -4. Line Printers - -Line printer output is represented by an ASCII file of lines separated -by the newline character. Overprinting is represented by a line ending -in return rather than newline. - -5. DECtapes - -DECtapes are structured as fixed length blocks. PDP-1/4/7/9/15 DECtapes -use 578 blocks of 256 32b words. Each 32b word contains 18b (6 lines) -of data. PDP-11 DECtapes use 578 blocks of 256 16b words. Each 16b word -contains 6 lines of data, with 2b omitted. This is compatible with native -PDP-11 DECtape dump facilities, and with John Wilson's PUTR Program. PDP-8 -DECtapes use 1474 blocks of 129 16b words. Each 16b word contains 12b -(4 lines) of data. PDP-8 OS/8 does not use the 129th word of each block, -and OS/8 DECtape dumps contain only 128 words per block. A utility, -DTOS8CVT.C, is provided to convert OS/8 DECtape dumps to simulator format. - -A known problem in DECtape format is that when a block is recorded in -one direction and read in the other, the bits in a word are scrambled -(to the complement obverse). The PDP-11 deals with this problem by -performing an automatic complement obverse on reverse writes and reads. -The other systems leave this problem to software. - -The simulator represents this difference as follows. On the PDP-11, all -data is represented in normal form. Data reads and writes are not direction -sensitive; read all and write all are direction sensitive. Real DECtapes -that are read forward will generate images with the correct representation -of the data. - -On the other systems, forward write creates data in normal form, while -reverse write creates data in complement obverse form. Forward read (and -read all) performs no transformations, while reverse read (and read all) -changes data to the complement obverse. Real DECtapes that are read forward -will generate data in normal form for blocks written forward, and complement -obverse data for blocks written in reverse, corresponding to the simulator -format. - -Appendix 2: Debug Status - -The debug status of each simulated CPU and device is as follows: - - system PDP-8 PDP-11 Nova PDP-1 18b PDP -device -CPU y y y y y -FPU - y - - h -EIS/CIS - h - - - -console y y y y y -paper tape y y y h y -card reader - - - - - -line printer y y y h y -clock y y y - y -extra terminal y y y - y -hard disk y y y - y -fixed disk y - h - y -floppy disk y y y - - -drum - - - h h -DECtape y y - h y -mag tape y y y - h - - system 1401 2100 PDP-10 H316 VAX -device -CPU y y y h y -FPU - y y - y -EIS/CIS - y y - - -console h y y h y -paper tape - y h h y -card reader y - - - - -line printer y y y h y -clock - y y h y -extra terminal - y y - y -hard disk - y y - y -fixed disk - n - - - -floppy disk - - h - - -drum - n - - - -DECtape - - - - - -mag tape y y y - y - - system GRI-909 1620 i16 i32 SDS940 -device -CPU h h d y d -FPU - - d y - -CIS - - - - - -console h h d y h -paper tape h h d y h -card reader - h - - - -line printer - h d y h -clock h - d y n -extra terminal - - h y h -hard disk - h d y h -fixed disk - - - - h -floppy disk - - d d - -drum - - - - h -DECtape - - - - - -mag tape - - d y h - -legend: y = runs operating system or sample program - d = runs diagnostics - h = runs hand-generated test cases - n = untested - - = not applicable - -Revision History (covering Rev 2.0 to present) - -Starting with Rev 2.7, detailed revision histories can be found -in file sim_rev.c. - -Rev 3.0, May, 03 - Added logical name support - Added multiple tape format support - Added 64b address support - Added PDP-4 EAE support - Added PDP-15 FP15 and XVM support - -Rev 2.10, Nov, 02 - Added Telnet console capability, removed VT emulation - Added DO with substitutable arguments (from Brian Knittel) - Added .ini initialization file (from Hans Pufal) - Added quiet mode (from Brian Knittel) - Added ! command (from Mark Pizzolato) - Added Telnet BREAK support (from Mark Pizzolato) - Added device enable/disable support - Added optional simulator hooks for input, output, commands - Added breakpoint actions - Added magtape simulation library - Added PDP-11 KW11P programmable clock - Added PDP-11 RK611/RK06/RK07 disk - Added PDP-11/VAX TMSCP tape - Added PDP-11/VAX DELQA Ethernet support (from David Hittner) - Added PDP-11/PDP-10 RX211/RX02 floppy disk - Added PDP-11/VAX autoconfiguration support - Added PDP-10/PDP-11/VAX variable vector support - Added PDP-1 DECtape - Added PDP-1, PDP-4 Type 24 serial drum support - Added PDP-8 RX28 support - Added PDP-9 RB09 fixed head disk, LP09 line printer - Added HP2100 12845A line printer - Added HP2100 13183 magtape support - Added HP2100 boot ROM support - Added HP2100 interprocessor link support - Added IBM 1620 - Added SDS 940 - Added Interdata 16b and 32b systems - Added 16b DECtape file format support - Added support for statically buffered devices - Added magtape end of medium support - Added 50/60Hz support to line frequency clocks - Added 7B/8B support to terminals and multiplexors - Added BREAK support to terminals and multiplexors - -Rev 2.9, Jan, 02 - Added circular register arrays - Replaced ENABLE/DISABLE with SET ENABLED/DISABLED - Replaced LOG/NOLOG with SET LOG/NOLOG - Generalized the timer calibration package - Added additional routines to the multiplexor library - Added SET DISCONNECT, SHOW STATISTICS commands to multiplexors - Reimplemented PDP-8 TTX as a unified multiplexor - Implemented a PC queue in most simulators - Added VAX simulator - Added GRI-909 simulator - Added Peter Schorn's MITS 8080/Z80 simulator - Added Brian Knittel's IBM 1130 simulator - Added HP2100 DQ, DR, MS, MUX devices - Added SET VT/NOVT commands - -Rev 2.8, Dec, 01 - Added DO command - Added general breakpoint facility - Added extended SET/SHOW capability - Replaced ADD/REMOVE with SET ONLINE/OFFLINE - Added global register name recognition - Added unit-based register arrays - Added Charles Owen's System 3 simulator - Added PDP-11 I/O bus map - Added PDP-11/VAX RQDX3 - Added PDP-8 RL8A - Revised 18b PDP interrupt structure - Revised directory and documentation structure - Added support for MINGW environment - -Rev 2.7, Sep, 01 - Added DZ11 (from Thord Nilson and Art Krewat) to PDP-11, - PDP-10 - Added additional terminals to PDP-8 - Added TSS/8 packed character format to PDP-8 - Added sim_sock and sim_tmxr libraries - Added sim_qcount and simulator exit detach all facilities - Added Macintosh sim_sock support (from Peter Schorn) - Added simulator revision level, SHOW version - Changed int64/uint64 to t_int64/t_uint64 for Windoze - Fixed bug in PDP-11 interrupt acknowledge - Fixed bugs in PDP-11 TS NXM check, boot code, error status; - added extended characteristics and status - Fixed bug in PDP-11 TC stop, stop all functions - Fixed receive interrupt while disconnected bug in DZ11 - Fixed multi-unit operation bugs, interrupt bugs in PDP-11 - RP, PDP-10 RP, PDP-10 TU - Fixed carrier detect bug in PDP-11, PDP-10 DZ - Fixed bug in PDP-8 reset routine - Fixed conditional in PDP-18b CPU - Fixed SC = 0 bug in PDP-18b EAE - Fixed bug in PDP-7 LPT - Upgraded Nova second terminal to use sim_tmxr - Upgraded PDP-18b second terminal to use sim_tmxr - Upgraded PDP-11 LTC to full KW11-L - Removed hack multiple console support - -Rev 2.6b, Aug, 01 - Added H316/516 simulator - Added Macintosh support from Louis Chrétien, Peter Schorn, - and Ben Supnik - Added bad block table option to PDP-11 RL, RP - Removed register in declarations - Fixed bugs found by Peter Schorn - -- endian error in PDP-10, PDP-11 RP - -- space reverse error in PDP-11 TS - -- symbolic input in 1401 - Fixed bug in PDP-1 RIM loader found by Derek Peschel - Fixed bug in Nova fixed head disk - -Rev 2.6a, Jun, 01 - Added PDP-9, PDP-15 API option - Added PDP-9, PDP-15 second terminal - Added PDP-10 option for TOPS-20 V4.1 bug fix - Added PDP-10 FE CTRL-C option for Windoze - Added console logging - Added multiple console support - Added comment recognition - Increased size of string buffers for long path names - Fixed bug in big-endian I/O found by Dave Conroy - Fixed DECtape reset in PDP-8, PDP-11, PDP-9/15 - Fixed RIM loader PC handling in PDP-9/15 - Fixed indirect pointers in PDP-10 paging - Fixed SSC handling in PDP-10 TM02/TU45 - Fixed JMS to non-existent memory in PDP-8 - Fixed error handling on command file - -Rev 2.6, May, 01 - Added ENABLE/DISABLE devices - Added SHOW DEVICES - Added examination/modification of register arrays - Added PDP-10 simulator - Added clock autocalibration to SCP, Nova, PDP-8, PDP-11, - PDP-18b - Added PDP-8, PDP-11, PDP-9/15 DECtape - Added PDP-8 DF32 - Added 4k Disk Monitor boot to PDP-8 RF08 and DF32 - Added PDP-4/7 funny format loader support - Added extension handling to the PDP-8 and -9/15 loaders - Added PDP-11 TS11/TSV05 - Added integer interval timer to SCP - Added filename argument to LOAD/DUMP - Revised magtape and DECtape bootstraps to rewind before - first instruction - Fixed 3 cycle data break sequence in PDP-8 RF - Fixed 3 cycle data break sequence in 18b PDP LP, MT, RF - Fixed CS1.TRE write, CS2.MXF,UPE write, and CS2.UAI in - PDP-11 RP - Fixed 4M memory size definition in PDP-11 - Fixed attach bug in RESTORE - Fixed detach bug for buffered devices - Updated copyright notices, fixed comments - -Rev 2.5a, Dec, 00 - Added CMD flop to HP paper tape and line printer - Added status input for HP paper tape punch and TTY - Added Charles Owen's 1401 mag tape boot routine - Added Bruce Ray's Nova plotter and second terminal modules - Added Charles Owen's Eclipse CPU support - Added PDP-9/PDP-15 RIM/BIN loader support - Added PDP-9/PDP-15 extend/bank initial state registers - Added PDP-9/PDP-15 half/full duplex support - Moved software documentation to a separate file - Fixed SCP handling of devices without units - Fixed FLG, FBF initialization in many HP peripherals - Fixed 1401 bugs found by Charles Owen - -- 4, 7 char NOPs are legal - -- 1 char B is chained BCE - -- MCE moves whole character, not digit, after first - Fixed Nova bugs found by Bruce Ray - -- traps implemented on Nova 3 as well as Nova 4 - -- DIV and DIVS 0/0 set carry - -- RETN sets SP from FP at outset - -- IORST does not clear carry - -- Nova 4 implements two undocumented instructions - Fixed bugs in 18b PDP's - -- XCT indirect address calculation - -- missing index instructions in PDP-15 - -- bank mode handling in PDP-15 - -Rev 2.5, Nov, 00 - Removed Digital and Compaq from copyrights, as authorized - by Compaq Sr VP Bill Strecker - Revised save/restore format for 64b simulators - Added examine to file - Added unsigned integer data types to sim_defs - Added Nova 3 and Nova 4 instructions to Nova CPU - Added HP2100 - Fixed indirect loop through autoinc/dec in Nova CPU - Fixed MDV enabled test in Nova CPU - -Rev 2.4, Jan, 99 - Placed all sources under X11-like open source license - Added DUMP command, revised sim_load interface - Added SHOW MODIFIERS command - Revised magtape format to include record error flag - Fixed 64b problems in SCP - Fixed big endian problem in PDP-11 bad block routine - Fixed interrupt on error bug in PDP-11 RP/RM disks - Fixed ROL/ROR inversion in PDP-11 symbolic routines - -Rev 2.3d, Sep, 98 - Added BeOS support - Added radix commands and switches - Added PDP-11 CIS support - Added RT11 V5.3 to distribution kits - Fixed "shift 32" bugs in SCP, PDP-11 floating point - Fixed bug in PDP-11 paper tape reader - Fixed bug in ^D handling - -Rev 2.3c, May, 98 - Fixed bug in PDP-11 DIV overflow check - Fixed bugs in PDP-11 magtape bootstrap - Fixed bug in PDP-11 magtape unit select - Replaced UNIX V7 disk images - -Rev 2.3b, May, 98 - Added switch recognition to all simulator commands - Added RIM loader to PDP-8 paper tape reader and loader - Added second block bootstrap to PDP-11 magtape - Fixed bug in PDP-8 RF bootstrap - Fixed bug in PDP-11 symbolic display - Fixed bugs in PDP-11 floating point (LDEXP, STEXP, - MODf, STCfi, overflow handling) - -Rev 2.3a, Nov, 97 - Added search capability - Added bad block table command to PDP-11 disks - Added bootstrap to PDP-11 magtape - Added additional Nova moving head disks - Added RT-11 sample software - Fixed bugs in PDP-11 RM/RP disks - Fixed bugs in Nova moving head disks - Fixed endian dependence in 18b PDP RIM loader - -Rev 2.3, Mar, 97 - Added PDP-11 RP - Added PDP-1 - Changed UNIX terminal I/O to TERMIOS - Changed magtape format to double ended - Changed PDP-8 current page mnemonic from T to C - Added endian independent I/O routines - Added precise integer data types - Fixed bug in sim_poll_kbd - Fixed bug in PDP-8 binary loader - Fixed bugs in TM11 magtape - Fixed bug in RX11 bootstrap - Fixed bug in 18b PDP ADD - Fixed bug in 18b PDP paper tape reader - Fixed bug in PDP-4 console - Fixed bug in PDP-4,7 line printer - -Rev 2.2d, Dec, 96 - Added ADD/REMOVE commands - Added unit enable/disable support to device simulators - Added features for IBM 1401 project - Added switch recognition for symbolic input - Fixed bug in variable length IEXAMINE - Fixed LCD bug in RX8E - Initial changes for Win32 - Added IBM 1401 - -Rev 2.2b, Apr, 96 - Added PDP-11 dynamic memory size support - -Rev 2.2a, Feb, 96 - New endian independent magtape format - -Rev 2.2 Jan, 96 - Added register buffers for save/restore - Added 18b PDP's - Guaranteed TTI, CLK times are non-zero - Fixed breakpoint/RUN interaction bug - Fixed magnetic tape backspace to EOF bug - Fixed ISZ/DCA inversion in PDP-8 symbol table - Fixed sixbit conversion in PDP-8 examine/deposit - Fixed origin increment bug in PDP-11 binary loader - Fixed GCC longjmp optimization bug in PDP-11 CPU - Fixed unit number calculation bug in SCP and in Nova, - Nova, PDP-11, 18b PDP moving head disks - -Rev 2.1 Dec, 95 - Fixed PTR bug (setting done on EOF) in PDP-8, Nova - Fixed RX bug (setting error on INIT if drive 1 is - not attached) in PDP-8, PDP-11 - Fixed RF treatment of photocell flag in PDP-8 - Fixed autosize bug (always chose smallest disk if new - file) in PDP-11, Nova - Fixed not attached bug (reported as not attachable) in - most mass storage devices - Fixed Nova boot ROMs - Fixed bug in RESTORE (didn't requeue if delay = 0) - Fixed bug in RESTORE (clobbered device position) - Declared static constant arrays as static const - Added PDP-8, Nova magnetic tape simulators - Added Dasher mode to Nova terminal simulator - Added LINUX support - -Rev 2.0 May, 95 - Added symbolic assembly/disassembly - -Acknowledgements - -SIMH would not have been possible without help from around the world. I -would like to acknowledge the help of the following people, all of whom -donated their time and talent to this "computer archaeology" project: - -Bill Ackerman PDP-1 consulting -Alan Bawden ITS consulting -Winfried Bergmann Linux port testing -Phil Budne Solaris port testing -Max Burnet PDP information, documentation, and software -Robert Alan Byer VMS socket support and testing -James Carpenter LINUX port testing -Chip Charlot PDP-11 RT-11, RSTS/E, RSX-11M legal permissions -Louis Chrétien Macintosh porting -Dave Conroy HP 21xx documentation, PDP-10, PDP-18b debugging -L Peter Deutsch PDP-1 LISP software -Ethan Dicks PDP-11 2.9 BSD debugging -John Dundas PDP-11 CPU debugging, programmable clock simulator -Jonathan Engdahl PDP-11 device debugging -Carl Friend Nova and Interdata documentation, and RDOS software -Megan Gentry PDP-11 integer debugging -Dave Gesswein PDP-8 and PDP-9.15 documentation, PDP-8 DECtape, disk, - and paper tape images, PDP-9/15 DECtape images -Dick Greeley PDP-8 OS/8 and PDP-10 TOPS-10/20 legal permissions -Gordon Greene PDP-1 LISP machine readable source -Lynne Grettum PDP-11 RT-11, RSTS/E, RSX-11M legal permissions -Franc Grootjen PDP-11 2.11 BSD debugging -Doug Gwyn Portability debugging -Kevin Handy TS11/TSV05 documentation, make file -Ken Harrenstein KLH PDP-10 simulator -Bill Haygood PDP-8 information, simulator, and software -Wolfgang Helbig DZ11 implementation -Mark Hittinger PDP-10 debugging -Dave Hittner SCP debugging, DEQNA emulator and Ethernet library -Sellam Ismail GRI-909 documentation -Jay Jaeger IBM 1401 consulting -Doug Jones PDP-8 information, simulator, and software -Brian Knittel IBM 1130 simulator, SCP extensions for GUI support -Al Kossow HP 21xx, Varian 620, TI 990, Interdata, DEC - documentation and software -Arthur Krewat DZ11 changes for the PDP-10 -Mirian Crzig Lennox ITS and DZ11 debugging -Don Lewine Nova documentation and legal permissions -Tim Litt PDP-10 hardware documentation and schematics, - tape images, and software sources -Tim Markson DZ11 debugging -Bill McDermith HP 2100 debugging, 12565A simulator -Scott McGregor PDP-11 UNIX legal permissions -Jeff Moffatt HP 2100 information, documentation, and software -Alec Muffett Solaris port testing -Terry Newton HP 21MX debugging -Thord Nilson DZ11 implementation -Charles Owen Nova moving head disk debugging, Altair simulator, - Eclipse simulator, IBM System 3 simulator, - IBM 1401 diagnostics, debugging, and magtape boot -Sergio Pedraja MINGW environment debugging -Derek Peschel PDP-10 debugging -Paul Pierce IBM 1401 diagnostics, media recovery -Mark Pizzolato SCP, Ethernet, and VAX simulator improvements -Hans Pufal PDP-10 debugging, PDP-15 bootstrap, DOS-15 recovery, - DOS-15 documentation, PDP-9 restoration -Bruce Ray Software, documentation, bug fixes, and new devices - for the Nova, OS/2 porting -Craig St Clair DEC documentation -Richard Schedler Public repository maintenance -Peter Schorn Macintosh porting -Stephen Schultz PDP-11 2.11 BSD debugging -Olaf Seibert NetBSD port testing -Brian & Barry Silverman PDP-1 simulator and software -Tim Shoppa Nova documentation, RDOS software, PDP-10 and PDP-11 - software archive, hosting for SIMH site -Van Snyder IBM 1401 zero footprint bootstraps -Michael Somos PDP-1 debugging -Hans-Michael Stahl OS/2 port testing, TERMIOS implementation -Tim Stark TS10 PDP-10 simulator -Larry Stewart Initial suggestion for the project -Bill Strecker Permission to revert copyrights -Chris Suddick PDP-11 floating point debugging -Ben Supnik Macintosh timing routine -Bob Supnik SIMH simulators -Ben Thomas VMS character-by-character I/O routines -Warren Toomey PDP-11 UNIX software -Deb Toivonen DEC documentation -Mike Umbricht DEC documentation, H316 documentation and schematics -Leendert Van Doorn PDP-11 UNIX V6 debugging, TERMIOS implementation -Fred Van Kempen Ethernet code, RK611 emulator, PDP-11 debugging, - VAX/Ultrix debugging -Holger Veit OS/2 socket support -David Waks PDP-8 ESI-X and PDP-7 SIM8 software -Tom West Nova documentation -Adrian Wise H316 simulator, documentation, and software -John Wilson PDP-11 simulator and software -Joe Young RP debugging on Ultrix-11 and BSD - -In addition, the following companies have graciously licensed their -software at no cost for hobbyist use: - -Data General Corporation -Digital Equipment Corporation -Compaq Computer Corporation -Mentec Corporation -The Santa Cruz Operation -Caldera Corporation -Hewlett-Packard Corporation - - diff --git a/simh_faq.txt b/simh_faq.txt deleted file mode 100644 index b101617c..00000000 --- a/simh_faq.txt +++ /dev/null @@ -1,606 +0,0 @@ -SIMH FAQ, 15-Sep-2003 - -1 General - -1.1 What is SIMH? -1.2 Why was SIMH written? -1.3 What is the history of SIMH? -1.4 Who writes and maintains SIMH? -1.5 How is SIMH licensed? -1.6 How is SIMH distributed? -1.7 Which computer systems can SIMH simulate? -1.8 Which host systems does SIMH run on? -1.9 What software packages are available for use with the SIMH simulators? -1.10 Where can I get more information about SIMH? - --------------------------------------------------------------------------------- - -2 Operational - -2.1 How do I install SIMH on Windows? -2.2 How do I install SIMH with Ethernet support on Windows? -2.3 How do I install SIMH on Unix? -2.4 How do I install SIMH on VMS? -2.5 How do I transcribe a real CD for use with SIMH? -2.6 How do I transcribe other archival media for use with SIMH? -2.7 How can I get text files in and out of SIMH? -2.8 How can I get binary files in and out of SIMH? -2.9 Can I connect real devices on the host computer to SIMH? -2.10 My Windows host can't communicate with the PDP-11 or VAX over Ethernet; why? - --------------------------------------------------------------------------------- - -3 Writing and Debugging New Code - -3.1 What resources are available for writing new simulators? -3.2 What debugging facilities are available in SIMH? -3.3 When do I need to use the host debugger for debugging a simulator? -3.4 What is the release process for SIMH? - --------------------------------------------------------------------------------- - -4 VAX - -4.1 Where can I get software and hobbyist licenses for the VAX? -4.2 How do I install VMS? -4.3 How do I install NetBSD? -4.4 How do I install Ultrix? -4.5 What's the CPU serial number for my hobbyist license PAK? -4.6 How do I change the simulator from a VAXserver 3900 to a - MicroVAX 3900? -4.7 Is there an example of the simulator running VMS? -4.8 How can I import files into a simulated VMS environment? -4.9 How can I export files from a simulated VMS environment? - --------------------------------------------------------------------------------- - -5 PDP-11 - -5.1 When installing RSTS/E from simulated magtape, the installation process - hangs with no error message; why? - -================================================================================ -1. General Questions -================================================================================ - -1.1 What is SIMH? - -SIMH is the Computer History Simulation system. It consists of simulators -for approximately 20 different computers, all written around a common user -interface package and set of supporting libraries. SIMH can be used to -simulate any computer system for which sufficient detail is available, but -the focus to date has been on simulating computer systems of historic interest. - --------------------------------------------------------------------------------- - -1.2 Why was SIMH written? - -Significant portions of the computing past are being irretrievably lost, as -old systems are scrapped, documentation and software is thrown out, media -become obsolete or unreadable, and inventors and pioneers die. SIMH was -written as a vehicle to allow the computing past to be made accessible to -a wider audience, for recreational and educational purposes. SIMH preserves -historic computers as portable software, that can be run on any modern -system. SIMH also preserves representative software packages for these -systems. With SIMH, anyone with a desktop computer can call up and run -significant samples from the computing past, at any time. - --------------------------------------------------------------------------------- - -1.3 What is the history of SIMH? - -The SIMH project started in 1993, at the suggestion of Larry Stewart of DEC. -Its immediate purpose was to preserve the fading hardware and software -record of early minicomputers. Since then, the project has been expanded -to include other important systems, spanning the history of computing from -the late 50's to the late 80's. - -SIMH's core design is based on an earlier simulation system called MIMIC. -MIMIC was written in the late 1960's at Applied Data Research, by Mike -McCarthy, Len Feshkens, and Bob Supnik. MIMIC was a mini-computer simulator -that ran on the PDP-10. Its purpose was to facilitate the development and -debugging of real-time embedded systems by using the the PDP-10 timesharing -environment for program development, instead of the limited facilities of -the native minicomputer environments. Ironically, given SIMH's mission to -preserve the computing record, all machine-readable copies of MIMIC have -been lost. - --------------------------------------------------------------------------------- - -1.4 Who writes and maintains SIMH? - -Many people have contributed, and continue to contribute, to SIMH. The full -list of contributors can be found on the SIMH web site. Bob Supnik coordinates -SIMH development. - --------------------------------------------------------------------------------- - -1.5 How is SIMH licensed? - -SIMH is licensed under a modified X-Windows license. This license allows more -or less unrestricted use of the sources and binaries. The license is included -with the documentation and is also included in every source module. The -software packages are available under various terms and conditions; see the -documentation included with each software package. - --------------------------------------------------------------------------------- - -1.6 How is SIMH distributed? - -SIMH is distributed in source form from the SIMH web site, in the form of a -Zip archive. For Windows users, pre-compiled binaries are also available. - --------------------------------------------------------------------------------- - -1.7 Which computer systems does SIMH simulate? - -SIMH simulates the following computer systems: - - Manufacturer Model - - Digital Equipment Corporation PDP-1, PDP-4, PDP-7, PDP-8, PDP-9, - PDP-10, PDP-11, PDP-15, VAX - Data General Corporation Nova, Eclipse - IBM Corporation 1130, 1401, 1620, System 3 - GRI Corporation GRI-909 - Honeywell Corporation H316/516 - Hewlett Packard Corporation HP2116, HP2100, HP21MX - Interdata Corporation 16b systems, 7/32, 8/32 - Scientific Data Systems SDS-940 - MITS Altair 8080, Altair Z80 - -The documentation contains more details on supported models and peripherals. - --------------------------------------------------------------------------------- - -1.8 Which host systems does SIMH run on? - - Host System Compiler comments - - OpenVMS/VAX DEC C no 64b support; no Ethernet support - OpenVMS/Alpha DEC C no Ethernet support - - Windows 9x or Mingw/gcc or requires WinPcap for Ethernet support - Windows 2000 or Visual C++ or - Windows XP Borland C++ - - Mac OS/X no Ethernet support - - Linux gcc - Tru64 UNIX DEC C no Ethernet support - AIX no Ethernet support - Solaris no Ethernet support - HP/UX no Ethernet support - NetBSD gcc - OpenBSD gcc - FreeBSD gcc no Ethernet support - - OS/2 EMX no Ethernet support - --------------------------------------------------------------------------------- - -1.9 What software packages are available to run on SIMH? - -The list of available software packages can be found on the SIMH web site. - --------------------------------------------------------------------------------- - -1.10 Where can I get more information on SIMH? - -The SIMH web site is http://simh.trailing-edge.com. - -================================================================================ -2 Operational Questions -================================================================================ - -2.1 How do I install SIMH on Windows? - -The simplest way is to download the pre-compiled binaries. Unzip these into the -directory where you want to run SIMH. You can then run whichever binary that you -want. - -If you want to run the VAX emulator, you will also need the KA655.bin file from -the source kit. - --------------------------------------------------------------------------------- - -2.2 How do I install SIMH with Ethernet support on Windows? - -Separate pre-compiled binaries contain Ethernet support. Before running these -binaries, you must download download and install the WinPCAP AutoInstaller from - - http://winpcap.polito.it - -This creates a network packet driver in Windows for SIMH to attach to. - -To use network support, you must either be an administrator on the Windows -machine (implied in Windows 9X), or you must set the windows packet driver to -autostart when the system boots; see the WinPCAP FAQ page for detailed -information on how to do this. - --------------------------------------------------------------------------------- - -2.3 How do I install SIMH on Unix? - -- Unzip the archive of sources to a new directory. You must specify the - -a switch to unzip for proper conversion of Windows cr-lf sequences - to UNIX newline sequences. - -- If your system supports gmake, you can compile the simulators with - the command: - - % gmake all - -- If you want Ethernet support in the PDP-11 and VAX, you should compile - the simulators with the command: - - % gmake USE_NETWORK=1 all - - Note that Ethernet support is available ONLY on Linux, NetBSD, and - OpenBSD. - --------------------------------------------------------------------------------- - -2.4 How do I install SIMH on VMS? - -Download the SIMH source kit, and UNZIP it using the /TEXT=AUTO qualifier to -the directory that you want SIMH to reside in. Use MMK or MMS and the -descrip.mms file to build the binaries. - -UNZIP can be found on the VMS freeware CDs, or from www.info-zip.org -MMK can be found on the VMS freeware CDs, or from www.madgoat.com -MMS can be licensed from HP/Compaq/Digital. - -Note that the PDP-10 emulator cannot be built and used on VAX/VMS, because -the DEC C compiler for VAX/VMS does not support 64-bit integers. DEC C on -on Alpha VMS has the required 64-bit capability to build and run all of the -emulators. - --------------------------------------------------------------------------------- - -2.5 How do I transcribe a real CD for use with SIMH? - -- On UNIX, you can copy a CD to an ISO file with the dd command: - - % dd /if=/dev/raw_cd_device /out=/path/cdimage.iso - - Linux, and many Unix variants, support direct access to the CD ROM - from SIMH: - - sim> set rq1 cdrom - sim> att rq1 /dev/cdrom_drive - -- On Windows, there are quite a few products that can do this. The two most - common products are detailed below. Make sure to disable any antivirus - software before proceeding. Antivirus software tends to interfere with - the smooth flow of data from the CD and will occasionally transform the - data in strange and unexpected ways to 'protect' you. - - 1) Roxio EZ-CD Creator 5.x - Go to the the Disc menu and select Disc Info (there will be a delay). - Select the track shown, then click the Read Track button. - Enter the Save file name, then OK. - - 2) Nero 5.5 - Select Recorder|Save Track - Select the track, set the output filename - In Options, you may need to set the Read Speed down; - the VMS Hobbyist CD didn't work after a 52x read, but worked fine at 8x - Click GO - --------------------------------------------------------------------------------- - -2.6 How do I transcribe other archival media for use with SIMH? - -You must have access to a real system that can read the media to be -transcribed (e.g., a system with a working DECtape drive to read a -DECtape). Most systems have utilities to copy raw data to a disk -file; that file can then be transferred over the console serial -line to a system with an Internet link. Utility programs are -available to convert raw data streams to SIMH format. - --------------------------------------------------------------------------------- - -2.7 How can I get text files in and out of SIMH? - -Since SIMH supports the universal serial interface using TELNET, text can -be transferred using one of the serial line transfer protocols (X/Y/Zmodem, -Kermit) or using standard cut and paste techniques, if the host's TELNET -program supports it. - -To use the TELNET feature, connect to the SIMH machine using TELNET, and -set the target environment into a 'receive' mode. This is usually something -like running a text editor. Then tell the TELNET program to 'send', 'transfer', -or 'paste' the text that you want sent into the SIMH system. - -To get text out of the system, have the TELNET program either log the output, -or if the TELNET program supports a backscroll region you can use that. Tell -the SIMH system to 'type' or 'cat' the text file, sending the output to the -TELNET device, where you can edit it into a text file. - -Many TELNET programs also support transferring large files via X/Y/ZModem or -Kermit, which you can use as long as the SIMH system has the appropriate -matching program. - -C-Kermit from Columbia University (http://www.columbia.edu/kermit) is probably -the most universal way to transfer files in and out of SIMH systems. - -If the SIMH system supports Ethernet connectivity (PDP-11, VAX), you can also -use the various network copy programs (FTP, DECNET) to transfer files. - -Finally, you can "print" text files to the simulated line printer. Printer -output is automatically formatted as an ASCII text file. - --------------------------------------------------------------------------------- - -2.8 How can I get binary files in and out of SIMH? - -Since SIMH supports the universal serial interface using TELNET, binary -files can be transferred using one of the serial line transfer protocols -(X/Y/ZModem, Kermit) or by converting the binary to a text-encoded file -(HEXify, UUENCODE, VMShare, etc.) and transferred in text mode (see section -2.7). - -Many TELNET programs also support transferring large files via X/Y/ZModem or -Kermit, which you can use as long as the SIMH system has the appropriate -matching program. - -C-Kermit from Columbia University (http://www.columbia.edu/kermit) is probably -the most universal way to transfer files in and out of SIMH systems. - -If the SIMH system supports Ethernet connectivity (PDP-11, VAX), you can also -use the various network copy programs (FTP, DECNET) to transfer files. - --------------------------------------------------------------------------------- - -2.9 Can I connect real devices on the host computer to SIMH? - -No. - --------------------------------------------------------------------------------- - -2.10 My Windows host can't communicate with the PDP-11 or VAX over Ethernet; why? - -Due to the inherent limitations of WinPCAP, the SIMH system _CANNOT_ communicate -with the host on the primary interface. To establish communications between SIMH -and a PC host, add a second Ethernet controller, attach both controllers to the -same hub, and attach SIMH to the second controller. The host and SIMH will now -be able to communicate across the physical network connection. - -================================================================================ -3 Writing and Debugging New Code -================================================================================ - -3.1 What resources are available for writing new simulators? - -The SIMH web site contains documentation on the internals of SIMH, as well -as specific help for writing new peripherals for several of the popular -simulators. - --------------------------------------------------------------------------------- - -3.2 What debugging facilities are available in SIMH? - -Most simulators provide the following debugging capabilities: - -- Symbolic assembly and disassembly of memory contents. -- Numeric examination and modification of the data store of any simulated - device. -- Numeric search on both memory and device data. -- Visibility to simulator internal structures, such as the event queue. -- An unlimited number of instruction breakpoints. -- Proceed counts on breakpoints. -- Automatic execution of simulator commands on a breakpoint. -- Stepped execution (from single step to 'n' steps). -- A PC change queue, usually 64 instructions deep. - -Specific simulators may provide additional features, such as an instruction -history buffer, CPU and/or device logging, and breakpoints on memory reads -and writes. - --------------------------------------------------------------------------------- - -3.3 When do I need to use the host debugger for debugging a simulator? - -While a simulator is being debugged, its execution of instructions -or debugging support code may be unreliable. During this process, -the programmer may need to use the host debugger to stop in the -middle of an instruction execution, or to trap an error condition. -Host debugger breakpoints should be invisible to the simulator; with -the exception of clock calibration, all simulator events are driven -off the event queue rather than real-world events. - -If the programmer needs to force a simulator stop from the host -debugger, most simulators provide an "address stop" global variable. -Setting this variable to 1 will cause the simulator to stop after -completing the current instruction. - --------------------------------------------------------------------------------- - -3.4 What is the release process for SIMH? - -SIMH is released whenever a significant number of new features, or -important bug fixes, has accumulated. This has averaged every 4-8 -weeks. The major version number has not been changed since the -addition of symbolic debugging and won't be changed unless the -internals of SCP change dramatically. The minor version number -is changed when the format of the save/restore file must be updated. - -================================================================================ -4 VAX -================================================================================ - -4.1 Where can I get software and hobbyist licenses for the VAX? - -HP (formerly Compaq formerly DEC) provides licenses to OpenVMS for -hobbyist use. A description of the hobbyist license program can be -found on http://www.montagar.com/hobbyist/. - --------------------------------------------------------------------------------- - -4.2 How do I install VMS? - -To install VMS, you will need a distribution CD ROM. Any version -after VMS 5.5-2 should run on the simulator. - -- Transcribe the distribution CD ROM to an ISO-format CD image file. - (See question 2.5 for information on how to do this.) -- Set drive RQ1 to be a CD ROM. -- Attach the CD ROM image file to simulated drive RQ1. -- Set drive RQ0 to be the type of disk you want. Be sure that the - disk is large enough to hold VMS. -- Attach a blank disk image file to simulated drive RQ0. -- Boot the CPU. -- When the self-test code completes, boot the CD ROM. -- Use standalone backup to restore the CD ROM contents to the simulated - disk. - - sim> set rq0 rd54 - sim> set rq1 cdrom - sim> att rq0 new_vms.dsk - sim> att rq1 cd_rom_image.iso - sim> boot cpu - : - >>> boot rq1 - - $ (prompt from standalone backup) - -A writeup on the procedure can be found on the VMS hobbyist site. - --------------------------------------------------------------------------------- - -4.3 How do I install NetBSD? - -Directions for installing NetBSD on the NetBSD web site, at -http://www.netbsd.org/Ports/vax/emulator-howto.html. - --------------------------------------------------------------------------------- - -4.4 How do I install Ultrix? - -Ultrix is not presently licensed for hobbyist use. If you have a -valid license for Ultrix, and distribution tapes for a version that -supports the MicroVAX 3900 series (V4 or later), then you should -be able to install Ultrix on the simulator. - -- Transcribe the distribution tapes to SIMH-format tape image files. - (See question 2.6 for information on how to do this.) -- Mount the installation tape image on simulated drive TQ0. -- Set drive RQ0 to be the type of disk you want. Be sure that the - disk is large enough to hold Ultrix. -- Mount a blank disk image file on simulated drive RQ0. -- Boot the CPU. -- When the self-test code completes, boot the installation tape. -- The installation tape will guide you through the installation of - Ultrix. - - sim> set rq0 rd54 - sim> att rq0 new_vms.dsk - sim> att tq0 ultrix_install.tap - sim> boot cpu - : - >>> boot mua0 - - (Ultrix installation dialog) - ---------------------------------------------------------------------------------- - -4.5 What's the CPU serial number for my hobbyist license PAK? - -On a MicroVAX 3900, the CPU serial number is not readable and can -be an arbitrary value. 12345 will work fine. - ---------------------------------------------------------------------------------- - -4.6 How do I change the simulator from a VAXserver 3900 to a MicroVAX 3900? - -The system type is controlled by a "magic byte" in the CPU's boot ROM. -By default, the system type is a VAXserver 3900. To change the type -to a MicroVAX 3900, patch the boot ROM as follows: - - sim> set ptr ena - sim> att ptr ka655.bin - sim> ie ptr 4 - 4: 2 1 - sim> det ptr - -and reboot the simulated VAX. - ---------------------------------------------------------------------------------- - -4.7 Is there an example of the simulator running VMS? - -This example assumes you are trying to emulate a MicroVAX 3900 with 64MB of -memory, with a single 1GB disk drive, a CDROM, and an Ethernet controller. - -The host OS is Windows NT/2000/XP, and you have previously dumped the contents -of the VMS Hobbyist CD to a disk file as detailed in 2.5, and have loaded -WinPCAP on the system for Ethernet support. Other host OS's will look -similar but will have different file name syntax. - -c:\simh> vax ; run VAX emulator -sim> set cpu 64m ; set memory size to 64MB -sim> load -r vax\ka655.bin ; load the MicroVAX 3900 console ROM -sim> attach NVR vax\ka655.nvr ; create/load a Non-Volatile RAM file -sim> set LPT disable ; disable devices we don't want/need -sim> set TQ disable ; " -sim> set rq0 ra90 ; set disk 0 to 1GB (RA90 size) -sim> attach rq0 vax\vaxsys.dsk ; create/use disk file -sim> set rq1 rrd40 ; set disk 1 as a cdrom -sim> attach -r rq1 vax\hobbyist.dsk ; attach cdrom dump file as read-only -sim> set rq2 offline ; turn off disk rq2 -sim> set rq3 offline ; turn off disk rq3 -sim> attach xq eth0 ; attach to host ethernet controller -sim> b cpu ; start (boot) VAX console - -KA655-B V5.3, VMB 2.7 - 1) Dansk ; will not appear if the controlling - .. ; keyboard doesn't support multi- -15) Svenska ; national characters! - (1..15): 5 -Performing normal system tests. -40..39..38..37..36..35..34..33..32..31..30..29..28..27..26..25.. -24..23..22..21..20..19..18..17..16..15..14..13..12..11..10..9.. -8..7..6..5..4..3.. -Tests completed. ->>> show device ; tell console to show all devices -UQSSP Disk Controller 0 (772150) --DUA0 (RA90) --DUA1 (RRD40) - -Ethernet Adapter 0 (774440) --XQA0 (08-00-2B-AA-BB-CC) ->>> b dua1 ; tell console to boot cdrom -(BOOT/R5:1 DUA1) - -2..1..0 - ---------------------------------------------------------------------------------- - -4.8 How can I import files to a simulated VMS environment? - -- Use a CD burner program, like Easy CD Creator or Nero, to create an ISO 9660 - CD image containing the files you want to import. Note that file names are - limite to DOS '8.3' conventions. -- Attach the simulated CD image to a simulated CD drive. -- Mount the simulated CD as an ISO 9660 file system under VMS. -- Copy the files you need from the simulated CD to the simulated disk. - -(Thanks to Tim Stark for this suggestion.) - ---------------------------------------------------------------------------------- - -4.9 How can I export files from a simulated VMS environment? - -- Utility ODS2 (available on the Web) can read an ODS-2 disk image and copy files - from that image to the host file system. -- Text files can be printed to the simulated line printer, as described above. - -================================================================================ -5 PDP-11 -================================================================================ - -5.1 When installing RSTS/E from simulated magtape, the installation process - hangs with no error message; why? - -- RSTS/E installation from magnetic tape requires that the tape be write locked. \ No newline at end of file diff --git a/simh_swre.txt b/simh_swre.txt deleted file mode 100644 index 662a0cc5..00000000 --- a/simh_swre.txt +++ /dev/null @@ -1,703 +0,0 @@ -To: Users -From: Bob Supnik -Subj: Sample Software Packages -Date: 15-Sep-2003 - -This memorandum documents the sample software packages available to run -with the SIMH simulators. Many of these packages are available under -limited use licenses; please read the license terms included with the -software. - -The following copyright notice applies to both the SIMH source and binary: - - Original code published in 1993-2003, written by Robert M Supnik - Copyright (c) 1993-2003, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - -1. PDP-8 - -1.1 ESI-X - -ESI-X is an interactive program for technical computation. It can -execute both immediate commands and stored programs (like BASIC). ESI-X -is provided as both source and as a binary loader format paper-tape -image. For more information see the documentation included with the -program. My thanks to Dave Waks, who wrote the program, and to Paul -Pierce and Tim Litt, who recovered the source from its archival medium. - -To load and run ESI-X: - - sim> load esix.bin - sim> run 5400 - _TYPE 2+2. - 2+2 = 4 - -1.2 FOCAL69 - -FOCAL69 is an interactive program for technical computations. It can -execute both immediate commands and stored programs (like BASIC). FOCAL69 -is provided as a binary loader format paper-tape image. To load and -run FOCAL69: - - sim> load focal69.bin - sim> run 200 - *TYPE 2+2 - = 4.000* - -1.3 PDP-8 OS/8 - -OS/8 is the PDP-8's mass storage-based operating system. It provides a -program development and execution environment for assembler, BASIC, and -FORTRAN programs. OS/8 is provided under license, as is, without fee, by -Digital Equipment Corporation, for non-commercial use only. Please read -the enclosed license agreement for full terms and conditions. This license -agreement must be reproduced with any copy of the OS/8 disk images. My -thanks to Doug Jones of the University of Iowa, who provided the disk -images, and to Digital Equipment Corporation, which provided the license. - -To boot and run OS/8: - - sim> att rx0 os8sys_rx.dsk - sim> att rx1 os8f4_rx.dsk - sim> boot rx0 - - .DA dd-mmm-yy - . - -Note that OS/8 only recognizes upper case characters. The first disk -(drive 0) is the system disk; it also includes BASIC. The second disk -(drive 1) includes FORTRAN. - -1.4 PDP-8 TSS/8 - -TSS/8 is the PDP-8's timesharing system. It provides a program development -and execution environment for assembler, BASIC, and FORTRAN programs. TSS/8 -is provided as is, without fee, by Digital Equipment Corporation, for non- -commercial use only. My thanks to John Wilson of Dbit Inc, who provided -the disk image and the initialization tape source. - -Loading TSS/8 -------------- - -Note: your environment must have a functioning second Teletype; that is, you -cannot at present run TSS if your host system does not support the SIMH -sockets library. - -- Load the paper-tape bootstrap: - - sim> load tss8_init.bin - -- Mount the TSS/8 disk image of the RF08: - - sim> attach rf tss8_rf.dsk - -- Assign a TCP/IP port to the Telnet listener for the extra terminals: - - sim> attach ttix -- 4000 typically works - -- Run the bootstrap: - - sim> run 24200 - -- TSS/8 will boot and go through its startup dialog - - LOAD, DUMP, START, ETC? START - MONTH-DAY-YEAR: mm:dd:yy -- numeric, yy in range [74:85] - HR:MIN - hh:mm -- numeric, 24 hour format - (type cr to get attention) - - . - - and is now ready for login. The list of accounts and passwords: - - PPN Password - [0,1] VH3M - [0,2] LXHE - [0,3] SHUG - [77,77] - [1,10] WBCN - [20,1] DT - [20,2] PT - [20,3] TSS8 - [20,4] EDIT - [20,5] 4TH - [1,50] JERK - -- Login using one of the existing accounts. The login command won't echo: - - .LOGIN 2 LXHE -- privileged library account - - TSS/8.24 JOB 01 [00,02] K00 23:23:06 - - SYSTEM IS DOWN, INC. - -- The system is now ready for commands. To get a directory listing: - - .R CAT - -- Other users can log in by connecting, from a Telnet client, to localhost - on the port specified in the ATTACH TTIX command. - -2. PDP-11 - -2.1 UNIX V5, V6, V7 - -UNIX was first developed on the PDP-7; its first widespread usage was on -the PDP-11. UNIX provides a program development and execution environment -for assembler and C programs. UNIX V5, V6, V7 for the PDP-11 is provided -under license, as is, without fee, by Caldera Corportion, for non-commercial -use only. Please read the enclosed license agreement for full terms and -conditions. This license must be reproduced with any copy of the UNIX V5, -V6, V7 disk images. My thanks to PUPS, the PDP-11 UNIX Preservation Society -of Australia, which provided the disk images, and to Caldera, which provided -the license. - -2.1.1 UNIX V5 - -UNIX V5 is contained on a single RK05 disk image. To boot UNIX: - - sim> set cpu 18b - sim> att rk0 unix_v5_rk.dsk - sim> boot rk - @unix - login: root - #ls -l - -2.1.2 UNIX V6 - -UNIX V6 is contained on four RK05 disk images. To boot UNIX: - - sim> set cpu 18b - sim> att rk0 unix0_v6_rk.dsk - sim> att rk1 unix1_v6_rk.dsk - sim> att rk2 unix2_v6_rk.dsk - sim> att rk3 unix3_v6_rk.dsk - sim> boot rk0 - @unix - login: root - # ls -l - -2.1.3 UNIX V7 - -UNIX V7 is contained on a single RL02 disk image. To boot UNIX: - - sim> set cpu 18b - sim> set rl0 RL02 - sim> att rl0 unix_v7_rl.dsk - sim> boot rl0 - @boot - New Boot, known devices are hp ht rk rl rp tm vt - : rl(0,0)rl2unix - # - -A smaller image is contained on a single RK05 disk image. To boot UNIX: - - sim> set cpu 18b - sim> att rk0 unix_v7_rk.dsk - sim> boot rk0 - @boot - New Boot, known devices are hp ht rk rl rp tm vt - : rk(0,0)rkunix - # STTY -LCASE - # - -2.2 RT-11 - -RT-11 is the PDP-11's single user operating system. It provides a program -development and execution environment for assembler, BASIC, and FORTRAN -programs. RT-11 is provided under license, as is, without fee, by Mentec -Corporation, for non-commercial use ONLY ON THIS SIMULATOR. Please read -the enclosed license agreement for full terms and conditions. This license -agreement must be reproduced with any copy of the RT-11 disk image. My -thanks to John Wilson, a private collector, who provided the disk image -for RT-11 V4; to Megan Gentry, of Digital Equipment Corporation, who -provided the disk image for RT-11 V5.3; and to Mentec Corporation, which -provided the license. - -2.2.1 RT-11 V4 - -RT-11 is contained in a single RK05 disk image. To boot and run RT-11: - - sim> att rk0 rtv4_rk.dsk - sim> boot rk0 - -For RL, HK, RM, and RP series disks, RT-11 expects to find a manufacturer's -bad block table in the last track of the disk. Therefore, INITialization of -a new (all zero's) disk fails, because there is no valid bad block table. To -create a minimal bad block table, use the SET BADBLOCK command. - -2.2.2 RT-11 V5.3 - -RT-11 is contained in a single RL02 disk image. To boot and run RT-11: - - sim> set rl0 rl02 - sim> att rl0 rtv53_rl.dsk - sim> boot rl0 - -This is a full RT-11 distribution kit. It expects the user to copy the -distribution pack and generate a new system. This requires mounting a -blank pack on RL1. When a blank pack is attached to the simulator, a -bad block table must be created with the SET BADBLOCK command. - -3. Nova and Eclipse RDOS - -RDOS is the Nova's real-time mass storage operating system. It provides a -program development and execution environment for assembler, BASIC, and -FORTRAN programs. RDOS is provided under license, as is, without fee, by -Data General Corporation, for non-commercial use only. Please read the -enclosed license agreement for full terms and conditions. This license -agreement must be reproduced with any copy of the RDOS disk image. My -thanks to Carl Friend, a private collector, who provided the disk image, -and to Data General Corporation, which provided the license. - -To boot and run RDOS for the Nova: - - sim> att dp0 rdos_d31.dsk - sim> set tti dasher - sim> boot dp0 - FILENAME? (cr) - DATE (mm/dd/yy)? xx/yy/zz - TIME (hh:mm:ss)? hh:mm:ss - R - list/e - -To boot and run RDOS for the Eclipse: - - sim> att dp0 zrdos75.dsk - sim> set tti dasher - sim> boot dp0 - FILENAME? (cr) - DATE (mm/dd/yy)? xx/yy/zz - TIME (hh:mm:ss)? hh:mm:ss - R - list/e - -4. PDP-1 - -4.1 PDP-1 LISP - -PDP-1 LISP is an interactive interpreter for the Lisp language. It can -execute both interactive commands and stored programs. The startup -instructions for LISP are complicated; see the documentation included -with the program for details. My thanks to Peter Deutsch, who wrote the -program, to Gordon Greene, who typed it in from a printed listing, and -to Paul McJones, who helped with the final debug process. - -4.2 PDP-1 DDT - -PDP-1 DDT is an interactive debugging tool for the PDP-1. It provides -symbolic debugging capabilities for PDP-1 programs. The documentation -included with the program provides information on loading and operating -DDT. My thanks to Derek Peschel, who transcribed and debugged DDT. - -5. PDP-7 SIM8 - -PDP-7 SIM8 is a PDP-8 simulator for the PDP-7. It implements an 8K -PDP-8/I with keyboard, teleprinter, reader, punch, and line printer. -It provides an interactive console environment for control and debug -of the simulated PDP-8. For more information see the documentation -included with the program. My thanks to Dave Waks, who wrote the -program, and to Paul Pierce and Tim Litt, who recovered the source -from its archival medium. - -To load and run SIM8: - - sim> load sim8.rim - sim> run - AC/ 0000 - -6. PDP-9/PDP-15 - -6.1 FOCAL - -FOCAL15 is an interactive program for technical computations. It can -execute both immediate commands and stored programs (like BASIC). -FOCAL15 is provided as a binary loader format paper-tape image. My -thanks to Al Kossow, who provided the binary image. To load and run -FOCAL15: - - sim> load focal15.bin - sim> run - *TYPE FSQT(2),! - = 1.4142 - * - -6.2 Advanced Software System/Keyboard Monitor - -The Advanced Software System Keyboard Monitor is the simplest mass -storage monitor for the PDP-15. It offers single-user program -development and execution capabilities. To load and run ADSS/KM-15: - -- On the PDP-9 (only), initialize extend mode to on: - - sim> d extm_init 1 - -- Load the paper-tape bootstrap into upper memory: - - sim> load dec-15u.rim 77637 - - You specify the load address. - -- Verify that the bootstrap loaded correctly: - - sim> ex pc - PC: 077646 - -- Change the default line printer to be the LP09 rather than the Type - 647 (PDP-9) or LP15 (PDP-15): - - sim> set lpt disa - sim> set lp9 ena - -- Mount the Advanced Software System DECtape image on DECtape unit 0: - - sim> attach dt adss15_32k.dtp - -- Run the bootstrap: - - sim> run - -- The DECtape will boot and print out - - KMS9-15 V5B000 - $ - - and is now ready for commands. Recognized commands include: - - D list system device directory - I list available commands - R list device assignments - SCOM list systems communication region - -- To run Focal, assign unused DAT slot 10 and then load Focal - - $A LPA0 10 - $GLOAD - LOADER V5B000 - >_FOCAL - FOCAL V9A - *TYPE 2+2,! - 4.0000 - * - -6.3 Advanced Software System/Foreground Background - -Note: your environment must have a functioning second Teletype; that is, -you cannot at present run Foreground/Background if your host system -does not support the SIMH sockets library. - -- Load the paper-tape bootstrap into upper memory: - - sim> load dec-15u.rim 77637 - - You specify the load address. - -- Verify that the bootstrap loaded correctly: - - sim> ex pc - PC: 077646 - -- Mount the Foregorund/Background DECtape image on DECtape unit 0: - - sim> attach dt fb15_32k.dtp - -- Turn on the API option: - - sim> set cpu api - -- Assign a TCP/IP port to the Telnet listener for the second terminal: - - sim> assign tti1 -- 4000 typically works - -- Start a Telnet client to act as the second terminal and connect to - localhost on the specified port. - -- Run the bootstrap: - - sim> run - -- The DECtape will boot, and the Foreground/Background Monitor will print - on the second terminal - - F9/15 V4A - $ - - and is now ready for commands. Recognized commands include: - - D 0 list system device directory - R list device assignments - -- To activate the background, load IDLE into the foreground: - - $A DTA0 -4 - $GLOAD - FGLOAD V2A - >_IDLE - - Background terminal responds with - - B9/15 V4A - $ - - and is now ready for commands. - -6.4 DOS-15 - -DOS-15 is a more polished version of ADSS-15 using the RF15 or RP15 -as its system device. To load and run DOS-15: - -- Load the DOS-15 paper tape bootstrap into upper memory: - - sim> load rfsboot.rim 77637 - -- Mount the DOS-15 RF disk image on the RF15: - - sim> att rf dosv2a_4p.rf - -- Run the bootstrap: - - sim> run - -- The RF disk will boot and print out - - DOS-15 V2A - ENTER DATE (MM/DD/YY) - - - Enter the date (the year must be between 70 and 99). DOS-15 will - print its prompt and is now ready for commands. Recognized commands - include: - - I system information - S system configuration - R system device assignments - - -7. IBM 1401 - -7.1 Single Card "Koans" - -One of the art forms for the IBM 1401 was packing useful programs into a -single punched card. Three samples are included: - -i1401_ctolp.cd prints a card deck on the line printer -i1401_ctopu.cd copies a card deck to the card punch -i1401_hello.cd prints "HELLO WORLD" on the line printer and stops - -To use the reproduction cards, simply insert them at the beginning of a -text file, terminated by newline. Attach the modified file to the card -reader, attach a blank file to the output device, and boot the card reader. - -7.2 Diagnostic Tape - -The software and writeup were provided by Charles Owens. - -This 1401 Diagnostics tape is a bootable tape containing a series of 1401 -diagnostics dating from about 1962. The 1407 Inquiry console is not used; -all control is via the front panel. - -To run in the simulator, attach thusly: - - sim> attach mt1 1401diag.mt - sim> attach lpt errorlist.txt - sim> boot mt1 - -The simulator will halt with IS = 433. At this point, you can set options -through the sense switches and memory. - -D 1252 "1" Will cause headings to print for each test run. - Otherwise no printing will occur unless there are errors. - -D SSB 1 Loop if an error is detected. - -D SSC 1 Prints all test cases not just errors. - -D SSD 1 Repeat the test run over and over. - -D SSE 1 Halt if any error is detected, otherwise continue. - -When you continue from this halt (use C to CON), the simulator will halt -at 3001. Enter C again and the tape will spin thru a series of basic -CPU diagnostics. - -7.3 SPS - -The software and writeup were provided by Charles Owens. - -sps1.obj and sps2.obj are the object card decks for the "Symbolic -Programming System", a primitive assembler for the 1401 that predates -the better known and more functional Autocoder. - -To use SPS, write an SPS program using your favourite editor (two -examples are provided, hello.sps and diaglist.sps). SPS decks are -not free-format, but operands must be placed in columns: - - 1 - 5 Line Count (optional) - 6 - 7 Count (number of characters when defining a constant). - 8 - 13 Label (six characters must start with alphabetic). -14 - 16 Opcode: Examples: - A = Add - B = Branch (must be d-mod for conditional) - BWZ = Branch if Wordmark or Zone - C = Compare - CC = Carriage Control (printer) - CS = CLear Storage - CU = Control Unit (e.g. tape) - CW = Clear Workmark - D = Divide - DC = Define Constant (no wordmark) - DCW = Define Constant (starts in 24, length in 6-7) - END = End of program - LCA = Load Characters - H = Halt - M = Multiply - MCE = Move and Edit - MCS = Move and Supress Zeros - MCW = Move Characters - MN = Move Numeric - MZ = Move Zone - ORG = Define Origin Point - P = Punch Card - R = Read Card - S = Subtract - SS = Stacker Select - SW = Set Wordmark - W = Write Line - ZA = Zero and Add - ZS = Zero and Subtract - Tape: - MCW %UX YYY W Write Tape from addr YYY w/o wordmarks) - LCA %UX YYY W Write Tape, Unit X from addr YYY w/wordmarks) - MCW %UX YYY R Read Tape from addr YYY w/o wordmarks) - LCA %UX YYY R Read Tape, Unit X from addr YYY w/wordmarks) - CU %UX M Write Tape Mark - CU %UX E Skip and Blank Tape - CU %UX B Backspace Record - CU %UX R Rewind Tape - CU %UX U Rewind and Unlaod tape -17 - 22 Address for A-operand (label or 4-digit actual address) -23 - 23 blank, + or - to adjust A-operand by a constant -24 - 26 3-digit number to adjust A-operand by if 23 is + or - -27 - 27 Index (?) -28 - 33 Address for B-operand -34 - 34 Blank, + or - -35 - 37 3-digit number of adjust B-address by if 34 is + or - -38 - 38 Index (?) -39 - 39 D-modifier for this instruction. Notes: - / = Compare is unequal - S = Branch if Compare Equal - T = B is less than A - U = B is greater than A - L = Tape read error - K = Tape end of reel -40 - 55 Comments - -The SPS deck should start with an ORG operation to specify where in storage -the program starts, and end with an END card, with an optional A-operand -showing where to start execution. - -To assemble an SPS program, place the SPS source between the SPS1.OBJ and -the SPS2.OBJ deck, and another copy of the same source after the SPS2.OBJ -deck (SPS is a two-pass assembler). SPS prints a listing on LPT and punches -an object deck on CDP, ready to run. - -A UNIX command script to assemble an SPS deck painlessly is in "sps". To -use the script, enter "sps programname". The script creates programname.lst -for the listing and programname.obj for the object deck. Windows users -are out of luck, for now. - -8. HP2116 16K BASIC - -HP BASIC is a paper-tape centric implementation of BASIC for a 16KW -HP2116. Device numbers correspond to the default simulator settings: - - PTR = 10 - TTY = 11 - PTP = 12 - -The program is a complete but early BASIC and has one unsual requirement: -all programs must include a valid END statement to run correctly. My -thanks to Jeff Moffatt for providing the program. - -To load and run BASIC: - - sim> load basic1.abs - sim> run 100 - READY - 10 PRINT SQR(2) - 20 END - RUN - 1.41421 - - -9. PDP-10 TOPS-10 7.03, TOPS-10 7.04, TOPS-20 V4.1 - -TOPS-10 was the primary time-shared operating system for the PDP-10. -TOPS-20 was a popular alternative derived from the BBN TENEX system. -Installation and distribution tapes for TOPS-10 7.03, TOPS-10 7.04, -and TOPS-20 4.1 are available at http://pdp-10.trailing-edge.com. - -10. Interdata 32b Systems - -10.1 Interdata 7/32 UNIX - -Interdata UNIX V6 was the first port of UNIX from its native environment -on the PDP-11. The port was done by Richard Miller and his colleagues -at the University of Wollongong, Australia, in 1976-77. UNIX V6 and V7 -for the Interdata 7/32 is provided under license, as is, without fee, by -Caldera Corportion, for non-commercial use only. Please read the enclosed -license agreement for full terms and conditions. This license must be -reproduced with any copy of the UNIX V6 and V7 disk images. My thanks to -Richard Miller, without whose guidance, knowledge, and patience the -recreation of Interdata UNIX would not have been possible, and to Caldera, -which provided the license. - -10.1.1 UNIX V6 - -UNIX V6 is contained on a single 10MB disk image. To boot UNIX V6: - - sim> set ttp ena - sim> set pas dev=12 - sim> set mt dev=85 - sim> att -e dp0 iu6_dp0.dsk - sim> boot dp0 - ?unix - login: root - # ls -l - -10.1.2 UNIX V7 - -UNIX V7 is contained on two 10MB disk images. To boot UNIX V7: - - sim> set ttp ena - sim> set pas dev=12 - sim> set mt dev=85 - sim> att -e dp0 iu6_dp0.dsk - sim> att -e dp1 iu6_dp1.dsk - sim> boot dp0 - Boot - : dsk(1,0)unix - # - -Type ^D to enable multiuser mode. The root password is root. - -[end simh_swre.txt]